Skip to content

Commit 9936e03

Browse files
Add support for default shank ix discriminators in nodes-from-anchor (#590)
* `feat`: Add support for default shank ix discriminators in nodes-from-anchor --------- Co-authored-by: Loris Leiva <[email protected]>
1 parent 13a19d6 commit 9936e03

File tree

6 files changed

+54
-9
lines changed

6 files changed

+54
-9
lines changed

.changeset/strong-planes-hide.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@codama/nodes-from-anchor': minor
3+
---
4+
5+
Add support for default shank ix discriminators (using 1 byte at the start of the ix data) in nodes-from-anchor

packages/nodes-from-anchor/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ pnpm install @codama/nodes-from-anchor
1616
```
1717

1818
> [!NOTE]
19-
> This package is **not** included in the main [`codama`](../library) package.
19+
>
20+
> - This package is **not** included in the main [`codama`](../library) package.
21+
> - If `metadata.origin` is not set on the IDL, it is assumed to be `"anchor"`. If you are trying to parse a Shank IDL, be sure that origin is set to `"shank"` so discriminators can be set correctly.
2022
2123
## Functions
2224

packages/nodes-from-anchor/src/v00/InstructionNode.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
bytesTypeNode,
3+
bytesValueNode,
34
camelCase,
45
DiscriminatorNode,
56
fieldDiscriminatorNode,
@@ -16,7 +17,11 @@ import { instructionAccountNodesFromAnchorV00 } from './InstructionAccountNode';
1617
import { instructionArgumentNodeFromAnchorV00 } from './InstructionArgumentNode';
1718
import { typeNodeFromAnchorV00 } from './typeNodes';
1819

19-
export function instructionNodeFromAnchorV00(idl: IdlV00Instruction, origin?: 'anchor' | 'shank'): InstructionNode {
20+
export function instructionNodeFromAnchorV00(
21+
idl: IdlV00Instruction,
22+
ixIndex: number,
23+
origin?: 'anchor' | 'shank',
24+
): InstructionNode {
2025
const idlName = idl.name ?? '';
2126
const name = camelCase(idlName);
2227
let dataArguments = (idl.args ?? []).map(instructionArgumentNodeFromAnchorV00);
@@ -41,6 +46,15 @@ export function instructionNodeFromAnchorV00(idl: IdlV00Instruction, origin?: 'a
4146
});
4247
dataArguments = [discriminatorField, ...dataArguments];
4348
discriminators = [fieldDiscriminatorNode('discriminator')];
49+
} else if (origin === 'shank') {
50+
const discriminatorField = instructionArgumentNode({
51+
defaultValue: bytesValueNode('base16', ixIndex.toString(16)),
52+
defaultValueStrategy: 'omitted',
53+
name: 'discriminator',
54+
type: fixedSizeTypeNode(bytesTypeNode(), 1),
55+
});
56+
dataArguments = [discriminatorField, ...dataArguments];
57+
discriminators = [fieldDiscriminatorNode('discriminator')];
4458
}
4559

4660
return instructionNode({

packages/nodes-from-anchor/src/v00/ProgramNode.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ export function programNodeFromAnchorV00(idl: IdlV00): ProgramNode {
1111
const origin = (idl?.metadata as { origin?: 'anchor' | 'shank' })?.origin ?? 'anchor';
1212
const pdas = (idl.accounts ?? []).filter(account => (account.seeds ?? []).length > 0).map(pdaNodeFromAnchorV00);
1313
const accounts = (idl.accounts ?? []).map(a => accountNodeFromAnchorV00(a, origin));
14-
const instructions = (idl.instructions ?? []).map(i => instructionNodeFromAnchorV00(i, origin));
14+
const instructions = (idl.instructions ?? []).map((instruction, index) =>
15+
instructionNodeFromAnchorV00(instruction, index, origin),
16+
);
1517
return programNode({
1618
accounts,
1719
definedTypes: (idl?.types ?? []).map(definedTypeNodeFromAnchorV00),

packages/nodes-from-anchor/test/v00/InstructionNode.test.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@ import { expect, test } from 'vitest';
1313
import { instructionNodeFromAnchorV00 } from '../../src';
1414

1515
test('it creates instruction nodes', () => {
16-
const node = instructionNodeFromAnchorV00({
17-
accounts: [{ isMut: true, isSigner: false, name: 'mint' }],
18-
args: [{ name: 'amount', type: 'u8' }],
19-
name: 'mintTokens',
20-
});
16+
const node = instructionNodeFromAnchorV00(
17+
{
18+
accounts: [{ isMut: true, isSigner: false, name: 'mint' }],
19+
args: [{ name: 'amount', type: 'u8' }],
20+
name: 'mintTokens',
21+
},
22+
0,
23+
);
2124

2225
expect(node).toEqual(
2326
instructionNode({
@@ -35,6 +38,7 @@ test('it creates instruction nodes with anchor discriminators', () => {
3538
args: [],
3639
name: 'myInstruction',
3740
},
41+
0,
3842
'anchor',
3943
);
4044

packages/nodes-from-anchor/test/v00/ProgramNode.test.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import {
22
accountNode,
3+
bytesTypeNode,
4+
bytesValueNode,
35
constantPdaSeedNodeFromProgramId,
46
definedTypeNode,
57
errorNode,
8+
fieldDiscriminatorNode,
9+
fixedSizeTypeNode,
10+
instructionArgumentNode,
611
instructionNode,
712
pdaLinkNode,
813
pdaNode,
@@ -36,7 +41,20 @@ test('it creates program nodes', () => {
3641
name: 'myError',
3742
}),
3843
],
39-
instructions: [instructionNode({ name: 'myInstruction' })],
44+
instructions: [
45+
instructionNode({
46+
arguments: [
47+
instructionArgumentNode({
48+
defaultValue: bytesValueNode('base16', (0).toString(16)),
49+
defaultValueStrategy: 'omitted',
50+
name: 'discriminator',
51+
type: fixedSizeTypeNode(bytesTypeNode(), 1),
52+
}),
53+
],
54+
discriminators: [fieldDiscriminatorNode('discriminator')],
55+
name: 'myInstruction',
56+
}),
57+
],
4058
name: 'myProgram',
4159
origin: 'shank',
4260
pdas: [pdaNode({ name: 'myAccount', seeds: [constantPdaSeedNodeFromProgramId()] })],

0 commit comments

Comments
 (0)