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
5 changes: 5 additions & 0 deletions .changeset/flat-transforms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@codama/spec': major
---

Replace the nested type wrappers with a flat `transforms` array. The seven wrapper type nodes (`fixedSizeTypeNode`, `sizePrefixTypeNode`, `preOffsetTypeNode`, `postOffsetTypeNode`, `sentinelTypeNode`, `hiddenPrefixTypeNode`, `hiddenSuffixTypeNode`) and the `nestedTypeNode` recursive alias are removed. Instead, a new `transform` category defines one transform node per former wrapper (same attributes minus the inner type), and every member of the `typeNode` union — links included — carries an optional `transforms` array, applied in order with the first transform innermost. A type's `kind` is now stable whether or not it is modified, and attributes that pinned a wrapped inner kind (`accountNode.data`, enum variant payloads, numeric prefixes) become plain node references.
12 changes: 6 additions & 6 deletions docs/AccountNode.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ An on-chain account: its name, data structure, optional fixed size, optional PDA

### Children

| Attribute | Type | Description |
| ---------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `data` | [`NestedTypeNode`](./typeNodes/NestedTypeNode.md)<[`StructTypeNode`](./typeNodes/StructTypeNode.md)> | The struct describing the account data. It must be a struct so its fields can be referenced by other nodes — e.g. `accountFieldValueNode`. |
| `pda` | [`PdaLinkNode`](./linkNodes/PdaLinkNode.md) _(optional)_ | A link to the PDA the account is derived from, if applicable. |
| `discriminators` | [`DiscriminatorNode`](./discriminatorNodes/DiscriminatorNode.md)[] _(optional)_ | Discriminators that distinguish this account from others in the program. When multiple are listed, they are combined with a logical AND. |
| `plugins` | [`PluginNode`](./PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. The universal extension point for renderer-specific or not-yet-standardised metadata. |
| Attribute | Type | Description |
| ---------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `data` | [`StructTypeNode`](./typeNodes/StructTypeNode.md) | The struct describing the account data. It must be a struct so its fields can be referenced by other nodes — e.g. `accountFieldValueNode`. |
| `pda` | [`PdaLinkNode`](./linkNodes/PdaLinkNode.md) _(optional)_ | A link to the PDA the account is derived from, if applicable. |
| `discriminators` | [`DiscriminatorNode`](./discriminatorNodes/DiscriminatorNode.md)[] _(optional)_ | Discriminators that distinguish this account from others in the program. When multiple are listed, they are combined with a logical AND. |
| `plugins` | [`PluginNode`](./PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. The universal extension point for renderer-specific or not-yet-standardised metadata. |

## Examples

Expand Down
12 changes: 8 additions & 4 deletions docs/EventNode.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,16 @@ eventNode({
```typescript
eventNode({
name: 'transferEvent',
data: hiddenPrefixTypeNode(structTypeNode([structFieldTypeNode({ name: 'amount', type: numberTypeNode('u64') })]), [
constantValueNode(fixedSizeTypeNode(bytesTypeNode(), 8), bytesValueNode('base16', '0102030405060708')),
]),
data: structTypeNode([structFieldTypeNode({ name: 'amount', type: numberTypeNode('u64') })], {
transforms: [
hiddenPrefixTransformNode([
constantValueNode(bytesTypeNode({ transforms: [fixedSizeTransformNode(8)] }), bytesValueNode('base16', '0102030405060708')),
]),
],
}),
discriminators: [
constantDiscriminatorNode(
constantValueNode(fixedSizeTypeNode(bytesTypeNode(), 8), bytesValueNode('base16', '0102030405060708')),
constantValueNode(bytesTypeNode({ transforms: [fixedSizeTransformNode(8)] }), bytesValueNode('base16', '0102030405060708')),
),
],
});
Expand Down
3 changes: 2 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ The canonical Codama node specification.

Spec version: 1.9.2 · Other majors: [v1](https://github.com/codama-idl/spec/blob/1.x/v1/docs/README.md)

Pages marked _(abstract)_ document unions: sets of nodes that can be used interchangeably. Pages marked _(recursive)_ document nested unions: wrapper nodes that may nest before reaching a base type.
Pages marked _(abstract)_ document unions: sets of nodes that can be used interchangeably.

## Base attributes

Expand All @@ -24,6 +24,7 @@ Codegen targets append them after each node's declared attributes, so they alway
- [Link](./linkNodes/README.md) - Link nodes — references to other named entities (programs, PDAs, accounts, …).
- [PdaSeed](./pdaSeedNodes/README.md) - PDA-seed nodes — the constants and variables a program uses to derive PDAs.
- [Shared](./sharedNodes/README.md) - Shared enumerations referenced from multiple node categories.
- [Transform](./transformNodes/README.md) - Transform nodes — modifiers applied to the serialisation of the type node that carries them.
- [Type](./typeNodes/README.md) - Type nodes — the building blocks of every value shape.
- [Value](./valueNodes/README.md) - Value nodes — concrete values whose shape is described by a type node.

Expand Down
8 changes: 4 additions & 4 deletions docs/countNodes/PrefixedCountNode.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ This enables nodes such as `arrayTypeNode` to represent collections whose length

### Children

| Attribute | Type | Description |
| --------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
| `prefix` | [`NestedTypeNode`](../typeNodes/NestedTypeNode.md)<[`NumberTypeNode`](../typeNodes/NumberTypeNode.md)> | The numeric type used as the count prefix. |
| `plugins` | [`PluginNode`](../PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. The universal extension point for renderer-specific or not-yet-standardised metadata. |
| Attribute | Type | Description |
| --------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `prefix` | [`NumberTypeNode`](../typeNodes/NumberTypeNode.md) | The numeric type used as the count prefix. |
| `plugins` | [`PluginNode`](../PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. The universal extension point for renderer-specific or not-yet-standardised metadata. |

## Examples

Expand Down
2 changes: 1 addition & 1 deletion docs/discriminatorNodes/FieldDiscriminatorNode.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ instructionNode({
arguments: [
instructionArgumentNode({
name: 'discriminator',
type: fixedSizeTypeNode(bytesTypeNode(), 8),
type: bytesTypeNode({ transforms: [fixedSizeTransformNode(8)] }),
defaultValue: bytesValueNode('base16', '0011223344556677'),
defaultValueStrategy: 'omitted',
}),
Expand Down
9 changes: 5 additions & 4 deletions docs/linkNodes/DefinedTypeLinkNode.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ A reference to a defined type — possibly in a different program.

### Children

| Attribute | Type | Description |
| --------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
| `program` | [`ProgramLinkNode`](./ProgramLinkNode.md) _(optional)_ | The program the referenced type is defined in. When omitted, the surrounding program is assumed. |
| `plugins` | [`PluginNode`](../PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. The universal extension point for renderer-specific or not-yet-standardised metadata. |
| Attribute | Type | Description |
| ------------ | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `program` | [`ProgramLinkNode`](./ProgramLinkNode.md) _(optional)_ | The program the referenced type is defined in. When omitted, the surrounding program is assumed. |
| `transforms` | [`TransformNode`](../transformNodes/TransformNode.md)[] _(optional)_ | Transforms applied to the serialisation of this type, in order — the first is the innermost. |
| `plugins` | [`PluginNode`](../PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. The universal extension point for renderer-specific or not-yet-standardised metadata. |

## Examples

Expand Down
6 changes: 3 additions & 3 deletions docs/sharedNodes/PostOffsetStrategy.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# PostOffsetStrategy

How a post-offset modifier interprets its offset value after serialising the wrapped type.
See `postOffsetTypeNode` for an illustrated walkthrough of each strategy.
How a post-offset transform interprets its offset value after serialising the transformed type.
See `postOffsetTransformNode` for an illustrated walkthrough of each strategy.

## Variants

- `absolute` - Move the cursor to the absolute byte position given by the offset; a negative offset counts backwards from the end of the buffer.
- `padded` - Move the cursor like `relative` while growing the buffer by the offset amount; a negative offset moves the cursor backwards and shrinks the buffer.
- `preOffset` - Move the cursor by the offset bytes relative to the pre-offset — where the wrapped type started — rather than where it ended; a negative offset moves it to the left of that position.
- `preOffset` - Move the cursor by the offset bytes relative to the pre-offset — where the transformed type started — rather than where it ended; a negative offset moves it to the left of that position.
- `relative` - Advance the cursor by the offset bytes relative to its current position; a negative offset moves it backwards.
4 changes: 2 additions & 2 deletions docs/sharedNodes/PreOffsetStrategy.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# PreOffsetStrategy

How a pre-offset modifier interprets its offset value before serialising the wrapped type.
See `preOffsetTypeNode` for an illustrated walkthrough of each strategy.
How a pre-offset transform interprets its offset value before serialising the transformed type.
See `preOffsetTransformNode` for an illustrated walkthrough of each strategy.

## Variants

Expand Down
4 changes: 2 additions & 2 deletions docs/sharedNodes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ Shared enumerations referenced from multiple node categories.
- [`InstructionLifecycle`](./InstructionLifecycle.md) - The lifecycle stage of an instruction.
- [`NumberFormat`](./NumberFormat.md) - The wire format of a numeric serialization.
- [`OptionalAccountStrategy`](./OptionalAccountStrategy.md) - How an absent optional account is represented when serialising an instruction.
- [`PostOffsetStrategy`](./PostOffsetStrategy.md) - How a post-offset modifier interprets its offset value after serialising the wrapped type.
- [`PreOffsetStrategy`](./PreOffsetStrategy.md) - How a pre-offset modifier interprets its offset value before serialising the wrapped type.
- [`PostOffsetStrategy`](./PostOffsetStrategy.md) - How a post-offset transform interprets its offset value after serialising the transformed type.
- [`PreOffsetStrategy`](./PreOffsetStrategy.md) - How a pre-offset transform interprets its offset value before serialising the transformed type.
- [`ProgramOrigin`](./ProgramOrigin.md) - The toolchain that originally generated a program description.
37 changes: 37 additions & 0 deletions docs/transformNodes/FixedSizeTransformNode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# FixedSizeTransformNode

Asserts a fixed total byte size for the transformed type. Padding or truncation is applied as needed.

## Attributes

### Data

| Attribute | Type | Description |
| --------- | -------------------------- | ----------------------------------------------------- |
| `kind` | `"fixedSizeTransformNode"` | The node discriminator. |
| `size` | `u64` | The total byte size the transformed type must occupy. |

### Children

| Attribute | Type | Description |
| --------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `plugins` | [`PluginNode`](../PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. The universal extension point for renderer-specific or not-yet-standardised metadata. |

## Examples

### Fixed UTF-8 strings

```typescript
stringTypeNode('utf8', { transforms: [fixedSizeTransformNode(10)] });

// Hello => 0x48656C6C6F0000000000
```

### Fixed byte arrays

```typescript
bytesTypeNode({ transforms: [fixedSizeTransformNode(4)] });

// [1, 2] => 0x01020000
// [1, 2, 3, 4, 5] => 0x01020304
```
44 changes: 44 additions & 0 deletions docs/transformNodes/HiddenPrefixTransformNode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# HiddenPrefixTransformNode

Prefixes the transformed type with a list of constant values that are written and read but not surfaced as fields to consumers.
When decoding, the prefixed constants are consumed and checked against their expected values before being discarded.

## Attributes

### Data

| Attribute | Type | Description |
| --------- | ----------------------------- | ----------------------- |
| `kind` | `"hiddenPrefixTransformNode"` | The node discriminator. |

### Children

| Attribute | Type | Description |
| --------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `prefix` | [`ConstantValueNode`](../valueNodes/ConstantValueNode.md)[] | The constant values written before the transformed type, in order. |
| `plugins` | [`PluginNode`](../PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. The universal extension point for renderer-specific or not-yet-standardised metadata. |

## Examples

### A number prefixed with 0xFFFF

```typescript
numberTypeNode('u32', {
transforms: [hiddenPrefixTransformNode([constantValueNode(bytesTypeNode(), bytesValueNode('base16', 'ffff'))])],
});

// 42 => 0xFFFF2A000000
```

### A fixed UTF-8 string prefixed with "Hello"

```typescript
stringTypeNode('utf8', {
transforms: [
fixedSizeTransformNode(10),
hiddenPrefixTransformNode([constantValueNode(stringTypeNode('utf8'), stringValueNode('Hello'))]),
],
});

// World => 0x48656C6C6F576F726C640000000000
```
44 changes: 44 additions & 0 deletions docs/transformNodes/HiddenSuffixTransformNode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# HiddenSuffixTransformNode

Suffixes the transformed type with a list of constant values that are written and read but not surfaced as fields to consumers.
When decoding, the suffixed constants are consumed and checked against their expected values before being discarded.

## Attributes

### Data

| Attribute | Type | Description |
| --------- | ----------------------------- | ----------------------- |
| `kind` | `"hiddenSuffixTransformNode"` | The node discriminator. |

### Children

| Attribute | Type | Description |
| --------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `suffix` | [`ConstantValueNode`](../valueNodes/ConstantValueNode.md)[] | The constant values written after the transformed type, in order. |
| `plugins` | [`PluginNode`](../PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. The universal extension point for renderer-specific or not-yet-standardised metadata. |

## Examples

### A number suffixed with 0xFFFF

```typescript
numberTypeNode('u32', {
transforms: [hiddenSuffixTransformNode([constantValueNode(bytesTypeNode(), bytesValueNode('base16', 'ffff'))])],
});

// 42 => 0x2A000000FFFF
```

### A fixed UTF-8 string suffixed with "Hello"

```typescript
stringTypeNode('utf8', {
transforms: [
fixedSizeTransformNode(10),
hiddenSuffixTransformNode([constantValueNode(stringTypeNode('utf8'), stringValueNode('Hello'))]),
],
});

// World => 0x576F726C64000000000048656c6c6F
```
Loading