@mixrpay/agent-sdk 0.1.0 β†’ 0.2.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 `http://localhost:3000`. For production, 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.remainingUsd);
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.remainingUsd} 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,28 @@ import {
179
197
  InsufficientBalanceError,
180
198
  SpendingLimitExceededError,
181
199
  SessionKeyExpiredError,
200
+ SessionExpiredError,
201
+ SessionLimitExceededError,
182
202
  } from '@mixrpay/agent-sdk';
183
203
 
184
204
  const wallet = new AgentWallet({ sessionKey: 'sk_live_...' });
185
205
 
186
206
  try {
187
- const response = await wallet.fetch('https://api.example.com/expensive');
188
- console.log(await response.json());
207
+ const response = await wallet.callMerchantApi({ ... });
189
208
  } catch (error) {
190
209
  if (error instanceof InsufficientBalanceError) {
191
210
  console.log(`❌ Not enough funds: need $${error.required}, have $${error.available}`);
192
211
  console.log(` Top up at: ${error.topUpUrl}`);
212
+ } else if (error instanceof SessionExpiredError) {
213
+ console.log('❌ Session expired, creating new one...');
214
+ // SDK will auto-create on next callMerchantApi()
215
+ } else if (error instanceof SessionLimitExceededError) {
216
+ console.log(`❌ Session limit exceeded: ${error.limitType}`);
217
+ console.log(` Limit: $${error.limit}, Requested: $${error.requested}`);
193
218
  } 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
- }
219
+ console.log(`❌ Session key limit exceeded: ${error.limitType}`);
198
220
  } else if (error instanceof SessionKeyExpiredError) {
199
221
  console.log(`❌ Session key expired at ${error.expiredAt}`);
200
- console.log(' Request a new key from the wallet owner.');
201
222
  } else {
202
223
  throw error;
203
224
  }
