feat: merge wallet CLI into unified zerion-cli#5
Conversation
Combine wallet analysis (read) and trading (write) capabilities into a single CLI distributed via npm, MCP, and the skills marketplace. - Add 26 trading commands: swap, bridge, buy/sell, wallet management, agent tokens, and security policies (from zerion-wallet-cli) - Adopt modular router architecture with separate command handlers - Merge API client with x402 pay-per-call support on all endpoints - Add wallet-trading skill for AI agent integration - Add MCP tool definitions for swap, wallet-create, and search - Lazy-load trading deps (OWS, Solana, qrcode) for lightweight reads - Port wallet-cli tests; all 139 tests pass Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Delete cli/lib.mjs — all functions moved to proper modules: - parseFlags → cli/lib/flags.js - basicAuthHeader → cli/lib/api-client.js (now exported) - validateChain, validatePositions, CHAIN_IDS, POSITION_FILTERS → cli/lib/validate.js (new) - summarizeAnalyze → cli/lib/analyze.js (new) - Create dedicated wallet-positions.js with --positions all|simple|defi and --chain filtering (was incorrectly aliased to portfolio handler) - Update wallet-analyze.js to import shared summarizeAnalyze - Repoint unit.test.mjs and consistency.test.mjs to new modules - Fix consistency tests to skip auth/method checks on CLI tool definitions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The chains command now uses local chain data instead of calling the API, so the "invalid API key returns error" test needs to use a command that actually hits the API (wallet pnl). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Restructure --help into categorized sections (wallet_management, wallet_analysis, trading, agent_tokens, agent_policies, watchlist) - Add policy flags, env vars, and supported chains to help output - Document ZERION_AGENT_TOKEN usage in help - Rewrite zerion-cli skill with end-to-end agent wallet setup flow, key management details, and comprehensive command reference Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Critical: - Fix chain ID mismatch: validate.js now imports SUPPORTED_CHAINS from chains.js instead of maintaining a separate set with wrong names Security: - wallet-export: require --yes or interactive confirmation before displaying seed phrase; output to stderr to prevent accidental piping - x402.js: read WALLET_PRIVATE_KEY at call time, not module load Code quality: - Extract resolveAddressOrWallet() shared helper (DRY 4 commands) - Lazy-init ENS client in resolve-wallet.js - Fix getApiKey() called twice per API request in fetchAPI - Import basicAuthHeader in simulate.js instead of inlining - Remove dead code: errors.js, MAX_UINT256 in tx.js, resolveOutputMode in output.js Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…on, and QA plan - Wallet create/import now always prompt for passphrase interactively with masked input (*) — the --passphrase flag is ignored to prevent exposure in shell history and process listings - Wallet export requires TTY, blocks agent mode, writes mnemonic to stderr only (never stdout), and prompts passphrase interactively - Add wallet delete command with passphrase verification + "Type DELETE" confirmation, agent-mode blocking, and TTY requirement - Add --limit, --offset, --search pagination to wallet list (default 20) - Remove unused simulate.js (Blockaid integration not wired in) - Add comprehensive QA-PLAN.md with 80+ test cases Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move flat command and lib files into domain subdirectories for scalability. Remove buy/sell convenience commands (use swap instead). Rename ambiguous files for clarity. Commands: wallet/, trading/, agent/, analytics/ + config.js Lib: util/, api/, chain/, wallet/, trading/ + config.js, analyze.js Key renames: - export → wallet/backup (seed phrase) + wallet/sync (Zerion app QR) - ows.js → keystore.js, tx.js → transaction.js - stdin.js → prompt.js, chains.js → registry.js - swap-tokens → list-tokens, analyze → activity/overview Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Rename walletExport→walletBackup, update error messages from "wallet export" to "wallet backup" in backup.js - Rename exportCmd→walletSync, export_error→sync_error in sync.js - Move lib/analyze.js→lib/util/analyze.js (no more orphans at lib root) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CRITICAL: create-policy.js used __dirname + ".." which now resolves to commands/ instead of cli/ after the directory restructure. This silently disabled all executable security policies (deny-transfers, deny-approvals, allowlist) at transaction time. Fixed to "../..". Also hardens pre-existing bare catch patterns: - revokeAgentToken: only fall through on "not found" errors - wallet delete: distinguish passphrase errors from keystore errors Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- run-policies.mjs: only catch module-not-found, rethrow real errors - wallet/create.js: log warning when listWallets fails in generateName - api/client.js: preserve raw response text on JSON parse failure - trading/swap.js: log fungible lookup failures instead of swallowing - trading/transaction.js: log gas estimation failures with fallback - wallet/resolve.js: distinguish "not found" from keystore errors Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
getAgentToken() previously just read the env var without checking if the token was still valid. A revoked token would still be passed to OWS as a passphrase, potentially allowing signing to succeed. Now validates the token against the active token list before returning it. Throws a clear error if the token is revoked. Also fixes suggestion strings to use "zerion-cli" consistently. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previously, swap and bridge commands passed `undefined` as passphrase when no ZERION_AGENT_TOKEN was set, allowing wallets without passphrases to sign transactions without any authentication. Now both commands prompt interactively via readPassphrase() when no agent token is present, ensuring every trade requires explicit authentication. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The token validation was comparing against listApiKeys() which doesn't return the token secret (only shown once at creation). Every valid token was being rejected. OWS already validates tokens when signing — if a token is revoked, ows.signTransaction() will fail with an auth error. No need to duplicate validation at the CLI layer. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
OWS returns "API key not found" when a revoked agent token is used for signing, which is confusing. Now swap/bridge catch this and show: "Agent token is revoked or invalid" with instructions to unset or create a new token. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Zerion API swap response includes chain_id which was being parsed and used for the transaction. This could return a different chain (e.g. Ethereum) than what the user specified with --chain, causing policy violations like "chain eip155:1 not in allowlist" even when --chain base was passed. Now always uses the chain ID derived from the user's --chain flag via getViemChain(), ensuring the transaction matches the user's intent and policy rules. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
OWS was checking chain policies against the wallet's default account chain (eip155:1 = Ethereum) instead of the transaction's target chain. A "base-only" policy would always fail because OWS saw eip155:1. Now passes the correct CAIP-2 chain ID (e.g. eip155:8453 for Base) to ows.signTransaction(), so policies enforce against the actual target chain. Applies to both swap and ERC-20 approval signing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add 30s AbortController timeout to all API fetch calls - Add 120s timeout to waitForTransactionReceipt (prevents hang on congested chains) - URL-encode wallet addresses in all API endpoint paths (ENS safety) - Add optional chaining for tx.attributes in history.js - Add optional chaining for attributes in resolve-token.js From API contract specialist review. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…orts Critical security fixes from specialist review: - create-token now requires interactive passphrase (was accepting via --passphrase flag or defaulting to empty string) - Redact token from stderr usage example (prevent log leakage) - Add path traversal guard for --key-file/--mnemonic-file in import Performance fix: - Cache config.json reads (was re-reading disk on every getConfigValue) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove unused Transaction/VersionedTransaction imports from solana.js - Remove unused txBase64 variable from solana.js - Remove dead validateChain from registry.js (validate.js is the canonical one) - Remove dead printQuiet from output.js (never called) From maintainability specialist review. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… codebase Also removes QA-PLAN.md (no longer needed). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- cli/README.md: rewritten with all commands, flags, env vars, error table - mcp/README.md: trimmed duplicated auth section, points to root README - skills/zerion-cli/SKILL.md: added positions shorthand and ENS note Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds every flag variant for wallet list, analyze, swap, bridge, search, agent tokens, policies, watchlist, config, and shorthands. Adds global flags table. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The npm package, binary, config directory, and all references are now "zerion" instead of "zerion-cli". A migration helper auto-moves ~/.zerion-cli to ~/.zerion on first run and notifies upgrading users. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…curity hardening Based on QA feedback testing the CLI with AI agents (Codex, Claude): - Add `zerion send` command for native and ERC-20 transfers - Add `wallet create --agent` for zero-prompt wallet + token setup - Auto-save agent tokens to config — no more env var export needed - Require agent token for all trading (swap/bridge/send) — no passphrase prompts - Add `--passphrase-file` for automated wallet setup commands - Add `--timeout` flag and progress output for bridge operations - Add bridge delivery polling via positions API (snapshot + poll) - Surface per-position 24h changes in `wallet positions` output - Separate broadcast failure from confirmation timeout in error handling - Add ERC-20 balance check (balanceOf) before send to prevent gas waste - Harden path traversal: lstatSync rejects symlinks, realpathSync resolves before blocklist - Fix operator precedence bug in import.js path guard - Atomic recovery file write (O_CREAT|O_EXCL), wallet name sanitization - Remove agent token from stdout/stderr — only saved to config - Extract shared guards.js (requireAgentToken, parseTimeout, handleTradingError) - Extract offer-agent-token.js shared module - Update all docs and skills for new commands and auth flow Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
realpathSync resolves /etc/passwd to /private/etc/passwd on macOS. Updated regex to match both /etc/ and /private/etc/ (and /proc, /sys, /dev). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
🔴 High 🟡 Medium 🟡 Medium 🔵 Low |
…tent HOME - Redact agentToken alongside apiKey in config list/get/set (credential leak fix) - Replace plain-text migration banner with JSON stderr notices - Unify HOME resolution via constants.js (os.homedir fallback for Windows) - Update integration tests to match current CLI output contract Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…y picker - Agent tokens now always require a security policy (no policy-less tokens) - Interactive 3-tier picker: Standard (deny-transfers + expiry), Strict (+ chain restriction), Custom (existing policy) - Expiry step: 7d / 30d / no expiry - Chain checklist with arrow keys + Space to toggle - Esc to go back to previous step from any sub-menu - Shared policy-picker.js used by both `wallet create` and `agent create-token` - Add `config unset <key>` command to remove config values - Add passphrase warning before wallet creation confirmation - Remove --key-file import option - Custom policy display now shows deny-transfers, expiry countdown, chain names - Update README, zerion skill, and wallet-trading skill Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- findMatchingPolicy checks for existing policies with same scope (scripts, chains, non-expired expiry with >50% time remaining) - Shows "Reusing policy" vs "Policy created" in output - Also includes unstaged changes from prior PR review round Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Rename --key to --evm-key for clarity - Add --sol-key for Solana private key import (base58, hex, byte array) - normalizeKeyToHex auto-detects key format and converts for OWS - Track wallet origin (evm-key/sol-key/mnemonic) in config - Suppress non-imported chain addresses in list, fund, and import output - Hide walletOrigins from config list (internal-only) - Strip null values from JSON output - Remove misleading import-only security warning, add passphrase warning - Update README, router help, and skills Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…kens - Add `agent use-token --wallet <name>` to switch active wallet and token - Store tokens as agentTokens map keyed by wallet name - Active token derived from agentTokens[defaultWallet] — no duplicate fields - Remove redundant agentToken and activeTokenWallet config fields - list-tokens shows wallet name and active flag - revoke-token cleans up agentTokens config - wallet delete revokes tokens, cleans config, promotes next wallet - Hide internal config keys (agentTokens, walletOrigins) from config list Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bugs: - Remove stale mnemonic-file flag check (would crash at runtime) - Block config get from leaking internal keys (agentTokens, walletOrigins) - Remove dead imports (node:fs, node:path) from import.js - Remove unused listSavedAgentTokens import from delete.js Code reuse: - Extract PASSPHRASE_WARNING and WALLET_ORIGIN constants to constants.js - Add getWalletAddresses() helper — replaces 3x duplicated origin filtering - Add getWalletNameById() to keystore.js — replaces 2x walletIdToName map - Add removeWalletOrigin() to config.js — replaces inline cleanup in delete.js - Validate key in config get (same as set/unset) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…n, send usage - Replace unreliable default RPC with llamarpc + publicnode fallbacks and retry logic - Support ETH_RPC_URL env var (matches existing SOLANA_RPC_URL pattern) - Only mark newest token per wallet as active (config only saves one per wallet) - Eliminate duplicate getWalletNameById lookups in list-tokens - Validate address input — reject invalid strings with clear error - Tighten Solana address regex to 43-44 chars (actual public key length) - Add --chain to send usage message Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Trading commands (swap, bridge, send) now execute immediately. The agent token requirement already provides authorization control. Updated all docs, skills, and usage messages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fixes API-key signing for wallets imported via private key (open-wallet-standard/core#151). The old version (1.1.2) tried to parse the decrypted key material as a mnemonic, causing "invalid mnemonic phrase" errors for non-mnemonic wallets. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
OWS enforces native rules (allowed_chains, expires_at) but does not run executable policy scripts. This adds CLI-side enforcement before signing for all trading commands (swap, bridge, send). Closes the gap where deny-transfers policies were stored but never actually checked during transaction execution. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…licy - Active token lookup now filters by defaultWallet instead of taking the newest token across all wallets (security: prevents policy bypass) - Policy lookup failures now block the transaction (fail-closed) instead of silently continuing Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add --from-chain to bridge examples (README, zerion SKILL, trading SKILL) - Add agent use-token command to docs - Add ETH_RPC_URL env var to README and zerion SKILL - Add missing flags (--from-chain, --to, --to-token, --timeout) to README - Remove commands.md from repo Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Both commands now resolve and display policy names so users can see which policies guard each wallet's active agent token at a glance. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Display chains, expiry, and executable guards inline so users can see what each wallet's active policy allows at a glance. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Trading and analysis commands are agent operations (no passphrase, fully automated). Wallet setup, token/policy creation require interactive input and are marked as manual/human-only. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
analyze command exits 1 when no API key exists (CI has no config). Test now accepts both exit 0 (key in config) and exit 1 (no key, graceful error with stderr output). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tests were silently skipping by checking only ZERION_API_KEY env var, ignoring the config file where the key actually lives. Also updates stale response shape assertions (chains, analyze, ENS label). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Wire analyze to correct handler (overview.js), add Solana positional address support, fix slippage 0 treated as falsy, include gas cost in native balance check, validate --chain in trading commands, resolve actual token decimals for send, validate policy script paths, use atomic config writes with corruption protection, fix stale chain IDs in skills, align MCP swap schema with always-execute behavior, remove ambiguous 'm' expiry unit, remove dead activity.js. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
Merges
zerion-wallet-cliinto a unifiedzerionCLI — single entry point for wallets, trading, agent tokens, policies, and analytics.Replaces monolithic
cli/zerion-cli.js(247 lines) with a domain-grouped router (cli/router.js) + 28 modular command handlers across 4 domains.Commands added
create,import,list,backup,delete,fund,watch,syncswap,bridge,send,search,list-tokens,chainscreate-token,revoke-token,list-tokens,use-token,create-policy,delete-policy,list-policies,show-policyportfolio,positions,pnl,activity,history,overviewset,get,list,resetShared libraries (
cli/lib/)api/— HTTP client with timeouts, URL encoding, null guards; x402 payment supportchain/— chain registry (14 chains, CAIP-2 IDs), Solana helperstrading/— token resolution, swap execution, transaction handling, trade guardswallet/— encrypted keystore, ENS/address resolution, watchlist, policy pickerutil/— flags, formatting, output, prompts, validation, analysis, migrationLocal policy engine (
cli/policies/)allowlist.mjs— restrict destinations to known addressesdeny-approvals.mjs— block unlimited token approvalsdeny-transfers.mjs— prevent transfers above thresholdrun-policies.mjs— orchestrates policy evaluation before signingSecurity hardening
catchreplaced with explicit error handling/etc→/private/etc)MCP tools
8 tool definitions:
wallet-create,swap,search,chains-list,wallet-portfolio,wallet-positions,wallet-pnl,wallet-transactionsSkills
4 skill packages:
zerion(full CLI reference),wallet-analysis,wallet-trading,chainsTests
cli-routingcliconsistencyintegrationtool-catalogunitwallet-configwallet-flagswallet-owsskillsexamples190 tests total — 176 pass, 0 fail, 14 skipped
Stats
96 files changed, 8281 insertions, 1244 deletions
Test plan
npm test— 176 pass, 0 failzerion wallet create --name testzerion swap --from ETH --to USDC --amount 0.01 --wallet testzerion agent create-token --wallet testzerion send --to <addr> --amount 0.01 --wallet test🤖 Generated with Claude Code