UNPKG

@codama/visitors

Version:

All visitors for the Codama framework

1,416 lines 53.7 kB
// src/index.ts
export * from "@codama/visitors-core";

// src/addPdasVisitor.ts
import { CODAMA_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_PDA_NAMES, CodamaError } from "@codama/errors";
import { assertIsNode, camelCase, pdaNode, programNode } from "@codama/nodes";
import { bottomUpTransformerVisitor } from "@codama/visitors-core";
function addPdasVisitor(pdas) {
  return bottomUpTransformerVisitor(
    Object.entries(pdas).map(([uncasedProgramName, newPdas]) => {
      const programName = camelCase(uncasedProgramName);
      return {
        select: `[programNode]${programName}`,
        transform: (node) => {
          assertIsNode(node, "programNode");
          const existingPdaNames = new Set(node.pdas.map((pda) => pda.name));
          const newPdaNames = new Set(newPdas.map((pda) => pda.name));
          const overlappingPdaNames = new Set([...existingPdaNames].filter((name) => newPdaNames.has(name)));
          if (overlappingPdaNames.size > 0) {
            throw new CodamaError(CODAMA_ERROR__VISITORS__CANNOT_ADD_DUPLICATED_PDA_NAMES, {
              duplicatedPdaNames: [...overlappingPdaNames],
              program: node,
              programName: node.name
            });
          }
          return programNode({
            ...node,
            pdas: [...node.pdas, ...newPdas.map((pda) => pdaNode({ name: pda.name, seeds: pda.seeds }))]
          });
        }
      };
    })
  );
}

// src/createSubInstructionsFromEnumArgsVisitor.ts
import { CODAMA_ERROR__VISITORS__INSTRUCTION_ENUM_ARGUMENT_NOT_FOUND, CodamaError as CodamaError3 } from "@codama/errors";
import {
  assertIsNode as assertIsNode3,
  camelCase as camelCase3,
  instructionArgumentNode as instructionArgumentNode2,
  instructionNode as instructionNode2,
  isNode as isNode2,
  numberTypeNode,
  numberValueNode
} from "@codama/nodes";
import {
  bottomUpTransformerVisitor as bottomUpTransformerVisitor3,
  LinkableDictionary,
  pipe,
  recordLinkablesOnFirstVisitVisitor
} from "@codama/visitors-core";

// src/flattenInstructionDataArgumentsVisitor.ts
import { CODAMA_ERROR__VISITORS__CANNOT_FLATTEN_STRUCT_WITH_CONFLICTING_ATTRIBUTES, CodamaError as CodamaError2 } from "@codama/errors";
import {
  assertIsNode as assertIsNode2,
  camelCase as camelCase2,
  instructionArgumentNode,
  instructionNode,
  isNode
} from "@codama/nodes";
import { bottomUpTransformerVisitor as bottomUpTransformerVisitor2 } from "@codama/visitors-core";
function flattenInstructionDataArgumentsVisitor() {
  return bottomUpTransformerVisitor2([
    {
      select: "[instructionNode]",
      transform: (instruction) => {
        assertIsNode2(instruction, "instructionNode");
        return instructionNode({
          ...instruction,
          arguments: flattenInstructionArguments(instruction.arguments)
        });
      }
    }
  ]);
}
var flattenInstructionArguments = (nodes, options = "*") => {
  const camelCaseOptions = options === "*" ? options : options.map(camelCase2);
  const shouldInline = (node) => options === "*" || camelCaseOptions.includes(camelCase2(node.name));
  const inlinedArguments = nodes.flatMap((node) => {
    if (isNode(node.type, "structTypeNode") && shouldInline(node)) {
      return node.type.fields.map((field) => instructionArgumentNode({ ...field }));
    }
    return node;
  });
  const inlinedFieldsNames = inlinedArguments.map((arg) => arg.name);
  const duplicates = inlinedFieldsNames.filter((e, i, a) => a.indexOf(e) !== i);
  const uniqueDuplicates = [...new Set(duplicates)];
  const hasConflictingNames = uniqueDuplicates.length > 0;
  if (hasConflictingNames) {
    throw new CodamaError2(CODAMA_ERROR__VISITORS__CANNOT_FLATTEN_STRUCT_WITH_CONFLICTING_ATTRIBUTES, {
      conflictingAttributes: uniqueDuplicates
    });
  }
  return hasConflictingNames ? nodes : inlinedArguments;
};

// src/createSubInstructionsFromEnumArgsVisitor.ts
function createSubInstructionsFromEnumArgsVisitor(map) {
  const linkables = new LinkableDictionary();
  const visitor = bottomUpTransformerVisitor3(
    Object.entries(map).map(
      ([selector, argNameInput]) => ({
        select: ["[instructionNode]", selector],
        transform: (node, stack) => {
          assertIsNode3(node, "instructionNode");
          const argFields = node.arguments;
          const argName = camelCase3(argNameInput);
          const argFieldIndex = argFields.findIndex((field) => field.name === argName);
          const argField = argFieldIndex >= 0 ? argFields[argFieldIndex] : null;
          if (!argField) {
            throw new CodamaError3(CODAMA_ERROR__VISITORS__INSTRUCTION_ENUM_ARGUMENT_NOT_FOUND, {
              argumentName: argName,
              instruction: node,
              instructionName: node.name
            });
          }
          let argType;
          if (isNode2(argField.type, "enumTypeNode")) {
            argType = argField.type;
          } else if (isNode2(argField.type, "definedTypeLinkNode") && linkables.has([...stack.getPath(), argField.type])) {
            const linkedType = linkables.get([...stack.getPath(), argField.type])?.type;
            assertIsNode3(linkedType, "enumTypeNode");
            argType = linkedType;
          } else {
            throw new CodamaError3(CODAMA_ERROR__VISITORS__INSTRUCTION_ENUM_ARGUMENT_NOT_FOUND, {
              argumentName: argName,
              instruction: node,
              instructionName: node.name
            });
          }
          const subInstructions = argType.variants.map((variant, index) => {
            const subName = camelCase3(`${node.name} ${variant.name}`);
            const subFields = argFields.slice(0, argFieldIndex);
            subFields.push(
              instructionArgumentNode2({
                defaultValue: numberValueNode(index),
                defaultValueStrategy: "omitted",
                name: `${subName}Discriminator`,
                type: numberTypeNode("u8")
              })
            );
            if (isNode2(variant, "enumStructVariantTypeNode")) {
              subFields.push(
                instructionArgumentNode2({
                  ...argField,
                  type: variant.struct
                })
              );
            } else if (isNode2(variant, "enumTupleVariantTypeNode")) {
              subFields.push(
                instructionArgumentNode2({
                  ...argField,
                  type: variant.tuple
                })
              );
            }
            subFields.push(...argFields.slice(argFieldIndex + 1));
            return instructionNode2({
              ...node,
              arguments: flattenInstructionArguments(subFields),
              name: subName
            });
          });
          return instructionNode2({
            ...node,
            subInstructions: [...node.subInstructions ?? [], ...subInstructions]
          });
        }
      })
    )
  );
  return pipe(visitor, (v) => recordLinkablesOnFirstVisitVisitor(v, linkables));
}

