Files
wasm/packages/quantus-codec/src/generated/quantus_codec.d.ts
rob thijssen 3a1611a92e feat: add @quantus/codec, driving encode and decode from runtime metadata
The extension has to build a signing payload, assemble an extrinsic and decode
a call well enough to show a user what they are approving. The obvious route was
@polkadot/api's codec. That is closed, and quantus/api#1 carries the tested
evidence:

  - @polkadot/types caps fixed arrays at 2048 bytes, and ML-DSA signatures are
    [u8;5261] and [u8;7219], so every Quantus extrinsic trips it
  - api.rpc.chain.getBlock throws on every block of this chain, at the timestamp
    inherent, because it reads the extrinsic preamble byte as a version when the
    top two bits are a type tag
  - it *guesses* that signed extensions it does not recognise contribute nothing
    to the signed payload

The third is why this is a package rather than a patch. The guess is right
today — the registry says ReversibleTransactionExtension and
WormholeProofRecorderExtension are empty on both halves — and it is right only
by luck. This chain's encoding has changed between runtimes, transactionVersion
has gone 2 -> 3 -> 6 across four upgrades, and when the guess stops holding the
wallet keeps signing: valid signatures over a payload missing bytes the runtime
put there, reported by the chain as BadProof, which is also what it reports for
a wrong key.

So nothing here names a pallet, a call, an extension or a signature scheme.
Every type id is read from metadata the node produced by running
Metadata_metadata against the runtime WASM in a given block's state, the same
oracle blackbeard.observer has been decoding against across four upgrade
boundaries. encode_extensions walks the declared extensions in order and refuses
to build a payload when one that encodes to something has no value supplied —
a wallet that cannot sign is a bug report, one that signs the wrong bytes is a
support case nobody diagnoses.

Proven end to end on Heisenberg at spec 148: a balances.transfer_keep_alive
built entirely here, signed by @quantus/crypto under QUANTUS_EXTRINSIC, included
at block 1050475 and read back from that block — inherent at index 0 included,
which is the block @polkadot/api cannot decode at all.

Two notes carried over from @quantus/crypto, both load-bearing: decode_checked
walks with scale_decode's IgnoreVisitor before scale_value touches the bytes,
because scale_value sizes a Vec from the length prefix before decoding an item
and an aborted allocation leaves no Err to catch; and the build needs binaryen
123, since 105 silently corrupts the output.

Closes #3

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012uDUodEcRbBwNRi3UCmw8f
2026-09-15 14:14:34 +03:00

101 lines
4.4 KiB
TypeScript

/* tslint:disable */
/* eslint-disable */
/**
* A loaded runtime description, held across calls so the metadata is parsed
* once per spec version rather than once per signature.
*/
export class QuantusRuntime {
free(): void;
[Symbol.dispose](): void;
/**
* Decode a bare call — what an approval screen shows the user.
*/
decodeCall(bytes: Uint8Array): string;
/**
* Decode one extrinsic as this runtime describes it, as JSON.
*/
decodeExtrinsic(blob: Uint8Array): string;
/**
* Encode a call by name. `args` is a JSON object keyed by argument name.
*/
encodeCall(pallet: string, call: string, args: string): Uint8Array;
/**
* The `extra` alone, which the extrinsic carries and the payload repeats.
*/
encodeExtra(extensions: string): Uint8Array;
/**
* Assemble a signed extrinsic, ready for `author_submitAndWatchExtrinsic`.
*/
encodeExtrinsic(address: string, signature: Uint8Array, extra: Uint8Array, call: Uint8Array): Uint8Array;
/**
* The extrinsic format version this runtime declares.
*/
extrinsicVersion(): number;
/**
* Parse metadata as `state_getMetadata` returns it.
*/
constructor(metadata: Uint8Array);
/**
* Every signed extension, in order, as
* `[{ identifier, needsExtra, needsAdditional }]`.
*
* The two booleans are what a caller has to satisfy, read from the
* registry. A caller that ignores them gets an error rather than a short
* payload.
*/
signedExtensions(): string;
/**
* The bytes to sign, given an encoded call and the extension values.
*
* `extensions` is a JSON object keyed by extension identifier, each value
* `{ extra?, additional? }`. Omitting one the runtime declares as non-empty
* is an error — see [`Runtime::encode_extensions`].
*/
signerPayload(call: Uint8Array, extensions: string): Uint8Array;
}
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
export interface InitOutput {
readonly memory: WebAssembly.Memory;
readonly __wbg_quantusruntime_free: (a: number, b: number) => void;
readonly quantusruntime_decodeCall: (a: number, b: number, c: number) => [number, number, number, number];
readonly quantusruntime_decodeExtrinsic: (a: number, b: number, c: number) => [number, number, number, number];
readonly quantusruntime_encodeCall: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number, number, number];
readonly quantusruntime_encodeExtra: (a: number, b: number, c: number) => [number, number, number, number];
readonly quantusruntime_encodeExtrinsic: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => [number, number, number, number];
readonly quantusruntime_extrinsicVersion: (a: number) => number;
readonly quantusruntime_new: (a: number, b: number) => [number, number, number];
readonly quantusruntime_signedExtensions: (a: number) => [number, number, number, number];
readonly quantusruntime_signerPayload: (a: number, b: number, c: number, d: number, e: number) => [number, number, number, number];
readonly __wbindgen_externrefs: WebAssembly.Table;
readonly __wbindgen_malloc: (a: number, b: number) => number;
readonly __externref_table_dealloc: (a: number) => void;
readonly __wbindgen_free: (a: number, b: number, c: number) => void;
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
readonly __wbindgen_start: () => void;
}
export type SyncInitInput = BufferSource | WebAssembly.Module;
/**
* Instantiates the given `module`, which can either be bytes or
* a precompiled `WebAssembly.Module`.
*
* @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
*
* @returns {InitOutput}
*/
export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
/**
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
* for everything else, calls `WebAssembly.instantiate` directly.
*
* @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
*
* @returns {Promise<InitOutput>}
*/
export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;