@picocash/sdk
v0.1.0
Published
Agent wallet-lite for picocash: mint, swap, melt, offline verification, and challenge-bound payments. Stateless-capable — token storage is the caller's responsibility.
Downloads
195
Readme
@picocash/sdk
Wallet-lite for agents (architecture component 5). Stateless-capable: the SDK holds no tokens — every method takes proofs and returns proofs, and storage is the caller's problem (a file, a DB row, a KV entry).
import { Wallet, verifyProofOffline } from '@picocash/sdk';
const wallet = new Wallet({ mintUrl: 'http://localhost:3338' });
const quote = await wallet.requestMintQuote(1_000_000); // → pay quote.deposit on Tempo
// … transferWithMemo(deposit.to, amount, deposit.memo) …
const proofs = await wallet.mintProofs(quote.quote_id, 1_000_000); // DLEQ-verified, carries r
const { bundle, change } = await wallet.send(proofs, 250_000); // exact bundle + change
const claimed = await wallet.receive(bundle); // offline-verify, then own via swap
await wallet.meltProofs('0x…', claimed); // back to on-chain fundsKey properties:
- Every minted/swapped proof carries
dleq: {e, s, r}, so anyone can verify it offline against the mint's published keys (verifyProofOffline) — the basis of agent-to-agent transfer and MPP accept-then-settle. - Every signature from the mint is DLEQ-verified before the SDK trusts it; a mint that can't prove its signatures throws.
serializeToken/parseTokenimplement PIP-06picoA…tokens;wallet.send()returns the string,wallet.receive()accepts it.wallet.createLink(token)/wallet.receive(link)implement PIP-07 token links: AES-GCM client-side, key in the URL fragment, burn-after-read at the relay.pcBindSecretHex/parsePcBindSecretimplement the canonicalPC-BINDchallenge-bound secrets from PIP-05.- Mint errors surface as
MintApiErrorwith the mint's machine-readablecodeandrecoveryhint.
Tests run against an in-process mint (no HTTP, no chain): npm test.
Locked tokens (PIP-08 P2PK)
import { p2pkPublicKey } from '@picocash/crypto';
// human: fund an agent that can spend only with merchant M; reclaim after 24h if unused
const { token, change } = await wallet.sendLocked(proofs, 500_000, merchantPubkey, {
locktime: Math.floor(Date.now() / 1000) + 86_400,
refund: [p2pkPublicKey(myKey)],
});
// merchant: claim (signs with its key and swaps to unconditional proofs)
const mine = await merchantWallet.receive(token, { unlockKey: merchantKey });
// anyone: inspect the lock offline
lockOf(proof); // { data: '02…', locktime, refund: […], … } | null