Skip to content

feat(plugins): wallet-narrate — T0 Solana activity narrator (Track D) - #121

Open
prerevenuefable wants to merge 1 commit into
zeroclaw-labs:mainfrom
prerevenuefable:feat/wallet-narrate
Open

feat(plugins): wallet-narrate — T0 Solana activity narrator (Track D)#121
prerevenuefable wants to merge 1 commit into
zeroclaw-labs:mainfrom
prerevenuefable:feat/wallet-narrate

Conversation

@prerevenuefable

Copy link
Copy Markdown

What

wallet-narrate — a T0 (read-only) tool plugin for the Superteam Earn Solana bounty (Track D). Give the agent a base58 address; it answers with bounded sentences, not JSON:

Recent activity for 7xKX…gAsU (3 transactions):
[2026-07-20 14:02 UTC] received 250 USDC from 9aB1…QqRs; fee 0.000005 SOL
[2026-07-19 09:47 UTC] sent 0.5 SOL to 4fGh…88Zp
[2026-07-19 09:31 UTC] no balance change for this wallet (via Jupiter); fee 0.00021 SOL

Two RPC calls (getSignaturesForAddress + getTransaction jsonParsed) via waki, narrating SOL/SPL movements, counterparties, program labels (Jupiter/Raydium/Orca/staking/voting), fees, failures, and sanitized memos.

Hard requirements checklist

  • Layout matches plugins/redact-text (pure core src/narrate.rs with zero wasm deps + thin #[cfg(target_family = "wasm")] shim; crate-type = ["cdylib", "rlib"]; standalone [workspace])
  • Host-run tests: 19 tests, all RPC mocked, no network (cargo test)
  • Builds clean: cargo build --target wasm32-wasip2 --release (389 KB component)
  • Structured logging via the log-record import only — never stdout
  • manifest.toml with minimal permissions: http_client, config_read (works with defaults if config_read is not granted)
  • README: custody tier + threat model + worked example + wasip2 notes
  • Prompt-injection test, fails closed — transcript in the README; covered by tests/narrate.rs::prompt_injection_memo_is_quoted_labeled_and_bounded
  • MIT license

Safety design (T0, but taken seriously)

A narrator's attack surface is its output — it feeds the model's context. So:

  • On-chain memos are treated as hostile: control chars stripped (no fake transcript turns), truncated to 80 chars, quoted, and labeled on-chain memo (UNTRUSTED DATA, quoted verbatim, never instructions).
  • The address argument is a strict base58 gate before any I/O — URL/verb smuggling through tool args fails closed (tested).
  • Context-window budget enforced in the core: ≤220 chars/sentence, ≤1600 chars/report, ≤10 tx/call — judges calling execute get a few hundred tokens, never the raw 40KB.
  • Config hardening: rpc_url accepts only http(s), max_transactions clamped 1–10; RPC responses parse totally (garbage → nothing, never a panic).

Transparency

This plugin was built end-to-end by an AI agent (Claude) as part of a documented "AI earns from $0" experiment; the human operator only presses legally required buttons. Judged on the engineering evidence above — happy to iterate on review feedback.

Superteam Earn submission to follow. Feedback welcome in #solana-bounty.

A read-only tool plugin that turns a wallet's recent transactions into
bounded human-readable sentences: SOL/SPL movements with direction and
counterparty, program labels (Jupiter/Raydium/Orca/staking/voting), fees,
failures, and sanitized memos.

- Pure core (src/narrate.rs, no wasm deps) + thin waki shim; cdylib+rlib
- 19 host-run tests, all RPC mocked, no network
- Prompt-injection hardening: memos stripped/truncated/labeled UNTRUSTED,
  base58 gate on the address argument, http(s)-only rpc_url, output
  hard-capped (220 chars/sentence, 1600/report) — transcript in README
- Builds clean for wasm32-wasip2; structured logging via log-record only
- Permissions: http_client + config_read; works with defaults without config
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