accountsPage.test.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import {
  2. accountNode,
  3. booleanTypeNode,
  4. constantDiscriminatorNode,
  5. constantValueNodeFromBytes,
  6. definedTypeLinkNode,
  7. definedTypeNode,
  8. enumEmptyVariantTypeNode,
  9. enumTypeNode,
  10. enumValueNode,
  11. fieldDiscriminatorNode,
  12. numberTypeNode,
  13. numberValueNode,
  14. pdaLinkNode,
  15. pdaNode,
  16. programNode,
  17. publicKeyTypeNode,
  18. structFieldTypeNode,
  19. structTypeNode,
  20. } from '@kinobi-so/nodes';
  21. import { visit } from '@kinobi-so/visitors-core';
  22. import { test } from 'vitest';
  23. import { getRenderMapVisitor } from '../src';
  24. import { renderMapContains } from './_setup';
  25. test('it renders PDA helpers for PDA with no seeds', async () => {
  26. // Given the following program with 1 account and 1 pda with empty seeds.
  27. const node = programNode({
  28. accounts: [accountNode({ name: 'foo', pda: pdaLinkNode('bar') })],
  29. name: 'myProgram',
  30. pdas: [pdaNode({ name: 'bar', seeds: [] })],
  31. publicKey: '1111',
  32. });
  33. // When we render it.
  34. const renderMap = visit(node, getRenderMapVisitor());
  35. // Then we expect the following fetch helper functions delegating to findBarPda.
  36. await renderMapContains(renderMap, 'accounts/foo.ts', [
  37. 'export async function fetchFooFromSeeds',
  38. 'export async function fetchMaybeFooFromSeeds',
  39. 'await findBarPda({ programAddress })',
  40. ]);
  41. });
  42. test('it renders an account with a defined type link as discriminator', async () => {
  43. // Given the following program with 1 account with a discriminator.
  44. const node = programNode({
  45. accounts: [
  46. accountNode({
  47. data: structTypeNode([
  48. structFieldTypeNode({
  49. defaultValue: enumValueNode('key', 'Asset'),
  50. defaultValueStrategy: 'omitted',
  51. name: 'key',
  52. type: definedTypeLinkNode('Key'),
  53. }),
  54. structFieldTypeNode({
  55. name: 'mutable',
  56. type: booleanTypeNode(),
  57. }),
  58. structFieldTypeNode({
  59. name: 'owner',
  60. type: publicKeyTypeNode(),
  61. }),
  62. ]),
  63. discriminators: [fieldDiscriminatorNode('key', 0)],
  64. name: 'asset',
  65. }),
  66. ],
  67. definedTypes: [
  68. definedTypeNode({
  69. name: 'key',
  70. type: enumTypeNode([enumEmptyVariantTypeNode('Uninitialized'), enumEmptyVariantTypeNode('Asset')]),
  71. }),
  72. ],
  73. name: 'splToken',
  74. publicKey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
  75. });
  76. const renderMap = visit(node, getRenderMapVisitor());
  77. // Then we expect the following import list with a reference to the disciminator type.
  78. await renderMapContains(renderMap, 'accounts/asset.ts', ['import { Key, getKeyDecoder, getKeyEncoder }']);
  79. });
  80. test('it renders constants for account field discriminators', async () => {
  81. // Given the following account with a field discriminator.
  82. const node = programNode({
  83. accounts: [
  84. accountNode({
  85. data: structTypeNode([
  86. structFieldTypeNode({
  87. defaultValue: numberValueNode(42),
  88. defaultValueStrategy: 'omitted',
  89. name: 'myDiscriminator',
  90. type: numberTypeNode('u64'),
  91. }),
  92. ]),
  93. discriminators: [fieldDiscriminatorNode('myDiscriminator')],
  94. name: 'myAccount',
  95. }),
  96. ],
  97. name: 'myProgram',
  98. publicKey: '1111',
  99. });
  100. // When we render it.
  101. const renderMap = visit(node, getRenderMapVisitor());
  102. // Then we expect the following constant and function to be rendered
  103. // And we expect the field default value to use that constant.
  104. await renderMapContains(renderMap, 'accounts/myAccount.ts', [
  105. 'export const MY_ACCOUNT_MY_DISCRIMINATOR = 42;',
  106. 'export function getMyAccountMyDiscriminatorBytes() { return getU64Encoder().encode(MY_ACCOUNT_MY_DISCRIMINATOR); }',
  107. '(value) => ({ ...value, myDiscriminator: MY_ACCOUNT_MY_DISCRIMINATOR })',
  108. ]);
  109. });
  110. test('it renders constants for account constant discriminators', async () => {
  111. // Given the following account with two constant discriminators.
  112. const node = programNode({
  113. accounts: [
  114. accountNode({
  115. discriminators: [
  116. constantDiscriminatorNode(constantValueNodeFromBytes('base16', '1111')),
  117. constantDiscriminatorNode(constantValueNodeFromBytes('base16', '2222'), 2),
  118. ],
  119. name: 'myAccount',
  120. }),
  121. ],
  122. name: 'myProgram',
  123. publicKey: '1111',
  124. });
  125. // When we render it.
  126. const renderMap = visit(node, getRenderMapVisitor());
  127. // Then we expect the following constants and functions to be rendered.
  128. await renderMapContains(renderMap, 'accounts/myAccount.ts', [
  129. 'export const MY_ACCOUNT_DISCRIMINATOR = new Uint8Array([ 17, 17 ]);',
  130. 'export function getMyAccountDiscriminatorBytes() { return getBytesEncoder().encode(MY_ACCOUNT_DISCRIMINATOR); }',
  131. 'export const MY_ACCOUNT_DISCRIMINATOR2 = new Uint8Array([ 34, 34 ]);',
  132. 'export function getMyAccountDiscriminator2Bytes() { return getBytesEncoder().encode(MY_ACCOUNT_DISCRIMINATOR2); }',
  133. ]);
  134. });