agentwallet-sdk 3.5.2 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/README.md +78 -391
  2. package/dist/__tests__/identity.did.test.d.ts +2 -0
  3. package/dist/__tests__/identity.did.test.d.ts.map +1 -0
  4. package/dist/__tests__/identity.did.test.js +56 -0
  5. package/dist/__tests__/identity.did.test.js.map +1 -0
  6. package/dist/__tests__/staking.test.d.ts +2 -0
  7. package/dist/__tests__/staking.test.d.ts.map +1 -0
  8. package/dist/__tests__/staking.test.js +70 -0
  9. package/dist/__tests__/staking.test.js.map +1 -0
  10. package/dist/__tests__/verify.test.d.ts +2 -0
  11. package/dist/__tests__/verify.test.d.ts.map +1 -0
  12. package/dist/__tests__/verify.test.js +57 -0
  13. package/dist/__tests__/verify.test.js.map +1 -0
  14. package/dist/abi.d.ts +46 -396
  15. package/dist/abi.d.ts.map +1 -1
  16. package/dist/abi.js +2 -0
  17. package/dist/abi.js.map +1 -1
  18. package/dist/bridge/abis.d.ts.map +1 -1
  19. package/dist/bridge/abis.js +2 -0
  20. package/dist/bridge/abis.js.map +1 -1
  21. package/dist/bridge/client.d.ts +43 -28
  22. package/dist/bridge/client.d.ts.map +1 -1
  23. package/dist/bridge/client.js +2 -0
  24. package/dist/bridge/client.js.map +1 -1
  25. package/dist/bridge/index.d.ts +0 -1
  26. package/dist/bridge/index.d.ts.map +1 -1
  27. package/dist/bridge/index.js +2 -0
  28. package/dist/bridge/index.js.map +1 -1
  29. package/dist/bridge/types.d.ts +32 -48
  30. package/dist/bridge/types.d.ts.map +1 -1
  31. package/dist/bridge/types.js +2 -0
  32. package/dist/bridge/types.js.map +1 -1
  33. package/dist/identity/did.d.ts +66 -0
  34. package/dist/identity/did.d.ts.map +1 -0
  35. package/dist/identity/did.js +186 -0
  36. package/dist/identity/did.js.map +1 -0
  37. package/dist/identity/erc8004.d.ts +141 -291
  38. package/dist/identity/erc8004.d.ts.map +1 -1
  39. package/dist/identity/erc8004.js +2 -0
  40. package/dist/identity/erc8004.js.map +1 -1
  41. package/dist/identity/index.d.ts +3 -0
  42. package/dist/identity/index.d.ts.map +1 -0
  43. package/dist/identity/index.js +3 -0
  44. package/dist/identity/index.js.map +1 -0
  45. package/dist/index.d.ts +1011 -32545
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +7 -0
  48. package/dist/index.js.map +1 -1
  49. package/dist/plugins/elizaos.d.ts +14 -26
  50. package/dist/plugins/elizaos.d.ts.map +1 -1
  51. package/dist/plugins/elizaos.js +2 -0
  52. package/dist/plugins/elizaos.js.map +1 -1
  53. package/dist/policy/SpendingPolicy.d.ts +15 -89
  54. package/dist/policy/SpendingPolicy.d.ts.map +1 -1
  55. package/dist/policy/SpendingPolicy.js +2 -0
  56. package/dist/policy/SpendingPolicy.js.map +1 -1
  57. package/dist/staking/AgentStakingPool.d.ts +100 -0
  58. package/dist/staking/AgentStakingPool.d.ts.map +1 -0
  59. package/dist/staking/AgentStakingPool.js +298 -0
  60. package/dist/staking/AgentStakingPool.js.map +1 -0
  61. package/dist/staking/index.d.ts +2 -0
  62. package/dist/staking/index.d.ts.map +1 -0
  63. package/dist/staking/index.js +2 -0
  64. package/dist/staking/index.js.map +1 -0
  65. package/dist/swap/SwapModule.d.ts +39 -28
  66. package/dist/swap/SwapModule.d.ts.map +1 -1
  67. package/dist/swap/SwapModule.js +2 -0
  68. package/dist/swap/SwapModule.js.map +1 -1
  69. package/dist/swap/abi.d.ts.map +1 -1
  70. package/dist/swap/abi.js +2 -0
  71. package/dist/swap/abi.js.map +1 -1
  72. package/dist/swap/index.d.ts +0 -1
  73. package/dist/swap/index.d.ts.map +1 -1
  74. package/dist/swap/index.js +2 -0
  75. package/dist/swap/index.js.map +1 -1
  76. package/dist/swap/types.d.ts +6 -40
  77. package/dist/swap/types.d.ts.map +1 -1
  78. package/dist/swap/types.js +2 -0
  79. package/dist/swap/types.js.map +1 -1
  80. package/dist/types.d.ts +5 -106
  81. package/dist/types.d.ts.map +1 -1
  82. package/dist/types.js +2 -0
  83. package/dist/types.js.map +1 -1
  84. package/dist/verify/index.d.ts +2 -0
  85. package/dist/verify/index.d.ts.map +1 -0
  86. package/dist/verify/index.js +2 -0
  87. package/dist/verify/index.js.map +1 -0
  88. package/dist/verify/verifyAgent.d.ts +42 -0
  89. package/dist/verify/verifyAgent.d.ts.map +1 -0
  90. package/dist/verify/verifyAgent.js +216 -0
  91. package/dist/verify/verifyAgent.js.map +1 -0
  92. package/dist/x402/budget.d.ts +15 -23
  93. package/dist/x402/budget.d.ts.map +1 -1
  94. package/dist/x402/budget.js +2 -0
  95. package/dist/x402/budget.js.map +1 -1
  96. package/dist/x402/chains/abstract/index.d.ts +59 -87
  97. package/dist/x402/chains/abstract/index.d.ts.map +1 -1
  98. package/dist/x402/chains/abstract/index.js +2 -0
  99. package/dist/x402/chains/abstract/index.js.map +1 -1
  100. package/dist/x402/client.d.ts +13 -27
  101. package/dist/x402/client.d.ts.map +1 -1
  102. package/dist/x402/client.js +2 -0
  103. package/dist/x402/client.js.map +1 -1
  104. package/dist/x402/index.d.ts +0 -2
  105. package/dist/x402/index.d.ts.map +1 -1
  106. package/dist/x402/index.js +2 -0
  107. package/dist/x402/index.js.map +1 -1
  108. package/dist/x402/middleware.d.ts +4 -4
  109. package/dist/x402/middleware.d.ts.map +1 -1
  110. package/dist/x402/middleware.js +2 -0
  111. package/dist/x402/middleware.js.map +1 -1
  112. package/dist/x402/types.d.ts +5 -88
  113. package/dist/x402/types.d.ts.map +1 -1
  114. package/dist/x402/types.js +2 -0
  115. package/dist/x402/types.js.map +1 -1
  116. package/package.json +32 -13
  117. package/dist/policy/SpendingPolicy.test.d.ts +0 -2
  118. package/dist/policy/SpendingPolicy.test.d.ts.map +0 -1
  119. package/dist/policy/SpendingPolicy.test.js +0 -143
  120. package/dist/policy/SpendingPolicy.test.js.map +0 -1
  121. package/dist/x402/__tests__/budget.test.d.ts +0 -2
  122. package/dist/x402/__tests__/budget.test.d.ts.map +0 -1
  123. package/dist/x402/__tests__/budget.test.js +0 -114
  124. package/dist/x402/__tests__/budget.test.js.map +0 -1
  125. package/dist/x402/__tests__/client.test.d.ts +0 -2
  126. package/dist/x402/__tests__/client.test.d.ts.map +0 -1
  127. package/dist/x402/__tests__/client.test.js +0 -107
  128. package/dist/x402/__tests__/client.test.js.map +0 -1
