This document describes the architecture and design decisions for x402-cli.
x402-cli is designed as a modular, extensible CLI tool following industry best practices. The architecture emphasizes:
- Modularity - Clear separation of concerns
- Type Safety - Strict TypeScript configuration
- Testability - Unit and integration tests
- Extensibility - Easy to add new commands and features
- Developer Experience - Clean APIs and comprehensive documentation
x402-cli/
├── src/
│ ├── cli.ts # Main CLI entry point
│ ├── commands/ # Command implementations
│ │ ├── pay.ts # Pay command
│ │ ├── verify.ts # Verify command
│ │ ├── init.ts # Init command
│ │ └── mock-server.ts # Mock server (future)
│ ├── core/ # Core business logic
│ │ ├── solana.ts # Solana blockchain interactions
│ │ ├── config.ts # Configuration management
│ │ ├── logger.ts # Logging utilities
│ │ └── utils.ts # Shared utilities
│ ├── types/ # TypeScript type definitions
│ │ └── index.d.ts
│ └── tests/ # Test files
│ ├── pay.test.ts
│ ├── verify.test.ts
│ └── mock-server.test.ts
├── .github/
│ └── workflows/
│ └── ci.yml # GitHub Actions CI
├── .husky/ # Git hooks
│ └── pre-commit
├── docs/ # Documentation
│ ├── architecture.md
│ ├── roadmap.md
│ └── contributing.md
└── [config files]
The main entry point that:
- Sets up Commander.js program
- Registers all commands
- Handles global options (verbose, version)
- Parses command-line arguments
Each command is a self-contained module that:
- Exports a
createXCommand()function - Returns a configured Commander.js
Commandinstance - Handles command-specific logic
- Uses core modules for business logic
Design Pattern:
- Commands are thin wrappers around core logic
- All business logic lives in
core/modules - Commands handle CLI-specific concerns (parsing, output formatting)
Handles all Solana blockchain interactions:
- Connection management
- Transaction creation and sending
- Keypair loading and management
- Balance queries
- Transaction verification and parsing
Design Decisions:
- Uses
@solana/web3.jsfor blockchain interactions - Supports multiple networks (devnet, mainnet-beta, testnet)
- Current implementation uses file-based keypairs (for development)
- Future: Integration with wallet adapters
Manages CLI configuration:
- Loads/saves configuration from
~/.x402-cli/config.json - Provides defaults
- Handles configuration merging
Design Decisions:
- Configuration stored in user's home directory
- JSON format for human readability
- Graceful fallback to defaults on corruption
Provides colored, formatted console output:
- Info, success, warning, error, debug levels
- Uses
chalkfor colors - Verbose mode support
Design Decisions:
- Centralized logging for consistent output
- Verbose mode for debugging
- Console-based (no file logging for CLI)
Shared utility functions:
- Address validation
- SOL/lamports conversion
- Address truncation
- Network RPC URL resolution
Design Decisions:
- Pure functions where possible
- Reusable across commands
- Well-tested
Centralized TypeScript type definitions:
CliConfig- Configuration structurePaymentOptions- Payment command optionsPaymentResult- Payment operation resultVerificationResult- Verification result- Shared types exported for use across modules
User Input
↓
cli.ts (parse args)
↓
commands/pay.ts (validate, parse options)
↓
core/solana.ts (sendPayment)
├─→ Load keypair
├─→ Create connection
├─→ Validate balance
├─→ Create transaction
└─→ Send transaction
↓
core/logger.ts (output result)
↓
Exit
User Input
↓
cli.ts (parse args)
↓
commands/init.ts (parse options)
↓
core/config.ts (saveConfig)
↓
core/logger.ts (output success)
↓
Exit
User Input
↓
cli.ts (parse args)
↓
commands/verify.ts (parse options, handle output)
↓
core/solana.ts (verifyTransactionSignature)
├─→ Fetch signature status
├─→ Load parsed transaction details
└─→ Extract transfer metadata (amount, accounts, memo)
↓
core/logger.ts (display summary or errors)
↓
Exit
- Core modules (
utils.ts,config.ts,logger.ts) - Pure functions
- Mocked dependencies
- End-to-end command execution
- Real Solana interactions (devnet)
- Transaction verification
- Vitest - Fast, Vite-native test runner
- Coverage - v8 coverage provider
- CI Integration - Automated testing on PR/commit
- Path:
~/.x402-cli/config.json - Format: JSON
- Defaults: Hardcoded in
config.ts
interface CliConfig {
rpcUrl?: string;
network?: 'devnet' | 'mainnet-beta' | 'testnet';
defaultWallet?: string;
}- Command-line arguments (highest priority)
- Configuration file
- Defaults (lowest priority)
- Validation Errors - Invalid input (addresses, amounts)
- Network Errors - RPC connection issues
- Transaction Errors - Insufficient balance, transaction failures
- File System Errors - Missing keypair files, config issues
- Commands catch errors and display user-friendly messages
- Core modules throw errors with clear messages
- CLI exits with appropriate exit codes (0 = success, 1 = error)
- Errors logged with
logger.error()
Current: File-based keypairs Future: Wallet adapter integration
- Support for browser wallets (Phantom, Solflare)
- CLI wallet prompts
- Hardware wallet support
Future: facilitator.ts module
- Facilitator discovery
- Payment routing
- Fee calculation
Future: mock-server.ts command
- Express.js server
- x402 API simulation
- Test payment endpoints
- Connection Pooling: Reuse Solana connections when possible
- Transaction Batching: Future support for batch payments
- Caching: Cache network configuration and RPC URLs
- Lazy Loading: Load keypairs only when needed
- Keypair Storage: Never commit keys to version control
- Input Validation: Validate all addresses and amounts
- Transaction Signing: Local signing only (no remote signing)
- Network Selection: Explicit network selection required
- Preflight Checks: Default enabled (can be skipped for testing)
@solana/web3.js- Solana blockchain SDKcommander- CLI frameworkchalk- Terminal colorsora- Spinners/loading indicators
typescript- TypeScript compilervitest- Test runnereslint- Lintingprettier- Code formattinghusky- Git hooks
- TypeScript compilation (
tsc) - Output to
dist/ - Type declarations included
- Source maps for debugging
- Package.json configured for npm publishing
dist/- Compiled JavaScriptREADME.md- DocumentationLICENSE- License filepackage.json- Package metadata
- Follows semantic versioning (semver)
- Automated via GitHub Actions on tag push
- Pre-publish checks: build, test, lint