0xtrails 0.5.0 → 0.6.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/analytics.d.ts +8 -3
- package/dist/analytics.d.ts.map +1 -1
- package/dist/{ccip-DhEkQ6QC.js → ccip-Dw5AN7oU.js} +1 -1
- package/dist/cctp.d.ts +0 -149
- package/dist/cctp.d.ts.map +1 -1
- package/dist/chains.d.ts +28 -3
- package/dist/chains.d.ts.map +1 -1
- package/dist/config.d.ts +11 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/contractUtils.d.ts.map +1 -1
- package/dist/estimate.d.ts.map +1 -1
- package/dist/fees.d.ts.map +1 -1
- package/dist/gasless.d.ts +12 -0
- package/dist/gasless.d.ts.map +1 -1
- package/dist/{index-MhD2DA7_.js → index-BtVUTbEZ.js} +30984 -38945
- package/dist/index.d.ts +7 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +108 -107
- package/dist/indexerClient.d.ts +2 -2
- package/dist/intents.d.ts +0 -17
- package/dist/intents.d.ts.map +1 -1
- package/dist/mutations.d.ts.map +1 -1
- package/dist/paymasterSend.d.ts.map +1 -1
- package/dist/prepareSend.d.ts +1 -1
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/sendUserOp.d.ts +0 -18
- package/dist/sendUserOp.d.ts.map +1 -1
- package/dist/tokenBalances.d.ts.map +1 -1
- package/dist/tokens.d.ts +10 -8
- package/dist/tokens.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts +4 -5
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/gaslessDeposit.d.ts +4 -5
- package/dist/transactionIntent/deposits/gaslessDeposit.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/standardDeposit.d.ts +2 -2
- package/dist/transactionIntent/deposits/standardDeposit.d.ts.map +1 -1
- package/dist/transactionIntent/execution/transactionState.d.ts +2 -2
- package/dist/transactionIntent/execution/transactionState.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/crossChain.d.ts +4 -4
- package/dist/transactionIntent/handlers/crossChain.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/index.d.ts +0 -1
- package/dist/transactionIntent/handlers/index.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts +4 -34
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts.map +1 -1
- package/dist/transactionIntent/quote/normalizeQuote.d.ts.map +1 -1
- package/dist/transactionIntent/quote/quoteHelpers.d.ts +2 -1
- package/dist/transactionIntent/quote/quoteHelpers.d.ts.map +1 -1
- package/dist/transactionIntent/types.d.ts +6 -19
- package/dist/transactionIntent/types.d.ts.map +1 -1
- package/dist/transactionIntent/utils/index.d.ts +0 -1
- package/dist/transactionIntent/utils/index.d.ts.map +1 -1
- package/dist/transactions.d.ts +2 -20
- package/dist/transactions.d.ts.map +1 -1
- package/dist/utils.d.ts +8 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/walletUtils.d.ts +21 -0
- package/dist/walletUtils.d.ts.map +1 -0
- package/dist/wallets.d.ts +33 -240
- package/dist/wallets.d.ts.map +1 -1
- package/dist/widget/components/AccountIntentTransactionHistory.d.ts.map +1 -1
- package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
- package/dist/widget/components/FeeOption.d.ts +8 -13
- package/dist/widget/components/FeeOption.d.ts.map +1 -1
- package/dist/widget/components/FeeOptions.d.ts +11 -5
- package/dist/widget/components/FeeOptions.d.ts.map +1 -1
- package/dist/widget/components/NativeGasOption.d.ts.map +1 -1
- package/dist/widget/components/Pay.d.ts.map +1 -1
- package/dist/widget/components/PoolDeposit.d.ts.map +1 -1
- package/dist/widget/components/QRCodeDeposit.d.ts +5 -0
- package/dist/widget/components/QRCodeDeposit.d.ts.map +1 -1
- package/dist/widget/components/QRCodeWalletSelect.d.ts +13 -0
- package/dist/widget/components/QRCodeWalletSelect.d.ts.map +1 -0
- package/dist/widget/components/QrCode.d.ts.map +1 -1
- package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
- package/dist/widget/components/Receipt.d.ts.map +1 -1
- package/dist/widget/components/ScreenHeader.d.ts +1 -1
- package/dist/widget/components/ScreenHeader.d.ts.map +1 -1
- package/dist/widget/components/Toast.d.ts.map +1 -1
- package/dist/widget/components/TokenImage.d.ts.map +1 -1
- package/dist/widget/css/compiled.css +1 -1
- package/dist/widget/hooks/useCheckout.d.ts +15 -1
- package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
- package/dist/widget/hooks/useCurrentScreen.d.ts +1 -1
- package/dist/widget/hooks/useCurrentScreen.d.ts.map +1 -1
- package/dist/widget/hooks/useDebugScreens.d.ts +1 -1
- package/dist/widget/hooks/useDebugScreens.d.ts.map +1 -1
- package/dist/widget/hooks/useIntentTransactionHistory.d.ts.map +1 -1
- package/dist/widget/hooks/useIsConnectedWalletSmartContract.d.ts +7 -0
- package/dist/widget/hooks/useIsConnectedWalletSmartContract.d.ts.map +1 -0
- package/dist/widget/hooks/useIsSequenceWallet.d.ts +6 -0
- package/dist/widget/hooks/useIsSequenceWallet.d.ts.map +1 -0
- package/dist/widget/hooks/useQuote.d.ts +5 -8
- package/dist/widget/hooks/useQuote.d.ts.map +1 -1
- package/dist/widget/hooks/useRecentTokens.d.ts.map +1 -1
- package/dist/widget/hooks/useSelectedFeeOption.d.ts +30 -0
- package/dist/widget/hooks/useSelectedFeeOption.d.ts.map +1 -0
- package/dist/widget/hooks/useSendForm.d.ts +6 -15
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
- package/dist/widget/index.js +1 -1
- package/dist/widget/providers/TrailsProvider.d.ts +23 -12
- package/dist/widget/providers/TrailsProvider.d.ts.map +1 -1
- package/dist/widget/widget.d.ts +11 -0
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/analytics.ts +53 -21
- package/src/cctp.ts +0 -1016
- package/src/chains.ts +93 -39
- package/src/config.ts +24 -6
- package/src/constants.ts +1 -4
- package/src/contractUtils.ts +6 -6
- package/src/estimate.ts +3 -6
- package/src/fees.ts +5 -10
- package/src/gasless.ts +45 -0
- package/src/index.ts +7 -6
- package/src/indexerClient.ts +2 -2
- package/src/intents.ts +52 -206
- package/src/mutations.ts +3 -2
- package/src/paymasterSend.ts +2 -5
- package/src/prepareSend.ts +9 -12
- package/src/sendUserOp.ts +3 -64
- package/src/tokenBalances.ts +2 -1
- package/src/tokens.ts +62 -133
- package/src/trailsClient.ts +1 -1
- package/src/transactionIntent/deposits/depositOrchestrator.ts +14 -15
- package/src/transactionIntent/deposits/gaslessDeposit.ts +70 -100
- package/src/transactionIntent/deposits/standardDeposit.ts +22 -28
- package/src/transactionIntent/execution/transactionState.ts +2 -2
- package/src/transactionIntent/handlers/crossChain.ts +165 -385
- package/src/transactionIntent/handlers/index.ts +0 -1
- package/src/transactionIntent/handlers/sameChainSameToken.ts +228 -94
- package/src/transactionIntent/quote/normalizeQuote.ts +4 -6
- package/src/transactionIntent/quote/quoteHelpers.ts +35 -3
- package/src/transactionIntent/types.ts +6 -27
- package/src/transactionIntent/utils/index.ts +0 -1
- package/src/transactions.ts +6 -203
- package/src/umd.tsx +1 -3
- package/src/utils.ts +28 -8
- package/src/walletUtils.ts +42 -0
- package/src/wallets.ts +361 -203
- package/src/widget/compiled.css +1 -1
- package/src/widget/components/AccountIntentTransactionHistory.tsx +73 -4
- package/src/widget/components/AccountSettings.tsx +17 -17
- package/src/widget/components/ChainList.tsx +3 -3
- package/src/widget/components/ClassicSwap.tsx +19 -10
- package/src/widget/components/ConfigDisplay.tsx +1 -1
- package/src/widget/components/FeeOption.tsx +63 -20
- package/src/widget/components/FeeOptions.tsx +54 -123
- package/src/widget/components/NativeGasOption.tsx +3 -1
- package/src/widget/components/Pay.tsx +18 -11
- package/src/widget/components/PoolDeposit.tsx +23 -10
- package/src/widget/components/QRCodeDeposit.tsx +50 -30
- package/src/widget/components/QRCodeWalletSelect.tsx +77 -0
- package/src/widget/components/QrCode.tsx +188 -233
- package/src/widget/components/QuoteDetails.tsx +48 -2
- package/src/widget/components/Receipt.tsx +5 -2
- package/src/widget/components/ScreenHeader.tsx +10 -8
- package/src/widget/components/Toast.tsx +10 -0
- package/src/widget/components/TokenImage.tsx +56 -13
- package/src/widget/hooks/useCheckout.ts +71 -0
- package/src/widget/hooks/useCurrentScreen.tsx +1 -0
- package/src/widget/hooks/useDebugScreens.ts +5 -0
- package/src/widget/hooks/useIntentTransactionHistory.ts +788 -418
- package/src/widget/hooks/useIsConnectedWalletSmartContract.ts +43 -0
- package/src/widget/hooks/useIsSequenceWallet.ts +17 -0
- package/src/widget/hooks/useQuote.ts +16 -17
- package/src/widget/hooks/useRecentTokens.ts +2 -1
- package/src/widget/hooks/useSelectedFeeOption.tsx +257 -0
- package/src/widget/hooks/useSendForm.ts +172 -47
- package/src/widget/hooks/useTokenList.ts +15 -2
- package/src/widget/providers/TrailsProvider.tsx +53 -25
- package/src/widget/widget.tsx +119 -48
- package/dist/cctpqueue.d.ts +0 -18
- package/dist/cctpqueue.d.ts.map +0 -1
- package/dist/preconditions.d.ts +0 -12
- package/dist/preconditions.d.ts.map +0 -1
- package/dist/transactionIntent/handlers/sameChainDifferentToken.d.ts +0 -62
- package/dist/transactionIntent/handlers/sameChainDifferentToken.d.ts.map +0 -1
- package/dist/transactionIntent/utils/lifiHelpers.d.ts +0 -10
- package/dist/transactionIntent/utils/lifiHelpers.d.ts.map +0 -1
- package/dist/widget/hooks/useSelectedFeeToken.d.ts +0 -33
- package/dist/widget/hooks/useSelectedFeeToken.d.ts.map +0 -1
- package/src/cctpqueue.ts +0 -69
- package/src/preconditions.ts +0 -47
- package/src/transactionIntent/handlers/sameChainDifferentToken.ts +0 -323
- package/src/transactionIntent/utils/lifiHelpers.ts +0 -68
- package/src/widget/hooks/useSelectedFeeToken.tsx +0 -288
|
@@ -1,323 +0,0 @@
|
|
|
1
|
-
import type { Account, PublicClient, WalletClient } from "viem"
|
|
2
|
-
import { zeroAddress, decodeFunctionData, erc20Abi, formatUnits } from "viem"
|
|
3
|
-
import type { TransactionState } from "../../transactions.js"
|
|
4
|
-
import type { PrepareSendReturn, SendReturn, TradeType } from "../types.js"
|
|
5
|
-
import { logger } from "../../logger.js"
|
|
6
|
-
import { getIsCustomCalldata } from "../../contractUtils.js"
|
|
7
|
-
import {
|
|
8
|
-
getRelaySDKQuote,
|
|
9
|
-
executeSimpleRelayTransaction,
|
|
10
|
-
getTxHashFromRelayResult,
|
|
11
|
-
type RelayTradeType,
|
|
12
|
-
} from "../../relaySdk.js"
|
|
13
|
-
import { getNormalizedQuoteObject } from "../quote/normalizeQuote.js"
|
|
14
|
-
import {
|
|
15
|
-
getFeesFromRelaySdkQuote,
|
|
16
|
-
getSlippageToleranceFromRelaySdkQuote,
|
|
17
|
-
getPriceImpactFromRelaySdkQuote,
|
|
18
|
-
getPriceImpactUsdFromRelaySdkQuote,
|
|
19
|
-
} from "../quote/feeExtractors.js"
|
|
20
|
-
import { checkAccountBalance } from "../utils/balanceChecker.js"
|
|
21
|
-
import { attemptSwitchChain } from "../../chainSwitch.js"
|
|
22
|
-
import { getTransactionStateFromReceipt } from "../execution/transactionState.js"
|
|
23
|
-
import { calcAmountUsdPrice } from "../../prices.js"
|
|
24
|
-
import { trackPaymentCompleted, trackPaymentError } from "../../analytics.js"
|
|
25
|
-
import { TradeType as LocalTradeType } from "../types.js"
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @description
|
|
29
|
-
* This handler manages same-chain token swaps (e.g., ETH to WETH on the same chain).
|
|
30
|
-
* It leverages the Relay SDK for quote and transaction execution.
|
|
31
|
-
*
|
|
32
|
-
* Key characteristics:
|
|
33
|
-
* - Uses Relay SDK directly for quote fetching and transaction execution
|
|
34
|
-
* - Single transaction leg (swap on origin chain)
|
|
35
|
-
* - No cross-chain bridging required
|
|
36
|
-
* - Supports various token pair combinations on the same chain
|
|
37
|
-
*
|
|
38
|
-
* Transaction Flow:
|
|
39
|
-
* 1. Fetch quote via getRelaySDKQuote (Relay SDK API)
|
|
40
|
-
* 2. Create intent via createIntent (Intent object created)
|
|
41
|
-
* 3. Execute swap via executeSimpleRelayTransaction (User submits swap transaction)
|
|
42
|
-
* 4. Monitor via waitIntentReceipt API for transaction completion
|
|
43
|
-
* 5. Update transaction state and invoke callbacks
|
|
44
|
-
*
|
|
45
|
-
* Relay SDK Integration:
|
|
46
|
-
* - Direct integration with Relay SDK for quote and transaction submission
|
|
47
|
-
* - Transaction hash extracted via getTxHashFromRelayResult
|
|
48
|
-
* - Receipt polling via Trails API for consistent monitoring
|
|
49
|
-
*
|
|
50
|
-
* Error Handling:
|
|
51
|
-
* - Balance validation before transaction submission
|
|
52
|
-
* - Chain switching if user is on wrong network
|
|
53
|
-
* - Relay SDK error handling with proper error propagation
|
|
54
|
-
* - Checkout error callbacks for UI feedback
|
|
55
|
-
*
|
|
56
|
-
* State Management:
|
|
57
|
-
* - transactionStates[0]: Swap transaction
|
|
58
|
-
* - Updates propagated via onTransactionStateChange callback
|
|
59
|
-
* - Analytics tracking for payment completion or errors
|
|
60
|
-
*/
|
|
61
|
-
export async function handleSameChainDifferentToken({
|
|
62
|
-
originTokenAddress,
|
|
63
|
-
originTokenDecimals,
|
|
64
|
-
swapAmount,
|
|
65
|
-
destinationTokenAddress,
|
|
66
|
-
destinationTokenDecimals,
|
|
67
|
-
destinationCalldata,
|
|
68
|
-
recipient,
|
|
69
|
-
originChainId,
|
|
70
|
-
walletClient,
|
|
71
|
-
publicClient,
|
|
72
|
-
account,
|
|
73
|
-
tradeType = LocalTradeType.EXACT_OUTPUT,
|
|
74
|
-
slippageTolerance,
|
|
75
|
-
onTransactionStateChange,
|
|
76
|
-
transactionStates,
|
|
77
|
-
sourceTokenPriceUsd,
|
|
78
|
-
destinationTokenPriceUsd,
|
|
79
|
-
originNativeTokenPriceUsd,
|
|
80
|
-
mode,
|
|
81
|
-
fundMethod,
|
|
82
|
-
originTokenSymbol,
|
|
83
|
-
destinationTokenSymbol,
|
|
84
|
-
}: {
|
|
85
|
-
originTokenAddress: string
|
|
86
|
-
originTokenDecimals: number
|
|
87
|
-
swapAmount: string
|
|
88
|
-
destinationTokenAddress: string
|
|
89
|
-
destinationTokenDecimals: number
|
|
90
|
-
destinationCalldata?: string
|
|
91
|
-
recipient: string
|
|
92
|
-
originChainId: number
|
|
93
|
-
walletClient: WalletClient
|
|
94
|
-
publicClient: PublicClient
|
|
95
|
-
account: Account
|
|
96
|
-
tradeType?: TradeType
|
|
97
|
-
slippageTolerance?: string
|
|
98
|
-
onTransactionStateChange: (transactionStates: TransactionState[]) => void
|
|
99
|
-
transactionStates: TransactionState[]
|
|
100
|
-
sourceTokenPriceUsd?: number | null
|
|
101
|
-
destinationTokenPriceUsd?: number | null
|
|
102
|
-
originNativeTokenPriceUsd?: number | null
|
|
103
|
-
mode?: "pay" | "fund" | "earn" | "swap" | "receive"
|
|
104
|
-
fundMethod?: string
|
|
105
|
-
originTokenSymbol: string
|
|
106
|
-
destinationTokenSymbol: string
|
|
107
|
-
}): Promise<PrepareSendReturn> {
|
|
108
|
-
const destinationTxs: { to: string; value: string; data: string }[] = []
|
|
109
|
-
const hasCustomCalldata = getIsCustomCalldata(destinationCalldata)
|
|
110
|
-
if (hasCustomCalldata && tradeType === LocalTradeType.EXACT_OUTPUT) {
|
|
111
|
-
destinationTxs.push({
|
|
112
|
-
to: recipient,
|
|
113
|
-
value: destinationTokenAddress === zeroAddress ? swapAmount : "0",
|
|
114
|
-
data: destinationCalldata as `0x${string}`,
|
|
115
|
-
})
|
|
116
|
-
} else if (hasCustomCalldata && tradeType === LocalTradeType.EXACT_INPUT) {
|
|
117
|
-
destinationTxs.push({
|
|
118
|
-
to: recipient,
|
|
119
|
-
value: "0",
|
|
120
|
-
data: destinationCalldata as `0x${string}`,
|
|
121
|
-
})
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const quote = await getRelaySDKQuote({
|
|
125
|
-
wallet: walletClient,
|
|
126
|
-
chainId: originChainId,
|
|
127
|
-
amount: swapAmount,
|
|
128
|
-
currency: originTokenAddress,
|
|
129
|
-
toCurrency: destinationTokenAddress,
|
|
130
|
-
txs: destinationTxs,
|
|
131
|
-
tradeType: tradeType as unknown as RelayTradeType,
|
|
132
|
-
slippageTolerance: slippageTolerance,
|
|
133
|
-
recipient: hasCustomCalldata ? recipient : undefined,
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
logger.console.log("[trails-sdk] relaysdk quote", quote)
|
|
137
|
-
let depositAmount = "0"
|
|
138
|
-
let destinationTokenAmount = "0"
|
|
139
|
-
|
|
140
|
-
if (tradeType === LocalTradeType.EXACT_INPUT) {
|
|
141
|
-
depositAmount = swapAmount
|
|
142
|
-
destinationTokenAmount = quote?.details?.currencyOut?.amount?.toString()
|
|
143
|
-
} else {
|
|
144
|
-
try {
|
|
145
|
-
destinationTokenAmount = swapAmount
|
|
146
|
-
depositAmount = quote.steps?.[0]?.items?.[0]?.data?.value
|
|
147
|
-
if (originTokenAddress !== zeroAddress) {
|
|
148
|
-
const decoded = decodeFunctionData({
|
|
149
|
-
abi: erc20Abi,
|
|
150
|
-
data: quote.steps?.[0]?.items?.[0]?.data?.data,
|
|
151
|
-
})
|
|
152
|
-
if (decoded.functionName === "approve") {
|
|
153
|
-
depositAmount = decoded.args[1].toString()
|
|
154
|
-
}
|
|
155
|
-
if (decoded.functionName === "transfer") {
|
|
156
|
-
depositAmount = decoded.args[1].toString()
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
} catch (error) {
|
|
160
|
-
logger.console.error("[trails-sdk] Error decoding function data:", error)
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
const depositOriginAddress =
|
|
165
|
-
quote?.steps?.[quote?.steps?.length - 1]?.items?.[
|
|
166
|
-
quote?.steps?.[quote?.steps?.length - 1]?.items?.length - 1
|
|
167
|
-
]?.data?.to
|
|
168
|
-
|
|
169
|
-
if (
|
|
170
|
-
quote?.details?.currencyIn?.amountFormatted &&
|
|
171
|
-
quote?.details?.currencyIn?.amountUsd
|
|
172
|
-
) {
|
|
173
|
-
const quoteProviderSourceTokenPriceUsd =
|
|
174
|
-
Number(quote.details.currencyIn.amountUsd) /
|
|
175
|
-
Number(quote.details.currencyIn.amountFormatted)
|
|
176
|
-
if (quoteProviderSourceTokenPriceUsd) {
|
|
177
|
-
sourceTokenPriceUsd = quoteProviderSourceTokenPriceUsd
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
if (
|
|
182
|
-
quote?.details?.currencyOut?.amountFormatted &&
|
|
183
|
-
quote?.details?.currencyOut?.amountUsd
|
|
184
|
-
) {
|
|
185
|
-
const quoteProviderDestinationTokenPriceUsd =
|
|
186
|
-
Number(quote.details.currencyOut.amountUsd) /
|
|
187
|
-
Number(quote.details.currencyOut.amountFormatted)
|
|
188
|
-
if (quoteProviderDestinationTokenPriceUsd) {
|
|
189
|
-
destinationTokenPriceUsd = quoteProviderDestinationTokenPriceUsd
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const normalizedQuote = await getNormalizedQuoteObject({
|
|
194
|
-
originDepositAddress: depositOriginAddress,
|
|
195
|
-
destinationDepositAddress: recipient,
|
|
196
|
-
destinationAddress: recipient,
|
|
197
|
-
destinationCalldata,
|
|
198
|
-
originAmount: depositAmount,
|
|
199
|
-
destinationAmount: destinationTokenAmount,
|
|
200
|
-
originTokenAddress: originTokenAddress,
|
|
201
|
-
destinationTokenAddress: destinationTokenAddress,
|
|
202
|
-
originTokenPriceUsd: sourceTokenPriceUsd?.toString() || null,
|
|
203
|
-
destinationTokenPriceUsd: destinationTokenPriceUsd?.toString() || null,
|
|
204
|
-
fees: getFeesFromRelaySdkQuote(quote),
|
|
205
|
-
slippageTolerance: getSlippageToleranceFromRelaySdkQuote(quote),
|
|
206
|
-
priceImpact: getPriceImpactFromRelaySdkQuote(quote),
|
|
207
|
-
priceImpactUsd: getPriceImpactUsdFromRelaySdkQuote(quote),
|
|
208
|
-
transactionStates,
|
|
209
|
-
originChainId,
|
|
210
|
-
destinationChainId: originChainId,
|
|
211
|
-
originNativeTokenPriceUsd,
|
|
212
|
-
quoteProvider: "relay",
|
|
213
|
-
intent: undefined,
|
|
214
|
-
})
|
|
215
|
-
|
|
216
|
-
return {
|
|
217
|
-
quote: normalizedQuote,
|
|
218
|
-
send: async ({
|
|
219
|
-
onOriginSend,
|
|
220
|
-
}: {
|
|
221
|
-
onOriginSend?: () => void
|
|
222
|
-
}): Promise<SendReturn> => {
|
|
223
|
-
const { hasEnoughBalance, balanceError } = await checkAccountBalance({
|
|
224
|
-
account,
|
|
225
|
-
tokenAddress: originTokenAddress,
|
|
226
|
-
depositAmount,
|
|
227
|
-
publicClient,
|
|
228
|
-
})
|
|
229
|
-
|
|
230
|
-
if (!hasEnoughBalance) {
|
|
231
|
-
throw balanceError
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
await attemptSwitchChain({
|
|
235
|
-
walletClient,
|
|
236
|
-
desiredChainId: originChainId,
|
|
237
|
-
})
|
|
238
|
-
|
|
239
|
-
const result = await executeSimpleRelayTransaction(quote, walletClient)
|
|
240
|
-
logger.console.log("[trails-sdk] relaysdk result", result)
|
|
241
|
-
|
|
242
|
-
const txHash = getTxHashFromRelayResult(result)
|
|
243
|
-
|
|
244
|
-
if (onOriginSend) {
|
|
245
|
-
onOriginSend()
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
const depositUserTxnReceipt =
|
|
249
|
-
await publicClient.waitForTransactionReceipt({
|
|
250
|
-
hash: txHash as `0x${string}`,
|
|
251
|
-
})
|
|
252
|
-
|
|
253
|
-
transactionStates[0] = getTransactionStateFromReceipt(
|
|
254
|
-
depositUserTxnReceipt,
|
|
255
|
-
originChainId,
|
|
256
|
-
transactionStates[0]?.label,
|
|
257
|
-
)
|
|
258
|
-
|
|
259
|
-
try {
|
|
260
|
-
onTransactionStateChange(transactionStates)
|
|
261
|
-
} catch (error) {
|
|
262
|
-
logger.console.error(
|
|
263
|
-
"[trails-sdk] Error calling onTransactionStateChange:",
|
|
264
|
-
error,
|
|
265
|
-
)
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
const depositAmountFormatted = Number(
|
|
269
|
-
formatUnits(BigInt(depositAmount), originTokenDecimals),
|
|
270
|
-
)
|
|
271
|
-
|
|
272
|
-
const depositAmountUsd = calcAmountUsdPrice({
|
|
273
|
-
amount: depositAmountFormatted,
|
|
274
|
-
usdPrice: sourceTokenPriceUsd,
|
|
275
|
-
})
|
|
276
|
-
|
|
277
|
-
const destinationTokenAmountFormatted = Number(
|
|
278
|
-
formatUnits(BigInt(destinationTokenAmount), destinationTokenDecimals),
|
|
279
|
-
)
|
|
280
|
-
|
|
281
|
-
const destinationTokenAmountUsd = calcAmountUsdPrice({
|
|
282
|
-
amount: Number(destinationTokenAmountFormatted),
|
|
283
|
-
usdPrice: destinationTokenPriceUsd,
|
|
284
|
-
})
|
|
285
|
-
|
|
286
|
-
// Track payment completion for same-chain different-token transaction
|
|
287
|
-
if (depositUserTxnReceipt && depositUserTxnReceipt.status === "success") {
|
|
288
|
-
trackPaymentCompleted({
|
|
289
|
-
userAddress: account.address,
|
|
290
|
-
originTxHash: depositUserTxnReceipt.transactionHash,
|
|
291
|
-
originChainId,
|
|
292
|
-
destinationChainId: originChainId, // Same chain
|
|
293
|
-
mode,
|
|
294
|
-
fundMethod,
|
|
295
|
-
originTokenAddress,
|
|
296
|
-
originTokenSymbol,
|
|
297
|
-
destinationTokenAddress,
|
|
298
|
-
destinationTokenSymbol,
|
|
299
|
-
depositTokenAmountUsd: depositAmountUsd?.toString(),
|
|
300
|
-
destinationTokenAmountUsd: destinationTokenAmountUsd?.toString(),
|
|
301
|
-
})
|
|
302
|
-
} else if (depositUserTxnReceipt) {
|
|
303
|
-
trackPaymentError({
|
|
304
|
-
error: "Relay transaction failed",
|
|
305
|
-
userAddress: account.address,
|
|
306
|
-
mode,
|
|
307
|
-
fundMethod,
|
|
308
|
-
originTokenAddress,
|
|
309
|
-
originTokenSymbol,
|
|
310
|
-
destinationTokenAddress,
|
|
311
|
-
destinationTokenSymbol,
|
|
312
|
-
})
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
return {
|
|
316
|
-
depositUserTxnReceipt: depositUserTxnReceipt,
|
|
317
|
-
originMetaTxnReceipt: null,
|
|
318
|
-
destinationMetaTxnReceipt: null,
|
|
319
|
-
totalCompletionSeconds: 0,
|
|
320
|
-
}
|
|
321
|
-
},
|
|
322
|
-
}
|
|
323
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { formatUnits, zeroAddress } from "viem"
|
|
2
|
-
import { calcAmountUsdPrice } from "../../prices.js"
|
|
3
|
-
import { logger } from "../../logger.js"
|
|
4
|
-
|
|
5
|
-
// ETH fee required by some bridges for low token amounts
|
|
6
|
-
// TODO: update backend API to return the native fee requirement, if any
|
|
7
|
-
export function getNeedsLifiNativeFee({
|
|
8
|
-
originTokenAddress,
|
|
9
|
-
destinationTokenAmount,
|
|
10
|
-
destinationTokenDecimals,
|
|
11
|
-
sourceTokenDecimals,
|
|
12
|
-
sourceTokenPriceUsd,
|
|
13
|
-
destinationTokenPriceUsd,
|
|
14
|
-
depositAmount,
|
|
15
|
-
}: {
|
|
16
|
-
originTokenAddress: string
|
|
17
|
-
destinationTokenAmount: string
|
|
18
|
-
destinationTokenDecimals: number
|
|
19
|
-
sourceTokenDecimals: number
|
|
20
|
-
sourceTokenPriceUsd: number | null
|
|
21
|
-
destinationTokenPriceUsd: number | null
|
|
22
|
-
depositAmount: string
|
|
23
|
-
}): boolean {
|
|
24
|
-
let needsNativeFee = false
|
|
25
|
-
if (
|
|
26
|
-
originTokenAddress !== zeroAddress &&
|
|
27
|
-
sourceTokenPriceUsd &&
|
|
28
|
-
destinationTokenPriceUsd &&
|
|
29
|
-
depositAmount &&
|
|
30
|
-
destinationTokenDecimals !== undefined &&
|
|
31
|
-
sourceTokenDecimals !== undefined
|
|
32
|
-
) {
|
|
33
|
-
// Convert from wei to token units using formatUnits
|
|
34
|
-
const destinationAmount = Number(
|
|
35
|
-
formatUnits(BigInt(destinationTokenAmount), destinationTokenDecimals),
|
|
36
|
-
)
|
|
37
|
-
const depositAmountFormatted = Number(
|
|
38
|
-
formatUnits(BigInt(depositAmount), sourceTokenDecimals),
|
|
39
|
-
)
|
|
40
|
-
logger.console.log("[trails-sdk] destinationAmount", destinationAmount)
|
|
41
|
-
logger.console.log(
|
|
42
|
-
"[trails-sdk] depositAmountFormatted",
|
|
43
|
-
depositAmountFormatted,
|
|
44
|
-
)
|
|
45
|
-
const destinationAmountUsd = calcAmountUsdPrice({
|
|
46
|
-
amount: destinationAmount,
|
|
47
|
-
usdPrice: destinationTokenPriceUsd,
|
|
48
|
-
})
|
|
49
|
-
const depositAmountUsd = calcAmountUsdPrice({
|
|
50
|
-
amount: depositAmountFormatted,
|
|
51
|
-
usdPrice: sourceTokenPriceUsd,
|
|
52
|
-
})
|
|
53
|
-
const diff = depositAmountUsd - destinationAmountUsd
|
|
54
|
-
logger.console.log(
|
|
55
|
-
"[trails-sdk] destinationAmountUsd",
|
|
56
|
-
destinationAmountUsd,
|
|
57
|
-
"[trails-sdk] depositAmountUsd",
|
|
58
|
-
depositAmountUsd,
|
|
59
|
-
"[trails-sdk] diff",
|
|
60
|
-
diff,
|
|
61
|
-
)
|
|
62
|
-
if (diff >= 0 && diff <= 0.02) {
|
|
63
|
-
needsNativeFee = true
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return needsNativeFee
|
|
68
|
-
}
|
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
createContext,
|
|
3
|
-
useContext,
|
|
4
|
-
useState,
|
|
5
|
-
useCallback,
|
|
6
|
-
useEffect,
|
|
7
|
-
useMemo,
|
|
8
|
-
type ReactNode,
|
|
9
|
-
} from "react"
|
|
10
|
-
import { logger } from "../../logger.js"
|
|
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
|
-
}
|
|
24
|
-
|
|
25
|
-
// Define the FeeOption interface with balance check properties
|
|
26
|
-
export interface FeeOption {
|
|
27
|
-
tokenAddress: string
|
|
28
|
-
tokenSymbol: string
|
|
29
|
-
tokenDecimals: number
|
|
30
|
-
amount: string
|
|
31
|
-
amountUSD: number
|
|
32
|
-
notEnoughBalance?: boolean
|
|
33
|
-
tokenImageUrl?: string
|
|
34
|
-
chainId?: number
|
|
35
|
-
amountUsdDisplay?: string // Formatted USD display like "≈ $0.39"
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Token type with balance information
|
|
39
|
-
export interface TokenWithBalance {
|
|
40
|
-
chainId: number
|
|
41
|
-
contractAddress?: string
|
|
42
|
-
balance?: string
|
|
43
|
-
imageUrl?: string
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
interface SelectedFeeTokenContextType {
|
|
47
|
-
selectedFeeToken: FeeOption | null
|
|
48
|
-
setSelectedFeeToken: (token: FeeOption | null) => void
|
|
49
|
-
clearSelectedFeeToken: () => void
|
|
50
|
-
processedFeeOptions: FeeOption[]
|
|
51
|
-
setRawFeeOptions: (
|
|
52
|
-
feeOptions: any[] | null | undefined,
|
|
53
|
-
originChainId: number | undefined,
|
|
54
|
-
availableTokens: TokenWithBalance[],
|
|
55
|
-
) => void
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const SelectedFeeTokenContext = createContext<
|
|
59
|
-
SelectedFeeTokenContextType | undefined
|
|
60
|
-
>(undefined)
|
|
61
|
-
|
|
62
|
-
interface SelectedFeeTokenProviderProps {
|
|
63
|
-
children: ReactNode
|
|
64
|
-
initialToken?: FeeOption | null
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export const SelectedFeeTokenProvider: React.FC<
|
|
68
|
-
SelectedFeeTokenProviderProps
|
|
69
|
-
> = ({ children, initialToken = null }) => {
|
|
70
|
-
const [selectedFeeToken, setSelectedFeeTokenInternalRaw] =
|
|
71
|
-
useState<FeeOption | null>(initialToken)
|
|
72
|
-
const [hasUserSelectedFeeOption, setHasUserSelectedFeeOption] =
|
|
73
|
-
useState(false)
|
|
74
|
-
const [rawFeeOptions, setRawFeeOptionsInternal] = useState<any[]>([])
|
|
75
|
-
const [originTokenChainId, setOriginTokenChainId] = useState<
|
|
76
|
-
number | undefined
|
|
77
|
-
>(undefined)
|
|
78
|
-
const [availableTokens, setAvailableTokens] = useState<TokenWithBalance[]>([])
|
|
79
|
-
|
|
80
|
-
// Wrapper to log all state changes to selectedFeeToken
|
|
81
|
-
const setSelectedFeeTokenInternal = useCallback((token: FeeOption | null) => {
|
|
82
|
-
logger.console.log(
|
|
83
|
-
"[trails-sdk] [FEE-SELECT] selectedFeeToken state changing:",
|
|
84
|
-
{
|
|
85
|
-
to: token,
|
|
86
|
-
toNull: token === null,
|
|
87
|
-
},
|
|
88
|
-
)
|
|
89
|
-
setSelectedFeeTokenInternalRaw(token)
|
|
90
|
-
}, [])
|
|
91
|
-
|
|
92
|
-
// Wrapper to track when user makes an explicit selection
|
|
93
|
-
const setSelectedFeeToken = useCallback(
|
|
94
|
-
(token: FeeOption | null) => {
|
|
95
|
-
logger.console.log(
|
|
96
|
-
"[trails-sdk] [FEE-SELECT] setSelectedFeeToken called (user selection):",
|
|
97
|
-
{
|
|
98
|
-
token,
|
|
99
|
-
isNull: token === null,
|
|
100
|
-
isUndefined: token === undefined,
|
|
101
|
-
},
|
|
102
|
-
)
|
|
103
|
-
setSelectedFeeTokenInternal(token)
|
|
104
|
-
setHasUserSelectedFeeOption(true)
|
|
105
|
-
},
|
|
106
|
-
[setSelectedFeeTokenInternal],
|
|
107
|
-
)
|
|
108
|
-
|
|
109
|
-
const clearSelectedFeeToken = useCallback(() => {
|
|
110
|
-
logger.console.log("[trails-sdk] [FEE-SELECT] Clearing selected fee token")
|
|
111
|
-
setSelectedFeeTokenInternal(null)
|
|
112
|
-
setHasUserSelectedFeeOption(false)
|
|
113
|
-
}, [setSelectedFeeTokenInternal])
|
|
114
|
-
|
|
115
|
-
// Process raw fee options with balance checks
|
|
116
|
-
const processedFeeOptions = useMemo(() => {
|
|
117
|
-
if (!rawFeeOptions || rawFeeOptions.length === 0) {
|
|
118
|
-
return []
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
logger.console.log("[trails-sdk] [FEE-SELECT] Processing fee options:", {
|
|
122
|
-
rawFeeOptions,
|
|
123
|
-
originTokenChainId,
|
|
124
|
-
availableTokensCount: availableTokens.length,
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
// Add balance check and additional properties to each fee option
|
|
128
|
-
const feeOptionsWithBalanceCheck = rawFeeOptions.map((option: any) => {
|
|
129
|
-
// For native token (zero/ETH address), check if user has enough native balance
|
|
130
|
-
if (isNativeTokenAddress(option.tokenAddress)) {
|
|
131
|
-
// Find the native token balance for the origin chain
|
|
132
|
-
const nativeTokenInfo = availableTokens.find(
|
|
133
|
-
(token) =>
|
|
134
|
-
token.chainId === originTokenChainId &&
|
|
135
|
-
(isNativeTokenAddress(token.contractAddress) ||
|
|
136
|
-
!token.contractAddress),
|
|
137
|
-
)
|
|
138
|
-
|
|
139
|
-
const nativeBalance = nativeTokenInfo?.balance || "0"
|
|
140
|
-
const requiredAmount = option.amount
|
|
141
|
-
const notEnoughBalance = BigInt(nativeBalance) < BigInt(requiredAmount)
|
|
142
|
-
|
|
143
|
-
return {
|
|
144
|
-
...option,
|
|
145
|
-
notEnoughBalance,
|
|
146
|
-
tokenImageUrl: nativeTokenInfo?.imageUrl,
|
|
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
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// For ERC-20 tokens, check user's token balances
|
|
154
|
-
const userTokenBalance = availableTokens.find(
|
|
155
|
-
(token) =>
|
|
156
|
-
token.contractAddress?.toLowerCase() ===
|
|
157
|
-
option.tokenAddress.toLowerCase() &&
|
|
158
|
-
token.chainId === originTokenChainId,
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
if (userTokenBalance) {
|
|
162
|
-
const userBalance = userTokenBalance.balance || "0"
|
|
163
|
-
const requiredAmount = option.amount
|
|
164
|
-
const notEnoughBalance = BigInt(userBalance) < BigInt(requiredAmount)
|
|
165
|
-
|
|
166
|
-
return {
|
|
167
|
-
...option,
|
|
168
|
-
notEnoughBalance,
|
|
169
|
-
tokenImageUrl: userTokenBalance.imageUrl,
|
|
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
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// If token balance not found, assume insufficient balance
|
|
177
|
-
return {
|
|
178
|
-
...option,
|
|
179
|
-
notEnoughBalance: true,
|
|
180
|
-
tokenImageUrl: undefined,
|
|
181
|
-
chainId: originTokenChainId, // Fallback to origin chain
|
|
182
|
-
amountUsdDisplay: formatUsdAmountDisplay(option.amountUsd),
|
|
183
|
-
amountUSD: option.amountUsd, // Normalize to uppercase for consistency
|
|
184
|
-
}
|
|
185
|
-
})
|
|
186
|
-
|
|
187
|
-
// Sort fee options: available options first, then disabled options at the bottom
|
|
188
|
-
const sortedFeeOptions = feeOptionsWithBalanceCheck.sort(
|
|
189
|
-
(a: FeeOption, b: FeeOption) => {
|
|
190
|
-
// If both have the same balance status, maintain original order
|
|
191
|
-
if (a.notEnoughBalance === b.notEnoughBalance) {
|
|
192
|
-
return 0
|
|
193
|
-
}
|
|
194
|
-
// Put available options (notEnoughBalance: false) before disabled options (notEnoughBalance: true)
|
|
195
|
-
return a.notEnoughBalance ? 1 : -1
|
|
196
|
-
},
|
|
197
|
-
)
|
|
198
|
-
|
|
199
|
-
logger.console.log(
|
|
200
|
-
"[trails-sdk] [FEE-SELECT] Processed and sorted fee options:",
|
|
201
|
-
sortedFeeOptions,
|
|
202
|
-
)
|
|
203
|
-
|
|
204
|
-
return sortedFeeOptions
|
|
205
|
-
}, [rawFeeOptions, originTokenChainId, availableTokens])
|
|
206
|
-
|
|
207
|
-
// Auto-select first ERC20 fee option with sufficient balance
|
|
208
|
-
// Only auto-select if user hasn't made an explicit selection yet
|
|
209
|
-
useEffect(() => {
|
|
210
|
-
if (
|
|
211
|
-
processedFeeOptions.length > 0 &&
|
|
212
|
-
!hasUserSelectedFeeOption &&
|
|
213
|
-
!selectedFeeToken
|
|
214
|
-
) {
|
|
215
|
-
// Find first token option with sufficient balance
|
|
216
|
-
const firstValidOption = processedFeeOptions.find(
|
|
217
|
-
(option: FeeOption) => !option.notEnoughBalance,
|
|
218
|
-
)
|
|
219
|
-
|
|
220
|
-
if (firstValidOption) {
|
|
221
|
-
logger.console.log(
|
|
222
|
-
"[trails-sdk] [FEE-SELECT] Auto-selecting first valid fee option:",
|
|
223
|
-
firstValidOption,
|
|
224
|
-
)
|
|
225
|
-
// Use internal setter to avoid marking as user selection
|
|
226
|
-
setSelectedFeeTokenInternal({
|
|
227
|
-
tokenAddress: firstValidOption.tokenAddress,
|
|
228
|
-
tokenSymbol: firstValidOption.tokenSymbol,
|
|
229
|
-
tokenDecimals: firstValidOption.tokenDecimals,
|
|
230
|
-
amount: firstValidOption.amount,
|
|
231
|
-
amountUSD: firstValidOption.amountUSD,
|
|
232
|
-
})
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}, [
|
|
236
|
-
processedFeeOptions,
|
|
237
|
-
selectedFeeToken,
|
|
238
|
-
hasUserSelectedFeeOption,
|
|
239
|
-
setSelectedFeeTokenInternal,
|
|
240
|
-
])
|
|
241
|
-
|
|
242
|
-
// Function to set raw fee options and process them
|
|
243
|
-
const setRawFeeOptions = useCallback(
|
|
244
|
-
(
|
|
245
|
-
feeOptions: any[] | null | undefined,
|
|
246
|
-
originChainId: number | undefined,
|
|
247
|
-
tokens: TokenWithBalance[],
|
|
248
|
-
) => {
|
|
249
|
-
const apiFeeOptions = feeOptions ?? []
|
|
250
|
-
setRawFeeOptionsInternal(apiFeeOptions)
|
|
251
|
-
setOriginTokenChainId(originChainId)
|
|
252
|
-
setAvailableTokens(tokens)
|
|
253
|
-
|
|
254
|
-
logger.console.log("[trails-sdk] [FEE-SELECT] Raw fee options set:", {
|
|
255
|
-
feeOptionsCount: apiFeeOptions.length,
|
|
256
|
-
originChainId: originChainId,
|
|
257
|
-
tokensCount: tokens.length,
|
|
258
|
-
})
|
|
259
|
-
},
|
|
260
|
-
[],
|
|
261
|
-
)
|
|
262
|
-
|
|
263
|
-
const value: SelectedFeeTokenContextType = {
|
|
264
|
-
selectedFeeToken,
|
|
265
|
-
setSelectedFeeToken,
|
|
266
|
-
clearSelectedFeeToken,
|
|
267
|
-
processedFeeOptions,
|
|
268
|
-
setRawFeeOptions,
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
return (
|
|
272
|
-
<SelectedFeeTokenContext.Provider value={value}>
|
|
273
|
-
{children}
|
|
274
|
-
</SelectedFeeTokenContext.Provider>
|
|
275
|
-
)
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
export const useSelectedFeeToken = (): SelectedFeeTokenContextType => {
|
|
279
|
-
const context = useContext(SelectedFeeTokenContext)
|
|
280
|
-
|
|
281
|
-
if (context === undefined) {
|
|
282
|
-
throw new Error(
|
|
283
|
-
"useSelectedFeeToken must be used within a SelectedFeeTokenProvider",
|
|
284
|
-
)
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
return context
|
|
288
|
-
}
|