@voyage_ai/v402-web-ts 0.3.0 → 1.0.2

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.
@@ -103,17 +103,21 @@ __export(wallet_exports, {
103
103
  clearAllWalletAddresses: () => clearAllWalletAddresses,
104
104
  clearWalletDisconnection: () => clearWalletDisconnection,
105
105
  formatAddress: () => formatAddress,
106
+ getAllConnectedWalletIds: () => getAllConnectedWalletIds,
106
107
  getAllWalletAddresses: () => getAllWalletAddresses,
107
108
  getCachedWalletAddress: () => getCachedWalletAddress,
108
109
  getConnectedNetworkType: () => getConnectedNetworkType,
110
+ getConnectedWalletId: () => getConnectedWalletId,
109
111
  getWalletDisplayName: () => getWalletDisplayName,
110
112
  getWalletInstallUrl: () => getWalletInstallUrl,
111
113
  getWalletProvider: () => getWalletProvider,
112
114
  isWalletInstalled: () => isWalletInstalled,
113
115
  isWalletManuallyDisconnected: () => isWalletManuallyDisconnected,
114
116
  markWalletDisconnected: () => markWalletDisconnected,
117
+ removeConnectedWalletId: () => removeConnectedWalletId,
115
118
  removeWalletAddress: () => removeWalletAddress,
116
119
  saveConnectedNetworkType: () => saveConnectedNetworkType,
120
+ saveConnectedWalletId: () => saveConnectedWalletId,
117
121
  saveWalletAddress: () => saveWalletAddress
118
122
  });
119
123
  function isWalletInstalled(networkType) {
@@ -266,7 +270,39 @@ function clearAllWalletAddresses() {
266
270
  localStorage.removeItem(WALLET_ADDRESSES_KEY);
267
271
  }
268
272
  }
