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.
Files changed (61) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +782 -0
  3. package/dist/index-BrBqP1I8.d.ts +199 -0
  4. package/dist/index-D6Sr4ARD.d.mts +429 -0
  5. package/dist/index-D6Sr4ARD.d.ts +429 -0
  6. package/dist/index-DJ4Cvrev.d.mts +199 -0
  7. package/dist/index.d.mts +3 -0
  8. package/dist/index.d.ts +3 -0
  9. package/dist/index.js +1178 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/index.mjs +1146 -0
  12. package/dist/index.mjs.map +1 -0
  13. package/dist/providers/evm/index.d.mts +84 -0
  14. package/dist/providers/evm/index.d.ts +84 -0
  15. package/dist/providers/evm/index.js +740 -0
  16. package/dist/providers/evm/index.js.map +1 -0
  17. package/dist/providers/evm/index.mjs +735 -0
  18. package/dist/providers/evm/index.mjs.map +1 -0
  19. package/dist/providers/near/index.d.mts +99 -0
  20. package/dist/providers/near/index.d.ts +99 -0
  21. package/dist/providers/near/index.js +483 -0
  22. package/dist/providers/near/index.js.map +1 -0
  23. package/dist/providers/near/index.mjs +478 -0
  24. package/dist/providers/near/index.mjs.map +1 -0
  25. package/dist/providers/solana/index.d.mts +115 -0
  26. package/dist/providers/solana/index.d.ts +115 -0
  27. package/dist/providers/solana/index.js +771 -0
  28. package/dist/providers/solana/index.js.map +1 -0
  29. package/dist/providers/solana/index.mjs +765 -0
  30. package/dist/providers/solana/index.mjs.map +1 -0
  31. package/dist/providers/stellar/index.d.mts +67 -0
  32. package/dist/providers/stellar/index.d.ts +67 -0
  33. package/dist/providers/stellar/index.js +306 -0
  34. package/dist/providers/stellar/index.js.map +1 -0
  35. package/dist/providers/stellar/index.mjs +301 -0
  36. package/dist/providers/stellar/index.mjs.map +1 -0
  37. package/dist/react/index.d.mts +73 -0
  38. package/dist/react/index.d.ts +73 -0
  39. package/dist/react/index.js +1218 -0
  40. package/dist/react/index.js.map +1 -0
  41. package/dist/react/index.mjs +1211 -0
  42. package/dist/react/index.mjs.map +1 -0
  43. package/dist/utils/index.d.mts +103 -0
  44. package/dist/utils/index.d.ts +103 -0
  45. package/dist/utils/index.js +575 -0
  46. package/dist/utils/index.js.map +1 -0
  47. package/dist/utils/index.mjs +562 -0
  48. package/dist/utils/index.mjs.map +1 -0
  49. package/package.json +149 -0
  50. package/src/chains/index.ts +539 -0
  51. package/src/client/X402Client.ts +663 -0
  52. package/src/client/index.ts +1 -0
  53. package/src/index.ts +166 -0
  54. package/src/providers/evm/index.ts +394 -0
  55. package/src/providers/near/index.ts +664 -0
  56. package/src/providers/solana/index.ts +489 -0
  57. package/src/providers/stellar/index.ts +376 -0
  58. package/src/react/index.tsx +417 -0
  59. package/src/types/index.ts +561 -0
  60. package/src/utils/index.ts +20 -0
  61. package/src/utils/x402.ts +295 -0
