@relayprotocol/relay-kit-ui 5.1.2 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/_cjs/src/components/common/BalanceDisplay.js +4 -3
  2. package/_cjs/src/components/common/BalanceDisplay.js.map +1 -1
  3. package/_cjs/src/components/common/MultiWalletDropdown.js +5 -4
  4. package/_cjs/src/components/common/MultiWalletDropdown.js.map +1 -1
  5. package/_cjs/src/components/common/PercentageButtons.js +9 -9
  6. package/_cjs/src/components/common/PercentageButtons.js.map +1 -1
  7. package/_cjs/src/components/common/SlippageToleranceConfig.js +30 -17
  8. package/_cjs/src/components/common/SlippageToleranceConfig.js.map +1 -1
  9. package/_cjs/src/components/common/TokenSelector/ChainFilter.js +21 -19
  10. package/_cjs/src/components/common/TokenSelector/ChainFilter.js.map +1 -1
  11. package/_cjs/src/components/common/TokenSelector/ChainFilterRow.js +117 -0
  12. package/_cjs/src/components/common/TokenSelector/ChainFilterRow.js.map +1 -0
  13. package/_cjs/src/components/common/TokenSelector/ChainFilterSidebar.js +2 -13
  14. package/_cjs/src/components/common/TokenSelector/ChainFilterSidebar.js.map +1 -1
  15. package/_cjs/src/components/common/TokenSelector/CompactChainFilter.js +180 -0
  16. package/_cjs/src/components/common/TokenSelector/CompactChainFilter.js.map +1 -0
  17. package/_cjs/src/components/common/TokenSelector/PaymentMethod.js +456 -0
  18. package/_cjs/src/components/common/TokenSelector/PaymentMethod.js.map +1 -0
  19. package/_cjs/src/components/common/TokenSelector/PaymentTokenList.js +83 -0
  20. package/_cjs/src/components/common/TokenSelector/PaymentTokenList.js.map +1 -0
  21. package/_cjs/src/components/common/TokenSelector/triggers/PaymentMethodTrigger.js +77 -0
  22. package/_cjs/src/components/common/TokenSelector/triggers/PaymentMethodTrigger.js.map +1 -0
  23. package/_cjs/src/components/primitives/ChainTokenIcon.js +3 -2
  24. package/_cjs/src/components/primitives/ChainTokenIcon.js.map +1 -1
  25. package/_cjs/src/components/primitives/SlippageButton.js +40 -0
  26. package/_cjs/src/components/primitives/SlippageButton.js.map +1 -0
  27. package/_cjs/src/components/primitives/Tabs.js +4 -2
  28. package/_cjs/src/components/primitives/Tabs.js.map +1 -1
  29. package/_cjs/src/components/widgets/SwapButton.js +35 -7
  30. package/_cjs/src/components/widgets/SwapButton.js.map +1 -1
  31. package/_cjs/src/components/widgets/TokenWidget/AmountModeToggle.js +31 -0
  32. package/_cjs/src/components/widgets/TokenWidget/AmountModeToggle.js.map +1 -0
  33. package/_cjs/src/components/widgets/TokenWidget/AmountSectionHeader.js +8 -0
  34. package/_cjs/src/components/widgets/TokenWidget/AmountSectionHeader.js.map +1 -0
  35. package/_cjs/src/components/widgets/TokenWidget/BuyTabContent.js +218 -0
  36. package/_cjs/src/components/widgets/TokenWidget/BuyTabContent.js.map +1 -0
  37. package/_cjs/src/components/widgets/TokenWidget/DestinationWalletSelector.js +20 -0
  38. package/_cjs/src/components/widgets/TokenWidget/DestinationWalletSelector.js.map +1 -0
  39. package/_cjs/src/components/widgets/TokenWidget/FeeBreakdownInfo.js +26 -0
  40. package/_cjs/src/components/widgets/TokenWidget/FeeBreakdownInfo.js.map +1 -0
  41. package/_cjs/src/components/widgets/TokenWidget/FeeBreakdownTooltip.js +40 -0
  42. package/_cjs/src/components/widgets/TokenWidget/FeeBreakdownTooltip.js.map +1 -0
  43. package/_cjs/src/components/widgets/TokenWidget/SectionContainer.js +22 -0
  44. package/_cjs/src/components/widgets/TokenWidget/SectionContainer.js.map +1 -0
  45. package/_cjs/src/components/widgets/TokenWidget/SellTabContent.js +280 -0
  46. package/_cjs/src/components/widgets/TokenWidget/SellTabContent.js.map +1 -0
  47. package/_cjs/src/components/widgets/TokenWidget/TransactionDetailsFooter.js +28 -0
  48. package/_cjs/src/components/widgets/TokenWidget/TransactionDetailsFooter.js.map +1 -0
  49. package/_cjs/src/components/widgets/TokenWidget/hooks/useWalletGuards.js +108 -0
  50. package/_cjs/src/components/widgets/TokenWidget/hooks/useWalletGuards.js.map +1 -0
  51. package/_cjs/src/components/widgets/TokenWidget/index.js +9 -0
  52. package/_cjs/src/components/widgets/TokenWidget/index.js.map +1 -0
  53. package/_cjs/src/components/widgets/TokenWidget/widget/TokenWidgetRenderer.js +770 -0
  54. package/_cjs/src/components/widgets/TokenWidget/widget/TokenWidgetRenderer.js.map +1 -0
  55. package/_cjs/src/components/widgets/TokenWidget/widget/index.js +1005 -0
  56. package/_cjs/src/components/widgets/TokenWidget/widget/index.js.map +1 -0
  57. package/_cjs/src/hooks/index.js +3 -1
  58. package/_cjs/src/hooks/index.js.map +1 -1
  59. package/_cjs/src/hooks/useDuneBalances.js +2 -1
  60. package/_cjs/src/hooks/useDuneBalances.js.map +1 -1
  61. package/_cjs/src/hooks/useEOADetection.js +3 -0
  62. package/_cjs/src/hooks/useEOADetection.js.map +1 -1
  63. package/_cjs/src/hooks/useMultiWalletBalances.js +119 -0
  64. package/_cjs/src/hooks/useMultiWalletBalances.js.map +1 -0
  65. package/_cjs/src/index.js.map +1 -1
  66. package/_cjs/src/styles.css +251 -88
  67. package/_cjs/src/utils/numbers.js +39 -1
  68. package/_cjs/src/utils/numbers.js.map +1 -1
  69. package/_cjs/src/utils/tokenSelector.js +4 -1
  70. package/_cjs/src/utils/tokenSelector.js.map +1 -1
  71. package/_cjs/src/utils/tokens.js +20 -1
  72. package/_cjs/src/utils/tokens.js.map +1 -1
  73. package/_cjs/src/version.js +1 -1
  74. package/_cjs/tsconfig.build.tsbuildinfo +1 -1
  75. package/_esm/src/components/common/BalanceDisplay.js +4 -3
  76. package/_esm/src/components/common/BalanceDisplay.js.map +1 -1
  77. package/_esm/src/components/common/MultiWalletDropdown.js +5 -4
  78. package/_esm/src/components/common/MultiWalletDropdown.js.map +1 -1
  79. package/_esm/src/components/common/PercentageButtons.js +10 -10
  80. package/_esm/src/components/common/PercentageButtons.js.map +1 -1
  81. package/_esm/src/components/common/SlippageToleranceConfig.js +31 -23
  82. package/_esm/src/components/common/SlippageToleranceConfig.js.map +1 -1
  83. package/_esm/src/components/common/TokenSelector/ChainFilter.js +25 -23
  84. package/_esm/src/components/common/TokenSelector/ChainFilter.js.map +1 -1
  85. package/_esm/src/components/common/TokenSelector/ChainFilterRow.js +112 -0
  86. package/_esm/src/components/common/TokenSelector/ChainFilterRow.js.map +1 -0
  87. package/_esm/src/components/common/TokenSelector/ChainFilterSidebar.js +4 -15
  88. package/_esm/src/components/common/TokenSelector/ChainFilterSidebar.js.map +1 -1
  89. package/_esm/src/components/common/TokenSelector/CompactChainFilter.js +176 -0
  90. package/_esm/src/components/common/TokenSelector/CompactChainFilter.js.map +1 -0
  91. package/_esm/src/components/common/TokenSelector/PaymentMethod.js +461 -0
  92. package/_esm/src/components/common/TokenSelector/PaymentMethod.js.map +1 -0
  93. package/_esm/src/components/common/TokenSelector/PaymentTokenList.js +79 -0
  94. package/_esm/src/components/common/TokenSelector/PaymentTokenList.js.map +1 -0
  95. package/_esm/src/components/common/TokenSelector/triggers/PaymentMethodTrigger.js +72 -0
  96. package/_esm/src/components/common/TokenSelector/triggers/PaymentMethodTrigger.js.map +1 -0
  97. package/_esm/src/components/primitives/ChainTokenIcon.js +3 -2
  98. package/_esm/src/components/primitives/ChainTokenIcon.js.map +1 -1
  99. package/_esm/src/components/primitives/SlippageButton.js +36 -0
  100. package/_esm/src/components/primitives/SlippageButton.js.map +1 -0
  101. package/_esm/src/components/primitives/Tabs.js +4 -2
  102. package/_esm/src/components/primitives/Tabs.js.map +1 -1
  103. package/_esm/src/components/widgets/SwapButton.js +35 -7
  104. package/_esm/src/components/widgets/SwapButton.js.map +1 -1
  105. package/_esm/src/components/widgets/TokenWidget/AmountModeToggle.js +30 -0
  106. package/_esm/src/components/widgets/TokenWidget/AmountModeToggle.js.map +1 -0
  107. package/_esm/src/components/widgets/TokenWidget/AmountSectionHeader.js +7 -0
  108. package/_esm/src/components/widgets/TokenWidget/AmountSectionHeader.js.map +1 -0
  109. package/_esm/src/components/widgets/TokenWidget/BuyTabContent.js +215 -0
  110. package/_esm/src/components/widgets/TokenWidget/BuyTabContent.js.map +1 -0
  111. package/_esm/src/components/widgets/TokenWidget/DestinationWalletSelector.js +16 -0
  112. package/_esm/src/components/widgets/TokenWidget/DestinationWalletSelector.js.map +1 -0
  113. package/_esm/src/components/widgets/TokenWidget/FeeBreakdownInfo.js +21 -0
  114. package/_esm/src/components/widgets/TokenWidget/FeeBreakdownInfo.js.map +1 -0
  115. package/_esm/src/components/widgets/TokenWidget/FeeBreakdownTooltip.js +39 -0
  116. package/_esm/src/components/widgets/TokenWidget/FeeBreakdownTooltip.js.map +1 -0
  117. package/_esm/src/components/widgets/TokenWidget/SectionContainer.js +22 -0
  118. package/_esm/src/components/widgets/TokenWidget/SectionContainer.js.map +1 -0
  119. package/_esm/src/components/widgets/TokenWidget/SellTabContent.js +283 -0
  120. package/_esm/src/components/widgets/TokenWidget/SellTabContent.js.map +1 -0
  121. package/_esm/src/components/widgets/TokenWidget/TransactionDetailsFooter.js +27 -0
  122. package/_esm/src/components/widgets/TokenWidget/TransactionDetailsFooter.js.map +1 -0
  123. package/_esm/src/components/widgets/TokenWidget/hooks/useWalletGuards.js +104 -0
  124. package/_esm/src/components/widgets/TokenWidget/hooks/useWalletGuards.js.map +1 -0
  125. package/_esm/src/components/widgets/TokenWidget/index.js +2 -0
  126. package/_esm/src/components/widgets/TokenWidget/index.js.map +1 -0
  127. package/_esm/src/components/widgets/TokenWidget/widget/TokenWidgetRenderer.js +795 -0
  128. package/_esm/src/components/widgets/TokenWidget/widget/TokenWidgetRenderer.js.map +1 -0
  129. package/_esm/src/components/widgets/TokenWidget/widget/index.js +1073 -0
  130. package/_esm/src/components/widgets/TokenWidget/widget/index.js.map +1 -0
  131. package/_esm/src/hooks/index.js +2 -1
  132. package/_esm/src/hooks/index.js.map +1 -1
  133. package/_esm/src/hooks/useDuneBalances.js +2 -1
  134. package/_esm/src/hooks/useDuneBalances.js.map +1 -1
  135. package/_esm/src/hooks/useEOADetection.js +3 -0
  136. package/_esm/src/hooks/useEOADetection.js.map +1 -1
  137. package/_esm/src/hooks/useMultiWalletBalances.js +122 -0
  138. package/_esm/src/hooks/useMultiWalletBalances.js.map +1 -0
  139. package/_esm/src/index.js.map +1 -1
  140. package/_esm/src/styles.css +251 -88
  141. package/_esm/src/utils/numbers.js +44 -1
  142. package/_esm/src/utils/numbers.js.map +1 -1
  143. package/_esm/src/utils/tokenSelector.js +4 -1
  144. package/_esm/src/utils/tokenSelector.js.map +1 -1
  145. package/_esm/src/utils/tokens.js +25 -0
  146. package/_esm/src/utils/tokens.js.map +1 -1
  147. package/_esm/src/version.js +1 -1
  148. package/_esm/tsconfig.build.tsbuildinfo +1 -1
  149. package/_types/src/components/common/BalanceDisplay.d.ts +2 -0
  150. package/_types/src/components/common/BalanceDisplay.d.ts.map +1 -1
  151. package/_types/src/components/common/MultiWalletDropdown.d.ts +2 -1
  152. package/_types/src/components/common/MultiWalletDropdown.d.ts.map +1 -1
  153. package/_types/src/components/common/PercentageButtons.d.ts +3 -1
  154. package/_types/src/components/common/PercentageButtons.d.ts.map +1 -1
  155. package/_types/src/components/common/SlippageToleranceConfig.d.ts +7 -0
  156. package/_types/src/components/common/SlippageToleranceConfig.d.ts.map +1 -1
  157. package/_types/src/components/common/TokenSelector/ChainFilter.d.ts.map +1 -1
  158. package/_types/src/components/common/TokenSelector/ChainFilterRow.d.ts +19 -0
  159. package/_types/src/components/common/TokenSelector/ChainFilterRow.d.ts.map +1 -0
  160. package/_types/src/components/common/TokenSelector/ChainFilterSidebar.d.ts.map +1 -1
  161. package/_types/src/components/common/TokenSelector/CompactChainFilter.d.ts +14 -0
  162. package/_types/src/components/common/TokenSelector/CompactChainFilter.d.ts.map +1 -0
  163. package/_types/src/components/common/TokenSelector/PaymentMethod.d.ts +24 -0
  164. package/_types/src/components/common/TokenSelector/PaymentMethod.d.ts.map +1 -0
  165. package/_types/src/components/common/TokenSelector/PaymentTokenList.d.ts +15 -0
  166. package/_types/src/components/common/TokenSelector/PaymentTokenList.d.ts.map +1 -0
  167. package/_types/src/components/common/TokenSelector/triggers/PaymentMethodTrigger.d.ts +13 -0
  168. package/_types/src/components/common/TokenSelector/triggers/PaymentMethodTrigger.d.ts.map +1 -0
  169. package/_types/src/components/primitives/ChainTokenIcon.d.ts +1 -0
  170. package/_types/src/components/primitives/ChainTokenIcon.d.ts.map +1 -1
  171. package/_types/src/components/primitives/SlippageButton.d.ts +8 -0
  172. package/_types/src/components/primitives/SlippageButton.d.ts.map +1 -0
  173. package/_types/src/components/primitives/Tabs.d.ts.map +1 -1
  174. package/_types/src/components/widgets/SwapButton.d.ts +5 -2
  175. package/_types/src/components/widgets/SwapButton.d.ts.map +1 -1
  176. package/_types/src/components/widgets/TokenWidget/AmountModeToggle.d.ts +12 -0
  177. package/_types/src/components/widgets/TokenWidget/AmountModeToggle.d.ts.map +1 -0
  178. package/_types/src/components/widgets/TokenWidget/AmountSectionHeader.d.ts +11 -0
  179. package/_types/src/components/widgets/TokenWidget/AmountSectionHeader.d.ts.map +1 -0
  180. package/_types/src/components/widgets/TokenWidget/BuyTabContent.d.ts +52 -0
  181. package/_types/src/components/widgets/TokenWidget/BuyTabContent.d.ts.map +1 -0
  182. package/_types/src/components/widgets/TokenWidget/DestinationWalletSelector.d.ts +17 -0
  183. package/_types/src/components/widgets/TokenWidget/DestinationWalletSelector.d.ts.map +1 -0
  184. package/_types/src/components/widgets/TokenWidget/FeeBreakdownInfo.d.ts +16 -0
  185. package/_types/src/components/widgets/TokenWidget/FeeBreakdownInfo.d.ts.map +1 -0
  186. package/_types/src/components/widgets/TokenWidget/FeeBreakdownTooltip.d.ts +15 -0
  187. package/_types/src/components/widgets/TokenWidget/FeeBreakdownTooltip.d.ts.map +1 -0
  188. package/_types/src/components/widgets/TokenWidget/SectionContainer.d.ts +8 -0
  189. package/_types/src/components/widgets/TokenWidget/SectionContainer.d.ts.map +1 -0
  190. package/_types/src/components/widgets/TokenWidget/SellTabContent.d.ts +61 -0
  191. package/_types/src/components/widgets/TokenWidget/SellTabContent.d.ts.map +1 -0
  192. package/_types/src/components/widgets/TokenWidget/TransactionDetailsFooter.d.ts +14 -0
  193. package/_types/src/components/widgets/TokenWidget/TransactionDetailsFooter.d.ts.map +1 -0
  194. package/_types/src/components/widgets/TokenWidget/hooks/useWalletGuards.d.ts +28 -0
  195. package/_types/src/components/widgets/TokenWidget/hooks/useWalletGuards.d.ts.map +1 -0
  196. package/_types/src/components/widgets/TokenWidget/index.d.ts +3 -0
  197. package/_types/src/components/widgets/TokenWidget/index.d.ts.map +1 -0
  198. package/_types/src/components/widgets/TokenWidget/widget/TokenWidgetRenderer.d.ts +125 -0
  199. package/_types/src/components/widgets/TokenWidget/widget/TokenWidgetRenderer.d.ts.map +1 -0
  200. package/_types/src/components/widgets/TokenWidget/widget/index.d.ts +57 -0
  201. package/_types/src/components/widgets/TokenWidget/widget/index.d.ts.map +1 -0
  202. package/_types/src/hooks/index.d.ts +2 -1
  203. package/_types/src/hooks/index.d.ts.map +1 -1
  204. package/_types/src/hooks/useDuneBalances.d.ts.map +1 -1
  205. package/_types/src/hooks/useEOADetection.d.ts.map +1 -1
  206. package/_types/src/hooks/useMultiWalletBalances.d.ts +26 -0
  207. package/_types/src/hooks/useMultiWalletBalances.d.ts.map +1 -0
  208. package/_types/src/index.d.ts +1 -0
  209. package/_types/src/index.d.ts.map +1 -1
  210. package/_types/src/utils/numbers.d.ts +8 -1
  211. package/_types/src/utils/numbers.d.ts.map +1 -1
  212. package/_types/src/utils/tokenSelector.d.ts +1 -1
  213. package/_types/src/utils/tokenSelector.d.ts.map +1 -1
  214. package/_types/src/utils/tokens.d.ts +17 -0
  215. package/_types/src/utils/tokens.d.ts.map +1 -1
  216. package/_types/src/version.d.ts +1 -1
  217. package/_types/tsconfig.build.tsbuildinfo +1 -1
  218. package/dist/panda.buildinfo.json +74 -33
  219. package/dist/styles.css +251 -88
  220. package/package.json +8 -3