269
- var WALLET_DISCONNECTED_KEY, WALLET_DISCONNECTED_NETWORKS_KEY, CONNECTED_NETWORK_TYPE_KEY, WALLET_ADDRESSES_KEY;
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;
270
306
  var init_wallet = __esm({
271
307
  "src/utils/wallet.ts"() {
272
308
  "use strict";
@@ -274,18 +310,332 @@ var init_wallet = __esm({
274
310
  WALLET_DISCONNECTED_NETWORKS_KEY = "wallet_disconnected_networks";
275
311
  CONNECTED_NETWORK_TYPE_KEY = "connected_network_type";
276
312
  WALLET_ADDRESSES_KEY = "wallet_addresses_cache";
313
+ CONNECTED_WALLET_IDS_KEY = "connected_wallet_ids";
314
+ }
315
+ });
316
+
317
+ // src/utils/wallet-discovery.ts
318
+ var wallet_discovery_exports = {};
319
+ __export(wallet_discovery_exports, {
320
+ clearConnectedWallet: () => clearConnectedWallet,
321
+ connectEVMWallet: () => connectEVMWallet,
322
+ connectSolanaWallet: () => connectSolanaWallet,
323
+ connectToWallet: () => connectToWallet,
324
+ getCurrentConnectedWallet: () => getCurrentConnectedWallet,
325
+ getEVMWallets: () => getEVMWallets,
326
+ getSolanaWallets: () => getSolanaWallets,
327
+ getValidatedWalletProvider: () => getValidatedWalletProvider,
328
+ getWalletById: () => getWalletById,
329
+ getWalletByName: () => getWalletByName,
330
+ getWalletProviderForPayment: () => getWalletProviderForPayment,
331
+ getWalletsForNetwork: () => getWalletsForNetwork,
332
+ initEVMWalletDiscovery: () => initEVMWalletDiscovery,
333
+ onEVMWalletsChanged: () => onEVMWalletsChanged,
334
+ setCurrentConnectedWallet: () => setCurrentConnectedWallet
335
+ });
336
+ function initEVMWalletDiscovery() {
337
+ if (typeof window === "undefined" || evmDiscoveryInitialized) return;
338
+ evmDiscoveryInitialized = true;
339
+ window.addEventListener("eip6963:announceProvider", ((event) => {
340
+ const { info, provider } = event.detail;
341
+ evmWallets.set(info.uuid, { info, provider });
342
+ evmDiscoveryListeners.forEach((listener) => listener());
343
+ }));
344
+ window.dispatchEvent(new Event("eip6963:requestProvider"));
345
+ }
346
+ function getEVMWallets() {
347
+ const wallets = [];
348
+ const detectedNames = /* @__PURE__ */ new Set();
349
+ evmWallets.forEach((detail, uuid) => {
350
+ if (!detectedNames.has(detail.info.name)) {
351
+ wallets.push({
352
+ id: uuid,
353
+ name: detail.info.name,
354
+ icon: detail.info.icon,
355
+ networkType: "evm" /* EVM */,
356
+ provider: detail.provider,
357
+ installed: true
358
+ });
359
+ detectedNames.add(detail.info.name);
360
+ }
361
+ });
362
+ if (wallets.length === 0 && typeof window !== "undefined" && window.ethereum) {
363
+ const ethereum = window.ethereum;
364
+ const walletName = ethereum.isMetaMask ? "MetaMask" : ethereum.isCoinbaseWallet ? "Coinbase Wallet" : ethereum.isOkxWallet ? "OKX Wallet" : "Browser Wallet";
365
+ if (!detectedNames.has(walletName)) {
366
+ wallets.push({
367
+ id: "injected",
368
+ name: walletName,
369
+ icon: "",
370
+ // Will use first letter as avatar
371
+ networkType: "evm" /* EVM */,
372
+ provider: ethereum,
373
+ installed: true
374
+ });
375
+ }
376
+ }
377
+ return wallets;
378
+ }
379
+ function onEVMWalletsChanged(callback) {
380
+ evmDiscoveryListeners.add(callback);
381
+ return () => {
382
+ evmDiscoveryListeners.delete(callback);
383
+ };
384
+ }
385
+ function getSolanaWallets() {
386
+ if (typeof window === "undefined") return [];
387
+ const wallets = [];
388
+ const detectedProviders = /* @__PURE__ */ new Set();
389
+ const detectedNames = /* @__PURE__ */ new Set();
390
+ for (const wallet of SOLANA_WALLETS) {
391
+ const provider = wallet.detect();
392
+ if (provider && !detectedNames.has(wallet.name)) {
393
+ wallets.push({
394
+ id: wallet.id,
395
+ name: wallet.name,
396
+ icon: wallet.icon,
397
+ networkType: "solana" /* SOLANA */,
398
+ provider,
399
+ installed: true
400
+ });
401
+ detectedProviders.add(provider);
402
+ detectedNames.add(wallet.name);
403
+ }
404
+ }
405
+ const windowSolana = window.solana;
406
+ if (windowSolana && !detectedProviders.has(windowSolana)) {
407
+ const walletName = windowSolana.isPhantom ? "Phantom" : windowSolana.isSolflare ? "Solflare" : windowSolana.isBackpack ? "Backpack" : windowSolana.walletName || "Solana Wallet";
408
+ if (!detectedNames.has(walletName)) {
409
+ wallets.push({
410
+ id: "solana-unknown",
411
+ name: walletName,
412
+ icon: "",
413
+ // Will use first letter as avatar
414
+ networkType: "solana" /* SOLANA */,
415
+ provider: windowSolana,
416
+ installed: true
417
+ });
418
+ }
419
+ }
420
+ return wallets;
421
+ }
422
+ function getWalletsForNetwork(networkType) {
423
+ switch (networkType) {
424
+ case "evm" /* EVM */:
425
+ return getEVMWallets();
426
+ case "solana" /* SOLANA */:
427
+ case "svm" /* SVM */:
428
+ return getSolanaWallets();
429
+ default:
430
+ return [];
431
+ }
432
+ }
433
+ function getWalletById(id, networkType) {
434
+ const wallets = getWalletsForNetwork(networkType);
435
+ return wallets.find((w) => w.id === id) || null;
436
+ }
437
+ function getWalletByName(name, networkType) {
438
+ const wallets = getWalletsForNetwork(networkType);
439
+ return wallets.find((w) => w.name === name) || null;
440
+ }
441
+ async function connectEVMWallet(wallet) {
442
+ if (!wallet.provider) {
443
+ throw new Error(`Wallet ${wallet.name} is not available`);
444
+ }
445
+ const accounts = await wallet.provider.request({
446
+ method: "eth_requestAccounts",
447
+ params: []
448
+ });
449
+ if (!accounts || accounts.length === 0) {
450
+ throw new Error("Failed to get wallet address");
451
+ }
452
+ return accounts[0];
453
+ }
454
+ async function connectSolanaWallet(wallet) {
455
+ if (!wallet.provider) {
456
+ throw new Error(`Wallet ${wallet.name} is not available`);
457
+ }
458
+ if (wallet.provider.isConnected) {
459
+ try {
460
+ await wallet.provider.disconnect();
461
+ } catch (err) {
462
+ console.warn("Failed to disconnect before connecting:", err);
463
+ }
464
+ }
465
+ const response = await wallet.provider.connect();
466
+ return response.publicKey.toString();
467
+ }
468
+ async function connectToWallet(wallet) {
469
+ let address;
470
+ switch (wallet.networkType) {
471
+ case "evm" /* EVM */:
472
+ address = await connectEVMWallet(wallet);
473
+ break;
474
+ case "solana" /* SOLANA */:
475
+ case "svm" /* SVM */:
476
+ address = await connectSolanaWallet(wallet);
477
+ break;
478
+ default:
479
+ throw new Error("Unsupported network type");
480
+ }
481
+ currentConnectedWallet = wallet;
482
+ saveConnectedWalletId(wallet.networkType, wallet.name);
483
+ return address;
484
+ }
485
+ function getCurrentConnectedWallet() {
486
+ return currentConnectedWallet;
487
+ }
488
+ function setCurrentConnectedWallet(wallet) {
489
+ currentConnectedWallet = wallet;
490
+ }
491
+ function clearConnectedWallet(networkType) {
492
+ if (networkType) {
493
+ removeConnectedWalletId(networkType);
494
+ }
495
+ currentConnectedWallet = null;
496
+ }
497
+ function restoreConnectedWallet(networkType) {
498
+ const savedWalletName = getConnectedWalletId(networkType);
499
+ if (!savedWalletName) {
500
+ return null;
501
+ }
502
+ const wallet = getWalletByName(savedWalletName, networkType);
503
+ if (wallet) {
504
+ currentConnectedWallet = wallet;
505
+ if ((networkType === "solana" /* SOLANA */ || networkType === "svm" /* SVM */) && wallet.provider) {
506
+ const providerPublicKey = wallet.provider.publicKey?.toString();
507
+ const cachedAddress = getCachedWalletAddress(networkType);
508
+ if (providerPublicKey && cachedAddress && providerPublicKey !== cachedAddress) {
509
+ saveWalletAddress(networkType, providerPublicKey);
510
+ }
511
+ }
512
+ return wallet;
513
+ }
514
+ return null;
515
+ }
516
+ function getWalletProviderForPayment(networkType) {
517
+ if (currentConnectedWallet && currentConnectedWallet.networkType === networkType) {
518
+ return currentConnectedWallet.provider;
519
+ }
520
+ const restoredWallet = restoreConnectedWallet(networkType);
521
+ if (restoredWallet) {
522
+ return restoredWallet.provider;
523
+ }
524
+ if (typeof window === "undefined") return null;
525
+ switch (networkType) {
526
+ case "evm" /* EVM */:
527
+ return window.ethereum;
528
+ case "solana" /* SOLANA */:
529
+ case "svm" /* SVM */:
530
+ return window.phantom?.solana || window.solana;
531
+ default:
532
+ return null;
533
+ }
534
+ }
535
+ async function getValidatedWalletProvider(networkType, expectedAddress) {
536
+ const provider = getWalletProviderForPayment(networkType);
537
+ if (!provider) {
538
+ return { provider: null, isValid: false };
539
+ }
540
+ if (networkType === "evm" /* EVM */) {
541
+ try {
542
+ const accounts = await provider.request({ method: "eth_accounts", params: [] });
543
+ const currentAddress = accounts?.[0];
544
+ const isValid = currentAddress?.toLowerCase() === expectedAddress?.toLowerCase();
545
+ if (!isValid) {
546
+ console.warn(`\u26A0\uFE0F Account mismatch: expected ${expectedAddress}, got ${currentAddress}`);
547
+ }
548
+ return { provider, isValid, currentAddress };
549
+ } catch (error) {
550
+ console.error("Failed to get current account:", error);
551
+ return { provider, isValid: false };
552
+ }
553
+ }
554
+ if (networkType === "solana" /* SOLANA */ || networkType === "svm" /* SVM */) {
555
+ if (provider.isConnected && provider.publicKey) {
556
+ const currentAddress = provider.publicKey.toString();
557
+ const isValid = currentAddress === expectedAddress;
558
+ if (!isValid) {
559
+ console.warn(`\u26A0\uFE0F Account mismatch: expected ${expectedAddress}, got ${currentAddress}`);
560
+ }
561
+ return { provider, isValid, currentAddress };
562
+ }
563
+ return { provider, isValid: false };
564
+ }
565
+ return { provider, isValid: true };
566
+ }
567
+ var SOLANA_WALLETS, evmWallets, evmDiscoveryListeners, evmDiscoveryInitialized, currentConnectedWallet;
568
+ var init_wallet_discovery = __esm({
569
+ "src/utils/wallet-discovery.ts"() {
570
+ "use strict";
571
+ init_wallet();
572
+ SOLANA_WALLETS = [
573
+ {
574
+ id: "phantom",
575
+ name: "Phantom",
576
+ // Phantom official icon
577
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiNBQjlGRjIiLz4KPHBhdGggZD0iTTExMC41IDY0QzExMC41IDg5Ljk1NjggODkuMjAxIDExMSA2My41IDExMUg0MS41QzM2LjI1MzMgMTExIDMyIDEwNi43NDcgMzIgMTAxLjVWNTQuNUMzMiAzMS4wMjggNTEuMDI4IDEyIDc0LjUgMTJDOTcuOTcyIDEyIDExNyAzMS4wMjggMTE3IDU0LjVWNTUuNUMxMTcgNTguNTM3NiAxMTQuNTM4IDYxIDExMS41IDYxSDEwOS41QzEwNi40NjIgNjEgMTA0IDYzLjQ2MjQgMTA0IDY2LjVWNjhDMTA0IDcxLjg2NiAxMDcuMTM0IDc1IDExMSA3NUgxMTEuNUMxMTQuNTM4IDc1IDExNyA3Mi41Mzc2IDExNyA2OS41VjY0SDExMC41WiIgZmlsbD0idXJsKCNwYWludDBfbGluZWFyXzEyOF8xMjgpIi8+CjxwYXRoIGQ9Ik00OC41IDY3QzUxLjUzNzYgNjcgNTQgNjQuNTM3NiA1NCA2MS41QzU0IDU4LjQ2MjQgNTEuNTM3NiA1NiA0OC41IDU2QzQ1LjQ2MjQgNTYgNDMgNTguNDYyNCA0MyA2MS41QzQzIDY0LjUzNzYgNDUuNDYyNCA2NyA0OC41IDY3WiIgZmlsbD0iIzFCMUIxQiIvPgo8cGF0aCBkPSJNNzMuNSA2N0M3Ni41Mzc2IDY3IDc5IDY0LjUzNzYgNzkgNjEuNUM3OSA1OC40NjI0IDc2LjUzNzYgNTYgNzMuNSA1NkM3MC40NjI0IDU2IDY4IDU4LjQ2MjQgNjggNjEuNUM2OCA2NC41Mzc2IDcwLjQ2MjQgNjcgNzMuNSA2N1oiIGZpbGw9IiMxQjFCMUIiLz4KPGRlZnM+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQwX2xpbmVhcl8xMjhfMTI4IiB4MT0iMTE3IiB5MT0iMTIiIHgyPSIxMTciIHkyPSIxMTEiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0ZGRkZGRiIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNGRkZGRkYiIHN0b3Atb3BhY2l0eT0iMC44MiIvPgo8L2xpbmVhckdyYWRpZW50Pgo8L2RlZnM+Cjwvc3ZnPg==",
578
+ detect: () => window.phantom?.solana
579
+ },
580
+ {
581
+ id: "solflare",
582
+ name: "Solflare",
583
+ // Solflare icon
584
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiNGQzZEMDEiLz4KPHBhdGggZD0iTTk2IDY0TDY0IDMyTDMyIDY0TDY0IDk2TDk2IDY0WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+",
585
+ detect: () => window.solflare
586
+ },
587
+ {
588
+ id: "backpack",
589
+ name: "Backpack",
590
+ // Backpack icon (red coral color)
591
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiNFMzM0MzAiLz4KPHBhdGggZD0iTTQwIDQ4SDg4VjgwQzg4IDg4LjgzNjYgODAuODM2NiA5NiA3MiA5Nkg1NkM0Ny4xNjM0IDk2IDQwIDg4LjgzNjYgNDAgODBWNDhaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNNTIgMzJINzZWNDhINTJWMzJaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4=",
592
+ detect: () => window.backpack
593
+ },
594
+ {
595
+ id: "okx-solana",
596
+ name: "OKX Wallet",
597
+ // OKX icon
598
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9ImJsYWNrIi8+CjxyZWN0IHg9IjI0IiB5PSIyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0id2hpdGUiLz4KPHJlY3QgeD0iNTIiIHk9IjI0IiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSJ3aGl0ZSIvPgo8cmVjdCB4PSI4MCIgeT0iMjQiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgcng9IjQiIGZpbGw9IndoaXRlIi8+CjxyZWN0IHg9IjI0IiB5PSI1MiIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0id2hpdGUiLz4KPHJlY3QgeD0iODAiIHk9IjUyIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSJ3aGl0ZSIvPgo8cmVjdCB4PSIyNCIgeT0iODAiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgcng9IjQiIGZpbGw9IndoaXRlIi8+CjxyZWN0IHg9IjUyIiB5PSI4MCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0id2hpdGUiLz4KPHJlY3QgeD0iODAiIHk9IjgwIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4=",
599
+ detect: () => window.okxwallet?.solana
600
+ },
601
+ {
602
+ id: "coinbase-solana",
603
+ name: "Coinbase Wallet",
604
+ // Coinbase icon (blue)
605
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiMwMDUyRkYiLz4KPGNpcmNsZSBjeD0iNjQiIGN5PSI2NCIgcj0iMzYiIGZpbGw9IndoaXRlIi8+CjxyZWN0IHg9IjQ4IiB5PSI1NiIgd2lkdGg9IjMyIiBoZWlnaHQ9IjE2IiByeD0iNCIgZmlsbD0iIzAwNTJGRiIvPgo8L3N2Zz4=",
606
+ detect: () => window.coinbaseSolana
607
+ },
608
+ {
609
+ id: "trust-solana",
610
+ name: "Trust Wallet",
611
+ // Trust Wallet icon
612
+ icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiMwNTAwRkYiLz4KPHBhdGggZD0iTTY0IDI0QzY0IDI0IDk2IDQwIDk2IDY0Qzk2IDg4IDY0IDEwNCA2NCAxMDRDNjQgMTA0IDMyIDg4IDMyIDY0QzMyIDQwIDY0IDI0IDY0IDI0WiIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSI2IiBmaWxsPSJub25lIi8+Cjwvc3ZnPg==",
613
+ detect: () => window.trustwallet?.solana
614
+ }
615
+ ];
616
+ evmWallets = /* @__PURE__ */ new Map();
617
+ evmDiscoveryListeners = /* @__PURE__ */ new Set();
618
+ evmDiscoveryInitialized = false;
619
+ currentConnectedWallet = null;
620
+ if (typeof window !== "undefined") {
621
+ initEVMWalletDiscovery();
622
+ }
277
623
  }
278
624
  });
279
625
 
280
626
  // src/react/index.ts
281
627
  var index_exports = {};
282
628
  __export(index_exports, {
283
- V402Checkout: () => V402Checkout,
629
+ AnimationStyles: () => AnimationStyles,
630
+ Toast: () => Toast,
631
+ V402CheckoutV2: () => V402CheckoutV2,
284
632
  WalletConnect: () => WalletConnect,
285
633
  WalletSelectModal: () => WalletSelectModal,
634
+ checkoutAnimations: () => checkoutAnimations,
286
635
  usePageNetwork: () => usePageNetwork,
287
636
  usePayment: () => usePayment,
288
637
  usePaymentInfo: () => usePaymentInfo,
638
+ useToast: () => useToast,
289
639
  useWallet: () => useWallet
290
640
  });
291
641
  module.exports = __toCommonJS(index_exports);
@@ -301,13 +651,13 @@ init_wallet();
301
651
  init_wallet();
302
652
  async function connectWallet(networkType, forceSelect = false) {
303
653
  if (typeof window === "undefined") {
304
- throw new Error("\u8BF7\u5728\u6D4F\u89C8\u5668\u73AF\u5883\u4E2D\u4F7F\u7528");
654
+ throw new Error("Please use in browser environment");
305
655
  }
306
656
  let address;
307
657
  switch (networkType) {
308
658
  case "evm" /* EVM */: {
309
659
  if (!window.ethereum) {
310
- throw new Error("\u8BF7\u5B89\u88C5 MetaMask \u6216\u5176\u4ED6\u4EE5\u592A\u574A\u94B1\u5305");
660
+ throw new Error("Please install MetaMask or another Ethereum wallet");
311
661
  }
312
662
  const ethereum = window.ethereum;
313
663
  if (forceSelect) {
@@ -325,7 +675,7 @@ async function connectWallet(networkType, forceSelect = false) {
325
675
  }
326
676
  } catch (err) {
327
677
  if (err.code === 4001) {
328
- throw new Error("\u7528\u6237\u53D6\u6D88\u4E86\u94B1\u5305\u8FDE\u63A5");
678
+ throw new Error("User cancelled wallet connection");
329
679
  }
330
680
  console.warn("wallet_requestPermissions failed, falling back to eth_requestAccounts");
331
681
  }
@@ -335,7 +685,7 @@ async function connectWallet(networkType, forceSelect = false) {
335
685
  params: []
336
686
  });
337
687
  if (!accounts || accounts.length === 0) {
338
- throw new Error("\u672A\u80FD\u83B7\u53D6\u5230\u94B1\u5305\u5730\u5740");
688
+ throw new Error("Failed to get wallet address");
339
689
  }
340
690
  address = accounts[0];
341
691
  break;
@@ -349,7 +699,7 @@ async function connectWallet(networkType, forceSelect = false) {
349
699
  solana = solflare;
350
700
  }
351
701
  if (!solana) {
352
- throw new Error("\u8BF7\u5B89\u88C5 Phantom \u6216\u5176\u4ED6 Solana \u94B1\u5305");
702
+ throw new Error("Please install Phantom or another Solana wallet");
353
703
  }
354
704
  if (forceSelect) {
355
705
  try {
@@ -375,7 +725,7 @@ async function connectWallet(networkType, forceSelect = false) {
375
725
  break;
376
726
  }
377
727
  default:
378
- throw new Error("\u4E0D\u652F\u6301\u7684\u7F51\u7EDC\u7C7B\u578B");
728
+ throw new Error("Unsupported network type");
379
729
  }
380
730
  clearWalletDisconnection(networkType);
381
731
  saveConnectedNetworkType(networkType);
@@ -413,8 +763,8 @@ async function disconnectWallet(networkType, clearAll = false) {
413
763
  await disconnectAllSolanaWallets();
414
764
  break;
415
765
  }
416
- // EVM 钱包(如 MetaMask)没有真正的 disconnect API
417
- // 只清除本地状态,下次连接时会重新请求权限
766
+ // EVM wallets (like MetaMask) don't have a real disconnect API
767
+ // Only clear local state, will request permissions again on next connection
418
768
  case "evm" /* EVM */:
419
769
  default:
420
770
  break;
@@ -445,36 +795,28 @@ async function getCurrentWallet(networkType) {
445
795
  return null;
446
796
  }
447
797
  const cachedAddress = getCachedWalletAddress(type);
448
- try {
449
- let currentAddress = null;
450
- switch (type) {
451
- case "evm" /* EVM */: {
452
- if (!window.ethereum) return cachedAddress;
798
+ if (type === "evm" /* EVM */) {
799
+ if (cachedAddress) {
800
+ return cachedAddress;
801
+ }
802
+ if (window.ethereum) {
803
+ try {
453
804
  const accounts = await window.ethereum.request({
454
805
  method: "eth_accounts",
455
806
  params: []
456
807
  });
457
- currentAddress = accounts && accounts.length > 0 ? accounts[0] : null;
458
- break;
808
+ return accounts && accounts.length > 0 ? accounts[0] : null;
809
+ } catch (error) {
810
+ console.error("Failed to get EVM accounts:", error);
811
+ return null;
459
812
  }
460
- case "solana" /* SOLANA */:
461
- case "svm" /* SVM */: {
462
- const solana = window.solana;
463
- if (!solana || !solana.isConnected) return cachedAddress;
464
- currentAddress = solana.publicKey?.toString() || null;
465
- break;
466
- }
467
- default:
468
- return cachedAddress;
469
813
  }
470
- if (currentAddress && currentAddress !== cachedAddress) {
471
- saveWalletAddress(type, currentAddress);
472
- }
473
- return currentAddress || cachedAddress;
474
- } catch (error) {
475
- console.error("Failed to get current wallet:", error);
814
+ return null;
815
+ }
816
+ if (type === "solana" /* SOLANA */ || type === "svm" /* SVM */) {
476
817
  return cachedAddress;
477
818
  }
819
+ return cachedAddress;
478
820
  }
479
821
  function onAccountsChanged(callback) {
480
822
  if (typeof window === "undefined" || !window.ethereum) {
@@ -537,219 +879,8 @@ async function switchNetwork(networkType) {
537
879
  return null;
538
880
  }
539
881
 
540
- // src/utils/wallet-discovery.ts
541
- var SOLANA_WALLETS = [
542
- {
543
- id: "phantom",
544
- name: "Phantom",
545
- // Phantom official icon
546
- icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiNBQjlGRjIiLz4KPHBhdGggZD0iTTExMC41IDY0QzExMC41IDg5Ljk1NjggODkuMjAxIDExMSA2My41IDExMUg0MS41QzM2LjI1MzMgMTExIDMyIDEwNi43NDcgMzIgMTAxLjVWNTQuNUMzMiAzMS4wMjggNTEuMDI4IDEyIDc0LjUgMTJDOTcuOTcyIDEyIDExNyAzMS4wMjggMTE3IDU0LjVWNTUuNUMxMTcgNTguNTM3NiAxMTQuNTM4IDYxIDExMS41IDYxSDEwOS41QzEwNi40NjIgNjEgMTA0IDYzLjQ2MjQgMTA0IDY2LjVWNjhDMTA0IDcxLjg2NiAxMDcuMTM0IDc1IDExMSA3NUgxMTEuNUMxMTQuNTM4IDc1IDExNyA3Mi41Mzc2IDExNyA2OS41VjY0SDExMC41WiIgZmlsbD0idXJsKCNwYWludDBfbGluZWFyXzEyOF8xMjgpIi8+CjxwYXRoIGQ9Ik00OC41IDY3QzUxLjUzNzYgNjcgNTQgNjQuNTM3NiA1NCA2MS41QzU0IDU4LjQ2MjQgNTEuNTM3NiA1NiA0OC41IDU2QzQ1LjQ2MjQgNTYgNDMgNTguNDYyNCA0MyA2MS41QzQzIDY0LjUzNzYgNDUuNDYyNCA2NyA0OC41IDY3WiIgZmlsbD0iIzFCMUIxQiIvPgo8cGF0aCBkPSJNNzMuNSA2N0M3Ni41Mzc2IDY3IDc5IDY0LjUzNzYgNzkgNjEuNUM3OSA1OC40NjI0IDc2LjUzNzYgNTYgNzMuNSA1NkM3MC40NjI0IDU2IDY4IDU4LjQ2MjQgNjggNjEuNUM2OCA2NC41Mzc2IDcwLjQ2MjQgNjcgNzMuNSA2N1oiIGZpbGw9IiMxQjFCMUIiLz4KPGRlZnM+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQwX2xpbmVhcl8xMjhfMTI4IiB4MT0iMTE3IiB5MT0iMTIiIHgyPSIxMTciIHkyPSIxMTEiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0ZGRkZGRiIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNGRkZGRkYiIHN0b3Atb3BhY2l0eT0iMC44MiIvPgo8L2xpbmVhckdyYWRpZW50Pgo8L2RlZnM+Cjwvc3ZnPg==",
547
- detect: () => window.phantom?.solana
548
- },
549
- {
550
- id: "solflare",
551
- name: "Solflare",
552
- // Solflare icon
553
- icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiNGQzZEMDEiLz4KPHBhdGggZD0iTTk2IDY0TDY0IDMyTDMyIDY0TDY0IDk2TDk2IDY0WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+",
554
- detect: () => window.solflare
555
- },
556
- {
557
- id: "backpack",
558
- name: "Backpack",
559
- // Backpack icon (red coral color)
560
- icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiNFMzM0MzAiLz4KPHBhdGggZD0iTTQwIDQ4SDg4VjgwQzg4IDg4LjgzNjYgODAuODM2NiA5NiA3MiA5Nkg1NkM0Ny4xNjM0IDk2IDQwIDg4LjgzNjYgNDAgODBWNDhaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNNTIgMzJINzZWNDhINTJWMzJaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4=",
561
- detect: () => window.backpack
562
- },
563
- {
564
- id: "okx-solana",
565
- name: "OKX Wallet",
566
- // OKX icon
567
- icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9ImJsYWNrIi8+CjxyZWN0IHg9IjI0IiB5PSIyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0id2hpdGUiLz4KPHJlY3QgeD0iNTIiIHk9IjI0IiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSJ3aGl0ZSIvPgo8cmVjdCB4PSI4MCIgeT0iMjQiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgcng9IjQiIGZpbGw9IndoaXRlIi8+CjxyZWN0IHg9IjI0IiB5PSI1MiIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0id2hpdGUiLz4KPHJlY3QgeD0iODAiIHk9IjUyIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSJ3aGl0ZSIvPgo8cmVjdCB4PSIyNCIgeT0iODAiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgcng9IjQiIGZpbGw9IndoaXRlIi8+CjxyZWN0IHg9IjUyIiB5PSI4MCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0id2hpdGUiLz4KPHJlY3QgeD0iODAiIHk9IjgwIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4=",
568
- detect: () => window.okxwallet?.solana
569
- },
570
- {
571
- id: "coinbase-solana",
572
- name: "Coinbase Wallet",
573
- // Coinbase icon (blue)
574
- icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiMwMDUyRkYiLz4KPGNpcmNsZSBjeD0iNjQiIGN5PSI2NCIgcj0iMzYiIGZpbGw9IndoaXRlIi8+CjxyZWN0IHg9IjQ4IiB5PSI1NiIgd2lkdGg9IjMyIiBoZWlnaHQ9IjE2IiByeD0iNCIgZmlsbD0iIzAwNTJGRiIvPgo8L3N2Zz4=",
575
- detect: () => window.coinbaseSolana
576
- },
577
- {
578
- id: "trust-solana",
579
- name: "Trust Wallet",
580
- // Trust Wallet icon
581
- icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYiIGZpbGw9IiMwNTAwRkYiLz4KPHBhdGggZD0iTTY0IDI0QzY0IDI0IDk2IDQwIDk2IDY0Qzk2IDg4IDY0IDEwNCA2NCAxMDRDNjQgMTA0IDMyIDg4IDMyIDY0QzMyIDQwIDY0IDI0IDY0IDI0WiIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSI2IiBmaWxsPSJub25lIi8+Cjwvc3ZnPg==",
582
- detect: () => window.trustwallet?.solana
583
- }
584
- ];
585
- var evmWallets = /* @__PURE__ */ new Map();
586
- var evmDiscoveryListeners = /* @__PURE__ */ new Set();
587
- var evmDiscoveryInitialized = false;
588
- var currentConnectedWallet = null;
589
- function initEVMWalletDiscovery() {
590
- if (typeof window === "undefined" || evmDiscoveryInitialized) return;
591
- evmDiscoveryInitialized = true;
592
- window.addEventListener("eip6963:announceProvider", ((event) => {
593
- const { info, provider } = event.detail;
594
- evmWallets.set(info.uuid, { info, provider });
595
- evmDiscoveryListeners.forEach((listener) => listener());
596
- }));
597
- window.dispatchEvent(new Event("eip6963:requestProvider"));
598
- }
599
- function getEVMWallets() {
600
- const wallets = [];
601
- const detectedNames = /* @__PURE__ */ new Set();
602
- evmWallets.forEach((detail, uuid) => {
603
- if (!detectedNames.has(detail.info.name)) {
604
- wallets.push({
605
- id: uuid,
606
- name: detail.info.name,
607
- icon: detail.info.icon,
608
- networkType: "evm" /* EVM */,
609
- provider: detail.provider,
610
- installed: true
611
- });
612
- detectedNames.add(detail.info.name);
613
- }
614
- });
615
- if (wallets.length === 0 && typeof window !== "undefined" && window.ethereum) {
616
- const ethereum = window.ethereum;
617
- const walletName = ethereum.isMetaMask ? "MetaMask" : ethereum.isCoinbaseWallet ? "Coinbase Wallet" : ethereum.isOkxWallet ? "OKX Wallet" : "Browser Wallet";
618
- if (!detectedNames.has(walletName)) {
619
- wallets.push({
620
- id: "injected",
621
- name: walletName,
622
- icon: "",
623
- // Will use first letter as avatar
624
- networkType: "evm" /* EVM */,
625
- provider: ethereum,
626
- installed: true
627
- });
628
- }
629
- }
630
- return wallets;
631
- }
632
- function onEVMWalletsChanged(callback) {
633
- evmDiscoveryListeners.add(callback);
634
- return () => {
635
- evmDiscoveryListeners.delete(callback);
636
- };
637
- }
638
- function getSolanaWallets() {
639
- if (typeof window === "undefined") return [];
640
- const wallets = [];
641
- const detectedProviders = /* @__PURE__ */ new Set();
642
- const detectedNames = /* @__PURE__ */ new Set();
643
- for (const wallet of SOLANA_WALLETS) {
644
- const provider = wallet.detect();
645
- if (provider && !detectedNames.has(wallet.name)) {
646
- wallets.push({
647
- id: wallet.id,
648
- name: wallet.name,
649
- icon: wallet.icon,
650
- networkType: "solana" /* SOLANA */,
651
- provider,
652
- installed: true
653
- });
654
- detectedProviders.add(provider);
655
- detectedNames.add(wallet.name);
656
- }
657
- }
658
- const windowSolana = window.solana;
659
- if (windowSolana && !detectedProviders.has(windowSolana)) {
660
- const walletName = windowSolana.isPhantom ? "Phantom" : windowSolana.isSolflare ? "Solflare" : windowSolana.isBackpack ? "Backpack" : windowSolana.walletName || "Solana Wallet";
661
- if (!detectedNames.has(walletName)) {
662
- wallets.push({
663
- id: "solana-unknown",
664
- name: walletName,
665
- icon: "",
666
- // Will use first letter as avatar
667
- networkType: "solana" /* SOLANA */,
668
- provider: windowSolana,
669
- installed: true
670
- });
671
- }
672
- }
673
- return wallets;
674
- }
675
- function getWalletsForNetwork(networkType) {
676
- switch (networkType) {
677
- case "evm" /* EVM */:
678
- return getEVMWallets();
679
- case "solana" /* SOLANA */:
680
- case "svm" /* SVM */:
681
- return getSolanaWallets();
682
- default:
683
- return [];
684
- }
685
- }
686
- async function connectEVMWallet(wallet) {
687
- if (!wallet.provider) {
688
- throw new Error(`\u94B1\u5305 ${wallet.name} \u4E0D\u53EF\u7528`);
689
- }
690
- const accounts = await wallet.provider.request({
691
- method: "eth_requestAccounts",
692
- params: []
693
- });
694
- if (!accounts || accounts.length === 0) {
695
- throw new Error("\u672A\u80FD\u83B7\u53D6\u5230\u94B1\u5305\u5730\u5740");
696
- }
697
- return accounts[0];
698
- }
699
- async function connectSolanaWallet(wallet) {
700
- if (!wallet.provider) {
701
- throw new Error(`\u94B1\u5305 ${wallet.name} \u4E0D\u53EF\u7528`);
702
- }
703
- if (wallet.provider.isConnected) {
704
- try {
705
- await wallet.provider.disconnect();
706
- } catch (err) {
707
- console.warn("Failed to disconnect before connecting:", err);
708
- }
709
- }
710
- const response = await wallet.provider.connect();
711
- return response.publicKey.toString();
712
- }
713
- async function connectToWallet(wallet) {
714
- let address;
715
- switch (wallet.networkType) {
716
- case "evm" /* EVM */:
717
- address = await connectEVMWallet(wallet);
718
- break;
719
- case "solana" /* SOLANA */:
720
- case "svm" /* SVM */:
721
- address = await connectSolanaWallet(wallet);
722
- break;
723
- default:
724
- throw new Error("\u4E0D\u652F\u6301\u7684\u7F51\u7EDC\u7C7B\u578B");
725
- }
726
- currentConnectedWallet = wallet;
727
- return address;
728
- }
729
- function setCurrentConnectedWallet(wallet) {
730
- currentConnectedWallet = wallet;
731
- }
732
- function clearConnectedWallet() {
733
- currentConnectedWallet = null;
734
- }
735
- function getWalletProviderForPayment(networkType) {
736
- if (currentConnectedWallet && currentConnectedWallet.networkType === networkType) {
737
- return currentConnectedWallet.provider;
738
- }
739
- if (typeof window === "undefined") return null;
740
- switch (networkType) {
741
- case "evm" /* EVM */:
742
- return window.ethereum;
743
- case "solana" /* SOLANA */:
744
- case "svm" /* SVM */:
745
- return window.phantom?.solana || window.solana;
746
- default:
747
- return null;
748
- }
749
- }
750
- if (typeof window !== "undefined") {
751
- initEVMWalletDiscovery();
752
- }
882
+ // src/utils/index.ts
883
+ init_wallet_discovery();
753
884
 
754
885
  // src/services/svm/payment-header.ts
755
886
  var import_web3 = require("@solana/web3.js");
@@ -1206,6 +1337,7 @@ async function handleEvmPayment(endpoint, config, requestInit) {
1206
1337
  // src/utils/payment-helpers.ts
1207
1338
  var import_ethers2 = require("ethers");
1208
1339
  init_common();
1340
+ init_wallet_discovery();
1209
1341
  function parsePaymentRequired(response) {
1210
1342
  if (response && typeof response === "object") {
1211
1343
  if ("x402Version" in response && "accepts" in response) {
@@ -1229,7 +1361,7 @@ function getSupportedNetworkTypes(paymentRequirements) {
1229
1361
  });
1230
1362
  return Array.from(networkTypes);
1231
1363
  }
1232
- async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, additionalParams) {
1364
+ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, additionalParams, expectedAddress) {
1233
1365
  const fullEndpoint = `${endpoint}/${merchantId}`;
1234
1366
  let response;
1235
1367
  const requestInit = additionalParams && Object.keys(additionalParams).length > 0 ? {
@@ -1241,11 +1373,19 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, ad
1241
1373
  if (networkType === "solana" /* SOLANA */ || networkType === "svm" /* SVM */) {
1242
1374
  const solana = getWalletProviderForPayment(networkType);
1243
1375
  if (!solana) {
1244
- throw new Error("\u8BF7\u5148\u8FDE\u63A5 Solana \u94B1\u5305");
1376
+ throw new Error("Please connect your Solana wallet first.");
1245
1377
  }
1246
1378
  if (!solana.isConnected) {
1247
1379
  await solana.connect();
1248
1380
  }
1381
+ const currentAddress = solana.publicKey?.toString();
1382
+ if (expectedAddress && currentAddress) {
1383
+ if (currentAddress !== expectedAddress) {
1384
+ throw new Error(
1385
+ `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.`
1386
+ );
1387
+ }
1388
+ }
1249
1389
  response = await handleSvmPayment(fullEndpoint, {
1250
1390
  wallet: solana,
1251
1391
  network: "solana"
@@ -1254,14 +1394,20 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, ad
1254
1394
  } else if (networkType === "evm" /* EVM */) {
1255
1395
  const ethereum = getWalletProviderForPayment(networkType);
1256
1396
  if (!ethereum) {
1257
- throw new Error("\u8BF7\u5148\u8FDE\u63A5 EVM \u94B1\u5305");
1397
+ throw new Error("Please connect the EVM wallet first");
1258
1398
  }
1259
1399
  const provider = new import_ethers2.ethers.BrowserProvider(ethereum);
1260
1400
  const signer = await provider.getSigner();
1401
+ const currentAddress = await signer.getAddress();
1402
+ if (expectedAddress && currentAddress.toLowerCase() !== expectedAddress.toLowerCase()) {
1403
+ throw new Error(
1404
+ `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.`
1405
+ );
1406
+ }
1261
1407
  const wallet = {
1262
- address: await signer.getAddress(),
1263
- signTypedData: async (domain, types, message2) => {
1264
- return await signer.signTypedData(domain, types, message2);
1408
+ address: currentAddress,
1409
+ signTypedData: async (domain, types, message) => {
1410
+ return await signer.signTypedData(domain, types, message);
1265
1411
  },
1266
1412
  // Get current chain ID from wallet
1267
1413
  getChainId: async () => {
@@ -1282,7 +1428,7 @@ async function makePayment(networkType, merchantId, endpoint = PROD_BACK_URL, ad
1282
1428
  // Will use backend's network configuration
1283
1429
  }, requestInit);
1284
1430
  } else {
1285
- throw new Error(`\u4E0D\u652F\u6301\u7684\u7F51\u7EDC\u7C7B\u578B: ${networkType}`);
1431
+ throw new Error(`Unsupported network types: ${networkType}`);
1286
1432
  }
1287
1433
  return response;
1288
1434
  }
@@ -1599,8 +1745,22 @@ var WalletStore = class {
1599
1745
  }
1600
1746
  this.setState({ isConnecting: true, error: null });
1601
1747
  try {
1602
- const address = await switchNetwork(type);
1748
+ let address = await switchNetwork(type);
1603
1749
  if (address) {
1750
+ const wallets = getWalletsForNetwork(type);
1751
+ if (wallets.length > 0) {
1752
+ const { getWalletProviderForPayment: getWalletProviderForPayment2 } = await Promise.resolve().then(() => (init_wallet_discovery(), wallet_discovery_exports));
1753
+ const provider = getWalletProviderForPayment2(type);
1754
+ if (provider) {
1755
+ if (type === "solana" /* SOLANA */ || type === "svm" /* SVM */) {
1756
+ const providerAddress = provider.publicKey?.toString();
1757
+ if (providerAddress && providerAddress !== address) {
1758
+ address = providerAddress;
1759
+ saveWalletAddress(type, providerAddress);
1760
+ }
1761
+ }
1762
+ }
1763
+ }
1604
1764
  this.setState({
1605
1765
  address,
1606
1766
  networkType: type,
@@ -1625,7 +1785,7 @@ var WalletStore = class {
1625
1785
  // Disconnect wallet
1626
1786
  async disconnect() {
1627
1787
  const currentNetwork = this.state.networkType;
1628
- clearConnectedWallet();
1788
+ clearConnectedWallet(currentNetwork || void 0);
1629
1789
  if (currentNetwork) {
1630
1790
  try {
1631
1791
  await disconnectWallet(currentNetwork);
@@ -1651,6 +1811,16 @@ var WalletStore = class {
1651
1811
  return;
1652
1812
  }
1653
1813
  if (this.state.networkType === expectedNetwork && this.state.address) {
1814
+ const { getWalletProviderForPayment: getWalletProviderForPayment2 } = await Promise.resolve().then(() => (init_wallet_discovery(), wallet_discovery_exports));
1815
+ const provider = getWalletProviderForPayment2(expectedNetwork);
1816
+ if (provider && (expectedNetwork === "solana" /* SOLANA */ || expectedNetwork === "svm" /* SVM */)) {
1817
+ const providerAddress = provider.publicKey?.toString();
1818
+ if (providerAddress && providerAddress !== this.state.address) {
1819
+ this.setState({ address: providerAddress });
1820
+ saveWalletAddress(expectedNetwork, providerAddress);
1821
+ return;
1822
+ }
1823
+ }
1654
1824
  return;
1655
1825
  }
1656
1826
  if (this.state.networkType !== expectedNetwork) {
@@ -1784,12 +1954,84 @@ function usePaymentInfo(merchantId, endpoint = PROD_BACK_URL, additionalParams)
1784
1954
  };
1785
1955
  }
1786
1956
 
1787
- // src/react/components/WalletConnect.tsx
1957
+ // src/react/hooks/useToast.tsx
1788
1958
  var import_react6 = __toESM(require("react"));
1789
1959
 
1790
- // src/react/components/WalletSelectModal.tsx
1960
+ // src/react/components/ui/Toast.tsx
1791
1961
  var import_react5 = __toESM(require("react"));
1792
1962
  var import_react_dom = require("react-dom");
1963
+ var Toast = ({ message, type, onClose }) => {
1964
+ (0, import_react5.useEffect)(() => {
1965
+ const timer = setTimeout(onClose, 3e3);
1966
+ return () => clearTimeout(timer);
1967
+ }, [onClose]);
1968
+ const bgColor = type === "success" ? "#22c55e" : type === "error" ? "#ef4444" : "#3b82f6";
1969
+ const icon = type === "success" ? "\u2713" : type === "error" ? "\u2717" : "\u2139";
1970
+ return (0, import_react_dom.createPortal)(
1971
+ /* @__PURE__ */ import_react5.default.createElement(
1972
+ "div",
1973
+ {
1974
+ className: "fixed top-4 right-4 z-[99999] animate-slide-in-right",
1975
+ style: {
1976
+ animation: "slideInRight 0.3s ease-out"
1977
+ }
1978
+ },
1979
+ /* @__PURE__ */ import_react5.default.createElement(
1980
+ "div",
1981
+ {
1982
+ className: "flex items-center gap-3 px-4 py-3 rounded-lg shadow-lg text-white font-mono text-sm",
1983
+ style: { backgroundColor: bgColor, minWidth: "280px" }
1984
+ },
1985
+ /* @__PURE__ */ import_react5.default.createElement("span", { className: "text-lg" }, icon),
1986
+ /* @__PURE__ */ import_react5.default.createElement("span", { className: "flex-1" }, message),
1987
+ /* @__PURE__ */ import_react5.default.createElement(
1988
+ "button",
1989
+ {
1990
+ onClick: onClose,
1991
+ className: "text-white/80 hover:text-white transition-colors"
1992
+ },
1993
+ "\xD7"
1994
+ )
1995
+ )
1996
+ ),
1997
+ document.body
1998
+ );
1999
+ };
2000
+
2001
+ // src/react/hooks/useToast.tsx
2002
+ var useToast = () => {
2003
+ const [toasts, setToasts] = (0, import_react6.useState)([]);
2004
+ const toastIdRef = (0, import_react6.useRef)(0);
2005
+ const showToast = (0, import_react6.useCallback)((message, type) => {
2006
+ const id = ++toastIdRef.current;
2007
+ setToasts((prev) => [...prev, { id, message, type }]);
2008
+ }, []);
2009
+ const removeToast = (0, import_react6.useCallback)((id) => {
2010
+ setToasts((prev) => prev.filter((t) => t.id !== id));
2011
+ }, []);
2012
+ const ToastContainer = () => /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, toasts.map((toast, index) => /* @__PURE__ */ import_react6.default.createElement(
2013
+ "div",
2014
+ {
2015
+ key: toast.id,
2016
+ style: { top: `${16 + index * 60}px` },
2017
+ className: "fixed right-4 z-[99999]"
2018
+ },
2019
+ import_react6.default.createElement(Toast, {
2020
+ message: toast.message,
2021
+ type: toast.type,
2022
+ onClose: () => removeToast(toast.id)
2023
+ })
2024
+ )));
2025
+ return { showToast, ToastContainer };
2026
+ };
2027
+
2028
+ // src/react/components/wallet/WalletConnect.tsx
2029
+ var import_react8 = __toESM(require("react"));
2030
+
2031
+ // src/react/components/wallet/WalletSelectModal.tsx
2032
+ var import_react7 = __toESM(require("react"));
2033
+ var import_react_dom2 = require("react-dom");
2034
+ init_wallet_discovery();
1793
2035
  var overlayStyle = {
1794
2036
  position: "fixed",
1795
2037
  top: 0,
@@ -1927,8 +2169,8 @@ function WalletItem({
1927
2169
  onSelect,
1928
2170
  onHover
1929
2171
  }) {
1930
- const [iconError, setIconError] = (0, import_react5.useState)(false);
1931
- return /* @__PURE__ */ import_react5.default.createElement(
2172
+ const [iconError, setIconError] = (0, import_react7.useState)(false);
2173
+ return /* @__PURE__ */ import_react7.default.createElement(
1932
2174
  "div",
1933
2175
  {
1934
2176
  style: getWalletItemStyle(isHovered),
@@ -1936,7 +2178,7 @@ function WalletItem({
1936
2178
  onMouseEnter: () => onHover(true),
1937
2179
  onMouseLeave: () => onHover(false)
1938
2180
  },
1939
- wallet.icon && !iconError ? /* @__PURE__ */ import_react5.default.createElement(
2181
+ wallet.icon && !iconError ? /* @__PURE__ */ import_react7.default.createElement(
1940
2182
  "img",
1941
2183
  {
1942
2184
  src: wallet.icon,
@@ -1944,8 +2186,8 @@ function WalletItem({
1944
2186
  style: walletIconStyle,
1945
2187
  onError: () => setIconError(true)
1946
2188
  }
1947
- ) : /* @__PURE__ */ import_react5.default.createElement("div", { style: getWalletIconPlaceholderStyle(wallet.name) }, wallet.name.charAt(0).toUpperCase()),
1948
- /* @__PURE__ */ import_react5.default.createElement("span", { style: walletNameStyle }, wallet.name)
2189
+ ) : /* @__PURE__ */ import_react7.default.createElement("div", { style: getWalletIconPlaceholderStyle(wallet.name) }, wallet.name.charAt(0).toUpperCase()),
2190
+ /* @__PURE__ */ import_react7.default.createElement("span", { style: walletNameStyle }, wallet.name)
1949
2191
  );
1950
2192
  }
1951
2193
  function WalletSelectModal({
@@ -1954,14 +2196,14 @@ function WalletSelectModal({
1954
2196
  onSelect,
1955
2197
  onClose
1956
2198
  }) {
1957
- const [wallets, setWallets] = (0, import_react5.useState)([]);
1958
- const [hoveredWallet, setHoveredWallet] = (0, import_react5.useState)(null);
1959
- const [mounted, setMounted] = (0, import_react5.useState)(false);
1960
- (0, import_react5.useEffect)(() => {
2199
+ const [wallets, setWallets] = (0, import_react7.useState)([]);
2200
+ const [hoveredWallet, setHoveredWallet] = (0, import_react7.useState)(null);
2201
+ const [mounted, setMounted] = (0, import_react7.useState)(false);
2202
+ (0, import_react7.useEffect)(() => {
1961
2203
  setMounted(true);
1962
2204
  return () => setMounted(false);
1963
2205
  }, []);
1964
- (0, import_react5.useEffect)(() => {
2206
+ (0, import_react7.useEffect)(() => {
1965
2207
  if (!isOpen) return;
1966
2208
  initEVMWalletDiscovery();
1967
2209
  const updateWallets = () => {
@@ -1982,7 +2224,7 @@ function WalletSelectModal({
1982
2224
  }
1983
2225
  };
1984
2226
  const networkName = getNetworkDisplayName(networkType);
1985
- const modalContent = /* @__PURE__ */ import_react5.default.createElement("div", { style: overlayStyle, onClick: handleOverlayClick }, /* @__PURE__ */ import_react5.default.createElement("div", { style: modalStyle }, /* @__PURE__ */ import_react5.default.createElement("div", { style: headerStyle }, /* @__PURE__ */ import_react5.default.createElement("h3", { style: titleStyle }, "Select Wallet"), /* @__PURE__ */ import_react5.default.createElement("button", { style: closeButtonStyle, onClick: onClose }, "\xD7")), /* @__PURE__ */ import_react5.default.createElement("p", { style: subtitleStyle }, "Connect a ", networkName, " wallet"), wallets.length > 0 ? /* @__PURE__ */ import_react5.default.createElement("div", { style: walletListStyle }, wallets.map((wallet) => /* @__PURE__ */ import_react5.default.createElement(
2227
+ 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(
1986
2228
  WalletItem,
1987
2229
  {
1988
2230
  key: wallet.id,
@@ -1991,9 +2233,9 @@ function WalletSelectModal({
1991
2233
  onSelect: () => onSelect(wallet),
1992
2234
  onHover: (hovered) => setHoveredWallet(hovered ? wallet.id : null)
1993
2235
  }
1994
- ))) : /* @__PURE__ */ import_react5.default.createElement("div", { style: emptyStateStyle }, /* @__PURE__ */ import_react5.default.createElement("p", { style: emptyTitleStyle }, "No wallets found"), /* @__PURE__ */ import_react5.default.createElement("p", { style: emptyDescStyle }, "Please install a ", networkName, " wallet extension."))));
2236
+ ))) : /* @__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."))));
1995
2237
  if (typeof document !== "undefined") {
1996
- return (0, import_react_dom.createPortal)(modalContent, document.body);
2238
+ return (0, import_react_dom2.createPortal)(modalContent, document.body);
1997
2239
  }
1998
2240
  return modalContent;
1999
2241
  }
@@ -2165,7 +2407,7 @@ var getErrorStyle = () => {
2165
2407
  };
2166
2408
  };
2167
2409
 
2168
- // src/react/components/WalletConnect.tsx
2410
+ // src/react/components/wallet/WalletConnect.tsx
2169
2411
  function WalletConnect({
2170
2412
  supportedNetworks = ["solana" /* SOLANA */, "evm" /* EVM */],
2171
2413
  className = "",
@@ -2174,9 +2416,9 @@ function WalletConnect({
2174
2416
  showSwitchWallet = true
2175
2417
  }) {
2176
2418
  const { address, networkType, isConnecting, error, connectWithWallet, disconnect } = useWallet();
2177
- const [hoveredButton, setHoveredButton] = (0, import_react6.useState)(null);
2178
- const [walletSelectOpen, setWalletSelectOpen] = (0, import_react6.useState)(false);
2179
- const [selectedNetworkType, setSelectedNetworkType] = (0, import_react6.useState)(null);
2419
+ const [hoveredButton, setHoveredButton] = (0, import_react8.useState)(null);
2420
+ const [walletSelectOpen, setWalletSelectOpen] = (0, import_react8.useState)(false);
2421
+ const [selectedNetworkType, setSelectedNetworkType] = (0, import_react8.useState)(null);
2180
2422
  const handleOpenWalletSelect = (network) => {
2181
2423
  setSelectedNetworkType(network);
2182
2424
  setWalletSelectOpen(true);
@@ -2198,7 +2440,7 @@ function WalletConnect({
2198
2440
  setWalletSelectOpen(true);
2199
2441
  }
2200
2442
  };
2201
- return /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, /* @__PURE__ */ import_react6.default.createElement("div", { style: { ...containerStyle, ...className ? {} : {} }, className }, !address ? /* @__PURE__ */ import_react6.default.createElement("div", { style: getSectionStyle() }, /* @__PURE__ */ import_react6.default.createElement("h3", { style: getTitleStyle() }, "Connect Wallet"), supportedNetworks.length === 0 ? /* @__PURE__ */ import_react6.default.createElement("p", { style: getHintStyle() }, "Please install a supported wallet extension") : /* @__PURE__ */ import_react6.default.createElement("div", { style: buttonsContainerStyle }, supportedNetworks.map((network) => /* @__PURE__ */ import_react6.default.createElement("div", { key: network, style: walletOptionStyle }, /* @__PURE__ */ import_react6.default.createElement(
2443
+ 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(
2202
2444
  "button",
2203
2445
  {
2204
2446
  style: getConnectButtonStyle(isConnecting, hoveredButton === network),
@@ -2208,7 +2450,7 @@ function WalletConnect({
2208
2450
  onMouseLeave: () => setHoveredButton(null)
2209
2451
  },
2210
2452
  isConnecting ? "Connecting..." : getNetworkDisplayName(network)
2211
- )))), error && /* @__PURE__ */ import_react6.default.createElement("p", { style: getErrorStyle() }, error), /* @__PURE__ */ import_react6.default.createElement("p", { style: getHintStyle() }, "Select a network to see available wallets")) : /* @__PURE__ */ import_react6.default.createElement("div", { style: getSectionStyle() }, /* @__PURE__ */ import_react6.default.createElement("div", { style: walletAddressStyle }, /* @__PURE__ */ import_react6.default.createElement("span", { style: getLabelStyle() }, "Connected ", networkType && `(${getNetworkDisplayName(networkType)})`), /* @__PURE__ */ import_react6.default.createElement("span", { style: getAddressStyle() }, formatAddress(address))), /* @__PURE__ */ import_react6.default.createElement("div", { style: walletActionsStyle }, showSwitchWallet && /* @__PURE__ */ import_react6.default.createElement(
2453
+ )))), 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(
2212
2454
  "button",
2213
2455
  {
2214
2456
  style: getConnectButtonStyle(isConnecting, hoveredButton === "switch"),
@@ -2218,7 +2460,7 @@ function WalletConnect({
2218
2460
  onMouseLeave: () => setHoveredButton(null)
2219
2461
  },
2220
2462
  isConnecting ? "Switching..." : "Switch Wallet"
2221
- ), /* @__PURE__ */ import_react6.default.createElement(
2463
+ ), /* @__PURE__ */ import_react8.default.createElement(
2222
2464
  "button",
2223
2465
  {
2224
2466
  style: getDisconnectButtonStyle(hoveredButton === "disconnect"),
@@ -2227,7 +2469,7 @@ function WalletConnect({
2227
2469
  onMouseLeave: () => setHoveredButton(null)
2228
2470
  },
2229
2471
  "Disconnect"
2230
- )), /* @__PURE__ */ import_react6.default.createElement("p", { style: getHintStyle() }, 'Click "Switch Wallet" to change wallet or account'))), selectedNetworkType && /* @__PURE__ */ import_react6.default.createElement(
2472
+ )), /* @__PURE__ */ import_react8.default.createElement("p", { style: getHintStyle() }, 'Click "Switch Wallet" to change wallet or account'))), selectedNetworkType && /* @__PURE__ */ import_react8.default.createElement(
2231
2473
  WalletSelectModal,
2232
2474
  {
2233
2475
  isOpen: walletSelectOpen,
@@ -2238,16 +2480,14 @@ function WalletConnect({
2238
2480
  ));
2239
2481
  }
2240
2482
 
2241
- // src/react/components/V402Checkout.tsx
2242
- var import_react8 = __toESM(require("react"));
2243
- var import_antd = require("antd");
2244
- var import_icons = require("@ant-design/icons");
2483
+ // src/react/components/checkout/V402CheckoutV2.tsx
2484
+ var import_react14 = __toESM(require("react"));
2245
2485
  init_common();
2246
2486
 
2247
2487
  // src/react/utils/CryptoIcons.tsx
2248
- var import_react7 = __toESM(require("react"));
2488
+ var import_react9 = __toESM(require("react"));
2249
2489
  var SolanaIcon = ({ width = 16, height = 16, className, style }) => {
2250
- return /* @__PURE__ */ import_react7.default.createElement(
2490
+ return /* @__PURE__ */ import_react9.default.createElement(
2251
2491
  "svg",
2252
2492
  {
2253
2493
  xmlns: "http://www.w3.org/2000/svg",
@@ -2257,14 +2497,14 @@ var SolanaIcon = ({ width = 16, height = 16, className, style }) => {
2257
2497
  className,
2258
2498
  style
2259
2499
  },
2260
- /* @__PURE__ */ import_react7.default.createElement("desc", null, "Solana SOL Fill Streamline Icon: https://streamlinehq.com"),
2261
- /* @__PURE__ */ import_react7.default.createElement("g", { fill: "none", fillRule: "evenodd" }, /* @__PURE__ */ import_react7.default.createElement(
2500
+ /* @__PURE__ */ import_react9.default.createElement("desc", null, "Solana SOL Fill Streamline Icon: https://streamlinehq.com"),
2501
+ /* @__PURE__ */ import_react9.default.createElement("g", { fill: "none", fillRule: "evenodd" }, /* @__PURE__ */ import_react9.default.createElement(
2262
2502
  "path",
2263
2503
  {
2264
2504
  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",
2265
2505
  strokeWidth: "0.6667"
2266
2506
  }
2267
- ), /* @__PURE__ */ import_react7.default.createElement(
2507
+ ), /* @__PURE__ */ import_react9.default.createElement(
2268
2508
  "path",
2269
2509
  {
2270
2510
  fill: "#000000",
@@ -2275,7 +2515,7 @@ var SolanaIcon = ({ width = 16, height = 16, className, style }) => {
2275
2515
  );
2276
2516
  };
2277
2517
  var BaseIcon = ({ width = 24, height = 24, className, style }) => {
2278
- return /* @__PURE__ */ import_react7.default.createElement(
2518
+ return /* @__PURE__ */ import_react9.default.createElement(
2279
2519
  "svg",
2280
2520
  {
2281
2521
  xmlns: "http://www.w3.org/2000/svg",
@@ -2289,8 +2529,8 @@ var BaseIcon = ({ width = 24, height = 24, className, style }) => {
2289
2529
  className,
2290
2530
  style
2291
2531
  },
2292
- /* @__PURE__ */ import_react7.default.createElement("desc", null, "Brand Coinbase Streamline Icon: https://streamlinehq.com"),
2293
- /* @__PURE__ */ import_react7.default.createElement(
2532
+ /* @__PURE__ */ import_react9.default.createElement("desc", null, "Brand Coinbase Streamline Icon: https://streamlinehq.com"),
2533
+ /* @__PURE__ */ import_react9.default.createElement(
2294
2534
  "path",
2295
2535
  {
2296
2536
  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",
@@ -2310,30 +2550,503 @@ var getNetworkIcon = (network) => {
2310
2550
  return BaseIcon;
2311
2551
  };
2312
2552
 
2313
- // src/react/components/V402Checkout.tsx
2314
- var { Title, Text } = import_antd.Typography;
2315
- var notify = {
2316
- success: (title, msg) => {
2317
- import_antd.message.success(`${title}: ${msg}`);
2553
+ // src/react/styles/animations.tsx
2554
+ var import_react10 = __toESM(require("react"));
2555
+ var checkoutAnimations = `
2556
+ @keyframes spin {
2557
+ from { transform: rotate(0deg); }
2558
+ to { transform: rotate(360deg); }
2559
+ }
2560
+
2561
+ @keyframes receiptShake {
2562
+ 0%, 100% { transform: rotate(-0.3deg); }
2563
+ 50% { transform: rotate(0.3deg); }
2564
+ }
2565
+
2566
+ @keyframes slideInRight {
2567
+ from {
2568
+ opacity: 0;
2569
+ transform: translateX(100px);
2570
+ }
2571
+ to {
2572
+ opacity: 1;
2573
+ transform: translateX(0);
2574
+ }
2575
+ }
2576
+
2577
+ @keyframes pulse {
2578
+ 0%, 100% { opacity: 1; }
2579
+ 50% { opacity: 0.4; }
2580
+ }
2581
+ `;
2582
+ var AnimationStyles = () => /* @__PURE__ */ import_react10.default.createElement("style", { dangerouslySetInnerHTML: { __html: checkoutAnimations } });
2583
+
2584
+ // src/react/components/checkout/Receipt.tsx
2585
+ var import_react11 = __toESM(require("react"));
2586
+ var Receipt = ({
2587
+ isLoading,
2588
+ isVisible,
2589
+ result,
2590
+ error,
2591
+ paymentDetails,
2592
+ address,
2593
+ onClose,
2594
+ primaryColor,
2595
+ receiptTitle,
2596
+ tempReceiptId
2597
+ }) => {
2598
+ const [animationState, setAnimationState] = (0, import_react11.useState)("hidden");
2599
+ (0, import_react11.useEffect)(() => {
2600
+ if (isLoading) {
2601
+ setAnimationState("printing");
2602
+ } else if (isVisible && (result || error)) {
2603
+ setAnimationState("visible");
2604
+ const timer = setTimeout(() => setAnimationState("bounce"), 50);
2605
+ return () => clearTimeout(timer);
2606
+ } else if (!isVisible) {
2607
+ setAnimationState("hidden");
2608
+ }
2609
+ }, [isLoading, isVisible, result, error]);
2610
+ (0, import_react11.useEffect)(() => {
2611
+ if (animationState === "bounce") {
2612
+ const timer = setTimeout(() => setAnimationState("visible"), 150);
2613
+ return () => clearTimeout(timer);
2614
+ }
2615
+ }, [animationState]);
2616
+ const now = /* @__PURE__ */ new Date();
2617
+ const dateStr = `${String(now.getMonth() + 1).padStart(2, "0")}/${String(now.getDate()).padStart(2, "0")}/${String(now.getFullYear()).slice(-2)}`;
2618
+ const timeStr = `${String(now.getHours()).padStart(2, "0")}:${String(now.getMinutes()).padStart(2, "0")}`;
2619
+ const receiptId = result?.transactionHash ? result.transactionHash.slice(-8).toUpperCase() : tempReceiptId;
2620
+ const getAnimationStyles = () => {
2621
+ 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)";
2622
+ switch (animationState) {
2623
+ case "hidden":
2624
+ return {
2625
+ opacity: 0,
2626
+ transform: "translateY(50px)",
2627
+ marginBottom: 0,
2628
+ transition: baseTransition
2629
+ };
2630
+ case "printing":
2631
+ return {
2632
+ opacity: 1,
2633
+ transform: "translateY(0)",
2634
+ marginBottom: "-4px",
2635
+ // 负边距让小票贴着机器,还没撕开的感觉
2636
+ animation: "receiptShake 0.12s ease-in-out infinite",
2637
+ transition: baseTransition
2638
+ };
2639
+ case "visible":
2640
+ return {
2641
+ opacity: 1,
2642
+ transform: "translateY(0)",
2643
+ marginBottom: "8px",
2644
+ transition: baseTransition
2645
+ };
2646
+ case "bounce":
2647
+ return {
2648
+ opacity: 1,
2649
+ transform: "translateY(-8px)",
2650
+ marginBottom: "8px",
2651
+ transition: baseTransition
2652
+ };
2653
+ default:
2654
+ return {};
2655
+ }
2656
+ };
2657
+ const getContentStyles = () => {
2658
+ const baseTransition = "all 0.5s cubic-bezier(0.34, 1.56, 0.64, 1)";
2659
+ switch (animationState) {
2660
+ case "hidden":
2661
+ return {
2662
+ maxHeight: 0,
2663
+ overflow: "hidden",
2664
+ transition: baseTransition
2665
+ };
2666
+ case "printing":
2667
+ return {
2668
+ maxHeight: "80px",
2669
+ overflow: "hidden",
2670
+ transition: baseTransition
2671
+ };
2672
+ case "visible":
2673
+ case "bounce":
2674
+ return {
2675
+ maxHeight: "600px",
2676
+ overflow: "visible",
2677
+ transition: baseTransition
2678
+ };
2679
+ default:
2680
+ return {};
2681
+ }
2682
+ };
2683
+ if (animationState === "hidden" && !isLoading) return null;
2684
+ return /* @__PURE__ */ import_react11.default.createElement(
2685
+ "div",
2686
+ {
2687
+ className: "w-full flex justify-center",
2688
+ style: getAnimationStyles()
2689
+ },
2690
+ /* @__PURE__ */ import_react11.default.createElement(
2691
+ "div",
2692
+ {
2693
+ className: "relative bg-white shadow-2xl",
2694
+ style: {
2695
+ width: "75%",
2696
+ maxWidth: "280px",
2697
+ backgroundImage: `
2698
+ repeating-linear-gradient(
2699
+ 0deg,
2700
+ transparent,
2701
+ transparent 1px,
2702
+ rgba(0,0,0,0.02) 1px,
2703
+ rgba(0,0,0,0.02) 2px
2704
+ )
2705
+ `
2706
+ }
2707
+ },
2708
+ /* @__PURE__ */ import_react11.default.createElement(
2709
+ "div",
2710
+ {
2711
+ className: "absolute top-0 left-0 right-0",
2712
+ style: {
2713
+ height: "8px",
2714
+ transform: "translateY(-100%)",
2715
+ background: `radial-gradient(circle at 50% 100%, white 5px, transparent 5px)`,
2716
+ backgroundSize: "12px 8px",
2717
+ backgroundPosition: "6px 0",
2718
+ backgroundRepeat: "repeat-x"
2719
+ }
2720
+ }
2721
+ ),
2722
+ /* @__PURE__ */ import_react11.default.createElement(
2723
+ "div",
2724
+ {
2725
+ className: "absolute left-0 right-0 bg-white",
2726
+ style: {
2727
+ height: "4px",
2728
+ top: "-4px"
2729
+ }
2730
+ }
2731
+ ),
2732
+ !isLoading && /* @__PURE__ */ import_react11.default.createElement(import_react11.default.Fragment, null, /* @__PURE__ */ import_react11.default.createElement(
2733
+ "div",
2734
+ {
2735
+ className: "absolute bottom-0 left-0 right-0",
2736
+ style: {
2737
+ height: "8px",
2738
+ transform: "translateY(100%)",
2739
+ background: `radial-gradient(circle at 50% 0%, white 5px, transparent 5px)`,
2740
+ backgroundSize: "12px 8px",
2741
+ backgroundPosition: "6px 0",
2742
+ backgroundRepeat: "repeat-x"
2743
+ }
2744
+ }
2745
+ ), /* @__PURE__ */ import_react11.default.createElement(
2746
+ "div",
2747
+ {
2748
+ className: "absolute left-0 right-0 bg-white",
2749
+ style: {
2750
+ height: "4px",
2751
+ bottom: "-4px"
2752
+ }
2753
+ }
2754
+ )),
2755
+ !isLoading && (result || error) && /* @__PURE__ */ import_react11.default.createElement(
2756
+ "button",
2757
+ {
2758
+ onClick: onClose,
2759
+ 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",
2760
+ style: { background: "none", border: "none" }
2761
+ },
2762
+ /* @__PURE__ */ import_react11.default.createElement("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" }, /* @__PURE__ */ import_react11.default.createElement("path", { d: "M18 6L6 18M6 6l12 12" }))
2763
+ ),
2764
+ /* @__PURE__ */ import_react11.default.createElement("div", { className: "p-4 font-mono text-sm", style: getContentStyles() }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "text-center mb-3" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "text-base font-bold tracking-wider text-gray-800" }, receiptTitle), /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex justify-between text-xs text-gray-500 mt-1" }, /* @__PURE__ */ import_react11.default.createElement("span", null, "ID: ", receiptId), /* @__PURE__ */ import_react11.default.createElement("span", null, dateStr, " ", timeStr))), /* @__PURE__ */ import_react11.default.createElement("div", { className: "border-t border-dashed border-gray-300 my-2" }), /* @__PURE__ */ import_react11.default.createElement(
2765
+ "div",
2766
+ {
2767
+ className: "max-h-64 overflow-y-auto pr-1",
2768
+ style: {
2769
+ scrollbarWidth: "thin",
2770
+ scrollbarColor: "#d1d5db transparent"
2771
+ }
2772
+ },
2773
+ isLoading ? /* @__PURE__ */ import_react11.default.createElement(LoadingContent, { primaryColor }) : error ? /* @__PURE__ */ import_react11.default.createElement(ErrorContent, { error }) : result ? /* @__PURE__ */ import_react11.default.createElement(
2774
+ SuccessContent,
2775
+ {
2776
+ result,
2777
+ paymentDetails,
2778
+ address,
2779
+ primaryColor
2780
+ }
2781
+ ) : null
2782
+ ), /* @__PURE__ */ import_react11.default.createElement("div", { className: "border-t border-dashed border-gray-300 my-2" }), /* @__PURE__ */ import_react11.default.createElement(Barcode, null), /* @__PURE__ */ import_react11.default.createElement("div", { className: "text-center text-xs text-gray-400 mt-1 tracking-widest" }, "POWERED BY", " ", /* @__PURE__ */ import_react11.default.createElement(
2783
+ "a",
2784
+ {
2785
+ href: "https://v402pay.onvoyage.ai",
2786
+ target: "_blank",
2787
+ rel: "noopener noreferrer",
2788
+ className: "text-gray-500 hover:text-gray-700 underline transition-colors"
2789
+ },
2790
+ "V402PAY"
2791
+ )))
2792
+ )
2793
+ );
2794
+ };
2795
+ var LoadingContent = ({ primaryColor }) => /* @__PURE__ */ import_react11.default.createElement("div", { className: "text-center py-4" }, /* @__PURE__ */ import_react11.default.createElement(
2796
+ "div",
2797
+ {
2798
+ className: "inline-block w-8 h-8 border-2 border-gray-200 rounded-full mb-2",
2799
+ style: {
2800
+ borderTopColor: primaryColor,
2801
+ animation: "spin 0.8s linear infinite"
2802
+ }
2803
+ }
2804
+ ), /* @__PURE__ */ import_react11.default.createElement("div", { className: "text-gray-700 font-semibold text-sm" }, "Processing..."), /* @__PURE__ */ import_react11.default.createElement("div", { className: "text-gray-400 text-xs mt-1" }, "Please wait"));
2805
+ var ErrorContent = ({ error }) => /* @__PURE__ */ import_react11.default.createElement("div", { className: "text-center py-3" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "text-red-500 text-2xl mb-2" }, "\u2717"), /* @__PURE__ */ import_react11.default.createElement("div", { className: "text-red-600 font-semibold mb-1 text-sm" }, "FAILED"), /* @__PURE__ */ import_react11.default.createElement("div", { className: "text-red-500 text-xs break-words px-2" }, error));
2806
+ var SuccessContent = ({
2807
+ result,
2808
+ paymentDetails,
2809
+ address,
2810
+ primaryColor
2811
+ }) => {
2812
+ const [copied, setCopied] = (0, import_react11.useState)(false);
2813
+ const handleCopy = async () => {
2814
+ try {
2815
+ await navigator.clipboard.writeText(JSON.stringify(result, null, 2));
2816
+ setCopied(true);
2817
+ setTimeout(() => setCopied(false), 2e3);
2818
+ } catch (err) {
2819
+ console.error("Failed to copy:", err);
2820
+ }
2821
+ };
2822
+ return /* @__PURE__ */ import_react11.default.createElement("div", null, /* @__PURE__ */ import_react11.default.createElement("div", { className: "text-center mb-2" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "text-2xl mb-1", style: { color: primaryColor } }, "\u2713"), /* @__PURE__ */ import_react11.default.createElement("div", { className: "font-semibold text-sm", style: { color: primaryColor } }, "SUCCESS")), /* @__PURE__ */ import_react11.default.createElement("div", { className: "space-y-1 text-xs" }, paymentDetails && /* @__PURE__ */ import_react11.default.createElement(import_react11.default.Fragment, null, /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex justify-between" }, /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-gray-500" }, "Amount:"), /* @__PURE__ */ import_react11.default.createElement("span", { className: "font-semibold" }, "$", paymentDetails.amount, " ", paymentDetails.currency)), /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex justify-between" }, /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-gray-500" }, "Network:"), /* @__PURE__ */ import_react11.default.createElement("span", { className: "font-semibold" }, paymentDetails.network))), address && /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex justify-between" }, /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-gray-500" }, "From:"), /* @__PURE__ */ import_react11.default.createElement("span", { className: "font-semibold" }, formatAddress(address))), result.transactionHash && /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex justify-between" }, /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-gray-500" }, "TX:"), /* @__PURE__ */ import_react11.default.createElement("span", { className: "font-semibold" }, formatAddress(result.transactionHash)))), /* @__PURE__ */ import_react11.default.createElement("div", { className: "border-t border-dashed border-gray-300 my-2" }), /* @__PURE__ */ import_react11.default.createElement("div", { className: "text-xs" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex justify-between items-center mb-1" }, /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-gray-500" }, "Response:"), /* @__PURE__ */ import_react11.default.createElement(
2823
+ "button",
2824
+ {
2825
+ onClick: handleCopy,
2826
+ 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",
2827
+ style: { background: "none", border: "none" }
2828
+ },
2829
+ copied ? /* @__PURE__ */ import_react11.default.createElement("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" }, /* @__PURE__ */ import_react11.default.createElement("path", { d: "M20 6L9 17l-5-5" })) : /* @__PURE__ */ import_react11.default.createElement("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }, /* @__PURE__ */ import_react11.default.createElement("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }), /* @__PURE__ */ import_react11.default.createElement("path", { d: "M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1" }))
2830
+ )), /* @__PURE__ */ import_react11.default.createElement(
2831
+ "pre",
2832
+ {
2833
+ className: "bg-gray-50 p-2 rounded text-xs overflow-auto whitespace-pre-wrap break-words",
2834
+ style: { maxHeight: "80px", fontSize: "10px" }
2835
+ },
2836
+ JSON.stringify(result, null, 2)
2837
+ )));
2838
+ };
2839
+ var Barcode = () => {
2840
+ const pattern = [2, 1, 2, 1, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 1];
2841
+ const heights = [10, 12, 11, 13, 10, 14, 11, 12, 13, 10, 11, 14, 12, 10, 13, 11, 12, 14, 10, 11];
2842
+ return /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-center justify-center gap-0.5 h-4 opacity-60" }, pattern.map((width, i) => /* @__PURE__ */ import_react11.default.createElement(
2843
+ "div",
2844
+ {
2845
+ key: i,
2846
+ className: "bg-gray-800",
2847
+ style: {
2848
+ width: `${width}px`,
2849
+ height: `${heights[i]}px`
2850
+ }
2851
+ }
2852
+ )));
2853
+ };
2854
+
2855
+ // src/react/components/checkout/TerminalScreen.tsx
2856
+ var import_react12 = __toESM(require("react"));
2857
+ var TerminalScreen = ({
2858
+ title,
2859
+ tooltipText,
2860
+ hasInvalidCheckoutId,
2861
+ fetchingPaymentInfo,
2862
+ address,
2863
+ paymentDetails,
2864
+ screenText,
2865
+ supportedNetworks
2866
+ }) => {
2867
+ return /* @__PURE__ */ import_react12.default.createElement(
2868
+ "div",
2869
+ {
2870
+ className: "rounded-xl p-3 mb-3",
2871
+ style: {
2872
+ backgroundColor: "#0a1a0a",
2873
+ boxShadow: "inset 0 3px 16px rgba(0,0,0,0.5)",
2874
+ border: "3px solid rgba(0,0,0,0.3)"
2875
+ }
2876
+ },
2877
+ /* @__PURE__ */ import_react12.default.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "flex items-center gap-1.5 flex-1 min-w-0" }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "w-2.5 h-2.5 rounded border border-green-700 flex-shrink-0" }), title ? /* @__PURE__ */ import_react12.default.createElement(
2878
+ "span",
2879
+ {
2880
+ className: "text-xs font-mono",
2881
+ style: { color: "#22c55e80" },
2882
+ title
2883
+ },
2884
+ title.length > 26 ? `${title.slice(0, 13)}...${title.slice(-13)}` : title
2885
+ ) : /* @__PURE__ */ import_react12.default.createElement("span", { className: "text-xs font-mono", style: { color: "#22c55e80" } }, "CHECKOUT")), /* @__PURE__ */ import_react12.default.createElement(
2886
+ "div",
2887
+ {
2888
+ className: "flex gap-0.5 flex-shrink-0 cursor-help",
2889
+ title: tooltipText
2890
+ },
2891
+ /* @__PURE__ */ import_react12.default.createElement(
2892
+ "div",
2893
+ {
2894
+ className: "w-1 h-1.5 rounded-sm",
2895
+ style: { backgroundColor: address ? "#22c55e80" : "#22c55e30" }
2896
+ }
2897
+ ),
2898
+ /* @__PURE__ */ import_react12.default.createElement(
2899
+ "div",
2900
+ {
2901
+ className: "w-1 h-1.5 rounded-sm",
2902
+ style: { backgroundColor: address ? "#22c55e80" : "#22c55e30" }
2903
+ }
2904
+ ),
2905
+ /* @__PURE__ */ import_react12.default.createElement("div", { className: "w-1 h-1.5 rounded-sm", style: { backgroundColor: "#22c55e80" } })
2906
+ )),
2907
+ /* @__PURE__ */ import_react12.default.createElement("div", { className: "min-h-[120px]" }, hasInvalidCheckoutId ? /* @__PURE__ */ import_react12.default.createElement(InvalidIdContent, null) : fetchingPaymentInfo ? /* @__PURE__ */ import_react12.default.createElement(LoadingContent2, null) : !address ? /* @__PURE__ */ import_react12.default.createElement(ConnectWalletContent, { supportedNetworks }) : /* @__PURE__ */ import_react12.default.createElement(
2908
+ PaymentInfoContent,
2909
+ {
2910
+ screenText,
2911
+ paymentDetails,
2912
+ address
2913
+ }
2914
+ ))
2915
+ );
2916
+ };
2917
+ var InvalidIdContent = () => /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-center py-3" }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-red-500 text-xl mb-1" }, "\u2717"), /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-red-500 font-mono text-sm mb-1" }, "INVALID ID"), /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-red-400 font-mono text-xs" }, "Check your checkout ID"));
2918
+ var LoadingContent2 = () => /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-center py-4" }, /* @__PURE__ */ import_react12.default.createElement(
2919
+ "div",
2920
+ {
2921
+ className: "inline-block w-5 h-5 border-2 rounded-full mb-2",
2922
+ style: {
2923
+ borderColor: "#22c55e40",
2924
+ borderTopColor: "#22c55e",
2925
+ animation: "spin 1s linear infinite"
2926
+ }
2927
+ }
2928
+ ), /* @__PURE__ */ import_react12.default.createElement("div", { className: "font-mono text-sm", style: { color: "#22c55e" } }, "LOADING..."));
2929
+ var ConnectWalletContent = ({ supportedNetworks }) => /* @__PURE__ */ import_react12.default.createElement("div", null, /* @__PURE__ */ import_react12.default.createElement(
2930
+ "div",
2931
+ {
2932
+ className: "font-mono text-base mb-3 tracking-wider",
2933
+ style: { color: "#f97316", textShadow: "0 0 10px #f9731640" }
2318
2934
  },
2319
- error: (title, msg) => {
2320
- import_antd.message.error(`${title}: ${msg}`);
2935
+ "CONNECT WALLET..."
2936
+ ), /* @__PURE__ */ import_react12.default.createElement(WalletConnect, { supportedNetworks, showSwitchWallet: false }));
2937
+ var PaymentInfoContent = ({
2938
+ screenText,
2939
+ paymentDetails,
2940
+ address
2941
+ }) => /* @__PURE__ */ import_react12.default.createElement("div", null, /* @__PURE__ */ import_react12.default.createElement(
2942
+ "div",
2943
+ {
2944
+ className: "font-mono text-base mb-3 tracking-wider",
2945
+ style: { color: "#f97316", textShadow: "0 0 10px #f9731640" }
2321
2946
  },
2322
- info: (title, msg) => {
2323
- import_antd.message.info(`${title}: ${msg}`);
2324
- }
2947
+ screenText
2948
+ ), paymentDetails && /* @__PURE__ */ import_react12.default.createElement("div", { className: "text-xs font-mono" }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "grid grid-cols-2 gap-1.5 mb-1.5" }, /* @__PURE__ */ import_react12.default.createElement("div", null, /* @__PURE__ */ import_react12.default.createElement("div", { style: { color: "#22c55e60" } }, "AMOUNT"), /* @__PURE__ */ import_react12.default.createElement("div", { style: { color: "#22c55e" } }, "$", paymentDetails.amount)), /* @__PURE__ */ import_react12.default.createElement("div", null, /* @__PURE__ */ import_react12.default.createElement("div", { style: { color: "#22c55e60" } }, "CURRENCY"), /* @__PURE__ */ import_react12.default.createElement("div", { style: { color: "#22c55e" } }, paymentDetails.currency))), /* @__PURE__ */ import_react12.default.createElement("div", null, /* @__PURE__ */ import_react12.default.createElement("div", { style: { color: "#22c55e60" } }, "WALLET"), /* @__PURE__ */ import_react12.default.createElement("div", { style: { color: "#22c55e", wordBreak: "break-all" } }, address))));
2949
+
2950
+ // src/react/components/checkout/TerminalButtons.tsx
2951
+ var import_react13 = __toESM(require("react"));
2952
+ var TerminalButtons = ({
2953
+ address,
2954
+ showReceipt,
2955
+ isProcessing,
2956
+ paymentDetails,
2957
+ hasInvalidCheckoutId,
2958
+ onDisconnect,
2959
+ onClearReceipt,
2960
+ onPayment
2961
+ }) => {
2962
+ const isPayDisabled = isProcessing || !paymentDetails || !address || hasInvalidCheckoutId;
2963
+ return /* @__PURE__ */ import_react13.default.createElement("div", { className: "flex items-center justify-between px-1" }, /* @__PURE__ */ import_react13.default.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ import_react13.default.createElement(
2964
+ CircleButton,
2965
+ {
2966
+ onClick: () => address && onDisconnect(),
2967
+ disabled: !address,
2968
+ title: "Disconnect",
2969
+ size: "small"
2970
+ },
2971
+ /* @__PURE__ */ import_react13.default.createElement("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "white", strokeWidth: "2" }, /* @__PURE__ */ import_react13.default.createElement("path", { d: "M18 6L6 18M6 6l12 12" }))
2972
+ ), /* @__PURE__ */ import_react13.default.createElement(
2973
+ CircleButton,
2974
+ {
2975
+ onClick: onClearReceipt,
2976
+ disabled: !showReceipt || isProcessing,
2977
+ title: "Clear",
2978
+ size: "small"
2979
+ },
2980
+ /* @__PURE__ */ import_react13.default.createElement("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "white", strokeWidth: "2" }, /* @__PURE__ */ import_react13.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" }))
2981
+ )), /* @__PURE__ */ import_react13.default.createElement("div", { className: "flex flex-col gap-0.5 opacity-40" }, /* @__PURE__ */ import_react13.default.createElement("div", { className: "w-6 h-0.5 rounded", style: { backgroundColor: "rgba(0,0,0,0.3)" } }), /* @__PURE__ */ import_react13.default.createElement("div", { className: "w-6 h-0.5 rounded", style: { backgroundColor: "rgba(0,0,0,0.3)" } }), /* @__PURE__ */ import_react13.default.createElement("div", { className: "w-6 h-0.5 rounded", style: { backgroundColor: "rgba(0,0,0,0.3)" } })), /* @__PURE__ */ import_react13.default.createElement(
2982
+ "button",
2983
+ {
2984
+ onClick: onPayment,
2985
+ disabled: isPayDisabled,
2986
+ className: "px-5 py-2.5 rounded-xl font-bold text-white flex items-center gap-2 transition-all active:scale-95",
2987
+ style: {
2988
+ backgroundColor: isPayDisabled ? "#9ca3af" : "#ea580c",
2989
+ boxShadow: isPayDisabled ? "none" : "0 4px 12px rgba(234,88,12,0.4), inset 0 -2px 4px rgba(0,0,0,0.2)",
2990
+ cursor: isPayDisabled ? "not-allowed" : "pointer"
2991
+ }
2992
+ },
2993
+ isProcessing ? /* @__PURE__ */ import_react13.default.createElement(import_react13.default.Fragment, null, /* @__PURE__ */ import_react13.default.createElement(
2994
+ "div",
2995
+ {
2996
+ className: "w-4 h-4 border-2 border-white/30 border-t-white rounded-full",
2997
+ style: { animation: "spin 0.8s linear infinite" }
2998
+ }
2999
+ ), /* @__PURE__ */ import_react13.default.createElement("span", { className: "font-mono tracking-wider text-sm" }, "PAYING...")) : /* @__PURE__ */ import_react13.default.createElement(import_react13.default.Fragment, null, /* @__PURE__ */ import_react13.default.createElement("span", { className: "font-mono tracking-wider text-sm" }, "PAY"), /* @__PURE__ */ import_react13.default.createElement(
3000
+ "svg",
3001
+ {
3002
+ width: "18",
3003
+ height: "18",
3004
+ viewBox: "0 0 24 24",
3005
+ fill: "none",
3006
+ stroke: "currentColor",
3007
+ strokeWidth: "2"
3008
+ },
3009
+ /* @__PURE__ */ import_react13.default.createElement("path", { d: "M12 2v20M17 5H9.5a3.5 3.5 0 000 7h5a3.5 3.5 0 010 7H6" })
3010
+ ))
3011
+ ));
3012
+ };
3013
+ var CircleButton = ({ onClick, disabled, title, size = "normal", children }) => {
3014
+ const sizeClass = size === "small" ? "w-10 h-10" : "w-12 h-12";
3015
+ return /* @__PURE__ */ import_react13.default.createElement(
3016
+ "button",
3017
+ {
3018
+ onClick,
3019
+ disabled,
3020
+ className: `${sizeClass} rounded-full flex items-center justify-center transition-transform active:scale-95`,
3021
+ style: {
3022
+ backgroundColor: "#374151",
3023
+ boxShadow: "inset 0 -2px 4px rgba(0,0,0,0.3), 0 2px 4px rgba(0,0,0,0.2)",
3024
+ opacity: disabled ? 0.5 : 1
3025
+ },
3026
+ title
3027
+ },
3028
+ children
3029
+ );
3030
+ };
3031
+
3032
+ // src/react/components/checkout/V402CheckoutV2.tsx
3033
+ var generateRandomId = () => {
3034
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
3035
+ return Array.from({ length: 8 }, () => chars[Math.floor(Math.random() * chars.length)]).join("");
2325
3036
  };
2326
- function V402Checkout({
3037
+ function V402CheckoutV2({
2327
3038
  checkoutId,
2328
3039
  headerInfo = {},
3040
+ primaryColor = "#84cc16",
2329
3041
  isModal = false,
2330
3042
  onPaymentComplete,
2331
3043
  additionalParams = {},
2332
3044
  expectedNetwork
2333
3045
  }) {
2334
3046
  const {
2335
- title = "V402Pay - Make x402Pay Easier",
2336
- subtitle = "onvoyage.ai",
3047
+ title = "V402Pay Checkout",
3048
+ brandName = "V402PAY",
3049
+ receiptTitle = "V402 PAYMENT",
2337
3050
  tooltipText = "V402Pay - Accept Crypto Payments Easier"
2338
3051
  } = headerInfo;
2339
3052
  const endpoint = PROD_BACK_URL;
@@ -2348,458 +3061,182 @@ function V402Checkout({
2348
3061
  { autoSwitch: !!targetNetwork, switchOnMount: true }
2349
3062
  );
2350
3063
  const { isProcessing, setIsProcessing, result, setResult, error, setError } = usePayment();
2351
- const [paymentDetails, setPaymentDetails] = (0, import_react8.useState)(null);
3064
+ const [paymentDetails, setPaymentDetails] = (0, import_react14.useState)(null);
3065
+ const [showReceipt, setShowReceipt] = (0, import_react14.useState)(false);
3066
+ const [tempReceiptId, setTempReceiptId] = (0, import_react14.useState)(() => generateRandomId());
2352
3067
  const handleDisconnect = () => {
2353
3068
  disconnect();
2354
3069
  setResult(null);
2355
3070
  setError(null);
2356
- notify.info("Wallet Disconnected", "Your wallet has been disconnected successfully.");
3071
+ setShowReceipt(false);
2357
3072
  };
2358
- (0, import_react8.useEffect)(() => {
2359
- if (paymentInfo && paymentInfo.length > 0) {
2360
- const firstPayment = paymentInfo[0];
2361
- const rawAmount = firstPayment.maxAmountRequired?.toString() || "0";
2362
- const decimals = 6;
2363
- const humanReadableAmount = (Number(rawAmount) / Math.pow(10, decimals)).toFixed(2);
2364
- const network = firstPayment.network || "Unknown";
2365
- const currency = "USDC";
2366
- setPaymentDetails({
2367
- amount: humanReadableAmount,
2368
- currency,
2369
- network
2370
- });
2371
- }
2372
- }, [paymentInfo]);
2373
- (0, import_react8.useEffect)(() => {
2374
- if (targetNetwork && !fetchingPaymentInfo && ensureNetwork) {
2375
- ensureNetwork(targetNetwork).catch((err) => {
2376
- console.error("Failed to ensure network:", err);
2377
- });
2378
- }
2379
- }, [targetNetwork, fetchingPaymentInfo]);
2380
3073
  const handlePayment = async () => {
2381
- if (!networkType) {
2382
- notify.error("Wallet Not Connected", "Please connect your wallet first.");
2383
- return;
2384
- }
3074
+ if (!networkType) return;
3075
+ setTempReceiptId(generateRandomId());
2385
3076
  setResult(null);
2386
3077
  setError(null);
2387
3078
  setIsProcessing(true);
3079
+ setShowReceipt(true);
2388
3080
  try {
2389
- const response = await makePayment(networkType, checkoutId, endpoint, additionalParams);
3081
+ const response = await makePayment(networkType, checkoutId, endpoint, additionalParams, address || void 0);
2390
3082
  const data = await response.json();
2391
3083
  setResult(data);
2392
- notify.success("Payment Successful!", "Your payment has been processed successfully.");
2393
3084
  if (onPaymentComplete) {
2394
3085
  onPaymentComplete(data);
2395
3086
  }
2396
3087
  } catch (err) {
2397
- const errorMessage = err.message || "Payment failed";
2398
- setError(errorMessage);
2399
- notify.error("Payment Failed", errorMessage);
3088
+ setError(err.message || "Payment failed");
2400
3089
  } finally {
2401
3090
  setIsProcessing(false);
2402
3091
  }
2403
3092
  };
2404
- const getNetworkColor = (network) => {
2405
- if (network.toLowerCase().includes("solana")) return "#14F195";
2406
- if (network.toLowerCase().includes("evm") || network.toLowerCase().includes("base")) return "#0052FF";
2407
- return "#8c8c8c";
3093
+ const handleCloseReceipt = () => {
3094
+ setShowReceipt(false);
3095
+ setResult(null);
3096
+ setError(null);
2408
3097
  };
2409
- const NetworkIcon = paymentDetails ? getNetworkIcon(paymentDetails.network) : null;
2410
- const networkColor = paymentDetails ? getNetworkColor(paymentDetails.network) : "#8c8c8c";
2411
- const loadingColor = "#8c8c8c";
3098
+ (0, import_react14.useEffect)(() => {
3099
+ if (paymentInfo && paymentInfo.length > 0) {
3100
+ const firstPayment = paymentInfo[0];
3101
+ const rawAmount = firstPayment.maxAmountRequired?.toString() || "0";
3102
+ const decimals = 6;
3103
+ const humanReadableAmount = (Number(rawAmount) / Math.pow(10, decimals)).toFixed(2);
3104
+ const network = firstPayment.network || "Unknown";
3105
+ const currency = "USDC";
3106
+ setPaymentDetails({ amount: humanReadableAmount, currency, network });
3107
+ }
3108
+ }, [paymentInfo]);
3109
+ (0, import_react14.useEffect)(() => {
3110
+ if (targetNetwork && !fetchingPaymentInfo && ensureNetwork) {
3111
+ ensureNetwork(targetNetwork).catch((err) => {
3112
+ console.error("Failed to ensure network:", err);
3113
+ });
3114
+ }
3115
+ }, [targetNetwork, fetchingPaymentInfo]);
3116
+ (0, import_react14.useEffect)(() => {
3117
+ if (isProcessing || result || error) {
3118
+ setShowReceipt(true);
3119
+ }
3120
+ }, [isProcessing, result, error]);
2412
3121
  const hasInvalidCheckoutId = !fetchingPaymentInfo && (!paymentInfo || paymentInfo.length === 0);
2413
- return /* @__PURE__ */ import_react8.default.createElement(
3122
+ const NetworkIcon = paymentDetails ? getNetworkIcon(paymentDetails.network) : null;
3123
+ const screenText = paymentDetails ? `PAY $${paymentDetails.amount} ${paymentDetails.currency}` : "AWAITING...";
3124
+ const getStatusText = () => {
3125
+ if (hasInvalidCheckoutId) return "ERROR";
3126
+ if (fetchingPaymentInfo) return "LOADING";
3127
+ if (!address) return "CONNECT";
3128
+ if (isProcessing) return "PAYING";
3129
+ return "READY";
3130
+ };
3131
+ return /* @__PURE__ */ import_react14.default.createElement("div", { className: isModal ? "bg-transparent" : "min-h-screen bg-gray-100 flex items-center justify-center p-4" }, /* @__PURE__ */ import_react14.default.createElement(
2414
3132
  "div",
2415
3133
  {
2416
- className: isModal ? "bg-white" : "h-screen bg-white flex items-center justify-center p-4 overflow-hidden"
3134
+ className: "flex flex-col items-center",
3135
+ style: { width: isModal ? "100%" : "380px", maxWidth: "100%" }
2417
3136
  },
2418
- /* @__PURE__ */ import_react8.default.createElement(
3137
+ /* @__PURE__ */ import_react14.default.createElement(
3138
+ Receipt,
3139
+ {
3140
+ isLoading: isProcessing,
3141
+ isVisible: showReceipt,
3142
+ result,
3143
+ error,
3144
+ paymentDetails,
3145
+ address,
3146
+ onClose: handleCloseReceipt,
3147
+ primaryColor,
3148
+ receiptTitle,
3149
+ tempReceiptId
3150
+ }
3151
+ ),
3152
+ /* @__PURE__ */ import_react14.default.createElement(
2419
3153
  "div",
2420
3154
  {
2421
- className: "flex gap-4 items-center justify-center",
3155
+ className: "relative rounded-2xl p-3 shadow-2xl w-full",
2422
3156
  style: {
2423
- maxWidth: isProcessing || result || error ? "1200px" : "480px",
2424
- transition: "max-width 0.4s ease-in-out",
2425
- width: "100%"
3157
+ backgroundColor: primaryColor,
3158
+ boxShadow: `0 16px 48px -8px ${primaryColor}66, 0 8px 24px -4px rgba(0,0,0,0.3);padding-bottom: 0px`
2426
3159
  }
2427
3160
  },
2428
- /* @__PURE__ */ import_react8.default.createElement(
2429
- import_antd.Card,
3161
+ /* @__PURE__ */ import_react14.default.createElement(
3162
+ "div",
3163
+ {
3164
+ className: "absolute top-0 left-1/2 -translate-x-1/2 w-1/3 h-2.5 rounded-b-lg",
3165
+ style: { backgroundColor: "rgba(0,0,0,0.4)" }
3166
+ }
3167
+ ),
3168
+ /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex justify-between items-center mb-2 mt-1 px-1" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react14.default.createElement(
3169
+ "div",
2430
3170
  {
2431
- className: "flex-shrink-0",
3171
+ className: "w-2 h-2 rounded-full",
2432
3172
  style: {
2433
- border: isModal ? "none" : "1px solid #e8e8e8",
2434
- borderRadius: isModal ? "0" : "16px",
2435
- boxShadow: isModal ? "none" : "0 4px 24px rgba(0, 0, 0, 0.06)",
2436
- maxHeight: isModal ? "calc(100vh - 100px)" : "calc(100vh - 32px)",
2437
- overflow: "auto",
2438
- width: isModal ? "100%" : "480px",
2439
- transition: "all 0.4s ease-in-out",
2440
- transform: result || error ? "translateX(0)" : "translateX(0)"
2441
- },
2442
- styles: { body: { padding: isModal ? "0px" : "32px 24px" } }
3173
+ backgroundColor: address ? "#22c55e" : "#ef4444",
3174
+ animation: "pulse 2s ease-in-out infinite"
3175
+ }
3176
+ }
3177
+ ), /* @__PURE__ */ import_react14.default.createElement(
3178
+ "span",
3179
+ {
3180
+ className: "text-xs font-mono font-bold tracking-wider",
3181
+ style: { color: "rgba(0,0,0,0.7)" }
2443
3182
  },
2444
- /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center gap-3 mb-4" }, /* @__PURE__ */ import_react8.default.createElement(
2445
- "div",
2446
- {
2447
- className: "w-12 h-12 rounded-xl flex items-center justify-center",
2448
- style: {
2449
- background: hasInvalidCheckoutId ? "#ff4d4f" : paymentDetails ? networkColor : loadingColor,
2450
- transition: "background 0.3s ease"
2451
- }
2452
- },
2453
- hasInvalidCheckoutId ? /* @__PURE__ */ import_react8.default.createElement("span", { style: { fontSize: "20px", color: "white", fontWeight: "bold" } }, "\u2717") : paymentDetails && NetworkIcon ? /* @__PURE__ */ import_react8.default.createElement(NetworkIcon, { width: 24, height: 24 }) : /* @__PURE__ */ import_react8.default.createElement(import_icons.LoadingOutlined, { style: { fontSize: "20px", color: "white" }, spin: true })
2454
- ), /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex-1" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react8.default.createElement(Title, { level: 4, style: { margin: 0, fontSize: "18px", fontWeight: 600 } }, title || "Echo Payment OnVoyage"), !hasInvalidCheckoutId && /* @__PURE__ */ import_react8.default.createElement(
2455
- import_antd.Tooltip,
2456
- {
2457
- title: tooltipText,
2458
- placement: "top"
2459
- },
2460
- /* @__PURE__ */ import_react8.default.createElement(
2461
- import_icons.InfoCircleOutlined,
2462
- {
2463
- style: { fontSize: "14px", color: "#8c8c8c", cursor: "help" }
2464
- }
2465
- )
2466
- )), /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, subtitle))),
2467
- /* @__PURE__ */ import_react8.default.createElement("div", { className: "text-center mb-5" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "inline-flex items-center justify-center w-12 h-12 rounded-full bg-gray-50 mb-3" }, /* @__PURE__ */ import_react8.default.createElement(import_icons.LockOutlined, { style: { fontSize: "20px", color: "#595959" } })), /* @__PURE__ */ import_react8.default.createElement(Title, { level: 3, style: { margin: "0 0 6px 0", fontSize: "20px", fontWeight: 600 } }, "Payment Required"), /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Pay ", paymentDetails ? `$${paymentDetails.amount} ${paymentDetails.currency}` : "the required amount", " to access")),
2468
- hasInvalidCheckoutId && /* @__PURE__ */ import_react8.default.createElement("div", { className: "text-center py-6" }, /* @__PURE__ */ import_react8.default.createElement(
2469
- "div",
2470
- {
2471
- className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
2472
- style: {
2473
- background: "linear-gradient(135deg, #ef4444 0%, #f87171 100%)",
2474
- boxShadow: "0 4px 20px rgba(239, 68, 68, 0.3)"
2475
- }
2476
- },
2477
- /* @__PURE__ */ import_react8.default.createElement("span", { style: { fontSize: "32px", color: "white" } }, "!")
2478
- ), /* @__PURE__ */ import_react8.default.createElement(
2479
- Title,
2480
- {
2481
- level: 4,
2482
- style: { margin: "0 0 12px 0", fontSize: "18px", fontWeight: 600, color: "#262626" }
2483
- },
2484
- "Invalid Checkout ID"
2485
- ), /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c", display: "block", marginBottom: "16px" } }, "The checkout ID you provided is invalid or has expired."), /* @__PURE__ */ import_react8.default.createElement(
2486
- "div",
2487
- {
2488
- style: {
2489
- background: "#fef2f2",
2490
- padding: "16px",
2491
- borderRadius: "12px",
2492
- border: "1px solid #fee2e2",
2493
- marginTop: "16px"
2494
- }
2495
- },
2496
- /* @__PURE__ */ import_react8.default.createElement(Text, { style: {
2497
- fontSize: "13px",
2498
- color: "#dc2626",
2499
- lineHeight: "1.6",
2500
- fontWeight: 500
2501
- } }, "Failed to load payment information. Please check your checkout ID.")
2502
- )),
2503
- !hasInvalidCheckoutId && fetchingPaymentInfo && /* @__PURE__ */ import_react8.default.createElement("div", { className: "text-center py-6" }, /* @__PURE__ */ import_react8.default.createElement(Text, { style: { color: "#8c8c8c" } }, "Loading payment information...")),
2504
- !hasInvalidCheckoutId && !fetchingPaymentInfo && !address && /* @__PURE__ */ import_react8.default.createElement("div", null, /* @__PURE__ */ import_react8.default.createElement(WalletConnect, { supportedNetworks })),
2505
- !hasInvalidCheckoutId && address && /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement(
2506
- "div",
2507
- {
2508
- className: "bg-gray-50 rounded-lg p-3 mb-4",
2509
- style: { border: "1px solid #f0f0f0" }
2510
- },
2511
- /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center gap-3 flex-1" }, /* @__PURE__ */ import_react8.default.createElement(
2512
- "div",
2513
- {
2514
- className: "w-10 h-10 rounded-full bg-black flex items-center justify-center text-white text-sm font-semibold"
2515
- },
2516
- address.slice(0, 2).toUpperCase()
2517
- ), /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react8.default.createElement(Text, { style: {
2518
- display: "block",
2519
- fontSize: "12px",
2520
- color: "#8c8c8c",
2521
- marginBottom: "2px"
2522
- } }, "Connected Wallet"), /* @__PURE__ */ import_react8.default.createElement(
2523
- Text,
2524
- {
2525
- style: {
2526
- fontSize: "13px",
2527
- fontWeight: 600,
2528
- fontFamily: "Monaco, monospace"
2529
- }
2530
- },
2531
- formatAddress(address)
2532
- ))), /* @__PURE__ */ import_react8.default.createElement(
2533
- import_antd.Button,
2534
- {
2535
- type: "text",
2536
- size: "small",
2537
- icon: /* @__PURE__ */ import_react8.default.createElement(import_icons.DisconnectOutlined, null),
2538
- onClick: handleDisconnect,
2539
- style: { color: "#ff4d4f" }
2540
- }
2541
- ))
2542
- ), paymentDetails && /* @__PURE__ */ import_react8.default.createElement("div", { className: "bg-gray-50 rounded-lg p-3 mb-4", style: { border: "1px solid #f0f0f0" } }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Payment Amount"), /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "18px", fontWeight: 600 } }, "$", paymentDetails.amount)), /* @__PURE__ */ import_react8.default.createElement(import_antd.Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Currency"), /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "14px", fontWeight: 500 } }, paymentDetails.currency)), /* @__PURE__ */ import_react8.default.createElement(import_antd.Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex justify-between items-center mb-2" }, /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Network"), /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "14px", fontWeight: 500 } }, paymentDetails.network)), /* @__PURE__ */ import_react8.default.createElement(import_antd.Divider, { style: { margin: "6px 0" } }), /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex justify-between items-start" }, /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Wallet Address"), /* @__PURE__ */ import_react8.default.createElement(Text, { style: {
2543
- fontSize: "11px",
2544
- fontWeight: 500,
2545
- fontFamily: "Monaco, monospace",
2546
- wordBreak: "break-all",
2547
- textAlign: "right",
2548
- maxWidth: "60%",
2549
- lineHeight: 1.4
2550
- } }, address))), /* @__PURE__ */ import_react8.default.createElement(
2551
- "div",
2552
- {
2553
- className: "flex items-center justify-center gap-2 mb-3 p-2 rounded-lg",
2554
- style: { background: "#f6ffed", border: "1px solid #d9f7be" }
2555
- },
2556
- /* @__PURE__ */ import_react8.default.createElement(import_icons.SafetyOutlined, { style: { color: "#52c41a", fontSize: "13px" } }),
2557
- /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "12px", color: "#52c41a", fontWeight: 500 } }, "Secure payment powered by v402pay")
2558
- ), /* @__PURE__ */ import_react8.default.createElement(
2559
- import_antd.Button,
2560
- {
2561
- type: "primary",
2562
- size: "large",
2563
- onClick: handlePayment,
2564
- disabled: isProcessing || !paymentDetails,
2565
- loading: isProcessing,
2566
- block: true,
2567
- style: {
2568
- height: "44px",
2569
- fontSize: "14px",
2570
- fontWeight: 600,
2571
- borderRadius: "8px",
2572
- ...!isProcessing && paymentDetails && {
2573
- background: "#1a1a1a",
2574
- borderColor: "#1a1a1a"
2575
- },
2576
- marginBottom: "10px"
2577
- }
2578
- },
2579
- isProcessing ? "Processing..." : !paymentDetails ? "Loading..." : `Pay $${paymentDetails.amount} ${paymentDetails.currency}`
2580
- ), /* @__PURE__ */ import_react8.default.createElement("div", { className: "text-center" }, /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "13px", color: "#8c8c8c" } }, "Don't have USDC?", " "), /* @__PURE__ */ import_react8.default.createElement(
2581
- "a",
2582
- {
2583
- href: "https://faucet.circle.com/",
2584
- target: "_blank",
2585
- rel: "noopener noreferrer",
2586
- className: "text-blue-600 hover:text-blue-700 text-sm font-medium inline-flex items-center gap-1"
2587
- },
2588
- "Get it here ",
2589
- /* @__PURE__ */ import_react8.default.createElement(import_icons.LinkOutlined, { style: { fontSize: "12px" } })
2590
- )), isModal && result && /* @__PURE__ */ import_react8.default.createElement(
2591
- "div",
2592
- {
2593
- className: "mt-4 p-4 rounded-lg",
2594
- style: { background: "#f6ffed", border: "1px solid #b7eb8f" }
2595
- },
2596
- /* @__PURE__ */ import_react8.default.createElement("div", { className: "text-center" }, /* @__PURE__ */ import_react8.default.createElement("span", { style: { fontSize: "20px" } }, "\u2713"), /* @__PURE__ */ import_react8.default.createElement(Text, { style: {
2597
- fontSize: "14px",
2598
- color: "#52c41a",
2599
- fontWeight: 600,
2600
- marginLeft: "8px"
2601
- } }, "Payment Successful!"))
2602
- ), isModal && error && /* @__PURE__ */ import_react8.default.createElement(
2603
- "div",
2604
- {
2605
- className: "mt-4 p-4 rounded-lg",
2606
- style: { background: "#fff2f0", border: "1px solid #ffccc7" }
2607
- },
2608
- /* @__PURE__ */ import_react8.default.createElement("div", { className: "text-center mb-3" }, /* @__PURE__ */ import_react8.default.createElement("span", { style: { fontSize: "20px" } }, "\u2717"), /* @__PURE__ */ import_react8.default.createElement(Text, { style: {
2609
- fontSize: "14px",
2610
- color: "#ff4d4f",
2611
- fontWeight: 600,
2612
- marginLeft: "8px",
2613
- display: "block",
2614
- marginTop: "4px"
2615
- } }, "Payment Failed")),
2616
- /* @__PURE__ */ import_react8.default.createElement(Text, { style: {
2617
- fontSize: "13px",
2618
- color: "#ff4d4f",
2619
- display: "block",
2620
- textAlign: "center"
2621
- } }, error)
2622
- ))
3183
+ getStatusText()
3184
+ )), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-1.5" }, paymentDetails && NetworkIcon && /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react14.default.createElement(NetworkIcon, { width: 12, height: 12, style: { color: "rgba(0,0,0,0.7)" } }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-xs font-mono font-bold", style: { color: "rgba(0,0,0,0.7)" } }, paymentDetails.network)))),
3185
+ /* @__PURE__ */ import_react14.default.createElement(
3186
+ TerminalScreen,
3187
+ {
3188
+ title,
3189
+ tooltipText,
3190
+ hasInvalidCheckoutId,
3191
+ fetchingPaymentInfo,
3192
+ address,
3193
+ paymentDetails,
3194
+ screenText,
3195
+ supportedNetworks
3196
+ }
2623
3197
  ),
