0xtrails 0.6.6 → 0.7.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.
- package/dist/aave.d.ts +10 -2
- package/dist/aave.d.ts.map +1 -1
- package/dist/analytics.d.ts +26 -0
- package/dist/analytics.d.ts.map +1 -1
- package/dist/{ccip-CbJrlK-L.js → ccip-fConRNoG.js} +21 -21
- package/dist/chains.d.ts +23 -8
- package/dist/chains.d.ts.map +1 -1
- package/dist/constants.d.ts +5 -5
- package/dist/constants.d.ts.map +1 -1
- package/dist/customTokens.d.ts +12 -0
- package/dist/customTokens.d.ts.map +1 -0
- package/dist/decoders.d.ts +2 -2
- package/dist/decoders.d.ts.map +1 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/fees.d.ts +37 -2
- package/dist/fees.d.ts.map +1 -1
- package/dist/gasless.d.ts +15 -36
- package/dist/gasless.d.ts.map +1 -1
- package/dist/{index-w7_dK4c5.js → index-BbajxCG_.js} +59269 -77146
- package/dist/index.d.ts +8 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +828 -359
- package/dist/indexerClient.d.ts.map +1 -1
- package/dist/intentReceiptMonitor.d.ts +1 -1
- package/dist/intentReceiptMonitor.d.ts.map +1 -1
- package/dist/intentReceiptPoller.d.ts +1 -1
- package/dist/intentReceiptPoller.d.ts.map +1 -1
- package/dist/intents.d.ts +3 -2
- package/dist/intents.d.ts.map +1 -1
- package/dist/mode.d.ts +1 -1
- package/dist/mode.d.ts.map +1 -1
- package/dist/mutations.d.ts +2 -2
- package/dist/mutations.d.ts.map +1 -1
- package/dist/prepareSend.d.ts +2 -2
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/prices.d.ts +1 -1
- package/dist/prices.d.ts.map +1 -1
- package/dist/sequenceWallet.d.ts +2 -2
- package/dist/sequenceWallet.d.ts.map +1 -1
- package/dist/time.d.ts +6 -0
- package/dist/time.d.ts.map +1 -1
- package/dist/tokenBalances.d.ts +40 -25
- package/dist/tokenBalances.d.ts.map +1 -1
- package/dist/tokens.d.ts +54 -14
- package/dist/tokens.d.ts.map +1 -1
- package/dist/trailsClient.d.ts +1 -1
- package/dist/trailsClient.d.ts.map +1 -1
- package/dist/trailsRouter.d.ts +2 -1
- package/dist/trailsRouter.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts +3 -2
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/gaslessDeposit.d.ts +2 -1
- package/dist/transactionIntent/deposits/gaslessDeposit.d.ts.map +1 -1
- package/dist/transactionIntent/execution/transactionState.d.ts +1 -1
- package/dist/transactionIntent/execution/transactionState.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/crossChain.d.ts +5 -3
- package/dist/transactionIntent/handlers/crossChain.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts +5 -3
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts.map +1 -1
- package/dist/transactionIntent/quote/feeExtractors.d.ts +1 -6
- package/dist/transactionIntent/quote/feeExtractors.d.ts.map +1 -1
- package/dist/transactionIntent/quote/normalizeQuote.d.ts +4 -2
- package/dist/transactionIntent/quote/normalizeQuote.d.ts.map +1 -1
- package/dist/transactionIntent/quote/quoteHelpers.d.ts +1 -1
- package/dist/transactionIntent/quote/quoteHelpers.d.ts.map +1 -1
- package/dist/transactionIntent/types.d.ts +28 -5
- package/dist/transactionIntent/types.d.ts.map +1 -1
- package/dist/transactionIntent/utils/testnetHelpers.d.ts +0 -1
- package/dist/transactionIntent/utils/testnetHelpers.d.ts.map +1 -1
- package/dist/transactionIntent/validators.d.ts +0 -2
- package/dist/transactionIntent/validators.d.ts.map +1 -1
- package/dist/transactions.d.ts +2 -2
- package/dist/transactions.d.ts.map +1 -1
- package/dist/utils.d.ts +7 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/wallets.d.ts +1 -0
- package/dist/wallets.d.ts.map +1 -1
- package/dist/widget/components/AccountIntentTransactionHistory.d.ts.map +1 -1
- package/dist/widget/components/AddressWalletIcon.d.ts +6 -0
- package/dist/widget/components/AddressWalletIcon.d.ts.map +1 -0
- package/dist/widget/components/ChainFilterDropdown.d.ts +2 -6
- package/dist/widget/components/ChainFilterDropdown.d.ts.map +1 -1
- package/dist/widget/components/ChainImage.d.ts.map +1 -1
- package/dist/widget/components/ChainList.d.ts +0 -5
- package/dist/widget/components/ChainList.d.ts.map +1 -1
- package/dist/widget/components/ClassicSwap.d.ts +6 -6
- package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
- package/dist/widget/components/ConnectWallet.d.ts.map +1 -1
- package/dist/widget/components/ConnectedWallets.d.ts.map +1 -1
- package/dist/widget/components/DebugMenu.d.ts +1 -1
- package/dist/widget/components/DebugMenu.d.ts.map +1 -1
- package/dist/widget/components/DebugScreensList.d.ts.map +1 -1
- package/dist/widget/components/DepositTracker.d.ts.map +1 -1
- package/dist/widget/components/Earn.d.ts +5 -5
- package/dist/widget/components/Earn.d.ts.map +1 -1
- package/dist/widget/components/FeeOption.d.ts +1 -1
- package/dist/widget/components/FeeOption.d.ts.map +1 -1
- package/dist/widget/components/FeeOptions.d.ts +2 -2
- package/dist/widget/components/FeeOptions.d.ts.map +1 -1
- package/dist/widget/components/Footer.d.ts +1 -1
- package/dist/widget/components/Footer.d.ts.map +1 -1
- package/dist/widget/components/Fund.d.ts +5 -5
- package/dist/widget/components/Fund.d.ts.map +1 -1
- package/dist/widget/components/FundMethods.d.ts +0 -1
- package/dist/widget/components/FundMethods.d.ts.map +1 -1
- package/dist/widget/components/FundSwap.d.ts +6 -6
- package/dist/widget/components/FundSwap.d.ts.map +1 -1
- package/dist/widget/components/HookModalContent.d.ts +8 -0
- package/dist/widget/components/HookModalContent.d.ts.map +1 -0
- package/dist/widget/components/OriginSelectionAmount.d.ts +11 -0
- package/dist/widget/components/OriginSelectionAmount.d.ts.map +1 -0
- package/dist/widget/components/Pay.d.ts +5 -5
- package/dist/widget/components/Pay.d.ts.map +1 -1
- package/dist/widget/components/PoolDeposit.d.ts +5 -5
- package/dist/widget/components/PoolDeposit.d.ts.map +1 -1
- package/dist/widget/components/PoolWithdraw.d.ts +3 -3
- package/dist/widget/components/PoolWithdraw.d.ts.map +1 -1
- package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
- package/dist/widget/components/Receipt.d.ts +2 -1
- package/dist/widget/components/Receipt.d.ts.map +1 -1
- package/dist/widget/components/RecentTokens.d.ts +4 -4
- package/dist/widget/components/RecentTokens.d.ts.map +1 -1
- package/dist/widget/components/RecipientSelectorButton.d.ts.map +1 -1
- package/dist/widget/components/ShadowPortal.d.ts +6 -0
- package/dist/widget/components/ShadowPortal.d.ts.map +1 -0
- package/dist/widget/components/Swap.d.ts +6 -6
- package/dist/widget/components/Swap.d.ts.map +1 -1
- package/dist/widget/components/ThemeProvider.d.ts +1 -1
- package/dist/widget/components/ThemeProvider.d.ts.map +1 -1
- package/dist/widget/components/TokenList.d.ts +3 -4
- package/dist/widget/components/TokenList.d.ts.map +1 -1
- package/dist/widget/components/TokenSelector.d.ts +3 -4
- package/dist/widget/components/TokenSelector.d.ts.map +1 -1
- package/dist/widget/components/Tooltip.d.ts +6 -1
- package/dist/widget/components/Tooltip.d.ts.map +1 -1
- package/dist/widget/components/TrailsHookModal.d.ts +10 -0
- package/dist/widget/components/TrailsHookModal.d.ts.map +1 -0
- package/dist/widget/components/WaasFeeOptions.d.ts +3 -0
- package/dist/widget/components/WaasFeeOptions.d.ts.map +1 -1
- package/dist/widget/components/WalletConfirmation.d.ts.map +1 -1
- package/dist/widget/components/WalletConnect.d.ts.map +1 -1
- package/dist/widget/components/WidgetProviders.d.ts +14 -0
- package/dist/widget/components/WidgetProviders.d.ts.map +1 -0
- package/dist/widget/css/compiled.css +1 -1
- package/dist/widget/hooks/useAddressWalletIcon.d.ts +10 -0
- package/dist/widget/hooks/useAddressWalletIcon.d.ts.map +1 -0
- package/dist/widget/hooks/useBalanceVisible.d.ts +1 -1
- package/dist/widget/hooks/useBalanceVisible.d.ts.map +1 -1
- package/dist/widget/hooks/useChainFilter.d.ts +1 -1
- package/dist/widget/hooks/useChainFilter.d.ts.map +1 -1
- package/dist/widget/hooks/useCheckout.d.ts +13 -1
- package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
- package/dist/widget/hooks/useConnector.d.ts +4 -0
- package/dist/widget/hooks/useConnector.d.ts.map +1 -0
- package/dist/widget/hooks/useCurrentScreen.d.ts +1 -1
- package/dist/widget/hooks/useCurrentScreen.d.ts.map +1 -1
- package/dist/widget/hooks/useCustomTokenFetch.d.ts +19 -0
- package/dist/widget/hooks/useCustomTokenFetch.d.ts.map +1 -0
- package/dist/widget/hooks/useCustomTokenSearch.d.ts +20 -0
- package/dist/widget/hooks/useCustomTokenSearch.d.ts.map +1 -0
- package/dist/widget/hooks/useDebounce.d.ts +10 -0
- package/dist/widget/hooks/useDebounce.d.ts.map +1 -0
- package/dist/widget/hooks/useDebugScreens.d.ts +7 -2
- package/dist/widget/hooks/useDebugScreens.d.ts.map +1 -1
- package/dist/widget/hooks/useDefaultTokenSelection.d.ts +3 -19
- package/dist/widget/hooks/useDefaultTokenSelection.d.ts.map +1 -1
- package/dist/widget/hooks/useDestinationSelectedToken.d.ts +1 -14
- package/dist/widget/hooks/useDestinationSelectedToken.d.ts.map +1 -1
- package/dist/widget/hooks/useEarnPool.d.ts +1 -1
- package/dist/widget/hooks/useEarnPool.d.ts.map +1 -1
- package/dist/widget/hooks/useIntentTransactionHistory.d.ts.map +1 -1
- package/dist/widget/hooks/useIsMobile.d.ts +5 -0
- package/dist/widget/hooks/useIsMobile.d.ts.map +1 -0
- package/dist/widget/hooks/useMode.d.ts +2 -2
- package/dist/widget/hooks/useMode.d.ts.map +1 -1
- package/dist/widget/hooks/useOriginSelectedToken.d.ts +2 -15
- package/dist/widget/hooks/useOriginSelectedToken.d.ts.map +1 -1
- package/dist/widget/hooks/usePayMessage.d.ts.map +1 -1
- package/dist/widget/hooks/usePriceImpactWarning.d.ts +1 -1
- package/dist/widget/hooks/usePriceImpactWarning.d.ts.map +1 -1
- package/dist/widget/hooks/useQuote.d.ts +173 -4
- package/dist/widget/hooks/useQuote.d.ts.map +1 -1
- package/dist/widget/hooks/useRecentTokens.d.ts +3 -3
- package/dist/widget/hooks/useRecentTokens.d.ts.map +1 -1
- package/dist/widget/hooks/useRecipients.d.ts +1 -1
- package/dist/widget/hooks/useRecipients.d.ts.map +1 -1
- package/dist/widget/hooks/useSelectedFeeOption.d.ts +2 -2
- package/dist/widget/hooks/useSelectedFeeOption.d.ts.map +1 -1
- package/dist/widget/hooks/useSelectedFundMethod.d.ts +1 -1
- package/dist/widget/hooks/useSelectedFundMethod.d.ts.map +1 -1
- package/dist/widget/hooks/useSelectedRecipient.d.ts +1 -1
- package/dist/widget/hooks/useSelectedRecipient.d.ts.map +1 -1
- package/dist/widget/hooks/useSendForm.d.ts +9 -31
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- package/dist/widget/hooks/useSwapAmount.d.ts +1 -1
- package/dist/widget/hooks/useSwapAmount.d.ts.map +1 -1
- package/dist/widget/hooks/useTheme.d.ts +1 -1
- package/dist/widget/hooks/useTheme.d.ts.map +1 -1
- package/dist/widget/hooks/useTokenList.d.ts +7 -31
- package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
- package/dist/widget/hooks/useTrailsSendTransaction.d.ts +83 -0
- package/dist/widget/hooks/useTrailsSendTransaction.d.ts.map +1 -0
- package/dist/widget/hooks/useWalletConnectUri.d.ts +11 -0
- package/dist/widget/hooks/useWalletConnectUri.d.ts.map +1 -0
- package/dist/widget/hooks/useWidgetProps.d.ts +5 -0
- package/dist/widget/hooks/useWidgetProps.d.ts.map +1 -1
- package/dist/widget/index.d.ts +2 -0
- package/dist/widget/index.d.ts.map +1 -1
- package/dist/widget/index.js +8 -5
- package/dist/widget/providers/TrailsModalProvider.d.ts +65 -0
- package/dist/widget/providers/TrailsModalProvider.d.ts.map +1 -0
- package/dist/widget/providers/TrailsProvider.d.ts +1 -1
- package/dist/widget/providers/TrailsProvider.d.ts.map +1 -1
- package/dist/widget/types.d.ts +11 -18
- package/dist/widget/types.d.ts.map +1 -1
- package/dist/widget/widget.d.ts +20 -11
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +45 -49
- package/src/aave.ts +387 -138
- package/src/analytics.ts +208 -2
- package/src/chains.ts +65 -64
- package/src/constants.ts +18 -14
- package/src/customTokens.ts +151 -0
- package/src/decoders.ts +4 -7
- package/src/error.ts +7 -3
- package/src/fees.ts +239 -125
- package/src/gasless.ts +54 -108
- package/src/index.ts +29 -9
- package/src/indexerClient.ts +2 -0
- package/src/intentReceiptMonitor.ts +1 -4
- package/src/intentReceiptPoller.ts +2 -2
- package/src/intents.ts +16 -5
- package/src/mode.ts +1 -1
- package/src/mutations.ts +7 -3
- package/src/prepareSend.ts +19 -14
- package/src/prices.ts +1 -1
- package/src/sequenceWallet.ts +2 -2
- package/src/time.ts +28 -0
- package/src/tokenBalances.ts +348 -153
- package/src/tokens.ts +393 -142
- package/src/trailsClient.ts +1 -1
- package/src/trailsRouter.ts +4 -5
- package/src/transactionIntent/deposits/depositOrchestrator.ts +6 -2
- package/src/transactionIntent/deposits/gaslessDeposit.ts +13 -7
- package/src/transactionIntent/deposits/standardDeposit.ts +1 -1
- package/src/transactionIntent/execution/transactionState.ts +1 -1
- package/src/transactionIntent/handlers/crossChain.ts +75 -37
- package/src/transactionIntent/handlers/sameChainSameToken.ts +66 -20
- package/src/transactionIntent/quote/feeExtractors.ts +1 -29
- package/src/transactionIntent/quote/normalizeQuote.ts +99 -7
- package/src/transactionIntent/quote/quoteHelpers.ts +1 -1
- package/src/transactionIntent/types.ts +31 -6
- package/src/transactionIntent/utils/testnetHelpers.ts +0 -5
- package/src/transactionIntent/validators.ts +0 -30
- package/src/transactions.ts +3 -3
- package/src/utils.ts +18 -0
- package/src/wallets.ts +32 -10
- package/src/widget/compiled.css +1 -1
- package/src/widget/components/AccountIntentTransactionHistory.tsx +2 -1
- package/src/widget/components/AccountIntentTransactionHistoryButton.tsx +2 -2
- package/src/widget/components/AddressWalletIcon.tsx +29 -0
- package/src/widget/components/ChainFilterDropdown.tsx +2 -8
- package/src/widget/components/ChainImage.tsx +8 -5
- package/src/widget/components/ChainList.tsx +6 -8
- package/src/widget/components/ClassicSwap.tsx +93 -85
- package/src/widget/components/ConnectWallet.tsx +1 -2
- package/src/widget/components/ConnectedWallets.tsx +17 -4
- package/src/widget/components/DebugMenu.tsx +2 -2
- package/src/widget/components/DebugScreensList.tsx +0 -1
- package/src/widget/components/DepositTracker.tsx +20 -34
- package/src/widget/components/Earn.tsx +7 -6
- package/src/widget/components/FeeOption.tsx +4 -4
- package/src/widget/components/FeeOptions.tsx +19 -39
- package/src/widget/components/Footer.tsx +1 -1
- package/src/widget/components/Fund.tsx +23 -119
- package/src/widget/components/FundMethods.tsx +9 -6
- package/src/widget/components/FundSwap.tsx +6 -5
- package/src/widget/components/FundingMethodSelectorButton.tsx +2 -2
- package/src/widget/components/HookModalContent.tsx +306 -0
- package/src/widget/components/Modal.tsx +1 -1
- package/src/widget/components/OriginSelectionAmount.tsx +135 -0
- package/src/widget/components/Pay.tsx +66 -124
- package/src/widget/components/PoolDeposit.tsx +11 -55
- package/src/widget/components/PoolWithdraw.tsx +3 -3
- package/src/widget/components/QuoteDetails.tsx +473 -728
- package/src/widget/components/Receipt.tsx +74 -7
- package/src/widget/components/RecentTokens.tsx +8 -8
- package/src/widget/components/RecipientSelectorButton.tsx +4 -2
- package/src/widget/components/ScreenHeader.tsx +2 -2
- package/src/widget/components/SearchInputField.tsx +1 -1
- package/src/widget/components/ShadowPortal.tsx +58 -0
- package/src/widget/components/Swap.tsx +6 -5
- package/src/widget/components/ThemeProvider.tsx +1 -1
- package/src/widget/components/TokenList.tsx +3 -4
- package/src/widget/components/TokenSelector.tsx +211 -80
- package/src/widget/components/Tooltip.tsx +18 -7
- package/src/widget/components/TrailsHookModal.tsx +118 -0
- package/src/widget/components/WaasFeeOptions.tsx +333 -138
- package/src/widget/components/WalletConfirmation.tsx +7 -2
- package/src/widget/components/WalletConnect.tsx +197 -235
- package/src/widget/components/WidgetProviders.tsx +75 -0
- package/src/widget/hooks/useAddressWalletIcon.ts +53 -0
- package/src/widget/hooks/useBalanceVisible.tsx +1 -1
- package/src/widget/hooks/useChainFilter.tsx +1 -1
- package/src/widget/hooks/useCheckout.ts +13 -1
- package/src/widget/hooks/useConnector.tsx +18 -0
- package/src/widget/hooks/useCurrentScreen.tsx +3 -3
- package/src/widget/hooks/useCustomTokenFetch.tsx +72 -0
- package/src/widget/hooks/useCustomTokenSearch.tsx +402 -0
- package/src/widget/hooks/useDebounce.ts +25 -0
- package/src/widget/hooks/useDebugScreens.ts +26 -10
- package/src/widget/hooks/useDefaultTokenSelection.tsx +99 -143
- package/src/widget/hooks/useDestinationSelectedToken.tsx +1 -14
- package/src/widget/hooks/useEarnPool.tsx +1 -1
- package/src/widget/hooks/useIntentTransactionHistory.ts +20 -11
- package/src/widget/hooks/useIsMobile.tsx +50 -0
- package/src/widget/hooks/useMode.ts +2 -3
- package/src/widget/hooks/useOriginSelectedToken.tsx +2 -15
- package/src/widget/hooks/usePayMessage.tsx +31 -11
- package/src/widget/hooks/usePriceImpactWarning.ts +1 -1
- package/src/widget/hooks/useQuote.ts +189 -6
- package/src/widget/hooks/useRecentTokens.ts +6 -6
- package/src/widget/hooks/useRecipients.ts +1 -1
- package/src/widget/hooks/useSelectedFeeOption.tsx +2 -2
- package/src/widget/hooks/useSelectedFundMethod.tsx +1 -1
- package/src/widget/hooks/useSelectedRecipient.tsx +1 -1
- package/src/widget/hooks/useSendForm.ts +328 -152
- package/src/widget/hooks/useSwapAmount.tsx +1 -1
- package/src/widget/hooks/useTheme.tsx +1 -1
- package/src/widget/hooks/useTokenList.ts +672 -400
- package/src/widget/hooks/useTrailsSendTransaction.ts +949 -0
- package/src/widget/hooks/useWalletConnectUri.tsx +228 -0
- package/src/widget/hooks/useWidgetProps.tsx +3 -1
- package/src/widget/index.tsx +12 -0
- package/src/widget/providers/TrailsModalProvider.tsx +195 -0
- package/src/widget/providers/TrailsProvider.tsx +9 -3
- package/src/widget/types.ts +12 -20
- package/src/widget/widget.tsx +598 -385
- package/dist/cctp.d.ts +0 -3
- package/dist/cctp.d.ts.map +0 -1
- package/dist/lifi.d.ts +0 -4
- package/dist/lifi.d.ts.map +0 -1
- package/dist/meshconnect.d.ts +0 -171
- package/dist/meshconnect.d.ts.map +0 -1
- package/dist/relaySdk.d.ts +0 -87
- package/dist/relaySdk.d.ts.map +0 -1
- package/dist/widget/components/MeshConnectExchanges.d.ts +0 -7
- package/dist/widget/components/MeshConnectExchanges.d.ts.map +0 -1
- package/dist/widget/components/MeshConnectFlow.d.ts +0 -13
- package/dist/widget/components/MeshConnectFlow.d.ts.map +0 -1
- package/dist/widget/components/MeshConnectIframe.d.ts +0 -15
- package/dist/widget/components/MeshConnectIframe.d.ts.map +0 -1
- package/dist/widget/components/Receive.d.ts +0 -12
- package/dist/widget/components/Receive.d.ts.map +0 -1
- package/dist/widget/hooks/useSelectedMeshExchange.d.ts +0 -14
- package/dist/widget/hooks/useSelectedMeshExchange.d.ts.map +0 -1
- package/src/cctp.ts +0 -54
- package/src/lifi.ts +0 -108
- package/src/meshconnect.ts +0 -531
- package/src/relaySdk.ts +0 -703
- package/src/widget/components/MeshConnectExchanges.tsx +0 -290
- package/src/widget/components/MeshConnectFlow.tsx +0 -90
- package/src/widget/components/MeshConnectIframe.tsx +0 -500
- package/src/widget/components/Receive.tsx +0 -175
- package/src/widget/hooks/useSelectedMeshExchange.tsx +0 -46
|
@@ -1,29 +1,30 @@
|
|
|
1
|
-
import { ChevronLeft, Copy } from "lucide-react"
|
|
1
|
+
import { ChevronLeft, Copy, AlertTriangle, Info } from "lucide-react"
|
|
2
2
|
import type React from "react"
|
|
3
3
|
import { useState, useMemo } from "react"
|
|
4
4
|
import { AnimatePresence, motion } from "motion/react"
|
|
5
5
|
import { zeroAddress } from "viem"
|
|
6
|
-
import type { Token, TokenFormatted } from "../hooks/useTokenList.js"
|
|
7
6
|
import { useTokenList } from "../hooks/useTokenList.js"
|
|
8
7
|
import { useChainFilter } from "../hooks/useChainFilter.js"
|
|
9
8
|
import { useBalanceVisible } from "../hooks/useBalanceVisible.js"
|
|
10
9
|
import { TokenImage } from "./TokenImage.js"
|
|
11
|
-
import type {
|
|
10
|
+
import type { Token } from "../../tokens.js"
|
|
12
11
|
import { RecentTokens } from "./RecentTokens.js"
|
|
13
12
|
import { getChainInfo } from "../../chains.js"
|
|
14
13
|
import { ChainFilterDropdown } from "./ChainFilterDropdown.js"
|
|
15
14
|
import { SearchInputField } from "./SearchInputField.js"
|
|
16
|
-
import { truncateAddress } from "../../utils.js"
|
|
15
|
+
import { truncateAddress, isValueZero } from "../../utils.js"
|
|
17
16
|
import { logger } from "../../logger.js"
|
|
18
17
|
import { useAccount } from "wagmi"
|
|
18
|
+
import { useCustomTokenSearch } from "../hooks/useCustomTokenSearch.js"
|
|
19
|
+
import { Tooltip } from "./Tooltip.js"
|
|
19
20
|
|
|
20
21
|
interface TokenSelectorProps {
|
|
21
22
|
onTokenSelect: (selectedToken: Token) => void
|
|
22
23
|
targetAmountUsd?: number | null
|
|
23
24
|
targetAmountUsdFormatted?: string | null
|
|
24
25
|
onError: (error: Error | string | null) => void
|
|
25
|
-
recentTokens?:
|
|
26
|
-
onRecentTokenSelect?: (token:
|
|
26
|
+
recentTokens?: Token[]
|
|
27
|
+
onRecentTokenSelect?: (token: Token) => void
|
|
27
28
|
fundMethod?: string | null
|
|
28
29
|
onNavigateToFundMethods?: () => void
|
|
29
30
|
showContinueButton?: boolean
|
|
@@ -65,6 +66,7 @@ export const TokenSelector: React.FC<TokenSelectorProps> = ({
|
|
|
65
66
|
handleTokenSelect,
|
|
66
67
|
filteredTokens,
|
|
67
68
|
isLoadingTokens,
|
|
69
|
+
isSearching,
|
|
68
70
|
isTokenSelected,
|
|
69
71
|
filteredTokensFormatted,
|
|
70
72
|
balanceError,
|
|
@@ -81,20 +83,22 @@ export const TokenSelector: React.FC<TokenSelectorProps> = ({
|
|
|
81
83
|
setSelectedChainId: setFilterByChainId,
|
|
82
84
|
} = useChainFilter()
|
|
83
85
|
|
|
84
|
-
//
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
86
|
+
// Handle custom token search and integration
|
|
87
|
+
const {
|
|
88
|
+
chainFilteredTokens,
|
|
89
|
+
isLoadingCustomToken,
|
|
90
|
+
customTokenError,
|
|
91
|
+
fetchChainId,
|
|
92
|
+
} = useCustomTokenSearch({
|
|
93
|
+
searchQuery,
|
|
94
|
+
filteredTokensFormatted,
|
|
95
|
+
filterByChainId,
|
|
96
|
+
})
|
|
93
97
|
|
|
94
98
|
// Get unique chains from all tokens (not filtered by chain)
|
|
95
99
|
const uniqueChains = useMemo(() => {
|
|
96
100
|
const chainIds = new Set(
|
|
97
|
-
filteredTokensFormatted.map((token) => token.chainId),
|
|
101
|
+
filteredTokensFormatted.map((token) => token.chainId || 0),
|
|
98
102
|
)
|
|
99
103
|
return Array.from(chainIds)
|
|
100
104
|
.map((chainId) => {
|
|
@@ -115,7 +119,7 @@ export const TokenSelector: React.FC<TokenSelectorProps> = ({
|
|
|
115
119
|
(token) =>
|
|
116
120
|
token.contractAddress.toLowerCase() ===
|
|
117
121
|
recentToken.contractAddress.toLowerCase() &&
|
|
118
|
-
token.chainId === recentToken.chainId,
|
|
122
|
+
(token.chainId || 0) === (recentToken.chainId || 0),
|
|
119
123
|
)
|
|
120
124
|
|
|
121
125
|
if (!existsInTokenList) return false
|
|
@@ -145,7 +149,7 @@ export const TokenSelector: React.FC<TokenSelectorProps> = ({
|
|
|
145
149
|
}
|
|
146
150
|
|
|
147
151
|
// Enhanced token select handler that resets chain filter
|
|
148
|
-
const handleTokenSelectWithReset = (token:
|
|
152
|
+
const handleTokenSelectWithReset = (token: Token) => {
|
|
149
153
|
// Reset chain filter after token selection
|
|
150
154
|
setFilterByChainId(null)
|
|
151
155
|
// Call the original handler
|
|
@@ -153,13 +157,13 @@ export const TokenSelector: React.FC<TokenSelectorProps> = ({
|
|
|
153
157
|
}
|
|
154
158
|
|
|
155
159
|
// Handle recent token selection by finding the actual token from the list
|
|
156
|
-
const handleRecentTokenSelect = (recentToken:
|
|
160
|
+
const handleRecentTokenSelect = (recentToken: Token) => {
|
|
157
161
|
// Find the actual token from the filtered tokens list
|
|
158
162
|
const actualToken = chainFilteredTokens.find(
|
|
159
163
|
(token) =>
|
|
160
164
|
token.contractAddress.toLowerCase() ===
|
|
161
165
|
recentToken.contractAddress.toLowerCase() &&
|
|
162
|
-
token.chainId === recentToken.chainId,
|
|
166
|
+
(token.chainId || 0) === (recentToken.chainId || 0),
|
|
163
167
|
)
|
|
164
168
|
|
|
165
169
|
if (actualToken) {
|
|
@@ -172,13 +176,44 @@ export const TokenSelector: React.FC<TokenSelectorProps> = ({
|
|
|
172
176
|
}
|
|
173
177
|
}
|
|
174
178
|
|
|
179
|
+
// Determine the error message to display
|
|
180
|
+
const errorMessage = useMemo(() => {
|
|
181
|
+
// Custom token error with chain info
|
|
182
|
+
if (
|
|
183
|
+
customTokenError &&
|
|
184
|
+
fetchChainId &&
|
|
185
|
+
searchQuery.trim().startsWith("0x")
|
|
186
|
+
) {
|
|
187
|
+
const chainInfo = getChainInfo(fetchChainId)
|
|
188
|
+
const networkName = chainInfo?.name || `Chain ${fetchChainId}`
|
|
189
|
+
return `Token not found on ${networkName}.`
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Search query provided but no results
|
|
193
|
+
if (searchQuery.trim()) {
|
|
194
|
+
return "No tokens found matching your search."
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Fund method doesn't require error message
|
|
198
|
+
if (fundMethod === "qr-code" || fundMethod === "exchange") {
|
|
199
|
+
return ""
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Address connected but no tokens available
|
|
203
|
+
if (address) {
|
|
204
|
+
return "No available tokens found"
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return ""
|
|
208
|
+
}, [customTokenError, fetchChainId, searchQuery, fundMethod, address])
|
|
209
|
+
|
|
175
210
|
return (
|
|
176
211
|
<div className="space-y-2">
|
|
177
212
|
{/* Search Field */}
|
|
178
213
|
<SearchInputField
|
|
179
214
|
value={searchQuery}
|
|
180
215
|
onChange={setSearchQuery}
|
|
181
|
-
placeholder="Search tokens"
|
|
216
|
+
placeholder="Search tokens, symbol, address"
|
|
182
217
|
autoFocus={true}
|
|
183
218
|
className="mb-2"
|
|
184
219
|
rightAlignedComponent={
|
|
@@ -211,48 +246,71 @@ export const TokenSelector: React.FC<TokenSelectorProps> = ({
|
|
|
211
246
|
)}
|
|
212
247
|
</AnimatePresence>
|
|
213
248
|
|
|
214
|
-
{
|
|
249
|
+
{/* Show full spinner only for initial load (when no tokens are available yet) */}
|
|
250
|
+
{((isLoadingTokens && chainFilteredTokens.length === 0) ||
|
|
251
|
+
isLoadingCustomToken) && (
|
|
215
252
|
<div className="text-center py-4">
|
|
216
253
|
<div className="animate-spin rounded-full h-8 w-8 border-b-2 mx-auto border-solid border-black dark:border-white"></div>
|
|
217
254
|
<p className="mt-2 text-gray-500 dark:text-gray-400">
|
|
218
|
-
|
|
255
|
+
{isLoadingCustomToken
|
|
256
|
+
? "Fetching token information..."
|
|
257
|
+
: "Loading your token balances..."}
|
|
219
258
|
</p>
|
|
220
259
|
</div>
|
|
221
260
|
)}
|
|
222
261
|
|
|
223
|
-
{
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
? ""
|
|
230
|
-
: address
|
|
231
|
-
? "No available tokens found"
|
|
232
|
-
: ""}
|
|
262
|
+
{/* Subtle search indicator when searching with existing tokens */}
|
|
263
|
+
{isSearching && chainFilteredTokens.length > 0 && (
|
|
264
|
+
<div className="flex items-center justify-center gap-2 py-2">
|
|
265
|
+
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-solid border-gray-400 dark:border-gray-500"></div>
|
|
266
|
+
<p className="text-xs text-gray-500 dark:text-gray-400">
|
|
267
|
+
Searching...
|
|
233
268
|
</p>
|
|
234
269
|
</div>
|
|
235
270
|
)}
|
|
236
271
|
|
|
272
|
+
{!isLoadingTokens &&
|
|
273
|
+
!isLoadingCustomToken &&
|
|
274
|
+
!balanceError &&
|
|
275
|
+
filteredTokens.length === 0 &&
|
|
276
|
+
chainFilteredTokens.length === 0 &&
|
|
277
|
+
errorMessage && (
|
|
278
|
+
<div className="text-center py-4 rounded-lg trails-bg-secondary">
|
|
279
|
+
<p className="text-gray-500 dark:text-gray-400">{errorMessage}</p>
|
|
280
|
+
</div>
|
|
281
|
+
)}
|
|
282
|
+
|
|
237
283
|
{/* Token List */}
|
|
238
284
|
{chainFilteredTokens.length > 0 && (
|
|
239
285
|
<div
|
|
240
286
|
className={`${compactMode ? "max-h-48" : filteredRecentTokens.length > 0 ? "max-h-[200px]" : "max-h-[250px]"} overflow-y-auto trails-scrollbar space-y-1`}
|
|
241
287
|
>
|
|
242
288
|
<AnimatePresence mode="popLayout">
|
|
243
|
-
{chainFilteredTokens.map((token:
|
|
289
|
+
{chainFilteredTokens.map((token: Token) => {
|
|
244
290
|
const {
|
|
245
291
|
symbol,
|
|
246
292
|
imageUrl,
|
|
247
293
|
chainId,
|
|
248
294
|
contractAddress,
|
|
249
295
|
balanceUsdFormatted,
|
|
250
|
-
|
|
296
|
+
balanceUsdDisplay,
|
|
297
|
+
name,
|
|
251
298
|
priceUsd,
|
|
252
299
|
balanceFormatted,
|
|
300
|
+
balance,
|
|
301
|
+
balanceUsd,
|
|
253
302
|
isSufficientBalance,
|
|
254
303
|
} = token
|
|
255
304
|
|
|
305
|
+
// Check if balance should be shown (hide if balance is 0 or empty)
|
|
306
|
+
const hasBalance =
|
|
307
|
+
!isValueZero(balance) ||
|
|
308
|
+
!isValueZero(balanceFormatted) ||
|
|
309
|
+
!isValueZero(balanceUsd) ||
|
|
310
|
+
!isValueZero(balanceUsdFormatted)
|
|
311
|
+
// Default isSufficientBalance to true if not set
|
|
312
|
+
const sufficientBalance = isSufficientBalance ?? true
|
|
313
|
+
|
|
256
314
|
return (
|
|
257
315
|
<motion.div
|
|
258
316
|
key={`${chainId}-${contractAddress}`}
|
|
@@ -273,22 +331,22 @@ export const TokenSelector: React.FC<TokenSelectorProps> = ({
|
|
|
273
331
|
}
|
|
274
332
|
}}
|
|
275
333
|
tabIndex={0}
|
|
276
|
-
aria-label={`Select ${
|
|
334
|
+
aria-label={`Select ${name} token`}
|
|
277
335
|
title={
|
|
278
|
-
!
|
|
336
|
+
!sufficientBalance &&
|
|
279
337
|
fundMethod !== "qr-code" &&
|
|
280
338
|
fundMethod !== "exchange"
|
|
281
339
|
? "Insufficient balance for this token"
|
|
282
|
-
: `Select ${
|
|
340
|
+
: `Select ${name} token`
|
|
283
341
|
}
|
|
284
342
|
className={`w-full py-2 px-4 flex items-center space-x-3 transition-all duration-200 trails-list-item trails-border-radius-list-button ${
|
|
285
343
|
isTokenSelected(token) ? "trails-list-item-selected" : ""
|
|
286
|
-
} ${!
|
|
344
|
+
} ${!sufficientBalance && fundMethod !== "qr-code" && fundMethod !== "exchange" ? "opacity-75 cursor-not-allowed" : "cursor-pointer"}`}
|
|
287
345
|
>
|
|
288
346
|
<div className="relative flex-shrink-0 mr-2">
|
|
289
347
|
<div
|
|
290
348
|
className={`rounded-full flex items-center justify-center bg-gray-100 dark:bg-gray-700 ${
|
|
291
|
-
!
|
|
349
|
+
!sufficientBalance &&
|
|
292
350
|
fundMethod !== "qr-code" &&
|
|
293
351
|
fundMethod !== "exchange"
|
|
294
352
|
? "opacity-80"
|
|
@@ -306,7 +364,7 @@ export const TokenSelector: React.FC<TokenSelectorProps> = ({
|
|
|
306
364
|
) : (
|
|
307
365
|
<span
|
|
308
366
|
className={`text-base font-medium text-gray-600 dark:text-gray-300 ${
|
|
309
|
-
!
|
|
367
|
+
!sufficientBalance &&
|
|
310
368
|
fundMethod !== "qr-code" &&
|
|
311
369
|
fundMethod !== "exchange"
|
|
312
370
|
? "opacity-70"
|
|
@@ -322,19 +380,19 @@ export const TokenSelector: React.FC<TokenSelectorProps> = ({
|
|
|
322
380
|
<div className="flex-1 min-w-0 text-left">
|
|
323
381
|
<h3
|
|
324
382
|
className={`text-sm font-medium truncate text-gray-900 dark:text-white ${
|
|
325
|
-
!
|
|
383
|
+
!sufficientBalance &&
|
|
326
384
|
fundMethod !== "qr-code" &&
|
|
327
385
|
fundMethod !== "exchange"
|
|
328
386
|
? "opacity-70"
|
|
329
387
|
: ""
|
|
330
388
|
}`}
|
|
331
389
|
>
|
|
332
|
-
{
|
|
390
|
+
{name}
|
|
333
391
|
</h3>
|
|
334
|
-
<div className="group relative
|
|
392
|
+
<div className="group relative w-full">
|
|
335
393
|
{/* Default state: show symbol */}
|
|
336
394
|
<div
|
|
337
|
-
className={`flex items-center transition-all duration-300 ease-in-out ${
|
|
395
|
+
className={`flex items-center gap-1.5 transition-all duration-300 ease-in-out ${
|
|
338
396
|
contractAddress &&
|
|
339
397
|
contractAddress.toLowerCase() !==
|
|
340
398
|
zeroAddress.toLowerCase()
|
|
@@ -351,6 +409,16 @@ export const TokenSelector: React.FC<TokenSelectorProps> = ({
|
|
|
351
409
|
<span className="text-xs text-gray-500 dark:text-gray-400 whitespace-nowrap">
|
|
352
410
|
{symbol}
|
|
353
411
|
</span>
|
|
412
|
+
{/* Custom token indicator */}
|
|
413
|
+
{token.isCustomToken && (
|
|
414
|
+
<div className="relative group/indicator">
|
|
415
|
+
<AlertTriangle className="w-3 h-3 text-gray-500 dark:text-gray-400" />
|
|
416
|
+
<div className="absolute bottom-full left-1/2 -translate-x-1/2 mb-1 px-2 py-1 text-xs text-white bg-gray-900 dark:bg-gray-700 rounded whitespace-nowrap opacity-0 group-hover/indicator:opacity-100 transition-opacity pointer-events-none z-50">
|
|
417
|
+
Custom token added by user
|
|
418
|
+
<div className="absolute top-full left-1/2 -translate-x-1/2 -mt-px border-4 border-transparent border-t-gray-900 dark:border-t-gray-700"></div>
|
|
419
|
+
</div>
|
|
420
|
+
</div>
|
|
421
|
+
)}
|
|
354
422
|
</div>
|
|
355
423
|
|
|
356
424
|
{/* Hover state: show address with copy button (only for non-zero addresses) */}
|
|
@@ -358,8 +426,8 @@ export const TokenSelector: React.FC<TokenSelectorProps> = ({
|
|
|
358
426
|
contractAddress.toLowerCase() !==
|
|
359
427
|
zeroAddress.toLowerCase() && (
|
|
360
428
|
<div
|
|
361
|
-
className={`absolute top-0 left-0 flex items-center transition-all duration-300 ease-in-out opacity-0 transform translate-x-2 ${
|
|
362
|
-
!
|
|
429
|
+
className={`absolute top-0 left-0 flex items-center gap-1.5 transition-all duration-300 ease-in-out opacity-0 transform translate-x-2 ${
|
|
430
|
+
!sufficientBalance &&
|
|
363
431
|
fundMethod !== "qr-code" &&
|
|
364
432
|
fundMethod !== "exchange"
|
|
365
433
|
? "group-hover:opacity-70"
|
|
@@ -374,7 +442,7 @@ export const TokenSelector: React.FC<TokenSelectorProps> = ({
|
|
|
374
442
|
onClick={(e) =>
|
|
375
443
|
handleCopyAddress(contractAddress, e)
|
|
376
444
|
}
|
|
377
|
-
className={`
|
|
445
|
+
className={`p-0.5 rounded transition-all duration-200 cursor-pointer ${
|
|
378
446
|
copiedAddress === contractAddress
|
|
379
447
|
? "bg-green-100 dark:bg-green-900/30"
|
|
380
448
|
: "hover:bg-gray-200 dark:hover:bg-gray-600"
|
|
@@ -405,29 +473,105 @@ export const TokenSelector: React.FC<TokenSelectorProps> = ({
|
|
|
405
473
|
<Copy className="w-3 h-3 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300" />
|
|
406
474
|
)}
|
|
407
475
|
</button>
|
|
476
|
+
{/* Token info tooltip */}
|
|
477
|
+
<Tooltip
|
|
478
|
+
content={
|
|
479
|
+
<div className="space-y-2 text-left">
|
|
480
|
+
<div>
|
|
481
|
+
<span className="opacity-70">Symbol:</span>{" "}
|
|
482
|
+
<span className="font-medium">
|
|
483
|
+
{token.symbol}
|
|
484
|
+
</span>
|
|
485
|
+
</div>
|
|
486
|
+
<div>
|
|
487
|
+
<span className="opacity-70">Name:</span>{" "}
|
|
488
|
+
<span className="font-medium">
|
|
489
|
+
{token.name}
|
|
490
|
+
</span>
|
|
491
|
+
</div>
|
|
492
|
+
<div>
|
|
493
|
+
<span className="opacity-70">Chain:</span>{" "}
|
|
494
|
+
<span className="font-medium">
|
|
495
|
+
{token.chainName ||
|
|
496
|
+
getChainInfo(token.chainId || 0)
|
|
497
|
+
?.name ||
|
|
498
|
+
`Chain ${token.chainId || 0}`}
|
|
499
|
+
</span>
|
|
500
|
+
</div>
|
|
501
|
+
<div>
|
|
502
|
+
<span className="opacity-70">
|
|
503
|
+
Decimals:
|
|
504
|
+
</span>{" "}
|
|
505
|
+
<span className="font-medium">
|
|
506
|
+
{token.decimals}
|
|
507
|
+
</span>
|
|
508
|
+
</div>
|
|
509
|
+
<div>
|
|
510
|
+
<span className="opacity-70">Address:</span>{" "}
|
|
511
|
+
<span className="font-mono text-[10px] break-all block mt-0.5">
|
|
512
|
+
{contractAddress}
|
|
513
|
+
</span>
|
|
514
|
+
</div>
|
|
515
|
+
</div>
|
|
516
|
+
}
|
|
517
|
+
side="top"
|
|
518
|
+
align="center"
|
|
519
|
+
sideOffset={8}
|
|
520
|
+
>
|
|
521
|
+
<Info className="w-3 h-3 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 cursor-pointer" />
|
|
522
|
+
</Tooltip>
|
|
523
|
+
{/* Custom token indicator on hover state */}
|
|
524
|
+
{token.isCustomToken && (
|
|
525
|
+
<div className="relative group/indicator">
|
|
526
|
+
<AlertTriangle className="w-3 h-3 text-gray-500 dark:text-gray-400" />
|
|
527
|
+
<div className="absolute bottom-full left-1/2 -translate-x-1/2 mb-1 px-2 py-1 text-xs text-white bg-gray-900 dark:bg-gray-700 rounded whitespace-nowrap opacity-0 group-hover/indicator:opacity-100 transition-opacity pointer-events-none z-50">
|
|
528
|
+
Custom token added by user
|
|
529
|
+
<div className="absolute top-full left-1/2 -translate-x-1/2 -mt-px border-4 border-transparent border-t-gray-900 dark:border-t-gray-700"></div>
|
|
530
|
+
</div>
|
|
531
|
+
</div>
|
|
532
|
+
)}
|
|
408
533
|
</div>
|
|
409
534
|
)}
|
|
410
535
|
</div>
|
|
411
536
|
</div>
|
|
412
537
|
|
|
413
|
-
{fundMethod !== "qr-code" &&
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
538
|
+
{fundMethod !== "qr-code" &&
|
|
539
|
+
fundMethod !== "exchange" &&
|
|
540
|
+
hasBalance && (
|
|
541
|
+
<div className="text-right flex-shrink-0">
|
|
542
|
+
{(priceUsd ?? 0) > 0 ? (
|
|
543
|
+
<>
|
|
544
|
+
<p
|
|
545
|
+
className={`text-sm font-medium text-gray-900 dark:text-white ${
|
|
546
|
+
!sufficientBalance &&
|
|
547
|
+
fundMethod !== "qr-code" &&
|
|
548
|
+
fundMethod !== "exchange"
|
|
549
|
+
? "opacity-70"
|
|
550
|
+
: ""
|
|
551
|
+
}`}
|
|
552
|
+
>
|
|
553
|
+
{isBalanceVisible
|
|
554
|
+
? balanceUsdDisplay ||
|
|
555
|
+
balanceUsdFormatted ||
|
|
556
|
+
"$0.00"
|
|
557
|
+
: "••••••"}
|
|
558
|
+
</p>
|
|
559
|
+
<p
|
|
560
|
+
className={`text-xs text-gray-500 dark:text-gray-400 ${
|
|
561
|
+
!sufficientBalance &&
|
|
562
|
+
fundMethod !== "qr-code" &&
|
|
563
|
+
fundMethod !== "exchange"
|
|
564
|
+
? "opacity-70"
|
|
565
|
+
: ""
|
|
566
|
+
}`}
|
|
567
|
+
>
|
|
568
|
+
{isBalanceVisible ? balanceFormatted : "••••••"}
|
|
569
|
+
</p>
|
|
570
|
+
</>
|
|
571
|
+
) : (
|
|
417
572
|
<p
|
|
418
573
|
className={`text-sm font-medium text-gray-900 dark:text-white ${
|
|
419
|
-
!
|
|
420
|
-
fundMethod !== "qr-code" &&
|
|
421
|
-
fundMethod !== "exchange"
|
|
422
|
-
? "opacity-70"
|
|
423
|
-
: ""
|
|
424
|
-
}`}
|
|
425
|
-
>
|
|
426
|
-
{isBalanceVisible ? balanceUsdFormatted : "••••••"}
|
|
427
|
-
</p>
|
|
428
|
-
<p
|
|
429
|
-
className={`text-xs text-gray-500 dark:text-gray-400 ${
|
|
430
|
-
!isSufficientBalance &&
|
|
574
|
+
!sufficientBalance &&
|
|
431
575
|
fundMethod !== "qr-code" &&
|
|
432
576
|
fundMethod !== "exchange"
|
|
433
577
|
? "opacity-70"
|
|
@@ -436,22 +580,9 @@ export const TokenSelector: React.FC<TokenSelectorProps> = ({
|
|
|
436
580
|
>
|
|
437
581
|
{isBalanceVisible ? balanceFormatted : "••••••"}
|
|
438
582
|
</p>
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
className={`text-sm font-medium text-gray-900 dark:text-white ${
|
|
443
|
-
!isSufficientBalance &&
|
|
444
|
-
fundMethod !== "qr-code" &&
|
|
445
|
-
fundMethod !== "exchange"
|
|
446
|
-
? "opacity-70"
|
|
447
|
-
: ""
|
|
448
|
-
}`}
|
|
449
|
-
>
|
|
450
|
-
{isBalanceVisible ? balanceFormatted : "••••••"}
|
|
451
|
-
</p>
|
|
452
|
-
)}
|
|
453
|
-
</div>
|
|
454
|
-
)}
|
|
583
|
+
)}
|
|
584
|
+
</div>
|
|
585
|
+
)}
|
|
455
586
|
</motion.div>
|
|
456
587
|
)
|
|
457
588
|
})}
|
|
@@ -3,17 +3,28 @@ import * as TooltipPrimitive from "@radix-ui/react-tooltip"
|
|
|
3
3
|
import { useTheme } from "./ThemeProvider.js"
|
|
4
4
|
|
|
5
5
|
interface TooltipProps {
|
|
6
|
-
message
|
|
6
|
+
message?: string
|
|
7
|
+
content?: React.ReactNode
|
|
7
8
|
children: React.ReactNode
|
|
8
9
|
className?: string
|
|
10
|
+
side?: "top" | "right" | "bottom" | "left"
|
|
11
|
+
align?: "start" | "center" | "end"
|
|
12
|
+
sideOffset?: number
|
|
13
|
+
alignOffset?: number
|
|
9
14
|
}
|
|
10
15
|
|
|
11
16
|
export const Tooltip: React.FC<TooltipProps> = ({
|
|
12
17
|
message,
|
|
18
|
+
content,
|
|
13
19
|
children,
|
|
14
20
|
className = "",
|
|
21
|
+
side = "top",
|
|
22
|
+
align = "center",
|
|
23
|
+
sideOffset = 4,
|
|
24
|
+
alignOffset = 0,
|
|
15
25
|
}) => {
|
|
16
26
|
const { isDark } = useTheme()
|
|
27
|
+
const tooltipContent = content ?? message
|
|
17
28
|
|
|
18
29
|
return (
|
|
19
30
|
<TooltipPrimitive.Provider>
|
|
@@ -23,7 +34,7 @@ export const Tooltip: React.FC<TooltipProps> = ({
|
|
|
23
34
|
</TooltipPrimitive.Trigger>
|
|
24
35
|
<TooltipPrimitive.Portal>
|
|
25
36
|
<TooltipPrimitive.Content
|
|
26
|
-
className="trails-border-radius-container px-3 py-2 text-xs font-medium shadow-lg z-
|
|
37
|
+
className="trails-border-radius-container px-3 py-2 text-xs font-medium shadow-lg z-[100] animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2"
|
|
27
38
|
style={{
|
|
28
39
|
maxWidth: "400px",
|
|
29
40
|
wordWrap: "break-word",
|
|
@@ -32,12 +43,12 @@ export const Tooltip: React.FC<TooltipProps> = ({
|
|
|
32
43
|
backgroundColor: isDark ? "#111827" : "#ffffff", // gray-900 or white
|
|
33
44
|
color: isDark ? "#ffffff" : "#000000", // white or black
|
|
34
45
|
}}
|
|
35
|
-
side=
|
|
36
|
-
align=
|
|
37
|
-
sideOffset={
|
|
38
|
-
alignOffset={
|
|
46
|
+
side={side}
|
|
47
|
+
align={align}
|
|
48
|
+
sideOffset={sideOffset}
|
|
49
|
+
alignOffset={alignOffset}
|
|
39
50
|
>
|
|
40
|
-
{
|
|
51
|
+
{tooltipContent}
|
|
41
52
|
<TooltipPrimitive.Arrow
|
|
42
53
|
style={{ fill: isDark ? "#111827" : "#ffffff" }} // gray-900 or white
|
|
43
54
|
/>
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { useState, useEffect, useContext, useMemo } from "react"
|
|
2
|
+
import { createPortal } from "react-dom"
|
|
3
|
+
import { http } from "viem"
|
|
4
|
+
import type { Chain } from "viem"
|
|
5
|
+
import { WagmiContext, WagmiProvider, createConfig, createStorage } from "wagmi"
|
|
6
|
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
|
|
7
|
+
import { logger } from "../../logger.js"
|
|
8
|
+
import { getAllChains, getRpcUrl } from "../../chains.js"
|
|
9
|
+
import { getConnectorsInternal } from "../../wallets.js"
|
|
10
|
+
import { PROD_SEQUENCE_NODE_GATEWAY_URL } from "../../constants.js"
|
|
11
|
+
import { TrailsContext } from "../providers/TrailsProvider.js"
|
|
12
|
+
import { ShadowPortal } from "./ShadowPortal.js"
|
|
13
|
+
import { ThemeProvider } from "./ThemeProvider.js"
|
|
14
|
+
import { WidgetProviders } from "./WidgetProviders.js"
|
|
15
|
+
import { HookModalContent } from "./HookModalContent.js"
|
|
16
|
+
|
|
17
|
+
// QueryClient for when we create our own WagmiProvider
|
|
18
|
+
const hookModalQueryClient = new QueryClient()
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Inner component that renders the portal with shared provider tree.
|
|
22
|
+
* Uses WidgetProviders to ensure all widget-level context providers are available.
|
|
23
|
+
*/
|
|
24
|
+
function TrailsHookModalInner() {
|
|
25
|
+
const [mounted, setMounted] = useState(false)
|
|
26
|
+
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
setMounted(true)
|
|
29
|
+
logger.console.log("[trails-sdk] [TrailsHookModalInner] Mounted")
|
|
30
|
+
}, [])
|
|
31
|
+
|
|
32
|
+
if (!mounted) {
|
|
33
|
+
return null
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return createPortal(
|
|
37
|
+
<ShadowPortal>
|
|
38
|
+
<ThemeProvider>
|
|
39
|
+
<WidgetProviders>
|
|
40
|
+
<HookModalContent />
|
|
41
|
+
</WidgetProviders>
|
|
42
|
+
</ThemeProvider>
|
|
43
|
+
</ShadowPortal>,
|
|
44
|
+
document.body,
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* TrailsHookModal is the modal component used by useTrailsSendTransaction.
|
|
50
|
+
* It creates its own WagmiProvider if none exists, ensuring it can work
|
|
51
|
+
* both with and without a parent TrailsWidget.
|
|
52
|
+
*
|
|
53
|
+
* The modal content is wrapped with WidgetProviders to ensure all widget-level
|
|
54
|
+
* context providers are available, making shared components like ScreenHeader work.
|
|
55
|
+
*/
|
|
56
|
+
export function TrailsHookModal() {
|
|
57
|
+
const wagmiContext = useContext(WagmiContext)
|
|
58
|
+
const trailsContext = useContext(TrailsContext)
|
|
59
|
+
|
|
60
|
+
logger.console.log("[trails-sdk] [TrailsHookModal] Check:", {
|
|
61
|
+
hasWagmiContext: !!wagmiContext,
|
|
62
|
+
hasTrailsContext: !!trailsContext,
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
// Create wagmi config if no parent WagmiProvider exists
|
|
66
|
+
const wagmiConfig = useMemo(() => {
|
|
67
|
+
if (wagmiContext) {
|
|
68
|
+
logger.console.log(
|
|
69
|
+
"[trails-sdk] [TrailsHookModal] Using parent WagmiProvider",
|
|
70
|
+
)
|
|
71
|
+
return null // Use parent's config
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
logger.console.log(
|
|
75
|
+
"[trails-sdk] [TrailsHookModal] Creating own WagmiProvider",
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
// Create our own config (similar to TrailsWidget)
|
|
79
|
+
const chains = getAllChains() as Chain[]
|
|
80
|
+
const apiKey = trailsContext?.trailsApiKey || ""
|
|
81
|
+
const nodeGatewayUrl =
|
|
82
|
+
trailsContext?.sequenceNodeGatewayUrl || PROD_SEQUENCE_NODE_GATEWAY_URL
|
|
83
|
+
|
|
84
|
+
return createConfig({
|
|
85
|
+
chains: chains as any,
|
|
86
|
+
transports: chains.reduce(
|
|
87
|
+
(acc, chain) => {
|
|
88
|
+
const sequenceRpcUrl = getRpcUrl(chain.id, apiKey, nodeGatewayUrl)
|
|
89
|
+
return {
|
|
90
|
+
...acc,
|
|
91
|
+
[chain.id]: sequenceRpcUrl ? http(sequenceRpcUrl) : http(),
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
{} as Record<number, ReturnType<typeof http>>,
|
|
95
|
+
),
|
|
96
|
+
connectors: getConnectorsInternal(apiKey),
|
|
97
|
+
storage: createStorage({
|
|
98
|
+
storage: localStorage,
|
|
99
|
+
key: "trails-hook-modal-wagmi",
|
|
100
|
+
}),
|
|
101
|
+
})
|
|
102
|
+
}, [wagmiContext, trailsContext])
|
|
103
|
+
|
|
104
|
+
const content = <TrailsHookModalInner />
|
|
105
|
+
|
|
106
|
+
// Wrap with WagmiProvider if we created our own config
|
|
107
|
+
if (wagmiConfig) {
|
|
108
|
+
return (
|
|
109
|
+
<WagmiProvider config={wagmiConfig}>
|
|
110
|
+
<QueryClientProvider client={hookModalQueryClient}>
|
|
111
|
+
{content}
|
|
112
|
+
</QueryClientProvider>
|
|
113
|
+
</WagmiProvider>
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return content
|
|
118
|
+
}
|