@b3dotfun/sdk 0.0.30-alpha.1 → 0.0.30-alpha.10

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.
Files changed (80) hide show
  1. package/dist/cjs/anyspend/react/components/common/ChainTokenIcon.d.ts +1 -1
  2. package/dist/cjs/anyspend/react/components/common/ChainTokenIcon.js +2 -1
  3. package/dist/cjs/anyspend/react/components/common/CryptoPaymentMethod.js +10 -9
  4. package/dist/cjs/anyspend/react/components/common/OrderDetails.js +5 -5
  5. package/dist/cjs/global-account/react/components/B3DynamicModal.js +2 -5
  6. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.js +5 -0
  7. package/dist/cjs/global-account/react/components/LinkAccount/LinkAccount.js +1 -0
  8. package/dist/cjs/global-account/react/components/ManageAccount/ContentTokens.d.ts +14 -0
  9. package/dist/cjs/global-account/react/components/ManageAccount/ContentTokens.js +267 -0
  10. package/dist/cjs/global-account/react/components/ManageAccount/ManageAccount.js +9 -14
  11. package/dist/cjs/global-account/react/components/ui/dialog.js +1 -1
  12. package/dist/cjs/global-account/react/hooks/index.d.ts +2 -0
  13. package/dist/cjs/global-account/react/hooks/index.js +5 -1
  14. package/dist/cjs/global-account/react/hooks/useAnalytics.d.ts +7 -0
  15. package/dist/cjs/global-account/react/hooks/useAnalytics.js +29 -0
  16. package/dist/cjs/global-account/react/hooks/useSimBalance.d.ts +24 -0
  17. package/dist/cjs/global-account/react/hooks/useSimBalance.js +29 -0
  18. package/dist/cjs/global-account/react/hooks/useUnifiedChainSwitchAndExecute.js +0 -1
  19. package/dist/cjs/global-account/react/stores/useModalStore.d.ts +2 -2
  20. package/dist/cjs/global-account/react/utils/profileDisplay.js +9 -0
  21. package/dist/cjs/global-account/utils/analytics.d.ts +16 -0
  22. package/dist/cjs/global-account/utils/analytics.js +55 -0
  23. package/dist/cjs/shared/generated/chain-networks.json +185 -17
  24. package/dist/esm/anyspend/react/components/common/ChainTokenIcon.d.ts +1 -1
  25. package/dist/esm/anyspend/react/components/common/ChainTokenIcon.js +2 -1
  26. package/dist/esm/anyspend/react/components/common/CryptoPaymentMethod.js +8 -7
  27. package/dist/esm/anyspend/react/components/common/OrderDetails.js +5 -5
  28. package/dist/esm/global-account/react/components/B3DynamicModal.js +2 -5
  29. package/dist/esm/global-account/react/components/B3Provider/B3Provider.js +5 -0
  30. package/dist/esm/global-account/react/components/LinkAccount/LinkAccount.js +1 -0
  31. package/dist/esm/global-account/react/components/ManageAccount/ContentTokens.d.ts +14 -0
  32. package/dist/esm/global-account/react/components/ManageAccount/ContentTokens.js +264 -0
  33. package/dist/esm/global-account/react/components/ManageAccount/ManageAccount.js +10 -15
  34. package/dist/esm/global-account/react/components/ui/dialog.js +1 -1
  35. package/dist/esm/global-account/react/hooks/index.d.ts +2 -0
  36. package/dist/esm/global-account/react/hooks/index.js +2 -0
  37. package/dist/esm/global-account/react/hooks/useAnalytics.d.ts +7 -0
  38. package/dist/esm/global-account/react/hooks/useAnalytics.js +26 -0
  39. package/dist/esm/global-account/react/hooks/useSimBalance.d.ts +24 -0
  40. package/dist/esm/global-account/react/hooks/useSimBalance.js +26 -0
  41. package/dist/esm/global-account/react/hooks/useUnifiedChainSwitchAndExecute.js +0 -1
  42. package/dist/esm/global-account/react/stores/useModalStore.d.ts +2 -2
  43. package/dist/esm/global-account/react/utils/profileDisplay.js +9 -0
  44. package/dist/esm/global-account/utils/analytics.d.ts +16 -0
  45. package/dist/esm/global-account/utils/analytics.js +50 -0
  46. package/dist/esm/shared/generated/chain-networks.json +185 -17
  47. package/dist/styles/index.css +1 -1
  48. package/dist/types/anyspend/react/components/common/ChainTokenIcon.d.ts +1 -1
  49. package/dist/types/global-account/react/components/ManageAccount/ContentTokens.d.ts +14 -0
  50. package/dist/types/global-account/react/hooks/index.d.ts +2 -0
  51. package/dist/types/global-account/react/hooks/useAnalytics.d.ts +7 -0
  52. package/dist/types/global-account/react/hooks/useSimBalance.d.ts +24 -0
  53. package/dist/types/global-account/react/stores/useModalStore.d.ts +2 -2
  54. package/dist/types/global-account/utils/analytics.d.ts +16 -0
  55. package/package.json +1 -1
  56. package/src/anyspend/react/components/common/ChainTokenIcon.tsx +8 -2
  57. package/src/anyspend/react/components/common/CryptoPaymentMethod.tsx +10 -14
  58. package/src/anyspend/react/components/common/OrderDetails.tsx +5 -5
  59. package/src/global-account/react/components/B3DynamicModal.tsx +8 -7
  60. package/src/global-account/react/components/B3Provider/B3Provider.tsx +6 -0
  61. package/src/global-account/react/components/LinkAccount/LinkAccount.tsx +2 -1
  62. package/src/global-account/react/components/ManageAccount/ContentTokens.tsx +565 -0
  63. package/src/global-account/react/components/ManageAccount/ManageAccount.tsx +94 -71
  64. package/src/global-account/react/components/ui/dialog.tsx +1 -1
  65. package/src/global-account/react/hooks/index.ts +2 -0
  66. package/src/global-account/react/hooks/useAccountAssets.ts +1 -0
  67. package/src/global-account/react/hooks/useAnalytics.tsx +30 -0
  68. package/src/global-account/react/hooks/useSimBalance.ts +56 -0
  69. package/src/global-account/react/hooks/useUnifiedChainSwitchAndExecute.ts +0 -1
  70. package/src/global-account/react/stores/useModalStore.ts +2 -2
  71. package/src/global-account/react/utils/profileDisplay.ts +9 -0
  72. package/src/global-account/utils/analytics.ts +64 -0
  73. package/src/shared/generated/chain-networks.json +185 -17
  74. package/src/{anyspend/types → types}/window.d.ts +5 -1
  75. package/dist/cjs/index.d.ts +0 -0
  76. package/dist/cjs/index.js +0 -2
  77. package/dist/esm/index.d.ts +0 -0
  78. package/dist/esm/index.js +0 -2
  79. package/dist/types/index.d.ts +0 -0
  80. package/src/index.ts +0 -1
@@ -1,5 +1,5 @@
1
1
  export declare function ChainTokenIcon({ chainUrl, tokenUrl, className, }: {
2
2
  chainUrl: string;
3
- tokenUrl: string;
3
+ tokenUrl?: string;
4
4
  className?: string;
5
5
  }): import("react/jsx-runtime").JSX.Element;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ChainTokenIcon = ChainTokenIcon;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const lucide_react_1 = require("lucide-react");
