diff --git a/.changeset/five-lemons-pump.md b/.changeset/five-lemons-pump.md new file mode 100644 index 000000000..1eddfca0a --- /dev/null +++ b/.changeset/five-lemons-pump.md @@ -0,0 +1,5 @@ +--- +'@metaplex-foundation/kinobi': patch +--- + +Add support for empty array seeds diff --git a/src/renderers/js-experimental/fragments/pdaFunction.ts b/src/renderers/js-experimental/fragments/pdaFunction.ts index 6564421b1..7399275b2 100644 --- a/src/renderers/js-experimental/fragments/pdaFunction.ts +++ b/src/renderers/js-experimental/fragments/pdaFunction.ts @@ -2,7 +2,7 @@ import { PdaNode, ProgramNode, isNode, isNodeFilter } from '../../../nodes'; import { visit } from '../../../visitors'; import { ImportMap } from '../ImportMap'; import type { GlobalFragmentScope } from '../getRenderMapVisitor'; -import { Fragment, fragment, fragmentFromTemplate } from './common'; +import { Fragment, fragmentFromTemplate } from './common'; export function getPdaFunctionFragment( scope: Pick< @@ -20,9 +20,6 @@ export function getPdaFunctionFragment( valueNodeVisitor, nameApi, } = scope; - if (pdaNode.seeds.length === 0) { - return fragment(''); - } // Seeds. const imports = new ImportMap(); diff --git a/src/renderers/rust/getRenderMapVisitor.ts b/src/renderers/rust/getRenderMapVisitor.ts index 4b2f7caea..94f6bce65 100644 --- a/src/renderers/rust/getRenderMapVisitor.ts +++ b/src/renderers/rust/getRenderMapVisitor.ts @@ -177,6 +177,7 @@ export function getRenderMapVisitor(options: GetRustRenderMapOptions = {}) { seeds, constantSeeds, hasVariableSeeds, + pda, }) ); }, diff --git a/src/renderers/rust/templates/accountsPage.njk b/src/renderers/rust/templates/accountsPage.njk index b50cbb2a1..4a5e1c45f 100644 --- a/src/renderers/rust/templates/accountsPage.njk +++ b/src/renderers/rust/templates/accountsPage.njk @@ -48,7 +48,7 @@ impl {{ account.name | pascalCase }} { {% endif %} {% endif %} - {% if seeds.length > 0 %} + {% if pda %} pub fn create_pda( {% if hasVariableSeeds %} {% for seed in seeds %} diff --git a/src/visitors/updateAccountsVisitor.ts b/src/visitors/updateAccountsVisitor.ts index 868358134..3fe456192 100644 --- a/src/visitors/updateAccountsVisitor.ts +++ b/src/visitors/updateAccountsVisitor.ts @@ -42,7 +42,7 @@ export function updateAccountsVisitor(map: Record) { const { seeds, pda, ...assignableUpdates } = updates; let newPda = node.pda; - if (pda && !pda.importFrom && seeds) { + if (pda && !pda.importFrom && seeds !== undefined) { newPda = pda; pdasToUpsert.push({ program: stack.getProgram()!.name, @@ -50,12 +50,12 @@ export function updateAccountsVisitor(map: Record) { }); } else if (pda) { newPda = pda; - } else if (seeds && node.pda) { + } else if (seeds !== undefined && node.pda) { pdasToUpsert.push({ program: stack.getProgram()!.name, pda: pdaNode(node.pda.name, seeds), }); - } else if (seeds) { + } else if (seeds !== undefined) { newPda = pdaLinkNode(newName ?? node.name); pdasToUpsert.push({ program: stack.getProgram()!.name, diff --git a/test/renderers/js-experimental/pdasPage.test.ts b/test/renderers/js-experimental/pdasPage.test.ts new file mode 100644 index 000000000..4330e90c4 --- /dev/null +++ b/test/renderers/js-experimental/pdasPage.test.ts @@ -0,0 +1,39 @@ +import test from 'ava'; +import { + accountNode, + pdaLinkNode, + pdaNode, + programNode, + visit, +} from '../../../src'; +import { getRenderMapVisitor } from '../../../src/renderers/js-experimental/getRenderMapVisitor'; +import { renderMapContains } from './_setup'; + +test('it renders an empty array seed used on a pda', (t) => { + // Given the following program with 1 account and 1 pda with empty seeds. + const node = programNode({ + name: 'splToken', + publicKey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', + accounts: [ + accountNode({ + name: 'testAccount', + discriminators: [], + pda: pdaLinkNode('testPda'), + }), + ], + pdas: [ + // Empty array seeds. + pdaNode('testPda', []), + ], + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + + // Then we expect the following function and and empty seeds + // array used on program derived address function. + renderMapContains(t, renderMap, 'pdas/testPda.ts', [ + /export async function findTestPdaPda/, + /getProgramDerivedAddress\({ programAddress, seeds: \[\] }\)/, + ]); +}); diff --git a/test/renderers/rust/accountsPage.test.ts b/test/renderers/rust/accountsPage.test.ts index 3b20ddba5..901cd9d1e 100644 --- a/test/renderers/rust/accountsPage.test.ts +++ b/test/renderers/rust/accountsPage.test.ts @@ -7,7 +7,7 @@ import { pdaNode, programNode, variablePdaSeedNode, - visit, + visit } from '../../../src'; import { getRenderMapVisitor } from '../../../src/renderers/rust/getRenderMapVisitor'; import { codeContains } from './_setup'; @@ -42,3 +42,32 @@ test('it renders a byte array seed used on an account', (t) => { `&byte_array_seed,`, ]); }); + +test('it renders an empty array seed used on an account', (t) => { + // Given the following program with 1 account and 1 pda with empty seeds. + const node = programNode({ + name: 'splToken', + publicKey: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', + accounts: [ + accountNode({ + name: 'testAccount', + discriminators: [], + pda: pdaLinkNode('testPda'), + }), + ], + pdas: [ + // Empty array seeds. + pdaNode('testPda', []), + ], + }); + + // When we render it. + const renderMap = visit(node, getRenderMapVisitor()); + + // Then we expect the following identifier and reference to the byte array + // as a parameters to be rendered. + codeContains(t, renderMap.get('accounts/test_account.rs'), [ + /pub fn find_pda\(/, + /&\[\s*\]/, + ]); +});