Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -37,29 +37,29 @@ export function codamaTypeToTS(type: TypeNode | undefined, definedTypes: Defined
if (!type.fields || type.fields.length === 0) return '{}';
const fields = type.fields
.filter(f => f.defaultValueStrategy !== 'omitted')
.map(f => `${f.name}: ${codamaTypeToTS(f.type, definedTypes)}`);
.map(f => `${f.identifier}: ${codamaTypeToTS(f.type, definedTypes)}`);
if (fields.length === 0) return '{}';
return `{ ${fields.join('; ')} }`;
}
case 'enumTypeNode': {
if (!type.variants || type.variants.length === 0) return 'unknown /** empty variants in enumTypeNode */';
const allEmpty = type.variants.every(v => v.kind === 'enumEmptyVariantTypeNode');
if (allEmpty) {
return type.variants.map(v => `'${v.name}'`).join(' | ');
return type.variants.map(v => `'${v.identifier}'`).join(' | ');
}
const variantTypes = type.variants.map(v => {
if (v.kind === 'enumEmptyVariantTypeNode') {
return `{ __kind: '${v.name}' }`;
return `{ __kind: '${v.identifier}' }`;
}
if (v.kind === 'enumStructVariantTypeNode' && v.struct) {
const inner = codamaTypeToTS(v.struct, definedTypes);
return `{ __kind: '${v.name}' } & ${inner}`;
return `{ __kind: '${v.identifier}' } & ${inner}`;
}
if (v.kind === 'enumTupleVariantTypeNode' && v.tuple) {
const inner = codamaTypeToTS(v.tuple, definedTypes);
return `{ __kind: '${v.name}'; fields: ${inner} }`;
return `{ __kind: '${v.identifier}'; fields: ${inner} }`;
}
return `{ __kind: '${v.name}' }`;
return `{ __kind: '${v.identifier}' }`;
});
return variantTypes.join(' | ');
}
Expand All @@ -79,8 +79,8 @@ export function codamaTypeToTS(type: TypeNode | undefined, definedTypes: Defined
return `Record<string, ${v}>`;
}
case 'definedTypeLinkNode': {
if (!type.name) return 'unknown /** name missing in definedTypeLinkNode */';
const def = definedTypes.find(d => d.name === type.name);
if (!type.identifier) return 'unknown /** name missing in definedTypeLinkNode */';
const def = definedTypes.find(d => d.identifier === type.identifier);
if (!def) return 'unknown /** DefinedTypeNode not found for definedTypeLinkNode */';
return codamaTypeToTS(def.type, definedTypes);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ export function collectPdaNodesFromIdl(idl: RootNode): Map<string, PdaNode> {
const pdas = new Map<string, PdaNode>();

for (const pda of idl.program.pdas ?? []) {
pdas.set(pda.name, pda);
pdas.set(pda.identifier, pda);
}

for (const ix of idl.program.instructions ?? []) {
for (const acc of ix.accounts ?? []) {
if (!acc.defaultValue || acc.defaultValue.kind !== 'pdaValueNode') continue;
const pdaDef = acc.defaultValue.pda;
if (!pdaDef || pdaDef.kind !== 'pdaNode') continue;
if (!pdas.has(pdaDef.name)) {
pdas.set(pdaDef.name, pdaDef);
if (!pdas.has(pdaDef.identifier)) {
pdas.set(pdaDef.identifier, pdaDef);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { collectPdaNodesFromIdl } from './collect-pda-nodes';
* Returns the type block with the aggregate map type name. `mapTypeName` is `null` when the program has no PDAs.
*/
export function generatePdaTypes(idl: RootNode): { mapTypeName: string | null; typeBlock: string } {
const programName = pascalCase(idl.program.name);
const programName = pascalCase(idl.program.identifier);
const definedTypes = idl.program.definedTypes ?? [];
const pdaMap = collectPdaNodesFromIdl(idl);

Expand All @@ -28,7 +28,7 @@ export function generatePdaTypes(idl: RootNode): { mapTypeName: string | null; t
const tsType = seed.type
? codamaTypeToTS(seed.type, definedTypes)
: 'unknown/** missing type in variablePdaSeedNode */';
output += ` ${seed.name}: ${tsType};\n`;
output += ` ${seed.identifier}: ${tsType};\n`;
}
output += '};\n\n';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ function generateTypeBlockForInstruction(ix: InstructionNode, definedTypes: Defi
const tsType = codamaTypeToTS(arg.type, definedTypes);
const isOptional = OPTIONAL_NODE_KINDS.includes(arg.type.kind);
const sep = isOptional ? '?:' : ':';
output += ` ${arg.name}${sep} ${tsType};\n`;
output += ` ${arg.identifier}${sep} ${tsType};\n`;
}
for (const ra of remainingAccountArgs) {
const sep = ra.isOptional ? '?:' : ':';
Expand All @@ -64,7 +64,7 @@ function generateTypeBlockForInstruction(ix: InstructionNode, definedTypes: Defi
for (const acc of ix.accounts ?? []) {
const omittable = isAccountAutoResolvable(acc) ? '?' : '';
const type = acc.isOptional ? 'Address | null' : 'Address';
output += ` ${acc.name}${omittable}: ${type};\n`;
output += ` ${acc.identifier}${omittable}: ${type};\n`;
}
output += '};\n\n';
output += `export type ${refs.accountsWithDataRef} = ${refs.accountsRef} & Record<string, Address | null | undefined>;\n\n`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export function generateTypesFromFile(opts: GenerateTypesFromFileOptions): void

let types: string;
try {
console.log(`Generating types for program: ${idl.program.name}`);
console.log(`Generating types for program: ${idl.program.identifier}`);
types = generate(idl);
} catch (err) {
throw new Error(`Cannot generate types for IDL: ${idlPath}`, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export type ResolutionRefs = {
};

export function getResolutionRefs(ix: InstructionNode): ResolutionRefs {
const typeName = pascalCase(ix.name);
const typeName = pascalCase(ix.identifier);

const args = (ix.arguments ?? []).filter(arg => arg.defaultValueStrategy !== 'omitted');
const remainingAccountArgs = (ix.remainingAccounts ?? []).filter(ra => ra.value.kind === 'argumentValueNode');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export async function resolveAccountAddress<
resolutionPath,
resolversInput,
}: ResolveAccountAddressContext<TAccounts, TArgs, TResolvers>): Promise<Address | null> {
const accountAddressInput = accountsInput?.[ixAccountNode.name];
const accountAddressInput = accountsInput?.[ixAccountNode.identifier];
// Optional accounts explicitly provided as null should be resolved based on optionalAccountStrategy
if (accountAddressInput === null && ixAccountNode.isOptional) {
return resolveOptionalAccountWithStrategy(root, ixNode, ixAccountNode);
Expand Down Expand Up @@ -77,8 +77,8 @@ export async function resolveAccountAddress<
}

throw new CodamaError(CODAMA_ERROR__DYNAMIC_CLIENT__ACCOUNT_MISSING, {
accountName: ixAccountNode.name,
instructionName: ixNode.name,
accountName: ixAccountNode.identifier,
instructionName: ixNode.identifier,
});
}

Expand All @@ -94,7 +94,7 @@ function resolveOptionalAccountWithStrategy(
) {
if (!ixAccountNode.isOptional) {
throw new CodamaError(CODAMA_ERROR__DYNAMIC_CLIENT__INVARIANT_VIOLATION, {
message: `resolveOptionalAccountWithStrategy called for non-optional account: ${ixAccountNode.name}`,
message: `resolveOptionalAccountWithStrategy called for non-optional account: ${ixAccountNode.identifier}`,
});
}
switch (ixNode.optionalAccountStrategy) {
Expand All @@ -104,8 +104,8 @@ function resolveOptionalAccountWithStrategy(
return toAddress(root.program.publicKey);
default:
throw new CodamaError(CODAMA_ERROR__DYNAMIC_CLIENT__UNSUPPORTED_OPTIONAL_ACCOUNT_STRATEGY, {
accountName: ixAccountNode.name,
instructionName: ixNode.name,
accountName: ixAccountNode.identifier,
instructionName: ixNode.identifier,
strategy: safeStringify(ixNode.optionalAccountStrategy),
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,29 +27,29 @@ export async function resolveAccountValueNodeAddress<
const { accountsInput, ixNode, resolutionPath } = ctx;

// Check if user provided the account address.
const providedAddress = accountsInput?.[node.name];
const providedAddress = accountsInput?.[node.identifier];
if (providedAddress !== undefined && providedAddress !== null) {
return toAddress(providedAddress);
}

// Find the referenced account in the instruction.
const referencedIxAccountNode = (ixNode.accounts ?? []).find(acc => acc.name === node.name);
const referencedIxAccountNode = (ixNode.accounts ?? []).find(acc => acc.identifier === node.identifier);
if (!referencedIxAccountNode) {
throw new CodamaError(CODAMA_ERROR__DYNAMIC_CLIENT__NODE_REFERENCE_NOT_FOUND, {
instructionName: ixNode.name,
referencedName: node.name,
instructionName: ixNode.identifier,
referencedName: node.identifier,
});
}

// Detect circular dependencies before recursing.
detectCircularDependency(node.name, resolutionPath);
detectCircularDependency(node.identifier, resolutionPath);

return await resolveAccountAddress({
accountsInput: ctx.accountsInput,
argumentsInput: ctx.argumentsInput,
ixAccountNode: referencedIxAccountNode,
ixNode,
resolutionPath: [...resolutionPath, node.name],
resolutionPath: [...resolutionPath, node.identifier],
resolversInput: ctx.resolversInput,
root: ctx.root,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export async function resolveConditionalValueNodeCondition<

if (!expectedValueNode && !ifTrue && !ifFalse) {
throw new CodamaError(CODAMA_ERROR__DYNAMIC_CLIENT__INVARIANT_VIOLATION, {
message: `Invalid conditionalValueNode: missing value and branches for account ${ixAccountNode.name} in ${ixNode.name}`,
message: `Invalid conditionalValueNode: missing value and branches for account ${ixAccountNode.identifier} in ${ixNode.identifier}`,
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export async function resolveInstructionAccountAddress<
resolversInput,
root,
}: ResolveInstructionAccountAddressInput<TAccounts, TArgs, TResolvers>): Promise<Address | null> {
const accountAddressInput = accountsInput?.[ixAccountNode.name];
const accountAddressInput = accountsInput?.[ixAccountNode.identifier];
const isAccountProvided = accountAddressInput !== undefined && accountAddressInput !== null;

// Accounts values (with default or with optionalAccountStrategy) can be omitted, as they are auto-resolved.
Expand All @@ -48,8 +48,8 @@ export async function resolveInstructionAccountAddress<

if (!isAccountProvided && !canAutoResolve) {
throw new CodamaError(CODAMA_ERROR__DYNAMIC_CLIENT__ACCOUNT_MISSING, {
accountName: ixAccountNode.name,
instructionName: ixNode.name,
accountName: ixAccountNode.identifier,
instructionName: ixNode.identifier,
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,12 @@ export async function resolvePDAAddress<

if (seedNode.kind === 'variablePdaSeedNode') {
const variableSeedValueNodes = pdaValueNode.seeds ?? [];
const seedName = seedNode.name;
const variableSeedValueNode = variableSeedValueNodes.find(node => node.name === seedName);
const seedName = seedNode.identifier;
const variableSeedValueNode = variableSeedValueNodes.find(node => node.identifier === seedName);

if (!variableSeedValueNode) {
throw new CodamaError(CODAMA_ERROR__DYNAMIC_CLIENT__NODE_REFERENCE_NOT_FOUND, {
instructionName: ixNode.name,
instructionName: ixNode.identifier,
referencedName: seedName,
});
}
Expand Down Expand Up @@ -107,12 +107,12 @@ export async function resolvePDAAddress<

function resolvePdaNode(pdaDefaultValue: PdaValueNode, pdas: PdaNode[]): PdaNode {
if (isNode(pdaDefaultValue.pda, 'pdaLinkNode')) {
const linkedPda = pdas.find(p => p.name === pdaDefaultValue.pda.name);
const linkedPda = pdas.find(p => p.identifier === pdaDefaultValue.pda.identifier);
if (!linkedPda) {
throw new CodamaError(CODAMA_ERROR__LINKED_NODE_NOT_FOUND, {
kind: 'pdaLinkNode',
linkNode: pdaDefaultValue.pda,
name: pdaDefaultValue.pda.name,
name: pdaDefaultValue.pda.identifier,
path: [],
});
}
Expand Down Expand Up @@ -162,10 +162,10 @@ function resolveVariablePdaSeed<
});
}

if (seedNode.name !== variableSeedValueNode.name) {
if (seedNode.identifier !== variableSeedValueNode.identifier) {
// Sanity check: this should not happen.
throw new CodamaError(CODAMA_ERROR__DYNAMIC_CLIENT__INVARIANT_VIOLATION, {
message: `Mismatched PDA seed names: expected [${seedNode.name}], got [${variableSeedValueNode.name}]`,
message: `Mismatched PDA seed names: expected [${seedNode.identifier}], got [${variableSeedValueNode.identifier}]`,
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ function resolveStandaloneVariableSeed(
seedNode: VariablePdaSeedNode,
seedInputs: Record<string, unknown>,
): Promise<ReadonlyUint8Array> {
const input = seedInputs[seedNode.name];
const input = seedInputs[seedNode.identifier];
const typeNode = seedNode.type;

// remainderOptionTypeNode seeds are optional — null means zero bytes.
Expand All @@ -73,7 +73,7 @@ function resolveStandaloneVariableSeed(
return Promise.resolve(new Uint8Array(0));
}
throw new CodamaError(CODAMA_ERROR__DYNAMIC_CLIENT__ARGUMENT_MISSING, {
argumentName: seedNode.name,
argumentName: seedNode.identifier,
instructionName: camelCase('standaloneSeedNode'),
});
}
Expand Down Expand Up @@ -103,7 +103,7 @@ function createSyntheticArgNode(seedNode: VariablePdaSeedNode) {
return {
docs: [] as string[],
kind: 'instructionArgumentNode' as const,
name: seedNode.name,
identifier: seedNode.identifier,
type: seedNode.type,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export function createAccountDefaultValueVisitor<
ctx: AccountDefaultValueVisitorContext<TAccounts, TArgs, TResolvers>,
): Visitor<Promise<Address | null>, AccountDefaultValueSupportedNodeKind> {
const { root, ixNode, ixAccountNode, argumentsInput, accountsInput, resolversInput, resolutionPath } = ctx;
const accountAddressInput = accountsInput?.[ixAccountNode.name];
const accountAddressInput = accountsInput?.[ixAccountNode.identifier];

return {
visitAccountBumpValue: async (_node: AccountBumpValueNode) => {
Expand All @@ -97,13 +97,13 @@ export function createAccountDefaultValueVisitor<
if (argValue === undefined || argValue === null) {
throw new CodamaError(CODAMA_ERROR__DYNAMIC_CLIENT__ARGUMENT_MISSING, {
argumentName: node.name,
instructionName: ixNode.name,
instructionName: ixNode.identifier,
});
}

if (!isAddressConvertible(argValue)) {
throw new CodamaError(CODAMA_ERROR__DYNAMIC_CLIENT__UNEXPECTED_ADDRESS_TYPE, {
accountName: ixAccountNode.name,
accountName: ixAccountNode.identifier,
actualType: formatValueType(argValue),
expectedType: 'Address | PublicKey',
});
Expand Down Expand Up @@ -132,8 +132,8 @@ export function createAccountDefaultValueVisitor<
return null;
}
throw new CodamaError(CODAMA_ERROR__DYNAMIC_CLIENT__ACCOUNT_MISSING, {
accountName: ixAccountNode.name,
instructionName: ixNode.name,
accountName: ixAccountNode.identifier,
instructionName: ixNode.identifier,
});
}
// Recursively resolve the chosen branch.
Expand All @@ -151,8 +151,8 @@ export function createAccountDefaultValueVisitor<
visitIdentityValue: async (_node: IdentityValueNode) => {
if (accountAddressInput === undefined || accountAddressInput === null) {
throw new CodamaError(CODAMA_ERROR__DYNAMIC_CLIENT__ACCOUNT_MISSING, {
accountName: ixAccountNode.name,
instructionName: ixNode.name,
accountName: ixAccountNode.identifier,
instructionName: ixNode.identifier,
});
}
return await Promise.resolve(toAddress(accountAddressInput));
Expand All @@ -161,8 +161,8 @@ export function createAccountDefaultValueVisitor<
visitPayerValue: async (_node: PayerValueNode) => {
if (accountAddressInput === undefined || accountAddressInput === null) {
throw new CodamaError(CODAMA_ERROR__DYNAMIC_CLIENT__ACCOUNT_MISSING, {
accountName: ixAccountNode.name,
instructionName: ixNode.name,
accountName: ixAccountNode.identifier,
instructionName: ixNode.identifier,
});
}
return await Promise.resolve(toAddress(accountAddressInput));
Expand All @@ -180,7 +180,7 @@ export function createAccountDefaultValueVisitor<
});
if (pda === null) {
throw new CodamaError(CODAMA_ERROR__DYNAMIC_CLIENT__FAILED_TO_DERIVE_PDA, {
accountName: ixAccountNode.name,
accountName: ixAccountNode.identifier,
});
}
return pda[0];
Expand All @@ -198,7 +198,7 @@ export function createAccountDefaultValueVisitor<
const resolverFn = resolversInput?.[node.name];
if (!resolverFn) {
throw new CodamaError(CODAMA_ERROR__DYNAMIC_CLIENT__ACCOUNT_RESOLVER_MISSING, {
accountName: ixAccountNode.name,
accountName: ixAccountNode.identifier,
resolverName: node.name,
});
}
Expand All @@ -210,13 +210,13 @@ export function createAccountDefaultValueVisitor<
cause: error,
resolverName: node.name,
targetKind: 'instructionAccountNode',
targetName: ixAccountNode.name,
targetName: ixAccountNode.identifier,
});
}

if (!isAddressConvertible(result)) {
throw new CodamaError(CODAMA_ERROR__DYNAMIC_CLIENT__INVALID_ACCOUNT_ADDRESS, {
accountName: ixAccountNode.name,
accountName: ixAccountNode.identifier,
value: safeStringify(result),
});
}
Expand Down
Loading