// src/deduplicateIdenticalDefinedTypesVisitor.ts
import { assertIsNode as assertIsNode4, getAllPrograms } from "@codama/nodes";
import {
  deleteNodesVisitor,
  getUniqueHashStringVisitor,
  rootNodeVisitor,
  visit
} from "@codama/visitors-core";
function deduplicateIdenticalDefinedTypesVisitor() {
  return rootNodeVisitor((root) => {
    const typeMap = /* @__PURE__ */ new Map();
    const allPrograms = getAllPrograms(root);
    allPrograms.forEach((program) => {
      program.definedTypes.forEach((type) => {
        const typeWithProgram = { program, type };
        const list = typeMap.get(type.name) ?? [];
        typeMap.set(type.name, [...list, typeWithProgram]);
      });
    });
    typeMap.forEach((list, name) => {
      if (list.length <= 1) {
        typeMap.delete(name);
      }
    });
    const hashVisitor = getUniqueHashStringVisitor({ removeDocs: true });
    typeMap.forEach((list, name) => {
      const types = list.map((item) => visit(item.type, hashVisitor));
      const typesAreEqual = types.every((type, _, arr) => type === arr[0]);
      if (!typesAreEqual) {
        typeMap.delete(name);
      }
    });
    const deleteSelectors = Array.from(typeMap.values()).flatMap((list) => {
      const sortedList = list.sort((a, b) => allPrograms.indexOf(a.program) - allPrograms.indexOf(b.program));
      const [, ...sortedListTail] = sortedList;
      return sortedListTail;
    }).map(({ program, type }) => `[programNode]${program.name}.[definedTypeNode]${type.name}`);
    if (deleteSelectors.length > 0) {
      const newRoot = visit(root, deleteNodesVisitor(deleteSelectors));
      assertIsNode4(newRoot, "rootNode");
      return newRoot;
    }
    return root;
  });
}

// src/fillDefaultPdaSeedValuesVisitor.ts
import { CODAMA_ERROR__VISITORS__INVALID_PDA_SEED_VALUES, CodamaError as CodamaError4 } from "@codama/errors";
import {
  accountValueNode,
  argumentValueNode,
  assertIsNode as assertIsNode5,
  getAllInstructionArguments,
  INSTRUCTION_INPUT_VALUE_NODES,
  isNode as isNode3,
  isNodeFilter,
  pdaSeedValueNode,
  pdaValueNode
} from "@codama/nodes";
import {
  extendVisitor,
  getLastNodeFromPath,
  identityVisitor,
  pipe as pipe2
} from "@codama/visitors-core";
function fillDefaultPdaSeedValuesVisitor(instructionPath, linkables, strictMode = false) {
  const instruction = getLastNodeFromPath(instructionPath);
  return pipe2(
    identityVisitor({ keys: INSTRUCTION_INPUT_VALUE_NODES }),
    (v) => extendVisitor(v, {
      visitPdaValue(node, { next }) {
        const visitedNode = next(node);
        assertIsNode5(visitedNode, "pdaValueNode");
        const foundPda = isNode3(visitedNode.pda, "pdaNode") ? visitedNode.pda : linkables.get([...instructionPath, visitedNode.pda]);
        if (!foundPda) return visitedNode;
        const seeds = addDefaultSeedValuesFromPdaWhenMissing(instruction, foundPda, visitedNode.seeds);
        if (strictMode && !allSeedsAreValid(instruction, foundPda, seeds)) {
          throw new CodamaError4(CODAMA_ERROR__VISITORS__INVALID_PDA_SEED_VALUES, {
            instruction,
            instructionName: instruction.name,
            pda: foundPda,
            pdaName: foundPda.name
          });
        }
        return pdaValueNode(visitedNode.pda, seeds);
      }
    })
  );
}
function addDefaultSeedValuesFromPdaWhenMissing(instruction, pda, existingSeeds) {
  const existingSeedNames = new Set(existingSeeds.map((seed) => seed.name));
  const defaultSeeds = getDefaultSeedValuesFromPda(instruction, pda).filter(
    (seed) => !existingSeedNames.has(seed.name)
  );
  return [...existingSeeds, ...defaultSeeds];
}
function getDefaultSeedValuesFromPda(instruction, pda) {
  return pda.seeds.flatMap((seed) => {
    if (!isNode3(seed, "variablePdaSeedNode")) return [];
    const hasMatchingAccount = instruction.accounts.some((a) => a.name === seed.name);
    if (isNode3(seed.type, "publicKeyTypeNode") && hasMatchingAccount) {
      return [pdaSeedValueNode(seed.name, accountValueNode(seed.name))];
    }
    const hasMatchingArgument = getAllInstructionArguments(instruction).some((a) => a.name === seed.name);
    if (hasMatchingArgument) {
      return [pdaSeedValueNode(seed.name, argumentValueNode(seed.name))];
    }
    return [];
  });
}
function allSeedsAreValid(instruction, foundPda, seeds) {
  const hasAllVariableSeeds = foundPda.seeds.filter(isNodeFilter("variablePdaSeedNode")).length === seeds.length;
  const allAccountsName = instruction.accounts.map((a) => a.name);
  const allArgumentsName = getAllInstructionArguments(instruction).map((a) => a.name);
  const validSeeds = seeds.every((seed) => {
    if (isNode3(seed.value, "accountValueNode")) {
      return allAccountsName.includes(seed.value.name);
    }
    if (isNode3(seed.value, "argumentValueNode")) {
      return allArgumentsName.includes(seed.value.name);
    }
    return true;
  });
  return hasAllVariableSeeds && validSeeds;
}

// src/flattenStructVisitor.ts
import { CODAMA_ERROR__VISITORS__CANNOT_FLATTEN_STRUCT_WITH_CONFLICTING_ATTRIBUTES as CODAMA_ERROR__VISITORS__CANNOT_FLATTEN_STRUCT_WITH_CONFLICTING_ATTRIBUTES2, CodamaError as CodamaError5 } from "@codama/errors";
import {
  assertIsNode as assertIsNode6,
  camelCase as camelCase4,
  isNode as isNode4,
  structTypeNode
} from "@codama/nodes";
import { bottomUpTransformerVisitor as bottomUpTransformerVisitor4 } from "@codama/visitors-core";
function flattenStructVisitor(map) {
  return bottomUpTransformerVisitor4(
    Object.entries(map).map(
      ([stack, options]) => ({
        select: `${stack}.[structTypeNode]`,
        transform: (node) => flattenStruct(node, options)
      })
    )
  );
}
var flattenStruct = (node, options = "*") => {
  assertIsNode6(node, "structTypeNode");
  const camelCaseOptions = options === "*" ? options : options.map(camelCase4);
  const shouldInline = (field) => options === "*" || camelCaseOptions.includes(camelCase4(field.name));
  const inlinedFields = node.fields.flatMap((field) => {
    if (isNode4(field.type, "structTypeNode") && shouldInline(field)) {
      return field.type.fields;
    }
    return [field];
  });
  const inlinedFieldsNames = inlinedFields.map((arg) => arg.name);
  const duplicates = inlinedFieldsNames.filter((e, i, a) => a.indexOf(e) !== i);
  const uniqueDuplicates = [...new Set(duplicates)];
  const hasConflictingNames = uniqueDuplicates.length > 0;
  if (hasConflictingNames) {
    throw new CodamaError5(CODAMA_ERROR__VISITORS__CANNOT_FLATTEN_STRUCT_WITH_CONFLICTING_ATTRIBUTES2, {
      conflictingAttributes: uniqueDuplicates
    });
  }
  return hasConflictingNames ? node : structTypeNode(inlinedFields);
};

