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
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
import type { Account, Chain, WalletClient } from "viem"
|
|
2
|
+
import {
|
|
3
|
+
createPublicClient,
|
|
4
|
+
ethAddress,
|
|
5
|
+
http,
|
|
6
|
+
maxUint256,
|
|
7
|
+
zeroAddress,
|
|
8
|
+
} from "viem"
|
|
9
|
+
import type {
|
|
10
|
+
TrailsAPIClient,
|
|
11
|
+
GasFeeOptions,
|
|
12
|
+
FeeOption,
|
|
13
|
+
DepositSignature,
|
|
14
|
+
ExecuteIntentResponse,
|
|
15
|
+
} from "@0xsequence/trails-api"
|
|
16
|
+
import type { SelectedFeeToken } from "../types.js"
|
|
17
|
+
import type { CheckoutOnHandlers } from "../../widget/hooks/useCheckout.js"
|
|
18
|
+
import type { TransactionState } from "../../transactions.js"
|
|
19
|
+
import { logger } from "../../logger.js"
|
|
20
|
+
import { attemptSwitchChain } from "../../chainSwitch.js"
|
|
21
|
+
import { getTransactionStateFromReceipt } from "../execution/transactionState.js"
|
|
22
|
+
import {
|
|
23
|
+
getDelegatorSmartAccount,
|
|
24
|
+
getPaymasterGaslessTransaction,
|
|
25
|
+
sendPaymasterGaslessTransaction,
|
|
26
|
+
} from "../../paymasterSend.js"
|
|
27
|
+
import { TRAILS_INTENT_ENTRYPOINT_ADDRESS } from "../../constants.js"
|
|
28
|
+
import {
|
|
29
|
+
getNeedsIntentEntrypointApproval,
|
|
30
|
+
getUserNonce,
|
|
31
|
+
signIntent,
|
|
32
|
+
getPermitSignature,
|
|
33
|
+
} from "../../gasless.js"
|
|
34
|
+
|
|
35
|
+
export async function attemptGaslessDeposit({
|
|
36
|
+
paymasterUrl,
|
|
37
|
+
depositTokenAddress,
|
|
38
|
+
depositTokenAmount,
|
|
39
|
+
depositRecipient,
|
|
40
|
+
onOriginSend,
|
|
41
|
+
walletClient,
|
|
42
|
+
chain,
|
|
43
|
+
account,
|
|
44
|
+
trailsClient,
|
|
45
|
+
feeOptions,
|
|
46
|
+
selectedFeeToken,
|
|
47
|
+
checkoutOnHandlers,
|
|
48
|
+
intentId,
|
|
49
|
+
onTransactionStateChange,
|
|
50
|
+
transactionStates,
|
|
51
|
+
executeIntentFn,
|
|
52
|
+
}: {
|
|
53
|
+
paymasterUrl?: string
|
|
54
|
+
depositTokenAddress: string
|
|
55
|
+
depositTokenAmount: string
|
|
56
|
+
depositRecipient: string
|
|
57
|
+
onOriginSend?: () => void
|
|
58
|
+
walletClient: WalletClient
|
|
59
|
+
chain: Chain
|
|
60
|
+
account: Account
|
|
61
|
+
trailsClient: TrailsAPIClient
|
|
62
|
+
feeOptions?: GasFeeOptions
|
|
63
|
+
selectedFeeToken?: SelectedFeeToken
|
|
64
|
+
abortSignal?: AbortSignal
|
|
65
|
+
checkoutOnHandlers?: CheckoutOnHandlers
|
|
66
|
+
intentId?: string
|
|
67
|
+
onTransactionStateChange?: (transactionStates: TransactionState[]) => void
|
|
68
|
+
transactionStates?: TransactionState[]
|
|
69
|
+
executeIntentFn?: (params: {
|
|
70
|
+
intentId: string
|
|
71
|
+
depositTransactionHash?: string
|
|
72
|
+
depositSignature?: DepositSignature
|
|
73
|
+
}) => Promise<ExecuteIntentResponse>
|
|
74
|
+
}): Promise<void> {
|
|
75
|
+
const originChainId = chain.id
|
|
76
|
+
|
|
77
|
+
logger.console.log(
|
|
78
|
+
"[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] attemptGaslessDeposit called with:",
|
|
79
|
+
{
|
|
80
|
+
originChainId,
|
|
81
|
+
depositTokenAddress,
|
|
82
|
+
depositTokenAmount,
|
|
83
|
+
depositRecipient,
|
|
84
|
+
hasFeeOptions: !!feeOptions,
|
|
85
|
+
feeOptionsLength: feeOptions?.feeOptions?.length,
|
|
86
|
+
selectedFeeToken,
|
|
87
|
+
hasSelectedFeeToken: !!selectedFeeToken,
|
|
88
|
+
paymasterUrl,
|
|
89
|
+
},
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
const publicClient = createPublicClient({
|
|
93
|
+
chain,
|
|
94
|
+
transport: http(),
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
logger.console.log("[trails-sdk] [GASLESS-FLOW] Intent entrypoint check:", {
|
|
98
|
+
chainId: chain.id,
|
|
99
|
+
chainName: chain.name,
|
|
100
|
+
intentEntrypoint: TRAILS_INTENT_ENTRYPOINT_ADDRESS,
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
// NEW FLOW: Use Intent Entrypoint API with permit2 support
|
|
104
|
+
logger.console.log(
|
|
105
|
+
"[trails-sdk] Using Intent Entrypoint API flow with permit2 support for gasless deposit",
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
// Switch to correct chain before requesting signatures
|
|
109
|
+
logger.console.log(
|
|
110
|
+
"[trails-sdk] [GASLESS-FLOW] Switching to chain before permit/intent signatures",
|
|
111
|
+
{ originChainId },
|
|
112
|
+
)
|
|
113
|
+
await attemptSwitchChain({
|
|
114
|
+
walletClient,
|
|
115
|
+
desiredChainId: originChainId,
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
if (paymasterUrl) {
|
|
120
|
+
logger.console.log(
|
|
121
|
+
"[trails-sdk] [GASLESS-FLOW] doing gasless with paymaster",
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
// Switch to correct chain before requesting signatures
|
|
125
|
+
logger.console.log(
|
|
126
|
+
"[trails-sdk] [GASLESS-FLOW] Switching chain for paymaster flow",
|
|
127
|
+
)
|
|
128
|
+
await attemptSwitchChain({
|
|
129
|
+
walletClient,
|
|
130
|
+
desiredChainId: originChainId,
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
const delegatorSmartAccount = await getDelegatorSmartAccount({
|
|
134
|
+
publicClient,
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
const calls: Array<{
|
|
138
|
+
to: string
|
|
139
|
+
data: string
|
|
140
|
+
value: string
|
|
141
|
+
}> = await getPaymasterGaslessTransaction({
|
|
142
|
+
walletClient,
|
|
143
|
+
chain,
|
|
144
|
+
tokenAddress: depositTokenAddress as `0x${string}`,
|
|
145
|
+
amount: BigInt(depositTokenAmount),
|
|
146
|
+
recipient: depositRecipient as `0x${string}`,
|
|
147
|
+
delegatorSmartAccount,
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
logger.console.log("[trails-sdk] calls", calls)
|
|
151
|
+
|
|
152
|
+
// Trigger signature request callback before prompting wallet
|
|
153
|
+
if (checkoutOnHandlers?.triggerCheckoutSignatureRequest) {
|
|
154
|
+
checkoutOnHandlers.triggerCheckoutSignatureRequest()
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const txHash = await sendPaymasterGaslessTransaction({
|
|
158
|
+
walletClient,
|
|
159
|
+
publicClient,
|
|
160
|
+
chain,
|
|
161
|
+
paymasterUrl,
|
|
162
|
+
delegatorSmartAccount,
|
|
163
|
+
calls,
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
// Trigger signature confirmed callback after successful signing
|
|
167
|
+
if (checkoutOnHandlers?.triggerCheckoutSignatureConfirmed) {
|
|
168
|
+
checkoutOnHandlers.triggerCheckoutSignatureConfirmed()
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (onOriginSend) {
|
|
172
|
+
onOriginSend()
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Update transaction state to pending with hash for paymaster flow
|
|
176
|
+
if (transactionStates?.[0] && onTransactionStateChange) {
|
|
177
|
+
transactionStates[0].state = "pending"
|
|
178
|
+
transactionStates[0].transactionHash = txHash
|
|
179
|
+
|
|
180
|
+
try {
|
|
181
|
+
onTransactionStateChange(transactionStates)
|
|
182
|
+
} catch (error) {
|
|
183
|
+
logger.console.error(
|
|
184
|
+
"[trails-sdk] Error calling onTransactionStateChange:",
|
|
185
|
+
error,
|
|
186
|
+
)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const receipt = await publicClient.waitForTransactionReceipt({
|
|
191
|
+
hash: txHash as `0x${string}`,
|
|
192
|
+
})
|
|
193
|
+
logger.console.log("[trails-sdk] receipt", receipt)
|
|
194
|
+
|
|
195
|
+
// Update transaction state to confirmed after receipt is obtained
|
|
196
|
+
if (transactionStates?.[0] && onTransactionStateChange && receipt) {
|
|
197
|
+
transactionStates[0] = getTransactionStateFromReceipt(
|
|
198
|
+
receipt,
|
|
199
|
+
chain.id,
|
|
200
|
+
transactionStates[0]?.label,
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
try {
|
|
204
|
+
onTransactionStateChange(transactionStates)
|
|
205
|
+
} catch (error) {
|
|
206
|
+
logger.console.error(
|
|
207
|
+
"[trails-sdk] Error calling onTransactionStateChange:",
|
|
208
|
+
error,
|
|
209
|
+
)
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const deadline = Math.floor(Date.now() / 1000) + 3600 // 1 hour from now
|
|
217
|
+
const hasFeeOptions = Boolean(
|
|
218
|
+
feeOptions && feeOptions.feeOptions?.length > 0,
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
// 1. Check if we need approval - check if we have enough allowance for this transaction (deposit + fee if same token)
|
|
222
|
+
let requiredAmount = BigInt(depositTokenAmount)
|
|
223
|
+
|
|
224
|
+
// Match selectedFeeToken by tokenAddress to get the latest fee amount from feeOptions
|
|
225
|
+
let selectedFeeOption: FeeOption | null = null
|
|
226
|
+
if (selectedFeeToken && hasFeeOptions && feeOptions) {
|
|
227
|
+
// Find matching fee option by tokenAddress to get latest amount
|
|
228
|
+
selectedFeeOption =
|
|
229
|
+
feeOptions.feeOptions.find(
|
|
230
|
+
(opt) =>
|
|
231
|
+
opt.tokenAddress?.toLowerCase() ===
|
|
232
|
+
selectedFeeToken.tokenAddress?.toLowerCase(),
|
|
233
|
+
) || null
|
|
234
|
+
logger.console.log(
|
|
235
|
+
"[trails-sdk] Matched selectedFeeToken to latest fee option:",
|
|
236
|
+
{
|
|
237
|
+
selectedFeeToken,
|
|
238
|
+
matchedOption: selectedFeeOption,
|
|
239
|
+
},
|
|
240
|
+
)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Fallback to first fee option if no match or no selectedFeeToken
|
|
244
|
+
if (!selectedFeeOption && hasFeeOptions && feeOptions) {
|
|
245
|
+
selectedFeeOption = feeOptions.feeOptions[0] || null
|
|
246
|
+
logger.console.log(
|
|
247
|
+
"[trails-sdk] Using first fee option as fallback:",
|
|
248
|
+
selectedFeeOption,
|
|
249
|
+
)
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Only include fee in required amount if the fee token is the same as the deposit token
|
|
253
|
+
if (selectedFeeOption?.amount && selectedFeeOption?.tokenAddress) {
|
|
254
|
+
const feeTokenIsSameAsDepositToken =
|
|
255
|
+
selectedFeeOption.tokenAddress.toLowerCase() ===
|
|
256
|
+
depositTokenAddress.toLowerCase()
|
|
257
|
+
|
|
258
|
+
if (feeTokenIsSameAsDepositToken) {
|
|
259
|
+
requiredAmount = requiredAmount + BigInt(selectedFeeOption.amount)
|
|
260
|
+
logger.console.log(
|
|
261
|
+
"[trails-sdk] Fee token matches deposit token, including fee in required approval amount:",
|
|
262
|
+
{
|
|
263
|
+
depositAmount: depositTokenAmount,
|
|
264
|
+
feeAmount: selectedFeeOption.amount,
|
|
265
|
+
feeTokenAddress: selectedFeeOption.tokenAddress,
|
|
266
|
+
depositTokenAddress,
|
|
267
|
+
totalRequired: requiredAmount.toString(),
|
|
268
|
+
},
|
|
269
|
+
)
|
|
270
|
+
} else {
|
|
271
|
+
logger.console.log(
|
|
272
|
+
"[trails-sdk] Fee token differs from deposit token, separate approval will be needed:",
|
|
273
|
+
{
|
|
274
|
+
depositAmount: depositTokenAmount,
|
|
275
|
+
depositTokenAddress,
|
|
276
|
+
feeAmount: selectedFeeOption.amount,
|
|
277
|
+
feeTokenAddress: selectedFeeOption.tokenAddress,
|
|
278
|
+
depositTokenRequired: requiredAmount.toString(),
|
|
279
|
+
},
|
|
280
|
+
)
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const needsApproval = await getNeedsIntentEntrypointApproval({
|
|
285
|
+
client: publicClient,
|
|
286
|
+
token: depositTokenAddress as `0x${string}`,
|
|
287
|
+
account: account.address,
|
|
288
|
+
entrypoint: TRAILS_INTENT_ENTRYPOINT_ADDRESS,
|
|
289
|
+
amount: requiredAmount, // Check if we have enough allowance for this specific transaction
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
logger.console.log(
|
|
293
|
+
"[trails-sdk] [GASLESS-FLOW] Checking permit requirements",
|
|
294
|
+
{
|
|
295
|
+
userAddress: account.address,
|
|
296
|
+
tokenAddress: depositTokenAddress,
|
|
297
|
+
depositAmount: depositTokenAmount,
|
|
298
|
+
requiredAmount: requiredAmount.toString(),
|
|
299
|
+
intentAddress: depositRecipient,
|
|
300
|
+
chainID: originChainId,
|
|
301
|
+
deadline,
|
|
302
|
+
needsApproval,
|
|
303
|
+
},
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
// 2. Get permit signature if approval needed for deposit token
|
|
307
|
+
// Note: Fee payment is handled by the backend/relayer, we only need permit for the deposit token
|
|
308
|
+
let permitSignature: string | undefined
|
|
309
|
+
let permitDeadline: number | undefined
|
|
310
|
+
|
|
311
|
+
if (needsApproval) {
|
|
312
|
+
logger.console.log(
|
|
313
|
+
"[trails-sdk] Getting permit signature for deposit token infinite approval",
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
// Use infinite approval (maxUint256) so user doesn't need to approve again
|
|
317
|
+
const permitAmount = maxUint256
|
|
318
|
+
logger.console.log(
|
|
319
|
+
"[trails-sdk] Using infinite approval for gasless deposits",
|
|
320
|
+
{
|
|
321
|
+
depositAmount: depositTokenAmount,
|
|
322
|
+
depositTokenAddress,
|
|
323
|
+
permitAmount: permitAmount.toString(),
|
|
324
|
+
},
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
const permitSig = await getPermitSignature({
|
|
328
|
+
publicClient,
|
|
329
|
+
walletClient,
|
|
330
|
+
signer: account.address,
|
|
331
|
+
spender: TRAILS_INTENT_ENTRYPOINT_ADDRESS,
|
|
332
|
+
tokenAddress: depositTokenAddress as `0x${string}`,
|
|
333
|
+
amount: permitAmount, // Infinite approval
|
|
334
|
+
chain,
|
|
335
|
+
deadline: BigInt(deadline),
|
|
336
|
+
})
|
|
337
|
+
permitSignature = permitSig.signature
|
|
338
|
+
permitDeadline = Number(permitSig.deadline)
|
|
339
|
+
logger.console.log(
|
|
340
|
+
"[trails-sdk] Deposit token permit signature obtained for infinite approval",
|
|
341
|
+
)
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// 3. Get current nonce for the user
|
|
345
|
+
logger.console.log("[trails-sdk] Getting user nonce")
|
|
346
|
+
const nonce = await getUserNonce({
|
|
347
|
+
publicClient,
|
|
348
|
+
userAddress: account.address,
|
|
349
|
+
intentEntrypoint: TRAILS_INTENT_ENTRYPOINT_ADDRESS,
|
|
350
|
+
})
|
|
351
|
+
logger.console.log("[trails-sdk] User nonce:", nonce.toString())
|
|
352
|
+
|
|
353
|
+
// 4. Get intent signature
|
|
354
|
+
logger.console.log("[trails-sdk] Requesting intent signature via EIP-712")
|
|
355
|
+
// Get fee collector address from the new schema:
|
|
356
|
+
// Priority: selectedFeeOption.feeCollectorAddress > feeOptions.feeCollectorAddress
|
|
357
|
+
const feeCollectorAddress = (selectedFeeOption?.feeCollectorAddress ||
|
|
358
|
+
feeOptions?.feeCollectorAddress) as `0x${string}` | undefined
|
|
359
|
+
|
|
360
|
+
// Validate that we have a valid fee collector address
|
|
361
|
+
if (!feeCollectorAddress || feeCollectorAddress === zeroAddress) {
|
|
362
|
+
throw new Error(
|
|
363
|
+
"[trails-sdk] Fee collector address not provided by API. Cannot proceed with gasless deposit. " +
|
|
364
|
+
"Please ensure the API is returning feeCollectorAddress in the gasFeeOptions response.",
|
|
365
|
+
)
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
logger.console.log(
|
|
369
|
+
"[trails-sdk] Using fee collector address:",
|
|
370
|
+
feeCollectorAddress,
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
// Trigger signature request callback before prompting wallet
|
|
374
|
+
if (checkoutOnHandlers?.triggerCheckoutSignatureRequest) {
|
|
375
|
+
checkoutOnHandlers.triggerCheckoutSignatureRequest()
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const { signature: intentSignature } = await signIntent({
|
|
379
|
+
client: walletClient,
|
|
380
|
+
intentParams: {
|
|
381
|
+
user: account.address,
|
|
382
|
+
token: depositTokenAddress as `0x${string}`,
|
|
383
|
+
amount: BigInt(depositTokenAmount),
|
|
384
|
+
intentAddress: depositRecipient as `0x${string}`,
|
|
385
|
+
deadline: BigInt(deadline),
|
|
386
|
+
chainId: originChainId,
|
|
387
|
+
contractAddress: TRAILS_INTENT_ENTRYPOINT_ADDRESS,
|
|
388
|
+
nonce,
|
|
389
|
+
feeAmount: BigInt(selectedFeeOption?.amount || "0"),
|
|
390
|
+
feeCollector: feeCollectorAddress,
|
|
391
|
+
},
|
|
392
|
+
})
|
|
393
|
+
logger.console.log("[trails-sdk] Intent signature received")
|
|
394
|
+
|
|
395
|
+
// Trigger signature confirmed callback after successful signing
|
|
396
|
+
if (checkoutOnHandlers?.triggerCheckoutSignatureConfirmed) {
|
|
397
|
+
checkoutOnHandlers.triggerCheckoutSignatureConfirmed()
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// 5. Call the deposit endpoint with permit support and optional fee
|
|
401
|
+
logger.console.log(
|
|
402
|
+
"[trails-sdk] Calling executeIntent with depositSignature",
|
|
403
|
+
{
|
|
404
|
+
usePermit: needsApproval,
|
|
405
|
+
hasFee: !!feeOptions,
|
|
406
|
+
hasIntentId: !!intentId,
|
|
407
|
+
},
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
// Validate that we have the intentId
|
|
411
|
+
if (!intentId) {
|
|
412
|
+
throw new Error(
|
|
413
|
+
"[trails-sdk] intentId is required for gasless deposits. " +
|
|
414
|
+
"The calling code must commit the intent first using commitIntent() and pass the intentId.",
|
|
415
|
+
)
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Validate that we have a selected fee option
|
|
419
|
+
if (!selectedFeeOption) {
|
|
420
|
+
throw new Error(
|
|
421
|
+
"[trails-sdk] selectedFeeOption is required for gasless deposits",
|
|
422
|
+
)
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// Build depositSignature for executeIntent with all required fields
|
|
426
|
+
const depositSignature = {
|
|
427
|
+
intentSignature,
|
|
428
|
+
permitSignature: needsApproval ? permitSignature : undefined,
|
|
429
|
+
permitDeadline: needsApproval ? permitDeadline : undefined,
|
|
430
|
+
permitAmount: needsApproval ? maxUint256 : undefined,
|
|
431
|
+
selectedGasFeeOption: selectedFeeOption,
|
|
432
|
+
userNonce: Number(nonce),
|
|
433
|
+
deadline,
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
logger.console.log(
|
|
437
|
+
"[trails-sdk] Executing intent with gasless deposit signature",
|
|
438
|
+
{ intentId, depositSignature },
|
|
439
|
+
)
|
|
440
|
+
|
|
441
|
+
// executeIntent will handle submitting to the relayer
|
|
442
|
+
// The backend processes the deposit signature and relays the transaction
|
|
443
|
+
const executeIntentFnToUse =
|
|
444
|
+
executeIntentFn || trailsClient.executeIntent.bind(trailsClient)
|
|
445
|
+
await executeIntentFnToUse({
|
|
446
|
+
intentId,
|
|
447
|
+
depositSignature,
|
|
448
|
+
})
|
|
449
|
+
|
|
450
|
+
logger.console.log(
|
|
451
|
+
"[trails-sdk] Intent execution submitted to backend. Transaction monitoring should happen via intent status polling.",
|
|
452
|
+
)
|
|
453
|
+
|
|
454
|
+
if (onOriginSend) {
|
|
455
|
+
onOriginSend()
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Update transaction state to pending for non-paymaster gasless flow
|
|
459
|
+
// Hash will be filled in later by the poller when backend confirms transaction
|
|
460
|
+
if (transactionStates?.[0] && onTransactionStateChange) {
|
|
461
|
+
transactionStates[0].state = "pending"
|
|
462
|
+
// transactionHash remains empty - will be updated by onDepositTransactionFound callback
|
|
463
|
+
|
|
464
|
+
try {
|
|
465
|
+
onTransactionStateChange(transactionStates)
|
|
466
|
+
} catch (error) {
|
|
467
|
+
logger.console.error(
|
|
468
|
+
"[trails-sdk] Error calling onTransactionStateChange:",
|
|
469
|
+
error,
|
|
470
|
+
)
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
} catch (error) {
|
|
474
|
+
logger.console.error(
|
|
475
|
+
"[trails-sdk] Error in Intent Entrypoint gasless deposit with permit2:",
|
|
476
|
+
error,
|
|
477
|
+
)
|
|
478
|
+
throw error
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
export function getDoGasless(
|
|
483
|
+
originTokenAddress: string,
|
|
484
|
+
feeOptions?: GasFeeOptions,
|
|
485
|
+
selectedFeeToken?: SelectedFeeToken,
|
|
486
|
+
walletId?: string,
|
|
487
|
+
): boolean {
|
|
488
|
+
// Don't use gasless flow for sequence-waas wallet
|
|
489
|
+
if (walletId === "sequence-waas") {
|
|
490
|
+
logger.console.log(
|
|
491
|
+
"[trails-sdk] [GASLESS-FLOW] getDoGasless: Skipping gasless flow for sequence-waas wallet",
|
|
492
|
+
)
|
|
493
|
+
return false
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
const hasFeeOptions = Boolean(feeOptions && feeOptions.feeOptions?.length > 0)
|
|
497
|
+
|
|
498
|
+
// Important: The UI passes selectedFeeToken in these states:
|
|
499
|
+
// - null: User explicitly chose "Pay with native gas"
|
|
500
|
+
// - {object}: User selected a fee token OR it was auto-selected
|
|
501
|
+
// - undefined: Should not happen (initial state auto-selects if options exist)
|
|
502
|
+
|
|
503
|
+
// If selectedFeeToken is null, user explicitly chose native gas
|
|
504
|
+
if (selectedFeeToken === null) {
|
|
505
|
+
logger.console.log(
|
|
506
|
+
"[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] getDoGasless: User explicitly selected native gas (null)",
|
|
507
|
+
)
|
|
508
|
+
return false
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// If selectedFeeToken is undefined and no fee options, can't do gasless
|
|
512
|
+
if (!selectedFeeToken && !hasFeeOptions) {
|
|
513
|
+
logger.console.log(
|
|
514
|
+
"[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] getDoGasless: No fee token selected and no fee options available",
|
|
515
|
+
)
|
|
516
|
+
return false
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// If selectedFeeToken is undefined but fee options exist, use first ERC20 option
|
|
520
|
+
let effectiveFeeToken = selectedFeeToken
|
|
521
|
+
if (!effectiveFeeToken && hasFeeOptions && feeOptions) {
|
|
522
|
+
const firstFeeOption = feeOptions.feeOptions[0]
|
|
523
|
+
|
|
524
|
+
// Check if first option is native gas
|
|
525
|
+
const isFirstOptionNative =
|
|
526
|
+
firstFeeOption?.tokenAddress === zeroAddress ||
|
|
527
|
+
firstFeeOption?.tokenAddress?.toLowerCase() === zeroAddress ||
|
|
528
|
+
firstFeeOption?.tokenAddress === ethAddress ||
|
|
529
|
+
firstFeeOption?.tokenAddress?.toLowerCase() === ethAddress.toLowerCase()
|
|
530
|
+
|
|
531
|
+
if (!isFirstOptionNative && firstFeeOption?.tokenAddress) {
|
|
532
|
+
// First fee option is ERC20, use it
|
|
533
|
+
effectiveFeeToken = firstFeeOption
|
|
534
|
+
logger.console.log(
|
|
535
|
+
"[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] getDoGasless: No fee token selected, using first ERC20 fee option",
|
|
536
|
+
{
|
|
537
|
+
feeOption: effectiveFeeToken,
|
|
538
|
+
},
|
|
539
|
+
)
|
|
540
|
+
} else {
|
|
541
|
+
logger.console.log(
|
|
542
|
+
"[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] getDoGasless: First fee option is native gas, skipping gasless",
|
|
543
|
+
)
|
|
544
|
+
return false
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// Check if the effective fee token is native gas
|
|
549
|
+
const isNativeGasFee =
|
|
550
|
+
!effectiveFeeToken ||
|
|
551
|
+
effectiveFeeToken.tokenAddress === zeroAddress ||
|
|
552
|
+
effectiveFeeToken.tokenAddress?.toLowerCase() === zeroAddress ||
|
|
553
|
+
effectiveFeeToken.tokenAddress === ethAddress ||
|
|
554
|
+
effectiveFeeToken.tokenAddress?.toLowerCase() === ethAddress.toLowerCase()
|
|
555
|
+
|
|
556
|
+
// Don't use gasless if origin token is native (sending ETH)
|
|
557
|
+
if (originTokenAddress === zeroAddress) {
|
|
558
|
+
logger.console.log(
|
|
559
|
+
"[trails-sdk] [GASLESS-FLOW] getDoGasless: Origin token is native, skipping gasless",
|
|
560
|
+
)
|
|
561
|
+
return false
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// Don't use gasless if fee token is native
|
|
565
|
+
if (isNativeGasFee) {
|
|
566
|
+
logger.console.log(
|
|
567
|
+
"[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] getDoGasless: Fee token is native gas, skipping gasless",
|
|
568
|
+
{
|
|
569
|
+
effectiveFeeToken,
|
|
570
|
+
},
|
|
571
|
+
)
|
|
572
|
+
return false
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// All conditions met, use gasless with ERC20 fee token
|
|
576
|
+
logger.console.log(
|
|
577
|
+
"[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] getDoGasless decision: Using gasless",
|
|
578
|
+
{
|
|
579
|
+
originTokenAddress,
|
|
580
|
+
hasFeeOptions,
|
|
581
|
+
selectedFeeToken,
|
|
582
|
+
effectiveFeeToken,
|
|
583
|
+
feeOptionsCount: feeOptions?.feeOptions?.length || 0,
|
|
584
|
+
},
|
|
585
|
+
)
|
|
586
|
+
|
|
587
|
+
return true
|
|
588
|
+
}
|