zinc-crypto
v1.0.0
Published
USDC treasury MCP server with self-custody wallets, payments, and x402 protocol support
Maintainers
Readme
Zinc Crypto Treasury
Production-shaped USDC treasury platform with self-custody wallets, multi-chain support, and AI agent integration.
Features
- Multi-Treasury Wallets — BIP-39 mnemonic-based HD wallets with self-custody key storage. Create and manage multiple independent treasuries, each with its own wallet and balance.
- Payment Intents — Full payment lifecycle:
RECEIVED → APPROVED → SUBMITTED → CONFIRMED/FAILED. Idempotent operations viaIdempotency-Keyheaders. - USD ↔ USDC Conversions — Mint and burn between USD (cents) and USDC (6-decimal micro-units) at 1:1 rate.
- Multi-Chain — Sandbox (in-memory, no blockchain), Base Sepolia (testnet), or Polygon (mainnet).
- x402 Protocol — HTTP 402 agent-to-merchant payment flow with signed authorization and nonce replay protection.
- MCP Server — 11 tools for AI agent integration via the Model Context Protocol.
- React Dashboard — Cyber-themed UI for managing wallets, payments, conversions, and x402 settlements.
- Swagger UI — Interactive API docs at
/docs.
Quick Start
# Backend
npm install
npm run dev # http://localhost:3000
# Dashboard (separate terminal)
cd ui && npm install
npm run dev # http://localhost:5173
# MCP server (for AI agents)
npm run dev:mcpArchitecture
src/
├── server.ts # Express entry point
├── mcp-server.ts # MCP server entry point
├── bootstrap.ts # Service wiring + wallet hydration from disk
├── config.ts # Chain & app configuration
├── domain/ # Models, enums, x402 types
├── controllers/routes.ts # REST API route handlers
├── services/
│ ├── TreasuryService.ts # Treasury & wallet management
│ ├── PaymentService.ts # Payment intent workflow
│ ├── ConversionService.ts # Mint/burn USD ↔ USDC
│ ├── X402Service.ts # x402 protocol settlement
│ ├── WalletService.ts # HD key generation (BIP-39)
│ └── LocalKeyStore.ts # Filesystem key storage
├── providers/
│ ├── SandboxStablecoinProvider.ts # In-memory sandbox
│ └── OnChainStablecoinProvider.ts # Real blockchain (viem)
├── repositories/ # In-memory data stores
├── mcp/
│ ├── tools.ts # 11 MCP tools
│ └── PolicyService.ts # Auto-approve policy engine
└── jobs/ # Transaction confirmation polling
ui/
├── src/
│ ├── App.tsx # Multi-treasury dashboard
│ ├── api.ts # API client
│ └── components/
│ ├── TreasurySwitcher # Treasury dropdown selector
│ ├── WalletPanel # Wallet creation + key display
│ ├── PaymentsPanel # Send USDC payments
│ ├── TransactionsPanel # Transaction history
│ ├── ConversionsPanel # Mint/burn operations
│ └── X402Panel # x402 merchant + settlementConfiguration
| Variable | Default | Description |
|----------|---------|-------------|
| PORT | 3000 | Server port |
| CHAIN_PROVIDER | sandbox | sandbox, base-sepolia, or polygon |
| CHAIN_ID | per provider | Override chain ID |
| RPC_URL | per provider | Override RPC endpoint |
| USDC_TOKEN_ADDRESS | per provider | Override USDC contract address |
| SANDBOX_INITIAL_USD_MINOR | 1000000 | Initial USD balance per treasury (cents, = $10,000) |
| ZINC_KEY_STORE_DIR | ~/.zinc-crypto/wallets | Wallet key storage directory |
| MCP_AUTO_APPROVE_LIMIT | 1000000000 | MCP auto-approve limit (USDC minor units = 1000 USDC) |
| MCP_DEFAULT_TREASURY_ID | default-treasury | Default treasury for MCP operations |
API Endpoints
Wallets
# Create wallet (shows mnemonic + private key on first call)
curl -X POST http://localhost:3000/treasuries/treasury-1/crypto-wallet
# Get wallet
curl http://localhost:3000/treasuries/treasury-1/crypto-wallet
# Import wallet from mnemonic
curl -X POST http://localhost:3000/treasuries/treasury-1/import-wallet \
-H "Content-Type: application/json" \
-d '{"mnemonic":"word1 word2 ... word12"}'
# List all wallets
curl http://localhost:3000/walletsBalances
# Get USD + USDC balance
curl http://localhost:3000/treasuries/treasury-1/balances
# Get on-chain USDC balance (non-sandbox only)
curl http://localhost:3000/treasuries/treasury-1/onchain-balancePayments
# Create payment intent
curl -X POST http://localhost:3000/crypto/payment-intents \
-H "Content-Type: application/json" \
-d '{"treasuryId":"treasury-1","toAddress":"0x1111...1111","amountMinor":500000}'
# Approve (idempotent)
curl -X POST http://localhost:3000/crypto/payment-intents/<id>/approve \
-H "Idempotency-Key: approve-1"
# Execute (idempotent)
curl -X POST http://localhost:3000/crypto/payment-intents/<id>/execute \
-H "Idempotency-Key: execute-1"
# Get payment status
curl http://localhost:3000/crypto/payment-intents/<id>
# List transactions
curl "http://localhost:3000/crypto/transactions?treasuryId=treasury-1&status=CONFIRMED"Conversions
# Mint: USD → USDC (100 cents = 1,000,000 USDC minor)
curl -X POST http://localhost:3000/treasury/mint \
-H "Content-Type: application/json" \
-H "Idempotency-Key: mint-1" \
-d '{"treasuryId":"treasury-1","usdMinor":100}'
# Burn: USDC → USD (must be divisible by 10,000)
curl -X POST http://localhost:3000/treasury/burn \
-H "Content-Type: application/json" \
-H "Idempotency-Key: burn-1" \
-d '{"treasuryId":"treasury-1","usdcMinor":1000000}'
# List conversions
curl "http://localhost:3000/treasury/conversions?treasuryId=treasury-1"x402 Protocol
# Generate payment requirement (merchant side)
curl -X POST http://localhost:3000/x402/payment-requirements \
-H "Content-Type: application/json" \
-d '{"treasuryId":"treasury-1","amountMinor":1000000,"resource":"https://api.example.com/data"}'
# Settle signed payment (merchant receives)
curl -X POST http://localhost:3000/x402/settle \
-H "Content-Type: application/json" \
-d '{"treasuryId":"treasury-1","signedPayload":"..."}'MCP Server Tools
The MCP server exposes 11 tools for AI agents:
| Tool | Description |
|------|-------------|
| get_wallet_address | Create or retrieve a wallet for a treasury |
| import_wallet | Import wallet from BIP-39 mnemonic |
| get_balances | Check USD and USDC balances |
| send_payment | Send USDC (auto-approved within policy limit) |
| get_payment_status | Check payment intent status |
| mint_usdc | Convert USD to USDC |
| burn_usdc | Convert USDC to USD |
| list_transactions | Query transaction history |
| list_wallets | List all local wallets |
| x402_create_payment_requirement | Generate merchant payment requirement |
| x402_settle_payment | Settle a signed x402 payment |
Configure in .mcp.json:
{
"mcpServers": {
"zinc-crypto": {
"command": "npx",
"args": ["tsx", "src/mcp-server.ts"],
"env": {
"MCP_AUTO_APPROVE_LIMIT": "1000000000",
"MCP_DEFAULT_TREASURY_ID": "default-treasury"
}
}
}
}Unit Conventions
| Currency | Field | Decimals | Example |
|----------|-------|----------|---------|
| USD | usdMinor | 2 (cents) | 100 = $1.00 |
| USDC | usdcMinor | 6 (micro) | 1000000 = 1 USDC |
Conversion rate: 1 USD = 1 USDC (usdcMinor = usdMinor * 10000)
Key Storage
Wallets are self-custodial. Private keys are stored as JSON files in ~/.zinc-crypto/wallets/ with 0600 permissions. Keys are shown once during wallet creation and never exposed again via the API. On server restart, wallets are automatically hydrated from disk.
Scripts
npm run dev # Dev server (Express + ts-node)
npm run build # Compile TypeScript
npm start # Run compiled server
npm run dev:mcp # Dev MCP server (tsx)
npm run build:mcp # Compile MCP server
npm run start:mcp # Run compiled MCP server