@vedmohan/agent-wallet
v2.4.1
Published
Private Agent Wallet for x402: AI agents pay for APIs in USDC on Avalanche with privacy-aware payment outputs and SmoothSend-sponsored execution.
Downloads
115
Maintainers
Readme
🤖 Private Agent Wallet — gasless x402 + ERC-8004
AI agents pay for APIs in USDC on Avalanche - including gas - and the privacy pivot now targets real eERC encrypted transfers for hidden amounts on-chain. No AVAX needed for the sponsored flow. Plus on-chain agent identity and reputation via ERC-8004.
Built on SmoothSend ERC-4337 infrastructure (VerifyingPaymaster + bundler on Avalanche C-Chain).
✨ Live Demo
x402avax.vercel.app — three tabs:
| Tab | What it does |
|-----|-------------|
| Live Demo | Toggle x402 OFF → see raw 402 Payment Required. Toggle ON → auto-pays in USDC, get weather data. Private spend mode masks cost details until you reveal them. City picker (Tokyo, London, Dubai, NYC, Singapore). |
| Marketplace | ERC-8004 agent registry. Register your agent, browse agents by reputation score, hire via x402 payment + on-chain feedback |
| Quick Start | Copy-paste code snippets |
Pivot Summary
This hackathon version now has a cleaner privacy story:
- gasless agent payments on Avalanche
- real eERC encrypted transfers for hidden amounts
- ERC-8004 identity and reputation as the trust layer
The old receipt-only privacy path is no longer the target demo. The public payment flow remains as a fallback, but the pitch should center on encrypted value movement.
SDK-first pivot
The package is now meant to be consumed as a real SDK:
AgentWalletstays the main entrypointpayForService()still handles gasless x402 flowprivateTransfer()routes to encrypted value movement when an eERC bridge is configuredgetEncryptedBalance()exposes the encrypted balance snapshot for private flows
If you want fully private transfers, provide an eercBridge adapter when creating the wallet. The SDK keeps the app-facing API small and lets the demo site or your own app wire the bridge implementation.
What's New in v2.0.0 — ERC-8004 Agent Registry
This release adds on-chain agent identity and reputation via ERC-8004: the Trustless Agents standard.
Two contracts deployed on Avalanche Fuji:
| Contract | Address | Role |
|----------|---------|------|
| IdentityRegistry | 0x3F5Ee79771C2628D3941Bc015d306C194DA2E425 | ERC-721 agent identities with EIP-712 wallet verification |
| ReputationRegistry | 0x351487d9E592B0D6682b0027a2eA099ab2652B10 | On-chain feedback scores with proof-of-payment |
Source: agent-wallet/contracts/contracts/
// New in v2.0.0 — ERC-8004 identity + reputation
const wallet = await AgentWallet.create({ ... });
// Register an agent identity (mints an ERC-721, gas sponsored)
const agentId = await wallet.registerIdentity(
'Weather Bot',
'Gets weather data via x402 on Avalanche'
);
// → Agent ID: 1 — on-chain identity created
// Get reputation score for any agent
const rep = await wallet.getReputation(agentId);
// → { count: 5, summaryValue: 42500, valueDecimals: 2, score: 85 }
// Submit feedback after a transaction
const feedbackTx = await wallet.submitFeedback({
agentId: 1,
value: 85,
tag1: 'x402',
feedbackURI: 'data:...,{"proofOfPayment":{"txHash":"0x..."}}',
});
// Get full marketplace listing
const listing = await wallet.getAgentListing(agentId);
// → { identity: { agentId, owner, agentWallet }, reputation: { count, score } }ERC-8004 Flow
AgentWallet.create()
→ registerIdentity(name, desc) // Mints ERC-721 on IdentityRegistry
→ x402.request(url) // Pays API in USDC
→ submitFeedback(agentId, score) // Posts feedback to ReputationRegistry
→ getReputation(agentId) // Reads on-chain reputation scoreThe IdentityRegistry uses EIP-712 signatures to verify the agent's payment wallet. The ReputationRegistry stores feedback as (value, valueDecimals, tag1, tag2) with optional proofOfPayment URIs. Both are per-chain singletons — one shared registry that all agents register to, building a networked reputation layer.
Monorepo Structure
agent-wallet/
├── src/ # SDK source (AgentWallet, X402Client, types)
├── contracts/ # ERC-8004 Solidity contracts
│ ├── contracts/
│ │ ├── IdentityRegistry.sol # ERC-721 agent identity
│ │ └── ReputationRegistry.sol # On-chain feedback
│ ├── scripts/deploy.ts # Fuji deploy script
│ ├── hardhat.config.ts
│ └── DEPLOYED.md # Contract addresses
├── demo-site/ # Next.js demo app (Vercel)
│ └── app/
│ ├── page.tsx # Main UI (3 tabs)
│ └── api/
│ ├── demo/route.ts # x402 flow + agent registration
│ ├── marketplace/route.ts # Agent listing API
│ └── merchant/route.ts # Merchant endpoint (402)
├── dist/ # Built SDK
└── package.json # @vedmohan/agent-walletWhy Agent Wallet?
Base's x402 protocol makes merchants pay gas in ETH. Agent Wallet flips this — the agent pays everything in USDC on Avalanche:
| | Plain x402 | Agent Wallet | |---|---|---| | Network | Base (ETH gas) | Avalanche C-Chain | | Merchant receives | ~96% | 100% | | Who pays gas | Merchant in ETH | Agent in USDC | | Gas token | ETH | USDC | | Agent needs ETH? | Yes | No — just USDC | | Setup | Deploy paymaster + KYC | 1 API key, 30s | | Identity | None | ERC-8004 on-chain | | Reputation | None | On-chain feedback |
Quick Start
npm install @vedmohan/agent-walletimport { AgentWallet, X402Client } from '@vedmohan/agent-wallet';
// Create wallet (smart account auto-deployed on first tx)
const wallet = await AgentWallet.create({
smoothSendApiKey: 'sk_nogas_...', // dashboard.smoothsend.xyz
dailyLimit: '100',
perTxLimit: '10',
network: 'avalanche-fuji',
});
console.log(`Smart Account: ${wallet.address}`);
console.log(`Balance: $${await wallet.getBalance()} USDC`);
// Optional: register an ERC-8004 identity
const agentId = await wallet.registerIdentity('My Bot', 'AI agent demo');
console.log(`Registered as Agent #${agentId}`);
// x402 calls — auto-pays when 402 is received
const x402 = new X402Client({ wallet });
const weather = await x402.request(
'https://api.example.com/weather?city=Tokyo'
);
console.log(`🌤️ ${weather.data.temperature}°C, ${weather.data.condition}`);
// 💸 Auto-paid $0.02 USDC — all in USDCAPI Reference
AgentWallet
const wallet = await AgentWallet.create(config)| Config Field | Required | Default | Description |
|---|---|---|---|
| smoothSendApiKey | ✅ | — | From dashboard.smoothsend.xyz |
| network | ✅ | — | avalanche-fuji or avalanche-mainnet |
| dailyLimit | ✅ | — | Max USDC/day (e.g. '100') |
| perTxLimit | ✅ | — | Max USDC/tx (e.g. '10') |
| privateKey | ❌ | Random EOA | Reuse wallet across restarts |
| privacyMode | ❌ | false | Redact payment output by default |
| privacyRegistryAddress | ❌ | undefined | Optional private envelope registry |
| eercBridge | ❌ | undefined | Adapter that provides encrypted balance + transfer methods |
| eercTokenAddress | ❌ | undefined | Default encrypted token address for private transfers |
| eercDecimals | ❌ | 2 | Decimals used when converting private transfer amounts |
| identityRegistryAddress | ❌ | Fuji deployment | Custom IdentityRegistry address |
| reputationRegistryAddress | ❌ | Fuji deployment | Custom ReputationRegistry address |
Methods:
| Method | Returns | Description |
|--------|---------|-------------|
| wallet.address | string | Smart account address (ERC-4337) |
| wallet.eoaAddress | string | EOA owner address |
| wallet.agentId | number \| null | ERC-8004 agent ID (after registerIdentity) |
| getBalance() | string | USDC balance |
| payForService(req) | PaymentResult | Pay merchant in USDC (auto-approves paymaster) |
| privateTransfer(req) | PaymentResult | Send an encrypted transfer through the eERC bridge |
| getEncryptedBalance(tokenAddress?) | EncryptedBalanceSnapshot | Read the encrypted balance snapshot from the bridge |
| getBudgetStatus() | BudgetStatus | Daily + per-tx budget info |
| exportPrivateKey() | string | Export EOA private key |
| registerIdentity(name, desc) | number | v2.0 Mint ERC-8004 identity, returns agentId |
| getReputation(agentId) | AgentReputation | v2.0 Read on-chain reputation score (0-100) |
| submitFeedback(input) | string | v2.0 Submit feedback for an agent (tx hash) |
| getAgentListing(agentId) | object | v2.0 Full identity + reputation listing |
X402Client
const x402 = new X402Client({ wallet });
const result = await x402.request(url | AxiosRequestConfig);
// → { data, status, paid, payment? }
const results = await x402.batch([url1, url2, ...]);paid: false→ no payment neededpaid: true→ 402 was paid,payment: { txHash, totalCost, gasCost, apiCost }
Architecture
┌─────────────────────────────────────────────────────┐
│ Agent Wallet SDK │
├─────────────┬──────────────┬────────────────────────┤
│ AgentWallet │ X402Client │ McpClient │
│ (wallet) │ (auto-pay) │ (tx lookup) │
├─────────────┴──────┬───────┴────────────────────────┤
│ │ │
│ SmoothSend Bundler (ERC-4337) │
│ VerifyingPaymaster (user-pays-erc20) │
│ EntryPoint v0.7 │
├─────────────────────────────────────────────────────┤
│ IdentityRegistry (ERC-8004) ReputationRegistry │
│ • register(name, desc) • giveFeedback() │
│ • setAgentWallet(EIP-712) • getSummary() │
│ • getAgentWallet() • revokeFeedback() │
├─────────────────────────────────────────────────────┤
│ eERC Bridge │
│ • getBalanceSnapshot() • transfer() │
│ • register() • withdraw() │
└─────────────────────────────────────────────────────┘eERC bridge contract
The SDK does not hardcode proof generation. Instead, it expects a small bridge object that wraps whatever eERC runtime you use.
import { AgentWallet, type EercBridge } from '@vedmohan/agent-wallet';
const eercBridge: EercBridge = {
async getBalanceSnapshot(tokenAddress) {
// Return decrypted + encrypted balance state for the current wallet.
return {
decryptedBalance: 1250000n,
parsedDecryptedBalance: '1.250000',
encryptedBalance: [0n, 0n],
auditorPublicKey: [0n, 0n],
decimals: 6n,
};
},
async transfer(to, amount, tokenAddress) {
// Call your eERC runtime here.
return { transactionHash: '0x...' };
},
};
const wallet = await AgentWallet.create({
smoothSendApiKey: process.env.SMOOTHSEND_API_KEY!,
dailyLimit: '100',
perTxLimit: '10',
network: 'avalanche-fuji',
eercBridge,
eercTokenAddress: '0xYourEncryptedToken',
eercDecimals: 6,
});
await wallet.privateTransfer({
to: '0xRecipient',
amount: '1.25',
private: true,
});Development
Running locally
cd agent-wallet/demo-site
npm install
npm run devThe demo site now consumes the published @vedmohan/agent-wallet package from npm by default.
Deploying contracts
cd agent-wallet/contracts
cp .env.example .env # add DEPLOYER_PRIVATE_KEY
npm run deploy:fujiPublishing the SDK
cd agent-wallet
npm run build
npm publish --access publicThen update any consumer to:
- depend on
@vedmohan/agent-wallet@^2.4.0 - rebuild their lockfile if it pins an older version
- pass an
eercBridgeadapter if they want the private transfer path
Consuming it in an app
Minimum setup:
import { AgentWallet, X402Client } from '@vedmohan/agent-wallet';
const wallet = await AgentWallet.create({
smoothSendApiKey: process.env.SMOOTHSEND_API_KEY!,
dailyLimit: '100',
perTxLimit: '10',
network: 'avalanche-fuji',
});
const x402 = new X402Client({ wallet });Private transfers:
const wallet = await AgentWallet.create({
smoothSendApiKey: process.env.SMOOTHSEND_API_KEY!,
dailyLimit: '100',
perTxLimit: '10',
network: 'avalanche-fuji',
eercBridge,
eercTokenAddress: '0xYourEncryptedToken',
eercDecimals: 6,
});
await wallet.privateTransfer({
to: '0xRecipient',
amount: '1.25',
private: true,
});License
MIT — © 2026 Ved Mohan
