Skip to content

Commit

Permalink
Export program error codes as constants on experimental renderer (#215)
Browse files Browse the repository at this point in the history
  • Loading branch information
lorisleiva authored Apr 15, 2024
1 parent 010f4d4 commit 092bc77
Show file tree
Hide file tree
Showing 17 changed files with 824 additions and 1,456 deletions.
5 changes: 5 additions & 0 deletions .changeset/thick-mails-love.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@metaplex-foundation/kinobi": minor
---

Export program error codes as constants on experimental renderer
1 change: 0 additions & 1 deletion src/renderers/js-experimental/ImportMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ const DEFAULT_MODULE_MAP: Record<string, string> = {
solanaCodecsStrings: '@solana/codecs',
solanaCodecsDataStructures: '@solana/codecs',
solanaInstructions: '@solana/instructions',
solanaPrograms: '@solana/programs',
solanaOptions: '@solana/codecs',
solanaSigners: '@solana/signers',

Expand Down
19 changes: 0 additions & 19 deletions src/renderers/js-experimental/fragments/program.njk
Original file line number Diff line number Diff line change
@@ -1,22 +1,3 @@
{% import "templates/macros.njk" as macros %}

export const {{ programAddressConstant }} = '{{ program.publicKey }}' as Address<'{{ program.publicKey }}'>;

{{ macros.docblock(program.docs) }}
export type {{ programType }} = Program<'{{ program.publicKey }}'>
{%- if program.errors.length > 0 %}
& ProgramWithErrors<{{ programErrorCode }}, {{ programErrorClass }}>
{% endif %}
;

export function {{ programCreateFunction }}(): {{ programType }}{
return {
name: '{{ program.name | camelCase }}',
address: {{ programAddressConstant }},
{% if program.errors.length > 0 %}
getErrorFromCode(code: {{ programErrorCode }}, cause?: Error) {
return {{ programGetErrorFromCodeFunction }}(code, cause);
},
{% endif %}
};
}
27 changes: 2 additions & 25 deletions src/renderers/js-experimental/fragments/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,9 @@ export function getProgramFragment(
}
): Fragment {
const { programNode, nameApi } = scope;
const programErrorClass = nameApi.programErrorClass(programNode.name);
const programErrorCode = nameApi.programErrorCodeEnum(programNode.name);
const programGetErrorFromCodeFunction =
nameApi.programGetErrorFromCodeFunction(programNode.name);

const programFragment = fragmentFromTemplate('program.njk', {
return fragmentFromTemplate('program.njk', {
program: programNode,
programType: nameApi.programType(programNode.name),
programAddressConstant: nameApi.programAddressConstant(programNode.name),
programCreateFunction: nameApi.programCreateFunction(programNode.name),
programErrorClass,
programErrorCode,
programGetErrorFromCodeFunction,
})
.addImports('solanaAddresses', ['Address'])
.addImports('solanaPrograms', ['Program']);

if (programNode.errors.length > 0) {
programFragment
.addImports('solanaPrograms', ['ProgramWithErrors'])
.addImports('generatedErrors', [
programErrorClass,
programErrorCode,
programGetErrorFromCodeFunction,
]);
}

return programFragment;
}).addImports('solanaAddresses', ['Address']);
}
41 changes: 15 additions & 26 deletions src/renderers/js-experimental/fragments/programErrors.njk
Original file line number Diff line number Diff line change
@@ -1,39 +1,28 @@
{% import "templates/macros.njk" as macros %}

export const enum {{ programErrorCodeEnum }} {
{% for error in errors | sort(false, false, 'code') %}
{{ macros.docblock(error.docs) }}
{{ error.name | snakeCase | upper }} = 0x{{ error.code.toString(16) }}, // {{ error.code }}
{% endfor %}
}

export class {{ programErrorClass }} extends Error {
override readonly name = '{{ programErrorClass }}';

readonly code: {{ programErrorCodeEnum }};
{% for error in errors | sort(false, false, 'code') %}
{{ macros.docblock(error.docs) }}
export const {{ getProgramErrorConstant(error.name) }} = 0x{{ error.code.toString(16) }}, // {{ error.code }}
{% endfor %}

readonly cause: Error | undefined;

constructor(code: {{ programErrorCodeEnum }}, name: string, message: string, cause?: Error) {
super(`${name} (${code}): ${message}`);
this.code = code;
this.cause = cause;
}
}
export type {{ programErrorUnion }} =
{% for error in errors | sort(false, false, 'name') %}
| typeof {{ getProgramErrorConstant(error.name) }}
{% endfor %};

let {{ programErrorCodeMap }}: Record<{{ programErrorCodeEnum }}, [string, string]> | undefined;
let {{ programErrorMessagesMap }}: Record<{{ programErrorUnion }}, string> | undefined;
if (__DEV__) {
{{ programErrorCodeMap }} = {
{% for error in errors | sort(false, false, 'code') %}
[{{ programErrorCodeEnum }}.{{ error.name | snakeCase | upper }}]: ['{{ error.name | pascalCase }}', `{{ error.message }}`],
{{ programErrorMessagesMap }} = {
{% for error in errors | sort(false, false, 'name') %}
[{{ getProgramErrorConstant(error.name) }}]: `{{ error.message }}`,
{% endfor %}
};
}

export function {{ programGetErrorFromCodeFunction }}(code: {{ programErrorCodeEnum }}, cause?: Error): {{ programErrorClass }} {
export function {{ programGetErrorMessageFunction }}(code: {{ programErrorUnion }}): string {
if (__DEV__) {
return new {{ programErrorClass }}(code, ...({{ programErrorCodeMap }} as Record<{{ programErrorCodeEnum }}, [string, string]>)[code], cause);
return ({{ programErrorMessagesMap }} as Record<{{ programErrorUnion }}, string>)[code];
}

return new {{ programErrorClass }}(code, 'Unknown', 'Error message not available in production bundles. Compile with __DEV__ set to true to see more information.', cause);
return 'Error message not available in production bundles. Compile with `__DEV__` set to true to see more information.';
}
10 changes: 6 additions & 4 deletions src/renderers/js-experimental/fragments/programErrors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ export function getProgramErrorsFragment(
const { programNode, nameApi } = scope;
return fragmentFromTemplate('programErrors.njk', {
errors: programNode.errors,
programErrorClass: nameApi.programErrorClass(programNode.name),
programErrorCodeEnum: nameApi.programErrorCodeEnum(programNode.name),
programErrorCodeMap: nameApi.programErrorCodeMap(programNode.name),
programGetErrorFromCodeFunction: nameApi.programGetErrorFromCodeFunction(
programErrorUnion: nameApi.programErrorUnion(programNode.name),
programErrorMessagesMap: nameApi.programErrorMessagesMap(programNode.name),
programGetErrorMessageFunction: nameApi.programGetErrorMessageFunction(
programNode.name
),
getProgramErrorConstant: (name: string) =>
nameApi.programErrorConstantPrefix(programNode.name) +
nameApi.programErrorConstant(name),
});
}
25 changes: 12 additions & 13 deletions src/renderers/js-experimental/nameTransformers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,19 @@ export type NameTransformerKey =
| 'instructionSyncFunction'
| 'instructionParsedType'
| 'instructionParseFunction'
| 'programType'
| 'programAddressConstant'
| 'programCreateFunction'
| 'programAccountsEnum'
| 'programAccountsEnumVariant'
| 'programAccountsIdentifierFunction'
| 'programInstructionsEnum'
| 'programInstructionsEnumVariant'
| 'programInstructionsIdentifierFunction'
| 'programInstructionsParsedUnionType'
| 'programErrorClass'
| 'programErrorCodeEnum'
| 'programErrorCodeMap'
| 'programGetErrorFromCodeFunction'
| 'programErrorConstantPrefix'
| 'programErrorConstant'
| 'programErrorUnion'
| 'programErrorMessagesMap'
| 'programGetErrorMessageFunction'
| 'resolverFunction';

export type NameTransformers = Record<NameTransformerKey, NameTransformer>;
Expand Down Expand Up @@ -119,10 +118,8 @@ export const DEFAULT_NAME_TRANSFORMERS: NameTransformers = {
instructionSyncFunction: (name) => `get${pascalCase(name)}Instruction`,
instructionParsedType: (name) => `Parsed${pascalCase(name)}Instruction`,
instructionParseFunction: (name) => `parse${pascalCase(name)}Instruction`,
programType: (name) => `${pascalCase(name)}Program`,
programAddressConstant: (name) =>
`${snakeCase(name).toUpperCase()}_PROGRAM_ADDRESS`,
programCreateFunction: (name) => `get${pascalCase(name)}Program`,
programAccountsEnum: (name) => `${pascalCase(name)}Account`,
programAccountsEnumVariant: (name) => `${pascalCase(name)}`,
programAccountsIdentifierFunction: (name) =>
Expand All @@ -133,10 +130,12 @@ export const DEFAULT_NAME_TRANSFORMERS: NameTransformers = {
`identify${pascalCase(name)}Instruction`,
programInstructionsParsedUnionType: (name) =>
`Parsed${pascalCase(name)}Instruction`,
programErrorClass: (name) => `${pascalCase(name)}ProgramError`,
programErrorCodeEnum: (name) => `${pascalCase(name)}ProgramErrorCode`,
programErrorCodeMap: (name) => `${camelCase(name)}ProgramErrorCodeMap`,
programGetErrorFromCodeFunction: (name) =>
`get${pascalCase(name)}ProgramErrorFromCode`,
programErrorConstantPrefix: (name) =>
`${snakeCase(name)}_ERROR__`.toUpperCase(),
programErrorConstant: (name) => snakeCase(name).toUpperCase(),
programErrorUnion: (name) => `${pascalCase(name)}Error`,
programErrorMessagesMap: (name) => `${camelCase(name)}ErrorMessages`,
programGetErrorMessageFunction: (name) =>
`get${pascalCase(name)}ErrorMessage`,
resolverFunction: (name) => `${camelCase(name)}`,
};
1 change: 0 additions & 1 deletion test/packages/js-experimental/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
"@solana/addresses": "2.0.0-preview.1.20240412114257.1882615a63943d158ad8ee86231f39d6f31763f2",
"@solana/codecs": "2.0.0-preview.1.20240412114257.1882615a63943d158ad8ee86231f39d6f31763f2",
"@solana/instructions": "2.0.0-preview.1.20240412114257.1882615a63943d158ad8ee86231f39d6f31763f2",
"@solana/programs": "2.0.0-preview.1.20240412114257.1882615a63943d158ad8ee86231f39d6f31763f2",
"@solana/signers": "2.0.0-preview.1.20240412114257.1882615a63943d158ad8ee86231f39d6f31763f2"
},
"devDependencies": {
Expand Down
7 changes: 0 additions & 7 deletions test/packages/js-experimental/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 092bc77

Please sign in to comment.