Skip to content

Commit 00a724f

Browse files
authored
Use programId of PdaValueNode when resolving instruction inputs (#917)
1 parent 538d0f3 commit 00a724f

File tree

2 files changed

+88
-1
lines changed

2 files changed

+88
-1
lines changed

packages/visitors-core/src/getResolvedInstructionInputsVisitor.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,10 @@ export function getInstructionDependencies(input: InstructionInput | Instruction
279279
dependencies.set(seed.value.name, { ...seed.value });
280280
}
281281
});
282-
return [...dependencies.values()];
282+
return <InstructionDependency[]>[
283+
...dependencies.values(),
284+
...(input.defaultValue.programId ? ([input.defaultValue.programId] as const) : []),
285+
];
283286
}
284287

285288
if (isNode(input.defaultValue, 'resolverValueNode')) {

packages/visitors-core/test/getResolvedInstructionInputsVisitor.test.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import {
44
instructionArgumentNode,
55
instructionNode,
66
numberTypeNode,
7+
pdaSeedValueNode,
8+
pdaValueNode,
79
publicKeyTypeNode,
810
} from '@codama/nodes';
911
import { expect, test } from 'vitest';
@@ -221,3 +223,85 @@ test('it returns an empty array for empty instructions', () => {
221223
// Then we expect an empty array.
222224
expect(result).toEqual([]);
223225
});
226+
227+
test('it resolves the seeds of a PdaValueNode first', () => {
228+
// Given the following instruction node with an account that defaults to another account.
229+
const node = instructionNode({
230+
accounts: [
231+
instructionAccountNode({
232+
defaultValue: pdaValueNode('counter', [pdaSeedValueNode('authority', accountValueNode('payer'))]),
233+
isSigner: false,
234+
isWritable: false,
235+
name: 'counter',
236+
}),
237+
instructionAccountNode({
238+
isSigner: true,
239+
isWritable: false,
240+
name: 'payer',
241+
}),
242+
],
243+
name: 'myInstruction',
244+
});
245+
246+
// When we get its resolved inputs.
247+
const result = visit(node, getResolvedInstructionInputsVisitor());
248+
249+
// Then we expect the accounts to be in order of resolution.
250+
expect(result).toEqual([
251+
{
252+
...node.accounts[1],
253+
dependsOn: [],
254+
isPda: false,
255+
resolvedIsOptional: false,
256+
resolvedIsSigner: true,
257+
},
258+
{
259+
...node.accounts[0],
260+
dependsOn: [accountValueNode('payer')],
261+
isPda: false,
262+
resolvedIsOptional: false,
263+
resolvedIsSigner: false,
264+
},
265+
]);
266+
});
267+
268+
test('it resolves the program id of a PdaValueNode first', () => {
269+
// Given the following instruction node with an account that defaults to another account.
270+
const node = instructionNode({
271+
accounts: [
272+
instructionAccountNode({
273+
defaultValue: pdaValueNode('counter', [], accountValueNode('counterProgram')),
274+
isSigner: false,
275+
isWritable: false,
276+
name: 'counter',
277+
}),
278+
instructionAccountNode({
279+
isSigner: false,
280+
isWritable: false,
281+
name: 'counterProgram',
282+
}),
283+
],
284+
name: 'myInstruction',
285+
});
286+
287+
// When we get its resolved inputs.
288+
const result = visit(node, getResolvedInstructionInputsVisitor());
289+
290+
// Then we expect the accounts to be in order of resolution.
291+
expect(result).toEqual([
292+
{
293+
...node.accounts[1],
294+
dependsOn: [],
295+
isPda: false,
296+
resolvedIsOptional: false,
297+
resolvedIsSigner: false,
298+
},
299+
{
300+
...node.accounts[0],
301+
dependsOn: [accountValueNode('counterProgram')],
302+
isPda: false,
303+
resolvedIsOptional: false,
304+
resolvedIsSigner: false,
305+
},
306+
]);
307+
});

0 commit comments

Comments
 (0)