@macalinao/codama-instruction-accounts-dedupe-visitor
Version:
Codama visitor for deduplicating instruction accounts from Anchor IDL
52 lines (51 loc) • 2.46 kB
JavaScript
import { instructionAccountNodesFromAnchorV01 } from "./instruction-account-nodes-from-anchor-v01.js";
import { assertIsNode, bottomUpTransformerVisitor, camelCase, visit } from "codama";
//#region src/instruction-accounts-dedupe-program-visitor.ts
/**
* Creates a Codama program visitor that deduplicates and flattens nested instruction accounts from an Anchor IDL.
*
* This is a program-level visitor that can be composed with other visitors. It transforms
* instruction nodes to have flattened account structures, removing nested account groups.
*
* @param idl - The Anchor IDL containing the instruction definitions with potentially nested accounts
* @returns A visitor that transforms all instruction nodes to have flattened account structures
*
* @example
* ```typescript
* // Use with a single program
* const programNode = programNodeFromAnchor(idl);
* const visitor = instructionAccountsDedupeProgramVisitor(idl);
* const transformedProgram = visit(programNode, visitor);
*
* // Or compose with other visitors
* const composedVisitor = mergeVisitor(
* instructionAccountsDedupeProgramVisitor(idl),
* otherProgramVisitor(),
* );
* ```
*
* @remarks
* - This visitor operates at the program level, not the root level
* - Account names are joined with underscores to maintain parent-child relationships
* - PDA seed paths are automatically updated to match the flattened structure
* - All account metadata and constraints are preserved during flattening
*/
function instructionAccountsDedupeProgramVisitor(idl, programNode) {
const accountNodes = programNode.accounts;
return visit(programNode, bottomUpTransformerVisitor([{
select: "[instructionNode]",
transform: (instructionNode) => {
assertIsNode(instructionNode, "instructionNode");
const idlIx = idl.instructions.find((ix) => camelCase(ix.name) === instructionNode.name);
if (!idlIx) throw new Error(`Instruction ${instructionNode.name} not found in IDL`);
const hasDuplicates = instructionNode.accounts.some((account) => instructionNode.accounts.some((otherAccount) => otherAccount.name === account.name && otherAccount !== account));
return {
...instructionNode,
accounts: hasDuplicates ? instructionAccountNodesFromAnchorV01(accountNodes, instructionNode.arguments, idlIx.accounts) : instructionNode.accounts
};
}
}]));
}
//#endregion
export { instructionAccountsDedupeProgramVisitor };
//# sourceMappingURL=instruction-accounts-dedupe-program-visitor.js.map