Skip to content

feat: Solana payment suite — nonce-transfer-build (T1), payment-watch (T0), x402-settle (T2)#130

Open
luongs3 wants to merge 1 commit into
zeroclaw-labs:mainfrom
luongs3:safe-hands-solana
Open

feat: Solana payment suite — nonce-transfer-build (T1), payment-watch (T0), x402-settle (T2)#130
luongs3 wants to merge 1 commit into
zeroclaw-labs:mainfrom
luongs3:safe-hands-solana

Conversation

@luongs3

@luongs3 luongs3 commented Jul 22, 2026

Copy link
Copy Markdown

What

Three new tool plugins that let a ZeroClaw agent participate in Solana payments safely, plus the shared pure-Rust primitives they build on (vendored per-plugin to keep each crate standalone):

Plugin Custody tier Tool What it does
nonce-transfer-build T1 — never holds a key build_nonce_transfer Builds unsigned, durable-nonce-anchored SPL transfers, so a human can review/sign hours later without blockhash expiry. Operator allowlist + per-tx caps are enforced in-plugin, fail-closed, before any bytes are built.
payment-watch T0 — read-only check_payment Chain-verifies that an expected payment actually landed (amount, mint, memo) via JSON-RPC — closes the loop for invoice/agent-commerce flows without trusting the counterparty's word.
x402-settle T2 — capped session key fetch_paid_resource HTTP 402 payment settlement per the x402 exact SVM scheme (X-PAYMENT header, partially-signed tx, extra.feePayer sponsor, verbatim seller memo ≤256B) with hard per-request caps enforced in-plugin.

Why

Payments are the sharpest edge an agent can touch. The suite is designed around one principle: the blast radius of a prompt injection must be bounded by operator config, not model behavior. Allowlists and caps live in the plugin's jailed config section and are checked before any transaction bytes exist; each README documents the threat model, custody tier, and includes a real injection-attempt transcript (tool-level refusal, independent of the model also refusing).

How

  • Pure-Rust wasm32-wasip2 components against wit/v0 tool-pluginno solana-sdk (it doesn't target wasip2). Base58, compact-u16, instruction encoding, legacy message + durable-nonce construction, JSON-RPC shaping, and the spend-policy engine are implemented in a small shared core, vendored under each plugin's vendor/solana-wasi-core/ so every crate stays a self-contained standalone workspace.
  • Pure cores are host-testable with plain cargo test — 25 tests across the suite plus 42 in the vendored core, including an ATA-derivation golden vector pinned against a real mainnet USDC ATA.
  • Permissions: http_client (JSON-RPC / 402 fetch) + config_read only. Deny-by-default; no sockets, no filesystem.
  • Honest limitation, documented in the READMEs: per-day cap tracking is host-side (fresh-store-per-call keeps plugins stateless); per-request/per-tx caps always bind in-plugin.

Validation

Local run of the CI gates on all three plugins (stable, aarch64-darwin):

  • cargo fmt --all -- --check
  • cargo test ✅ (8 / 7 / 10 per plugin + 42 core)
  • cargo clippy --all-targets -- -D warnings ✅ (host)
  • cargo clippy --target wasm32-wasip2 -- -D warnings
  • cargo build --target wasm32-wasip2 --release ✅ (399 KB / 358 KB / 438 KB)
  • wit/v0 untouched (byte-identical to the vendored pin); registry.json untouched (CI-generated).

Also exercised end-to-end against a from-source zeroclaw host (--features plugins-wasm,plugins-wasm-cranelift) on devnet: agent → build_nonce_transfer → out-of-band human sign → landed transaction (43YH62EC…E3f8, slot 478052328, err: null), and check_payment verifying a live transfer with memo matching.

Happy to split the suite into three PRs if you prefer one plugin per PR — they're independent crates.

Three tool plugins that let a ZeroClaw agent participate in Solana payments
without ever holding a signing key it shouldn't:

- nonce-transfer-build (T1): builds unsigned, durable-nonce-anchored SPL
  transfers that survive human approval delays. Operator allowlist + per-tx
  caps enforced in-plugin before any bytes are built.
- payment-watch (T0): read-only chain verification that an expected payment
  landed (amount, mint, memo) — closes the loop for invoice flows.
- x402-settle (T2): HTTP 402 x402 exact-svm scheme settlement with hard
  per-request caps; verbatim seller memo, partially-signed tx per spec.

Pure-Rust wasip2 components (no solana-sdk): shared primitives (base58,
compact-u16, instruction encoding, legacy message + durable-nonce
construction, JSON-RPC shaping, fail-closed spend policy) are vendored
per-plugin under vendor/solana-wasi-core to keep each crate standalone.
Host-testable cores with plain cargo test (25 tests across the suite;
ATA-derivation golden vector pinned against a real mainnet USDC ATA).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant