@x402-crosschain/sdk 1.0.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 +498 -0
- package/dist/client/browser-client.d.ts +9 -0
- package/dist/client/browser-client.d.ts.map +1 -0
- package/dist/client/browser-client.js +158 -0
- package/dist/client/browser-client.js.map +1 -0
- package/dist/client/payment-client.d.ts +8 -0
- package/dist/client/payment-client.d.ts.map +1 -0
- package/dist/client/payment-client.js +195 -0
- package/dist/client/payment-client.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/payment-middleware.d.ts +15 -0
- package/dist/middleware/payment-middleware.d.ts.map +1 -0
- package/dist/middleware/payment-middleware.js +123 -0
- package/dist/middleware/payment-middleware.js.map +1 -0
- package/dist/types.d.ts +46 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +48 -0
package/README.md
ADDED
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
# @x402-crosschain/sdk
|
|
2
|
+
|
|
3
|
+
> **Cross-chain payment SDK extending x402 protocol with instant multi-chain support**
|
|
4
|
+
|
|
5
|
+
Enable your application to accept payments in any token on any chain, with instant settlement in USDC on Base. Built on the x402 payment protocol with Relay's instant bridging (2-3 second settlement).
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@x402-crosschain/sdk)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 🎯 **Key Features**
|
|
13
|
+
|
|
14
|
+
- ⚡ **Instant Settlement** - 2-3 second cross-chain payments via Relay
|
|
15
|
+
- 🌐 **69+ Chains** - Support for Ethereum, Arbitrum, Base, Polygon, Solana, and more
|
|
16
|
+
- 💰 **Any Token** - Accept payments in ETH, USDC, USDT, or any supported token
|
|
17
|
+
- 🔒 **Secure** - Built on x402 standard with on-chain settlement verification
|
|
18
|
+
- 🎯 **Merchant-Friendly** - Simple Express middleware integration
|
|
19
|
+
- 🚀 **Production Ready** - Used in production with proven reliability
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 📦 **Installation**
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install @x402-crosschain/sdk
|
|
27
|
+
# or
|
|
28
|
+
yarn add @x402-crosschain/sdk
|
|
29
|
+
# or
|
|
30
|
+
pnpm add @x402-crosschain/sdk
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## 🚀 **Quick Start**
|
|
36
|
+
|
|
37
|
+
### **For Merchants (Backend)**
|
|
38
|
+
|
|
39
|
+
Protect your API endpoints with payment requirements:
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import express from 'express';
|
|
43
|
+
import { paymentMiddleware } from '@x402-crosschain/sdk';
|
|
44
|
+
|
|
45
|
+
const app = express();
|
|
46
|
+
|
|
47
|
+
// Protect endpoint with payment requirement
|
|
48
|
+
app.use(
|
|
49
|
+
'/premium-content',
|
|
50
|
+
paymentMiddleware({
|
|
51
|
+
recipient: '0xYourWalletAddress',
|
|
52
|
+
price: '1.00', // $1.00 in USDC on Base
|
|
53
|
+
network: 'base',
|
|
54
|
+
facilitatorUrl: 'https://facilitator.yourdomain.com',
|
|
55
|
+
})
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
app.get('/premium-content', (req, res) => {
|
|
59
|
+
res.json({ content: 'This premium content is only accessible after payment' });
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
app.listen(3000, () => console.log('Server running on port 3000'));
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### **For Customers (Frontend)**
|
|
66
|
+
|
|
67
|
+
Make cross-chain payments easily:
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
import { payX402 } from '@x402-crosschain/sdk';
|
|
71
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
72
|
+
|
|
73
|
+
// Create wallet/signer
|
|
74
|
+
const account = privateKeyToAccount('0xYourPrivateKey');
|
|
75
|
+
|
|
76
|
+
// Make API request
|
|
77
|
+
const response = await fetch('https://api.example.com/premium-content');
|
|
78
|
+
|
|
79
|
+
// If payment required (402 status)
|
|
80
|
+
if (response.status === 402) {
|
|
81
|
+
// Pay with any token on any chain
|
|
82
|
+
const result = await payX402(response, account, {
|
|
83
|
+
fromChainId: 42161, // Arbitrum
|
|
84
|
+
fromToken: '0x0000000000000000000000000000000000000000', // Native ETH
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
console.log('Payment completed:', result.txHash);
|
|
88
|
+
|
|
89
|
+
// Retry request - now authenticated
|
|
90
|
+
const paidResponse = await fetch('https://api.example.com/premium-content', {
|
|
91
|
+
headers: {
|
|
92
|
+
'X-Payment-Signature': result.signature,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const content = await paidResponse.json();
|
|
97
|
+
console.log('Content:', content);
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 🏗️ **Architecture**
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
┌─────────────────────────────────────────────────────────┐
|
|
107
|
+
│ Your Application │
|
|
108
|
+
├─────────────────────────────────────────────────────────┤
|
|
109
|
+
│ │
|
|
110
|
+
│ Merchant Backend Customer Frontend │
|
|
111
|
+
│ (Express + SDK) (Browser + SDK) │
|
|
112
|
+
│ │ │ │
|
|
113
|
+
│ └──────────┬───────────────┘ │
|
|
114
|
+
│ │ │
|
|
115
|
+
└────────────────────┼────────────────────────────────────┘
|
|
116
|
+
│
|
|
117
|
+
▼
|
|
118
|
+
┌────────────────────────┐
|
|
119
|
+
│ x402 Facilitator │
|
|
120
|
+
│ (Your deployment or │
|
|
121
|
+
│ hosted service) │
|
|
122
|
+
└────────────────────────┘
|
|
123
|
+
│
|
|
124
|
+
▼
|
|
125
|
+
┌────────────────────────┐
|
|
126
|
+
│ Relay Network │
|
|
127
|
+
│ (Instant bridging via │
|
|
128
|
+
│ liquidity pools) │
|
|
129
|
+
└────────────────────────┘
|
|
130
|
+
│
|
|
131
|
+
┌────────────┴────────────┐
|
|
132
|
+
▼ ▼
|
|
133
|
+
Arbitrum Base
|
|
134
|
+
(Customer pays) (Merchant receives)
|
|
135
|
+
ETH, USDC, etc. USDC
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## 📚 **API Reference**
|
|
141
|
+
|
|
142
|
+
### **Merchant Middleware**
|
|
143
|
+
|
|
144
|
+
#### `paymentMiddleware(config: PaymentConfig)`
|
|
145
|
+
|
|
146
|
+
Protects Express routes with payment requirements.
|
|
147
|
+
|
|
148
|
+
**Parameters:**
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
interface PaymentConfig {
|
|
152
|
+
recipient: string; // Wallet address to receive payments
|
|
153
|
+
price: string; // Price in USD (e.g., "1.00")
|
|
154
|
+
network: 'base' | 'base-sepolia'; // Settlement network
|
|
155
|
+
facilitatorUrl: string; // Facilitator endpoint URL
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**Example:**
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
app.use(
|
|
163
|
+
'/api/premium',
|
|
164
|
+
paymentMiddleware({
|
|
165
|
+
recipient: '0x742d35Cc6634C0532925a3b8D9d4DB0a2D7DD5B3',
|
|
166
|
+
price: '5.00',
|
|
167
|
+
network: 'base',
|
|
168
|
+
facilitatorUrl: 'https://facilitator.yourdomain.com',
|
|
169
|
+
})
|
|
170
|
+
);
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
### **Customer Payment Client**
|
|
176
|
+
|
|
177
|
+
#### `payX402(response, signer, userPreference)`
|
|
178
|
+
|
|
179
|
+
Completes a cross-chain payment for a 402 Payment Required response.
|
|
180
|
+
|
|
181
|
+
**Parameters:**
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
interface UserPaymentPreference {
|
|
185
|
+
fromChainId: number; // Source chain ID (e.g., 42161 for Arbitrum)
|
|
186
|
+
fromToken: string; // Token address (0x0000... for native)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Signer can be:
|
|
190
|
+
// - viem Account: privateKeyToAccount('0x...')
|
|
191
|
+
// - ethers Signer: new Wallet('0x...', provider)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Returns:**
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
interface PaymentResult {
|
|
198
|
+
success: boolean;
|
|
199
|
+
txHash: string; // Transaction hash on source chain
|
|
200
|
+
paymentId: string; // Unique payment identifier
|
|
201
|
+
signature: string; // Payment proof for subsequent requests
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
**Example:**
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
const result = await payX402(response, signer, {
|
|
209
|
+
fromChainId: 42161, // Arbitrum
|
|
210
|
+
fromToken: '0x0000000000000000000000000000000000000000', // ETH
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
if (result.success) {
|
|
214
|
+
console.log('Payment successful:', result.txHash);
|
|
215
|
+
// Use result.signature for subsequent authenticated requests
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## 🌍 **Supported Chains**
|
|
222
|
+
|
|
223
|
+
The SDK supports 69+ chains via Relay Network:
|
|
224
|
+
|
|
225
|
+
### **Major EVM Chains**
|
|
226
|
+
- Ethereum (1)
|
|
227
|
+
- Base (8453)
|
|
228
|
+
- Arbitrum (42161)
|
|
229
|
+
- Optimism (10)
|
|
230
|
+
- Polygon (137)
|
|
231
|
+
- BNB Chain (56)
|
|
232
|
+
- Avalanche (43114)
|
|
233
|
+
- And 60+ more...
|
|
234
|
+
|
|
235
|
+
### **Multi-VM Support**
|
|
236
|
+
- ✅ EVM chains
|
|
237
|
+
- ✅ Solana
|
|
238
|
+
- ✅ Bitcoin
|
|
239
|
+
- ✅ Sui
|
|
240
|
+
- ✅ Tron
|
|
241
|
+
|
|
242
|
+
See full list: https://docs.relay.link/resources/supported-chains
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## 💰 **Token Support**
|
|
247
|
+
|
|
248
|
+
### **Source Chains (What customers can pay with)**
|
|
249
|
+
- Native tokens (ETH, MATIC, AVAX, etc.)
|
|
250
|
+
- USDC
|
|
251
|
+
- USDT
|
|
252
|
+
- WETH
|
|
253
|
+
- DAI
|
|
254
|
+
- And more...
|
|
255
|
+
|
|
256
|
+
### **Settlement Chain (What merchants receive)**
|
|
257
|
+
- Always settles in **USDC on Base**
|
|
258
|
+
- Instant finality (~2 seconds)
|
|
259
|
+
- Low gas costs
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## 🔧 **Advanced Configuration**
|
|
264
|
+
|
|
265
|
+
### **Dynamic Pricing**
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
app.use(
|
|
269
|
+
'/api/content/:id',
|
|
270
|
+
paymentMiddleware({
|
|
271
|
+
recipient: '0xYourAddress',
|
|
272
|
+
price: async (req) => {
|
|
273
|
+
// Fetch dynamic pricing from database
|
|
274
|
+
const content = await db.getContent(req.params.id);
|
|
275
|
+
return content.price.toString();
|
|
276
|
+
},
|
|
277
|
+
network: 'base',
|
|
278
|
+
facilitatorUrl: process.env.FACILITATOR_URL,
|
|
279
|
+
})
|
|
280
|
+
);
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### **Custom Token Selection**
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
// Customer chooses preferred payment token
|
|
287
|
+
const result = await payX402(response, signer, {
|
|
288
|
+
fromChainId: 137, // Polygon
|
|
289
|
+
fromToken: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', // USDC on Polygon
|
|
290
|
+
});
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### **Error Handling**
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
try {
|
|
297
|
+
const result = await payX402(response, signer, userPreference);
|
|
298
|
+
|
|
299
|
+
if (!result.success) {
|
|
300
|
+
console.error('Payment failed');
|
|
301
|
+
}
|
|
302
|
+
} catch (error) {
|
|
303
|
+
if (error.message.includes('insufficient funds')) {
|
|
304
|
+
console.error('User does not have enough tokens');
|
|
305
|
+
} else if (error.message.includes('user rejected')) {
|
|
306
|
+
console.error('User cancelled transaction');
|
|
307
|
+
} else {
|
|
308
|
+
console.error('Payment error:', error);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## 🏃 **Self-Hosting the Facilitator**
|
|
316
|
+
|
|
317
|
+
You can run your own facilitator for full control:
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
import { startFacilitator } from '@x402-crosschain/facilitator';
|
|
321
|
+
|
|
322
|
+
await startFacilitator({
|
|
323
|
+
port: 3001,
|
|
324
|
+
baseRpcUrl: 'https://mainnet.base.org',
|
|
325
|
+
paymentSettlementAddress: '0xYourContractAddress',
|
|
326
|
+
settlerPrivateKey: process.env.SETTLER_PRIVATE_KEY,
|
|
327
|
+
});
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
See [Facilitator Documentation](../facilitator/README.md) for details.
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## 📊 **Fee Structure**
|
|
335
|
+
|
|
336
|
+
### **Cross-Chain Payment Costs**
|
|
337
|
+
|
|
338
|
+
| Component | Cost | Who Pays |
|
|
339
|
+
|-----------|------|----------|
|
|
340
|
+
| **Bridge Fee** | 0.1-0.3% | Customer |
|
|
341
|
+
| **Gas (Source Chain)** | $0.01-0.10 | Customer |
|
|
342
|
+
| **Gas (Destination)** | Included | Relay |
|
|
343
|
+
| **Settlement Gas** | $0.001 | Facilitator |
|
|
344
|
+
|
|
345
|
+
### **Recommended Minimum Payment**
|
|
346
|
+
|
|
347
|
+
- **Minimum**: $1.00 (15% total fee)
|
|
348
|
+
- **Optimal**: $10+ (2-3% total fee)
|
|
349
|
+
- **Not recommended**: < $0.50 (fees dominate)
|
|
350
|
+
|
|
351
|
+
**Example:**
|
|
352
|
+
```
|
|
353
|
+
Payment: $10.00
|
|
354
|
+
Bridge fee: $0.02 (0.2%)
|
|
355
|
+
Gas costs: $0.03
|
|
356
|
+
Total cost: $10.05
|
|
357
|
+
Effective fee: 0.5%
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
## 🔒 **Security**
|
|
363
|
+
|
|
364
|
+
### **Payment Verification**
|
|
365
|
+
- All payments verified on-chain
|
|
366
|
+
- Settlement contract ensures atomicity
|
|
367
|
+
- Non-custodial (no funds held by facilitator)
|
|
368
|
+
|
|
369
|
+
### **Best Practices**
|
|
370
|
+
```typescript
|
|
371
|
+
// ✅ Good: Use environment variables
|
|
372
|
+
facilitatorUrl: process.env.FACILITATOR_URL,
|
|
373
|
+
|
|
374
|
+
// ❌ Bad: Hardcode private keys
|
|
375
|
+
const signer = new Wallet('0xhardcodedkey...');
|
|
376
|
+
|
|
377
|
+
// ✅ Good: Use secure key management
|
|
378
|
+
const signer = new Wallet(process.env.PRIVATE_KEY, provider);
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
## 🧪 **Testing**
|
|
384
|
+
|
|
385
|
+
### **Test Networks**
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
// Use Base Sepolia for testing
|
|
389
|
+
paymentMiddleware({
|
|
390
|
+
recipient: '0xTestWallet',
|
|
391
|
+
price: '0.01',
|
|
392
|
+
network: 'base-sepolia',
|
|
393
|
+
facilitatorUrl: 'https://testnet-facilitator.yourdomain.com',
|
|
394
|
+
});
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### **Get Test Tokens**
|
|
398
|
+
|
|
399
|
+
- **Base Sepolia ETH**: https://www.alchemy.com/faucets/base-sepolia
|
|
400
|
+
- **Arbitrum Sepolia ETH**: https://faucets.chain.link/arbitrum-sepolia
|
|
401
|
+
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
## 📖 **Examples**
|
|
405
|
+
|
|
406
|
+
### **E-commerce API**
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
import express from 'express';
|
|
410
|
+
import { paymentMiddleware } from '@x402-crosschain/sdk';
|
|
411
|
+
|
|
412
|
+
const app = express();
|
|
413
|
+
|
|
414
|
+
// Product catalog
|
|
415
|
+
const products = {
|
|
416
|
+
'prod_1': { name: 'Premium Article', price: '2.00' },
|
|
417
|
+
'prod_2': { name: 'Video Course', price: '49.00' },
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
// Dynamic payment per product
|
|
421
|
+
app.use(
|
|
422
|
+
'/api/product/:id',
|
|
423
|
+
paymentMiddleware({
|
|
424
|
+
recipient: process.env.MERCHANT_WALLET,
|
|
425
|
+
price: (req) => products[req.params.id].price,
|
|
426
|
+
network: 'base',
|
|
427
|
+
facilitatorUrl: process.env.FACILITATOR_URL,
|
|
428
|
+
})
|
|
429
|
+
);
|
|
430
|
+
|
|
431
|
+
app.get('/api/product/:id', (req, res) => {
|
|
432
|
+
const product = products[req.params.id];
|
|
433
|
+
res.json({ product: product.name, delivered: true });
|
|
434
|
+
});
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### **Creator Marketplace**
|
|
438
|
+
|
|
439
|
+
```typescript
|
|
440
|
+
// Protect creator content
|
|
441
|
+
app.use(
|
|
442
|
+
'/api/creator/:creatorId/content/:contentId',
|
|
443
|
+
paymentMiddleware({
|
|
444
|
+
recipient: async (req) => {
|
|
445
|
+
// Get creator's wallet from database
|
|
446
|
+
const creator = await db.getCreator(req.params.creatorId);
|
|
447
|
+
return creator.walletAddress;
|
|
448
|
+
},
|
|
449
|
+
price: async (req) => {
|
|
450
|
+
const content = await db.getContent(req.params.contentId);
|
|
451
|
+
return content.price;
|
|
452
|
+
},
|
|
453
|
+
network: 'base',
|
|
454
|
+
facilitatorUrl: process.env.FACILITATOR_URL,
|
|
455
|
+
})
|
|
456
|
+
);
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
---
|
|
460
|
+
|
|
461
|
+
## 🤝 **Support**
|
|
462
|
+
|
|
463
|
+
- **Documentation**: [https://docs.x402crosschain.com](https://docs.x402crosschain.com)
|
|
464
|
+
- **GitHub Issues**: [https://github.com/your-org/x402-cross-bridge-sdk/issues](https://github.com/your-org/x402-cross-bridge-sdk/issues)
|
|
465
|
+
- **Discord**: [Join our community](https://discord.gg/your-invite)
|
|
466
|
+
- **Email**: support@x402crosschain.com
|
|
467
|
+
|
|
468
|
+
---
|
|
469
|
+
|
|
470
|
+
## 📄 **License**
|
|
471
|
+
|
|
472
|
+
Apache 2.0 License - see [LICENSE](LICENSE) file for details.
|
|
473
|
+
|
|
474
|
+
---
|
|
475
|
+
|
|
476
|
+
## 🙏 **Acknowledgments**
|
|
477
|
+
|
|
478
|
+
Built on top of:
|
|
479
|
+
- [x402 Protocol](https://x402.org) - Open payment standard
|
|
480
|
+
- [Relay Network](https://relay.link) - Instant cross-chain bridging
|
|
481
|
+
- [viem](https://viem.sh) - TypeScript EVM library
|
|
482
|
+
- [ethers.js](https://docs.ethers.org) - Ethereum library
|
|
483
|
+
|
|
484
|
+
---
|
|
485
|
+
|
|
486
|
+
## 🔄 **Changelog**
|
|
487
|
+
|
|
488
|
+
### v1.0.0
|
|
489
|
+
- Initial release
|
|
490
|
+
- Support for 69+ chains via Relay
|
|
491
|
+
- Express middleware for merchants
|
|
492
|
+
- Browser client for customers
|
|
493
|
+
- Self-hosted facilitator option
|
|
494
|
+
- Comprehensive documentation
|
|
495
|
+
|
|
496
|
+
---
|
|
497
|
+
|
|
498
|
+
**Made with ❤️ by the x402 Cross-Chain Team**
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { AxiosInstance } from 'axios';
|
|
2
|
+
import type { WalletClient } from 'viem';
|
|
3
|
+
import type { PaymentPreferences } from '../types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Create an x402 payment client for BROWSER use with MetaMask/Coinbase Wallet
|
|
6
|
+
* Automatically handles cross-chain payments via Relay
|
|
7
|
+
*/
|
|
8
|
+
export declare function createBrowserPaymentClient(walletClient: WalletClient, preferences?: PaymentPreferences): AxiosInstance;
|
|
9
|
+
//# sourceMappingURL=browser-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-client.d.ts","sourceRoot":"","sources":["../../src/client/browser-client.ts"],"names":[],"mappings":"AAAA,OAAc,EAAE,aAAa,EAAc,MAAM,OAAO,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AACzC,OAAO,KAAK,EAAuC,kBAAkB,EAAgB,MAAM,aAAa,CAAC;AAEzG;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,YAAY,EAC1B,WAAW,CAAC,EAAE,kBAAkB,GAC/B,aAAa,CAkHf"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
/**
|
|
3
|
+
* Create an x402 payment client for BROWSER use with MetaMask/Coinbase Wallet
|
|
4
|
+
* Automatically handles cross-chain payments via Relay
|
|
5
|
+
*/
|
|
6
|
+
export function createBrowserPaymentClient(walletClient, preferences) {
|
|
7
|
+
const client = axios.create();
|
|
8
|
+
// Add request interceptor to include preference headers
|
|
9
|
+
client.interceptors.request.use((config) => {
|
|
10
|
+
if (preferences?.preferredToken) {
|
|
11
|
+
config.headers['X-PREFERRED-TOKEN'] = preferences.preferredToken;
|
|
12
|
+
}
|
|
13
|
+
if (preferences?.preferredNetwork) {
|
|
14
|
+
config.headers['X-PREFERRED-NETWORK'] = preferences.preferredNetwork;
|
|
15
|
+
}
|
|
16
|
+
return config;
|
|
17
|
+
});
|
|
18
|
+
// Add response interceptor to handle 402 Payment Required
|
|
19
|
+
client.interceptors.response.use((response) => response, async (error) => {
|
|
20
|
+
if (!error.response || error.response.status !== 402) {
|
|
21
|
+
return Promise.reject(error);
|
|
22
|
+
}
|
|
23
|
+
const originalRequest = error.config;
|
|
24
|
+
if (!originalRequest || originalRequest._retry) {
|
|
25
|
+
return Promise.reject(error);
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
const x402Response = error.response.data;
|
|
29
|
+
const { x402Version, accepts } = x402Response;
|
|
30
|
+
if (!accepts || accepts.length === 0) {
|
|
31
|
+
throw new Error('No payment requirements provided');
|
|
32
|
+
}
|
|
33
|
+
const paymentRequirements = accepts[0];
|
|
34
|
+
console.log('[Browser Payment] Payment required:', {
|
|
35
|
+
amount: paymentRequirements.maxAmountRequired,
|
|
36
|
+
token: paymentRequirements.asset,
|
|
37
|
+
network: paymentRequirements.network,
|
|
38
|
+
payTo: paymentRequirements.payTo,
|
|
39
|
+
});
|
|
40
|
+
// Get user's current chain
|
|
41
|
+
const userChainId = await walletClient.getChainId();
|
|
42
|
+
const merchantChainId = getChainIdFromNetwork(paymentRequirements.network);
|
|
43
|
+
const isCrossChain = userChainId !== merchantChainId;
|
|
44
|
+
if (isCrossChain) {
|
|
45
|
+
console.log('[Browser Payment] Cross-chain payment detected');
|
|
46
|
+
console.log(` Your chain: ${userChainId}`);
|
|
47
|
+
console.log(` Merchant chain: ${merchantChainId}`);
|
|
48
|
+
}
|
|
49
|
+
// Get user address
|
|
50
|
+
const userAddress = walletClient.account?.address;
|
|
51
|
+
if (!userAddress) {
|
|
52
|
+
throw new Error('No wallet address found');
|
|
53
|
+
}
|
|
54
|
+
// Execute cross-chain payment
|
|
55
|
+
let txHash;
|
|
56
|
+
if (isCrossChain) {
|
|
57
|
+
txHash = await executeBrowserCrossChainPayment(walletClient, userAddress, userChainId, preferences?.preferredToken || '0x0000000000000000000000000000000000000000', paymentRequirements);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
throw new Error('Same-chain payments not yet implemented. Use cross-chain for now.');
|
|
61
|
+
}
|
|
62
|
+
// Create payment payload
|
|
63
|
+
const paymentPayload = {
|
|
64
|
+
x402Version,
|
|
65
|
+
networkId: userChainId,
|
|
66
|
+
scheme: 'exact',
|
|
67
|
+
data: {
|
|
68
|
+
transactionHash: txHash,
|
|
69
|
+
from: userAddress,
|
|
70
|
+
to: paymentRequirements.payTo,
|
|
71
|
+
value: paymentRequirements.maxAmountRequired,
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
// Encode payment payload as base64
|
|
75
|
+
const paymentHeader = Buffer.from(JSON.stringify(paymentPayload)).toString('base64');
|
|
76
|
+
// Retry request with payment header
|
|
77
|
+
originalRequest._retry = true;
|
|
78
|
+
originalRequest.headers['X-PAYMENT'] = paymentHeader;
|
|
79
|
+
// Add preference headers for cross-chain verification
|
|
80
|
+
if (isCrossChain) {
|
|
81
|
+
originalRequest.headers['X-PREFERRED-TOKEN'] = preferences?.preferredToken || '0x0000000000000000000000000000000000000000';
|
|
82
|
+
originalRequest.headers['X-PREFERRED-NETWORK'] = getNetworkName(userChainId);
|
|
83
|
+
paymentRequirements.srcTokenAddress = preferences?.preferredToken || '0x0000000000000000000000000000000000000000';
|
|
84
|
+
paymentRequirements.srcNetwork = getNetworkName(userChainId);
|
|
85
|
+
}
|
|
86
|
+
console.log('[Browser Payment] Retrying request with payment');
|
|
87
|
+
return client.request(originalRequest);
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
console.error('[Browser Payment] Payment failed:', err);
|
|
91
|
+
return Promise.reject(err);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
return client;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Execute cross-chain payment via Relay using browser wallet
|
|
98
|
+
*/
|
|
99
|
+
async function executeBrowserCrossChainPayment(walletClient, userAddress, fromChainId, fromToken, paymentRequirements) {
|
|
100
|
+
console.log('[Cross-Chain] Getting Relay quote...');
|
|
101
|
+
// Get Relay quote
|
|
102
|
+
const quoteResponse = await fetch('https://api.relay.link/quote', {
|
|
103
|
+
method: 'POST',
|
|
104
|
+
headers: { 'Content-Type': 'application/json' },
|
|
105
|
+
body: JSON.stringify({
|
|
106
|
+
user: userAddress,
|
|
107
|
+
originChainId: fromChainId,
|
|
108
|
+
destinationChainId: getChainIdFromNetwork(paymentRequirements.network),
|
|
109
|
+
originCurrency: fromToken,
|
|
110
|
+
destinationCurrency: paymentRequirements.asset,
|
|
111
|
+
amount: paymentRequirements.maxAmountRequired,
|
|
112
|
+
tradeType: 'EXACT_OUTPUT',
|
|
113
|
+
recipient: userAddress,
|
|
114
|
+
}),
|
|
115
|
+
});
|
|
116
|
+
const quote = await quoteResponse.json();
|
|
117
|
+
const txData = quote.steps[0].items[0].data;
|
|
118
|
+
console.log('[Cross-Chain] Quote received');
|
|
119
|
+
console.log('[Cross-Chain] Please approve transaction in your wallet...');
|
|
120
|
+
// Send transaction using user's wallet
|
|
121
|
+
const hash = await walletClient.sendTransaction({
|
|
122
|
+
to: txData.to,
|
|
123
|
+
data: txData.data,
|
|
124
|
+
value: BigInt(txData.value || '0'),
|
|
125
|
+
account: walletClient.account,
|
|
126
|
+
chain: walletClient.chain,
|
|
127
|
+
});
|
|
128
|
+
console.log('[Cross-Chain] Transaction sent:', hash);
|
|
129
|
+
console.log('[Cross-Chain] Relay will bridge in 2-3 seconds...');
|
|
130
|
+
return hash;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Get chain ID from network name
|
|
134
|
+
*/
|
|
135
|
+
function getChainIdFromNetwork(network) {
|
|
136
|
+
const map = {
|
|
137
|
+
'mainnet': 1,
|
|
138
|
+
'base': 8453,
|
|
139
|
+
'arbitrum': 42161,
|
|
140
|
+
'optimism': 10,
|
|
141
|
+
'polygon': 137,
|
|
142
|
+
};
|
|
143
|
+
return map[network] || 8453;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Get network name from chain ID
|
|
147
|
+
*/
|
|
148
|
+
function getNetworkName(chainId) {
|
|
149
|
+
const map = {
|
|
150
|
+
1: 'mainnet',
|
|
151
|
+
8453: 'base',
|
|
152
|
+
42161: 'arbitrum',
|
|
153
|
+
10: 'optimism',
|
|
154
|
+
137: 'polygon',
|
|
155
|
+
};
|
|
156
|
+
return map[chainId] || 'base';
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=browser-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-client.js","sourceRoot":"","sources":["../../src/client/browser-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { AxiosInstance } from 'axios';
|
|
2
|
+
import type { PaymentPreferences } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Create an x402 payment client with cross-chain support
|
|
5
|
+
* Uses Relay for automatic bridging when customer is on different chain than merchant requires
|
|
6
|
+
*/
|
|
7
|
+
export declare function createPaymentClient(privateKey: `0x${string}`, preferences?: PaymentPreferences): AxiosInstance;
|
|
8
|
+
//# sourceMappingURL=payment-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payment-client.d.ts","sourceRoot":"","sources":["../../src/client/payment-client.ts"],"names":[],"mappings":"AAAA,OAAc,EAAE,aAAa,EAAc,MAAM,OAAO,CAAC;AAIzD,OAAO,KAAK,EAAuC,kBAAkB,EAAgB,MAAM,aAAa,CAAC;AAmBzG;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,KAAK,MAAM,EAAE,EACzB,WAAW,CAAC,EAAE,kBAAkB,GAC/B,aAAa,CAqHf"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
3
|
+
import { createWalletClient, http } from 'viem';
|
|
4
|
+
import { arbitrum, base, optimism, polygon, mainnet } from 'viem/chains';
|
|
5
|
+
// Chain mapping
|
|
6
|
+
const CHAIN_MAP = {
|
|
7
|
+
1: mainnet,
|
|
8
|
+
8453: base,
|
|
9
|
+
42161: arbitrum,
|
|
10
|
+
10: optimism,
|
|
11
|
+
137: polygon,
|
|
12
|
+
};
|
|
13
|
+
const RPC_URLS = {
|
|
14
|
+
1: 'https://eth.llamarpc.com',
|
|
15
|
+
8453: 'https://mainnet.base.org',
|
|
16
|
+
42161: 'https://arb1.arbitrum.io/rpc',
|
|
17
|
+
10: 'https://mainnet.optimism.io',
|
|
18
|
+
137: 'https://polygon-rpc.com',
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Create an x402 payment client with cross-chain support
|
|
22
|
+
* Uses Relay for automatic bridging when customer is on different chain than merchant requires
|
|
23
|
+
*/
|
|
24
|
+
export function createPaymentClient(privateKey, preferences) {
|
|
25
|
+
const account = privateKeyToAccount(privateKey);
|
|
26
|
+
const client = axios.create();
|
|
27
|
+
// Add request interceptor to include preference headers
|
|
28
|
+
client.interceptors.request.use((config) => {
|
|
29
|
+
if (preferences?.preferredToken) {
|
|
30
|
+
config.headers['X-PREFERRED-TOKEN'] = preferences.preferredToken;
|
|
31
|
+
}
|
|
32
|
+
if (preferences?.preferredNetwork) {
|
|
33
|
+
config.headers['X-PREFERRED-NETWORK'] = preferences.preferredNetwork;
|
|
34
|
+
}
|
|
35
|
+
return config;
|
|
36
|
+
});
|
|
37
|
+
// Add response interceptor to handle 402 Payment Required
|
|
38
|
+
client.interceptors.response.use((response) => response, async (error) => {
|
|
39
|
+
if (!error.response || error.response.status !== 402) {
|
|
40
|
+
return Promise.reject(error);
|
|
41
|
+
}
|
|
42
|
+
const originalRequest = error.config;
|
|
43
|
+
if (!originalRequest || originalRequest._retry) {
|
|
44
|
+
return Promise.reject(error);
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const x402Response = error.response.data;
|
|
48
|
+
const { x402Version, accepts } = x402Response;
|
|
49
|
+
if (!accepts || accepts.length === 0) {
|
|
50
|
+
throw new Error('No payment requirements provided');
|
|
51
|
+
}
|
|
52
|
+
// Select first payment requirement
|
|
53
|
+
// TODO: Add smart selection based on user's chain/token
|
|
54
|
+
const paymentRequirements = accepts[0];
|
|
55
|
+
console.log('[Payment Client] Payment required:', {
|
|
56
|
+
amount: paymentRequirements.maxAmountRequired,
|
|
57
|
+
token: paymentRequirements.asset,
|
|
58
|
+
network: paymentRequirements.network,
|
|
59
|
+
payTo: paymentRequirements.payTo,
|
|
60
|
+
});
|
|
61
|
+
// Detect if cross-chain payment is needed
|
|
62
|
+
const customerChainId = preferences?.preferredChainId || 42161; // Default to Arbitrum
|
|
63
|
+
const merchantChainId = getChainIdFromNetwork(paymentRequirements.network);
|
|
64
|
+
const isCrossChain = customerChainId !== merchantChainId;
|
|
65
|
+
if (isCrossChain) {
|
|
66
|
+
console.log('[Payment Client] Cross-chain payment detected');
|
|
67
|
+
console.log(` Customer chain: ${customerChainId}`);
|
|
68
|
+
console.log(` Merchant chain: ${merchantChainId}`);
|
|
69
|
+
}
|
|
70
|
+
// Get Relay quote for cross-chain bridge if needed
|
|
71
|
+
let txHash;
|
|
72
|
+
let requestId;
|
|
73
|
+
if (isCrossChain) {
|
|
74
|
+
const result = await executeCrossChainPayment(account.address, privateKey, customerChainId, preferences?.preferredToken || '0x0000000000000000000000000000000000000000', paymentRequirements);
|
|
75
|
+
txHash = result.txHash;
|
|
76
|
+
requestId = result.requestId;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
// Same-chain payment (not yet implemented)
|
|
80
|
+
throw new Error('Same-chain payments not yet implemented. Use cross-chain for now.');
|
|
81
|
+
}
|
|
82
|
+
// Create payment payload
|
|
83
|
+
const paymentPayload = {
|
|
84
|
+
x402Version,
|
|
85
|
+
networkId: customerChainId,
|
|
86
|
+
scheme: 'exact',
|
|
87
|
+
data: {
|
|
88
|
+
transactionHash: txHash,
|
|
89
|
+
requestId: requestId, // Relay request ID for status checking
|
|
90
|
+
from: account.address,
|
|
91
|
+
to: paymentRequirements.payTo,
|
|
92
|
+
value: paymentRequirements.maxAmountRequired,
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
// Encode payment payload as base64
|
|
96
|
+
const paymentHeader = Buffer.from(JSON.stringify(paymentPayload)).toString('base64');
|
|
97
|
+
// Retry request with payment header
|
|
98
|
+
originalRequest._retry = true;
|
|
99
|
+
originalRequest.headers['X-PAYMENT'] = paymentHeader;
|
|
100
|
+
// Add preference headers for cross-chain verification
|
|
101
|
+
if (isCrossChain) {
|
|
102
|
+
originalRequest.headers['X-PREFERRED-TOKEN'] = preferences?.preferredToken || '0x0000000000000000000000000000000000000000';
|
|
103
|
+
originalRequest.headers['X-PREFERRED-NETWORK'] = getNetworkName(customerChainId);
|
|
104
|
+
// Add to payment requirements for facilitator
|
|
105
|
+
paymentRequirements.srcTokenAddress = preferences?.preferredToken || '0x0000000000000000000000000000000000000000';
|
|
106
|
+
paymentRequirements.srcNetwork = getNetworkName(customerChainId);
|
|
107
|
+
}
|
|
108
|
+
console.log('[Payment Client] Retrying request with payment header');
|
|
109
|
+
return client.request(originalRequest);
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
console.error('[Payment Client] Payment failed:', err);
|
|
113
|
+
return Promise.reject(err);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
return client;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Execute cross-chain payment via Relay
|
|
120
|
+
*/
|
|
121
|
+
async function executeCrossChainPayment(userAddress, privateKey, fromChainId, fromToken, paymentRequirements) {
|
|
122
|
+
console.log('[Cross-Chain] Getting Relay quote...');
|
|
123
|
+
// Get Relay quote
|
|
124
|
+
const quoteResponse = await axios.post('https://api.relay.link/quote', {
|
|
125
|
+
user: userAddress,
|
|
126
|
+
originChainId: fromChainId,
|
|
127
|
+
destinationChainId: getChainIdFromNetwork(paymentRequirements.network),
|
|
128
|
+
originCurrency: fromToken,
|
|
129
|
+
destinationCurrency: paymentRequirements.asset,
|
|
130
|
+
amount: paymentRequirements.maxAmountRequired,
|
|
131
|
+
tradeType: 'EXACT_OUTPUT',
|
|
132
|
+
recipient: userAddress,
|
|
133
|
+
});
|
|
134
|
+
const quote = quoteResponse.data;
|
|
135
|
+
const requestId = quote.steps[0].requestId; // Relay's request ID
|
|
136
|
+
const txData = quote.steps[0].items[0].data;
|
|
137
|
+
console.log('[Cross-Chain] Quote received, sending transaction...');
|
|
138
|
+
console.log('[Cross-Chain] Relay Request ID:', requestId);
|
|
139
|
+
// Create wallet client
|
|
140
|
+
const chain = CHAIN_MAP[fromChainId];
|
|
141
|
+
const walletClient = createWalletClient({
|
|
142
|
+
account: privateKeyToAccount(privateKey),
|
|
143
|
+
chain,
|
|
144
|
+
transport: http(RPC_URLS[fromChainId]),
|
|
145
|
+
});
|
|
146
|
+
// Send transaction
|
|
147
|
+
const hash = await walletClient.sendTransaction({
|
|
148
|
+
to: txData.to,
|
|
149
|
+
data: txData.data,
|
|
150
|
+
value: BigInt(txData.value || '0'),
|
|
151
|
+
chain,
|
|
152
|
+
});
|
|
153
|
+
console.log('[Cross-Chain] Transaction sent:', hash);
|
|
154
|
+
// IMPORTANT: Notify Relay to index the transaction immediately
|
|
155
|
+
// This accelerates indexing and ensures Relay detects the deposit
|
|
156
|
+
try {
|
|
157
|
+
await axios.post('https://api.relay.link/transactions/index', {
|
|
158
|
+
txHash: hash,
|
|
159
|
+
chainId: fromChainId,
|
|
160
|
+
});
|
|
161
|
+
console.log('[Cross-Chain] Transaction indexed with Relay');
|
|
162
|
+
}
|
|
163
|
+
catch (indexError) {
|
|
164
|
+
console.warn('[Cross-Chain] Failed to index transaction, Relay will index it eventually:', indexError);
|
|
165
|
+
}
|
|
166
|
+
console.log('[Cross-Chain] Relay will bridge in 2-3 seconds...');
|
|
167
|
+
return { txHash: hash, requestId };
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Get chain ID from network name
|
|
171
|
+
*/
|
|
172
|
+
function getChainIdFromNetwork(network) {
|
|
173
|
+
const map = {
|
|
174
|
+
'mainnet': 1,
|
|
175
|
+
'base': 8453,
|
|
176
|
+
'arbitrum': 42161,
|
|
177
|
+
'optimism': 10,
|
|
178
|
+
'polygon': 137,
|
|
179
|
+
};
|
|
180
|
+
return map[network] || 8453; // Default to Base
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Get network name from chain ID
|
|
184
|
+
*/
|
|
185
|
+
function getNetworkName(chainId) {
|
|
186
|
+
const map = {
|
|
187
|
+
1: 'mainnet',
|
|
188
|
+
8453: 'base',
|
|
189
|
+
42161: 'arbitrum',
|
|
190
|
+
10: 'optimism',
|
|
191
|
+
137: 'polygon',
|
|
192
|
+
};
|
|
193
|
+
return map[chainId] || 'base';
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=payment-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payment-client.js","sourceRoot":"","sources":["../../src/client/payment-client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { createPaymentClient } from './client/payment-client.js';
|
|
2
|
+
export { createBrowserPaymentClient } from './client/browser-client.js';
|
|
3
|
+
export { paymentMiddleware } from './middleware/payment-middleware.js';
|
|
4
|
+
export type { PaymentRequirements, PaymentPayload, VerifyResponse, SettleResponse, X402Response, PaymentPreferences, } from './types.js';
|
|
5
|
+
export type { MiddlewareConfig } from './middleware/payment-middleware.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAGxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAGvE,YAAY,EACV,mBAAmB,EACnB,cAAc,EACd,cAAc,EACd,cAAc,EACd,YAAY,EACZ,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Export clients
|
|
2
|
+
export { createPaymentClient } from './client/payment-client.js'; // For Node.js (private keys)
|
|
3
|
+
export { createBrowserPaymentClient } from './client/browser-client.js'; // For Browser (MetaMask/wallets)
|
|
4
|
+
// Export middleware
|
|
5
|
+
export { paymentMiddleware } from './middleware/payment-middleware.js';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iBAAiB;AACjB,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC,CAAC,6BAA6B;AAC/F,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC,CAAC,iCAAiC;AAE1G,oBAAoB;AACpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
export interface MiddlewareConfig {
|
|
3
|
+
payTo: string;
|
|
4
|
+
price: string;
|
|
5
|
+
network: string;
|
|
6
|
+
facilitatorUrl: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* x402 payment middleware for Express
|
|
11
|
+
* Protects routes with payment requirements
|
|
12
|
+
* Supports cross-chain payments via preference headers (AnySpend-style)
|
|
13
|
+
*/
|
|
14
|
+
export declare function paymentMiddleware(config: MiddlewareConfig): (req: Request, res: Response, next: NextFunction) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
15
|
+
//# sourceMappingURL=payment-middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payment-middleware.d.ts","sourceRoot":"","sources":["../../src/middleware/payment-middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAI1D,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,IAC1C,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,6DAgI9D"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
/**
|
|
3
|
+
* x402 payment middleware for Express
|
|
4
|
+
* Protects routes with payment requirements
|
|
5
|
+
* Supports cross-chain payments via preference headers (AnySpend-style)
|
|
6
|
+
*/
|
|
7
|
+
export function paymentMiddleware(config) {
|
|
8
|
+
return async (req, res, next) => {
|
|
9
|
+
try {
|
|
10
|
+
// Check for payment header
|
|
11
|
+
const paymentHeader = req.headers['x-payment'];
|
|
12
|
+
if (!paymentHeader) {
|
|
13
|
+
// No payment provided, return 402 with payment requirements
|
|
14
|
+
const paymentRequirements = {
|
|
15
|
+
scheme: 'exact',
|
|
16
|
+
asset: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC on Base
|
|
17
|
+
maxAmountRequired: parsePrice(config.price),
|
|
18
|
+
network: config.network,
|
|
19
|
+
payTo: config.payTo,
|
|
20
|
+
maxTimeoutSeconds: 60,
|
|
21
|
+
description: config.description || 'Payment required for access',
|
|
22
|
+
};
|
|
23
|
+
return res.status(402).json({
|
|
24
|
+
x402Version: 1,
|
|
25
|
+
accepts: [paymentRequirements],
|
|
26
|
+
error: 'Payment required',
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
// Decode payment payload
|
|
30
|
+
const paymentPayload = JSON.parse(Buffer.from(paymentHeader, 'base64').toString('utf-8'));
|
|
31
|
+
// Build payment requirements
|
|
32
|
+
const paymentRequirements = {
|
|
33
|
+
scheme: 'exact',
|
|
34
|
+
asset: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
35
|
+
maxAmountRequired: parsePrice(config.price),
|
|
36
|
+
network: config.network,
|
|
37
|
+
payTo: config.payTo,
|
|
38
|
+
};
|
|
39
|
+
// Add cross-chain support: Get preference headers
|
|
40
|
+
const preferredToken = req.headers['x-preferred-token'];
|
|
41
|
+
const preferredNetwork = req.headers['x-preferred-network'];
|
|
42
|
+
if (preferredToken || preferredNetwork) {
|
|
43
|
+
console.log('[Middleware] Cross-chain payment detected:', {
|
|
44
|
+
srcToken: preferredToken,
|
|
45
|
+
srcNetwork: preferredNetwork,
|
|
46
|
+
destNetwork: config.network,
|
|
47
|
+
});
|
|
48
|
+
paymentRequirements.srcTokenAddress = preferredToken;
|
|
49
|
+
paymentRequirements.srcNetwork = preferredNetwork;
|
|
50
|
+
}
|
|
51
|
+
// Verify payment with facilitator
|
|
52
|
+
console.log('[Middleware] Verifying payment...');
|
|
53
|
+
const verifyResponse = await axios.post(`${config.facilitatorUrl}/verify`, {
|
|
54
|
+
paymentPayload,
|
|
55
|
+
paymentRequirements,
|
|
56
|
+
});
|
|
57
|
+
if (!verifyResponse.data.isValid) {
|
|
58
|
+
return res.status(402).json({
|
|
59
|
+
x402Version: 1,
|
|
60
|
+
accepts: [paymentRequirements],
|
|
61
|
+
error: verifyResponse.data.invalidReason || 'Payment verification failed',
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
console.log('[Middleware] Payment verified, processing request...');
|
|
65
|
+
// Store payment info in request for access in route handler
|
|
66
|
+
req.payment = {
|
|
67
|
+
verified: true,
|
|
68
|
+
payer: paymentPayload.data.from,
|
|
69
|
+
amount: paymentRequirements.maxAmountRequired,
|
|
70
|
+
};
|
|
71
|
+
// Execute the protected route
|
|
72
|
+
await new Promise((resolve) => {
|
|
73
|
+
const originalSend = res.send.bind(res);
|
|
74
|
+
const originalJson = res.json.bind(res);
|
|
75
|
+
let settled = false;
|
|
76
|
+
const settlePayment = async () => {
|
|
77
|
+
if (settled)
|
|
78
|
+
return;
|
|
79
|
+
settled = true;
|
|
80
|
+
try {
|
|
81
|
+
console.log('[Middleware] Settling payment...');
|
|
82
|
+
const settleResponse = await axios.post(`${config.facilitatorUrl}/settle`, {
|
|
83
|
+
paymentPayload,
|
|
84
|
+
paymentRequirements,
|
|
85
|
+
});
|
|
86
|
+
if (settleResponse.data.success) {
|
|
87
|
+
console.log('[Middleware] Payment settled successfully');
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
console.error('[Middleware] Settlement failed:', settleResponse.data.errorReason);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
console.error('[Middleware] Settlement error:', error);
|
|
95
|
+
}
|
|
96
|
+
resolve();
|
|
97
|
+
};
|
|
98
|
+
res.send = function (body) {
|
|
99
|
+
settlePayment().then(() => originalSend(body));
|
|
100
|
+
return this;
|
|
101
|
+
};
|
|
102
|
+
res.json = function (body) {
|
|
103
|
+
settlePayment().then(() => originalJson(body));
|
|
104
|
+
return this;
|
|
105
|
+
};
|
|
106
|
+
next();
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
console.error('[Middleware] Error:', error);
|
|
111
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Parse price string (e.g., '$0.01') to wei amount (USDC has 6 decimals)
|
|
117
|
+
*/
|
|
118
|
+
function parsePrice(price) {
|
|
119
|
+
const numericPrice = parseFloat(price.replace('$', ''));
|
|
120
|
+
const usdcAmount = Math.floor(numericPrice * 1_000_000); // USDC has 6 decimals
|
|
121
|
+
return usdcAmount.toString();
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=payment-middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payment-middleware.js","sourceRoot":"","sources":["../../src/middleware/payment-middleware.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export interface PaymentRequirements {
|
|
2
|
+
scheme: string;
|
|
3
|
+
asset: string;
|
|
4
|
+
maxAmountRequired: string;
|
|
5
|
+
network: string;
|
|
6
|
+
payTo: string;
|
|
7
|
+
maxTimeoutSeconds?: number;
|
|
8
|
+
description?: string;
|
|
9
|
+
mimeType?: string;
|
|
10
|
+
resource?: string;
|
|
11
|
+
srcTokenAddress?: string;
|
|
12
|
+
srcNetwork?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface PaymentPayload {
|
|
15
|
+
x402Version: number;
|
|
16
|
+
networkId: number;
|
|
17
|
+
scheme: string;
|
|
18
|
+
data: {
|
|
19
|
+
transactionHash?: string;
|
|
20
|
+
from?: string;
|
|
21
|
+
to?: string;
|
|
22
|
+
value?: string;
|
|
23
|
+
[key: string]: any;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export interface VerifyResponse {
|
|
27
|
+
isValid: boolean;
|
|
28
|
+
invalidReason?: string;
|
|
29
|
+
payer?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface SettleResponse {
|
|
32
|
+
success: boolean;
|
|
33
|
+
errorReason?: string;
|
|
34
|
+
transactionHash?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface X402Response {
|
|
37
|
+
x402Version: number;
|
|
38
|
+
accepts: PaymentRequirements[];
|
|
39
|
+
error?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface PaymentPreferences {
|
|
42
|
+
preferredToken?: string;
|
|
43
|
+
preferredNetwork?: string;
|
|
44
|
+
preferredChainId?: number;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE;QACJ,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC;CACH;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@x402-crosschain/sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "x402 cross-chain payment SDK with Relay Network support",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"dev": "tsc --watch",
|
|
15
|
+
"clean": "rm -rf dist",
|
|
16
|
+
"prepublishOnly": "pnpm build"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"axios": "^1.6.0",
|
|
20
|
+
"viem": "^2.7.0",
|
|
21
|
+
"express": "^4.18.0"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/express": "^4.17.21",
|
|
25
|
+
"@types/node": "^20.10.0",
|
|
26
|
+
"typescript": "^5.3.3"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"x402",
|
|
30
|
+
"cross-chain",
|
|
31
|
+
"payments",
|
|
32
|
+
"relay",
|
|
33
|
+
"web3",
|
|
34
|
+
"ethereum",
|
|
35
|
+
"blockchain",
|
|
36
|
+
"crypto-payments"
|
|
37
|
+
],
|
|
38
|
+
"author": "Divyansh Sharma <divyansh242805@gmail.com>",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "https://github.com/divi2806/x402-cross-bridge-sdk.git",
|
|
43
|
+
"directory": "packages/sdk"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
}
|
|
48
|
+
}
|