Skip to content

feat(cli): add yacd wallet verbs with direct tx submission#106

Merged
jmgilman merged 2 commits into
masterfrom
feat/cli-wallet-verbs
Jun 4, 2026
Merged

feat(cli): add yacd wallet verbs with direct tx submission#106
jmgilman merged 2 commits into
masterfrom
feat/cli-wallet-verbs

Conversation

@jmgilman
Copy link
Copy Markdown
Contributor

@jmgilman jmgilman commented Jun 4, 2026

Phase 3 — CLI-native wallets / faucet-removal plan

Adds a yacd wallet command subtree that manages test wallets as Kubernetes Secrets and funds them by building, signing, and submitting transactions directly against Ogmios/Kupo (via internal/cardano/tx), spending from the genesis-funded faucet wallet (P2). The standalone yacd topup and its faucet-HTTP transport + token trust gate are removed and folded into wallet topup.

Verbs

  • yacd wallet list NET [--json]
  • yacd wallet add NET [--name N] [--topup L] [--await] — keygen → owned Secret → optional fund from faucet
  • yacd wallet topup NET WALLET L [--from SRC] [--await] — fund a wallet (or raw address) from faucet/--from
  • yacd wallet export NET WALLET [--out DIR] [--force] — write 0600 .skey/.vkey/.addr
  • yacd wallet remove NET WALLET

WALLET is a second positional accepting a name / pubkey-hex / bech32 address (a raw address funds directly). Names come from an embedded adjective-noun wordlist (collision-checked, ~50/network ceiling).

Internals

  • wallet.DecodePaymentKeyEnvelope (manager-safe) decodes the cardano-cli key envelope → raw 32-byte hex for both skey (signing) and vkey (pubkey).
  • cli/internal/wallet store (labeled Secrets matching P2's yacd.meigma.io/wallet-name/wallet-source, ownerRef → the network) + name/pubkey/address selector + wordlist.
  • kube.Client gains Secret CRUD/list-by-label; an injectable tx.Submitter seam makes the funding verbs unit-testable without a real chain.
  • Funding self-forwards Ogmios+Kupo (loopback) via the existing forwardEndpoints; confirmation reuses the kugo path.

Manager boundary (load-bearing)

go list -deps ./cmd stays free of ogmigo/kugo/internal/cardano/tx; internal/cardano/wallet's new helper is manager-safe (cbor/json/ed25519 only). Only the CLI gains the chain-tx stack.

Verification

  • moon run root:check ✅ · moon run root:test ✅ (wallet verbs + store + decode, all against mocks — --from, readiness gating, partial-failure, export edge cases, selector resolution, ceiling). gofmt/go build/go vet clean.
  • Live-proven on the Kind dev stack: wallet add alice --topup 1000000000 --await had the CLI build+sign+submit a real funding tx from the faucet wallet (tx 1198bc05…, confirmed on-chain); cardano-cli query utxo showed alice holding 1,000,000,000 lovelace; wallet list showed her; wallet export wrote a valid 0600 cardano-cli .skey.

Known follow-up (not blocking)

Apollo's chain-context init logs a transient Ogmios websocket hiccup (the known ogmigo/Gorilla-WS behavior) during funding; the tx still succeeds. Worth quieting/handling later.

Plan context

Phase 3 of 5. Next: P4 (cut over devnet/dev-wallet funding to the CLI, then delete the in-cluster faucet service + spec.chainAPI.{faucet,wallet}).

🤖 Generated with Claude Code

Add a `yacd wallet` subtree (list/add/topup/export/remove) that manages test wallets as labeled Kubernetes Secrets and funds them by building, signing, and submitting transactions directly against Ogmios/Kupo via internal/cardano/tx, spending from the genesis-funded faucet wallet. The standalone `yacd topup` command and its faucet-HTTP transport + token trust gate are removed and folded into `wallet topup` (faucet is the default --from source).

New: wallet.DecodePaymentKeyEnvelope (manager-safe); a cli/internal/wallet store + name|pubkey|address selector + embedded wordlist; kube.Client Secret ops; an injectable tx.Submitter seam for unit-testable funding. The manager (./cmd) stays free of ogmigo/kugo/tx; only the CLI gains the chain-tx stack. Phase 3 of the CLI-native wallets / faucet-removal plan.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jmgilman added a commit that referenced this pull request Jun 4, 2026
- Route Apollo's genesis-config warning (a hardcoded fmt.Printf to stdout during chain-context init) to stderr while funding, so 'wallet topup/add --json' emits valid JSON.

- Validate the wallet name as a DNS-1123 label up front, with a clear error instead of a raw Kubernetes label-validation message.

- Report a missing wallet as 'wallet "X" not found' for 'export' and 'remove' (consistent with the funding path), instead of leaking the Secret name or printing a misleading 'Removed'.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jmgilman
Copy link
Copy Markdown
Contributor Author

jmgilman commented Jun 4, 2026

Full manual functional test (Kind dev stack) — done, with fixes

Ran the complete yacd wallet surface against a live local faucet network. Everything works, including the end-to-end key story (real cardano-cli derives the same address from an exported vkey and round-trips skeyvkey), cross-wallet funding with exact balance math, all three selector forms (name / pubkey / address), and the faucet-gate on a faucet-less network.

Found and fixed 4 UX issues (commit c765310), each re-validated live:

  1. --json was broken on funding — Apollo's OgmiosChainContext.GenesisParams does a hardcoded fmt.Printf to stdout on a non-fatal genesis-config fetch hiccup, corrupting wallet topup/add --json. Now routed to stderr; --json stdout is clean valid JSON.
  2. Invalid wallet name now validated as a DNS-1123 label up front (clear error vs a raw Kubernetes label-validation message).
  3. export of a missing wallet now says wallet "X" not found (was leaking the Secret name).
  4. remove of a missing wallet now says wallet "X" not found (was a misleading "Removed").

Added test coverage for the new validation + not-found paths. root:check/root:test green.

@jmgilman jmgilman merged commit 0b3a629 into master Jun 4, 2026
12 checks passed
@jmgilman jmgilman deleted the feat/cli-wallet-verbs branch June 4, 2026 13:53
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