From a0b8d907487511e36d730262351ad28cfbc6fb6b Mon Sep 17 00:00:00 2001 From: Loris Leiva Date: Mon, 15 Apr 2024 11:22:28 +0100 Subject: [PATCH] Support nested instruction accounts from IDL (#213) Fix #210 --- .changeset/cool-rockets-smash.md | 5 +++++ src/idl/IdlInstruction.ts | 7 ++++++- src/nodes/InstructionAccountNode.ts | 12 +++++++++++- src/nodes/InstructionNode.ts | 6 ++---- 4 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 .changeset/cool-rockets-smash.md diff --git a/.changeset/cool-rockets-smash.md b/.changeset/cool-rockets-smash.md new file mode 100644 index 000000000..77d7bdd4d --- /dev/null +++ b/.changeset/cool-rockets-smash.md @@ -0,0 +1,5 @@ +--- +"@metaplex-foundation/kinobi": patch +--- + +Support nested instruction accounts from IDL diff --git a/src/idl/IdlInstruction.ts b/src/idl/IdlInstruction.ts index 891d33117..e058b8d3c 100644 --- a/src/idl/IdlInstruction.ts +++ b/src/idl/IdlInstruction.ts @@ -2,7 +2,7 @@ import type { IdlType } from './IdlType'; export type IdlInstruction = { name: string; - accounts: IdlInstructionAccount[]; + accounts: (IdlInstructionAccount | IdlInstructionNestedAccounts)[]; args: IdlInstructionArg[]; defaultOptionalAccounts?: boolean; legacyOptionalAccountsStrategy?: boolean; @@ -21,6 +21,11 @@ export type IdlInstructionAccount = { desc?: string; }; +export type IdlInstructionNestedAccounts = { + name: string; + accounts: (IdlInstructionAccount | IdlInstructionNestedAccounts)[]; +}; + export type IdlInstructionArg = { name: string; type: IdlType; diff --git a/src/nodes/InstructionAccountNode.ts b/src/nodes/InstructionAccountNode.ts index 68d2b5bda..2cd3dc440 100644 --- a/src/nodes/InstructionAccountNode.ts +++ b/src/nodes/InstructionAccountNode.ts @@ -1,4 +1,4 @@ -import { IdlInstructionAccount } from '../idl'; +import { IdlInstructionAccount, IdlInstructionNestedAccounts } from '../idl'; import { MainCaseString, PartialExcept, mainCase } from '../shared'; import { InstructionInputValueNode } from './contextualValueNodes'; @@ -50,6 +50,16 @@ export function instructionAccountNode< }; } +export function instructionAccountNodesFromIdl( + idl: (IdlInstructionAccount | IdlInstructionNestedAccounts)[] +): InstructionAccountNode[] { + return idl.flatMap((account) => + 'accounts' in account + ? instructionAccountNodesFromIdl(account.accounts) + : [instructionAccountNodeFromIdl(account)] + ); +} + export function instructionAccountNodeFromIdl( idl: IdlInstructionAccount ): InstructionAccountNode { diff --git a/src/nodes/InstructionNode.ts b/src/nodes/InstructionNode.ts index 650a2c541..f81d7dde8 100644 --- a/src/nodes/InstructionNode.ts +++ b/src/nodes/InstructionNode.ts @@ -2,7 +2,7 @@ import type { IdlInstruction } from '../idl'; import { InvalidKinobiTreeError, MainCaseString, mainCase } from '../shared'; import { InstructionAccountNode, - instructionAccountNodeFromIdl, + instructionAccountNodesFromIdl, } from './InstructionAccountNode'; import { InstructionArgumentNode, @@ -171,9 +171,7 @@ export function instructionNodeFromIdl( name, idlName, docs: idl.docs ?? [], - accounts: (idl.accounts ?? []).map((account) => - instructionAccountNodeFromIdl(account) - ), + accounts: instructionAccountNodesFromIdl(idl.accounts ?? []), arguments: dataArguments, discriminators, optionalAccountStrategy: idl.legacyOptionalAccountsStrategy