The codec module is the bridge between anDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Proof-labs/trading-sdk/llms.txt
Use this file to discover all available pages before exploring further.
Action object and the raw bytes the exchange accepts over the wire. It serialises action payloads with @msgpack/msgpack, constructs the deterministic signing message, applies an Ed25519 signature, and wraps everything into the V2 wire envelope — all in a single call. A matching decoder lets you inspect or round-trip any signed transaction without communicating with the exchange. Understanding the codec is essential for offline signing, cross-language conformance testing, and any integration that manages transaction bytes directly rather than delegating to ExchangeClient.
Wire Envelope Format
Every signed transaction is a 6-element MessagePack array:| Index | Field | Type | Description |
|---|---|---|---|
| 0 | version | number | Always 2 for the current V2 envelope |
| 1 | action_type | number | Single-byte ActionType wire value |
| 2 | seq | bigint | Monotonically increasing sequence number |
| 3 | payload | Uint8Array | MessagePack-encoded action payload (inner envelope) |
| 4 | pubkey | Uint8Array | 32-byte Ed25519 public key of the signer |
| 5 | signature | Uint8Array | 64-byte Ed25519 signature over the V3 signing message |
BigInt and Minimal-Int Encoding
The exchange engine usesrmp-serde (Rust), which always writes integers in their minimal MessagePack form — a u32 field with value 1 becomes a 1-byte positive fixint, not a 9-byte uint64. @msgpack/msgpack with useBigInt64: true would write every BigInt as a 9-byte uint64, even for small values, causing the payload bytes to differ from what the engine re-encodes during signature verification.
The codec resolves this by walking the value tree before encoding and converting any BigInt in the range 0..=2^32-1 to a plain Number. @msgpack/msgpack then applies its own minimal-int encoding (fixint / uint8 / uint16 / uint32), matching rmp-serde exactly. BigInt values ≥ 2^32 are kept as BigInt so useBigInt64 emits them as uint64 — which also matches rmp-serde for those magnitudes.
Envelope fields
pubkey and signature are encoded as MessagePack bin (byte string), because the Rust WireTxEnvelope uses #[serde(with = "serde_bytes")] for those slots. Action payload byte-array fields (owner addresses, signer addresses) are encoded as msgpack arrays of u8 integers, because the Rust action structs use plain [u8; N] without serde_bytes.Primary Functions
signAndEncode(chainId, action, seq, privateKey)
The main encoding path for offline signing. Encodes the action payload, constructs the V3 signing message, computes the Ed25519 signature, derives the public key from privateKey, and returns the complete signed wire envelope ready for submission.
32-byte chain ID binding. Production callers must supply
chainIdFromString(cometbftChainId) or the result of fetchChainId. Only pass UNBOUND_CHAIN_ID in unit tests.Discriminated-union action object, e.g.
{ type: "PlaceOrder", data: { ... } }. See Actions Overview for all variants.Monotonically increasing sequence number.
BigInt(Date.now()) is the standard approach; the exchange rejects replayed or out-of-order sequences.32-byte Ed25519 secret key. The public key is derived internally — never included in the return value in plaintext; only the signature and public key are embedded in the envelope.
Complete V2 signed wire envelope as MessagePack bytes, ready for direct submission.
encodeSignedTx(action, seq, pubkey, signature)
Assembles the V2 wire envelope from an already-encoded action and pre-computed signature components. Use this when you hold raw signature bytes from an external signing device, HSM, or MPC wallet rather than a raw private key.
Discriminated-union action object. The codec encodes the payload internally.
Sequence number to embed in the wire envelope.
32-byte Ed25519 public key of the signer. Encoded as MessagePack
bin in the envelope.64-byte Ed25519 signature over the V3 signing message. Encoded as MessagePack
bin in the envelope.Complete V2 wire envelope as MessagePack bytes.
signEnvelopeFromPayload(chainId, actionType, seq, payloadBytes, privateKey)
Signs and wraps a pre-encoded payload into a V2 signed envelope. Lower-level than signAndEncode — callers supply raw MessagePack payload bytes and the numeric action type directly, bypassing the Action-object encoder. Useful for cross-language conformance testing where payload bytes are pre-computed by a reference implementation.
32-byte chain ID. Must be exactly 32 bytes.
Single-byte action type wire value (e.g.
ActionType.PlaceOrder = 0x01).Sequence number for the signing message and the envelope.
Already-encoded MessagePack payload bytes, typically from
encodePayloadBytes or a reference implementation.32-byte Ed25519 secret key used to sign the V3 message and derive the embedded public key.
Complete V2 signed wire envelope as MessagePack bytes.
encodePayloadBytes(action)
Encodes only the action payload — the inner payload field of the wire envelope — without the surrounding signature envelope. Useful for cross-SDK conformance testing, since payload bytes must match byte-for-byte across Rust, Python, and TypeScript implementations.
Any member of the
Action discriminated union.MessagePack-encoded payload array. Field order matches the Rust struct definitions; changing field order breaks signature verification.
Decoding Functions
decodeTx(bytes)
Decodes a complete V2 wire envelope back into its constituent parts. The seq field is always returned as bigint regardless of how it was encoded on the wire (fixint vs. uint64), so downstream code can rely on a single type.
Raw MessagePack wire bytes as produced by
signAndEncode, encodeSignedTx, or signEnvelopeFromPayload.Envelope version number. Currently always
2; the function throws on any other value.Fully decoded
Action discriminated-union object with all field types normalised (e.g. BigInt for u64 fields, Uint8Array for address fields).Sequence number, always returned as
bigint.32-byte Ed25519 public key extracted from the envelope.
64-byte Ed25519 signature extracted from the envelope.
peekActionType(bytes)
Reads the action_type byte from a wire envelope without performing a full decode. Returns null if the bytes cannot be parsed.
Raw MessagePack wire bytes.
The numeric
ActionType value at index 1 of the envelope array, or null if decoding fails.Complete Example
Underlying Libraries
| Library | Purpose |
|---|---|
@msgpack/msgpack | MessagePack encoder (Encoder) and decoder (Decoder), both configured with useBigInt64: true. The encoder is wrapped with minimizeBigInts to ensure rmp-serde compatibility. |
@proof/trading-sdk (crypto) | signingMessage, sign, and getPublicKey used internally by signAndEncode and signEnvelopeFromPayload. |