5
6
  function ChainTokenIcon({ chainUrl, tokenUrl, className = "", }) {
6
- return ((0, jsx_runtime_1.jsxs)("div", { className: `relative ${className}`, children: [(0, jsx_runtime_1.jsx)("img", { src: tokenUrl, alt: "Token", className: "h-full w-full rounded-full" }), (0, jsx_runtime_1.jsx)("div", { className: "bg-as-on-surface-1 border-as-stroke absolute bottom-0 right-0 h-[45%] w-[45%] rounded border", children: (0, jsx_runtime_1.jsx)("img", { src: chainUrl, alt: "Chain", className: "h-full w-full rounded" }) })] }));
7
+ return ((0, jsx_runtime_1.jsxs)("div", { className: `relative ${className}`, children: [tokenUrl ? ((0, jsx_runtime_1.jsx)("img", { src: tokenUrl, alt: "Token", className: "h-full w-full rounded-full" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.HelpCircle, { className: "text-b3-react-foreground h-full w-full" })), (0, jsx_runtime_1.jsx)("div", { className: "bg-as-on-surface-1 border-as-stroke absolute bottom-0 right-0 h-[45%] w-[45%] rounded border", children: (0, jsx_runtime_1.jsx)("img", { src: chainUrl, alt: "Chain", className: "h-full w-full rounded" }) })] }));
7
8
  }
@@ -7,8 +7,9 @@ const jsx_runtime_1 = require("react/jsx-runtime");
7
7
  const react_1 = require("../../../../global-account/react");
8
8
  const cn_1 = require("../../../../shared/utils/cn");
9
9
  const formatAddress_1 = require("../../../../shared/utils/formatAddress");
10
+ const react_2 = require("@web3icons/react");
10
11
  const lucide_react_1 = require("lucide-react");
11
- const react_2 = require("react");
12
+ const react_3 = require("react");
12
13
  const react_dom_1 = require("react-dom");
13
14
  const sonner_1 = require("sonner");
14
15
  const wagmi_1 = require("wagmi");
@@ -24,43 +25,43 @@ function CryptoPaymentMethod({ selectedPaymentMethod, setSelectedPaymentMethod,
24
25
  const { connect, connectors, isPending } = (0, wagmi_1.useConnect)();
25
26
  const { disconnect } = (0, wagmi_1.useDisconnect)();
26
27
  const { data: walletClient } = (0, wagmi_1.useWalletClient)();
27
- const [showWalletModal, setShowWalletModal] = (0, react_2.useState)(false);
28
+ const [showWalletModal, setShowWalletModal] = (0, react_3.useState)(false);
28
29
  // Define available wallet connectors
29
- const availableConnectors = connectors.filter(connector => ["MetaMask", "WalletConnect", "Coinbase Wallet", "Rainbow"].includes(connector.name));
30
+ const availableConnectors = connectors.filter(connector => ["MetaMask", "WalletConnect", "Coinbase Wallet", "Rainbow", "Phantom"].includes(connector.name));
30
31
  // Define wallet options with icons and info
31
32
  const walletOptions = [
32
33
  {
33
34
  id: "metamask",
34
35
  name: "MetaMask",
35
- icon: "🦊",
36
+ icon: (0, jsx_runtime_1.jsx)(react_2.WalletMetamask, { size: 48 }),
36
37
  description: "Connect using MetaMask browser extension",
37
38
  connector: availableConnectors.find(c => c.name === "MetaMask"),
38
39
  },
39
40
  {
40
41
  id: "coinbase",
41
42
  name: "Coinbase Wallet",
42
- icon: "🔵",
43
+ icon: (0, jsx_runtime_1.jsx)(react_2.WalletCoinbase, { size: 48 }),
43
44
  description: "Connect using Coinbase Wallet",
44
45
  connector: availableConnectors.find(c => c.name === "Coinbase Wallet"),
45
46
  },
46
47
  {
47
48
  id: "rainbow",
48
49
  name: "Rainbow",
49
- icon: "🌈",
50
+ icon: (0, jsx_runtime_1.jsx)(react_2.WalletRainbow, { size: 48 }),
50
51
  description: "Connect using Rainbow wallet",
51
52
  connector: availableConnectors.find(c => c.name === "Rainbow"),
52
53
  },
53
54
  {
54
55
  id: "walletconnect",
55
56
  name: "WalletConnect",
56
- icon: "🔗",
57
+ icon: (0, jsx_runtime_1.jsx)(react_2.WalletWalletConnect, { size: 48 }),
57
58
  description: "Connect using WalletConnect protocol",
58
59
  connector: availableConnectors.find(c => c.name === "WalletConnect"),
59
60
  },
60
61
  {
61
62
  id: "phantom",
62
63
  name: "Phantom",
63
- icon: "https://phantom.app/favicon.ico",
64
+ icon: (0, jsx_runtime_1.jsx)(react_2.WalletPhantom, { size: 48 }),
64
65
  description: "Connect using Phantom wallet",
65
66
  connector: availableConnectors.find(c => c.name === "Phantom"),
66
67
  },
@@ -146,6 +147,6 @@ function CryptoPaymentMethod({ selectedPaymentMethod, setSelectedPaymentMethod,
146
147
  await requestWalletPermissions(walletOption.connector);
147
148
  }, disabled: isPending, className: `wallet-option w-full rounded-xl border p-4 text-left transition-all hover:shadow-md disabled:opacity-50 ${isCurrentWallet
148
149
  ? "wallet-option--active border-blue-500 bg-blue-50 dark:bg-blue-900/20"
149
- : "border-gray-200 bg-white hover:border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:hover:border-gray-500"}`, children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)("div", { className: `flex h-12 w-12 items-center justify-center rounded-xl text-xl ${isCurrentWallet ? "bg-blue-100 dark:bg-blue-800" : "bg-gray-100 dark:bg-gray-700"}`, children: walletOption.icon }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-sm font-semibold text-gray-900 dark:text-white", children: walletOption.name }), isCurrentWallet && ((0, jsx_runtime_1.jsx)("span", { className: "rounded-full bg-blue-100 px-2 py-0.5 text-xs font-medium text-blue-700 dark:bg-blue-800 dark:text-blue-200", children: "Connected" }))] }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-gray-500 dark:text-gray-400", children: isCurrentWallet ? "Switch account or reconnect" : walletOption.description })] })] }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRightCircle, { className: "h-5 w-5 text-gray-400" })] }) }, walletOption.id));
150
+ : "border-gray-200 bg-white hover:border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:hover:border-gray-500"}`, children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [walletOption.icon, (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("div", { className: "wallet-option-name flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-sm font-semibold text-gray-900 dark:text-white", children: walletOption.name }), isCurrentWallet && ((0, jsx_runtime_1.jsx)("span", { className: "rounded-full bg-blue-100 px-2 py-0.5 text-xs font-medium text-blue-700 dark:bg-blue-800 dark:text-blue-200", children: "Connected" }))] }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-gray-500 dark:text-gray-400", children: isCurrentWallet ? "Switch account or reconnect" : walletOption.description })] })] }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRightCircle, { className: "h-5 w-5 text-gray-400" })] }) }, walletOption.id));
150
151
  }) }) })] }) }), typeof window !== "undefined" ? document.getElementById("b3-root") || document.body : document.body)] }));
151
152
  }
@@ -401,7 +401,7 @@ exports.OrderDetails = (0, react_5.memo)(function OrderDetails({ mode = "modal",
401
401
  : `Received ${(0, number_1.formatTokenAmount)(BigInt(dTx.amount), srcToken.decimals)} ${srcToken.symbol}`, chainId: order.srcChain, tx: dTx, isProcessing: false }, dTx.txHash)))
402
402
  : null, refundTxs
403
403
  ? refundTxs.map(rTx => ((0, jsx_runtime_1.jsx)(TransactionDetails, { title: `Refunded ${(0, number_1.formatTokenAmount)(BigInt(rTx.amount), srcToken.decimals)} ${srcToken.symbol}`, chainId: order.srcChain, tx: rTx, isProcessing: false }, rTx.txHash)))
404
- : null] }) })] }) }), order.errorDetails && ((0, jsx_runtime_1.jsx)("div", { className: "flex justify-center", children: (0, jsx_runtime_1.jsx)("span", { className: "text-as-primary/50 text-center text-sm", style: { maxWidth: "40ch" }, children: (0, anyspend_1.getErrorDisplay)(order.errorDetails) }) })), (0, jsx_runtime_1.jsx)("button", { className: "bg-as-brand flex w-full items-center justify-center gap-2 rounded-lg p-2 font-semibold text-white", onClick: mode === "page" ? handleBack : handleCloseModal, children: mode === "page" ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Return to Home ", (0, jsx_runtime_1.jsx)(lucide_react_1.Home, { className: "ml-2 h-4 w-4" })] })) : ("Close") })] }));
404
+ : null] }) })] }) }), order.errorDetails && ((0, jsx_runtime_1.jsx)("div", { className: "flex justify-center", children: (0, jsx_runtime_1.jsx)("span", { className: "text-as-primary/50 text-center text-sm", style: { maxWidth: "40ch" }, children: (0, anyspend_1.getErrorDisplay)(order.errorDetails) }) })), (0, jsx_runtime_1.jsx)("button", { className: "order-close-button bg-as-brand flex w-full items-center justify-center gap-2 rounded-lg p-2 font-semibold text-white", onClick: mode === "page" ? handleBack : handleCloseModal, children: mode === "page" ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Return to Home ", (0, jsx_runtime_1.jsx)(lucide_react_1.Home, { className: "ml-2 h-4 w-4" })] })) : ("Close") })] }));
405
405
  }
406
406
  if (executeTx) {
407
407
  return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(OrderDetailsCollapsible_1.OrderDetailsCollapsible, { order: order, dstToken: dstToken, tournament: tournament, nft: nft, recipientName: recipientName, formattedExpectedDstAmount: formattedExpectedDstAmount }), (0, jsx_runtime_1.jsx)(Accordion_1.Accordion, { type: "single", collapsible: true, className: "w-full", children: (0, jsx_runtime_1.jsxs)(Accordion_1.AccordionItem, { value: "execute-details", children: [(0, jsx_runtime_1.jsx)(Accordion_1.AccordionTrigger, { children: "Transaction Details" }), (0, jsx_runtime_1.jsx)(Accordion_1.AccordionContent, { children: (0, jsx_runtime_1.jsxs)("div", { className: "relative flex w-full flex-col gap-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "bg-as-surface-secondary absolute bottom-2 left-4 top-2 z-[5] w-2", children: (0, jsx_runtime_1.jsx)(react_4.motion.div, { className: "bg-as-border-primary absolute left-[2px] top-0 z-10 w-[3px]", initial: { height: "0%" }, animate: { height: "100%" }, transition: { duration: 1.5, ease: "easeInOut" } }) }), depositTxs
@@ -416,14 +416,14 @@ exports.OrderDetails = (0, react_5.memo)(function OrderDetails({ mode = "modal",
416
416
  ? "Joined Tournament"
417
417
  : order.type === "fund_tournament"
418
418
  ? "Funded Tournament"
419
- : "Processed Order", chainId: order.dstChain, tx: executeTx, isProcessing: false, delay: 1 })] }) })] }) }), (0, jsx_runtime_1.jsx)("div", { className: "flex w-full flex-col gap-8", children: (0, jsx_runtime_1.jsx)(react_1.Button, { variant: "link", asChild: true, children: (0, jsx_runtime_1.jsxs)("a", { href: (0, anyspend_1.getExplorerTxUrl)(order.dstChain, executeTx.txHash), target: "_blank", className: "text-as-primary/70 hover:text-as-primary", style: { whiteSpace: "normal" }, children: [getOrderSuccessText({
419
+ : "Processed Order", chainId: order.dstChain, tx: executeTx, isProcessing: false, delay: 1 })] }) })] }) }), (0, jsx_runtime_1.jsx)("div", { className: "flex w-full flex-col gap-8", children: (0, jsx_runtime_1.jsx)(react_1.Button, { variant: "link", asChild: true, children: (0, jsx_runtime_1.jsxs)("a", { href: (0, anyspend_1.getExplorerTxUrl)(order.dstChain, executeTx.txHash), target: "_blank", className: "order-success-text text-as-primary/70 hover:text-as-primary", style: { whiteSpace: "normal" }, children: [getOrderSuccessText({
420
420
  order,
421
421
  tournament,
422
422
  formattedActualDstAmount: formattedActualDstAmount,
423
423
  dstToken,
424
424
  recipientName,
425
425
  centerTruncate: centerTruncate_1.default,
426
- }), (0, jsx_runtime_1.jsx)(lucide_react_1.ExternalLink, { className: "ml-2 h-4 w-4" })] }) }) }), order.type === "join_tournament" && order.status === "executed" && ((0, jsx_runtime_1.jsxs)(react_1.ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", className: "flex w-full items-center gap-2", disabled: txLoading || isSwitchingOrExecuting, onClick: handleCloseModal, children: [(0, jsx_runtime_1.jsx)("span", { className: "pl-4", children: "Continue to Tournament" }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: "h-4 w-4" })] })), order.status === "executed" && ((0, jsx_runtime_1.jsx)("button", { className: "bg-as-brand flex w-full items-center justify-center gap-2 rounded-lg p-2 font-semibold text-white", onClick: mode === "page" ? handleBack : handleCloseModal, children: mode === "page" ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Return to Home ", (0, jsx_runtime_1.jsx)(lucide_react_1.Home, { className: "ml-2 h-4 w-4" })] })) : ("Close") }))] }));
426
+ }), (0, jsx_runtime_1.jsx)(lucide_react_1.ExternalLink, { className: "ml-2 h-4 w-4" })] }) }) }), order.type === "join_tournament" && order.status === "executed" && ((0, jsx_runtime_1.jsxs)(react_1.ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", className: "flex w-full items-center gap-2", disabled: txLoading || isSwitchingOrExecuting, onClick: handleCloseModal, children: [(0, jsx_runtime_1.jsx)("span", { className: "pl-4", children: "Continue to Tournament" }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: "h-4 w-4" })] })), order.status === "executed" && ((0, jsx_runtime_1.jsx)("button", { className: "order-close-button bg-as-brand flex w-full items-center justify-center gap-2 rounded-lg p-2 font-semibold text-white", onClick: mode === "page" ? handleBack : handleCloseModal, children: mode === "page" ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Return to Home ", (0, jsx_runtime_1.jsx)(lucide_react_1.Home, { className: "ml-2 h-4 w-4" })] })) : ("Close") }))] }));
427
427
  }
428
428
  if (relayTx && relayTx.status === "success") {
429
429
  return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(OrderDetailsCollapsible_1.OrderDetailsCollapsible, { order: order, dstToken: dstToken, tournament: tournament, nft: nft, recipientName: recipientName, formattedExpectedDstAmount: formattedExpectedDstAmount }), (0, jsx_runtime_1.jsx)(Accordion_1.Accordion, { type: "single", collapsible: true, className: "w-full", children: (0, jsx_runtime_1.jsxs)(Accordion_1.AccordionItem, { value: "more-details", children: [(0, jsx_runtime_1.jsx)(Accordion_1.AccordionTrigger, { children: "More Details" }), (0, jsx_runtime_1.jsx)(Accordion_1.AccordionContent, { children: (0, jsx_runtime_1.jsxs)("div", { className: "relative flex w-full flex-col gap-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "bg-as-surface-secondary absolute bottom-2 left-4 top-2 z-[5] w-2", children: (0, jsx_runtime_1.jsx)(react_4.motion.div, { className: "bg-as-border-primary absolute left-[2px] top-0 z-10 w-[3px]", initial: { height: "0%" }, animate: { height: "100%" }, transition: { duration: 1.5, ease: "easeInOut" } }) }), depositTxs
@@ -446,14 +446,14 @@ exports.OrderDetails = (0, react_5.memo)(function OrderDetails({ mode = "modal",
446
446
  ? "Joining Tournament"
447
447
  : order.type === "fund_tournament"
448
448
  ? "Funding Tournament"
449
- : "Processing Bridge", chainId: order.dstChain, isProcessing: true, tx: executeTx, delay: 1 })] }))] }) })] }) }), (0, jsx_runtime_1.jsx)("div", { className: "flex w-full flex-col gap-8", children: (0, jsx_runtime_1.jsx)(react_1.Button, { variant: "link", asChild: true, children: (0, jsx_runtime_1.jsxs)("a", { href: (0, anyspend_1.getExplorerTxUrl)(order.dstChain, relayTx.txHash), target: "_blank", className: "text-as-primary/70 hover:text-as-primary", style: { whiteSpace: "normal" }, children: [getOrderSuccessText({
449
+ : "Processing Bridge", chainId: order.dstChain, isProcessing: true, tx: executeTx, delay: 1 })] }))] }) })] }) }), (0, jsx_runtime_1.jsx)("div", { className: "flex w-full flex-col gap-8", children: (0, jsx_runtime_1.jsx)(react_1.Button, { variant: "link", asChild: true, children: (0, jsx_runtime_1.jsxs)("a", { href: (0, anyspend_1.getExplorerTxUrl)(order.dstChain, relayTx.txHash), target: "_blank", className: "order-success-text text-as-primary/70 hover:text-as-primary", style: { whiteSpace: "normal" }, children: [getOrderSuccessText({
450
450
  order,
451
451
  tournament,
452
452
  formattedActualDstAmount,
453
453
  dstToken,
454
454
  recipientName,
455
455
  centerTruncate: centerTruncate_1.default,
456
- }), (0, jsx_runtime_1.jsx)(lucide_react_1.ExternalLink, { className: "ml-2 h-4 w-4" })] }) }) }), order.type === "join_tournament" && order.status === "executed" && ((0, jsx_runtime_1.jsxs)(react_1.ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", className: "flex w-full items-center gap-2", disabled: txLoading || isSwitchingOrExecuting, onClick: handleCloseModal, children: [(0, jsx_runtime_1.jsx)("span", { className: "pl-4", children: "Continue to Tournament" }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: "h-4 w-4" })] })), order.status === "executed" && ((0, jsx_runtime_1.jsx)("button", { className: "bg-as-brand flex w-full items-center justify-center gap-2 rounded-lg p-2 font-semibold text-white", onClick: mode === "page" ? handleBack : handleCloseModal, children: mode === "page" ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Return to Home ", (0, jsx_runtime_1.jsx)(lucide_react_1.Home, { className: "ml-2 h-4 w-4" })] })) : ("Close") }))] }));
456
+ }), (0, jsx_runtime_1.jsx)(lucide_react_1.ExternalLink, { className: "ml-2 h-4 w-4" })] }) }) }), order.type === "join_tournament" && order.status === "executed" && ((0, jsx_runtime_1.jsxs)(react_1.ShinyButton, { accentColor: "hsl(var(--as-brand))", textColor: "text-white", className: "flex w-full items-center gap-2", disabled: txLoading || isSwitchingOrExecuting, onClick: handleCloseModal, children: [(0, jsx_runtime_1.jsx)("span", { className: "pl-4", children: "Continue to Tournament" }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: "h-4 w-4" })] })), order.status === "executed" && ((0, jsx_runtime_1.jsx)("button", { className: "order-close-button bg-as-brand flex w-full items-center justify-center gap-2 rounded-lg p-2 font-semibold text-white", onClick: mode === "page" ? handleBack : handleCloseModal, children: mode === "page" ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Return to Home ", (0, jsx_runtime_1.jsx)(lucide_react_1.Home, { className: "ml-2 h-4 w-4" })] })) : ("Close") }))] }));
457
457
  }
458
458
  // This boolean indicates that user finish payment, and waiting for the deposit to be confirmed. We get this from query params (waitingForDeposit=true)
459
459
  const waitingForDeposit = new URLSearchParams(window.location.search).get("waitingForDeposit") === "true";
@@ -20,7 +20,6 @@ function B3DynamicModal() {
20
20
  const { isOpen, setB3ModalOpen, contentType, history, navigateBack } = (0, react_2.useModalStore)();
21
21
  const { theme } = (0, useB3_1.useB3)();
22
22
  const isMobile = (0, react_2.useIsMobile)();
23
- let hideCloseButton = false;
24
23
  // Define arrays for different modal type groups
25
24
  const fullWidthTypes = [
26
25
  "anySpend",
@@ -46,9 +45,7 @@ function B3DynamicModal() {
46
45
  ];
47
46
  // Check if current content type is in freestyle types
48
47
  const isFreestyleType = freestyleTypes.includes(contentType?.type);
49
- if (isFreestyleType) {
50
- hideCloseButton = true;
51
- }
48
+ const hideCloseButton = isFreestyleType;
52
49
  // Build content class using cn utility
53
50
  // eslint-disable-next-line tailwindcss/no-custom-classname
54
51
  const contentClass = (0, cn_1.cn)("b3-modal", theme === "dark" && "dark", fullWidthTypes.includes(contentType?.type) && "w-full", isFreestyleType && "b3-modal-freestyle", contentType?.type === "signInWithB3" && "p-0", contentType?.type === "anySpend" && "md:px-6", contentType?.type === "transak" && "transak-modal");
@@ -98,5 +95,5 @@ function B3DynamicModal() {
98
95
  const ModalContent = isMobile ? drawer_1.DrawerContent : dialog_1.DialogContent;
99
96
  const ModalTitle = isMobile ? drawer_1.DrawerTitle : dialog_1.DialogTitle;
100
97
  const ModalDescription = isMobile ? drawer_1.DrawerDescription : dialog_1.DialogDescription;
101
- return ((0, jsx_runtime_1.jsx)(ModalComponent, { open: isOpen, onOpenChange: setB3ModalOpen, children: (0, jsx_runtime_1.jsxs)(ModalContent, { className: (0, cn_1.cn)(contentClass, "rounded-2xl bg-white shadow-xl dark:bg-gray-900", "border border-gray-200 dark:border-gray-800", "mx-auto w-full max-w-md", "sm:max-w-lg"), hideCloseButton: hideCloseButton, children: [(0, jsx_runtime_1.jsx)(ModalTitle, { className: "sr-only hidden", children: contentType?.type || "Modal" }), (0, jsx_runtime_1.jsx)(ModalDescription, { className: "sr-only hidden", children: contentType?.type || "Modal Body" }), (0, jsx_runtime_1.jsxs)("div", { className: "no-scrollbar max-h-[90dvh] overflow-auto sm:max-h-[80dvh]", children: [history.length > 0 && contentType?.showBackButton && ((0, jsx_runtime_1.jsxs)("button", { onClick: navigateBack, className: "flex items-center gap-2 px-6 py-4 text-gray-600 transition-colors hover:text-gray-900 dark:text-gray-400 dark:hover:text-white", children: [(0, jsx_runtime_1.jsxs)("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [(0, jsx_runtime_1.jsx)("path", { d: "M15.8337 10H4.16699", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }), (0, jsx_runtime_1.jsx)("path", { d: "M10.0003 15.8334L4.16699 10L10.0003 4.16669", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })] }), (0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium", children: "Back" })] })), renderContent()] })] }) }));
98
+ return ((0, jsx_runtime_1.jsx)(ModalComponent, { open: isOpen, onOpenChange: setB3ModalOpen, children: (0, jsx_runtime_1.jsxs)(ModalContent, { className: (0, cn_1.cn)(contentClass, "rounded-2xl bg-white shadow-xl dark:bg-gray-900", "border border-gray-200 dark:border-gray-800", "mx-auto w-full max-w-md", "sm:max-w-lg sm:rounded-b-none"), hideCloseButton: hideCloseButton, children: [(0, jsx_runtime_1.jsx)(ModalTitle, { className: "sr-only hidden", children: contentType?.type || "Modal" }), (0, jsx_runtime_1.jsx)(ModalDescription, { className: "sr-only hidden", children: contentType?.type || "Modal Body" }), (0, jsx_runtime_1.jsxs)("div", { className: (0, cn_1.cn)("no-scrollbar max-h-[90dvh] overflow-auto sm:max-h-[80dvh]", contentType?.type === "manageAccount" && "h-[90dvh]"), children: [history.length > 0 && contentType?.showBackButton && ((0, jsx_runtime_1.jsxs)("button", { onClick: navigateBack, className: "flex items-center gap-2 px-6 py-4 text-gray-600 transition-colors hover:text-gray-900 dark:text-gray-400 dark:hover:text-white", children: [(0, jsx_runtime_1.jsxs)("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [(0, jsx_runtime_1.jsx)("path", { d: "M15.8337 10H4.16699", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }), (0, jsx_runtime_1.jsx)("path", { d: "M10.0003 15.8334L4.16699 10L10.0003 4.16669", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })] }), (0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium", children: "Back" })] })), renderContent()] })] }) }));
102
99
  }
@@ -5,6 +5,7 @@ exports.B3Provider = B3Provider;
5
5
  exports.InnerProvider = InnerProvider;
6
6
  const jsx_runtime_1 = require("react/jsx-runtime");
7
7
  const react_1 = require("../../../../global-account/react");
8
+ const analytics_1 = require("../../../../global-account/utils/analytics");
8
9
  const supported_1 = require("../../../../shared/constants/chains/supported");
9
10
  const react_query_1 = require("@tanstack/react-query");
10
11
  const react_2 = require("react");
@@ -33,6 +34,10 @@ const queryClient = new react_query_1.QueryClient();
33
34
  * Main B3Provider component
34
35
  */
35
36
  function B3Provider({ theme = "light", children, accountOverride, environment, automaticallySetFirstEoa, simDuneApiKey, toaster, }) {
37
+ // Initialize Google Analytics on mount
38
+ (0, react_2.useEffect)(() => {
39
+ (0, analytics_1.loadGA4Script)();
40
+ }, []);
36
41
  return ((0, jsx_runtime_1.jsx)(wagmi_1.WagmiProvider, { config: exports.wagmiConfig, children: (0, jsx_runtime_1.jsx)(react_query_1.QueryClientProvider, { client: queryClient, children: (0, jsx_runtime_1.jsx)(react_3.ThirdwebProvider, { children: (0, jsx_runtime_1.jsx)(react_1.TooltipProvider, { children: (0, jsx_runtime_1.jsx)(InnerProvider, { accountOverride: accountOverride, environment: environment, theme: theme, automaticallySetFirstEoa: !!automaticallySetFirstEoa, children: (0, jsx_runtime_1.jsxs)(react_1.RelayKitProviderWrapper, { simDuneApiKey: simDuneApiKey, children: [children, (0, jsx_runtime_1.jsx)(StyleRoot_1.StyleRoot, { id: "b3-root" }), (0, jsx_runtime_1.jsx)(sonner_1.Toaster, { theme: theme, position: toaster?.position, style: toaster?.style })] }) }) }) }) }) }));
37
42
  }
38
43
  /**
@@ -20,6 +20,7 @@ const AUTH_METHODS = [
20
20
  { id: "x", label: "X (Twitter)", enabled: true },
21
21
  { id: "discord", label: "Discord", enabled: true },
22
22
  { id: "apple", label: "Apple", enabled: true },
23
+ { id: "farcaster", label: "Farcaster", enabled: true },
23
24
  ];
24
25
  function LinkAccount({ onSuccess: onSuccessCallback, onError, onClose, chain, partnerId, }) {
25
26
  const { isLinking, linkingMethod, setLinkingState, navigateBack, setB3ModalContentType } = (0, useModalStore_1.useModalStore)();
@@ -0,0 +1,14 @@
1
+ interface ContentTokensProps {
2
+ activeTab: string;
3
+ }
4
+ /**
5
+ * ContentTokens Component
6
+ *
7
+ * Displays user's token balances with ability to send tokens. Features:
8
+ * - Animated transitions between token list and send form
9
+ * - Smart filtering (shows all tokens when ≤5 valuable tokens or no $1+ tokens)
10
+ * - NumericFormat inputs for proper number handling
11
+ * - Focus preservation during transitions (see render functions pattern below)
12
+ */
13
+ export declare function ContentTokens({ activeTab }: ContentTokensProps): import("react/jsx-runtime").JSX.Element;
14
+ export {};
@@ -0,0 +1,267 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ContentTokens = ContentTokens;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const anyspend_1 = require("../../../../anyspend");
6
+ const ChainTokenIcon_1 = require("../../../../anyspend/react/components/common/ChainTokenIcon");
7
+ const react_1 = require("../../../../global-account/react");
8
+ const number_1 = require("../../../../shared/utils/number");
9
+ const lucide_react_1 = require("lucide-react");
10
+ const react_2 = require("react");
11
+ const react_number_format_1 = require("react-number-format");
12
+ const sonner_1 = require("sonner");
13
+ const react_3 = require("thirdweb/react");
14
+ const viem_1 = require("viem");
15
+ // Panel view enum for managing navigation between token list and send form
16
+ var TokenPanelView;
17
+ (function (TokenPanelView) {
18
+ TokenPanelView[TokenPanelView["LIST"] = 0] = "LIST";
19
+ TokenPanelView[TokenPanelView["SEND"] = 1] = "SEND";
20
+ })(TokenPanelView || (TokenPanelView = {}));
21
+ /**
22
+ * ContentTokens Component
23
+ *
24
+ * Displays user's token balances with ability to send tokens. Features:
25
+ * - Animated transitions between token list and send form
26
+ * - Smart filtering (shows all tokens when ≤5 valuable tokens or no $1+ tokens)
27
+ * - NumericFormat inputs for proper number handling
28
+ * - Focus preservation during transitions (see render functions pattern below)
29
+ */
30
+ function ContentTokens({ activeTab }) {
31
+ // === TOKEN FILTERING STATE ===
32
+ const [showAllTokens, setShowAllTokens] = (0, react_2.useState)(false);
33
+ // === NAVIGATION STATE ===
34
+ const [tokenPanelView, setTokenPanelView] = (0, react_2.useState)(TokenPanelView.LIST);
35
+ // === SEND FORM STATE ===
36
+ const [selectedToken, setSelectedToken] = (0, react_2.useState)(null);
37
+ const [recipientAddress, setRecipientAddress] = (0, react_2.useState)("");
38
+ const [sendAmount, setSendAmount] = (0, react_2.useState)("");
39
+ const [isSending, setIsSending] = (0, react_2.useState)(false);
40
+ const [addressError, setAddressError] = (0, react_2.useState)("");
41
+ // === ANIMATION STATE ===
42
+ // CRITICAL: useRef for animation direction prevents component remounting
43
+ // This ensures input focus is preserved during panel transitions
44
+ const animationDirection = (0, react_2.useRef)(null);
45
+ // === DATA FETCHING ===
46
+ const account = (0, react_3.useActiveAccount)();
47
+ const { data: simBalance, refetch: refetchSimBalance, isLoading: isLoadingBalance } = (0, react_1.useSimBalance)(account?.address);
48
+ // === BLOCKCHAIN INTERACTION ===
49
+ const { switchChainAndExecute } = (0, react_1.useUnifiedChainSwitchAndExecute)();
50
+ // === ANALYTICS ===
51
+ const { sendAnalyticsEvent } = (0, react_1.useAnalytics)();
52
+ // === ADDRESS VALIDATION ===
53
+ // Handle recipient address change with real-time validation using viem
54
+ const handleRecipientAddressChange = (value) => {
55
+ setRecipientAddress(value);
56
+ // Only show error if user has typed something and it's invalid
57
+ // Using viem's isAddress for robust EVM address validation
58
+ if (value && !(0, viem_1.isAddress)(value)) {
59
+ setAddressError("Please enter a valid EVM address (0x...)");
60
+ }
61
+ else {
62
+ setAddressError("");
63
+ }
64
+ };
65
+ // === TAB RESET EFFECT ===
66
+ // Reset all state when user switches away from tokens tab
67
+ (0, react_2.useEffect)(() => {
68
+ if (activeTab !== "tokens") {
69
+ setTokenPanelView(TokenPanelView.LIST);
70
+ setSelectedToken(null);
71
+ setRecipientAddress("");
72
+ setSendAmount("");
73
+ setIsSending(false);
74
+ setAddressError("");
75
+ animationDirection.current = null;
76
+ }
77
+ }, [activeTab]);
78
+ // === HELPER FUNCTION ===
79
+ // Get current version of selected token from fresh balance data
80
+ // 🔧 FIX: Prevents auto-navigation back to token list when balance refreshes
81
+ // The useSimBalance hook refreshes data, creating new token object references
82
+ // This helper ensures we always get the fresh token data instead of stale references
83
+ const getCurrentSelectedToken = () => {
84
+ if (!selectedToken || !simBalance?.balances) {
85
+ return null;
86
+ }
87
+ const found = simBalance.balances.find(token => token.chain_id === selectedToken.chain_id && token.address === selectedToken.address);
88
+ return found || null;
89
+ };
90
+ // ==================================================================================
91
+ // === RENDER FUNCTIONS (NOT COMPONENTS!) ===
92
+ // ==================================================================================
93
+ //
94
+ // 🚨 CRITICAL ARCHITECTURE DECISION:
95
+ // These are render functions, NOT component functions with useCallback!
96
+ //
97
+ // WHY THIS WORKS:
98
+ // ✅ Stable wrapper <div> elements with consistent keys
99
+ // ✅ React never sees these as "new components"
100
+ // ✅ Input focus is preserved during transitions
101
+ // ✅ No component remounting issues
102
+ //
103
+ // WHY useCallback DIDN'T WORK:
104
+ // ❌ useCallback(() => <JSX />, [deps]) still creates new component instances
105
+ // ❌ React treats each render as a different component
106
+ // ❌ Causes remounting and focus loss
107
+ //
108
+ // THE PATTERN:
109
+ // Instead of: {[<ComponentA />, <ComponentB />]}
110
+ // We use: {[<div key="a">{renderA()}</div>, <div key="b">{renderB()}</div>]}
111
+ // ==================================================================================
112
+ /**
113
+ * Renders the send token form panel
114
+ * Includes recipient input, amount input with NumericFormat, and percentage buttons
115
+ */
116
+ const renderSendTokenPanel = () => {
117
+ // Get fresh token data to prevent stale references
118
+ const currentToken = getCurrentSelectedToken();
119
+ // 🔧 SINGLE FALLBACK STRATEGY:
120
+ // Use fresh token data when available, fall back to selectedToken if needed
121
+ // This prevents duplication of "currentToken || selectedToken" throughout the component
122
+ const displayToken = currentToken || selectedToken;
123
+ // Handle percentage button clicks (25%, 50%, 75%, 100%)
124
+ const handlePercentageClick = (percentage) => {
125
+ if (displayToken) {
126
+ const tokenBalance = (BigInt(displayToken.amount) * BigInt(percentage)) / BigInt(100);
127
+ const amount = (0, number_1.formatTokenAmount)(tokenBalance, displayToken.decimals, 30, false);
128
+ setSendAmount(amount);
129
+ }
130
+ };
131
+ // Execute token transfer transaction
132
+ const handleSend = async () => {
133
+ if (!displayToken || !recipientAddress || !sendAmount || parseFloat(sendAmount) <= 0) {
134
+ return;
135
+ }
136
+ setIsSending(true);
137
+ const amountInWei = (0, viem_1.parseUnits)(sendAmount, displayToken.decimals);
138
+ // Prepare analytics event data
139
+ const analyticsData = {
140
+ amount: sendAmount,
141
+ symbol: displayToken.symbol,
142
+ chain_id: displayToken.chain_id,
143
+ address: displayToken.address,
144
+ };
145
+ try {
146
+ const sendTokenData = (0, viem_1.encodeFunctionData)({
147
+ abi: viem_1.erc20Abi,
148
+ functionName: "transfer",
149
+ args: [recipientAddress, amountInWei],
150
+ });
151
+ const tx = await switchChainAndExecute(displayToken.chain_id, {
152
+ to: displayToken.address === "native" ? recipientAddress : displayToken.address,
153
+ data: sendTokenData,
154
+ value: displayToken.address === "native" ? amountInWei : BigInt(0),
155
+ });
156
+ if (tx) {
157
+ // Track successful send
158
+ sendAnalyticsEvent("send_token_button_click", {
159
+ ...analyticsData,
160
+ success: true,
161
+ tx: (0, anyspend_1.getExplorerTxUrl)(displayToken.chain_id, tx),
162
+ });
163
+ // Reset form
164
+ setSendAmount("");
165
+ }
166
+ }
167
+ catch (error) {
168
+ // Track failed send
169
+ sendAnalyticsEvent("send_token_button_click", {
170
+ ...analyticsData,
171
+ success: false,
172
+ reason: error.message || "Unknown error",
173
+ });
174
+ // Error
175
+ sonner_1.toast.error(`Failed to send ${displayToken.symbol}: ${error.message || "Unknown error"}`);
176
+ }
177
+ finally {
178
+ // Wait 1 second to make sure the tx is indexed on sim api.
179
+ setTimeout(async () => {
180
+ // Force refetch to bypass cache and get fresh balance data
181
+ await refetchSimBalance();
182
+ }, 1000);
183
+ setIsSending(false);
184
+ }
185
+ };
186
+ // Show loading state only if no token data is available at all
187
+ if (!displayToken) {
188
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-center justify-center py-12 text-center", children: [(0, jsx_runtime_1.jsx)("div", { className: "bg-b3-line/50 mb-4 rounded-full p-4", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "text-b3-foreground-muted h-8 w-8 animate-spin" }) }), (0, jsx_runtime_1.jsx)("h3", { className: "text-b3-grey font-neue-montreal-semibold mb-2", children: "Loading token data..." }), (0, jsx_runtime_1.jsx)("p", { className: "text-b3-foreground-muted font-neue-montreal-medium text-sm", children: "Please wait while we fetch the latest information" })] }));
189
+ }
190
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)(react_1.Button, { variant: "ghost", size: "icon", onClick: () => {
191
+ animationDirection.current = "back";
192
+ setTokenPanelView(TokenPanelView.LIST);
193
+ }, className: "hover:bg-b3-line/60", disabled: isSending, children: (0, jsx_runtime_1.jsx)(lucide_react_1.ArrowLeft, { className: "h-5 w-5" }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex h-8 w-8 items-center justify-center", children: anyspend_1.ALL_CHAINS[displayToken.chain_id]?.logoUrl ? ((0, jsx_runtime_1.jsx)(ChainTokenIcon_1.ChainTokenIcon, { chainUrl: anyspend_1.ALL_CHAINS[displayToken.chain_id].logoUrl, tokenUrl: displayToken.token_metadata?.logo, className: "size-8" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.CircleHelp, { className: "text-b3-react-foreground size-8" })) }), (0, jsx_runtime_1.jsxs)("h2", { className: "text-b3-grey font-neue-montreal-semibold text-lg", children: ["Send ", displayToken.symbol] })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-2", children: [(0, jsx_runtime_1.jsx)("label", { className: "text-b3-grey font-neue-montreal-medium text-sm", children: "Recipient Address" }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-1", children: [(0, jsx_runtime_1.jsxs)("div", { className: "relative", children: [(0, jsx_runtime_1.jsx)("input", { type: "text", value: recipientAddress, onChange: e => handleRecipientAddressChange(e.target.value), placeholder: "Enter wallet address (0x...)", className: `border-b3-line bg-b3-background text-b3-grey font-neue-montreal-medium placeholder:text-b3-foreground-muted w-full rounded-xl border px-4 py-3 pr-12 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 ${addressError ? "border-red-500 focus:border-red-500" : "focus:border-b3-primary-blue"}`, disabled: isSending }), (0, jsx_runtime_1.jsx)(react_1.Button, { variant: "ghost", size: "icon", className: "hover:bg-b3-line/60 absolute right-2 top-1/2 h-8 w-8 -translate-y-1/2", disabled: isSending, onClick: () => {
194
+ navigator.clipboard.readText().then(text => {
195
+ handleRecipientAddressChange(text);
196
+ });
197
+ }, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { className: "h-4 w-4" }) })] }), addressError && (0, jsx_runtime_1.jsx)("p", { className: "font-neue-montreal-medium text-xs text-red-500", children: addressError })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-2", children: [(0, jsx_runtime_1.jsx)("label", { className: "text-b3-grey font-neue-montreal-medium text-sm", children: "Amount" }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-3", children: [(0, jsx_runtime_1.jsx)(react_number_format_1.NumericFormat, { decimalSeparator: ".", allowedDecimalSeparators: [","], thousandSeparator: true, inputMode: "decimal", autoComplete: "off", autoCorrect: "off", type: "text", placeholder: "0.00", minLength: 1, maxLength: 30, spellCheck: "false", className: "border-b3-line bg-b3-background text-b3-grey font-neue-montreal-medium placeholder:text-b3-foreground-muted focus:border-b3-primary-blue w-full rounded-xl border px-4 py-3 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50", pattern: "^[0-9]*[.,]?[0-9]*$", disabled: isSending, value: sendAmount, allowNegative: false, onChange: e => setSendAmount(e.currentTarget.value) }), (0, jsx_runtime_1.jsx)("div", { className: "grid grid-cols-4 gap-2", children: [25, 50, 75, 100].map(percentage => ((0, jsx_runtime_1.jsxs)(react_1.Button, { variant: "outline", onClick: () => handlePercentageClick(percentage), className: "hover:bg-b3-primary-wash border-b3-line text-b3-grey font-neue-montreal-medium text-sm", disabled: isSending, children: [percentage, "%"] }, percentage))) }), (0, jsx_runtime_1.jsxs)("div", { className: "text-b3-foreground-muted font-neue-montreal-medium text-sm", children: ["Available: ", (0, number_1.formatTokenAmount)(BigInt(displayToken.amount), displayToken.decimals), " ", displayToken.symbol] })] })] }), (0, jsx_runtime_1.jsx)(react_1.Button, { onClick: handleSend, disabled: !recipientAddress ||
198
+ !sendAmount ||
199
+ parseFloat(sendAmount) <= 0 ||
200
+ isSending ||
201
+ !!addressError ||
202
+ !(0, viem_1.isAddress)(recipientAddress), className: "bg-b3-primary-blue hover:bg-b3-primary-blue/90 font-neue-montreal-semibold disabled:bg-b3-line disabled:text-b3-foreground-muted w-full rounded-xl py-3 text-white", children: isSending ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Sending..."] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Send, { className: "mr-2 h-4 w-4" }), "Send ", displayToken.symbol] })) })] }));
203
+ };
204
+ // Skeleton loading component for token list
205
+ const LoadingIndicator = () => ((0, jsx_runtime_1.jsx)("div", { className: "space-y-4", children: (0, jsx_runtime_1.jsx)("div", { className: "space-y-1", children: [...Array(3)].map((_, index) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between rounded-xl p-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)("div", { className: "bg-b3-line h-10 w-10 animate-pulse rounded-full" }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "bg-b3-line mb-1 h-4 w-16 animate-pulse rounded" }), (0, jsx_runtime_1.jsx)("div", { className: "bg-b3-line h-3 w-24 animate-pulse rounded" })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "text-right", children: [(0, jsx_runtime_1.jsx)("div", { className: "bg-b3-line mb-1 h-4 w-20 animate-pulse rounded" }), (0, jsx_runtime_1.jsx)("div", { className: "bg-b3-line h-3 w-16 animate-pulse rounded" })] })] }, index))) }) }));
206
+ /**
207
+ * Renders the token list panel with smart filtering
208
+ * Features intelligent token display logic to reduce noise while ensuring visibility
209
+ */
210
+ const renderTokenListPanel = () => {
211
+ // Show loading indicator when balance is loading
212
+ if (isLoadingBalance) {
213
+ return (0, jsx_runtime_1.jsx)(LoadingIndicator, {});
214
+ }
215
+ // Show empty state when no account or no balance data
216
+ if (!account?.address || !simBalance) {
217
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-center justify-center py-12 text-center", children: [(0, jsx_runtime_1.jsx)("div", { className: "bg-b3-line/50 mb-4 rounded-full p-4", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "text-b3-foreground-muted h-8 w-8" }) }), (0, jsx_runtime_1.jsx)("h3", { className: "text-b3-grey font-neue-montreal-semibold mb-2", children: "No wallet connected" }), (0, jsx_runtime_1.jsx)("p", { className: "text-b3-foreground-muted font-neue-montreal-medium text-sm", children: "Connect your wallet to view token balances" })] }));
218
+ }
219
+ // === SMART FILTERING LOGIC ===
220
+ // Filter tokens with value >= $1 to reduce noise from dust tokens
221
+ const filteredTokens = simBalance?.balances.filter(token => token.value_usd !== undefined && token.value_usd >= 1) || [];
222
+ // 🧠 INTELLIGENT DISPLAY LOGIC:
223
+ // Show all tokens automatically when filtering would be unhelpful:
224
+ // 1. User explicitly requested to show all, OR
225
+ // 2. No tokens with value >= $1 (user has only dust), OR
226
+ // 3. 5 or fewer tokens with value >= $1 (not enough to warrant filtering)
227
+ const shouldShowAllTokens = showAllTokens || filteredTokens.length === 0 || filteredTokens.length <= 5;
228
+ const tokensToShow = shouldShowAllTokens ? simBalance?.balances || [] : filteredTokens;
229
+ const hasHiddenTokens = !shouldShowAllTokens && (simBalance?.balances.length || 0) > filteredTokens.length;
230
+ // Handle token selection and navigate to send form
231
+ const handleTokenClick = (token) => {
232
+ setSelectedToken(token);
233
+ animationDirection.current = "forward"; // Set animation direction BEFORE state change
234
+ setTokenPanelView(TokenPanelView.SEND);
235
+ // Reset form when selecting a new token
236
+ setRecipientAddress("");
237
+ setSendAmount("");
238
+ setIsSending(false);
239
+ setAddressError("");
240
+ };
241
+ // Show empty state when no tokens are available
242
+ if (tokensToShow.length === 0) {
243
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-center justify-center py-12 text-center", children: [(0, jsx_runtime_1.jsx)("div", { className: "bg-b3-line/50 mb-4 rounded-full p-4", children: (0, jsx_runtime_1.jsx)(lucide_react_1.CircleHelp, { className: "text-b3-foreground-muted h-8 w-8" }) }), (0, jsx_runtime_1.jsx)("h3", { className: "text-b3-grey font-neue-montreal-semibold mb-2", children: "No tokens found" }), (0, jsx_runtime_1.jsx)("p", { className: "text-b3-foreground-muted font-neue-montreal-medium text-sm", children: "No token balances found in your wallet." })] }));
244
+ }
245
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "space-y-1", children: tokensToShow.map(token => ((0, jsx_runtime_1.jsxs)("div", { className: "hover:bg-b3-line/60 dark:hover:bg-b3-primary-wash/40 group flex cursor-pointer items-center justify-between rounded-xl p-3 transition-all duration-200", onClick: () => handleTokenClick(token), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex h-10 w-10 items-center justify-center rounded-full", children: anyspend_1.ALL_CHAINS[token.chain_id]?.logoUrl ? ((0, jsx_runtime_1.jsx)(ChainTokenIcon_1.ChainTokenIcon, { chainUrl: anyspend_1.ALL_CHAINS[token.chain_id].logoUrl, tokenUrl: token.token_metadata?.logo, className: "size-10" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.CircleHelp, { className: "text-b3-react-foreground size-10" })) }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-2", children: (0, jsx_runtime_1.jsx)("span", { className: "text-b3-grey font-neue-montreal-semibold transition-colors duration-200 group-hover:font-bold group-hover:text-black", children: token.symbol }) }), (0, jsx_runtime_1.jsx)("div", { className: "text-b3-foreground-muted font-neue-montreal-medium text-sm transition-colors duration-200 group-hover:text-gray-700", children: token.name })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "text-right", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-b3-grey font-neue-montreal-semibold transition-colors duration-200 group-hover:font-bold group-hover:text-black", children: (0, number_1.formatTokenAmount)(BigInt(token.amount), token.decimals) }), (0, jsx_runtime_1.jsx)("div", { className: "text-b3-foreground-muted font-neue-montreal-medium text-sm transition-colors duration-200 group-hover:text-gray-700", children: (0, number_1.formatDisplayNumber)(token.value_usd, { style: "currency", fractionDigits: 2 }) })] })] }, token.chain_id + "_" + token.address))) }), hasHiddenTokens && !showAllTokens && ((0, jsx_runtime_1.jsx)("div", { className: "flex justify-center", children: (0, jsx_runtime_1.jsx)(react_1.Button, { variant: "ghost", className: "text-b3-primary-blue hover:text-b3-primary-blue/80 font-neue-montreal-semibold text-sm", onClick: () => setShowAllTokens(true), children: "Show more" }) }))] }));
246
+ };
247
+ // === ANIMATION CONFIGURATION ===
248
+ // Memoize variants to prevent re-creation and unwanted re-renders
249
+ const variants = (0, react_2.useMemo)(() => ({
250
+ enter: (direction) => ({
251
+ x: direction === "back" ? -300 : 300, // Back: slide from left, Forward: slide from right
252
+ opacity: 0,
253
+ }),
254
+ center: { x: 0, opacity: 1 }, // Final position: centered and visible
255
+ exit: (direction) => ({
256
+ x: direction === "back" ? 300 : -300, // Back: slide to right, Forward: slide to left
257
+ opacity: 0,
258
+ }),
259
+ }), []);
260
+ // Memoize transition config for consistent spring animation
261
+ const transition = (0, react_2.useMemo)(() => ({
262
+ type: "spring",
263
+ stiffness: 300, // Spring tension
264
+ damping: 30, // Spring damping
265
+ }), []);
266
+ return ((0, jsx_runtime_1.jsx)(react_1.TransitionPanel, { activeIndex: tokenPanelView, className: "min-h-[400px]", custom: animationDirection.current, variants: variants, transition: transition, children: [(0, jsx_runtime_1.jsx)("div", { children: renderTokenListPanel() }, "token-list"), (0, jsx_runtime_1.jsx)("div", { children: renderSendTokenPanel() }, "send-token")] }));
267
+ }