uvd-x402-sdk 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +782 -0
- package/dist/index-BrBqP1I8.d.ts +199 -0
- package/dist/index-D6Sr4ARD.d.mts +429 -0
- package/dist/index-D6Sr4ARD.d.ts +429 -0
- package/dist/index-DJ4Cvrev.d.mts +199 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1178 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1146 -0
- package/dist/index.mjs.map +1 -0
- package/dist/providers/evm/index.d.mts +84 -0
- package/dist/providers/evm/index.d.ts +84 -0
- package/dist/providers/evm/index.js +740 -0
- package/dist/providers/evm/index.js.map +1 -0
- package/dist/providers/evm/index.mjs +735 -0
- package/dist/providers/evm/index.mjs.map +1 -0
- package/dist/providers/near/index.d.mts +99 -0
- package/dist/providers/near/index.d.ts +99 -0
- package/dist/providers/near/index.js +483 -0
- package/dist/providers/near/index.js.map +1 -0
- package/dist/providers/near/index.mjs +478 -0
- package/dist/providers/near/index.mjs.map +1 -0
- package/dist/providers/solana/index.d.mts +115 -0
- package/dist/providers/solana/index.d.ts +115 -0
- package/dist/providers/solana/index.js +771 -0
- package/dist/providers/solana/index.js.map +1 -0
- package/dist/providers/solana/index.mjs +765 -0
- package/dist/providers/solana/index.mjs.map +1 -0
- package/dist/providers/stellar/index.d.mts +67 -0
- package/dist/providers/stellar/index.d.ts +67 -0
- package/dist/providers/stellar/index.js +306 -0
- package/dist/providers/stellar/index.js.map +1 -0
- package/dist/providers/stellar/index.mjs +301 -0
- package/dist/providers/stellar/index.mjs.map +1 -0
- package/dist/react/index.d.mts +73 -0
- package/dist/react/index.d.ts +73 -0
- package/dist/react/index.js +1218 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/index.mjs +1211 -0
- package/dist/react/index.mjs.map +1 -0
- package/dist/utils/index.d.mts +103 -0
- package/dist/utils/index.d.ts +103 -0
- package/dist/utils/index.js +575 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/index.mjs +562 -0
- package/dist/utils/index.mjs.map +1 -0
- package/package.json +149 -0
- package/src/chains/index.ts +539 -0
- package/src/client/X402Client.ts +663 -0
- package/src/client/index.ts +1 -0
- package/src/index.ts +166 -0
- package/src/providers/evm/index.ts +394 -0
- package/src/providers/near/index.ts +664 -0
- package/src/providers/solana/index.ts +489 -0
- package/src/providers/stellar/index.ts +376 -0
- package/src/react/index.tsx +417 -0
- package/src/types/index.ts +561 -0
- package/src/utils/index.ts +20 -0
- package/src/utils/x402.ts +295 -0
package/README.md
ADDED
|
@@ -0,0 +1,782 @@
|
|
|
1
|
+
# uvd-x402-sdk
|
|
2
|
+
|
|
3
|
+
> Gasless crypto payments across 15 blockchain networks using the x402 protocol.
|
|
4
|
+
|
|
5
|
+
The x402 SDK enables any application to accept USDC payments without requiring users to pay gas fees. Users sign a message or transaction, and the Ultravioleta facilitator handles on-chain settlement.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **15 Supported Networks**: EVM chains, Solana, Fogo, Stellar, and NEAR
|
|
10
|
+
- **x402 v1 & v2**: Full support for both protocol versions with automatic detection
|
|
11
|
+
- **Gasless Payments**: Users never pay gas - the facilitator covers all network fees
|
|
12
|
+
- **Multi-Network**: Accept payments on multiple networks simultaneously
|
|
13
|
+
- **Type-Safe**: Comprehensive TypeScript definitions
|
|
14
|
+
- **Framework Agnostic**: Works with any JavaScript framework
|
|
15
|
+
- **React Hooks**: First-class React integration
|
|
16
|
+
- **Modular**: Import only what you need
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import { X402Client } from 'uvd-x402-sdk';
|
|
22
|
+
|
|
23
|
+
const client = new X402Client({ defaultChain: 'base' });
|
|
24
|
+
|
|
25
|
+
// Connect wallet
|
|
26
|
+
const address = await client.connect('base');
|
|
27
|
+
|
|
28
|
+
// Create payment
|
|
29
|
+
const result = await client.createPayment({
|
|
30
|
+
recipient: '0x...',
|
|
31
|
+
amount: '10.00',
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Use in your API request
|
|
35
|
+
await fetch('/api/purchase', {
|
|
36
|
+
method: 'POST',
|
|
37
|
+
headers: {
|
|
38
|
+
'Content-Type': 'application/json',
|
|
39
|
+
'X-PAYMENT': result.paymentHeader,
|
|
40
|
+
},
|
|
41
|
+
body: JSON.stringify({ item: 'premium-feature' }),
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install uvd-x402-sdk
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Peer Dependencies by Network
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# EVM chains (Base, Ethereum, etc.) - included by default
|
|
55
|
+
npm install ethers@^6
|
|
56
|
+
|
|
57
|
+
# Solana & Fogo (SVM chains)
|
|
58
|
+
npm install @solana/web3.js @solana/spl-token
|
|
59
|
+
|
|
60
|
+
# Stellar
|
|
61
|
+
npm install @stellar/stellar-sdk @stellar/freighter-api
|
|
62
|
+
|
|
63
|
+
# NEAR
|
|
64
|
+
npm install @near-wallet-selector/core @near-wallet-selector/my-near-wallet
|
|
65
|
+
|
|
66
|
+
# React hooks (optional)
|
|
67
|
+
npm install react
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Network Examples
|
|
73
|
+
|
|
74
|
+
### EVM Chains (11 Networks)
|
|
75
|
+
|
|
76
|
+
All EVM chains use EIP-712 typed data signing with ERC-3009 TransferWithAuthorization.
|
|
77
|
+
|
|
78
|
+
#### Base (Recommended - Fastest & Cheapest)
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { X402Client } from 'uvd-x402-sdk';
|
|
82
|
+
|
|
83
|
+
const client = new X402Client({ defaultChain: 'base' });
|
|
84
|
+
|
|
85
|
+
// Connect to Base
|
|
86
|
+
const address = await client.connect('base');
|
|
87
|
+
console.log('Connected:', address);
|
|
88
|
+
|
|
89
|
+
// Check balance
|
|
90
|
+
const balance = await client.getBalance();
|
|
91
|
+
console.log('USDC Balance:', balance);
|
|
92
|
+
|
|
93
|
+
// Create payment
|
|
94
|
+
const result = await client.createPayment({
|
|
95
|
+
recipient: '0xD3868E1eD738CED6945A574a7c769433BeD5d474',
|
|
96
|
+
amount: '10.00',
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
console.log('Payment header:', result.paymentHeader);
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
#### Ethereum
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
import { X402Client } from 'uvd-x402-sdk';
|
|
106
|
+
|
|
107
|
+
const client = new X402Client({ defaultChain: 'ethereum' });
|
|
108
|
+
const address = await client.connect('ethereum');
|
|
109
|
+
|
|
110
|
+
const result = await client.createPayment({
|
|
111
|
+
recipient: '0xD3868E1eD738CED6945A574a7c769433BeD5d474',
|
|
112
|
+
amount: '100.00', // Higher amounts common on Ethereum
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
#### Polygon
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
import { X402Client } from 'uvd-x402-sdk';
|
|
120
|
+
|
|
121
|
+
const client = new X402Client({ defaultChain: 'polygon' });
|
|
122
|
+
const address = await client.connect('polygon');
|
|
123
|
+
|
|
124
|
+
const result = await client.createPayment({
|
|
125
|
+
recipient: '0xD3868E1eD738CED6945A574a7c769433BeD5d474',
|
|
126
|
+
amount: '10.00',
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
#### Arbitrum
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
import { X402Client } from 'uvd-x402-sdk';
|
|
134
|
+
|
|
135
|
+
const client = new X402Client({ defaultChain: 'arbitrum' });
|
|
136
|
+
const address = await client.connect('arbitrum');
|
|
137
|
+
|
|
138
|
+
const result = await client.createPayment({
|
|
139
|
+
recipient: '0xD3868E1eD738CED6945A574a7c769433BeD5d474',
|
|
140
|
+
amount: '10.00',
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
#### Optimism
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
import { X402Client } from 'uvd-x402-sdk';
|
|
148
|
+
|
|
149
|
+
const client = new X402Client({ defaultChain: 'optimism' });
|
|
150
|
+
const address = await client.connect('optimism');
|
|
151
|
+
|
|
152
|
+
const result = await client.createPayment({
|
|
153
|
+
recipient: '0xD3868E1eD738CED6945A574a7c769433BeD5d474',
|
|
154
|
+
amount: '10.00',
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
#### Avalanche C-Chain
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
import { X402Client } from 'uvd-x402-sdk';
|
|
162
|
+
|
|
163
|
+
const client = new X402Client({ defaultChain: 'avalanche' });
|
|
164
|
+
const address = await client.connect('avalanche');
|
|
165
|
+
|
|
166
|
+
const result = await client.createPayment({
|
|
167
|
+
recipient: '0xD3868E1eD738CED6945A574a7c769433BeD5d474',
|
|
168
|
+
amount: '10.00',
|
|
169
|
+
});
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
#### Celo
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
import { X402Client } from 'uvd-x402-sdk';
|
|
176
|
+
|
|
177
|
+
const client = new X402Client({ defaultChain: 'celo' });
|
|
178
|
+
const address = await client.connect('celo');
|
|
179
|
+
|
|
180
|
+
const result = await client.createPayment({
|
|
181
|
+
recipient: '0xD3868E1eD738CED6945A574a7c769433BeD5d474',
|
|
182
|
+
amount: '10.00',
|
|
183
|
+
});
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
#### HyperEVM
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
import { X402Client } from 'uvd-x402-sdk';
|
|
190
|
+
|
|
191
|
+
const client = new X402Client({ defaultChain: 'hyperevm' });
|
|
192
|
+
const address = await client.connect('hyperevm');
|
|
193
|
+
|
|
194
|
+
const result = await client.createPayment({
|
|
195
|
+
recipient: '0xD3868E1eD738CED6945A574a7c769433BeD5d474',
|
|
196
|
+
amount: '10.00',
|
|
197
|
+
});
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
#### Unichain
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
import { X402Client } from 'uvd-x402-sdk';
|
|
204
|
+
|
|
205
|
+
const client = new X402Client({ defaultChain: 'unichain' });
|
|
206
|
+
const address = await client.connect('unichain');
|
|
207
|
+
|
|
208
|
+
const result = await client.createPayment({
|
|
209
|
+
recipient: '0xD3868E1eD738CED6945A574a7c769433BeD5d474',
|
|
210
|
+
amount: '10.00',
|
|
211
|
+
});
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
#### Monad
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
import { X402Client } from 'uvd-x402-sdk';
|
|
218
|
+
|
|
219
|
+
const client = new X402Client({ defaultChain: 'monad' });
|
|
220
|
+
const address = await client.connect('monad');
|
|
221
|
+
|
|
222
|
+
const result = await client.createPayment({
|
|
223
|
+
recipient: '0xD3868E1eD738CED6945A574a7c769433BeD5d474',
|
|
224
|
+
amount: '10.00',
|
|
225
|
+
});
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
### SVM Chains (Solana Virtual Machine)
|
|
231
|
+
|
|
232
|
+
SVM chains use partially-signed transactions where the facilitator is the fee payer.
|
|
233
|
+
|
|
234
|
+
#### Solana
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
import { SVMProvider } from 'uvd-x402-sdk/solana';
|
|
238
|
+
import { getChainByName } from 'uvd-x402-sdk';
|
|
239
|
+
|
|
240
|
+
const svm = new SVMProvider();
|
|
241
|
+
|
|
242
|
+
// Check if Phantom is installed
|
|
243
|
+
if (!svm.isAvailable()) {
|
|
244
|
+
throw new Error('Please install Phantom wallet from phantom.app');
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Connect
|
|
248
|
+
const address = await svm.connect();
|
|
249
|
+
console.log('Connected Solana wallet:', address);
|
|
250
|
+
|
|
251
|
+
// Get chain config
|
|
252
|
+
const chainConfig = getChainByName('solana')!;
|
|
253
|
+
|
|
254
|
+
// Get balance
|
|
255
|
+
const balance = await svm.getBalance(chainConfig);
|
|
256
|
+
console.log('USDC Balance:', balance);
|
|
257
|
+
|
|
258
|
+
// Create payment
|
|
259
|
+
const paymentPayload = await svm.signPayment(
|
|
260
|
+
{
|
|
261
|
+
recipient: '5Y32Dk6weq1LrMRdujpJyDbTN3SjwXGoQS9QN39WQ9Cq',
|
|
262
|
+
amount: '10.00',
|
|
263
|
+
facilitator: 'F742C4VfFLQ9zRQyithoj5229ZgtX2WqKCSFKgH2EThq',
|
|
264
|
+
},
|
|
265
|
+
chainConfig
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
// Encode as X-PAYMENT header
|
|
269
|
+
const header = svm.encodePaymentHeader(paymentPayload, chainConfig);
|
|
270
|
+
console.log('Payment header:', header);
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
#### Fogo
|
|
274
|
+
|
|
275
|
+
Fogo is an SVM chain with ultra-fast ~400ms finality.
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
import { SVMProvider } from 'uvd-x402-sdk/solana';
|
|
279
|
+
import { getChainByName } from 'uvd-x402-sdk';
|
|
280
|
+
|
|
281
|
+
const svm = new SVMProvider();
|
|
282
|
+
|
|
283
|
+
// Connect (same wallet works for all SVM chains)
|
|
284
|
+
const address = await svm.connect();
|
|
285
|
+
|
|
286
|
+
// Get Fogo chain config
|
|
287
|
+
const chainConfig = getChainByName('fogo')!;
|
|
288
|
+
|
|
289
|
+
// Get balance on Fogo
|
|
290
|
+
const balance = await svm.getBalance(chainConfig);
|
|
291
|
+
console.log('Fogo USDC Balance:', balance);
|
|
292
|
+
|
|
293
|
+
// Create Fogo payment
|
|
294
|
+
const paymentPayload = await svm.signPayment(
|
|
295
|
+
{
|
|
296
|
+
recipient: '5Y32Dk6weq1LrMRdujpJyDbTN3SjwXGoQS9QN39WQ9Cq',
|
|
297
|
+
amount: '10.00',
|
|
298
|
+
facilitator: 'F742C4VfFLQ9zRQyithoj5229ZgtX2WqKCSFKgH2EThq',
|
|
299
|
+
},
|
|
300
|
+
chainConfig
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
// Encode with correct network name ('fogo')
|
|
304
|
+
const header = svm.encodePaymentHeader(paymentPayload, chainConfig);
|
|
305
|
+
console.log('Fogo payment header:', header);
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
### Stellar
|
|
311
|
+
|
|
312
|
+
Stellar uses Soroban authorization entries for gasless transfers.
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
import { StellarProvider } from 'uvd-x402-sdk/stellar';
|
|
316
|
+
import { getChainByName } from 'uvd-x402-sdk';
|
|
317
|
+
|
|
318
|
+
const stellar = new StellarProvider();
|
|
319
|
+
|
|
320
|
+
// Check if Freighter is installed
|
|
321
|
+
if (!stellar.isAvailable()) {
|
|
322
|
+
throw new Error('Please install Freighter wallet from freighter.app');
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Connect
|
|
326
|
+
const address = await stellar.connect();
|
|
327
|
+
console.log('Connected Stellar wallet:', address);
|
|
328
|
+
|
|
329
|
+
// Get chain config
|
|
330
|
+
const chainConfig = getChainByName('stellar')!;
|
|
331
|
+
|
|
332
|
+
// Get balance
|
|
333
|
+
const balance = await stellar.getBalance(chainConfig);
|
|
334
|
+
console.log('USDC Balance:', balance);
|
|
335
|
+
|
|
336
|
+
// Create payment
|
|
337
|
+
const paymentPayload = await stellar.signPayment(
|
|
338
|
+
{
|
|
339
|
+
recipient: 'GD3FWQ4QFSCO2F2KVXZPQWOC27CQHXHYCRCRRZBMWU3DNOZW2IIGOU54',
|
|
340
|
+
amount: '10.00',
|
|
341
|
+
},
|
|
342
|
+
chainConfig
|
|
343
|
+
);
|
|
344
|
+
|
|
345
|
+
// Encode as X-PAYMENT header
|
|
346
|
+
const header = stellar.encodePaymentHeader(paymentPayload);
|
|
347
|
+
console.log('Payment header:', header);
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
### NEAR Protocol
|
|
353
|
+
|
|
354
|
+
NEAR uses NEP-366 meta-transactions where the facilitator pays all gas.
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
import { NEARProvider } from 'uvd-x402-sdk/near';
|
|
358
|
+
import { getChainByName } from 'uvd-x402-sdk';
|
|
359
|
+
|
|
360
|
+
const near = new NEARProvider();
|
|
361
|
+
|
|
362
|
+
// Check if NEAR wallet is available
|
|
363
|
+
if (!near.isAvailable()) {
|
|
364
|
+
throw new Error('Please install MyNearWallet or Meteor wallet');
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Connect
|
|
368
|
+
const accountId = await near.connect();
|
|
369
|
+
console.log('Connected NEAR account:', accountId);
|
|
370
|
+
|
|
371
|
+
// Get chain config
|
|
372
|
+
const chainConfig = getChainByName('near')!;
|
|
373
|
+
|
|
374
|
+
// Get balance
|
|
375
|
+
const balance = await near.getBalance(chainConfig);
|
|
376
|
+
console.log('USDC Balance:', balance);
|
|
377
|
+
|
|
378
|
+
// Create payment
|
|
379
|
+
const paymentPayload = await near.signPayment(
|
|
380
|
+
{
|
|
381
|
+
recipient: '0xultravioleta.near',
|
|
382
|
+
amount: '10.00',
|
|
383
|
+
},
|
|
384
|
+
chainConfig
|
|
385
|
+
);
|
|
386
|
+
|
|
387
|
+
// Encode as X-PAYMENT header
|
|
388
|
+
const header = near.encodePaymentHeader(paymentPayload);
|
|
389
|
+
console.log('Payment header:', header);
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
## x402 Protocol Versions
|
|
395
|
+
|
|
396
|
+
The SDK supports both x402 v1 and v2 protocols.
|
|
397
|
+
|
|
398
|
+
### v1 (Default)
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
// v1 uses simple network names
|
|
402
|
+
{
|
|
403
|
+
"x402Version": 1,
|
|
404
|
+
"scheme": "exact",
|
|
405
|
+
"network": "base",
|
|
406
|
+
"payload": { ... }
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### v2 (CAIP-2)
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
// v2 uses CAIP-2 chain identifiers
|
|
414
|
+
{
|
|
415
|
+
"x402Version": 2,
|
|
416
|
+
"scheme": "exact",
|
|
417
|
+
"network": "eip155:8453",
|
|
418
|
+
"payload": { ... },
|
|
419
|
+
"accepts": [
|
|
420
|
+
{ "network": "eip155:8453", "asset": "0x833...", "amount": "10000000" },
|
|
421
|
+
{ "network": "solana:5eykt...", "asset": "EPjF...", "amount": "10000000" }
|
|
422
|
+
]
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### Version Detection and Conversion
|
|
427
|
+
|
|
428
|
+
```typescript
|
|
429
|
+
import {
|
|
430
|
+
detectX402Version,
|
|
431
|
+
chainToCAIP2,
|
|
432
|
+
caip2ToChain,
|
|
433
|
+
convertX402Header,
|
|
434
|
+
} from 'uvd-x402-sdk';
|
|
435
|
+
|
|
436
|
+
// Detect version from response
|
|
437
|
+
const version = detectX402Version(response402);
|
|
438
|
+
// Returns: 1 or 2
|
|
439
|
+
|
|
440
|
+
// Convert between formats
|
|
441
|
+
const caip2 = chainToCAIP2('base');
|
|
442
|
+
// Returns: 'eip155:8453'
|
|
443
|
+
|
|
444
|
+
const chainName = caip2ToChain('eip155:8453');
|
|
445
|
+
// Returns: 'base'
|
|
446
|
+
|
|
447
|
+
// Convert headers between versions
|
|
448
|
+
const v2Header = convertX402Header(v1Header, 2);
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### Configure Version
|
|
452
|
+
|
|
453
|
+
```typescript
|
|
454
|
+
const client = new X402Client({
|
|
455
|
+
defaultChain: 'base',
|
|
456
|
+
x402Version: 2, // Force v2 format
|
|
457
|
+
// or
|
|
458
|
+
x402Version: 'auto', // Auto-detect from 402 response (default)
|
|
459
|
+
});
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
---
|
|
463
|
+
|
|
464
|
+
## Multi-Payment Support
|
|
465
|
+
|
|
466
|
+
Accept payments on multiple networks simultaneously.
|
|
467
|
+
|
|
468
|
+
### Configuration
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
const client = new X402Client({
|
|
472
|
+
defaultChain: 'base',
|
|
473
|
+
multiPayment: {
|
|
474
|
+
networks: ['base', 'solana', 'stellar', 'near'],
|
|
475
|
+
defaultNetwork: 'base',
|
|
476
|
+
autoDetect: true, // Auto-select based on user's wallet
|
|
477
|
+
},
|
|
478
|
+
});
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### Generate Payment Options
|
|
482
|
+
|
|
483
|
+
```typescript
|
|
484
|
+
import { generatePaymentOptions, getEnabledChains } from 'uvd-x402-sdk';
|
|
485
|
+
|
|
486
|
+
// Get all enabled chain configs
|
|
487
|
+
const chains = getEnabledChains();
|
|
488
|
+
|
|
489
|
+
// Generate v2 payment options
|
|
490
|
+
const options = generatePaymentOptions(chains, '10.00');
|
|
491
|
+
|
|
492
|
+
// Result:
|
|
493
|
+
// [
|
|
494
|
+
// { network: 'eip155:8453', asset: '0x833...', amount: '10000000' },
|
|
495
|
+
// { network: 'solana:5eykt...', asset: 'EPjF...', amount: '10000000' },
|
|
496
|
+
// { network: 'stellar:pubnet', asset: 'CCW67...', amount: '100000000' },
|
|
497
|
+
// { network: 'near:mainnet', asset: '17208...', amount: '10000000' },
|
|
498
|
+
// ]
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
---
|
|
502
|
+
|
|
503
|
+
## React Integration
|
|
504
|
+
|
|
505
|
+
```tsx
|
|
506
|
+
import { X402Provider, useX402, usePayment, useBalance } from 'uvd-x402-sdk/react';
|
|
507
|
+
|
|
508
|
+
function App() {
|
|
509
|
+
return (
|
|
510
|
+
<X402Provider config={{ defaultChain: 'base' }}>
|
|
511
|
+
<PaymentPage />
|
|
512
|
+
</X402Provider>
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
function PaymentPage() {
|
|
517
|
+
const { connect, disconnect, isConnected, address, network } = useX402();
|
|
518
|
+
const { balance, isLoading: balanceLoading } = useBalance();
|
|
519
|
+
const { pay, isPaying, error } = usePayment();
|
|
520
|
+
|
|
521
|
+
const handlePurchase = async () => {
|
|
522
|
+
const result = await pay({
|
|
523
|
+
recipient: '0xD3868E1eD738CED6945A574a7c769433BeD5d474',
|
|
524
|
+
amount: '10.00',
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
await fetch('/api/purchase', {
|
|
528
|
+
headers: { 'X-PAYMENT': result.paymentHeader },
|
|
529
|
+
method: 'POST',
|
|
530
|
+
body: JSON.stringify({ item: 'premium' }),
|
|
531
|
+
});
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
if (!isConnected) {
|
|
535
|
+
return <button onClick={() => connect('base')}>Connect Wallet</button>;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
return (
|
|
539
|
+
<div>
|
|
540
|
+
<p>Connected: {address}</p>
|
|
541
|
+
<p>Network: {network}</p>
|
|
542
|
+
<p>Balance: {balanceLoading ? 'Loading...' : `${balance} USDC`}</p>
|
|
543
|
+
<button onClick={handlePurchase} disabled={isPaying}>
|
|
544
|
+
{isPaying ? 'Processing...' : 'Pay $10 USDC'}
|
|
545
|
+
</button>
|
|
546
|
+
{error && <p style={{ color: 'red' }}>{error}</p>}
|
|
547
|
+
</div>
|
|
548
|
+
);
|
|
549
|
+
}
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
---
|
|
553
|
+
|
|
554
|
+
## Supported Networks
|
|
555
|
+
|
|
556
|
+
### EVM Networks (11)
|
|
557
|
+
|
|
558
|
+
| Network | Chain ID | USDC Decimals | Status |
|
|
559
|
+
|---------|----------|---------------|--------|
|
|
560
|
+
| Base | 8453 | 6 | Enabled |
|
|
561
|
+
| Ethereum | 1 | 6 | Enabled |
|
|
562
|
+
| Polygon | 137 | 6 | Enabled |
|
|
563
|
+
| Arbitrum | 42161 | 6 | Enabled |
|
|
564
|
+
| Optimism | 10 | 6 | Enabled |
|
|
565
|
+
| Avalanche | 43114 | 6 | Enabled |
|
|
566
|
+
| Celo | 42220 | 6 | Enabled |
|
|
567
|
+
| HyperEVM | 999 | 6 | Enabled |
|
|
568
|
+
| Unichain | 130 | 6 | Enabled |
|
|
569
|
+
| Monad | 143 | 6 | Enabled |
|
|
570
|
+
| BSC | 56 | 18 | Disabled* |
|
|
571
|
+
|
|
572
|
+
*BSC USDC doesn't support ERC-3009 transferWithAuthorization
|
|
573
|
+
|
|
574
|
+
### SVM Networks (2)
|
|
575
|
+
|
|
576
|
+
| Network | USDC Mint | Decimals | Wallet | Status |
|
|
577
|
+
|---------|-----------|----------|--------|--------|
|
|
578
|
+
| Solana | EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v | 6 | Phantom | Enabled |
|
|
579
|
+
| Fogo | uSd2czE61Evaf76RNbq4KPpXnkiL3irdzgLFUMe3NoG | 6 | Phantom | Enabled |
|
|
580
|
+
|
|
581
|
+
### Other Networks (2)
|
|
582
|
+
|
|
583
|
+
| Network | USDC Address | Decimals | Wallet | Status |
|
|
584
|
+
|---------|--------------|----------|--------|--------|
|
|
585
|
+
| Stellar | CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75 | 7 | Freighter | Enabled |
|
|
586
|
+
| NEAR | 17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1 | 6 | MyNearWallet | Enabled |
|
|
587
|
+
|
|
588
|
+
---
|
|
589
|
+
|
|
590
|
+
## API Reference
|
|
591
|
+
|
|
592
|
+
### X402Client
|
|
593
|
+
|
|
594
|
+
```typescript
|
|
595
|
+
const client = new X402Client(config?: X402ClientConfig);
|
|
596
|
+
|
|
597
|
+
interface X402ClientConfig {
|
|
598
|
+
facilitatorUrl?: string; // Default: 'https://facilitator.ultravioletadao.xyz'
|
|
599
|
+
defaultChain?: string; // Default: 'base'
|
|
600
|
+
autoConnect?: boolean; // Default: false
|
|
601
|
+
debug?: boolean; // Default: false
|
|
602
|
+
x402Version?: 1 | 2 | 'auto'; // Default: 'auto'
|
|
603
|
+
customChains?: Record<string, Partial<ChainConfig>>;
|
|
604
|
+
rpcOverrides?: Record<string, string>;
|
|
605
|
+
multiPayment?: MultiPaymentConfig;
|
|
606
|
+
}
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
#### Methods
|
|
610
|
+
|
|
611
|
+
| Method | Description |
|
|
612
|
+
|--------|-------------|
|
|
613
|
+
| `connect(chainName?)` | Connect wallet to specified chain |
|
|
614
|
+
| `disconnect()` | Disconnect current wallet |
|
|
615
|
+
| `switchChain(chainName)` | Switch to different EVM chain |
|
|
616
|
+
| `createPayment(paymentInfo)` | Create payment authorization |
|
|
617
|
+
| `getBalance()` | Get USDC balance on current chain |
|
|
618
|
+
| `getState()` | Get current wallet state |
|
|
619
|
+
| `isConnected()` | Check if wallet is connected |
|
|
620
|
+
| `on(event, handler)` | Subscribe to events |
|
|
621
|
+
|
|
622
|
+
### Chain Utilities
|
|
623
|
+
|
|
624
|
+
```typescript
|
|
625
|
+
import {
|
|
626
|
+
SUPPORTED_CHAINS,
|
|
627
|
+
getChainByName,
|
|
628
|
+
getChainById,
|
|
629
|
+
getEnabledChains,
|
|
630
|
+
getChainsByNetworkType,
|
|
631
|
+
getSVMChains,
|
|
632
|
+
isSVMChain,
|
|
633
|
+
getExplorerTxUrl,
|
|
634
|
+
getExplorerAddressUrl,
|
|
635
|
+
} from 'uvd-x402-sdk';
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
### x402 Utilities
|
|
639
|
+
|
|
640
|
+
```typescript
|
|
641
|
+
import {
|
|
642
|
+
detectX402Version,
|
|
643
|
+
chainToCAIP2,
|
|
644
|
+
caip2ToChain,
|
|
645
|
+
createX402V1Header,
|
|
646
|
+
createX402V2Header,
|
|
647
|
+
encodeX402Header,
|
|
648
|
+
decodeX402Header,
|
|
649
|
+
convertX402Header,
|
|
650
|
+
generatePaymentOptions,
|
|
651
|
+
} from 'uvd-x402-sdk';
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
---
|
|
655
|
+
|
|
656
|
+
## Error Handling
|
|
657
|
+
|
|
658
|
+
```typescript
|
|
659
|
+
import { X402Error } from 'uvd-x402-sdk';
|
|
660
|
+
|
|
661
|
+
try {
|
|
662
|
+
await client.createPayment(paymentInfo);
|
|
663
|
+
} catch (error) {
|
|
664
|
+
if (error instanceof X402Error) {
|
|
665
|
+
switch (error.code) {
|
|
666
|
+
case 'WALLET_NOT_FOUND':
|
|
667
|
+
alert('Please install a wallet');
|
|
668
|
+
break;
|
|
669
|
+
case 'WALLET_CONNECTION_REJECTED':
|
|
670
|
+
alert('Connection cancelled');
|
|
671
|
+
break;
|
|
672
|
+
case 'INSUFFICIENT_BALANCE':
|
|
673
|
+
alert('Not enough USDC');
|
|
674
|
+
break;
|
|
675
|
+
case 'SIGNATURE_REJECTED':
|
|
676
|
+
alert('Payment cancelled');
|
|
677
|
+
break;
|
|
678
|
+
case 'CHAIN_NOT_SUPPORTED':
|
|
679
|
+
alert('Network not supported');
|
|
680
|
+
break;
|
|
681
|
+
default:
|
|
682
|
+
alert(error.message);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
### Error Codes
|
|
689
|
+
|
|
690
|
+
| Code | Description |
|
|
691
|
+
|------|-------------|
|
|
692
|
+
| `WALLET_NOT_FOUND` | No compatible wallet detected |
|
|
693
|
+
| `WALLET_NOT_CONNECTED` | Wallet not connected |
|
|
694
|
+
| `WALLET_CONNECTION_REJECTED` | User rejected connection |
|
|
695
|
+
| `CHAIN_NOT_SUPPORTED` | Chain not supported |
|
|
696
|
+
| `CHAIN_SWITCH_REJECTED` | User rejected chain switch |
|
|
697
|
+
| `INSUFFICIENT_BALANCE` | Not enough USDC |
|
|
698
|
+
| `SIGNATURE_REJECTED` | User rejected signature |
|
|
699
|
+
| `PAYMENT_FAILED` | Payment processing failed |
|
|
700
|
+
| `NETWORK_ERROR` | Network request failed |
|
|
701
|
+
| `INVALID_CONFIG` | Invalid configuration |
|
|
702
|
+
|
|
703
|
+
---
|
|
704
|
+
|
|
705
|
+
## Troubleshooting
|
|
706
|
+
|
|
707
|
+
### Common Issues
|
|
708
|
+
|
|
709
|
+
#### "No Ethereum wallet found"
|
|
710
|
+
|
|
711
|
+
Install MetaMask or another EVM wallet. For mobile, use WalletConnect.
|
|
712
|
+
|
|
713
|
+
#### "Phantom wallet not installed"
|
|
714
|
+
|
|
715
|
+
Install Phantom from [phantom.app](https://phantom.app) for Solana/Fogo support.
|
|
716
|
+
|
|
717
|
+
#### "Freighter wallet not installed"
|
|
718
|
+
|
|
719
|
+
Install Freighter from [freighter.app](https://www.freighter.app) for Stellar support.
|
|
720
|
+
|
|
721
|
+
#### "No NEAR wallet found"
|
|
722
|
+
|
|
723
|
+
Install MyNearWallet or Meteor wallet for NEAR support.
|
|
724
|
+
|
|
725
|
+
#### "Chain not supported"
|
|
726
|
+
|
|
727
|
+
Check if the chain is enabled in `SUPPORTED_CHAINS`. BSC is disabled because its USDC doesn't support ERC-3009.
|
|
728
|
+
|
|
729
|
+
#### "Signature rejected by user"
|
|
730
|
+
|
|
731
|
+
User clicked "Reject" in their wallet. This is not an error - just user cancellation.
|
|
732
|
+
|
|
733
|
+
#### Wrong network in X-PAYMENT header
|
|
734
|
+
|
|
735
|
+
For SVM chains, always pass `chainConfig` to `encodePaymentHeader()`:
|
|
736
|
+
|
|
737
|
+
```typescript
|
|
738
|
+
// WRONG - will use 'solana' for Fogo
|
|
739
|
+
const header = svm.encodePaymentHeader(payload);
|
|
740
|
+
|
|
741
|
+
// CORRECT - uses 'fogo' for Fogo
|
|
742
|
+
const fogoConfig = getChainByName('fogo')!;
|
|
743
|
+
const header = svm.encodePaymentHeader(payload, fogoConfig);
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
### Debug Mode
|
|
747
|
+
|
|
748
|
+
Enable debug logging:
|
|
749
|
+
|
|
750
|
+
```typescript
|
|
751
|
+
const client = new X402Client({
|
|
752
|
+
debug: true,
|
|
753
|
+
defaultChain: 'base',
|
|
754
|
+
});
|
|
755
|
+
```
|
|
756
|
+
|
|
757
|
+
---
|
|
758
|
+
|
|
759
|
+
## Security
|
|
760
|
+
|
|
761
|
+
- Users NEVER pay gas or submit transactions directly
|
|
762
|
+
- EVM: Users sign EIP-712 structured messages only
|
|
763
|
+
- Solana/Fogo: Users sign partial transactions (USDC transfer instruction only)
|
|
764
|
+
- Stellar: Users sign Soroban authorization entries only
|
|
765
|
+
- NEAR: Users sign NEP-366 meta-transactions only
|
|
766
|
+
- The facilitator submits and pays for all transactions
|
|
767
|
+
|
|
768
|
+
---
|
|
769
|
+
|
|
770
|
+
## License
|
|
771
|
+
|
|
772
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
773
|
+
|
|
774
|
+
---
|
|
775
|
+
|
|
776
|
+
## Links
|
|
777
|
+
|
|
778
|
+
- [x402 Protocol](https://x402.org)
|
|
779
|
+
- [Ultravioleta DAO](https://ultravioletadao.xyz)
|
|
780
|
+
- [402milly](https://402milly.xyz)
|
|
781
|
+
- [GitHub](https://github.com/ultravioletadao/uvd-x402-sdk)
|
|
782
|
+
- [npm](https://www.npmjs.com/package/uvd-x402-sdk)
|