Repository Public
1// Plugin contract for chain families beyond the three built-in ones (evm, btc, sol).2// One file per family implements this; the signer, the API pre-check and the address validator all go through it,3// so the bytes the owner approves, the bytes the API simulates and the bytes the signer signs come from the same code.4import type { Intent } from './intent.ts';5import type { NetworkDef } from './networks.ts';67/** Signing capability handed to a plugin by the signer. The private key itself never leaves the signer's key module. */8export interface KeyHandle {9 curve: 'secp256k1' | 'ed25519';10 /** secp256k1: 33-byte compressed key. ed25519: 32-byte key (Cardano, keyScheme 'cip1852': 64 bytes = payment key ‖ stake key; only the payment key signs). */11 publicKey: Uint8Array;12 /** secp256k1 only: sign a 32-byte digest (deterministic, low-S). */13 signDigest?(digest: Uint8Array): { compact: Uint8Array; recovery: number; der: Uint8Array };14 /** ed25519 only: sign a message. */15 signMessage?(message: Uint8Array): Uint8Array;16}1718export interface Signed { raw: string; txid: string }1920export interface FamilyPlugin {21 family: string;22 curve: 'secp256k1' | 'ed25519';23 /**24 * v8-cardano-polkadot: how an ed25519 key is derived from the seed. Absent / 'slip10' = SLIP-0010 from the BIP-39 seed (every25 * family before Cardano). 'cip1852' = BIP32-Ed25519 (Icarus master key from the BIP-39 entropy), which allows soft derivation.26 */27 keyScheme?: 'slip10' | 'cip1852';28 /** derivation path for this network (hardened-only for ed25519 / SLIP-0010) */29 path(net: NetworkDef): string;30 /** the wallet's address on this network, from its public key */31 address(net: NetworkDef, publicKey: Uint8Array): string;32 /** validate and normalize a destination address; throws when invalid */33 normalizeAddress(net: NetworkDef, addr: string): string;34 /**35 * Rebuild the exact transaction from the intent alone and return what will be signed.36 * Must throw on anything that is not a plain native transfer or an allowlisted token transfer,37 * on a fee above intent.maxFee, and on any field it does not understand. `aux` is unauthenticated helper data38 * (never trusted: everything in it must be verified against the intent).39 */40 build(i: Intent, net: NetworkDef, aux?: Record<string, unknown>): { signDocs: Uint8Array[]; describe: Record<string, string> };41 /** build + sign + serialize for broadcast */42 sign(i: Intent, net: NetworkDef, key: KeyHandle, aux?: Record<string, unknown>): Signed;43}4445export const PLUGINS: Record<string, FamilyPlugin> = {};46export function registerFamily(p: FamilyPlugin): void { PLUGINS[p.family] = p; }47export function pluginFor(net: NetworkDef): FamilyPlugin {48 const p = PLUGINS[net.family];49 if (!p) throw new Error(`no implementation for chain family "${net.family}"`);50 return p;51}52export const isBuiltinFamily = (f: string) => f === 'evm' || f === 'btc' || f === 'sol';53