SDKs
Two SDKs, one design. Both follow the shared contract in
SDK & docs contract (docs/SDK_DESIGN.md): the same clients,
actions and names (camelCase in TypeScript, snake_case in Python), the same errors, and the same
byte-exact results.
| TypeScript | Python | |
|---|---|---|
| Package | arrekta-sdk (npm) | arrekta-sdk (pip), import arrekta_sdk |
| Runtime | Node ≥ 20 and browsers, ESM, no Node-only APIs in core paths | Python ≥ 3.13 |
| Clients | createClient, createGatewayClient | Client, AsyncClient (httpx), gateway variants |
| Crypto | @noble/post-quantum (ML-DSA), @noble/hashes (SHA-3), @scure/base (bech32m) | the reference package arrekta (core/), so protocol code can't drift |
| REST types | generated from openapi.json with openapi-typescript | generated models |
| Amounts | bigint base units | int base units |
Design
- Clients from a transport, standalone actions (from viem):
getBlock(client, { id }), so bundlers drop what you don't use. Python also exposes every action as a client method. - Post-quantum accounts: keys from a 32-byte seed, ML-DSA-65 by default, ML-DSA-87 optional.
- Issued assets, policy locks and PST as first-class types.
- Subscriptions as async iterators with
AbortSignalsupport that resume from the last event id. - Conformance: each SDK reproduces every vector in
core/vectors/*.json(keys, hashing, transactions, PST, base layer, security) byte for byte, and CI runs the examples against a regtest node.
Same example, both languages
/**
* Send a payment: derive a wallet, fund it on regtest, pay 1.5 ARRK, confirm.
*
* ARREKTA_URL=http://127.0.0.1:28332 ARREKTA_ADMIN_TOKEN=... npx tsx examples/send-payment.ts
*/
import { createClient, formatArrk, fromHex, generateSeed, getAddress, getChain, getCoins, keychainFromSeed, mine, sendPayment } from 'arrekta-sdk';
const URL = process.env.ARREKTA_URL ?? 'http://127.0.0.1:28332';
const ADMIN = process.env.ARREKTA_ADMIN_TOKEN; // regtest mining for the demo
const SEED = fromHex(process.env.ARREKTA_SEED ?? 'a1'.repeat(32));
// 1. Connect and read the chain.
const client = createClient({ url: URL, adminToken: ADMIN });
const chain = await getChain(client);
console.log(`connected to ${chain.network} at height ${chain.height}`);
// 2. Alice's wallet from her seed; Bob gets a fresh one.
const alice = keychainFromSeed(SEED, { network: chain.network });
const bob = keychainFromSeed(generateSeed(), { network: chain.network });
// 3. Fund Alice (regtest: mine past coinbase maturity).
if ((await getCoins(client, { wallet: alice })).length === 0) await mine(client, alice.address(0), 101);
// 4. Pay Bob 1.5 ARRK (fee rate from the node's estimate).
const sent = await sendPayment(client, { wallet: alice, to: bob.address(0), amount: '1.5' });
console.log(`sent ${sent.txid} (fee ${formatArrk(sent.fee)} ARRK)`);
// 5. Confirm and check Bob's balance.
await mine(client, alice.address(0), 1);
const balance = (await getAddress(client, { address: bob.address(0) })).balances[0]!;
console.log(`bob has ${formatArrk(balance.spendable)} ARRK`);"""Send a payment: derive a wallet, fund it on regtest, pay 1.5 ARRK, confirm.
ARREKTA_URL=http://127.0.0.1:28332 ARREKTA_ADMIN_TOKEN=... python examples/send_payment.py
"""
import os
from arrekta_sdk import Client, format_arrk, generate_seed, keychain_from_seed
URL = os.environ.get("ARREKTA_URL", "http://127.0.0.1:28332")
ADMIN = os.environ.get("ARREKTA_ADMIN_TOKEN") # regtest mining for the demo
SEED = bytes.fromhex(os.environ.get("ARREKTA_SEED", "a1" * 32))
def main() -> None:
# 1. Connect and read the chain.
client = Client(URL, admin_token=ADMIN)
chain = client.get_chain()
print(f"connected to {chain['network']} at height {chain['height']}")
# 2. Alice's wallet from her seed; Bob gets a fresh one.
alice = keychain_from_seed(SEED, network=chain["network"])
bob = keychain_from_seed(generate_seed(), network=chain["network"])
# 3. Fund Alice (regtest: mine past coinbase maturity).
if not client.get_coins(alice):
client.mine(alice.address(0), 101)
# 4. Pay Bob 1.5 ARRK (fee rate from the node's estimate).
sent = client.send_payment(alice, bob.address(0), "1.5")
print(f"sent {sent.txid} (fee {format_arrk(sent.fee)} ARRK)")
# 5. Confirm and check Bob's balance.
client.mine(alice.address(0), 1)
balance = client.get_address(bob.address(0))["balances"][0]
print(f"bob has {format_arrk(balance['spendable'])} ARRK")
if __name__ == "__main__":
main()Source: sdk/typescript/examples/send-payment.ts (updated 2026-11-02) · sdk/python/examples/send_payment.py (updated 2026-11-02). Runnable against a regtest node; CI runs every example.
Sections
| Topic | TypeScript | Python |
|---|---|---|
| Install | Install | Install |
| Clients | Clients | Clients |
| Actions | Actions | Actions |
| Accounts & keys | Accounts | Accounts |
| Transactions | Transactions | Transactions |
| PST | PST | PST |
| Errors | Errors | Errors |
| Units | Units | Units |