// src/getDefinedTypeHistogramVisitor.ts
import {
  extendVisitor as extendVisitor2,
  findProgramNodeFromPath,
  interceptVisitor,
  mergeVisitor,
  NodeStack,
  pipe as pipe3,
  recordNodeStackVisitor,
  visit as visit2
} from "@codama/visitors-core";
function mergeHistograms(histograms) {
  const result = {};
  histograms.forEach((histogram) => {
    Object.keys(histogram).forEach((key) => {
      const mainCaseKey = key;
      if (result[mainCaseKey] === void 0) {
        result[mainCaseKey] = histogram[mainCaseKey];
      } else {
        result[mainCaseKey].total += histogram[mainCaseKey].total;
        result[mainCaseKey].inAccounts += histogram[mainCaseKey].inAccounts;
        result[mainCaseKey].inDefinedTypes += histogram[mainCaseKey].inDefinedTypes;
        result[mainCaseKey].inInstructionArgs += histogram[mainCaseKey].inInstructionArgs;
        result[mainCaseKey].directlyAsInstructionArgs += histogram[mainCaseKey].directlyAsInstructionArgs;
      }
    });
  });
  return result;
}
function getDefinedTypeHistogramVisitor() {
  const stack = new NodeStack();
  let mode = null;
  let stackLevel = 0;
  return pipe3(
    mergeVisitor(
      () => ({}),
      (_, histograms) => mergeHistograms(histograms)
    ),
    (v) => interceptVisitor(v, (node, next) => {
      stackLevel += 1;
      const newNode = next(node);
      stackLevel -= 1;
      return newNode;
    }),
    (v) => extendVisitor2(v, {
      visitAccount(node, { self }) {
        mode = "account";
        stackLevel = 0;
        const histogram = visit2(node.data, self);
        mode = null;
        return histogram;
      },
      visitDefinedType(node, { self }) {
        mode = "definedType";
        stackLevel = 0;
        const histogram = visit2(node.type, self);
        mode = null;
        return histogram;
      },
      visitDefinedTypeLink(node) {
        const program = findProgramNodeFromPath(stack.getPath());
        const key = program ? `${program.name}.${node.name}` : node.name;
        return {
          [key]: {
            directlyAsInstructionArgs: Number(mode === "instruction" && stackLevel <= 1),
            inAccounts: Number(mode === "account"),
            inDefinedTypes: Number(mode === "definedType"),
            inInstructionArgs: Number(mode === "instruction"),
            total: 1
          }
        };
      },
      visitInstruction(node, { self }) {
        mode = "instruction";
        stackLevel = 0;
        const dataHistograms = node.arguments.map((arg) => visit2(arg, self));
        const extraHistograms = (node.extraArguments ?? []).map((arg) => visit2(arg, self));
        mode = null;
        const subHistograms = (node.subInstructions ?? []).map((ix) => visit2(ix, self));
        return mergeHistograms([...dataHistograms, ...extraHistograms, ...subHistograms]);
      }
    }),
    (v) => recordNodeStackVisitor(v, stack)
  );
}

// src/setAccountDiscriminatorFromFieldVisitor.ts
import { CODAMA_ERROR__VISITORS__ACCOUNT_FIELD_NOT_FOUND, CodamaError as CodamaError6 } from "@codama/errors";
import {
  accountNode,
  assertIsNode as assertIsNode7,
  fieldDiscriminatorNode,
  resolveNestedTypeNode,
  structFieldTypeNode,
  structTypeNode as structTypeNode2,
  transformNestedTypeNode
} from "@codama/nodes";
import { bottomUpTransformerVisitor as bottomUpTransformerVisitor5 } from "@codama/visitors-core";
function setAccountDiscriminatorFromFieldVisitor(map) {
  return bottomUpTransformerVisitor5(
    Object.entries(map).map(
      ([selector, { field, value, offset }]) => ({
        select: ["[accountNode]", selector],
        transform: (node) => {
          assertIsNode7(node, "accountNode");
          const accountData = resolveNestedTypeNode(node.data);
          const fieldIndex = accountData.fields.findIndex((f) => f.name === field);
          if (fieldIndex < 0) {
            throw new CodamaError6(CODAMA_ERROR__VISITORS__ACCOUNT_FIELD_NOT_FOUND, {
              account: node,
              missingField: field,
              name: node.name
            });
          }
          const fieldNode = accountData.fields[fieldIndex];
          return accountNode({
            ...node,
            data: transformNestedTypeNode(
              node.data,
              () => structTypeNode2([
                ...accountData.fields.slice(0, fieldIndex),
                structFieldTypeNode({
                  ...fieldNode,
                  defaultValue: value,
                  defaultValueStrategy: "omitted"
                }),
                ...accountData.fields.slice(fieldIndex + 1)
              ])
            ),
            discriminators: [fieldDiscriminatorNode(field, offset), ...node.discriminators ?? []]
          });
        }
      })
    )
  );
}

// src/setFixedAccountSizesVisitor.ts
import { accountNode as accountNode2, assertIsNode as assertIsNode8 } from "@codama/nodes";
import {
  getByteSizeVisitor,
  getLastNodeFromPath as getLastNodeFromPath2,
  isNodePath,
  LinkableDictionary as LinkableDictionary3,
  pipe as pipe4,
  recordLinkablesOnFirstVisitVisitor as recordLinkablesOnFirstVisitVisitor2,
  topDownTransformerVisitor,
  visit as visit3
} from "@codama/visitors-core";
function setFixedAccountSizesVisitor() {
  const linkables = new LinkableDictionary3();
  const visitor = topDownTransformerVisitor(
    [
      {
        select: (path) => isNodePath(path, "accountNode") && getLastNodeFromPath2(path).size === void 0,
        transform: (node, stack) => {
          assertIsNode8(node, "accountNode");
          const size = visit3(node.data, getByteSizeVisitor(linkables, { stack }));
          if (size === null) return node;
          return accountNode2({ ...node, size });
        }
      }
    ],
    { keys: ["rootNode", "programNode", "accountNode"] }
  );
  return pipe4(visitor, (v) => recordLinkablesOnFirstVisitVisitor2(v, linkables));
}

