io.github.hifriendbot/agentwallet
编码与调试by hifriendbot
为 AI agents 提供钱包基础设施,支持 EVM 与 Solana、x402 支付,且无需 KYC。
什么是 io.github.hifriendbot/agentwallet?
为 AI agents 提供钱包基础设施,支持 EVM 与 Solana、x402 支付,且无需 KYC。
README
AgentWallet MCP Server
Permissionless wallet infrastructure for AI agents. Create wallets, sign transactions, and broadcast on-chain, on any EVM chain and Solana. Built-in guards. No KYC. The only AI agent wallet that accepts crypto for its own API fees.
Your keys can stay on your machine. Set one environment variable and every signature happens in your own process. No server sees the key, no company can freeze the wallet, and you can verify that claim by reading src/local-wallet.ts or by running the server with the API pointed at a closed port.
No KYC. No KYT. No approval process. No transaction monitoring. No one can block your wallet. Pay with USDC on-chain, no credit card required.
Two modes
| Local (self-custody) | Hosted (custodial) | |
|---|---|---|
| Who holds the key | You, in your own process | Encrypted on AgentWallet servers |
| Set up | One env var, no account needed | API key |
| Chains | EVM + Solana | EVM + Solana |
| Can anyone freeze it | No | Yes, that is what pause is for |
| Spend guards | AGENTWALLET_MAX_TX_NATIVE, AGENTWALLET_MAX_TX_TOKEN, AGENTWALLET_MAX_TX_SOL, AGENTWALLET_MAX_AUTOPAY | Server-side limits, pause, rate limits |
| Paywalls, usage, billing | Needs an API key too | Included |
Run wallet_mode at any time and the server will tell you which one you are in, and which address it controls.
Local signing in one variable
{
"mcpServers": {
"agentwallet": {
"command": "npx",
"args": ["-y", "agentwallet-mcp"],
"env": {
"AGENTWALLET_PRIVATE_KEY": "0xyour_key",
"AGENTWALLET_RPC_8453": "https://your-own-rpc",
"AGENTWALLET_MAX_TX_NATIVE": "0.05"
}
}
}
}
Use AGENTWALLET_KEYFILE=/path/to/key instead if you would rather keep the key out of your shell config (one or the other: the server refuses to start when both are set). The key is read once, never written to disk, never logged, and never included in an error message.
AGENTWALLET_RPC_<chainId> (or AGENTWALLET_RPC_URL for all chains) points at an endpoint you trust (https; plain http only on localhost). Without it a public RPC is used, and a public RPC can see which addresses you ask about. Decimals for a token outside the registry come from that RPC and are accepted only up to 18; pin anything else with AGENTWALLET_TOKEN_DECIMALS.
AGENTWALLET_MAX_TX_NATIVE is a per-transaction ceiling in native units (ETH, MATIC and so on). In hosted mode the server enforces limits; in local mode there is no server, so these guards are the only ones there are. Set them.
AGENTWALLET_MAX_TX_TOKEN is the equivalent ceiling for ERC-20 movement, in human units of the token. Set this one too if you hold stablecoins. The native cap cannot see a token transfer: an ERC-20 send carries value = 0 with the amount in the calldata, so AGENTWALLET_MAX_TX_NATIVE alone leaves a USDC balance uncapped. AGENTWALLET_MAX_TX_TOKEN covers transfer, transferFrom, approve, increaseAllowance, Permit2 approve, and deposit() / withdraw(uint256) on the chain's own wrapped-native contract (so wrap_eth and unwrap_eth keep working under the cap), the approvals because an unbounded allowance is a drain waiting to happen. Any other calldata sent to a token contract or to Permit2 is refused while the cap is set, because the guard cannot price it; set AGENTWALLET_ALLOW_UNKNOWN_TOKEN_CALLS=1 to allow such calls deliberately. increaseAllowance is judged on the resulting total: the current allowance is read first and the call refuses if it cannot be, so two compliant increments cannot stack a standing allowance above the cap. Calls to other contracts (routers, bridges) pass, since they can only pull what an approval already allowed; a contract counts as "other" only when it demonstrably declines decimals(), so an absurd or malformed answer, or an RPC that cannot be reached, refuses rather than allows. Decimals are resolved locally from the trusted registry, then the token's own decimals(); a token that resolves neither way is evaluated at 0 decimals, the only value that cannot fail open. For a token outside the registry the RPC is the only source of decimals, and an RPC you do not control could scale the amount and the cap together; pin such tokens with AGENTWALLET_TOKEN_DECIMALS (for example 8453:0x<token>=6) and the pin is used everywhere the RPC's answer would have been.
Solana local signing
"env": {
"AGENTWALLET_SOLANA_KEY": "[12,34...]",
"AGENTWALLET_SOLANA_RPC": "https://your-own-rpc",
"AGENTWALLET_MAX_TX_SOL": "1",
"AGENTWALLET_MAX_TX_TOKEN": "25"
}
Accepts whichever format you already have: a solana-keygen id.json array, a base58 secret key as exported by Phantom, or base64. Use AGENTWALLET_SOLANA_KEYFILE to point at a file instead. Native SOL and SPL token transfers are both signed locally, and a missing associated token account is created for the recipient automatically.
Set either key, or both. They are independent: run EVM locally and Solana hosted, or the reverse.
An operation with no matching local key is refused, never silently routed to the hosted signer. If you have an EVM key configured and ask for a Solana transfer with no Solana key, the server stops and tells you which variable is missing. Quietly moving funds onto a key you do not hold, while you believe you are in self-custody, is the worst thing this server could do.
About the dependency tree
Local signing uses viem for EVM and @solana/web3.js for Solana, plus bs58 for key parsing. SPL instructions are built by hand rather than with @solana/spl-token, because that package pulls in bigint-buffer, which carries a high severity buffer overflow advisory. A wallet has no business shipping that to save a dozen lines of instruction encoding.
npm audit reports no advisories as of 1.13.5; the overrides in package.json keep two advisories under @solana/web3.js's jayson closed. Earlier releases carried advisories inside @modelcontextprotocol/sdk's HTTP transport dependencies. This server speaks stdio, so that code never loads, and the SDK is not something this package can patch. Run the audit yourself. Publishing a tree you can inspect is the point.
Features
- 40 MCP tools: create wallets, send transactions, approve tokens, wrap ETH, transfer SPL tokens, quote, discover, pay and accept x402 payments, verify custody mode, and more
- Spend policy: rolling daily and monthly budgets, per-host ceilings, host and recipient lists, human approval through MCP elicitation, and a tool allowlist, in one JSON file, enforced from a hash-chained ledger. The key stays yours and the agent still cannot overspend.
- EVM + Solana: Ethereum, Base, Polygon, BSC, Arbitrum, Optimism, Avalanche, Zora, PulseChain, Solana, and any other EVM-compatible chain
- SOL + SPL tokens: native SOL transfers and SPL token transfers (USDC, USDT, etc.) with automatic account creation
- Built-in guards: in hosted mode, daily spending limits, gas price protection, emergency pause and rate limiting are enforced server-side by default. In local mode your protection is the per-transaction caps you set (
AGENTWALLET_MAX_TX_NATIVE,AGENTWALLET_MAX_TX_TOKEN,AGENTWALLET_MAX_TX_SOL,AGENTWALLET_MAX_AUTOPAY). x402 replay protection and on-chain verification apply either way - x402 payments: pay for x402-enabled APIs automatically, or accept x402 payments on your own endpoints (EVM and Solana)
- Self-custody option: run local mode and the key never leaves your machine. In hosted mode, keys are encrypted at rest, decrypted only during signing, and zeroed from memory immediately after. Either way you can export and walk away.
- Permissionless: No KYC. No KYT. No identity verification. No approval process. No compliance gatekeeping. Sign up, get an API key, and start transacting immediately.
- 30-second setup: three lines of config. No SDK to install. No dependencies to manage.
Pricing
- $0.00345 per operation
- 6,000 free operations/month
- $0.0005 per x402 verification
- 1,000 free x402 verifications/month
- Pay with USDC on-chain via x402, no credit card required
- No monthly fee, no tiers, just pay as you go
Competitor comparisons are kept at hifriendbot.com/wallet/#pricing with the date they were last verified. They live there rather than here because a published npm README cannot be corrected when someone else changes their prices.
Quick Start
Get your free API key at hifriendbot.com/wallet, no credit card required, no KYC, no approval wait.
Claude Desktop / OpenClaw
Add to your config:
{
"mcpServers": {
"agentwallet": {
"command": "npx",
"args": ["-y", "agentwallet-mcp"],
"env": {
"AGENTWALLET_USER": "your_username",
"AGENTWALLET_PASS": "your_api_key",
"AGENTWALLET_WALLET_ID": "1"
}
}
}
}
AGENTWALLET_WALLET_IDis optional. Set it to enable x402 auto-pay: when you exceed the free tier without a credit card, the MCP server automatically pays for operations with USDC from this wallet. Only the metered routes (creating a wallet, signing, sending) are paid this way, at mostAGENTWALLET_MAX_AUTOPAY_PER_HOURtimes an hour (default 20), and every automatic payment is reported in the tool result underautopay_payment. A 402 on any other route is reported, never paid.Auto-pay safety cap.
AGENTWALLET_MAX_AUTOPAY(optional, default1) is the most one x402 payment may authorize, in stablecoin units:1means one dollar. It prices registry stablecoins only (USDC, USDT, USDbC, DAI on the supported chains, USDC and USDT on Solana). A requirement in the chain's native asset or in any other token is refused, because "1" measured in ETH is a few thousand dollars; list such assets inAGENTWALLET_AUTOPAY_ASSETS(comma-separated addresses or mints, or the wordnative) to allow them, and the cap then applies in that asset's own units. Any requirement above the cap is rejected instead of paid, so a malformed or tampered payment requirement cannot drain the wallet. This automatic path settlesexactrequirements only; anuptooffer from the API is refused before any wallet call, because paying a usage maximum upfront is not what the offer means (usepay_x402, which signs a Permit2 authorization for it). The cap is the operator's ceiling: amax_paymentargument can lower it for one call but never raise it. Raise the variable itself if you genuinely need larger automatic payments (for example"5"for up to 5 USDC per call).
Claude Code
claude mcp add agentwallet \
-e AGENTWALLET_USER=your_username \
-e AGENTWALLET_PASS=your_api_key \
-e AGENTWALLET_WALLET_ID=1 \
-- npx -y agentwallet-mcp
VS Code
Add to your settings:
{
"mcp": {
"servers": {
"agentwallet": {
"command": "npx",
"args": ["-y", "agentwallet-mcp"],
"env": {
"AGENTWALLET_USER": "your_username",
"AGENTWALLET_PASS": "your_api_key",
"AGENTWALLET_WALLET_ID": "1"
}
}
}
}
}
Tools
| Tool | Description |
|---|---|
create_wallet | Create a new EVM or Solana wallet |
list_wallets | List all your wallets |
get_wallet | Get wallet details by ID |
get_balance | Check native token balance on any chain |
get_token_balance | Check ERC-20 or SPL token balance |
get_token_info | Get ERC-20 token name, symbol, and decimals |
transfer | Send native tokens (ETH, SOL, POL, BNB, etc.) |
transfer_token | Send ERC-20 or SPL tokens (USDC, USDT, etc.) |
send_transaction | Sign and broadcast a raw transaction |
sign_transaction | Sign a transaction without broadcasting |
call_contract | Read-only contract call (eth_call) |
approve_token | Approve ERC-20 token spending for DeFi |
get_allowance | Check ERC-20 token allowance |
wrap_eth | Wrap native tokens to WETH/WAVAX/etc. |
unwrap_eth | Unwrap WETH back to native tokens |
pay_x402 | Pay x402 invoices (exact via EIP-3009, upto via Permit2), with approvals above the cap |
quote_x402 | What an x402 endpoint charges and whether the cap, policy and budgets would allow it; nothing signed |
discover_x402 | Find x402-paid APIs by subject in the public x402 index (the Bazaar) |
list_payments | Spends on the ledger with their outcomes, newest first |
export_receipts | The ledger as CSV or JSONL for expense records |
spend_policy | The policy in force, its sha256, budgets spent and remaining, ledger integrity |
simulate_transaction | Dry-run an EVM transaction: guards, policy, gas estimate, fee, return data, nothing signed |
check_approval | Status of a human approval created by an over-cap pay_x402 |
approve_permit2 | One-time token approval to Permit2 for upto endpoints |
check_token_risk | Honeypot, tax, owner-power and holder-concentration flags for a token |
create_paywall | Create an x402 paywall to charge for a resource |
list_paywalls | List all your x402 paywalls |
get_paywall | Get paywall details by ID |
update_paywall | Update paywall pricing, resource, or status |
delete_paywall | Delete a paywall |
get_paywall_payments | View payment history for a paywall |
get_x402_revenue | Aggregate revenue stats across all paywalls |
wallet_mode | Report whether signing is local (self-custody) or hosted, and which address is in use |
export_wallet_key | How to export a hosted wallet key and move to self-custody |
buy_verification_credits | Buy x402 verification credits with USDC on-chain |
get_usage | Check your monthly usage and billing |
get_chains | List all supported chains |
pause_wallet | Emergency pause a wallet |
unpause_wallet | Resume a paused wallet |
delete_wallet | Delete a wallet |
Supported Chains
| Chain | ID | Native Token | Stablecoin |
|---|---|---|---|
| Ethereum | 1 | ETH | USDC |
| Base | 8453 | ETH | USDC |
| Polygon | 137 | POL | USDC |
| BSC | 56 | BNB | USDT |
| Arbitrum | 42161 | ETH | USDC |
| Optimism | 10 | ETH | USDC |
| Avalanche | 43114 | AVAX | USDC |
| Zora | 7777777 | ETH | USDC |
| PulseChain | 369 | PLS | USDC |
| Solana | 900 | SOL | USDC |
| Solana Devnet | 901 | SOL | USDC |
Use Case: GuessMarket
Pair with guessmarket-mcp to let your AI agent trade prediction markets:
- Create a wallet on Base
- Approve USDC spending
- Buy YES/NO shares on prediction markets
- Provide liquidity and earn trading fees
- Claim winnings
All on-chain. All through MCP. No frontend needed.
x402 Payments
AgentWallet speaks the x402 open payment standard the way the spec defines it. When your Ai agent hits an API that answers HTTP 402, pay_x402 does the whole flow:
- Fetches the URL and reads the payment requirements, from the v2
PAYMENT-REQUIREDheader or the v1 JSON body. - Picks an
exactoption (you can steer it withprefer_chain). - Signs an EIP-3009
TransferWithAuthorizationfor exactly that amount. Nothing is broadcast and no gas is paid by the payer; the endpoint's facilitator settles it on-chain. - Retries the request with the payment header (
PAYMENT-SIGNATUREfor v2,X-PAYMENTfor v1). - Returns the response, the settlement receipt (
PAYMENT-RESPONSE/X-PAYMENT-RESPONSE) and, if the endpoint declined, its stated reason inretry_error.
Verified against Coinbase's public facilitator (isValid: true for v1 and v2 payloads) and live x402 servers on Base. Works in both custody modes: the local key signs in-process; hosted wallets sign through POST /wallets/{id}/x402/authorize, a narrow endpoint that only ever signs this one struct and runs the same pause and token-cap checks as a transfer.
pay_x402(
url="https://api.example.com/premium-data",
wallet_id=1,
max_payment="1.00"
)
max_payment lowers the cap for one call. It cannot raise it: AGENTWALLET_MAX_AUTOPAY (default 1) is the operator's ceiling, and a max_payment above it is ignored and reported back as max_payment_ignored, so neither a malicious 402 endpoint nor a prompt-injected agent can authorize more than the operator allowed. Hosted wallets can go above the ceiling only through an emailed owner approval (below); local mode raises the variable. In local mode AGENTWALLET_MAX_TX_TOKEN applies to authorizations too, because an authorization is a transfer somebody else executes. Authorizations are valid for at most AGENTWALLET_X402_MAX_TIMEOUT seconds (default 3600) however long the endpoint asks for, and a repeat pay_x402 call for the same endpoint, amount and recipient inside that window re-sends the earlier signature instead of signing a second one (its nonce is single-use, so a server that withheld the resource after settling cannot be paid twice; pass fresh_authorization=true to force a new one). The label shown for the asset comes from the registry or the chain, never from the 402 body.
Schemes. exact (EIP-3009, gasless for the payer) is preferred and works on every EVM chain AgentWallet knows. upto (a Permit2 maximum the seller settles at actual usage) is signed as a PermitWitnessTransferFrom bound to the endpoint's facilitator; it needs a one-time approve_permit2 per token (or AGENTWALLET_PERMIT2_AUTO_APPROVE=1). An upto option without extra.facilitatorAddress is refused, never approximated with an upfront transfer. Native-asset and Solana requests, and AgentWallet's own paywalls, are paid by an on-chain transfer proved by transaction hash, which is what those servers verify.
Approvals above the cap. On a hosted wallet, a payment above the cap does not have to fail. With request_approval (default on; AGENTWALLET_APPROVALS=0 turns it off) the wallet owner gets an email with approve and deny links, pay_x402 returns an approval_id, and the agent retries with it once check_approval says approved. An approval is bound to one wallet, chain, asset, recipient and maximum, expires in 24 hours, and is consumed by one signature. Local mode has no approval channel: the caps in your environment are the policy, and an approval_id passed there is refused.
Asset risk. check_token_risk (and every approve_token result) reports honeypot, tax, owner-power, verified-source, holder-concentration and liquidity flags from GoPlus Security, with an on-chain fallback. A warning for the caller to weigh, never a block.
Proof. Real settlements are listed in PAYMENTS.md; the first is a 0.02 USDC exact payment on Base with the facilitator paying the gas.
Pay any x402 API from Claude in three steps
- Add the server (one of the snippets under Quick Start). Self-custody: set
AGENTWALLET_PRIVATE_KEYto a key that holds USDC on Base. Hosted:AGENTWALLET_USERandAGENTWALLET_PASSfrom hifriendbot.com/wallet. - Ask: "Use pay_x402 to POST https://api.ozdreamtools.de/api/holidays with body {"year":2026,"state":"BY"} and a max_payment of 0.05."
- Read the result:
payment_made: true, the amount,payment_method, andsettlement.transaction, the on-chain hash. No ETH needed forexact: the endpoint's facilitator pays the gas.
Token domains. The EIP-712 domain comes from the endpoint's extra.name / extra.version, then a short registry of USDC deployments, then the token contract's own name() / version(). If none of those answer, the payment is refused rather than signed with a guessed domain.
Delegated payers. If the paying address is an EIP-7702 delegated account, pay_x402 reports it in payer_delegation (the delegate and whether it answers ERC-1271). A delegate without ERC-1271 is declined by facilitators that check account code before recovering the signer, and the reason they return reads like a signature fault; the warning names the real cause. Pay from a plain EOA for reliable settlement.
x402 Acceptance
AgentWallet also lets you accept x402 payments. Create a paywall, point it at any resource, and get a public URL that charges agents automatically:
create_paywall(
wallet_id=1,
name="Premium API",
amount="0.01",
token_name="USDC",
token_address="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
chain_id=8453,
resource_url="https://your-api.com/data"
)
When an agent hits the paywall URL:
- Gets back HTTP 402 with payment requirements
- Pays on-chain using
pay_x402(or any x402-compatible client) - Retries with proof of payment
- Receives the protected content
On-chain verification ensures every payment is real. Replay protection prevents double-spending. Revenue tracking shows you who paid, how much, and when. 1,000 free verifications/month, then $0.0005 each. See the pricing comparison for how that stacks up.
How We Compare
| Feature | Coinbase CDP | AgentWallet |
|---|---|---|
| Setup Time | Install SDK + configure | 3 lines of config |
| Approval Process | Identity verification required | None, instant access |
| KYC Required | Yes | No |
| KYT / Transaction Monitoring | Yes | No |
| Can Block Your Wallet | Yes | No |
| Built-in Guards | Yes (requires setup) | Yes (hosted: active by default; local: env caps you set) |
| Free Operations / Month | 5,000 | 6,000 |
| Cost Per Operation | $0.005 | $0.00345 |
| x402 Verification Cost | $0.001 | $0.0005 |
| Free x402 Verifications / Month | 1,000 | 1,000 |
| x402 Acceptance (Paywalls) | No | Yes |
| Pay for API Fees with Crypto | No (credit card only) | Yes (USDC via x402) |
| Supported Chains | 8 EVM + Solana | Any EVM + Solana |
| Token Tools | Yes | ERC-20 + SPL (34 tools) |
| MCP Server | Yes | Yes |
Pay with Crypto, No Credit Card Required
AgentWallet is the only AI agent wallet infrastructure that accepts crypto for its own API fees. Every competitor, Coinbase CDP, Circle, MoonPay, Crossmint, Turnkey, requires a credit card or monthly invoice. With AgentWallet, your agent can pay for operations with USDC on-chain via the x402 protocol. No credit card, no invoice, no billing portal. Just on-chain payments.
When your agent exceeds the free tier (6,000 ops/month) without a credit card configured, the API returns HTTP 402 with USDC payment instructions. Your agent pays on-chain, retries with proof of payment, and the operation executes. Fully automated via the MCP server.
You can also pre-purchase x402 verification credits with USDC using the buy_verification_credits tool, keeping your paywalls running beyond the free 1,000 verifications/month without needing a credit card.
Built-in Guards
Which guards apply depends on who holds the key.
Hosted mode (the server holds the key): every guard below is active by default, no configuration required.
- Encrypted at rest: private keys encrypted before storage and never leave the server
- Memory zeroing: keys wiped from memory immediately after every signing operation
- Daily spending limits: set a per-wallet daily cap in USD, enforced by the server on every transaction
- Gas price protection: transactions blocked when gas prices spike above safe thresholds
- Emergency pause: instantly freeze any wallet or all wallets with one click
- Rate limiting: API requests capped per minute to prevent abuse and brute force attacks
Local mode (you hold the key): there is no server in the signing path, so the server-side limits and pause above cannot see or stop a locally signed transaction, and nobody (including us) can freeze a local wallet. Your protection is the per-transaction caps enforced inside your own process before anything is signed. Set them before you fund the wallet; an unset cap means no limit.
-
AGENTWALLET_MAX_TX_NATIVE: ceiling per transaction in native units (ETH, MATIC, and so on) -
AGENTWALLET_MAX_FEE_NATIVE: the most one transaction may burn in fees, gas x max fee per gas, in native units (default0.01). The value cap alone did not bound fees: a node answering an absurd tip or gas estimate could take the whole balance as priority fee on a cap-compliant transfer. Caller-suppliedgas_limit/max_fee/priority_feeare honoured and then bounded by this cap -
AGENTWALLET_MAX_TX_TOKEN: ceiling per ERC-20 transfer or approval, in human units of the token -
AGENTWALLET_ALLOW_UNKNOWN_TOKEN_CALLS: set to1to let calldata the token cap cannot price reach a token contract or Permit2 (refused by default while the cap is set) -
AGENTWALLET_TOKEN_DECIMALS: pin decimals for tokens outside the registry (8453:0x<token>=6,<mint>=9); a pin is used for amounts and caps instead of asking the RPC -
AGENTWALLET_MAX_TX_SOL: ceiling per native SOL transfer (also charged for the rent of a recipient token account an SPL send has to create). It does not cover SPL token amounts:AGENTWALLET_MAX_TX_TOKENdoes, on Solana as on EVM -
AGENTWALLET_MAX_AUTOPAY: ceiling per x402 auto-payment in stablecoin units (default1);AGENTWALLET_AUTOPAY_ASSETSopts native or non-stable assets in;AGENTWALLET_X402_MAX_TIMEOUTbounds how long a signed authorization stays valid (default 3600 seconds) -
AGENTWALLET_SOLANA_RPC_<chainId>(orAGENTWALLET_SOLANA_RPCfor all clusters): the RPC's genesis hash is checked against the chain id before anything is sent, and an EVM RPC'seth_chainIdlikewise, so one URL cannot silently serve a different network than the one requested -
AGENTWALLET_TOKEN_RISK=0: skip the GoPlus lookupapprove_tokenperforms (a third-party call that reveals which token you are about to approve) -
AGENTWALLET_CHAIN_ID: the EVM chain used when a call names none (default 8453) -
AGENTWALLET_LEGACY_PAYWALL_ORIGINS: comma-separated https origins whose legacy-shaped 402 may be settled by an on-chain transfer proved by hash; every other host gets a signed authorization -
AGENTWALLET_POLICY: a spend policy file (see below) that bounds sums, hosts, recipients, chains, assets and tools;AGENTWALLET_LEDGERnames the ledger it is enforced from -
AGENTWALLET_KEYFILE_PASSPHRASEorAGENTWALLET_KEYFILE_PASSPHRASE_FILE: opens an encrypted keyfile (see below) -
AGENTWALLET_WEBHOOK_URL(https, or http on localhost) andAGENTWALLET_WEBHOOK_SECRET: every ledger line is POSTed as JSON, signedX-AgentWallet-Signature: sha256=<hmac>when a secret is set; a webhook never delays or fails a signature
Every AGENTWALLET_* variable is validated at startup: a malformed cap stops the server rather than reading as "no limit", and an unrecognised name (a misspelled cap) stops it too. wallet_mode reports every guard with its parsed value. Tool arguments are strict: an unknown argument name (a typo in max_payment) is an error, never silently ignored. pay_x402 signs one live authorization per resource; a second, different requirement for the same resource is refused until the first expires unless fresh_authorization is passed. Node.js 22.19 or newer is required.
Spend policy: bounding sums, not just single payments
A per-transaction cap bounds one signature. It cannot see that the five hundredth payment of 0.99 under a cap of 1 is the five hundredth. A spend policy can. Point AGENTWALLET_POLICY at a JSON file:
{
"version": 1,
"name": "research agent",
"budget": { "daily": "5", "monthly": "50" },
"native_budget": { "8453": { "daily": "0.01" } },
"hosts": { "allow": ["*.example.com", "api.ozdreamtools.de"], "deny": ["evil.example.com"] },
"per_host": { "*.example.com": { "daily": "2", "per_payment": "0.25" } },
"recipients": { "deny": ["0x0000000000000000000000000000000000000000"] },
"chains": { "allow": [8453, 900] },
"approval": { "above": "0.50", "max": "20" },
"tools": { "allow": ["pay_x402", "quote_x402", "discover_x402", "get_balance", "list_payments", "spend_policy", "wallet_mode"] }
}
budget: rolling dollar budgets (last 24 hours, last 30 days, lifetime) across every chain, counting x402 payments, stablecoin transfers and stablecoin approvals in registry stablecoins. A spend the budget cannot price (a token outside the registry) is refused while a budget is set, unless"unpriced_spends": "allow". An SPL send is priced at the mint's own decimals; atoken_decimalshint that disagrees with the mint is refused before any request is made.native_budget: the same per chain, in the chain's own coin, counting native transfers and the native value sent into any contract (wrap_eth,send_transactionwith value and calldata), including value carried on a token transfer or approval call (a payable token contract keeps it, so it is a second spend, to that contract).- Approvals are spends. An ERC-20 allowance (
approve_token,approve_permit2,increaseAllowance,approveAndCall, Permit2approve, or the same calldata throughsend_transaction) is what the spender will take later, so it is priced, checked and reserved on the ledger when it is granted, the spender is checked against the recipient lists, and an unlimited approval (2^128 base units or more) is refused outright, since no budget can count it; grant an exact amount. A zero-value call to any other contract (a router, a bridge) reserves nothing: it can only pull what an approval already granted. hosts,per_host: which endpointspay_x402may pay, and how much per host per day, per month and per payment. A denied host is never contacted, not even for a quote. A host is matched by its canonical DNS name (lowercase, the root label's trailing dot removed), soapi.example.com.and its percent-encoded spelling areapi.example.comto every list and to the ledger's per-host sums.recipients: where funds may go (transfers, x402payTo, approval spenders, contracts that receive native value). The allow list covers those funds destinations; the contract a zero-value call is aimed at (a token being approved, a router) is checked against the deny list and the chain list.chains,assets: allow lists; an asset entry can be scoped"8453:0x..."or be the wordnative.approval: aboveabove, every x402 payment is put to the human at the MCP client through elicitation (the client shows the amount, token, recipient and resource and asks yes or no; a client that declared no elicitation support cannot answer, so the payment is refused). In local mode an accepted answer may admit a payment above the per-payment cap, up tomax. Budgets are never lifted by anyone's approval.tools: the tools the model sees. A payer-only deployment exposes seven; the rest are not registered.wallet_modeandspend_policyare always present so the operator can see what the server is.
An unknown key stops the server, so a misspelled budgets cannot run unbounded. spend_policy reports the file, its sha256 (compare it with the file you reviewed), what each budget has spent and has left, and which tools the policy hid. quote_x402 answers "would this be paid?" for a URL before anything is signed.
The ledger. Budgets are enforced from an append-only, hash-chained JSONL file (AGENTWALLET_LEDGER, or the policy's ledger, or agentwallet-ledger.jsonl beside the policy when a budget needs one). A spend is reserved on it before the signature exists; a reservation whose signing fails is voided by a later line; the endpoint's or chain's answer is settled onto it afterwards. A spend that may already be on the wire (a broadcast that failed after the bytes left, a hosted request the API host took and then dropped) is kept counted as unknown rather than voided; a failure before anything left this process, including a policy or local-mode refusal, is always voided and never consumes budget. The chain is verified on every read, and a ledger that does not verify refuses every spend until the operator has looked at it. Several agentwallet-mcp processes may share one ledger (two MCP clients on one wallet): the file is re-read before every check, and the check-and-append step holds an exclusive lock file (<ledger>.lock) across processes, so the budget is one budget however many processes enforce it; a lock older than 30 seconds is treated as left by a dead process. A transaction signed without being broadcast (sign_transaction) is reserved and counted like a send, since whoever holds it can broadcast it. A call that moves two things (a token transfer that also carries native value) is two lines, reserved in turn and released together when either is refused. list_payments reads it, export_receipts turns it into CSV or JSONL, and AGENTWALLET_WEBHOOK_URL receives every line as it is written.
Encrypted keyfiles
A plaintext key in a shell config or a file is readable by anything that can read the disk. Seal it:
npx agentwallet-mcp encrypt-keyfile ./plain.key ./agent.keyfile
The passphrase is asked for on the terminal (or taken from AGENTWALLET_KEYFILE_PASSPHRASE for scripted use); scrypt derives the key and AES-256-GCM seals the material, with Node's own crypto and no new dependency. Point AGENTWALLET_KEYFILE or AGENTWALLET_SOLANA_KEYFILE at the result, set AGENTWALLET_KEYFILE_PASSPHRASE or AGENTWALLET_KEYFILE_PASSPHRASE_FILE, confirm with wallet_mode that the same address appears, then delete the plaintext. A wrong passphrase fails with a fixed message that never includes the key.
Either mode, for x402 paywalls you run through the hosted API:
- Replay protection: every x402 payment verified on-chain with unique transaction tracking
- On-chain verification: x402 payments verified directly on the blockchain with finalized commitment
Bug bounty program: $50 to $500 for responsible disclosure (details).
Links
- Website: hifriendbot.com/wallet
- npm: agentwallet-mcp
- Security: security@hifriendbot.com, policy and disclosure history in SECURITY.md
Security
pay_x402 validates the target URL before every outbound request and again on
each redirect hop. IP literals are canonicalized (including IPv4-mapped IPv6
such as [::ffff:127.0.0.1]) and hostnames are resolved, with loopback,
private, link-local, carrier-grade NAT, multicast and cloud-metadata
destinations refused.
Validation and connection use the same DNS answer. Each hop resolves once, and
the socket is pinned to an address from that answer, so a hostname cannot
resolve public for the check and private for the connection. The hostname is
still used for the Host header and for TLS SNI and certificate validation, so
pinning is invisible to legitimate endpoints.
Credentials stay with the origin they were given to. If an endpoint redirects
pay_x402 to a different origin, the caller-supplied Authorization, Cookie
and X-PAYMENT headers, and every other custom header, are dropped before the
next hop; only content-negotiation headers (Accept, Accept-Language,
Accept-Encoding, User-Agent, Content-Type) are carried. A redirect that
turns a POST into a GET also sheds the body headers. Same-origin redirects keep
everything, as a browser would.
Report security issues privately to security@hifriendbot.com.
License
MIT
常见问题
io.github.hifriendbot/agentwallet 是什么?
为 AI agents 提供钱包基础设施,支持 EVM 与 Solana、x402 支付,且无需 KYC。
相关 Skills
网页构建器
by anthropics
面向复杂 claude.ai HTML artifact 开发,快速初始化 React + Tailwind CSS + shadcn/ui 项目并打包为单文件 HTML,适合需要状态管理、路由或多组件交互的页面。
✎ 在 claude.ai 里做复杂网页 Artifact 很省心,多组件、状态和路由都能顺手搭起来,React、Tailwind 与 shadcn/ui 组合效率高、成品也更精致。
网页应用测试
by anthropics
用 Playwright 为本地 Web 应用编写自动化测试,支持启动开发服务器、校验前端交互、排查 UI 异常、抓取截图与浏览器日志,适合调试动态页面和回归验证。
✎ 借助 Playwright 一站式验证本地 Web 应用前端功能,调 UI 时还能同步查看日志和截图,定位问题更快。
前端设计
by anthropics
面向组件、页面、海报和 Web 应用开发,按鲜明视觉方向生成可直接落地的前端代码与高质感 UI,适合做 landing page、Dashboard 或美化现有界面,避开千篇一律的 AI 审美。
✎ 想把页面做得既能上线又有设计感,就用前端设计:组件到整站都能产出,难得的是能避开千篇一律的 AI 味。
相关 MCP Server
GitHub
编辑精选by GitHub
GitHub 是 MCP 官方参考服务器,让 Claude 直接读写你的代码仓库和 Issues。
✎ 这个参考服务器解决了开发者想让 AI 安全访问 GitHub 数据的问题,适合需要自动化代码审查或 Issue 管理的团队。但注意它只是参考实现,生产环境得自己加固安全。
Context7 文档查询
编辑精选by Context7
Context7 是实时拉取最新文档和代码示例的智能助手,让你告别过时资料。
✎ 它能解决开发者查找文档时信息滞后的问题,特别适合快速上手新库或跟进更新。不过,依赖外部源可能导致偶尔的数据延迟,建议结合官方文档使用。
by tldraw
tldraw 是让 AI 助手直接在无限画布上绘图和协作的 MCP 服务器。
✎ 这解决了 AI 只能输出文本、无法视觉化协作的痛点——想象让 Claude 帮你画流程图或白板讨论。最适合需要快速原型设计或头脑风暴的开发者。不过,目前它只是个基础连接器,你得自己搭建画布应用才能发挥全部潜力。