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
|
@@ -0,0 +1,740 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var ethers = require('ethers');
|
|
6
|
+
|
|
7
|
+
// src/providers/evm/index.ts
|
|
8
|
+
|
|
9
|
+
// src/types/index.ts
|
|
10
|
+
var CAIP2_IDENTIFIERS = {
|
|
11
|
+
// EVM chains
|
|
12
|
+
base: "eip155:8453",
|
|
13
|
+
ethereum: "eip155:1",
|
|
14
|
+
polygon: "eip155:137",
|
|
15
|
+
arbitrum: "eip155:42161",
|
|
16
|
+
optimism: "eip155:10",
|
|
17
|
+
avalanche: "eip155:43114",
|
|
18
|
+
celo: "eip155:42220",
|
|
19
|
+
hyperevm: "eip155:999",
|
|
20
|
+
unichain: "eip155:130",
|
|
21
|
+
monad: "eip155:143",
|
|
22
|
+
bsc: "eip155:56",
|
|
23
|
+
// SVM chains
|
|
24
|
+
solana: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
|
|
25
|
+
fogo: "svm:fogo",
|
|
26
|
+
// Stellar
|
|
27
|
+
stellar: "stellar:pubnet",
|
|
28
|
+
// NEAR
|
|
29
|
+
near: "near:mainnet"
|
|
30
|
+
};
|
|
31
|
+
Object.fromEntries(
|
|
32
|
+
Object.entries(CAIP2_IDENTIFIERS).map(([k, v]) => [v, k])
|
|
33
|
+
);
|
|
34
|
+
var X402Error = class _X402Error extends Error {
|
|
35
|
+
code;
|
|
36
|
+
details;
|
|
37
|
+
constructor(message, code, details) {
|
|
38
|
+
super(message);
|
|
39
|
+
this.name = "X402Error";
|
|
40
|
+
this.code = code;
|
|
41
|
+
this.details = details;
|
|
42
|
+
if (Error.captureStackTrace) {
|
|
43
|
+
Error.captureStackTrace(this, _X402Error);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// src/chains/index.ts
|
|
49
|
+
var DEFAULT_FACILITATOR_URL = "https://facilitator.ultravioletadao.xyz";
|
|
50
|
+
var SUPPORTED_CHAINS = {
|
|
51
|
+
// ============================================================================
|
|
52
|
+
// EVM CHAINS (11 networks)
|
|
53
|
+
// ============================================================================
|
|
54
|
+
base: {
|
|
55
|
+
chainId: 8453,
|
|
56
|
+
chainIdHex: "0x2105",
|
|
57
|
+
name: "base",
|
|
58
|
+
displayName: "Base",
|
|
59
|
+
networkType: "evm",
|
|
60
|
+
rpcUrl: "https://mainnet.base.org",
|
|
61
|
+
explorerUrl: "https://basescan.org",
|
|
62
|
+
nativeCurrency: {
|
|
63
|
+
name: "Ethereum",
|
|
64
|
+
symbol: "ETH",
|
|
65
|
+
decimals: 18
|
|
66
|
+
},
|
|
67
|
+
usdc: {
|
|
68
|
+
address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
69
|
+
decimals: 6,
|
|
70
|
+
name: "USD Coin",
|
|
71
|
+
version: "2"
|
|
72
|
+
},
|
|
73
|
+
x402: {
|
|
74
|
+
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
75
|
+
enabled: true
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
avalanche: {
|
|
79
|
+
chainId: 43114,
|
|
80
|
+
chainIdHex: "0xa86a",
|
|
81
|
+
name: "avalanche",
|
|
82
|
+
displayName: "Avalanche C-Chain",
|
|
83
|
+
networkType: "evm",
|
|
84
|
+
rpcUrl: "https://avalanche-c-chain-rpc.publicnode.com",
|
|
85
|
+
explorerUrl: "https://snowtrace.io",
|
|
86
|
+
nativeCurrency: {
|
|
87
|
+
name: "Avalanche",
|
|
88
|
+
symbol: "AVAX",
|
|
89
|
+
decimals: 18
|
|
90
|
+
},
|
|
91
|
+
usdc: {
|
|
92
|
+
address: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
|
|
93
|
+
decimals: 6,
|
|
94
|
+
name: "USD Coin",
|
|
95
|
+
version: "2"
|
|
96
|
+
},
|
|
97
|
+
x402: {
|
|
98
|
+
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
99
|
+
enabled: true
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
ethereum: {
|
|
103
|
+
chainId: 1,
|
|
104
|
+
chainIdHex: "0x1",
|
|
105
|
+
name: "ethereum",
|
|
106
|
+
displayName: "Ethereum",
|
|
107
|
+
networkType: "evm",
|
|
108
|
+
rpcUrl: "https://eth.llamarpc.com",
|
|
109
|
+
explorerUrl: "https://etherscan.io",
|
|
110
|
+
nativeCurrency: {
|
|
111
|
+
name: "Ethereum",
|
|
112
|
+
symbol: "ETH",
|
|
113
|
+
decimals: 18
|
|
114
|
+
},
|
|
115
|
+
usdc: {
|
|
116
|
+
address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
117
|
+
decimals: 6,
|
|
118
|
+
name: "USD Coin",
|
|
119
|
+
version: "2"
|
|
120
|
+
},
|
|
121
|
+
x402: {
|
|
122
|
+
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
123
|
+
enabled: true
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
polygon: {
|
|
127
|
+
chainId: 137,
|
|
128
|
+
chainIdHex: "0x89",
|
|
129
|
+
name: "polygon",
|
|
130
|
+
displayName: "Polygon",
|
|
131
|
+
networkType: "evm",
|
|
132
|
+
rpcUrl: "https://polygon-rpc.com",
|
|
133
|
+
explorerUrl: "https://polygonscan.com",
|
|
134
|
+
nativeCurrency: {
|
|
135
|
+
name: "Polygon",
|
|
136
|
+
symbol: "POL",
|
|
137
|
+
decimals: 18
|
|
138
|
+
},
|
|
139
|
+
usdc: {
|
|
140
|
+
address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
141
|
+
decimals: 6,
|
|
142
|
+
name: "USD Coin",
|
|
143
|
+
version: "2"
|
|
144
|
+
},
|
|
145
|
+
x402: {
|
|
146
|
+
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
147
|
+
enabled: true
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
arbitrum: {
|
|
151
|
+
chainId: 42161,
|
|
152
|
+
chainIdHex: "0xa4b1",
|
|
153
|
+
name: "arbitrum",
|
|
154
|
+
displayName: "Arbitrum One",
|
|
155
|
+
networkType: "evm",
|
|
156
|
+
rpcUrl: "https://arb1.arbitrum.io/rpc",
|
|
157
|
+
explorerUrl: "https://arbiscan.io",
|
|
158
|
+
nativeCurrency: {
|
|
159
|
+
name: "Ethereum",
|
|
160
|
+
symbol: "ETH",
|
|
161
|
+
decimals: 18
|
|
162
|
+
},
|
|
163
|
+
usdc: {
|
|
164
|
+
address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
|
|
165
|
+
decimals: 6,
|
|
166
|
+
name: "USD Coin",
|
|
167
|
+
version: "2"
|
|
168
|
+
},
|
|
169
|
+
x402: {
|
|
170
|
+
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
171
|
+
enabled: true
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
optimism: {
|
|
175
|
+
chainId: 10,
|
|
176
|
+
chainIdHex: "0xa",
|
|
177
|
+
name: "optimism",
|
|
178
|
+
displayName: "Optimism",
|
|
179
|
+
networkType: "evm",
|
|
180
|
+
rpcUrl: "https://mainnet.optimism.io",
|
|
181
|
+
explorerUrl: "https://optimistic.etherscan.io",
|
|
182
|
+
nativeCurrency: {
|
|
183
|
+
name: "Ethereum",
|
|
184
|
+
symbol: "ETH",
|
|
185
|
+
decimals: 18
|
|
186
|
+
},
|
|
187
|
+
usdc: {
|
|
188
|
+
address: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
|
|
189
|
+
decimals: 6,
|
|
190
|
+
name: "USD Coin",
|
|
191
|
+
version: "2"
|
|
192
|
+
},
|
|
193
|
+
x402: {
|
|
194
|
+
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
195
|
+
enabled: true
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
celo: {
|
|
199
|
+
chainId: 42220,
|
|
200
|
+
chainIdHex: "0xa4ec",
|
|
201
|
+
name: "celo",
|
|
202
|
+
displayName: "Celo",
|
|
203
|
+
networkType: "evm",
|
|
204
|
+
rpcUrl: "https://forno.celo.org",
|
|
205
|
+
explorerUrl: "https://celoscan.io",
|
|
206
|
+
nativeCurrency: {
|
|
207
|
+
name: "Celo",
|
|
208
|
+
symbol: "CELO",
|
|
209
|
+
decimals: 18
|
|
210
|
+
},
|
|
211
|
+
usdc: {
|
|
212
|
+
address: "0xcebA9300f2b948710d2653dD7B07f33A8B32118C",
|
|
213
|
+
decimals: 6,
|
|
214
|
+
name: "USDC",
|
|
215
|
+
// Celo uses "USDC" not "USD Coin" for EIP-712
|
|
216
|
+
version: "2"
|
|
217
|
+
},
|
|
218
|
+
x402: {
|
|
219
|
+
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
220
|
+
enabled: true
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
hyperevm: {
|
|
224
|
+
chainId: 999,
|
|
225
|
+
chainIdHex: "0x3e7",
|
|
226
|
+
name: "hyperevm",
|
|
227
|
+
displayName: "HyperEVM",
|
|
228
|
+
networkType: "evm",
|
|
229
|
+
rpcUrl: "https://rpc.hyperliquid.xyz/evm",
|
|
230
|
+
explorerUrl: "https://hyperevmscan.io",
|
|
231
|
+
nativeCurrency: {
|
|
232
|
+
name: "Ethereum",
|
|
233
|
+
symbol: "ETH",
|
|
234
|
+
decimals: 18
|
|
235
|
+
},
|
|
236
|
+
usdc: {
|
|
237
|
+
address: "0xb88339CB7199b77E23DB6E890353E22632Ba630f",
|
|
238
|
+
decimals: 6,
|
|
239
|
+
name: "USDC",
|
|
240
|
+
// HyperEVM uses "USDC" not "USD Coin"
|
|
241
|
+
version: "2"
|
|
242
|
+
},
|
|
243
|
+
x402: {
|
|
244
|
+
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
245
|
+
enabled: true
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
unichain: {
|
|
249
|
+
chainId: 130,
|
|
250
|
+
chainIdHex: "0x82",
|
|
251
|
+
name: "unichain",
|
|
252
|
+
displayName: "Unichain",
|
|
253
|
+
networkType: "evm",
|
|
254
|
+
rpcUrl: "https://unichain-rpc.publicnode.com",
|
|
255
|
+
explorerUrl: "https://uniscan.xyz",
|
|
256
|
+
nativeCurrency: {
|
|
257
|
+
name: "Ethereum",
|
|
258
|
+
symbol: "ETH",
|
|
259
|
+
decimals: 18
|
|
260
|
+
},
|
|
261
|
+
usdc: {
|
|
262
|
+
address: "0x078d782b760474a361dda0af3839290b0ef57ad6",
|
|
263
|
+
decimals: 6,
|
|
264
|
+
name: "USDC",
|
|
265
|
+
// Unichain uses "USDC" not "USD Coin"
|
|
266
|
+
version: "2"
|
|
267
|
+
},
|
|
268
|
+
x402: {
|
|
269
|
+
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
270
|
+
enabled: true
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
monad: {
|
|
274
|
+
chainId: 143,
|
|
275
|
+
chainIdHex: "0x8f",
|
|
276
|
+
name: "monad",
|
|
277
|
+
displayName: "Monad",
|
|
278
|
+
networkType: "evm",
|
|
279
|
+
rpcUrl: "https://rpc.monad.xyz",
|
|
280
|
+
explorerUrl: "https://monad.socialscan.io",
|
|
281
|
+
nativeCurrency: {
|
|
282
|
+
name: "Monad",
|
|
283
|
+
symbol: "MON",
|
|
284
|
+
decimals: 18
|
|
285
|
+
},
|
|
286
|
+
usdc: {
|
|
287
|
+
address: "0x754704bc059f8c67012fed69bc8a327a5aafb603",
|
|
288
|
+
decimals: 6,
|
|
289
|
+
name: "USDC",
|
|
290
|
+
// Monad uses "USDC" not "USD Coin"
|
|
291
|
+
version: "2"
|
|
292
|
+
},
|
|
293
|
+
x402: {
|
|
294
|
+
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
295
|
+
enabled: true
|
|
296
|
+
}
|
|
297
|
+
},
|
|
298
|
+
// BSC disabled: USDC doesn't support ERC-3009 transferWithAuthorization
|
|
299
|
+
bsc: {
|
|
300
|
+
chainId: 56,
|
|
301
|
+
chainIdHex: "0x38",
|
|
302
|
+
name: "bsc",
|
|
303
|
+
displayName: "BNB Smart Chain",
|
|
304
|
+
networkType: "evm",
|
|
305
|
+
rpcUrl: "https://binance.llamarpc.com",
|
|
306
|
+
explorerUrl: "https://bscscan.com",
|
|
307
|
+
nativeCurrency: {
|
|
308
|
+
name: "Binance Coin",
|
|
309
|
+
symbol: "BNB",
|
|
310
|
+
decimals: 18
|
|
311
|
+
},
|
|
312
|
+
usdc: {
|
|
313
|
+
address: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",
|
|
314
|
+
decimals: 18,
|
|
315
|
+
// BSC USDC uses 18 decimals
|
|
316
|
+
name: "USD Coin",
|
|
317
|
+
version: "2"
|
|
318
|
+
},
|
|
319
|
+
x402: {
|
|
320
|
+
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
321
|
+
enabled: false
|
|
322
|
+
// Disabled: BSC USDC doesn't support ERC-3009
|
|
323
|
+
}
|
|
324
|
+
},
|
|
325
|
+
// ============================================================================
|
|
326
|
+
// SVM CHAINS (2 networks) - Solana Virtual Machine
|
|
327
|
+
// ============================================================================
|
|
328
|
+
solana: {
|
|
329
|
+
chainId: 0,
|
|
330
|
+
// Non-EVM
|
|
331
|
+
chainIdHex: "0x0",
|
|
332
|
+
name: "solana",
|
|
333
|
+
displayName: "Solana",
|
|
334
|
+
networkType: "svm",
|
|
335
|
+
rpcUrl: "https://api.mainnet-beta.solana.com",
|
|
336
|
+
explorerUrl: "https://solscan.io",
|
|
337
|
+
nativeCurrency: {
|
|
338
|
+
name: "Solana",
|
|
339
|
+
symbol: "SOL",
|
|
340
|
+
decimals: 9
|
|
341
|
+
},
|
|
342
|
+
usdc: {
|
|
343
|
+
address: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
|
|
344
|
+
// USDC SPL token mint
|
|
345
|
+
decimals: 6,
|
|
346
|
+
name: "USD Coin",
|
|
347
|
+
version: "1"
|
|
348
|
+
},
|
|
349
|
+
x402: {
|
|
350
|
+
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
351
|
+
enabled: true
|
|
352
|
+
}
|
|
353
|
+
},
|
|
354
|
+
fogo: {
|
|
355
|
+
chainId: 0,
|
|
356
|
+
// Non-EVM (SVM)
|
|
357
|
+
chainIdHex: "0x0",
|
|
358
|
+
name: "fogo",
|
|
359
|
+
displayName: "Fogo",
|
|
360
|
+
networkType: "svm",
|
|
361
|
+
rpcUrl: "https://rpc.fogo.nightly.app/",
|
|
362
|
+
explorerUrl: "https://explorer.fogo.nightly.app",
|
|
363
|
+
nativeCurrency: {
|
|
364
|
+
name: "Fogo",
|
|
365
|
+
symbol: "FOGO",
|
|
366
|
+
decimals: 9
|
|
367
|
+
},
|
|
368
|
+
usdc: {
|
|
369
|
+
address: "uSd2czE61Evaf76RNbq4KPpXnkiL3irdzgLFUMe3NoG",
|
|
370
|
+
// Fogo USDC mint
|
|
371
|
+
decimals: 6,
|
|
372
|
+
name: "USDC",
|
|
373
|
+
version: "1"
|
|
374
|
+
},
|
|
375
|
+
x402: {
|
|
376
|
+
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
377
|
+
enabled: true
|
|
378
|
+
}
|
|
379
|
+
},
|
|
380
|
+
// ============================================================================
|
|
381
|
+
// STELLAR (1 network)
|
|
382
|
+
// ============================================================================
|
|
383
|
+
stellar: {
|
|
384
|
+
chainId: 0,
|
|
385
|
+
// Non-EVM
|
|
386
|
+
chainIdHex: "0x0",
|
|
387
|
+
name: "stellar",
|
|
388
|
+
displayName: "Stellar",
|
|
389
|
+
networkType: "stellar",
|
|
390
|
+
rpcUrl: "https://horizon.stellar.org",
|
|
391
|
+
explorerUrl: "https://stellar.expert/explorer/public",
|
|
392
|
+
nativeCurrency: {
|
|
393
|
+
name: "Lumens",
|
|
394
|
+
symbol: "XLM",
|
|
395
|
+
decimals: 7
|
|
396
|
+
// Stellar uses 7 decimals (stroops)
|
|
397
|
+
},
|
|
398
|
+
usdc: {
|
|
399
|
+
address: "CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75",
|
|
400
|
+
// Soroban Asset Contract
|
|
401
|
+
decimals: 7,
|
|
402
|
+
// Stellar USDC uses 7 decimals
|
|
403
|
+
name: "USDC",
|
|
404
|
+
version: "1"
|
|
405
|
+
},
|
|
406
|
+
x402: {
|
|
407
|
+
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
408
|
+
enabled: true
|
|
409
|
+
}
|
|
410
|
+
},
|
|
411
|
+
// ============================================================================
|
|
412
|
+
// NEAR (1 network) - Uses NEP-366 meta-transactions
|
|
413
|
+
// ============================================================================
|
|
414
|
+
near: {
|
|
415
|
+
chainId: 0,
|
|
416
|
+
// Non-EVM
|
|
417
|
+
chainIdHex: "0x0",
|
|
418
|
+
name: "near",
|
|
419
|
+
displayName: "NEAR Protocol",
|
|
420
|
+
networkType: "near",
|
|
421
|
+
rpcUrl: "https://rpc.mainnet.near.org",
|
|
422
|
+
explorerUrl: "https://nearblocks.io",
|
|
423
|
+
nativeCurrency: {
|
|
424
|
+
name: "NEAR",
|
|
425
|
+
symbol: "NEAR",
|
|
426
|
+
decimals: 24
|
|
427
|
+
// NEAR uses 24 decimals (yoctoNEAR)
|
|
428
|
+
},
|
|
429
|
+
usdc: {
|
|
430
|
+
address: "17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1",
|
|
431
|
+
// Native Circle USDC
|
|
432
|
+
decimals: 6,
|
|
433
|
+
name: "USDC",
|
|
434
|
+
version: "1"
|
|
435
|
+
},
|
|
436
|
+
x402: {
|
|
437
|
+
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
438
|
+
enabled: true
|
|
439
|
+
// NEP-366 meta-transactions supported
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
function getChainById(chainId) {
|
|
444
|
+
return Object.values(SUPPORTED_CHAINS).find((chain) => chain.chainId === chainId);
|
|
445
|
+
}
|
|
446
|
+
function getChainByName(name) {
|
|
447
|
+
return SUPPORTED_CHAINS[name.toLowerCase()];
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// src/providers/evm/index.ts
|
|
451
|
+
var EVMProvider = class {
|
|
452
|
+
id = "injected";
|
|
453
|
+
name = "EVM Wallet";
|
|
454
|
+
networkType = "evm";
|
|
455
|
+
provider = null;
|
|
456
|
+
signer = null;
|
|
457
|
+
address = null;
|
|
458
|
+
chainId = null;
|
|
459
|
+
chainName = null;
|
|
460
|
+
/**
|
|
461
|
+
* Check if an EVM wallet is available
|
|
462
|
+
*/
|
|
463
|
+
isAvailable() {
|
|
464
|
+
if (typeof window === "undefined") return false;
|
|
465
|
+
return typeof window.ethereum !== "undefined";
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Connect to an EVM wallet
|
|
469
|
+
*/
|
|
470
|
+
async connect(chainName) {
|
|
471
|
+
const targetChainName = chainName || "base";
|
|
472
|
+
const chain = getChainByName(targetChainName);
|
|
473
|
+
if (!chain) {
|
|
474
|
+
throw new X402Error(`Unsupported chain: ${targetChainName}`, "CHAIN_NOT_SUPPORTED");
|
|
475
|
+
}
|
|
476
|
+
if (chain.networkType !== "evm") {
|
|
477
|
+
throw new X402Error(`${targetChainName} is not an EVM chain`, "CHAIN_NOT_SUPPORTED");
|
|
478
|
+
}
|
|
479
|
+
const ethereum = window.ethereum;
|
|
480
|
+
if (!ethereum) {
|
|
481
|
+
throw new X402Error(
|
|
482
|
+
"No Ethereum wallet found. Please install MetaMask or another EVM wallet.",
|
|
483
|
+
"WALLET_NOT_FOUND"
|
|
484
|
+
);
|
|
485
|
+
}
|
|
486
|
+
try {
|
|
487
|
+
this.provider = new ethers.ethers.BrowserProvider(ethereum);
|
|
488
|
+
await this.provider.send("eth_requestAccounts", []);
|
|
489
|
+
await this.switchChain(targetChainName);
|
|
490
|
+
this.signer = await this.provider.getSigner();
|
|
491
|
+
this.address = await this.signer.getAddress();
|
|
492
|
+
return this.address;
|
|
493
|
+
} catch (error) {
|
|
494
|
+
if (error instanceof Error) {
|
|
495
|
+
if (error.message.includes("User rejected") || error.code === 4001) {
|
|
496
|
+
throw new X402Error("Connection rejected by user", "WALLET_CONNECTION_REJECTED");
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
throw new X402Error(
|
|
500
|
+
`Failed to connect wallet: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
501
|
+
"UNKNOWN_ERROR",
|
|
502
|
+
error
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Disconnect from wallet
|
|
508
|
+
*/
|
|
509
|
+
async disconnect() {
|
|
510
|
+
this.provider = null;
|
|
511
|
+
this.signer = null;
|
|
512
|
+
this.address = null;
|
|
513
|
+
this.chainId = null;
|
|
514
|
+
this.chainName = null;
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Switch to a different EVM chain
|
|
518
|
+
*/
|
|
519
|
+
async switchChain(chainName) {
|
|
520
|
+
const chain = getChainByName(chainName);
|
|
521
|
+
if (!chain) {
|
|
522
|
+
throw new X402Error(`Unsupported chain: ${chainName}`, "CHAIN_NOT_SUPPORTED");
|
|
523
|
+
}
|
|
524
|
+
if (!this.provider) {
|
|
525
|
+
throw new X402Error("Wallet not connected", "WALLET_NOT_CONNECTED");
|
|
526
|
+
}
|
|
527
|
+
try {
|
|
528
|
+
await this.provider.send("wallet_switchEthereumChain", [{ chainId: chain.chainIdHex }]);
|
|
529
|
+
} catch (switchError) {
|
|
530
|
+
if (switchError.code === 4902) {
|
|
531
|
+
try {
|
|
532
|
+
await this.provider.send("wallet_addEthereumChain", [
|
|
533
|
+
{
|
|
534
|
+
chainId: chain.chainIdHex,
|
|
535
|
+
chainName: chain.displayName,
|
|
536
|
+
nativeCurrency: chain.nativeCurrency,
|
|
537
|
+
rpcUrls: [chain.rpcUrl],
|
|
538
|
+
blockExplorerUrls: [chain.explorerUrl]
|
|
539
|
+
}
|
|
540
|
+
]);
|
|
541
|
+
} catch (addError) {
|
|
542
|
+
throw new X402Error(
|
|
543
|
+
`Failed to add ${chain.displayName} network`,
|
|
544
|
+
"CHAIN_SWITCH_REJECTED",
|
|
545
|
+
addError
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
} else if (switchError.code === 4001) {
|
|
549
|
+
throw new X402Error("Network switch rejected by user", "CHAIN_SWITCH_REJECTED");
|
|
550
|
+
} else {
|
|
551
|
+
throw new X402Error(
|
|
552
|
+
`Failed to switch to ${chain.displayName}`,
|
|
553
|
+
"CHAIN_SWITCH_REJECTED",
|
|
554
|
+
switchError
|
|
555
|
+
);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
this.chainId = chain.chainId;
|
|
559
|
+
this.chainName = chain.name;
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Get current address
|
|
563
|
+
*/
|
|
564
|
+
getAddress() {
|
|
565
|
+
return this.address;
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Get current chain ID
|
|
569
|
+
*/
|
|
570
|
+
getChainId() {
|
|
571
|
+
return this.chainId;
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Get current chain name
|
|
575
|
+
*/
|
|
576
|
+
getChainName() {
|
|
577
|
+
return this.chainName;
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Get USDC balance
|
|
581
|
+
*/
|
|
582
|
+
async getBalance(chainConfig) {
|
|
583
|
+
if (!this.address) {
|
|
584
|
+
throw new X402Error("Wallet not connected", "WALLET_NOT_CONNECTED");
|
|
585
|
+
}
|
|
586
|
+
const publicProvider = new ethers.ethers.JsonRpcProvider(chainConfig.rpcUrl);
|
|
587
|
+
const usdcAbi = ["function balanceOf(address owner) view returns (uint256)"];
|
|
588
|
+
const usdcContract = new ethers.ethers.Contract(chainConfig.usdc.address, usdcAbi, publicProvider);
|
|
589
|
+
try {
|
|
590
|
+
const balance = await usdcContract.balanceOf(this.address);
|
|
591
|
+
const formatted = ethers.ethers.formatUnits(balance, chainConfig.usdc.decimals);
|
|
592
|
+
return parseFloat(formatted).toFixed(2);
|
|
593
|
+
} catch {
|
|
594
|
+
return "0.00";
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Create EVM payment (EIP-712 TransferWithAuthorization)
|
|
599
|
+
*/
|
|
600
|
+
async signPayment(paymentInfo, chainConfig) {
|
|
601
|
+
if (!this.signer || !this.address) {
|
|
602
|
+
throw new X402Error("Wallet not connected", "WALLET_NOT_CONNECTED");
|
|
603
|
+
}
|
|
604
|
+
const recipient = paymentInfo.recipients?.evm || paymentInfo.recipient;
|
|
605
|
+
const nonceBytes = new Uint8Array(32);
|
|
606
|
+
if (typeof window !== "undefined" && window.crypto) {
|
|
607
|
+
window.crypto.getRandomValues(nonceBytes);
|
|
608
|
+
} else {
|
|
609
|
+
for (let i = 0; i < 32; i++) {
|
|
610
|
+
nonceBytes[i] = Math.floor(Math.random() * 256);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
const nonce = ethers.ethers.hexlify(nonceBytes);
|
|
614
|
+
const validAfter = 0;
|
|
615
|
+
const validityWindowSeconds = chainConfig.name === "base" ? 300 : 60;
|
|
616
|
+
const validBefore = Math.floor(Date.now() / 1e3) + validityWindowSeconds;
|
|
617
|
+
const domain = {
|
|
618
|
+
name: chainConfig.usdc.name,
|
|
619
|
+
version: chainConfig.usdc.version,
|
|
620
|
+
chainId: chainConfig.chainId,
|
|
621
|
+
verifyingContract: chainConfig.usdc.address
|
|
622
|
+
};
|
|
623
|
+
const types = {
|
|
624
|
+
TransferWithAuthorization: [
|
|
625
|
+
{ name: "from", type: "address" },
|
|
626
|
+
{ name: "to", type: "address" },
|
|
627
|
+
{ name: "value", type: "uint256" },
|
|
628
|
+
{ name: "validAfter", type: "uint256" },
|
|
629
|
+
{ name: "validBefore", type: "uint256" },
|
|
630
|
+
{ name: "nonce", type: "bytes32" }
|
|
631
|
+
]
|
|
632
|
+
};
|
|
633
|
+
const value = ethers.ethers.parseUnits(paymentInfo.amount, chainConfig.usdc.decimals);
|
|
634
|
+
const from = this.address;
|
|
635
|
+
const to = ethers.ethers.getAddress(recipient);
|
|
636
|
+
const message = {
|
|
637
|
+
from,
|
|
638
|
+
to,
|
|
639
|
+
value,
|
|
640
|
+
validAfter,
|
|
641
|
+
validBefore,
|
|
642
|
+
nonce
|
|
643
|
+
};
|
|
644
|
+
let signature;
|
|
645
|
+
try {
|
|
646
|
+
signature = await this.signer.signTypedData(domain, types, message);
|
|
647
|
+
} catch (error) {
|
|
648
|
+
if (error instanceof Error && (error.message.includes("User rejected") || error.code === 4001)) {
|
|
649
|
+
throw new X402Error("Signature rejected by user", "SIGNATURE_REJECTED");
|
|
650
|
+
}
|
|
651
|
+
throw new X402Error(
|
|
652
|
+
`Failed to sign payment: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
653
|
+
"PAYMENT_FAILED",
|
|
654
|
+
error
|
|
655
|
+
);
|
|
656
|
+
}
|
|
657
|
+
const sig = ethers.ethers.Signature.from(signature);
|
|
658
|
+
const payload = {
|
|
659
|
+
from,
|
|
660
|
+
to,
|
|
661
|
+
value: value.toString(),
|
|
662
|
+
validAfter,
|
|
663
|
+
validBefore,
|
|
664
|
+
nonce,
|
|
665
|
+
v: sig.v,
|
|
666
|
+
r: sig.r,
|
|
667
|
+
s: sig.s,
|
|
668
|
+
chainId: chainConfig.chainId,
|
|
669
|
+
token: chainConfig.usdc.address
|
|
670
|
+
};
|
|
671
|
+
return JSON.stringify(payload);
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* Encode EVM payment as X-PAYMENT header
|
|
675
|
+
*/
|
|
676
|
+
encodePaymentHeader(paymentPayload, chainConfig) {
|
|
677
|
+
const payload = JSON.parse(paymentPayload);
|
|
678
|
+
const fullSignature = payload.r + payload.s.slice(2) + payload.v.toString(16).padStart(2, "0");
|
|
679
|
+
const x402Payload = {
|
|
680
|
+
x402Version: 1,
|
|
681
|
+
scheme: "exact",
|
|
682
|
+
network: chainConfig.name,
|
|
683
|
+
payload: {
|
|
684
|
+
signature: fullSignature,
|
|
685
|
+
authorization: {
|
|
686
|
+
from: payload.from,
|
|
687
|
+
to: payload.to,
|
|
688
|
+
value: payload.value,
|
|
689
|
+
validAfter: payload.validAfter.toString(),
|
|
690
|
+
validBefore: payload.validBefore.toString(),
|
|
691
|
+
nonce: payload.nonce
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
};
|
|
695
|
+
return btoa(JSON.stringify(x402Payload));
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Setup event listeners for wallet events
|
|
699
|
+
*/
|
|
700
|
+
setupEventListeners(onAccountsChanged, onChainChanged) {
|
|
701
|
+
const ethereum = window.ethereum;
|
|
702
|
+
if (!ethereum?.on || !ethereum?.removeListener) {
|
|
703
|
+
return () => {
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
const handleAccountsChanged = (accounts) => {
|
|
707
|
+
if (Array.isArray(accounts)) {
|
|
708
|
+
if (accounts.length === 0) {
|
|
709
|
+
this.disconnect();
|
|
710
|
+
} else if (accounts[0] !== this.address) {
|
|
711
|
+
this.address = accounts[0];
|
|
712
|
+
}
|
|
713
|
+
onAccountsChanged?.(accounts);
|
|
714
|
+
}
|
|
715
|
+
};
|
|
716
|
+
const handleChainChanged = (chainIdHex) => {
|
|
717
|
+
if (typeof chainIdHex === "string") {
|
|
718
|
+
const chainId = parseInt(chainIdHex, 16);
|
|
719
|
+
const chain = getChainById(chainId);
|
|
720
|
+
if (chain) {
|
|
721
|
+
this.chainId = chainId;
|
|
722
|
+
this.chainName = chain.name;
|
|
723
|
+
}
|
|
724
|
+
onChainChanged?.(chainId);
|
|
725
|
+
}
|
|
726
|
+
};
|
|
727
|
+
ethereum.on("accountsChanged", handleAccountsChanged);
|
|
728
|
+
ethereum.on("chainChanged", handleChainChanged);
|
|
729
|
+
return () => {
|
|
730
|
+
ethereum.removeListener("accountsChanged", handleAccountsChanged);
|
|
731
|
+
ethereum.removeListener("chainChanged", handleChainChanged);
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
};
|
|
735
|
+
var evm_default = EVMProvider;
|
|
736
|
+
|
|
737
|
+
exports.EVMProvider = EVMProvider;
|
|
738
|
+
exports.default = evm_default;
|
|
739
|
+
//# sourceMappingURL=index.js.map
|
|
740
|
+
//# sourceMappingURL=index.js.map
|