Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion packages/node-types/src/ProgramNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export interface ProgramNode<
readonly name: CamelCaseString;
readonly publicKey: string;
readonly version: ProgramVersion;
readonly origin?: 'anchor' | 'shank';
readonly docs?: Docs;

// Children.
Expand Down
1 change: 0 additions & 1 deletion packages/nodes-from-anchor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ pnpm install @codama/nodes-from-anchor
> [!NOTE]
>
> - This package is **not** included in the main [`codama`](../library) package.
> - 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.

## Functions

Expand Down
7 changes: 2 additions & 5 deletions packages/nodes-from-anchor/src/v00/AccountNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ import { getAnchorAccountDiscriminatorV00 } from '../discriminators';
import { IdlV00AccountDef } from './idl';
import { structTypeNodeFromAnchorV00 } from './typeNodes';

export function accountNodeFromAnchorV00(
idl: IdlV00AccountDef,
origin?: 'anchor' | 'shank',
): AccountNode<StructTypeNode> {
export function accountNodeFromAnchorV00(idl: IdlV00AccountDef, addDiscriminator = false): AccountNode<StructTypeNode> {
const idlName = idl.name ?? '';
const name = camelCase(idlName);
const idlStruct = idl.type ?? { fields: [], kind: 'struct' };
Expand All @@ -30,7 +27,7 @@ export function accountNodeFromAnchorV00(

// Account discriminator.
let discriminators: DiscriminatorNode[] | undefined;
if (origin === 'anchor') {
if (addDiscriminator) {
const discriminator = structFieldTypeNode({
defaultValue: getAnchorAccountDiscriminatorV00(idlName),
defaultValueStrategy: 'omitted',
Expand Down
18 changes: 2 additions & 16 deletions packages/nodes-from-anchor/src/v00/InstructionNode.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {
bytesTypeNode,
bytesValueNode,
camelCase,
DiscriminatorNode,
fieldDiscriminatorNode,
Expand All @@ -17,11 +16,7 @@ import { instructionAccountNodesFromAnchorV00 } from './InstructionAccountNode';
import { instructionArgumentNodeFromAnchorV00 } from './InstructionArgumentNode';
import { typeNodeFromAnchorV00 } from './typeNodes';

export function instructionNodeFromAnchorV00(
idl: IdlV00Instruction,
ixIndex: number,
origin?: 'anchor' | 'shank',
): InstructionNode {
export function instructionNodeFromAnchorV00(idl: IdlV00Instruction, addDiscriminator = false): InstructionNode {
const idlName = idl.name ?? '';
const name = camelCase(idlName);
let dataArguments = (idl.args ?? []).map(instructionArgumentNodeFromAnchorV00);
Expand All @@ -37,7 +32,7 @@ export function instructionNodeFromAnchorV00(
});
dataArguments = [discriminatorField, ...dataArguments];
discriminators = [fieldDiscriminatorNode('discriminator')];
} else if (origin === 'anchor') {
} else if (addDiscriminator) {
const discriminatorField = instructionArgumentNode({
defaultValue: getAnchorInstructionDiscriminatorV00(idlName),
defaultValueStrategy: 'omitted',
Expand All @@ -46,15 +41,6 @@ export function instructionNodeFromAnchorV00(
});
dataArguments = [discriminatorField, ...dataArguments];
discriminators = [fieldDiscriminatorNode('discriminator')];
} else if (origin === 'shank') {
const discriminatorField = instructionArgumentNode({
defaultValue: bytesValueNode('base16', ixIndex.toString(16)),
defaultValueStrategy: 'omitted',
name: 'discriminator',
type: fixedSizeTypeNode(bytesTypeNode(), 1),
});
dataArguments = [discriminatorField, ...dataArguments];
discriminators = [fieldDiscriminatorNode('discriminator')];
}

return instructionNode({
Expand Down
8 changes: 2 additions & 6 deletions packages/nodes-from-anchor/src/v00/ProgramNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,15 @@ import { instructionNodeFromAnchorV00 } from './InstructionNode';
import { pdaNodeFromAnchorV00 } from './PdaNode';

export function programNodeFromAnchorV00(idl: IdlV00): ProgramNode {
const origin = (idl?.metadata as { origin?: 'anchor' | 'shank' })?.origin ?? 'anchor';
const pdas = (idl.accounts ?? []).filter(account => (account.seeds ?? []).length > 0).map(pdaNodeFromAnchorV00);
const accounts = (idl.accounts ?? []).map(a => accountNodeFromAnchorV00(a, origin));
const instructions = (idl.instructions ?? []).map((instruction, index) =>
instructionNodeFromAnchorV00(instruction, index, origin),
);
const accounts = (idl.accounts ?? []).map(a => accountNodeFromAnchorV00(a, true));
const instructions = (idl.instructions ?? []).map(instruction => instructionNodeFromAnchorV00(instruction, true));
return programNode({
accounts,
definedTypes: (idl?.types ?? []).map(definedTypeNodeFromAnchorV00),
errors: (idl?.errors ?? []).map(errorNodeFromAnchorV00),
instructions,
name: idl?.name ?? '',
origin,
pdas,
publicKey: (idl?.metadata as { address?: string })?.address ?? '',
version: idl.version as ProgramVersion,
Expand Down
1 change: 0 additions & 1 deletion packages/nodes-from-anchor/src/v01/ProgramNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ export function programNodeFromAnchorV01(idl: IdlV01): ProgramNode {
errors: errors.map(errorNodeFromAnchorV01),
instructions: instructions.map(instruction => instructionNodeFromAnchorV01(instruction, generics)),
name: idl.metadata.name,
origin: 'anchor',
publicKey: idl.address,
version: idl.metadata.version as ProgramVersion,
});
Expand Down
1 change: 0 additions & 1 deletion packages/nodes-from-anchor/test/rootNodeFromAnchor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ test('it creates root nodes from IDL version 0.0', () => {
rootNode(
programNode({
name: 'myProgram',
origin: 'anchor',
publicKey: '1111',
version: '1.2.3',
}),
Expand Down
2 changes: 1 addition & 1 deletion packages/nodes-from-anchor/test/v00/AccountNode.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ test('it creates account nodes with anchor discriminators', () => {
name: 'myAccount',
type: { fields: [], kind: 'struct' },
},
'anchor',
true,
);

expect(node).toEqual(
Expand Down
16 changes: 6 additions & 10 deletions packages/nodes-from-anchor/test/v00/InstructionNode.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,11 @@ import { expect, test } from 'vitest';
import { instructionNodeFromAnchorV00 } from '../../src';

test('it creates instruction nodes', () => {
const node = instructionNodeFromAnchorV00(
{
accounts: [{ isMut: true, isSigner: false, name: 'mint' }],
args: [{ name: 'amount', type: 'u8' }],
name: 'mintTokens',
},
0,
);
const node = instructionNodeFromAnchorV00({
accounts: [{ isMut: true, isSigner: false, name: 'mint' }],
args: [{ name: 'amount', type: 'u8' }],
name: 'mintTokens',
});

expect(node).toEqual(
instructionNode({
Expand All @@ -38,8 +35,7 @@ test('it creates instruction nodes with anchor discriminators', () => {
args: [],
name: 'myInstruction',
},
0,
'anchor',
true,
);

expect(node).toEqual(
Expand Down
26 changes: 20 additions & 6 deletions packages/nodes-from-anchor/test/v00/ProgramNode.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,41 @@ import {
pdaLinkNode,
pdaNode,
programNode,
structFieldTypeNode,
structTypeNode,
} from '@codama/nodes';
import { expect, test } from 'vitest';

import { programNodeFromAnchorV00 } from '../../src';
import { getAnchorInstructionDiscriminatorV00, programNodeFromAnchorV00 } from '../../src';

test('it creates program nodes', () => {
const node = programNodeFromAnchorV00({
accounts: [{ name: 'myAccount', seeds: [{ kind: 'programId' }], type: { fields: [], kind: 'struct' } }],
errors: [{ code: 42, msg: 'my error message', name: 'myError' }],
instructions: [{ accounts: [], args: [], name: 'myInstruction' }],
metadata: { address: '1111', origin: 'shank' },
metadata: { address: '1111' },
name: 'myProgram',
types: [{ name: 'myType', type: { fields: [], kind: 'struct' } }],
version: '1.2.3',
});

expect(node).toEqual(
programNode({
accounts: [accountNode({ name: 'myAccount', pda: pdaLinkNode('myAccount') })],
accounts: [
accountNode({
data: structTypeNode([
structFieldTypeNode({
defaultValue: bytesValueNode('base16', 'f61c0657fb2d322a'),
defaultValueStrategy: 'omitted',
name: 'discriminator',
type: fixedSizeTypeNode(bytesTypeNode(), 8),
}),
]),
discriminators: [fieldDiscriminatorNode('discriminator')],
name: 'myAccount',
pda: pdaLinkNode('myAccount'),
}),
],
definedTypes: [definedTypeNode({ name: 'myType', type: structTypeNode([]) })],
errors: [
errorNode({
Expand All @@ -45,18 +60,17 @@ test('it creates program nodes', () => {
instructionNode({
arguments: [
instructionArgumentNode({
defaultValue: bytesValueNode('base16', (0).toString(16)),
defaultValue: getAnchorInstructionDiscriminatorV00('myInstruction'),
defaultValueStrategy: 'omitted',
name: 'discriminator',
type: fixedSizeTypeNode(bytesTypeNode(), 1),
type: fixedSizeTypeNode(bytesTypeNode(), 8),
}),
],
discriminators: [fieldDiscriminatorNode('discriminator')],
name: 'myInstruction',
}),
],
name: 'myProgram',
origin: 'shank',
pdas: [pdaNode({ name: 'myAccount', seeds: [constantPdaSeedNodeFromProgramId()] })],
publicKey: '1111',
version: '1.2.3',
Expand Down
1 change: 0 additions & 1 deletion packages/nodes-from-anchor/test/v00/RootNode.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ test('it creates root nodes', () => {
rootNode(
programNode({
name: 'myProgram',
origin: 'anchor',
publicKey: '1111',
version: '1.2.3',
}),
Expand Down
2 changes: 0 additions & 2 deletions packages/nodes-from-anchor/test/v01/ProgramNode.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ test('it creates program nodes', () => {
}),
],
name: 'myProgram',
origin: 'anchor',
pdas: [],
publicKey: '1111',
version: '1.2.3',
Expand Down Expand Up @@ -300,7 +299,6 @@ test('it unwraps and removes generic types', () => {
}),
],
name: 'myProgram',
origin: 'anchor',
pdas: [],
publicKey: '1111',
version: '1.2.3',
Expand Down
1 change: 0 additions & 1 deletion packages/nodes-from-anchor/test/v01/RootNode.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ test('it creates root nodes', () => {
rootNode(
programNode({
name: 'myProgram',
origin: 'anchor',
publicKey: '1111',
version: '1.2.3',
}),
Expand Down
15 changes: 7 additions & 8 deletions packages/nodes/docs/ProgramNode.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,13 @@ This node represents an entire program deployed on-chain. It defines all element

### Data

| Attribute | Type | Description |
| ----------- | ----------------------- | ---------------------------------------------------------------------------- |
| `kind` | `"programNode"` | The node discriminator. |
| `name` | `CamelCaseString` | The name of the program. |
| `publicKey` | `string` | The 32-bytes address of the program base58 encoded. |
| `version` | `\d.\d.\d` | The semantic version of the program being defined. |
| `docs` | `string[]` | Markdown documentation for the program. |
| `origin` | `"anchor"` \| `"shank"` | (Optional) An optional attribute tells us how this program node was created. |
| Attribute | Type | Description |
| ----------- | ----------------- | --------------------------------------------------- |
| `kind` | `"programNode"` | The node discriminator. |
| `name` | `CamelCaseString` | The name of the program. |
| `publicKey` | `string` | The 32-bytes address of the program base58 encoded. |
| `version` | `\d.\d.\d` | The semantic version of the program being defined. |
| `docs` | `string[]` | Markdown documentation for the program. |

### Children

Expand Down
1 change: 0 additions & 1 deletion packages/nodes/src/ProgramNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ export function programNode<
name: camelCase(input.name),
publicKey: input.publicKey,
version: input.version ?? '0.0.0',
...(input.origin !== undefined && { origin: input.origin }),
docs: parseDocs(input.docs),

// Children.
Expand Down
3 changes: 0 additions & 3 deletions packages/validators/src/getValidationItemsVisitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,6 @@ export function getValidationItemsVisitor(): Visitor<readonly ValidationItem[]>
if (!node.version) {
items.push(validationItem('warn', 'Program has no version.', node, stack));
}
if (!node.origin) {
items.push(validationItem('info', 'Program has no origin.', node, stack));
}
return [...items, ...next(node)];
},

Expand Down
2 changes: 0 additions & 2 deletions packages/validators/test/getValidationItemsVisitor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ test('it validates program nodes', () => {
errors: [],
instructions: [],
name: '',
origin: undefined,
publicKey: '',
// @ts-expect-error Empty string does not match ProgramVersion.
version: '',
Expand All @@ -26,7 +25,6 @@ test('it validates program nodes', () => {
validationItem('error', 'Program has no name.', node, []),
validationItem('error', 'Program has no public key.', node, []),
validationItem('warn', 'Program has no version.', node, []),
validationItem('info', 'Program has no origin.', node, []),
]);
});

Expand Down