@dexterai/x402 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.
@@ -0,0 +1,602 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __esm = (fn, res) => function __init() {
7
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
8
+ };
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
+
23
+ // src/adapters/solana.ts
24
+ function isSolanaWallet(wallet) {
25
+ if (!wallet || typeof wallet !== "object") return false;
26
+ const w = wallet;
27
+ return "publicKey" in w && "signTransaction" in w && typeof w.signTransaction === "function";
28
+ }
29
+ function createSolanaAdapter(config) {
30
+ return new SolanaAdapter(config);
31
+ }
32
+ var import_web3, import_spl_token, SOLANA_MAINNET, SOLANA_DEVNET, SOLANA_TESTNET, DEFAULT_RPC_URLS, DEFAULT_COMPUTE_UNIT_LIMIT, DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS, SolanaAdapter;
33
+ var init_solana = __esm({
34
+ "src/adapters/solana.ts"() {
35
+ "use strict";
36
+ import_web3 = require("@solana/web3.js");
37
+ import_spl_token = require("@solana/spl-token");
38
+ SOLANA_MAINNET = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
39
+ SOLANA_DEVNET = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1";
40
+ SOLANA_TESTNET = "solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z";
41
+ DEFAULT_RPC_URLS = {
42
+ [SOLANA_MAINNET]: "https://api.mainnet-beta.solana.com",
43
+ [SOLANA_DEVNET]: "https://api.devnet.solana.com",
44
+ [SOLANA_TESTNET]: "https://api.testnet.solana.com"
45
+ };
46
+ DEFAULT_COMPUTE_UNIT_LIMIT = 12e3;
47
+ DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS = 1;
48
+ SolanaAdapter = class {
49
+ name = "Solana";
50
+ networks = [SOLANA_MAINNET, SOLANA_DEVNET, SOLANA_TESTNET];
51
+ config;
52
+ log;
53
+ constructor(config = {}) {
54
+ this.config = config;
55
+ this.log = config.verbose ? console.log.bind(console, "[x402:solana]") : () => {
56
+ };
57
+ }
58
+ canHandle(network) {
59
+ if (this.networks.includes(network)) return true;
60
+ if (network === "solana") return true;
61
+ if (network === "solana-devnet") return true;
62
+ if (network === "solana-testnet") return true;
63
+ if (network.startsWith("solana:")) return true;
64
+ return false;
65
+ }
66
+ getDefaultRpcUrl(network) {
67
+ if (this.config.rpcUrls?.[network]) {
68
+ return this.config.rpcUrls[network];
69
+ }
70
+ if (DEFAULT_RPC_URLS[network]) {
71
+ return DEFAULT_RPC_URLS[network];
72
+ }
73
+ if (network === "solana") return DEFAULT_RPC_URLS[SOLANA_MAINNET];
74
+ if (network === "solana-devnet") return DEFAULT_RPC_URLS[SOLANA_DEVNET];
75
+ if (network === "solana-testnet") return DEFAULT_RPC_URLS[SOLANA_TESTNET];
76
+ return DEFAULT_RPC_URLS[SOLANA_MAINNET];
77
+ }
78
+ getAddress(wallet) {
79
+ if (!isSolanaWallet(wallet)) return null;
80
+ return wallet.publicKey?.toBase58() ?? null;
81
+ }
82
+ isConnected(wallet) {
83
+ if (!isSolanaWallet(wallet)) return false;
84
+ return wallet.publicKey !== null;
85
+ }
86
+ async getBalance(accept, wallet, rpcUrl) {
87
+ if (!isSolanaWallet(wallet) || !wallet.publicKey) {
88
+ return 0;
89
+ }
90
+ const url = rpcUrl || this.getDefaultRpcUrl(accept.network);
91
+ const connection = new import_web3.Connection(url, "confirmed");
92
+ const userPubkey = new import_web3.PublicKey(wallet.publicKey.toBase58());
93
+ const mintPubkey = new import_web3.PublicKey(accept.asset);
94
+ try {
95
+ const mintInfo = await connection.getAccountInfo(mintPubkey, "confirmed");
96
+ const programId = mintInfo?.owner.toBase58() === import_spl_token.TOKEN_2022_PROGRAM_ID.toBase58() ? import_spl_token.TOKEN_2022_PROGRAM_ID : import_spl_token.TOKEN_PROGRAM_ID;
97
+ const ata = await (0, import_spl_token.getAssociatedTokenAddress)(
98
+ mintPubkey,
99
+ userPubkey,
100
+ false,
101
+ programId
102
+ );
103
+ const account = await (0, import_spl_token.getAccount)(connection, ata, void 0, programId);
104
+ const decimals = accept.extra?.decimals ?? 6;
105
+ return Number(account.amount) / Math.pow(10, decimals);
106
+ } catch {
107
+ return 0;
108
+ }
109
+ }
110
+ async buildTransaction(accept, wallet, rpcUrl) {
111
+ if (!isSolanaWallet(wallet)) {
112
+ throw new Error("Invalid Solana wallet");
113
+ }
114
+ if (!wallet.publicKey) {
115
+ throw new Error("Wallet not connected");
116
+ }
117
+ const url = rpcUrl || this.getDefaultRpcUrl(accept.network);
118
+ const connection = new import_web3.Connection(url, "confirmed");
119
+ const userPubkey = new import_web3.PublicKey(wallet.publicKey.toBase58());
120
+ const { payTo, asset, amount, extra } = accept;
121
+ if (!extra?.feePayer) {
122
+ throw new Error("Missing feePayer in payment requirements");
123
+ }
124
+ if (typeof extra?.decimals !== "number") {
125
+ throw new Error("Missing decimals in payment requirements");
126
+ }
127
+ const feePayerPubkey = new import_web3.PublicKey(extra.feePayer);
128
+ const mintPubkey = new import_web3.PublicKey(asset);
129
+ const destinationPubkey = new import_web3.PublicKey(payTo);
130
+ this.log("Building transaction:", {
131
+ from: userPubkey.toBase58(),
132
+ to: payTo,
133
+ amount,
134
+ asset,
135
+ feePayer: extra.feePayer
136
+ });
137
+ const instructions = [];
138
+ instructions.push(
139
+ import_web3.ComputeBudgetProgram.setComputeUnitLimit({
140
+ units: DEFAULT_COMPUTE_UNIT_LIMIT
141
+ })
142
+ );
143
+ instructions.push(
144
+ import_web3.ComputeBudgetProgram.setComputeUnitPrice({
145
+ microLamports: DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS
146
+ })
147
+ );
148
+ const mintInfo = await connection.getAccountInfo(mintPubkey, "confirmed");
149
+ if (!mintInfo) {
150
+ throw new Error(`Token mint ${asset} not found`);
151
+ }
152
+ const programId = mintInfo.owner.toBase58() === import_spl_token.TOKEN_2022_PROGRAM_ID.toBase58() ? import_spl_token.TOKEN_2022_PROGRAM_ID : import_spl_token.TOKEN_PROGRAM_ID;
153
+ const mint = await (0, import_spl_token.getMint)(connection, mintPubkey, void 0, programId);
154
+ if (mint.decimals !== extra.decimals) {
155
+ this.log(
156
+ `Decimals mismatch: requirements say ${extra.decimals}, mint says ${mint.decimals}`
157
+ );
158
+ }
159
+ const sourceAta = await (0, import_spl_token.getAssociatedTokenAddress)(
160
+ mintPubkey,
161
+ userPubkey,
162
+ false,
163
+ programId
164
+ );
165
+ const destinationAta = await (0, import_spl_token.getAssociatedTokenAddress)(
166
+ mintPubkey,
167
+ destinationPubkey,
168
+ false,
169
+ programId
170
+ );
171
+ const sourceAtaInfo = await connection.getAccountInfo(sourceAta, "confirmed");
172
+ if (!sourceAtaInfo) {
173
+ throw new Error(
174
+ `No token account found for ${asset}. Please ensure you have USDC in your wallet.`
175
+ );
176
+ }
177
+ const destAtaInfo = await connection.getAccountInfo(destinationAta, "confirmed");
178
+ if (!destAtaInfo) {
179
+ throw new Error(
180
+ `Seller token account not found. The seller (${payTo}) must have a USDC account.`
181
+ );
182
+ }
183
+ const amountBigInt = BigInt(amount);
184
+ instructions.push(
185
+ (0, import_spl_token.createTransferCheckedInstruction)(
186
+ sourceAta,
187
+ mintPubkey,
188
+ destinationAta,
189
+ userPubkey,
190
+ amountBigInt,
191
+ mint.decimals,
192
+ [],
193
+ programId
194
+ )
195
+ );
196
+ const { blockhash } = await connection.getLatestBlockhash("confirmed");
197
+ const message = new import_web3.TransactionMessage({
198
+ payerKey: feePayerPubkey,
199
+ recentBlockhash: blockhash,
200
+ instructions
201
+ }).compileToV0Message();
202
+ const transaction = new import_web3.VersionedTransaction(message);
203
+ const signedTx = await wallet.signTransaction(transaction);
204
+ this.log("Transaction signed successfully");
205
+ return {
206
+ serialized: Buffer.from(signedTx.serialize()).toString("base64")
207
+ };
208
+ }
209
+ };
210
+ }
211
+ });
212
+
213
+ // src/adapters/evm.ts
214
+ function isEvmWallet(wallet) {
215
+ if (!wallet || typeof wallet !== "object") return false;
216
+ const w = wallet;
217
+ return "address" in w && typeof w.address === "string" && w.address.startsWith("0x");
218
+ }
219
+ function createEvmAdapter(config) {
220
+ return new EvmAdapter(config);
221
+ }
222
+ var BASE_MAINNET, BASE_SEPOLIA, ETHEREUM_MAINNET, ARBITRUM_ONE, CHAIN_IDS, DEFAULT_RPC_URLS2, USDC_ADDRESSES, EvmAdapter;
223
+ var init_evm = __esm({
224
+ "src/adapters/evm.ts"() {
225
+ "use strict";
226
+ BASE_MAINNET = "eip155:8453";
227
+ BASE_SEPOLIA = "eip155:84532";
228
+ ETHEREUM_MAINNET = "eip155:1";
229
+ ARBITRUM_ONE = "eip155:42161";
230
+ CHAIN_IDS = {
231
+ [BASE_MAINNET]: 8453,
232
+ [BASE_SEPOLIA]: 84532,
233
+ [ETHEREUM_MAINNET]: 1,
234
+ [ARBITRUM_ONE]: 42161
235
+ };
236
+ DEFAULT_RPC_URLS2 = {
237
+ [BASE_MAINNET]: "https://mainnet.base.org",
238
+ [BASE_SEPOLIA]: "https://sepolia.base.org",
239
+ [ETHEREUM_MAINNET]: "https://eth.llamarpc.com",
240
+ [ARBITRUM_ONE]: "https://arb1.arbitrum.io/rpc"
241
+ };
242
+ USDC_ADDRESSES = {
243
+ [BASE_MAINNET]: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
244
+ [ETHEREUM_MAINNET]: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
245
+ [ARBITRUM_ONE]: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
246
+ };
247
+ EvmAdapter = class {
248
+ name = "EVM";
249
+ networks = [BASE_MAINNET, BASE_SEPOLIA, ETHEREUM_MAINNET, ARBITRUM_ONE];
250
+ config;
251
+ log;
252
+ constructor(config = {}) {
253
+ this.config = config;
254
+ this.log = config.verbose ? console.log.bind(console, "[x402:evm]") : () => {
255
+ };
256
+ }
257
+ canHandle(network) {
258
+ if (this.networks.includes(network)) return true;
259
+ if (network === "base") return true;
260
+ if (network === "ethereum") return true;
261
+ if (network === "arbitrum") return true;
262
+ if (network.startsWith("eip155:")) return true;
263
+ return false;
264
+ }
265
+ getDefaultRpcUrl(network) {
266
+ if (this.config.rpcUrls?.[network]) {
267
+ return this.config.rpcUrls[network];
268
+ }
269
+ if (DEFAULT_RPC_URLS2[network]) {
270
+ return DEFAULT_RPC_URLS2[network];
271
+ }
272
+ if (network === "base") return DEFAULT_RPC_URLS2[BASE_MAINNET];
273
+ if (network === "ethereum") return DEFAULT_RPC_URLS2[ETHEREUM_MAINNET];
274
+ if (network === "arbitrum") return DEFAULT_RPC_URLS2[ARBITRUM_ONE];
275
+ return DEFAULT_RPC_URLS2[BASE_MAINNET];
276
+ }
277
+ getAddress(wallet) {
278
+ if (!isEvmWallet(wallet)) return null;
279
+ return wallet.address;
280
+ }
281
+ isConnected(wallet) {
282
+ if (!isEvmWallet(wallet)) return false;
283
+ return !!wallet.address;
284
+ }
285
+ getChainId(network) {
286
+ if (CHAIN_IDS[network]) return CHAIN_IDS[network];
287
+ if (network.startsWith("eip155:")) {
288
+ const chainIdStr = network.split(":")[1];
289
+ return parseInt(chainIdStr, 10);
290
+ }
291
+ if (network === "base") return 8453;
292
+ if (network === "ethereum") return 1;
293
+ if (network === "arbitrum") return 42161;
294
+ return 8453;
295
+ }
296
+ async getBalance(accept, wallet, rpcUrl) {
297
+ if (!isEvmWallet(wallet) || !wallet.address) {
298
+ return 0;
299
+ }
300
+ const url = rpcUrl || this.getDefaultRpcUrl(accept.network);
301
+ try {
302
+ const data = this.encodeBalanceOf(wallet.address);
303
+ const response = await fetch(url, {
304
+ method: "POST",
305
+ headers: { "Content-Type": "application/json" },
306
+ body: JSON.stringify({
307
+ jsonrpc: "2.0",
308
+ id: 1,
309
+ method: "eth_call",
310
+ params: [
311
+ {
312
+ to: accept.asset,
313
+ data
314
+ },
315
+ "latest"
316
+ ]
317
+ })
318
+ });
319
+ const result = await response.json();
320
+ if (result.error || !result.result) {
321
+ return 0;
322
+ }
323
+ const balance = BigInt(result.result);
324
+ const decimals = accept.extra?.decimals ?? 6;
325
+ return Number(balance) / Math.pow(10, decimals);
326
+ } catch {
327
+ return 0;
328
+ }
329
+ }
330
+ encodeBalanceOf(address) {
331
+ const selector = "0x70a08231";
332
+ const paddedAddress = address.slice(2).toLowerCase().padStart(64, "0");
333
+ return selector + paddedAddress;
334
+ }
335
+ async buildTransaction(accept, wallet, _rpcUrl) {
336
+ if (!isEvmWallet(wallet)) {
337
+ throw new Error("Invalid EVM wallet");
338
+ }
339
+ if (!wallet.address) {
340
+ throw new Error("Wallet not connected");
341
+ }
342
+ const { payTo, asset, amount, extra } = accept;
343
+ this.log("Building EVM transaction:", {
344
+ from: wallet.address,
345
+ to: payTo,
346
+ amount,
347
+ asset,
348
+ network: accept.network
349
+ });
350
+ const chainId = this.getChainId(accept.network);
351
+ const domain = {
352
+ name: extra?.name ?? "USD Coin",
353
+ version: extra?.version ?? "2",
354
+ chainId: BigInt(chainId),
355
+ verifyingContract: asset
356
+ };
357
+ const types = {
358
+ TransferWithAuthorization: [
359
+ { name: "from", type: "address" },
360
+ { name: "to", type: "address" },
361
+ { name: "value", type: "uint256" },
362
+ { name: "validAfter", type: "uint256" },
363
+ { name: "validBefore", type: "uint256" },
364
+ { name: "nonce", type: "bytes32" }
365
+ ]
366
+ };
367
+ const nonce = "0x" + [...Array(32)].map(() => Math.floor(Math.random() * 256).toString(16).padStart(2, "0")).join("");
368
+ const now = Math.floor(Date.now() / 1e3);
369
+ const authorization = {
370
+ from: wallet.address,
371
+ to: payTo,
372
+ value: amount,
373
+ // string
374
+ validAfter: String(now - 600),
375
+ // 10 minutes before (matching upstream)
376
+ validBefore: String(now + (accept.maxTimeoutSeconds || 60)),
377
+ nonce
378
+ };
379
+ const message = {
380
+ from: wallet.address,
381
+ to: payTo,
382
+ value: BigInt(amount),
383
+ validAfter: BigInt(now - 600),
384
+ validBefore: BigInt(now + (accept.maxTimeoutSeconds || 60)),
385
+ nonce
386
+ };
387
+ if (!wallet.signTypedData) {
388
+ throw new Error("Wallet does not support signTypedData (EIP-712)");
389
+ }
390
+ const signature = await wallet.signTypedData({
391
+ domain,
392
+ types,
393
+ primaryType: "TransferWithAuthorization",
394
+ message
395
+ });
396
+ this.log("EIP-712 signature obtained");
397
+ const payload = {
398
+ authorization,
399
+ signature
400
+ };
401
+ return {
402
+ serialized: JSON.stringify(payload),
403
+ signature
404
+ };
405
+ }
406
+ };
407
+ }
408
+ });
409
+
410
+ // src/client/index.ts
411
+ var client_exports = {};
412
+ __export(client_exports, {
413
+ BASE_MAINNET: () => BASE_MAINNET,
414
+ DEXTER_FACILITATOR_URL: () => DEXTER_FACILITATOR_URL,
415
+ SOLANA_MAINNET: () => SOLANA_MAINNET,
416
+ USDC_MINT: () => USDC_MINT,
417
+ X402Error: () => X402Error,
418
+ createEvmAdapter: () => createEvmAdapter,
419
+ createSolanaAdapter: () => createSolanaAdapter,
420
+ createX402Client: () => createX402Client
421
+ });
422
+ module.exports = __toCommonJS(client_exports);
423
+
424
+ // src/types.ts
425
+ var USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
426
+ var DEXTER_FACILITATOR_URL = "https://x402.dexter.cash";
427
+ var X402Error = class _X402Error extends Error {
428
+ /** Error code for programmatic handling */
429
+ code;
430
+ /** Additional error details */
431
+ details;
432
+ constructor(code, message, details) {
433
+ super(message);
434
+ this.name = "X402Error";
435
+ this.code = code;
436
+ this.details = details;
437
+ Object.setPrototypeOf(this, _X402Error.prototype);
438
+ }
439
+ };
440
+
441
+ // src/adapters/index.ts
442
+ init_solana();
443
+ init_evm();
444
+
445
+ // src/client/x402-client.ts
446
+ function createX402Client(config) {
447
+ const {
448
+ adapters = [createSolanaAdapter({ verbose: config.verbose }), createEvmAdapter({ verbose: config.verbose })],
449
+ wallets: walletSet,
450
+ wallet: legacyWallet,
451
+ preferredNetwork,
452
+ rpcUrls = {},
453
+ maxAmountAtomic,
454
+ fetch: customFetch = globalThis.fetch,
455
+ verbose = false
456
+ } = config;
457
+ const log = verbose ? console.log.bind(console, "[x402]") : () => {
458
+ };
459
+ const wallets = walletSet || {};
460
+ if (legacyWallet && !wallets.solana && isSolanaWallet(legacyWallet)) {
461
+ wallets.solana = legacyWallet;
462
+ }
463
+ if (legacyWallet && !wallets.evm && isEvmWallet(legacyWallet)) {
464
+ wallets.evm = legacyWallet;
465
+ }
466
+ function findPaymentOption(accepts) {
467
+ const candidates = [];
468
+ for (const accept of accepts) {
469
+ const adapter = adapters.find((a) => a.canHandle(accept.network));
470
+ if (!adapter) continue;
471
+ let wallet;
472
+ if (adapter.name === "Solana") {
473
+ wallet = wallets.solana;
474
+ } else if (adapter.name === "EVM") {
475
+ wallet = wallets.evm;
476
+ }
477
+ if (wallet && adapter.isConnected(wallet)) {
478
+ candidates.push({ accept, adapter, wallet });
479
+ }
480
+ }
481
+ if (candidates.length === 0) {
482
+ return null;
483
+ }
484
+ if (preferredNetwork) {
485
+ const preferred = candidates.find((c) => c.accept.network === preferredNetwork);
486
+ if (preferred) return preferred;
487
+ }
488
+ return candidates[0];
489
+ }
490
+ function getRpcUrl(network, adapter) {
491
+ return rpcUrls[network] || adapter.getDefaultRpcUrl(network);
492
+ }
493
+ async function x402Fetch(input, init) {
494
+ log("Making request:", input);
495
+ const response = await customFetch(input, init);
496
+ if (response.status !== 402) {
497
+ return response;
498
+ }
499
+ log("Received 402 Payment Required");
500
+ const paymentRequiredHeader = response.headers.get("PAYMENT-REQUIRED");
501
+ if (!paymentRequiredHeader) {
502
+ throw new X402Error(
503
+ "missing_payment_required_header",
504
+ "Server returned 402 but no PAYMENT-REQUIRED header"
505
+ );
506
+ }
507
+ let requirements;
508
+ try {
509
+ const decoded = atob(paymentRequiredHeader);
510
+ requirements = JSON.parse(decoded);
511
+ } catch {
512
+ throw new X402Error(
513
+ "invalid_payment_required",
514
+ "Failed to decode PAYMENT-REQUIRED header"
515
+ );
516
+ }
517
+ log("Payment requirements:", requirements);
518
+ const match = findPaymentOption(requirements.accepts);
519
+ if (!match) {
520
+ const availableNetworks = requirements.accepts.map((a) => a.network).join(", ");
521
+ throw new X402Error(
522
+ "no_matching_payment_option",
523
+ `No connected wallet for any available network: ${availableNetworks}`
524
+ );
525
+ }
526
+ const { accept, adapter, wallet } = match;
527
+ log(`Using ${adapter.name} for ${accept.network}`);
528
+ if (adapter.name === "Solana" && !accept.extra?.feePayer) {
529
+ throw new X402Error(
530
+ "missing_fee_payer",
531
+ "Solana payment option missing feePayer in extra"
532
+ );
533
+ }
534
+ if (typeof accept.extra?.decimals !== "number") {
535
+ throw new X402Error(
536
+ "missing_decimals",
537
+ "Payment option missing decimals in extra"
538
+ );
539
+ }
540
+ if (maxAmountAtomic && BigInt(accept.amount) > BigInt(maxAmountAtomic)) {
541
+ throw new X402Error(
542
+ "amount_exceeds_max",
543
+ `Payment amount ${accept.amount} exceeds maximum ${maxAmountAtomic}`
544
+ );
545
+ }
546
+ log("Building transaction...");
547
+ const rpcUrl = getRpcUrl(accept.network, adapter);
548
+ const signedTx = await adapter.buildTransaction(accept, wallet, rpcUrl);
549
+ log("Transaction signed");
550
+ let payload;
551
+ if (adapter.name === "EVM") {
552
+ payload = JSON.parse(signedTx.serialized);
553
+ } else {
554
+ payload = { transaction: signedTx.serialized };
555
+ }
556
+ const paymentSignature = {
557
+ x402Version: 2,
558
+ resource: requirements.resource,
559
+ accepted: accept,
560
+ payload
561
+ };
562
+ const paymentSignatureHeader = btoa(JSON.stringify(paymentSignature));
563
+ log("Retrying request with payment...");
564
+ const retryResponse = await customFetch(input, {
565
+ ...init,
566
+ headers: {
567
+ ...init?.headers || {},
568
+ "PAYMENT-SIGNATURE": paymentSignatureHeader
569
+ }
570
+ });
571
+ log("Retry response status:", retryResponse.status);
572
+ if (retryResponse.status === 402) {
573
+ let reason = "unknown";
574
+ try {
575
+ const body = await retryResponse.clone().json();
576
+ reason = String(body.error || body.message || JSON.stringify(body));
577
+ log("Rejection reason:", reason);
578
+ } catch {
579
+ }
580
+ throw new X402Error(
581
+ "payment_rejected",
582
+ `Payment was rejected by the server: ${reason}`
583
+ );
584
+ }
585
+ return retryResponse;
586
+ }
587
+ return {
588
+ fetch: x402Fetch
589
+ };
590
+ }
591
+ // Annotate the CommonJS export names for ESM import in node:
592
+ 0 && (module.exports = {
593
+ BASE_MAINNET,
594
+ DEXTER_FACILITATOR_URL,
595
+ SOLANA_MAINNET,
596
+ USDC_MINT,
597
+ X402Error,
598
+ createEvmAdapter,
599
+ createSolanaAdapter,
600
+ createX402Client
601
+ });
602
+ //# sourceMappingURL=index.cjs.map