@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.
@@ -98,6 +98,28 @@ var init_types = __esm({
98
98
  });
99
99
 
100
100
  // src/utils/wallet.ts
101
+ var wallet_exports = {};
102
+ __export(wallet_exports, {
103
+ clearAllWalletAddresses: () => clearAllWalletAddresses,
104
+ clearWalletDisconnection: () => clearWalletDisconnection,
105
+ formatAddress: () => formatAddress,
106
+ getAllConnectedWalletIds: () => getAllConnectedWalletIds,
107
+ getAllWalletAddresses: () => getAllWalletAddresses,
108
+ getCachedWalletAddress: () => getCachedWalletAddress,
109
+ getConnectedNetworkType: () => getConnectedNetworkType,
110
+ getConnectedWalletId: () => getConnectedWalletId,
111
+ getWalletDisplayName: () => getWalletDisplayName,
112
+ getWalletInstallUrl: () => getWalletInstallUrl,
113
+ getWalletProvider: () => getWalletProvider,
114
+ isWalletInstalled: () => isWalletInstalled,
115
+ isWalletManuallyDisconnected: () => isWalletManuallyDisconnected,
116
+ markWalletDisconnected: () => markWalletDisconnected,
117
+ removeConnectedWalletId: () => removeConnectedWalletId,
118
+ removeWalletAddress: () => removeWalletAddress,
119
+ saveConnectedNetworkType: () => saveConnectedNetworkType,
120
+ saveConnectedWalletId: () => saveConnectedWalletId,
121
+ saveWalletAddress: () => saveWalletAddress
122
+ });
101
123
  function isWalletInstalled(networkType) {
102
124
  if (typeof window === "undefined") {
103
125
  return false;
@@ -112,6 +134,20 @@ function isWalletInstalled(networkType) {
112
134
  return false;
113
135
  }
114
136
  }
137
+ function getWalletProvider(networkType) {
138
+ if (typeof window === "undefined") {
139
+ return null;
140
+ }
141
+ switch (networkType) {
142
+ case "evm" /* EVM */:
143
+ return window.ethereum;
144
+ case "solana" /* SOLANA */:
145
+ case "svm" /* SVM */:
146
+ return window.solana || window.phantom;
147
+ default:
148
+ return null;
149
+ }
150
+ }
115
151
  function formatAddress(address) {
116
152
  if (!address || address.length < 10) {
117
153
  return address;
@@ -186,6 +222,17 @@ function getWalletInstallUrl(networkType) {
186
222
  return "#";
187
223
  }
188
224
  }
225
+ function getWalletDisplayName(networkType) {
226
+ switch (networkType) {
227
+ case "evm" /* EVM */:
228
+ return "MetaMask";
229
+ case "solana" /* SOLANA */:
230
+ case "svm" /* SVM */:
231
+ return "Phantom";
232
+ default:
233
+ return "Unknown Wallet";
234
+ }
235
+ }
189
236
  function getAllWalletAddresses() {
190
237
  if (typeof window === "undefined") {
191
238
  return {};
@@ -218,7 +265,44 @@ function removeWalletAddress(networkType) {
218
265
  delete addresses[networkType];
219
266
  localStorage.setItem(WALLET_ADDRESSES_KEY, JSON.stringify(addresses));
220
267
  }
221
- var WALLET_DISCONNECTED_KEY, WALLET_DISCONNECTED_NETWORKS_KEY, CONNECTED_NETWORK_TYPE_KEY, WALLET_ADDRESSES_KEY;
268
+ function clearAllWalletAddresses() {
269
+ if (typeof window !== "undefined") {
270
+ localStorage.removeItem(WALLET_ADDRESSES_KEY);
271
+ }
272
+ }
273
+ function getAllConnectedWalletIds() {
274
+ if (typeof window === "undefined") {
275
+ return {};
276
+ }
277
+ try {
278
+ const cached = localStorage.getItem(CONNECTED_WALLET_IDS_KEY);
279
+ return cached ? JSON.parse(cached) : {};
280
+ } catch (error) {
281
+ console.error("Failed to parse connected wallet IDs:", error);
282
+ return {};
283
+ }
284
+ }
285
+ function saveConnectedWalletId(networkType, walletId) {
286
+ if (typeof window === "undefined") {
287
+ return;
288
+ }
289
+ const walletIds = getAllConnectedWalletIds();
290
+ walletIds[networkType] = walletId;
291
+ localStorage.setItem(CONNECTED_WALLET_IDS_KEY, JSON.stringify(walletIds));
292
+ }
293
+ function getConnectedWalletId(networkType) {
294
+ const walletIds = getAllConnectedWalletIds();
295
+ return walletIds[networkType] || null;
296
+ }
297
+ function removeConnectedWalletId(networkType) {
298
+ if (typeof window === "undefined") {
299
+ return;
300
+ }
301
+ const walletIds = getAllConnectedWalletIds();
302
+ delete walletIds[networkType];
303
+ localStorage.setItem(CONNECTED_WALLET_IDS_KEY, JSON.stringify(walletIds));
304
+ }
305
+ var WALLET_DISCONNECTED_KEY, WALLET_DISCONNECTED_NETWORKS_KEY, CONNECTED_NETWORK_TYPE_KEY, WALLET_ADDRESSES_KEY, CONNECTED_WALLET_IDS_KEY;
222
306
  var init_wallet = __esm({
223
307
  "src/utils/wallet.ts"() {
224
308
  "use strict";
@@ -226,17 +310,24 @@ var init_wallet = __esm({
226
310
  WALLET_DISCONNECTED_NETWORKS_KEY = "wallet_disconnected_networks";
227
311
  CONNECTED_NETWORK_TYPE_KEY = "connected_network_type";
228
312
  WALLET_ADDRESSES_KEY = "wallet_addresses_cache";
313
+ CONNECTED_WALLET_IDS_KEY = "connected_wallet_ids";
229
314
  }
230
315
  });
231
316
 
232
317
  // src/react/index.ts
233
318
  var index_exports = {};
234
319
  __export(index_exports, {
320
+ AnimationStyles: () => AnimationStyles,
321
+ Toast: () => Toast,
235
322
  V402Checkout: () => V402Checkout,
323
+ V402CheckoutV2: () => V402CheckoutV2,
236
324
  WalletConnect: () => WalletConnect,
325
+ WalletSelectModal: () => WalletSelectModal,
326
+ checkoutAnimations: () => checkoutAnimations,
237
327
  usePageNetwork: () => usePageNetwork,
238
328
  usePayment: () => usePayment,
239
329
  usePaymentInfo: () => usePaymentInfo,
330
+ useToast: () => useToast,
240
331
  useWallet: () => useWallet
241
332
  });
242
333
  module.exports = __toCommonJS(index_exports);
@@ -250,45 +341,143 @@ init_wallet();
250
341
 
251
342
  // src/utils/wallet-connect.ts
252
343
  init_wallet();
253
- async function connectWallet(networkType) {
344
+ async function connectWallet(networkType, forceSelect = false) {
254
345
  if (typeof window === "undefined") {
255
- throw new Error("\u8BF7\u5728\u6D4F\u89C8\u5668\u73AF\u5883\u4E2D\u4F7F\u7528");
346
+ throw new Error("Please use in browser environment");
256
347
  }
257
348
  let address;
258
349
  switch (networkType) {
259
350
  case "evm" /* EVM */: {
260
351
  if (!window.ethereum) {
261
- throw new Error("\u8BF7\u5B89\u88C5 MetaMask \u6216\u5176\u4ED6\u4EE5\u592A\u574A\u94B1\u5305");
352
+ throw new Error("Please install MetaMask or another Ethereum wallet");
262
353
  }
263
354
  const ethereum = window.ethereum;
355
+ if (forceSelect) {
356
+ try {
357
+ const permissions = await ethereum.request({
358
+ method: "wallet_requestPermissions",
359
+ params: [{ eth_accounts: {} }]
360
+ });
361
+ const accountsPermission = permissions?.find(
362
+ (p) => p.parentCapability === "eth_accounts"
363
+ );
364
+ if (accountsPermission?.caveats?.[0]?.value?.length > 0) {
365
+ address = accountsPermission.caveats[0].value[0];
366
+ break;
367
+ }
368
+ } catch (err) {
369
+ if (err.code === 4001) {
370
+ throw new Error("User cancelled wallet connection");
371
+ }
372
+ console.warn("wallet_requestPermissions failed, falling back to eth_requestAccounts");
373
+ }
374
+ }
264
375
  const accounts = await ethereum.request({
265
376
  method: "eth_requestAccounts",
266
377
  params: []
267
378
  });
268
379
  if (!accounts || accounts.length === 0) {
269
- throw new Error("\u672A\u80FD\u83B7\u53D6\u5230\u94B1\u5305\u5730\u5740");
380
+ throw new Error("Failed to get wallet address");
270
381
  }
271
382
  address = accounts[0];
272
383
  break;
273
384
  }
274
385
  case "solana" /* SOLANA */:
275
386
  case "svm" /* SVM */: {
276
- const solana = window.solana;
387
+ const phantom = window.phantom?.solana || window.solana;
388
+ const solflare = window.solflare;
389
+ let solana = phantom;
390
+ if (!solana && solflare?.isSolflare) {
391
+ solana = solflare;
392
+ }
277
393
  if (!solana) {
278
- throw new Error("\u8BF7\u5B89\u88C5 Phantom \u6216\u5176\u4ED6 Solana \u94B1\u5305");
394
+ throw new Error("Please install Phantom or another Solana wallet");
395
+ }
396
+ if (forceSelect) {
397
+ try {
398
+ if (phantom?.isConnected) {
399
+ await phantom.disconnect();
400
+ }
401
+ if (solflare?.isConnected) {
402
+ await solflare.disconnect();
403
+ }
404
+ await new Promise((resolve) => setTimeout(resolve, 100));
405
+ } catch (err) {
406
+ console.warn("Failed to disconnect Solana wallet:", err);
407
+ }
408
+ } else if (solana.isConnected) {
409
+ try {
410
+ await solana.disconnect();
411
+ } catch (err) {
412
+ console.warn("Failed to disconnect Solana wallet:", err);
413
+ }
279
414
  }
280
415
  const response = await solana.connect();
281
416
  address = response.publicKey.toString();
282
417
  break;
283
418
  }
284
419
  default:
285
- throw new Error("\u4E0D\u652F\u6301\u7684\u7F51\u7EDC\u7C7B\u578B");
420
+ throw new Error("Unsupported network type");
286
421
  }
287
422
  clearWalletDisconnection(networkType);
288
423
  saveConnectedNetworkType(networkType);
289
424
  saveWalletAddress(networkType, address);
290
425
  return address;
291
426
  }
427
+ async function disconnectAllSolanaWallets() {
428
+ if (typeof window === "undefined") return;
429
+ const phantom = window.phantom?.solana || window.solana;
430
+ const solflare = window.solflare;
431
+ const disconnectPromises = [];
432
+ if (phantom?.isConnected) {
433
+ disconnectPromises.push(
434
+ phantom.disconnect().catch(
435
+ (err) => console.warn("Failed to disconnect Phantom:", err)
436
+ )
437
+ );
438
+ }
439
+ if (solflare?.isConnected) {
440
+ disconnectPromises.push(
441
+ solflare.disconnect().catch(
442
+ (err) => console.warn("Failed to disconnect Solflare:", err)
443
+ )
444
+ );
445
+ }
446
+ await Promise.all(disconnectPromises);
447
+ }
448
+ async function disconnectWallet(networkType, clearAll = false) {
449
+ const targetNetwork = networkType || getConnectedNetworkType();
450
+ if (targetNetwork && typeof window !== "undefined") {
451
+ try {
452
+ switch (targetNetwork) {
453
+ case "solana" /* SOLANA */:
454
+ case "svm" /* SVM */: {
455
+ await disconnectAllSolanaWallets();
456
+ break;
457
+ }
458
+ // EVM wallets (like MetaMask) don't have a real disconnect API
459
+ // Only clear local state, will request permissions again on next connection
460
+ case "evm" /* EVM */:
461
+ default:
462
+ break;
463
+ }
464
+ } catch (err) {
465
+ console.warn("Failed to disconnect wallet:", err);
466
+ }
467
+ }
468
+ if (clearAll) {
469
+ const { clearAllWalletAddresses: clearAllWalletAddresses2 } = (init_wallet(), __toCommonJS(wallet_exports));
470
+ clearAllWalletAddresses2();
471
+ markWalletDisconnected();
472
+ await disconnectAllSolanaWallets();
473
+ } else if (networkType) {
474
+ removeWalletAddress(networkType);
475
+ } else {
476
+ if (targetNetwork) {
477
+ removeWalletAddress(targetNetwork);
478
+ }
479
+ }
480
+ }
292
481
  async function getCurrentWallet(networkType) {
293
482
  if (typeof window === "undefined") {
294
483
  return null;
@@ -298,36 +487,32 @@ async function getCurrentWallet(networkType) {
298
487
  return null;
299
488
  }
300
489
  const cachedAddress = getCachedWalletAddress(type);
301
- try {
302
- let currentAddress = null;
303
- switch (type) {
304
- case "evm" /* EVM */: {
305
- if (!window.ethereum) return cachedAddress;
490
+ if (type === "evm" /* EVM */) {
491
+ if (cachedAddress) {
492
+ return cachedAddress;
493
+ }
494
+ if (window.ethereum) {
495
+ try {
306
496
  const accounts = await window.ethereum.request({
307
497
  method: "eth_accounts",
308
498
  params: []
309
499
  });
310
- currentAddress = accounts && accounts.length > 0 ? accounts[0] : null;
311
- break;
312
- }
313
- case "solana" /* SOLANA */:
314
- case "svm" /* SVM */: {
315
- const solana = window.solana;
316
- if (!solana || !solana.isConnected) return cachedAddress;
317
- currentAddress = solana.publicKey?.toString() || null;
318
- break;
500
+ return accounts && accounts.length > 0 ? accounts[0] : null;
501
+ } catch (error) {
502
+ console.error("Failed to get EVM accounts:", error);
503
+ return null;
319
504
  }
320
- default:
321
- return cachedAddress;
322
505
  }
323
- if (currentAddress && currentAddress !== cachedAddress) {
324
- saveWalletAddress(type, currentAddress);
506
+ return null;
507
+ }
508
+ if (type === "solana" /* SOLANA */ || type === "svm" /* SVM */) {
509
+ const solana = window.solana;
510
+ if (!solana || !solana.isConnected) {
511
+ return cachedAddress;
325
512
  }
326
- return currentAddress || cachedAddress;
327
- } catch (error) {
328
- console.error("Failed to get current wallet:", error);
329
- return cachedAddress;
513
+ return solana.publicKey?.toString() || cachedAddress;
330
514
  }
515
+ return cachedAddress;
331
516
  }
332
517
  function onAccountsChanged(callback) {
333
518
  if (typeof window === "undefined" || !window.ethereum) {
@@ -390,12 +575,251 @@ async function switchNetwork(networkType) {
390
575
  return null;
391
576
  }
392
577
 
578
+ // src/utils/wallet-discovery.ts
579
+ init_wallet();
580
+ var SOLANA_WALLETS = [
581
+ {
582
+ id: "phantom",
583
+ name: "Phantom",
584
+ // Phantom official icon
585
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiNBQjlGRjIiLz4KPHBhdGggZD0iTTExMC41IDY0QzExMC41IDg5Ljk1NjggODkuMjAxIDExMSA2My41IDExMUg0MS41QzM2LjI1MzMgMTExIDMyIDEwNi43NDcgMzIgMTAxLjVWNTQuNUMzMiAzMS4wMjggNTEuMDI4IDEyIDc0LjUgMTJDOTcuOTcyIDEyIDExNyAzMS4wMjggMTE3IDU0LjVWNTUuNUMxMTcgNTguNTM3NiAxMTQuNTM4IDYxIDExMS41IDYxSDEwOS41QzEwNi40NjIgNjEgMTA0IDYzLjQ2MjQgMTA0IDY2LjVWNjhDMTA0IDcxLjg2NiAxMDcuMTM0IDc1IDExMSA3NUgxMTEuNUMxMTQuNTM4IDc1IDExNyA3Mi41Mzc2IDExNyA2OS41VjY0SDExMC41WiIgZmlsbD0idXJsKCNwYWludDBfbGluZWFyXzEyOF8xMjgpIi8+CjxwYXRoIGQ9Ik00OC41IDY3QzUxLjUzNzYgNjcgNTQgNjQuNTM3NiA1NCA2MS41QzU0IDU4LjQ2MjQgNTEuNTM3NiA1NiA0OC41IDU2QzQ1LjQ2MjQgNTYgNDMgNTguNDYyNCA0MyA2MS41QzQzIDY0LjUzNzYgNDUuNDYyNCA2NyA0OC41IDY3WiIgZmlsbD0iIzFCMUIxQiIvPgo8cGF0aCBkPSJNNzMuNSA2N0M3Ni41Mzc2IDY3IDc5IDY0LjUzNzYgNzkgNjEuNUM3OSA1OC40NjI0IDc2LjUzNzYgNTYgNzMuNSA1NkM3MC40NjI0IDU2IDY4IDU4LjQ2MjQgNjggNjEuNUM2OCA2NC41Mzc2IDcwLjQ2MjQgNjcgNzMuNSA2N1oiIGZpbGw9IiMxQjFCMUIiLz4KPGRlZnM+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQwX2xpbmVhcl8xMjhfMTI4IiB4MT0iMTE3IiB5MT0iMTIiIHgyPSIxMTciIHkyPSIxMTEiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0ZGRkZGRiIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNGRkZGRkYiIHN0b3Atb3BhY2l0eT0iMC44MiIvPgo8L2xpbmVhckdyYWRpZW50Pgo8L2RlZnM+Cjwvc3ZnPg==",
586
+ detect: () => window.phantom?.solana
587
+ },
588
+ {
589
+ id: "solflare",
590
+ name: "Solflare",
591
+ // Solflare icon
592
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiNGQzZEMDEiLz4KPHBhdGggZD0iTTk2IDY0TDY0IDMyTDMyIDY0TDY0IDk2TDk2IDY0WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+",
593
+ detect: () => window.solflare
594
+ },
595
+ {
596
+ id: "backpack",
597
+ name: "Backpack",
598
+ // Backpack icon (red coral color)
599
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiNFMzM0MzAiLz4KPHBhdGggZD0iTTQwIDQ4SDg4VjgwQzg4IDg4LjgzNjYgODAuODM2NiA5NiA3MiA5Nkg1NkM0Ny4xNjM0IDk2IDQwIDg4LjgzNjYgNDAgODBWNDhaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNNTIgMzJINzZWNDhINTJWMzJaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4=",
600
+ detect: () => window.backpack
601
+ },
602
+ {
603
+ id: "okx-solana",
604
+ name: "OKX Wallet",
605
+ // OKX icon
606
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9ImJsYWNrIi8+CjxyZWN0IHg9IjI0IiB5PSIyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0id2hpdGUiLz4KPHJlY3QgeD0iNTIiIHk9IjI0IiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSJ3aGl0ZSIvPgo8cmVjdCB4PSI4MCIgeT0iMjQiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgcng9IjQiIGZpbGw9IndoaXRlIi8+CjxyZWN0IHg9IjI0IiB5PSI1MiIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0id2hpdGUiLz4KPHJlY3QgeD0iODAiIHk9IjUyIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSJ3aGl0ZSIvPgo8cmVjdCB4PSIyNCIgeT0iODAiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgcng9IjQiIGZpbGw9IndoaXRlIi8+CjxyZWN0IHg9IjUyIiB5PSI4MCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0id2hpdGUiLz4KPHJlY3QgeD0iODAiIHk9IjgwIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4=",
607
+ detect: () => window.okxwallet?.solana
608
+ },
609
+ {
610
+ id: "coinbase-solana",
611
+ name: "Coinbase Wallet",
612
+ // Coinbase icon (blue)
613
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiMwMDUyRkYiLz4KPGNpcmNsZSBjeD0iNjQiIGN5PSI2NCIgcj0iMzYiIGZpbGw9IndoaXRlIi8+CjxyZWN0IHg9IjQ4IiB5PSI1NiIgd2lkdGg9IjMyIiBoZWlnaHQ9IjE2IiByeD0iNCIgZmlsbD0iIzAwNTJGRiIvPgo8L3N2Zz4=",
614
+ detect: () => window.coinbaseSolana
615
+ },
616
+ {
617
+ id: "trust-solana",
618
+ name: "Trust Wallet",
619
+ // Trust Wallet icon
620
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiMwNTAwRkYiLz4KPHBhdGggZD0iTTY0IDI0QzY0IDI0IDk2IDQwIDk2IDY0Qzk2IDg4IDY0IDEwNCA2NCAxMDRDNjQgMTA0IDMyIDg4IDMyIDY0QzMyIDQwIDY0IDI0IDY0IDI0WiIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSI2IiBmaWxsPSJub25lIi8+Cjwvc3ZnPg==",
621
+ detect: () => window.trustwallet?.solana
622
+ }
623
+ ];
624
+ var evmWallets = /* @__PURE__ */ new Map();
625
+ var evmDiscoveryListeners = /* @__PURE__ */ new Set();
626
+ var evmDiscoveryInitialized = false;
627
+ var currentConnectedWallet = null;
628
+ function initEVMWalletDiscovery() {
629
+ if (typeof window === "undefined" || evmDiscoveryInitialized) return;
630
+ evmDiscoveryInitialized = true;
631
+ window.addEventListener("eip6963:announceProvider", ((event) => {
632
+ const { info, provider } = event.detail;
633
+ evmWallets.set(info.uuid, { info, provider });
634
+ evmDiscoveryListeners.forEach((listener) => listener());
635
+ }));
636
+ window.dispatchEvent(new Event("eip6963:requestProvider"));
637
+ }
638
+ function getEVMWallets() {
639
+ const wallets = [];
640
+ const detectedNames = /* @__PURE__ */ new Set();
641
+ evmWallets.forEach((detail, uuid) => {
642
+ if (!detectedNames.has(detail.info.name)) {
643
+ wallets.push({
644
+ id: uuid,
645
+ name: detail.info.name,
646
+ icon: detail.info.icon,
647
+ networkType: "evm" /* EVM */,
648
+ provider: detail.provider,
649
+ installed: true
650
+ });
651
+ detectedNames.add(detail.info.name);
652
+ }
653
+ });
654
+ if (wallets.length === 0 && typeof window !== "undefined" && window.ethereum) {
655
+ const ethereum = window.ethereum;
656
+ const walletName = ethereum.isMetaMask ? "MetaMask" : ethereum.isCoinbaseWallet ? "Coinbase Wallet" : ethereum.isOkxWallet ? "OKX Wallet" : "Browser Wallet";
657
+ if (!detectedNames.has(walletName)) {
658
+ wallets.push({
659
+ id: "injected",
660
+ name: walletName,
661
+ icon: "",
662
+ // Will use first letter as avatar
663
+ networkType: "evm" /* EVM */,
664
+ provider: ethereum,
665
+ installed: true
666
+ });
667
+ }
668
+ }
669
+ return wallets;
670
+ }
671
+ function onEVMWalletsChanged(callback) {
672
+ evmDiscoveryListeners.add(callback);
673
+ return () => {
674
+ evmDiscoveryListeners.delete(callback);
675
+ };
676
+ }
677
+ function getSolanaWallets() {
678
+ if (typeof window === "undefined") return [];
679
+ const wallets = [];
680
+ const detectedProviders = /* @__PURE__ */ new Set();
681
+ const detectedNames = /* @__PURE__ */ new Set();
682
+ for (const wallet of SOLANA_WALLETS) {
683
+ const provider = wallet.detect();
684
+ if (provider && !detectedNames.has(wallet.name)) {
685
+ wallets.push({
686
+ id: wallet.id,
687
+ name: wallet.name,
688
+ icon: wallet.icon,
689
+ networkType: "solana" /* SOLANA */,
690
+ provider,
691
+ installed: true
692
+ });
693
+ detectedProviders.add(provider);
694
+ detectedNames.add(wallet.name);
695
+ }
696
+ }
697
+ const windowSolana = window.solana;
698
+ if (windowSolana && !detectedProviders.has(windowSolana)) {
699
+ const walletName = windowSolana.isPhantom ? "Phantom" : windowSolana.isSolflare ? "Solflare" : windowSolana.isBackpack ? "Backpack" : windowSolana.walletName || "Solana Wallet";
700
+ if (!detectedNames.has(walletName)) {
701
+ wallets.push({
702
+ id: "solana-unknown",
703
+ name: walletName,
704
+ icon: "",
705
+ // Will use first letter as avatar
706
+ networkType: "solana" /* SOLANA */,
707
+ provider: windowSolana,
708
+ installed: true
709
+ });
710
+ }
711
+ }
712
+ return wallets;
713
+ }
714
+ function getWalletsForNetwork(networkType) {
715
+ switch (networkType) {
716
+ case "evm" /* EVM */:
717
+ return getEVMWallets();
718
+ case "solana" /* SOLANA */:
719
+ case "svm" /* SVM */:
720
+ return getSolanaWallets();
721
+ default:
722
+ return [];
723
+ }
724
+ }
725
+ function getWalletByName(name, networkType) {
726
+ const wallets = getWalletsForNetwork(networkType);
727
+ return wallets.find((w) => w.name === name) || null;
728
+ }
729
+ async function connectEVMWallet(wallet) {
730
+ if (!wallet.provider) {
731
+ throw new Error(`Wallet ${wallet.name} is not available`);
732
+ }
733
+ const accounts = await wallet.provider.request({
734
+ method: "eth_requestAccounts",
735
+ params: []
736
+ });
737
+ if (!accounts || accounts.length === 0) {
738
+ throw new Error("Failed to get wallet address");
739
+ }
740
+ return accounts[0];
741
+ }
742
+ async function connectSolanaWallet(wallet) {
743
+ if (!wallet.provider) {
744
+ throw new Error(`Wallet ${wallet.name} is not available`);
745
+ }
746
+ if (wallet.provider.isConnected) {
747
+ try {
748
+ await wallet.provider.disconnect();
749
+ } catch (err) {
750
+ console.warn("Failed to disconnect before connecting:", err);
751
+ }
752
+ }
753
+ const response = await wallet.provider.connect();
754
+ return response.publicKey.toString();
755
+ }
756
+ async function connectToWallet(wallet) {
757
+ let address;
758
+ switch (wallet.networkType) {
759
+ case "evm" /* EVM */:
760
+ address = await connectEVMWallet(wallet);
761
+ break;
762
+ case "solana" /* SOLANA */:
763
+ case "svm" /* SVM */:
764
+ address = await connectSolanaWallet(wallet);
765
+ break;
766
+ default:
767
+ throw new Error("Unsupported network type");
768
+ }
769
+ currentConnectedWallet = wallet;
770
+ saveConnectedWalletId(wallet.networkType, wallet.name);
771
+ return address;
772
+ }
773
+ function setCurrentConnectedWallet(wallet) {
774
+ currentConnectedWallet = wallet;
775
+ }
776
+ function clearConnectedWallet(networkType) {
777
+ if (networkType) {
778
+ removeConnectedWalletId(networkType);
779
+ }
780
+ currentConnectedWallet = null;
781
+ }
782
+ function restoreConnectedWallet(networkType) {
783
+ const savedWalletName = getConnectedWalletId(networkType);
784
+ if (!savedWalletName) return null;
785
+ const wallet = getWalletByName(savedWalletName, networkType);
786
+ if (wallet) {
787
+ currentConnectedWallet = wallet;
788
+ console.log(`\u2705 Restored wallet provider: ${wallet.name}`);
789
+ return wallet;
790
+ }
791
+ console.warn(`\u26A0\uFE0F Could not find wallet with name: ${savedWalletName}`);
792
+ return null;
793
+ }
794
+ function getWalletProviderForPayment(networkType) {
795
+ if (currentConnectedWallet && currentConnectedWallet.networkType === networkType) {
796
+ return currentConnectedWallet.provider;
797
+ }
798
+ const restoredWallet = restoreConnectedWallet(networkType);
799
+ if (restoredWallet) {
800
+ return restoredWallet.provider;
801
+ }
802
+ if (typeof window === "undefined") return null;
803
+ switch (networkType) {
804
+ case "evm" /* EVM */:
805
+ return window.ethereum;
806
+ case "solana" /* SOLANA */:
807
+ case "svm" /* SVM */:
808
+ return window.phantom?.solana || window.solana;
809
+ default:
810
+ return null;
811
+ }
812
+ }
813
+ if (typeof window !== "undefined") {
814
+ initEVMWalletDiscovery();
815
+ }
816
+
393
817
  // src/services/svm/payment-header.ts
394
818
  var import_web3 = require("@solana/web3.js");
395
819
  var import_spl_token = require("@solana/spl-token");
396
820
  async function createSvmPaymentHeader(params) {
397
821
  const { wallet, paymentRequirements, x402Version, rpcUrl } = params;
398
- const connection = new import_web3.Connection(rpcUrl, "confirmed");
822
+ const connection = new import_web3.Connection(rpcUrl);
399
823
  const feePayer = paymentRequirements?.extra?.feePayer;
400
824
  if (typeof feePayer !== "string" || !feePayer) {
401
825
  throw new Error("Missing facilitator feePayer in payment requirements (extra.feePayer).");
@@ -409,83 +833,85 @@ async function createSvmPaymentHeader(params) {
409
833
  if (!paymentRequirements?.payTo) {
410
834
  throw new Error("Missing payTo in payment requirements");
411
835
  }
412
- const destination = new import_web3.PublicKey(paymentRequirements.payTo);
413
- const instructions = [];
414
- instructions.push(
415
- import_web3.ComputeBudgetProgram.setComputeUnitLimit({
416
- units: 7e3
417
- // Sufficient for SPL token transfer
418
- })
419
- );
420
- instructions.push(
421
- import_web3.ComputeBudgetProgram.setComputeUnitPrice({
422
- microLamports: 1
423
- // Minimal price
424
- })
425
- );
836
+ const destinationPubkey = new import_web3.PublicKey(paymentRequirements.payTo);
426
837
  if (!paymentRequirements.asset) {
427
838
  throw new Error("Missing token mint for SPL transfer");
428
839
  }
429
840
  const mintPubkey = new import_web3.PublicKey(paymentRequirements.asset);
430
- const mintInfo = await connection.getAccountInfo(mintPubkey, "confirmed");
431
- const programId = mintInfo?.owner?.toBase58() === import_spl_token.TOKEN_2022_PROGRAM_ID.toBase58() ? import_spl_token.TOKEN_2022_PROGRAM_ID : import_spl_token.TOKEN_PROGRAM_ID;
432
- const mint = await (0, import_spl_token.getMint)(connection, mintPubkey, void 0, programId);
433
- const sourceAta = await (0, import_spl_token.getAssociatedTokenAddress)(
841
+ const mintAccountInfo = await connection.getAccountInfo(mintPubkey);
842
+ if (!mintAccountInfo) {
843
+ throw new Error(`Mint account ${mintPubkey.toBase58()} not found`);
844
+ }
845
+ const tokenProgramId = mintAccountInfo.owner.equals(import_spl_token.TOKEN_2022_PROGRAM_ID) ? import_spl_token.TOKEN_2022_PROGRAM_ID : import_spl_token.TOKEN_PROGRAM_ID;
846
+ const mint = await (0, import_spl_token.getMint)(connection, mintPubkey, void 0, tokenProgramId);
847
+ const sourceAta = (0, import_spl_token.getAssociatedTokenAddressSync)(
434
848
  mintPubkey,
435
849
  userPubkey,
436
850
  false,
437
- programId
851
+ tokenProgramId
438
852
  );
439
- const destinationAta = await (0, import_spl_token.getAssociatedTokenAddress)(
853
+ const destinationAta = (0, import_spl_token.getAssociatedTokenAddressSync)(
440
854
  mintPubkey,
441
- destination,
855
+ destinationPubkey,
442
856
  false,
443
- programId
857
+ tokenProgramId
444
858
  );
445
- const sourceAtaInfo = await connection.getAccountInfo(sourceAta, "confirmed");
859
+ const sourceAtaInfo = await connection.getAccountInfo(sourceAta);
446
860
  if (!sourceAtaInfo) {
447
861
  throw new Error(
448
862
  `User does not have an Associated Token Account for ${paymentRequirements.asset}. Please create one first or ensure you have the required token.`
449
863
  );
450
864
  }
451
- const destAtaInfo = await connection.getAccountInfo(destinationAta, "confirmed");
865
+ const destAtaInfo = await connection.getAccountInfo(destinationAta);
452
866
  if (!destAtaInfo) {
453
867
  throw new Error(
454
868
  `Destination does not have an Associated Token Account for ${paymentRequirements.asset}. The receiver must create their token account before receiving payments.`
455
869
  );
456
870
  }
457
- const amount = BigInt(paymentRequirements.maxAmountRequired);
458
- instructions.push(
871
+ const instructions = [
872
+ import_web3.ComputeBudgetProgram.setComputeUnitLimit({
873
+ units: 7e3
874
+ // Sufficient for SPL token transfer
875
+ }),
876
+ import_web3.ComputeBudgetProgram.setComputeUnitPrice({
877
+ microLamports: 1
878
+ // Minimal price
879
+ }),
459
880
  (0, import_spl_token.createTransferCheckedInstruction)(
460
881
  sourceAta,
461
882
  mintPubkey,
462
883
  destinationAta,
463
884
  userPubkey,
464
- amount,
885
+ BigInt(paymentRequirements.maxAmountRequired),
465
886
  mint.decimals,
466
887
  [],
467
- programId
888
+ tokenProgramId
468
889
  )
469
- );
470
- const { blockhash } = await connection.getLatestBlockhash("confirmed");
471
- const message2 = new import_web3.TransactionMessage({
890
+ ];
891
+ const { blockhash } = await connection.getLatestBlockhash();
892
+ const messageV0 = new import_web3.TransactionMessage({
472
893
  payerKey: feePayerPubkey,
473
894
  recentBlockhash: blockhash,
474
895
  instructions
475
896
  }).compileToV0Message();
476
- const transaction = new import_web3.VersionedTransaction(message2);
897
+ const transaction = new import_web3.VersionedTransaction(messageV0);
477
898
  if (typeof wallet?.signTransaction !== "function") {
478
899
  throw new Error("Connected wallet does not support signTransaction");
479
900
  }
480
- let userSignedTx;
901
+ let signedTransaction;
481
902
  try {
482
- userSignedTx = await wallet.signTransaction(transaction);
903
+ signedTransaction = await wallet.signTransaction(transaction);
483
904
  console.log("\u2705 Transaction signed successfully");
484
905
  } catch (error) {
485
906
  console.error("\u274C Failed to sign transaction:", error);
486
907
  throw wrapPaymentError(error);
487
908
  }
488
- const serializedTransaction = Buffer.from(userSignedTx.serialize()).toString("base64");
909
+ const serializedBytes = signedTransaction.serialize();
910
+ let binary = "";
911
+ for (let i = 0; i < serializedBytes.length; i++) {
912
+ binary += String.fromCharCode(serializedBytes[i]);
913
+ }
914
+ const serializedTransaction = btoa(binary);
489
915
  const paymentPayload = {
490
916
  x402Version,
491
917
  scheme: paymentRequirements.scheme,
@@ -494,7 +920,7 @@ async function createSvmPaymentHeader(params) {
494
920
  transaction: serializedTransaction
495
921
  }
496
922
  };
497
- const paymentHeader = Buffer.from(JSON.stringify(paymentPayload)).toString("base64");
923
+ const paymentHeader = btoa(JSON.stringify(paymentPayload));
498
924
  return paymentHeader;
499
925
  }
500
926
  function getDefaultSolanaRpcUrl(network) {
@@ -510,7 +936,7 @@ function getDefaultSolanaRpcUrl(network) {
510
936
  // src/services/svm/payment-handler.ts
511
937
  init_types();
512
938
  async function handleSvmPayment(endpoint, config, requestInit) {
513
- const { wallet, network, rpcUrl, maxPaymentAmount } = config;
939
+ const { wallet, rpcUrl, maxPaymentAmount } = config;
514
940
  const initialResponse = await fetch(endpoint, {
515
941
  ...requestInit,
516
942
  method: requestInit?.method || "POST"
@@ -519,26 +945,10 @@ async function handleSvmPayment(endpoint, config, requestInit) {
519
945
  return initialResponse;
520
946
  }
521
947
  const rawResponse = await initialResponse.json();
522
- const IGNORED_ERRORS = [
523
- "X-PAYMENT header is required",
524
- "missing X-PAYMENT header",
525
- "payment_required"
526
- ];
527
- if (rawResponse.error && !IGNORED_ERRORS.includes(rawResponse.error)) {
948
+ if (rawResponse.error && !IGNORED_402_ERRORS.includes(rawResponse.error)) {
528
949
  console.error(`\u274C Payment verification failed: ${rawResponse.error}`);
529
- const ERROR_MESSAGES = {
530
- "insufficient_funds": "Insufficient balance to complete this payment",
531
- "invalid_signature": "Invalid payment signature",
532
- "expired": "Payment authorization has expired",
533
- "already_used": "This payment has already been used",
534
- "network_mismatch": "Payment network does not match",
535
- "invalid_payment": "Invalid payment data",
536
- "verification_failed": "Payment verification failed",
537
- "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."
538
- };
539
- const errorMessage = ERROR_MESSAGES[rawResponse.error] || `Payment failed: ${rawResponse.error}`;
540
- const error = new Error(errorMessage);
541
- throw wrapPaymentError(error);
950
+ const errorMessage = PAYMENT_ERROR_MESSAGES[rawResponse.error] || `Payment failed: ${rawResponse.error}`;
951
+ throw wrapPaymentError(new Error(errorMessage));
542
952
  }
543
953
  const x402Version = rawResponse.x402Version;
544
954
  const parsedPaymentRequirements = rawResponse.accepts || [];
@@ -588,26 +998,10 @@ async function handleSvmPayment(endpoint, config, requestInit) {
588
998
  if (retryResponse.status === 402) {
589
999
  try {
590
1000
  const retryData = await retryResponse.json();
591
- const IGNORED_ERRORS2 = [
592
- "X-PAYMENT header is required",
593
- "missing X-PAYMENT header",
594
- "payment_required"
595
- ];
596
- if (retryData.error && !IGNORED_ERRORS2.includes(retryData.error)) {
1001
+ if (retryData.error && !IGNORED_402_ERRORS.includes(retryData.error)) {
597
1002
  console.error(`\u274C Payment verification failed: ${retryData.error}`);
598
- const ERROR_MESSAGES = {
599
- "insufficient_funds": "Insufficient balance to complete this payment",
600
- "invalid_signature": "Invalid payment signature",
601
- "expired": "Payment authorization has expired",
602
- "already_used": "This payment has already been used",
603
- "network_mismatch": "Payment network does not match",
604
- "invalid_payment": "Invalid payment data",
605
- "verification_failed": "Payment verification failed",
606
- "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."
607
- };
608
- const errorMessage = ERROR_MESSAGES[retryData.error] || `Payment failed: ${retryData.error}`;
609
- const error = new Error(errorMessage);
610
- throw wrapPaymentError(error);
1003
+ const errorMessage = PAYMENT_ERROR_MESSAGES[retryData.error] || `Payment failed: ${retryData.error}`;
1004
+ throw wrapPaymentError(new Error(errorMessage));
611
1005
  }
612
1006
  } catch (error) {
613
1007
  if (error instanceof PaymentOperationError) {
@@ -734,6 +1128,15 @@ function getChainIdFromNetwork(network) {
734
1128
 
735
1129
  // src/services/evm/payment-handler.ts
736
1130
  init_types();
1131
+ var NETWORK_NAMES = {
1132
+ 1: "Ethereum Mainnet",
1133
+ 11155111: "Sepolia Testnet",
1134
+ 8453: "Base Mainnet",
1135
+ 84532: "Base Sepolia Testnet",
1136
+ 137: "Polygon Mainnet",
1137
+ 42161: "Arbitrum One",
1138
+ 10: "Optimism Mainnet"
1139
+ };
737
1140
  async function handleEvmPayment(endpoint, config, requestInit) {
738
1141
  const { wallet, network, maxPaymentAmount } = config;
739
1142
  const initialResponse = await fetch(endpoint, {
@@ -744,25 +1147,10 @@ async function handleEvmPayment(endpoint, config, requestInit) {
744
1147
  return initialResponse;
745
1148
  }
746
1149
  const rawResponse = await initialResponse.json();
747
- const IGNORED_ERRORS = [
748
- "X-PAYMENT header is required",
749
- "missing X-PAYMENT header",
750
- "payment_required"
751
- ];
752
- if (rawResponse.error && !IGNORED_ERRORS.includes(rawResponse.error)) {
1150
+ if (rawResponse.error && !IGNORED_402_ERRORS.includes(rawResponse.error)) {
753
1151
  console.error(`\u274C Payment verification failed: ${rawResponse.error}`);
754
- const ERROR_MESSAGES = {
755
- "insufficient_funds": "Insufficient balance to complete this payment",
756
- "invalid_signature": "Invalid payment signature",
757
- "expired": "Payment authorization has expired",
758
- "already_used": "This payment has already been used",
759
- "network_mismatch": "Payment network does not match",
760
- "invalid_payment": "Invalid payment data",
761
- "verification_failed": "Payment verification failed"
762
- };
763
- const errorMessage = ERROR_MESSAGES[rawResponse.error] || `Payment failed: ${rawResponse.error}`;
764
- const error = new Error(errorMessage);
765
- throw wrapPaymentError(error);
1152
+ const errorMessage = PAYMENT_ERROR_MESSAGES[rawResponse.error] || `Payment failed: ${rawResponse.error}`;
1153
+ throw wrapPaymentError(new Error(errorMessage));
766
1154
  }
767
1155
  const x402Version = rawResponse.x402Version;
768
1156
  const parsedPaymentRequirements = rawResponse.accepts || [];
@@ -794,19 +1182,10 @@ async function handleEvmPayment(endpoint, config, requestInit) {
794
1182
  console.warn("\u26A0\uFE0F Failed to get current chainId:", error);
795
1183
  }
796
1184
  }
797
- const networkNames = {
798
- 1: "Ethereum Mainnet",
799
- 11155111: "Sepolia Testnet",
800
- 8453: "Base Mainnet",
801
- 84532: "Base Sepolia Testnet",
802
- 137: "Polygon Mainnet",
803
- 42161: "Arbitrum One",
804
- 10: "Optimism Mainnet"
805
- };
806
1185
  if (currentChainId && currentChainId !== targetChainId) {
807
1186
  if (!wallet.switchChain) {
808
- const currentNetworkName = networkNames[currentChainId] || `Chain ${currentChainId}`;
809
- const targetNetworkName = networkNames[targetChainId] || selectedRequirements.network;
1187
+ const currentNetworkName = NETWORK_NAMES[currentChainId] || `Chain ${currentChainId}`;
1188
+ const targetNetworkName = NETWORK_NAMES[targetChainId] || selectedRequirements.network;
810
1189
  const error = new Error(
811
1190
  `Network mismatch: Your wallet is connected to ${currentNetworkName}, but payment requires ${targetNetworkName}. Please switch to ${targetNetworkName} manually in your wallet.`
812
1191
  );
@@ -818,7 +1197,7 @@ async function handleEvmPayment(endpoint, config, requestInit) {
818
1197
  console.log(`\u2705 Successfully switched to chain ${targetChainId}`);
819
1198
  } catch (error) {
820
1199
  console.error("\u274C Failed to switch chain:", error);
821
- const targetNetworkName = networkNames[targetChainId] || selectedRequirements.network;
1200
+ const targetNetworkName = NETWORK_NAMES[targetChainId] || selectedRequirements.network;
822
1201
  const wrappedError = wrapPaymentError(error);
823
1202
  let finalError;
824
1203
  if (wrappedError.code === "USER_REJECTED" /* USER_REJECTED */) {
@@ -872,25 +1251,10 @@ async function handleEvmPayment(endpoint, config, requestInit) {
872
1251
  if (retryResponse.status === 402) {
873
1252
  try {
874
1253
  const retryData = await retryResponse.json();
875
- const IGNORED_ERRORS2 = [
876
- "X-PAYMENT header is required",
877
- "missing X-PAYMENT header",
878
- "payment_required"
879
- ];
880
- if (retryData.error && !IGNORED_ERRORS2.includes(retryData.error)) {
1254
+ if (retryData.error && !IGNORED_402_ERRORS.includes(retryData.error)) {
881
1255
  console.error(`\u274C Payment verification failed: ${retryData.error}`);
882
- const ERROR_MESSAGES = {
883
- "insufficient_funds": "Insufficient balance to complete this payment",
884
- "invalid_signature": "Invalid payment signature",
885
- "expired": "Payment authorization has expired",
886
- "already_used": "This payment has already been used",
887
- "network_mismatch": "Payment network does not match",
888
- "invalid_payment": "Invalid payment data",
889
- "verification_failed": "Payment verification failed"
890
- };
891
- const errorMessage = ERROR_MESSAGES[retryData.error] || `Payment failed: ${retryData.error}`;
892
- const error = new Error(errorMessage);
893
- throw wrapPaymentError(error);
1256
+ const errorMessage = PAYMENT_ERROR_MESSAGES[retryData.error] || `Payment failed: ${retryData.error}`;
1257
+ throw wrapPaymentError(new Error(errorMessage));
894
1258
  }
895
1259
  } catch (error) {
896
1260
  if (error instanceof PaymentOperationError) {
@@ -928,7 +1292,7 @@ function getSupportedNetworkTypes(paymentRequirements) {
928
1292
  });
929
1293
  return Array.from(networkTypes);
930
1294
  }
931
- async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, additionalParams) {
1295
+ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, additionalParams, expectedAddress) {
932
1296
  const fullEndpoint = `${endpoint}/${merchantId}`;
933
1297
  let response;
934
1298
  const requestInit = additionalParams && Object.keys(additionalParams).length > 0 ? {
@@ -938,26 +1302,41 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, ad
938
1302
  }
939
1303
  } : {};
940
1304
  if (networkType === "solana" /* SOLANA */ || networkType === "svm" /* SVM */) {
941
- const solana = window.solana;
1305
+ const solana = getWalletProviderForPayment(networkType);
942
1306
  if (!solana) {
943
- throw new Error("\u8BF7\u5B89\u88C5 Phantom \u94B1\u5305");
1307
+ throw new Error("Please connect your Solana wallet first.");
944
1308
  }
945
1309
  if (!solana.isConnected) {
946
1310
  await solana.connect();
947
1311
  }
1312
+ if (expectedAddress && solana.publicKey) {
1313
+ const currentAddress = solana.publicKey.toString();
1314
+ if (currentAddress !== expectedAddress) {
1315
+ throw new Error(
1316
+ `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.`
1317
+ );
1318
+ }
1319
+ }
948
1320
  response = await handleSvmPayment(fullEndpoint, {
949
1321
  wallet: solana,
950
1322
  network: "solana"
951
1323
  // Will use backend's network configuration
952
1324
  }, requestInit);
953
1325
  } else if (networkType === "evm" /* EVM */) {
954
- if (!window.ethereum) {
955
- throw new Error("\u8BF7\u5B89\u88C5 MetaMask \u94B1\u5305");
1326
+ const ethereum = getWalletProviderForPayment(networkType);
1327
+ if (!ethereum) {
1328
+ throw new Error("Please connect the EVM wallet first");
956
1329
  }
957
- const provider = new import_ethers2.ethers.BrowserProvider(window.ethereum);
1330
+ const provider = new import_ethers2.ethers.BrowserProvider(ethereum);
958
1331
  const signer = await provider.getSigner();
1332
+ const currentAddress = await signer.getAddress();
1333
+ if (expectedAddress && currentAddress.toLowerCase() !== expectedAddress.toLowerCase()) {
1334
+ throw new Error(
1335
+ `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.`
1336
+ );
1337
+ }
959
1338
  const wallet = {
960
- address: await signer.getAddress(),
1339
+ address: currentAddress,
961
1340
  signTypedData: async (domain, types, message2) => {
962
1341
  return await signer.signTypedData(domain, types, message2);
963
1342
  },
@@ -968,7 +1347,7 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, ad
968
1347
  },
969
1348
  // Switch to a different chain
970
1349
  switchChain: async (chainId) => {
971
- await window.ethereum.request({
1350
+ await ethereum.request({
972
1351
  method: "wallet_switchEthereumChain",
973
1352
  params: [{ chainId }]
974
1353
  });
@@ -980,7 +1359,7 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, ad
980
1359
  // Will use backend's network configuration
981
1360
  }, requestInit);
982
1361
  } else {
983
- throw new Error(`\u4E0D\u652F\u6301\u7684\u7F51\u7EDC\u7C7B\u578B: ${networkType}`);
1362
+ throw new Error(`Unsupported network types: ${networkType}`);
984
1363
  }
985
1364
  return response;
986
1365
  }
@@ -1023,6 +1402,21 @@ function getNetworkDisplayName(network) {
1023
1402
  }
1024
1403
 
1025
1404
  // src/utils/payment-error-handler.ts
1405
+ var IGNORED_402_ERRORS = [
1406
+ "X-PAYMENT header is required",
1407
+ "missing X-PAYMENT header",
1408
+ "payment_required"
1409
+ ];
1410
+ var PAYMENT_ERROR_MESSAGES = {
1411
+ "insufficient_funds": "Insufficient balance to complete this payment",
1412
+ "invalid_signature": "Invalid payment signature",
1413
+ "expired": "Payment authorization has expired",
1414
+ "already_used": "This payment has already been used",
1415
+ "network_mismatch": "Payment network does not match",
1416
+ "invalid_payment": "Invalid payment data",
1417
+ "verification_failed": "Payment verification failed",
1418
+ "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."
1419
+ };
1026
1420
  function parsePaymentError(error) {
1027
1421
  if (!error) {
1028
1422
  return {
@@ -1226,13 +1620,18 @@ var WalletStore = class {
1226
1620
  });
1227
1621
  }
1228
1622
  // Connect wallet
1229
- async connect(type) {
1623
+ // @param forceSelect - 强制弹出钱包选择界面,用于切换账户
1624
+ async connect(type, forceSelect = false) {
1230
1625
  if (this.state.address && this.state.networkType && this.state.networkType !== type) {
1231
1626
  saveWalletAddress(this.state.networkType, this.state.address);
1232
1627
  }
1233
1628
  this.setState({ isConnecting: true, error: null });
1234
1629
  try {
1235
- const walletAddress = await connectWallet(type);
1630
+ const walletAddress = await connectWallet(type, forceSelect);
1631
+ const wallets = getWalletsForNetwork(type);
1632
+ if (wallets.length > 0) {
1633
+ setCurrentConnectedWallet(wallets[0]);
1634
+ }
1236
1635
  this.setState({
1237
1636
  address: walletAddress,
1238
1637
  networkType: type,
@@ -1246,6 +1645,30 @@ var WalletStore = class {
1246
1645
  throw err;
1247
1646
  }
1248
1647
  }
1648
+ // Connect to a specific wallet (from wallet discovery)
1649
+ async connectWithWallet(wallet) {
1650
+ if (this.state.address && this.state.networkType && this.state.networkType !== wallet.networkType) {
1651
+ saveWalletAddress(this.state.networkType, this.state.address);
1652
+ }
1653
+ this.setState({ isConnecting: true, error: null });
1654
+ try {
1655
+ const walletAddress = await connectToWallet(wallet);
1656
+ clearWalletDisconnection(wallet.networkType);
1657
+ saveConnectedNetworkType(wallet.networkType);
1658
+ saveWalletAddress(wallet.networkType, walletAddress);
1659
+ this.setState({
1660
+ address: walletAddress,
1661
+ networkType: wallet.networkType,
1662
+ isConnecting: false
1663
+ });
1664
+ } catch (err) {
1665
+ this.setState({
1666
+ error: err.message || "Failed to connect wallet",
1667
+ isConnecting: false
1668
+ });
1669
+ throw err;
1670
+ }
1671
+ }
1249
1672
  // Switch network (use cached wallet if available)
1250
1673
  async switchNetwork(type) {
1251
1674
  if (this.state.address && this.state.networkType) {
@@ -1277,9 +1700,15 @@ var WalletStore = class {
1277
1700
  }
1278
1701
  }
1279
1702
  // Disconnect wallet
1280
- disconnect() {
1703
+ async disconnect() {
1281
1704
  const currentNetwork = this.state.networkType;
1705
+ clearConnectedWallet(currentNetwork || void 0);
1282
1706
  if (currentNetwork) {
1707
+ try {
1708
+ await disconnectWallet(currentNetwork);
1709
+ } catch (err) {
1710
+ console.warn("Failed to disconnect wallet provider:", err);
1711
+ }
1283
1712
  this.handleDisconnect(currentNetwork);
1284
1713
  } else {
1285
1714
  this.setState({
@@ -1323,7 +1752,8 @@ function useWallet() {
1323
1752
  );
1324
1753
  return {
1325
1754
  ...state,
1326
- connect: (type) => walletStore.connect(type),
1755
+ connect: (type, forceSelect) => walletStore.connect(type, forceSelect),
1756
+ connectWithWallet: (wallet) => walletStore.connectWithWallet(wallet),
1327
1757
  switchNetwork: (type) => walletStore.switchNetwork(type),
1328
1758
  ensureNetwork: (type) => walletStore.ensureNetwork(type),
1329
1759
  disconnect: () => walletStore.disconnect(),
@@ -1431,41 +1861,323 @@ function usePaymentInfo(merchantId, endpoint = PROD_BACK_URL, additionalParams)
1431
1861
  };
1432
1862
  }
1433
1863
 
1434
- // src/react/components/WalletConnect.tsx
1864
+ // src/react/hooks/useToast.tsx
1865
+ var import_react6 = __toESM(require("react"));
1866
+
1867
+ // src/react/components/ui/Toast.tsx
1435
1868
  var import_react5 = __toESM(require("react"));
1869
+ var import_react_dom = require("react-dom");
1870
+ var Toast = ({ message: message2, type, onClose }) => {
1871
+ (0, import_react5.useEffect)(() => {
1872
+ const timer = setTimeout(onClose, 3e3);
1873
+ return () => clearTimeout(timer);
1874
+ }, [onClose]);
1875
+ const bgColor = type === "success" ? "#22c55e" : type === "error" ? "#ef4444" : "#3b82f6";
1876
+ const icon = type === "success" ? "\u2713" : type === "error" ? "\u2717" : "\u2139";
1877
+ return (0, import_react_dom.createPortal)(
1878
+ /* @__PURE__ */ import_react5.default.createElement(
1879
+ "div",
1880
+ {
1881
+ className: "fixed top-4 right-4 z-[99999] animate-slide-in-right",
1882
+ style: {
1883
+ animation: "slideInRight 0.3s ease-out"
1884
+ }
1885
+ },
1886
+ /* @__PURE__ */ import_react5.default.createElement(
1887
+ "div",
1888
+ {
1889
+ className: "flex items-center gap-3 px-4 py-3 rounded-lg shadow-lg text-white font-mono text-sm",
1890
+ style: { backgroundColor: bgColor, minWidth: "280px" }
1891
+ },
1892
+ /* @__PURE__ */ import_react5.default.createElement("span", { className: "text-lg" }, icon),
1893
+ /* @__PURE__ */ import_react5.default.createElement("span", { className: "flex-1" }, message2),
1894
+ /* @__PURE__ */ import_react5.default.createElement(
1895
+ "button",
1896
+ {
1897
+ onClick: onClose,
1898
+ className: "text-white/80 hover:text-white transition-colors"
1899
+ },
1900
+ "\xD7"
1901
+ )
1902
+ )
1903
+ ),
1904
+ document.body
1905
+ );
1906
+ };
1436
1907
 
1437
- // src/react/styles/inline-styles.ts
1438
- var isDarkMode = () => {
1439
- if (typeof window === "undefined") return false;
1440
- return window.matchMedia?.("(prefers-color-scheme: dark)").matches ?? false;
1908
+ // src/react/hooks/useToast.tsx
1909
+ var useToast = () => {
1910
+ const [toasts, setToasts] = (0, import_react6.useState)([]);
1911
+ const toastIdRef = (0, import_react6.useRef)(0);
1912
+ const showToast = (0, import_react6.useCallback)((message2, type) => {
1913
+ const id = ++toastIdRef.current;
1914
+ setToasts((prev) => [...prev, { id, message: message2, type }]);
1915
+ }, []);
1916
+ const removeToast = (0, import_react6.useCallback)((id) => {
1917
+ setToasts((prev) => prev.filter((t) => t.id !== id));
1918
+ }, []);
1919
+ const ToastContainer = () => /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, toasts.map((toast, index) => /* @__PURE__ */ import_react6.default.createElement(
1920
+ "div",
1921
+ {
1922
+ key: toast.id,
1923
+ style: { top: `${16 + index * 60}px` },
1924
+ className: "fixed right-4 z-[99999]"
1925
+ },
1926
+ import_react6.default.createElement(Toast, {
1927
+ message: toast.message,
1928
+ type: toast.type,
1929
+ onClose: () => removeToast(toast.id)
1930
+ })
1931
+ )));
1932
+ return { showToast, ToastContainer };
1441
1933
  };
1442
- var colors = {
1443
- // Light mode
1444
- light: {
1445
- background: "#fafafa",
1446
- cardBg: "#ffffff",
1447
- text: "#0a0a0a",
1448
- textSecondary: "#737373",
1449
- primary: "#000000",
1450
- primaryHover: "#262626",
1451
- danger: "#ef4444",
1452
- dangerHover: "#dc2626",
1453
- success: "#10b981",
1454
- successHover: "#059669",
1455
- disabled: "#e5e5e5",
1456
- disabledText: "#a3a3a3",
1457
- errorBg: "#fef2f2",
1458
- errorText: "#dc2626"
1459
- },
1460
- // Dark mode
1461
- dark: {
1462
- background: "#0a0a0a",
1463
- cardBg: "#171717",
1464
- text: "#fafafa",
1465
- textSecondary: "#a3a3a3",
1466
- primary: "#ffffff",
1467
- primaryHover: "#e5e5e5",
1468
- danger: "#f87171",
1934
+
1935
+ // src/react/components/wallet/WalletConnect.tsx
1936
+ var import_react8 = __toESM(require("react"));
1937
+
1938
+ // src/react/components/wallet/WalletSelectModal.tsx
1939
+ var import_react7 = __toESM(require("react"));
1940
+ var import_react_dom2 = require("react-dom");
1941
+ var overlayStyle = {
1942
+ position: "fixed",
1943
+ top: 0,
1944
+ left: 0,
1945
+ right: 0,
1946
+ bottom: 0,
1947
+ backgroundColor: "rgba(0, 0, 0, 0.4)",
1948
+ display: "flex",
1949
+ alignItems: "center",
1950
+ justifyContent: "center",
1951
+ zIndex: 99999
1952
+ };
1953
+ var modalStyle = {
1954
+ backgroundColor: "#ffffff",
1955
+ borderRadius: "12px",
1956
+ padding: "16px",
1957
+ maxWidth: "320px",
1958
+ width: "90%",
1959
+ maxHeight: "70vh",
1960
+ overflow: "auto",
1961
+ boxShadow: "0 10px 25px rgba(0, 0, 0, 0.15)"
1962
+ };
1963
+ var headerStyle = {
1964
+ display: "flex",
1965
+ alignItems: "center",
1966
+ justifyContent: "space-between",
1967
+ marginBottom: "12px"
1968
+ };
1969
+ var titleStyle = {
1970
+ fontSize: "15px",
1971
+ fontWeight: 600,
1972
+ color: "#1a1a1a",
1973
+ margin: 0
1974
+ };
1975
+ var closeButtonStyle = {
1976
+ background: "none",
1977
+ border: "none",
1978
+ fontSize: "20px",
1979
+ cursor: "pointer",
1980
+ color: "#666",
1981
+ padding: "2px 6px",
1982
+ lineHeight: 1,
1983
+ borderRadius: "4px"
1984
+ };
1985
+ var subtitleStyle = {
1986
+ fontSize: "12px",
1987
+ color: "#666",
1988
+ marginBottom: "12px"
1989
+ };
1990
+ var walletListStyle = {
1991
+ display: "flex",
1992
+ flexDirection: "column",
1993
+ gap: "6px"
1994
+ };
1995
+ var getWalletItemStyle = (isHovered) => ({
1996
+ display: "flex",
1997
+ alignItems: "center",
1998
+ gap: "10px",
1999
+ padding: "10px 12px",
2000
+ border: "1px solid #e5e5e5",
2001
+ borderRadius: "8px",
2002
+ cursor: "pointer",
2003
+ transition: "all 0.15s ease",
2004
+ backgroundColor: isHovered ? "#f5f5f5" : "#ffffff",
2005
+ borderColor: isHovered ? "#d0d0d0" : "#e5e5e5"
2006
+ });
2007
+ var walletIconStyle = {
2008
+ width: "32px",
2009
+ height: "32px",
2010
+ borderRadius: "8px",
2011
+ objectFit: "contain",
2012
+ backgroundColor: "#f5f5f5"
2013
+ };
2014
+ var getAvatarColor = (name) => {
2015
+ const colors2 = [
2016
+ "#6366f1",
2017
+ // indigo
2018
+ "#8b5cf6",
2019
+ // violet
2020
+ "#ec4899",
2021
+ // pink
2022
+ "#f43f5e",
2023
+ // rose
2024
+ "#f97316",
2025
+ // orange
2026
+ "#eab308",
2027
+ // yellow
2028
+ "#22c55e",
2029
+ // green
2030
+ "#14b8a6",
2031
+ // teal
2032
+ "#06b6d4",
2033
+ // cyan
2034
+ "#3b82f6"
2035
+ // blue
2036
+ ];
2037
+ const index = name.charCodeAt(0) % colors2.length;
2038
+ return colors2[index];
2039
+ };
2040
+ var getWalletIconPlaceholderStyle = (walletName) => ({
2041
+ width: "32px",
2042
+ height: "32px",
2043
+ borderRadius: "8px",
2044
+ backgroundColor: getAvatarColor(walletName),
2045
+ display: "flex",
2046
+ alignItems: "center",
2047
+ justifyContent: "center",
2048
+ fontSize: "14px",
2049
+ fontWeight: 600,
2050
+ color: "#ffffff"
2051
+ });
2052
+ var walletNameStyle = {
2053
+ fontSize: "14px",
2054
+ fontWeight: 500,
2055
+ color: "#1a1a1a"
2056
+ };
2057
+ var emptyStateStyle = {
2058
+ textAlign: "center",
2059
+ padding: "24px 12px",
2060
+ color: "#666"
2061
+ };
2062
+ var emptyTitleStyle = {
2063
+ fontSize: "14px",
2064
+ fontWeight: 500,
2065
+ marginBottom: "6px",
2066
+ color: "#1a1a1a"
2067
+ };
2068
+ var emptyDescStyle = {
2069
+ fontSize: "12px",
2070
+ color: "#888"
2071
+ };
2072
+ function WalletItem({
2073
+ wallet,
2074
+ isHovered,
2075
+ onSelect,
2076
+ onHover
2077
+ }) {
2078
+ const [iconError, setIconError] = (0, import_react7.useState)(false);
2079
+ return /* @__PURE__ */ import_react7.default.createElement(
2080
+ "div",
2081
+ {
2082
+ style: getWalletItemStyle(isHovered),
2083
+ onClick: onSelect,
2084
+ onMouseEnter: () => onHover(true),
2085
+ onMouseLeave: () => onHover(false)
2086
+ },
2087
+ wallet.icon && !iconError ? /* @__PURE__ */ import_react7.default.createElement(
2088
+ "img",
2089
+ {
2090
+ src: wallet.icon,
2091
+ alt: wallet.name,
2092
+ style: walletIconStyle,
2093
+ onError: () => setIconError(true)
2094
+ }
2095
+ ) : /* @__PURE__ */ import_react7.default.createElement("div", { style: getWalletIconPlaceholderStyle(wallet.name) }, wallet.name.charAt(0).toUpperCase()),
2096
+ /* @__PURE__ */ import_react7.default.createElement("span", { style: walletNameStyle }, wallet.name)
2097
+ );
2098
+ }
2099
+ function WalletSelectModal({
2100
+ isOpen,
2101
+ networkType,
2102
+ onSelect,
2103
+ onClose
2104
+ }) {
2105
+ const [wallets, setWallets] = (0, import_react7.useState)([]);
2106
+ const [hoveredWallet, setHoveredWallet] = (0, import_react7.useState)(null);
2107
+ const [mounted, setMounted] = (0, import_react7.useState)(false);
2108
+ (0, import_react7.useEffect)(() => {
2109
+ setMounted(true);
2110
+ return () => setMounted(false);
2111
+ }, []);
2112
+ (0, import_react7.useEffect)(() => {
2113
+ if (!isOpen) return;
2114
+ initEVMWalletDiscovery();
2115
+ const updateWallets = () => {
2116
+ setWallets(getWalletsForNetwork(networkType));
2117
+ };
2118
+ updateWallets();
2119
+ const unsubscribe = onEVMWalletsChanged(updateWallets);
2120
+ const timer = setTimeout(updateWallets, 500);
2121
+ return () => {
2122
+ unsubscribe();
2123
+ clearTimeout(timer);
2124
+ };
2125
+ }, [isOpen, networkType]);
2126
+ if (!isOpen || !mounted) return null;
2127
+ const handleOverlayClick = (e) => {
2128
+ if (e.target === e.currentTarget) {
2129
+ onClose();
2130
+ }
2131
+ };
2132
+ const networkName = getNetworkDisplayName(networkType);
2133
+ const modalContent = /* @__PURE__ */ import_react7.default.createElement("div", { style: overlayStyle, onClick: handleOverlayClick }, /* @__PURE__ */ import_react7.default.createElement("div", { style: modalStyle }, /* @__PURE__ */ import_react7.default.createElement("div", { style: headerStyle }, /* @__PURE__ */ import_react7.default.createElement("h3", { style: titleStyle }, "Select Wallet"), /* @__PURE__ */ import_react7.default.createElement("button", { style: closeButtonStyle, onClick: onClose }, "\xD7")), /* @__PURE__ */ import_react7.default.createElement("p", { style: subtitleStyle }, "Connect a ", networkName, " wallet"), wallets.length > 0 ? /* @__PURE__ */ import_react7.default.createElement("div", { style: walletListStyle }, wallets.map((wallet) => /* @__PURE__ */ import_react7.default.createElement(
2134
+ WalletItem,
2135
+ {
2136
+ key: wallet.id,
2137
+ wallet,
2138
+ isHovered: hoveredWallet === wallet.id,
2139
+ onSelect: () => onSelect(wallet),
2140
+ onHover: (hovered) => setHoveredWallet(hovered ? wallet.id : null)
2141
+ }
2142
+ ))) : /* @__PURE__ */ import_react7.default.createElement("div", { style: emptyStateStyle }, /* @__PURE__ */ import_react7.default.createElement("p", { style: emptyTitleStyle }, "No wallets found"), /* @__PURE__ */ import_react7.default.createElement("p", { style: emptyDescStyle }, "Please install a ", networkName, " wallet extension."))));
2143
+ if (typeof document !== "undefined") {
2144
+ return (0, import_react_dom2.createPortal)(modalContent, document.body);
2145
+ }
2146
+ return modalContent;
2147
+ }
2148
+
2149
+ // src/react/styles/inline-styles.ts
2150
+ var isDarkMode = () => {
2151
+ if (typeof window === "undefined") return false;
2152
+ return window.matchMedia?.("(prefers-color-scheme: dark)").matches ?? false;
2153
+ };
2154
+ var colors = {
2155
+ // Light mode
2156
+ light: {
2157
+ background: "#fafafa",
2158
+ cardBg: "#ffffff",
2159
+ text: "#0a0a0a",
2160
+ textSecondary: "#737373",
2161
+ primary: "#000000",
2162
+ primaryHover: "#262626",
2163
+ danger: "#ef4444",
2164
+ dangerHover: "#dc2626",
2165
+ success: "#10b981",
2166
+ successHover: "#059669",
2167
+ disabled: "#e5e5e5",
2168
+ disabledText: "#a3a3a3",
2169
+ errorBg: "#fef2f2",
2170
+ errorText: "#dc2626"
2171
+ },
2172
+ // Dark mode
2173
+ dark: {
2174
+ background: "#0a0a0a",
2175
+ cardBg: "#171717",
2176
+ text: "#fafafa",
2177
+ textSecondary: "#a3a3a3",
2178
+ primary: "#ffffff",
2179
+ primaryHover: "#e5e5e5",
2180
+ danger: "#f87171",
1469
2181
  dangerHover: "#ef4444",
1470
2182
  success: "#34d399",
1471
2183
  successHover: "#10b981",
@@ -1549,18 +2261,6 @@ var getDisconnectButtonStyle = (isHovered) => {
1549
2261
  color: "#ffffff"
1550
2262
  };
1551
2263
  };
1552
- var getInstallLinkStyle = (isHovered) => {
1553
- const c = getColors();
1554
- return {
1555
- display: "inline-block",
1556
- padding: "0.5rem",
1557
- fontSize: "0.8125rem",
1558
- color: c.textSecondary,
1559
- textDecoration: isHovered ? "underline" : "none",
1560
- textAlign: "center",
1561
- fontWeight: 500
1562
- };
1563
- };
1564
2264
  var walletAddressStyle = {
1565
2265
  display: "flex",
1566
2266
  flexDirection: "column",
@@ -1613,51 +2313,60 @@ var getErrorStyle = () => {
1613
2313
  };
1614
2314
  };
1615
2315
 
1616
- // src/react/components/WalletConnect.tsx
2316
+ // src/react/components/wallet/WalletConnect.tsx
1617
2317
  function WalletConnect({
1618
2318
  supportedNetworks = ["solana" /* SOLANA */, "evm" /* EVM */],
1619
2319
  className = "",
1620
2320
  onConnect,
1621
- onDisconnect
2321
+ onDisconnect,
2322
+ showSwitchWallet = true
1622
2323
  }) {
1623
- const { address, networkType, isConnecting, error, connect, disconnect } = useWallet();
1624
- const [hoveredButton, setHoveredButton] = (0, import_react5.useState)(null);
1625
- const [hoveredLink, setHoveredLink] = (0, import_react5.useState)(null);
1626
- const handleConnect = async (network) => {
2324
+ const { address, networkType, isConnecting, error, connectWithWallet, disconnect } = useWallet();
2325
+ const [hoveredButton, setHoveredButton] = (0, import_react8.useState)(null);
2326
+ const [walletSelectOpen, setWalletSelectOpen] = (0, import_react8.useState)(false);
2327
+ const [selectedNetworkType, setSelectedNetworkType] = (0, import_react8.useState)(null);
2328
+ const handleOpenWalletSelect = (network) => {
2329
+ setSelectedNetworkType(network);
2330
+ setWalletSelectOpen(true);
2331
+ };
2332
+ const handleWalletSelect = async (wallet) => {
2333
+ setWalletSelectOpen(false);
1627
2334
  try {
1628
- await connect(network);
2335
+ await connectWithWallet(wallet);
1629
2336
  } catch (err) {
1630
2337
  }
1631
2338
  };
1632
- const handleDisconnect = () => {
1633
- disconnect();
2339
+ const handleDisconnect = async () => {
2340
+ await disconnect();
1634
2341
  onDisconnect?.();
1635
2342
  };
1636
- return /* @__PURE__ */ import_react5.default.createElement("div", { style: { ...containerStyle, ...className ? {} : {} }, className }, !address ? /* @__PURE__ */ import_react5.default.createElement("div", { style: getSectionStyle() }, /* @__PURE__ */ import_react5.default.createElement("h3", { style: getTitleStyle() }, "Connect Wallet"), supportedNetworks.length === 0 ? /* @__PURE__ */ import_react5.default.createElement("p", { style: getHintStyle() }, "Please install a supported wallet extension") : /* @__PURE__ */ import_react5.default.createElement("div", { style: buttonsContainerStyle }, supportedNetworks.map((network) => {
1637
- const installed = isWalletInstalled(network);
1638
- return /* @__PURE__ */ import_react5.default.createElement("div", { key: network, style: walletOptionStyle }, /* @__PURE__ */ import_react5.default.createElement(
1639
- "button",
1640
- {
1641
- style: getConnectButtonStyle(isConnecting || !installed, hoveredButton === network),
1642
- onClick: () => handleConnect(network),
1643
- disabled: isConnecting || !installed,
1644
- onMouseEnter: () => setHoveredButton(network),
1645
- onMouseLeave: () => setHoveredButton(null)
1646
- },
1647
- isConnecting ? "Connecting..." : getNetworkDisplayName(network)
1648
- ), !installed && /* @__PURE__ */ import_react5.default.createElement(
1649
- "a",
1650
- {
1651
- href: getWalletInstallUrl(network),
1652
- target: "_blank",
1653
- rel: "noopener noreferrer",
1654
- style: getInstallLinkStyle(hoveredLink === network),
1655
- onMouseEnter: () => setHoveredLink(network),
1656
- onMouseLeave: () => setHoveredLink(null)
1657
- },
1658
- "Install Wallet"
1659
- ));
1660
- })), error && /* @__PURE__ */ import_react5.default.createElement("p", { style: getErrorStyle() }, error), /* @__PURE__ */ import_react5.default.createElement("p", { style: getHintStyle() }, "To switch accounts, please change it in your wallet extension")) : /* @__PURE__ */ import_react5.default.createElement("div", { style: getSectionStyle() }, /* @__PURE__ */ import_react5.default.createElement("div", { style: walletAddressStyle }, /* @__PURE__ */ import_react5.default.createElement("span", { style: getLabelStyle() }, "Connected ", networkType && `(${getNetworkDisplayName(networkType)})`), /* @__PURE__ */ import_react5.default.createElement("span", { style: getAddressStyle() }, formatAddress(address))), /* @__PURE__ */ import_react5.default.createElement("div", { style: walletActionsStyle }, /* @__PURE__ */ import_react5.default.createElement(
2343
+ const handleSwitchWallet = () => {
2344
+ if (networkType) {
2345
+ setSelectedNetworkType(networkType);
2346
+ setWalletSelectOpen(true);
2347
+ }
2348
+ };
2349
+ return /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement("div", { style: { ...containerStyle, ...className ? {} : {} }, className }, !address ? /* @__PURE__ */ import_react8.default.createElement("div", { style: getSectionStyle() }, /* @__PURE__ */ import_react8.default.createElement("h3", { style: getTitleStyle() }, "Connect Wallet"), supportedNetworks.length === 0 ? /* @__PURE__ */ import_react8.default.createElement("p", { style: getHintStyle() }, "Please install a supported wallet extension") : /* @__PURE__ */ import_react8.default.createElement("div", { style: buttonsContainerStyle }, supportedNetworks.map((network) => /* @__PURE__ */ import_react8.default.createElement("div", { key: network, style: walletOptionStyle }, /* @__PURE__ */ import_react8.default.createElement(
2350
+ "button",
2351
+ {
2352
+ style: getConnectButtonStyle(isConnecting, hoveredButton === network),
2353
+ onClick: () => handleOpenWalletSelect(network),
2354
+ disabled: isConnecting,
2355
+ onMouseEnter: () => setHoveredButton(network),
2356
+ onMouseLeave: () => setHoveredButton(null)
2357
+ },
2358
+ isConnecting ? "Connecting..." : getNetworkDisplayName(network)
2359
+ )))), error && /* @__PURE__ */ import_react8.default.createElement("p", { style: getErrorStyle() }, error), /* @__PURE__ */ import_react8.default.createElement("p", { style: getHintStyle() }, "Select a network to see available wallets")) : /* @__PURE__ */ import_react8.default.createElement("div", { style: getSectionStyle() }, /* @__PURE__ */ import_react8.default.createElement("div", { style: walletAddressStyle }, /* @__PURE__ */ import_react8.default.createElement("span", { style: getLabelStyle() }, "Connected ", networkType && `(${getNetworkDisplayName(networkType)})`), /* @__PURE__ */ import_react8.default.createElement("span", { style: getAddressStyle() }, formatAddress(address))), /* @__PURE__ */ import_react8.default.createElement("div", { style: walletActionsStyle }, showSwitchWallet && /* @__PURE__ */ import_react8.default.createElement(
2360
+ "button",
2361
+ {
2362
+ style: getConnectButtonStyle(isConnecting, hoveredButton === "switch"),
2363
+ onClick: handleSwitchWallet,
2364
+ disabled: isConnecting,
2365
+ onMouseEnter: () => setHoveredButton("switch"),
2366
+ onMouseLeave: () => setHoveredButton(null)
2367
+ },
2368
+ isConnecting ? "Switching..." : "Switch Wallet"
2369
+ ), /* @__PURE__ */ import_react8.default.createElement(
1661
2370
  "button",
1662
2371
  {
1663
2372
  style: getDisconnectButtonStyle(hoveredButton === "disconnect"),
@@ -1666,19 +2375,27 @@ function WalletConnect({
1666
2375
  onMouseLeave: () => setHoveredButton(null)
1667
2376
  },
1668
2377
  "Disconnect"
1669
- )), /* @__PURE__ */ import_react5.default.createElement("p", { style: getHintStyle() }, "Switch account in your wallet to change address")));
2378
+ )), /* @__PURE__ */ import_react8.default.createElement("p", { style: getHintStyle() }, 'Click "Switch Wallet" to change wallet or account'))), selectedNetworkType && /* @__PURE__ */ import_react8.default.createElement(
2379
+ WalletSelectModal,
2380
+ {
2381
+ isOpen: walletSelectOpen,
2382
+ networkType: selectedNetworkType,
2383
+ onSelect: handleWalletSelect,
2384
+ onClose: () => setWalletSelectOpen(false)
2385
+ }
2386
+ ));
1670
2387
  }
1671
2388
 
1672
- // src/react/components/V402Checkout.tsx
1673
- var import_react7 = __toESM(require("react"));
2389
+ // src/react/components/checkout/V402Checkout.tsx
2390
+ var import_react10 = __toESM(require("react"));
1674
2391
  var import_antd = require("antd");
1675
2392
  var import_icons = require("@ant-design/icons");
1676
2393
  init_common();
1677
2394
 
1678
2395
  // src/react/utils/CryptoIcons.tsx
1679
- var import_react6 = __toESM(require("react"));
2396
+ var import_react9 = __toESM(require("react"));
1680
2397
  var SolanaIcon = ({ width = 16, height = 16, className, style }) => {
1681
- return /* @__PURE__ */ import_react6.default.createElement(
2398
+ return /* @__PURE__ */ import_react9.default.createElement(
1682
2399
  "svg",
1683
2400
  {
1684
2401
  xmlns: "http://www.w3.org/2000/svg",
@@ -1688,14 +2405,14 @@ var SolanaIcon = ({ width = 16, height = 16, className, style }) => {
1688
2405
  className,
1689
2406
  style
1690
2407
  },
1691
- /* @__PURE__ */ import_react6.default.createElement("desc", null, "Solana SOL Fill Streamline Icon: https://streamlinehq.com"),
1692
- /* @__PURE__ */ import_react6.default.createElement("g", { fill: "none", fillRule: "evenodd" }, /* @__PURE__ */ import_react6.default.createElement(
2408
+ /* @__PURE__ */ import_react9.default.createElement("desc", null, "Solana SOL Fill Streamline Icon: https://streamlinehq.com"),
2409
+ /* @__PURE__ */ import_react9.default.createElement("g", { fill: "none", fillRule: "evenodd" }, /* @__PURE__ */ import_react9.default.createElement(
1693
2410
  "path",
1694
2411
  {
1695
2412
  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",
1696
2413
  strokeWidth: "0.6667"
1697
2414
  }
1698
- ), /* @__PURE__ */ import_react6.default.createElement(
2415
+ ), /* @__PURE__ */ import_react9.default.createElement(
1699
2416
  "path",
1700
2417
  {
1701
2418
  fill: "#000000",
@@ -1706,7 +2423,7 @@ var SolanaIcon = ({ width = 16, height = 16, className, style }) => {
1706
2423
  );
1707
2424
  };
1708
2425
  var BaseIcon = ({ width = 24, height = 24, className, style }) => {
1709
- return /* @__PURE__ */ import_react6.default.createElement(
2426
+ return /* @__PURE__ */ import_react9.default.createElement(
1710
2427
  "svg",
1711
2428
  {
1712
2429
  xmlns: "http://www.w3.org/2000/svg",
@@ -1720,8 +2437,8 @@ var BaseIcon = ({ width = 24, height = 24, className, style }) => {
1720
2437
  className,
1721
2438
  style
1722
2439
  },
1723
- /* @__PURE__ */ import_react6.default.createElement("desc", null, "Brand Coinbase Streamline Icon: https://streamlinehq.com"),
1724
- /* @__PURE__ */ import_react6.default.createElement(
2440
+ /* @__PURE__ */ import_react9.default.createElement("desc", null, "Brand Coinbase Streamline Icon: https://streamlinehq.com"),
2441
+ /* @__PURE__ */ import_react9.default.createElement(
1725
2442
  "path",
1726
2443
  {
1727
2444
  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",
@@ -1741,7 +2458,7 @@ var getNetworkIcon = (network) => {
1741
2458
  return BaseIcon;
1742
2459
  };
1743
2460
 
1744
- // src/react/components/V402Checkout.tsx
2461
+ // src/react/components/checkout/V402Checkout.tsx
1745
2462
  var { Title, Text } = import_antd.Typography;
1746
2463
  var notify = {
1747
2464
  success: (title, msg) => {
@@ -1779,14 +2496,14 @@ function V402Checkout({
1779
2496
  { autoSwitch: !!targetNetwork, switchOnMount: true }
1780
2497
  );
1781
2498
  const { isProcessing, setIsProcessing, result, setResult, error, setError } = usePayment();
1782
- const [paymentDetails, setPaymentDetails] = (0, import_react7.useState)(null);
2499
+ const [paymentDetails, setPaymentDetails] = (0, import_react10.useState)(null);
1783
2500
  const handleDisconnect = () => {
1784
2501
  disconnect();
1785
2502
  setResult(null);
1786
2503
  setError(null);
1787
2504
  notify.info("Wallet Disconnected", "Your wallet has been disconnected successfully.");
1788
2505
  };
1789
- (0, import_react7.useEffect)(() => {
2506
+ (0, import_react10.useEffect)(() => {
1790
2507
  if (paymentInfo && paymentInfo.length > 0) {
1791
2508
  const firstPayment = paymentInfo[0];
1792
2509
  const rawAmount = firstPayment.maxAmountRequired?.toString() || "0";
@@ -1801,7 +2518,7 @@ function V402Checkout({
1801
2518
  });
1802
2519
  }
1803
2520
  }, [paymentInfo]);
1804
- (0, import_react7.useEffect)(() => {
2521
+ (0, import_react10.useEffect)(() => {
1805
2522
  if (targetNetwork && !fetchingPaymentInfo && ensureNetwork) {
1806
2523
  ensureNetwork(targetNetwork).catch((err) => {
1807
2524
  console.error("Failed to ensure network:", err);
@@ -1817,7 +2534,7 @@ function V402Checkout({
1817
2534
  setError(null);
1818
2535
  setIsProcessing(true);
1819
2536
  try {
1820
- const response = await makePayment(networkType, checkoutId, endpoint, additionalParams);
2537
+ const response = await makePayment(networkType, checkoutId, endpoint, additionalParams, address || void 0);
1821
2538
  const data = await response.json();
1822
2539
  setResult(data);
1823
2540
  notify.success("Payment Successful!", "Your payment has been processed successfully.");
@@ -1841,12 +2558,12 @@ function V402Checkout({
1841
2558
  const networkColor = paymentDetails ? getNetworkColor(paymentDetails.network) : "#8c8c8c";
1842
2559
  const loadingColor = "#8c8c8c";
1843
2560
  const hasInvalidCheckoutId = !fetchingPaymentInfo && (!paymentInfo || paymentInfo.length === 0);
1844
- return /* @__PURE__ */ import_react7.default.createElement(
2561
+ return /* @__PURE__ */ import_react10.default.createElement(
1845
2562
  "div",
1846
2563
  {
1847
2564
  className: isModal ? "bg-white" : "h-screen bg-white flex items-center justify-center p-4 overflow-hidden"
1848
2565
  },
1849
- /* @__PURE__ */ import_react7.default.createElement(
2566
+ /* @__PURE__ */ import_react10.default.createElement(
1850
2567
  "div",
1851
2568
  {
1852
2569
  className: "flex gap-4 items-center justify-center",
@@ -1856,7 +2573,7 @@ function V402Checkout({
1856
2573
  width: "100%"
1857
2574
  }
1858
2575
  },
1859
- /* @__PURE__ */ import_react7.default.createElement(
2576
+ /* @__PURE__ */ import_react10.default.createElement(
1860
2577
  import_antd.Card,
1861
2578
  {
1862
2579
  className: "flex-shrink-0",
@@ -1872,7 +2589,7 @@ function V402Checkout({
1872
2589
  },
1873
2590
  styles: { body: { padding: isModal ? "0px" : "32px 24px" } }
1874
2591
  },
1875
- /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex items-center gap-3 mb-4" }, /* @__PURE__ */ import_react7.default.createElement(
2592
+ /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex items-center gap-3 mb-4" }, /* @__PURE__ */ import_react10.default.createElement(
1876
2593
  "div",
1877
2594
  {
1878
2595
  className: "w-12 h-12 rounded-xl flex items-center justify-center",
@@ -1881,22 +2598,22 @@ function V402Checkout({
1881
2598
  transition: "background 0.3s ease"
1882
2599
  }
1883
2600
  },
1884
- hasInvalidCheckoutId ? /* @__PURE__ */ import_react7.default.createElement("span", { style: { fontSize: "20px", color: "white", fontWeight: "bold" } }, "\u2717") : paymentDetails && NetworkIcon ? /* @__PURE__ */ import_react7.default.createElement(NetworkIcon, { width: 24, height: 24 }) : /* @__PURE__ */ import_react7.default.createElement(import_icons.LoadingOutlined, { style: { fontSize: "20px", color: "white" }, spin: true })
1885
- ), /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex-1" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react7.default.createElement(Title, { level: 4, style: { margin: 0, fontSize: "18px", fontWeight: 600 } }, title || "Echo Payment OnVoyage"), !hasInvalidCheckoutId && /* @__PURE__ */ import_react7.default.createElement(
2601
+ hasInvalidCheckoutId ? /* @__PURE__ */ import_react10.default.createElement("span", { style: { fontSize: "20px", color: "white", fontWeight: "bold" } }, "\u2717") : paymentDetails && NetworkIcon ? /* @__PURE__ */ import_react10.default.createElement(NetworkIcon, { width: 24, height: 24 }) : /* @__PURE__ */ import_react10.default.createElement(import_icons.LoadingOutlined, { style: { fontSize: "20px", color: "white" }, spin: true })
2602
+ ), /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex-1" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react10.default.createElement(Title, { level: 4, style: { margin: 0, fontSize: "18px", fontWeight: 600 } }, title || "Echo Payment OnVoyage"), !hasInvalidCheckoutId && /* @__PURE__ */ import_react10.default.createElement(
1886
2603
  import_antd.Tooltip,
1887
2604
  {
1888
2605
  title: tooltipText,
1889
2606
  placement: "top"
1890
2607
  },
1891
- /* @__PURE__ */ import_react7.default.createElement(
2608
+ /* @__PURE__ */ import_react10.default.createElement(
1892
2609
  import_icons.InfoCircleOutlined,
1893
2610
  {
1894
2611
  style: { fontSize: "14px", color: "#8c8c8c", cursor: "help" }
1895
2612
  }
1896
2613
  )
1897
- )), /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, subtitle))),
1898
- /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-center mb-5" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "inline-flex items-center justify-center w-12 h-12 rounded-full bg-gray-50 mb-3" }, /* @__PURE__ */ import_react7.default.createElement(import_icons.LockOutlined, { style: { fontSize: "20px", color: "#595959" } })), /* @__PURE__ */ import_react7.default.createElement(Title, { level: 3, style: { margin: "0 0 6px 0", fontSize: "20px", fontWeight: 600 } }, "Payment Required"), /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Pay ", paymentDetails ? `$${paymentDetails.amount} ${paymentDetails.currency}` : "the required amount", " to access")),
1899
- hasInvalidCheckoutId && /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-center py-6" }, /* @__PURE__ */ import_react7.default.createElement(
2614
+ )), /* @__PURE__ */ import_react10.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, subtitle))),
2615
+ /* @__PURE__ */ import_react10.default.createElement("div", { className: "text-center mb-5" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "inline-flex items-center justify-center w-12 h-12 rounded-full bg-gray-50 mb-3" }, /* @__PURE__ */ import_react10.default.createElement(import_icons.LockOutlined, { style: { fontSize: "20px", color: "#595959" } })), /* @__PURE__ */ import_react10.default.createElement(Title, { level: 3, style: { margin: "0 0 6px 0", fontSize: "20px", fontWeight: 600 } }, "Payment Required"), /* @__PURE__ */ import_react10.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Pay ", paymentDetails ? `$${paymentDetails.amount} ${paymentDetails.currency}` : "the required amount", " to access")),
2616
+ hasInvalidCheckoutId && /* @__PURE__ */ import_react10.default.createElement("div", { className: "text-center py-6" }, /* @__PURE__ */ import_react10.default.createElement(
1900
2617
  "div",
1901
2618
  {
1902
2619
  className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
@@ -1905,15 +2622,15 @@ function V402Checkout({
1905
2622
  boxShadow: "0 4px 20px rgba(239, 68, 68, 0.3)"
1906
2623
  }
1907
2624
  },
1908
- /* @__PURE__ */ import_react7.default.createElement("span", { style: { fontSize: "32px", color: "white" } }, "!")
1909
- ), /* @__PURE__ */ import_react7.default.createElement(
2625
+ /* @__PURE__ */ import_react10.default.createElement("span", { style: { fontSize: "32px", color: "white" } }, "!")
2626
+ ), /* @__PURE__ */ import_react10.default.createElement(
1910
2627
  Title,
1911
2628
  {
1912
2629
  level: 4,
1913
2630
  style: { margin: "0 0 12px 0", fontSize: "18px", fontWeight: 600, color: "#262626" }
1914
2631
  },
1915
2632
  "Invalid Checkout ID"
1916
- ), /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c", display: "block", marginBottom: "16px" } }, "The checkout ID you provided is invalid or has expired."), /* @__PURE__ */ import_react7.default.createElement(
2633
+ ), /* @__PURE__ */ import_react10.default.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c", display: "block", marginBottom: "16px" } }, "The checkout ID you provided is invalid or has expired."), /* @__PURE__ */ import_react10.default.createElement(
1917
2634
  "div",
1918
2635
  {
1919
2636
  style: {
@@ -1924,33 +2641,33 @@ function V402Checkout({
1924
2641
  marginTop: "16px"
1925
2642
  }
1926
2643
  },
1927
- /* @__PURE__ */ import_react7.default.createElement(Text, { style: {
2644
+ /* @__PURE__ */ import_react10.default.createElement(Text, { style: {
1928
2645
  fontSize: "13px",
1929
2646
  color: "#dc2626",
1930
2647
  lineHeight: "1.6",
1931
2648
  fontWeight: 500
1932
2649
  } }, "Failed to load payment information. Please check your checkout ID.")
1933
2650
  )),
1934
- !hasInvalidCheckoutId && fetchingPaymentInfo && /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-center py-6" }, /* @__PURE__ */ import_react7.default.createElement(Text, { style: { color: "#8c8c8c" } }, "Loading payment information...")),
1935
- !hasInvalidCheckoutId && !fetchingPaymentInfo && !address && /* @__PURE__ */ import_react7.default.createElement("div", null, /* @__PURE__ */ import_react7.default.createElement(WalletConnect, { supportedNetworks })),
1936
- !hasInvalidCheckoutId && address && /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, /* @__PURE__ */ import_react7.default.createElement(
2651
+ !hasInvalidCheckoutId && fetchingPaymentInfo && /* @__PURE__ */ import_react10.default.createElement("div", { className: "text-center py-6" }, /* @__PURE__ */ import_react10.default.createElement(Text, { style: { color: "#8c8c8c" } }, "Loading payment information...")),
2652
+ !hasInvalidCheckoutId && !fetchingPaymentInfo && !address && /* @__PURE__ */ import_react10.default.createElement("div", null, /* @__PURE__ */ import_react10.default.createElement(WalletConnect, { supportedNetworks })),
2653
+ !hasInvalidCheckoutId && address && /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null, /* @__PURE__ */ import_react10.default.createElement(
1937
2654
  "div",
1938
2655
  {
1939
2656
  className: "bg-gray-50 rounded-lg p-3 mb-4",
1940
2657
  style: { border: "1px solid #f0f0f0" }
1941
2658
  },
1942
- /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex items-center gap-3 flex-1" }, /* @__PURE__ */ import_react7.default.createElement(
2659
+ /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex items-center gap-3 flex-1" }, /* @__PURE__ */ import_react10.default.createElement(
1943
2660
  "div",
1944
2661
  {
1945
2662
  className: "w-10 h-10 rounded-full bg-black flex items-center justify-center text-white text-sm font-semibold"
1946
2663
  },
1947
2664
  address.slice(0, 2).toUpperCase()
1948
- ), /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react7.default.createElement(Text, { style: {
2665
+ ), /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react10.default.createElement(Text, { style: {
1949
2666
  display: "block",
1950
2667
  fontSize: "12px",
1951
2668
  color: "#8c8c8c",
1952
2669
  marginBottom: "2px"
1953
- } }, "Connected Wallet"), /* @__PURE__ */ import_react7.default.createElement(
2670
+ } }, "Connected Wallet"), /* @__PURE__ */ import_react10.default.createElement(
1954
2671
  Text,
1955
2672
  {
1956
2673
  style: {
@@ -1960,17 +2677,17 @@ function V402Checkout({
1960
2677
  }
1961
2678
  },
1962
2679
  formatAddress(address)
1963
- ))), /* @__PURE__ */ import_react7.default.createElement(
2680
+ ))), /* @__PURE__ */ import_react10.default.createElement(
1964
2681
  import_antd.Button,
1965
2682
  {
1966
2683
  type: "text",
1967
2684
  size: "small",
1968
- icon: /* @__PURE__ */ import_react7.default.createElement(import_icons.DisconnectOutlined, null),
2685
+ icon: /* @__PURE__ */ import_react10.default.createElement(import_icons.DisconnectOutlined, null),
1969
2686
  onClick: handleDisconnect,
1970
2687
  style: { color: "#ff4d4f" }
1971
2688
  }
1972
2689
  ))
1973
- ), paymentDetails && /* @__PURE__ */ import_react7.default.createElement("div", { className: "bg-gray-50 rounded-lg p-3 mb-4", style: { border: "1px solid #f0f0f0" } }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Payment Amount"), /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "18px", fontWeight: 600 } }, "$", paymentDetails.amount)), /* @__PURE__ */ import_react7.default.createElement(import_antd.Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Currency"), /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "14px", fontWeight: 500 } }, paymentDetails.currency)), /* @__PURE__ */ import_react7.default.createElement(import_antd.Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Network"), /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "14px", fontWeight: 500 } }, paymentDetails.network)), /* @__PURE__ */ import_react7.default.createElement(import_antd.Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex justify-between items-start" }, /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Wallet Address"), /* @__PURE__ */ import_react7.default.createElement(Text, { style: {
2690
+ ), paymentDetails && /* @__PURE__ */ import_react10.default.createElement("div", { className: "bg-gray-50 rounded-lg p-3 mb-4", style: { border: "1px solid #f0f0f0" } }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ import_react10.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Payment Amount"), /* @__PURE__ */ import_react10.default.createElement(Text, { style: { fontSize: "18px", fontWeight: 600 } }, "$", paymentDetails.amount)), /* @__PURE__ */ import_react10.default.createElement(import_antd.Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ import_react10.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Currency"), /* @__PURE__ */ import_react10.default.createElement(Text, { style: { fontSize: "14px", fontWeight: 500 } }, paymentDetails.currency)), /* @__PURE__ */ import_react10.default.createElement(import_antd.Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ import_react10.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Network"), /* @__PURE__ */ import_react10.default.createElement(Text, { style: { fontSize: "14px", fontWeight: 500 } }, paymentDetails.network)), /* @__PURE__ */ import_react10.default.createElement(import_antd.Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex justify-between items-start" }, /* @__PURE__ */ import_react10.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Wallet Address"), /* @__PURE__ */ import_react10.default.createElement(Text, { style: {
1974
2691
  fontSize: "11px",
1975
2692
  fontWeight: 500,
1976
2693
  fontFamily: "Monaco, monospace",
@@ -1978,15 +2695,15 @@ function V402Checkout({
1978
2695
  textAlign: "right",
1979
2696
  maxWidth: "60%",
1980
2697
  lineHeight: 1.4
1981
- } }, address))), /* @__PURE__ */ import_react7.default.createElement(
2698
+ } }, address))), /* @__PURE__ */ import_react10.default.createElement(
1982
2699
  "div",
1983
2700
  {
1984
2701
  className: "flex items-center justify-center gap-2 mb-3 p-2 rounded-lg",
1985
2702
  style: { background: "#f6ffed", border: "1px solid #d9f7be" }
1986
2703
  },
1987
- /* @__PURE__ */ import_react7.default.createElement(import_icons.SafetyOutlined, { style: { color: "#52c41a", fontSize: "13px" } }),
1988
- /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "12px", color: "#52c41a", fontWeight: 500 } }, "Secure payment powered by v402pay")
1989
- ), /* @__PURE__ */ import_react7.default.createElement(
2704
+ /* @__PURE__ */ import_react10.default.createElement(import_icons.SafetyOutlined, { style: { color: "#52c41a", fontSize: "13px" } }),
2705
+ /* @__PURE__ */ import_react10.default.createElement(Text, { style: { fontSize: "12px", color: "#52c41a", fontWeight: 500 } }, "Secure payment powered by v402pay")
2706
+ ), /* @__PURE__ */ import_react10.default.createElement(
1990
2707
  import_antd.Button,
1991
2708
  {
1992
2709
  type: "primary",
@@ -2008,7 +2725,7 @@ function V402Checkout({
2008
2725
  }
2009
2726
  },
2010
2727
  isProcessing ? "Processing..." : !paymentDetails ? "Loading..." : `Pay $${paymentDetails.amount} ${paymentDetails.currency}`
2011
- ), /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-center" }, /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Don't have USDC?", " "), /* @__PURE__ */ import_react7.default.createElement(
2728
+ ), /* @__PURE__ */ import_react10.default.createElement("div", { className: "text-center" }, /* @__PURE__ */ import_react10.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Don't have USDC?", " "), /* @__PURE__ */ import_react10.default.createElement(
2012
2729
  "a",
2013
2730
  {
2014
2731
  href: "https://faucet.circle.com/",
@@ -2017,26 +2734,26 @@ function V402Checkout({
2017
2734
  className: "text-blue-600 hover:text-blue-700 text-sm font-medium inline-flex items-center gap-1"
2018
2735
  },
2019
2736
  "Get it here ",
2020
- /* @__PURE__ */ import_react7.default.createElement(import_icons.LinkOutlined, { style: { fontSize: "12px" } })
2021
- )), isModal && result && /* @__PURE__ */ import_react7.default.createElement(
2737
+ /* @__PURE__ */ import_react10.default.createElement(import_icons.LinkOutlined, { style: { fontSize: "12px" } })
2738
+ )), isModal && result && /* @__PURE__ */ import_react10.default.createElement(
2022
2739
  "div",
2023
2740
  {
2024
2741
  className: "mt-4 p-4 rounded-lg",
2025
2742
  style: { background: "#f6ffed", border: "1px solid #b7eb8f" }
2026
2743
  },
2027
- /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-center" }, /* @__PURE__ */ import_react7.default.createElement("span", { style: { fontSize: "20px" } }, "\u2713"), /* @__PURE__ */ import_react7.default.createElement(Text, { style: {
2744
+ /* @__PURE__ */ import_react10.default.createElement("div", { className: "text-center" }, /* @__PURE__ */ import_react10.default.createElement("span", { style: { fontSize: "20px" } }, "\u2713"), /* @__PURE__ */ import_react10.default.createElement(Text, { style: {
2028
2745
  fontSize: "14px",
2029
2746
  color: "#52c41a",
2030
2747
  fontWeight: 600,
2031
2748
  marginLeft: "8px"
2032
2749
  } }, "Payment Successful!"))
2033
- ), isModal && error && /* @__PURE__ */ import_react7.default.createElement(
2750
+ ), isModal && error && /* @__PURE__ */ import_react10.default.createElement(
2034
2751
  "div",
2035
2752
  {
2036
2753
  className: "mt-4 p-4 rounded-lg",
2037
2754
  style: { background: "#fff2f0", border: "1px solid #ffccc7" }
2038
2755
  },
2039
- /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-center mb-3" }, /* @__PURE__ */ import_react7.default.createElement("span", { style: { fontSize: "20px" } }, "\u2717"), /* @__PURE__ */ import_react7.default.createElement(Text, { style: {
2756
+ /* @__PURE__ */ import_react10.default.createElement("div", { className: "text-center mb-3" }, /* @__PURE__ */ import_react10.default.createElement("span", { style: { fontSize: "20px" } }, "\u2717"), /* @__PURE__ */ import_react10.default.createElement(Text, { style: {
2040
2757
  fontSize: "14px",
2041
2758
  color: "#ff4d4f",
2042
2759
  fontWeight: 600,
@@ -2044,7 +2761,7 @@ function V402Checkout({
2044
2761
  display: "block",
2045
2762
  marginTop: "4px"
2046
2763
  } }, "Payment Failed")),
2047
- /* @__PURE__ */ import_react7.default.createElement(Text, { style: {
2764
+ /* @__PURE__ */ import_react10.default.createElement(Text, { style: {
2048
2765
  fontSize: "13px",
2049
2766
  color: "#ff4d4f",
2050
2767
  display: "block",
@@ -2052,11 +2769,11 @@ function V402Checkout({
2052
2769
  } }, error)
2053
2770
  ))
2054
2771
  ),
2055
- !isModal && (isProcessing || result || error) && /* @__PURE__ */ import_react7.default.createElement(
2772
+ !isModal && (isProcessing || result || error) && /* @__PURE__ */ import_react10.default.createElement(
2056
2773
  import_antd.Card,
2057
2774
  {
2058
- title: /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex items-center gap-2" }, isProcessing && !result && !error ? /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, /* @__PURE__ */ import_react7.default.createElement(import_icons.LoadingOutlined, { style: { color: "#14b8a6", fontSize: "16px" } }), /* @__PURE__ */ import_react7.default.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Processing Payment")) : result ? /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, /* @__PURE__ */ import_react7.default.createElement("span", { style: { color: "#52c41a", fontSize: "18px" } }, "\u2713"), /* @__PURE__ */ import_react7.default.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Payment Successful")) : /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, /* @__PURE__ */ import_react7.default.createElement("span", { style: { color: "#ff4d4f", fontSize: "18px" } }, "\u2717"), /* @__PURE__ */ import_react7.default.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Payment Failed"))),
2059
- extra: !isProcessing && /* @__PURE__ */ import_react7.default.createElement(
2775
+ title: /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex items-center gap-2" }, isProcessing && !result && !error ? /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null, /* @__PURE__ */ import_react10.default.createElement(import_icons.LoadingOutlined, { style: { color: "#14b8a6", fontSize: "16px" } }), /* @__PURE__ */ import_react10.default.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Processing Payment")) : result ? /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null, /* @__PURE__ */ import_react10.default.createElement("span", { style: { color: "#52c41a", fontSize: "18px" } }, "\u2713"), /* @__PURE__ */ import_react10.default.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Payment Successful")) : /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null, /* @__PURE__ */ import_react10.default.createElement("span", { style: { color: "#ff4d4f", fontSize: "18px" } }, "\u2717"), /* @__PURE__ */ import_react10.default.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Payment Failed"))),
2776
+ extra: !isProcessing && /* @__PURE__ */ import_react10.default.createElement(
2060
2777
  import_antd.Button,
2061
2778
  {
2062
2779
  type: "text",
@@ -2084,7 +2801,7 @@ function V402Checkout({
2084
2801
  }
2085
2802
  }
2086
2803
  },
2087
- isProcessing && !result && !error && /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-center py-10" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "relative inline-block" }, /* @__PURE__ */ import_react7.default.createElement(
2804
+ isProcessing && !result && !error && /* @__PURE__ */ import_react10.default.createElement("div", { className: "text-center py-10" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "relative inline-block" }, /* @__PURE__ */ import_react10.default.createElement(
2088
2805
  "div",
2089
2806
  {
2090
2807
  className: "absolute inset-0 rounded-full blur-xl opacity-40",
@@ -2093,12 +2810,12 @@ function V402Checkout({
2093
2810
  animation: "pulse 2s ease-in-out infinite"
2094
2811
  }
2095
2812
  }
2096
- ), /* @__PURE__ */ import_react7.default.createElement(
2813
+ ), /* @__PURE__ */ import_react10.default.createElement(
2097
2814
  import_antd.Spin,
2098
2815
  {
2099
- indicator: /* @__PURE__ */ import_react7.default.createElement(import_icons.LoadingOutlined, { style: { fontSize: 56, color: "#14b8a6" } })
2816
+ indicator: /* @__PURE__ */ import_react10.default.createElement(import_icons.LoadingOutlined, { style: { fontSize: 56, color: "#14b8a6" } })
2100
2817
  }
2101
- )), /* @__PURE__ */ import_react7.default.createElement("div", { className: "mt-6" }, /* @__PURE__ */ import_react7.default.createElement(Text, { strong: true, style: { fontSize: "18px", color: "#262626", letterSpacing: "-0.02em" } }, "Verifying Payment")), /* @__PURE__ */ import_react7.default.createElement("div", { className: "mt-2 mb-6" }, /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c", lineHeight: "1.6" } }, "Please wait while we confirm your transaction")), /* @__PURE__ */ import_react7.default.createElement(
2818
+ )), /* @__PURE__ */ import_react10.default.createElement("div", { className: "mt-6" }, /* @__PURE__ */ import_react10.default.createElement(Text, { strong: true, style: { fontSize: "18px", color: "#262626", letterSpacing: "-0.02em" } }, "Verifying Payment")), /* @__PURE__ */ import_react10.default.createElement("div", { className: "mt-2 mb-6" }, /* @__PURE__ */ import_react10.default.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c", lineHeight: "1.6" } }, "Please wait while we confirm your transaction")), /* @__PURE__ */ import_react10.default.createElement(
2102
2819
  "div",
2103
2820
  {
2104
2821
  className: "mt-4 p-4 rounded-xl",
@@ -2107,9 +2824,9 @@ function V402Checkout({
2107
2824
  border: "1px solid #ccfbf1"
2108
2825
  }
2109
2826
  },
2110
- /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex items-center justify-center gap-2" }, /* @__PURE__ */ import_react7.default.createElement("span", { style: { fontSize: "16px" } }, "\u23F1\uFE0F"), /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "13px", color: "#0f766e", fontWeight: 500 } }, "This may take a few moments"))
2827
+ /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex items-center justify-center gap-2" }, /* @__PURE__ */ import_react10.default.createElement("span", { style: { fontSize: "16px" } }, "\u23F1\uFE0F"), /* @__PURE__ */ import_react10.default.createElement(Text, { style: { fontSize: "13px", color: "#0f766e", fontWeight: 500 } }, "This may take a few moments"))
2111
2828
  )),
2112
- result && /* @__PURE__ */ import_react7.default.createElement("div", null, /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-center mb-6" }, /* @__PURE__ */ import_react7.default.createElement(
2829
+ result && /* @__PURE__ */ import_react10.default.createElement("div", null, /* @__PURE__ */ import_react10.default.createElement("div", { className: "text-center mb-6" }, /* @__PURE__ */ import_react10.default.createElement(
2113
2830
  "div",
2114
2831
  {
2115
2832
  className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
@@ -2118,13 +2835,13 @@ function V402Checkout({
2118
2835
  boxShadow: "0 4px 20px rgba(16, 185, 129, 0.3)"
2119
2836
  }
2120
2837
  },
2121
- /* @__PURE__ */ import_react7.default.createElement("span", { style: { fontSize: "32px", color: "white" } }, "\u2713")
2122
- ), /* @__PURE__ */ import_react7.default.createElement("div", null, /* @__PURE__ */ import_react7.default.createElement(Text, { strong: true, style: {
2838
+ /* @__PURE__ */ import_react10.default.createElement("span", { style: { fontSize: "32px", color: "white" } }, "\u2713")
2839
+ ), /* @__PURE__ */ import_react10.default.createElement("div", null, /* @__PURE__ */ import_react10.default.createElement(Text, { strong: true, style: {
2123
2840
  fontSize: "20px",
2124
2841
  color: "#262626",
2125
2842
  display: "block",
2126
2843
  marginBottom: "8px"
2127
- } }, "Payment Successful!"), /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c" } }, "Your transaction has been confirmed"))), /* @__PURE__ */ import_react7.default.createElement(import_antd.Divider, { style: { margin: "20px 0", borderColor: "#f0f0f0" } }, /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "12px", color: "#8c8c8c", fontWeight: 500 } }, "RESPONSE DATA")), /* @__PURE__ */ import_react7.default.createElement(
2844
+ } }, "Payment Successful!"), /* @__PURE__ */ import_react10.default.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c" } }, "Your transaction has been confirmed"))), /* @__PURE__ */ import_react10.default.createElement(import_antd.Divider, { style: { margin: "20px 0", borderColor: "#f0f0f0" } }, /* @__PURE__ */ import_react10.default.createElement(Text, { style: { fontSize: "12px", color: "#8c8c8c", fontWeight: 500 } }, "RESPONSE DATA")), /* @__PURE__ */ import_react10.default.createElement(
2128
2845
  "pre",
2129
2846
  {
2130
2847
  style: {
@@ -2144,7 +2861,7 @@ function V402Checkout({
2144
2861
  },
2145
2862
  JSON.stringify(result, null, 2)
2146
2863
  )),
2147
- error && /* @__PURE__ */ import_react7.default.createElement("div", null, /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-center mb-6" }, /* @__PURE__ */ import_react7.default.createElement(
2864
+ error && /* @__PURE__ */ import_react10.default.createElement("div", null, /* @__PURE__ */ import_react10.default.createElement("div", { className: "text-center mb-6" }, /* @__PURE__ */ import_react10.default.createElement(
2148
2865
  "div",
2149
2866
  {
2150
2867
  className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
@@ -2153,13 +2870,13 @@ function V402Checkout({
2153
2870
  boxShadow: "0 4px 20px rgba(239, 68, 68, 0.3)"
2154
2871
  }
2155
2872
  },
2156
- /* @__PURE__ */ import_react7.default.createElement("span", { style: { fontSize: "32px", color: "white" } }, "\u2717")
2157
- ), /* @__PURE__ */ import_react7.default.createElement("div", null, /* @__PURE__ */ import_react7.default.createElement(Text, { strong: true, style: {
2873
+ /* @__PURE__ */ import_react10.default.createElement("span", { style: { fontSize: "32px", color: "white" } }, "\u2717")
2874
+ ), /* @__PURE__ */ import_react10.default.createElement("div", null, /* @__PURE__ */ import_react10.default.createElement(Text, { strong: true, style: {
2158
2875
  fontSize: "20px",
2159
2876
  color: "#262626",
2160
2877
  display: "block",
2161
2878
  marginBottom: "8px"
2162
- } }, "Payment Failed"), /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c" } }, "Something went wrong with your transaction"))), /* @__PURE__ */ import_react7.default.createElement(import_antd.Divider, { style: { margin: "20px 0", borderColor: "#f0f0f0" } }, /* @__PURE__ */ import_react7.default.createElement(Text, { style: { fontSize: "12px", color: "#8c8c8c", fontWeight: 500 } }, "ERROR DETAILS")), /* @__PURE__ */ import_react7.default.createElement(
2879
+ } }, "Payment Failed"), /* @__PURE__ */ import_react10.default.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c" } }, "Something went wrong with your transaction"))), /* @__PURE__ */ import_react10.default.createElement(import_antd.Divider, { style: { margin: "20px 0", borderColor: "#f0f0f0" } }, /* @__PURE__ */ import_react10.default.createElement(Text, { style: { fontSize: "12px", color: "#8c8c8c", fontWeight: 500 } }, "ERROR DETAILS")), /* @__PURE__ */ import_react10.default.createElement(
2163
2880
  "div",
2164
2881
  {
2165
2882
  style: {
@@ -2169,13 +2886,13 @@ function V402Checkout({
2169
2886
  border: "1px solid #fee2e2"
2170
2887
  }
2171
2888
  },
2172
- /* @__PURE__ */ import_react7.default.createElement(Text, { style: {
2889
+ /* @__PURE__ */ import_react10.default.createElement(Text, { style: {
2173
2890
  fontSize: "14px",
2174
2891
  color: "#dc2626",
2175
2892
  lineHeight: "1.6",
2176
2893
  fontWeight: 500
2177
2894
  } }, error)
2178
- ), /* @__PURE__ */ import_react7.default.createElement("div", { className: "mt-4 text-center" }, /* @__PURE__ */ import_react7.default.createElement(
2895
+ ), /* @__PURE__ */ import_react10.default.createElement("div", { className: "mt-4 text-center" }, /* @__PURE__ */ import_react10.default.createElement(
2179
2896
  import_antd.Button,
2180
2897
  {
2181
2898
  size: "large",
@@ -2196,7 +2913,7 @@ function V402Checkout({
2196
2913
  )))
2197
2914
  )
2198
2915
  ),
2199
- /* @__PURE__ */ import_react7.default.createElement("style", { dangerouslySetInnerHTML: {
2916
+ /* @__PURE__ */ import_react10.default.createElement("style", { dangerouslySetInnerHTML: {
2200
2917
  __html: `
2201
2918
  @keyframes slideInRight {
2202
2919
  from {
@@ -2223,13 +2940,699 @@ function V402Checkout({
2223
2940
  } })
2224
2941
  );
2225
2942
  }
2943
+
2944
+ // src/react/components/checkout/V402CheckoutV2.tsx
2945
+ var import_react15 = __toESM(require("react"));
2946
+ init_common();
2947
+
2948
+ // src/react/styles/animations.tsx
2949
+ var import_react11 = __toESM(require("react"));
2950
+ var checkoutAnimations = `
2951
+ @keyframes spin {
2952
+ from { transform: rotate(0deg); }
2953
+ to { transform: rotate(360deg); }
2954
+ }
2955
+
2956
+ @keyframes receiptShake {
2957
+ 0%, 100% { transform: rotate(-0.3deg); }
2958
+ 50% { transform: rotate(0.3deg); }
2959
+ }
2960
+
2961
+ @keyframes slideInRight {
2962
+ from {
2963
+ opacity: 0;
2964
+ transform: translateX(100px);
2965
+ }
2966
+ to {
2967
+ opacity: 1;
2968
+ transform: translateX(0);
2969
+ }
2970
+ }
2971
+
2972
+ @keyframes pulse {
2973
+ 0%, 100% { opacity: 1; }
2974
+ 50% { opacity: 0.4; }
2975
+ }
2976
+ `;
2977
+ var AnimationStyles = () => /* @__PURE__ */ import_react11.default.createElement("style", { dangerouslySetInnerHTML: { __html: checkoutAnimations } });
2978
+
2979
+ // src/react/components/checkout/Receipt.tsx
2980
+ var import_react12 = __toESM(require("react"));
2981
+ var Receipt = ({
2982
+ isLoading,
2983
+ isVisible,
2984
+ result,
2985
+ error,
2986
+ paymentDetails,
2987
+ address,
2988
+ onClose,
2989
+ primaryColor,
2990
+ receiptTitle,
2991
+ tempReceiptId
2992
+ }) => {
2993
+ const [animationState, setAnimationState] = (0, import_react12.useState)("hidden");
2994
+ (0, import_react12.useEffect)(() => {
2995
+ if (isLoading) {
2996
+ setAnimationState("printing");
2997
+ } else if (isVisible && (result || error)) {
2998
+ setAnimationState("visible");
2999
+ const timer = setTimeout(() => setAnimationState("bounce"), 50);
3000
+ return () => clearTimeout(timer);
3001
+ } else if (!isVisible) {
3002
+ setAnimationState("hidden");
3003
+ }
3004
+ }, [isLoading, isVisible, result, error]);
3005
+ (0, import_react12.useEffect)(() => {
3006
+ if (animationState === "bounce") {
3007
+ const timer = setTimeout(() => setAnimationState("visible"), 150);
3008
+ return () => clearTimeout(timer);
3009
+ }
3010
+ }, [animationState]);
3011
+ const now = /* @__PURE__ */ new Date();
3012
+ const dateStr = `${String(now.getMonth() + 1).padStart(2, "0")}/${String(now.getDate()).padStart(2, "0")}/${String(now.getFullYear()).slice(-2)}`;
3013
+ const timeStr = `${String(now.getHours()).padStart(2, "0")}:${String(now.getMinutes()).padStart(2, "0")}`;
3014
+ const receiptId = result?.transactionHash ? result.transactionHash.slice(-8).toUpperCase() : tempReceiptId;
3015
+ const getAnimationStyles = () => {
3016
+ 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)";
3017
+ switch (animationState) {
3018
+ case "hidden":
3019
+ return {
3020
+ opacity: 0,
3021
+ transform: "translateY(50px)",
3022
+ marginBottom: 0,
3023
+ transition: baseTransition
3024
+ };
3025
+ case "printing":
3026
+ return {
3027
+ opacity: 1,
3028
+ transform: "translateY(0)",
3029
+ marginBottom: "-4px",
3030
+ // 负边距让小票贴着机器,还没撕开的感觉
3031
+ animation: "receiptShake 0.12s ease-in-out infinite",
3032
+ transition: baseTransition
3033
+ };
3034
+ case "visible":
3035
+ return {
3036
+ opacity: 1,
3037
+ transform: "translateY(0)",
3038
+ marginBottom: "8px",
3039
+ transition: baseTransition
3040
+ };
3041
+ case "bounce":
3042
+ return {
3043
+ opacity: 1,
3044
+ transform: "translateY(-8px)",
3045
+ marginBottom: "8px",
3046
+ transition: baseTransition
3047
+ };
3048
+ default:
3049
+ return {};
3050
+ }
3051
+ };
3052
+ const getContentStyles = () => {
3053
+ const baseTransition = "all 0.5s cubic-bezier(0.34, 1.56, 0.64, 1)";
3054
+ switch (animationState) {
3055
+ case "hidden":
3056
+ return {
3057
+ maxHeight: 0,
3058
+ overflow: "hidden",
3059
+ transition: baseTransition
3060
+ };
3061
+ case "printing":
3062
+ return {
3063
+ maxHeight: "80px",
3064
+ overflow: "hidden",
3065
+ transition: baseTransition
3066
+ };
3067
+ case "visible":
3068
+ case "bounce":
3069
+ return {
3070
+ maxHeight: "600px",
3071
+ overflow: "visible",
3072
+ transition: baseTransition
3073
+ };
3074
+ default:
3075
+ return {};
3076
+ }
3077
+ };
3078
+ if (animationState === "hidden" && !isLoading) return null;
3079
+ return /* @__PURE__ */ import_react12.default.createElement(
3080
+ "div",
3081
+ {
3082
+ className: "w-full flex justify-center",
3083
+ style: getAnimationStyles()
3084
+ },
3085
+ /* @__PURE__ */ import_react12.default.createElement(
3086
+ "div",
3087
+ {
3088
+ className: "relative bg-white shadow-2xl",
3089
+ style: {
3090
+ width: "75%",
3091
+ maxWidth: "280px",
3092
+ backgroundImage: `
3093
+ repeating-linear-gradient(
3094
+ 0deg,
3095
+ transparent,
3096
+ transparent 1px,
3097
+ rgba(0,0,0,0.02) 1px,
3098
+ rgba(0,0,0,0.02) 2px
3099
+ )
3100
+ `
3101
+ }
3102
+ },
3103
+ /* @__PURE__ */ import_react12.default.createElement(
3104
+ "div",
3105
+ {
3106
+ className: "absolute top-0 left-0 right-0",
3107
+ style: {
3108
+ height: "8px",
3109
+ transform: "translateY(-100%)",
3110
+ background: `radial-gradient(circle at 50% 100%, white 5px, transparent 5px)`,
3111
+ backgroundSize: "12px 8px",
3112
+ backgroundPosition: "6px 0",
3113
+ backgroundRepeat: "repeat-x"
3114
+ }
3115
+ }
3116
+ ),
3117
+ /* @__PURE__ */ import_react12.default.createElement(
3118
+ "div",
3119
+ {
3120
+ className: "absolute left-0 right-0 bg-white",
3121
+ style: {
3122
+ height: "4px",
3123
+ top: "-4px"
3124
+ }
3125
+ }
3126
+ ),
3127
+ !isLoading && /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, null, /* @__PURE__ */ import_react12.default.createElement(
3128
+ "div",
3129
+ {
3130
+ className: "absolute bottom-0 left-0 right-0",
3131
+ style: {
3132
+ height: "8px",
3133
+ transform: "translateY(100%)",
3134
+ background: `radial-gradient(circle at 50% 0%, white 5px, transparent 5px)`,
3135
+ backgroundSize: "12px 8px",
3136
+ backgroundPosition: "6px 0",
3137
+ backgroundRepeat: "repeat-x"
3138
+ }
3139
+ }
3140
+ ), /* @__PURE__ */ import_react12.default.createElement(
3141
+ "div",
3142
+ {
3143
+ className: "absolute left-0 right-0 bg-white",
3144
+ style: {
3145
+ height: "4px",
3146
+ bottom: "-4px"
3147
+ }
3148
+ }
3149
+ )),
3150
+ !isLoading && (result || error) && /* @__PURE__ */ import_react12.default.createElement(
3151
+ "button",
3152
+ {
3153
+ onClick: onClose,
3154
+ 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",
3155
+ style: { background: "none", border: "none" }
3156
+ },
3157
+ /* @__PURE__ */ import_react12.default.createElement("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" }, /* @__PURE__ */ import_react12.default.createElement("path", { d: "M18 6L6 18M6 6l12 12" }))
3158
+ ),
3159
+ /* @__PURE__ */ import_react12.default.createElement("div", { className: "p-4 font-mono text-sm", style: getContentStyles() }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-center mb-3" }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-base font-bold tracking-wider text-gray-800" }, receiptTitle), /* @__PURE__ */ import_react12.default.createElement("div", { className: "flex justify-between text-xs text-gray-500 mt-1" }, /* @__PURE__ */ import_react12.default.createElement("span", null, "ID: ", receiptId), /* @__PURE__ */ import_react12.default.createElement("span", null, dateStr, " ", timeStr))), /* @__PURE__ */ import_react12.default.createElement("div", { className: "border-t border-dashed border-gray-300 my-2" }), /* @__PURE__ */ import_react12.default.createElement(
3160
+ "div",
3161
+ {
3162
+ className: "max-h-64 overflow-y-auto pr-1",
3163
+ style: {
3164
+ scrollbarWidth: "thin",
3165
+ scrollbarColor: "#d1d5db transparent"
3166
+ }
3167
+ },
3168
+ isLoading ? /* @__PURE__ */ import_react12.default.createElement(LoadingContent, { primaryColor }) : error ? /* @__PURE__ */ import_react12.default.createElement(ErrorContent, { error }) : result ? /* @__PURE__ */ import_react12.default.createElement(
3169
+ SuccessContent,
3170
+ {
3171
+ result,
3172
+ paymentDetails,
3173
+ address,
3174
+ primaryColor
3175
+ }
3176
+ ) : null
3177
+ ), /* @__PURE__ */ import_react12.default.createElement("div", { className: "border-t border-dashed border-gray-300 my-2" }), /* @__PURE__ */ import_react12.default.createElement(Barcode, null), /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-center text-xs text-gray-400 mt-1 tracking-widest" }, "POWERED BY", " ", /* @__PURE__ */ import_react12.default.createElement(
3178
+ "a",
3179
+ {
3180
+ href: "https://v402pay.onvoyage.ai",
3181
+ target: "_blank",
3182
+ rel: "noopener noreferrer",
3183
+ className: "text-gray-500 hover:text-gray-700 underline transition-colors"
3184
+ },
3185
+ "V402PAY"
3186
+ )))
3187
+ )
3188
+ );
3189
+ };
3190
+ var LoadingContent = ({ primaryColor }) => /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-center py-4" }, /* @__PURE__ */ import_react12.default.createElement(
3191
+ "div",
3192
+ {
3193
+ className: "inline-block w-8 h-8 border-2 border-gray-200 rounded-full mb-2",
3194
+ style: {
3195
+ borderTopColor: primaryColor,
3196
+ animation: "spin 0.8s linear infinite"
3197
+ }
3198
+ }
3199
+ ), /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-gray-700 font-semibold text-sm" }, "Processing..."), /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-gray-400 text-xs mt-1" }, "Please wait"));
3200
+ var ErrorContent = ({ error }) => /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-center py-3" }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-red-500 text-2xl mb-2" }, "\u2717"), /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-red-600 font-semibold mb-1 text-sm" }, "FAILED"), /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-red-500 text-xs break-words px-2" }, error));
3201
+ var SuccessContent = ({
3202
+ result,
3203
+ paymentDetails,
3204
+ address,
3205
+ primaryColor
3206
+ }) => {
3207
+ const [copied, setCopied] = (0, import_react12.useState)(false);
3208
+ const handleCopy = async () => {
3209
+ try {
3210
+ await navigator.clipboard.writeText(JSON.stringify(result, null, 2));
3211
+ setCopied(true);
3212
+ setTimeout(() => setCopied(false), 2e3);
3213
+ } catch (err) {
3214
+ console.error("Failed to copy:", err);
3215
+ }
3216
+ };
3217
+ return /* @__PURE__ */ import_react12.default.createElement("div", null, /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-center mb-2" }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-2xl mb-1", style: { color: primaryColor } }, "\u2713"), /* @__PURE__ */ import_react12.default.createElement("div", { className: "font-semibold text-sm", style: { color: primaryColor } }, "SUCCESS")), /* @__PURE__ */ import_react12.default.createElement("div", { className: "space-y-1 text-xs" }, paymentDetails && /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, null, /* @__PURE__ */ import_react12.default.createElement("div", { className: "flex justify-between" }, /* @__PURE__ */ import_react12.default.createElement("span", { className: "text-gray-500" }, "Amount:"), /* @__PURE__ */ import_react12.default.createElement("span", { className: "font-semibold" }, "$", paymentDetails.amount, " ", paymentDetails.currency)), /* @__PURE__ */ import_react12.default.createElement("div", { className: "flex justify-between" }, /* @__PURE__ */ import_react12.default.createElement("span", { className: "text-gray-500" }, "Network:"), /* @__PURE__ */ import_react12.default.createElement("span", { className: "font-semibold" }, paymentDetails.network))), address && /* @__PURE__ */ import_react12.default.createElement("div", { className: "flex justify-between" }, /* @__PURE__ */ import_react12.default.createElement("span", { className: "text-gray-500" }, "From:"), /* @__PURE__ */ import_react12.default.createElement("span", { className: "font-semibold" }, formatAddress(address))), result.transactionHash && /* @__PURE__ */ import_react12.default.createElement("div", { className: "flex justify-between" }, /* @__PURE__ */ import_react12.default.createElement("span", { className: "text-gray-500" }, "TX:"), /* @__PURE__ */ import_react12.default.createElement("span", { className: "font-semibold" }, formatAddress(result.transactionHash)))), /* @__PURE__ */ import_react12.default.createElement("div", { className: "border-t border-dashed border-gray-300 my-2" }), /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-xs" }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "flex justify-between items-center mb-1" }, /* @__PURE__ */ import_react12.default.createElement("span", { className: "text-gray-500" }, "Response:"), /* @__PURE__ */ import_react12.default.createElement(
3218
+ "button",
3219
+ {
3220
+ onClick: handleCopy,
3221
+ 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",
3222
+ style: { background: "none", border: "none" }
3223
+ },
3224
+ copied ? /* @__PURE__ */ import_react12.default.createElement("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" }, /* @__PURE__ */ import_react12.default.createElement("path", { d: "M20 6L9 17l-5-5" })) : /* @__PURE__ */ import_react12.default.createElement("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }, /* @__PURE__ */ import_react12.default.createElement("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }), /* @__PURE__ */ import_react12.default.createElement("path", { d: "M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1" }))
3225
+ )), /* @__PURE__ */ import_react12.default.createElement(
3226
+ "pre",
3227
+ {
3228
+ className: "bg-gray-50 p-2 rounded text-xs overflow-auto whitespace-pre-wrap break-words",
3229
+ style: { maxHeight: "80px", fontSize: "10px" }
3230
+ },
3231
+ JSON.stringify(result, null, 2)
3232
+ )));
3233
+ };
3234
+ var Barcode = () => {
3235
+ const pattern = [2, 1, 2, 1, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 1];
3236
+ const heights = [10, 12, 11, 13, 10, 14, 11, 12, 13, 10, 11, 14, 12, 10, 13, 11, 12, 14, 10, 11];
3237
+ return /* @__PURE__ */ import_react12.default.createElement("div", { className: "flex items-center justify-center gap-0.5 h-4 opacity-60" }, pattern.map((width, i) => /* @__PURE__ */ import_react12.default.createElement(
3238
+ "div",
3239
+ {
3240
+ key: i,
3241
+ className: "bg-gray-800",
3242
+ style: {
3243
+ width: `${width}px`,
3244
+ height: `${heights[i]}px`
3245
+ }
3246
+ }
3247
+ )));
3248
+ };
3249
+
3250
+ // src/react/components/checkout/TerminalScreen.tsx
3251
+ var import_react13 = __toESM(require("react"));
3252
+ var TerminalScreen = ({
3253
+ title,
3254
+ tooltipText,
3255
+ hasInvalidCheckoutId,
3256
+ fetchingPaymentInfo,
3257
+ address,
3258
+ paymentDetails,
3259
+ screenText,
3260
+ supportedNetworks
3261
+ }) => {
3262
+ return /* @__PURE__ */ import_react13.default.createElement(
3263
+ "div",
3264
+ {
3265
+ className: "rounded-xl p-3 mb-3",
3266
+ style: {
3267
+ backgroundColor: "#0a1a0a",
3268
+ boxShadow: "inset 0 3px 16px rgba(0,0,0,0.5)",
3269
+ border: "3px solid rgba(0,0,0,0.3)"
3270
+ }
3271
+ },
3272
+ /* @__PURE__ */ import_react13.default.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ import_react13.default.createElement("div", { className: "flex items-center gap-1.5 flex-1 min-w-0" }, /* @__PURE__ */ import_react13.default.createElement("div", { className: "w-2.5 h-2.5 rounded border border-green-700 flex-shrink-0" }), title ? /* @__PURE__ */ import_react13.default.createElement(
3273
+ "span",
3274
+ {
3275
+ className: "text-xs font-mono",
3276
+ style: { color: "#22c55e80" },
3277
+ title
3278
+ },
3279
+ title.length > 26 ? `${title.slice(0, 13)}...${title.slice(-13)}` : title
3280
+ ) : /* @__PURE__ */ import_react13.default.createElement("span", { className: "text-xs font-mono", style: { color: "#22c55e80" } }, "CHECKOUT")), /* @__PURE__ */ import_react13.default.createElement(
3281
+ "div",
3282
+ {
3283
+ className: "flex gap-0.5 flex-shrink-0 cursor-help",
3284
+ title: tooltipText
3285
+ },
3286
+ /* @__PURE__ */ import_react13.default.createElement(
3287
+ "div",
3288
+ {
3289
+ className: "w-1 h-1.5 rounded-sm",
3290
+ style: { backgroundColor: address ? "#22c55e80" : "#22c55e30" }
3291
+ }
3292
+ ),
3293
+ /* @__PURE__ */ import_react13.default.createElement(
3294
+ "div",
3295
+ {
3296
+ className: "w-1 h-1.5 rounded-sm",
3297
+ style: { backgroundColor: address ? "#22c55e80" : "#22c55e30" }
3298
+ }
3299
+ ),
3300
+ /* @__PURE__ */ import_react13.default.createElement("div", { className: "w-1 h-1.5 rounded-sm", style: { backgroundColor: "#22c55e80" } })
3301
+ )),
3302
+ /* @__PURE__ */ import_react13.default.createElement("div", { className: "min-h-[120px]" }, hasInvalidCheckoutId ? /* @__PURE__ */ import_react13.default.createElement(InvalidIdContent, null) : fetchingPaymentInfo ? /* @__PURE__ */ import_react13.default.createElement(LoadingContent2, null) : !address ? /* @__PURE__ */ import_react13.default.createElement(ConnectWalletContent, { supportedNetworks }) : /* @__PURE__ */ import_react13.default.createElement(
3303
+ PaymentInfoContent,
3304
+ {
3305
+ screenText,
3306
+ paymentDetails,
3307
+ address
3308
+ }
3309
+ ))
3310
+ );
3311
+ };
3312
+ var InvalidIdContent = () => /* @__PURE__ */ import_react13.default.createElement("div", { className: "text-center py-3" }, /* @__PURE__ */ import_react13.default.createElement("div", { className: "text-red-500 text-xl mb-1" }, "\u2717"), /* @__PURE__ */ import_react13.default.createElement("div", { className: "text-red-500 font-mono text-sm mb-1" }, "INVALID ID"), /* @__PURE__ */ import_react13.default.createElement("div", { className: "text-red-400 font-mono text-xs" }, "Check your checkout ID"));
3313
+ var LoadingContent2 = () => /* @__PURE__ */ import_react13.default.createElement("div", { className: "text-center py-4" }, /* @__PURE__ */ import_react13.default.createElement(
3314
+ "div",
3315
+ {
3316
+ className: "inline-block w-5 h-5 border-2 rounded-full mb-2",
3317
+ style: {
3318
+ borderColor: "#22c55e40",
3319
+ borderTopColor: "#22c55e",
3320
+ animation: "spin 1s linear infinite"
3321
+ }
3322
+ }
3323
+ ), /* @__PURE__ */ import_react13.default.createElement("div", { className: "font-mono text-sm", style: { color: "#22c55e" } }, "LOADING..."));
3324
+ var ConnectWalletContent = ({ supportedNetworks }) => /* @__PURE__ */ import_react13.default.createElement("div", null, /* @__PURE__ */ import_react13.default.createElement(
3325
+ "div",
3326
+ {
3327
+ className: "font-mono text-base mb-3 tracking-wider",
3328
+ style: { color: "#f97316", textShadow: "0 0 10px #f9731640" }
3329
+ },
3330
+ "CONNECT WALLET..."
3331
+ ), /* @__PURE__ */ import_react13.default.createElement(WalletConnect, { supportedNetworks, showSwitchWallet: false }));
3332
+ var PaymentInfoContent = ({
3333
+ screenText,
3334
+ paymentDetails,
3335
+ address
3336
+ }) => /* @__PURE__ */ import_react13.default.createElement("div", null, /* @__PURE__ */ import_react13.default.createElement(
3337
+ "div",
3338
+ {
3339
+ className: "font-mono text-base mb-3 tracking-wider",
3340
+ style: { color: "#f97316", textShadow: "0 0 10px #f9731640" }
3341
+ },
3342
+ screenText
3343
+ ), paymentDetails && /* @__PURE__ */ import_react13.default.createElement("div", { className: "text-xs font-mono" }, /* @__PURE__ */ import_react13.default.createElement("div", { className: "grid grid-cols-2 gap-1.5 mb-1.5" }, /* @__PURE__ */ import_react13.default.createElement("div", null, /* @__PURE__ */ import_react13.default.createElement("div", { style: { color: "#22c55e60" } }, "AMOUNT"), /* @__PURE__ */ import_react13.default.createElement("div", { style: { color: "#22c55e" } }, "$", paymentDetails.amount)), /* @__PURE__ */ import_react13.default.createElement("div", null, /* @__PURE__ */ import_react13.default.createElement("div", { style: { color: "#22c55e60" } }, "CURRENCY"), /* @__PURE__ */ import_react13.default.createElement("div", { style: { color: "#22c55e" } }, paymentDetails.currency))), /* @__PURE__ */ import_react13.default.createElement("div", null, /* @__PURE__ */ import_react13.default.createElement("div", { style: { color: "#22c55e60" } }, "WALLET"), /* @__PURE__ */ import_react13.default.createElement("div", { style: { color: "#22c55e", wordBreak: "break-all" } }, address))));
3344
+
3345
+ // src/react/components/checkout/TerminalButtons.tsx
3346
+ var import_react14 = __toESM(require("react"));
3347
+ var TerminalButtons = ({
3348
+ address,
3349
+ showReceipt,
3350
+ isProcessing,
3351
+ paymentDetails,
3352
+ hasInvalidCheckoutId,
3353
+ onDisconnect,
3354
+ onClearReceipt,
3355
+ onPayment
3356
+ }) => {
3357
+ const isPayDisabled = isProcessing || !paymentDetails || !address || hasInvalidCheckoutId;
3358
+ return /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center justify-between px-1" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ import_react14.default.createElement(
3359
+ CircleButton,
3360
+ {
3361
+ onClick: () => address && onDisconnect(),
3362
+ disabled: !address,
3363
+ title: "Disconnect",
3364
+ size: "small"
3365
+ },
3366
+ /* @__PURE__ */ import_react14.default.createElement("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "white", strokeWidth: "2" }, /* @__PURE__ */ import_react14.default.createElement("path", { d: "M18 6L6 18M6 6l12 12" }))
3367
+ ), /* @__PURE__ */ import_react14.default.createElement(
3368
+ CircleButton,
3369
+ {
3370
+ onClick: onClearReceipt,
3371
+ disabled: !showReceipt || isProcessing,
3372
+ title: "Clear",
3373
+ size: "small"
3374
+ },
3375
+ /* @__PURE__ */ import_react14.default.createElement("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "white", strokeWidth: "2" }, /* @__PURE__ */ import_react14.default.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" }))
3376
+ )), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex flex-col gap-0.5 opacity-40" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "w-6 h-0.5 rounded", style: { backgroundColor: "rgba(0,0,0,0.3)" } }), /* @__PURE__ */ import_react14.default.createElement("div", { className: "w-6 h-0.5 rounded", style: { backgroundColor: "rgba(0,0,0,0.3)" } }), /* @__PURE__ */ import_react14.default.createElement("div", { className: "w-6 h-0.5 rounded", style: { backgroundColor: "rgba(0,0,0,0.3)" } })), /* @__PURE__ */ import_react14.default.createElement(
3377
+ "button",
3378
+ {
3379
+ onClick: onPayment,
3380
+ disabled: isPayDisabled,
3381
+ className: "px-5 py-2.5 rounded-xl font-bold text-white flex items-center gap-2 transition-all active:scale-95",
3382
+ style: {
3383
+ backgroundColor: isPayDisabled ? "#9ca3af" : "#ea580c",
3384
+ boxShadow: isPayDisabled ? "none" : "0 4px 12px rgba(234,88,12,0.4), inset 0 -2px 4px rgba(0,0,0,0.2)",
3385
+ cursor: isPayDisabled ? "not-allowed" : "pointer"
3386
+ }
3387
+ },
3388
+ isProcessing ? /* @__PURE__ */ import_react14.default.createElement(import_react14.default.Fragment, null, /* @__PURE__ */ import_react14.default.createElement(
3389
+ "div",
3390
+ {
3391
+ className: "w-4 h-4 border-2 border-white/30 border-t-white rounded-full",
3392
+ style: { animation: "spin 0.8s linear infinite" }
3393
+ }
3394
+ ), /* @__PURE__ */ import_react14.default.createElement("span", { className: "font-mono tracking-wider text-sm" }, "PAYING...")) : /* @__PURE__ */ import_react14.default.createElement(import_react14.default.Fragment, null, /* @__PURE__ */ import_react14.default.createElement("span", { className: "font-mono tracking-wider text-sm" }, "PAY"), /* @__PURE__ */ import_react14.default.createElement(
3395
+ "svg",
3396
+ {
3397
+ width: "18",
3398
+ height: "18",
3399
+ viewBox: "0 0 24 24",
3400
+ fill: "none",
3401
+ stroke: "currentColor",
3402
+ strokeWidth: "2"
3403
+ },
3404
+ /* @__PURE__ */ import_react14.default.createElement("path", { d: "M12 2v20M17 5H9.5a3.5 3.5 0 000 7h5a3.5 3.5 0 010 7H6" })
3405
+ ))
3406
+ ));
3407
+ };
3408
+ var CircleButton = ({ onClick, disabled, title, size = "normal", children }) => {
3409
+ const sizeClass = size === "small" ? "w-10 h-10" : "w-12 h-12";
3410
+ return /* @__PURE__ */ import_react14.default.createElement(
3411
+ "button",
3412
+ {
3413
+ onClick,
3414
+ disabled,
3415
+ className: `${sizeClass} rounded-full flex items-center justify-center transition-transform active:scale-95`,
3416
+ style: {
3417
+ backgroundColor: "#374151",
3418
+ boxShadow: "inset 0 -2px 4px rgba(0,0,0,0.3), 0 2px 4px rgba(0,0,0,0.2)",
3419
+ opacity: disabled ? 0.5 : 1
3420
+ },
3421
+ title
3422
+ },
3423
+ children
3424
+ );
3425
+ };
3426
+
3427
+ // src/react/components/checkout/V402CheckoutV2.tsx
3428
+ var generateRandomId = () => {
3429
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
3430
+ return Array.from({ length: 8 }, () => chars[Math.floor(Math.random() * chars.length)]).join("");
3431
+ };
3432
+ function V402CheckoutV2({
3433
+ checkoutId,
3434
+ headerInfo = {},
3435
+ primaryColor = "#84cc16",
3436
+ isModal = false,
3437
+ onPaymentComplete,
3438
+ additionalParams = {},
3439
+ expectedNetwork
3440
+ }) {
3441
+ const {
3442
+ title = "V402Pay Checkout",
3443
+ brandName = "V402PAY",
3444
+ receiptTitle = "V402 PAYMENT",
3445
+ tooltipText = "V402Pay - Accept Crypto Payments Easier"
3446
+ } = headerInfo;
3447
+ const endpoint = PROD_BACK_URL;
3448
+ const {
3449
+ supportedNetworks,
3450
+ isLoading: fetchingPaymentInfo,
3451
+ paymentInfo
3452
+ } = usePaymentInfo(checkoutId, endpoint, additionalParams);
3453
+ const targetNetwork = expectedNetwork || supportedNetworks[0];
3454
+ const { address, networkType, disconnect, ensureNetwork } = usePageNetwork(
3455
+ targetNetwork,
3456
+ { autoSwitch: !!targetNetwork, switchOnMount: true }
3457
+ );
3458
+ const { isProcessing, setIsProcessing, result, setResult, error, setError } = usePayment();
3459
+ const [paymentDetails, setPaymentDetails] = (0, import_react15.useState)(null);
3460
+ const [showReceipt, setShowReceipt] = (0, import_react15.useState)(false);
3461
+ const [tempReceiptId, setTempReceiptId] = (0, import_react15.useState)(() => generateRandomId());
3462
+ const handleDisconnect = () => {
3463
+ disconnect();
3464
+ setResult(null);
3465
+ setError(null);
3466
+ setShowReceipt(false);
3467
+ };
3468
+ const handlePayment = async () => {
3469
+ if (!networkType) return;
3470
+ setTempReceiptId(generateRandomId());
3471
+ setResult(null);
3472
+ setError(null);
3473
+ setIsProcessing(true);
3474
+ setShowReceipt(true);
3475
+ try {
3476
+ const response = await makePayment(networkType, checkoutId, endpoint, additionalParams, address || void 0);
3477
+ const data = await response.json();
3478
+ setResult(data);
3479
+ if (onPaymentComplete) {
3480
+ onPaymentComplete(data);
3481
+ }
3482
+ } catch (err) {
3483
+ setError(err.message || "Payment failed");
3484
+ } finally {
3485
+ setIsProcessing(false);
3486
+ }
3487
+ };
3488
+ const handleCloseReceipt = () => {
3489
+ setShowReceipt(false);
3490
+ setResult(null);
3491
+ setError(null);
3492
+ };
3493
+ (0, import_react15.useEffect)(() => {
3494
+ if (paymentInfo && paymentInfo.length > 0) {
3495
+ const firstPayment = paymentInfo[0];
3496
+ const rawAmount = firstPayment.maxAmountRequired?.toString() || "0";
3497
+ const decimals = 6;
3498
+ const humanReadableAmount = (Number(rawAmount) / Math.pow(10, decimals)).toFixed(2);
3499
+ const network = firstPayment.network || "Unknown";
3500
+ const currency = "USDC";
3501
+ setPaymentDetails({ amount: humanReadableAmount, currency, network });
3502
+ }
3503
+ }, [paymentInfo]);
3504
+ (0, import_react15.useEffect)(() => {
3505
+ if (targetNetwork && !fetchingPaymentInfo && ensureNetwork) {
3506
+ ensureNetwork(targetNetwork).catch((err) => {
3507
+ console.error("Failed to ensure network:", err);
3508
+ });
3509
+ }
3510
+ }, [targetNetwork, fetchingPaymentInfo]);
3511
+ (0, import_react15.useEffect)(() => {
3512
+ if (isProcessing || result || error) {
3513
+ setShowReceipt(true);
3514
+ }
3515
+ }, [isProcessing, result, error]);
3516
+ const hasInvalidCheckoutId = !fetchingPaymentInfo && (!paymentInfo || paymentInfo.length === 0);
3517
+ const NetworkIcon = paymentDetails ? getNetworkIcon(paymentDetails.network) : null;
3518
+ const screenText = paymentDetails ? `PAY $${paymentDetails.amount} ${paymentDetails.currency}` : "AWAITING...";
3519
+ const getStatusText = () => {
3520
+ if (hasInvalidCheckoutId) return "ERROR";
3521
+ if (fetchingPaymentInfo) return "LOADING";
3522
+ if (!address) return "CONNECT";
3523
+ if (isProcessing) return "PAYING";
3524
+ return "READY";
3525
+ };
3526
+ return /* @__PURE__ */ import_react15.default.createElement("div", { className: isModal ? "bg-transparent" : "min-h-screen bg-gray-100 flex items-center justify-center p-4" }, /* @__PURE__ */ import_react15.default.createElement(
3527
+ "div",
3528
+ {
3529
+ className: "flex flex-col items-center",
3530
+ style: { width: isModal ? "100%" : "380px", maxWidth: "100%" }
3531
+ },
3532
+ /* @__PURE__ */ import_react15.default.createElement(
3533
+ Receipt,
3534
+ {
3535
+ isLoading: isProcessing,
3536
+ isVisible: showReceipt,
3537
+ result,
3538
+ error,
3539
+ paymentDetails,
3540
+ address,
3541
+ onClose: handleCloseReceipt,
3542
+ primaryColor,
3543
+ receiptTitle,
3544
+ tempReceiptId
3545
+ }
3546
+ ),
3547
+ /* @__PURE__ */ import_react15.default.createElement(
3548
+ "div",
3549
+ {
3550
+ className: "relative rounded-2xl p-3 shadow-2xl w-full",
3551
+ style: {
3552
+ backgroundColor: primaryColor,
3553
+ boxShadow: `0 16px 48px -8px ${primaryColor}66, 0 8px 24px -4px rgba(0,0,0,0.3);padding-bottom: 0px`
3554
+ }
3555
+ },
3556
+ /* @__PURE__ */ import_react15.default.createElement(
3557
+ "div",
3558
+ {
3559
+ className: "absolute top-0 left-1/2 -translate-x-1/2 w-1/3 h-2.5 rounded-b-lg",
3560
+ style: { backgroundColor: "rgba(0,0,0,0.4)" }
3561
+ }
3562
+ ),
3563
+ /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex justify-between items-center mb-2 mt-1 px-1" }, /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react15.default.createElement(
3564
+ "div",
3565
+ {
3566
+ className: "w-2 h-2 rounded-full",
3567
+ style: {
3568
+ backgroundColor: address ? "#22c55e" : "#ef4444",
3569
+ animation: "pulse 2s ease-in-out infinite"
3570
+ }
3571
+ }
3572
+ ), /* @__PURE__ */ import_react15.default.createElement(
3573
+ "span",
3574
+ {
3575
+ className: "text-xs font-mono font-bold tracking-wider",
3576
+ style: { color: "rgba(0,0,0,0.7)" }
3577
+ },
3578
+ getStatusText()
3579
+ )), /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex items-center gap-1.5" }, paymentDetails && NetworkIcon && /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react15.default.createElement(NetworkIcon, { width: 12, height: 12, style: { color: "rgba(0,0,0,0.7)" } }), /* @__PURE__ */ import_react15.default.createElement("span", { className: "text-xs font-mono font-bold", style: { color: "rgba(0,0,0,0.7)" } }, paymentDetails.network)))),
3580
+ /* @__PURE__ */ import_react15.default.createElement(
3581
+ TerminalScreen,
3582
+ {
3583
+ title,
3584
+ tooltipText,
3585
+ hasInvalidCheckoutId,
3586
+ fetchingPaymentInfo,
3587
+ address,
3588
+ paymentDetails,
3589
+ screenText,
3590
+ supportedNetworks
3591
+ }
3592
+ ),
3593
+ /* @__PURE__ */ import_react15.default.createElement(
3594
+ TerminalButtons,
3595
+ {
3596
+ address,
3597
+ showReceipt,
3598
+ isProcessing,
3599
+ paymentDetails,
3600
+ hasInvalidCheckoutId,
3601
+ onDisconnect: handleDisconnect,
3602
+ onClearReceipt: handleCloseReceipt,
3603
+ onPayment: handlePayment
3604
+ }
3605
+ ),
3606
+ brandName && /* @__PURE__ */ import_react15.default.createElement("div", { className: "text-center mt-0 mb-0" }, /* @__PURE__ */ import_react15.default.createElement(
3607
+ "div",
3608
+ {
3609
+ className: "inline-block px-2 py-0.5 rounded text-[10px] font-mono font-bold tracking-[0.2em]",
3610
+ style: {
3611
+ backgroundColor: "#1a1a1a",
3612
+ color: "#9acd32",
3613
+ boxShadow: "inset 0 1px 3px rgba(0,0,0,0.8), 0 1px 0 rgba(255,255,255,0.1)",
3614
+ border: "1px solid rgba(0,0,0,0.5)",
3615
+ textShadow: "0 0 4px #9acd3280"
3616
+ }
3617
+ },
3618
+ brandName
3619
+ ))
3620
+ )
3621
+ ), /* @__PURE__ */ import_react15.default.createElement(AnimationStyles, null));
3622
+ }
2226
3623
  // Annotate the CommonJS export names for ESM import in node:
2227
3624
  0 && (module.exports = {
3625
+ AnimationStyles,
3626
+ Toast,
2228
3627
  V402Checkout,
3628
+ V402CheckoutV2,
2229
3629
  WalletConnect,
3630
+ WalletSelectModal,
3631
+ checkoutAnimations,
2230
3632
  usePageNetwork,
2231
3633
  usePayment,
2232
3634
  usePaymentInfo,
3635
+ useToast,
2233
3636
  useWallet
2234
3637
  });
2235
3638
  //# sourceMappingURL=index.js.map