Arrekta SDKs and documentation site: shared design contract
2026-10-18. Read by the three parallel workstreams: sdk/typescript, sdk/python and
docs-site. Any change to this contract must be applied to all three.
1. One source of truth: change once, update everywhere
| Source | Owns | Consumers |
|---|---|---|
core/PROTOCOL.md | encodings, consensus rules, error codes | SDK codecs; docs "Protocol" section (rendered from the file at build time, never copied) |
core/vectors/*.json | byte-exact expected outputs | both SDKs' conformance tests (keys, hashing, transactions, pst, base_layer, security) |
docs/api/openapi.json | REST contract of the node (/v1/..., /rpc) | generated TypeScript types (openapi-typescript), generated Python models, docs "REST API" reference (generated pages) |
sdk/*/examples/* | runnable examples | docs code tabs import these files, and CI runs them against a regtest node |
docs/OPERATIONS.md, docs/*.md | operator docs | docs "Operate" section (rendered from the files) |
One command regenerates everything derived: tools/sdkgen/gen.sh. It regenerates TypeScript
types, Python models and the docs API pages from openapi.json. A CI check fails if generated
files are stale. When the protocol changes: update PROTOCOL.md, regenerate the vectors, and
both SDKs' conformance tests fail until they follow.
2. Design references (what we copy, what we improve)
| Reference | Copied idea | Arrekta twist |
|---|---|---|
| viem (Ethereum) | Clients made from a transport; tree-shakable standalone actions (getBlock(client, …)); strict types; bigint amounts; typed errors | Post-quantum accounts; issued assets as first-class types; policy locks; PST |
| @solana/kit | Functional, composable codecs; RPC and subscriptions as separate modules; async-iterator subscriptions with AbortSignal | Subscriptions resume from the last event id (gateway streams) |
| bitcoinjs-lib | UTXO transaction builder; PSBT-style multi-party flow | PST with a constructor phase, policy-lock satisfaction, issuer controls |
| web3.py v7 | Sync and async clients over one core; provider/middleware split | Shares the protocol code with the reference implementation |
| viem.sh / wagmi.sh docs (Vocs) | React + Vite docs, code tabs, search, API reference | Docs generated from the spec, vectors and OpenAPI; runnable examples |
3. API surface (both languages; TypeScript camelCase, Python snake_case)
Clients
createClient({ url, network?, fetch? }) → Client (node REST /v1 + /rpc)
createGatewayClient({ url, apiKey }) → Client for the gateway (/v1 proxied, /gateway/v1, /wallet/v1, /issuer/v1)
Python: Client(url) and AsyncClient(url) (httpx); same action names as methods and as functions
Actions (standalone functions taking a client; Python also exposes them as client methods)
getChain, getBlock({ id }), getBlockFilter({ id }), getFilterHeaders({ start, count }),
getTransaction({ txid }), getRawTransaction({ txid }), decodeTransaction({ hex }),
sendTransaction({ tx | hex }), sendPackage({ parent, child }),
getAddress({ address }), getUtxos({ address, asset? }), getAddressHistory({ address }),
getAssets(), getAsset({ idOrTicker }), getFrozen({ asset }),
getMempool(), estimateFee(), getDeployments(), getCheckpoints(), submitCheckpoint({ hex }),
getMiningTemplate({ address }), createAuxBlock({ address }), submitAuxBlock({ hash, auxpow })
watchEvents({ signal?, lastEventId? }) → async iterator (node SSE /v1/events; gateway /gateway/v1/stream)
Accounts and keys
generateSeed(); keychainFromSeed(seed, { network, scheme? }) → { key(i, change), lock(i), address(i), signingKeys(n) }
privateKeyFromSeed(seed32) → { publicKey, sign(msg, context), keyHash } (ML-DSA-65 default, ML-DSA-87 optional)
Addresses: encodeAddress(lock, hrp), decodeAddress(addr, hrp) (bech32m arrk/tarrk/rarrk)
Locks and policies
lockFromPublicKey(pk), multisigLock(m, keys), policyLock(node);
policy builders key/multi/after/older/sha3/and/or/thresh plus templates htlc/vault/vesting
Transactions
buildTransaction({ coins, payments, change, feeRate, issuances?, mints?, freezes?, version?, validUntil? })
signTransaction(tx, spentOutputs, signingKeys, network); txid/wtxid; serialize/deserialize; sighash
fee bumping: bumpFee (RBF rebuild with a higher fee rate), cpfp (child package)
PST (multi-party)
createPst, signPst, combinePst, finalizePst, decode/encode, status
Light clients
verifyFilter(filter, header, prevHeader), matchFilter(prevHash, filter, items), verifyMerkleBranch(...),
verifyCheckpoint(checkpoint, signerSet, network)
Units and errors
parseArrk("1.5") → 150000000n; formatArrk(150000000n) → "1.5"; parseUnits/formatUnits(decimals)
ArrektaError { status, code, title, detail }, from RFC 9457 problem+json; DecodeError; ValidationError(code)
4. Implementation rules
- TypeScript (
sdk/typescript, npmarrekta-sdk): ESM, Node ≥ 20 and browsers, zero Node-only APIs in core paths.- Crypto:
@noble/post-quantumfor ML-DSA (keygen from the 32-byte seed ξ; context"ARRK-TX-v1"), and@noble/hashesfor SHA-3, SHA-256 and SHAKE256.@scure/basefor bech32m. - Build with
tsup, test withvitest, generate types withopenapi-typescript. - Pin exact versions.
- Crypto:
- Python (
sdk/python, piparrekta-sdk, importarrekta_sdk): depends on the reference packagearrekta(core/) for all protocol code (encodings, crypto, tx, PST, policy, filters), so it can't drift. Addshttpxsync and async clients, typed models generated from OpenAPI, the ergonomic action API, units and errors. Python ≥ 3.13,ruff,pytest. - Conformance: each SDK has a test that loads
core/vectors/*.json(by relative path) and reproduces keys, addresses, tx encodings, txids, sighashes, PST, policies and filters byte for byte. - Integration tests: start a throwaway regtest node on free ports in a temp directory, using
node-rs/target/release/arrekta-node-rs(built) orcore/.venv/bin/arrekta-node. Never touch the running Docker devnet (ports 28332/28342/28352, 29333) or the soak test. - Licence: MIT OR Apache-2.0 (as the workspace). Dependencies must be permissive; record them
in
THIRD_PARTY_NOTICES.md.
5. Documentation site (docs-site, Vocs = React + Vite)
- Sections:
- Introduction: what Arrekta is, quick start.
- Concepts: UTXO and multi-asset, locks and policies, PST, merged mining, checkpoints and finality, fees and RBF, light clients, snapshots, post-quantum crypto.
- Guides: send a payment, issue an asset, multisig with PST, HTLC swap, vault, light client, run a node, merged mining for pools, checkpoint signer, snapshots.
- SDK: TypeScript and Python, with tabs for the same example in both languages.
- REST API: generated from OpenAPI.
- Protocol:
core/PROTOCOL.md. - Operate:
docs/OPERATIONS.md, security policy.
- Markdown sources outside
docs-siteare imported at build time (a small Vite or remark step copies or includes them), never duplicated by hand. - Production standard:
- fast static build (
vocs build), search, dark mode, mobile layout, accessible colours; - a versioned API reference;
- an edit-on-repo link and a "last updated" date from the source;
- no external trackers.
- fast static build (