@dexterai/x402 1.7.2 → 1.8.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.
@@ -1,9 +1,180 @@
1
+ var __defProp = Object.defineProperty;
1
2
  var __getOwnPropNames = Object.getOwnPropertyNames;
2
3
  var __esm = (fn, res) => function __init() {
3
4
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
4
5
  };
5
- var __commonJS = (cb, mod) => function __require() {
6
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+
11
+ // node_modules/base-x/src/esm/index.js
12
+ function base(ALPHABET2) {
13
+ if (ALPHABET2.length >= 255) {
14
+ throw new TypeError("Alphabet too long");
15
+ }
16
+ const BASE_MAP = new Uint8Array(256);
17
+ for (let j = 0; j < BASE_MAP.length; j++) {
18
+ BASE_MAP[j] = 255;
19
+ }
20
+ for (let i = 0; i < ALPHABET2.length; i++) {
21
+ const x = ALPHABET2.charAt(i);
22
+ const xc = x.charCodeAt(0);
23
+ if (BASE_MAP[xc] !== 255) {
24
+ throw new TypeError(x + " is ambiguous");
25
+ }
26
+ BASE_MAP[xc] = i;
27
+ }
28
+ const BASE = ALPHABET2.length;
29
+ const LEADER = ALPHABET2.charAt(0);
30
+ const FACTOR = Math.log(BASE) / Math.log(256);
31
+ const iFACTOR = Math.log(256) / Math.log(BASE);
32
+ function encode(source) {
33
+ if (source instanceof Uint8Array) {
34
+ } else if (ArrayBuffer.isView(source)) {
35
+ source = new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
36
+ } else if (Array.isArray(source)) {
37
+ source = Uint8Array.from(source);
38
+ }
39
+ if (!(source instanceof Uint8Array)) {
40
+ throw new TypeError("Expected Uint8Array");
41
+ }
42
+ if (source.length === 0) {
43
+ return "";
44
+ }
45
+ let zeroes = 0;
46
+ let length = 0;
47
+ let pbegin = 0;
48
+ const pend = source.length;
49
+ while (pbegin !== pend && source[pbegin] === 0) {
50
+ pbegin++;
51
+ zeroes++;
52
+ }
53
+ const size = (pend - pbegin) * iFACTOR + 1 >>> 0;
54
+ const b58 = new Uint8Array(size);
55
+ while (pbegin !== pend) {
56
+ let carry = source[pbegin];
57
+ let i = 0;
58
+ for (let it1 = size - 1; (carry !== 0 || i < length) && it1 !== -1; it1--, i++) {
59
+ carry += 256 * b58[it1] >>> 0;
60
+ b58[it1] = carry % BASE >>> 0;
61
+ carry = carry / BASE >>> 0;
62
+ }
63
+ if (carry !== 0) {
64
+ throw new Error("Non-zero carry");
65
+ }
66
+ length = i;
67
+ pbegin++;
68
+ }
69
+ let it2 = size - length;
70
+ while (it2 !== size && b58[it2] === 0) {
71
+ it2++;
72
+ }
73
+ let str = LEADER.repeat(zeroes);
74
+ for (; it2 < size; ++it2) {
75
+ str += ALPHABET2.charAt(b58[it2]);
76
+ }
77
+ return str;
78
+ }
79
+ function decodeUnsafe(source) {
80
+ if (typeof source !== "string") {
81
+ throw new TypeError("Expected String");
82
+ }
83
+ if (source.length === 0) {
84
+ return new Uint8Array();
85
+ }
86
+ let psz = 0;
87
+ let zeroes = 0;
88
+ let length = 0;
89
+ while (source[psz] === LEADER) {
90
+ zeroes++;
91
+ psz++;
92
+ }
93
+ const size = (source.length - psz) * FACTOR + 1 >>> 0;
94
+ const b256 = new Uint8Array(size);
95
+ while (psz < source.length) {
96
+ const charCode = source.charCodeAt(psz);
97
+ if (charCode > 255) {
98
+ return;
99
+ }
100
+ let carry = BASE_MAP[charCode];
101
+ if (carry === 255) {
102
+ return;
103
+ }
104
+ let i = 0;
105
+ for (let it3 = size - 1; (carry !== 0 || i < length) && it3 !== -1; it3--, i++) {
106
+ carry += BASE * b256[it3] >>> 0;
107
+ b256[it3] = carry % 256 >>> 0;
108
+ carry = carry / 256 >>> 0;
109
+ }
110
+ if (carry !== 0) {
111
+ throw new Error("Non-zero carry");
112
+ }
113
+ length = i;
114
+ psz++;
115
+ }
116
+ let it4 = size - length;
117
+ while (it4 !== size && b256[it4] === 0) {
118
+ it4++;
119
+ }
120
+ const vch = new Uint8Array(zeroes + (size - it4));
121
+ let j = zeroes;
122
+ while (it4 !== size) {
123
+ vch[j++] = b256[it4++];
124
+ }
125
+ return vch;
126
+ }
127
+ function decode(string) {
128
+ const buffer = decodeUnsafe(string);
129
+ if (buffer) {
130
+ return buffer;
131
+ }
132
+ throw new Error("Non-base" + BASE + " character");
133
+ }
134
+ return {
135
+ encode,
136
+ decodeUnsafe,
137
+ decode
138
+ };
139
+ }
140
+ var esm_default;
141
+ var init_esm = __esm({
142
+ "node_modules/base-x/src/esm/index.js"() {
143
+ "use strict";
144
+ esm_default = base;
145
+ }
146
+ });
147
+
148
+ // node_modules/bs58/src/esm/index.js
149
+ var esm_exports = {};
150
+ __export(esm_exports, {
151
+ default: () => esm_default2
152
+ });
153
+ var ALPHABET, esm_default2;
154
+ var init_esm2 = __esm({
155
+ "node_modules/bs58/src/esm/index.js"() {
156
+ "use strict";
157
+ init_esm();
158
+ ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
159
+ esm_default2 = esm_default(ALPHABET);
160
+ }
161
+ });
162
+
163
+ // src/types.ts
164
+ var USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
165
+ var DEXTER_FACILITATOR_URL = "https://x402.dexter.cash";
166
+ var X402Error = class _X402Error extends Error {
167
+ /** Error code for programmatic handling */
168
+ code;
169
+ /** Additional error details */
170
+ details;
171
+ constructor(code, message, details) {
172
+ super(message);
173
+ this.name = "X402Error";
174
+ this.code = code;
175
+ this.details = details;
176
+ Object.setPrototypeOf(this, _X402Error.prototype);
177
+ }
7
178
  };
8
179
 
9
180
  // src/adapters/solana.ts
@@ -22,568 +193,420 @@ import {
22
193
  TOKEN_PROGRAM_ID,
23
194
  TOKEN_2022_PROGRAM_ID
24
195
  } from "@solana/spl-token";
196
+ var SOLANA_MAINNET = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
197
+ var SOLANA_DEVNET = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1";
198
+ var SOLANA_TESTNET = "solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z";
199
+ var DEFAULT_RPC_URLS = {
200
+ [SOLANA_MAINNET]: "https://api.dexter.cash/api/solana/rpc",
201
+ [SOLANA_DEVNET]: "https://api.devnet.solana.com",
202
+ [SOLANA_TESTNET]: "https://api.testnet.solana.com"
203
+ };
204
+ var DEFAULT_COMPUTE_UNIT_LIMIT = 12e3;
205
+ var DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS = 1;
25
206
  function isSolanaWallet(wallet) {
26
207
  if (!wallet || typeof wallet !== "object") return false;
27
208
  const w = wallet;
28
209
  return "publicKey" in w && "signTransaction" in w && typeof w.signTransaction === "function";
29
210
  }
30
- function createSolanaAdapter(config) {
31
- return new SolanaAdapter(config);
32
- }
33
- var SOLANA_MAINNET, SOLANA_DEVNET, SOLANA_TESTNET, DEFAULT_RPC_URLS, DEFAULT_COMPUTE_UNIT_LIMIT, DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS, SolanaAdapter;
34
- var init_solana = __esm({
35
- "src/adapters/solana.ts"() {
36
- "use strict";
37
- SOLANA_MAINNET = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
38
- SOLANA_DEVNET = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1";
39
- SOLANA_TESTNET = "solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z";
40
- DEFAULT_RPC_URLS = {
41
- [SOLANA_MAINNET]: "https://api.dexter.cash/api/solana/rpc",
42
- [SOLANA_DEVNET]: "https://api.devnet.solana.com",
43
- [SOLANA_TESTNET]: "https://api.testnet.solana.com"
211
+ var SolanaAdapter = class {
212
+ name = "Solana";
213
+ networks = [SOLANA_MAINNET, SOLANA_DEVNET, SOLANA_TESTNET];
214
+ config;
215
+ log;
216
+ constructor(config = {}) {
217
+ this.config = config;
218
+ this.log = config.verbose ? console.log.bind(console, "[x402:solana]") : () => {
44
219
  };
45
- DEFAULT_COMPUTE_UNIT_LIMIT = 12e3;
46
- DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS = 1;
47
- SolanaAdapter = class {
48
- name = "Solana";
49
- networks = [SOLANA_MAINNET, SOLANA_DEVNET, SOLANA_TESTNET];
50
- config;
51
- log;
52
- constructor(config = {}) {
53
- this.config = config;
54
- this.log = config.verbose ? console.log.bind(console, "[x402:solana]") : () => {
55
- };
56
- }
57
- canHandle(network) {
58
- if (this.networks.includes(network)) return true;
59
- if (network === "solana") return true;
60
- if (network === "solana-devnet") return true;
61
- if (network === "solana-testnet") return true;
62
- if (network.startsWith("solana:")) return true;
63
- return false;
64
- }
65
- getDefaultRpcUrl(network) {
66
- if (this.config.rpcUrls?.[network]) {
67
- return this.config.rpcUrls[network];
68
- }
69
- if (DEFAULT_RPC_URLS[network]) {
70
- return DEFAULT_RPC_URLS[network];
71
- }
72
- if (network === "solana") return DEFAULT_RPC_URLS[SOLANA_MAINNET];
73
- if (network === "solana-devnet") return DEFAULT_RPC_URLS[SOLANA_DEVNET];
74
- if (network === "solana-testnet") return DEFAULT_RPC_URLS[SOLANA_TESTNET];
75
- return DEFAULT_RPC_URLS[SOLANA_MAINNET];
76
- }
77
- getAddress(wallet) {
78
- if (!isSolanaWallet(wallet)) return null;
79
- return wallet.publicKey?.toBase58() ?? null;
80
- }
81
- isConnected(wallet) {
82
- if (!isSolanaWallet(wallet)) return false;
83
- return wallet.publicKey !== null;
84
- }
85
- async getBalance(accept, wallet, rpcUrl) {
86
- if (!isSolanaWallet(wallet) || !wallet.publicKey) {
87
- return 0;
88
- }
89
- const url = rpcUrl || this.getDefaultRpcUrl(accept.network);
90
- const connection = new Connection(url, "confirmed");
91
- const userPubkey = new PublicKey(wallet.publicKey.toBase58());
92
- const mintPubkey = new PublicKey(accept.asset);
93
- try {
94
- const mintInfo = await connection.getAccountInfo(mintPubkey, "confirmed");
95
- const programId = mintInfo?.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58() ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID;
96
- const ata = await getAssociatedTokenAddress(
97
- mintPubkey,
98
- userPubkey,
99
- false,
100
- programId
101
- );
102
- const account = await getAccount(connection, ata, void 0, programId);
103
- const decimals = accept.extra?.decimals ?? 6;
104
- return Number(account.amount) / Math.pow(10, decimals);
105
- } catch {
106
- return 0;
107
- }
108
- }
109
- async buildTransaction(accept, wallet, rpcUrl) {
110
- if (!isSolanaWallet(wallet)) {
111
- throw new Error("Invalid Solana wallet");
112
- }
113
- if (!wallet.publicKey) {
114
- throw new Error("Wallet not connected");
115
- }
116
- const url = rpcUrl || this.getDefaultRpcUrl(accept.network);
117
- const connection = new Connection(url, "confirmed");
118
- const userPubkey = new PublicKey(wallet.publicKey.toBase58());
119
- const { payTo, asset, extra } = accept;
120
- const amount = accept.amount || accept.maxAmountRequired;
121
- if (!amount) {
122
- throw new Error("Missing amount in payment requirements");
123
- }
124
- if (!extra?.feePayer) {
125
- throw new Error("Missing feePayer in payment requirements");
126
- }
127
- const feePayerPubkey = new PublicKey(extra.feePayer);
128
- const mintPubkey = new PublicKey(asset);
129
- const destinationPubkey = new 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
- ComputeBudgetProgram.setComputeUnitLimit({
140
- units: DEFAULT_COMPUTE_UNIT_LIMIT
141
- })
142
- );
143
- instructions.push(
144
- 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() === TOKEN_2022_PROGRAM_ID.toBase58() ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID;
153
- const mint = await getMint(connection, mintPubkey, void 0, programId);
154
- if (typeof extra?.decimals === "number" && mint.decimals !== extra.decimals) {
155
- this.log(
156
- `Decimals mismatch: requirements say ${extra.decimals}, mint says ${mint.decimals}`
157
- );
158
- }
159
- const sourceAta = await getAssociatedTokenAddress(
160
- mintPubkey,
161
- userPubkey,
162
- false,
163
- programId
164
- );
165
- const destinationAta = await 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
- 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 TransactionMessage({
198
- payerKey: feePayerPubkey,
199
- recentBlockhash: blockhash,
200
- instructions
201
- }).compileToV0Message();
202
- const transaction = new 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
- }
220
+ }
221
+ canHandle(network) {
222
+ if (this.networks.includes(network)) return true;
223
+ if (network === "solana") return true;
224
+ if (network === "solana-devnet") return true;
225
+ if (network === "solana-testnet") return true;
226
+ if (network.startsWith("solana:")) return true;
227
+ return false;
228
+ }
229
+ getDefaultRpcUrl(network) {
230
+ if (this.config.rpcUrls?.[network]) {
231
+ return this.config.rpcUrls[network];
232
+ }
233
+ if (DEFAULT_RPC_URLS[network]) {
234
+ return DEFAULT_RPC_URLS[network];
235
+ }
236
+ if (network === "solana") return DEFAULT_RPC_URLS[SOLANA_MAINNET];
237
+ if (network === "solana-devnet") return DEFAULT_RPC_URLS[SOLANA_DEVNET];
238
+ if (network === "solana-testnet") return DEFAULT_RPC_URLS[SOLANA_TESTNET];
239
+ return DEFAULT_RPC_URLS[SOLANA_MAINNET];
240
+ }
241
+ getAddress(wallet) {
242
+ if (!isSolanaWallet(wallet)) return null;
243
+ return wallet.publicKey?.toBase58() ?? null;
244
+ }
245
+ isConnected(wallet) {
246
+ if (!isSolanaWallet(wallet)) return false;
247
+ return wallet.publicKey !== null;
248
+ }
249
+ async getBalance(accept, wallet, rpcUrl) {
250
+ if (!isSolanaWallet(wallet) || !wallet.publicKey) {
251
+ return 0;
252
+ }
253
+ const url = rpcUrl || this.getDefaultRpcUrl(accept.network);
254
+ const connection = new Connection(url, "confirmed");
255
+ const userPubkey = new PublicKey(wallet.publicKey.toBase58());
256
+ const mintPubkey = new PublicKey(accept.asset);
257
+ try {
258
+ const mintInfo = await connection.getAccountInfo(mintPubkey, "confirmed");
259
+ const programId = mintInfo?.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58() ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID;
260
+ const ata = await getAssociatedTokenAddress(
261
+ mintPubkey,
262
+ userPubkey,
263
+ false,
264
+ programId
265
+ );
266
+ const account = await getAccount(connection, ata, void 0, programId);
267
+ const decimals = accept.extra?.decimals ?? 6;
268
+ return Number(account.amount) / Math.pow(10, decimals);
269
+ } catch {
270
+ return 0;
271
+ }
272
+ }
273
+ async buildTransaction(accept, wallet, rpcUrl) {
274
+ if (!isSolanaWallet(wallet)) {
275
+ throw new Error("Invalid Solana wallet");
276
+ }
277
+ if (!wallet.publicKey) {
278
+ throw new Error("Wallet not connected");
279
+ }
280
+ const url = rpcUrl || this.getDefaultRpcUrl(accept.network);
281
+ const connection = new Connection(url, "confirmed");
282
+ const userPubkey = new PublicKey(wallet.publicKey.toBase58());
283
+ const { payTo, asset, extra } = accept;
284
+ const amount = accept.amount || accept.maxAmountRequired;
285
+ if (!amount) {
286
+ throw new Error("Missing amount in payment requirements");
287
+ }
288
+ if (!extra?.feePayer) {
289
+ throw new Error("Missing feePayer in payment requirements");
290
+ }
291
+ const feePayerPubkey = new PublicKey(extra.feePayer);
292
+ const mintPubkey = new PublicKey(asset);
293
+ const destinationPubkey = new PublicKey(payTo);
294
+ this.log("Building transaction:", {
295
+ from: userPubkey.toBase58(),
296
+ to: payTo,
297
+ amount,
298
+ asset,
299
+ feePayer: extra.feePayer
300
+ });
301
+ const instructions = [];
302
+ instructions.push(
303
+ ComputeBudgetProgram.setComputeUnitLimit({
304
+ units: DEFAULT_COMPUTE_UNIT_LIMIT
305
+ })
306
+ );
307
+ instructions.push(
308
+ ComputeBudgetProgram.setComputeUnitPrice({
309
+ microLamports: DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS
310
+ })
311
+ );
312
+ const mintInfo = await connection.getAccountInfo(mintPubkey, "confirmed");
313
+ if (!mintInfo) {
314
+ throw new Error(`Token mint ${asset} not found`);
315
+ }
316
+ const programId = mintInfo.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58() ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID;
317
+ const mint = await getMint(connection, mintPubkey, void 0, programId);
318
+ if (typeof extra?.decimals === "number" && mint.decimals !== extra.decimals) {
319
+ this.log(
320
+ `Decimals mismatch: requirements say ${extra.decimals}, mint says ${mint.decimals}`
321
+ );
322
+ }
323
+ const sourceAta = await getAssociatedTokenAddress(
324
+ mintPubkey,
325
+ userPubkey,
326
+ false,
327
+ programId
328
+ );
329
+ const destinationAta = await getAssociatedTokenAddress(
330
+ mintPubkey,
331
+ destinationPubkey,
332
+ false,
333
+ programId
334
+ );
335
+ const sourceAtaInfo = await connection.getAccountInfo(sourceAta, "confirmed");
336
+ if (!sourceAtaInfo) {
337
+ throw new Error(
338
+ `No token account found for ${asset}. Please ensure you have USDC in your wallet.`
339
+ );
340
+ }
341
+ const destAtaInfo = await connection.getAccountInfo(destinationAta, "confirmed");
342
+ if (!destAtaInfo) {
343
+ throw new Error(
344
+ `Seller token account not found. The seller (${payTo}) must have a USDC account.`
345
+ );
346
+ }
347
+ const amountBigInt = BigInt(amount);
348
+ instructions.push(
349
+ createTransferCheckedInstruction(
350
+ sourceAta,
351
+ mintPubkey,
352
+ destinationAta,
353
+ userPubkey,
354
+ amountBigInt,
355
+ mint.decimals,
356
+ [],
357
+ programId
358
+ )
359
+ );
360
+ const { blockhash } = await connection.getLatestBlockhash("confirmed");
361
+ const message = new TransactionMessage({
362
+ payerKey: feePayerPubkey,
363
+ recentBlockhash: blockhash,
364
+ instructions
365
+ }).compileToV0Message();
366
+ const transaction = new VersionedTransaction(message);
367
+ const signedTx = await wallet.signTransaction(transaction);
368
+ this.log("Transaction signed successfully");
369
+ return {
370
+ serialized: Buffer.from(signedTx.serialize()).toString("base64")
209
371
  };
210
372
  }
211
- });
373
+ };
374
+ function createSolanaAdapter(config) {
375
+ return new SolanaAdapter(config);
376
+ }
212
377
 
213
378
  // src/adapters/evm.ts
379
+ var BASE_MAINNET = "eip155:8453";
380
+ var BASE_SEPOLIA = "eip155:84532";
381
+ var ARBITRUM_ONE = "eip155:42161";
382
+ var POLYGON = "eip155:137";
383
+ var OPTIMISM = "eip155:10";
384
+ var AVALANCHE = "eip155:43114";
385
+ var SKALE_BASE = "eip155:1187947933";
386
+ var SKALE_BASE_SEPOLIA = "eip155:324705682";
387
+ var ETHEREUM_MAINNET = "eip155:1";
388
+ var CHAIN_IDS = {
389
+ [BASE_MAINNET]: 8453,
390
+ [BASE_SEPOLIA]: 84532,
391
+ [ARBITRUM_ONE]: 42161,
392
+ [POLYGON]: 137,
393
+ [OPTIMISM]: 10,
394
+ [AVALANCHE]: 43114,
395
+ [SKALE_BASE]: 1187947933,
396
+ [SKALE_BASE_SEPOLIA]: 324705682,
397
+ [ETHEREUM_MAINNET]: 1
398
+ };
399
+ var DEFAULT_RPC_URLS2 = {
400
+ [BASE_MAINNET]: "https://api.dexter.cash/api/base/rpc",
401
+ [BASE_SEPOLIA]: "https://sepolia.base.org",
402
+ [ARBITRUM_ONE]: "https://arb1.arbitrum.io/rpc",
403
+ [POLYGON]: "https://polygon-rpc.com",
404
+ [OPTIMISM]: "https://mainnet.optimism.io",
405
+ [AVALANCHE]: "https://api.avax.network/ext/bc/C/rpc",
406
+ [SKALE_BASE]: "https://skale-base.skalenodes.com/v1/base",
407
+ [SKALE_BASE_SEPOLIA]: "https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha",
408
+ [ETHEREUM_MAINNET]: "https://eth.llamarpc.com"
409
+ };
410
+ var USDC_ADDRESSES = {
411
+ [BASE_MAINNET]: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
412
+ [BASE_SEPOLIA]: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
413
+ [ARBITRUM_ONE]: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
414
+ [POLYGON]: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
415
+ [OPTIMISM]: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
416
+ [AVALANCHE]: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
417
+ [SKALE_BASE]: "0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20",
418
+ [SKALE_BASE_SEPOLIA]: "0x2e08028E3C4c2356572E096d8EF835cD5C6030bD",
419
+ [ETHEREUM_MAINNET]: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
420
+ };
214
421
  function isEvmWallet(wallet) {
215
422
  if (!wallet || typeof wallet !== "object") return false;
216
423
  const w = wallet;
217
424
  return "address" in w && typeof w.address === "string" && w.address.startsWith("0x");
218
425
  }
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://api.dexter.cash/api/base/rpc",
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, extra } = accept;
343
- const amount = accept.amount || accept.maxAmountRequired;
344
- if (!amount) {
345
- throw new Error("Missing amount in payment requirements");
346
- }
347
- this.log("Building EVM transaction:", {
348
- from: wallet.address,
349
- to: payTo,
350
- amount,
351
- asset,
352
- network: accept.network
353
- });
354
- const chainId = this.getChainId(accept.network);
355
- const domain = {
356
- name: extra?.name ?? "USD Coin",
357
- version: extra?.version ?? "2",
358
- chainId: BigInt(chainId),
359
- verifyingContract: asset
360
- };
361
- const types = {
362
- TransferWithAuthorization: [
363
- { name: "from", type: "address" },
364
- { name: "to", type: "address" },
365
- { name: "value", type: "uint256" },
366
- { name: "validAfter", type: "uint256" },
367
- { name: "validBefore", type: "uint256" },
368
- { name: "nonce", type: "bytes32" }
369
- ]
370
- };
371
- const nonce = "0x" + [...Array(32)].map(() => Math.floor(Math.random() * 256).toString(16).padStart(2, "0")).join("");
372
- const now = Math.floor(Date.now() / 1e3);
373
- const authorization = {
374
- from: wallet.address,
375
- to: payTo,
376
- value: amount,
377
- // string
378
- validAfter: String(now - 600),
379
- // 10 minutes before (matching upstream)
380
- validBefore: String(now + (accept.maxTimeoutSeconds || 60)),
381
- nonce
382
- };
383
- const message = {
384
- from: wallet.address,
385
- to: payTo,
386
- value: BigInt(amount),
387
- validAfter: BigInt(now - 600),
388
- validBefore: BigInt(now + (accept.maxTimeoutSeconds || 60)),
389
- nonce
390
- };
391
- if (!wallet.signTypedData) {
392
- throw new Error("Wallet does not support signTypedData (EIP-712)");
393
- }
394
- const signature = await wallet.signTypedData({
395
- domain,
396
- types,
397
- primaryType: "TransferWithAuthorization",
398
- message
399
- });
400
- this.log("EIP-712 signature obtained");
401
- const payload = {
402
- authorization,
403
- signature
404
- };
405
- return {
406
- serialized: JSON.stringify(payload),
407
- signature
408
- };
409
- }
426
+ var EvmAdapter = class {
427
+ name = "EVM";
428
+ networks = [BASE_MAINNET, BASE_SEPOLIA, ETHEREUM_MAINNET, ARBITRUM_ONE];
429
+ config;
430
+ log;
431
+ constructor(config = {}) {
432
+ this.config = config;
433
+ this.log = config.verbose ? console.log.bind(console, "[x402:evm]") : () => {
410
434
  };
411
435
  }
412
- });
413
-
414
- // node_modules/base-x/src/cjs/index.cjs
415
- var require_cjs = __commonJS({
416
- "node_modules/base-x/src/cjs/index.cjs"(exports) {
417
- "use strict";
418
- Object.defineProperty(exports, "__esModule", { value: true });
419
- function base(ALPHABET) {
420
- if (ALPHABET.length >= 255) {
421
- throw new TypeError("Alphabet too long");
422
- }
423
- const BASE_MAP = new Uint8Array(256);
424
- for (let j = 0; j < BASE_MAP.length; j++) {
425
- BASE_MAP[j] = 255;
426
- }
427
- for (let i = 0; i < ALPHABET.length; i++) {
428
- const x = ALPHABET.charAt(i);
429
- const xc = x.charCodeAt(0);
430
- if (BASE_MAP[xc] !== 255) {
431
- throw new TypeError(x + " is ambiguous");
432
- }
433
- BASE_MAP[xc] = i;
434
- }
435
- const BASE = ALPHABET.length;
436
- const LEADER = ALPHABET.charAt(0);
437
- const FACTOR = Math.log(BASE) / Math.log(256);
438
- const iFACTOR = Math.log(256) / Math.log(BASE);
439
- function encode(source) {
440
- if (source instanceof Uint8Array) {
441
- } else if (ArrayBuffer.isView(source)) {
442
- source = new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
443
- } else if (Array.isArray(source)) {
444
- source = Uint8Array.from(source);
445
- }
446
- if (!(source instanceof Uint8Array)) {
447
- throw new TypeError("Expected Uint8Array");
448
- }
449
- if (source.length === 0) {
450
- return "";
451
- }
452
- let zeroes = 0;
453
- let length = 0;
454
- let pbegin = 0;
455
- const pend = source.length;
456
- while (pbegin !== pend && source[pbegin] === 0) {
457
- pbegin++;
458
- zeroes++;
459
- }
460
- const size = (pend - pbegin) * iFACTOR + 1 >>> 0;
461
- const b58 = new Uint8Array(size);
462
- while (pbegin !== pend) {
463
- let carry = source[pbegin];
464
- let i = 0;
465
- for (let it1 = size - 1; (carry !== 0 || i < length) && it1 !== -1; it1--, i++) {
466
- carry += 256 * b58[it1] >>> 0;
467
- b58[it1] = carry % BASE >>> 0;
468
- carry = carry / BASE >>> 0;
469
- }
470
- if (carry !== 0) {
471
- throw new Error("Non-zero carry");
472
- }
473
- length = i;
474
- pbegin++;
475
- }
476
- let it2 = size - length;
477
- while (it2 !== size && b58[it2] === 0) {
478
- it2++;
479
- }
480
- let str = LEADER.repeat(zeroes);
481
- for (; it2 < size; ++it2) {
482
- str += ALPHABET.charAt(b58[it2]);
483
- }
484
- return str;
485
- }
486
- function decodeUnsafe(source) {
487
- if (typeof source !== "string") {
488
- throw new TypeError("Expected String");
489
- }
490
- if (source.length === 0) {
491
- return new Uint8Array();
492
- }
493
- let psz = 0;
494
- let zeroes = 0;
495
- let length = 0;
496
- while (source[psz] === LEADER) {
497
- zeroes++;
498
- psz++;
499
- }
500
- const size = (source.length - psz) * FACTOR + 1 >>> 0;
501
- const b256 = new Uint8Array(size);
502
- while (psz < source.length) {
503
- const charCode = source.charCodeAt(psz);
504
- if (charCode > 255) {
505
- return;
506
- }
507
- let carry = BASE_MAP[charCode];
508
- if (carry === 255) {
509
- return;
510
- }
511
- let i = 0;
512
- for (let it3 = size - 1; (carry !== 0 || i < length) && it3 !== -1; it3--, i++) {
513
- carry += BASE * b256[it3] >>> 0;
514
- b256[it3] = carry % 256 >>> 0;
515
- carry = carry / 256 >>> 0;
516
- }
517
- if (carry !== 0) {
518
- throw new Error("Non-zero carry");
519
- }
520
- length = i;
521
- psz++;
522
- }
523
- let it4 = size - length;
524
- while (it4 !== size && b256[it4] === 0) {
525
- it4++;
526
- }
527
- const vch = new Uint8Array(zeroes + (size - it4));
528
- let j = zeroes;
529
- while (it4 !== size) {
530
- vch[j++] = b256[it4++];
531
- }
532
- return vch;
533
- }
534
- function decode(string) {
535
- const buffer = decodeUnsafe(string);
536
- if (buffer) {
537
- return buffer;
538
- }
539
- throw new Error("Non-base" + BASE + " character");
436
+ canHandle(network) {
437
+ if (this.networks.includes(network)) return true;
438
+ if (network === "base") return true;
439
+ if (network === "ethereum") return true;
440
+ if (network === "arbitrum") return true;
441
+ if (network.startsWith("eip155:")) return true;
442
+ return false;
443
+ }
444
+ getDefaultRpcUrl(network) {
445
+ if (this.config.rpcUrls?.[network]) {
446
+ return this.config.rpcUrls[network];
447
+ }
448
+ if (DEFAULT_RPC_URLS2[network]) {
449
+ return DEFAULT_RPC_URLS2[network];
450
+ }
451
+ if (network === "base") return DEFAULT_RPC_URLS2[BASE_MAINNET];
452
+ if (network === "ethereum") return DEFAULT_RPC_URLS2[ETHEREUM_MAINNET];
453
+ if (network === "arbitrum") return DEFAULT_RPC_URLS2[ARBITRUM_ONE];
454
+ return DEFAULT_RPC_URLS2[BASE_MAINNET];
455
+ }
456
+ getAddress(wallet) {
457
+ if (!isEvmWallet(wallet)) return null;
458
+ return wallet.address;
459
+ }
460
+ isConnected(wallet) {
461
+ if (!isEvmWallet(wallet)) return false;
462
+ return !!wallet.address;
463
+ }
464
+ getChainId(network) {
465
+ if (CHAIN_IDS[network]) return CHAIN_IDS[network];
466
+ if (network.startsWith("eip155:")) {
467
+ const chainIdStr = network.split(":")[1];
468
+ return parseInt(chainIdStr, 10);
469
+ }
470
+ if (network === "base") return 8453;
471
+ if (network === "ethereum") return 1;
472
+ if (network === "arbitrum") return 42161;
473
+ return 8453;
474
+ }
475
+ async getBalance(accept, wallet, rpcUrl) {
476
+ if (!isEvmWallet(wallet) || !wallet.address) {
477
+ return 0;
478
+ }
479
+ const url = rpcUrl || this.getDefaultRpcUrl(accept.network);
480
+ try {
481
+ const data = this.encodeBalanceOf(wallet.address);
482
+ const response = await fetch(url, {
483
+ method: "POST",
484
+ headers: { "Content-Type": "application/json" },
485
+ body: JSON.stringify({
486
+ jsonrpc: "2.0",
487
+ id: 1,
488
+ method: "eth_call",
489
+ params: [
490
+ {
491
+ to: accept.asset,
492
+ data
493
+ },
494
+ "latest"
495
+ ]
496
+ })
497
+ });
498
+ const result = await response.json();
499
+ if (result.error || !result.result) {
500
+ return 0;
540
501
  }
541
- return {
542
- encode,
543
- decodeUnsafe,
544
- decode
545
- };
502
+ const balance = BigInt(result.result);
503
+ const decimals = accept.extra?.decimals ?? 6;
504
+ return Number(balance) / Math.pow(10, decimals);
505
+ } catch {
506
+ return 0;
546
507
  }
547
- exports.default = base;
548
508
  }
549
- });
550
-
551
- // node_modules/bs58/src/cjs/index.cjs
552
- var require_cjs2 = __commonJS({
553
- "node_modules/bs58/src/cjs/index.cjs"(exports) {
554
- "use strict";
555
- var __importDefault = exports && exports.__importDefault || function(mod) {
556
- return mod && mod.__esModule ? mod : { "default": mod };
557
- };
558
- Object.defineProperty(exports, "__esModule", { value: true });
559
- var base_x_1 = __importDefault(require_cjs());
560
- var ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
561
- exports.default = (0, base_x_1.default)(ALPHABET);
509
+ encodeBalanceOf(address) {
510
+ const selector = "0x70a08231";
511
+ const paddedAddress = address.slice(2).toLowerCase().padStart(64, "0");
512
+ return selector + paddedAddress;
562
513
  }
563
- });
564
-
565
- // src/types.ts
566
- var USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
567
- var DEXTER_FACILITATOR_URL = "https://x402.dexter.cash";
568
- var X402Error = class _X402Error extends Error {
569
- /** Error code for programmatic handling */
570
- code;
571
- /** Additional error details */
572
- details;
573
- constructor(code, message, details) {
574
- super(message);
575
- this.name = "X402Error";
576
- this.code = code;
577
- this.details = details;
578
- Object.setPrototypeOf(this, _X402Error.prototype);
514
+ async buildTransaction(accept, wallet, _rpcUrl) {
515
+ if (!isEvmWallet(wallet)) {
516
+ throw new Error("Invalid EVM wallet");
517
+ }
518
+ if (!wallet.address) {
519
+ throw new Error("Wallet not connected");
520
+ }
521
+ const { payTo, asset, extra } = accept;
522
+ const amount = accept.amount || accept.maxAmountRequired;
523
+ if (!amount) {
524
+ throw new Error("Missing amount in payment requirements");
525
+ }
526
+ this.log("Building EVM transaction:", {
527
+ from: wallet.address,
528
+ to: payTo,
529
+ amount,
530
+ asset,
531
+ network: accept.network
532
+ });
533
+ const chainId = this.getChainId(accept.network);
534
+ const domain = {
535
+ name: extra?.name ?? "USD Coin",
536
+ version: extra?.version ?? "2",
537
+ chainId: BigInt(chainId),
538
+ verifyingContract: asset
539
+ };
540
+ const types = {
541
+ TransferWithAuthorization: [
542
+ { name: "from", type: "address" },
543
+ { name: "to", type: "address" },
544
+ { name: "value", type: "uint256" },
545
+ { name: "validAfter", type: "uint256" },
546
+ { name: "validBefore", type: "uint256" },
547
+ { name: "nonce", type: "bytes32" }
548
+ ]
549
+ };
550
+ const nonce = "0x" + [...Array(32)].map(() => Math.floor(Math.random() * 256).toString(16).padStart(2, "0")).join("");
551
+ const now = Math.floor(Date.now() / 1e3);
552
+ const authorization = {
553
+ from: wallet.address,
554
+ to: payTo,
555
+ value: amount,
556
+ // string
557
+ validAfter: String(now - 600),
558
+ // 10 minutes before (matching upstream)
559
+ validBefore: String(now + (accept.maxTimeoutSeconds || 60)),
560
+ nonce
561
+ };
562
+ const message = {
563
+ from: wallet.address,
564
+ to: payTo,
565
+ value: BigInt(amount),
566
+ validAfter: BigInt(now - 600),
567
+ validBefore: BigInt(now + (accept.maxTimeoutSeconds || 60)),
568
+ nonce
569
+ };
570
+ if (!wallet.signTypedData) {
571
+ throw new Error("Wallet does not support signTypedData (EIP-712)");
572
+ }
573
+ const signature = await wallet.signTypedData({
574
+ domain,
575
+ types,
576
+ primaryType: "TransferWithAuthorization",
577
+ message
578
+ });
579
+ this.log("EIP-712 signature obtained");
580
+ const payload = {
581
+ authorization,
582
+ signature
583
+ };
584
+ return {
585
+ serialized: JSON.stringify(payload),
586
+ signature
587
+ };
579
588
  }
580
589
  };
590
+ function createEvmAdapter(config) {
591
+ return new EvmAdapter(config);
592
+ }
581
593
 
582
594
  // src/adapters/index.ts
583
- init_solana();
584
- init_evm();
595
+ function isKnownUSDC(asset) {
596
+ if (asset === "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v") return true;
597
+ if (asset === "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU") return true;
598
+ const lc = asset.toLowerCase();
599
+ for (const addr of Object.values(USDC_ADDRESSES)) {
600
+ if (addr.toLowerCase() === lc) return true;
601
+ }
602
+ return false;
603
+ }
585
604
 
586
605
  // src/client/x402-client.ts
606
+ var receiptStore = /* @__PURE__ */ new WeakMap();
607
+ function getPaymentReceipt(response) {
608
+ return receiptStore.get(response);
609
+ }
587
610
  function createX402Client(config) {
588
611
  const {
589
612
  adapters = [createSolanaAdapter({ verbose: config.verbose }), createEvmAdapter({ verbose: config.verbose })],
@@ -701,13 +724,7 @@ function createX402Client(config) {
701
724
  if (!match) return null;
702
725
  const { accept, adapter, wallet } = match;
703
726
  if (adapter.name === "Solana" && !accept.extra?.feePayer) return null;
704
- const USDC_MINTS = [
705
- "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
706
- "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
707
- "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
708
- "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
709
- ];
710
- const decimals = accept.extra?.decimals ?? (USDC_MINTS.includes(accept.asset) ? 6 : void 0);
727
+ const decimals = accept.extra?.decimals ?? (isKnownUSDC(accept.asset) ? 6 : void 0);
711
728
  if (typeof decimals !== "number") return null;
712
729
  const paymentAmount = accept.amount || accept.maxAmountRequired;
713
730
  if (!paymentAmount) return null;
@@ -846,17 +863,7 @@ function createX402Client(config) {
846
863
  "Solana payment option missing feePayer in extra"
847
864
  );
848
865
  }
849
- const USDC_MINTS = [
850
- "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
851
- // Solana mainnet
852
- "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
853
- // Solana devnet
854
- "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
855
- // Base mainnet
856
- "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
857
- // Base sepolia
858
- ];
859
- const decimals = accept.extra?.decimals ?? (USDC_MINTS.includes(accept.asset) ? 6 : void 0);
866
+ const decimals = accept.extra?.decimals ?? (isKnownUSDC(accept.asset) ? 6 : void 0);
860
867
  if (typeof decimals !== "number") {
861
868
  throw new X402Error(
862
869
  "missing_decimals",
@@ -953,7 +960,8 @@ function createX402Client(config) {
953
960
  if (paymentResponseHeader) {
954
961
  try {
955
962
  const receipt = JSON.parse(atob(paymentResponseHeader));
956
- retryResponse._x402 = receipt;
963
+ receiptStore.set(retryResponse, receipt);
964
+ retryResponse["_x402"] = receipt;
957
965
  if (receipt.extensions) {
958
966
  log("Settlement extensions:", Object.keys(receipt.extensions).join(", "));
959
967
  }
@@ -969,16 +977,22 @@ function createX402Client(config) {
969
977
 
970
978
  // src/client/keypair-wallet.ts
971
979
  import { Keypair, VersionedTransaction as VersionedTransaction2, Transaction } from "@solana/web3.js";
972
- function createKeypairWallet(privateKey) {
980
+ async function createKeypairWallet(privateKey) {
973
981
  let keypair;
974
982
  if (typeof privateKey === "string") {
975
- const bs58 = require_cjs2();
976
- const decode = bs58.decode || bs58.default?.decode;
977
- if (!decode) {
978
- throw new Error("bs58 module not found or incompatible version");
983
+ let bs58Decode;
984
+ try {
985
+ const mod = await Promise.resolve().then(() => (init_esm2(), esm_exports));
986
+ const resolve = mod.decode ?? mod.default?.decode;
987
+ if (!resolve) throw new Error("decode not found");
988
+ bs58Decode = resolve;
989
+ } catch (e) {
990
+ throw new Error(
991
+ 'The "bs58" package is required for base58 private keys. Install it with: npm install bs58'
992
+ );
979
993
  }
980
994
  try {
981
- const decoded = decode(privateKey);
995
+ const decoded = bs58Decode(privateKey);
982
996
  keypair = Keypair.fromSecretKey(decoded);
983
997
  } catch (e) {
984
998
  try {
@@ -1057,7 +1071,6 @@ function wrapFetch(fetchImpl, options) {
1057
1071
  walletPrivateKey,
1058
1072
  evmPrivateKey,
1059
1073
  preferredNetwork,
1060
- // facilitatorUrl is reserved for future use when we add facilitator selection
1061
1074
  rpcUrls,
1062
1075
  maxAmountAtomic,
1063
1076
  verbose,
@@ -1067,17 +1080,26 @@ function wrapFetch(fetchImpl, options) {
1067
1080
  throw new Error("At least one wallet private key is required (walletPrivateKey or evmPrivateKey)");
1068
1081
  }
1069
1082
  const wallets = {};
1083
+ const walletInits = [];
1070
1084
  if (walletPrivateKey) {
1071
- wallets.solana = createKeypairWallet(walletPrivateKey);
1085
+ walletInits.push(
1086
+ createKeypairWallet(walletPrivateKey).then((w) => {
1087
+ wallets.solana = w;
1088
+ }).catch((e) => {
1089
+ console.warn(`[x402] Solana wallet init failed: ${e.message}`);
1090
+ })
1091
+ );
1072
1092
  }
1073
- let evmReady = null;
1074
1093
  if (evmPrivateKey) {
1075
- evmReady = createEvmKeypairWallet(evmPrivateKey).then((w) => {
1076
- wallets.evm = w;
1077
- }).catch((e) => {
1078
- console.warn(`[x402] ${e.message}`);
1079
- });
1094
+ walletInits.push(
1095
+ createEvmKeypairWallet(evmPrivateKey).then((w) => {
1096
+ wallets.evm = w;
1097
+ }).catch((e) => {
1098
+ console.warn(`[x402] EVM wallet init failed: ${e.message}`);
1099
+ })
1100
+ );
1080
1101
  }
1102
+ const walletsReady = walletInits.length > 0 ? Promise.all(walletInits) : null;
1081
1103
  const clientConfig = {
1082
1104
  wallets,
1083
1105
  preferredNetwork,
@@ -1089,9 +1111,9 @@ function wrapFetch(fetchImpl, options) {
1089
1111
  };
1090
1112
  const client = createX402Client(clientConfig);
1091
1113
  const clientFetch = client.fetch.bind(client);
1092
- if (evmReady) {
1114
+ if (walletsReady) {
1093
1115
  return (async (input, init) => {
1094
- await evmReady;
1116
+ await walletsReady;
1095
1117
  return clientFetch(input, init);
1096
1118
  });
1097
1119
  }
@@ -1108,6 +1130,7 @@ export {
1108
1130
  createKeypairWallet,
1109
1131
  createSolanaAdapter,
1110
1132
  createX402Client,
1133
+ getPaymentReceipt,
1111
1134
  isEvmKeypairWallet,
1112
1135
  isKeypairWallet,
1113
1136
  wrapFetch