@voyage_ai/v402-web-ts 0.2.1 → 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.
@@ -1,7 +1,23 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
1
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
2
5
  var __esm = (fn, res) => function __init() {
3
6
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
4
7
  };
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
5
21
 
6
22
  // src/types/common.ts
7
23
  var PROD_BACK_URL;
@@ -79,6 +95,28 @@ var init_types = __esm({
79
95
  });
80
96
 
81
97
  // src/utils/wallet.ts
98
+ var wallet_exports = {};
99
+ __export(wallet_exports, {
100
+ clearAllWalletAddresses: () => clearAllWalletAddresses,
101
+ clearWalletDisconnection: () => clearWalletDisconnection,
102
+ formatAddress: () => formatAddress,
103
+ getAllConnectedWalletIds: () => getAllConnectedWalletIds,
104
+ getAllWalletAddresses: () => getAllWalletAddresses,
105
+ getCachedWalletAddress: () => getCachedWalletAddress,
106
+ getConnectedNetworkType: () => getConnectedNetworkType,
107
+ getConnectedWalletId: () => getConnectedWalletId,
108
+ getWalletDisplayName: () => getWalletDisplayName,
109
+ getWalletInstallUrl: () => getWalletInstallUrl,
110
+ getWalletProvider: () => getWalletProvider,
111
+ isWalletInstalled: () => isWalletInstalled,
112
+ isWalletManuallyDisconnected: () => isWalletManuallyDisconnected,
113
+ markWalletDisconnected: () => markWalletDisconnected,
114
+ removeConnectedWalletId: () => removeConnectedWalletId,
115
+ removeWalletAddress: () => removeWalletAddress,
116
+ saveConnectedNetworkType: () => saveConnectedNetworkType,
117
+ saveConnectedWalletId: () => saveConnectedWalletId,
118
+ saveWalletAddress: () => saveWalletAddress
119
+ });
82
120
  function isWalletInstalled(networkType) {
83
121
  if (typeof window === "undefined") {
84
122
  return false;
@@ -93,6 +131,20 @@ function isWalletInstalled(networkType) {
93
131
  return false;
94
132
  }
95
133
  }
134
+ function getWalletProvider(networkType) {
135
+ if (typeof window === "undefined") {
136
+ return null;
137
+ }
138
+ switch (networkType) {
139
+ case "evm" /* EVM */:
140
+ return window.ethereum;
141
+ case "solana" /* SOLANA */:
142
+ case "svm" /* SVM */:
143
+ return window.solana || window.phantom;
144
+ default:
145
+ return null;
146
+ }
147
+ }
96
148
  function formatAddress(address) {
97
149
  if (!address || address.length < 10) {
98
150
  return address;
@@ -167,6 +219,17 @@ function getWalletInstallUrl(networkType) {
167
219
  return "#";
168
220
  }
169
221
  }
222
+ function getWalletDisplayName(networkType) {
223
+ switch (networkType) {
224
+ case "evm" /* EVM */:
225
+ return "MetaMask";
226
+ case "solana" /* SOLANA */:
227
+ case "svm" /* SVM */:
228
+ return "Phantom";
229
+ default:
230
+ return "Unknown Wallet";
231
+ }
232
+ }
170
233
  function getAllWalletAddresses() {
171
234
  if (typeof window === "undefined") {
172
235
  return {};
@@ -199,7 +262,44 @@ function removeWalletAddress(networkType) {
199
262
  delete addresses[networkType];
200
263
  localStorage.setItem(WALLET_ADDRESSES_KEY, JSON.stringify(addresses));
201
264
  }
202
- var WALLET_DISCONNECTED_KEY, WALLET_DISCONNECTED_NETWORKS_KEY, CONNECTED_NETWORK_TYPE_KEY, WALLET_ADDRESSES_KEY;
265
+ function clearAllWalletAddresses() {
266
+ if (typeof window !== "undefined") {
267
+ localStorage.removeItem(WALLET_ADDRESSES_KEY);
268
+ }
269
+ }
270
+ function getAllConnectedWalletIds() {
271
+ if (typeof window === "undefined") {
272
+ return {};
273
+ }
274
+ try {
275
+ const cached = localStorage.getItem(CONNECTED_WALLET_IDS_KEY);
276
+ return cached ? JSON.parse(cached) : {};
277
+ } catch (error) {
278
+ console.error("Failed to parse connected wallet IDs:", error);
279
+ return {};
280
+ }
281
+ }
282
+ function saveConnectedWalletId(networkType, walletId) {
283
+ if (typeof window === "undefined") {
284
+ return;
285
+ }
286
+ const walletIds = getAllConnectedWalletIds();
287
+ walletIds[networkType] = walletId;
288
+ localStorage.setItem(CONNECTED_WALLET_IDS_KEY, JSON.stringify(walletIds));
289
+ }
290
+ function getConnectedWalletId(networkType) {
291
+ const walletIds = getAllConnectedWalletIds();
292
+ return walletIds[networkType] || null;
293
+ }
294
+ function removeConnectedWalletId(networkType) {
295
+ if (typeof window === "undefined") {
296
+ return;
297
+ }
298
+ const walletIds = getAllConnectedWalletIds();
299
+ delete walletIds[networkType];
300
+ localStorage.setItem(CONNECTED_WALLET_IDS_KEY, JSON.stringify(walletIds));
301
+ }
302
+ var WALLET_DISCONNECTED_KEY, WALLET_DISCONNECTED_NETWORKS_KEY, CONNECTED_NETWORK_TYPE_KEY, WALLET_ADDRESSES_KEY, CONNECTED_WALLET_IDS_KEY;
203
303
  var init_wallet = __esm({
204
304
  "src/utils/wallet.ts"() {
205
305
  "use strict";
@@ -207,6 +307,7 @@ var init_wallet = __esm({
207
307
  WALLET_DISCONNECTED_NETWORKS_KEY = "wallet_disconnected_networks";
208
308
  CONNECTED_NETWORK_TYPE_KEY = "connected_network_type";
209
309
  WALLET_ADDRESSES_KEY = "wallet_addresses_cache";
310
+ CONNECTED_WALLET_IDS_KEY = "connected_wallet_ids";
210
311
  }
211
312
  });
212
313
 
@@ -221,45 +322,143 @@ init_wallet();
221
322
 
222
323
  // src/utils/wallet-connect.ts
223
324
  init_wallet();
224
- async function connectWallet(networkType) {
325
+ async function connectWallet(networkType, forceSelect = false) {
225
326
  if (typeof window === "undefined") {
226
- throw new Error("\u8BF7\u5728\u6D4F\u89C8\u5668\u73AF\u5883\u4E2D\u4F7F\u7528");
327
+ throw new Error("Please use in browser environment");
227
328
  }
228
329
  let address;
229
330
  switch (networkType) {
230
331
  case "evm" /* EVM */: {
231
332
  if (!window.ethereum) {
232
- throw new Error("\u8BF7\u5B89\u88C5 MetaMask \u6216\u5176\u4ED6\u4EE5\u592A\u574A\u94B1\u5305");
333
+ throw new Error("Please install MetaMask or another Ethereum wallet");
233
334
  }
234
335
  const ethereum = window.ethereum;
336
+ if (forceSelect) {
337
+ try {
338
+ const permissions = await ethereum.request({
339
+ method: "wallet_requestPermissions",
340
+ params: [{ eth_accounts: {} }]
341
+ });
342
+ const accountsPermission = permissions?.find(
343
+ (p) => p.parentCapability === "eth_accounts"
344
+ );
345
+ if (accountsPermission?.caveats?.[0]?.value?.length > 0) {
346
+ address = accountsPermission.caveats[0].value[0];
347
+ break;
348
+ }
349
+ } catch (err) {
350
+ if (err.code === 4001) {
351
+ throw new Error("User cancelled wallet connection");
352
+ }
353
+ console.warn("wallet_requestPermissions failed, falling back to eth_requestAccounts");
354
+ }
355
+ }
235
356
  const accounts = await ethereum.request({
236
357
  method: "eth_requestAccounts",
237
358
  params: []
238
359
  });
239
360
  if (!accounts || accounts.length === 0) {
240
- throw new Error("\u672A\u80FD\u83B7\u53D6\u5230\u94B1\u5305\u5730\u5740");
361
+ throw new Error("Failed to get wallet address");
241
362
  }
242
363
  address = accounts[0];
243
364
  break;
244
365
  }
245
366
  case "solana" /* SOLANA */:
246
367
  case "svm" /* SVM */: {
247
- const solana = window.solana;
368
+ const phantom = window.phantom?.solana || window.solana;
369
+ const solflare = window.solflare;
370
+ let solana = phantom;
371
+ if (!solana && solflare?.isSolflare) {
372
+ solana = solflare;
373
+ }
248
374
  if (!solana) {
249
- throw new Error("\u8BF7\u5B89\u88C5 Phantom \u6216\u5176\u4ED6 Solana \u94B1\u5305");
375
+ throw new Error("Please install Phantom or another Solana wallet");
376
+ }
377
+ if (forceSelect) {
378
+ try {
379
+ if (phantom?.isConnected) {
380
+ await phantom.disconnect();
381
+ }
382
+ if (solflare?.isConnected) {
383
+ await solflare.disconnect();
384
+ }
385
+ await new Promise((resolve) => setTimeout(resolve, 100));
386
+ } catch (err) {
387
+ console.warn("Failed to disconnect Solana wallet:", err);
388
+ }
389
+ } else if (solana.isConnected) {
390
+ try {
391
+ await solana.disconnect();
392
+ } catch (err) {
393
+ console.warn("Failed to disconnect Solana wallet:", err);
394
+ }
250
395
  }
251
396
  const response = await solana.connect();
252
397
  address = response.publicKey.toString();
253
398
  break;
254
399
  }
255
400
  default:
256
- throw new Error("\u4E0D\u652F\u6301\u7684\u7F51\u7EDC\u7C7B\u578B");
401
+ throw new Error("Unsupported network type");
257
402
  }
258
403
  clearWalletDisconnection(networkType);
259
404
  saveConnectedNetworkType(networkType);
260
405
  saveWalletAddress(networkType, address);
261
406
  return address;
262
407
  }
408
+ async function disconnectAllSolanaWallets() {
409
+ if (typeof window === "undefined") return;
410
+ const phantom = window.phantom?.solana || window.solana;
411
+ const solflare = window.solflare;
412
+ const disconnectPromises = [];
413
+ if (phantom?.isConnected) {
414
+ disconnectPromises.push(
415
+ phantom.disconnect().catch(
416
+ (err) => console.warn("Failed to disconnect Phantom:", err)
417
+ )
418
+ );
419
+ }
420
+ if (solflare?.isConnected) {
421
+ disconnectPromises.push(
422
+ solflare.disconnect().catch(
423
+ (err) => console.warn("Failed to disconnect Solflare:", err)
424
+ )
425
+ );
426
+ }
427
+ await Promise.all(disconnectPromises);
428
+ }
429
+ async function disconnectWallet(networkType, clearAll = false) {
430
+ const targetNetwork = networkType || getConnectedNetworkType();
431
+ if (targetNetwork && typeof window !== "undefined") {
432
+ try {
433
+ switch (targetNetwork) {
434
+ case "solana" /* SOLANA */:
435
+ case "svm" /* SVM */: {
436
+ await disconnectAllSolanaWallets();
437
+ break;
438
+ }
439
+ // EVM wallets (like MetaMask) don't have a real disconnect API
440
+ // Only clear local state, will request permissions again on next connection
441
+ case "evm" /* EVM */:
442
+ default:
443
+ break;
444
+ }
445
+ } catch (err) {
446
+ console.warn("Failed to disconnect wallet:", err);
447
+ }
448
+ }
449
+ if (clearAll) {
450
+ const { clearAllWalletAddresses: clearAllWalletAddresses2 } = (init_wallet(), __toCommonJS(wallet_exports));
451
+ clearAllWalletAddresses2();
452
+ markWalletDisconnected();
453
+ await disconnectAllSolanaWallets();
454
+ } else if (networkType) {
455
+ removeWalletAddress(networkType);
456
+ } else {
457
+ if (targetNetwork) {
458
+ removeWalletAddress(targetNetwork);
459
+ }
460
+ }
461
+ }
263
462
  async function getCurrentWallet(networkType) {
264
463
  if (typeof window === "undefined") {
265
464
  return null;
@@ -269,36 +468,32 @@ async function getCurrentWallet(networkType) {
269
468
  return null;
270
469
  }
271
470
  const cachedAddress = getCachedWalletAddress(type);
272
- try {
273
- let currentAddress = null;
274
- switch (type) {
275
- case "evm" /* EVM */: {
276
- if (!window.ethereum) return cachedAddress;
471
+ if (type === "evm" /* EVM */) {
472
+ if (cachedAddress) {
473
+ return cachedAddress;
474
+ }
475
+ if (window.ethereum) {
476
+ try {
277
477
  const accounts = await window.ethereum.request({
278
478
  method: "eth_accounts",
279
479
  params: []
280
480
  });
281
- currentAddress = accounts && accounts.length > 0 ? accounts[0] : null;
282
- break;
481
+ return accounts && accounts.length > 0 ? accounts[0] : null;
482
+ } catch (error) {
483
+ console.error("Failed to get EVM accounts:", error);
484
+ return null;
283
485
  }
284
- case "solana" /* SOLANA */:
285
- case "svm" /* SVM */: {
286
- const solana = window.solana;
287
- if (!solana || !solana.isConnected) return cachedAddress;
288
- currentAddress = solana.publicKey?.toString() || null;
289
- break;
290
- }
291
- default:
292
- return cachedAddress;
293
486
  }
294
- if (currentAddress && currentAddress !== cachedAddress) {
295
- saveWalletAddress(type, currentAddress);
487
+ return null;
488
+ }
489
+ if (type === "solana" /* SOLANA */ || type === "svm" /* SVM */) {
490
+ const solana = window.solana;
491
+ if (!solana || !solana.isConnected) {
492
+ return cachedAddress;
296
493
  }
297
- return currentAddress || cachedAddress;
298
- } catch (error) {
299
- console.error("Failed to get current wallet:", error);
300
- return cachedAddress;
494
+ return solana.publicKey?.toString() || cachedAddress;
301
495
  }
496
+ return cachedAddress;
302
497
  }
303
498
  function onAccountsChanged(callback) {
304
499
  if (typeof window === "undefined" || !window.ethereum) {
@@ -361,24 +556,257 @@ async function switchNetwork(networkType) {
361
556
  return null;
362
557
  }
363
558
 
559
+ // src/utils/wallet-discovery.ts
560
+ init_wallet();
561
+ var SOLANA_WALLETS = [
562
+ {
563
+ id: "phantom",
564
+ name: "Phantom",
565
+ // Phantom official icon
566
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiNBQjlGRjIiLz4KPHBhdGggZD0iTTExMC41IDY0QzExMC41IDg5Ljk1NjggODkuMjAxIDExMSA2My41IDExMUg0MS41QzM2LjI1MzMgMTExIDMyIDEwNi43NDcgMzIgMTAxLjVWNTQuNUMzMiAzMS4wMjggNTEuMDI4IDEyIDc0LjUgMTJDOTcuOTcyIDEyIDExNyAzMS4wMjggMTE3IDU0LjVWNTUuNUMxMTcgNTguNTM3NiAxMTQuNTM4IDYxIDExMS41IDYxSDEwOS41QzEwNi40NjIgNjEgMTA0IDYzLjQ2MjQgMTA0IDY2LjVWNjhDMTA0IDcxLjg2NiAxMDcuMTM0IDc1IDExMSA3NUgxMTEuNUMxMTQuNTM4IDc1IDExNyA3Mi41Mzc2IDExNyA2OS41VjY0SDExMC41WiIgZmlsbD0idXJsKCNwYWludDBfbGluZWFyXzEyOF8xMjgpIi8+CjxwYXRoIGQ9Ik00OC41IDY3QzUxLjUzNzYgNjcgNTQgNjQuNTM3NiA1NCA2MS41QzU0IDU4LjQ2MjQgNTEuNTM3NiA1NiA0OC41IDU2QzQ1LjQ2MjQgNTYgNDMgNTguNDYyNCA0MyA2MS41QzQzIDY0LjUzNzYgNDUuNDYyNCA2NyA0OC41IDY3WiIgZmlsbD0iIzFCMUIxQiIvPgo8cGF0aCBkPSJNNzMuNSA2N0M3Ni41Mzc2IDY3IDc5IDY0LjUzNzYgNzkgNjEuNUM3OSA1OC40NjI0IDc2LjUzNzYgNTYgNzMuNSA1NkM3MC40NjI0IDU2IDY4IDU4LjQ2MjQgNjggNjEuNUM2OCA2NC41Mzc2IDcwLjQ2MjQgNjcgNzMuNSA2N1oiIGZpbGw9IiMxQjFCMUIiLz4KPGRlZnM+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQwX2xpbmVhcl8xMjhfMTI4IiB4MT0iMTE3IiB5MT0iMTIiIHgyPSIxMTciIHkyPSIxMTEiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0ZGRkZGRiIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNGRkZGRkYiIHN0b3Atb3BhY2l0eT0iMC44MiIvPgo8L2xpbmVhckdyYWRpZW50Pgo8L2RlZnM+Cjwvc3ZnPg==",
567
+ detect: () => window.phantom?.solana
568
+ },
569
+ {
570
+ id: "solflare",
571
+ name: "Solflare",
572
+ // Solflare icon
573
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiNGQzZEMDEiLz4KPHBhdGggZD0iTTk2IDY0TDY0IDMyTDMyIDY0TDY0IDk2TDk2IDY0WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+",
574
+ detect: () => window.solflare
575
+ },
576
+ {
577
+ id: "backpack",
578
+ name: "Backpack",
579
+ // Backpack icon (red coral color)
580
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiNFMzM0MzAiLz4KPHBhdGggZD0iTTQwIDQ4SDg4VjgwQzg4IDg4LjgzNjYgODAuODM2NiA5NiA3MiA5Nkg1NkM0Ny4xNjM0IDk2IDQwIDg4LjgzNjYgNDAgODBWNDhaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNNTIgMzJINzZWNDhINTJWMzJaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4=",
581
+ detect: () => window.backpack
582
+ },
583
+ {
584
+ id: "okx-solana",
585
+ name: "OKX Wallet",
586
+ // OKX icon
587
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9ImJsYWNrIi8+CjxyZWN0IHg9IjI0IiB5PSIyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0id2hpdGUiLz4KPHJlY3QgeD0iNTIiIHk9IjI0IiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSJ3aGl0ZSIvPgo8cmVjdCB4PSI4MCIgeT0iMjQiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgcng9IjQiIGZpbGw9IndoaXRlIi8+CjxyZWN0IHg9IjI0IiB5PSI1MiIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0id2hpdGUiLz4KPHJlY3QgeD0iODAiIHk9IjUyIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSJ3aGl0ZSIvPgo8cmVjdCB4PSIyNCIgeT0iODAiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgcng9IjQiIGZpbGw9IndoaXRlIi8+CjxyZWN0IHg9IjUyIiB5PSI4MCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0id2hpdGUiLz4KPHJlY3QgeD0iODAiIHk9IjgwIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4=",
588
+ detect: () => window.okxwallet?.solana
589
+ },
590
+ {
591
+ id: "coinbase-solana",
592
+ name: "Coinbase Wallet",
593
+ // Coinbase icon (blue)
594
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiMwMDUyRkYiLz4KPGNpcmNsZSBjeD0iNjQiIGN5PSI2NCIgcj0iMzYiIGZpbGw9IndoaXRlIi8+CjxyZWN0IHg9IjQ4IiB5PSI1NiIgd2lkdGg9IjMyIiBoZWlnaHQ9IjE2IiByeD0iNCIgZmlsbD0iIzAwNTJGRiIvPgo8L3N2Zz4=",
595
+ detect: () => window.coinbaseSolana
596
+ },
597
+ {
598
+ id: "trust-solana",
599
+ name: "Trust Wallet",
600
+ // Trust Wallet icon
601
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiMwNTAwRkYiLz4KPHBhdGggZD0iTTY0IDI0QzY0IDI0IDk2IDQwIDk2IDY0Qzk2IDg4IDY0IDEwNCA2NCAxMDRDNjQgMTA0IDMyIDg4IDMyIDY0QzMyIDQwIDY0IDI0IDY0IDI0WiIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSI2IiBmaWxsPSJub25lIi8+Cjwvc3ZnPg==",
602
+ detect: () => window.trustwallet?.solana
603
+ }
604
+ ];
605
+ var evmWallets = /* @__PURE__ */ new Map();
606
+ var evmDiscoveryListeners = /* @__PURE__ */ new Set();
607
+ var evmDiscoveryInitialized = false;
608
+ var currentConnectedWallet = null;
609
+ function initEVMWalletDiscovery() {
610
+ if (typeof window === "undefined" || evmDiscoveryInitialized) return;
611
+ evmDiscoveryInitialized = true;
612
+ window.addEventListener("eip6963:announceProvider", ((event) => {
613
+ const { info, provider } = event.detail;
614
+ evmWallets.set(info.uuid, { info, provider });
615
+ evmDiscoveryListeners.forEach((listener) => listener());
616
+ }));
617
+ window.dispatchEvent(new Event("eip6963:requestProvider"));
618
+ }
619
+ function getEVMWallets() {
620
+ const wallets = [];
621
+ const detectedNames = /* @__PURE__ */ new Set();
622
+ evmWallets.forEach((detail, uuid) => {
623
+ if (!detectedNames.has(detail.info.name)) {
624
+ wallets.push({
625
+ id: uuid,
626
+ name: detail.info.name,
627
+ icon: detail.info.icon,
628
+ networkType: "evm" /* EVM */,
629
+ provider: detail.provider,
630
+ installed: true
631
+ });
632
+ detectedNames.add(detail.info.name);
633
+ }
634
+ });
635
+ if (wallets.length === 0 && typeof window !== "undefined" && window.ethereum) {
636
+ const ethereum = window.ethereum;
637
+ const walletName = ethereum.isMetaMask ? "MetaMask" : ethereum.isCoinbaseWallet ? "Coinbase Wallet" : ethereum.isOkxWallet ? "OKX Wallet" : "Browser Wallet";
638
+ if (!detectedNames.has(walletName)) {
639
+ wallets.push({
640
+ id: "injected",
641
+ name: walletName,
642
+ icon: "",
643
+ // Will use first letter as avatar
644
+ networkType: "evm" /* EVM */,
645
+ provider: ethereum,
646
+ installed: true
647
+ });
648
+ }
649
+ }
650
+ return wallets;
651
+ }
652
+ function onEVMWalletsChanged(callback) {
653
+ evmDiscoveryListeners.add(callback);
654
+ return () => {
655
+ evmDiscoveryListeners.delete(callback);
656
+ };
657
+ }
658
+ function getSolanaWallets() {
659
+ if (typeof window === "undefined") return [];
660
+ const wallets = [];
661
+ const detectedProviders = /* @__PURE__ */ new Set();
662
+ const detectedNames = /* @__PURE__ */ new Set();
663
+ for (const wallet of SOLANA_WALLETS) {
664
+ const provider = wallet.detect();
665
+ if (provider && !detectedNames.has(wallet.name)) {
666
+ wallets.push({
667
+ id: wallet.id,
668
+ name: wallet.name,
669
+ icon: wallet.icon,
670
+ networkType: "solana" /* SOLANA */,
671
+ provider,
672
+ installed: true
673
+ });
674
+ detectedProviders.add(provider);
675
+ detectedNames.add(wallet.name);
676
+ }
677
+ }
678
+ const windowSolana = window.solana;
679
+ if (windowSolana && !detectedProviders.has(windowSolana)) {
680
+ const walletName = windowSolana.isPhantom ? "Phantom" : windowSolana.isSolflare ? "Solflare" : windowSolana.isBackpack ? "Backpack" : windowSolana.walletName || "Solana Wallet";
681
+ if (!detectedNames.has(walletName)) {
682
+ wallets.push({
683
+ id: "solana-unknown",
684
+ name: walletName,
685
+ icon: "",
686
+ // Will use first letter as avatar
687
+ networkType: "solana" /* SOLANA */,
688
+ provider: windowSolana,
689
+ installed: true
690
+ });
691
+ }
692
+ }
693
+ return wallets;
694
+ }
695
+ function getWalletsForNetwork(networkType) {
696
+ switch (networkType) {
697
+ case "evm" /* EVM */:
698
+ return getEVMWallets();
699
+ case "solana" /* SOLANA */:
700
+ case "svm" /* SVM */:
701
+ return getSolanaWallets();
702
+ default:
703
+ return [];
704
+ }
705
+ }
706
+ function getWalletByName(name, networkType) {
707
+ const wallets = getWalletsForNetwork(networkType);
708
+ return wallets.find((w) => w.name === name) || null;
709
+ }
710
+ async function connectEVMWallet(wallet) {
711
+ if (!wallet.provider) {
712
+ throw new Error(`Wallet ${wallet.name} is not available`);
713
+ }
714
+ const accounts = await wallet.provider.request({
715
+ method: "eth_requestAccounts",
716
+ params: []
717
+ });
718
+ if (!accounts || accounts.length === 0) {
719
+ throw new Error("Failed to get wallet address");
720
+ }
721
+ return accounts[0];
722
+ }
723
+ async function connectSolanaWallet(wallet) {
724
+ if (!wallet.provider) {
725
+ throw new Error(`Wallet ${wallet.name} is not available`);
726
+ }
727
+ if (wallet.provider.isConnected) {
728
+ try {
729
+ await wallet.provider.disconnect();
730
+ } catch (err) {
731
+ console.warn("Failed to disconnect before connecting:", err);
732
+ }
733
+ }
734
+ const response = await wallet.provider.connect();
735
+ return response.publicKey.toString();
736
+ }
737
+ async function connectToWallet(wallet) {
738
+ let address;
739
+ switch (wallet.networkType) {
740
+ case "evm" /* EVM */:
741
+ address = await connectEVMWallet(wallet);
742
+ break;
743
+ case "solana" /* SOLANA */:
744
+ case "svm" /* SVM */:
745
+ address = await connectSolanaWallet(wallet);
746
+ break;
747
+ default:
748
+ throw new Error("Unsupported network type");
749
+ }
750
+ currentConnectedWallet = wallet;
751
+ saveConnectedWalletId(wallet.networkType, wallet.name);
752
+ return address;
753
+ }
754
+ function setCurrentConnectedWallet(wallet) {
755
+ currentConnectedWallet = wallet;
756
+ }
757
+ function clearConnectedWallet(networkType) {
758
+ if (networkType) {
759
+ removeConnectedWalletId(networkType);
760
+ }
761
+ currentConnectedWallet = null;
762
+ }
763
+ function restoreConnectedWallet(networkType) {
764
+ const savedWalletName = getConnectedWalletId(networkType);
765
+ if (!savedWalletName) return null;
766
+ const wallet = getWalletByName(savedWalletName, networkType);
767
+ if (wallet) {
768
+ currentConnectedWallet = wallet;
769
+ console.log(`\u2705 Restored wallet provider: ${wallet.name}`);
770
+ return wallet;
771
+ }
772
+ console.warn(`\u26A0\uFE0F Could not find wallet with name: ${savedWalletName}`);
773
+ return null;
774
+ }
775
+ function getWalletProviderForPayment(networkType) {
776
+ if (currentConnectedWallet && currentConnectedWallet.networkType === networkType) {
777
+ return currentConnectedWallet.provider;
778
+ }
779
+ const restoredWallet = restoreConnectedWallet(networkType);
780
+ if (restoredWallet) {
781
+ return restoredWallet.provider;
782
+ }
783
+ if (typeof window === "undefined") return null;
784
+ switch (networkType) {
785
+ case "evm" /* EVM */:
786
+ return window.ethereum;
787
+ case "solana" /* SOLANA */:
788
+ case "svm" /* SVM */:
789
+ return window.phantom?.solana || window.solana;
790
+ default:
791
+ return null;
792
+ }
793
+ }
794
+ if (typeof window !== "undefined") {
795
+ initEVMWalletDiscovery();
796
+ }
797
+
364
798
  // src/services/svm/payment-header.ts
365
- import {
366
- ComputeBudgetProgram,
367
- Connection,
368
- PublicKey,
369
- TransactionMessage,
370
- VersionedTransaction
371
- } from "@solana/web3.js";
799
+ import { ComputeBudgetProgram, Connection, PublicKey, TransactionMessage, VersionedTransaction } from "@solana/web3.js";
372
800
  import {
373
801
  createTransferCheckedInstruction,
374
- getAssociatedTokenAddress,
802
+ getAssociatedTokenAddressSync,
375
803
  getMint,
376
804
  TOKEN_2022_PROGRAM_ID,
377
805
  TOKEN_PROGRAM_ID
378
806
  } from "@solana/spl-token";
379
807
  async function createSvmPaymentHeader(params) {
380
808
  const { wallet, paymentRequirements, x402Version, rpcUrl } = params;
381
- const connection = new Connection(rpcUrl, "confirmed");
809
+ const connection = new Connection(rpcUrl);
382
810
  const feePayer = paymentRequirements?.extra?.feePayer;
383
811
  if (typeof feePayer !== "string" || !feePayer) {
384
812
  throw new Error("Missing facilitator feePayer in payment requirements (extra.feePayer).");
@@ -392,83 +820,85 @@ async function createSvmPaymentHeader(params) {
392
820
  if (!paymentRequirements?.payTo) {
393
821
  throw new Error("Missing payTo in payment requirements");
394
822
  }
395
- const destination = new PublicKey(paymentRequirements.payTo);
396
- const instructions = [];
397
- instructions.push(
398
- ComputeBudgetProgram.setComputeUnitLimit({
399
- units: 7e3
400
- // Sufficient for SPL token transfer
401
- })
402
- );
403
- instructions.push(
404
- ComputeBudgetProgram.setComputeUnitPrice({
405
- microLamports: 1
406
- // Minimal price
407
- })
408
- );
823
+ const destinationPubkey = new PublicKey(paymentRequirements.payTo);
409
824
  if (!paymentRequirements.asset) {
410
825
  throw new Error("Missing token mint for SPL transfer");
411
826
  }
412
827
  const mintPubkey = new PublicKey(paymentRequirements.asset);
413
- const mintInfo = await connection.getAccountInfo(mintPubkey, "confirmed");
414
- const programId = mintInfo?.owner?.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58() ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID;
415
- const mint = await getMint(connection, mintPubkey, void 0, programId);
416
- const sourceAta = await getAssociatedTokenAddress(
828
+ const mintAccountInfo = await connection.getAccountInfo(mintPubkey);
829
+ if (!mintAccountInfo) {
830
+ throw new Error(`Mint account ${mintPubkey.toBase58()} not found`);
831
+ }
832
+ const tokenProgramId = mintAccountInfo.owner.equals(TOKEN_2022_PROGRAM_ID) ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID;
833
+ const mint = await getMint(connection, mintPubkey, void 0, tokenProgramId);
834
+ const sourceAta = getAssociatedTokenAddressSync(
417
835
  mintPubkey,
418
836
  userPubkey,
419
837
  false,
420
- programId
838
+ tokenProgramId
421
839
  );
422
- const destinationAta = await getAssociatedTokenAddress(
840
+ const destinationAta = getAssociatedTokenAddressSync(
423
841
  mintPubkey,
424
- destination,
842
+ destinationPubkey,
425
843
  false,
426
- programId
844
+ tokenProgramId
427
845
  );
428
- const sourceAtaInfo = await connection.getAccountInfo(sourceAta, "confirmed");
846
+ const sourceAtaInfo = await connection.getAccountInfo(sourceAta);
429
847
  if (!sourceAtaInfo) {
430
848
  throw new Error(
431
849
  `User does not have an Associated Token Account for ${paymentRequirements.asset}. Please create one first or ensure you have the required token.`
432
850
  );
433
851
  }
434
- const destAtaInfo = await connection.getAccountInfo(destinationAta, "confirmed");
852
+ const destAtaInfo = await connection.getAccountInfo(destinationAta);
435
853
  if (!destAtaInfo) {
436
854
  throw new Error(
437
855
  `Destination does not have an Associated Token Account for ${paymentRequirements.asset}. The receiver must create their token account before receiving payments.`
438
856
  );
439
857
  }
440
- const amount = BigInt(paymentRequirements.maxAmountRequired);
441
- instructions.push(
858
+ const instructions = [
859
+ ComputeBudgetProgram.setComputeUnitLimit({
860
+ units: 7e3
861
+ // Sufficient for SPL token transfer
862
+ }),
863
+ ComputeBudgetProgram.setComputeUnitPrice({
864
+ microLamports: 1
865
+ // Minimal price
866
+ }),
442
867
  createTransferCheckedInstruction(
443
868
  sourceAta,
444
869
  mintPubkey,
445
870
  destinationAta,
446
871
  userPubkey,
447
- amount,
872
+ BigInt(paymentRequirements.maxAmountRequired),
448
873
  mint.decimals,
449
874
  [],
450
- programId
875
+ tokenProgramId
451
876
  )
452
- );
453
- const { blockhash } = await connection.getLatestBlockhash("confirmed");
454
- const message2 = new TransactionMessage({
877
+ ];
878
+ const { blockhash } = await connection.getLatestBlockhash();
879
+ const messageV0 = new TransactionMessage({
455
880
  payerKey: feePayerPubkey,
456
881
  recentBlockhash: blockhash,
457
882
  instructions
458
883
  }).compileToV0Message();
459
- const transaction = new VersionedTransaction(message2);
884
+ const transaction = new VersionedTransaction(messageV0);
460
885
  if (typeof wallet?.signTransaction !== "function") {
461
886
  throw new Error("Connected wallet does not support signTransaction");
462
887
  }
463
- let userSignedTx;
888
+ let signedTransaction;
464
889
  try {
465
- userSignedTx = await wallet.signTransaction(transaction);
890
+ signedTransaction = await wallet.signTransaction(transaction);
466
891
  console.log("\u2705 Transaction signed successfully");
467
892
  } catch (error) {
468
893
  console.error("\u274C Failed to sign transaction:", error);
469
894
  throw wrapPaymentError(error);
470
895
  }
471
- const serializedTransaction = Buffer.from(userSignedTx.serialize()).toString("base64");
896
+ const serializedBytes = signedTransaction.serialize();
897
+ let binary = "";
898
+ for (let i = 0; i < serializedBytes.length; i++) {
899
+ binary += String.fromCharCode(serializedBytes[i]);
900
+ }
901
+ const serializedTransaction = btoa(binary);
472
902
  const paymentPayload = {
473
903
  x402Version,
474
904
  scheme: paymentRequirements.scheme,
@@ -477,7 +907,7 @@ async function createSvmPaymentHeader(params) {
477
907
  transaction: serializedTransaction
478
908
  }
479
909
  };
480
- const paymentHeader = Buffer.from(JSON.stringify(paymentPayload)).toString("base64");
910
+ const paymentHeader = btoa(JSON.stringify(paymentPayload));
481
911
  return paymentHeader;
482
912
  }
483
913
  function getDefaultSolanaRpcUrl(network) {
@@ -493,7 +923,7 @@ function getDefaultSolanaRpcUrl(network) {
493
923
  // src/services/svm/payment-handler.ts
494
924
  init_types();
495
925
  async function handleSvmPayment(endpoint, config, requestInit) {
496
- const { wallet, network, rpcUrl, maxPaymentAmount } = config;
926
+ const { wallet, rpcUrl, maxPaymentAmount } = config;
497
927
  const initialResponse = await fetch(endpoint, {
498
928
  ...requestInit,
499
929
  method: requestInit?.method || "POST"
@@ -502,26 +932,10 @@ async function handleSvmPayment(endpoint, config, requestInit) {
502
932
  return initialResponse;
503
933
  }
504
934
  const rawResponse = await initialResponse.json();
505
- const IGNORED_ERRORS = [
506
- "X-PAYMENT header is required",
507
- "missing X-PAYMENT header",
508
- "payment_required"
509
- ];
510
- if (rawResponse.error && !IGNORED_ERRORS.includes(rawResponse.error)) {
935
+ if (rawResponse.error && !IGNORED_402_ERRORS.includes(rawResponse.error)) {
511
936
  console.error(`\u274C Payment verification failed: ${rawResponse.error}`);
512
- const ERROR_MESSAGES = {
513
- "insufficient_funds": "Insufficient balance to complete this payment",
514
- "invalid_signature": "Invalid payment signature",
515
- "expired": "Payment authorization has expired",
516
- "already_used": "This payment has already been used",
517
- "network_mismatch": "Payment network does not match",
518
- "invalid_payment": "Invalid payment data",
519
- "verification_failed": "Payment verification failed",
520
- "invalid_exact_svm_payload_transaction_simulation_failed": "Transaction simulation failed due to insufficient balance. Please check your wallet balance carefully and ensure you have enough funds to cover the payment and transaction fees."
521
- };
522
- const errorMessage = ERROR_MESSAGES[rawResponse.error] || `Payment failed: ${rawResponse.error}`;
523
- const error = new Error(errorMessage);
524
- throw wrapPaymentError(error);
937
+ const errorMessage = PAYMENT_ERROR_MESSAGES[rawResponse.error] || `Payment failed: ${rawResponse.error}`;
938
+ throw wrapPaymentError(new Error(errorMessage));
525
939
  }
526
940
  const x402Version = rawResponse.x402Version;
527
941
  const parsedPaymentRequirements = rawResponse.accepts || [];
@@ -571,26 +985,10 @@ async function handleSvmPayment(endpoint, config, requestInit) {
571
985
  if (retryResponse.status === 402) {
572
986
  try {
573
987
  const retryData = await retryResponse.json();
574
- const IGNORED_ERRORS2 = [
575
- "X-PAYMENT header is required",
576
- "missing X-PAYMENT header",
577
- "payment_required"
578
- ];
579
- if (retryData.error && !IGNORED_ERRORS2.includes(retryData.error)) {
988
+ if (retryData.error && !IGNORED_402_ERRORS.includes(retryData.error)) {
580
989
  console.error(`\u274C Payment verification failed: ${retryData.error}`);
581
- const ERROR_MESSAGES = {
582
- "insufficient_funds": "Insufficient balance to complete this payment",
583
- "invalid_signature": "Invalid payment signature",
584
- "expired": "Payment authorization has expired",
585
- "already_used": "This payment has already been used",
586
- "network_mismatch": "Payment network does not match",
587
- "invalid_payment": "Invalid payment data",
588
- "verification_failed": "Payment verification failed",
589
- "invalid_exact_svm_payload_transaction_simulation_failed": "Transaction simulation failed due to insufficient balance. Please check your wallet balance carefully and ensure you have enough funds to cover the payment and transaction fees."
590
- };
591
- const errorMessage = ERROR_MESSAGES[retryData.error] || `Payment failed: ${retryData.error}`;
592
- const error = new Error(errorMessage);
593
- throw wrapPaymentError(error);
990
+ const errorMessage = PAYMENT_ERROR_MESSAGES[retryData.error] || `Payment failed: ${retryData.error}`;
991
+ throw wrapPaymentError(new Error(errorMessage));
594
992
  }
595
993
  } catch (error) {
596
994
  if (error instanceof PaymentOperationError) {
@@ -717,6 +1115,15 @@ function getChainIdFromNetwork(network) {
717
1115
 
718
1116
  // src/services/evm/payment-handler.ts
719
1117
  init_types();
1118
+ var NETWORK_NAMES = {
1119
+ 1: "Ethereum Mainnet",
1120
+ 11155111: "Sepolia Testnet",
1121
+ 8453: "Base Mainnet",
1122
+ 84532: "Base Sepolia Testnet",
1123
+ 137: "Polygon Mainnet",
1124
+ 42161: "Arbitrum One",
1125
+ 10: "Optimism Mainnet"
1126
+ };
720
1127
  async function handleEvmPayment(endpoint, config, requestInit) {
721
1128
  const { wallet, network, maxPaymentAmount } = config;
722
1129
  const initialResponse = await fetch(endpoint, {
@@ -727,25 +1134,10 @@ async function handleEvmPayment(endpoint, config, requestInit) {
727
1134
  return initialResponse;
728
1135
  }
729
1136
  const rawResponse = await initialResponse.json();
730
- const IGNORED_ERRORS = [
731
- "X-PAYMENT header is required",
732
- "missing X-PAYMENT header",
733
- "payment_required"
734
- ];
735
- if (rawResponse.error && !IGNORED_ERRORS.includes(rawResponse.error)) {
1137
+ if (rawResponse.error && !IGNORED_402_ERRORS.includes(rawResponse.error)) {
736
1138
  console.error(`\u274C Payment verification failed: ${rawResponse.error}`);
737
- const ERROR_MESSAGES = {
738
- "insufficient_funds": "Insufficient balance to complete this payment",
739
- "invalid_signature": "Invalid payment signature",
740
- "expired": "Payment authorization has expired",
741
- "already_used": "This payment has already been used",
742
- "network_mismatch": "Payment network does not match",
743
- "invalid_payment": "Invalid payment data",
744
- "verification_failed": "Payment verification failed"
745
- };
746
- const errorMessage = ERROR_MESSAGES[rawResponse.error] || `Payment failed: ${rawResponse.error}`;
747
- const error = new Error(errorMessage);
748
- throw wrapPaymentError(error);
1139
+ const errorMessage = PAYMENT_ERROR_MESSAGES[rawResponse.error] || `Payment failed: ${rawResponse.error}`;
1140
+ throw wrapPaymentError(new Error(errorMessage));
749
1141
  }
750
1142
  const x402Version = rawResponse.x402Version;
751
1143
  const parsedPaymentRequirements = rawResponse.accepts || [];
@@ -777,19 +1169,10 @@ async function handleEvmPayment(endpoint, config, requestInit) {
777
1169
  console.warn("\u26A0\uFE0F Failed to get current chainId:", error);
778
1170
  }
779
1171
  }
780
- const networkNames = {
781
- 1: "Ethereum Mainnet",
782
- 11155111: "Sepolia Testnet",
783
- 8453: "Base Mainnet",
784
- 84532: "Base Sepolia Testnet",
785
- 137: "Polygon Mainnet",
786
- 42161: "Arbitrum One",
787
- 10: "Optimism Mainnet"
788
- };
789
1172
  if (currentChainId && currentChainId !== targetChainId) {
790
1173
  if (!wallet.switchChain) {
791
- const currentNetworkName = networkNames[currentChainId] || `Chain ${currentChainId}`;
792
- const targetNetworkName = networkNames[targetChainId] || selectedRequirements.network;
1174
+ const currentNetworkName = NETWORK_NAMES[currentChainId] || `Chain ${currentChainId}`;
1175
+ const targetNetworkName = NETWORK_NAMES[targetChainId] || selectedRequirements.network;
793
1176
  const error = new Error(
794
1177
  `Network mismatch: Your wallet is connected to ${currentNetworkName}, but payment requires ${targetNetworkName}. Please switch to ${targetNetworkName} manually in your wallet.`
795
1178
  );
@@ -801,7 +1184,7 @@ async function handleEvmPayment(endpoint, config, requestInit) {
801
1184
  console.log(`\u2705 Successfully switched to chain ${targetChainId}`);
802
1185
  } catch (error) {
803
1186
  console.error("\u274C Failed to switch chain:", error);
804
- const targetNetworkName = networkNames[targetChainId] || selectedRequirements.network;
1187
+ const targetNetworkName = NETWORK_NAMES[targetChainId] || selectedRequirements.network;
805
1188
  const wrappedError = wrapPaymentError(error);
806
1189
  let finalError;
807
1190
  if (wrappedError.code === "USER_REJECTED" /* USER_REJECTED */) {
@@ -855,25 +1238,10 @@ async function handleEvmPayment(endpoint, config, requestInit) {
855
1238
  if (retryResponse.status === 402) {
856
1239
  try {
857
1240
  const retryData = await retryResponse.json();
858
- const IGNORED_ERRORS2 = [
859
- "X-PAYMENT header is required",
860
- "missing X-PAYMENT header",
861
- "payment_required"
862
- ];
863
- if (retryData.error && !IGNORED_ERRORS2.includes(retryData.error)) {
1241
+ if (retryData.error && !IGNORED_402_ERRORS.includes(retryData.error)) {
864
1242
  console.error(`\u274C Payment verification failed: ${retryData.error}`);
865
- const ERROR_MESSAGES = {
866
- "insufficient_funds": "Insufficient balance to complete this payment",
867
- "invalid_signature": "Invalid payment signature",
868
- "expired": "Payment authorization has expired",
869
- "already_used": "This payment has already been used",
870
- "network_mismatch": "Payment network does not match",
871
- "invalid_payment": "Invalid payment data",
872
- "verification_failed": "Payment verification failed"
873
- };
874
- const errorMessage = ERROR_MESSAGES[retryData.error] || `Payment failed: ${retryData.error}`;
875
- const error = new Error(errorMessage);
876
- throw wrapPaymentError(error);
1243
+ const errorMessage = PAYMENT_ERROR_MESSAGES[retryData.error] || `Payment failed: ${retryData.error}`;
1244
+ throw wrapPaymentError(new Error(errorMessage));
877
1245
  }
878
1246
  } catch (error) {
879
1247
  if (error instanceof PaymentOperationError) {
@@ -911,7 +1279,7 @@ function getSupportedNetworkTypes(paymentRequirements) {
911
1279
  });
912
1280
  return Array.from(networkTypes);
913
1281
  }
914
- async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, additionalParams) {
1282
+ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, additionalParams, expectedAddress) {
915
1283
  const fullEndpoint = `${endpoint}/${merchantId}`;
916
1284
  let response;
917
1285
  const requestInit = additionalParams && Object.keys(additionalParams).length > 0 ? {
@@ -921,26 +1289,41 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, ad
921
1289
  }
922
1290
  } : {};
923
1291
  if (networkType === "solana" /* SOLANA */ || networkType === "svm" /* SVM */) {
924
- const solana = window.solana;
1292
+ const solana = getWalletProviderForPayment(networkType);
925
1293
  if (!solana) {
926
- throw new Error("\u8BF7\u5B89\u88C5 Phantom \u94B1\u5305");
1294
+ throw new Error("Please connect your Solana wallet first.");
927
1295
  }
928
1296
  if (!solana.isConnected) {
929
1297
  await solana.connect();
930
1298
  }
1299
+ if (expectedAddress && solana.publicKey) {
1300
+ const currentAddress = solana.publicKey.toString();
1301
+ if (currentAddress !== expectedAddress) {
1302
+ throw new Error(
1303
+ `Wallet account mismatch: the current wallet account is ${currentAddress.slice(0, 8)}...\uFF0CBut the desired account is ${expectedAddress.slice(0, 8)}.... Please switch to the correct account in your wallet.`
1304
+ );
1305
+ }
1306
+ }
931
1307
  response = await handleSvmPayment(fullEndpoint, {
932
1308
  wallet: solana,
933
1309
  network: "solana"
934
1310
  // Will use backend's network configuration
935
1311
  }, requestInit);
936
1312
  } else if (networkType === "evm" /* EVM */) {
937
- if (!window.ethereum) {
938
- throw new Error("\u8BF7\u5B89\u88C5 MetaMask \u94B1\u5305");
1313
+ const ethereum = getWalletProviderForPayment(networkType);
1314
+ if (!ethereum) {
1315
+ throw new Error("Please connect the EVM wallet first");
939
1316
  }
940
- const provider = new ethers2.BrowserProvider(window.ethereum);
1317
+ const provider = new ethers2.BrowserProvider(ethereum);
941
1318
  const signer = await provider.getSigner();
1319
+ const currentAddress = await signer.getAddress();
1320
+ if (expectedAddress && currentAddress.toLowerCase() !== expectedAddress.toLowerCase()) {
1321
+ throw new Error(
1322
+ `Wallet account mismatch: the current wallet account is ${currentAddress.slice(0, 8)}...\uFF0CBut the desired account is ${expectedAddress.slice(0, 8)}.... Please switch to the correct account in your wallet.`
1323
+ );
1324
+ }
942
1325
  const wallet = {
943
- address: await signer.getAddress(),
1326
+ address: currentAddress,
944
1327
  signTypedData: async (domain, types, message2) => {
945
1328
  return await signer.signTypedData(domain, types, message2);
946
1329
  },
@@ -951,7 +1334,7 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, ad
951
1334
  },
952
1335
  // Switch to a different chain
953
1336
  switchChain: async (chainId) => {
954
- await window.ethereum.request({
1337
+ await ethereum.request({
955
1338
  method: "wallet_switchEthereumChain",
956
1339
  params: [{ chainId }]
957
1340
  });
@@ -963,7 +1346,7 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, ad
963
1346
  // Will use backend's network configuration
964
1347
  }, requestInit);
965
1348
  } else {
966
- throw new Error(`\u4E0D\u652F\u6301\u7684\u7F51\u7EDC\u7C7B\u578B: ${networkType}`);
1349
+ throw new Error(`Unsupported network types: ${networkType}`);
967
1350
  }
968
1351
  return response;
969
1352
  }
@@ -1006,6 +1389,21 @@ function getNetworkDisplayName(network) {
1006
1389
  }
1007
1390
 
1008
1391
  // src/utils/payment-error-handler.ts
1392
+ var IGNORED_402_ERRORS = [
1393
+ "X-PAYMENT header is required",
1394
+ "missing X-PAYMENT header",
1395
+ "payment_required"
1396
+ ];
1397
+ var PAYMENT_ERROR_MESSAGES = {
1398
+ "insufficient_funds": "Insufficient balance to complete this payment",
1399
+ "invalid_signature": "Invalid payment signature",
1400
+ "expired": "Payment authorization has expired",
1401
+ "already_used": "This payment has already been used",
1402
+ "network_mismatch": "Payment network does not match",
1403
+ "invalid_payment": "Invalid payment data",
1404
+ "verification_failed": "Payment verification failed",
1405
+ "invalid_exact_svm_payload_transaction_simulation_failed": "Transaction simulation failed due to insufficient balance. Please check your wallet balance carefully and ensure you have enough funds to cover the payment and transaction fees."
1406
+ };
1009
1407
  function parsePaymentError(error) {
1010
1408
  if (!error) {
1011
1409
  return {
@@ -1209,13 +1607,18 @@ var WalletStore = class {
1209
1607
  });
1210
1608
  }
1211
1609
  // Connect wallet
1212
- async connect(type) {
1610
+ // @param forceSelect - 强制弹出钱包选择界面,用于切换账户
1611
+ async connect(type, forceSelect = false) {
1213
1612
  if (this.state.address && this.state.networkType && this.state.networkType !== type) {
1214
1613
  saveWalletAddress(this.state.networkType, this.state.address);
1215
1614
  }
1216
1615
  this.setState({ isConnecting: true, error: null });
1217
1616
  try {
1218
- const walletAddress = await connectWallet(type);
1617
+ const walletAddress = await connectWallet(type, forceSelect);
1618
+ const wallets = getWalletsForNetwork(type);
1619
+ if (wallets.length > 0) {
1620
+ setCurrentConnectedWallet(wallets[0]);
1621
+ }
1219
1622
  this.setState({
1220
1623
  address: walletAddress,
1221
1624
  networkType: type,
@@ -1229,6 +1632,30 @@ var WalletStore = class {
1229
1632
  throw err;
1230
1633
  }
1231
1634
  }
1635
+ // Connect to a specific wallet (from wallet discovery)
1636
+ async connectWithWallet(wallet) {
1637
+ if (this.state.address && this.state.networkType && this.state.networkType !== wallet.networkType) {
1638
+ saveWalletAddress(this.state.networkType, this.state.address);
1639
+ }
1640
+ this.setState({ isConnecting: true, error: null });
1641
+ try {
1642
+ const walletAddress = await connectToWallet(wallet);
1643
+ clearWalletDisconnection(wallet.networkType);
1644
+ saveConnectedNetworkType(wallet.networkType);
1645
+ saveWalletAddress(wallet.networkType, walletAddress);
1646
+ this.setState({
1647
+ address: walletAddress,
1648
+ networkType: wallet.networkType,
1649
+ isConnecting: false
1650
+ });
1651
+ } catch (err) {
1652
+ this.setState({
1653
+ error: err.message || "Failed to connect wallet",
1654
+ isConnecting: false
1655
+ });
1656
+ throw err;
1657
+ }
1658
+ }
1232
1659
  // Switch network (use cached wallet if available)
1233
1660
  async switchNetwork(type) {
1234
1661
  if (this.state.address && this.state.networkType) {
@@ -1260,9 +1687,15 @@ var WalletStore = class {
1260
1687
  }
1261
1688
  }
1262
1689
  // Disconnect wallet
1263
- disconnect() {
1690
+ async disconnect() {
1264
1691
  const currentNetwork = this.state.networkType;
1692
+ clearConnectedWallet(currentNetwork || void 0);
1265
1693
  if (currentNetwork) {
1694
+ try {
1695
+ await disconnectWallet(currentNetwork);
1696
+ } catch (err) {
1697
+ console.warn("Failed to disconnect wallet provider:", err);
1698
+ }
1266
1699
  this.handleDisconnect(currentNetwork);
1267
1700
  } else {
1268
1701
  this.setState({
@@ -1306,7 +1739,8 @@ function useWallet() {
1306
1739
  );
1307
1740
  return {
1308
1741
  ...state,
1309
- connect: (type) => walletStore.connect(type),
1742
+ connect: (type, forceSelect) => walletStore.connect(type, forceSelect),
1743
+ connectWithWallet: (wallet) => walletStore.connectWithWallet(wallet),
1310
1744
  switchNetwork: (type) => walletStore.switchNetwork(type),
1311
1745
  ensureNetwork: (type) => walletStore.ensureNetwork(type),
1312
1746
  disconnect: () => walletStore.disconnect(),
@@ -1414,45 +1848,327 @@ function usePaymentInfo(merchantId, endpoint = PROD_BACK_URL, additionalParams)
1414
1848
  };
1415
1849
  }
1416
1850
 
1417
- // src/react/components/WalletConnect.tsx
1418
- import React, { useState as useState3 } from "react";
1851
+ // src/react/hooks/useToast.tsx
1852
+ import React2, { useCallback as useCallback2, useRef, useState as useState3 } from "react";
1419
1853
 
1420
- // src/react/styles/inline-styles.ts
1421
- var isDarkMode = () => {
1422
- if (typeof window === "undefined") return false;
1423
- return window.matchMedia?.("(prefers-color-scheme: dark)").matches ?? false;
1854
+ // src/react/components/ui/Toast.tsx
1855
+ import React, { useEffect as useEffect3 } from "react";
1856
+ import { createPortal } from "react-dom";
1857
+ var Toast = ({ message: message2, type, onClose }) => {
1858
+ useEffect3(() => {
1859
+ const timer = setTimeout(onClose, 3e3);
1860
+ return () => clearTimeout(timer);
1861
+ }, [onClose]);
1862
+ const bgColor = type === "success" ? "#22c55e" : type === "error" ? "#ef4444" : "#3b82f6";
1863
+ const icon = type === "success" ? "\u2713" : type === "error" ? "\u2717" : "\u2139";
1864
+ return createPortal(
1865
+ /* @__PURE__ */ React.createElement(
1866
+ "div",
1867
+ {
1868
+ className: "fixed top-4 right-4 z-[99999] animate-slide-in-right",
1869
+ style: {
1870
+ animation: "slideInRight 0.3s ease-out"
1871
+ }
1872
+ },
1873
+ /* @__PURE__ */ React.createElement(
1874
+ "div",
1875
+ {
1876
+ className: "flex items-center gap-3 px-4 py-3 rounded-lg shadow-lg text-white font-mono text-sm",
1877
+ style: { backgroundColor: bgColor, minWidth: "280px" }
1878
+ },
1879
+ /* @__PURE__ */ React.createElement("span", { className: "text-lg" }, icon),
1880
+ /* @__PURE__ */ React.createElement("span", { className: "flex-1" }, message2),
1881
+ /* @__PURE__ */ React.createElement(
1882
+ "button",
1883
+ {
1884
+ onClick: onClose,
1885
+ className: "text-white/80 hover:text-white transition-colors"
1886
+ },
1887
+ "\xD7"
1888
+ )
1889
+ )
1890
+ ),
1891
+ document.body
1892
+ );
1424
1893
  };
1425
- var colors = {
1426
- // Light mode
1427
- light: {
1428
- background: "#fafafa",
1429
- cardBg: "#ffffff",
1430
- text: "#0a0a0a",
1431
- textSecondary: "#737373",
1432
- primary: "#000000",
1433
- primaryHover: "#262626",
1434
- danger: "#ef4444",
1435
- dangerHover: "#dc2626",
1436
- success: "#10b981",
1437
- successHover: "#059669",
1438
- disabled: "#e5e5e5",
1439
- disabledText: "#a3a3a3",
1440
- errorBg: "#fef2f2",
1441
- errorText: "#dc2626"
1442
- },
1443
- // Dark mode
1444
- dark: {
1445
- background: "#0a0a0a",
1446
- cardBg: "#171717",
1447
- text: "#fafafa",
1448
- textSecondary: "#a3a3a3",
1449
- primary: "#ffffff",
1450
- primaryHover: "#e5e5e5",
1451
- danger: "#f87171",
1452
- dangerHover: "#ef4444",
1453
- success: "#34d399",
1454
- successHover: "#10b981",
1455
- disabled: "#262626",
1894
+
1895
+ // src/react/hooks/useToast.tsx
1896
+ var useToast = () => {
1897
+ const [toasts, setToasts] = useState3([]);
1898
+ const toastIdRef = useRef(0);
1899
+ const showToast = useCallback2((message2, type) => {
1900
+ const id = ++toastIdRef.current;
1901
+ setToasts((prev) => [...prev, { id, message: message2, type }]);
1902
+ }, []);
1903
+ const removeToast = useCallback2((id) => {
1904
+ setToasts((prev) => prev.filter((t) => t.id !== id));
1905
+ }, []);
1906
+ const ToastContainer = () => /* @__PURE__ */ React2.createElement(React2.Fragment, null, toasts.map((toast, index) => /* @__PURE__ */ React2.createElement(
1907
+ "div",
1908
+ {
1909
+ key: toast.id,
1910
+ style: { top: `${16 + index * 60}px` },
1911
+ className: "fixed right-4 z-[99999]"
1912
+ },
1913
+ React2.createElement(Toast, {
1914
+ message: toast.message,
1915
+ type: toast.type,
1916
+ onClose: () => removeToast(toast.id)
1917
+ })
1918
+ )));
1919
+ return { showToast, ToastContainer };
1920
+ };
1921
+
1922
+ // src/react/components/wallet/WalletConnect.tsx
1923
+ import React4, { useState as useState5 } from "react";
1924
+
1925
+ // src/react/components/wallet/WalletSelectModal.tsx
1926
+ import React3, { useEffect as useEffect4, useState as useState4 } from "react";
1927
+ import { createPortal as createPortal2 } from "react-dom";
1928
+ var overlayStyle = {
1929
+ position: "fixed",
1930
+ top: 0,
1931
+ left: 0,
1932
+ right: 0,
1933
+ bottom: 0,
1934
+ backgroundColor: "rgba(0, 0, 0, 0.4)",
1935
+ display: "flex",
1936
+ alignItems: "center",
1937
+ justifyContent: "center",
1938
+ zIndex: 99999
1939
+ };
1940
+ var modalStyle = {
1941
+ backgroundColor: "#ffffff",
1942
+ borderRadius: "12px",
1943
+ padding: "16px",
1944
+ maxWidth: "320px",
1945
+ width: "90%",
1946
+ maxHeight: "70vh",
1947
+ overflow: "auto",
1948
+ boxShadow: "0 10px 25px rgba(0, 0, 0, 0.15)"
1949
+ };
1950
+ var headerStyle = {
1951
+ display: "flex",
1952
+ alignItems: "center",
1953
+ justifyContent: "space-between",
1954
+ marginBottom: "12px"
1955
+ };
1956
+ var titleStyle = {
1957
+ fontSize: "15px",
1958
+ fontWeight: 600,
1959
+ color: "#1a1a1a",
1960
+ margin: 0
1961
+ };
1962
+ var closeButtonStyle = {
1963
+ background: "none",
1964
+ border: "none",
1965
+ fontSize: "20px",
1966
+ cursor: "pointer",
1967
+ color: "#666",
1968
+ padding: "2px 6px",
1969
+ lineHeight: 1,
1970
+ borderRadius: "4px"
1971
+ };
1972
+ var subtitleStyle = {
1973
+ fontSize: "12px",
1974
+ color: "#666",
1975
+ marginBottom: "12px"
1976
+ };
1977
+ var walletListStyle = {
1978
+ display: "flex",
1979
+ flexDirection: "column",
1980
+ gap: "6px"
1981
+ };
1982
+ var getWalletItemStyle = (isHovered) => ({
1983
+ display: "flex",
1984
+ alignItems: "center",
1985
+ gap: "10px",
1986
+ padding: "10px 12px",
1987
+ border: "1px solid #e5e5e5",
1988
+ borderRadius: "8px",
1989
+ cursor: "pointer",
1990
+ transition: "all 0.15s ease",
1991
+ backgroundColor: isHovered ? "#f5f5f5" : "#ffffff",
1992
+ borderColor: isHovered ? "#d0d0d0" : "#e5e5e5"
1993
+ });
1994
+ var walletIconStyle = {
1995
+ width: "32px",
1996
+ height: "32px",
1997
+ borderRadius: "8px",
1998
+ objectFit: "contain",
1999
+ backgroundColor: "#f5f5f5"
2000
+ };
2001
+ var getAvatarColor = (name) => {
2002
+ const colors2 = [
2003
+ "#6366f1",
2004
+ // indigo
2005
+ "#8b5cf6",
2006
+ // violet
2007
+ "#ec4899",
2008
+ // pink
2009
+ "#f43f5e",
2010
+ // rose
2011
+ "#f97316",
2012
+ // orange
2013
+ "#eab308",
2014
+ // yellow
2015
+ "#22c55e",
2016
+ // green
2017
+ "#14b8a6",
2018
+ // teal
2019
+ "#06b6d4",
2020
+ // cyan
2021
+ "#3b82f6"
2022
+ // blue
2023
+ ];
2024
+ const index = name.charCodeAt(0) % colors2.length;
2025
+ return colors2[index];
2026
+ };
2027
+ var getWalletIconPlaceholderStyle = (walletName) => ({
2028
+ width: "32px",
2029
+ height: "32px",
2030
+ borderRadius: "8px",
2031
+ backgroundColor: getAvatarColor(walletName),
2032
+ display: "flex",
2033
+ alignItems: "center",
2034
+ justifyContent: "center",
2035
+ fontSize: "14px",
2036
+ fontWeight: 600,
2037
+ color: "#ffffff"
2038
+ });
2039
+ var walletNameStyle = {
2040
+ fontSize: "14px",
2041
+ fontWeight: 500,
2042
+ color: "#1a1a1a"
2043
+ };
2044
+ var emptyStateStyle = {
2045
+ textAlign: "center",
2046
+ padding: "24px 12px",
2047
+ color: "#666"
2048
+ };
2049
+ var emptyTitleStyle = {
2050
+ fontSize: "14px",
2051
+ fontWeight: 500,
2052
+ marginBottom: "6px",
2053
+ color: "#1a1a1a"
2054
+ };
2055
+ var emptyDescStyle = {
2056
+ fontSize: "12px",
2057
+ color: "#888"
2058
+ };
2059
+ function WalletItem({
2060
+ wallet,
2061
+ isHovered,
2062
+ onSelect,
2063
+ onHover
2064
+ }) {
2065
+ const [iconError, setIconError] = useState4(false);
2066
+ return /* @__PURE__ */ React3.createElement(
2067
+ "div",
2068
+ {
2069
+ style: getWalletItemStyle(isHovered),
2070
+ onClick: onSelect,
2071
+ onMouseEnter: () => onHover(true),
2072
+ onMouseLeave: () => onHover(false)
2073
+ },
2074
+ wallet.icon && !iconError ? /* @__PURE__ */ React3.createElement(
2075
+ "img",
2076
+ {
2077
+ src: wallet.icon,
2078
+ alt: wallet.name,
2079
+ style: walletIconStyle,
2080
+ onError: () => setIconError(true)
2081
+ }
2082
+ ) : /* @__PURE__ */ React3.createElement("div", { style: getWalletIconPlaceholderStyle(wallet.name) }, wallet.name.charAt(0).toUpperCase()),
2083
+ /* @__PURE__ */ React3.createElement("span", { style: walletNameStyle }, wallet.name)
2084
+ );
2085
+ }
2086
+ function WalletSelectModal({
2087
+ isOpen,
2088
+ networkType,
2089
+ onSelect,
2090
+ onClose
2091
+ }) {
2092
+ const [wallets, setWallets] = useState4([]);
2093
+ const [hoveredWallet, setHoveredWallet] = useState4(null);
2094
+ const [mounted, setMounted] = useState4(false);
2095
+ useEffect4(() => {
2096
+ setMounted(true);
2097
+ return () => setMounted(false);
2098
+ }, []);
2099
+ useEffect4(() => {
2100
+ if (!isOpen) return;
2101
+ initEVMWalletDiscovery();
2102
+ const updateWallets = () => {
2103
+ setWallets(getWalletsForNetwork(networkType));
2104
+ };
2105
+ updateWallets();
2106
+ const unsubscribe = onEVMWalletsChanged(updateWallets);
2107
+ const timer = setTimeout(updateWallets, 500);
2108
+ return () => {
2109
+ unsubscribe();
2110
+ clearTimeout(timer);
2111
+ };
2112
+ }, [isOpen, networkType]);
2113
+ if (!isOpen || !mounted) return null;
2114
+ const handleOverlayClick = (e) => {
2115
+ if (e.target === e.currentTarget) {
2116
+ onClose();
2117
+ }
2118
+ };
2119
+ const networkName = getNetworkDisplayName(networkType);
2120
+ const modalContent = /* @__PURE__ */ React3.createElement("div", { style: overlayStyle, onClick: handleOverlayClick }, /* @__PURE__ */ React3.createElement("div", { style: modalStyle }, /* @__PURE__ */ React3.createElement("div", { style: headerStyle }, /* @__PURE__ */ React3.createElement("h3", { style: titleStyle }, "Select Wallet"), /* @__PURE__ */ React3.createElement("button", { style: closeButtonStyle, onClick: onClose }, "\xD7")), /* @__PURE__ */ React3.createElement("p", { style: subtitleStyle }, "Connect a ", networkName, " wallet"), wallets.length > 0 ? /* @__PURE__ */ React3.createElement("div", { style: walletListStyle }, wallets.map((wallet) => /* @__PURE__ */ React3.createElement(
2121
+ WalletItem,
2122
+ {
2123
+ key: wallet.id,
2124
+ wallet,
2125
+ isHovered: hoveredWallet === wallet.id,
2126
+ onSelect: () => onSelect(wallet),
2127
+ onHover: (hovered) => setHoveredWallet(hovered ? wallet.id : null)
2128
+ }
2129
+ ))) : /* @__PURE__ */ React3.createElement("div", { style: emptyStateStyle }, /* @__PURE__ */ React3.createElement("p", { style: emptyTitleStyle }, "No wallets found"), /* @__PURE__ */ React3.createElement("p", { style: emptyDescStyle }, "Please install a ", networkName, " wallet extension."))));
2130
+ if (typeof document !== "undefined") {
2131
+ return createPortal2(modalContent, document.body);
2132
+ }
2133
+ return modalContent;
2134
+ }
2135
+
2136
+ // src/react/styles/inline-styles.ts
2137
+ var isDarkMode = () => {
2138
+ if (typeof window === "undefined") return false;
2139
+ return window.matchMedia?.("(prefers-color-scheme: dark)").matches ?? false;
2140
+ };
2141
+ var colors = {
2142
+ // Light mode
2143
+ light: {
2144
+ background: "#fafafa",
2145
+ cardBg: "#ffffff",
2146
+ text: "#0a0a0a",
2147
+ textSecondary: "#737373",
2148
+ primary: "#000000",
2149
+ primaryHover: "#262626",
2150
+ danger: "#ef4444",
2151
+ dangerHover: "#dc2626",
2152
+ success: "#10b981",
2153
+ successHover: "#059669",
2154
+ disabled: "#e5e5e5",
2155
+ disabledText: "#a3a3a3",
2156
+ errorBg: "#fef2f2",
2157
+ errorText: "#dc2626"
2158
+ },
2159
+ // Dark mode
2160
+ dark: {
2161
+ background: "#0a0a0a",
2162
+ cardBg: "#171717",
2163
+ text: "#fafafa",
2164
+ textSecondary: "#a3a3a3",
2165
+ primary: "#ffffff",
2166
+ primaryHover: "#e5e5e5",
2167
+ danger: "#f87171",
2168
+ dangerHover: "#ef4444",
2169
+ success: "#34d399",
2170
+ successHover: "#10b981",
2171
+ disabled: "#262626",
1456
2172
  disabledText: "#525252",
1457
2173
  errorBg: "#1c1917",
1458
2174
  errorText: "#f87171"
@@ -1532,18 +2248,6 @@ var getDisconnectButtonStyle = (isHovered) => {
1532
2248
  color: "#ffffff"
1533
2249
  };
1534
2250
  };
1535
- var getInstallLinkStyle = (isHovered) => {
1536
- const c = getColors();
1537
- return {
1538
- display: "inline-block",
1539
- padding: "0.5rem",
1540
- fontSize: "0.8125rem",
1541
- color: c.textSecondary,
1542
- textDecoration: isHovered ? "underline" : "none",
1543
- textAlign: "center",
1544
- fontWeight: 500
1545
- };
1546
- };
1547
2251
  var walletAddressStyle = {
1548
2252
  display: "flex",
1549
2253
  flexDirection: "column",
@@ -1596,51 +2300,60 @@ var getErrorStyle = () => {
1596
2300
  };
1597
2301
  };
1598
2302
 
1599
- // src/react/components/WalletConnect.tsx
2303
+ // src/react/components/wallet/WalletConnect.tsx
1600
2304
  function WalletConnect({
1601
2305
  supportedNetworks = ["solana" /* SOLANA */, "evm" /* EVM */],
1602
2306
  className = "",
1603
2307
  onConnect,
1604
- onDisconnect
2308
+ onDisconnect,
2309
+ showSwitchWallet = true
1605
2310
  }) {
1606
- const { address, networkType, isConnecting, error, connect, disconnect } = useWallet();
1607
- const [hoveredButton, setHoveredButton] = useState3(null);
1608
- const [hoveredLink, setHoveredLink] = useState3(null);
1609
- const handleConnect = async (network) => {
2311
+ const { address, networkType, isConnecting, error, connectWithWallet, disconnect } = useWallet();
2312
+ const [hoveredButton, setHoveredButton] = useState5(null);
2313
+ const [walletSelectOpen, setWalletSelectOpen] = useState5(false);
2314
+ const [selectedNetworkType, setSelectedNetworkType] = useState5(null);
2315
+ const handleOpenWalletSelect = (network) => {
2316
+ setSelectedNetworkType(network);
2317
+ setWalletSelectOpen(true);
2318
+ };
2319
+ const handleWalletSelect = async (wallet) => {
2320
+ setWalletSelectOpen(false);
1610
2321
  try {
1611
- await connect(network);
2322
+ await connectWithWallet(wallet);
1612
2323
  } catch (err) {
1613
2324
  }
1614
2325
  };
1615
- const handleDisconnect = () => {
1616
- disconnect();
2326
+ const handleDisconnect = async () => {
2327
+ await disconnect();
1617
2328
  onDisconnect?.();
1618
2329
  };
1619
- return /* @__PURE__ */ React.createElement("div", { style: { ...containerStyle, ...className ? {} : {} }, className }, !address ? /* @__PURE__ */ React.createElement("div", { style: getSectionStyle() }, /* @__PURE__ */ React.createElement("h3", { style: getTitleStyle() }, "Connect Wallet"), supportedNetworks.length === 0 ? /* @__PURE__ */ React.createElement("p", { style: getHintStyle() }, "Please install a supported wallet extension") : /* @__PURE__ */ React.createElement("div", { style: buttonsContainerStyle }, supportedNetworks.map((network) => {
1620
- const installed = isWalletInstalled(network);
1621
- return /* @__PURE__ */ React.createElement("div", { key: network, style: walletOptionStyle }, /* @__PURE__ */ React.createElement(
1622
- "button",
1623
- {
1624
- style: getConnectButtonStyle(isConnecting || !installed, hoveredButton === network),
1625
- onClick: () => handleConnect(network),
1626
- disabled: isConnecting || !installed,
1627
- onMouseEnter: () => setHoveredButton(network),
1628
- onMouseLeave: () => setHoveredButton(null)
1629
- },
1630
- isConnecting ? "Connecting..." : getNetworkDisplayName(network)
1631
- ), !installed && /* @__PURE__ */ React.createElement(
1632
- "a",
1633
- {
1634
- href: getWalletInstallUrl(network),
1635
- target: "_blank",
1636
- rel: "noopener noreferrer",
1637
- style: getInstallLinkStyle(hoveredLink === network),
1638
- onMouseEnter: () => setHoveredLink(network),
1639
- onMouseLeave: () => setHoveredLink(null)
1640
- },
1641
- "Install Wallet"
1642
- ));
1643
- })), error && /* @__PURE__ */ React.createElement("p", { style: getErrorStyle() }, error), /* @__PURE__ */ React.createElement("p", { style: getHintStyle() }, "To switch accounts, please change it in your wallet extension")) : /* @__PURE__ */ React.createElement("div", { style: getSectionStyle() }, /* @__PURE__ */ React.createElement("div", { style: walletAddressStyle }, /* @__PURE__ */ React.createElement("span", { style: getLabelStyle() }, "Connected ", networkType && `(${getNetworkDisplayName(networkType)})`), /* @__PURE__ */ React.createElement("span", { style: getAddressStyle() }, formatAddress(address))), /* @__PURE__ */ React.createElement("div", { style: walletActionsStyle }, /* @__PURE__ */ React.createElement(
2330
+ const handleSwitchWallet = () => {
2331
+ if (networkType) {
2332
+ setSelectedNetworkType(networkType);
2333
+ setWalletSelectOpen(true);
2334
+ }
2335
+ };
2336
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement("div", { style: { ...containerStyle, ...className ? {} : {} }, className }, !address ? /* @__PURE__ */ React4.createElement("div", { style: getSectionStyle() }, /* @__PURE__ */ React4.createElement("h3", { style: getTitleStyle() }, "Connect Wallet"), supportedNetworks.length === 0 ? /* @__PURE__ */ React4.createElement("p", { style: getHintStyle() }, "Please install a supported wallet extension") : /* @__PURE__ */ React4.createElement("div", { style: buttonsContainerStyle }, supportedNetworks.map((network) => /* @__PURE__ */ React4.createElement("div", { key: network, style: walletOptionStyle }, /* @__PURE__ */ React4.createElement(
2337
+ "button",
2338
+ {
2339
+ style: getConnectButtonStyle(isConnecting, hoveredButton === network),
2340
+ onClick: () => handleOpenWalletSelect(network),
2341
+ disabled: isConnecting,
2342
+ onMouseEnter: () => setHoveredButton(network),
2343
+ onMouseLeave: () => setHoveredButton(null)
2344
+ },
2345
+ isConnecting ? "Connecting..." : getNetworkDisplayName(network)
2346
+ )))), error && /* @__PURE__ */ React4.createElement("p", { style: getErrorStyle() }, error), /* @__PURE__ */ React4.createElement("p", { style: getHintStyle() }, "Select a network to see available wallets")) : /* @__PURE__ */ React4.createElement("div", { style: getSectionStyle() }, /* @__PURE__ */ React4.createElement("div", { style: walletAddressStyle }, /* @__PURE__ */ React4.createElement("span", { style: getLabelStyle() }, "Connected ", networkType && `(${getNetworkDisplayName(networkType)})`), /* @__PURE__ */ React4.createElement("span", { style: getAddressStyle() }, formatAddress(address))), /* @__PURE__ */ React4.createElement("div", { style: walletActionsStyle }, showSwitchWallet && /* @__PURE__ */ React4.createElement(
2347
+ "button",
2348
+ {
2349
+ style: getConnectButtonStyle(isConnecting, hoveredButton === "switch"),
2350
+ onClick: handleSwitchWallet,
2351
+ disabled: isConnecting,
2352
+ onMouseEnter: () => setHoveredButton("switch"),
2353
+ onMouseLeave: () => setHoveredButton(null)
2354
+ },
2355
+ isConnecting ? "Switching..." : "Switch Wallet"
2356
+ ), /* @__PURE__ */ React4.createElement(
1644
2357
  "button",
1645
2358
  {
1646
2359
  style: getDisconnectButtonStyle(hoveredButton === "disconnect"),
@@ -1649,11 +2362,19 @@ function WalletConnect({
1649
2362
  onMouseLeave: () => setHoveredButton(null)
1650
2363
  },
1651
2364
  "Disconnect"
1652
- )), /* @__PURE__ */ React.createElement("p", { style: getHintStyle() }, "Switch account in your wallet to change address")));
2365
+ )), /* @__PURE__ */ React4.createElement("p", { style: getHintStyle() }, 'Click "Switch Wallet" to change wallet or account'))), selectedNetworkType && /* @__PURE__ */ React4.createElement(
2366
+ WalletSelectModal,
2367
+ {
2368
+ isOpen: walletSelectOpen,
2369
+ networkType: selectedNetworkType,
2370
+ onSelect: handleWalletSelect,
2371
+ onClose: () => setWalletSelectOpen(false)
2372
+ }
2373
+ ));
1653
2374
  }
1654
2375
 
1655
- // src/react/components/V402Checkout.tsx
1656
- import React3, { useEffect as useEffect3, useState as useState4 } from "react";
2376
+ // src/react/components/checkout/V402Checkout.tsx
2377
+ import React6, { useEffect as useEffect5, useState as useState6 } from "react";
1657
2378
  import { Button, Card, Divider, message, Spin, Tooltip, Typography } from "antd";
1658
2379
  import {
1659
2380
  DisconnectOutlined,
@@ -1666,9 +2387,9 @@ import {
1666
2387
  init_common();
1667
2388
 
1668
2389
  // src/react/utils/CryptoIcons.tsx
1669
- import React2 from "react";
2390
+ import React5 from "react";
1670
2391
  var SolanaIcon = ({ width = 16, height = 16, className, style }) => {
1671
- return /* @__PURE__ */ React2.createElement(
2392
+ return /* @__PURE__ */ React5.createElement(
1672
2393
  "svg",
1673
2394
  {
1674
2395
  xmlns: "http://www.w3.org/2000/svg",
@@ -1678,14 +2399,14 @@ var SolanaIcon = ({ width = 16, height = 16, className, style }) => {
1678
2399
  className,
1679
2400
  style
1680
2401
  },
1681
- /* @__PURE__ */ React2.createElement("desc", null, "Solana SOL Fill Streamline Icon: https://streamlinehq.com"),
1682
- /* @__PURE__ */ React2.createElement("g", { fill: "none", fillRule: "evenodd" }, /* @__PURE__ */ React2.createElement(
2402
+ /* @__PURE__ */ React5.createElement("desc", null, "Solana SOL Fill Streamline Icon: https://streamlinehq.com"),
2403
+ /* @__PURE__ */ React5.createElement("g", { fill: "none", fillRule: "evenodd" }, /* @__PURE__ */ React5.createElement(
1683
2404
  "path",
1684
2405
  {
1685
2406
  d: "M16 0v16H0V0h16ZM8.395333333333333 15.505333333333333l-0.007333333333333332 0.0013333333333333333 -0.047333333333333324 0.023333333333333334 -0.013333333333333332 0.0026666666666666666 -0.009333333333333332 -0.0026666666666666666 -0.047333333333333324 -0.023333333333333334c-0.006666666666666666 -0.0026666666666666666 -0.012666666666666666 -0.0006666666666666666 -0.016 0.003333333333333333l-0.0026666666666666666 0.006666666666666666 -0.011333333333333334 0.2853333333333333 0.003333333333333333 0.013333333333333332 0.006666666666666666 0.008666666666666666 0.06933333333333333 0.049333333333333326 0.009999999999999998 0.0026666666666666666 0.008 -0.0026666666666666666 0.06933333333333333 -0.049333333333333326 0.008 -0.010666666666666666 0.0026666666666666666 -0.011333333333333334 -0.011333333333333334 -0.2846666666666666c-0.0013333333333333333 -0.006666666666666666 -0.005999999999999999 -0.011333333333333334 -0.011333333333333334 -0.011999999999999999Zm0.17666666666666667 -0.07533333333333334 -0.008666666666666666 0.0013333333333333333 -0.12333333333333332 0.062 -0.006666666666666666 0.006666666666666666 -0.002 0.007333333333333332 0.011999999999999999 0.2866666666666666 0.003333333333333333 0.008 0.005333333333333333 0.004666666666666666 0.134 0.062c0.008 0.0026666666666666666 0.015333333333333332 0 0.019333333333333334 -0.005333333333333333l0.0026666666666666666 -0.009333333333333332 -0.02266666666666667 -0.4093333333333333c-0.002 -0.008 -0.006666666666666666 -0.013333333333333332 -0.013333333333333332 -0.014666666666666665Zm-0.4766666666666666 0.0013333333333333333a0.015333333333333332 0.015333333333333332 0 0 0 -0.018 0.004l-0.004 0.009333333333333332 -0.02266666666666667 0.4093333333333333c0 0.008 0.004666666666666666 0.013333333333333332 0.011333333333333334 0.016l0.009999999999999998 -0.0013333333333333333 0.134 -0.062 0.006666666666666666 -0.005333333333333333 0.0026666666666666666 -0.007333333333333332 0.011333333333333334 -0.2866666666666666 -0.002 -0.008 -0.006666666666666666 -0.006666666666666666 -0.12266666666666666 -0.06133333333333333Z",
1686
2407
  strokeWidth: "0.6667"
1687
2408
  }
1688
- ), /* @__PURE__ */ React2.createElement(
2409
+ ), /* @__PURE__ */ React5.createElement(
1689
2410
  "path",
1690
2411
  {
1691
2412
  fill: "#000000",
@@ -1696,7 +2417,7 @@ var SolanaIcon = ({ width = 16, height = 16, className, style }) => {
1696
2417
  );
1697
2418
  };
1698
2419
  var BaseIcon = ({ width = 24, height = 24, className, style }) => {
1699
- return /* @__PURE__ */ React2.createElement(
2420
+ return /* @__PURE__ */ React5.createElement(
1700
2421
  "svg",
1701
2422
  {
1702
2423
  xmlns: "http://www.w3.org/2000/svg",
@@ -1710,8 +2431,8 @@ var BaseIcon = ({ width = 24, height = 24, className, style }) => {
1710
2431
  className,
1711
2432
  style
1712
2433
  },
1713
- /* @__PURE__ */ React2.createElement("desc", null, "Brand Coinbase Streamline Icon: https://streamlinehq.com"),
1714
- /* @__PURE__ */ React2.createElement(
2434
+ /* @__PURE__ */ React5.createElement("desc", null, "Brand Coinbase Streamline Icon: https://streamlinehq.com"),
2435
+ /* @__PURE__ */ React5.createElement(
1715
2436
  "path",
1716
2437
  {
1717
2438
  d: "M12.95 22c-4.503 0 -8.445 -3.04 -9.61 -7.413 -1.165 -4.373 0.737 -8.988 4.638 -11.25a9.906 9.906 0 0 1 12.008 1.598l-3.335 3.367a5.185 5.185 0 0 0 -7.354 0.013 5.252 5.252 0 0 0 0 7.393 5.185 5.185 0 0 0 7.354 0.013L20 19.088A9.887 9.887 0 0 1 12.95 22z",
@@ -1731,7 +2452,7 @@ var getNetworkIcon = (network) => {
1731
2452
  return BaseIcon;
1732
2453
  };
1733
2454
 
1734
- // src/react/components/V402Checkout.tsx
2455
+ // src/react/components/checkout/V402Checkout.tsx
1735
2456
  var { Title, Text } = Typography;
1736
2457
  var notify = {
1737
2458
  success: (title, msg) => {
@@ -1769,14 +2490,14 @@ function V402Checkout({
1769
2490
  { autoSwitch: !!targetNetwork, switchOnMount: true }
1770
2491
  );
1771
2492
  const { isProcessing, setIsProcessing, result, setResult, error, setError } = usePayment();
1772
- const [paymentDetails, setPaymentDetails] = useState4(null);
2493
+ const [paymentDetails, setPaymentDetails] = useState6(null);
1773
2494
  const handleDisconnect = () => {
1774
2495
  disconnect();
1775
2496
  setResult(null);
1776
2497
  setError(null);
1777
2498
  notify.info("Wallet Disconnected", "Your wallet has been disconnected successfully.");
1778
2499
  };
1779
- useEffect3(() => {
2500
+ useEffect5(() => {
1780
2501
  if (paymentInfo && paymentInfo.length > 0) {
1781
2502
  const firstPayment = paymentInfo[0];
1782
2503
  const rawAmount = firstPayment.maxAmountRequired?.toString() || "0";
@@ -1791,7 +2512,7 @@ function V402Checkout({
1791
2512
  });
1792
2513
  }
1793
2514
  }, [paymentInfo]);
1794
- useEffect3(() => {
2515
+ useEffect5(() => {
1795
2516
  if (targetNetwork && !fetchingPaymentInfo && ensureNetwork) {
1796
2517
  ensureNetwork(targetNetwork).catch((err) => {
1797
2518
  console.error("Failed to ensure network:", err);
@@ -1807,7 +2528,7 @@ function V402Checkout({
1807
2528
  setError(null);
1808
2529
  setIsProcessing(true);
1809
2530
  try {
1810
- const response = await makePayment(networkType, checkoutId, endpoint, additionalParams);
2531
+ const response = await makePayment(networkType, checkoutId, endpoint, additionalParams, address || void 0);
1811
2532
  const data = await response.json();
1812
2533
  setResult(data);
1813
2534
  notify.success("Payment Successful!", "Your payment has been processed successfully.");
@@ -1831,12 +2552,12 @@ function V402Checkout({
1831
2552
  const networkColor = paymentDetails ? getNetworkColor(paymentDetails.network) : "#8c8c8c";
1832
2553
  const loadingColor = "#8c8c8c";
1833
2554
  const hasInvalidCheckoutId = !fetchingPaymentInfo && (!paymentInfo || paymentInfo.length === 0);
1834
- return /* @__PURE__ */ React3.createElement(
2555
+ return /* @__PURE__ */ React6.createElement(
1835
2556
  "div",
1836
2557
  {
1837
2558
  className: isModal ? "bg-white" : "h-screen bg-white flex items-center justify-center p-4 overflow-hidden"
1838
2559
  },
1839
- /* @__PURE__ */ React3.createElement(
2560
+ /* @__PURE__ */ React6.createElement(
1840
2561
  "div",
1841
2562
  {
1842
2563
  className: "flex gap-4 items-center justify-center",
@@ -1846,7 +2567,7 @@ function V402Checkout({
1846
2567
  width: "100%"
1847
2568
  }
1848
2569
  },
1849
- /* @__PURE__ */ React3.createElement(
2570
+ /* @__PURE__ */ React6.createElement(
1850
2571
  Card,
1851
2572
  {
1852
2573
  className: "flex-shrink-0",
@@ -1862,7 +2583,7 @@ function V402Checkout({
1862
2583
  },
1863
2584
  styles: { body: { padding: isModal ? "0px" : "32px 24px" } }
1864
2585
  },
1865
- /* @__PURE__ */ React3.createElement("div", { className: "flex items-center gap-3 mb-4" }, /* @__PURE__ */ React3.createElement(
2586
+ /* @__PURE__ */ React6.createElement("div", { className: "flex items-center gap-3 mb-4" }, /* @__PURE__ */ React6.createElement(
1866
2587
  "div",
1867
2588
  {
1868
2589
  className: "w-12 h-12 rounded-xl flex items-center justify-center",
@@ -1871,22 +2592,22 @@ function V402Checkout({
1871
2592
  transition: "background 0.3s ease"
1872
2593
  }
1873
2594
  },
1874
- hasInvalidCheckoutId ? /* @__PURE__ */ React3.createElement("span", { style: { fontSize: "20px", color: "white", fontWeight: "bold" } }, "\u2717") : paymentDetails && NetworkIcon ? /* @__PURE__ */ React3.createElement(NetworkIcon, { width: 24, height: 24 }) : /* @__PURE__ */ React3.createElement(LoadingOutlined, { style: { fontSize: "20px", color: "white" }, spin: true })
1875
- ), /* @__PURE__ */ React3.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React3.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React3.createElement(Title, { level: 4, style: { margin: 0, fontSize: "18px", fontWeight: 600 } }, title || "Echo Payment OnVoyage"), !hasInvalidCheckoutId && /* @__PURE__ */ React3.createElement(
2595
+ hasInvalidCheckoutId ? /* @__PURE__ */ React6.createElement("span", { style: { fontSize: "20px", color: "white", fontWeight: "bold" } }, "\u2717") : paymentDetails && NetworkIcon ? /* @__PURE__ */ React6.createElement(NetworkIcon, { width: 24, height: 24 }) : /* @__PURE__ */ React6.createElement(LoadingOutlined, { style: { fontSize: "20px", color: "white" }, spin: true })
2596
+ ), /* @__PURE__ */ React6.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React6.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React6.createElement(Title, { level: 4, style: { margin: 0, fontSize: "18px", fontWeight: 600 } }, title || "Echo Payment OnVoyage"), !hasInvalidCheckoutId && /* @__PURE__ */ React6.createElement(
1876
2597
  Tooltip,
1877
2598
  {
1878
2599
  title: tooltipText,
1879
2600
  placement: "top"
1880
2601
  },
1881
- /* @__PURE__ */ React3.createElement(
2602
+ /* @__PURE__ */ React6.createElement(
1882
2603
  InfoCircleOutlined,
1883
2604
  {
1884
2605
  style: { fontSize: "14px", color: "#8c8c8c", cursor: "help" }
1885
2606
  }
1886
2607
  )
1887
- )), /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, subtitle))),
1888
- /* @__PURE__ */ React3.createElement("div", { className: "text-center mb-5" }, /* @__PURE__ */ React3.createElement("div", { className: "inline-flex items-center justify-center w-12 h-12 rounded-full bg-gray-50 mb-3" }, /* @__PURE__ */ React3.createElement(LockOutlined, { style: { fontSize: "20px", color: "#595959" } })), /* @__PURE__ */ React3.createElement(Title, { level: 3, style: { margin: "0 0 6px 0", fontSize: "20px", fontWeight: 600 } }, "Payment Required"), /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Pay ", paymentDetails ? `$${paymentDetails.amount} ${paymentDetails.currency}` : "the required amount", " to access")),
1889
- hasInvalidCheckoutId && /* @__PURE__ */ React3.createElement("div", { className: "text-center py-6" }, /* @__PURE__ */ React3.createElement(
2608
+ )), /* @__PURE__ */ React6.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, subtitle))),
2609
+ /* @__PURE__ */ React6.createElement("div", { className: "text-center mb-5" }, /* @__PURE__ */ React6.createElement("div", { className: "inline-flex items-center justify-center w-12 h-12 rounded-full bg-gray-50 mb-3" }, /* @__PURE__ */ React6.createElement(LockOutlined, { style: { fontSize: "20px", color: "#595959" } })), /* @__PURE__ */ React6.createElement(Title, { level: 3, style: { margin: "0 0 6px 0", fontSize: "20px", fontWeight: 600 } }, "Payment Required"), /* @__PURE__ */ React6.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Pay ", paymentDetails ? `$${paymentDetails.amount} ${paymentDetails.currency}` : "the required amount", " to access")),
2610
+ hasInvalidCheckoutId && /* @__PURE__ */ React6.createElement("div", { className: "text-center py-6" }, /* @__PURE__ */ React6.createElement(
1890
2611
  "div",
1891
2612
  {
1892
2613
  className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
@@ -1895,15 +2616,15 @@ function V402Checkout({
1895
2616
  boxShadow: "0 4px 20px rgba(239, 68, 68, 0.3)"
1896
2617
  }
1897
2618
  },
1898
- /* @__PURE__ */ React3.createElement("span", { style: { fontSize: "32px", color: "white" } }, "!")
1899
- ), /* @__PURE__ */ React3.createElement(
2619
+ /* @__PURE__ */ React6.createElement("span", { style: { fontSize: "32px", color: "white" } }, "!")
2620
+ ), /* @__PURE__ */ React6.createElement(
1900
2621
  Title,
1901
2622
  {
1902
2623
  level: 4,
1903
2624
  style: { margin: "0 0 12px 0", fontSize: "18px", fontWeight: 600, color: "#262626" }
1904
2625
  },
1905
2626
  "Invalid Checkout ID"
1906
- ), /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c", display: "block", marginBottom: "16px" } }, "The checkout ID you provided is invalid or has expired."), /* @__PURE__ */ React3.createElement(
2627
+ ), /* @__PURE__ */ React6.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c", display: "block", marginBottom: "16px" } }, "The checkout ID you provided is invalid or has expired."), /* @__PURE__ */ React6.createElement(
1907
2628
  "div",
1908
2629
  {
1909
2630
  style: {
@@ -1914,33 +2635,33 @@ function V402Checkout({
1914
2635
  marginTop: "16px"
1915
2636
  }
1916
2637
  },
1917
- /* @__PURE__ */ React3.createElement(Text, { style: {
2638
+ /* @__PURE__ */ React6.createElement(Text, { style: {
1918
2639
  fontSize: "13px",
1919
2640
  color: "#dc2626",
1920
2641
  lineHeight: "1.6",
1921
2642
  fontWeight: 500
1922
2643
  } }, "Failed to load payment information. Please check your checkout ID.")
1923
2644
  )),
1924
- !hasInvalidCheckoutId && fetchingPaymentInfo && /* @__PURE__ */ React3.createElement("div", { className: "text-center py-6" }, /* @__PURE__ */ React3.createElement(Text, { style: { color: "#8c8c8c" } }, "Loading payment information...")),
1925
- !hasInvalidCheckoutId && !fetchingPaymentInfo && !address && /* @__PURE__ */ React3.createElement("div", null, /* @__PURE__ */ React3.createElement(WalletConnect, { supportedNetworks })),
1926
- !hasInvalidCheckoutId && address && /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(
2645
+ !hasInvalidCheckoutId && fetchingPaymentInfo && /* @__PURE__ */ React6.createElement("div", { className: "text-center py-6" }, /* @__PURE__ */ React6.createElement(Text, { style: { color: "#8c8c8c" } }, "Loading payment information...")),
2646
+ !hasInvalidCheckoutId && !fetchingPaymentInfo && !address && /* @__PURE__ */ React6.createElement("div", null, /* @__PURE__ */ React6.createElement(WalletConnect, { supportedNetworks })),
2647
+ !hasInvalidCheckoutId && address && /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(
1927
2648
  "div",
1928
2649
  {
1929
2650
  className: "bg-gray-50 rounded-lg p-3 mb-4",
1930
2651
  style: { border: "1px solid #f0f0f0" }
1931
2652
  },
1932
- /* @__PURE__ */ React3.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React3.createElement("div", { className: "flex items-center gap-3 flex-1" }, /* @__PURE__ */ React3.createElement(
2653
+ /* @__PURE__ */ React6.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React6.createElement("div", { className: "flex items-center gap-3 flex-1" }, /* @__PURE__ */ React6.createElement(
1933
2654
  "div",
1934
2655
  {
1935
2656
  className: "w-10 h-10 rounded-full bg-black flex items-center justify-center text-white text-sm font-semibold"
1936
2657
  },
1937
2658
  address.slice(0, 2).toUpperCase()
1938
- ), /* @__PURE__ */ React3.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ React3.createElement(Text, { style: {
2659
+ ), /* @__PURE__ */ React6.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ React6.createElement(Text, { style: {
1939
2660
  display: "block",
1940
2661
  fontSize: "12px",
1941
2662
  color: "#8c8c8c",
1942
2663
  marginBottom: "2px"
1943
- } }, "Connected Wallet"), /* @__PURE__ */ React3.createElement(
2664
+ } }, "Connected Wallet"), /* @__PURE__ */ React6.createElement(
1944
2665
  Text,
1945
2666
  {
1946
2667
  style: {
@@ -1950,17 +2671,17 @@ function V402Checkout({
1950
2671
  }
1951
2672
  },
1952
2673
  formatAddress(address)
1953
- ))), /* @__PURE__ */ React3.createElement(
2674
+ ))), /* @__PURE__ */ React6.createElement(
1954
2675
  Button,
1955
2676
  {
1956
2677
  type: "text",
1957
2678
  size: "small",
1958
- icon: /* @__PURE__ */ React3.createElement(DisconnectOutlined, null),
2679
+ icon: /* @__PURE__ */ React6.createElement(DisconnectOutlined, null),
1959
2680
  onClick: handleDisconnect,
1960
2681
  style: { color: "#ff4d4f" }
1961
2682
  }
1962
2683
  ))
1963
- ), paymentDetails && /* @__PURE__ */ React3.createElement("div", { className: "bg-gray-50 rounded-lg p-3 mb-4", style: { border: "1px solid #f0f0f0" } }, /* @__PURE__ */ React3.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Payment Amount"), /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "18px", fontWeight: 600 } }, "$", paymentDetails.amount)), /* @__PURE__ */ React3.createElement(Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ React3.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Currency"), /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "14px", fontWeight: 500 } }, paymentDetails.currency)), /* @__PURE__ */ React3.createElement(Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ React3.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Network"), /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "14px", fontWeight: 500 } }, paymentDetails.network)), /* @__PURE__ */ React3.createElement(Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ React3.createElement("div", { className: "flex justify-between items-start" }, /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Wallet Address"), /* @__PURE__ */ React3.createElement(Text, { style: {
2684
+ ), paymentDetails && /* @__PURE__ */ React6.createElement("div", { className: "bg-gray-50 rounded-lg p-3 mb-4", style: { border: "1px solid #f0f0f0" } }, /* @__PURE__ */ React6.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ React6.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Payment Amount"), /* @__PURE__ */ React6.createElement(Text, { style: { fontSize: "18px", fontWeight: 600 } }, "$", paymentDetails.amount)), /* @__PURE__ */ React6.createElement(Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ React6.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ React6.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Currency"), /* @__PURE__ */ React6.createElement(Text, { style: { fontSize: "14px", fontWeight: 500 } }, paymentDetails.currency)), /* @__PURE__ */ React6.createElement(Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ React6.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ React6.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Network"), /* @__PURE__ */ React6.createElement(Text, { style: { fontSize: "14px", fontWeight: 500 } }, paymentDetails.network)), /* @__PURE__ */ React6.createElement(Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ React6.createElement("div", { className: "flex justify-between items-start" }, /* @__PURE__ */ React6.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Wallet Address"), /* @__PURE__ */ React6.createElement(Text, { style: {
1964
2685
  fontSize: "11px",
1965
2686
  fontWeight: 500,
1966
2687
  fontFamily: "Monaco, monospace",
@@ -1968,15 +2689,15 @@ function V402Checkout({
1968
2689
  textAlign: "right",
1969
2690
  maxWidth: "60%",
1970
2691
  lineHeight: 1.4
1971
- } }, address))), /* @__PURE__ */ React3.createElement(
2692
+ } }, address))), /* @__PURE__ */ React6.createElement(
1972
2693
  "div",
1973
2694
  {
1974
2695
  className: "flex items-center justify-center gap-2 mb-3 p-2 rounded-lg",
1975
2696
  style: { background: "#f6ffed", border: "1px solid #d9f7be" }
1976
2697
  },
1977
- /* @__PURE__ */ React3.createElement(SafetyOutlined, { style: { color: "#52c41a", fontSize: "13px" } }),
1978
- /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "12px", color: "#52c41a", fontWeight: 500 } }, "Secure payment powered by v402pay")
1979
- ), /* @__PURE__ */ React3.createElement(
2698
+ /* @__PURE__ */ React6.createElement(SafetyOutlined, { style: { color: "#52c41a", fontSize: "13px" } }),
2699
+ /* @__PURE__ */ React6.createElement(Text, { style: { fontSize: "12px", color: "#52c41a", fontWeight: 500 } }, "Secure payment powered by v402pay")
2700
+ ), /* @__PURE__ */ React6.createElement(
1980
2701
  Button,
1981
2702
  {
1982
2703
  type: "primary",
@@ -1998,7 +2719,7 @@ function V402Checkout({
1998
2719
  }
1999
2720
  },
2000
2721
  isProcessing ? "Processing..." : !paymentDetails ? "Loading..." : `Pay $${paymentDetails.amount} ${paymentDetails.currency}`
2001
- ), /* @__PURE__ */ React3.createElement("div", { className: "text-center" }, /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Don't have USDC?", " "), /* @__PURE__ */ React3.createElement(
2722
+ ), /* @__PURE__ */ React6.createElement("div", { className: "text-center" }, /* @__PURE__ */ React6.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Don't have USDC?", " "), /* @__PURE__ */ React6.createElement(
2002
2723
  "a",
2003
2724
  {
2004
2725
  href: "https://faucet.circle.com/",
@@ -2007,26 +2728,26 @@ function V402Checkout({
2007
2728
  className: "text-blue-600 hover:text-blue-700 text-sm font-medium inline-flex items-center gap-1"
2008
2729
  },
2009
2730
  "Get it here ",
2010
- /* @__PURE__ */ React3.createElement(LinkOutlined, { style: { fontSize: "12px" } })
2011
- )), isModal && result && /* @__PURE__ */ React3.createElement(
2731
+ /* @__PURE__ */ React6.createElement(LinkOutlined, { style: { fontSize: "12px" } })
2732
+ )), isModal && result && /* @__PURE__ */ React6.createElement(
2012
2733
  "div",
2013
2734
  {
2014
2735
  className: "mt-4 p-4 rounded-lg",
2015
2736
  style: { background: "#f6ffed", border: "1px solid #b7eb8f" }
2016
2737
  },
2017
- /* @__PURE__ */ React3.createElement("div", { className: "text-center" }, /* @__PURE__ */ React3.createElement("span", { style: { fontSize: "20px" } }, "\u2713"), /* @__PURE__ */ React3.createElement(Text, { style: {
2738
+ /* @__PURE__ */ React6.createElement("div", { className: "text-center" }, /* @__PURE__ */ React6.createElement("span", { style: { fontSize: "20px" } }, "\u2713"), /* @__PURE__ */ React6.createElement(Text, { style: {
2018
2739
  fontSize: "14px",
2019
2740
  color: "#52c41a",
2020
2741
  fontWeight: 600,
2021
2742
  marginLeft: "8px"
2022
2743
  } }, "Payment Successful!"))
2023
- ), isModal && error && /* @__PURE__ */ React3.createElement(
2744
+ ), isModal && error && /* @__PURE__ */ React6.createElement(
2024
2745
  "div",
2025
2746
  {
2026
2747
  className: "mt-4 p-4 rounded-lg",
2027
2748
  style: { background: "#fff2f0", border: "1px solid #ffccc7" }
2028
2749
  },
2029
- /* @__PURE__ */ React3.createElement("div", { className: "text-center mb-3" }, /* @__PURE__ */ React3.createElement("span", { style: { fontSize: "20px" } }, "\u2717"), /* @__PURE__ */ React3.createElement(Text, { style: {
2750
+ /* @__PURE__ */ React6.createElement("div", { className: "text-center mb-3" }, /* @__PURE__ */ React6.createElement("span", { style: { fontSize: "20px" } }, "\u2717"), /* @__PURE__ */ React6.createElement(Text, { style: {
2030
2751
  fontSize: "14px",
2031
2752
  color: "#ff4d4f",
2032
2753
  fontWeight: 600,
@@ -2034,7 +2755,7 @@ function V402Checkout({
2034
2755
  display: "block",
2035
2756
  marginTop: "4px"
2036
2757
  } }, "Payment Failed")),
2037
- /* @__PURE__ */ React3.createElement(Text, { style: {
2758
+ /* @__PURE__ */ React6.createElement(Text, { style: {
2038
2759
  fontSize: "13px",
2039
2760
  color: "#ff4d4f",
2040
2761
  display: "block",
@@ -2042,11 +2763,11 @@ function V402Checkout({
2042
2763
  } }, error)
2043
2764
  ))
2044
2765
  ),
2045
- !isModal && (isProcessing || result || error) && /* @__PURE__ */ React3.createElement(
2766
+ !isModal && (isProcessing || result || error) && /* @__PURE__ */ React6.createElement(
2046
2767
  Card,
2047
2768
  {
2048
- title: /* @__PURE__ */ React3.createElement("div", { className: "flex items-center gap-2" }, isProcessing && !result && !error ? /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(LoadingOutlined, { style: { color: "#14b8a6", fontSize: "16px" } }), /* @__PURE__ */ React3.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Processing Payment")) : result ? /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("span", { style: { color: "#52c41a", fontSize: "18px" } }, "\u2713"), /* @__PURE__ */ React3.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Payment Successful")) : /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("span", { style: { color: "#ff4d4f", fontSize: "18px" } }, "\u2717"), /* @__PURE__ */ React3.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Payment Failed"))),
2049
- extra: !isProcessing && /* @__PURE__ */ React3.createElement(
2769
+ title: /* @__PURE__ */ React6.createElement("div", { className: "flex items-center gap-2" }, isProcessing && !result && !error ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(LoadingOutlined, { style: { color: "#14b8a6", fontSize: "16px" } }), /* @__PURE__ */ React6.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Processing Payment")) : result ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement("span", { style: { color: "#52c41a", fontSize: "18px" } }, "\u2713"), /* @__PURE__ */ React6.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Payment Successful")) : /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement("span", { style: { color: "#ff4d4f", fontSize: "18px" } }, "\u2717"), /* @__PURE__ */ React6.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Payment Failed"))),
2770
+ extra: !isProcessing && /* @__PURE__ */ React6.createElement(
2050
2771
  Button,
2051
2772
  {
2052
2773
  type: "text",
@@ -2074,7 +2795,7 @@ function V402Checkout({
2074
2795
  }
2075
2796
  }
2076
2797
  },
2077
- isProcessing && !result && !error && /* @__PURE__ */ React3.createElement("div", { className: "text-center py-10" }, /* @__PURE__ */ React3.createElement("div", { className: "relative inline-block" }, /* @__PURE__ */ React3.createElement(
2798
+ isProcessing && !result && !error && /* @__PURE__ */ React6.createElement("div", { className: "text-center py-10" }, /* @__PURE__ */ React6.createElement("div", { className: "relative inline-block" }, /* @__PURE__ */ React6.createElement(
2078
2799
  "div",
2079
2800
  {
2080
2801
  className: "absolute inset-0 rounded-full blur-xl opacity-40",
@@ -2083,12 +2804,12 @@ function V402Checkout({
2083
2804
  animation: "pulse 2s ease-in-out infinite"
2084
2805
  }
2085
2806
  }
2086
- ), /* @__PURE__ */ React3.createElement(
2807
+ ), /* @__PURE__ */ React6.createElement(
2087
2808
  Spin,
2088
2809
  {
2089
- indicator: /* @__PURE__ */ React3.createElement(LoadingOutlined, { style: { fontSize: 56, color: "#14b8a6" } })
2810
+ indicator: /* @__PURE__ */ React6.createElement(LoadingOutlined, { style: { fontSize: 56, color: "#14b8a6" } })
2090
2811
  }
2091
- )), /* @__PURE__ */ React3.createElement("div", { className: "mt-6" }, /* @__PURE__ */ React3.createElement(Text, { strong: true, style: { fontSize: "18px", color: "#262626", letterSpacing: "-0.02em" } }, "Verifying Payment")), /* @__PURE__ */ React3.createElement("div", { className: "mt-2 mb-6" }, /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c", lineHeight: "1.6" } }, "Please wait while we confirm your transaction")), /* @__PURE__ */ React3.createElement(
2812
+ )), /* @__PURE__ */ React6.createElement("div", { className: "mt-6" }, /* @__PURE__ */ React6.createElement(Text, { strong: true, style: { fontSize: "18px", color: "#262626", letterSpacing: "-0.02em" } }, "Verifying Payment")), /* @__PURE__ */ React6.createElement("div", { className: "mt-2 mb-6" }, /* @__PURE__ */ React6.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c", lineHeight: "1.6" } }, "Please wait while we confirm your transaction")), /* @__PURE__ */ React6.createElement(
2092
2813
  "div",
2093
2814
  {
2094
2815
  className: "mt-4 p-4 rounded-xl",
@@ -2097,9 +2818,9 @@ function V402Checkout({
2097
2818
  border: "1px solid #ccfbf1"
2098
2819
  }
2099
2820
  },
2100
- /* @__PURE__ */ React3.createElement("div", { className: "flex items-center justify-center gap-2" }, /* @__PURE__ */ React3.createElement("span", { style: { fontSize: "16px" } }, "\u23F1\uFE0F"), /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "13px", color: "#0f766e", fontWeight: 500 } }, "This may take a few moments"))
2821
+ /* @__PURE__ */ React6.createElement("div", { className: "flex items-center justify-center gap-2" }, /* @__PURE__ */ React6.createElement("span", { style: { fontSize: "16px" } }, "\u23F1\uFE0F"), /* @__PURE__ */ React6.createElement(Text, { style: { fontSize: "13px", color: "#0f766e", fontWeight: 500 } }, "This may take a few moments"))
2101
2822
  )),
2102
- result && /* @__PURE__ */ React3.createElement("div", null, /* @__PURE__ */ React3.createElement("div", { className: "text-center mb-6" }, /* @__PURE__ */ React3.createElement(
2823
+ result && /* @__PURE__ */ React6.createElement("div", null, /* @__PURE__ */ React6.createElement("div", { className: "text-center mb-6" }, /* @__PURE__ */ React6.createElement(
2103
2824
  "div",
2104
2825
  {
2105
2826
  className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
@@ -2108,13 +2829,13 @@ function V402Checkout({
2108
2829
  boxShadow: "0 4px 20px rgba(16, 185, 129, 0.3)"
2109
2830
  }
2110
2831
  },
2111
- /* @__PURE__ */ React3.createElement("span", { style: { fontSize: "32px", color: "white" } }, "\u2713")
2112
- ), /* @__PURE__ */ React3.createElement("div", null, /* @__PURE__ */ React3.createElement(Text, { strong: true, style: {
2832
+ /* @__PURE__ */ React6.createElement("span", { style: { fontSize: "32px", color: "white" } }, "\u2713")
2833
+ ), /* @__PURE__ */ React6.createElement("div", null, /* @__PURE__ */ React6.createElement(Text, { strong: true, style: {
2113
2834
  fontSize: "20px",
2114
2835
  color: "#262626",
2115
2836
  display: "block",
2116
2837
  marginBottom: "8px"
2117
- } }, "Payment Successful!"), /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c" } }, "Your transaction has been confirmed"))), /* @__PURE__ */ React3.createElement(Divider, { style: { margin: "20px 0", borderColor: "#f0f0f0" } }, /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "12px", color: "#8c8c8c", fontWeight: 500 } }, "RESPONSE DATA")), /* @__PURE__ */ React3.createElement(
2838
+ } }, "Payment Successful!"), /* @__PURE__ */ React6.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c" } }, "Your transaction has been confirmed"))), /* @__PURE__ */ React6.createElement(Divider, { style: { margin: "20px 0", borderColor: "#f0f0f0" } }, /* @__PURE__ */ React6.createElement(Text, { style: { fontSize: "12px", color: "#8c8c8c", fontWeight: 500 } }, "RESPONSE DATA")), /* @__PURE__ */ React6.createElement(
2118
2839
  "pre",
2119
2840
  {
2120
2841
  style: {
@@ -2134,7 +2855,7 @@ function V402Checkout({
2134
2855
  },
2135
2856
  JSON.stringify(result, null, 2)
2136
2857
  )),
2137
- error && /* @__PURE__ */ React3.createElement("div", null, /* @__PURE__ */ React3.createElement("div", { className: "text-center mb-6" }, /* @__PURE__ */ React3.createElement(
2858
+ error && /* @__PURE__ */ React6.createElement("div", null, /* @__PURE__ */ React6.createElement("div", { className: "text-center mb-6" }, /* @__PURE__ */ React6.createElement(
2138
2859
  "div",
2139
2860
  {
2140
2861
  className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
@@ -2143,13 +2864,13 @@ function V402Checkout({
2143
2864
  boxShadow: "0 4px 20px rgba(239, 68, 68, 0.3)"
2144
2865
  }
2145
2866
  },
2146
- /* @__PURE__ */ React3.createElement("span", { style: { fontSize: "32px", color: "white" } }, "\u2717")
2147
- ), /* @__PURE__ */ React3.createElement("div", null, /* @__PURE__ */ React3.createElement(Text, { strong: true, style: {
2867
+ /* @__PURE__ */ React6.createElement("span", { style: { fontSize: "32px", color: "white" } }, "\u2717")
2868
+ ), /* @__PURE__ */ React6.createElement("div", null, /* @__PURE__ */ React6.createElement(Text, { strong: true, style: {
2148
2869
  fontSize: "20px",
2149
2870
  color: "#262626",
2150
2871
  display: "block",
2151
2872
  marginBottom: "8px"
2152
- } }, "Payment Failed"), /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c" } }, "Something went wrong with your transaction"))), /* @__PURE__ */ React3.createElement(Divider, { style: { margin: "20px 0", borderColor: "#f0f0f0" } }, /* @__PURE__ */ React3.createElement(Text, { style: { fontSize: "12px", color: "#8c8c8c", fontWeight: 500 } }, "ERROR DETAILS")), /* @__PURE__ */ React3.createElement(
2873
+ } }, "Payment Failed"), /* @__PURE__ */ React6.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c" } }, "Something went wrong with your transaction"))), /* @__PURE__ */ React6.createElement(Divider, { style: { margin: "20px 0", borderColor: "#f0f0f0" } }, /* @__PURE__ */ React6.createElement(Text, { style: { fontSize: "12px", color: "#8c8c8c", fontWeight: 500 } }, "ERROR DETAILS")), /* @__PURE__ */ React6.createElement(
2153
2874
  "div",
2154
2875
  {
2155
2876
  style: {
@@ -2159,13 +2880,13 @@ function V402Checkout({
2159
2880
  border: "1px solid #fee2e2"
2160
2881
  }
2161
2882
  },
2162
- /* @__PURE__ */ React3.createElement(Text, { style: {
2883
+ /* @__PURE__ */ React6.createElement(Text, { style: {
2163
2884
  fontSize: "14px",
2164
2885
  color: "#dc2626",
2165
2886
  lineHeight: "1.6",
2166
2887
  fontWeight: 500
2167
2888
  } }, error)
2168
- ), /* @__PURE__ */ React3.createElement("div", { className: "mt-4 text-center" }, /* @__PURE__ */ React3.createElement(
2889
+ ), /* @__PURE__ */ React6.createElement("div", { className: "mt-4 text-center" }, /* @__PURE__ */ React6.createElement(
2169
2890
  Button,
2170
2891
  {
2171
2892
  size: "large",
@@ -2186,7 +2907,7 @@ function V402Checkout({
2186
2907
  )))
2187
2908
  )
2188
2909
  ),
2189
- /* @__PURE__ */ React3.createElement("style", { dangerouslySetInnerHTML: {
2910
+ /* @__PURE__ */ React6.createElement("style", { dangerouslySetInnerHTML: {
2190
2911
  __html: `
2191
2912
  @keyframes slideInRight {
2192
2913
  from {
@@ -2213,12 +2934,698 @@ function V402Checkout({
2213
2934
  } })
2214
2935
  );
2215
2936
  }
2937
+
2938
+ // src/react/components/checkout/V402CheckoutV2.tsx
2939
+ import React11, { useEffect as useEffect7, useState as useState8 } from "react";
2940
+ init_common();
2941
+
2942
+ // src/react/styles/animations.tsx
2943
+ import React7 from "react";
2944
+ var checkoutAnimations = `
2945
+ @keyframes spin {
2946
+ from { transform: rotate(0deg); }
2947
+ to { transform: rotate(360deg); }
2948
+ }
2949
+
2950
+ @keyframes receiptShake {
2951
+ 0%, 100% { transform: rotate(-0.3deg); }
2952
+ 50% { transform: rotate(0.3deg); }
2953
+ }
2954
+
2955
+ @keyframes slideInRight {
2956
+ from {
2957
+ opacity: 0;
2958
+ transform: translateX(100px);
2959
+ }
2960
+ to {
2961
+ opacity: 1;
2962
+ transform: translateX(0);
2963
+ }
2964
+ }
2965
+
2966
+ @keyframes pulse {
2967
+ 0%, 100% { opacity: 1; }
2968
+ 50% { opacity: 0.4; }
2969
+ }
2970
+ `;
2971
+ var AnimationStyles = () => /* @__PURE__ */ React7.createElement("style", { dangerouslySetInnerHTML: { __html: checkoutAnimations } });
2972
+
2973
+ // src/react/components/checkout/Receipt.tsx
2974
+ import React8, { useEffect as useEffect6, useState as useState7 } from "react";
2975
+ var Receipt = ({
2976
+ isLoading,
2977
+ isVisible,
2978
+ result,
2979
+ error,
2980
+ paymentDetails,
2981
+ address,
2982
+ onClose,
2983
+ primaryColor,
2984
+ receiptTitle,
2985
+ tempReceiptId
2986
+ }) => {
2987
+ const [animationState, setAnimationState] = useState7("hidden");
2988
+ useEffect6(() => {
2989
+ if (isLoading) {
2990
+ setAnimationState("printing");
2991
+ } else if (isVisible && (result || error)) {
2992
+ setAnimationState("visible");
2993
+ const timer = setTimeout(() => setAnimationState("bounce"), 50);
2994
+ return () => clearTimeout(timer);
2995
+ } else if (!isVisible) {
2996
+ setAnimationState("hidden");
2997
+ }
2998
+ }, [isLoading, isVisible, result, error]);
2999
+ useEffect6(() => {
3000
+ if (animationState === "bounce") {
3001
+ const timer = setTimeout(() => setAnimationState("visible"), 150);
3002
+ return () => clearTimeout(timer);
3003
+ }
3004
+ }, [animationState]);
3005
+ const now = /* @__PURE__ */ new Date();
3006
+ const dateStr = `${String(now.getMonth() + 1).padStart(2, "0")}/${String(now.getDate()).padStart(2, "0")}/${String(now.getFullYear()).slice(-2)}`;
3007
+ const timeStr = `${String(now.getHours()).padStart(2, "0")}:${String(now.getMinutes()).padStart(2, "0")}`;
3008
+ const receiptId = result?.transactionHash ? result.transactionHash.slice(-8).toUpperCase() : tempReceiptId;
3009
+ const getAnimationStyles = () => {
3010
+ const baseTransition = animationState === "bounce" ? "all 0.15s cubic-bezier(0.34, 1.56, 0.64, 1)" : "all 0.5s cubic-bezier(0.34, 1.56, 0.64, 1)";
3011
+ switch (animationState) {
3012
+ case "hidden":
3013
+ return {
3014
+ opacity: 0,
3015
+ transform: "translateY(50px)",
3016
+ marginBottom: 0,
3017
+ transition: baseTransition
3018
+ };
3019
+ case "printing":
3020
+ return {
3021
+ opacity: 1,
3022
+ transform: "translateY(0)",
3023
+ marginBottom: "-4px",
3024
+ // 负边距让小票贴着机器,还没撕开的感觉
3025
+ animation: "receiptShake 0.12s ease-in-out infinite",
3026
+ transition: baseTransition
3027
+ };
3028
+ case "visible":
3029
+ return {
3030
+ opacity: 1,
3031
+ transform: "translateY(0)",
3032
+ marginBottom: "8px",
3033
+ transition: baseTransition
3034
+ };
3035
+ case "bounce":
3036
+ return {
3037
+ opacity: 1,
3038
+ transform: "translateY(-8px)",
3039
+ marginBottom: "8px",
3040
+ transition: baseTransition
3041
+ };
3042
+ default:
3043
+ return {};
3044
+ }
3045
+ };
3046
+ const getContentStyles = () => {
3047
+ const baseTransition = "all 0.5s cubic-bezier(0.34, 1.56, 0.64, 1)";
3048
+ switch (animationState) {
3049
+ case "hidden":
3050
+ return {
3051
+ maxHeight: 0,
3052
+ overflow: "hidden",
3053
+ transition: baseTransition
3054
+ };
3055
+ case "printing":
3056
+ return {
3057
+ maxHeight: "80px",
3058
+ overflow: "hidden",
3059
+ transition: baseTransition
3060
+ };
3061
+ case "visible":
3062
+ case "bounce":
3063
+ return {
3064
+ maxHeight: "600px",
3065
+ overflow: "visible",
3066
+ transition: baseTransition
3067
+ };
3068
+ default:
3069
+ return {};
3070
+ }
3071
+ };
3072
+ if (animationState === "hidden" && !isLoading) return null;
3073
+ return /* @__PURE__ */ React8.createElement(
3074
+ "div",
3075
+ {
3076
+ className: "w-full flex justify-center",
3077
+ style: getAnimationStyles()
3078
+ },
3079
+ /* @__PURE__ */ React8.createElement(
3080
+ "div",
3081
+ {
3082
+ className: "relative bg-white shadow-2xl",
3083
+ style: {
3084
+ width: "75%",
3085
+ maxWidth: "280px",
3086
+ backgroundImage: `
3087
+ repeating-linear-gradient(
3088
+ 0deg,
3089
+ transparent,
3090
+ transparent 1px,
3091
+ rgba(0,0,0,0.02) 1px,
3092
+ rgba(0,0,0,0.02) 2px
3093
+ )
3094
+ `
3095
+ }
3096
+ },
3097
+ /* @__PURE__ */ React8.createElement(
3098
+ "div",
3099
+ {
3100
+ className: "absolute top-0 left-0 right-0",
3101
+ style: {
3102
+ height: "8px",
3103
+ transform: "translateY(-100%)",
3104
+ background: `radial-gradient(circle at 50% 100%, white 5px, transparent 5px)`,
3105
+ backgroundSize: "12px 8px",
3106
+ backgroundPosition: "6px 0",
3107
+ backgroundRepeat: "repeat-x"
3108
+ }
3109
+ }
3110
+ ),
3111
+ /* @__PURE__ */ React8.createElement(
3112
+ "div",
3113
+ {
3114
+ className: "absolute left-0 right-0 bg-white",
3115
+ style: {
3116
+ height: "4px",
3117
+ top: "-4px"
3118
+ }
3119
+ }
3120
+ ),
3121
+ !isLoading && /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(
3122
+ "div",
3123
+ {
3124
+ className: "absolute bottom-0 left-0 right-0",
3125
+ style: {
3126
+ height: "8px",
3127
+ transform: "translateY(100%)",
3128
+ background: `radial-gradient(circle at 50% 0%, white 5px, transparent 5px)`,
3129
+ backgroundSize: "12px 8px",
3130
+ backgroundPosition: "6px 0",
3131
+ backgroundRepeat: "repeat-x"
3132
+ }
3133
+ }
3134
+ ), /* @__PURE__ */ React8.createElement(
3135
+ "div",
3136
+ {
3137
+ className: "absolute left-0 right-0 bg-white",
3138
+ style: {
3139
+ height: "4px",
3140
+ bottom: "-4px"
3141
+ }
3142
+ }
3143
+ )),
3144
+ !isLoading && (result || error) && /* @__PURE__ */ React8.createElement(
3145
+ "button",
3146
+ {
3147
+ onClick: onClose,
3148
+ className: "absolute top-3 right-3 text-gray-300 hover:text-gray-500 transition-colors bg-transparent border-none outline-none p-0 cursor-pointer",
3149
+ style: { background: "none", border: "none" }
3150
+ },
3151
+ /* @__PURE__ */ React8.createElement("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" }, /* @__PURE__ */ React8.createElement("path", { d: "M18 6L6 18M6 6l12 12" }))
3152
+ ),
3153
+ /* @__PURE__ */ React8.createElement("div", { className: "p-4 font-mono text-sm", style: getContentStyles() }, /* @__PURE__ */ React8.createElement("div", { className: "text-center mb-3" }, /* @__PURE__ */ React8.createElement("div", { className: "text-base font-bold tracking-wider text-gray-800" }, receiptTitle), /* @__PURE__ */ React8.createElement("div", { className: "flex justify-between text-xs text-gray-500 mt-1" }, /* @__PURE__ */ React8.createElement("span", null, "ID: ", receiptId), /* @__PURE__ */ React8.createElement("span", null, dateStr, " ", timeStr))), /* @__PURE__ */ React8.createElement("div", { className: "border-t border-dashed border-gray-300 my-2" }), /* @__PURE__ */ React8.createElement(
3154
+ "div",
3155
+ {
3156
+ className: "max-h-64 overflow-y-auto pr-1",
3157
+ style: {
3158
+ scrollbarWidth: "thin",
3159
+ scrollbarColor: "#d1d5db transparent"
3160
+ }
3161
+ },
3162
+ isLoading ? /* @__PURE__ */ React8.createElement(LoadingContent, { primaryColor }) : error ? /* @__PURE__ */ React8.createElement(ErrorContent, { error }) : result ? /* @__PURE__ */ React8.createElement(
3163
+ SuccessContent,
3164
+ {
3165
+ result,
3166
+ paymentDetails,
3167
+ address,
3168
+ primaryColor
3169
+ }
3170
+ ) : null
3171
+ ), /* @__PURE__ */ React8.createElement("div", { className: "border-t border-dashed border-gray-300 my-2" }), /* @__PURE__ */ React8.createElement(Barcode, null), /* @__PURE__ */ React8.createElement("div", { className: "text-center text-xs text-gray-400 mt-1 tracking-widest" }, "POWERED BY", " ", /* @__PURE__ */ React8.createElement(
3172
+ "a",
3173
+ {
3174
+ href: "https://v402pay.onvoyage.ai",
3175
+ target: "_blank",
3176
+ rel: "noopener noreferrer",
3177
+ className: "text-gray-500 hover:text-gray-700 underline transition-colors"
3178
+ },
3179
+ "V402PAY"
3180
+ )))
3181
+ )
3182
+ );
3183
+ };
3184
+ var LoadingContent = ({ primaryColor }) => /* @__PURE__ */ React8.createElement("div", { className: "text-center py-4" }, /* @__PURE__ */ React8.createElement(
3185
+ "div",
3186
+ {
3187
+ className: "inline-block w-8 h-8 border-2 border-gray-200 rounded-full mb-2",
3188
+ style: {
3189
+ borderTopColor: primaryColor,
3190
+ animation: "spin 0.8s linear infinite"
3191
+ }
3192
+ }
3193
+ ), /* @__PURE__ */ React8.createElement("div", { className: "text-gray-700 font-semibold text-sm" }, "Processing..."), /* @__PURE__ */ React8.createElement("div", { className: "text-gray-400 text-xs mt-1" }, "Please wait"));
3194
+ var ErrorContent = ({ error }) => /* @__PURE__ */ React8.createElement("div", { className: "text-center py-3" }, /* @__PURE__ */ React8.createElement("div", { className: "text-red-500 text-2xl mb-2" }, "\u2717"), /* @__PURE__ */ React8.createElement("div", { className: "text-red-600 font-semibold mb-1 text-sm" }, "FAILED"), /* @__PURE__ */ React8.createElement("div", { className: "text-red-500 text-xs break-words px-2" }, error));
3195
+ var SuccessContent = ({
3196
+ result,
3197
+ paymentDetails,
3198
+ address,
3199
+ primaryColor
3200
+ }) => {
3201
+ const [copied, setCopied] = useState7(false);
3202
+ const handleCopy = async () => {
3203
+ try {
3204
+ await navigator.clipboard.writeText(JSON.stringify(result, null, 2));
3205
+ setCopied(true);
3206
+ setTimeout(() => setCopied(false), 2e3);
3207
+ } catch (err) {
3208
+ console.error("Failed to copy:", err);
3209
+ }
3210
+ };
3211
+ return /* @__PURE__ */ React8.createElement("div", null, /* @__PURE__ */ React8.createElement("div", { className: "text-center mb-2" }, /* @__PURE__ */ React8.createElement("div", { className: "text-2xl mb-1", style: { color: primaryColor } }, "\u2713"), /* @__PURE__ */ React8.createElement("div", { className: "font-semibold text-sm", style: { color: primaryColor } }, "SUCCESS")), /* @__PURE__ */ React8.createElement("div", { className: "space-y-1 text-xs" }, paymentDetails && /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement("div", { className: "flex justify-between" }, /* @__PURE__ */ React8.createElement("span", { className: "text-gray-500" }, "Amount:"), /* @__PURE__ */ React8.createElement("span", { className: "font-semibold" }, "$", paymentDetails.amount, " ", paymentDetails.currency)), /* @__PURE__ */ React8.createElement("div", { className: "flex justify-between" }, /* @__PURE__ */ React8.createElement("span", { className: "text-gray-500" }, "Network:"), /* @__PURE__ */ React8.createElement("span", { className: "font-semibold" }, paymentDetails.network))), address && /* @__PURE__ */ React8.createElement("div", { className: "flex justify-between" }, /* @__PURE__ */ React8.createElement("span", { className: "text-gray-500" }, "From:"), /* @__PURE__ */ React8.createElement("span", { className: "font-semibold" }, formatAddress(address))), result.transactionHash && /* @__PURE__ */ React8.createElement("div", { className: "flex justify-between" }, /* @__PURE__ */ React8.createElement("span", { className: "text-gray-500" }, "TX:"), /* @__PURE__ */ React8.createElement("span", { className: "font-semibold" }, formatAddress(result.transactionHash)))), /* @__PURE__ */ React8.createElement("div", { className: "border-t border-dashed border-gray-300 my-2" }), /* @__PURE__ */ React8.createElement("div", { className: "text-xs" }, /* @__PURE__ */ React8.createElement("div", { className: "flex justify-between items-center mb-1" }, /* @__PURE__ */ React8.createElement("span", { className: "text-gray-500" }, "Response:"), /* @__PURE__ */ React8.createElement(
3212
+ "button",
3213
+ {
3214
+ onClick: handleCopy,
3215
+ className: "text-gray-300 hover:text-gray-500 transition-colors flex items-center gap-1 bg-transparent border-none outline-none p-0 cursor-pointer",
3216
+ style: { background: "none", border: "none" }
3217
+ },
3218
+ copied ? /* @__PURE__ */ React8.createElement("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" }, /* @__PURE__ */ React8.createElement("path", { d: "M20 6L9 17l-5-5" })) : /* @__PURE__ */ React8.createElement("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }, /* @__PURE__ */ React8.createElement("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }), /* @__PURE__ */ React8.createElement("path", { d: "M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1" }))
3219
+ )), /* @__PURE__ */ React8.createElement(
3220
+ "pre",
3221
+ {
3222
+ className: "bg-gray-50 p-2 rounded text-xs overflow-auto whitespace-pre-wrap break-words",
3223
+ style: { maxHeight: "80px", fontSize: "10px" }
3224
+ },
3225
+ JSON.stringify(result, null, 2)
3226
+ )));
3227
+ };
3228
+ var Barcode = () => {
3229
+ const pattern = [2, 1, 2, 1, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 1];
3230
+ const heights = [10, 12, 11, 13, 10, 14, 11, 12, 13, 10, 11, 14, 12, 10, 13, 11, 12, 14, 10, 11];
3231
+ return /* @__PURE__ */ React8.createElement("div", { className: "flex items-center justify-center gap-0.5 h-4 opacity-60" }, pattern.map((width, i) => /* @__PURE__ */ React8.createElement(
3232
+ "div",
3233
+ {
3234
+ key: i,
3235
+ className: "bg-gray-800",
3236
+ style: {
3237
+ width: `${width}px`,
3238
+ height: `${heights[i]}px`
3239
+ }
3240
+ }
3241
+ )));
3242
+ };
3243
+
3244
+ // src/react/components/checkout/TerminalScreen.tsx
3245
+ import React9 from "react";
3246
+ var TerminalScreen = ({
3247
+ title,
3248
+ tooltipText,
3249
+ hasInvalidCheckoutId,
3250
+ fetchingPaymentInfo,
3251
+ address,
3252
+ paymentDetails,
3253
+ screenText,
3254
+ supportedNetworks
3255
+ }) => {
3256
+ return /* @__PURE__ */ React9.createElement(
3257
+ "div",
3258
+ {
3259
+ className: "rounded-xl p-3 mb-3",
3260
+ style: {
3261
+ backgroundColor: "#0a1a0a",
3262
+ boxShadow: "inset 0 3px 16px rgba(0,0,0,0.5)",
3263
+ border: "3px solid rgba(0,0,0,0.3)"
3264
+ }
3265
+ },
3266
+ /* @__PURE__ */ React9.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ React9.createElement("div", { className: "flex items-center gap-1.5 flex-1 min-w-0" }, /* @__PURE__ */ React9.createElement("div", { className: "w-2.5 h-2.5 rounded border border-green-700 flex-shrink-0" }), title ? /* @__PURE__ */ React9.createElement(
3267
+ "span",
3268
+ {
3269
+ className: "text-xs font-mono",
3270
+ style: { color: "#22c55e80" },
3271
+ title
3272
+ },
3273
+ title.length > 26 ? `${title.slice(0, 13)}...${title.slice(-13)}` : title
3274
+ ) : /* @__PURE__ */ React9.createElement("span", { className: "text-xs font-mono", style: { color: "#22c55e80" } }, "CHECKOUT")), /* @__PURE__ */ React9.createElement(
3275
+ "div",
3276
+ {
3277
+ className: "flex gap-0.5 flex-shrink-0 cursor-help",
3278
+ title: tooltipText
3279
+ },
3280
+ /* @__PURE__ */ React9.createElement(
3281
+ "div",
3282
+ {
3283
+ className: "w-1 h-1.5 rounded-sm",
3284
+ style: { backgroundColor: address ? "#22c55e80" : "#22c55e30" }
3285
+ }
3286
+ ),
3287
+ /* @__PURE__ */ React9.createElement(
3288
+ "div",
3289
+ {
3290
+ className: "w-1 h-1.5 rounded-sm",
3291
+ style: { backgroundColor: address ? "#22c55e80" : "#22c55e30" }
3292
+ }
3293
+ ),
3294
+ /* @__PURE__ */ React9.createElement("div", { className: "w-1 h-1.5 rounded-sm", style: { backgroundColor: "#22c55e80" } })
3295
+ )),
3296
+ /* @__PURE__ */ React9.createElement("div", { className: "min-h-[120px]" }, hasInvalidCheckoutId ? /* @__PURE__ */ React9.createElement(InvalidIdContent, null) : fetchingPaymentInfo ? /* @__PURE__ */ React9.createElement(LoadingContent2, null) : !address ? /* @__PURE__ */ React9.createElement(ConnectWalletContent, { supportedNetworks }) : /* @__PURE__ */ React9.createElement(
3297
+ PaymentInfoContent,
3298
+ {
3299
+ screenText,
3300
+ paymentDetails,
3301
+ address
3302
+ }
3303
+ ))
3304
+ );
3305
+ };
3306
+ var InvalidIdContent = () => /* @__PURE__ */ React9.createElement("div", { className: "text-center py-3" }, /* @__PURE__ */ React9.createElement("div", { className: "text-red-500 text-xl mb-1" }, "\u2717"), /* @__PURE__ */ React9.createElement("div", { className: "text-red-500 font-mono text-sm mb-1" }, "INVALID ID"), /* @__PURE__ */ React9.createElement("div", { className: "text-red-400 font-mono text-xs" }, "Check your checkout ID"));
3307
+ var LoadingContent2 = () => /* @__PURE__ */ React9.createElement("div", { className: "text-center py-4" }, /* @__PURE__ */ React9.createElement(
3308
+ "div",
3309
+ {
3310
+ className: "inline-block w-5 h-5 border-2 rounded-full mb-2",
3311
+ style: {
3312
+ borderColor: "#22c55e40",
3313
+ borderTopColor: "#22c55e",
3314
+ animation: "spin 1s linear infinite"
3315
+ }
3316
+ }
3317
+ ), /* @__PURE__ */ React9.createElement("div", { className: "font-mono text-sm", style: { color: "#22c55e" } }, "LOADING..."));
3318
+ var ConnectWalletContent = ({ supportedNetworks }) => /* @__PURE__ */ React9.createElement("div", null, /* @__PURE__ */ React9.createElement(
3319
+ "div",
3320
+ {
3321
+ className: "font-mono text-base mb-3 tracking-wider",
3322
+ style: { color: "#f97316", textShadow: "0 0 10px #f9731640" }
3323
+ },
3324
+ "CONNECT WALLET..."
3325
+ ), /* @__PURE__ */ React9.createElement(WalletConnect, { supportedNetworks, showSwitchWallet: false }));
3326
+ var PaymentInfoContent = ({
3327
+ screenText,
3328
+ paymentDetails,
3329
+ address
3330
+ }) => /* @__PURE__ */ React9.createElement("div", null, /* @__PURE__ */ React9.createElement(
3331
+ "div",
3332
+ {
3333
+ className: "font-mono text-base mb-3 tracking-wider",
3334
+ style: { color: "#f97316", textShadow: "0 0 10px #f9731640" }
3335
+ },
3336
+ screenText
3337
+ ), paymentDetails && /* @__PURE__ */ React9.createElement("div", { className: "text-xs font-mono" }, /* @__PURE__ */ React9.createElement("div", { className: "grid grid-cols-2 gap-1.5 mb-1.5" }, /* @__PURE__ */ React9.createElement("div", null, /* @__PURE__ */ React9.createElement("div", { style: { color: "#22c55e60" } }, "AMOUNT"), /* @__PURE__ */ React9.createElement("div", { style: { color: "#22c55e" } }, "$", paymentDetails.amount)), /* @__PURE__ */ React9.createElement("div", null, /* @__PURE__ */ React9.createElement("div", { style: { color: "#22c55e60" } }, "CURRENCY"), /* @__PURE__ */ React9.createElement("div", { style: { color: "#22c55e" } }, paymentDetails.currency))), /* @__PURE__ */ React9.createElement("div", null, /* @__PURE__ */ React9.createElement("div", { style: { color: "#22c55e60" } }, "WALLET"), /* @__PURE__ */ React9.createElement("div", { style: { color: "#22c55e", wordBreak: "break-all" } }, address))));
3338
+
3339
+ // src/react/components/checkout/TerminalButtons.tsx
3340
+ import React10 from "react";
3341
+ var TerminalButtons = ({
3342
+ address,
3343
+ showReceipt,
3344
+ isProcessing,
3345
+ paymentDetails,
3346
+ hasInvalidCheckoutId,
3347
+ onDisconnect,
3348
+ onClearReceipt,
3349
+ onPayment
3350
+ }) => {
3351
+ const isPayDisabled = isProcessing || !paymentDetails || !address || hasInvalidCheckoutId;
3352
+ return /* @__PURE__ */ React10.createElement("div", { className: "flex items-center justify-between px-1" }, /* @__PURE__ */ React10.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React10.createElement(
3353
+ CircleButton,
3354
+ {
3355
+ onClick: () => address && onDisconnect(),
3356
+ disabled: !address,
3357
+ title: "Disconnect",
3358
+ size: "small"
3359
+ },
3360
+ /* @__PURE__ */ React10.createElement("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "white", strokeWidth: "2" }, /* @__PURE__ */ React10.createElement("path", { d: "M18 6L6 18M6 6l12 12" }))
3361
+ ), /* @__PURE__ */ React10.createElement(
3362
+ CircleButton,
3363
+ {
3364
+ onClick: onClearReceipt,
3365
+ disabled: !showReceipt || isProcessing,
3366
+ title: "Clear",
3367
+ size: "small"
3368
+ },
3369
+ /* @__PURE__ */ React10.createElement("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "white", strokeWidth: "2" }, /* @__PURE__ */ React10.createElement("path", { d: "M3 6h18M8 6V4a2 2 0 012-2h4a2 2 0 012 2v2m3 0v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6h14z" }))
3370
+ )), /* @__PURE__ */ React10.createElement("div", { className: "flex flex-col gap-0.5 opacity-40" }, /* @__PURE__ */ React10.createElement("div", { className: "w-6 h-0.5 rounded", style: { backgroundColor: "rgba(0,0,0,0.3)" } }), /* @__PURE__ */ React10.createElement("div", { className: "w-6 h-0.5 rounded", style: { backgroundColor: "rgba(0,0,0,0.3)" } }), /* @__PURE__ */ React10.createElement("div", { className: "w-6 h-0.5 rounded", style: { backgroundColor: "rgba(0,0,0,0.3)" } })), /* @__PURE__ */ React10.createElement(
3371
+ "button",
3372
+ {
3373
+ onClick: onPayment,
3374
+ disabled: isPayDisabled,
3375
+ className: "px-5 py-2.5 rounded-xl font-bold text-white flex items-center gap-2 transition-all active:scale-95",
3376
+ style: {
3377
+ backgroundColor: isPayDisabled ? "#9ca3af" : "#ea580c",
3378
+ boxShadow: isPayDisabled ? "none" : "0 4px 12px rgba(234,88,12,0.4), inset 0 -2px 4px rgba(0,0,0,0.2)",
3379
+ cursor: isPayDisabled ? "not-allowed" : "pointer"
3380
+ }
3381
+ },
3382
+ isProcessing ? /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(
3383
+ "div",
3384
+ {
3385
+ className: "w-4 h-4 border-2 border-white/30 border-t-white rounded-full",
3386
+ style: { animation: "spin 0.8s linear infinite" }
3387
+ }
3388
+ ), /* @__PURE__ */ React10.createElement("span", { className: "font-mono tracking-wider text-sm" }, "PAYING...")) : /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement("span", { className: "font-mono tracking-wider text-sm" }, "PAY"), /* @__PURE__ */ React10.createElement(
3389
+ "svg",
3390
+ {
3391
+ width: "18",
3392
+ height: "18",
3393
+ viewBox: "0 0 24 24",
3394
+ fill: "none",
3395
+ stroke: "currentColor",
3396
+ strokeWidth: "2"
3397
+ },
3398
+ /* @__PURE__ */ React10.createElement("path", { d: "M12 2v20M17 5H9.5a3.5 3.5 0 000 7h5a3.5 3.5 0 010 7H6" })
3399
+ ))
3400
+ ));
3401
+ };
3402
+ var CircleButton = ({ onClick, disabled, title, size = "normal", children }) => {
3403
+ const sizeClass = size === "small" ? "w-10 h-10" : "w-12 h-12";
3404
+ return /* @__PURE__ */ React10.createElement(
3405
+ "button",
3406
+ {
3407
+ onClick,
3408
+ disabled,
3409
+ className: `${sizeClass} rounded-full flex items-center justify-center transition-transform active:scale-95`,
3410
+ style: {
3411
+ backgroundColor: "#374151",
3412
+ boxShadow: "inset 0 -2px 4px rgba(0,0,0,0.3), 0 2px 4px rgba(0,0,0,0.2)",
3413
+ opacity: disabled ? 0.5 : 1
3414
+ },
3415
+ title
3416
+ },
3417
+ children
3418
+ );
3419
+ };
3420
+
3421
+ // src/react/components/checkout/V402CheckoutV2.tsx
3422
+ var generateRandomId = () => {
3423
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
3424
+ return Array.from({ length: 8 }, () => chars[Math.floor(Math.random() * chars.length)]).join("");
3425
+ };
3426
+ function V402CheckoutV2({
3427
+ checkoutId,
3428
+ headerInfo = {},
3429
+ primaryColor = "#84cc16",
3430
+ isModal = false,
3431
+ onPaymentComplete,
3432
+ additionalParams = {},
3433
+ expectedNetwork
3434
+ }) {
3435
+ const {
3436
+ title = "V402Pay Checkout",
3437
+ brandName = "V402PAY",
3438
+ receiptTitle = "V402 PAYMENT",
3439
+ tooltipText = "V402Pay - Accept Crypto Payments Easier"
3440
+ } = headerInfo;
3441
+ const endpoint = PROD_BACK_URL;
3442
+ const {
3443
+ supportedNetworks,
3444
+ isLoading: fetchingPaymentInfo,
3445
+ paymentInfo
3446
+ } = usePaymentInfo(checkoutId, endpoint, additionalParams);
3447
+ const targetNetwork = expectedNetwork || supportedNetworks[0];
3448
+ const { address, networkType, disconnect, ensureNetwork } = usePageNetwork(
3449
+ targetNetwork,
3450
+ { autoSwitch: !!targetNetwork, switchOnMount: true }
3451
+ );
3452
+ const { isProcessing, setIsProcessing, result, setResult, error, setError } = usePayment();
3453
+ const [paymentDetails, setPaymentDetails] = useState8(null);
3454
+ const [showReceipt, setShowReceipt] = useState8(false);
3455
+ const [tempReceiptId, setTempReceiptId] = useState8(() => generateRandomId());
3456
+ const handleDisconnect = () => {
3457
+ disconnect();
3458
+ setResult(null);
3459
+ setError(null);
3460
+ setShowReceipt(false);
3461
+ };
3462
+ const handlePayment = async () => {
3463
+ if (!networkType) return;
3464
+ setTempReceiptId(generateRandomId());
3465
+ setResult(null);
3466
+ setError(null);
3467
+ setIsProcessing(true);
3468
+ setShowReceipt(true);
3469
+ try {
3470
+ const response = await makePayment(networkType, checkoutId, endpoint, additionalParams, address || void 0);
3471
+ const data = await response.json();
3472
+ setResult(data);
3473
+ if (onPaymentComplete) {
3474
+ onPaymentComplete(data);
3475
+ }
3476
+ } catch (err) {
3477
+ setError(err.message || "Payment failed");
3478
+ } finally {
3479
+ setIsProcessing(false);
3480
+ }
3481
+ };
3482
+ const handleCloseReceipt = () => {
3483
+ setShowReceipt(false);
3484
+ setResult(null);
3485
+ setError(null);
3486
+ };
3487
+ useEffect7(() => {
3488
+ if (paymentInfo && paymentInfo.length > 0) {
3489
+ const firstPayment = paymentInfo[0];
3490
+ const rawAmount = firstPayment.maxAmountRequired?.toString() || "0";
3491
+ const decimals = 6;
3492
+ const humanReadableAmount = (Number(rawAmount) / Math.pow(10, decimals)).toFixed(2);
3493
+ const network = firstPayment.network || "Unknown";
3494
+ const currency = "USDC";
3495
+ setPaymentDetails({ amount: humanReadableAmount, currency, network });
3496
+ }
3497
+ }, [paymentInfo]);
3498
+ useEffect7(() => {
3499
+ if (targetNetwork && !fetchingPaymentInfo && ensureNetwork) {
3500
+ ensureNetwork(targetNetwork).catch((err) => {
3501
+ console.error("Failed to ensure network:", err);
3502
+ });
3503
+ }
3504
+ }, [targetNetwork, fetchingPaymentInfo]);
3505
+ useEffect7(() => {
3506
+ if (isProcessing || result || error) {
3507
+ setShowReceipt(true);
3508
+ }
3509
+ }, [isProcessing, result, error]);
3510
+ const hasInvalidCheckoutId = !fetchingPaymentInfo && (!paymentInfo || paymentInfo.length === 0);
3511
+ const NetworkIcon = paymentDetails ? getNetworkIcon(paymentDetails.network) : null;
3512
+ const screenText = paymentDetails ? `PAY $${paymentDetails.amount} ${paymentDetails.currency}` : "AWAITING...";
3513
+ const getStatusText = () => {
3514
+ if (hasInvalidCheckoutId) return "ERROR";
3515
+ if (fetchingPaymentInfo) return "LOADING";
3516
+ if (!address) return "CONNECT";
3517
+ if (isProcessing) return "PAYING";
3518
+ return "READY";
3519
+ };
3520
+ return /* @__PURE__ */ React11.createElement("div", { className: isModal ? "bg-transparent" : "min-h-screen bg-gray-100 flex items-center justify-center p-4" }, /* @__PURE__ */ React11.createElement(
3521
+ "div",
3522
+ {
3523
+ className: "flex flex-col items-center",
3524
+ style: { width: isModal ? "100%" : "380px", maxWidth: "100%" }
3525
+ },
3526
+ /* @__PURE__ */ React11.createElement(
3527
+ Receipt,
3528
+ {
3529
+ isLoading: isProcessing,
3530
+ isVisible: showReceipt,
3531
+ result,
3532
+ error,
3533
+ paymentDetails,
3534
+ address,
3535
+ onClose: handleCloseReceipt,
3536
+ primaryColor,
3537
+ receiptTitle,
3538
+ tempReceiptId
3539
+ }
3540
+ ),
3541
+ /* @__PURE__ */ React11.createElement(
3542
+ "div",
3543
+ {
3544
+ className: "relative rounded-2xl p-3 shadow-2xl w-full",
3545
+ style: {
3546
+ backgroundColor: primaryColor,
3547
+ boxShadow: `0 16px 48px -8px ${primaryColor}66, 0 8px 24px -4px rgba(0,0,0,0.3);padding-bottom: 0px`
3548
+ }
3549
+ },
3550
+ /* @__PURE__ */ React11.createElement(
3551
+ "div",
3552
+ {
3553
+ className: "absolute top-0 left-1/2 -translate-x-1/2 w-1/3 h-2.5 rounded-b-lg",
3554
+ style: { backgroundColor: "rgba(0,0,0,0.4)" }
3555
+ }
3556
+ ),
3557
+ /* @__PURE__ */ React11.createElement("div", { className: "flex justify-between items-center mb-2 mt-1 px-1" }, /* @__PURE__ */ React11.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React11.createElement(
3558
+ "div",
3559
+ {
3560
+ className: "w-2 h-2 rounded-full",
3561
+ style: {
3562
+ backgroundColor: address ? "#22c55e" : "#ef4444",
3563
+ animation: "pulse 2s ease-in-out infinite"
3564
+ }
3565
+ }
3566
+ ), /* @__PURE__ */ React11.createElement(
3567
+ "span",
3568
+ {
3569
+ className: "text-xs font-mono font-bold tracking-wider",
3570
+ style: { color: "rgba(0,0,0,0.7)" }
3571
+ },
3572
+ getStatusText()
3573
+ )), /* @__PURE__ */ React11.createElement("div", { className: "flex items-center gap-1.5" }, paymentDetails && NetworkIcon && /* @__PURE__ */ React11.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React11.createElement(NetworkIcon, { width: 12, height: 12, style: { color: "rgba(0,0,0,0.7)" } }), /* @__PURE__ */ React11.createElement("span", { className: "text-xs font-mono font-bold", style: { color: "rgba(0,0,0,0.7)" } }, paymentDetails.network)))),
3574
+ /* @__PURE__ */ React11.createElement(
3575
+ TerminalScreen,
3576
+ {
3577
+ title,
3578
+ tooltipText,
3579
+ hasInvalidCheckoutId,
3580
+ fetchingPaymentInfo,
3581
+ address,
3582
+ paymentDetails,
3583
+ screenText,
3584
+ supportedNetworks
3585
+ }
3586
+ ),
3587
+ /* @__PURE__ */ React11.createElement(
3588
+ TerminalButtons,
3589
+ {
3590
+ address,
3591
+ showReceipt,
3592
+ isProcessing,
3593
+ paymentDetails,
3594
+ hasInvalidCheckoutId,
3595
+ onDisconnect: handleDisconnect,
3596
+ onClearReceipt: handleCloseReceipt,
3597
+ onPayment: handlePayment
3598
+ }
3599
+ ),
3600
+ brandName && /* @__PURE__ */ React11.createElement("div", { className: "text-center mt-0 mb-0" }, /* @__PURE__ */ React11.createElement(
3601
+ "div",
3602
+ {
3603
+ className: "inline-block px-2 py-0.5 rounded text-[10px] font-mono font-bold tracking-[0.2em]",
3604
+ style: {
3605
+ backgroundColor: "#1a1a1a",
3606
+ color: "#9acd32",
3607
+ boxShadow: "inset 0 1px 3px rgba(0,0,0,0.8), 0 1px 0 rgba(255,255,255,0.1)",
3608
+ border: "1px solid rgba(0,0,0,0.5)",
3609
+ textShadow: "0 0 4px #9acd3280"
3610
+ }
3611
+ },
3612
+ brandName
3613
+ ))
3614
+ )
3615
+ ), /* @__PURE__ */ React11.createElement(AnimationStyles, null));
3616
+ }
2216
3617
  export {
3618
+ AnimationStyles,
3619
+ Toast,
2217
3620
  V402Checkout,
3621
+ V402CheckoutV2,
2218
3622
  WalletConnect,
3623
+ WalletSelectModal,
3624
+ checkoutAnimations,
2219
3625
  usePageNetwork,
2220
3626
  usePayment,
2221
3627
  usePaymentInfo,
3628
+ useToast,
2222
3629
  useWallet
2223
3630
  };
2224
3631
  //# sourceMappingURL=index.mjs.map