@mixrpay/agent-sdk 0.1.1 β†’ 0.3.0

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
@@ -1,6 +1,6 @@
1
1
  # MixrPay Agent SDK for JavaScript/TypeScript
2
2
 
3
- Enable AI agents to make autonomous payments using x402 protocol with session keys.
3
+ Enable AI agents to make autonomous payments. Supports both session-based payments (for MixrPay merchants) and x402 protocol (for external APIs).
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@mixrpay/agent-sdk)](https://www.npmjs.com/package/@mixrpay/agent-sdk)
6
6
  [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue)](https://www.typescriptlang.org/)
@@ -10,20 +10,20 @@ Enable AI agents to make autonomous payments using x402 protocol with session ke
10
10
  ```typescript
11
11
  import { AgentWallet } from '@mixrpay/agent-sdk';
12
12
 
13
- // 1. Initialize with a session key (get this from the wallet owner)
14
13
  const wallet = new AgentWallet({
15
- sessionKey: 'sk_live_...'
14
+ sessionKey: 'sk_live_...' // Get from wallet owner
16
15
  });
17
16
 
18
- // 2. Make requests - payments are handled automatically!
19
- const response = await wallet.fetch('https://api.paid-service.com/query', {
20
- method: 'POST',
21
- headers: { 'Content-Type': 'application/json' },
22
- body: JSON.stringify({ prompt: 'Hello world' })
17
+ // For MixrPay merchants (recommended):
18
+ const response = await wallet.callMerchantApi({
19
+ url: 'https://api.merchant.com/generate',
20
+ merchantPublicKey: 'pk_live_abc123',
21
+ priceUsd: 0.05,
22
+ body: { prompt: 'Hello world' }
23
23
  });
24
24
 
25
- // 3. Use the response just like regular fetch
26
- console.log(await response.json());
25
+ // For external x402 APIs:
26
+ const response = await wallet.fetch('https://external-api.com/query');
27
27
  ```
28
28
 
29
29
  ## πŸ“¦ Installation
@@ -36,52 +36,57 @@ yarn add @mixrpay/agent-sdk
36
36
  pnpm add @mixrpay/agent-sdk
37
37
  ```
38
38
 
39
- ## πŸ”§ Configuration
39
+ ## Two Payment Methods
40
+
41
+ The Agent SDK supports **two payment patterns** depending on what API you're calling:
42
+
43
+ ### 1. Session-Based Payments (For MixrPay Merchants) ⭐ Recommended
40
44
 
41
- By default, the SDK connects to `https://mixrpay.com`. For local development, set your MixrPay server URL:
45
+ Use `callMerchantApi()` when the API uses MixrPay:
42
46
 
43
47
  ```typescript
44
- const wallet = new AgentWallet({
45
- sessionKey: 'sk_live_...',
46
- baseUrl: 'https://your-mixrpay-server.com', // Your MixrPay deployment
48
+ const response = await wallet.callMerchantApi({
49
+ url: 'https://api.merchant.com/generate',
50
+ merchantPublicKey: 'pk_live_abc123', // Merchant's MixrPay public key
51
+ priceUsd: 0.05,
52
+ method: 'POST',
53
+ body: { prompt: 'Hello world' },
47
54
  });
48
-
49
- // Or use environment variable: MIXRPAY_BASE_URL
50
55
  ```
51
56
 
52
- ## βœ… Verify Installation
57
+ **How it works:**
58
+ 1. SDK creates/reuses a session authorization with the merchant
59
+ 2. SDK charges against the session
60
+ 3. Request is sent with `X-Mixr-Session` header
61
+ 4. No 402 round-trip neededβ€”faster and cheaper
53
62
 
54
- Run this quick test to ensure the SDK is installed correctly:
63
+ **When to use:** APIs built with MixrPay, or any API that accepts `X-Mixr-Session` headers.
55
64
 
56
- ```typescript
57
- import { AgentWallet, SDK_VERSION } from '@mixrpay/agent-sdk';
65
+ ### 2. x402 Protocol (For External APIs)
58
66
 
59
- // Check SDK version
60
- console.log(`MixrPay Agent SDK v${SDK_VERSION}`);
67
+ Use `fetch()` when calling APIs that implement x402 but aren't MixrPay merchants:
61
68
 
62
- // Create a wallet instance (will validate session key format)
63
- try {
64
- const wallet = new AgentWallet({
65
- sessionKey: 'sk_test_0000000000000000000000000000000000000000000000000000000000000000',
66
- baseUrl: 'http://localhost:3000',
67
- });
68
- console.log('βœ“ SDK initialized successfully');
69
-
70
- // Check connection (will fail without a running server, but validates setup)
71
- wallet.getBalance().catch(() => {
72
- console.log('βœ“ SDK configured (server not running - expected in test)');
73
- });
74
- } catch (error) {
75
- console.error('βœ— SDK initialization failed:', error);
76
- }
69
+ ```typescript
70
+ const response = await wallet.fetch('https://external-api.com/query', {
71
+ method: 'POST',
72
+ body: JSON.stringify({ prompt: 'Hello' })
73
+ });
77
74
  ```
78
75
 
76
+ **How it works:**
77
+ 1. SDK makes initial request
78
+ 2. API returns `402 Payment Required`
79
+ 3. SDK signs payment authorization
80
+ 4. SDK retries with `X-PAYMENT` header
81
+
82
+ **When to use:** External APIs that use standard x402 protocol.
83
+
79
84
  ## πŸ”‘ Getting Session Keys
80
85
 
81
86
  Session keys are created by wallet owners and grant spending permissions to agents:
82
87
 
83
- 1. **From a wallet owner**: They create a session key at your MixrPay server's `/wallet/sessions` page
84
- 2. **Programmatically**: Via the MixrPay API (for applications managing their own wallets)
88
+ 1. **From a wallet owner**: They create a session key at `/wallet/sessions`
89
+ 2. **Programmatically**: Via the MixrPay API
85
90
 
86
91
  Session keys look like: `sk_live_abc123...` (mainnet) or `sk_test_abc123...` (testnet)
87
92
 
@@ -93,58 +98,76 @@ Each session key has configurable spending limits:
93
98
  - **Total**: Maximum lifetime spend
94
99
  - **Expiration**: When the key becomes invalid
95
100
 
96
- ## πŸ’‘ How It Works
101
+ ## πŸ“– Session Management
97
102
 
98
- ```
99
- β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
100
- β”‚ Agent │────▢│ Paid API │────▢│ Facilitator β”‚
101
- β”‚ (you) │◀────│ (402) │◀────│ (x402) β”‚
102
- β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
103
- β”‚ β”‚ β”‚
104
- β”‚ 1. Request β”‚ β”‚
105
- β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Άβ”‚ β”‚
106
- β”‚ β”‚ β”‚
107
- β”‚ 2. 402 + price β”‚ β”‚
108
- │◀─────────────────── β”‚
109
- β”‚ β”‚ β”‚
110
- β”‚ 3. Sign payment β”‚ β”‚
111
- β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Άβ”‚ β”‚
112
- β”‚ β”‚ 4. Process β”‚
113
- β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Άβ”‚
114
- β”‚ β”‚ β”‚
115
- β”‚ 5. Response β”‚ 5. Confirm β”‚
116
- │◀───────────────────◀───────────────────
117
- β”‚ β”‚ β”‚
118
- ```
103
+ ### Automatic (Recommended)
119
104
 
120
- 1. Your agent makes a request to a paid API
121
- 2. The server returns `402 Payment Required` with pricing
122
- 3. The SDK automatically signs a USDC transfer authorization
123
- 4. The facilitator processes the payment
124
- 5. You receive the API response
105
+ `callMerchantApi()` handles sessions automatically:
125
106
 
126
- ## πŸ“– Usage Examples
107
+ ```typescript
108
+ // Sessions are created and reused automatically
109
+ const response = await wallet.callMerchantApi({
110
+ url: 'https://api.merchant.com/generate',
111
+ merchantPublicKey: 'pk_live_abc123',
112
+ priceUsd: 0.05,
113
+ body: { prompt: 'Hello' }
114
+ });
115
+ ```
127
116
 
128
- ### Basic Request
117
+ ### Manual Control
129
118
 
130
- ```typescript
131
- import { AgentWallet } from '@mixrpay/agent-sdk';
119
+ For fine-grained control over sessions:
132
120
 
133
- const wallet = new AgentWallet({
134
- sessionKey: process.env.MIXRPAY_SESSION_KEY!,
121
+ ```typescript
122
+ // Get or create a session
123
+ const session = await wallet.getOrCreateSession({
124
+ merchantPublicKey: 'pk_live_abc123',
125
+ spendingLimitUsd: 25, // Max total spending
126
+ durationDays: 7, // Session validity
135
127
  });
136
128
 
137
- // GET request
138
- const response = await wallet.fetch('https://api.example.com/data');
129
+ console.log('Session ID:', session.id);
130
+ console.log('Remaining:', session.remainingLimitUsd);
131
+ console.log('Expires:', session.expiresAt);
139
132
 
140
- // POST request with JSON
141
- const result = await wallet.fetch('https://api.example.com/generate', {
133
+ // Charge manually
134
+ const charge = await wallet.chargeSession(session.id, 0.05, {
135
+ feature: 'generate',
136
+ idempotencyKey: `charge-${Date.now()}`,
137
+ });
138
+
139
+ // Then make your API call with the session
140
+ const response = await fetch('https://api.merchant.com/generate', {
142
141
  method: 'POST',
143
- headers: { 'Content-Type': 'application/json' },
144
- body: JSON.stringify({ prompt: 'Write a poem' })
142
+ headers: {
143
+ 'Content-Type': 'application/json',
144
+ 'X-Mixr-Session': session.id,
145
+ 'X-Mixr-Charged': 'true', // Tell merchant payment is done
146
+ },
147
+ body: JSON.stringify({ prompt: 'Hello' }),
145
148
  });
146
149
  ```
147
150
 
151
+ ### List and Revoke Sessions
152
+
153
+ ```typescript
154
+ // List all active sessions
155
+ const sessions = await wallet.listSessions();
156
+ for (const session of sessions) {
157
+ console.log(`${session.merchantName}: $${session.remainingLimitUsd} remaining`);
158
+ }
159
+
160
+ // Revoke a session (e.g., when done with a merchant)
161
+ await wallet.revokeSession(session.id);
162
+
163
+ // Get session statistics
164
+ const stats = await wallet.getSessionStats();
165
+ console.log(`Active sessions: ${stats.activeCount}`);
166
+ console.log(`Total authorized: $${stats.totalAuthorizedUsd}`);
167
+ ```
168
+
169
+ ## πŸ’‘ Usage Examples
170
+
148
171
  ### With Payment Tracking
149
172
 
150
173
  ```typescript
@@ -154,21 +177,16 @@ const wallet = new AgentWallet({
154
177
  sessionKey: 'sk_live_...',
155
178
  onPayment: (payment: PaymentEvent) => {
156
179
  console.log(`πŸ’Έ Paid $${payment.amountUsd.toFixed(4)} to ${payment.recipient}`);
157
- console.log(` For: ${payment.description || 'API call'}`);
158
180
  },
159
181
  });
160
182
 
161
183
  // Make requests
162
- for (let i = 0; i < 5; i++) {
163
- await wallet.fetch(`https://api.example.com/query/${i}`);
164
- }
184
+ const response = await wallet.callMerchantApi({ ... });
165
185
 
166
186
  // Check spending
167
187
  const stats = await wallet.getSpendingStats();
168
- console.log(`\nπŸ“Š Session Summary:`);
169
- console.log(` Total spent: $${stats.totalSpentUsd.toFixed(2)}`);
170
- console.log(` Transactions: ${stats.txCount}`);
171
- console.log(` Remaining daily: $${stats.remainingDailyUsd?.toFixed(2) ?? 'unlimited'}`);
188
+ console.log(`Total spent: $${stats.totalSpentUsd.toFixed(2)}`);
189
+ console.log(`Transactions: ${stats.txCount}`);
172
190
  ```
173
191
 
174
192
  ### Error Handling
@@ -179,25 +197,35 @@ import {
179
197
  InsufficientBalanceError,
180
198
  SpendingLimitExceededError,
181
199
  SessionKeyExpiredError,
200
+ // Session Authorization Errors
201
+ SessionExpiredError,
202
+ SessionLimitExceededError,
203
+ SessionNotFoundError,
204
+ SessionRevokedError,
182
205
  } from '@mixrpay/agent-sdk';
183
206
 
184
207
  const wallet = new AgentWallet({ sessionKey: 'sk_live_...' });
185
208
 
186
209
  try {
187
- const response = await wallet.fetch('https://api.example.com/expensive');
188
- console.log(await response.json());
210
+ const response = await wallet.callMerchantApi({ ... });
189
211
  } catch (error) {
190
212
  if (error instanceof InsufficientBalanceError) {
191
213
  console.log(`❌ Not enough funds: need $${error.required}, have $${error.available}`);
192
214
  console.log(` Top up at: ${error.topUpUrl}`);
215
+ } else if (error instanceof SessionExpiredError) {
216
+ console.log(`❌ Session ${error.sessionId} expired`);
217
+ // SDK will auto-create on next callMerchantApi()
218
+ } else if (error instanceof SessionLimitExceededError) {
219
+ console.log(`❌ Session limit exceeded`);
220
+ console.log(` Limit: $${error.limit}, Requested: $${error.requested}, Remaining: $${error.remaining}`);
221
+ } else if (error instanceof SessionNotFoundError) {
222
+ console.log(`❌ Session ${error.sessionId} not found`);
223
+ } else if (error instanceof SessionRevokedError) {
224
+ console.log(`❌ Session ${error.sessionId} was revoked: ${error.reason || 'no reason given'}`);
193
225
  } else if (error instanceof SpendingLimitExceededError) {
194
- console.log(`❌ Limit exceeded: ${error.limitType} limit is $${error.limit}`);
195
- if (error.limitType === 'daily') {
196
- console.log(' Try again tomorrow, or request a higher limit.');
197
- }
226
+ console.log(`❌ Session key limit exceeded: ${error.limitType}`);
198
227
  } else if (error instanceof SessionKeyExpiredError) {
199
228
  console.log(`❌ Session key expired at ${error.expiredAt}`);
200
- console.log(' Request a new key from the wallet owner.');
201
229
  } else {
202
230
  throw error;
203
231
  }
@@ -227,28 +255,6 @@ const wallet = new AgentWallet({
227
255
 
228
256
  // Or toggle at runtime
229
257
  wallet.setDebug(true);
230
- await wallet.fetch('https://api.example.com/endpoint');
231
- wallet.setDebug(false);
232
- ```
233
-
234
- ### Diagnostics
235
-
236
- ```typescript
237
- const wallet = new AgentWallet({ sessionKey: 'sk_live_...' });
238
-
239
- // Run health checks
240
- const diagnostics = await wallet.runDiagnostics();
241
-
242
- if (diagnostics.healthy) {
243
- console.log('βœ… Wallet is ready to use');
244
- console.log(` Network: ${diagnostics.network}`);
245
- console.log(` Wallet: ${diagnostics.walletAddress}`);
246
- } else {
247
- console.log('❌ Issues found:');
248
- for (const issue of diagnostics.issues) {
249
- console.log(` - ${issue}`);
250
- }
251
- }
252
258
  ```
253
259
 
254
260
  ## πŸ€– AI Framework Integrations
@@ -256,15 +262,14 @@ if (diagnostics.healthy) {
256
262
  ### Vercel AI SDK
257
263
 
258
264
  ```typescript
259
- import { AgentWallet, InsufficientBalanceError, SpendingLimitExceededError } from '@mixrpay/agent-sdk';
265
+ import { AgentWallet, SessionLimitExceededError } from '@mixrpay/agent-sdk';
260
266
  import { generateText } from 'ai';
261
267
  import { openai } from '@ai-sdk/openai';
262
268
  import { z } from 'zod';
263
269
 
264
270
  const wallet = new AgentWallet({
265
271
  sessionKey: process.env.MIXRPAY_SESSION_KEY!,
266
- maxPaymentUsd: 1.00, // Safety limit per request
267
- onPayment: (p) => console.log(`Paid $${p.amountUsd} for API call`),
272
+ maxPaymentUsd: 1.00,
268
273
  });
269
274
 
270
275
  const result = await generateText({
@@ -275,25 +280,23 @@ const result = await generateText({
275
280
  parameters: z.object({ query: z.string() }),
276
281
  execute: async ({ query }) => {
277
282
  try {
278
- const response = await wallet.fetch('https://api.search.com/query', {
279
- method: 'POST',
280
- headers: { 'Content-Type': 'application/json' },
281
- body: JSON.stringify({ query })
283
+ const response = await wallet.callMerchantApi({
284
+ url: 'https://api.search.com/query',
285
+ merchantPublicKey: 'pk_live_...',
286
+ priceUsd: 0.05,
287
+ body: { query }
282
288
  });
283
289
  return response.json();
284
290
  } catch (error) {
285
- if (error instanceof InsufficientBalanceError) {
286
- return { error: 'Insufficient funds', topUpUrl: error.topUpUrl };
291
+ if (error instanceof SessionLimitExceededError) {
292
+ return { error: 'Budget exceeded', limit: error.limitType };
287
293
  }
288
- if (error instanceof SpendingLimitExceededError) {
289
- return { error: 'Spending limit reached', limit: error.limitType };
290
- }
291
- throw error; // Re-throw unexpected errors
294
+ throw error;
292
295
  }
293
296
  }
294
297
  }
295
298
  },
296
- prompt: 'Search for the latest AI news and summarize it'
299
+ prompt: 'Search for the latest AI news'
297
300
  });
298
301
  ```
299
302
 
@@ -305,33 +308,30 @@ import { DynamicTool } from '@langchain/core/tools';
305
308
 
306
309
  const wallet = new AgentWallet({
307
310
  sessionKey: process.env.MIXRPAY_SESSION_KEY!,
308
- maxPaymentUsd: 0.50, // Cap per tool invocation
311
+ maxPaymentUsd: 0.50,
309
312
  });
310
313
 
311
314
  const paidSearchTool = new DynamicTool({
312
315
  name: 'paid_search',
313
- description: 'Premium search API ($0.05/query) - use for high-quality results',
316
+ description: 'Premium search API ($0.05/query)',
314
317
  func: async (query: string) => {
315
318
  try {
316
- const response = await wallet.fetch('https://api.search.com/query', {
317
- method: 'POST',
318
- headers: { 'Content-Type': 'application/json' },
319
- body: JSON.stringify({ query })
319
+ const response = await wallet.callMerchantApi({
320
+ url: 'https://api.search.com/query',
321
+ merchantPublicKey: 'pk_live_...',
322
+ priceUsd: 0.05,
323
+ body: { query }
320
324
  });
321
325
  const data = await response.json();
322
326
  return JSON.stringify(data.results);
323
327
  } catch (error) {
324
328
  if (error instanceof InsufficientBalanceError) {
325
- return `Error: Low balance ($${error.available}). Need $${error.required}. Top up: ${error.topUpUrl}`;
329
+ return `Error: Low balance. Top up: ${error.topUpUrl}`;
326
330
  }
327
- return `Error: ${error instanceof Error ? error.message : 'Unknown error'}`;
331
+ return `Error: ${error instanceof Error ? error.message : 'Unknown'}`;
328
332
  }
329
333
  }
330
334
  });
331
-
332
- // Check spending before expensive operations
333
- const stats = await wallet.getSpendingStats();
334
- console.log(`Budget remaining: $${stats.remainingDailyUsd ?? 'unlimited'}`);
335
335
  ```
336
336
 
337
337
  ## πŸ“š API Reference
@@ -354,11 +354,17 @@ new AgentWallet({
354
354
  })
355
355
  ```
356
356
 
357
- #### Methods
357
+ ### Methods
358
358
 
359
359
  | Method | Description |
360
360
  |--------|-------------|
361
- | `fetch(url, init?)` | Make HTTP request (drop-in for native fetch) |
361
+ | `callMerchantApi(options)` | Make request to MixrPay merchant (session-based) |
362
+ | `fetch(url, init?)` | Make request to x402 API (drop-in for native fetch) |
363
+ | `getOrCreateSession(options)` | Get or create session with merchant |
364
+ | `chargeSession(id, amount, options?)` | Charge against a session |
365
+ | `listSessions()` | List all active sessions |
366
+ | `revokeSession(id)` | Revoke a session |
367
+ | `getSessionStats()` | Get session statistics |
362
368
  | `getBalance()` | Get USDC balance in USD |
363
369
  | `getSpendingStats()` | Get spending statistics |
364
370
  | `getSessionKeyInfo()` | Get session key details and limits |
@@ -369,44 +375,54 @@ new AgentWallet({
369
375
  | `isTestnet()` | Check if using testnet |
370
376
  | `runDiagnostics()` | Run health checks |
371
377
  | `setDebug(enable)` | Toggle debug logging |
372
- | `setLogLevel(level)` | Set log level |
373
378
 
374
379
  ### Types
375
380
 
376
381
  ```typescript
377
- interface PaymentEvent {
378
- amountUsd: number; // Payment amount in USD
379
- recipient: string; // Recipient address
380
- txHash: string | null; // Transaction hash
381
- timestamp: Date; // When payment was made
382
- description?: string; // What was paid for
383
- url?: string; // URL that triggered payment
382
+ interface SessionAuthorization {
383
+ id: string;
384
+ merchantId: string;
385
+ merchantName: string;
386
+ status: 'pending' | 'active' | 'expired' | 'revoked';
387
+ spendingLimitUsd: number;
388
+ amountUsedUsd: number;
389
+ remainingLimitUsd: number;
390
+ expiresAt: Date;
391
+ createdAt: Date;
384
392
  }
385
393
 
386
- interface SpendingStats {
394
+ interface SessionStats {
395
+ activeCount: number;
396
+ expiredCount: number;
397
+ revokedCount: number;
398
+ totalAuthorizedUsd: number;
387
399
  totalSpentUsd: number;
388
- txCount: number;
389
- remainingDailyUsd: number | null;
390
- remainingTotalUsd: number | null;
391
- expiresAt: Date | null;
400
+ totalRemainingUsd: number;
401
+ activeSessions: Array<{
402
+ id: string;
403
+ merchantName: string;
404
+ merchantPublicKey: string;
405
+ spendingLimitUsd: number;
406
+ remainingUsd: number;
407
+ expiresAt: Date;
408
+ }>;
392
409
  }
393
410
 
394
- interface SessionKeyInfo {
395
- address: string;
396
- isValid: boolean;
397
- limits: {
398
- perTxUsd: number | null;
399
- dailyUsd: number | null;
400
- totalUsd: number | null;
401
- };
402
- usage: {
403
- todayUsd: number;
404
- totalUsd: number;
405
- txCount: number;
406
- };
407
- expiresAt: Date | null;
408
- createdAt: Date | null;
409
- name?: string;
411
+ interface ChargeResult {
412
+ success: boolean;
413
+ chargeId: string;
414
+ amountUsd: number;
415
+ txHash?: string;
416
+ remainingSessionBalanceUsd: number;
417
+ }
418
+
419
+ interface PaymentEvent {
420
+ amountUsd: number;
421
+ recipient: string;
422
+ txHash: string | null;
423
+ timestamp: Date;
424
+ description?: string;
425
+ url?: string;
410
426
  }
411
427
  ```
412
428
 
@@ -416,10 +432,14 @@ interface SessionKeyInfo {
416
432
  |-----------|-------------|
417
433
  | `InsufficientBalanceError` | Wallet doesn't have enough USDC |
418
434
  | `SessionKeyExpiredError` | Session key has expired |
419
- | `SpendingLimitExceededError` | Payment would exceed limits |
435
+ | `SpendingLimitExceededError` | Would exceed session key limits |
436
+ | `SessionExpiredError` | Session authorization has expired |
437
+ | `SessionLimitExceededError` | Would exceed session spending limit |
438
+ | `SessionNotFoundError` | Session ID is invalid |
439
+ | `SessionRevokedError` | Session was revoked |
420
440
  | `PaymentFailedError` | Payment transaction failed |
421
441
  | `InvalidSessionKeyError` | Invalid session key format |
422
- | `X402ProtocolError` | Protocol handling error |
442
+ | `X402ProtocolError` | x402 protocol handling error |
423
443
 
424
444
  ## 🌐 Networks
425
445
 
@@ -430,19 +450,15 @@ interface SessionKeyInfo {
430
450
 
431
451
  ### Testing on Testnet
432
452
 
433
- 1. **Get test ETH**: Use the [Base Sepolia faucet](https://www.alchemy.com/faucets/base-sepolia)
434
- 2. **Get test USDC**: Available from the wallet dashboard after funding with test ETH
435
- 3. **Create test session key**: Use the wallet dashboard to create `sk_test_...` keys
436
- 4. **Test your integration**: Use test keys with your development environment
437
-
438
453
  ```typescript
439
454
  // Test environment setup
440
455
  const wallet = new AgentWallet({
441
- sessionKey: process.env.MIXRPAY_SESSION_KEY!, // sk_test_...
442
- baseUrl: 'http://localhost:3000', // Your local MixrPay server
456
+ sessionKey: 'sk_test_...', // Use test key
457
+ baseUrl: 'http://localhost:3000', // Local dev server
443
458
  });
444
459
 
445
460
  // The SDK automatically detects testnet from sk_test_ prefix
461
+ console.log(`Testnet: ${wallet.isTestnet()}`); // true
446
462
  ```
447
463
 
448
464
  ## πŸ”§ Environment Variables
@@ -452,32 +468,6 @@ const wallet = new AgentWallet({
452
468
  | `MIXRPAY_SESSION_KEY` | Yes | Your session key (`sk_live_...` or `sk_test_...`) |
453
469
  | `MIXRPAY_BASE_URL` | No | MixrPay server URL (default: `https://mixrpay.com`) |
454
470
 
455
- ### x402 Facilitator
456
-
457
- The SDK uses the x402 protocol facilitator at `https://x402.org/facilitator` by default. The facilitator:
458
- - Verifies payment signatures
459
- - Submits transactions to the blockchain
460
- - Returns settlement confirmation
461
-
462
- You can use a custom facilitator for testing or self-hosted deployments:
463
- ```typescript
464
- const wallet = new AgentWallet({
465
- sessionKey: 'sk_live_...',
466
- facilitatorUrl: 'https://your-facilitator.com', // Custom facilitator
467
- });
468
- ```
469
-
470
- Example `.env` file:
471
- ```bash
472
- # Production
473
- MIXRPAY_SESSION_KEY=sk_live_abc123...
474
- MIXRPAY_BASE_URL=https://your-mixrpay-server.com
475
-
476
- # Development (testnet)
477
- MIXRPAY_SESSION_KEY=sk_test_abc123...
478
- MIXRPAY_BASE_URL=http://localhost:3000
479
- ```
480
-
481
471
  ## πŸ”’ Security Best Practices
482
472
 
483
473
  1. **Store session keys securely** - Use environment variables, never commit to source
@@ -486,22 +476,19 @@ MIXRPAY_BASE_URL=http://localhost:3000
486
476
  4. **Use testnet first** - Test with `sk_test_` keys before production
487
477
  5. **Configure base URL** - Always set `baseUrl` explicitly in production
488
478
 
489
- ## 🌐 Browser Support
490
-
491
- This SDK works in both Node.js and browser environments. In browsers, it uses the native `fetch` and `crypto` APIs.
492
-
493
479
  ## πŸ“‹ Changelog
494
480
 
495
- ### v0.1.0 (Current)
481
+ ### v0.2.0 (Current)
482
+ - Added session-based payments (`callMerchantApi()`)
483
+ - Added session management (`getOrCreateSession()`, `listSessions()`, `revokeSession()`)
484
+ - Added session-related error types
485
+ - Improved documentation
486
+
487
+ ### v0.1.0
496
488
  - Initial release
497
- - Core `AgentWallet` class with x402 payment handling
498
- - Automatic 402 response detection and payment flow
499
- - Session key validation and spending limit enforcement
500
- - Payment callbacks and spending statistics
501
- - Vercel AI SDK and LangChain.js integration examples
502
- - Debug mode and diagnostics
503
-
504
- See [CHANGELOG.md](./CHANGELOG.md) for full release history.
489
+ - x402 payment handling via `fetch()`
490
+ - Session key validation and spending limits
491
+ - Payment callbacks and statistics
505
492
 
506
493
  ## πŸ“ License
507
494