Skip to content

Commit

Permalink
fix: filtering pdas from instruction accounts.
Browse files Browse the repository at this point in the history
  • Loading branch information
kespinola committed May 6, 2024
1 parent 4418cdf commit b880ad7
Show file tree
Hide file tree
Showing 11 changed files with 68 additions and 32 deletions.
9 changes: 7 additions & 2 deletions packages/errors/src/codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const KINOBI_ERROR__UNRECOGNIZED_NODE_KIND = 1 as const;
export const KINOBI_ERROR__UNEXPECTED_NODE_KIND = 2 as const;
export const KINOBI_ERROR__UNEXPECTED_NESTED_NODE_KIND = 3 as const;
export const KINOBI_ERROR__LINKED_NODE_NOT_FOUND = 4 as const;
export const KINOBI_ERROR__UNRECOGNIZED_ANCHOR_IDL_TYPE = 5 as const;
export const KINOBI_ERROR__ANCHOR__UNRECOGNIZED_IDL_TYPE = 5 as const;
export const KINOBI_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE = 6 as const;

// Visitors-related errors.
Expand All @@ -48,6 +48,10 @@ export const KINOBI_ERROR__VISITORS__INSTRUCTION_ENUM_ARGUMENT_NOT_FOUND = 12000
export const KINOBI_ERROR__VISITORS__CANNOT_FLATTEN_STRUCT_WITH_CONFLICTING_ATTRIBUTES = 1200010 as const;
export const KINOBI_ERROR__VISITORS__RENDER_MAP_KEY_NOT_FOUND = 1200011 as const;

// Anchor-related errors.
// Reserve error codes in the range [1300000-1300999].
export const KINOBI_ERROR__ANCHOR__ACCOUNT_TYPE_MISSING = 1300000 as const;

/**
* A union of every Kinobi error code
*
Expand All @@ -64,11 +68,12 @@ export const KINOBI_ERROR__VISITORS__RENDER_MAP_KEY_NOT_FOUND = 1200011 as const
* is not safe, for a variety of reasons covered here: https://stackoverflow.com/a/28818850
*/
export type KinobiErrorCode =
| typeof KINOBI_ERROR__ANCHOR__ACCOUNT_TYPE_MISSING
| typeof KINOBI_ERROR__ANCHOR__UNRECOGNIZED_IDL_TYPE
| typeof KINOBI_ERROR__LINKED_NODE_NOT_FOUND
| typeof KINOBI_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE
| typeof KINOBI_ERROR__UNEXPECTED_NESTED_NODE_KIND
| typeof KINOBI_ERROR__UNEXPECTED_NODE_KIND
| typeof KINOBI_ERROR__UNRECOGNIZED_ANCHOR_IDL_TYPE
| typeof KINOBI_ERROR__UNRECOGNIZED_NODE_KIND
| typeof KINOBI_ERROR__VISITORS__ACCOUNT_FIELD_NOT_FOUND
| typeof KINOBI_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_PDA_NAMES
Expand Down
8 changes: 4 additions & 4 deletions packages/errors/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ import {
} from '@kinobi-so/node-types';

