0xtrails 0.2.5 → 0.3.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 +2 -0
- package/dist/aave.d.ts.map +1 -1
- package/dist/abortController.d.ts +8 -0
- package/dist/abortController.d.ts.map +1 -0
- package/dist/{ccip-CXlshvBY.js → ccip-BMB3uDZt.js} +1 -1
- package/dist/config.d.ts +0 -5
- package/dist/config.d.ts.map +1 -1
- package/dist/constants.d.ts +4 -4
- package/dist/constants.d.ts.map +1 -1
- package/dist/error.d.ts +4 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/fees.d.ts +19 -0
- package/dist/fees.d.ts.map +1 -0
- package/dist/{index-_QuyGrjU.js → index-QXPUrZVv.js} +48719 -50852
- package/dist/index.d.ts +9 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +811 -784
- package/dist/intentReceiptMonitor.d.ts +24 -0
- package/dist/intentReceiptMonitor.d.ts.map +1 -0
- package/dist/intentReceiptPoller.d.ts +69 -0
- package/dist/intentReceiptPoller.d.ts.map +1 -0
- package/dist/intents.d.ts +15 -11
- package/dist/intents.d.ts.map +1 -1
- package/dist/morpho.d.ts +6 -5
- package/dist/morpho.d.ts.map +1 -1
- package/dist/mutations.d.ts +16 -0
- package/dist/mutations.d.ts.map +1 -0
- package/dist/preconditions.d.ts +5 -4
- package/dist/preconditions.d.ts.map +1 -1
- package/dist/prepareSend.d.ts +7 -258
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/prices.d.ts +9 -6
- package/dist/prices.d.ts.map +1 -1
- package/dist/sequenceWallet.d.ts +3 -16
- package/dist/sequenceWallet.d.ts.map +1 -1
- package/dist/tokenBalances.d.ts +17 -13
- package/dist/tokenBalances.d.ts.map +1 -1
- package/dist/trails.d.ts +24 -40
- package/dist/trails.d.ts.map +1 -1
- package/dist/transactionIntent/constants.d.ts +7 -0
- package/dist/transactionIntent/constants.d.ts.map +1 -0
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts +44 -0
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -0
- package/dist/transactionIntent/deposits/gaslessDeposit.d.ts +30 -0
- package/dist/transactionIntent/deposits/gaslessDeposit.d.ts.map +1 -0
- package/dist/transactionIntent/deposits/index.d.ts +4 -0
- package/dist/transactionIntent/deposits/index.d.ts.map +1 -0
- package/dist/transactionIntent/deposits/standardDeposit.d.ts +30 -0
- package/dist/transactionIntent/deposits/standardDeposit.d.ts.map +1 -0
- package/dist/transactionIntent/execution/index.d.ts +2 -0
- package/dist/transactionIntent/execution/index.d.ts.map +1 -0
- package/dist/transactionIntent/execution/transactionState.d.ts +5 -0
- package/dist/transactionIntent/execution/transactionState.d.ts.map +1 -0
- package/dist/transactionIntent/handlers/crossChain.d.ts +82 -0
- package/dist/transactionIntent/handlers/crossChain.d.ts.map +1 -0
- package/dist/transactionIntent/handlers/index.d.ts +4 -0
- package/dist/transactionIntent/handlers/index.d.ts.map +1 -0
- package/dist/transactionIntent/handlers/sameChainDifferentToken.d.ts +62 -0
- package/dist/transactionIntent/handlers/sameChainDifferentToken.d.ts.map +1 -0
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts +72 -0
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts.map +1 -0
- package/dist/transactionIntent/index.d.ts +9 -0
- package/dist/transactionIntent/index.d.ts.map +1 -0
- package/dist/transactionIntent/quote/feeExtractors.d.ts +17 -0
- package/dist/transactionIntent/quote/feeExtractors.d.ts.map +1 -0
- package/dist/transactionIntent/quote/index.d.ts +4 -0
- package/dist/transactionIntent/quote/index.d.ts.map +1 -0
- package/dist/transactionIntent/quote/normalizeQuote.d.ts +34 -0
- package/dist/transactionIntent/quote/normalizeQuote.d.ts.map +1 -0
- package/dist/transactionIntent/quote/quoteHelpers.d.ts +5 -0
- package/dist/transactionIntent/quote/quoteHelpers.d.ts.map +1 -0
- package/dist/transactionIntent/types.d.ts +131 -0
- package/dist/transactionIntent/types.d.ts.map +1 -0
- package/dist/transactionIntent/utils/balanceChecker.d.ts +18 -0
- package/dist/transactionIntent/utils/balanceChecker.d.ts.map +1 -0
- package/dist/transactionIntent/utils/index.d.ts +4 -0
- package/dist/transactionIntent/utils/index.d.ts.map +1 -0
- package/dist/transactionIntent/utils/lifiHelpers.d.ts +10 -0
- package/dist/transactionIntent/utils/lifiHelpers.d.ts.map +1 -0
- package/dist/transactionIntent/utils/testnetHelpers.d.ts +3 -0
- package/dist/transactionIntent/utils/testnetHelpers.d.ts.map +1 -0
- package/dist/transactionIntent/validators.d.ts +6 -0
- package/dist/transactionIntent/validators.d.ts.map +1 -0
- package/dist/transactions.d.ts +6 -3
- package/dist/transactions.d.ts.map +1 -1
- package/dist/widget/components/AccountIntentTransactionHistoryButton.d.ts +4 -0
- package/dist/widget/components/AccountIntentTransactionHistoryButton.d.ts.map +1 -0
- package/dist/widget/components/AccountSettings.d.ts.map +1 -1
- package/dist/widget/components/ChainFilterDropdown.d.ts.map +1 -1
- package/dist/widget/components/ClassicSwap.d.ts +2 -3
- package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
- package/dist/widget/components/ConfigDisplay.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/DynamicInputStyles.d.ts +18 -0
- package/dist/widget/components/DynamicInputStyles.d.ts.map +1 -0
- package/dist/widget/components/DynamicSizeInputField.d.ts +13 -0
- package/dist/widget/components/DynamicSizeInputField.d.ts.map +1 -0
- package/dist/widget/components/Earn.d.ts +2 -3
- package/dist/widget/components/Earn.d.ts.map +1 -1
- package/dist/widget/components/ErrorAnimationIcon.d.ts +2 -0
- package/dist/widget/components/ErrorAnimationIcon.d.ts.map +1 -0
- package/dist/widget/components/FeeBreakdown.d.ts +9 -0
- package/dist/widget/components/FeeBreakdown.d.ts.map +1 -0
- package/dist/widget/components/FeeOptions.d.ts +5 -13
- package/dist/widget/components/FeeOptions.d.ts.map +1 -1
- package/dist/widget/components/Fund.d.ts +2 -3
- package/dist/widget/components/Fund.d.ts.map +1 -1
- package/dist/widget/components/FundMethods.d.ts.map +1 -1
- package/dist/widget/components/FundSwap.d.ts +2 -3
- package/dist/widget/components/FundSwap.d.ts.map +1 -1
- package/dist/widget/components/FundingMethodSelectorButton.d.ts.map +1 -1
- package/dist/widget/components/Identicon.d.ts.map +1 -1
- package/dist/widget/components/MeshConnectExchanges.d.ts +0 -3
- package/dist/widget/components/MeshConnectExchanges.d.ts.map +1 -1
- package/dist/widget/components/Modal.d.ts.map +1 -1
- package/dist/widget/components/Pay.d.ts +2 -3
- package/dist/widget/components/Pay.d.ts.map +1 -1
- package/dist/widget/components/PoolDeposit.d.ts +3 -3
- package/dist/widget/components/PoolDeposit.d.ts.map +1 -1
- package/dist/widget/components/PoolWithdraw.d.ts +3 -20
- package/dist/widget/components/PoolWithdraw.d.ts.map +1 -1
- package/dist/widget/components/QuoteDetails.d.ts +2 -0
- package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
- package/dist/widget/components/Receipt.d.ts.map +1 -1
- package/dist/widget/components/RecipientSelectorButton.d.ts.map +1 -1
- package/dist/widget/components/ScreenHeader.d.ts.map +1 -1
- package/dist/widget/components/Swap.d.ts +2 -3
- package/dist/widget/components/Swap.d.ts.map +1 -1
- package/dist/widget/components/ThemeProvider.d.ts.map +1 -1
- package/dist/widget/components/TokenDisplayNonSelectable.d.ts +11 -0
- package/dist/widget/components/TokenDisplayNonSelectable.d.ts.map +1 -0
- package/dist/widget/components/TokenSelector.d.ts.map +1 -1
- package/dist/widget/components/TokenSelectorButton.d.ts.map +1 -1
- package/dist/widget/components/Tooltip.d.ts +9 -0
- package/dist/widget/components/Tooltip.d.ts.map +1 -0
- package/dist/widget/components/TransferPendingVertical.d.ts.map +1 -1
- package/dist/widget/components/WaasFeeOptions.d.ts +1 -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/css/compiled.css +2 -2
- package/dist/widget/hooks/useCheckout.d.ts +17 -4
- package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
- package/dist/widget/hooks/useDefaultTokenSelection.d.ts.map +1 -1
- package/dist/widget/hooks/useQuote.d.ts +82 -0
- package/dist/widget/hooks/useQuote.d.ts.map +1 -0
- package/dist/widget/hooks/useSelectedFeeToken.d.ts +1 -0
- package/dist/widget/hooks/useSelectedFeeToken.d.ts.map +1 -1
- package/dist/widget/hooks/useSendForm.d.ts +5 -6
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
- package/dist/widget/hooks/useWalletConnectionContext.d.ts +25 -0
- package/dist/widget/hooks/useWalletConnectionContext.d.ts.map +1 -0
- package/dist/widget/index.js +2 -2
- package/dist/widget/widget.d.ts +17 -7
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +19 -21
- package/src/aave.ts +54 -1
- package/src/abortController.ts +35 -0
- package/src/config.ts +57 -58
- package/src/constants.ts +11 -9
- package/src/error.ts +21 -3
- package/src/fees.ts +210 -0
- package/src/index.ts +35 -13
- package/src/intentReceiptMonitor.ts +102 -0
- package/src/intentReceiptPoller.ts +299 -0
- package/src/intents.ts +205 -171
- package/src/morpho.ts +58 -9
- package/src/mutations.ts +129 -0
- package/src/preconditions.ts +16 -21
- package/src/prepareSend.ts +92 -4699
- package/src/prices.ts +26 -22
- package/src/relaySdk.ts +2 -2
- package/src/sequenceWallet.ts +6 -73
- package/src/tokenBalances.ts +175 -69
- package/src/trails.ts +230 -722
- package/src/transactionIntent/constants.ts +11 -0
- package/src/transactionIntent/deposits/depositOrchestrator.ts +210 -0
- package/src/transactionIntent/deposits/gaslessDeposit.ts +588 -0
- package/src/transactionIntent/deposits/index.ts +3 -0
- package/src/transactionIntent/deposits/standardDeposit.ts +379 -0
- package/src/transactionIntent/execution/index.ts +1 -0
- package/src/transactionIntent/execution/transactionState.ts +35 -0
- package/src/transactionIntent/handlers/crossChain.ts +1707 -0
- package/src/transactionIntent/handlers/index.ts +3 -0
- package/src/transactionIntent/handlers/sameChainDifferentToken.ts +323 -0
- package/src/transactionIntent/handlers/sameChainSameToken.ts +712 -0
- package/src/transactionIntent/index.ts +9 -0
- package/src/transactionIntent/quote/feeExtractors.ts +81 -0
- package/src/transactionIntent/quote/index.ts +3 -0
- package/src/transactionIntent/quote/normalizeQuote.ts +367 -0
- package/src/transactionIntent/quote/quoteHelpers.ts +53 -0
- package/src/transactionIntent/types.ts +157 -0
- package/src/transactionIntent/utils/balanceChecker.ts +96 -0
- package/src/transactionIntent/utils/index.ts +3 -0
- package/src/transactionIntent/utils/lifiHelpers.ts +68 -0
- package/src/transactionIntent/utils/testnetHelpers.ts +10 -0
- package/src/transactionIntent/validators.ts +57 -0
- package/src/transactions.ts +98 -71
- package/src/widget/compiled.css +2 -2
- package/src/widget/components/AccountIntentTransactionHistory.tsx +36 -36
- package/src/widget/components/AccountIntentTransactionHistoryButton.tsx +22 -0
- package/src/widget/components/AccountSettings.tsx +70 -41
- package/src/widget/components/ChainFilterDropdown.tsx +24 -3
- package/src/widget/components/ClassicSwap.tsx +44 -107
- package/src/widget/components/ConfigDisplay.tsx +0 -11
- package/src/widget/components/ConnectWallet.tsx +4 -1
- package/src/widget/components/ConnectedWallets.tsx +51 -25
- package/src/widget/components/DynamicInputStyles.tsx +76 -0
- package/src/widget/components/DynamicSizeInputField.tsx +109 -0
- package/src/widget/components/Earn.tsx +34 -45
- package/src/widget/components/ErrorAnimationIcon.tsx +130 -0
- package/src/widget/components/FeeBreakdown.tsx +155 -0
- package/src/widget/components/FeeOption.tsx +2 -2
- package/src/widget/components/FeeOptions.tsx +151 -112
- package/src/widget/components/Fund.tsx +10 -29
- package/src/widget/components/FundMethods.tsx +4 -3
- package/src/widget/components/FundSwap.tsx +2 -3
- package/src/widget/components/FundingMethodSelectorButton.tsx +24 -14
- package/src/widget/components/Identicon.tsx +164 -95
- package/src/widget/components/MeshConnectExchanges.tsx +2 -15
- package/src/widget/components/Modal.tsx +0 -12
- package/src/widget/components/Pay.tsx +72 -75
- package/src/widget/components/PoolDeposit.tsx +221 -242
- package/src/widget/components/PoolWithdraw.tsx +347 -469
- package/src/widget/components/PriceImpactWarning.tsx +1 -1
- package/src/widget/components/QuoteDetails.tsx +906 -484
- package/src/widget/components/Receipt.tsx +16 -2
- package/src/widget/components/RecipientSelectorButton.tsx +7 -5
- package/src/widget/components/Recipients.tsx +1 -1
- package/src/widget/components/ScreenHeader.tsx +60 -36
- package/src/widget/components/Swap.tsx +2 -3
- package/src/widget/components/ThemeProvider.tsx +2 -1
- package/src/widget/components/TokenDisplayNonSelectable.tsx +40 -0
- package/src/widget/components/TokenImage.tsx +1 -1
- package/src/widget/components/TokenSelector.tsx +62 -53
- package/src/widget/components/TokenSelectorButton.tsx +38 -15
- package/src/widget/components/Tooltip.tsx +51 -0
- package/src/widget/components/TransferPendingVertical.tsx +12 -8
- package/src/widget/components/WaasFeeOptions.tsx +139 -4
- package/src/widget/components/WalletConfirmation.tsx +23 -13
- package/src/widget/components/WalletConnect.tsx +93 -29
- package/src/widget/hooks/useAmountUsd.ts +9 -9
- package/src/widget/hooks/useCheckout.ts +97 -9
- package/src/widget/hooks/useDefaultTokenSelection.tsx +27 -21
- package/src/widget/hooks/useQuote.ts +466 -0
- package/src/widget/hooks/useSelectedFeeToken.tsx +32 -37
- package/src/widget/hooks/useSendForm.ts +45 -51
- package/src/widget/hooks/useTokenList.ts +34 -26
- package/src/widget/hooks/useWalletConnectionContext.tsx +128 -0
- package/src/widget/widget.tsx +365 -390
- package/dist/apiClient.d.ts +0 -9
- package/dist/apiClient.d.ts.map +0 -1
- package/dist/intentEntrypoint.d.ts +0 -114
- package/dist/intentEntrypoint.d.ts.map +0 -1
- package/dist/metaTxnMonitor.d.ts +0 -15
- package/dist/metaTxnMonitor.d.ts.map +0 -1
- package/dist/metaTxns.d.ts +0 -11
- package/dist/metaTxns.d.ts.map +0 -1
- package/dist/relayer.d.ts +0 -43
- package/dist/relayer.d.ts.map +0 -1
- package/src/apiClient.ts +0 -35
- package/src/intentEntrypoint.ts +0 -203
- package/src/metaTxnMonitor.ts +0 -171
- package/src/metaTxns.ts +0 -45
- package/src/relayer.ts +0 -289
|
@@ -462,28 +462,34 @@ function useDefaultTokenSelectionInternal(): UseDefaultTokenSelectionReturn {
|
|
|
462
462
|
|
|
463
463
|
const decimals = destToken?.decimals
|
|
464
464
|
if (!decimals) {
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
contractAddress: destToken.contractAddress || zeroAddress,
|
|
477
|
-
balanceUsdFormatted: "0",
|
|
478
|
-
tokenPriceUsd: 0,
|
|
479
|
-
decimals, // Top-level decimals
|
|
480
|
-
contractInfo: {
|
|
481
|
-
decimals,
|
|
482
|
-
symbol: destToken.symbol,
|
|
465
|
+
logger.console.warn(
|
|
466
|
+
"[trails-sdk] Missing decimals for destination token, skipping:",
|
|
467
|
+
{
|
|
468
|
+
token: destToken,
|
|
469
|
+
},
|
|
470
|
+
)
|
|
471
|
+
destinationToken = null
|
|
472
|
+
} else {
|
|
473
|
+
destinationToken = destToken
|
|
474
|
+
? {
|
|
475
|
+
id: destToken.chainId,
|
|
483
476
|
name: destToken.name,
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
477
|
+
symbol: destToken.symbol,
|
|
478
|
+
balance: "0", // Destination token doesn't have balance yet
|
|
479
|
+
imageUrl: destToken.imageUrl || "",
|
|
480
|
+
chainId: destToken.chainId,
|
|
481
|
+
contractAddress: destToken.contractAddress || zeroAddress,
|
|
482
|
+
balanceUsdFormatted: "0",
|
|
483
|
+
tokenPriceUsd: 0,
|
|
484
|
+
decimals, // Top-level decimals
|
|
485
|
+
contractInfo: {
|
|
486
|
+
decimals,
|
|
487
|
+
symbol: destToken.symbol,
|
|
488
|
+
name: destToken.name,
|
|
489
|
+
},
|
|
490
|
+
}
|
|
491
|
+
: null
|
|
492
|
+
}
|
|
487
493
|
}
|
|
488
494
|
|
|
489
495
|
logger.console.log("[trails-sdk] Default token selection:", {
|
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
import { useQuery } from "@tanstack/react-query"
|
|
2
|
+
import { useRef } from "react"
|
|
3
|
+
import type { TransactionReceipt } from "viem"
|
|
4
|
+
import { zeroAddress } from "viem"
|
|
5
|
+
import { useIndexerGatewayClient } from "../../indexerClient.js"
|
|
6
|
+
import { getTokenBalancesWithPrices } from "../../tokenBalances.js"
|
|
7
|
+
import { logger } from "../../logger.js"
|
|
8
|
+
import { useSupportedTokens } from "../../tokens.js"
|
|
9
|
+
import { useTrailsClient } from "../../trailsClient.js"
|
|
10
|
+
import { getExplorerUrl } from "../../explorer.js"
|
|
11
|
+
import { getFullErrorMessage, getPrettifiedErrorMessage } from "../../error.js"
|
|
12
|
+
import { prepareSend } from "../../prepareSend.js"
|
|
13
|
+
import { abortControllerRegistry } from "../../abortController.js"
|
|
14
|
+
import { TradeType } from "../../prepareSend.js"
|
|
15
|
+
import { getChainInfo } from "../../chains.js"
|
|
16
|
+
import type { MetaTxnReceipt } from "../../transactionIntent/types.js"
|
|
17
|
+
import type { Chain } from "../../chains.js"
|
|
18
|
+
import type { SupportedToken } from "../../tokens.js"
|
|
19
|
+
import type { TransactionState } from "../../transactions.js"
|
|
20
|
+
import type { PrepareSendFees } from "../../prepareSend.js"
|
|
21
|
+
import type { SequenceEnv } from "../../config.js"
|
|
22
|
+
import { getTokenPrice } from "../../prices.js"
|
|
23
|
+
import { useCommitIntent, useExecuteIntent } from "../../mutations.js"
|
|
24
|
+
|
|
25
|
+
export type UseQuoteProps = {
|
|
26
|
+
walletClient?: any // TODO: fix this, has to do with viem/wagmi versions
|
|
27
|
+
fromTokenAddress?: string | null
|
|
28
|
+
fromChainId?: number | null
|
|
29
|
+
toTokenAddress?: string | null
|
|
30
|
+
toChainId?: number | null
|
|
31
|
+
toCalldata?: string | null
|
|
32
|
+
swapAmount?: string | bigint
|
|
33
|
+
toRecipient?: string | null
|
|
34
|
+
tradeType?: TradeType | null
|
|
35
|
+
slippageTolerance?: string | number | null
|
|
36
|
+
onStatusUpdate?: ((transactionStates: TransactionState[]) => void) | null
|
|
37
|
+
quoteProvider?: string | null
|
|
38
|
+
paymasterUrl?: string
|
|
39
|
+
selectedFeeToken?: {
|
|
40
|
+
tokenAddress: string
|
|
41
|
+
tokenSymbol?: string
|
|
42
|
+
} | null
|
|
43
|
+
abortSignal?: AbortSignal
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type SwapReturn = {
|
|
47
|
+
originTransaction: {
|
|
48
|
+
transactionHash?: string | null
|
|
49
|
+
explorerUrl?: string | null
|
|
50
|
+
receipt: TransactionReceipt | MetaTxnReceipt | null
|
|
51
|
+
}
|
|
52
|
+
destinationTransaction: {
|
|
53
|
+
transactionHash?: string | null
|
|
54
|
+
explorerUrl?: string | null
|
|
55
|
+
receipt: MetaTxnReceipt | null
|
|
56
|
+
}
|
|
57
|
+
totalCompletionSeconds?: number
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type QuoteProviderInfo = {
|
|
61
|
+
id: string
|
|
62
|
+
name: string
|
|
63
|
+
url: string
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export type Quote = {
|
|
67
|
+
fromAmount: string
|
|
68
|
+
fromAmountMin: string
|
|
69
|
+
toAmount: string
|
|
70
|
+
toAmountMin: string
|
|
71
|
+
originToken: SupportedToken
|
|
72
|
+
destinationToken: SupportedToken
|
|
73
|
+
originChain: Chain
|
|
74
|
+
destinationChain: Chain
|
|
75
|
+
fees: PrepareSendFees
|
|
76
|
+
slippageTolerance: string
|
|
77
|
+
priceImpact: string
|
|
78
|
+
completionEstimateSeconds: number
|
|
79
|
+
transactionStates?: TransactionState[]
|
|
80
|
+
originTokenRate?: string
|
|
81
|
+
quoteProvider?: QuoteProviderInfo | null
|
|
82
|
+
destinationTokenRate?: string
|
|
83
|
+
fromAmountUsdDisplay?: string
|
|
84
|
+
toAmountUsdDisplay?: string
|
|
85
|
+
gasCostUsd?: number
|
|
86
|
+
gasCostUsdDisplay?: string
|
|
87
|
+
gasCost?: string
|
|
88
|
+
gasCostFormatted?: string
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export type UseQuoteReturn = {
|
|
92
|
+
quote: Quote | null
|
|
93
|
+
swap: (() => Promise<SwapReturn | null>) | null
|
|
94
|
+
isLoadingQuote: boolean
|
|
95
|
+
quoteError: unknown
|
|
96
|
+
quoteErrorPrettified: string
|
|
97
|
+
refetchQuote: () => void
|
|
98
|
+
abort: () => void
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// TODO: consolidate useSendForm, prepareSend, and useQuote hooks into a single hook
|
|
102
|
+
export function useQuote({
|
|
103
|
+
walletClient,
|
|
104
|
+
fromTokenAddress,
|
|
105
|
+
fromChainId,
|
|
106
|
+
toTokenAddress,
|
|
107
|
+
toChainId,
|
|
108
|
+
swapAmount,
|
|
109
|
+
tradeType,
|
|
110
|
+
toRecipient,
|
|
111
|
+
toCalldata,
|
|
112
|
+
slippageTolerance,
|
|
113
|
+
onStatusUpdate,
|
|
114
|
+
quoteProvider,
|
|
115
|
+
paymasterUrl,
|
|
116
|
+
selectedFeeToken,
|
|
117
|
+
nodeGatewayEnv,
|
|
118
|
+
abortSignal: externalAbortSignal,
|
|
119
|
+
}: Partial<
|
|
120
|
+
UseQuoteProps & { nodeGatewayEnv?: SequenceEnv }
|
|
121
|
+
> = {}): UseQuoteReturn {
|
|
122
|
+
// Set node gateway environment override for this quote session
|
|
123
|
+
if (nodeGatewayEnv) {
|
|
124
|
+
;(globalThis as any).__testNodeGatewayEnv = nodeGatewayEnv
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Create abort controller for this hook instance
|
|
128
|
+
const abortControllerRef = useRef<AbortController>(new AbortController())
|
|
129
|
+
|
|
130
|
+
// Combine external abort signal with internal abort controller
|
|
131
|
+
const combinedAbortSignal = externalAbortSignal
|
|
132
|
+
? (() => {
|
|
133
|
+
const controller = new AbortController()
|
|
134
|
+
|
|
135
|
+
// Listen to external abort signal
|
|
136
|
+
externalAbortSignal.addEventListener("abort", () => {
|
|
137
|
+
controller.abort()
|
|
138
|
+
abortControllerRef.current?.abort()
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
// Listen to internal abort controller
|
|
142
|
+
abortControllerRef.current?.signal.addEventListener("abort", () => {
|
|
143
|
+
controller.abort()
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
return controller.signal
|
|
147
|
+
})()
|
|
148
|
+
: abortControllerRef.current.signal
|
|
149
|
+
|
|
150
|
+
const trailsClient = useTrailsClient()
|
|
151
|
+
const indexerGatewayClient = useIndexerGatewayClient()
|
|
152
|
+
|
|
153
|
+
const { supportedTokens } = useSupportedTokens()
|
|
154
|
+
|
|
155
|
+
// Get mutation hooks for passing to prepareSend
|
|
156
|
+
const commitIntentMutation = useCommitIntent()
|
|
157
|
+
const executeIntentMutation = useExecuteIntent()
|
|
158
|
+
|
|
159
|
+
const { data, isLoading, error, refetch } = useQuery({
|
|
160
|
+
queryKey: [
|
|
161
|
+
"prepareSend",
|
|
162
|
+
fromTokenAddress,
|
|
163
|
+
fromChainId,
|
|
164
|
+
toTokenAddress,
|
|
165
|
+
toChainId,
|
|
166
|
+
swapAmount?.toString(),
|
|
167
|
+
toRecipient,
|
|
168
|
+
toCalldata,
|
|
169
|
+
tradeType,
|
|
170
|
+
slippageTolerance,
|
|
171
|
+
quoteProvider,
|
|
172
|
+
],
|
|
173
|
+
queryFn: async () => {
|
|
174
|
+
try {
|
|
175
|
+
// Reset the abort controller for new queries to ensure fresh state
|
|
176
|
+
if (abortControllerRef.current.signal.aborted) {
|
|
177
|
+
logger.console.log(
|
|
178
|
+
"[trails-sdk] Resetting aborted controller for new query",
|
|
179
|
+
)
|
|
180
|
+
abortControllerRef.current = new AbortController()
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (
|
|
184
|
+
!walletClient ||
|
|
185
|
+
!trailsClient ||
|
|
186
|
+
!fromTokenAddress ||
|
|
187
|
+
!toTokenAddress ||
|
|
188
|
+
!swapAmount ||
|
|
189
|
+
!toRecipient ||
|
|
190
|
+
!fromChainId ||
|
|
191
|
+
!toChainId ||
|
|
192
|
+
!indexerGatewayClient
|
|
193
|
+
) {
|
|
194
|
+
return null
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Get token balance using async method
|
|
198
|
+
let balances: any[] = []
|
|
199
|
+
try {
|
|
200
|
+
const result = await getTokenBalancesWithPrices({
|
|
201
|
+
account: walletClient.account!.address,
|
|
202
|
+
indexerGatewayClient,
|
|
203
|
+
trailsClient,
|
|
204
|
+
})
|
|
205
|
+
balances = result.balances
|
|
206
|
+
} catch (balanceError) {
|
|
207
|
+
const balanceErrorMessage = getFullErrorMessage(balanceError)
|
|
208
|
+
const isCorsError =
|
|
209
|
+
balanceErrorMessage.includes("Cross-Origin") ||
|
|
210
|
+
balanceErrorMessage.includes("CORS") ||
|
|
211
|
+
balanceErrorMessage.includes("Same Origin Policy")
|
|
212
|
+
const isNetworkError =
|
|
213
|
+
balanceErrorMessage.includes("fetch failed") ||
|
|
214
|
+
balanceErrorMessage.includes("network")
|
|
215
|
+
|
|
216
|
+
if (isCorsError || isNetworkError) {
|
|
217
|
+
logger.console.warn(
|
|
218
|
+
"[trails-sdk] [useQuote] Network or CORS error fetching balances, proceeding with quote using zero balance:",
|
|
219
|
+
{
|
|
220
|
+
error: balanceErrorMessage,
|
|
221
|
+
account: walletClient.account!.address,
|
|
222
|
+
},
|
|
223
|
+
)
|
|
224
|
+
// Continue with empty balances instead of crashing
|
|
225
|
+
balances = []
|
|
226
|
+
} else {
|
|
227
|
+
throw balanceError
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const originTokenBalance = balances.find(
|
|
232
|
+
(b) =>
|
|
233
|
+
b.chainId === fromChainId &&
|
|
234
|
+
(b.contractAddress?.toLowerCase() ===
|
|
235
|
+
fromTokenAddress.toLowerCase() ||
|
|
236
|
+
(!b.contractAddress && fromTokenAddress === zeroAddress)),
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
const originTokenBalanceAmount = originTokenBalance?.balance ?? "0"
|
|
240
|
+
|
|
241
|
+
// Note: Disable this check for now to allow fetching a quote even when the origin balance is zero
|
|
242
|
+
// if (originTokenBalanceAmount === "0") {
|
|
243
|
+
// return null
|
|
244
|
+
// }
|
|
245
|
+
|
|
246
|
+
// logger.console.log("supportedTokens", supportedTokens)
|
|
247
|
+
|
|
248
|
+
// Get native token price for origin chain (for gas cost calculation)
|
|
249
|
+
let originNativeTokenPriceUsd = 0
|
|
250
|
+
try {
|
|
251
|
+
const originChain = getChainInfo(fromChainId)
|
|
252
|
+
const nativeTokenSymbol = originChain?.nativeCurrency?.symbol ?? ""
|
|
253
|
+
if (nativeTokenSymbol) {
|
|
254
|
+
const nativePrice = await getTokenPrice(trailsClient, {
|
|
255
|
+
tokenSymbol: nativeTokenSymbol,
|
|
256
|
+
tokenAddress: zeroAddress,
|
|
257
|
+
chainId: fromChainId,
|
|
258
|
+
})
|
|
259
|
+
originNativeTokenPriceUsd = nativePrice?.priceUsd ?? 0
|
|
260
|
+
logger.console.log(
|
|
261
|
+
"[trails-sdk] [useQuote] Origin native token price:",
|
|
262
|
+
{
|
|
263
|
+
chainId: fromChainId,
|
|
264
|
+
symbol: nativeTokenSymbol,
|
|
265
|
+
priceUsd: originNativeTokenPriceUsd,
|
|
266
|
+
},
|
|
267
|
+
)
|
|
268
|
+
}
|
|
269
|
+
} catch (error) {
|
|
270
|
+
logger.console.error(
|
|
271
|
+
"[trails-sdk] [useQuote] Error getting origin native token price:",
|
|
272
|
+
error,
|
|
273
|
+
)
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const originToken = supportedTokens?.find(
|
|
277
|
+
(token) =>
|
|
278
|
+
token.contractAddress?.toLowerCase() ===
|
|
279
|
+
fromTokenAddress?.toLowerCase() && token.chainId === fromChainId,
|
|
280
|
+
)
|
|
281
|
+
const destinationToken = supportedTokens?.find(
|
|
282
|
+
(token) =>
|
|
283
|
+
token.contractAddress?.toLowerCase() ===
|
|
284
|
+
toTokenAddress?.toLowerCase() && token.chainId === toChainId,
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
const sourceTokenDecimals = originToken?.decimals
|
|
288
|
+
if (!sourceTokenDecimals) {
|
|
289
|
+
logger.console.error(
|
|
290
|
+
"[trails-sdk] [useQuote] Missing source token decimals:",
|
|
291
|
+
{
|
|
292
|
+
originToken,
|
|
293
|
+
fromTokenAddress,
|
|
294
|
+
fromChainId,
|
|
295
|
+
},
|
|
296
|
+
)
|
|
297
|
+
throw new Error("Source token decimals not found")
|
|
298
|
+
}
|
|
299
|
+
const destinationTokenDecimals = destinationToken?.decimals
|
|
300
|
+
if (!destinationTokenDecimals) {
|
|
301
|
+
logger.console.error(
|
|
302
|
+
"[trails-sdk] Missing destination token decimals:",
|
|
303
|
+
{
|
|
304
|
+
destinationToken,
|
|
305
|
+
toTokenAddress,
|
|
306
|
+
toChainId,
|
|
307
|
+
},
|
|
308
|
+
)
|
|
309
|
+
throw new Error("Destination token decimals not found")
|
|
310
|
+
}
|
|
311
|
+
const destinationTokenSymbol = destinationToken?.symbol ?? ""
|
|
312
|
+
const originTokenSymbol = originToken?.symbol ?? ""
|
|
313
|
+
|
|
314
|
+
const options = {
|
|
315
|
+
account: walletClient.account!,
|
|
316
|
+
originTokenAddress: fromTokenAddress,
|
|
317
|
+
originChainId: fromChainId,
|
|
318
|
+
originTokenBalance: originTokenBalanceAmount,
|
|
319
|
+
destinationChainId: toChainId,
|
|
320
|
+
recipient: toRecipient,
|
|
321
|
+
destinationTokenAddress: toTokenAddress,
|
|
322
|
+
swapAmount: swapAmount.toString(),
|
|
323
|
+
tradeType: tradeType ?? TradeType.EXACT_OUTPUT,
|
|
324
|
+
originTokenSymbol: originTokenSymbol,
|
|
325
|
+
destinationTokenSymbol: destinationTokenSymbol,
|
|
326
|
+
destinationCalldata: toCalldata as string,
|
|
327
|
+
client: walletClient,
|
|
328
|
+
trailsClient,
|
|
329
|
+
sourceTokenDecimals,
|
|
330
|
+
destinationTokenDecimals,
|
|
331
|
+
fee: "0",
|
|
332
|
+
dryMode: false,
|
|
333
|
+
onTransactionStateChange: onStatusUpdate ?? (() => {}),
|
|
334
|
+
slippageTolerance: slippageTolerance?.toString(),
|
|
335
|
+
quoteProvider: quoteProvider,
|
|
336
|
+
paymasterUrl: paymasterUrl,
|
|
337
|
+
selectedFeeToken: selectedFeeToken ?? undefined,
|
|
338
|
+
abortSignal: combinedAbortSignal,
|
|
339
|
+
originNativeTokenPriceUsd: originNativeTokenPriceUsd,
|
|
340
|
+
commitIntentFn: commitIntentMutation.mutateAsync,
|
|
341
|
+
executeIntentFn: executeIntentMutation.mutateAsync,
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
logger.console.log("[trails-sdk] options", options)
|
|
345
|
+
|
|
346
|
+
const { quote: prepareSendQuote, send } = await prepareSend(options)
|
|
347
|
+
|
|
348
|
+
const quote = {
|
|
349
|
+
fromAmount: prepareSendQuote.originAmount,
|
|
350
|
+
toAmount: prepareSendQuote.destinationAmount,
|
|
351
|
+
fromAmountMin: prepareSendQuote.originAmountMin,
|
|
352
|
+
toAmountMin: prepareSendQuote.destinationAmountMin,
|
|
353
|
+
originToken: prepareSendQuote.originToken,
|
|
354
|
+
destinationToken: prepareSendQuote.destinationToken,
|
|
355
|
+
originChain: prepareSendQuote.originChain,
|
|
356
|
+
destinationChain: prepareSendQuote.destinationChain,
|
|
357
|
+
fees: prepareSendQuote.fees,
|
|
358
|
+
priceImpact: prepareSendQuote.priceImpact,
|
|
359
|
+
completionEstimateSeconds: prepareSendQuote.completionEstimateSeconds,
|
|
360
|
+
slippageTolerance: prepareSendQuote.slippageTolerance,
|
|
361
|
+
transactionStates: prepareSendQuote.transactionStates,
|
|
362
|
+
originTokenRate: prepareSendQuote.originTokenRate,
|
|
363
|
+
destinationTokenRate: prepareSendQuote.destinationTokenRate,
|
|
364
|
+
quoteProvider: prepareSendQuote.quoteProvider,
|
|
365
|
+
fromAmountUsdDisplay:
|
|
366
|
+
prepareSendQuote.originAmountUsdDisplay ?? undefined,
|
|
367
|
+
toAmountUsdDisplay:
|
|
368
|
+
prepareSendQuote.destinationAmountUsdDisplay ?? undefined,
|
|
369
|
+
gasCostUsd: prepareSendQuote.gasCostUsd ?? undefined,
|
|
370
|
+
gasCostUsdDisplay: prepareSendQuote.gasCostUsdDisplay ?? undefined,
|
|
371
|
+
gasCost: prepareSendQuote.gasCost ?? undefined,
|
|
372
|
+
gasCostFormatted: prepareSendQuote.gasCostFormatted ?? undefined,
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
const swap = async (): Promise<SwapReturn> => {
|
|
376
|
+
const {
|
|
377
|
+
depositUserTxnReceipt,
|
|
378
|
+
destinationMetaTxnReceipt,
|
|
379
|
+
totalCompletionSeconds,
|
|
380
|
+
} = await send({
|
|
381
|
+
selectedFeeToken: selectedFeeToken ?? undefined,
|
|
382
|
+
})
|
|
383
|
+
|
|
384
|
+
return {
|
|
385
|
+
originTransaction: {
|
|
386
|
+
transactionHash: depositUserTxnReceipt?.transactionHash,
|
|
387
|
+
explorerUrl: getExplorerUrl({
|
|
388
|
+
txHash: depositUserTxnReceipt?.transactionHash as string,
|
|
389
|
+
chainId: fromChainId,
|
|
390
|
+
}),
|
|
391
|
+
receipt: depositUserTxnReceipt,
|
|
392
|
+
},
|
|
393
|
+
destinationTransaction: {
|
|
394
|
+
transactionHash: destinationMetaTxnReceipt?.txnHash,
|
|
395
|
+
explorerUrl: getExplorerUrl({
|
|
396
|
+
txHash: destinationMetaTxnReceipt?.txnHash as string,
|
|
397
|
+
chainId: toChainId,
|
|
398
|
+
}),
|
|
399
|
+
receipt: destinationMetaTxnReceipt,
|
|
400
|
+
},
|
|
401
|
+
totalCompletionSeconds,
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return {
|
|
406
|
+
quote,
|
|
407
|
+
swap,
|
|
408
|
+
}
|
|
409
|
+
} catch (error) {
|
|
410
|
+
logger.console.error(
|
|
411
|
+
"[trails-sdk] [useQuote] Error getting quote:",
|
|
412
|
+
error,
|
|
413
|
+
)
|
|
414
|
+
throw getFullErrorMessage(error)
|
|
415
|
+
}
|
|
416
|
+
},
|
|
417
|
+
// Prevent unnecessary refetching
|
|
418
|
+
enabled: Boolean(
|
|
419
|
+
walletClient &&
|
|
420
|
+
trailsClient &&
|
|
421
|
+
fromTokenAddress &&
|
|
422
|
+
toTokenAddress &&
|
|
423
|
+
swapAmount &&
|
|
424
|
+
toRecipient &&
|
|
425
|
+
fromChainId &&
|
|
426
|
+
toChainId &&
|
|
427
|
+
indexerGatewayClient &&
|
|
428
|
+
// !isLoadingTokens &&
|
|
429
|
+
supportedTokens &&
|
|
430
|
+
supportedTokens.length > 0,
|
|
431
|
+
),
|
|
432
|
+
staleTime: 30 * 1000, // Consider data fresh for 30 seconds
|
|
433
|
+
refetchOnWindowFocus: false, // Don't refetch when window regains focus
|
|
434
|
+
refetchOnMount: false, // Don't refetch on component remount if data exists
|
|
435
|
+
refetchInterval: false, // Disable automatic polling
|
|
436
|
+
retry: 2, // Limit retry attempts
|
|
437
|
+
refetchOnReconnect: true, // Refetch when network reconnects
|
|
438
|
+
})
|
|
439
|
+
|
|
440
|
+
return {
|
|
441
|
+
quote: data?.quote || null,
|
|
442
|
+
swap: data?.swap || null,
|
|
443
|
+
isLoadingQuote: isLoading,
|
|
444
|
+
quoteError: error,
|
|
445
|
+
quoteErrorPrettified: getPrettifiedErrorMessage(error),
|
|
446
|
+
refetchQuote: () => refetch(),
|
|
447
|
+
abort: () => {
|
|
448
|
+
logger.console.log("[trails-sdk] useQuote abort() called")
|
|
449
|
+
logger.console.log(
|
|
450
|
+
"[trails-sdk] Active operations before abort:",
|
|
451
|
+
abortControllerRegistry.getAll(),
|
|
452
|
+
)
|
|
453
|
+
|
|
454
|
+
// Abort the internal abort controller
|
|
455
|
+
abortControllerRef.current.abort()
|
|
456
|
+
|
|
457
|
+
// Also abort all active polling operations in prepareSend
|
|
458
|
+
abortControllerRegistry.abortAll()
|
|
459
|
+
|
|
460
|
+
logger.console.log(
|
|
461
|
+
"[trails-sdk] Abort completed, active operations:",
|
|
462
|
+
abortControllerRegistry.getAll(),
|
|
463
|
+
)
|
|
464
|
+
},
|
|
465
|
+
}
|
|
466
|
+
}
|
|
@@ -8,7 +8,19 @@ import React, {
|
|
|
8
8
|
type ReactNode,
|
|
9
9
|
} from "react"
|
|
10
10
|
import { logger } from "../../logger.js"
|
|
11
|
-
import { zeroAddress } from "viem"
|
|
11
|
+
import { ethAddress, zeroAddress } from "viem"
|
|
12
|
+
import { formatUsdAmountDisplay } from "../../tokenBalances.js"
|
|
13
|
+
|
|
14
|
+
const ZERO_ADDRESS = zeroAddress.toLowerCase()
|
|
15
|
+
const ETH_ADDRESS = ethAddress.toLowerCase()
|
|
16
|
+
|
|
17
|
+
const normalizeAddress = (address?: string | null): string =>
|
|
18
|
+
(address ?? "").toLowerCase()
|
|
19
|
+
|
|
20
|
+
const isNativeTokenAddress = (address?: string | null): boolean => {
|
|
21
|
+
const normalized = normalizeAddress(address)
|
|
22
|
+
return normalized === ZERO_ADDRESS || normalized === ETH_ADDRESS
|
|
23
|
+
}
|
|
12
24
|
|
|
13
25
|
// Define the FeeOption interface with balance check properties
|
|
14
26
|
export interface FeeOption {
|
|
@@ -20,6 +32,7 @@ export interface FeeOption {
|
|
|
20
32
|
notEnoughBalance?: boolean
|
|
21
33
|
tokenImageUrl?: string
|
|
22
34
|
chainId?: number
|
|
35
|
+
amountUsdDisplay?: string // Formatted USD display like "≈ $0.39"
|
|
23
36
|
}
|
|
24
37
|
|
|
25
38
|
// Token type with balance information
|
|
@@ -113,13 +126,14 @@ export const SelectedFeeTokenProvider: React.FC<
|
|
|
113
126
|
|
|
114
127
|
// Add balance check and additional properties to each fee option
|
|
115
128
|
const feeOptionsWithBalanceCheck = rawFeeOptions.map((option: any) => {
|
|
116
|
-
// For native token (zero address), check if user has enough native balance
|
|
117
|
-
if (option.tokenAddress
|
|
129
|
+
// For native token (zero/ETH address), check if user has enough native balance
|
|
130
|
+
if (isNativeTokenAddress(option.tokenAddress)) {
|
|
118
131
|
// Find the native token balance for the origin chain
|
|
119
132
|
const nativeTokenInfo = availableTokens.find(
|
|
120
133
|
(token) =>
|
|
121
|
-
token.
|
|
122
|
-
|
|
134
|
+
token.chainId === originTokenChainId &&
|
|
135
|
+
(isNativeTokenAddress(token.contractAddress) ||
|
|
136
|
+
!token.contractAddress),
|
|
123
137
|
)
|
|
124
138
|
|
|
125
139
|
const nativeBalance = nativeTokenInfo?.balance || "0"
|
|
@@ -131,6 +145,8 @@ export const SelectedFeeTokenProvider: React.FC<
|
|
|
131
145
|
notEnoughBalance,
|
|
132
146
|
tokenImageUrl: nativeTokenInfo?.imageUrl,
|
|
133
147
|
chainId: originTokenChainId, // Native token is on the same chain as origin
|
|
148
|
+
amountUsdDisplay: formatUsdAmountDisplay(option.amountUsd),
|
|
149
|
+
amountUSD: option.amountUsd, // Normalize to uppercase for consistency
|
|
134
150
|
}
|
|
135
151
|
}
|
|
136
152
|
|
|
@@ -152,6 +168,8 @@ export const SelectedFeeTokenProvider: React.FC<
|
|
|
152
168
|
notEnoughBalance,
|
|
153
169
|
tokenImageUrl: userTokenBalance.imageUrl,
|
|
154
170
|
chainId: userTokenBalance.chainId, // Use the actual token's chain ID
|
|
171
|
+
amountUsdDisplay: formatUsdAmountDisplay(option.amountUsd),
|
|
172
|
+
amountUSD: option.amountUsd, // Normalize to uppercase for consistency
|
|
155
173
|
}
|
|
156
174
|
}
|
|
157
175
|
|
|
@@ -161,6 +179,8 @@ export const SelectedFeeTokenProvider: React.FC<
|
|
|
161
179
|
notEnoughBalance: true,
|
|
162
180
|
tokenImageUrl: undefined,
|
|
163
181
|
chainId: originTokenChainId, // Fallback to origin chain
|
|
182
|
+
amountUsdDisplay: formatUsdAmountDisplay(option.amountUsd),
|
|
183
|
+
amountUSD: option.amountUsd, // Normalize to uppercase for consistency
|
|
164
184
|
}
|
|
165
185
|
})
|
|
166
186
|
|
|
@@ -184,36 +204,17 @@ export const SelectedFeeTokenProvider: React.FC<
|
|
|
184
204
|
return sortedFeeOptions
|
|
185
205
|
}, [rawFeeOptions, originTokenChainId, availableTokens])
|
|
186
206
|
|
|
187
|
-
// Auto-select first fee option with sufficient balance
|
|
188
|
-
// Only auto-select
|
|
189
|
-
// If no ERC20 fee options are available, selectedFeeToken stays null (native gas)
|
|
207
|
+
// Auto-select first ERC20 fee option with sufficient balance
|
|
208
|
+
// Only auto-select if user hasn't made an explicit selection yet
|
|
190
209
|
useEffect(() => {
|
|
191
|
-
logger.console.log(
|
|
192
|
-
"[trails-sdk] [FEE-SELECT] Auto-selection useEffect triggered:",
|
|
193
|
-
{
|
|
194
|
-
processedFeeOptionsLength: processedFeeOptions.length,
|
|
195
|
-
hasUserSelectedFeeOption,
|
|
196
|
-
selectedFeeToken,
|
|
197
|
-
willAutoSelect:
|
|
198
|
-
processedFeeOptions.length > 0 &&
|
|
199
|
-
!hasUserSelectedFeeOption &&
|
|
200
|
-
!selectedFeeToken,
|
|
201
|
-
},
|
|
202
|
-
)
|
|
203
|
-
|
|
204
|
-
// Only auto-select if:
|
|
205
|
-
// 1. We have fee options
|
|
206
|
-
// 2. User hasn't made an explicit selection yet
|
|
207
|
-
// 3. No fee token is currently selected
|
|
208
210
|
if (
|
|
209
211
|
processedFeeOptions.length > 0 &&
|
|
210
212
|
!hasUserSelectedFeeOption &&
|
|
211
213
|
!selectedFeeToken
|
|
212
214
|
) {
|
|
213
|
-
// Find first
|
|
215
|
+
// Find first token option with sufficient balance
|
|
214
216
|
const firstValidOption = processedFeeOptions.find(
|
|
215
|
-
(option: FeeOption) =>
|
|
216
|
-
option.tokenAddress !== zeroAddress && !option.notEnoughBalance,
|
|
217
|
+
(option: FeeOption) => !option.notEnoughBalance,
|
|
217
218
|
)
|
|
218
219
|
|
|
219
220
|
if (firstValidOption) {
|
|
@@ -221,20 +222,14 @@ export const SelectedFeeTokenProvider: React.FC<
|
|
|
221
222
|
"[trails-sdk] [FEE-SELECT] Auto-selecting first valid fee option:",
|
|
222
223
|
firstValidOption,
|
|
223
224
|
)
|
|
224
|
-
//
|
|
225
|
-
|
|
225
|
+
// Use internal setter to avoid marking as user selection
|
|
226
|
+
setSelectedFeeTokenInternal({
|
|
226
227
|
tokenAddress: firstValidOption.tokenAddress,
|
|
227
228
|
tokenSymbol: firstValidOption.tokenSymbol,
|
|
228
229
|
tokenDecimals: firstValidOption.tokenDecimals,
|
|
229
230
|
amount: firstValidOption.amount,
|
|
230
231
|
amountUSD: firstValidOption.amountUSD,
|
|
231
|
-
}
|
|
232
|
-
// Use internal setter to avoid marking as user selection
|
|
233
|
-
setSelectedFeeTokenInternal(cleanOption)
|
|
234
|
-
} else {
|
|
235
|
-
logger.console.log(
|
|
236
|
-
"[trails-sdk] [FEE-SELECT] No valid ERC20 fee options available, will use native gas",
|
|
237
|
-
)
|
|
232
|
+
})
|
|
238
233
|
}
|
|
239
234
|
}
|
|
240
235
|
}, [
|