Skip to content
Merged
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
2 changes: 2 additions & 0 deletions packages/errors/src/codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export const CODAMA_ERROR__VISITORS__UNRECOGNIZED_UPDATE_KEYS = 1200015;
export const CODAMA_ERROR__VISITORS__INSTRUCTION_DATA_FIELD_NOT_FOUND = 1200016;
export const CODAMA_ERROR__VISITORS__INSTRUCTION_ACCOUNT_NOT_FOUND = 1200017;
export const CODAMA_ERROR__VISITORS__DEFINED_TYPE_MEMBER_NOT_FOUND = 1200018;
export const CODAMA_ERROR__VISITORS__CANNOT_SET_INSTRUCTION_DISCRIMINATOR = 1200019;

// Anchor-related errors.
// Reserve error codes in the range [2100000-2100999].
Expand Down Expand Up @@ -166,6 +167,7 @@ export type CodamaErrorCode =
| typeof CODAMA_ERROR__VISITORS__CANNOT_FLATTEN_STRUCT_WITH_CONFLICTING_ATTRIBUTES
| typeof CODAMA_ERROR__VISITORS__CANNOT_FLATTEN_STRUCT_WITH_PLUGINS
| typeof CODAMA_ERROR__VISITORS__CANNOT_REMOVE_LAST_PATH_IN_NODE_STACK
| typeof CODAMA_ERROR__VISITORS__CANNOT_SET_INSTRUCTION_DISCRIMINATOR
| typeof CODAMA_ERROR__VISITORS__CANNOT_USE_OPTIONAL_ACCOUNT_AS_PDA_SEED_VALUE
| typeof CODAMA_ERROR__VISITORS__CYCLIC_DEPENDENCY_DETECTED_WHEN_RESOLVING_INSTRUCTION_DEFAULT_VALUES
| typeof CODAMA_ERROR__VISITORS__DEFINED_TYPE_MEMBER_NOT_FOUND
Expand Down
10 changes: 9 additions & 1 deletion packages/errors/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ import {
CODAMA_ERROR__VISITORS__CANNOT_FLATTEN_STRUCT_WITH_CONFLICTING_ATTRIBUTES,
CODAMA_ERROR__VISITORS__CANNOT_FLATTEN_STRUCT_WITH_PLUGINS,
CODAMA_ERROR__VISITORS__CANNOT_REMOVE_LAST_PATH_IN_NODE_STACK,
CODAMA_ERROR__VISITORS__CANNOT_SET_INSTRUCTION_DISCRIMINATOR,
CODAMA_ERROR__VISITORS__CANNOT_USE_OPTIONAL_ACCOUNT_AS_PDA_SEED_VALUE,
CODAMA_ERROR__VISITORS__CYCLIC_DEPENDENCY_DETECTED_WHEN_RESOLVING_INSTRUCTION_DEFAULT_VALUES,
CODAMA_ERROR__VISITORS__DEFINED_TYPE_MEMBER_NOT_FOUND,
Expand Down Expand Up @@ -284,6 +285,11 @@ export type CodamaErrorContext = DefaultUnspecifiedErrorContextToUndefined<{
[CODAMA_ERROR__VISITORS__CANNOT_REMOVE_LAST_PATH_IN_NODE_STACK]: {
path: readonly Node[];
};
[CODAMA_ERROR__VISITORS__CANNOT_SET_INSTRUCTION_DISCRIMINATOR]: {
instruction: InstructionNode;
instructionName: IdentifierString;
reason: string;
};
[CODAMA_ERROR__VISITORS__CANNOT_USE_OPTIONAL_ACCOUNT_AS_PDA_SEED_VALUE]: {
instruction: InstructionNode;
instructionAccount: InstructionAccountNode;
Expand Down Expand Up @@ -334,7 +340,9 @@ export type CodamaErrorContext = DefaultUnspecifiedErrorContextToUndefined<{
parentName: IdentifierString | PathString;
};
[CODAMA_ERROR__VISITORS__INVALID_NUMBER_WRAPPER]: {
wrapper: string;
kind: string;
reason: string;
wrapper: object;
};
[CODAMA_ERROR__VISITORS__INVALID_PDA_SEED_VALUES]: {
instruction: InstructionNode;
Expand Down
5 changes: 4 additions & 1 deletion packages/errors/src/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import {
CODAMA_ERROR__VISITORS__CANNOT_FLATTEN_STRUCT_WITH_CONFLICTING_ATTRIBUTES,
CODAMA_ERROR__VISITORS__CANNOT_FLATTEN_STRUCT_WITH_PLUGINS,
CODAMA_ERROR__VISITORS__CANNOT_REMOVE_LAST_PATH_IN_NODE_STACK,
CODAMA_ERROR__VISITORS__CANNOT_SET_INSTRUCTION_DISCRIMINATOR,
CODAMA_ERROR__VISITORS__CANNOT_USE_OPTIONAL_ACCOUNT_AS_PDA_SEED_VALUE,
CODAMA_ERROR__VISITORS__CYCLIC_DEPENDENCY_DETECTED_WHEN_RESOLVING_INSTRUCTION_DEFAULT_VALUES,
CODAMA_ERROR__VISITORS__DEFINED_TYPE_MEMBER_NOT_FOUND,
Expand Down Expand Up @@ -147,6 +148,8 @@ export const CodamaErrorMessages: Readonly<{
[CODAMA_ERROR__VISITORS__CANNOT_FLATTEN_STRUCT_WITH_PLUGINS]:
'Cannot flatten the struct of field [$fieldName] since it carries plugins that would be lost.',
[CODAMA_ERROR__VISITORS__CANNOT_REMOVE_LAST_PATH_IN_NODE_STACK]: 'Cannot remove the last path in the node stack.',
[CODAMA_ERROR__VISITORS__CANNOT_SET_INSTRUCTION_DISCRIMINATOR]:
'Cannot set the discriminator of instruction [$instructionName]: $reason.',
[CODAMA_ERROR__VISITORS__CANNOT_USE_OPTIONAL_ACCOUNT_AS_PDA_SEED_VALUE]:
'Cannot use optional account [$seedValueName] as the [$seedName] PDA seed for the [$instructionAccountName] account of the [$instructionName] instruction.',
[CODAMA_ERROR__VISITORS__CYCLIC_DEPENDENCY_DETECTED_WHEN_RESOLVING_INSTRUCTION_DEFAULT_VALUES]:
Expand All @@ -162,7 +165,7 @@ export const CodamaErrorMessages: Readonly<{
'Could not find an enum data field named [$fieldName] for instruction [$instructionName].',
[CODAMA_ERROR__VISITORS__INVALID_INSTRUCTION_DEFAULT_VALUE_DEPENDENCY]:
'Dependency [$dependencyName] of kind [$dependencyKind] is not a valid dependency of [$parentName] of kind [$parentKind] in the [$instructionName] instruction.',
[CODAMA_ERROR__VISITORS__INVALID_NUMBER_WRAPPER]: 'Invalid number wrapper kind [$wrapper].',
[CODAMA_ERROR__VISITORS__INVALID_NUMBER_WRAPPER]: 'Invalid number wrapper [$kind]: $reason.',
[CODAMA_ERROR__VISITORS__INVALID_PDA_SEED_VALUES]:
'Invalid seed values for PDA [$pdaName] in instruction [$instructionName].',
[CODAMA_ERROR__VISITORS__INVALID_PROVIDED_VALUE]:
Expand Down
31 changes: 24 additions & 7 deletions packages/visitors/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,11 +205,14 @@ codama.update(setFixedAccountSizesVisitor());

### `setInstructionAccountDefaultValuesVisitor`

This visitor helps set the default values of instruction accounts in bulk. It accepts an array of "rule" objects that must contain the default value to set and the name of the instruction account to set it on. The account name may also be a regular expression to match more complex patterns.
This visitor helps set the default values of instruction accounts in bulk, including the accounts of sub-instructions. It accepts an array of "rule" objects that must contain the default value to set and the identifier of the instruction account to set it on (matched exactly). The account identifier may also be a regular expression to match more complex patterns. Rules restricted to an `instruction` take precedence over the others, and `ignoreIfOptional` leaves optional or already defaulted accounts untouched.

Missing seeds of `PdaValueNode` default values are filled using the `fillDefaultPdaSeedValuesVisitor`; a rule whose seeds cannot all be filled is skipped for that account. The `getCommonInstructionAccountDefaultRules` function returns rules for common accounts such as payers, authorities, well-known programs and sysvars, matching both their camelCase and snake_case identifiers.

```ts
codama.update(
setInstructionAccountDefaultValuesVisitor([
...getCommonInstructionAccountDefaultRules(),
{
// Set this public key as default value to any account named 'counterProgram'.
account: 'counterProgram',
Expand All @@ -226,28 +229,42 @@ codama.update(

### `setInstructionDiscriminatorsVisitor`

This visitor adds a new instruction argument to each of the provided instruction names. The new argument is added before any existing argument and marked as a discriminator of the instruction. This is useful if your Codama IDL is missing discriminators in the instruction data.
This visitor adds a discriminator to the data of each of the provided instructions. This is useful if your Codama IDL is missing discriminators in the instruction data.

- When the instruction data is an inline `StructTypeNode` without transforms (or absent), the discriminator is added as its first field (named `discriminator` by default) and a `FieldDiscriminatorNode` pointing to it is added.
- Otherwise, such as when the data links to a defined type or carries transforms, the discriminator is added as a `HiddenPrefixTransformNode` on the data, leaving the defined type untouched, and a `ConstantDiscriminatorNode` is added.

The discriminator type defaults to `u8` and must have a fixed size, since the offsets of existing discriminators are shifted by it.

```ts
codama.update(
setInstructionDiscriminatorsVisitor({
mint: { name: 'discriminator', type: numberTypeNode('u8'), value: numberValueNode(0) },
transfer: { name: 'discriminator', type: numberTypeNode('u8'), value: numberValueNode(1) },
burn: { name: 'discriminator', type: numberTypeNode('u8'), value: numberValueNode(2) },
mint: { value: integerValueNode('0') },
transfer: { value: integerValueNode('1') },
burn: { identifier: 'kind', type: integerTypeNode('u32'), value: integerValueNode('2') },
}),
);
```

### `setNumberWrappersVisitor`

This visitor helps wrap `NumberTypeNodes` matching a given name with a specific number wrapper.
This visitor gives semantic meaning to the numbers matching the provided `NodeSelectors`, using the following wrappers:

- `FixedPoint` and `SolAmount` wrap an integer in a `FixedPointTypeNode`, `SolAmount` being a fixed point of scale 9 in `SOL`.
- `DateTime` and `Duration` wrap an integer in a `DateTimeTypeNode` or a `DurationTypeNode`.
- `Unit` sets the `unit` of an integer or a float.
- `AmountDisplay` and `UnitDisplay` set the `display` of an integer to an `AmountNumberDisplayNode` or a `UnitNumberDisplayNode`. `UnitDisplay` also applies to floats.

Wrappers carry the transforms of the number they wrap. Integers used as sizes or prefixes, and numbers within the type of a constant, are left untouched.

```ts
codama.update(
setNumberWrappersVisitor({
lamports: { kind: 'SolAmount' },
timestamp: { kind: 'DateTime' },
percent: { decimals: 2, kind: 'Amount', unit: '%' },
'mint.supply': { kind: 'FixedPoint', scale: 6, unit: 'USDC' },
'transfer.amount': { decimals: injectedValueNode({ key: 'decimals' }), kind: 'AmountDisplay' },
percent: { kind: 'Unit', unit: '%' },
}),
);
```
Expand Down
Loading
Loading