import {
KINOBI_ERROR__ANCHOR__UNRECOGNIZED_IDL_TYPE,
KINOBI_ERROR__LINKED_NODE_NOT_FOUND,
KINOBI_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE,
KINOBI_ERROR__UNEXPECTED_NESTED_NODE_KIND,
KINOBI_ERROR__UNEXPECTED_NODE_KIND,
KINOBI_ERROR__UNRECOGNIZED_ANCHOR_IDL_TYPE,
KINOBI_ERROR__UNRECOGNIZED_NODE_KIND,
KINOBI_ERROR__VISITORS__ACCOUNT_FIELD_NOT_FOUND,
KINOBI_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_PDA_NAMES,
Expand All @@ -49,6 +49,9 @@ type DefaultUnspecifiedErrorContextToUndefined<T> = {
* - Don't change or remove members of an error's context.
*/
export type KinobiErrorContext = DefaultUnspecifiedErrorContextToUndefined<{
[KINOBI_ERROR__ANCHOR__UNRECOGNIZED_IDL_TYPE]: {
idlType: string;
};
[KINOBI_ERROR__LINKED_NODE_NOT_FOUND]: {
kind: LinkNode['kind'];
linkNode: LinkNode;
Expand All @@ -67,9 +70,6 @@ export type KinobiErrorContext = DefaultUnspecifiedErrorContextToUndefined<{
kind: NodeKind | null;
node: Node | null | undefined;
};
[KINOBI_ERROR__UNRECOGNIZED_ANCHOR_IDL_TYPE]: {
idlType: string;
};
[KINOBI_ERROR__UNRECOGNIZED_NODE_KIND]: {
kind: string;
};
Expand Down
6 changes: 4 additions & 2 deletions packages/errors/src/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
*/

import {
KINOBI_ERROR__ANCHOR__ACCOUNT_TYPE_MISSING,
KINOBI_ERROR__ANCHOR__UNRECOGNIZED_IDL_TYPE,
KINOBI_ERROR__LINKED_NODE_NOT_FOUND,
KINOBI_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE,
KINOBI_ERROR__UNEXPECTED_NESTED_NODE_KIND,
KINOBI_ERROR__UNEXPECTED_NODE_KIND,
KINOBI_ERROR__UNRECOGNIZED_ANCHOR_IDL_TYPE,
KINOBI_ERROR__UNRECOGNIZED_NODE_KIND,
KINOBI_ERROR__VISITORS__ACCOUNT_FIELD_NOT_FOUND,
KINOBI_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_PDA_NAMES,
Expand All @@ -34,12 +35,13 @@ export const KinobiErrorMessages: Readonly<{
// TypeScript will fail to build this project if add an error code without a message.
[P in KinobiErrorCode]: string;
}> = {
[KINOBI_ERROR__ANCHOR__ACCOUNT_TYPE_MISSING]: 'Account type [$name] is missing from the IDL types.',
[KINOBI_ERROR__ANCHOR__UNRECOGNIZED_IDL_TYPE]: 'Unrecognized Anchor IDL type [$idlType].',
[KINOBI_ERROR__LINKED_NODE_NOT_FOUND]: 'Could not found linked node [$name] from [$kind].',
[KINOBI_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE]:
'Node.js filesystem function [$fsFunction] is not available in your environment.',
[KINOBI_ERROR__UNEXPECTED_NESTED_NODE_KIND]: 'Expected nested node of kind [$expectedKinds], got [$kind]',
[KINOBI_ERROR__UNEXPECTED_NODE_KIND]: 'Expected node of kind [$expectedKinds], got [$kind].',
[KINOBI_ERROR__UNRECOGNIZED_ANCHOR_IDL_TYPE]: 'Unrecognized Anchor IDL type [$idlType].',
[KINOBI_ERROR__UNRECOGNIZED_NODE_KIND]: 'Unrecognized node kind [$kind].',
[KINOBI_ERROR__VISITORS__ACCOUNT_FIELD_NOT_FOUND]: 'Account [$name] does not have a field named [$missingField].',
[KINOBI_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_PDA_NAMES]:
Expand Down
6 changes: 3 additions & 3 deletions packages/nodes-from-anchor/src/v00/typeNodes/TypeNode.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { KINOBI_ERROR__UNRECOGNIZED_ANCHOR_IDL_TYPE, KinobiError } from '@kinobi-so/errors';
import { KINOBI_ERROR__ANCHOR__UNRECOGNIZED_IDL_TYPE, KinobiError } from '@kinobi-so/errors';
import {
booleanTypeNode,
bytesTypeNode,
Expand Down Expand Up @@ -59,7 +59,7 @@ export const typeNodeFromAnchorV00 = (idlType: IdlV00Type | IdlV00TypeDefTy): Ty

// Ensure eveything else is an object.
if (typeof idlType !== 'object') {
throw new KinobiError(KINOBI_ERROR__UNRECOGNIZED_ANCHOR_IDL_TYPE, {
throw new KinobiError(KINOBI_ERROR__ANCHOR__UNRECOGNIZED_IDL_TYPE, {
idlType: JSON.stringify(idlType),
});
}
Expand Down Expand Up @@ -112,7 +112,7 @@ export const typeNodeFromAnchorV00 = (idlType: IdlV00Type | IdlV00TypeDefTy): Ty
return tupleTypeNodeFromAnchorV00(idlType as IdlV00TypeTuple);
}

throw new KinobiError(KINOBI_ERROR__UNRECOGNIZED_ANCHOR_IDL_TYPE, {
throw new KinobiError(KINOBI_ERROR__ANCHOR__UNRECOGNIZED_IDL_TYPE, {
idlType: JSON.stringify(idlType),
});
};
Expand Down
20 changes: 9 additions & 11 deletions packages/nodes-from-anchor/src/v01/AccountNode.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { KINOBI_ERROR__VISITORS__ACCOUNT_FIELD_NOT_FOUND, KinobiError } from '@kinobi-so/errors';
import { KINOBI_ERROR__ANCHOR__ACCOUNT_TYPE_MISSING, KinobiError } from '@kinobi-so/errors';
import {
AccountNode,
accountNode,
assertIsNode,
bytesTypeNode,
camelCase,
fieldDiscriminatorNode,
Expand All @@ -10,8 +11,8 @@ import {
} from '@kinobi-so/nodes';

import { getAnchorDiscriminatorV01 } from './../discriminators';
import { IdlV01Account, IdlV01TypeDef, IdlV01TypeDefTyStruct } from './idl';
import { structTypeNodeFromAnchorV01 } from './typeNodes';
import { IdlV01Account, IdlV01TypeDef } from './idl';
import { typeNodeFromAnchorV01 } from './typeNodes';

export function accountNodeFromAnchorV01(idl: IdlV01Account, types: IdlV01TypeDef[]): AccountNode {
const idlName = idl.name;
Expand All @@ -20,16 +21,13 @@ export function accountNodeFromAnchorV01(idl: IdlV01Account, types: IdlV01TypeDe
const type = types.find(t => t.name === idl.name);

if (!type) {
throw new KinobiError(KINOBI_ERROR__VISITORS__ACCOUNT_FIELD_NOT_FOUND, {});
throw new KinobiError(KINOBI_ERROR__ANCHOR__ACCOUNT_TYPE_MISSING, {
name,
});
}

if (type.type.kind !== 'struct') {
throw new KinobiError(KINOBI_ERROR__VISITORS__ACCOUNT_FIELD_NOT_FOUND, {});
}

const idlTypeStruct = type.type as IdlV01TypeDefTyStruct;

const data = structTypeNodeFromAnchorV01(idlTypeStruct);
const data = typeNodeFromAnchorV01(type.type);
assertIsNode(data, 'structTypeNode');

const discriminator = structFieldTypeNode({
defaultValue: getAnchorDiscriminatorV01(idl.discriminator),
Expand Down
6 changes: 3 additions & 3 deletions packages/nodes-from-anchor/src/v01/PdaNode.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { KINOBI_ERROR__UNRECOGNIZED_ANCHOR_IDL_TYPE, KinobiError } from '@kinobi-so/errors';
import { KINOBI_ERROR__ANCHOR__UNRECOGNIZED_IDL_TYPE, KinobiError } from '@kinobi-so/errors';
import {
bytesTypeNode,
camelCase,
Expand All @@ -21,12 +21,12 @@ export function pdaNodeFromAnchorV01(idl: IdlV01InstructionAccount): PdaNode {
case 'account':
return variablePdaSeedNode(seed.path, publicKeyTypeNode());
case 'arg':
throw new KinobiError(KINOBI_ERROR__UNRECOGNIZED_ANCHOR_IDL_TYPE, { idlType: seed });
throw new KinobiError(KINOBI_ERROR__ANCHOR__UNRECOGNIZED_IDL_TYPE, { idlType: seed });
}
});

if (!seeds) {
throw new KinobiError(KINOBI_ERROR__UNRECOGNIZED_ANCHOR_IDL_TYPE, { idlType: idl });
throw new KinobiError(KINOBI_ERROR__ANCHOR__UNRECOGNIZED_IDL_TYPE, { idlType: idl });
}

const name = camelCase(idl.name);
Expand Down
2 changes: 1 addition & 1 deletion packages/nodes-from-anchor/src/v01/ProgramNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function programNodeFromAnchorV01(idl: IdlV01): ProgramNode {
const accountNodeFromAnchorV01 = accountNodeFromAnchorV01WithTypeDefinition(types);
const pdas = instructions
.flatMap<IdlV01InstructionAccount>(instruction => instruction.accounts)
.filter(account => !account.pda?.program)
.filter(account => !!account.pda && !account.pda?.program)
.map(pdaNodeFromAnchorV01);

return programNode({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { KINOBI_ERROR__UNRECOGNIZED_ANCHOR_IDL_TYPE, KinobiError } from '@kinobi-so/errors';
import { KINOBI_ERROR__ANCHOR__UNRECOGNIZED_IDL_TYPE, KinobiError } from '@kinobi-so/errors';
import { StructFieldTypeNode, structFieldTypeNode } from '@kinobi-so/nodes';

import { IdlV01Field, IdlV01Type } from '../idl';
Expand All @@ -17,7 +17,7 @@ export function structFieldTypeNodeFromAnchorV01(idl: IdlV01Field | IdlV01Type):
});
}

throw new KinobiError(KINOBI_ERROR__UNRECOGNIZED_ANCHOR_IDL_TYPE, {
throw new KinobiError(KINOBI_ERROR__ANCHOR__UNRECOGNIZED_IDL_TYPE, {
idlType: JSON.stringify(idl),
});
}
6 changes: 3 additions & 3 deletions packages/nodes-from-anchor/src/v01/typeNodes/TypeNode.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { KINOBI_ERROR__UNRECOGNIZED_ANCHOR_IDL_TYPE, KinobiError } from '@kinobi-so/errors';
import { KINOBI_ERROR__ANCHOR__UNRECOGNIZED_IDL_TYPE, KinobiError } from '@kinobi-so/errors';
import {
booleanTypeNode,
bytesTypeNode,
Expand Down Expand Up @@ -57,7 +57,7 @@ export const typeNodeFromAnchorV01 = (idlType: IdlV01Type | IdlV01TypeDefTy): Ty

// Ensure eveything else is an object.
if (typeof idlType !== 'object') {
throw new KinobiError(KINOBI_ERROR__UNRECOGNIZED_ANCHOR_IDL_TYPE, {
throw new KinobiError(KINOBI_ERROR__ANCHOR__UNRECOGNIZED_IDL_TYPE, {
idlType: JSON.stringify(idlType),
});
}
Expand Down Expand Up @@ -101,7 +101,7 @@ export const typeNodeFromAnchorV01 = (idlType: IdlV01Type | IdlV01TypeDefTy): Ty
return structTypeNodeFromAnchorV01(idlType as IdlV01TypeDefTyStruct);
}

throw new KinobiError(KINOBI_ERROR__UNRECOGNIZED_ANCHOR_IDL_TYPE, {
throw new KinobiError(KINOBI_ERROR__ANCHOR__UNRECOGNIZED_IDL_TYPE, {
idlType: JSON.stringify(idlType),
});
};
Expand Down
8 changes: 8 additions & 0 deletions packages/nodes-from-anchor/test/v01/ProgramNode.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ test('it creates program nodes', () => {
],
},
},
{
name: 'some_account',
},
],
args: [],
discriminator: [246, 28, 6, 87, 251, 45, 50, 42],
Expand Down Expand Up @@ -79,6 +82,11 @@ test('it creates program nodes', () => {
isWritable: false,
name: 'authority',
}),
instructionAccountNode({
isSigner: false,
isWritable: false,
name: 'someAccount',
}),
],
arguments: [
instructionArgumentNode({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { numberTypeNode, publicKeyTypeNode, tupleTypeNode } from '@kinobi-so/nodes';
import {
numberTypeNode,
publicKeyTypeNode,
structFieldTypeNode,
structTypeNode,
tupleTypeNode,
} from '@kinobi-so/nodes';
import { expect, test } from 'vitest';

import { typeNodeFromAnchorV01 } from '../../../src/index.js';
Expand All @@ -11,3 +17,20 @@ test('it creates tuple type nodes', () => {

expect(node).toEqual(tupleTypeNode([numberTypeNode('u8'), publicKeyTypeNode()]));
});

test('it creates struct type when defined field names', () => {
const node = typeNodeFromAnchorV01({
fields: [
{ name: 'symbol', type: 'u8' },
{ name: 'mint', type: 'pubkey' },
],
kind: 'struct',
});

expect(node).toEqual(
structTypeNode([
structFieldTypeNode({ name: 'symbol', type: numberTypeNode('u8') }),
structFieldTypeNode({ name: 'mint', type: publicKeyTypeNode() }),
]),
);
});

0 comments on commit b880ad7

Please sign in to comment.