agentwallet-sdk 5.0.2 → 5.0.3

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.
package/README.md CHANGED
@@ -204,9 +204,45 @@ await escrow.verify(escrowId);
204
204
 
205
205
  Premium access: [github.com/up2itnow/AgentNexus2](https://github.com/up2itnow/AgentNexus2)
206
206
 
207
+ ## x402 Protocol: Supported Chains and Payment Rails
208
+
209
+ x402 (HTTP 402 Payment Required) is the native payment protocol for agent-to-service transactions. The agent encounters a 402 response, signs a payment proof, and re-sends the request. One round trip. No accounts, no API keys, no invoices.
210
+
211
+ As of March 2026, x402 is live on 3 chains/rails:
212
+
213
+ | Chain / Rail | Status | Settlement Token | Gas Cost | Notes |
214
+ |---|---|---|---|---|
215
+ | **Base** (Coinbase L2) | Live | USDC | Sub-cent | Primary x402 chain. 15M+ transactions in Jan 2026. |
216
+ | **Etherlink** (Tezos L2) | Live (Mar 2026) | USDC | Sub-cent | EVM-compatible. Same x402 integration, different RPC + chain ID. |
217
+ | **Stripe** (Fiat offramp) | Live (Feb 2026) | USDC -> USD | N/A | Vendors receive USD in Stripe dashboard. Agents pay USDC. |
218
+
219
+ ### x402 + Etherlink Quick Start
220
+
221
+ ```typescript
222
+ import { createWallet, agentExecute } from 'agentwallet-sdk';
223
+
224
+ const wallet = createWallet({
225
+ accountAddress: '0xYourAgent',
226
+ chain: 'etherlink', // new: Tezos L2 support
227
+ walletClient,
228
+ });
229
+
230
+ // x402 payment flow is identical across chains
231
+ const response = await fetch('https://api.vendor.com/data');
232
+ if (response.status === 402) {
233
+ const details = await response.json();
234
+ const proof = await wallet.createX402Proof(details);
235
+ const paid = await fetch('https://api.vendor.com/data', {
236
+ headers: { 'X-Payment': proof }
237
+ });
238
+ }
239
+ ```
240
+
241
+ The SDK handles chain-specific RPC endpoints, gas estimation, and USDC contract addresses automatically. Swap `chain: 'base'` to `chain: 'etherlink'` and the x402 flow works identically.
242
+
207
243
  ## Supported Chains
208
244
 
209
- Mainnet: Ethereum, Base, Arbitrum, Polygon, Optimism, Avalanche, BSC, Celo, Gnosis, Linea, Mantle, Scroll, and more.
245
+ Mainnet: Ethereum, Base, Arbitrum, Polygon, Optimism, Avalanche, BSC, Celo, Gnosis, Linea, Mantle, Scroll, Etherlink, and more.
210
246
 
211
247
  Testnet: Base Sepolia, Arbitrum Sepolia, and corresponding testnets.
212
248
 
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Mastercard Verifiable Intent module for agentwallet-sdk.
3
+ * @module verifiable-intent
4
+ */
5
+
6
+ export interface AgentIdentity {
7
+ agentId: string;
8
+ principalId: string;
9
+ agenticToken: string;
10
+ issuedAt: number;
11
+ expiresAt: number;
12
+ }
13
+
14
+ export interface ScopeConstraints {
15
+ maxAmountPerTx: number;
16
+ maxAmountPerDay: number;
17
+ maxTxPerDay: number;
18
+ allowedMerchantCategories?: string[];
19
+ allowedCurrencies?: string[];
20
+ windowStartUtc?: number;
21
+ windowEndUtc?: number;
22
+ }
23
+
24
+ export interface IntentDeclaration {
25
+ intentId: string;
26
+ agentId: string;
27
+ action: 'pay' | 'subscribe' | 'escrow' | 'refund';
28
+ amount: number;
29
+ currency: string;
30
+ recipientId: string;
31
+ description: string;
32
+ createdAt: number;
33
+ expiresAt: number;
34
+ metadata?: Record<string, unknown>;
35
+ }
36
+
37
+ export interface SignedIntent {
38
+ intent: IntentDeclaration;
39
+ signature: string;
40
+ agenticToken: string;
41
+ signatureAlgorithm: string;
42
+ }
43
+
44
+ export interface VerificationResult {
45
+ valid: boolean;
46
+ errors: string[];
47
+ }
48
+
49
+ export interface VerifiableIntentConfig {
50
+ agentId: string;
51
+ principalId: string;
52
+ signingSecret: string;
53
+ scope: ScopeConstraints;
54
+ tokenTtlSeconds?: number;
55
+ intentTtlSeconds?: number;
56
+ }
57
+
58
+ export declare class VerifiableIntentClient {
59
+ identity: AgentIdentity;
60
+ constructor(config: VerifiableIntentConfig);
61
+ createIntent(params: {
62
+ action: 'pay' | 'subscribe' | 'escrow' | 'refund';
63
+ amount: number;
64
+ currency: string;
65
+ recipientId: string;
66
+ description: string;
67
+ metadata?: Record<string, unknown>;
68
+ }): SignedIntent;
69
+ verify(signedIntent: SignedIntent): VerificationResult;
70
+ recordExecution(signedIntent: SignedIntent): void;
71
+ getDailyUsage(): {
72
+ spentToday: number;
73
+ txToday: number;
74
+ remainingBudget: number;
75
+ remainingTx: number;
76
+ };
77
+ static serialize(signedIntent: SignedIntent): string;
78
+ static deserialize(json: string): SignedIntent;
79
+ }
80
+
81
+ export declare class VerifiableIntentError extends Error {
82
+ context?: unknown;
83
+ constructor(message: string, context?: unknown);
84
+ }
@@ -0,0 +1,385 @@
1
+ /**
2
+ * VerifiableIntent — Mastercard Verifiable Intent implementation for agentwallet-sdk
3
+ *
4
+ * Implements the Mastercard Verifiable Intent open standard (March 2026):
5
+ * - Create signed intent declarations for agent transactions
6
+ * - Verify intent signatures and scope constraints
7
+ * - Enforce spending caps, time windows, and merchant category limits
8
+ * - Compatible with Google AP2 (Agent Payments Protocol)
9
+ *
10
+ * The spec defines four pillars:
11
+ * 1. Agent Identity — unique Agentic Token per agent
12
+ * 2. Intent Declaration — structured payload describing the transaction
13
+ * 3. Authorization Chain — proof of human/system delegation
14
+ * 4. Scope Limits — spending caps, time windows, merchant categories
15
+ *
16
+ * @module verifiable-intent
17
+ */
18
+
19
+ import { createHash, createHmac, randomUUID } from 'crypto';
20
+
21
+ // ---------------------------------------------------------------------------
22
+ // Types
23
+ // ---------------------------------------------------------------------------
24
+
25
+ /**
26
+ * @typedef {Object} AgentIdentity
27
+ * @property {string} agentId - Unique agent identifier (UUID or DID)
28
+ * @property {string} principalId - Human/system that delegated authority
29
+ * @property {string} agenticToken - Signed token proving agent registration
30
+ * @property {number} issuedAt - Unix timestamp of token issuance
31
+ * @property {number} expiresAt - Unix timestamp of token expiry
32
+ */
33
+
34
+ /**
35
+ * @typedef {Object} ScopeConstraints
36
+ * @property {number} maxAmountPerTx - Maximum amount per single transaction (in minor units)
37
+ * @property {number} maxAmountPerDay - Maximum cumulative daily spend (in minor units)
38
+ * @property {number} maxTxPerDay - Maximum number of transactions per day
39
+ * @property {string[]} [allowedMerchantCategories] - MCC codes the agent can transact with
40
+ * @property {string[]} [allowedCurrencies] - ISO 4217 currency codes permitted
41
+ * @property {number} [windowStartUtc] - Unix timestamp: scope validity start
42
+ * @property {number} [windowEndUtc] - Unix timestamp: scope validity end
43
+ */
44
+
45
+ /**
46
+ * @typedef {Object} IntentDeclaration
47
+ * @property {string} intentId - Unique ID for this intent (UUID v4)
48
+ * @property {string} agentId - Agent making the request
49
+ * @property {string} action - What the agent wants to do ('pay', 'subscribe', 'escrow', 'refund')
50
+ * @property {number} amount - Transaction amount in minor units
51
+ * @property {string} currency - ISO 4217 currency code
52
+ * @property {string} recipientId - Merchant/service/agent receiving payment
53
+ * @property {string} description - Human-readable purpose
54
+ * @property {number} createdAt - Unix timestamp
55
+ * @property {number} expiresAt - Unix timestamp when intent becomes invalid
56
+ * @property {Object} [metadata] - Additional key-value pairs
57
+ */
58
+
59
+ /**
60
+ * @typedef {Object} SignedIntent
61
+ * @property {IntentDeclaration} intent - The intent payload
62
+ * @property {string} signature - HMAC-SHA256 signature of the canonical intent
63
+ * @property {string} agenticToken - The agent's identity token
64
+ * @property {string} signatureAlgorithm - Always 'HMAC-SHA256' in this implementation
65
+ */
66
+
67
+ /**
68
+ * @typedef {Object} VerificationResult
69
+ * @property {boolean} valid - Whether the intent passes all checks
70
+ * @property {string[]} errors - List of validation failures (empty if valid)
71
+ */
72
+
73
+ // ---------------------------------------------------------------------------
74
+ // Core Implementation
75
+ // ---------------------------------------------------------------------------
76
+
77
+ /**
78
+ * VerifiableIntentClient — Create, sign, and verify Mastercard Verifiable Intent payloads.
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * const vi = new VerifiableIntentClient({
83
+ * agentId: 'agent-001',
84
+ * principalId: 'user-bill',
85
+ * signingSecret: process.env.AGENT_SIGNING_SECRET,
86
+ * scope: {
87
+ * maxAmountPerTx: 10000, // $100.00
88
+ * maxAmountPerDay: 50000, // $500.00
89
+ * maxTxPerDay: 20,
90
+ * allowedCurrencies: ['USD', 'EUR'],
91
+ * }
92
+ * });
93
+ *
94
+ * const signed = vi.createIntent({
95
+ * action: 'pay',
96
+ * amount: 5000,
97
+ * currency: 'USD',
98
+ * recipientId: 'merchant-xyz',
99
+ * description: 'API compute credits',
100
+ * });
101
+ *
102
+ * const result = vi.verify(signed);
103
+ * // { valid: true, errors: [] }
104
+ * ```
105
+ */
106
+ export class VerifiableIntentClient {
107
+ /**
108
+ * @param {Object} config
109
+ * @param {string} config.agentId - Unique agent identifier
110
+ * @param {string} config.principalId - Human/system principal who delegated authority
111
+ * @param {string} config.signingSecret - Secret key for HMAC signing (min 32 chars)
112
+ * @param {ScopeConstraints} config.scope - Spending and authorization constraints
113
+ * @param {number} [config.tokenTtlSeconds=86400] - Agentic token lifetime (default 24h)
114
+ * @param {number} [config.intentTtlSeconds=300] - Intent validity window (default 5 min)
115
+ */
116
+ constructor(config) {
117
+ if (!config.signingSecret || config.signingSecret.length < 32) {
118
+ throw new VerifiableIntentError('signingSecret must be at least 32 characters');
119
+ }
120
+ this.agentId = config.agentId;
121
+ this.principalId = config.principalId;
122
+ this.signingSecret = config.signingSecret;
123
+ this.scope = config.scope;
124
+ this.tokenTtlSeconds = config.tokenTtlSeconds ?? 86400;
125
+ this.intentTtlSeconds = config.intentTtlSeconds ?? 300;
126
+
127
+ // Daily tracking for scope enforcement
128
+ this._dailySpend = 0;
129
+ this._dailyTxCount = 0;
130
+ this._dailyResetDate = this._todayUtc();
131
+
132
+ // Generate agentic token on initialization
133
+ this.identity = this._issueAgenticToken();
134
+ }
135
+
136
+ /**
137
+ * Create and sign a Verifiable Intent declaration.
138
+ *
139
+ * @param {Object} params
140
+ * @param {string} params.action - 'pay' | 'subscribe' | 'escrow' | 'refund'
141
+ * @param {number} params.amount - Amount in minor units (cents)
142
+ * @param {string} params.currency - ISO 4217 currency code
143
+ * @param {string} params.recipientId - Recipient identifier
144
+ * @param {string} params.description - Human-readable purpose
145
+ * @param {Object} [params.metadata] - Additional context
146
+ * @returns {SignedIntent}
147
+ */
148
+ createIntent(params) {
149
+ const now = Math.floor(Date.now() / 1000);
150
+
151
+ // Check token validity
152
+ if (now >= this.identity.expiresAt) {
153
+ this.identity = this._issueAgenticToken();
154
+ }
155
+
156
+ const intent = {
157
+ intentId: randomUUID(),
158
+ agentId: this.agentId,
159
+ action: params.action,
160
+ amount: params.amount,
161
+ currency: params.currency,
162
+ recipientId: params.recipientId,
163
+ description: params.description,
164
+ createdAt: now,
165
+ expiresAt: now + this.intentTtlSeconds,
166
+ metadata: params.metadata ?? {},
167
+ };
168
+
169
+ // Pre-sign scope validation
170
+ const scopeCheck = this._checkScope(intent);
171
+ if (!scopeCheck.valid) {
172
+ throw new VerifiableIntentError(
173
+ `Intent blocked by scope constraints: ${scopeCheck.errors.join(', ')}`
174
+ );
175
+ }
176
+
177
+ const canonical = this._canonicalize(intent);
178
+ const signature = this._sign(canonical);
179
+
180
+ return {
181
+ intent,
182
+ signature,
183
+ agenticToken: this.identity.agenticToken,
184
+ signatureAlgorithm: 'HMAC-SHA256',
185
+ };
186
+ }
187
+
188
+ /**
189
+ * Verify a signed intent declaration.
190
+ *
191
+ * Checks:
192
+ * 1. Signature validity (HMAC-SHA256)
193
+ * 2. Intent not expired
194
+ * 3. Agent identity matches
195
+ * 4. Scope constraints satisfied
196
+ *
197
+ * @param {SignedIntent} signedIntent
198
+ * @returns {VerificationResult}
199
+ */
200
+ verify(signedIntent) {
201
+ const errors = [];
202
+ const { intent, signature, agenticToken } = signedIntent;
203
+ const now = Math.floor(Date.now() / 1000);
204
+
205
+ // 1. Signature check
206
+ const canonical = this._canonicalize(intent);
207
+ const expectedSig = this._sign(canonical);
208
+ if (signature !== expectedSig) {
209
+ errors.push('Invalid signature');
210
+ }
211
+
212
+ // 2. Expiry check
213
+ if (now >= intent.expiresAt) {
214
+ errors.push(`Intent expired at ${new Date(intent.expiresAt * 1000).toISOString()}`);
215
+ }
216
+
217
+ // 3. Agent identity check
218
+ if (intent.agentId !== this.agentId) {
219
+ errors.push(`Agent ID mismatch: expected ${this.agentId}, got ${intent.agentId}`);
220
+ }
221
+
222
+ // 4. Agentic token check
223
+ if (agenticToken !== this.identity.agenticToken) {
224
+ errors.push('Agentic token mismatch or expired');
225
+ }
226
+
227
+ // 5. Scope constraints
228
+ const scopeResult = this._checkScope(intent);
229
+ errors.push(...scopeResult.errors);
230
+
231
+ return { valid: errors.length === 0, errors };
232
+ }
233
+
234
+ /**
235
+ * Record a completed transaction against daily limits.
236
+ * Call this after a verified intent is successfully executed.
237
+ *
238
+ * @param {SignedIntent} signedIntent - The executed intent
239
+ */
240
+ recordExecution(signedIntent) {
241
+ this._resetDailyIfNeeded();
242
+ this._dailySpend += signedIntent.intent.amount;
243
+ this._dailyTxCount += 1;
244
+ }
245
+
246
+ /**
247
+ * Get current daily usage against scope limits.
248
+ *
249
+ * @returns {{ spentToday: number, txToday: number, remainingBudget: number, remainingTx: number }}
250
+ */
251
+ getDailyUsage() {
252
+ this._resetDailyIfNeeded();
253
+ return {
254
+ spentToday: this._dailySpend,
255
+ txToday: this._dailyTxCount,
256
+ remainingBudget: Math.max(0, this.scope.maxAmountPerDay - this._dailySpend),
257
+ remainingTx: Math.max(0, this.scope.maxTxPerDay - this._dailyTxCount),
258
+ };
259
+ }
260
+
261
+ /**
262
+ * Serialize a signed intent to a portable JSON string for transmission.
263
+ *
264
+ * @param {SignedIntent} signedIntent
265
+ * @returns {string} JSON string
266
+ */
267
+ static serialize(signedIntent) {
268
+ return JSON.stringify(signedIntent);
269
+ }
270
+
271
+ /**
272
+ * Deserialize a JSON string back to a SignedIntent object.
273
+ *
274
+ * @param {string} json
275
+ * @returns {SignedIntent}
276
+ */
277
+ static deserialize(json) {
278
+ const parsed = JSON.parse(json);
279
+ if (!parsed.intent || !parsed.signature || !parsed.agenticToken) {
280
+ throw new VerifiableIntentError('Invalid SignedIntent structure');
281
+ }
282
+ return parsed;
283
+ }
284
+
285
+ // -------------------------------------------------------------------------
286
+ // Private methods
287
+ // -------------------------------------------------------------------------
288
+
289
+ _issueAgenticToken() {
290
+ const now = Math.floor(Date.now() / 1000);
291
+ const payload = `${this.agentId}:${this.principalId}:${now}`;
292
+ const token = createHmac('sha256', this.signingSecret)
293
+ .update(payload)
294
+ .digest('hex');
295
+ return {
296
+ agentId: this.agentId,
297
+ principalId: this.principalId,
298
+ agenticToken: token,
299
+ issuedAt: now,
300
+ expiresAt: now + this.tokenTtlSeconds,
301
+ };
302
+ }
303
+
304
+ _canonicalize(intent) {
305
+ // Deterministic JSON serialization: sorted keys, no whitespace
306
+ const ordered = {
307
+ action: intent.action,
308
+ agentId: intent.agentId,
309
+ amount: intent.amount,
310
+ createdAt: intent.createdAt,
311
+ currency: intent.currency,
312
+ description: intent.description,
313
+ expiresAt: intent.expiresAt,
314
+ intentId: intent.intentId,
315
+ metadata: intent.metadata,
316
+ recipientId: intent.recipientId,
317
+ };
318
+ return JSON.stringify(ordered);
319
+ }
320
+
321
+ _sign(canonical) {
322
+ return createHmac('sha256', this.signingSecret)
323
+ .update(canonical)
324
+ .digest('hex');
325
+ }
326
+
327
+ _checkScope(intent) {
328
+ const errors = [];
329
+ this._resetDailyIfNeeded();
330
+
331
+ if (intent.amount > this.scope.maxAmountPerTx) {
332
+ errors.push(`Amount ${intent.amount} exceeds per-tx limit ${this.scope.maxAmountPerTx}`);
333
+ }
334
+
335
+ if (this._dailySpend + intent.amount > this.scope.maxAmountPerDay) {
336
+ errors.push(
337
+ `Daily spend would be ${this._dailySpend + intent.amount}, exceeds limit ${this.scope.maxAmountPerDay}`
338
+ );
339
+ }
340
+
341
+ if (this._dailyTxCount + 1 > this.scope.maxTxPerDay) {
342
+ errors.push(`Daily tx count would exceed limit ${this.scope.maxTxPerDay}`);
343
+ }
344
+
345
+ if (this.scope.allowedCurrencies && !this.scope.allowedCurrencies.includes(intent.currency)) {
346
+ errors.push(`Currency ${intent.currency} not in allowed list: ${this.scope.allowedCurrencies.join(', ')}`);
347
+ }
348
+
349
+ const now = Math.floor(Date.now() / 1000);
350
+ if (this.scope.windowStartUtc && now < this.scope.windowStartUtc) {
351
+ errors.push('Current time is before scope validity window');
352
+ }
353
+ if (this.scope.windowEndUtc && now >= this.scope.windowEndUtc) {
354
+ errors.push('Current time is past scope validity window');
355
+ }
356
+
357
+ return { valid: errors.length === 0, errors };
358
+ }
359
+
360
+ _todayUtc() {
361
+ return new Date().toISOString().slice(0, 10);
362
+ }
363
+
364
+ _resetDailyIfNeeded() {
365
+ const today = this._todayUtc();
366
+ if (today !== this._dailyResetDate) {
367
+ this._dailySpend = 0;
368
+ this._dailyTxCount = 0;
369
+ this._dailyResetDate = today;
370
+ }
371
+ }
372
+ }
373
+
374
+ // ---------------------------------------------------------------------------
375
+ // Error class
376
+ // ---------------------------------------------------------------------------
377
+
378
+ export class VerifiableIntentError extends Error {
379
+ constructor(message, context) {
380
+ super(message);
381
+ this.context = context;
382
+ this.name = 'VerifiableIntentError';
383
+ }
384
+ }
385
+ //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentwallet-sdk",
3
- "version": "5.0.2",
3
+ "version": "5.0.3",
4
4
  "description": "Non-custodial AI agent wallet SDK. ERC-8004 identity & reputation registries, mutual stake escrow, x402 payments, 17-chain CCTP bridging, ERC-6551 TBA, SpendingPolicy guardrails, Uniswap V3 swap. The agent holds the keys.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -48,4 +48,4 @@
48
48
  "typescript": "5.3.3",
49
49
  "vitest": "4.0.18"
50
50
  }
51
- }
51
+ }