2624
- !isModal && (isProcessing || result || error) && /* @__PURE__ */ import_react8.default.createElement(
2625
- import_antd.Card,
3198
+ /* @__PURE__ */ import_react14.default.createElement(
3199
+ TerminalButtons,
2626
3200
  {
2627
- title: /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center gap-2" }, isProcessing && !result && !error ? /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement(import_icons.LoadingOutlined, { style: { color: "#14b8a6", fontSize: "16px" } }), /* @__PURE__ */ import_react8.default.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Processing Payment")) : result ? /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement("span", { style: { color: "#52c41a", fontSize: "18px" } }, "\u2713"), /* @__PURE__ */ import_react8.default.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Payment Successful")) : /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement("span", { style: { color: "#ff4d4f", fontSize: "18px" } }, "\u2717"), /* @__PURE__ */ import_react8.default.createElement(Text, { strong: true, style: { fontSize: "16px", color: "#262626" } }, "Payment Failed"))),
2628
- extra: !isProcessing && /* @__PURE__ */ import_react8.default.createElement(
2629
- import_antd.Button,
2630
- {
2631
- type: "text",
2632
- size: "small",
2633
- onClick: () => {
2634
- setResult(null);
2635
- setError(null);
2636
- }
2637
- },
2638
- "Close"
2639
- ),
3201
+ address,
3202
+ showReceipt,
3203
+ isProcessing,
3204
+ paymentDetails,
3205
+ hasInvalidCheckoutId,
3206
+ onDisconnect: handleDisconnect,
3207
+ onClearReceipt: handleCloseReceipt,
3208
+ onPayment: handlePayment
3209
+ }
3210
+ ),
3211
+ brandName && /* @__PURE__ */ import_react14.default.createElement("div", { className: "text-center mt-0 mb-0" }, /* @__PURE__ */ import_react14.default.createElement(
3212
+ "div",
3213
+ {
3214
+ className: "inline-block px-2 py-0.5 rounded text-[10px] font-mono font-bold tracking-[0.2em]",
2640
3215
  style: {
2641
- border: "1px solid #e8e8e8",
2642
- borderRadius: "16px",
2643
- boxShadow: "0 4px 24px rgba(0, 0, 0, 0.06)",
2644
- maxHeight: "calc(100vh - 32px)",
2645
- width: "480px",
2646
- animation: "slideInRight 0.4s ease-out"
2647
- },
2648
- styles: {
2649
- body: {
2650
- padding: "24px",
2651
- maxHeight: "calc(100vh - 120px)",
2652
- overflow: "auto"
2653
- }
3216
+ backgroundColor: "#1a1a1a",
3217
+ color: "#9acd32",
3218
+ boxShadow: "inset 0 1px 3px rgba(0,0,0,0.8), 0 1px 0 rgba(255,255,255,0.1)",
3219
+ border: "1px solid rgba(0,0,0,0.5)",
3220
+ textShadow: "0 0 4px #9acd3280"
2654
3221
  }
2655
3222
  },
2656
- isProcessing && !result && !error && /* @__PURE__ */ import_react8.default.createElement("div", { className: "text-center py-10" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "relative inline-block" }, /* @__PURE__ */ import_react8.default.createElement(
2657
- "div",
2658
- {
2659
- className: "absolute inset-0 rounded-full blur-xl opacity-40",
2660
- style: {
2661
- background: "linear-gradient(135deg, #14b8a6 0%, #06b6d4 100%)",
2662
- animation: "pulse 2s ease-in-out infinite"
2663
- }
2664
- }
2665
- ), /* @__PURE__ */ import_react8.default.createElement(
2666
- import_antd.Spin,
2667
- {
2668
- indicator: /* @__PURE__ */ import_react8.default.createElement(import_icons.LoadingOutlined, { style: { fontSize: 56, color: "#14b8a6" } })
2669
- }
2670
- )), /* @__PURE__ */ import_react8.default.createElement("div", { className: "mt-6" }, /* @__PURE__ */ import_react8.default.createElement(Text, { strong: true, style: { fontSize: "18px", color: "#262626", letterSpacing: "-0.02em" } }, "Verifying Payment")), /* @__PURE__ */ import_react8.default.createElement("div", { className: "mt-2 mb-6" }, /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c", lineHeight: "1.6" } }, "Please wait while we confirm your transaction")), /* @__PURE__ */ import_react8.default.createElement(
2671
- "div",
2672
- {
2673
- className: "mt-4 p-4 rounded-xl",
2674
- style: {
2675
- background: "linear-gradient(135deg, #f0fdfa 0%, #ecfeff 100%)",
2676
- border: "1px solid #ccfbf1"
2677
- }
2678
- },
2679
- /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center justify-center gap-2" }, /* @__PURE__ */ import_react8.default.createElement("span", { style: { fontSize: "16px" } }, "\u23F1\uFE0F"), /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "13px", color: "#0f766e", fontWeight: 500 } }, "This may take a few moments"))
2680
- )),
2681
- result && /* @__PURE__ */ import_react8.default.createElement("div", null, /* @__PURE__ */ import_react8.default.createElement("div", { className: "text-center mb-6" }, /* @__PURE__ */ import_react8.default.createElement(
2682
- "div",
2683
- {
2684
- className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
2685
- style: {
2686
- background: "linear-gradient(135deg, #10b981 0%, #34d399 100%)",
2687
- boxShadow: "0 4px 20px rgba(16, 185, 129, 0.3)"
2688
- }
2689
- },
2690
- /* @__PURE__ */ import_react8.default.createElement("span", { style: { fontSize: "32px", color: "white" } }, "\u2713")
2691
- ), /* @__PURE__ */ import_react8.default.createElement("div", null, /* @__PURE__ */ import_react8.default.createElement(Text, { strong: true, style: {
2692
- fontSize: "20px",
2693
- color: "#262626",
2694
- display: "block",
2695
- marginBottom: "8px"
2696
- } }, "Payment Successful!"), /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c" } }, "Your transaction has been confirmed"))), /* @__PURE__ */ import_react8.default.createElement(import_antd.Divider, { style: { margin: "20px 0", borderColor: "#f0f0f0" } }, /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "12px", color: "#8c8c8c", fontWeight: 500 } }, "RESPONSE DATA")), /* @__PURE__ */ import_react8.default.createElement(
2697
- "pre",
2698
- {
2699
- style: {
2700
- background: "#fafafa",
2701
- padding: "20px",
2702
- borderRadius: "12px",
2703
- fontSize: "12px",
2704
- lineHeight: "1.8",
2705
- overflow: "auto",
2706
- margin: 0,
2707
- fontFamily: "Monaco, Courier New, monospace",
2708
- whiteSpace: "pre-wrap",
2709
- wordBreak: "break-word",
2710
- border: "1px solid #e8e8e8",
2711
- color: "#262626"
2712
- }
2713
- },
2714
- JSON.stringify(result, null, 2)
2715
- )),
2716
- error && /* @__PURE__ */ import_react8.default.createElement("div", null, /* @__PURE__ */ import_react8.default.createElement("div", { className: "text-center mb-6" }, /* @__PURE__ */ import_react8.default.createElement(
2717
- "div",
2718
- {
2719
- className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
2720
- style: {
2721
- background: "linear-gradient(135deg, #ef4444 0%, #f87171 100%)",
2722
- boxShadow: "0 4px 20px rgba(239, 68, 68, 0.3)"
2723
- }
2724
- },
2725
- /* @__PURE__ */ import_react8.default.createElement("span", { style: { fontSize: "32px", color: "white" } }, "\u2717")
2726
- ), /* @__PURE__ */ import_react8.default.createElement("div", null, /* @__PURE__ */ import_react8.default.createElement(Text, { strong: true, style: {
2727
- fontSize: "20px",
2728
- color: "#262626",
2729
- display: "block",
2730
- marginBottom: "8px"
2731
- } }, "Payment Failed"), /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "14px", color: "#8c8c8c" } }, "Something went wrong with your transaction"))), /* @__PURE__ */ import_react8.default.createElement(import_antd.Divider, { style: { margin: "20px 0", borderColor: "#f0f0f0" } }, /* @__PURE__ */ import_react8.default.createElement(Text, { style: { fontSize: "12px", color: "#8c8c8c", fontWeight: 500 } }, "ERROR DETAILS")), /* @__PURE__ */ import_react8.default.createElement(
2732
- "div",
2733
- {
2734
- style: {
2735
- background: "#fef2f2",
2736
- padding: "20px",
2737
- borderRadius: "12px",
2738
- border: "1px solid #fee2e2"
2739
- }
2740
- },
2741
- /* @__PURE__ */ import_react8.default.createElement(Text, { style: {
2742
- fontSize: "14px",
2743
- color: "#dc2626",
2744
- lineHeight: "1.6",
2745
- fontWeight: 500
2746
- } }, error)
2747
- ), /* @__PURE__ */ import_react8.default.createElement("div", { className: "mt-4 text-center" }, /* @__PURE__ */ import_react8.default.createElement(
2748
- import_antd.Button,
2749
- {
2750
- size: "large",
2751
- onClick: handlePayment,
2752
- style: {
2753
- height: "44px",
2754
- fontSize: "14px",
2755
- fontWeight: 600,
2756
- borderRadius: "8px",
2757
- background: "#1a1a1a",
2758
- borderColor: "#1a1a1a",
2759
- color: "white",
2760
- paddingLeft: "32px",
2761
- paddingRight: "32px"
2762
- }
2763
- },
2764
- "Try Again"
2765
- )))
2766
- )
2767
- ),
2768
- /* @__PURE__ */ import_react8.default.createElement("style", { dangerouslySetInnerHTML: {
2769
- __html: `
2770
- @keyframes slideInRight {
2771
- from {
2772
- opacity: 0;
2773
- transform: translateX(100px);
2774
- }
2775
- to {
2776
- opacity: 1;
2777
- transform: translateX(0);
2778
- }
2779
- }
2780
-
2781
- @keyframes pulse {
2782
- 0%, 100% {
2783
- transform: scale(1);
2784
- opacity: 0.4;
2785
- }
2786
- 50% {
2787
- transform: scale(1.1);
2788
- opacity: 0.6;
2789
- }
2790
- }
2791
- `
2792
- } })
2793
- );
3223
+ brandName
3224
+ ))
3225
+ )
3226
+ ), /* @__PURE__ */ import_react14.default.createElement(AnimationStyles, null));
2794
3227
  }
2795
3228
  // Annotate the CommonJS export names for ESM import in node:
2796
3229
  0 && (module.exports = {
2797
- V402Checkout,
3230
+ AnimationStyles,
3231
+ Toast,
3232
+ V402CheckoutV2,
2798
3233
  WalletConnect,
2799
3234
  WalletSelectModal,
3235
+ checkoutAnimations,
2800
3236
  usePageNetwork,
2801
3237
  usePayment,
2802
3238
  usePaymentInfo,
3239
+ useToast,
2803
3240
  useWallet
2804
3241
  });
2805
3242
  //# sourceMappingURL=index.js.map