@@ -227,28 +248,6 @@ const wallet = new AgentWallet({
227
248
 
228
249
  // Or toggle at runtime
229
250
  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
251
  ```
253
252
 
254
253
  ## πŸ€– AI Framework Integrations
@@ -256,15 +255,14 @@ if (diagnostics.healthy) {
256
255
  ### Vercel AI SDK
257
256
 
258
257
  ```typescript
259
- import { AgentWallet, InsufficientBalanceError, SpendingLimitExceededError } from '@mixrpay/agent-sdk';
258
+ import { AgentWallet, SessionLimitExceededError } from '@mixrpay/agent-sdk';
260
259
  import { generateText } from 'ai';
261
260
  import { openai } from '@ai-sdk/openai';
262
261
  import { z } from 'zod';
263
262
 
264
263
  const wallet = new AgentWallet({
265
264
  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`),
265
+ maxPaymentUsd: 1.00,
268
266
  });
269
267
 
270
268
  const result = await generateText({
@@ -275,25 +273,23 @@ const result = await generateText({
275
273
  parameters: z.object({ query: z.string() }),
276
274
  execute: async ({ query }) => {
277
275
  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 })
276
+ const response = await wallet.callMerchantApi({
277
+ url: 'https://api.search.com/query',
278
+ merchantPublicKey: 'pk_live_...',
279
+ priceUsd: 0.05,
280
+ body: { query }
282
281
  });
283
282
  return response.json();
284
283
  } catch (error) {
285
- if (error instanceof InsufficientBalanceError) {
286
- return { error: 'Insufficient funds', topUpUrl: error.topUpUrl };
284
+ if (error instanceof SessionLimitExceededError) {
285
+ return { error: 'Budget exceeded', limit: error.limitType };
287
286
  }
288
- if (error instanceof SpendingLimitExceededError) {
289
- return { error: 'Spending limit reached', limit: error.limitType };
290
- }
291
- throw error; // Re-throw unexpected errors
287
+ throw error;
292
288
  }
293
289
  }
294
290
  }
295
291
  },
296
- prompt: 'Search for the latest AI news and summarize it'
292
+ prompt: 'Search for the latest AI news'
297
293
  });
298
294
  ```
299
295
 
@@ -305,33 +301,30 @@ import { DynamicTool } from '@langchain/core/tools';
305
301
 
306
302
  const wallet = new AgentWallet({
307
303
  sessionKey: process.env.MIXRPAY_SESSION_KEY!,
308
- maxPaymentUsd: 0.50, // Cap per tool invocation
304
+ maxPaymentUsd: 0.50,
309
305
  });
310
306
 
311
307
  const paidSearchTool = new DynamicTool({
312
308
  name: 'paid_search',
313
- description: 'Premium search API ($0.05/query) - use for high-quality results',
309
+ description: 'Premium search API ($0.05/query)',
314
310
  func: async (query: string) => {
315
311
  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 })
312
+ const response = await wallet.callMerchantApi({
313
+ url: 'https://api.search.com/query',
314
+ merchantPublicKey: 'pk_live_...',
315
+ priceUsd: 0.05,
316
+ body: { query }
320
317
  });
321
318
  const data = await response.json();
322
319
  return JSON.stringify(data.results);
323
320
  } catch (error) {
324
321
  if (error instanceof InsufficientBalanceError) {
325
- return `Error: Low balance ($${error.available}). Need $${error.required}. Top up: ${error.topUpUrl}`;
322
+ return `Error: Low balance. Top up: ${error.topUpUrl}`;
326
323
  }
327
- return `Error: ${error instanceof Error ? error.message : 'Unknown error'}`;
324
+ return `Error: ${error instanceof Error ? error.message : 'Unknown'}`;
328
325
  }
329
326
  }
330
327
  });
331
-
332
- // Check spending before expensive operations
333
- const stats = await wallet.getSpendingStats();
334
- console.log(`Budget remaining: $${stats.remainingDailyUsd ?? 'unlimited'}`);
335
328
  ```
336
329
 
337
330
  ## πŸ“š API Reference
@@ -354,11 +347,17 @@ new AgentWallet({
354
347
  })
355
348
  ```
356
349
 
357
- #### Methods
350
+ ### Methods
358
351
 
359
352
  | Method | Description |
360
353
  |--------|-------------|
361
- | `fetch(url, init?)` | Make HTTP request (drop-in for native fetch) |
354
+ | `callMerchantApi(options)` | Make request to MixrPay merchant (session-based) |
355
+ | `fetch(url, init?)` | Make request to x402 API (drop-in for native fetch) |
356
+ | `getOrCreateSession(options)` | Get or create session with merchant |
357
+ | `chargeSession(id, amount, options?)` | Charge against a session |
358
+ | `listSessions()` | List all active sessions |
359
+ | `revokeSession(id)` | Revoke a session |
360
+ | `getSessionStats()` | Get session statistics |
362
361
  | `getBalance()` | Get USDC balance in USD |
363
362
  | `getSpendingStats()` | Get spending statistics |
364
363
  | `getSessionKeyInfo()` | Get session key details and limits |
@@ -369,44 +368,37 @@ new AgentWallet({
369
368
  | `isTestnet()` | Check if using testnet |
370
369
  | `runDiagnostics()` | Run health checks |
371
370
  | `setDebug(enable)` | Toggle debug logging |
372
- | `setLogLevel(level)` | Set log level |
373
371
 
374
372
  ### Types
375
373
 
376
374
  ```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
375
+ interface Session {
376
+ id: string;
377
+ merchantPublicKey: string;
378
+ merchantName?: string;
379
+ spendingLimitUsd: number;
380
+ spentUsd: number;
381
+ remainingUsd: number;
382
+ status: 'active' | 'expired' | 'revoked';
383
+ expiresAt: Date;
384
+ createdAt: Date;
384
385
  }
385
386
 
386
- interface SpendingStats {
387
- totalSpentUsd: number;
388
- txCount: number;
389
- remainingDailyUsd: number | null;
390
- remainingTotalUsd: number | null;
391
- expiresAt: Date | null;
387
+ interface ChargeResult {
388
+ success: boolean;
389
+ chargeId: string;
390
+ amountUsd: number;
391
+ txHash?: string;
392
+ remainingUsd: number;
392
393
  }
393
394
 
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;
395
+ interface PaymentEvent {
396
+ amountUsd: number;
397
+ recipient: string;
398
+ txHash: string | null;
399
+ timestamp: Date;
400
+ description?: string;
401
+ url?: string;
410
402
  }
411
403
  ```
412
404
 
@@ -416,10 +408,14 @@ interface SessionKeyInfo {
416
408
  |-----------|-------------|
417
409
  | `InsufficientBalanceError` | Wallet doesn't have enough USDC |
418
410
  | `SessionKeyExpiredError` | Session key has expired |
419
- | `SpendingLimitExceededError` | Payment would exceed limits |
411
+ | `SpendingLimitExceededError` | Would exceed session key limits |
412
+ | `SessionExpiredError` | Session authorization has expired |
413
+ | `SessionLimitExceededError` | Would exceed session spending limit |
414
+ | `SessionNotFoundError` | Session ID is invalid |
415
+ | `SessionRevokedError` | Session was revoked |
420
416
  | `PaymentFailedError` | Payment transaction failed |
421
417
  | `InvalidSessionKeyError` | Invalid session key format |
422
- | `X402ProtocolError` | Protocol handling error |
418
+ | `X402ProtocolError` | x402 protocol handling error |
423
419
 
424
420
  ## 🌐 Networks
425
421
 
@@ -430,19 +426,15 @@ interface SessionKeyInfo {
430
426
 
431
427
  ### Testing on Testnet
432
428
 
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
429
  ```typescript
439
430
  // Test environment setup
440
431
  const wallet = new AgentWallet({
441
- sessionKey: process.env.MIXRPAY_SESSION_KEY!, // sk_test_...
442
- baseUrl: 'http://localhost:3000', // Your local MixrPay server
432
+ sessionKey: 'sk_test_...', // Use test key
433
+ baseUrl: 'http://localhost:3000', // Local dev server
443
434
  });
444
435
 
445
436
  // The SDK automatically detects testnet from sk_test_ prefix
437
+ console.log(`Testnet: ${wallet.isTestnet()}`); // true
446
438
  ```
447
439
 
448
440
  ## πŸ”§ Environment Variables
@@ -450,33 +442,7 @@ const wallet = new AgentWallet({
450
442
  | Variable | Required | Description |
451
443
  |----------|----------|-------------|
452
444
  | `MIXRPAY_SESSION_KEY` | Yes | Your session key (`sk_live_...` or `sk_test_...`) |
453
- | `MIXRPAY_BASE_URL` | No | MixrPay server URL (default: `http://localhost:3000`) |
454
-
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
- ```
445
+ | `MIXRPAY_BASE_URL` | No | MixrPay server URL (default: `https://mixrpay.com`) |
480
446
 
481
447
  ## πŸ”’ Security Best Practices
482
448
 
@@ -486,22 +452,19 @@ MIXRPAY_BASE_URL=http://localhost:3000
486
452
  4. **Use testnet first** - Test with `sk_test_` keys before production
487
453
  5. **Configure base URL** - Always set `baseUrl` explicitly in production
488
454
 
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
455
  ## πŸ“‹ Changelog
494
456
 
495
- ### v0.1.0 (Current)
457
+ ### v0.2.0 (Current)
458
+ - Added session-based payments (`callMerchantApi()`)
459
+ - Added session management (`getOrCreateSession()`, `listSessions()`, `revokeSession()`)
460
+ - Added session-related error types
461
+ - Improved documentation
462
+
463
+ ### v0.1.0
496
464
  - 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.
465
+ - x402 payment handling via `fetch()`
466
+ - Session key validation and spending limits
467
+ - Payment callbacks and statistics
505
468
 
506
469
  ## πŸ“ License
507
470