@@ -0,0 +1,1073 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Flex, Button, Text } from '../../../primitives/index.js';
3
+ import { TabsRoot, TabsList, TabsTrigger } from '../../../primitives/Tabs.js';
4
+ import { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
5
+ import { useRelayClient } from '../../../../hooks/index.js';
6
+ import { formatUnits } from 'viem';
7
+ import { usePublicClient } from 'wagmi';
8
+ import { ASSETS_RELAY_API } from '@relayprotocol/relay-sdk';
9
+ import { EventNames } from '../../../../constants/events.js';
10
+ import WidgetContainer from '../../WidgetContainer.js';
11
+ import { ProviderOptionsContext } from '../../../../providers/RelayKitProvider.js';
12
+ import { findBridgableToken, generateTokenImageUrl } from '../../../../utils/tokens.js';
13
+ import { UnverifiedTokenModal } from '../../../common/UnverifiedTokenModal.js';
14
+ import { alreadyAcceptedToken } from '../../../../utils/localStorage.js';
15
+ import { calculateUsdValue, getSwapEventData } from '../../../../utils/quote.js';
16
+ import { getFeeBufferAmount } from '../../../../utils/nativeMaxAmount.js';
17
+ import TokenWidgetRenderer, {} from './TokenWidgetRenderer.js';
18
+ import BuyTabContent from '../BuyTabContent.js';
19
+ import SellTabContent from '../SellTabContent.js';
20
+ import { useTokenList, useQuote } from '@relayprotocol/relay-kit-hooks';
21
+ import { useWalletGuards } from '../hooks/useWalletGuards.js';
22
+ const TokenWidget = ({ fromToken, setFromToken, toToken, setToToken, defaultFromTokenAddress, defaultFromTokenChainId, defaultToTokenAddress, defaultToTokenChainId, defaultToAddress, defaultAmount, defaultTradeType, slippageTolerance, onOpenSlippageConfig, lockToToken = false, lockFromToken = false, lockChainId, singleChainMode = false, wallet, multiWalletSupportEnabled = false, linkedWallets, supportedWalletVMs, disableInputAutoFocus = false, popularChainIds, disablePasteWalletAddressOption, useSecureBaseUrl, onSetPrimaryWallet, onLinkNewWallet, onFromTokenChange, onToTokenChange, onConnectWallet, onAnalyticEvent: _onAnalyticEvent, onSwapSuccess, onSwapValidating, onSwapError }) => {
23
+ const onAnalyticEvent = useCallback((eventName, data) => {
24
+ try {
25
+ _onAnalyticEvent?.(eventName, data);
26
+ }
27
+ catch (e) {
28
+ console.error('Error in onAnalyticEvent', eventName, data, e);
29
+ }
30
+ }, [_onAnalyticEvent]);
31
+ const relayClient = useRelayClient();
32
+ const providerOptionsContext = useContext(ProviderOptionsContext);
33
+ const connectorKeyOverrides = providerOptionsContext.vmConnectorKeyOverrides;
34
+ const [transactionModalOpen, setTransactionModalOpen] = useState(false);
35
+ const [depositAddressModalOpen, setDepositAddressModalOpen] = useState(false);
36
+ const [addressModalOpen, setAddressModalOpen] = useState(false);
37
+ const [pendingSuccessFlush, setPendingSuccessFlush] = useState(false);
38
+ const [unverifiedTokens, setUnverifiedTokens] = useState([]);
39
+ const [isUsdInputMode, setIsUsdInputMode] = useState(false);
40
+ const [usdInputValue, setUsdInputValue] = useState('');
41
+ const [usdOutputValue, setUsdOutputValue] = useState('');
42
+ const [tokenInputCache, setTokenInputCache] = useState('');
43
+ const [activeTab, setActiveTab] = useState('buy');
44
+ const tabTokenStateRef = useRef({ buy: {}, sell: {} });
45
+ const tabRecipientRef = useRef({ buy: {}, sell: {} });
46
+ const setTradeTypeRef = useRef(null);
47
+ const tradeTypeRef = useRef(defaultTradeType ?? 'EXPECTED_OUTPUT');
48
+ // Token resolution from address/chainId
49
+ const [resolvedFromToken, setResolvedFromToken] = useState(fromToken);
50
+ const [resolvedToToken, setResolvedToToken] = useState(toToken);
51
+ const hasLockedToken = lockFromToken || lockToToken;
52
+ const isSingleChainLocked = singleChainMode && lockChainId !== undefined;
53
+ const [localSlippageTolerance, setLocalSlippageTolerance] = useState(slippageTolerance);
54
+ // Query for fromToken if address/chainId provided but no token object
55
+ const { data: fromTokenList } = useTokenList(relayClient?.baseApiUrl, defaultFromTokenAddress && defaultFromTokenChainId && !fromToken
56
+ ? {
57
+ chainIds: [defaultFromTokenChainId],
58
+ address: defaultFromTokenAddress,
59
+ limit: 1
60
+ }
61
+ : undefined, {
62
+ enabled: !!(defaultFromTokenAddress &&
63
+ defaultFromTokenChainId &&
64
+ !fromToken &&
65
+ relayClient)
66
+ });
67
+ // Query for toToken if address/chainId provided but no token object
68
+ const { data: toTokenList } = useTokenList(relayClient?.baseApiUrl, defaultToTokenAddress && defaultToTokenChainId && !toToken
69
+ ? {
70
+ chainIds: [defaultToTokenChainId],
71
+ address: defaultToTokenAddress,
72
+ limit: 1
73
+ }
74
+ : undefined, {
75
+ enabled: !!(defaultToTokenAddress &&
76
+ defaultToTokenChainId &&
77
+ !toToken &&
78
+ relayClient)
79
+ });
80
+ // Resolve fromToken from API response
81
+ useEffect(() => {
82
+ if (fromToken) {
83
+ setResolvedFromToken(fromToken);
84
+ }
85
+ else if (fromTokenList?.[0]) {
86
+ const apiToken = fromTokenList[0];
87
+ const resolved = {
88
+ chainId: apiToken.chainId,
89
+ address: apiToken.address,
90
+ name: apiToken.name,
91
+ symbol: apiToken.symbol,
92
+ decimals: apiToken.decimals,
93
+ logoURI: generateTokenImageUrl(apiToken),
94
+ verified: apiToken.metadata?.verified ?? false
95
+ };
96
+ // In buy mode, the token from URL should be the token to buy (toToken)
97
+ // In sell mode, it should be the token to sell (fromToken)
98
+ if (activeTab === 'buy' && !toToken && !resolvedToToken) {
99
+ setResolvedToToken(resolved);
100
+ setToToken?.(resolved);
101
+ }
102
+ else if (activeTab === 'sell') {
103
+ setResolvedFromToken(resolved);
104
+ setFromToken?.(resolved);
105
+ }
106
+ }
107
+ }, [
108
+ fromToken,
109
+ fromTokenList,
110
+ setFromToken,
111
+ activeTab,
112
+ toToken,
113
+ resolvedToToken,
114
+ setToToken
115
+ ]);
116
+ // Resolve toToken from API response
117
+ useEffect(() => {
118
+ if (toToken) {
119
+ setResolvedToToken(toToken);
120
+ }
121
+ else if (toTokenList?.[0] && activeTab !== 'sell') {
122
+ // Don't auto-select tokens in sell tab - let user explicitly choose
123
+ const apiToken = toTokenList[0];
124
+ const resolved = {
125
+ chainId: apiToken.chainId,
126
+ address: apiToken.address,
127
+ name: apiToken.name,
128
+ symbol: apiToken.symbol,
129
+ decimals: apiToken.decimals,
130
+ logoURI: generateTokenImageUrl(apiToken),
131
+ verified: apiToken.metadata?.verified ?? false
132
+ };
133
+ setResolvedToToken(resolved);
134
+ setToToken?.(resolved);
135
+ }
136
+ }, [toToken, toTokenList, setToToken, activeTab]);
137
+ useEffect(() => {
138
+ setLocalSlippageTolerance(slippageTolerance);
139
+ }, [slippageTolerance]);
140
+ useEffect(() => {
141
+ const desiredTradeType = activeTab === 'buy' ? 'EXPECTED_OUTPUT' : 'EXACT_INPUT';
142
+ if (tradeTypeRef.current !== desiredTradeType) {
143
+ setTradeTypeRef.current?.(desiredTradeType);
144
+ }
145
+ }, [activeTab]);
146
+ const handleOpenSlippageConfig = () => {
147
+ onOpenSlippageConfig?.();
148
+ };
149
+ const handleSlippageToleranceChange = (value) => {
150
+ setLocalSlippageTolerance(value);
151
+ };
152
+ const computedDefaultTradeType = defaultTradeType ??
153
+ (activeTab === 'buy' ? 'EXPECTED_OUTPUT' : 'EXACT_INPUT');
154
+ //Handle external unverified tokens
155
+ useEffect(() => {
156
+ if (resolvedFromToken &&
157
+ 'verified' in resolvedFromToken &&
158
+ !resolvedFromToken.verified) {
159
+ const isAlreadyAccepted = alreadyAcceptedToken(resolvedFromToken);
160
+ if (!isAlreadyAccepted) {
161
+ unverifiedTokens.push({ token: resolvedFromToken, context: 'from' });
162
+ setResolvedFromToken(undefined);
163
+ setFromToken?.(undefined);
164
+ }
165
+ }
166
+ if (resolvedToToken &&
167
+ 'verified' in resolvedToToken &&
168
+ !resolvedToToken.verified) {
169
+ const isAlreadyAccepted = alreadyAcceptedToken(resolvedToToken);
170
+ if (!isAlreadyAccepted) {
171
+ unverifiedTokens.push({ token: resolvedToToken, context: 'to' });
172
+ setResolvedToToken(undefined);
173
+ setToToken?.(undefined);
174
+ }
175
+ }
176
+ }, [resolvedFromToken, resolvedToToken]);
177
+ return (_jsx(TokenWidgetRenderer, { context: "Swap", transactionModalOpen: transactionModalOpen, setTransactionModalOpen: setTransactionModalOpen, depositAddressModalOpen: depositAddressModalOpen, defaultAmount: defaultAmount, defaultToAddress: defaultToAddress, defaultTradeType: computedDefaultTradeType, toToken: resolvedToToken, setToToken: setResolvedToToken, fromToken: resolvedFromToken, setFromToken: setResolvedFromToken, slippageTolerance: localSlippageTolerance, wallet: wallet, linkedWallets: linkedWallets, multiWalletSupportEnabled: multiWalletSupportEnabled, onSwapError: onSwapError, onAnalyticEvent: onAnalyticEvent, supportedWalletVMs: supportedWalletVMs, useSecureBaseUrl: useSecureBaseUrl, children: ({ quote, steps, swap, setSteps, feeBreakdown, fromToken, setFromToken, toToken, setToToken, error, toDisplayName, address, originAddressOverride: _originAddressOverride, setOriginAddressOverride, recipient, customToAddress, setCustomToAddress, destinationAddressOverride, setDestinationAddressOverride, tradeType, setTradeType, isSameCurrencySameRecipientSwap, allowUnsupportedOrigin, setAllowUnsupportedOrigin, allowUnsupportedRecipient, setAllowUnsupportedRecipient, debouncedInputAmountValue, debouncedAmountInputControls, setAmountInputValue, amountInputValue, amountOutputValue, debouncedOutputAmountValue, debouncedAmountOutputControls, setAmountOutputValue, toBalance, toBalancePending, isLoadingToBalance, isFetchingQuote, isLoadingFromBalance, fromBalance, fromBalancePending, highRelayerServiceFee, relayerFeeProportion, hasInsufficientBalance, isInsufficientLiquidityError, isCapacityExceededError, isCouldNotExecuteError, ctaCopy, isFromNative, timeEstimate, isSvmSwap, isBvmSwap, isValidFromAddress, isValidToAddress, supportsExternalLiquidity, useExternalLiquidity, slippageTolerance, canonicalTimeEstimate, fromChainWalletVMSupported, toChainWalletVMSupported, isRecipientLinked, swapError, recipientWalletSupportsChain, linkedWallet, quoteParameters, setSwapError, setUseExternalLiquidity, invalidateBalanceQueries, invalidateQuoteQuery, quoteInProgress, setQuoteInProgress, abortController, fromTokenPriceData, toTokenPriceData, isLoadingFromTokenPrice, isLoadingToTokenPrice }) => {
178
+ setTradeTypeRef.current = setTradeType;
179
+ tradeTypeRef.current = tradeType;
180
+ useEffect(() => {
181
+ tabTokenStateRef.current[activeTab] = {
182
+ fromToken,
183
+ toToken
184
+ };
185
+ }, [activeTab, fromToken, toToken]);
186
+ useEffect(() => {
187
+ tabRecipientRef.current[activeTab] = {
188
+ override: typeof destinationAddressOverride === 'string'
189
+ ? destinationAddressOverride
190
+ : undefined,
191
+ custom: typeof customToAddress === 'string' ? customToAddress : undefined
192
+ };
193
+ }, [activeTab, destinationAddressOverride, customToAddress]);
194
+ useEffect(() => {
195
+ setAllowUnsupportedOrigin(activeTab === 'buy');
196
+ setAllowUnsupportedRecipient(activeTab === 'sell');
197
+ }, [activeTab, setAllowUnsupportedOrigin, setAllowUnsupportedRecipient]);
198
+ // Auto-select first compatible wallet in buy tab when toToken is set and no destination is selected
199
+ useEffect(() => {
200
+ if (activeTab === 'buy' &&
201
+ toToken &&
202
+ multiWalletSupportEnabled &&
203
+ linkedWallets &&
204
+ linkedWallets.length > 0 &&
205
+ !destinationAddressOverride &&
206
+ !customToAddress) {
207
+ // Find the destination chain for filtering compatible wallets
208
+ const toChain = relayClient?.chains?.find((c) => c.id === toToken.chainId);
209
+ if (toChain) {
210
+ // Filter wallets compatible with the destination chain VM type
211
+ const compatibleWallets = linkedWallets.filter((wallet) => {
212
+ return wallet.vmType === toChain.vmType;
213
+ });
214
+ // Auto-select the first compatible wallet (prefer the current address if compatible)
215
+ const currentAddressWallet = compatibleWallets.find((w) => w.address.toLowerCase() === address?.toLowerCase());
216
+ const walletToSelect = currentAddressWallet || compatibleWallets[0];
217
+ if (walletToSelect) {
218
+ setDestinationAddressOverride(walletToSelect.address);
219
+ }
220
+ }
221
+ }
222
+ }, [
223
+ activeTab,
224
+ toToken,
225
+ multiWalletSupportEnabled,
226
+ linkedWallets,
227
+ destinationAddressOverride,
228
+ customToAddress,
229
+ relayClient?.chains,
230
+ setDestinationAddressOverride,
231
+ address
232
+ ]);
233
+ // Calculate the USD value of the input amount
234
+ const inputAmountUsd = useMemo(() => {
235
+ return (calculateUsdValue(fromTokenPriceData?.price, amountInputValue) ??
236
+ null);
237
+ }, [fromTokenPriceData, amountInputValue]);
238
+ // Calculate the USD value of the output amount
239
+ const outputAmountUsd = useMemo(() => {
240
+ return (calculateUsdValue(toTokenPriceData?.price, amountOutputValue) ??
241
+ null);
242
+ }, [toTokenPriceData, amountOutputValue]);
243
+ const percentageOptions = [20, 50];
244
+ const handleMaxAmountClicked = async (amount, percent, bufferAmount) => {
245
+ if (fromToken) {
246
+ const formattedAmount = formatUnits(amount, fromToken?.decimals);
247
+ setAmountInputValue(formattedAmount);
248
+ setTradeType('EXACT_INPUT');
249
+ debouncedAmountOutputControls.cancel();
250
+ debouncedAmountInputControls.flush();
251
+ onAnalyticEvent?.(EventNames.MAX_AMOUNT_CLICKED, {
252
+ percent: percent,
253
+ bufferAmount: bufferAmount ? bufferAmount.toString() : '0',
254
+ chainType: fromChain?.vmType
255
+ });
256
+ if (isUsdInputMode && conversionRate) {
257
+ const numericTokenAmount = Number(formattedAmount);
258
+ if (!isNaN(numericTokenAmount)) {
259
+ const usdEquivalent = numericTokenAmount * conversionRate;
260
+ setUsdInputValue(usdEquivalent.toFixed(2));
261
+ }
262
+ }
263
+ }
264
+ };
265
+ const fromChain = relayClient?.chains?.find((chain) => chain.id === fromToken?.chainId);
266
+ const toChain = relayClient?.chains?.find((chain) => chain.id === toToken?.chainId);
267
+ const handleSetToToken = useCallback((token) => {
268
+ if (!token) {
269
+ setToToken(undefined);
270
+ onToTokenChange?.(undefined);
271
+ return;
272
+ }
273
+ let _token = token;
274
+ if (!fromChainWalletVMSupported) {
275
+ const newToChain = relayClient?.chains.find((chain) => token?.chainId == chain.id);
276
+ if (newToChain) {
277
+ const _toToken = findBridgableToken(newToChain, _token);
278
+ if (_toToken && _toToken.address != _token?.address) {
279
+ _token = _toToken;
280
+ }
281
+ }
282
+ }
283
+ setToToken(_token);
284
+ onToTokenChange?.(_token);
285
+ }, [fromChainWalletVMSupported, onToTokenChange, relayClient, setToToken]);
286
+ const handleSetFromToken = useCallback((token) => {
287
+ if (!token) {
288
+ setFromToken(undefined);
289
+ onFromTokenChange?.(undefined);
290
+ return;
291
+ }
292
+ let _token = token;
293
+ const newFromChain = relayClient?.chains.find((chain) => token?.chainId == chain.id);
294
+ if (newFromChain?.vmType &&
295
+ !supportedWalletVMs.includes(newFromChain?.vmType)) {
296
+ setTradeType('EXACT_INPUT');
297
+ const _toToken = findBridgableToken(toChain, toToken);
298
+ if (_toToken && _toToken?.address != toToken?.address) {
299
+ handleSetToToken(_toToken);
300
+ }
301
+ const _fromToken = findBridgableToken(newFromChain, _token);
302
+ if (_fromToken && _fromToken.address != _token?.address) {
303
+ _token = _fromToken;
304
+ }
305
+ }
306
+ setFromToken(_token);
307
+ onFromTokenChange?.(_token);
308
+ }, [
309
+ handleSetToToken,
310
+ onFromTokenChange,
311
+ relayClient,
312
+ setFromToken,
313
+ setTradeType,
314
+ supportedWalletVMs,
315
+ toChain,
316
+ toToken
317
+ ]);
318
+ // Get public client for the fromChain to estimate gas
319
+ const publicClient = usePublicClient({ chainId: fromChain?.id });
320
+ useWalletGuards({
321
+ multiWalletSupportEnabled,
322
+ allowUnsupportedOrigin,
323
+ allowUnsupportedRecipient,
324
+ fromChain,
325
+ toChain,
326
+ address,
327
+ recipient,
328
+ linkedWallets,
329
+ connectorKeyOverrides,
330
+ onSetPrimaryWallet,
331
+ isValidFromAddress,
332
+ isValidToAddress,
333
+ setOriginAddressOverride,
334
+ setCustomToAddress,
335
+ disablePasteWalletAddressOption,
336
+ customToAddress: customToAddress,
337
+ originAddressOverride: _originAddressOverride,
338
+ destinationAddressOverride: destinationAddressOverride,
339
+ setDestinationAddressOverride
340
+ });
341
+ const promptSwitchRoute = (isCapacityExceededError || isCouldNotExecuteError) &&
342
+ supportsExternalLiquidity &&
343
+ !isSingleChainLocked;
344
+ const isAutoSlippage = slippageTolerance === undefined;
345
+ const isHighPriceImpact = Number(quote?.details?.totalImpact?.percent) < -3.5;
346
+ const totalImpactUsd = quote?.details?.totalImpact?.usd;
347
+ const showHighPriceImpactWarning = Boolean(isHighPriceImpact && totalImpactUsd && Number(totalImpactUsd) <= -10);
348
+ // Calculate conversion rate
349
+ const conversionRate = useMemo(() => {
350
+ if (isUsdInputMode) {
351
+ // When in USD input mode, the conversion rate is the price of the fromToken.
352
+ if (fromTokenPriceData?.price && fromTokenPriceData.price > 0) {
353
+ return fromTokenPriceData.price;
354
+ }
355
+ else {
356
+ // If no price data, or price is 0, return null to avoid stale calculations.
357
+ return null;
358
+ }
359
+ }
360
+ else {
361
+ // When in token input mode, calculate rate from quote if available.
362
+ if (amountInputValue &&
363
+ Number(amountInputValue) > 0 &&
364
+ quote?.details?.currencyIn?.amountUsd) {
365
+ const tokenVal = Number(amountInputValue);
366
+ const usdVal = Number(quote.details.currencyIn.amountUsd);
367
+ if (tokenVal > 0 && usdVal > 0) {
368
+ const rate = usdVal / tokenVal;
369
+ return rate;
370
+ }
371
+ else {
372
+ return null;
373
+ }
374
+ }
375
+ else {
376
+ // If in token mode and token input is cleared or zero, return null
377
+ return null;
378
+ }
379
+ }
380
+ }, [
381
+ isUsdInputMode,
382
+ fromTokenPriceData?.price,
383
+ quote?.details?.currencyIn?.amountUsd,
384
+ amountInputValue
385
+ ]);
386
+ // toggle between token and usd input mode
387
+ const toggleInputMode = () => {
388
+ if (!isUsdInputMode) {
389
+ // Switching TO USD mode
390
+ let newUsdInputValue = '';
391
+ let newUsdOutputValue = '';
392
+ // Calculate USD input value
393
+ if (quote?.details?.currencyIn?.amountUsd &&
394
+ Number(quote.details.currencyIn.amountUsd) > 0) {
395
+ newUsdInputValue = String(Number(quote.details.currencyIn.amountUsd));
396
+ }
397
+ else if (inputAmountUsd && inputAmountUsd > 0) {
398
+ newUsdInputValue = inputAmountUsd.toFixed(2);
399
+ }
400
+ else if (amountInputValue &&
401
+ Number(amountInputValue) > 0 &&
402
+ conversionRate &&
403
+ conversionRate > 0) {
404
+ newUsdInputValue = (Number(amountInputValue) * conversionRate).toFixed(2);
405
+ }
406
+ // Calculate USD output value
407
+ if (quote?.details?.currencyOut?.amountUsd &&
408
+ Number(quote.details.currencyOut.amountUsd) > 0) {
409
+ newUsdOutputValue = String(Number(quote.details.currencyOut.amountUsd));
410
+ }
411
+ else if (outputAmountUsd && outputAmountUsd > 0) {
412
+ newUsdOutputValue = outputAmountUsd.toFixed(2);
413
+ }
414
+ else if (amountOutputValue &&
415
+ Number(amountOutputValue) > 0 &&
416
+ toTokenPriceData?.price &&
417
+ toTokenPriceData.price > 0) {
418
+ newUsdOutputValue = (Number(amountOutputValue) * toTokenPriceData.price).toFixed(2);
419
+ }
420
+ setTokenInputCache(amountInputValue);
421
+ setUsdInputValue(newUsdInputValue);
422
+ setUsdOutputValue(newUsdOutputValue);
423
+ setIsUsdInputMode(true);
424
+ // Default to EXACT_INPUT unless we're currently in EXPECTED_OUTPUT mode with a valid USD output value
425
+ if (tradeType !== 'EXPECTED_OUTPUT' || !newUsdOutputValue) {
426
+ setTradeType('EXACT_INPUT');
427
+ }
428
+ }
429
+ else {
430
+ // Switching FROM USD mode
431
+ if (!usdInputValue && tokenInputCache) {
432
+ setAmountInputValue(tokenInputCache);
433
+ }
434
+ setUsdInputValue('');
435
+ setUsdOutputValue('');
436
+ setIsUsdInputMode(false);
437
+ // Maintain current trade type when switching back to token mode
438
+ }
439
+ };
440
+ //Update token input value when USD input changes in USD mode
441
+ useEffect(() => {
442
+ if (isUsdInputMode) {
443
+ if (conversionRate && conversionRate > 0 && usdInputValue) {
444
+ const usdValue = Number(usdInputValue);
445
+ if (!isNaN(usdValue) && usdValue > 0) {
446
+ const tokenEquivalent = (usdValue / conversionRate).toFixed(fromToken?.decimals ?? 8);
447
+ setAmountInputValue(tokenEquivalent);
448
+ }
449
+ }
450
+ else if (usdInputValue === '' || Number(usdInputValue) === 0) {
451
+ setAmountInputValue('');
452
+ }
453
+ }
454
+ }, [
455
+ isUsdInputMode,
456
+ usdInputValue,
457
+ conversionRate,
458
+ setAmountInputValue,
459
+ fromToken?.decimals
460
+ ]);
461
+ //Update token output value when USD output changes in USD mode
462
+ useEffect(() => {
463
+ if (isUsdInputMode && tradeType === 'EXPECTED_OUTPUT') {
464
+ if (toTokenPriceData?.price &&
465
+ toTokenPriceData.price > 0 &&
466
+ usdOutputValue) {
467
+ const usdValue = Number(usdOutputValue);
468
+ if (!isNaN(usdValue) && usdValue > 0) {
469
+ const tokenEquivalent = (usdValue / toTokenPriceData.price).toFixed(toToken?.decimals ?? 8);
470
+ setAmountOutputValue(tokenEquivalent);
471
+ }
472
+ }
473
+ else if (usdOutputValue === '' || Number(usdOutputValue) === 0) {
474
+ setAmountOutputValue('');
475
+ }
476
+ }
477
+ }, [
478
+ isUsdInputMode,
479
+ tradeType,
480
+ usdOutputValue,
481
+ toTokenPriceData?.price,
482
+ setAmountOutputValue,
483
+ toToken?.decimals
484
+ ]);
485
+ //Update USD output value when in USD mode
486
+ useEffect(() => {
487
+ if (isUsdInputMode) {
488
+ // For EXPECTED_OUTPUT, don't override user's typed value
489
+ if (tradeType === 'EXPECTED_OUTPUT') {
490
+ // User is controlling the output value directly
491
+ return;
492
+ }
493
+ // For EXACT_INPUT, update based on quote or calculations
494
+ if (quote?.details?.currencyOut?.amountUsd && !isFetchingQuote) {
495
+ // Use quote USD value when available
496
+ const quoteUsdValue = Number(quote.details.currencyOut.amountUsd);
497
+ if (!isNaN(quoteUsdValue) && quoteUsdValue >= 0) {
498
+ setUsdOutputValue(quoteUsdValue.toFixed(2));
499
+ }
500
+ }
501
+ else if (toTokenPriceData?.price &&
502
+ toTokenPriceData.price > 0 &&
503
+ amountOutputValue &&
504
+ Number(amountOutputValue) > 0) {
505
+ // Fallback to direct token price calculation
506
+ const tokenAmount = Number(amountOutputValue);
507
+ const usdEquivalent = tokenAmount * toTokenPriceData.price;
508
+ if (!isNaN(usdEquivalent) && usdEquivalent >= 0) {
509
+ setUsdOutputValue(usdEquivalent.toFixed(2));
510
+ }
511
+ }
512
+ else if (!amountOutputValue || Number(amountOutputValue) === 0) {
513
+ setUsdOutputValue('');
514
+ }
515
+ }
516
+ }, [
517
+ isUsdInputMode,
518
+ tradeType,
519
+ quote?.details?.currencyOut?.amountUsd,
520
+ isFetchingQuote,
521
+ toTokenPriceData?.price,
522
+ amountOutputValue
523
+ ]);
524
+ //Update USD input value when in EXPECTED_OUTPUT mode
525
+ useEffect(() => {
526
+ if (isUsdInputMode && tradeType === 'EXPECTED_OUTPUT') {
527
+ if (quote?.details?.currencyIn?.amountUsd && !isFetchingQuote) {
528
+ // Use quote USD value when available
529
+ const quoteUsdValue = Number(quote.details.currencyIn.amountUsd);
530
+ if (!isNaN(quoteUsdValue) && quoteUsdValue >= 0) {
531
+ setUsdInputValue(quoteUsdValue.toFixed(2));
532
+ }
533
+ }
534
+ else if (!amountInputValue || Number(amountInputValue) === 0) {
535
+ setUsdInputValue('');
536
+ }
537
+ }
538
+ }, [
539
+ isUsdInputMode,
540
+ tradeType,
541
+ quote?.details?.currencyIn?.amountUsd,
542
+ isFetchingQuote,
543
+ amountInputValue
544
+ ]);
545
+ const recipientLinkedWallet = linkedWallets?.find((wallet) => wallet.address === recipient);
546
+ const handlePrimaryAction = () => {
547
+ if (fromChainWalletVMSupported) {
548
+ if (!isValidToAddress || !isValidFromAddress) {
549
+ if (multiWalletSupportEnabled &&
550
+ (isValidToAddress ||
551
+ (!isValidToAddress && toChainWalletVMSupported))) {
552
+ const chain = !isValidFromAddress ? fromChain : toChain;
553
+ if (!address) {
554
+ onConnectWallet?.();
555
+ }
556
+ else {
557
+ onLinkNewWallet?.({
558
+ chain,
559
+ direction: !isValidFromAddress ? 'from' : 'to'
560
+ })?.then((wallet) => {
561
+ if (!isValidFromAddress) {
562
+ onSetPrimaryWallet?.(wallet.address);
563
+ }
564
+ else {
565
+ setDestinationAddressOverride(wallet.address);
566
+ setCustomToAddress(undefined);
567
+ }
568
+ });
569
+ }
570
+ }
571
+ else {
572
+ setAddressModalOpen(true);
573
+ }
574
+ }
575
+ else {
576
+ swap();
577
+ }
578
+ }
579
+ else {
580
+ if (!isValidToAddress) {
581
+ if (multiWalletSupportEnabled && toChainWalletVMSupported) {
582
+ if (!address) {
583
+ onConnectWallet?.();
584
+ }
585
+ else {
586
+ onLinkNewWallet?.({
587
+ chain: toChain,
588
+ direction: 'to'
589
+ })?.then((wallet) => {
590
+ if (!wallet) {
591
+ return;
592
+ }
593
+ setDestinationAddressOverride(wallet.address);
594
+ setCustomToAddress(undefined);
595
+ });
596
+ }
597
+ }
598
+ else {
599
+ setAddressModalOpen(true);
600
+ }
601
+ }
602
+ else {
603
+ const swapEventData = getSwapEventData(quote?.details, quote?.fees, quote?.steps ? quote?.steps : null, linkedWallet?.connector, quoteParameters);
604
+ onAnalyticEvent?.(EventNames.SWAP_CTA_CLICKED, swapEventData);
605
+ setDepositAddressModalOpen(true);
606
+ }
607
+ }
608
+ };
609
+ useEffect(() => {
610
+ if (activeTab === 'buy' &&
611
+ !address &&
612
+ !linkedWallets?.length &&
613
+ !fromToken &&
614
+ !defaultFromTokenAddress &&
615
+ !defaultFromTokenChainId &&
616
+ relayClient) {
617
+ const baseUSDC = {
618
+ chainId: 8453,
619
+ address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
620
+ name: 'USD Coin',
621
+ symbol: 'USDC',
622
+ decimals: 6,
623
+ logoURI: `${ASSETS_RELAY_API}/icons/currencies/usdc.png`,
624
+ verified: true
625
+ };
626
+ handleSetFromToken(baseUSDC);
627
+ }
628
+ }, [
629
+ activeTab,
630
+ address,
631
+ linkedWallets?.length,
632
+ fromToken,
633
+ defaultFromTokenAddress,
634
+ defaultFromTokenChainId,
635
+ relayClient,
636
+ handleSetFromToken
637
+ ]);
638
+ return (_jsxs(_Fragment, { children: [_jsx(WidgetContainer, { steps: steps, setSteps: setSteps, quoteInProgress: quoteInProgress, setQuoteInProgress: setQuoteInProgress, transactionModalOpen: transactionModalOpen, setTransactionModalOpen: setTransactionModalOpen, depositAddressModalOpen: depositAddressModalOpen, setDepositAddressModalOpen: setDepositAddressModalOpen, addressModalOpen: addressModalOpen, setAddressModalOpen: setAddressModalOpen, fromToken: fromToken, fromChain: fromChain, toToken: toToken, toChain: toChain, address: address, recipient: recipient, amountInputValue: amountInputValue, amountOutputValue: amountOutputValue, debouncedInputAmountValue: debouncedInputAmountValue, debouncedOutputAmountValue: debouncedOutputAmountValue, tradeType: tradeType, onTransactionModalOpenChange: (open) => {
639
+ if (!open) {
640
+ if (pendingSuccessFlush) {
641
+ setPendingSuccessFlush(false);
642
+ }
643
+ else if (steps) {
644
+ invalidateQuoteQuery();
645
+ }
646
+ // Abort ongoing execution
647
+ if (abortController) {
648
+ abortController.abort();
649
+ }
650
+ setSwapError(null);
651
+ setSteps(null);
652
+ setQuoteInProgress(null);
653
+ }
654
+ else if (pendingSuccessFlush) {
655
+ setPendingSuccessFlush(false);
656
+ }
657
+ }, onDepositAddressModalOpenChange: (open) => {
658
+ if (!open) {
659
+ setSwapError(null);
660
+ if (pendingSuccessFlush) {
661
+ setPendingSuccessFlush(false);
662
+ }
663
+ else {
664
+ invalidateQuoteQuery();
665
+ }
666
+ }
667
+ else if (pendingSuccessFlush) {
668
+ setPendingSuccessFlush(false);
669
+ }
670
+ }, useExternalLiquidity: useExternalLiquidity, slippageTolerance: localSlippageTolerance, swapError: swapError, setSwapError: setSwapError, onSwapSuccess: (data) => {
671
+ setPendingSuccessFlush(true);
672
+ setAmountInputValue('');
673
+ setAmountOutputValue('');
674
+ onSwapSuccess?.(data);
675
+ }, onSwapValidating: onSwapValidating, onAnalyticEvent: onAnalyticEvent, invalidateBalanceQueries: invalidateBalanceQueries, invalidateQuoteQuery: invalidateQuoteQuery, customToAddress: customToAddress, setCustomToAddress: setCustomToAddress, timeEstimate: timeEstimate, wallet: wallet, linkedWallets: linkedWallets, multiWalletSupportEnabled: multiWalletSupportEnabled, children: () => {
676
+ return (_jsx(Flex, { direction: "column", css: { gap: '3', width: '100%' }, children: _jsx(TabsRoot, { value: activeTab, onValueChange: (value) => {
677
+ const nextTab = value;
678
+ setAllowUnsupportedOrigin(nextTab === 'buy');
679
+ setAllowUnsupportedRecipient(nextTab === 'sell');
680
+ if (nextTab !== activeTab) {
681
+ tabTokenStateRef.current[activeTab] = {
682
+ fromToken,
683
+ toToken
684
+ };
685
+ tabRecipientRef.current[activeTab] = {
686
+ override: typeof destinationAddressOverride === 'string'
687
+ ? destinationAddressOverride
688
+ : undefined,
689
+ custom: typeof customToAddress === 'string'
690
+ ? customToAddress
691
+ : undefined
692
+ };
693
+ const currentState = tabTokenStateRef.current[activeTab] ?? {};
694
+ const storedNextState = tabTokenStateRef.current[nextTab] ?? {};
695
+ const storedNextRecipient = tabRecipientRef.current[nextTab] ?? {};
696
+ let nextFromToken = storedNextState.fromToken;
697
+ let nextToToken = storedNextState.toToken;
698
+ if (nextTab === 'sell') {
699
+ const sellToken = nextFromToken ??
700
+ currentState.toToken ??
701
+ toToken ??
702
+ fromToken;
703
+ const receiveToken = nextToToken ?? currentState.fromToken ?? fromToken;
704
+ nextFromToken = sellToken ?? undefined;
705
+ nextToToken = receiveToken ?? undefined;
706
+ }
707
+ else {
708
+ const buyToken = nextToToken ??
709
+ currentState.toToken ??
710
+ toToken ??
711
+ fromToken;
712
+ const payToken = nextFromToken ??
713
+ currentState.fromToken ??
714
+ fromToken ??
715
+ currentState.toToken;
716
+ nextFromToken = payToken ?? undefined;
717
+ nextToToken = buyToken ?? undefined;
718
+ }
719
+ tabTokenStateRef.current[nextTab] = {
720
+ fromToken: nextFromToken,
721
+ toToken: nextToToken
722
+ };
723
+ tabRecipientRef.current[nextTab] = storedNextRecipient;
724
+ handleSetFromToken(nextFromToken);
725
+ handleSetToToken(nextToToken);
726
+ setDestinationAddressOverride(storedNextRecipient.override);
727
+ setCustomToAddress(storedNextRecipient.custom);
728
+ // Auto-select first compatible wallet in buy tab if no destination is set
729
+ if (nextTab === 'buy' &&
730
+ multiWalletSupportEnabled &&
731
+ linkedWallets &&
732
+ linkedWallets.length > 0 &&
733
+ !storedNextRecipient.override &&
734
+ !storedNextRecipient.custom) {
735
+ // Find the destination chain for filtering compatible wallets
736
+ const toChain = relayClient?.chains?.find((c) => c.id === nextToToken?.chainId);
737
+ if (toChain) {
738
+ // Filter wallets compatible with the destination chain VM type
739
+ const compatibleWallets = linkedWallets.filter((wallet) => {
740
+ return wallet.vmType === toChain.vmType;
741
+ });
742
+ // Auto-select the first compatible wallet
743
+ if (compatibleWallets.length > 0) {
744
+ setDestinationAddressOverride(compatibleWallets[0].address);
745
+ }
746
+ }
747
+ }
748
+ setAmountInputValue('');
749
+ setAmountOutputValue('');
750
+ setUsdInputValue('');
751
+ setUsdOutputValue('');
752
+ setTokenInputCache('');
753
+ setIsUsdInputMode(false);
754
+ debouncedAmountInputControls.cancel();
755
+ debouncedAmountOutputControls.cancel();
756
+ setOriginAddressOverride(undefined);
757
+ }
758
+ setActiveTab(nextTab);
759
+ const desiredTradeType = nextTab === 'buy' ? 'EXPECTED_OUTPUT' : 'EXACT_INPUT';
760
+ if (tradeType !== desiredTradeType) {
761
+ setTradeType(desiredTradeType);
762
+ }
763
+ onAnalyticEvent?.('TAB_SWITCHED', {
764
+ tab: value
765
+ });
766
+ }, children: _jsxs(Flex, { direction: "column", css: {
767
+ width: '100%',
768
+ overflow: 'hidden',
769
+ border: 'widget-border',
770
+ minWidth: 300,
771
+ maxWidth: 408
772
+ }, children: [_jsxs(TabsList, { css: {
773
+ backgroundColor: 'transparent',
774
+ p: '0',
775
+ mb: '2'
776
+ }, children: [_jsx(TabsTrigger, { value: "buy", css: {
777
+ padding: '12px',
778
+ background: 'none',
779
+ border: '1px solid transparent',
780
+ color: 'gray11',
781
+ '&[data-state="active"]': {
782
+ background: 'white',
783
+ borderRadius: '12px',
784
+ borderColor: 'slate.4',
785
+ color: 'gray12'
786
+ },
787
+ '&:not([data-state="active"])': {
788
+ _hover: {
789
+ backgroundColor: 'transparent !important'
790
+ }
791
+ },
792
+ _dark: {
793
+ '&[data-state="active"]': {
794
+ background: 'gray1',
795
+ borderColor: 'gray.4'
796
+ },
797
+ '&:not([data-state="active"])': {
798
+ _hover: {
799
+ backgroundColor: 'transparent !important'
800
+ }
801
+ }
802
+ }
803
+ }, children: _jsx(Text, { style: "subtitle1", children: "Buy" }) }), _jsx(TabsTrigger, { value: "sell", css: {
804
+ padding: '12px',
805
+ background: 'none',
806
+ border: '1px solid transparent',
807
+ color: 'gray11',
808
+ '&[data-state="active"]': {
809
+ background: 'white',
810
+ borderRadius: '12px',
811
+ borderColor: 'slate.4',
812
+ color: 'gray12'
813
+ },
814
+ '&:not([data-state="active"])': {
815
+ _hover: {
816
+ backgroundColor: 'transparent !important'
817
+ }
818
+ },
819
+ _dark: {
820
+ '&[data-state="active"]': {
821
+ background: 'gray1',
822
+ borderColor: 'gray.4'
823
+ },
824
+ '&:not([data-state="active"])': {
825
+ _hover: {
826
+ backgroundColor: 'transparent !important'
827
+ }
828
+ }
829
+ }
830
+ }, children: "Sell" })] }), _jsx(BuyTabContent, {
831
+ // Slippage configuration
832
+ slippageTolerance: localSlippageTolerance,
833
+ onOpenSlippageConfig: handleOpenSlippageConfig,
834
+ onSlippageToleranceChange: handleSlippageToleranceChange,
835
+ // Input/output state
836
+ isUsdInputMode,
837
+ usdOutputValue,
838
+ tradeType,
839
+ amountOutputValue,
840
+ amountInputValue,
841
+ outputAmountUsd,
842
+ setUsdOutputValue,
843
+ setTradeType,
844
+ setAmountOutputValue,
845
+ setAmountInputValue,
846
+ setUsdInputValue,
847
+ toggleInputMode,
848
+ debouncedAmountOutputControls,
849
+ // Tokens and pricing
850
+ toToken,
851
+ fromToken,
852
+ quote,
853
+ isFetchingQuote,
854
+ isLoadingToTokenPrice,
855
+ toTokenPriceData,
856
+ handleSetFromToken,
857
+ handleSetToToken,
858
+ // Balance information
859
+ feeBreakdown,
860
+ isLoadingFromBalance,
861
+ fromBalance,
862
+ fromBalancePending,
863
+ toBalance,
864
+ isLoadingToBalance,
865
+ toBalancePending,
866
+ hasInsufficientBalance,
867
+ // Wallet and address management
868
+ address,
869
+ multiWalletSupportEnabled,
870
+ linkedWallets,
871
+ onSetPrimaryWallet,
872
+ setOriginAddressOverride,
873
+ onConnectWallet,
874
+ onLinkNewWallet,
875
+ disablePasteWalletAddressOption,
876
+ setAddressModalOpen,
877
+ // Chain and VM support
878
+ fromChain,
879
+ toChain,
880
+ toChainWalletVMSupported,
881
+ fromChainWalletVMSupported,
882
+ supportedWalletVMs,
883
+ // Recipient configuration
884
+ recipient,
885
+ setCustomToAddress,
886
+ setDestinationAddressOverride,
887
+ isValidToAddress,
888
+ isRecipientLinked,
889
+ toDisplayName,
890
+ isValidFromAddress,
891
+ recipientWalletSupportsChain,
892
+ recipientLinkedWallet,
893
+ // Chain and token locking
894
+ lockToToken,
895
+ lockFromToken,
896
+ isSingleChainLocked,
897
+ lockChainId,
898
+ popularChainIds,
899
+ // Modal states
900
+ transactionModalOpen,
901
+ depositAddressModalOpen,
902
+ // Error and validation states
903
+ error,
904
+ isInsufficientLiquidityError,
905
+ isSameCurrencySameRecipientSwap,
906
+ isCapacityExceededError,
907
+ isCouldNotExecuteError,
908
+ supportsExternalLiquidity,
909
+ // UI state and interactions
910
+ showHighPriceImpactWarning,
911
+ disableSwapButton: promptSwitchRoute,
912
+ onPrimaryAction: handlePrimaryAction,
913
+ debouncedInputAmountValue,
914
+ debouncedOutputAmountValue,
915
+ // Fee and estimation
916
+ timeEstimate,
917
+ relayerFeeProportion,
918
+ highRelayerServiceFee,
919
+ // Event handling and misc
920
+ onAnalyticEvent,
921
+ toChainVmType: toChain?.vmType,
922
+ ctaCopy }), _jsx(SellTabContent, {
923
+ // Slippage configuration
924
+ slippageTolerance: localSlippageTolerance,
925
+ onOpenSlippageConfig: handleOpenSlippageConfig,
926
+ onSlippageToleranceChange: handleSlippageToleranceChange,
927
+ // Input/output state
928
+ disableInputAutoFocus,
929
+ isUsdInputMode,
930
+ usdInputValue,
931
+ tradeType,
932
+ amountInputValue,
933
+ amountOutputValue,
934
+ conversionRate,
935
+ inputAmountUsd,
936
+ setUsdInputValue,
937
+ setTradeType,
938
+ setTokenInputCache,
939
+ setAmountInputValue,
940
+ setAmountOutputValue,
941
+ setUsdOutputValue,
942
+ toggleInputMode,
943
+ debouncedAmountInputControls,
944
+ // Tokens and pricing
945
+ fromToken,
946
+ toToken,
947
+ quote,
948
+ isFetchingQuote,
949
+ fromTokenPriceData,
950
+ isLoadingFromTokenPrice,
951
+ handleSetFromToken,
952
+ handleSetToToken,
953
+ // Balance information
954
+ feeBreakdown,
955
+ fromBalance,
956
+ isLoadingFromBalance,
957
+ toBalance,
958
+ isLoadingToBalance,
959
+ toBalancePending,
960
+ hasInsufficientBalance,
961
+ fromBalancePending,
962
+ // Wallet and address management
963
+ address,
964
+ multiWalletSupportEnabled,
965
+ linkedWallets,
966
+ onSetPrimaryWallet,
967
+ setOriginAddressOverride,
968
+ onConnectWallet,
969
+ onLinkNewWallet,
970
+ disablePasteWalletAddressOption,
971
+ setAddressModalOpen,
972
+ // Chain and VM support
973
+ fromChain,
974
+ toChain,
975
+ fromChainWalletVMSupported,
976
+ toChainWalletVMSupported,
977
+ supportedWalletVMs,
978
+ // Recipient configuration
979
+ recipient,
980
+ setCustomToAddress,
981
+ setDestinationAddressOverride,
982
+ isValidToAddress,
983
+ isRecipientLinked,
984
+ toDisplayName,
985
+ isValidFromAddress,
986
+ recipientWalletSupportsChain,
987
+ recipientLinkedWallet,
988
+ // Chain and token locking
989
+ lockToToken,
990
+ lockFromToken,
991
+ isSingleChainLocked,
992
+ lockChainId,
993
+ popularChainIds,
994
+ // Modal states
995
+ transactionModalOpen,
996
+ depositAddressModalOpen,
997
+ // Error and validation states
998
+ error,
999
+ isInsufficientLiquidityError,
1000
+ isSameCurrencySameRecipientSwap,
1001
+ isCapacityExceededError,
1002
+ isCouldNotExecuteError,
1003
+ supportsExternalLiquidity,
1004
+ // UI state and interactions
1005
+ showHighPriceImpactWarning,
1006
+ disableSwapButton: promptSwitchRoute,
1007
+ onPrimaryAction: handlePrimaryAction,
1008
+ debouncedInputAmountValue,
1009
+ debouncedOutputAmountValue,
1010
+ percentOptions: percentageOptions,
1011
+ onMaxAmountClicked: handleMaxAmountClicked,
1012
+ publicClient,
1013
+ isFromNative,
1014
+ getFeeBufferAmount,
1015
+ // Fee and estimation
1016
+ timeEstimate,
1017
+ relayerFeeProportion,
1018
+ highRelayerServiceFee,
1019
+ // Event handling and misc
1020
+ onAnalyticEvent,
1021
+ toChainVmType: toChain?.vmType,
1022
+ ctaCopy }), promptSwitchRoute ? (_jsx(Button, { color: "primary", cta: true, css: { flexGrow: '1', justifyContent: 'center' }, onClick: () => {
1023
+ setUseExternalLiquidity(true);
1024
+ onAnalyticEvent?.(EventNames.CTA_SWITCH_ROUTE_CLICKED);
1025
+ }, children: "Switch Route" })) : null] }) }) }));
1026
+ } }), _jsx(UnverifiedTokenModal, { open: unverifiedTokens.length > 0, onOpenChange: () => { }, data: unverifiedTokens.length > 0 ? unverifiedTokens[0] : undefined, onDecline: (token, context) => {
1027
+ const tokens = unverifiedTokens.filter((unverifiedToken) => !(unverifiedToken.context === context &&
1028
+ unverifiedToken.token.address === token?.address &&
1029
+ unverifiedToken.token.chainId === token?.chainId));
1030
+ setUnverifiedTokens(tokens);
1031
+ }, onAcceptToken: (token, context) => {
1032
+ if (token) {
1033
+ if (context === 'to') {
1034
+ onAnalyticEvent?.(EventNames.SWAP_TOKEN_SELECT, {
1035
+ direction: 'output',
1036
+ token_symbol: token.symbol
1037
+ });
1038
+ if (token.address === fromToken?.address &&
1039
+ token.chainId === fromToken?.chainId &&
1040
+ address === recipient &&
1041
+ (!lockToToken || !fromToken)) {
1042
+ handleSetToToken(fromToken);
1043
+ handleSetFromToken(toToken);
1044
+ }
1045
+ else {
1046
+ handleSetToToken(token);
1047
+ }
1048
+ }
1049
+ else if (context === 'from') {
1050
+ onAnalyticEvent?.(EventNames.SWAP_TOKEN_SELECT, {
1051
+ direction: 'input',
1052
+ token_symbol: token.symbol
1053
+ });
1054
+ if (token.address === toToken?.address &&
1055
+ token.chainId === toToken?.chainId &&
1056
+ address === recipient &&
1057
+ (!lockToToken || !fromToken)) {
1058
+ handleSetFromToken(toToken);
1059
+ handleSetToToken(fromToken);
1060
+ }
1061
+ else {
1062
+ handleSetFromToken(token);
1063
+ }
1064
+ }
1065
+ }
1066
+ const tokens = unverifiedTokens.filter((unverifiedToken) => !(unverifiedToken.token.address === token?.address &&
1067
+ unverifiedToken.token.chainId === token?.chainId));
1068
+ setUnverifiedTokens(tokens);
1069
+ } })] }));
1070
+ } }));
1071
+ };
1072
+ export default TokenWidget;
1073
+ //# sourceMappingURL=index.js.map