JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 41
  • Score
    100M100P100Q72306F
  • License MIT

Get codecs on demand for Codama IDLs

Package Exports

  • @codama/dynamic-codecs

Readme

Codama ➤ Dynamic Codecs

npm npm-downloads

This package provides a set of helpers that provide Codecs for Codama nodes that describe data.

Installation

pnpm install @codama/dynamic-codecs

[!NOTE] This package is not included in the main codama package.

Functions

getNodeCodec(path, options?)

Given the full NodePath of a node inside a Codama IDL, returns a Codec<unknown> (as defined in @solana/codecs) that enables encoding and decoding data for that node.

const codec = getNodeCodec([root, program, definedType]);
const bytes = codec.encode(someData);
const decodedData = codec.decode(bytes);

Note that it is important to provide the full NodePath of the node in order to properly follow link nodes inside the Codama IDL. Here is a more complex example illustrating how link nodes are resolved:

// Here we define a program with two types, one of which is a link to the other.
const root = rootNode(
    programNode({
        definedTypes: [
            definedTypeNode({ name: 'slot', type: numberTypeNode('u64') }),
            definedTypeNode({ name: 'lastSlot', type: definedTypeLinkNode('slot') }),
        ],
        name: 'myProgram',
        publicKey: '1111',
    }),
);

// The codec for the linked `lastSlot` defined type is resolved using the `slot` defined type.
const codec = getNodeCodec([root, root.program, root.program.definedTypes[1]]);
expect(codec.encode(42)).toStrictEqual(hex('2a00000000000000'));
expect(codec.decode(hex('2a00000000000000'))).toBe(42n);

Options

The getNodeCodec function accepts the following options.

Name Type Default Description
bytesEncoding BytesEncoding "base64" The default encoding to use when formatting plain bytes.

Decoded format

In the table below, we illustrate the format of each codec based on the node from which it was created.

Note that we purposefully avoid types such as Uint8Array, Set or Map in order to keep the format JSON compatible. For instance, plain bytes are not provided as Uint8Array but as a tuple of type [BytesEncoding, string] — e.g. ["base64", "HelloWorld++"] — where the default bytes encoding is base64 which is configurable via the bytesEncoding option.

Node Example Notes
AccountLinkNode - Same as AccountNode
AccountNode - Same as node.data
DefinedTypeLinkNode - Same as DefinedTypeNode
DefinedTypeNode - Same as node.type
InstructionArgumentLinkNode - Same as InstructionArgumentNode
InstructionArgumentNode - Same as node.type
InstructionLinkNode - Same as InstructionNode
InstructionNode - Same as a StructTypeNode containing all node.arguments
AmountTypeNode 42 Same as NumberTypeNode
ArrayTypeNode [1, 2, 3]
BooleanTypeNode true or false
BytesTypeNode ["base16", "00ffaa"] Uses bytesEncoding option to decode
DateTimeTypeNode 42 Same as NumberTypeNode
EnumTypeNode 2 or { __kind: "move", x: 12, y: 34 } Uses number indices for scalar enums. Uses discriminated unions otherwise.
FixedSizeTypeNode - Same as node.type
HiddenPrefixTypeNode - Same as node.type
HiddenSuffixTypeNode - Same as node.type
MapTypeNode { key1: "value1", key2: "value2" } Represent Maps as objects
NumberTypeNode 42 This could be a bigint
OptionTypeNode { __option: "Some", value: 42 } or { __option: "None" } Uses value objects (instead of T | null) to avoid loosing information on nested options.
PostOffsetTypeNode - Same as node.type
PreOffsetTypeNode - Same as node.type
PublicKeyTypeNode "3QC7Pnv2KfwwdC44gPcmQWuZXmRSbUpmWMJnhenMC8CU" Uses base58 representations of public keys
RemainderOptionTypeNode { __option: "Some", value: 42 } or { __option: "None" } Same as OptionTypeNode
SentinelTypeNode - Same as node.type
SetTypeNode [1, 2, 3] Same as ArrayTypeNode
SizePrefixTypeNode - Same as node.type
SolAmountTypeNode 42 Same as NumberTypeNode
StringTypeNode "Hello World" Uses the encoding defined in the node — i.e. node.encoding
StructTypeNode { name: "John", age: 42 }
TupleTypeNode ["John", 42] Uses arrays to create tuples
ZeroableOptionTypeNode { __option: "Some", value: 42 } or { __option: "None" } Same as OptionTypeNode

getNodeCodecVisitor(linkables, options?)

This visitor is used by getNodeCodec under the hood. It returns a Codec<unknown> for the visited node.

return visit(someTypeNode, getNodeCodecVisitor(linkables));

getValueNodeVisitor(linkables, options?)

This visitor is used by the getValueNodeVisitor under the hood. It returns an unknown value for the visited ValueNode.

return visit(someValueNode, getValueNodeVisitor(linkables));