@@ -0,0 +1,771 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ // src/types/index.ts
6
+ var CAIP2_IDENTIFIERS = {
7
+ // EVM chains
8
+ base: "eip155:8453",
9
+ ethereum: "eip155:1",
10
+ polygon: "eip155:137",
11
+ arbitrum: "eip155:42161",
12
+ optimism: "eip155:10",
13
+ avalanche: "eip155:43114",
14
+ celo: "eip155:42220",
15
+ hyperevm: "eip155:999",
16
+ unichain: "eip155:130",
17
+ monad: "eip155:143",
18
+ bsc: "eip155:56",
19
+ // SVM chains
20
+ solana: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
21
+ fogo: "svm:fogo",
22
+ // Stellar
23
+ stellar: "stellar:pubnet",
24
+ // NEAR
25
+ near: "near:mainnet"
26
+ };
27
+ Object.fromEntries(
28
+ Object.entries(CAIP2_IDENTIFIERS).map(([k, v]) => [v, k])
29
+ );
30
+ var X402Error = class _X402Error extends Error {
31
+ code;
32
+ details;
33
+ constructor(message, code, details) {
34
+ super(message);
35
+ this.name = "X402Error";
36
+ this.code = code;
37
+ this.details = details;
38
+ if (Error.captureStackTrace) {
39
+ Error.captureStackTrace(this, _X402Error);
40
+ }
41
+ }
42
+ };
43
+
44
+ // src/chains/index.ts
45
+ var DEFAULT_FACILITATOR_URL = "https://facilitator.ultravioletadao.xyz";
46
+ var SUPPORTED_CHAINS = {
47
+ // ============================================================================
48
+ // EVM CHAINS (11 networks)
49
+ // ============================================================================
50
+ base: {
51
+ chainId: 8453,
52
+ chainIdHex: "0x2105",
53
+ name: "base",
54
+ displayName: "Base",
55
+ networkType: "evm",
56
+ rpcUrl: "https://mainnet.base.org",
57
+ explorerUrl: "https://basescan.org",
58
+ nativeCurrency: {
59
+ name: "Ethereum",
60
+ symbol: "ETH",
61
+ decimals: 18
62
+ },
63
+ usdc: {
64
+ address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
65
+ decimals: 6,
66
+ name: "USD Coin",
67
+ version: "2"
68
+ },
69
+ x402: {
70
+ facilitatorUrl: DEFAULT_FACILITATOR_URL,
71
+ enabled: true
72
+ }
73
+ },
74
+ avalanche: {
75
+ chainId: 43114,
76
+ chainIdHex: "0xa86a",
77
+ name: "avalanche",
78
+ displayName: "Avalanche C-Chain",
79
+ networkType: "evm",
80
+ rpcUrl: "https://avalanche-c-chain-rpc.publicnode.com",
81
+ explorerUrl: "https://snowtrace.io",
82
+ nativeCurrency: {
83
+ name: "Avalanche",
84
+ symbol: "AVAX",
85
+ decimals: 18
86
+ },
87
+ usdc: {
88
+ address: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
89
+ decimals: 6,
90
+ name: "USD Coin",
91
+ version: "2"
92
+ },
93
+ x402: {
94
+ facilitatorUrl: DEFAULT_FACILITATOR_URL,
95
+ enabled: true
96
+ }
97
+ },
98
+ ethereum: {
99
+ chainId: 1,
100
+ chainIdHex: "0x1",
101
+ name: "ethereum",
102
+ displayName: "Ethereum",
103
+ networkType: "evm",
104
+ rpcUrl: "https://eth.llamarpc.com",
105
+ explorerUrl: "https://etherscan.io",
106
+ nativeCurrency: {
107
+ name: "Ethereum",
108
+ symbol: "ETH",
109
+ decimals: 18
110
+ },
111
+ usdc: {
112
+ address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
113
+ decimals: 6,
114
+ name: "USD Coin",
115
+ version: "2"
116
+ },
117
+ x402: {
118
+ facilitatorUrl: DEFAULT_FACILITATOR_URL,
119
+ enabled: true
120
+ }
121
+ },
122
+ polygon: {
123
+ chainId: 137,
124
+ chainIdHex: "0x89",
125
+ name: "polygon",
126
+ displayName: "Polygon",
127
+ networkType: "evm",
128
+ rpcUrl: "https://polygon-rpc.com",
129
+ explorerUrl: "https://polygonscan.com",
130
+ nativeCurrency: {
131
+ name: "Polygon",
132
+ symbol: "POL",
133
+ decimals: 18
134
+ },
135
+ usdc: {
136
+ address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
137
+ decimals: 6,
138
+ name: "USD Coin",
139
+ version: "2"
140
+ },
141
+ x402: {
142
+ facilitatorUrl: DEFAULT_FACILITATOR_URL,
143
+ enabled: true
144
+ }
145
+ },
146
+ arbitrum: {
147
+ chainId: 42161,
148
+ chainIdHex: "0xa4b1",
149
+ name: "arbitrum",
150
+ displayName: "Arbitrum One",
151
+ networkType: "evm",
152
+ rpcUrl: "https://arb1.arbitrum.io/rpc",
153
+ explorerUrl: "https://arbiscan.io",
154
+ nativeCurrency: {
155
+ name: "Ethereum",
156
+ symbol: "ETH",
157
+ decimals: 18
158
+ },
159
+ usdc: {
160
+ address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
161
+ decimals: 6,
162
+ name: "USD Coin",
163
+ version: "2"
164
+ },
165
+ x402: {
166
+ facilitatorUrl: DEFAULT_FACILITATOR_URL,
167
+ enabled: true
168
+ }
169
+ },
170
+ optimism: {
171
+ chainId: 10,
172
+ chainIdHex: "0xa",
173
+ name: "optimism",
174
+ displayName: "Optimism",
175
+ networkType: "evm",
176
+ rpcUrl: "https://mainnet.optimism.io",
177
+ explorerUrl: "https://optimistic.etherscan.io",
178
+ nativeCurrency: {
179
+ name: "Ethereum",
180
+ symbol: "ETH",
181
+ decimals: 18
182
+ },
183
+ usdc: {
184
+ address: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
185
+ decimals: 6,
186
+ name: "USD Coin",
187
+ version: "2"
188
+ },
189
+ x402: {
190
+ facilitatorUrl: DEFAULT_FACILITATOR_URL,
191
+ enabled: true
192
+ }
193
+ },
194
+ celo: {
195
+ chainId: 42220,
196
+ chainIdHex: "0xa4ec",
197
+ name: "celo",
198
+ displayName: "Celo",
199
+ networkType: "evm",
200
+ rpcUrl: "https://forno.celo.org",
201
+ explorerUrl: "https://celoscan.io",
202
+ nativeCurrency: {
203
+ name: "Celo",
204
+ symbol: "CELO",
205
+ decimals: 18
206
+ },
207
+ usdc: {
208
+ address: "0xcebA9300f2b948710d2653dD7B07f33A8B32118C",
209
+ decimals: 6,
210
+ name: "USDC",
211
+ // Celo uses "USDC" not "USD Coin" for EIP-712
212
+ version: "2"
213
+ },
214
+ x402: {
215
+ facilitatorUrl: DEFAULT_FACILITATOR_URL,
216
+ enabled: true
217
+ }
218
+ },
219
+ hyperevm: {
220
+ chainId: 999,
221
+ chainIdHex: "0x3e7",
222
+ name: "hyperevm",
223
+ displayName: "HyperEVM",
224
+ networkType: "evm",
225
+ rpcUrl: "https://rpc.hyperliquid.xyz/evm",
226
+ explorerUrl: "https://hyperevmscan.io",
227
+ nativeCurrency: {
228
+ name: "Ethereum",
229
+ symbol: "ETH",
230
+ decimals: 18
231
+ },
232
+ usdc: {
233
+ address: "0xb88339CB7199b77E23DB6E890353E22632Ba630f",
234
+ decimals: 6,
235
+ name: "USDC",
236
+ // HyperEVM uses "USDC" not "USD Coin"
237
+ version: "2"
238
+ },
239
+ x402: {
240
+ facilitatorUrl: DEFAULT_FACILITATOR_URL,
241
+ enabled: true
242
+ }
243
+ },
244
+ unichain: {
245
+ chainId: 130,
246
+ chainIdHex: "0x82",
247
+ name: "unichain",
248
+ displayName: "Unichain",
249
+ networkType: "evm",
250
+ rpcUrl: "https://unichain-rpc.publicnode.com",
251
+ explorerUrl: "https://uniscan.xyz",
252
+ nativeCurrency: {
253
+ name: "Ethereum",
254
+ symbol: "ETH",
255
+ decimals: 18
256
+ },
257
+ usdc: {
258
+ address: "0x078d782b760474a361dda0af3839290b0ef57ad6",
259
+ decimals: 6,
260
+ name: "USDC",
261
+ // Unichain uses "USDC" not "USD Coin"
262
+ version: "2"
263
+ },
264
+ x402: {
265
+ facilitatorUrl: DEFAULT_FACILITATOR_URL,
266
+ enabled: true
267
+ }
268
+ },
269
+ monad: {
270
+ chainId: 143,
271
+ chainIdHex: "0x8f",
272
+ name: "monad",
273
+ displayName: "Monad",
274
+ networkType: "evm",
275
+ rpcUrl: "https://rpc.monad.xyz",
276
+ explorerUrl: "https://monad.socialscan.io",
277
+ nativeCurrency: {
278
+ name: "Monad",
279
+ symbol: "MON",
280
+ decimals: 18
281
+ },
282
+ usdc: {
283
+ address: "0x754704bc059f8c67012fed69bc8a327a5aafb603",
284
+ decimals: 6,
285
+ name: "USDC",
286
+ // Monad uses "USDC" not "USD Coin"
287
+ version: "2"
288
+ },
289
+ x402: {
290
+ facilitatorUrl: DEFAULT_FACILITATOR_URL,
291
+ enabled: true
292
+ }
293
+ },
294
+ // BSC disabled: USDC doesn't support ERC-3009 transferWithAuthorization
295
+ bsc: {
296
+ chainId: 56,
297
+ chainIdHex: "0x38",
298
+ name: "bsc",
299
+ displayName: "BNB Smart Chain",
300
+ networkType: "evm",
301
+ rpcUrl: "https://binance.llamarpc.com",
302
+ explorerUrl: "https://bscscan.com",
303
+ nativeCurrency: {
304
+ name: "Binance Coin",
305
+ symbol: "BNB",
306
+ decimals: 18
307
+ },
308
+ usdc: {
309
+ address: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",
310
+ decimals: 18,
311
+ // BSC USDC uses 18 decimals
312
+ name: "USD Coin",
313
+ version: "2"
314
+ },
315
+ x402: {
316
+ facilitatorUrl: DEFAULT_FACILITATOR_URL,
317
+ enabled: false
318
+ // Disabled: BSC USDC doesn't support ERC-3009
319
+ }
320
+ },
321
+ // ============================================================================
322
+ // SVM CHAINS (2 networks) - Solana Virtual Machine
323
+ // ============================================================================
324
+ solana: {
325
+ chainId: 0,
326
+ // Non-EVM
327
+ chainIdHex: "0x0",
328
+ name: "solana",
329
+ displayName: "Solana",
330
+ networkType: "svm",
331
+ rpcUrl: "https://api.mainnet-beta.solana.com",
332
+ explorerUrl: "https://solscan.io",
333
+ nativeCurrency: {
334
+ name: "Solana",
335
+ symbol: "SOL",
336
+ decimals: 9
337
+ },
338
+ usdc: {
339
+ address: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
340
+ // USDC SPL token mint
341
+ decimals: 6,
342
+ name: "USD Coin",
343
+ version: "1"
344
+ },
345
+ x402: {
346
+ facilitatorUrl: DEFAULT_FACILITATOR_URL,
347
+ enabled: true
348
+ }
349
+ },
350
+ fogo: {
351
+ chainId: 0,
352
+ // Non-EVM (SVM)
353
+ chainIdHex: "0x0",
354
+ name: "fogo",
355
+ displayName: "Fogo",
356
+ networkType: "svm",
357
+ rpcUrl: "https://rpc.fogo.nightly.app/",
358
+ explorerUrl: "https://explorer.fogo.nightly.app",
359
+ nativeCurrency: {
360
+ name: "Fogo",
361
+ symbol: "FOGO",
362
+ decimals: 9
363
+ },
364
+ usdc: {
365
+ address: "uSd2czE61Evaf76RNbq4KPpXnkiL3irdzgLFUMe3NoG",
366
+ // Fogo USDC mint
367
+ decimals: 6,
368
+ name: "USDC",
369
+ version: "1"
370
+ },
371
+ x402: {
372
+ facilitatorUrl: DEFAULT_FACILITATOR_URL,
373
+ enabled: true
374
+ }
375
+ },
376
+ // ============================================================================
377
+ // STELLAR (1 network)
378
+ // ============================================================================
379
+ stellar: {
380
+ chainId: 0,
381
+ // Non-EVM
382
+ chainIdHex: "0x0",
383
+ name: "stellar",
384
+ displayName: "Stellar",
385
+ networkType: "stellar",
386
+ rpcUrl: "https://horizon.stellar.org",
387
+ explorerUrl: "https://stellar.expert/explorer/public",
388
+ nativeCurrency: {
389
+ name: "Lumens",
390
+ symbol: "XLM",
391
+ decimals: 7
392
+ // Stellar uses 7 decimals (stroops)
393
+ },
394
+ usdc: {
395
+ address: "CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75",
396
+ // Soroban Asset Contract
397
+ decimals: 7,
398
+ // Stellar USDC uses 7 decimals
399
+ name: "USDC",
400
+ version: "1"
401
+ },
402
+ x402: {
403
+ facilitatorUrl: DEFAULT_FACILITATOR_URL,
404
+ enabled: true
405
+ }
406
+ },
407
+ // ============================================================================
408
+ // NEAR (1 network) - Uses NEP-366 meta-transactions
409
+ // ============================================================================
410
+ near: {
411
+ chainId: 0,
412
+ // Non-EVM
413
+ chainIdHex: "0x0",
414
+ name: "near",
415
+ displayName: "NEAR Protocol",
416
+ networkType: "near",
417
+ rpcUrl: "https://rpc.mainnet.near.org",
418
+ explorerUrl: "https://nearblocks.io",
419
+ nativeCurrency: {
420
+ name: "NEAR",
421
+ symbol: "NEAR",
422
+ decimals: 24
423
+ // NEAR uses 24 decimals (yoctoNEAR)
424
+ },
425
+ usdc: {
426
+ address: "17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1",
427
+ // Native Circle USDC
428
+ decimals: 6,
429
+ name: "USDC",
430
+ version: "1"
431
+ },
432
+ x402: {
433
+ facilitatorUrl: DEFAULT_FACILITATOR_URL,
434
+ enabled: true
435
+ // NEP-366 meta-transactions supported
436
+ }
437
+ }
438
+ };
439
+ function getChainByName(name) {
440
+ return SUPPORTED_CHAINS[name.toLowerCase()];
441
+ }
442
+
443
+ // src/providers/solana/index.ts
444
+ function uint8ArrayToBase64(bytes) {
445
+ let binary = "";
446
+ for (let i = 0; i < bytes.length; i++) {
447
+ binary += String.fromCharCode(bytes[i]);
448
+ }
449
+ return btoa(binary);
450
+ }
451
+ var Connection;
452
+ var PublicKey;
453
+ var TransactionMessage;
454
+ var VersionedTransaction;
455
+ var ComputeBudgetProgram;
456
+ var getAssociatedTokenAddress;
457
+ var createTransferCheckedInstruction;
458
+ var createAssociatedTokenAccountIdempotentInstruction;
459
+ var TOKEN_PROGRAM_ID;
460
+ async function loadSolanaDeps() {
461
+ if (!Connection) {
462
+ const web3 = await import('@solana/web3.js');
463
+ const splToken = await import('@solana/spl-token');
464
+ Connection = web3.Connection;
465
+ PublicKey = web3.PublicKey;
466
+ TransactionMessage = web3.TransactionMessage;
467
+ VersionedTransaction = web3.VersionedTransaction;
468
+ ComputeBudgetProgram = web3.ComputeBudgetProgram;
469
+ getAssociatedTokenAddress = splToken.getAssociatedTokenAddress;
470
+ createTransferCheckedInstruction = splToken.createTransferCheckedInstruction;
471
+ createAssociatedTokenAccountIdempotentInstruction = splToken.createAssociatedTokenAccountIdempotentInstruction;
472
+ TOKEN_PROGRAM_ID = splToken.TOKEN_PROGRAM_ID;
473
+ }
474
+ }
475
+ var SVMProvider = class {
476
+ id = "phantom";
477
+ name = "Phantom";
478
+ networkType = "svm";
479
+ provider = null;
480
+ publicKey = null;
481
+ connections = /* @__PURE__ */ new Map();
482
+ address = null;
483
+ /**
484
+ * Check if Phantom wallet is available
485
+ */
486
+ isAvailable() {
487
+ if (typeof window === "undefined") return false;
488
+ return !!(window.phantom?.solana?.isPhantom || window.solana?.isPhantom);
489
+ }
490
+ /**
491
+ * Connect to Phantom wallet
492
+ */
493
+ async connect() {
494
+ await loadSolanaDeps();
495
+ this.provider = await this.getPhantomProvider();
496
+ if (!this.provider) {
497
+ throw new X402Error(
498
+ "Phantom wallet not installed. Please install from phantom.app",
499
+ "WALLET_NOT_FOUND"
500
+ );
501
+ }
502
+ try {
503
+ if (this.provider.publicKey && this.provider.isConnected) {
504
+ const publicKeyString2 = this.provider.publicKey.toBase58();
505
+ this.publicKey = new PublicKey(publicKeyString2);
506
+ this.address = publicKeyString2;
507
+ await this.initConnection();
508
+ return publicKeyString2;
509
+ }
510
+ const resp = await this.provider.connect();
511
+ const publicKeyString = resp.publicKey.toBase58();
512
+ this.publicKey = new PublicKey(publicKeyString);
513
+ this.address = publicKeyString;
514
+ await this.initConnection();
515
+ return publicKeyString;
516
+ } catch (error) {
517
+ if (error instanceof Error) {
518
+ if (error.message.includes("User rejected") || error.code === 4001) {
519
+ throw new X402Error("Connection rejected by user", "WALLET_CONNECTION_REJECTED");
520
+ }
521
+ }
522
+ throw new X402Error(
523
+ `Failed to connect Phantom: ${error instanceof Error ? error.message : "Unknown error"}`,
524
+ "UNKNOWN_ERROR",
525
+ error
526
+ );
527
+ }
528
+ }
529
+ /**
530
+ * Disconnect from Phantom
531
+ */
532
+ async disconnect() {
533
+ if (this.provider) {
534
+ try {
535
+ await this.provider.disconnect();
536
+ } catch {
537
+ }
538
+ }
539
+ this.provider = null;
540
+ this.publicKey = null;
541
+ this.connections.clear();
542
+ this.address = null;
543
+ }
544
+ /**
545
+ * Get current address
546
+ */
547
+ getAddress() {
548
+ return this.address;
549
+ }
550
+ /**
551
+ * Get USDC balance
552
+ */
553
+ async getBalance(chainConfig) {
554
+ await loadSolanaDeps();
555
+ if (!this.address) {
556
+ throw new X402Error("Wallet not connected", "WALLET_NOT_CONNECTED");
557
+ }
558
+ await this.initConnection(chainConfig);
559
+ const connection = this.connections.get(chainConfig.name);
560
+ if (!connection) {
561
+ throw new X402Error("Failed to connect to Solana RPC", "NETWORK_ERROR");
562
+ }
563
+ try {
564
+ const response = await fetch(chainConfig.rpcUrl, {
565
+ method: "POST",
566
+ headers: { "Content-Type": "application/json" },
567
+ body: JSON.stringify({
568
+ jsonrpc: "2.0",
569
+ id: 1,
570
+ method: "getTokenAccountsByOwner",
571
+ params: [
572
+ this.address,
573
+ { mint: chainConfig.usdc.address },
574
+ { encoding: "jsonParsed" }
575
+ ]
576
+ })
577
+ });
578
+ const data = await response.json();
579
+ if (!data.result?.value?.length) {
580
+ return "0.00";
581
+ }
582
+ const tokenAccountInfo = data.result.value[0].account.data.parsed.info;
583
+ const balance = Number(tokenAccountInfo.tokenAmount.amount) / Math.pow(10, tokenAccountInfo.tokenAmount.decimals);
584
+ return balance.toFixed(2);
585
+ } catch {
586
+ return "0.00";
587
+ }
588
+ }
589
+ /**
590
+ * Create SVM payment (partially-signed transaction)
591
+ *
592
+ * Works for both Solana and Fogo chains.
593
+ *
594
+ * Transaction structure required by facilitator:
595
+ * 1. SetComputeUnitLimit
596
+ * 2. SetComputeUnitPrice
597
+ * 3. (Optional) CreateAssociatedTokenAccount if recipient ATA doesn't exist
598
+ * 4. TransferChecked (USDC transfer)
599
+ *
600
+ * Fee payer: Facilitator (not user)
601
+ * User pays: ZERO SOL/FOGO
602
+ */
603
+ async signPayment(paymentInfo, chainConfig) {
604
+ await loadSolanaDeps();
605
+ if (!this.provider || !this.publicKey || !this.address) {
606
+ throw new X402Error("Wallet not connected", "WALLET_NOT_CONNECTED");
607
+ }
608
+ const connection = await this.getConnection(chainConfig);
609
+ if (!connection) {
610
+ throw new X402Error(`Failed to connect to ${chainConfig.displayName} RPC`, "NETWORK_ERROR");
611
+ }
612
+ const recipient = paymentInfo.recipients?.solana || paymentInfo.recipient;
613
+ const facilitatorAddress = paymentInfo.facilitator;
614
+ if (!facilitatorAddress) {
615
+ throw new X402Error("Facilitator address not provided", "INVALID_CONFIG");
616
+ }
617
+ const recipientPubkey = new PublicKey(recipient);
618
+ const facilitatorPubkey = new PublicKey(facilitatorAddress);
619
+ const usdcMint = new PublicKey(chainConfig.usdc.address);
620
+ const amount = Math.floor(parseFloat(paymentInfo.amount) * 1e6);
621
+ const fromTokenAccount = await getAssociatedTokenAddress(
622
+ usdcMint,
623
+ this.publicKey,
624
+ true,
625
+ TOKEN_PROGRAM_ID
626
+ );
627
+ const toTokenAccount = await getAssociatedTokenAddress(
628
+ usdcMint,
629
+ recipientPubkey,
630
+ true,
631
+ TOKEN_PROGRAM_ID
632
+ );
633
+ const toTokenAccountInfo = await connection.getAccountInfo(toTokenAccount);
634
+ const needsATACreation = toTokenAccountInfo === null;
635
+ const { blockhash } = await connection.getLatestBlockhash("finalized");
636
+ const instructions = [];
637
+ instructions.push(
638
+ ComputeBudgetProgram.setComputeUnitLimit({
639
+ units: needsATACreation ? 5e4 : 2e4
640
+ })
641
+ );
642
+ instructions.push(
643
+ ComputeBudgetProgram.setComputeUnitPrice({
644
+ microLamports: 1
645
+ })
646
+ );
647
+ if (needsATACreation) {
648
+ instructions.push(
649
+ createAssociatedTokenAccountIdempotentInstruction(
650
+ this.publicKey,
651
+ // User pays for ATA creation
652
+ toTokenAccount,
653
+ recipientPubkey,
654
+ usdcMint,
655
+ TOKEN_PROGRAM_ID
656
+ )
657
+ );
658
+ }
659
+ instructions.push(
660
+ createTransferCheckedInstruction(
661
+ fromTokenAccount,
662
+ usdcMint,
663
+ toTokenAccount,
664
+ this.publicKey,
665
+ amount,
666
+ 6,
667
+ [],
668
+ TOKEN_PROGRAM_ID
669
+ )
670
+ );
671
+ const messageV0 = new TransactionMessage({
672
+ payerKey: facilitatorPubkey,
673
+ recentBlockhash: blockhash,
674
+ instructions
675
+ }).compileToV0Message();
676
+ const transaction = new VersionedTransaction(messageV0);
677
+ let signedTransaction;
678
+ try {
679
+ signedTransaction = await this.provider.signTransaction(transaction);
680
+ } catch (error) {
681
+ if (error instanceof Error && error.message.includes("User rejected")) {
682
+ throw new X402Error("Signature rejected by user", "SIGNATURE_REJECTED");
683
+ }
684
+ throw new X402Error(
685
+ `Failed to sign transaction: ${error instanceof Error ? error.message : "Unknown error"}`,
686
+ "PAYMENT_FAILED",
687
+ error
688
+ );
689
+ }
690
+ const serialized = signedTransaction.serialize();
691
+ const payload = {
692
+ transaction: uint8ArrayToBase64(serialized)
693
+ };
694
+ return JSON.stringify(payload);
695
+ }
696
+ /**
697
+ * Encode SVM payment as X-PAYMENT header
698
+ *
699
+ * @param paymentPayload - The payment payload JSON string
700
+ * @param chainConfig - Optional chain config (defaults to 'solana' if not provided)
701
+ */
702
+ encodePaymentHeader(paymentPayload, chainConfig) {
703
+ const payload = JSON.parse(paymentPayload);
704
+ const networkName = chainConfig?.name || "solana";
705
+ const x402Payload = {
706
+ x402Version: 1,
707
+ scheme: "exact",
708
+ network: networkName,
709
+ payload: {
710
+ transaction: payload.transaction
711
+ }
712
+ };
713
+ return btoa(JSON.stringify(x402Payload));
714
+ }
715
+ // Private helpers
716
+ async getPhantomProvider() {
717
+ if (typeof window === "undefined") return null;
718
+ const win = window;
719
+ if (win.phantom?.solana?.isPhantom) {
720
+ return win.phantom.solana;
721
+ }
722
+ if (win.solana?.isPhantom) {
723
+ return win.solana;
724
+ }
725
+ for (let i = 0; i < 5; i++) {
726
+ await new Promise((resolve) => setTimeout(resolve, 100));
727
+ if (win.phantom?.solana?.isPhantom) {
728
+ return win.phantom.solana;
729
+ }
730
+ if (win.solana?.isPhantom) {
731
+ return win.solana;
732
+ }
733
+ }
734
+ return null;
735
+ }
736
+ /**
737
+ * Get or create a connection for a specific chain
738
+ */
739
+ async getConnection(chainConfig) {
740
+ await loadSolanaDeps();
741
+ const config = chainConfig || getChainByName("solana");
742
+ if (!config) {
743
+ throw new X402Error("Chain config not found", "CHAIN_NOT_SUPPORTED");
744
+ }
745
+ if (this.connections.has(config.name)) {
746
+ return this.connections.get(config.name);
747
+ }
748
+ const connection = new Connection(config.rpcUrl, "confirmed");
749
+ this.connections.set(config.name, connection);
750
+ return connection;
751
+ }
752
+ /**
753
+ * @deprecated Use getConnection instead
754
+ */
755
+ async initConnection(chainConfig) {
756
+ await this.getConnection(chainConfig);
757
+ }
758
+ };
759
+ var SolanaProvider = class extends SVMProvider {
760
+ constructor() {
761
+ super();
762
+ console.warn("SolanaProvider is deprecated. Use SVMProvider instead.");
763
+ }
764
+ };
765
+ var solana_default = SVMProvider;
766
+
767
+ exports.SVMProvider = SVMProvider;
768
+ exports.SolanaProvider = SolanaProvider;
769
+ exports.default = solana_default;
770
+ //# sourceMappingURL=index.js.map
771
+ //# sourceMappingURL=index.js.map