Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2.x] Add instruction bundles #143

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ node_modules
# misc
.DS_Store
*.pem
.idea
.vscode

# debug
npm-debug.log*
Expand Down
5 changes: 5 additions & 0 deletions packages/errors/src/codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export const KINOBI_ERROR__VISITORS__FAILED_TO_VALIDATE_NODE = 1200008 as const;
export const KINOBI_ERROR__VISITORS__INSTRUCTION_ENUM_ARGUMENT_NOT_FOUND = 1200009 as const;
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;
export const KINOBI_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_ADDITIONAL_PROGRAMS = 1200012 as const;
export const KINOBI_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_INSTRUCTION_BUNDLE_NAMES = 1200013 as const;

// Anchor-related errors.
// Reserve error codes in the range [2100000-2100999].
Expand Down Expand Up @@ -89,6 +91,8 @@ export type KinobiErrorCode =
| typeof KINOBI_ERROR__UNRECOGNIZED_NODE_KIND
| typeof KINOBI_ERROR__VERSION_MISMATCH
| typeof KINOBI_ERROR__VISITORS__ACCOUNT_FIELD_NOT_FOUND
| typeof KINOBI_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_ADDITIONAL_PROGRAMS
| typeof KINOBI_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_INSTRUCTION_BUNDLE_NAMES
| typeof KINOBI_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_PDA_NAMES
| typeof KINOBI_ERROR__VISITORS__CANNOT_EXTEND_MISSING_VISIT_FUNCTION
| typeof KINOBI_ERROR__VISITORS__CANNOT_FLATTEN_STRUCT_WITH_CONFLICTING_ATTRIBUTES
Expand All @@ -100,3 +104,4 @@ export type KinobiErrorCode =
| typeof KINOBI_ERROR__VISITORS__INVALID_NUMBER_WRAPPER
| typeof KINOBI_ERROR__VISITORS__INVALID_PDA_SEED_VALUES
| typeof KINOBI_ERROR__VISITORS__RENDER_MAP_KEY_NOT_FOUND;