package/README.md CHANGED
@@ -1,444 +1,131 @@
1
- # 🤖 Agent Wallet SDK
1
+ # agentwallet-sdk
2
2
 
3
- **Let your AI agent spend crypto. Stay in control.**
3
+ Non-custodial agent wallet SDK. Your agent holds its own keys - no custodian, no KYC, no freeze risk.
4
4
 
5
- Agent Wallet gives AI agents autonomous spending power with hard on-chain limits. No more choosing between "agent can drain everything" and "every transaction needs manual approval."
6
-
7
- ```text
8
- Agent wants to spend $15 → ✅ Auto-approved (under $25 limit)
9
- Agent wants to spend $500 → ⏳ Queued for your approval
10
- Agent spent $490 today → 🛑 Next tx queued ($500/day limit hit)
11
- ```text
12
-
13
- ## Why Agent Wallet?
14
-
15
- | Approach | Problem |
16
- |----------|---------|
17
- | Raw EOA wallet | Agent can drain everything. One prompt injection = rugged. |
18
- | Multisig (Safe) | Every tx needs human sigs. Kills agent autonomy. |
19
- | Custodial API (Stripe) | Centralized, KYC friction, not crypto-native. |
20
- | **Agent Wallet** | **Agents spend freely within limits. Everything else queues for approval.** |
21
-
22
- Built on **ERC-6551** (token-bound accounts). Your agent's wallet is tied to an NFT — portable, auditable, fully on-chain.
23
-
24
- ## Quick Start
5
+ [![npm](https://img.shields.io/npm/v/agentwallet-sdk?style=flat-square)](https://www.npmjs.com/package/agentwallet-sdk)
6
+ [![Discord](https://img.shields.io/discord/1475549260140253194?label=Community&logo=discord&color=5865F2)](https://discord.gg/958AACqf7Y)
7
+ ![x402](https://img.shields.io/badge/x402-native-green?style=flat-square)
8
+ ![CCTP V2](https://img.shields.io/badge/CCTP_V2-17_chains-red?style=flat-square)
9
+ ![Tests](https://img.shields.io/badge/tests-376_passing-brightgreen?style=flat-square)
25
10
 
26
11
  ```bash
27
- npm install @agentwallet/sdk viem
28
- ```text
29
-
30
- ```typescript
31
- import {
32
- createWallet,
33
- setSpendPolicy,
34
- agentExecute,
35
- checkBudget,
36
- getPendingApprovals,
37
- approveTransaction,
38
- NATIVE_TOKEN,
39
- } from '@agentwallet/sdk';
40
- import { createWalletClient, http } from 'viem';
41
- import { privateKeyToAccount } from 'viem/accounts';
42
-
43
- // 1. Connect to your agent's wallet
44
- const walletClient = createWalletClient({
45
- account: privateKeyToAccount('0xAGENT_PRIVATE_KEY'),
46
- transport: http('https://mainnet.base.org'),
47
- });
48
-
49
- const wallet = createWallet({
50
- accountAddress: '0xYOUR_AGENT_ACCOUNT',
51
- chain: 'base',
52
- walletClient,
53
- });
54
-
55
- // 2. Owner sets spending limits (one-time setup)
56
- await setSpendPolicy(wallet, {
57
- token: NATIVE_TOKEN, // ETH
58
- perTxLimit: 25_000000000000000n, // 0.025 ETH per tx
59
- periodLimit: 500_000000000000000n, // 0.5 ETH per day
60
- periodLength: 86400, // 24 hours
61
- });
62
-
63
- // 3. Agent spends autonomously
64
- await agentExecute(wallet, {
65
- to: '0xSOME_SERVICE',
66
- value: 10_000000000000000n, // 0.01 ETH — under limit, executes immediately
67
- });
68
-
69
- // 4. Check remaining budget
70
- const budget = await checkBudget(wallet, NATIVE_TOKEN);
71
- console.log(`Remaining today: ${budget.remainingInPeriod}`);
72
-
73
- // 5. Owner reviews queued transactions
74
- const pending = await getPendingApprovals(wallet);
75
- for (const tx of pending) {
76
- console.log(`Pending #${tx.txId}: ${tx.amount} to ${tx.to}`);
77
- await approveTransaction(wallet, tx.txId);
78
- }
79
- ```text
80
-
81
- ## API Reference
82
-
83
- ### `createWallet(config)`
84
-
85
- Connect to an existing AgentAccountV2 contract.
86
-
87
- | Param | Type | Description |
88
- |-------|------|-------------|
89
- | `accountAddress` | `Address` | Deployed AgentAccountV2 address |
90
- | `chain` | `string` | `'base'` \| `'base-sepolia'` \| `'ethereum'` \| `'arbitrum'` \| `'polygon'` |
91
- | `walletClient` | `WalletClient` | viem wallet client (agent or owner key) |
92
- | `rpcUrl?` | `string` | Custom RPC URL |
93
-
94
- ### `setSpendPolicy(wallet, policy)` — Owner only
95
-
96
- Set per-token spending limits.
97
-
98
- | Field | Type | Description |
99
- |-------|------|-------------|
100
- | `token` | `Address` | Token address (`NATIVE_TOKEN` for ETH) |
101
- | `perTxLimit` | `bigint` | Max single tx (0 = all txs need approval) |
102
- | `periodLimit` | `bigint` | Max per rolling window (0 = no autonomous spending) |
103
- | `periodLength` | `number` | Window in seconds (default: 86400 = 24h) |
104
-
105
- ### `agentExecute(wallet, { to, value?, data? })`
106
-
107
- Execute a native ETH transaction. Auto-approves if within limits, queues if over.
108
-
109
- **Returns:** `{ executed: boolean, txHash: Hash, pendingTxId?: bigint }`
110
-
111
- ### `agentTransferToken(wallet, { token, to, amount })`
112
-
113
- Transfer ERC20 tokens, respecting spend limits.
114
-
115
- ### `checkBudget(wallet, token?)`
116
-
117
- Check remaining autonomous spending budget.
118
-
119
- **Returns:** `{ token, perTxLimit, remainingInPeriod }`
120
-
121
- ### `getPendingApprovals(wallet, fromId?, toId?)`
122
-
123
- List all pending (unexecuted, uncancelled) transactions awaiting owner approval.
124
-
125
- ### `approveTransaction(wallet, txId)` — Owner only
126
-
127
- Approve and execute a queued transaction.
128
-
129
- ### `cancelTransaction(wallet, txId)` — Owner only
12
+ npm i agentwallet-sdk
13
+ ```
130
14
 
131
- Cancel a queued transaction.
15
+ ---
132
16
 
133
- ### `setOperator(wallet, operator, authorized)` — Owner only
17
+ ## Why agent-wallet-sdk?
134
18
 
135
- Add or remove an agent operator address.
19
+ Most agent wallet solutions compromise on the thing that matters most: who controls the keys.
136
20
 
137
- ### `getBudgetForecast(wallet, token?, now?)`
21
+ | | agent-wallet-sdk | Coinbase Agentic Wallets | MoonPay Agents |
22
+ |---|---|---|---|
23
+ | **Key custody** | Agent holds own keys | Coinbase TEE (custodial) | MoonPay managed |
24
+ | **Freeze risk** | None - on-chain only | Yes - platform can freeze | Yes - KYC-gated |
25
+ | **Cross-chain** | 17 chains via CCTP V2 | Base only | Limited |
26
+ | **x402 support** | Native (v2.0.1+) | No public x402 client | No |
27
+ | **Spend limits** | On-chain, enforced by contract | Platform-enforced | Platform-enforced |
28
+ | **KYC required** | No | No | Yes |
29
+ | **MCP compatible** | Yes | No | No |
138
30
 
139
- **[MAX-ADDED]** Time-aware budget forecast know not just what's left, but when it refills.
31
+ ### Coinbase Agentic Wallets - what "TEE-custodial" means
140
32
 
141
- **Returns:** `BudgetForecast` includes `remainingInPeriod`, `secondsUntilReset`, `utilizationPercent`, full period metadata.
33
+ Coinbase stores private keys in Trusted Execution Environments on their infrastructure. The keys are not yours. If Coinbase freezes your account, halts the service, or gets a court order, your agent stops working. The TEE makes the custody tamper-resistant to Coinbase employees - but it does not make it non-custodial. You are still trusting Coinbase.
142
34
 
143
- ```typescript
144
- const forecast = await getBudgetForecast(wallet, NATIVE_TOKEN);
145
- console.log(`${forecast.utilizationPercent}% used, resets in ${forecast.secondsUntilReset}s`);
146
- ```text
35
+ ### MoonPay Agents - the CLI-bound, KYC wall
147
36
 
148
- ### `getWalletHealth(wallet, operators?, tokens?, now?)`
37
+ MoonPay requires identity verification before an agent can transact. That kills the autonomous agent use case - you can't run an agent at 2 AM that needs to pay an API if the payment rails need KYC approval first. MoonPay also does not expose an x402 interface, so agents using MoonPay can't participate in the emerging x402 payment ecosystem.
149
38
 
150
- **[MAX-ADDED]** Single-call diagnostic snapshot for agent self-monitoring.
39
+ ### agent-wallet-sdk - true non-custody
151
40
 
152
- **Returns:** `WalletHealth` address, NFT binding, operator epoch, active operator statuses, pending queue depth, budget forecasts.
41
+ The wallet is an ERC-6551 token-bound account on-chain. The agent's private key lives in the agent's environment, controlled by whoever runs the agent. Nobody else has it. Spend limits are enforced by the smart contract - not by a platform policy that can change overnight.
153
42
 
154
43
  ```typescript
155
- const health = await getWalletHealth(wallet, [agentHotWallet], [NATIVE_TOKEN, usdcAddress]);
156
- if (health.pendingQueueDepth > 5) console.warn('Queue backing up!');
157
- if (!health.activeOperators[0].active) console.error('Agent operator deactivated!');
158
- ```text
44
+ import { createWallet, createX402Fetch, NATIVE_TOKEN } from 'agentwallet-sdk';
159
45
 
160
- ### `batchAgentTransfer(wallet, transfers)`
46
+ // Agent holds its own key
47
+ const wallet = createWallet({ accountAddress: '0x...', chain: 'base', walletClient });
161
48
 
162
- **[MAX-ADDED]** Execute multiple token transfers sequentially reduces boilerplate for multi-recipient payments.
163
-
164
- ```typescript
165
- const hashes = await batchAgentTransfer(wallet, [
166
- { token: USDC, to: serviceA, amount: 100n },
167
- { token: USDC, to: serviceB, amount: 200n },
168
- ]);
169
- ```text
49
+ // x402 payments: agent pays APIs automatically, no human needed
50
+ const fetch = createX402Fetch(wallet, { globalDailyLimit: 10_000_000n });
51
+ const data = await fetch('https://api.example.com/premium');
52
+ // Server returned 402? Payment handled. Original request retried. Human not consulted.
170
53
 
171
- ### `getActivityHistory(wallet, { fromBlock?, toBlock? })`
54
+ // Spend limits are on-chain - agent can't exceed them even under prompt injection
55
+ ```
172
56
 
173
- **[MAX-ADDED]** Query on-chain event history for self-auditing — no external indexer needed.
57
+ ### Cross-chain without the ceremony
174
58
 
175
- **Returns:** `ActivityEntry[]` sorted by block number, covers executions, queued txs, approvals, cancellations, policy updates, operator changes.
59
+ One bridge interface across 17 chains. Coinbase Agentic Wallets are Base-only. MoonPay is not cross-chain native.
176
60
 
177
61
  ```typescript
178
- const history = await getActivityHistory(wallet, { fromBlock: 10000n });
179
- for (const entry of history) {
180
- console.log(`[${entry.type}] block ${entry.blockNumber}: ${JSON.stringify(entry.args)}`);
181
- }
182
- ```text
183
-
184
- ## Supported Chains
185
-
186
- | Chain | Status | Best For |
187
- |-------|--------|----------|
188
- | **Base** | ✅ Primary | Low gas, USDC native |
189
- | **Base Sepolia** | ✅ Testnet | Development |
190
- | **Ethereum** | ✅ | High-value operations |
191
- | **Arbitrum** | ✅ | DeFi agents |
192
- | **Polygon** | ✅ | Micropayments |
193
- | **Etherlink** | ✅ | x402 multichain payments |
194
-
195
- ## x402 Protocol Support
62
+ import { UnifiedBridge } from 'agentwallet-sdk';
196
63
 
197
- > **March 2026:** x402 just landed on Etherlink (Tezos L2). agent-wallet-sdk explicitly supports x402 on both **Base** (primary, USDC-native) and **Etherlink** — making it one of the first non-custodial SDKs to span both x402 chains. [Submit your agent to the x402 Bazaar](https://x402.org/bazaar) to get indexed.
64
+ const bridge = new UnifiedBridge({ evmSigner, solanaWallet });
198
65
 
199
- Agent Wallet natively supports the [x402 protocol](https://x402.org) — the open standard for HTTP 402 machine payments. Your agent can automatically pay any x402-enabled API (Stripe, Coinbase, etc.) using USDC on Base or Etherlink, while respecting on-chain spend limits.
200
-
201
- ### Quick Start
202
-
203
- ```typescript
204
- import { createWallet, createX402Client } from 'agentwallet-sdk';
205
-
206
- // 1. Create your wallet
207
- const wallet = createWallet({ accountAddress, chain: 'base', walletClient });
208
-
209
- // 2. Create an x402-aware client
210
- const client = createX402Client(wallet, {
211
- globalDailyLimit: 50_000_000n, // 50 USDC/day
212
- globalPerRequestMax: 5_000_000n, // 5 USDC max per request
213
- serviceBudgets: [
214
- { service: 'api.weather.com', maxPerRequest: 1_000_000n, dailyLimit: 10_000_000n },
215
- ],
66
+ // Solana -> Base in one call
67
+ await bridge.bridge({
68
+ amount: 1_000_000n,
69
+ sourceChain: 'solana',
70
+ destinationChain: 'base',
71
+ destinationAddress: '0x...',
216
72
  });
73
+ ```
217
74
 
218
- // 3. Use it like fetch 402 responses are handled automatically
219
- const response = await client.fetch('https://api.weather.com/forecast');
220
- const data = await response.json();
221
- // If the API returned 402, the client:
222
- // - Parsed payment requirements from the PAYMENT-REQUIRED header
223
- // - Checked your budget (client-side + on-chain)
224
- // - Paid USDC via your AgentWallet contract
225
- // - Retried the request with payment proof
226
- ```text
227
-
228
- ### Drop-in Fetch Replacement
229
-
230
- ```typescript
231
- import { createX402Fetch } from 'agentwallet-sdk';
232
-
233
- const x402Fetch = createX402Fetch(wallet, { globalDailyLimit: 100_000_000n });
234
-
235
- // Use exactly like fetch()
236
- const res = await x402Fetch('https://any-x402-api.com/endpoint');
237
- ```text
238
-
239
- ### Budget Controls
240
-
241
- ```typescript
242
- // Check spending
243
- const summary = client.getDailySpendSummary();
244
- console.log(`Today's spend: ${summary.global} (resets at ${summary.resetsAt})`);
245
-
246
- // View transaction log
247
- const logs = client.getTransactionLog({ service: 'api.weather.com' });
248
-
249
- // Add budget at runtime
250
- client.budgetTracker.setServiceBudget({
251
- service: 'new-api.com',
252
- maxPerRequest: 2_000_000n,
253
- dailyLimit: 20_000_000n,
254
- });
255
- ```text
75
+ Supported chains: Base, Ethereum, Solana, Arbitrum, Optimism, Polygon, Avalanche, Unichain, Linea, Codex, Sonic, World Chain, Sei, XDC, HyperEVM, Ink, Plume.
256
76
 
257
- ### Payment Approval Callback
77
+ ---
258
78
 
259
- ```typescript
260
- const client = createX402Client(wallet, {
261
- onBeforePayment: async (req, url) => {
262
- console.log(`About to pay ${req.amount} to ${req.payTo} for ${url}`);
263
- return true; // return false to reject
264
- },
265
- onPaymentComplete: (log) => {
266
- console.log(`Paid ${log.amount} via tx ${log.txHash}`);
267
- },
268
- });
269
- ```text
79
+ ## Install
270
80
 
271
- ### Etherlink x402 - Non-Custodial ERC-20 Payments via Permit2
81
+ ```bash
82
+ npm i agentwallet-sdk
83
+ ```
272
84
 
273
- Etherlink (Tezos L2) launched x402 support in March 2026 with a Permit2 proxy for non-custodial ERC-20 payments. `agentwallet-sdk` supports this directly:
85
+ ## Quick Start
274
86
 
275
87
  ```typescript
276
- import { createWallet, createX402Client } from 'agentwallet-sdk';
88
+ import { createWallet, setSpendPolicy, agentExecute, NATIVE_TOKEN } from 'agentwallet-sdk';
277
89
  import { createWalletClient, http } from 'viem';
278
90
  import { privateKeyToAccount } from 'viem/accounts';
279
91
 
280
92
  const walletClient = createWalletClient({
281
- account: privateKeyToAccount(process.env.AGENT_KEY!),
282
- transport: http('https://node.mainnet.etherlink.com'),
93
+ account: privateKeyToAccount(process.env.AGENT_PRIVATE_KEY),
94
+ transport: http('https://mainnet.base.org'),
283
95
  });
284
96
 
285
97
  const wallet = createWallet({
286
- accountAddress: '0xYOUR_AGENT_CONTRACT',
287
- chain: 'etherlink',
98
+ accountAddress: '0xYOUR_AGENT_ACCOUNT',
99
+ chain: 'base',
288
100
  walletClient,
289
101
  });
290
102
 
291
- // x402 client on Etherlink -- same API, near-zero fees
292
- const client = createX402Client(wallet, {
293
- preferredChain: 'etherlink',
294
- globalDailyLimit: 100_000_000n, // 100 USDC/day
295
- globalPerRequestMax: 2_000_000n, // 2 USDC max per request
296
- });
297
-
298
- // Fetch x402-gated resources -- 402 handled automatically
299
- const response = await client.fetch('https://api.example.com/agent-data');
300
- // Client parsed 402, checked budget, signed via Permit2, retried with proof
301
- ```
302
-
303
- Unlike custodial x402 implementations (Coinbase, OKX OnchainOS), the key never leaves your environment. The Permit2 proxy handles ERC-20 approval flow, but authorization is signed locally.
304
-
305
- ### How x402 Works
306
-
307
- ```text
308
- Agent → GET /api/data → Server returns 402 + PAYMENT-REQUIRED header
309
-
310
- Client parses payment requirements (amount, token, recipient, network)
311
-
312
- Budget check (client-side caps + on-chain spend limits)
313
-
314
- AgentWallet executes USDC transfer on Base or Etherlink
315
-
316
- Client retries request with X-PAYMENT header (payment proof)
317
-
318
- Server verifies payment → returns 200 + data
319
- ```text
320
-
321
- Your agent's keys never leave the non-custodial wallet. All payments respect on-chain spend limits set by the wallet owner.
322
-
323
- ## Why agent-wallet-sdk?
324
-
325
- Every major AI company launched an agent wallet in early 2026. Coinbase Agentic Wallets went live February 13. MoonPay Agents launched March 4. Stripe added x402 on February 11. The problem: every single one of them holds your agent's keys.
326
-
327
- Here's the direct comparison:
328
-
329
- | | Coinbase AgentKit | MoonPay Agents | Circuit & Chisel ATXP | agent-wallet-sdk |
330
- |---|---|---|---|---|
331
- | **Key custody** | Coinbase servers | MoonPay servers | Enterprise custodian | Your environment only |
332
- | **SDK type** | TypeScript SDK | CLI-only | No public SDK | TypeScript SDK |
333
- | **Spend limits** | Session caps (off-chain API) | None | Nested policy layer | Per-tx + daily, on-chain contract |
334
- | **x402 support** | Yes (Base/USDC) | No | Partial | Yes (Base, Etherlink, full spec) |
335
- | **Cross-chain** | Base only (USDC) | No CCTP | EVM-only | 5 chains via CCTP V2 |
336
- | **Freeze risk** | Yes (KYC, compliance) | Yes | Yes (enterprise terms) | None -- contract on-chain |
337
- | **Audit trail** | API logs (centralized) | API logs | Enterprise dashboard | On-chain events, self-queryable |
338
- | **Open source** | No | No | No | Yes (MIT) |
339
- | **KYC required** | Yes | Yes | Yes | No |
340
- | **Agent-sovereign** | No | No | No | Yes |
341
-
342
- **The three questions that matter:**
343
-
344
- **1. Who holds the key?** With Coinbase and MoonPay, their infrastructure holds your agent's private key. That means they can freeze it, they get hacked and your key goes with it, and they can shut down the product. agent-wallet-sdk generates keys locally and they never leave your environment.
345
-
346
- **2. Where are spend limits enforced?** Coinbase uses session caps enforced at the API layer -- those can change. MoonPay has no per-transaction limits at all. agent-wallet-sdk enforces limits inside an EVM contract. A `perTxLimit` of 25 USDC means the contract will physically not execute a transaction over 25 USDC. No API to call, no policy to change.
347
-
348
- **3. What happens when the platform shuts down?** Custodial wallets disappear with the platform. Your agent's wallet contract is deployed on-chain. It exists as long as the EVM exists.
349
-
350
- ```typescript
351
- // Your keys stay in your environment -- not on Coinbase, not on MoonPay
352
- const wallet = createWallet({
353
- accountAddress: '0xYOUR_CONTRACT',
354
- walletClient: createWalletClient({
355
- account: privateKeyToAccount(process.env.AGENT_KEY), // never transmitted
356
- transport: http('https://mainnet.base.org'),
357
- }),
358
- chain: 'base',
103
+ // Set spend limits once (owner operation)
104
+ await setSpendPolicy(wallet, {
105
+ token: NATIVE_TOKEN,
106
+ perTxLimit: 25_000000000000000n, // 0.025 ETH per tx
107
+ periodLimit: 500_000000000000000n, // 0.5 ETH per day
108
+ periodLength: 86400,
359
109
  });
360
- ```
361
-
362
- If you need a quick integration and you're already in the Coinbase ecosystem: their product works for demos and low-stakes use cases. But if you're building agents that handle real funds, run autonomously for weeks, or need to survive beyond a single platform's product lifecycle -- you want the keys under your own control.
363
-
364
- ---
365
-
366
- ## Why Non-Custodial Matters for Agents
367
-
368
- Three reasons agents need non-custodial wallets, not exchange accounts:
369
-
370
- - **Agent-sovereign by design.** The agent's private key lives in its own environment -- not on OKX, not on Coinbase, not on anyone's server. No exchange can freeze it, no compliance team can lock it, no API deprecation can kill it.
371
- - **On-chain spend limits, not platform policies.** Custodial wallets enforce limits at the API layer. Those policies can change. This SDK enforces limits inside an EVM contract -- the chain enforces it, not a company.
372
- - **No exchange holds the keys.** When OKX OnchainOS or Coinbase Agentic Wallets hold your agent's key, they own the wallet. If they go down, if they get hacked, if they decide to shut down the product -- your agent stops working. Non-custodial means the wallet is yours as long as the chain runs.
373
-
374
- ## Why Non-Custodial Beats Exchange Wallets
375
-
376
- OKX OnchainOS supports 60+ chains. Coinbase Agentic Wallets are backed by a trillion-dollar exchange. Both look impressive on paper. Here's the problem: **they hold your agent's keys.**
377
-
378
- That's not a minor implementation detail. It's the entire trust model.
379
-
380
- ### What custody actually means
381
-
382
- When you use an exchange-based agent wallet, your agent's private key lives on their servers. Every transaction your agent signs goes through their infrastructure. They can:
383
- - Freeze your agent's wallet for any reason (KYC, compliance, a bad week)
384
- - Be subpoenaed for your agent's transaction history
385
- - Get hacked — and your agent's keys go with it
386
- - Change their API, deprecate their SDK, sunset the product
387
-
388
- This isn't theoretical. Exchange platforms shut down products, freeze accounts, and go dark. It's happened before. It'll happen again.
389
110
 
390
- ### The non-custodial difference
391
-
392
- With `agentwallet-sdk`:
393
- - Your agent's private key is generated locally and **never transmitted anywhere**
394
- - The wallet contract lives on-chain — no server to shut down
395
- - Spend limits are enforced by EVM bytecode, not an API policy
396
- - You can self-host, self-audit, and self-custody everything
397
-
398
- ```typescript
399
- // Your keys stay in your environment
400
- const wallet = createWallet({
401
- accountAddress: '0xYOUR_CONTRACT',
402
- walletClient: createWalletClient({
403
- account: privateKeyToAccount(process.env.AGENT_KEY), // lives here, not on OKX
404
- transport: http('https://mainnet.base.org'),
405
- }),
406
- chain: 'base',
407
- });
111
+ // Agent executes autonomously within limits
112
+ await agentExecute(wallet, { to: '0xSOME_SERVICE', value: 10_000000000000000n });
408
113
  ```
409
114
 
410
- The spend limits (`$25/tx`, `$500/day`) are enforced by the contract itself — not by an exchange API that can change its terms. An agent running over-limit? The contract queues it. No custodian involved.
411
-
412
- ### When exchange wallets make sense
413
-
414
- If you're building a quick demo, need zero infrastructure setup, or are already deep in the Coinbase or OKX ecosystem — their hosted products are fast to integrate. No judgment.
415
-
416
- But if you're building production agents that handle real funds, run autonomously, or need to survive beyond a single platform's product lifecycle, you want the keys under your own control.
417
-
418
- That's what this SDK is for.
419
-
420
- ### x402 without custody
421
-
422
- The x402 protocol is becoming the standard for AI agent payments. Stripe validated it in February 2026. Coinbase built it into Base. Abstract launched their delegated facilitator model this week.
423
-
424
- Every x402 implementation in `agentwallet-sdk` is non-custodial by design:
425
- - Solana x402: direct signing from your local keypair
426
- - Base x402: USDC transfer via your on-chain contract
427
- - Abstract x402: EIP-712 delegated permit, signed locally — the facilitator executes it, but your key authorizes it
428
-
429
- OKX OnchainOS supports x402 too — through their custody layer. Your call which model you trust.
430
-
431
- ---
115
+ ## Key Features
432
116
 
433
- ## How It Works
117
+ - **Non-custodial**: Agent holds its own private key. No custodian.
118
+ - **x402 native**: Drop-in fetch wrapper for automatic API payment handling
119
+ - **17-chain CCTP V2**: Cross-chain USDC via Circle's bridge - EVM + Solana
120
+ - **On-chain spend limits**: ERC-6551 token-bound accounts with contract-enforced policies
121
+ - **MCP compatible**: Use with any MCP-based agent framework
122
+ - **376 tests passing**
434
123
 
435
- 1. **Deploy** an AgentAccountV2 (ERC-6551 token-bound account tied to an NFT)
436
- 2. **Configure** spend policies per token — set per-tx and daily limits
437
- 3. **Register** your agent's hot wallet as an operator
438
- 4. **Agent operates autonomously** — transactions within limits execute instantly
439
- 5. **Over-limit transactions queue** — owner gets notified, approves or cancels
124
+ ## Resources
440
125
 
441
- All limits enforced on-chain. No off-chain dependencies. Fully auditable.
126
+ - [npm package](https://www.npmjs.com/package/agentwallet-sdk)
127
+ - [Discord community](https://discord.gg/958AACqf7Y)
128
+ - [x402 docs](https://docs.x402.org)
442
129
 
443
130
  ## License
444
131
 
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=identity.did.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.did.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/identity.did.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,56 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { deriveAgentDID, issueCredential, verifyCredential, exportDIDDocument, } from '../identity/did.js';
3
+ const TEST_PRIVATE_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80';
4
+ describe('Agent DID (did:key)', () => {
5
+ it('derives a deterministic DID from a private key', () => {
6
+ const did1 = deriveAgentDID(TEST_PRIVATE_KEY);
7
+ const did2 = deriveAgentDID(TEST_PRIVATE_KEY);
8
+ expect(did1.did).toBe(did2.did);
9
+ expect(did1.did).toMatch(/^did:key:z6Mk/);
10
+ });
11
+ it('derives different DIDs for different private keys', () => {
12
+ const key2 = '0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d';
13
+ const did1 = deriveAgentDID(TEST_PRIVATE_KEY);
14
+ const did2 = deriveAgentDID(key2);
15
+ expect(did1.did).not.toBe(did2.did);
16
+ });
17
+ it('exports a valid W3C DID Document', () => {
18
+ const did = deriveAgentDID(TEST_PRIVATE_KEY);
19
+ const doc = exportDIDDocument(did);
20
+ expect(doc['@context']).toContain('https://www.w3.org/ns/did/v1');
21
+ expect(doc.id).toBe(did.did);
22
+ expect(doc.verificationMethod).toHaveLength(1);
23
+ expect(doc.verificationMethod[0].type).toBe('Ed25519VerificationKey2020');
24
+ expect(doc.authentication).toHaveLength(1);
25
+ });
26
+ it('issues and verifies a Verifiable Credential', () => {
27
+ const did = deriveAgentDID(TEST_PRIVATE_KEY);
28
+ const vc = issueCredential(did, TEST_PRIVATE_KEY, {
29
+ agentType: 'autonomous',
30
+ capability: 'payment',
31
+ });
32
+ expect(vc['@context']).toContain('https://www.w3.org/2018/credentials/v1');
33
+ expect(vc.issuer).toBe(did.did);
34
+ expect(vc.type).toContain('VerifiableCredential');
35
+ expect(vc.credentialSubject.agentType).toBe('autonomous');
36
+ expect(vc.proof.type).toBe('Ed25519Signature2020');
37
+ const valid = verifyCredential(vc);
38
+ expect(valid).toBe(true);
39
+ });
40
+ it('rejects a tampered credential', () => {
41
+ const did = deriveAgentDID(TEST_PRIVATE_KEY);
42
+ const vc = issueCredential(did, TEST_PRIVATE_KEY, { role: 'agent' });
43
+ const tampered = {
44
+ ...vc,
45
+ credentialSubject: { ...vc.credentialSubject, role: 'admin' },
46
+ };
47
+ expect(verifyCredential(tampered)).toBe(false);
48
+ });
49
+ it('rejects credential with wrong issuer DID', () => {
50
+ const did = deriveAgentDID(TEST_PRIVATE_KEY);
51
+ const vc = issueCredential(did, TEST_PRIVATE_KEY, { role: 'agent' });
52
+ const tampered = { ...vc, issuer: 'did:key:z6MkFake' };
53
+ expect(verifyCredential(tampered)).toBe(false);
54
+ });
55
+ });
56
+ //# sourceMappingURL=identity.did.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.did.test.js","sourceRoot":"","sources":["../../src/__tests__/identity.did.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=staking.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staking.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/staking.test.ts"],"names":[],"mappings":""}