// src/setInstructionAccountDefaultValuesVisitor.ts
import {
  camelCase as camelCase5,
  identityValueNode,
  instructionNode as instructionNode3,
  payerValueNode,
  programIdValueNode,
  publicKeyValueNode
} from "@codama/nodes";
import {
  extendVisitor as extendVisitor3,
  LinkableDictionary as LinkableDictionary4,
  NodeStack as NodeStack2,
  nonNullableIdentityVisitor,
  pipe as pipe5,
  recordLinkablesOnFirstVisitVisitor as recordLinkablesOnFirstVisitVisitor3,
  recordNodeStackVisitor as recordNodeStackVisitor2,
  visit as visit4
} from "@codama/visitors-core";
var getCommonInstructionAccountDefaultRules = () => [
  {
    account: /^(payer|feePayer)$/,
    defaultValue: payerValueNode(),
    ignoreIfOptional: true
  },
  {
    account: /^(authority)$/,
    defaultValue: identityValueNode(),
    ignoreIfOptional: true
  },
  {
    account: /^(programId)$/,
    defaultValue: programIdValueNode(),
    ignoreIfOptional: true
  },
  {
    account: /^(systemProgram|splSystemProgram)$/,
    defaultValue: publicKeyValueNode("11111111111111111111111111111111", "splSystem"),
    ignoreIfOptional: true
  },
  {
    account: /^(tokenProgram|splTokenProgram)$/,
    defaultValue: publicKeyValueNode("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "splToken"),
    ignoreIfOptional: true
  },
  {
    account: /^(ataProgram|splAtaProgram)$/,
    defaultValue: publicKeyValueNode("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", "splAssociatedToken"),
    ignoreIfOptional: true
  },
  {
    account: /^(tokenMetadataProgram|mplTokenMetadataProgram)$/,
    defaultValue: publicKeyValueNode("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", "mplTokenMetadata"),
    ignoreIfOptional: true
  },
  {
    account: /^(tokenAuth|mplTokenAuth|authorization|mplAuthorization|auth|mplAuth)RulesProgram$/,
    defaultValue: publicKeyValueNode("auth9SigNpDKz4sJJ1DfCTuZrZNSAgh9sFD3rboVmgg", "mplTokenAuthRules"),
    ignoreIfOptional: true
  },
  {
    account: /^(candyMachineProgram|mplCandyMachineProgram)$/,
    defaultValue: publicKeyValueNode("CndyV3LdqHUfDLmE5naZjVN8rBZz4tqhdefbAnjHG3JR", "mplCandyMachine"),
    ignoreIfOptional: true
  },
  {
    account: /^(candyGuardProgram|mplCandyGuardProgram)$/,
    defaultValue: publicKeyValueNode("Guard1JwRhJkVH6XZhzoYxeBVQe872VH6QggF4BWmS9g", "mplCandyGuard"),
    ignoreIfOptional: true
  },
  {
    account: /^(clockSysvar|sysvarClock)$/,
    defaultValue: publicKeyValueNode("SysvarC1ock11111111111111111111111111111111"),
    ignoreIfOptional: true
  },
  {
    account: /^(epochScheduleSysvar|sysvarEpochSchedule)$/,
    defaultValue: publicKeyValueNode("SysvarEpochSchedu1e111111111111111111111111"),
    ignoreIfOptional: true
  },
  {
    account: /^(instructions?Sysvar|sysvarInstructions?)(Account)?$/,
    defaultValue: publicKeyValueNode("Sysvar1nstructions1111111111111111111111111"),
    ignoreIfOptional: true
  },
  {
    account: /^(recentBlockhashesSysvar|sysvarRecentBlockhashes)$/,
    defaultValue: publicKeyValueNode("SysvarRecentB1ockHashes11111111111111111111"),
    ignoreIfOptional: true
  },
  {
    account: /^(rent|rentSysvar|sysvarRent)$/,
    defaultValue: publicKeyValueNode("SysvarRent111111111111111111111111111111111"),
    ignoreIfOptional: true
  },
  {
    account: /^(rewardsSysvar|sysvarRewards)$/,
    defaultValue: publicKeyValueNode("SysvarRewards111111111111111111111111111111"),
    ignoreIfOptional: true
  },
  {
    account: /^(slotHashesSysvar|sysvarSlotHashes)$/,
    defaultValue: publicKeyValueNode("SysvarS1otHashes111111111111111111111111111"),
    ignoreIfOptional: true
  },
  {
    account: /^(slotHistorySysvar|sysvarSlotHistory)$/,
    defaultValue: publicKeyValueNode("SysvarS1otHistory11111111111111111111111111"),
    ignoreIfOptional: true
  },
  {
    account: /^(stakeHistorySysvar|sysvarStakeHistory)$/,
    defaultValue: publicKeyValueNode("SysvarStakeHistory1111111111111111111111111"),
    ignoreIfOptional: true
  },
  {
    account: /^(mplCoreProgram)$/,
    defaultValue: publicKeyValueNode("CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d", "mplCore"),
    ignoreIfOptional: true
  }
];
function setInstructionAccountDefaultValuesVisitor(rules) {
  const linkables = new LinkableDictionary4();
  const stack = new NodeStack2();
  const sortedRules = rules.sort((a, b) => {
    const ia = "instruction" in a;
    const ib = "instruction" in b;
    if (ia && ib || !a && !ib) return 0;
    return ia ? -1 : 1;
  });
  function matchRule(instruction, account) {
    return sortedRules.find((rule) => {
      if ("instruction" in rule && rule.instruction && camelCase5(rule.instruction) !== instruction.name) {
        return false;
      }
      return typeof rule.account === "string" ? camelCase5(rule.account) === account.name : rule.account.test(account.name);
    });
  }
  return pipe5(
    nonNullableIdentityVisitor({ keys: ["rootNode", "programNode", "instructionNode"] }),
    (v) => extendVisitor3(v, {
      visitInstruction(node) {
        const instructionPath = stack.getPath("instructionNode");
        const instructionAccounts = node.accounts.map((account) => {
          const rule = matchRule(node, account);
          if (!rule) return account;
          if ((rule.ignoreIfOptional ?? false) && (account.isOptional || !!account.defaultValue)) {
            return account;
          }
          try {
            return {
              ...account,
              defaultValue: visit4(
                rule.defaultValue,
                fillDefaultPdaSeedValuesVisitor(instructionPath, linkables, true)
              )
            };
          } catch {
            return account;
          }
        });
        return instructionNode3({
          ...node,
          accounts: instructionAccounts
        });
      }
    }),
    (v) => recordNodeStackVisitor2(v, stack),
    (v) => recordLinkablesOnFirstVisitVisitor3(v, linkables)
  );
}

// src/setInstructionDiscriminatorsVisitor.ts
import {
  assertIsNode as assertIsNode9,
  fieldDiscriminatorNode as fieldDiscriminatorNode2,
  instructionArgumentNode as instructionArgumentNode3,
  instructionNode as instructionNode4,
  numberTypeNode as numberTypeNode2
} from "@codama/nodes";
import { bottomUpTransformerVisitor as bottomUpTransformerVisitor6 } from "@codama/visitors-core";
function setInstructionDiscriminatorsVisitor(map) {
  return bottomUpTransformerVisitor6(
    Object.entries(map).map(
      ([selector, discriminator]) => ({
        select: ["[instructionNode]", selector],
        transform: (node) => {
          assertIsNode9(node, "instructionNode");
          const discriminatorArgument = instructionArgumentNode3({
            defaultValue: discriminator.value,
            defaultValueStrategy: discriminator.strategy ?? "omitted",
            docs: discriminator.docs ?? [],
            name: discriminator.name ?? "discriminator",
            type: discriminator.type ?? numberTypeNode2("u8")
          });
          return instructionNode4({
            ...node,
            arguments: [discriminatorArgument, ...node.arguments],
            discriminators: [
              fieldDiscriminatorNode2(discriminator.name ?? "discriminator"),
              ...node.discriminators ?? []
            ]
          });
        }
      })
    )
  );
}

// src/setNumberWrappersVisitor.ts
import { CODAMA_ERROR__VISITORS__INVALID_NUMBER_WRAPPER, CodamaError as CodamaError7 } from "@codama/errors";
import { amountTypeNode, assertIsNestedTypeNode, dateTimeTypeNode, solAmountTypeNode } from "@codama/nodes";
import { bottomUpTransformerVisitor as bottomUpTransformerVisitor7 } from "@codama/visitors-core";
function setNumberWrappersVisitor(map) {
  return bottomUpTransformerVisitor7(
    Object.entries(map).map(
      ([selectorStack, wrapper]) => ({
        select: `${selectorStack}.[numberTypeNode]`,
        transform: (node) => {
          assertIsNestedTypeNode(node, "numberTypeNode");
          switch (wrapper.kind) {
            case "DateTime":
              return dateTimeTypeNode(node);
            case "SolAmount":
              return solAmountTypeNode(node);
            case "Amount":
              return amountTypeNode(node, wrapper.decimals, wrapper.unit);
            default:
              throw new CodamaError7(CODAMA_ERROR__VISITORS__INVALID_NUMBER_WRAPPER, { wrapper });
          }
        }
      })
    )
  );
}

// src/setStructDefaultValuesVisitor.ts
import {
  assertIsNode as assertIsNode10,
  camelCase as camelCase6,
  instructionArgumentNode as instructionArgumentNode4,
  instructionNode as instructionNode5,
  structFieldTypeNode as structFieldTypeNode2,
  structTypeNode as structTypeNode3
} from "@codama/nodes";
import { bottomUpTransformerVisitor as bottomUpTransformerVisitor8 } from "@codama/visitors-core";
function setStructDefaultValuesVisitor(map) {
  return bottomUpTransformerVisitor8(
    Object.entries(map).flatMap(([stack, defaultValues]) => {
      const camelCasedDefaultValues = Object.fromEntries(
        Object.entries(defaultValues).map(([key, value]) => [camelCase6(key), value])
      );
      return [
        {
          select: `${stack}.[structTypeNode]`,
          transform: (node) => {
            assertIsNode10(node, "structTypeNode");
            const fields = node.fields.map((field) => {
              const defaultValue = camelCasedDefaultValues[field.name];
              if (defaultValue === void 0) return field;
              if (defaultValue === null) {
                return structFieldTypeNode2({
                  ...field,
                  defaultValue: void 0,
                  defaultValueStrategy: void 0
                });
              }
              return structFieldTypeNode2({
                ...field,
                defaultValue: "kind" in defaultValue ? defaultValue : defaultValue.value,
                defaultValueStrategy: "kind" in defaultValue ? void 0 : defaultValue.strategy
              });
            });
            return structTypeNode3(fields);
          }
        },
        {
          select: ["[instructionNode]", stack],
          transform: (node) => {
            assertIsNode10(node, "instructionNode");
            const transformArguments = (arg) => {
              const defaultValue = camelCasedDefaultValues[arg.name];
              if (defaultValue === void 0) return arg;
              if (defaultValue === null) {
                return instructionArgumentNode4({
                  ...arg,
                  defaultValue: void 0,
                  defaultValueStrategy: void 0
                });
              }
              return instructionArgumentNode4({
                ...arg,
                defaultValue: "kind" in defaultValue ? defaultValue : defaultValue.value,
                defaultValueStrategy: "kind" in defaultValue ? void 0 : defaultValue.strategy
              });
            };
            return instructionNode5({
              ...node,
              arguments: node.arguments.map(transformArguments),
              extraArguments: node.extraArguments ? node.extraArguments.map(transformArguments) : void 0
            });
          }
        }
      ];
    })
  );
}

// src/transformDefinedTypesIntoAccountsVisitor.ts
import { accountNode as accountNode3, assertIsNode as assertIsNode11, programNode as programNode2 } from "@codama/nodes";
import { extendVisitor as extendVisitor4, nonNullableIdentityVisitor as nonNullableIdentityVisitor2, pipe as pipe6 } from "@codama/visitors-core";
function transformDefinedTypesIntoAccountsVisitor(definedTypes) {
  return pipe6(
    nonNullableIdentityVisitor2({ keys: ["rootNode", "programNode"] }),
    (v) => extendVisitor4(v, {
      visitProgram(program) {
        const typesToExtract = program.definedTypes.filter((node) => definedTypes.includes(node.name));
        const newDefinedTypes = program.definedTypes.filter((node) => !definedTypes.includes(node.name));
        const newAccounts = typesToExtract.map((node) => {
          assertIsNode11(node.type, "structTypeNode");
          return accountNode3({
            ...node,
            data: node.type,
            discriminators: [],
            size: void 0
          });
        });
        return programNode2({
          ...program,
          accounts: [...program.accounts, ...newAccounts],
          definedTypes: newDefinedTypes
        });
      }
    })
  );
}

// src/transformU8ArraysToBytesVisitor.ts
import {
  arrayTypeNode,
  assertIsNode as assertIsNode12,
  bytesTypeNode,
  fixedSizeTypeNode,
  isNode as isNode5,
  TYPE_NODES
} from "@codama/nodes";
import { extendVisitor as extendVisitor5, nonNullableIdentityVisitor as nonNullableIdentityVisitor3, pipe as pipe7, visit as visit5 } from "@codama/visitors-core";
function transformU8ArraysToBytesVisitor(sizes = "*") {
  const hasRequiredSize = (count) => {
    if (!isNode5(count, "fixedCountNode")) return false;
    return sizes === "*" || sizes.includes(count.value);
  };
  return pipe7(
    nonNullableIdentityVisitor3(),
    (v) => extendVisitor5(v, {
      visitArrayType(node, { self }) {
        const child = visit5(node.item, self);
        assertIsNode12(child, TYPE_NODES);
        if (isNode5(child, "numberTypeNode") && child.format === "u8" && isNode5(node.count, "fixedCountNode") && hasRequiredSize(node.count)) {
          return fixedSizeTypeNode(bytesTypeNode(), node.count.value);
        }
        return arrayTypeNode(child, node.count);
      }
    })
  );
}

// src/unwrapDefinedTypesVisitor.ts
import { assertIsNodeFilter, camelCase as camelCase7, programNode as programNode3 } from "@codama/nodes";
import {
  extendVisitor as extendVisitor6,
  findProgramNodeFromPath as findProgramNodeFromPath2,
  getLastNodeFromPath as getLastNodeFromPath3,
  LinkableDictionary as LinkableDictionary5,
  NodeStack as NodeStack3,
  nonNullableIdentityVisitor as nonNullableIdentityVisitor4,
  pipe as pipe8,
  recordLinkablesOnFirstVisitVisitor as recordLinkablesOnFirstVisitVisitor4,
  recordNodeStackVisitor as recordNodeStackVisitor3,
  visit as visit6
} from "@codama/visitors-core";
function unwrapDefinedTypesVisitor(typesToInline = "*") {
  const linkables = new LinkableDictionary5();
  const stack = new NodeStack3();
  const typesToInlineCamelCased = (typesToInline === "*" ? [] : typesToInline).map((fullPath) => {
    if (!fullPath.includes(".")) return camelCase7(fullPath);
    const [programName, typeName] = fullPath.split(".");
    return `${camelCase7(programName)}.${camelCase7(typeName)}`;
  });
  const shouldInline = (typeName, programName) => {
    if (typesToInline === "*") return true;
    const fullPath = `${programName}.${typeName}`;
    if (!!programName && typesToInlineCamelCased.includes(fullPath)) return true;
    return typesToInlineCamelCased.includes(typeName);
  };
  return pipe8(
    nonNullableIdentityVisitor4(),
    (v) => extendVisitor6(v, {
      visitDefinedTypeLink(linkType, { self }) {
        const programName = linkType.program?.name ?? findProgramNodeFromPath2(stack.getPath())?.name;
        if (!shouldInline(linkType.name, programName)) {
          return linkType;
        }
        const definedTypePath = linkables.getPathOrThrow(stack.getPath("definedTypeLinkNode"));
        const definedType = getLastNodeFromPath3(definedTypePath);
        stack.pushPath(definedTypePath);
        const result = visit6(definedType.type, self);
        stack.popPath();
        return result;
      },
      visitProgram(program, { self }) {
        return programNode3({
          ...program,
          accounts: program.accounts.map((account) => visit6(account, self)).filter(assertIsNodeFilter("accountNode")),
          definedTypes: program.definedTypes.filter((definedType) => !shouldInline(definedType.name, program.name)).map((type) => visit6(type, self)).filter(assertIsNodeFilter("definedTypeNode")),
          instructions: program.instructions.map((instruction) => visit6(instruction, self)).filter(assertIsNodeFilter("instructionNode"))
        });
      }
    }),
    (v) => recordNodeStackVisitor3(v, stack),
    (v) => recordLinkablesOnFirstVisitVisitor4(v, linkables)
  );
}

// src/unwrapInstructionArgsDefinedTypesVisitor.ts
import { assertIsNode as assertIsNode13, definedTypeLinkNode, isNode as isNode6 } from "@codama/nodes";
import { getRecordLinkablesVisitor, LinkableDictionary as LinkableDictionary6, rootNodeVisitor as rootNodeVisitor2, visit as visit7 } from "@codama/visitors-core";
function unwrapInstructionArgsDefinedTypesVisitor() {
  return rootNodeVisitor2((root) => {
    const histogram = visit7(root, getDefinedTypeHistogramVisitor());
    const linkables = new LinkableDictionary6();
    visit7(root, getRecordLinkablesVisitor(linkables));
    const definedTypesToInline = Object.keys(histogram).filter((key) => (histogram[key].total ?? 0) === 1 && (histogram[key].directlyAsInstructionArgs ?? 0) === 1).filter((key) => {
      const names = key.split(".");
      const link = names.length == 2 ? definedTypeLinkNode(names[1], names[0]) : definedTypeLinkNode(key);
      const found = linkables.get([link]);
      return found && !isNode6(found.type, "enumTypeNode");
    });
    if (definedTypesToInline.length > 0) {
      const inlineVisitor = unwrapDefinedTypesVisitor(definedTypesToInline);
      const newRoot = visit7(root, inlineVisitor);
      assertIsNode13(newRoot, "rootNode");
      return newRoot;
    }
    return root;
  });
}

// src/unwrapTupleEnumWithSingleStructVisitor.ts
import {
  assertIsNode as assertIsNode14,
  enumStructVariantTypeNode,
  getAllDefinedTypes,
  isNode as isNode7,
  resolveNestedTypeNode as resolveNestedTypeNode2,
  transformNestedTypeNode as transformNestedTypeNode2
} from "@codama/nodes";
import {
  bottomUpTransformerVisitor as bottomUpTransformerVisitor9,
  getNodeSelectorFunction,
  rootNodeVisitor as rootNodeVisitor3,
  visit as visit8
} from "@codama/visitors-core";
function unwrapTupleEnumWithSingleStructVisitor(enumsOrVariantsToUnwrap = "*") {
  const selectorFunctions = enumsOrVariantsToUnwrap === "*" ? [() => true] : enumsOrVariantsToUnwrap.map((selector) => getNodeSelectorFunction(selector));
  const shouldUnwrap = (stack) => selectorFunctions.some((selector) => selector(stack.getPath()));
  return rootNodeVisitor3((root) => {
    const typesToPotentiallyUnwrap = [];
    const definedTypes = new Map(
      getAllDefinedTypes(root).map((definedType) => [definedType.name, definedType])
    );
    let newRoot = visit8(
      root,
      bottomUpTransformerVisitor9([
        {
          select: "[enumTupleVariantTypeNode]",
          transform: (node, stack) => {
            assertIsNode14(node, "enumTupleVariantTypeNode");
            if (!shouldUnwrap(stack)) return node;
            const tupleNode = resolveNestedTypeNode2(node.tuple);
            if (tupleNode.items.length !== 1) return node;
            let item = tupleNode.items[0];
            if (isNode7(item, "definedTypeLinkNode")) {
              const definedType = definedTypes.get(item.name);
              if (!definedType) return node;
              if (!isNode7(definedType.type, "structTypeNode")) return node;
              typesToPotentiallyUnwrap.push(item.name);
              item = definedType.type;
            }
            if (!isNode7(item, "structTypeNode")) return node;
            const nestedStruct = transformNestedTypeNode2(node.tuple, () => item);
            return enumStructVariantTypeNode(node.name, nestedStruct);
          }
        }
      ])
    );
    assertIsNode14(newRoot, "rootNode");
    const histogram = visit8(newRoot, getDefinedTypeHistogramVisitor());
    const typesToUnwrap = typesToPotentiallyUnwrap.filter(
      (type) => !histogram[type] || histogram[type].total === 0
    );
    newRoot = visit8(newRoot, unwrapDefinedTypesVisitor(typesToUnwrap));
    assertIsNode14(newRoot, "rootNode");
    return newRoot;
  });
}

// src/unwrapTypeDefinedLinksVisitor.ts
import {
  bottomUpTransformerVisitor as bottomUpTransformerVisitor10,
  LinkableDictionary as LinkableDictionary7,
  pipe as pipe9,
  recordLinkablesOnFirstVisitVisitor as recordLinkablesOnFirstVisitVisitor5
} from "@codama/visitors-core";
function unwrapTypeDefinedLinksVisitor(definedLinksType) {
  const linkables = new LinkableDictionary7();
  const transformers = definedLinksType.map((selector) => ({
    select: ["[definedTypeLinkNode]", selector],
    transform: (_, stack) => {
      const definedType = linkables.getOrThrow(stack.getPath("definedTypeLinkNode"));
      return definedType.type;
    }
  }));
  return pipe9(bottomUpTransformerVisitor10(transformers), (v) => recordLinkablesOnFirstVisitVisitor5(v, linkables));
}

// src/updateAccountsVisitor.ts
import {
  accountLinkNode,
  accountNode as accountNode4,
  assertIsNode as assertIsNode15,
  camelCase as camelCase8,
  pdaLinkNode,
  pdaNode as pdaNode2,
  programNode as programNode4,
  transformNestedTypeNode as transformNestedTypeNode3
} from "@codama/nodes";
import {
  bottomUpTransformerVisitor as bottomUpTransformerVisitor11,
  findProgramNodeFromPath as findProgramNodeFromPath3
} from "@codama/visitors-core";

// src/renameHelpers.ts
import {
  enumEmptyVariantTypeNode,
  enumStructVariantTypeNode as enumStructVariantTypeNode2,
  enumTupleVariantTypeNode,
  enumTypeNode,
  isNode as isNode8,
  structFieldTypeNode as structFieldTypeNode3,
  structTypeNode as structTypeNode4
} from "@codama/nodes";
function renameStructNode(node, map) {
  return structTypeNode4(
    node.fields.map((field) => map[field.name] ? structFieldTypeNode3({ ...field, name: map[field.name] }) : field)
  );
}
function renameEnumNode(node, map) {
  return enumTypeNode(
    node.variants.map((variant) => map[variant.name] ? renameEnumVariant(variant, map[variant.name]) : variant),
    { ...node }
  );
}
function renameEnumVariant(variant, newName) {
  if (isNode8(variant, "enumStructVariantTypeNode")) {
    return enumStructVariantTypeNode2(newName, variant.struct);
  }
  if (isNode8(variant, "enumTupleVariantTypeNode")) {
    return enumTupleVariantTypeNode(newName, variant.tuple);
  }
  return enumEmptyVariantTypeNode(newName);
}

// src/updateAccountsVisitor.ts
function updateAccountsVisitor(map) {
  return bottomUpTransformerVisitor11(
    Object.entries(map).flatMap(([selector, updates]) => {
      const newName = typeof updates === "object" && "name" in updates && updates.name ? camelCase8(updates.name) : void 0;
      const pdasToUpsert = [];
      const transformers = [
        {
          select: ["[accountNode]", selector],
          transform: (node, stack) => {
            assertIsNode15(node, "accountNode");
            if ("delete" in updates) return null;
            const programNode6 = findProgramNodeFromPath3(stack.getPath());
            const { seeds, pda, ...assignableUpdates } = updates;
            let newPda = node.pda;
            if (pda && seeds !== void 0) {
              newPda = pda;
              pdasToUpsert.push({
                pda: pdaNode2({ name: pda.name, seeds }),
                program: programNode6.name
              });
            } else if (pda) {
              newPda = pda;
            } else if (seeds !== void 0 && node.pda) {
              pdasToUpsert.push({
                pda: pdaNode2({ name: node.pda.name, seeds }),
                program: programNode6.name
              });
            } else if (seeds !== void 0) {
              newPda = pdaLinkNode(newName ?? node.name);
              pdasToUpsert.push({
                pda: pdaNode2({ name: newName ?? node.name, seeds }),
                program: programNode6.name
              });
            }
            return accountNode4({
              ...node,
              ...assignableUpdates,
              data: transformNestedTypeNode3(
                node.data,
                (struct) => renameStructNode(struct, updates.data ?? {})
              ),
              pda: newPda
            });
          }
        },
        {
          select: `[programNode]`,
          transform: (node) => {
            assertIsNode15(node, "programNode");
            const pdasToUpsertForProgram = pdasToUpsert.filter((p) => p.program === node.name).map((p) => p.pda);
            if (pdasToUpsertForProgram.length === 0) return node;
            const existingPdaNames = new Set(node.pdas.map((pda) => pda.name));
            const pdasToCreate = pdasToUpsertForProgram.filter((p) => !existingPdaNames.has(p.name));
            const pdasToUpdate = new Map(
              pdasToUpsertForProgram.filter((p) => existingPdaNames.has(p.name)).map((p) => [p.name, p])
            );
            const newPdas = [...node.pdas.map((p) => pdasToUpdate.get(p.name) ?? p), ...pdasToCreate];
            return programNode4({ ...node, pdas: newPdas });
          }
        }
      ];
      if (newName) {
        transformers.push(
          {
            select: ["[accountLinkNode]", selector],
            transform: (node) => {
              assertIsNode15(node, "accountLinkNode");
              return accountLinkNode(newName);
            }
          },
          {
            select: ["[pdaNode]", selector],
            transform: (node) => {
              assertIsNode15(node, "pdaNode");
              return pdaNode2({ name: newName, seeds: node.seeds });
            }
          },
          {
            select: ["[pdaLinkNode]", selector],
            transform: (node) => {
              assertIsNode15(node, "pdaLinkNode");
              return pdaLinkNode(newName);
            }
          }
        );
      }
      return transformers;
    })
  );
}

// src/updateDefinedTypesVisitor.ts
import {
  assertIsNode as assertIsNode16,
  camelCase as camelCase9,
  definedTypeLinkNode as definedTypeLinkNode2,
  definedTypeNode,
  isNode as isNode9
} from "@codama/nodes";
import { bottomUpTransformerVisitor as bottomUpTransformerVisitor12 } from "@codama/visitors-core";
function updateDefinedTypesVisitor(map) {
  return bottomUpTransformerVisitor12(
    Object.entries(map).flatMap(([selector, updates]) => {
      const newName = typeof updates === "object" && "name" in updates && updates.name ? camelCase9(updates.name) : void 0;
      const transformers = [
        {
          select: ["[definedTypeNode]", selector],
          transform: (node) => {
            assertIsNode16(node, "definedTypeNode");
            if ("delete" in updates) {
              return null;
            }
            const { data: dataUpdates, ...otherUpdates } = updates;
            let newType = node.type;
            if (isNode9(node.type, "structTypeNode")) {
              newType = renameStructNode(node.type, dataUpdates ?? {});
            } else if (isNode9(node.type, "enumTypeNode")) {
              newType = renameEnumNode(node.type, dataUpdates ?? {});
            }
            return definedTypeNode({
              ...node,
              ...otherUpdates,
              name: newName ?? node.name,
              type: newType
            });
          }
        }
      ];
      if (newName) {
        transformers.push({
          select: ["[definedTypeLinkNode]", selector],
          transform: (node) => {
            assertIsNode16(node, "definedTypeLinkNode");
            return definedTypeLinkNode2(newName);
          }
        });
      }
      return transformers;
    })
  );
}

// src/updateErrorsVisitor.ts
import { assertIsNode as assertIsNode17, errorNode } from "@codama/nodes";
import { bottomUpTransformerVisitor as bottomUpTransformerVisitor13 } from "@codama/visitors-core";
function updateErrorsVisitor(map) {
  return bottomUpTransformerVisitor13(
    Object.entries(map).map(
      ([name, updates]) => ({
        select: `[errorNode]${name}`,
        transform: (node) => {
          assertIsNode17(node, "errorNode");
          if ("delete" in updates) return null;
          return errorNode({ ...node, ...updates });
        }
      })
    )
  );
}

// src/updateInstructionsVisitor.ts
import {
  assertIsNode as assertIsNode18,
  instructionAccountNode,
  instructionArgumentNode as instructionArgumentNode5,
  instructionNode as instructionNode6,
  TYPE_NODES as TYPE_NODES2
} from "@codama/nodes";
import {
  bottomUpTransformerVisitor as bottomUpTransformerVisitor14,
  LinkableDictionary as LinkableDictionary8,
  NodeStack as NodeStack5,
  pipe as pipe10,
  recordLinkablesOnFirstVisitVisitor as recordLinkablesOnFirstVisitVisitor6,
  recordNodeStackVisitor as recordNodeStackVisitor4,
  visit as visit9
} from "@codama/visitors-core";
function updateInstructionsVisitor(map) {
  const linkables = new LinkableDictionary8();
  const stack = new NodeStack5();
  const transformers = Object.entries(map).map(
    ([selector, updates]) => ({
      select: ["[instructionNode]", selector],
      transform: (node) => {
        assertIsNode18(node, "instructionNode");
        if ("delete" in updates) {
          return null;
        }
        const instructionPath = stack.getPath("instructionNode");
        const { accounts: accountUpdates, arguments: argumentUpdates, ...metadataUpdates } = updates;
        const { newArguments, newExtraArguments } = handleInstructionArguments(node, argumentUpdates ?? {});
        const newAccounts = node.accounts.map(
          (account) => handleInstructionAccount(instructionPath, account, accountUpdates ?? {}, linkables)
        );
        return instructionNode6({
          ...node,
          ...metadataUpdates,
          accounts: newAccounts,
          arguments: newArguments,
          extraArguments: newExtraArguments.length > 0 ? newExtraArguments : void 0
        });
      }
    })
  );
  return pipe10(
    bottomUpTransformerVisitor14(transformers),
    (v) => recordNodeStackVisitor4(v, stack),
    (v) => recordLinkablesOnFirstVisitVisitor6(v, linkables)
  );
}
function handleInstructionAccount(instructionPath, account, accountUpdates, linkables) {
  const accountUpdate = accountUpdates?.[account.name];
  if (!accountUpdate) return account;
  const { defaultValue, ...acountWithoutDefault } = {
    ...account,
    ...accountUpdate
  };
  if (!defaultValue) {
    return instructionAccountNode(acountWithoutDefault);
  }
  return instructionAccountNode({
    ...acountWithoutDefault,
    defaultValue: visit9(defaultValue, fillDefaultPdaSeedValuesVisitor(instructionPath, linkables))
  });
}
function handleInstructionArguments(instruction, argUpdates) {
  const usedArguments = /* @__PURE__ */ new Set();
  const newArguments = instruction.arguments.map((node) => {
    const argUpdate = argUpdates[node.name];
    if (!argUpdate) return node;
    usedArguments.add(node.name);
    return instructionArgumentNode5({
      ...node,
      defaultValue: argUpdate.defaultValue ?? node.defaultValue,
      defaultValueStrategy: argUpdate.defaultValueStrategy ?? node.defaultValueStrategy,
      docs: argUpdate.docs ?? node.docs,
      name: argUpdate.name ?? node.name,
      type: argUpdate.type ?? node.type
    });
  });
  const updatedExtraArguments = (instruction.extraArguments ?? []).map((node) => {
    if (usedArguments.has(node.name)) return node;
    const argUpdate = argUpdates[node.name];
    if (!argUpdate) return node;
    usedArguments.add(node.name);
    return instructionArgumentNode5({
      ...node,
      defaultValue: argUpdate.defaultValue ?? node.defaultValue,
      defaultValueStrategy: argUpdate.defaultValueStrategy ?? node.defaultValueStrategy,
      docs: argUpdate.docs ?? node.docs,
      name: argUpdate.name ?? node.name,
      type: argUpdate.type ?? node.type
    });
  });
  const newExtraArguments = [
    ...updatedExtraArguments,
    ...Object.entries(argUpdates).filter(([argName]) => !usedArguments.has(argName)).map(([argName, argUpdate]) => {
      const { type } = argUpdate;
      assertIsNode18(type, TYPE_NODES2);
      return instructionArgumentNode5({
        defaultValue: argUpdate.defaultValue ?? void 0,
        defaultValueStrategy: argUpdate.defaultValueStrategy ?? void 0,
        docs: argUpdate.docs ?? [],
        name: argUpdate.name ?? argName,
        type
      });
    })
  ];
  return { newArguments, newExtraArguments };
}

// src/updateProgramsVisitor.ts
import { assertIsNode as assertIsNode19, camelCase as camelCase10, programLinkNode, programNode as programNode5 } from "@codama/nodes";
import { bottomUpTransformerVisitor as bottomUpTransformerVisitor15 } from "@codama/visitors-core";
function updateProgramsVisitor(map) {
  return bottomUpTransformerVisitor15(
    Object.entries(map).flatMap(([name, updates]) => {
      const newName = typeof updates === "object" && "name" in updates && updates.name ? camelCase10(updates.name) : void 0;
      const transformers = [
        {
          select: `[programNode]${name}`,
          transform: (node) => {
            assertIsNode19(node, "programNode");
            if ("delete" in updates) return null;
            return programNode5({ ...node, ...updates });
          }
        }
      ];
      if (newName) {
        transformers.push({
          select: `[programLinkNode]${name}`,
          transform: (node) => {
            assertIsNode19(node, "programLinkNode");
            return programLinkNode(newName);
          }
        });
      }
      return transformers;
    })
  );
}
export {
  addPdasVisitor,
  createSubInstructionsFromEnumArgsVisitor,
  deduplicateIdenticalDefinedTypesVisitor,
  fillDefaultPdaSeedValuesVisitor,
  flattenInstructionArguments,
  flattenInstructionDataArgumentsVisitor,
  flattenStruct,
  flattenStructVisitor,
  getCommonInstructionAccountDefaultRules,
  getDefinedTypeHistogramVisitor,
  setAccountDiscriminatorFromFieldVisitor,
  setFixedAccountSizesVisitor,
  setInstructionAccountDefaultValuesVisitor,
  setInstructionDiscriminatorsVisitor,
  setNumberWrappersVisitor,
  setStructDefaultValuesVisitor,
  transformDefinedTypesIntoAccountsVisitor,
  transformU8ArraysToBytesVisitor,
  unwrapDefinedTypesVisitor,
  unwrapInstructionArgsDefinedTypesVisitor,
  unwrapTupleEnumWithSingleStructVisitor,
  unwrapTypeDefinedLinksVisitor,
  updateAccountsVisitor,
  updateDefinedTypesVisitor,
  updateErrorsVisitor,
  updateInstructionsVisitor,
  updateProgramsVisitor
};
//# sourceMappingURL=index.node.mjs.map