12 changes: 12 additions & 0 deletions packages/errors/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import {
KINOBI_ERROR__UNRECOGNIZED_NODE_KIND,
KINOBI_ERROR__VERSION_MISMATCH,
KINOBI_ERROR__VISITORS__ACCOUNT_FIELD_NOT_FOUND,
KINOBI_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_ADDITIONAL_PROGRAMS,
KINOBI_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_INSTRUCTION_BUNDLE_NAMES,
KINOBI_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_PDA_NAMES,
KINOBI_ERROR__VISITORS__CANNOT_EXTEND_MISSING_VISIT_FUNCTION,
KINOBI_ERROR__VISITORS__CANNOT_FLATTEN_STRUCT_WITH_CONFLICTING_ATTRIBUTES,
Expand Down Expand Up @@ -105,6 +107,16 @@ export type KinobiErrorContext = DefaultUnspecifiedErrorContextToUndefined<{
missingField: CamelCaseString;
name: CamelCaseString;
};
[KINOBI_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_ADDITIONAL_PROGRAMS]: {
duplicatedProgramNames: CamelCaseString[];
program: ProgramNode;
programName: CamelCaseString;
};
[KINOBI_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_INSTRUCTION_BUNDLE_NAMES]: {
duplicatedInstructionBundleNames: CamelCaseString[];
program: ProgramNode;
programName: CamelCaseString;
};
[KINOBI_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_PDA_NAMES]: {
duplicatedPdaNames: CamelCaseString[];
program: ProgramNode;
Expand Down
8 changes: 7 additions & 1 deletion packages/errors/src/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {
KINOBI_ERROR__UNRECOGNIZED_NODE_KIND,
KINOBI_ERROR__VERSION_MISMATCH,
KINOBI_ERROR__VISITORS__ACCOUNT_FIELD_NOT_FOUND,
KINOBI_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_ADDITIONAL_PROGRAMS,
KINOBI_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_INSTRUCTION_BUNDLE_NAMES,
KINOBI_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_PDA_NAMES,
KINOBI_ERROR__VISITORS__CANNOT_EXTEND_MISSING_VISIT_FUNCTION,
KINOBI_ERROR__VISITORS__CANNOT_FLATTEN_STRUCT_WITH_CONFLICTING_ATTRIBUTES,
Expand All @@ -28,7 +30,7 @@ import {
KINOBI_ERROR__VISITORS__INVALID_NUMBER_WRAPPER,
KINOBI_ERROR__VISITORS__INVALID_PDA_SEED_VALUES,
KINOBI_ERROR__VISITORS__RENDER_MAP_KEY_NOT_FOUND,
KinobiErrorCode,
KinobiErrorCode
} from './codes';

/**
Expand All @@ -55,6 +57,10 @@ export const KinobiErrorMessages: Readonly<{
[KINOBI_ERROR__VERSION_MISMATCH]:
'The provided RootNode version [$rootVersion] is not compatible with the installed Kinobi version [$kinobiVersion].',
[KINOBI_ERROR__VISITORS__ACCOUNT_FIELD_NOT_FOUND]: 'Account [$name] does not have a field named [$missingField].',
[KINOBI_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_ADDITIONAL_PROGRAMS]:
'Cannot add additional program to program [$programName] because the following programs already exist [$duplicatedProgramPublicKeys].',
[KINOBI_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_INSTRUCTION_BUNDLE_NAMES]:
'Cannot add instruction bundles to program [$programName] because the following bundles already exist [$duplicatedInstructionBundleNames].',
[KINOBI_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_PDA_NAMES]:
'Cannot add PDAs to program [$programName] because the following PDA names already exist [$duplicatedPdaNames].',
[KINOBI_ERROR__VISITORS__CANNOT_EXTEND_MISSING_VISIT_FUNCTION]:
Expand Down
17 changes: 17 additions & 0 deletions packages/node-types/src/InstructionBundleNode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { InstructionLinkNode } from './linkNodes';
import { OverrideNode } from './overrideNodes';
import type { CamelCaseString } from './shared';

export interface InstructionBundleNode<
TInstructions extends InstructionLinkNode[] = InstructionLinkNode[],
TOverrides extends OverrideNode[] | undefined = OverrideNode[] | undefined,
> {
readonly kind: 'instructionBundleNode';

// Data.
readonly name: CamelCaseString;

// Children.
readonly instructions: TInstructions;
readonly override?: TOverrides;
}
4 changes: 4 additions & 0 deletions packages/node-types/src/Node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import type { RegisteredDiscriminatorNode } from './discriminatorNodes/Discrimin
import type { ErrorNode } from './ErrorNode';
import type { InstructionAccountNode } from './InstructionAccountNode';
import type { InstructionArgumentNode } from './InstructionArgumentNode';
import type { InstructionBundleNode } from './InstructionBundleNode';
import type { InstructionByteDeltaNode } from './InstructionByteDeltaNode';
import type { InstructionNode } from './InstructionNode';
import type { InstructionRemainingAccountsNode } from './InstructionRemainingAccountsNode';
import type { RegisteredLinkNode } from './linkNodes/LinkNode';
import type { RegisteredOverrideNode } from './overrideNodes/OverrideNode';
import type { PdaNode } from './PdaNode';
import type { RegisteredPdaSeedNode } from './pdaSeedNodes/PdaSeedNode';
import type { ProgramNode } from './ProgramNode';
Expand All @@ -25,6 +27,7 @@ export type Node =
| ErrorNode
| InstructionAccountNode
| InstructionArgumentNode
| InstructionBundleNode
| InstructionByteDeltaNode
| InstructionNode
| InstructionRemainingAccountsNode
Expand All @@ -34,6 +37,7 @@ export type Node =
| RegisteredCountNode
| RegisteredDiscriminatorNode
| RegisteredLinkNode
| RegisteredOverrideNode
| RegisteredPdaSeedNode
| RegisteredTypeNode
| RegisteredValueNode
Expand Down
3 changes: 3 additions & 0 deletions packages/node-types/src/ProgramNode.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { AccountNode } from './AccountNode';
import type { DefinedTypeNode } from './DefinedTypeNode';
import type { ErrorNode } from './ErrorNode';
import { InstructionBundleNode } from './InstructionBundleNode';
import type { InstructionNode } from './InstructionNode';
import type { PdaNode } from './PdaNode';
import type { CamelCaseString, Docs, ProgramVersion } from './shared';
Expand All @@ -9,6 +10,7 @@ export interface ProgramNode<
TPdas extends PdaNode[] = PdaNode[],
TAccounts extends AccountNode[] = AccountNode[],
TInstructions extends InstructionNode[] = InstructionNode[],
TInstructionBundles extends InstructionBundleNode[] = InstructionBundleNode[],
TDefinedTypes extends DefinedTypeNode[] = DefinedTypeNode[],
TErrors extends ErrorNode[] = ErrorNode[],
> {
Expand All @@ -24,6 +26,7 @@ export interface ProgramNode<
// Children.
readonly accounts: TAccounts;
readonly instructions: TInstructions;
readonly instructionBundles?: TInstructionBundles;
readonly definedTypes: TDefinedTypes;
readonly pdas: TPdas;
readonly errors: TErrors;
Expand Down
2 changes: 2 additions & 0 deletions packages/node-types/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from './DefinedTypeNode';
export * from './ErrorNode';
export * from './InstructionAccountNode';
export * from './InstructionArgumentNode';
export * from './InstructionBundleNode';
export * from './InstructionByteDeltaNode';
export * from './InstructionNode';
export * from './InstructionRemainingAccountsNode';
Expand All @@ -19,3 +20,4 @@ export * from './pdaSeedNodes';
export * from './shared';
export * from './typeNodes';
export * from './valueNodes';
export * from './overrideNodes';
4 changes: 3 additions & 1 deletion packages/node-types/src/linkNodes/AccountLinkNode.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import type { CamelCaseString, ImportFrom } from '../shared';
import { ProgramLinkNode } from './ProgramLinkNode';

export interface AccountLinkNode {
export interface AccountLinkNode <TProgram extends ProgramLinkNode | undefined = ProgramLinkNode | undefined>{
readonly kind: 'accountLinkNode';

// Data.
readonly name: CamelCaseString;
readonly importFrom?: ImportFrom;
readonly program?: TProgram;
}
13 changes: 13 additions & 0 deletions packages/node-types/src/linkNodes/InstructionAccountLinkNode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { CamelCaseString, ImportFrom } from '../shared';
import { InstructionLinkNode } from './InstructionLinkNode';

export interface InstructionAccountLinkNode<
TInstruction extends InstructionLinkNode = InstructionLinkNode
> {
readonly kind: 'instructionAccountLinkNode';

// Data.
readonly name: CamelCaseString;
readonly instruction: TInstruction;
readonly importFrom?: ImportFrom;
}
13 changes: 13 additions & 0 deletions packages/node-types/src/linkNodes/InstructionArgumentLinkNode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { CamelCaseString, ImportFrom } from '../shared';
import { InstructionLinkNode } from './InstructionLinkNode';

export interface InstructionArgumentLinkNode<
TInstruction extends InstructionLinkNode = InstructionLinkNode
> {
readonly kind: 'instructionArgumentLinkNode';

// Data.
readonly name: CamelCaseString;
readonly instruction: TInstruction;
readonly importFrom?: ImportFrom;
}
11 changes: 11 additions & 0 deletions packages/node-types/src/linkNodes/InstructionLinkNode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { CamelCaseString, ImportFrom } from '../shared';
import { ProgramLinkNode } from './ProgramLinkNode';

export interface InstructionLinkNode<TProgram extends ProgramLinkNode | undefined = ProgramLinkNode | undefined> {
readonly kind: 'instructionLinkNode';

// Data.
readonly name: CamelCaseString;
readonly importFrom?: ImportFrom;
readonly program?: TProgram;
}
5 changes: 4 additions & 1 deletion packages/node-types/src/linkNodes/LinkNode.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import type { AccountLinkNode } from './AccountLinkNode';
import type { DefinedTypeLinkNode } from './DefinedTypeLinkNode';
import { InstructionAccountLinkNode } from './InstructionAccountLinkNode';
import { InstructionArgumentLinkNode } from './InstructionArgumentLinkNode';
import type { InstructionLinkNode } from './InstructionLinkNode';
import type { PdaLinkNode } from './PdaLinkNode';
import type { ProgramLinkNode } from './ProgramLinkNode';

// Link Node Registration.
export type RegisteredLinkNode = AccountLinkNode | DefinedTypeLinkNode | PdaLinkNode | ProgramLinkNode;
export type RegisteredLinkNode = AccountLinkNode | DefinedTypeLinkNode | InstructionAccountLinkNode | InstructionArgumentLinkNode | InstructionLinkNode | PdaLinkNode | ProgramLinkNode;

// Link Node Helpers.
export type LinkNode = RegisteredLinkNode;
4 changes: 3 additions & 1 deletion packages/node-types/src/linkNodes/PdaLinkNode.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import type { CamelCaseString, ImportFrom } from '../shared';
import { ProgramLinkNode } from './ProgramLinkNode';

export interface PdaLinkNode {
export interface PdaLinkNode <TProgram extends ProgramLinkNode | undefined = ProgramLinkNode | undefined> {
readonly kind: 'pdaLinkNode';

// Data.
readonly name: CamelCaseString;
readonly importFrom?: ImportFrom;
readonly program?: TProgram;
}
3 changes: 3 additions & 0 deletions packages/node-types/src/linkNodes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ export * from './DefinedTypeLinkNode';
export * from './LinkNode';
export * from './PdaLinkNode';
export * from './ProgramLinkNode';
export * from './InstructionLinkNode';
export * from './InstructionArgumentLinkNode';
export * from './InstructionAccountLinkNode';
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { AccountNode } from '../AccountNode';
import { InstructionAccountLinkNode } from '../linkNodes';
import type { CamelCaseString, ImportFrom } from '../shared';

export interface InstructionAccountOverrideNode<
TAccounts extends InstructionAccountLinkNode[] = InstructionAccountLinkNode[],
TDefaultAccount extends AccountNode | undefined = AccountNode | undefined
> {
readonly kind: 'instructionAccountOverrideNode';

// Data.
readonly name: CamelCaseString;
readonly replace?: TAccounts;
readonly defaultAccount?: TDefaultAccount;
readonly importFrom?: ImportFrom;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { InstructionInputValueNode } from '../contextualValueNodes';
import { InstructionArgumentLinkNode } from '../linkNodes';
import type { CamelCaseString, ImportFrom } from '../shared';

export interface InstructionArgumentOverrideNode<
TArguments extends InstructionArgumentLinkNode[] = InstructionArgumentLinkNode[],
TDefaultValue extends InstructionInputValueNode | undefined = InstructionInputValueNode | undefined
> {
readonly kind: 'instructionArgumentOverrideNode';

// Data.
readonly name: CamelCaseString;
readonly replace?: TArguments;
readonly defaultValue?: TDefaultValue;
readonly importFrom?: ImportFrom;
}
8 changes: 8 additions & 0 deletions packages/node-types/src/overrideNodes/OverrideNode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { InstructionAccountOverrideNode } from './InstructionAccountOverrideNode';
import type { InstructionArgumentOverrideNode } from './InstructionArgumentOverrideNode';

// Override Node Registration.
export type RegisteredOverrideNode = InstructionAccountOverrideNode | InstructionArgumentOverrideNode;

// Override Node Helpers.
export type OverrideNode = RegisteredOverrideNode;
3 changes: 3 additions & 0 deletions packages/node-types/src/overrideNodes/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./InstructionAccountOverrideNode";
export * from "./InstructionArgumentOverrideNode";
export * from "./OverrideNode";
30 changes: 30 additions & 0 deletions packages/nodes/src/InstructionBundleNode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type {
InstructionBundleNode,
InstructionLinkNode,
OverrideNode
} from '@kinobi-so/node-types';

import { camelCase } from './shared';

export type InstructionBundleNodeInput<
TInstructions extends InstructionLinkNode[] = InstructionLinkNode[],
TOverrides extends OverrideNode[] | undefined = OverrideNode[] | undefined,
> = Omit<Partial<InstructionBundleNode<TInstructions, TOverrides>>, 'kind' | 'name'> & { readonly name: string; };

export function instructionBundleNode<
TInstructions extends InstructionLinkNode[] = InstructionLinkNode[],
TOverrides extends OverrideNode[] | undefined = OverrideNode[] | undefined,
>(
input: InstructionBundleNodeInput<TInstructions, TOverrides>,
): InstructionBundleNode<TInstructions, TOverrides> {
return Object.freeze({
kind: 'instructionBundleNode',

// Data.
name: camelCase(input.name),

// Children.
instructions: (input.instructions ?? []) as TInstructions,
...(input.override !== undefined && { override: input.override as TOverrides }),
});
}
3 changes: 3 additions & 0 deletions packages/nodes/src/Node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { REGISTERED_CONTEXTUAL_VALUE_NODE_KINDS } from './contextualValueNodes/C
import { REGISTERED_COUNT_NODE_KINDS } from './countNodes/CountNode';
import { REGISTERED_DISCRIMINATOR_NODE_KINDS } from './discriminatorNodes/DiscriminatorNode';
import { REGISTERED_LINK_NODE_KINDS } from './linkNodes/LinkNode';
import { REGISTERED_OVERRIDE_NODE_KINDS } from './overrideNodes/OverrideNode';
import { REGISTERED_PDA_SEED_NODE_KINDS } from './pdaSeedNodes/PdaSeedNode';
import { REGISTERED_TYPE_NODE_KINDS } from './typeNodes/TypeNode';
import { REGISTERED_VALUE_NODE_KINDS } from './valueNodes/ValueNode';
Expand All @@ -18,12 +19,14 @@ export const REGISTERED_NODE_KINDS = [
...REGISTERED_COUNT_NODE_KINDS,
...REGISTERED_TYPE_NODE_KINDS,
...REGISTERED_VALUE_NODE_KINDS,
...REGISTERED_OVERRIDE_NODE_KINDS,
'rootNode' as const,
'programNode' as const,
'pdaNode' as const,
'accountNode' as const,
'instructionAccountNode' as const,
'instructionArgumentNode' as const,
'instructionBundleNode' as const,
'instructionByteDeltaNode' as const,
'instructionNode' as const,
'instructionRemainingAccountsNode' as const,
Expand Down
Loading