0xtrails 0.2.2 → 0.2.5
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 +8 -0
- package/dist/aave.d.ts.map +1 -1
- package/dist/{ccip-ConT1gDe.js → ccip-CXlshvBY.js} +1 -1
- package/dist/chains.d.ts +5 -1
- package/dist/chains.d.ts.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/constants.d.ts +5 -4
- package/dist/constants.d.ts.map +1 -1
- package/dist/error.d.ts +1 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/estimate.d.ts +52 -0
- package/dist/estimate.d.ts.map +1 -1
- package/dist/{index-CMh8uEbV.js → index-_QuyGrjU.js} +86304 -83380
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/intentEntrypoint.d.ts +0 -8
- package/dist/intentEntrypoint.d.ts.map +1 -1
- package/dist/intents.d.ts +40 -0
- package/dist/intents.d.ts.map +1 -1
- package/dist/metaTxnMonitor.d.ts +5 -4
- package/dist/metaTxnMonitor.d.ts.map +1 -1
- package/dist/metaTxns.d.ts +3 -3
- package/dist/metaTxns.d.ts.map +1 -1
- package/dist/morpho.d.ts +8 -0
- package/dist/morpho.d.ts.map +1 -1
- package/dist/prepareSend.d.ts +16 -6
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/queryParams.d.ts.map +1 -1
- package/dist/relayer.d.ts +10 -7
- package/dist/relayer.d.ts.map +1 -1
- package/dist/sequenceWallet.d.ts +3 -2
- package/dist/sequenceWallet.d.ts.map +1 -1
- package/dist/tokenBalances.d.ts +7 -0
- package/dist/tokenBalances.d.ts.map +1 -1
- package/dist/tokens.d.ts +2 -1
- package/dist/tokens.d.ts.map +1 -1
- package/dist/trails.d.ts +2 -2
- package/dist/trails.d.ts.map +1 -1
- package/dist/wallets.d.ts.map +1 -1
- package/dist/widget/components/AccountActionsDropdown.d.ts.map +1 -1
- package/dist/widget/components/AccountSettings.d.ts.map +1 -1
- package/dist/widget/components/ClassicSwap.d.ts +2 -0
- package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
- package/dist/widget/components/ConnectWallet.d.ts.map +1 -1
- package/dist/widget/components/ConnectedWallets.d.ts +4 -0
- package/dist/widget/components/ConnectedWallets.d.ts.map +1 -1
- package/dist/widget/components/Earn.d.ts.map +1 -1
- package/dist/widget/components/EarnPools.d.ts.map +1 -1
- package/dist/widget/components/Fund.d.ts +1 -0
- package/dist/widget/components/Fund.d.ts.map +1 -1
- package/dist/widget/components/FundMethods.d.ts.map +1 -1
- package/dist/widget/components/{FundSendForm.d.ts → FundSwap.d.ts} +11 -5
- package/dist/widget/components/FundSwap.d.ts.map +1 -0
- package/dist/widget/components/FundingMethodSelectorButton.d.ts +4 -0
- package/dist/widget/components/FundingMethodSelectorButton.d.ts.map +1 -0
- package/dist/widget/components/Modal.d.ts.map +1 -1
- package/dist/widget/components/Pay.d.ts +1 -0
- package/dist/widget/components/Pay.d.ts.map +1 -1
- package/dist/widget/components/PercentageMaxButtons.d.ts +12 -0
- package/dist/widget/components/PercentageMaxButtons.d.ts.map +1 -0
- package/dist/widget/components/{PaySendForm.d.ts → PoolDeposit.d.ts} +11 -34
- package/dist/widget/components/PoolDeposit.d.ts.map +1 -0
- package/dist/widget/components/{SimpleSwap.d.ts → PoolWithdraw.d.ts} +16 -8
- package/dist/widget/components/PoolWithdraw.d.ts.map +1 -0
- package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
- package/dist/widget/components/Receive.d.ts.map +1 -1
- package/dist/widget/components/RecipientSelectorButton.d.ts +4 -0
- package/dist/widget/components/RecipientSelectorButton.d.ts.map +1 -0
- package/dist/widget/components/Recipients.d.ts.map +1 -1
- package/dist/widget/components/RefundWarning.d.ts +1 -0
- package/dist/widget/components/RefundWarning.d.ts.map +1 -1
- package/dist/widget/components/RequiredPropsError.d.ts +8 -0
- package/dist/widget/components/RequiredPropsError.d.ts.map +1 -0
- package/dist/widget/components/ScreenHeader.d.ts.map +1 -1
- package/dist/widget/components/SlippageToleranceSettings.d.ts.map +1 -1
- package/dist/widget/components/Swap.d.ts +1 -0
- package/dist/widget/components/Swap.d.ts.map +1 -1
- package/dist/widget/components/SwapSettings.d.ts.map +1 -1
- package/dist/widget/components/TokenImage.d.ts +1 -0
- package/dist/widget/components/TokenImage.d.ts.map +1 -1
- package/dist/widget/components/TokenList.d.ts.map +1 -1
- package/dist/widget/components/TokenSelector.d.ts.map +1 -1
- package/dist/widget/components/TokenSelectorButton.d.ts +16 -0
- package/dist/widget/components/TokenSelectorButton.d.ts.map +1 -0
- package/dist/widget/components/UserPreferences.d.ts.map +1 -1
- package/dist/widget/components/WaasFeeOptions.d.ts +8 -0
- package/dist/widget/components/WaasFeeOptions.d.ts.map +1 -0
- package/dist/widget/components/WalletConfirmation.d.ts.map +1 -1
- package/dist/widget/components/WalletList.d.ts.map +1 -1
- package/dist/widget/css/compiled.css +2 -0
- package/dist/widget/css/index.css +554 -0
- package/dist/widget/hooks/useBack.d.ts +6 -0
- package/dist/widget/hooks/useBack.d.ts.map +1 -1
- package/dist/widget/hooks/useCheckout.d.ts +1 -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/useDefaultTokenSelection.d.ts +3 -3
- package/dist/widget/hooks/useDefaultTokenSelection.d.ts.map +1 -1
- package/dist/widget/hooks/useInitialRedirect.d.ts +7 -0
- package/dist/widget/hooks/useInitialRedirect.d.ts.map +1 -0
- package/dist/widget/hooks/usePayMessage.d.ts.map +1 -1
- package/dist/widget/hooks/useSelectedFeeToken.d.ts.map +1 -1
- package/dist/widget/hooks/useSelectedFundMethod.d.ts +12 -0
- package/dist/widget/hooks/useSelectedFundMethod.d.ts.map +1 -0
- package/dist/widget/hooks/useSelectedRecipient.d.ts.map +1 -1
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- package/dist/widget/index.js +1 -1
- package/dist/widget/widget.d.ts +4 -4
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +30 -23
- package/src/aave.ts +32 -0
- package/src/chains.ts +23 -3
- package/src/config.ts +12 -4
- package/src/constants.ts +11 -16
- package/src/error.ts +20 -2
- package/src/estimate.ts +416 -5
- package/src/index.ts +8 -3
- package/src/intentEntrypoint.ts +0 -15
- package/src/intents.ts +161 -11
- package/src/metaTxnMonitor.ts +28 -22
- package/src/metaTxns.ts +3 -3
- package/src/morpho.ts +32 -0
- package/src/prepareSend.ts +710 -458
- package/src/queryParams.ts +2 -1
- package/src/relayer.ts +15 -16
- package/src/sequenceWallet.ts +7 -3
- package/src/tokenBalances.ts +47 -0
- package/src/tokens.ts +17 -1
- package/src/trails.ts +2 -2
- package/src/wallets.ts +8 -0
- package/src/widget/compiled.css +2 -2
- package/src/widget/components/AccountActionsDropdown.tsx +9 -15
- package/src/widget/components/AccountIntentTransactionHistory.tsx +1 -1
- package/src/widget/components/AccountSettings.tsx +10 -27
- package/src/widget/components/ChainFilterDropdown.tsx +1 -1
- package/src/widget/components/ChainList.tsx +1 -1
- package/src/widget/components/ClassicSwap.tsx +111 -155
- package/src/widget/components/ConnectWallet.tsx +10 -39
- package/src/widget/components/ConnectedWallets.tsx +113 -58
- package/src/widget/components/Earn.tsx +73 -589
- package/src/widget/components/EarnPools.tsx +2 -1
- package/src/widget/components/Fund.tsx +81 -109
- package/src/widget/components/FundMethods.tsx +82 -159
- package/src/widget/components/FundSwap.tsx +52 -0
- package/src/widget/components/FundingMethodSelectorButton.tsx +60 -0
- package/src/widget/components/Modal.tsx +6 -2
- package/src/widget/components/Pay.tsx +198 -200
- package/src/widget/components/PercentageMaxButtons.tsx +77 -0
- package/src/widget/components/PoolDeposit.tsx +593 -0
- package/src/widget/components/PoolWithdraw.tsx +903 -0
- package/src/widget/components/QuoteDetails.tsx +22 -8
- package/src/widget/components/Receive.tsx +1 -3
- package/src/widget/components/RecipientSelectorButton.tsx +42 -0
- package/src/widget/components/Recipients.tsx +64 -156
- package/src/widget/components/RefundWarning.tsx +5 -1
- package/src/widget/components/RequiredPropsError.tsx +33 -0
- package/src/widget/components/ScreenHeader.tsx +5 -1
- package/src/widget/components/SlippageToleranceSettings.tsx +2 -1
- package/src/widget/components/Swap.tsx +2 -43
- package/src/widget/components/SwapSettings.tsx +3 -15
- package/src/widget/components/TokenImage.tsx +21 -4
- package/src/widget/components/TokenList.tsx +0 -1
- package/src/widget/components/TokenSelector.tsx +2 -1
- package/src/widget/components/TokenSelectorButton.tsx +75 -0
- package/src/widget/components/UserPreferences.tsx +6 -24
- package/src/widget/components/WaasFeeOptions.tsx +331 -0
- package/src/widget/components/WalletConfirmation.tsx +55 -3
- package/src/widget/components/WalletList.tsx +7 -5
- package/src/widget/hooks/useBack.tsx +113 -9
- package/src/widget/hooks/useCheckout.ts +36 -20
- package/src/widget/hooks/useCurrentScreen.tsx +1 -0
- package/src/widget/hooks/useDefaultTokenSelection.tsx +104 -28
- package/src/widget/hooks/useInitialRedirect.tsx +70 -0
- package/src/widget/hooks/usePayMessage.tsx +86 -11
- package/src/widget/hooks/useSelectedFeeToken.tsx +10 -16
- package/src/widget/hooks/useSelectedFundMethod.tsx +41 -0
- package/src/widget/hooks/useSelectedRecipient.tsx +10 -0
- package/src/widget/hooks/useSendForm.ts +34 -12
- package/src/widget/hooks/useTokenList.ts +1 -1
- package/src/widget/index.css +27 -0
- package/src/widget/widget.tsx +245 -208
- package/dist/widget/components/FundSendForm.d.ts.map +0 -1
- package/dist/widget/components/PaySendForm.d.ts.map +0 -1
- package/dist/widget/components/SimpleSwap.d.ts.map +0 -1
- package/dist/widget/hooks/useSwapSettings.d.ts +0 -16
- package/dist/widget/hooks/useSwapSettings.d.ts.map +0 -1
- package/src/widget/components/FundSendForm.tsx +0 -903
- package/src/widget/components/PaySendForm.tsx +0 -869
- package/src/widget/components/SimpleSwap.tsx +0 -983
- package/src/widget/hooks/useSwapSettings.tsx +0 -100
- /package/dist/{style.css → 0xtrails.css} +0 -0
package/src/prepareSend.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type {
|
|
|
4
4
|
IntentPrecondition,
|
|
5
5
|
} from "@0xsequence/trails-api"
|
|
6
6
|
import type { TrailsAPIClient } from "@0xsequence/trails-api"
|
|
7
|
-
import type { Relayer } from "@0xsequence/
|
|
7
|
+
import type { Relayer } from "@0xsequence/relayer"
|
|
8
8
|
import { useQuery } from "@tanstack/react-query"
|
|
9
9
|
import type {
|
|
10
10
|
Account,
|
|
@@ -56,28 +56,31 @@ import {
|
|
|
56
56
|
getSlippageTolerance,
|
|
57
57
|
type SequenceEnv,
|
|
58
58
|
} from "./config.js"
|
|
59
|
-
import {
|
|
59
|
+
import { TRAILS_INTENT_ENTRYPOINT_ADDRESS } from "./constants.js"
|
|
60
60
|
import {
|
|
61
61
|
decodeGuestModuleEvents,
|
|
62
62
|
decodeTrailsTokenSweeperEvents,
|
|
63
63
|
} from "./decoders.js"
|
|
64
64
|
import { getERC20TransferData } from "./encoders.js"
|
|
65
|
-
import { InsufficientBalanceError } from "./error.js"
|
|
66
|
-
import {
|
|
65
|
+
import { getFullErrorMessage, InsufficientBalanceError } from "./error.js"
|
|
66
|
+
import {
|
|
67
|
+
estimateGasCost,
|
|
68
|
+
estimateGasCostUsd,
|
|
69
|
+
estimateGasLimit,
|
|
70
|
+
DEFAULT_MIN_GASLIMIT,
|
|
71
|
+
} from "./estimate.js"
|
|
67
72
|
import { getExplorerUrl } from "./explorer.js"
|
|
68
73
|
import {
|
|
69
74
|
getNeedsIntentEntrypointApproval,
|
|
70
|
-
getPermitCalls,
|
|
71
75
|
getPermitSignature,
|
|
72
76
|
getUserNonce,
|
|
73
77
|
signIntent,
|
|
74
78
|
} from "./gasless.js"
|
|
75
|
-
import {
|
|
76
|
-
getIntentEntrypointFeeOptions,
|
|
77
|
-
isIntentEntrypointSupported,
|
|
78
|
-
} from "./intentEntrypoint.js"
|
|
79
|
+
import { getIntentEntrypointFeeOptions } from "./intentEntrypoint.js"
|
|
79
80
|
import { useIndexerGatewayClient } from "./indexerClient.js"
|
|
80
81
|
import {
|
|
82
|
+
buildSameChainTransactionParams,
|
|
83
|
+
buildCrossChainDepositParams,
|
|
81
84
|
commitIntentConfig,
|
|
82
85
|
getIntentCallsPayloads as getIntentCallsPayloadsFromIntents,
|
|
83
86
|
sendOriginTransaction,
|
|
@@ -86,11 +89,6 @@ import type { IntentRequestParams } from "./intents.js"
|
|
|
86
89
|
import type { MetaTxn } from "./metaTxnMonitor.js"
|
|
87
90
|
import { getMetaTxStatus } from "./metaTxnMonitor.js"
|
|
88
91
|
import { relayerSendMetaTx } from "./metaTxns.js"
|
|
89
|
-
import {
|
|
90
|
-
getDelegatorSmartAccount,
|
|
91
|
-
getPaymasterGaslessTransaction,
|
|
92
|
-
sendPaymasterGaslessTransaction,
|
|
93
|
-
} from "./paymasterSend.js"
|
|
94
92
|
import { findFirstPreconditionForChainId } from "./preconditions.js"
|
|
95
93
|
import { calcAmountUsdPrice, getTokenPrice } from "./prices.js"
|
|
96
94
|
import { getQueryParam } from "./queryParams.js"
|
|
@@ -136,6 +134,11 @@ import { getIsCustomCalldata } from "./contractUtils.js"
|
|
|
136
134
|
import type { SequenceAPIClient } from "@0xsequence/api"
|
|
137
135
|
import { useTrailsClient } from "./trailsClient.js"
|
|
138
136
|
import { updatePersistentToast } from "./toast.js"
|
|
137
|
+
import {
|
|
138
|
+
getDelegatorSmartAccount,
|
|
139
|
+
getPaymasterGaslessTransaction,
|
|
140
|
+
sendPaymasterGaslessTransaction,
|
|
141
|
+
} from "./paymasterSend.js"
|
|
139
142
|
|
|
140
143
|
export enum TradeType {
|
|
141
144
|
EXACT_INPUT = "EXACT_INPUT",
|
|
@@ -160,8 +163,8 @@ export type PrepareSendOptions = {
|
|
|
160
163
|
dryMode: boolean
|
|
161
164
|
apiClient: SequenceAPIClient
|
|
162
165
|
trailsClient: TrailsAPIClient
|
|
163
|
-
originRelayer: Relayer.
|
|
164
|
-
destinationRelayer: Relayer.
|
|
166
|
+
originRelayer: Relayer.RpcRelayer
|
|
167
|
+
destinationRelayer: Relayer.RpcRelayer
|
|
165
168
|
destinationCalldata?: string
|
|
166
169
|
onTransactionStateChange: (transactionStates: TransactionState[]) => void
|
|
167
170
|
sourceTokenPriceUsd?: number | null
|
|
@@ -178,6 +181,7 @@ export type PrepareSendOptions = {
|
|
|
178
181
|
checkoutOnHandlers?: CheckoutOnHandlers
|
|
179
182
|
refundAddress?: string
|
|
180
183
|
selectedFeeToken?: any
|
|
184
|
+
walletId?: string
|
|
181
185
|
}
|
|
182
186
|
|
|
183
187
|
export type PrepareSendFees = {
|
|
@@ -222,6 +226,8 @@ export type PrepareSendQuote = {
|
|
|
222
226
|
transactionStates: TransactionState[]
|
|
223
227
|
gasCostUsd: number
|
|
224
228
|
gasCostUsdDisplay: string
|
|
229
|
+
gasCost: string
|
|
230
|
+
gasCostFormatted: string
|
|
225
231
|
originTokenRate: string
|
|
226
232
|
destinationTokenRate: string
|
|
227
233
|
quoteProvider: QuoteProviderInfo | null
|
|
@@ -389,6 +395,7 @@ export async function prepareSend(
|
|
|
389
395
|
mode,
|
|
390
396
|
checkoutOnHandlers,
|
|
391
397
|
selectedFeeToken,
|
|
398
|
+
walletId,
|
|
392
399
|
} = options
|
|
393
400
|
let { sourceTokenPriceUsd, destinationTokenPriceUsd } = options
|
|
394
401
|
|
|
@@ -572,18 +579,20 @@ export async function prepareSend(
|
|
|
572
579
|
label: isToSameChain && isToSameToken ? "Execute" : "Transfer",
|
|
573
580
|
})
|
|
574
581
|
|
|
575
|
-
// swap (+ bridge tx)
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
582
|
+
// swap (+ bridge tx) - skip for same-chain-same-token as there's no second transaction
|
|
583
|
+
if (!(isToSameChain && isToSameToken)) {
|
|
584
|
+
transactionStates.push({
|
|
585
|
+
transactionHash: "",
|
|
586
|
+
explorerUrl: "",
|
|
587
|
+
chainId: originChainId,
|
|
588
|
+
state: "pending",
|
|
589
|
+
label: isToSameToken
|
|
590
|
+
? "Bridge"
|
|
591
|
+
: isToSameChain && !isToSameToken
|
|
592
|
+
? "Swap"
|
|
593
|
+
: "Swap & Bridge",
|
|
594
|
+
})
|
|
595
|
+
}
|
|
587
596
|
|
|
588
597
|
// additional execute tx on same chain if needed
|
|
589
598
|
if (isToSameChain && hasCustomCalldata && !isToSameToken) {
|
|
@@ -656,6 +665,13 @@ export async function prepareSend(
|
|
|
656
665
|
originNativeTokenPriceUsd,
|
|
657
666
|
slippageTolerance,
|
|
658
667
|
checkoutOnHandlers,
|
|
668
|
+
gasless,
|
|
669
|
+
paymasterUrl,
|
|
670
|
+
selectedFeeToken,
|
|
671
|
+
trailsClient,
|
|
672
|
+
originRelayer,
|
|
673
|
+
mode,
|
|
674
|
+
fundMethod,
|
|
659
675
|
})
|
|
660
676
|
}
|
|
661
677
|
|
|
@@ -697,6 +713,7 @@ export async function prepareSend(
|
|
|
697
713
|
mode,
|
|
698
714
|
checkoutOnHandlers,
|
|
699
715
|
selectedFeeToken,
|
|
716
|
+
walletId,
|
|
700
717
|
})
|
|
701
718
|
}
|
|
702
719
|
|
|
@@ -737,6 +754,7 @@ async function sendHandlerForDifferentChainDifferentToken({
|
|
|
737
754
|
mode,
|
|
738
755
|
checkoutOnHandlers,
|
|
739
756
|
selectedFeeToken,
|
|
757
|
+
walletId,
|
|
740
758
|
}: {
|
|
741
759
|
mainSignerAddress: string
|
|
742
760
|
originChainId: number
|
|
@@ -757,8 +775,8 @@ async function sendHandlerForDifferentChainDifferentToken({
|
|
|
757
775
|
destinationTokenDecimals: number
|
|
758
776
|
gasless: boolean
|
|
759
777
|
paymasterUrl?: string
|
|
760
|
-
originRelayer: Relayer.
|
|
761
|
-
destinationRelayer: Relayer.
|
|
778
|
+
originRelayer: Relayer.RpcRelayer
|
|
779
|
+
destinationRelayer: Relayer.RpcRelayer
|
|
762
780
|
walletClient: WalletClient
|
|
763
781
|
publicClient: PublicClient
|
|
764
782
|
chain: Chain
|
|
@@ -775,6 +793,7 @@ async function sendHandlerForDifferentChainDifferentToken({
|
|
|
775
793
|
mode?: "pay" | "fund" | "earn" | "swap" | "receive"
|
|
776
794
|
checkoutOnHandlers?: CheckoutOnHandlers
|
|
777
795
|
selectedFeeToken?: any
|
|
796
|
+
walletId?: string
|
|
778
797
|
}): Promise<PrepareSendReturn> {
|
|
779
798
|
const testnet = isTestnetDebugMode()
|
|
780
799
|
const useCctp = getUseCctp(
|
|
@@ -1124,6 +1143,42 @@ async function sendHandlerForDifferentChainDifferentToken({
|
|
|
1124
1143
|
}
|
|
1125
1144
|
}
|
|
1126
1145
|
|
|
1146
|
+
// Estimate gas limit for the quote (same logic as in attemptNonGaslessUserDeposit)
|
|
1147
|
+
const originCallParamsForEstimate = buildCrossChainDepositParams({
|
|
1148
|
+
originTokenAddress,
|
|
1149
|
+
originIntentAddress,
|
|
1150
|
+
depositAmount: firstPreconditionMin,
|
|
1151
|
+
fee,
|
|
1152
|
+
originChainId,
|
|
1153
|
+
chain,
|
|
1154
|
+
})
|
|
1155
|
+
|
|
1156
|
+
logger.console.log(
|
|
1157
|
+
"[trails-sdk][gas-estimation] About to estimate gas limit for cross-chain quote with params:",
|
|
1158
|
+
{
|
|
1159
|
+
account: account.address,
|
|
1160
|
+
to: originCallParamsForEstimate.to,
|
|
1161
|
+
data: originCallParamsForEstimate.data,
|
|
1162
|
+
value: originCallParamsForEstimate.value,
|
|
1163
|
+
},
|
|
1164
|
+
)
|
|
1165
|
+
|
|
1166
|
+
const estimatedGasLimitForQuote = await estimateGasLimit(
|
|
1167
|
+
publicClient,
|
|
1168
|
+
{
|
|
1169
|
+
account: account.address,
|
|
1170
|
+
to: originCallParamsForEstimate.to,
|
|
1171
|
+
data: originCallParamsForEstimate.data,
|
|
1172
|
+
value: BigInt(originCallParamsForEstimate.value),
|
|
1173
|
+
},
|
|
1174
|
+
"quote",
|
|
1175
|
+
)
|
|
1176
|
+
|
|
1177
|
+
logger.console.log(
|
|
1178
|
+
"[trails-sdk][gas-estimation] Estimated gas limit for cross-chain quote:",
|
|
1179
|
+
estimatedGasLimitForQuote,
|
|
1180
|
+
)
|
|
1181
|
+
|
|
1127
1182
|
const quote = await getNormalizedQuoteObject({
|
|
1128
1183
|
originDepositAddress: originIntentAddress,
|
|
1129
1184
|
destinationDepositAddress: intent.payloads.destinationIntentAddress,
|
|
@@ -1151,6 +1206,7 @@ async function sendHandlerForDifferentChainDifferentToken({
|
|
|
1151
1206
|
originNativeTokenPriceUsd,
|
|
1152
1207
|
quoteProvider: intent.payloads?.quote?.quoteProvider,
|
|
1153
1208
|
noSufficientBalance,
|
|
1209
|
+
estimatedGasLimit: estimatedGasLimitForQuote,
|
|
1154
1210
|
})
|
|
1155
1211
|
|
|
1156
1212
|
// Call onCheckoutQuote callback if provided
|
|
@@ -1158,45 +1214,43 @@ async function sendHandlerForDifferentChainDifferentToken({
|
|
|
1158
1214
|
checkoutOnHandlers.triggerCheckoutQuote(quote)
|
|
1159
1215
|
}
|
|
1160
1216
|
|
|
1161
|
-
// Get intent entrypoint fee options if supported
|
|
1217
|
+
// Get intent entrypoint fee options if supported and gasless is enabled
|
|
1218
|
+
// Note: We fetch fee options whenever gasless is true, regardless of fundMethod,
|
|
1219
|
+
// because gasless scenarios (including tests) need fee collector information
|
|
1220
|
+
// Skip gasless fee options for sequence-waas wallet
|
|
1162
1221
|
let intentEntrypointFeeOptions: any = null
|
|
1163
|
-
if (gasless &&
|
|
1222
|
+
if (gasless && walletId !== "sequence-waas") {
|
|
1164
1223
|
try {
|
|
1165
1224
|
logger.console.log(
|
|
1166
|
-
"[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] Gasless enabled
|
|
1225
|
+
"[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] Gasless enabled, checking intent entrypoint support for chain:",
|
|
1167
1226
|
originChainId,
|
|
1168
1227
|
)
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
"[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] Intent entrypoint fee options:",
|
|
1183
|
-
intentEntrypointFeeOptions,
|
|
1184
|
-
)
|
|
1185
|
-
} else {
|
|
1186
|
-
logger.console.log(
|
|
1187
|
-
"[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] Chain not supported for intent entrypoint:",
|
|
1188
|
-
originChainId,
|
|
1189
|
-
)
|
|
1190
|
-
}
|
|
1228
|
+
|
|
1229
|
+
intentEntrypointFeeOptions = await getIntentEntrypointFeeOptions({
|
|
1230
|
+
trailsClient,
|
|
1231
|
+
userAddress: mainSignerAddress as `0x${string}`,
|
|
1232
|
+
tokenAddress: originTokenAddress as `0x${string}`,
|
|
1233
|
+
amount: depositAmount,
|
|
1234
|
+
intentAddress: originIntentAddress as `0x${string}`,
|
|
1235
|
+
chainId: originChainId,
|
|
1236
|
+
})
|
|
1237
|
+
logger.console.log(
|
|
1238
|
+
"[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] Intent entrypoint fee options:",
|
|
1239
|
+
intentEntrypointFeeOptions,
|
|
1240
|
+
)
|
|
1191
1241
|
} catch (error) {
|
|
1192
1242
|
logger.console.error(
|
|
1193
1243
|
"[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] Error getting intent entrypoint fee options:",
|
|
1194
1244
|
error,
|
|
1195
1245
|
)
|
|
1196
1246
|
}
|
|
1247
|
+
} else if (walletId === "sequence-waas") {
|
|
1248
|
+
logger.console.log(
|
|
1249
|
+
"[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] Skipping gasless fee options for sequence-waas wallet",
|
|
1250
|
+
)
|
|
1197
1251
|
} else {
|
|
1198
1252
|
logger.console.log(
|
|
1199
|
-
"[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] Gasless disabled
|
|
1253
|
+
"[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] Gasless disabled, skipping intent entrypoint fee options fetch",
|
|
1200
1254
|
)
|
|
1201
1255
|
}
|
|
1202
1256
|
|
|
@@ -1362,6 +1416,7 @@ async function sendHandlerForDifferentChainDifferentToken({
|
|
|
1362
1416
|
feeOptions: intentEntrypointFeeOptions,
|
|
1363
1417
|
trailsClient,
|
|
1364
1418
|
selectedFeeToken: effectiveSelectedFeeToken,
|
|
1419
|
+
walletId,
|
|
1365
1420
|
})
|
|
1366
1421
|
|
|
1367
1422
|
if (!originUserTxReceipt) {
|
|
@@ -1814,7 +1869,7 @@ async function sendHandlerForDifferentChainDifferentToken({
|
|
|
1814
1869
|
}
|
|
1815
1870
|
|
|
1816
1871
|
checkForDepositTx().catch((error) => {
|
|
1817
|
-
console.error("Error checking for deposit tx", error)
|
|
1872
|
+
logger.console.error("Error checking for deposit tx", error)
|
|
1818
1873
|
})
|
|
1819
1874
|
|
|
1820
1875
|
// Phase 1: Send meta transactions and queue CCTP
|
|
@@ -2032,11 +2087,14 @@ async function sendHandlerForDifferentChainDifferentToken({
|
|
|
2032
2087
|
|
|
2033
2088
|
onTransactionStateChange(transactionStates)
|
|
2034
2089
|
} catch (error) {
|
|
2035
|
-
console.error(
|
|
2090
|
+
logger.console.error(
|
|
2091
|
+
"Error decoding destination tx events",
|
|
2092
|
+
error,
|
|
2093
|
+
)
|
|
2036
2094
|
}
|
|
2037
2095
|
}
|
|
2038
2096
|
} catch (error) {
|
|
2039
|
-
console.error(
|
|
2097
|
+
logger.console.error(
|
|
2040
2098
|
"[trails-sdk] Error waiting for destination receipt:",
|
|
2041
2099
|
error,
|
|
2042
2100
|
)
|
|
@@ -2072,6 +2130,17 @@ async function sendHandlerForDifferentChainDifferentToken({
|
|
|
2072
2130
|
|
|
2073
2131
|
// Track payment completion for different chain and different token
|
|
2074
2132
|
if (originUserTxReceipt && destinationMetaTxnReceipt) {
|
|
2133
|
+
// Check if any transaction failed or was refunded
|
|
2134
|
+
const hasAnyCallFailed = transactionStates.some((tx) =>
|
|
2135
|
+
tx?.decodedGuestModuleEvents?.some(
|
|
2136
|
+
(e: any) => e?.type === "CallFailed",
|
|
2137
|
+
),
|
|
2138
|
+
)
|
|
2139
|
+
const hasAnyRefunded = transactionStates.some((tx) => tx?.refunded)
|
|
2140
|
+
const txStatus =
|
|
2141
|
+
!hasAnyCallFailed && !hasAnyRefunded ? "success" : "fail"
|
|
2142
|
+
|
|
2143
|
+
// Always track payment completion regardless of success/failure
|
|
2075
2144
|
trackPaymentCompleted({
|
|
2076
2145
|
userAddress: account.address,
|
|
2077
2146
|
originIntentAddress,
|
|
@@ -2092,9 +2161,9 @@ async function sendHandlerForDifferentChainDifferentToken({
|
|
|
2092
2161
|
effectiveDestinationTokenAmountUsd?.toString(),
|
|
2093
2162
|
})
|
|
2094
2163
|
|
|
2095
|
-
// Call onCheckoutComplete callback
|
|
2164
|
+
// Call onCheckoutComplete callback with transaction status
|
|
2096
2165
|
if (checkoutOnHandlers?.triggerCheckoutComplete) {
|
|
2097
|
-
checkoutOnHandlers.triggerCheckoutComplete()
|
|
2166
|
+
checkoutOnHandlers.triggerCheckoutComplete(txStatus)
|
|
2098
2167
|
}
|
|
2099
2168
|
} else {
|
|
2100
2169
|
if (
|
|
@@ -2203,6 +2272,11 @@ async function sendHandlerForSameChainSameToken({
|
|
|
2203
2272
|
checkoutOnHandlers,
|
|
2204
2273
|
mode,
|
|
2205
2274
|
fundMethod,
|
|
2275
|
+
gasless,
|
|
2276
|
+
paymasterUrl,
|
|
2277
|
+
selectedFeeToken,
|
|
2278
|
+
trailsClient,
|
|
2279
|
+
originRelayer,
|
|
2206
2280
|
}: {
|
|
2207
2281
|
originTokenAddress: string
|
|
2208
2282
|
originTokenDecimals: number
|
|
@@ -2224,6 +2298,11 @@ async function sendHandlerForSameChainSameToken({
|
|
|
2224
2298
|
checkoutOnHandlers?: CheckoutOnHandlers
|
|
2225
2299
|
mode?: "pay" | "fund" | "earn" | "swap" | "receive"
|
|
2226
2300
|
fundMethod?: string
|
|
2301
|
+
gasless?: boolean
|
|
2302
|
+
paymasterUrl?: string
|
|
2303
|
+
selectedFeeToken?: any
|
|
2304
|
+
trailsClient: TrailsAPIClient
|
|
2305
|
+
originRelayer: Relayer.RpcRelayer
|
|
2227
2306
|
}): Promise<PrepareSendReturn> {
|
|
2228
2307
|
logger.console.log("[trails-sdk] isToSameToken && isToSameChain")
|
|
2229
2308
|
const testnet = isTestnetDebugMode()
|
|
@@ -2250,6 +2329,44 @@ async function sendHandlerForSameChainSameToken({
|
|
|
2250
2329
|
noSufficientBalance = true
|
|
2251
2330
|
}
|
|
2252
2331
|
|
|
2332
|
+
// Build origin call params and estimate gas limit for the quote
|
|
2333
|
+
const hasCustomCalldata = getIsCustomCalldata(destinationCalldata)
|
|
2334
|
+
const originCallParamsBase = buildSameChainTransactionParams({
|
|
2335
|
+
hasCustomCalldata,
|
|
2336
|
+
recipient,
|
|
2337
|
+
effectiveOriginTokenAddress,
|
|
2338
|
+
destinationCalldata,
|
|
2339
|
+
swapAmount,
|
|
2340
|
+
effectiveOriginChainId,
|
|
2341
|
+
effectiveOriginChain,
|
|
2342
|
+
})
|
|
2343
|
+
|
|
2344
|
+
logger.console.log(
|
|
2345
|
+
"[trails-sdk][gas-estimation] About to estimate gas limit for quote with params:",
|
|
2346
|
+
{
|
|
2347
|
+
account: account.address,
|
|
2348
|
+
to: originCallParamsBase.to,
|
|
2349
|
+
data: originCallParamsBase.data,
|
|
2350
|
+
value: originCallParamsBase.value,
|
|
2351
|
+
},
|
|
2352
|
+
)
|
|
2353
|
+
|
|
2354
|
+
const estimatedGasLimitForQuote = await estimateGasLimit(
|
|
2355
|
+
effectivePublicClient,
|
|
2356
|
+
{
|
|
2357
|
+
account: account.address,
|
|
2358
|
+
to: originCallParamsBase.to,
|
|
2359
|
+
data: originCallParamsBase.data,
|
|
2360
|
+
value: BigInt(originCallParamsBase.value),
|
|
2361
|
+
},
|
|
2362
|
+
"quote",
|
|
2363
|
+
)
|
|
2364
|
+
|
|
2365
|
+
logger.console.log(
|
|
2366
|
+
"[trails-sdk][gas-estimation] Estimated gas limit for quote:",
|
|
2367
|
+
estimatedGasLimitForQuote,
|
|
2368
|
+
)
|
|
2369
|
+
|
|
2253
2370
|
const quote = await getNormalizedQuoteObject({
|
|
2254
2371
|
originDepositAddress: recipient,
|
|
2255
2372
|
destinationDepositAddress: recipient,
|
|
@@ -2268,6 +2385,7 @@ async function sendHandlerForSameChainSameToken({
|
|
|
2268
2385
|
slippageTolerance,
|
|
2269
2386
|
quoteProvider: "",
|
|
2270
2387
|
noSufficientBalance,
|
|
2388
|
+
estimatedGasLimit: estimatedGasLimitForQuote,
|
|
2271
2389
|
})
|
|
2272
2390
|
|
|
2273
2391
|
// Call onCheckoutQuote callback if provided
|
|
@@ -2303,26 +2421,33 @@ async function sendHandlerForSameChainSameToken({
|
|
|
2303
2421
|
})
|
|
2304
2422
|
|
|
2305
2423
|
const hasCustomCalldata = getIsCustomCalldata(destinationCalldata)
|
|
2424
|
+
|
|
2425
|
+
// Build origin call params (reusing the same logic as quote estimation)
|
|
2426
|
+
const originCallParamsBase = buildSameChainTransactionParams({
|
|
2427
|
+
hasCustomCalldata,
|
|
2428
|
+
recipient,
|
|
2429
|
+
effectiveOriginTokenAddress,
|
|
2430
|
+
destinationCalldata,
|
|
2431
|
+
swapAmount,
|
|
2432
|
+
effectiveOriginChainId,
|
|
2433
|
+
effectiveOriginChain,
|
|
2434
|
+
})
|
|
2435
|
+
|
|
2436
|
+
// Estimate gas limit for consistency with actual transaction
|
|
2437
|
+
const gasLimit = await estimateGasLimit(
|
|
2438
|
+
effectivePublicClient,
|
|
2439
|
+
{
|
|
2440
|
+
account: account.address,
|
|
2441
|
+
to: originCallParamsBase.to,
|
|
2442
|
+
data: originCallParamsBase.data,
|
|
2443
|
+
value: BigInt(originCallParamsBase.value),
|
|
2444
|
+
},
|
|
2445
|
+
"send",
|
|
2446
|
+
)
|
|
2447
|
+
|
|
2306
2448
|
const originCallParams = {
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
: effectiveOriginTokenAddress === zeroAddress
|
|
2310
|
-
? recipient
|
|
2311
|
-
: effectiveOriginTokenAddress,
|
|
2312
|
-
data: hasCustomCalldata
|
|
2313
|
-
? destinationCalldata
|
|
2314
|
-
: effectiveOriginTokenAddress === zeroAddress
|
|
2315
|
-
? "0x"
|
|
2316
|
-
: getERC20TransferData({
|
|
2317
|
-
recipient,
|
|
2318
|
-
amount: BigInt(swapAmount),
|
|
2319
|
-
}),
|
|
2320
|
-
value:
|
|
2321
|
-
effectiveOriginTokenAddress === zeroAddress
|
|
2322
|
-
? BigInt(swapAmount)
|
|
2323
|
-
: "0",
|
|
2324
|
-
chainId: effectiveOriginChainId,
|
|
2325
|
-
chain: effectiveOriginChain,
|
|
2449
|
+
...originCallParamsBase,
|
|
2450
|
+
gasLimit,
|
|
2326
2451
|
}
|
|
2327
2452
|
|
|
2328
2453
|
logger.console.log("[trails-sdk] origin call params", originCallParams)
|
|
@@ -2353,105 +2478,207 @@ async function sendHandlerForSameChainSameToken({
|
|
|
2353
2478
|
)
|
|
2354
2479
|
}
|
|
2355
2480
|
|
|
2356
|
-
|
|
2481
|
+
// For gasless transactions with custom calldata, use the gasless deposit flow
|
|
2482
|
+
if (gasless && hasCustomCalldata) {
|
|
2483
|
+
logger.console.log(
|
|
2484
|
+
"[trails-sdk] Using gasless intent entrypoint flow for same-chain transaction with custom calldata",
|
|
2485
|
+
)
|
|
2486
|
+
|
|
2487
|
+
// Fetch fee options for gasless deposit
|
|
2488
|
+
let feeOptions: any = null
|
|
2357
2489
|
try {
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2490
|
+
feeOptions = await getIntentEntrypointFeeOptions({
|
|
2491
|
+
trailsClient,
|
|
2492
|
+
userAddress: account.address as `0x${string}`,
|
|
2493
|
+
tokenAddress: effectiveOriginTokenAddress as `0x${string}`,
|
|
2494
|
+
amount: swapAmount,
|
|
2495
|
+
intentAddress: recipient as `0x${string}`,
|
|
2496
|
+
chainId: effectiveOriginChainId,
|
|
2497
|
+
})
|
|
2498
|
+
logger.console.log(
|
|
2499
|
+
"[trails-sdk] [GASLESS-FLOW] Fetched intent entrypoint fee options for same-chain transaction:",
|
|
2500
|
+
feeOptions,
|
|
2501
|
+
)
|
|
2502
|
+
} catch (error) {
|
|
2503
|
+
logger.console.error(
|
|
2504
|
+
"[trails-sdk] [GASLESS-FLOW] Error fetching fee options for same-chain gasless transaction:",
|
|
2505
|
+
error,
|
|
2506
|
+
)
|
|
2507
|
+
}
|
|
2508
|
+
|
|
2509
|
+
const receipt = await attemptGaslessDeposit({
|
|
2510
|
+
account,
|
|
2511
|
+
walletClient,
|
|
2512
|
+
chain: effectiveOriginChain,
|
|
2513
|
+
depositTokenAddress: effectiveOriginTokenAddress,
|
|
2514
|
+
depositTokenAmount: swapAmount,
|
|
2515
|
+
depositRecipient: recipient,
|
|
2516
|
+
onOriginSend: () => {}, // No-op callback
|
|
2517
|
+
feeOptions,
|
|
2518
|
+
paymasterUrl,
|
|
2519
|
+
selectedFeeToken,
|
|
2520
|
+
trailsClient,
|
|
2521
|
+
originRelayer,
|
|
2522
|
+
})
|
|
2523
|
+
|
|
2524
|
+
if (receipt) {
|
|
2525
|
+
originUserTxReceipt = receipt
|
|
2526
|
+
|
|
2527
|
+
// Track the confirmed transaction
|
|
2528
|
+
trackTransactionConfirmed({
|
|
2529
|
+
transactionHash: receipt.transactionHash,
|
|
2530
|
+
chainId: effectiveOriginChainId,
|
|
2531
|
+
userAddress: account.address,
|
|
2532
|
+
blockNumber: Number(receipt.blockNumber),
|
|
2533
|
+
originTokenAddress,
|
|
2534
|
+
depositTokenAmountUsd: depositAmountUsd?.toString(),
|
|
2364
2535
|
})
|
|
2365
2536
|
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2537
|
+
// Toast will be shown after transaction state analysis
|
|
2538
|
+
|
|
2539
|
+
// Update transaction state
|
|
2540
|
+
try {
|
|
2541
|
+
onTransactionStateChange([
|
|
2542
|
+
getTransactionStateFromReceipt(
|
|
2543
|
+
receipt,
|
|
2544
|
+
effectiveOriginChainId,
|
|
2545
|
+
transactionStates[0]?.label,
|
|
2546
|
+
),
|
|
2547
|
+
])
|
|
2548
|
+
} catch (error) {
|
|
2549
|
+
logger.console.error(
|
|
2550
|
+
"[trails-sdk] Error calling onTransactionStateChange:",
|
|
2551
|
+
error,
|
|
2552
|
+
)
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
} else {
|
|
2556
|
+
// Non-gasless flow: handle approval if needed
|
|
2557
|
+
if (hasCustomCalldata) {
|
|
2558
|
+
try {
|
|
2559
|
+
const needsApproval = await getNeedsApproval({
|
|
2560
|
+
publicClient: effectivePublicClient,
|
|
2561
|
+
token: effectiveOriginTokenAddress,
|
|
2562
|
+
account: account.address,
|
|
2370
2563
|
spender: recipient,
|
|
2371
2564
|
amount: maxUint256,
|
|
2372
|
-
chain: effectiveOriginChain,
|
|
2373
2565
|
})
|
|
2374
2566
|
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2567
|
+
if (needsApproval) {
|
|
2568
|
+
const txHash = await approveERC20({
|
|
2569
|
+
walletClient,
|
|
2570
|
+
tokenAddress: effectiveOriginTokenAddress,
|
|
2571
|
+
spender: recipient,
|
|
2572
|
+
amount: maxUint256,
|
|
2573
|
+
chain: effectiveOriginChain,
|
|
2574
|
+
})
|
|
2575
|
+
|
|
2576
|
+
logger.console.log("waiting for approve", txHash)
|
|
2577
|
+
await effectivePublicClient.waitForTransactionReceipt({
|
|
2578
|
+
hash: txHash,
|
|
2579
|
+
})
|
|
2580
|
+
logger.console.log("approve done")
|
|
2581
|
+
}
|
|
2582
|
+
} catch (error) {
|
|
2583
|
+
logger.console.error(
|
|
2584
|
+
"[trails-sdk] Error approving ERC20",
|
|
2585
|
+
error,
|
|
2586
|
+
)
|
|
2380
2587
|
}
|
|
2381
|
-
} catch (error) {
|
|
2382
|
-
logger.console.error("[trails-sdk] Error approving ERC20", error)
|
|
2383
2588
|
}
|
|
2384
|
-
}
|
|
2385
2589
|
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2590
|
+
// Show persistent toast for checkout flow
|
|
2591
|
+
updatePersistentToast(
|
|
2592
|
+
"Payment Started",
|
|
2593
|
+
"Waiting for wallet confirmation...",
|
|
2594
|
+
"info",
|
|
2595
|
+
)
|
|
2392
2596
|
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2597
|
+
logger.console.log(
|
|
2598
|
+
"[trails-sdk] origin call params",
|
|
2599
|
+
originCallParams,
|
|
2600
|
+
)
|
|
2601
|
+
const txHash = await sendOriginTransaction(
|
|
2602
|
+
account,
|
|
2603
|
+
walletClient,
|
|
2604
|
+
originCallParams as any,
|
|
2605
|
+
{
|
|
2606
|
+
depositTokenAmountUsd: depositAmountUsd?.toString(),
|
|
2607
|
+
},
|
|
2608
|
+
) // TODO: Add proper type
|
|
2405
2609
|
|
|
2406
|
-
|
|
2610
|
+
logger.console.log("[trails-sdk] origin tx", txHash)
|
|
2407
2611
|
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2612
|
+
if (onOriginSend) {
|
|
2613
|
+
onOriginSend()
|
|
2614
|
+
}
|
|
2411
2615
|
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
originUserTxReceipt = receipt
|
|
2616
|
+
// Wait for transaction receipt
|
|
2617
|
+
const receipt =
|
|
2618
|
+
await effectivePublicClient.waitForTransactionReceipt({
|
|
2619
|
+
hash: txHash,
|
|
2620
|
+
})
|
|
2621
|
+
logger.console.log("[trails-sdk] receipt", receipt)
|
|
2622
|
+
originUserTxReceipt = receipt
|
|
2420
2623
|
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2624
|
+
trackTransactionConfirmed({
|
|
2625
|
+
transactionHash: txHash,
|
|
2626
|
+
chainId: effectiveOriginChainId,
|
|
2627
|
+
userAddress: account.address,
|
|
2628
|
+
blockNumber: Number(receipt.blockNumber),
|
|
2629
|
+
originTokenAddress,
|
|
2630
|
+
depositTokenAmountUsd: depositAmountUsd?.toString(),
|
|
2631
|
+
})
|
|
2429
2632
|
|
|
2430
|
-
|
|
2431
|
-
const chainInfo = getChainInfo(effectiveOriginChainId)
|
|
2432
|
-
updatePersistentToast(
|
|
2433
|
-
"Transfer Confirmed",
|
|
2434
|
-
`Your transaction on ${chainInfo?.name || "chain"} has been confirmed`,
|
|
2435
|
-
"info",
|
|
2436
|
-
)
|
|
2633
|
+
// Toast will be shown after transaction state analysis
|
|
2437
2634
|
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2635
|
+
try {
|
|
2636
|
+
onTransactionStateChange([
|
|
2637
|
+
getTransactionStateFromReceipt(
|
|
2638
|
+
originUserTxReceipt,
|
|
2639
|
+
effectiveOriginChainId,
|
|
2640
|
+
transactionStates[0]?.label,
|
|
2641
|
+
),
|
|
2642
|
+
])
|
|
2643
|
+
} catch (error) {
|
|
2644
|
+
logger.console.error(
|
|
2645
|
+
"[trails-sdk] Error calling onTransactionStateChange:",
|
|
2646
|
+
error,
|
|
2647
|
+
)
|
|
2648
|
+
}
|
|
2649
|
+
}
|
|
2650
|
+
|
|
2651
|
+
// Show conditional toast based on transaction status
|
|
2652
|
+
const chainInfo = getChainInfo(effectiveOriginChainId)
|
|
2653
|
+
if (originUserTxReceipt) {
|
|
2654
|
+
if (originUserTxReceipt?.status === "success") {
|
|
2655
|
+
updatePersistentToast(
|
|
2656
|
+
"Transfer Confirmed",
|
|
2657
|
+
`Your transaction on ${chainInfo?.name || "chain"} has been confirmed`,
|
|
2658
|
+
"info",
|
|
2659
|
+
)
|
|
2660
|
+
} else {
|
|
2661
|
+
updatePersistentToast(
|
|
2662
|
+
"Transfer Failed",
|
|
2663
|
+
`Your transaction on ${chainInfo?.name || "chain"} failed`,
|
|
2664
|
+
"error",
|
|
2665
|
+
)
|
|
2666
|
+
}
|
|
2451
2667
|
}
|
|
2452
2668
|
|
|
2453
2669
|
// Track payment completion for same-chain same-token transaction
|
|
2454
2670
|
if (originUserTxReceipt && originUserTxReceipt.status === "success") {
|
|
2671
|
+
// Check if any transaction failed or was refunded
|
|
2672
|
+
const hasAnyCallFailed = transactionStates.some((tx) =>
|
|
2673
|
+
tx?.decodedGuestModuleEvents?.some(
|
|
2674
|
+
(e: any) => e?.type === "CallFailed",
|
|
2675
|
+
),
|
|
2676
|
+
)
|
|
2677
|
+
const hasAnyRefunded = transactionStates.some((tx) => tx?.refunded)
|
|
2678
|
+
const txStatus =
|
|
2679
|
+
!hasAnyCallFailed && !hasAnyRefunded ? "success" : "fail"
|
|
2680
|
+
|
|
2681
|
+
// Always track payment completion regardless of success/failure
|
|
2455
2682
|
trackPaymentCompleted({
|
|
2456
2683
|
userAddress: account.address,
|
|
2457
2684
|
originTxHash: originUserTxReceipt.transactionHash,
|
|
@@ -2463,9 +2690,9 @@ async function sendHandlerForSameChainSameToken({
|
|
|
2463
2690
|
destinationTokenAmountUsd: depositAmountUsd?.toString(), // same as deposit amount
|
|
2464
2691
|
})
|
|
2465
2692
|
|
|
2466
|
-
// Call onCheckoutComplete callback
|
|
2693
|
+
// Call onCheckoutComplete callback with transaction status
|
|
2467
2694
|
if (checkoutOnHandlers?.triggerCheckoutComplete) {
|
|
2468
|
-
checkoutOnHandlers.triggerCheckoutComplete()
|
|
2695
|
+
checkoutOnHandlers.triggerCheckoutComplete(txStatus)
|
|
2469
2696
|
}
|
|
2470
2697
|
} else if (originUserTxReceipt) {
|
|
2471
2698
|
trackPaymentError({
|
|
@@ -2620,7 +2847,7 @@ async function _sendHandlerForSameChainDifferentToken({
|
|
|
2620
2847
|
}
|
|
2621
2848
|
}
|
|
2622
2849
|
} catch (error) {
|
|
2623
|
-
console.error("[trails-sdk] Error decoding function data:", error)
|
|
2850
|
+
logger.console.error("[trails-sdk] Error decoding function data:", error)
|
|
2624
2851
|
}
|
|
2625
2852
|
}
|
|
2626
2853
|
|
|
@@ -2806,7 +3033,7 @@ async function attemptGaslessDeposit({
|
|
|
2806
3033
|
chain: Chain
|
|
2807
3034
|
account: Account
|
|
2808
3035
|
trailsClient: TrailsAPIClient
|
|
2809
|
-
originRelayer: Relayer.
|
|
3036
|
+
originRelayer: Relayer.RpcRelayer
|
|
2810
3037
|
feeOptions: any
|
|
2811
3038
|
selectedFeeToken?: any
|
|
2812
3039
|
}): Promise<TransactionReceipt | null> {
|
|
@@ -2833,29 +3060,28 @@ async function attemptGaslessDeposit({
|
|
|
2833
3060
|
transport: http(),
|
|
2834
3061
|
})
|
|
2835
3062
|
|
|
2836
|
-
const intentEntrypoint = intentEntrypoints[chain.id]
|
|
2837
3063
|
logger.console.log("[trails-sdk] [GASLESS-FLOW] Intent entrypoint check:", {
|
|
2838
3064
|
chainId: chain.id,
|
|
2839
3065
|
chainName: chain.name,
|
|
2840
|
-
intentEntrypoint,
|
|
2841
|
-
hasIntentEntrypoint: !!intentEntrypoint,
|
|
2842
|
-
availableChains: Object.keys(intentEntrypoints).map(Number),
|
|
3066
|
+
intentEntrypoint: TRAILS_INTENT_ENTRYPOINT_ADDRESS,
|
|
2843
3067
|
})
|
|
2844
3068
|
|
|
2845
|
-
//
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
`Gasless deposits with fee options are only supported on chains: ${Object.keys(intentEntrypoints).join(", ")}. ` +
|
|
2850
|
-
`Falling back to old flow (permit2/paymaster).`,
|
|
2851
|
-
)
|
|
3069
|
+
// NEW FLOW: Use Intent Entrypoint API with permit2 support
|
|
3070
|
+
logger.console.log(
|
|
3071
|
+
"[trails-sdk] Using Intent Entrypoint API flow with permit2 support for gasless deposit",
|
|
3072
|
+
)
|
|
2852
3073
|
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
3074
|
+
// Switch to correct chain before requesting signatures
|
|
3075
|
+
logger.console.log(
|
|
3076
|
+
"[trails-sdk] [GASLESS-FLOW] Switching to chain before permit/intent signatures",
|
|
3077
|
+
{ originChainId },
|
|
3078
|
+
)
|
|
3079
|
+
await attemptSwitchChain({
|
|
3080
|
+
walletClient,
|
|
3081
|
+
desiredChainId: originChainId,
|
|
3082
|
+
})
|
|
2858
3083
|
|
|
3084
|
+
try {
|
|
2859
3085
|
if (paymasterUrl) {
|
|
2860
3086
|
logger.console.log(
|
|
2861
3087
|
"[trails-sdk] [GASLESS-FLOW] doing gasless with paymaster",
|
|
@@ -2874,7 +3100,11 @@ async function attemptGaslessDeposit({
|
|
|
2874
3100
|
publicClient,
|
|
2875
3101
|
})
|
|
2876
3102
|
|
|
2877
|
-
calls
|
|
3103
|
+
const calls: Array<{
|
|
3104
|
+
to: string
|
|
3105
|
+
data: string
|
|
3106
|
+
value: string
|
|
3107
|
+
}> = await getPaymasterGaslessTransaction({
|
|
2878
3108
|
walletClient,
|
|
2879
3109
|
chain,
|
|
2880
3110
|
tokenAddress: depositTokenAddress as `0x${string}`,
|
|
@@ -2903,97 +3133,14 @@ async function attemptGaslessDeposit({
|
|
|
2903
3133
|
})
|
|
2904
3134
|
logger.console.log("[trails-sdk] receipt", receipt)
|
|
2905
3135
|
return receipt
|
|
2906
|
-
} else {
|
|
2907
|
-
logger.console.log(
|
|
2908
|
-
"[trails-sdk] [GASLESS-FLOW] doing gasless with sequence wallet",
|
|
2909
|
-
)
|
|
2910
|
-
const delegatorPrivateKey = generatePrivateKey()
|
|
2911
|
-
const delegatorAccount = privateKeyToAccount(delegatorPrivateKey)
|
|
2912
|
-
const delegatorClient = createWalletClient({
|
|
2913
|
-
account: delegatorAccount,
|
|
2914
|
-
chain,
|
|
2915
|
-
transport: http(),
|
|
2916
|
-
})
|
|
2917
|
-
|
|
2918
|
-
logger.console.log("[trails-sdk] attempting to switch chain")
|
|
2919
|
-
await attemptSwitchChain({
|
|
2920
|
-
walletClient,
|
|
2921
|
-
desiredChainId: originChainId,
|
|
2922
|
-
})
|
|
2923
|
-
|
|
2924
|
-
logger.console.log("[trails-sdk] creating sequence wallet")
|
|
2925
|
-
const sequenceWalletAddress = await simpleCreateSequenceWallet(
|
|
2926
|
-
delegatorAccount as any,
|
|
2927
|
-
)
|
|
2928
|
-
logger.console.log(
|
|
2929
|
-
"[trails-sdk] sequenceWalletAddress",
|
|
2930
|
-
sequenceWalletAddress,
|
|
2931
|
-
)
|
|
2932
|
-
|
|
2933
|
-
const { signature, deadline } = await getPermitSignature({
|
|
2934
|
-
publicClient,
|
|
2935
|
-
walletClient,
|
|
2936
|
-
signer: account.address,
|
|
2937
|
-
spender: sequenceWalletAddress,
|
|
2938
|
-
tokenAddress: depositTokenAddress as `0x${string}`,
|
|
2939
|
-
amount: BigInt(depositTokenAmount),
|
|
2940
|
-
chain,
|
|
2941
|
-
})
|
|
2942
|
-
|
|
2943
|
-
calls = getPermitCalls(
|
|
2944
|
-
account.address,
|
|
2945
|
-
sequenceWalletAddress,
|
|
2946
|
-
BigInt(depositTokenAmount),
|
|
2947
|
-
deadline,
|
|
2948
|
-
signature,
|
|
2949
|
-
depositRecipient as `0x${string}`,
|
|
2950
|
-
depositTokenAddress as `0x${string}`,
|
|
2951
|
-
)
|
|
2952
|
-
|
|
2953
|
-
logger.console.log("[trails-sdk] calls", calls)
|
|
2954
|
-
|
|
2955
|
-
const sequenceTxHash = await sequenceSendTransaction(
|
|
2956
|
-
sequenceWalletAddress,
|
|
2957
|
-
delegatorClient,
|
|
2958
|
-
publicClient,
|
|
2959
|
-
calls,
|
|
2960
|
-
chain,
|
|
2961
|
-
)
|
|
2962
|
-
logger.console.log("[trails-sdk] sequenceTxHash", sequenceTxHash)
|
|
2963
|
-
if (onOriginSend) {
|
|
2964
|
-
onOriginSend()
|
|
2965
|
-
}
|
|
2966
|
-
|
|
2967
|
-
const receipt = await publicClient.waitForTransactionReceipt({
|
|
2968
|
-
hash: sequenceTxHash as `0x${string}`,
|
|
2969
|
-
})
|
|
2970
|
-
logger.console.log("[trails-sdk] receipt", receipt)
|
|
2971
|
-
return receipt
|
|
2972
3136
|
}
|
|
2973
|
-
}
|
|
2974
|
-
|
|
2975
|
-
// NEW FLOW: Use Intent Entrypoint API with permit2 support
|
|
2976
|
-
logger.console.log(
|
|
2977
|
-
"[trails-sdk] Using Intent Entrypoint API flow with permit2 support for gasless deposit",
|
|
2978
|
-
)
|
|
2979
|
-
|
|
2980
|
-
// Switch to correct chain before requesting signatures
|
|
2981
|
-
logger.console.log(
|
|
2982
|
-
"[trails-sdk] [GASLESS-FLOW] Switching to chain before permit/intent signatures",
|
|
2983
|
-
{ originChainId },
|
|
2984
|
-
)
|
|
2985
|
-
await attemptSwitchChain({
|
|
2986
|
-
walletClient,
|
|
2987
|
-
desiredChainId: originChainId,
|
|
2988
|
-
})
|
|
2989
3137
|
|
|
2990
|
-
try {
|
|
2991
3138
|
const deadline = Math.floor(Date.now() / 1000) + 3600 // 1 hour from now
|
|
2992
3139
|
const hasFeeOptions = Boolean(
|
|
2993
3140
|
feeOptions && feeOptions.feeOptions?.length > 0,
|
|
2994
3141
|
)
|
|
2995
3142
|
|
|
2996
|
-
// 1. Check if we need approval - check if we have enough allowance for this transaction (deposit + fee)
|
|
3143
|
+
// 1. Check if we need approval - check if we have enough allowance for this transaction (deposit + fee if same token)
|
|
2997
3144
|
let requiredAmount = BigInt(depositTokenAmount)
|
|
2998
3145
|
|
|
2999
3146
|
// Match selectedFeeToken by tokenAddress to get the latest fee amount from feeOptions
|
|
@@ -3023,21 +3170,43 @@ async function attemptGaslessDeposit({
|
|
|
3023
3170
|
)
|
|
3024
3171
|
}
|
|
3025
3172
|
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3173
|
+
// Only include fee in required amount if the fee token is the same as the deposit token
|
|
3174
|
+
if (selectedFeeOption?.amount && selectedFeeOption?.tokenAddress) {
|
|
3175
|
+
const feeTokenIsSameAsDepositToken =
|
|
3176
|
+
selectedFeeOption.tokenAddress.toLowerCase() ===
|
|
3177
|
+
depositTokenAddress.toLowerCase()
|
|
3178
|
+
|
|
3179
|
+
if (feeTokenIsSameAsDepositToken) {
|
|
3180
|
+
requiredAmount = requiredAmount + BigInt(selectedFeeOption.amount)
|
|
3181
|
+
logger.console.log(
|
|
3182
|
+
"[trails-sdk] Fee token matches deposit token, including fee in required approval amount:",
|
|
3183
|
+
{
|
|
3184
|
+
depositAmount: depositTokenAmount,
|
|
3185
|
+
feeAmount: selectedFeeOption.amount,
|
|
3186
|
+
feeTokenAddress: selectedFeeOption.tokenAddress,
|
|
3187
|
+
depositTokenAddress,
|
|
3188
|
+
totalRequired: requiredAmount.toString(),
|
|
3189
|
+
},
|
|
3190
|
+
)
|
|
3191
|
+
} else {
|
|
3192
|
+
logger.console.log(
|
|
3193
|
+
"[trails-sdk] Fee token differs from deposit token, separate approval will be needed:",
|
|
3194
|
+
{
|
|
3195
|
+
depositAmount: depositTokenAmount,
|
|
3196
|
+
depositTokenAddress,
|
|
3197
|
+
feeAmount: selectedFeeOption.amount,
|
|
3198
|
+
feeTokenAddress: selectedFeeOption.tokenAddress,
|
|
3199
|
+
depositTokenRequired: requiredAmount.toString(),
|
|
3200
|
+
},
|
|
3201
|
+
)
|
|
3202
|
+
}
|
|
3034
3203
|
}
|
|
3035
3204
|
|
|
3036
3205
|
const needsApproval = await getNeedsIntentEntrypointApproval({
|
|
3037
3206
|
client: publicClient,
|
|
3038
3207
|
token: depositTokenAddress as `0x${string}`,
|
|
3039
3208
|
account: account.address,
|
|
3040
|
-
entrypoint:
|
|
3209
|
+
entrypoint: TRAILS_INTENT_ENTRYPOINT_ADDRESS,
|
|
3041
3210
|
amount: requiredAmount, // Check if we have enough allowance for this specific transaction
|
|
3042
3211
|
})
|
|
3043
3212
|
|
|
@@ -3055,13 +3224,14 @@ async function attemptGaslessDeposit({
|
|
|
3055
3224
|
},
|
|
3056
3225
|
)
|
|
3057
3226
|
|
|
3058
|
-
// 2. Get permit signature if approval needed
|
|
3227
|
+
// 2. Get permit signature if approval needed for deposit token
|
|
3228
|
+
// Note: Fee payment is handled by the backend/relayer, we only need permit for the deposit token
|
|
3059
3229
|
let permitSignature: string | undefined
|
|
3060
3230
|
let permitDeadline: number | undefined
|
|
3061
3231
|
|
|
3062
3232
|
if (needsApproval) {
|
|
3063
3233
|
logger.console.log(
|
|
3064
|
-
"[trails-sdk] Getting permit signature for infinite approval",
|
|
3234
|
+
"[trails-sdk] Getting permit signature for deposit token infinite approval",
|
|
3065
3235
|
)
|
|
3066
3236
|
|
|
3067
3237
|
// Use infinite approval (maxUint256) so user doesn't need to approve again
|
|
@@ -3070,6 +3240,7 @@ async function attemptGaslessDeposit({
|
|
|
3070
3240
|
"[trails-sdk] Using infinite approval for gasless deposits",
|
|
3071
3241
|
{
|
|
3072
3242
|
depositAmount: depositTokenAmount,
|
|
3243
|
+
depositTokenAddress,
|
|
3073
3244
|
permitAmount: permitAmount.toString(),
|
|
3074
3245
|
},
|
|
3075
3246
|
)
|
|
@@ -3078,7 +3249,7 @@ async function attemptGaslessDeposit({
|
|
|
3078
3249
|
publicClient,
|
|
3079
3250
|
walletClient,
|
|
3080
3251
|
signer: account.address,
|
|
3081
|
-
spender:
|
|
3252
|
+
spender: TRAILS_INTENT_ENTRYPOINT_ADDRESS,
|
|
3082
3253
|
tokenAddress: depositTokenAddress as `0x${string}`,
|
|
3083
3254
|
amount: permitAmount, // Infinite approval
|
|
3084
3255
|
chain,
|
|
@@ -3087,7 +3258,7 @@ async function attemptGaslessDeposit({
|
|
|
3087
3258
|
permitSignature = permitSig.signature
|
|
3088
3259
|
permitDeadline = Number(permitSig.deadline)
|
|
3089
3260
|
logger.console.log(
|
|
3090
|
-
"[trails-sdk]
|
|
3261
|
+
"[trails-sdk] Deposit token permit signature obtained for infinite approval",
|
|
3091
3262
|
)
|
|
3092
3263
|
}
|
|
3093
3264
|
|
|
@@ -3096,7 +3267,7 @@ async function attemptGaslessDeposit({
|
|
|
3096
3267
|
const nonce = await getUserNonce({
|
|
3097
3268
|
publicClient,
|
|
3098
3269
|
userAddress: account.address,
|
|
3099
|
-
intentEntrypoint:
|
|
3270
|
+
intentEntrypoint: TRAILS_INTENT_ENTRYPOINT_ADDRESS,
|
|
3100
3271
|
})
|
|
3101
3272
|
logger.console.log("[trails-sdk] User nonce:", nonce.toString())
|
|
3102
3273
|
|
|
@@ -3128,7 +3299,7 @@ async function attemptGaslessDeposit({
|
|
|
3128
3299
|
intentAddress: depositRecipient as `0x${string}`,
|
|
3129
3300
|
deadline: BigInt(deadline),
|
|
3130
3301
|
chainId: originChainId,
|
|
3131
|
-
contractAddress:
|
|
3302
|
+
contractAddress: TRAILS_INTENT_ENTRYPOINT_ADDRESS,
|
|
3132
3303
|
nonce,
|
|
3133
3304
|
feeAmount: BigInt(selectedFeeOption?.amount || "0"),
|
|
3134
3305
|
feeCollector: feeCollectorAddress,
|
|
@@ -3314,24 +3485,31 @@ export async function attemptNonGaslessUserDeposit({
|
|
|
3314
3485
|
|
|
3315
3486
|
logger.console.log("[trails-sdk] needsNativeFee", needsNativeFee)
|
|
3316
3487
|
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
? "0x"
|
|
3325
|
-
: getERC20TransferData({
|
|
3326
|
-
recipient: originIntentAddress,
|
|
3327
|
-
amount: BigInt(firstPreconditionMin) + BigInt(fee),
|
|
3328
|
-
}),
|
|
3329
|
-
value:
|
|
3330
|
-
originTokenAddress === zeroAddress
|
|
3331
|
-
? BigInt(firstPreconditionMin) + BigInt(fee)
|
|
3332
|
-
: "0",
|
|
3333
|
-
chainId: originChainId,
|
|
3488
|
+
// Build origin call params
|
|
3489
|
+
const originCallParamsBase = buildCrossChainDepositParams({
|
|
3490
|
+
originTokenAddress,
|
|
3491
|
+
originIntentAddress,
|
|
3492
|
+
depositAmount: firstPreconditionMin,
|
|
3493
|
+
fee,
|
|
3494
|
+
originChainId,
|
|
3334
3495
|
chain,
|
|
3496
|
+
})
|
|
3497
|
+
|
|
3498
|
+
// Estimate gas limit for consistency with actual transaction
|
|
3499
|
+
const gasLimit = await estimateGasLimit(
|
|
3500
|
+
publicClient,
|
|
3501
|
+
{
|
|
3502
|
+
account: account.address,
|
|
3503
|
+
to: originCallParamsBase.to,
|
|
3504
|
+
data: originCallParamsBase.data,
|
|
3505
|
+
value: BigInt(originCallParamsBase.value),
|
|
3506
|
+
},
|
|
3507
|
+
"deposit",
|
|
3508
|
+
)
|
|
3509
|
+
|
|
3510
|
+
const originCallParams = {
|
|
3511
|
+
...originCallParamsBase,
|
|
3512
|
+
gasLimit,
|
|
3335
3513
|
}
|
|
3336
3514
|
|
|
3337
3515
|
await attemptSwitchChain({
|
|
@@ -3587,13 +3765,14 @@ async function attemptUserDepositTx({
|
|
|
3587
3765
|
feeOptions,
|
|
3588
3766
|
trailsClient,
|
|
3589
3767
|
selectedFeeToken,
|
|
3768
|
+
walletId,
|
|
3590
3769
|
}: {
|
|
3591
3770
|
originTokenAddress: string
|
|
3592
3771
|
gasless: boolean
|
|
3593
3772
|
paymasterUrl?: string
|
|
3594
3773
|
chain: Chain
|
|
3595
3774
|
account: Account
|
|
3596
|
-
originRelayer: Relayer.
|
|
3775
|
+
originRelayer: Relayer.RpcRelayer
|
|
3597
3776
|
firstPreconditionMin: string
|
|
3598
3777
|
originIntentAddress: string
|
|
3599
3778
|
onOriginSend?: () => void
|
|
@@ -3615,6 +3794,7 @@ async function attemptUserDepositTx({
|
|
|
3615
3794
|
feeOptions?: any
|
|
3616
3795
|
trailsClient: TrailsAPIClient
|
|
3617
3796
|
selectedFeeToken?: any
|
|
3797
|
+
walletId?: string
|
|
3618
3798
|
}): Promise<TransactionReceipt | null> {
|
|
3619
3799
|
let originUserTxReceipt: TransactionReceipt | null = null
|
|
3620
3800
|
const originChainId = chain.id
|
|
@@ -3638,6 +3818,7 @@ async function attemptUserDepositTx({
|
|
|
3638
3818
|
gasless,
|
|
3639
3819
|
feeOptions,
|
|
3640
3820
|
selectedFeeToken,
|
|
3821
|
+
walletId,
|
|
3641
3822
|
)
|
|
3642
3823
|
logger.console.log(
|
|
3643
3824
|
"[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] doGasless check results:",
|
|
@@ -3680,12 +3861,15 @@ async function attemptUserDepositTx({
|
|
|
3680
3861
|
})
|
|
3681
3862
|
} catch (error) {
|
|
3682
3863
|
logger.console.log("[trails-sdk] gassless attempt failed", error)
|
|
3683
|
-
throw error
|
|
3864
|
+
// In strict gasless mode, re-throw error instead of falling back
|
|
3865
|
+
if (gasless) {
|
|
3866
|
+
throw error
|
|
3867
|
+
}
|
|
3684
3868
|
}
|
|
3685
3869
|
}
|
|
3686
3870
|
|
|
3687
3871
|
// If gasless attempt failed, try to send a regular transaction
|
|
3688
|
-
if (!originUserTxReceipt) {
|
|
3872
|
+
if (!originUserTxReceipt && !gasless) {
|
|
3689
3873
|
originUserTxReceipt = await attemptNonGaslessUserDeposit({
|
|
3690
3874
|
originTokenAddress,
|
|
3691
3875
|
firstPreconditionMin,
|
|
@@ -3719,7 +3903,16 @@ export function getDoGasless(
|
|
|
3719
3903
|
gasless: boolean,
|
|
3720
3904
|
feeOptions?: any,
|
|
3721
3905
|
selectedFeeToken?: any,
|
|
3906
|
+
walletId?: string,
|
|
3722
3907
|
): boolean {
|
|
3908
|
+
// Don't use gasless flow for sequence-waas wallet
|
|
3909
|
+
if (walletId === "sequence-waas") {
|
|
3910
|
+
logger.console.log(
|
|
3911
|
+
"[trails-sdk] [GASLESS-FLOW] getDoGasless: Skipping gasless flow for sequence-waas wallet",
|
|
3912
|
+
)
|
|
3913
|
+
return false
|
|
3914
|
+
}
|
|
3915
|
+
|
|
3723
3916
|
const hasFeeOptions = Boolean(feeOptions && feeOptions.feeOptions?.length > 0)
|
|
3724
3917
|
|
|
3725
3918
|
// Important: The UI passes selectedFeeToken in these states:
|
|
@@ -3856,7 +4049,7 @@ async function sendMetaTxAndWaitForReceipt({
|
|
|
3856
4049
|
feeQuote,
|
|
3857
4050
|
}: {
|
|
3858
4051
|
metaTx: MetaTxn
|
|
3859
|
-
relayer: Relayer.
|
|
4052
|
+
relayer: Relayer.RpcRelayer
|
|
3860
4053
|
precondition: IntentPrecondition | null
|
|
3861
4054
|
feeQuote?: string
|
|
3862
4055
|
}): Promise<{
|
|
@@ -4015,7 +4208,7 @@ async function checkAccountBalance({
|
|
|
4015
4208
|
balanceError,
|
|
4016
4209
|
}
|
|
4017
4210
|
} catch (error) {
|
|
4018
|
-
console.error("[trails-sdk] Error checking account balance:", error)
|
|
4211
|
+
logger.console.error("[trails-sdk] Error checking account balance:", error)
|
|
4019
4212
|
return {
|
|
4020
4213
|
hasEnoughBalance: false,
|
|
4021
4214
|
balance: BigInt(0),
|
|
@@ -4107,6 +4300,10 @@ export type UseQuoteProps = {
|
|
|
4107
4300
|
quoteProvider?: string | null
|
|
4108
4301
|
gasless?: boolean
|
|
4109
4302
|
paymasterUrl?: string
|
|
4303
|
+
selectedFeeToken?: {
|
|
4304
|
+
tokenAddress: string
|
|
4305
|
+
tokenSymbol?: string
|
|
4306
|
+
} | null
|
|
4110
4307
|
}
|
|
4111
4308
|
|
|
4112
4309
|
export type SwapReturn = {
|
|
@@ -4150,6 +4347,8 @@ export type Quote = {
|
|
|
4150
4347
|
toAmountUsdDisplay?: string
|
|
4151
4348
|
gasCostUsd?: number
|
|
4152
4349
|
gasCostUsdDisplay?: string
|
|
4350
|
+
gasCost?: string
|
|
4351
|
+
gasCostFormatted?: string
|
|
4153
4352
|
}
|
|
4154
4353
|
|
|
4155
4354
|
export type UseQuoteReturn = {
|
|
@@ -4175,6 +4374,7 @@ export function useQuote({
|
|
|
4175
4374
|
quoteProvider,
|
|
4176
4375
|
gasless,
|
|
4177
4376
|
paymasterUrl,
|
|
4377
|
+
selectedFeeToken,
|
|
4178
4378
|
relayerEnv,
|
|
4179
4379
|
nodeGatewayEnv,
|
|
4180
4380
|
}: Partial<
|
|
@@ -4209,174 +4409,187 @@ export function useQuote({
|
|
|
4209
4409
|
quoteProvider,
|
|
4210
4410
|
],
|
|
4211
4411
|
queryFn: async () => {
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
// Get token balance using async method
|
|
4228
|
-
const { balances } = await getTokenBalancesWithPrices({
|
|
4229
|
-
account: walletClient.account!.address,
|
|
4230
|
-
indexerGatewayClient,
|
|
4231
|
-
apiClient,
|
|
4232
|
-
})
|
|
4412
|
+
try {
|
|
4413
|
+
if (
|
|
4414
|
+
!walletClient ||
|
|
4415
|
+
!apiClient ||
|
|
4416
|
+
!trailsClient ||
|
|
4417
|
+
!fromTokenAddress ||
|
|
4418
|
+
!toTokenAddress ||
|
|
4419
|
+
!swapAmount ||
|
|
4420
|
+
!toRecipient ||
|
|
4421
|
+
!fromChainId ||
|
|
4422
|
+
!toChainId ||
|
|
4423
|
+
!indexerGatewayClient
|
|
4424
|
+
) {
|
|
4425
|
+
return null
|
|
4426
|
+
}
|
|
4233
4427
|
|
|
4234
|
-
|
|
4235
|
-
(
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
)
|
|
4428
|
+
// Get token balance using async method
|
|
4429
|
+
const { balances } = await getTokenBalancesWithPrices({
|
|
4430
|
+
account: walletClient.account!.address,
|
|
4431
|
+
indexerGatewayClient,
|
|
4432
|
+
apiClient,
|
|
4433
|
+
})
|
|
4241
4434
|
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4435
|
+
const originTokenBalance = balances.find(
|
|
4436
|
+
(b) =>
|
|
4437
|
+
b.chainId === fromChainId &&
|
|
4438
|
+
(b.contractAddress?.toLowerCase() ===
|
|
4439
|
+
fromTokenAddress.toLowerCase() ||
|
|
4440
|
+
(!b.contractAddress && fromTokenAddress === zeroAddress)),
|
|
4441
|
+
)
|
|
4245
4442
|
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
// }
|
|
4443
|
+
const originTokenBalanceAmount = originTokenBalance?.balance ?? "0"
|
|
4444
|
+
const destinationRelayer = getRelayer(toChainId)
|
|
4445
|
+
const originRelayer = getRelayer(fromChainId)
|
|
4250
4446
|
|
|
4251
|
-
|
|
4447
|
+
// Note: Disable this check for now to allow fetching a quote even when the origin balance is zero
|
|
4448
|
+
// if (originTokenBalanceAmount === "0") {
|
|
4449
|
+
// return null
|
|
4450
|
+
// }
|
|
4252
4451
|
|
|
4253
|
-
|
|
4254
|
-
(token) =>
|
|
4255
|
-
token.contractAddress?.toLowerCase() ===
|
|
4256
|
-
fromTokenAddress?.toLowerCase() && token.chainId === fromChainId,
|
|
4257
|
-
)
|
|
4258
|
-
const destinationToken = supportedTokens?.find(
|
|
4259
|
-
(token) =>
|
|
4260
|
-
token.contractAddress?.toLowerCase() ===
|
|
4261
|
-
toTokenAddress?.toLowerCase() && token.chainId === toChainId,
|
|
4262
|
-
)
|
|
4452
|
+
// logger.console.log("supportedTokens", supportedTokens)
|
|
4263
4453
|
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
{
|
|
4269
|
-
originToken,
|
|
4270
|
-
fromTokenAddress,
|
|
4271
|
-
fromChainId,
|
|
4272
|
-
},
|
|
4454
|
+
const originToken = supportedTokens?.find(
|
|
4455
|
+
(token) =>
|
|
4456
|
+
token.contractAddress?.toLowerCase() ===
|
|
4457
|
+
fromTokenAddress?.toLowerCase() && token.chainId === fromChainId,
|
|
4273
4458
|
)
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
logger.console.error(
|
|
4279
|
-
"[trails-sdk] Missing destination token decimals:",
|
|
4280
|
-
{
|
|
4281
|
-
destinationToken,
|
|
4282
|
-
toTokenAddress,
|
|
4283
|
-
toChainId,
|
|
4284
|
-
},
|
|
4459
|
+
const destinationToken = supportedTokens?.find(
|
|
4460
|
+
(token) =>
|
|
4461
|
+
token.contractAddress?.toLowerCase() ===
|
|
4462
|
+
toTokenAddress?.toLowerCase() && token.chainId === toChainId,
|
|
4285
4463
|
)
|
|
4286
|
-
throw new Error("Destination token decimals not found")
|
|
4287
|
-
}
|
|
4288
|
-
const destinationTokenSymbol = destinationToken?.symbol ?? ""
|
|
4289
|
-
const originTokenSymbol = originToken?.symbol ?? ""
|
|
4290
|
-
|
|
4291
|
-
const options = {
|
|
4292
|
-
account: walletClient.account!,
|
|
4293
|
-
originTokenAddress: fromTokenAddress,
|
|
4294
|
-
originChainId: fromChainId,
|
|
4295
|
-
originTokenBalance: originTokenBalanceAmount,
|
|
4296
|
-
destinationChainId: toChainId,
|
|
4297
|
-
recipient: toRecipient,
|
|
4298
|
-
destinationTokenAddress: toTokenAddress,
|
|
4299
|
-
swapAmount: swapAmount.toString(),
|
|
4300
|
-
tradeType: tradeType ?? TradeType.EXACT_OUTPUT,
|
|
4301
|
-
originTokenSymbol: originTokenSymbol,
|
|
4302
|
-
destinationTokenSymbol: destinationTokenSymbol,
|
|
4303
|
-
destinationCalldata: toCalldata as string,
|
|
4304
|
-
client: walletClient,
|
|
4305
|
-
apiClient,
|
|
4306
|
-
trailsClient,
|
|
4307
|
-
originRelayer,
|
|
4308
|
-
destinationRelayer,
|
|
4309
|
-
sourceTokenDecimals,
|
|
4310
|
-
destinationTokenDecimals,
|
|
4311
|
-
fee: "0",
|
|
4312
|
-
dryMode: false,
|
|
4313
|
-
onTransactionStateChange: onStatusUpdate ?? (() => {}),
|
|
4314
|
-
slippageTolerance: slippageTolerance?.toString(),
|
|
4315
|
-
quoteProvider: quoteProvider,
|
|
4316
|
-
gasless: gasless ?? false,
|
|
4317
|
-
paymasterUrl: paymasterUrl,
|
|
4318
|
-
}
|
|
4319
4464
|
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4465
|
+
const sourceTokenDecimals = originToken?.decimals
|
|
4466
|
+
if (!sourceTokenDecimals) {
|
|
4467
|
+
logger.console.error(
|
|
4468
|
+
"[trails-sdk] [useQuote] Missing source token decimals:",
|
|
4469
|
+
{
|
|
4470
|
+
originToken,
|
|
4471
|
+
fromTokenAddress,
|
|
4472
|
+
fromChainId,
|
|
4473
|
+
},
|
|
4474
|
+
)
|
|
4475
|
+
throw new Error("Source token decimals not found")
|
|
4476
|
+
}
|
|
4477
|
+
const destinationTokenDecimals = destinationToken?.decimals
|
|
4478
|
+
if (!destinationTokenDecimals) {
|
|
4479
|
+
logger.console.error(
|
|
4480
|
+
"[trails-sdk] Missing destination token decimals:",
|
|
4481
|
+
{
|
|
4482
|
+
destinationToken,
|
|
4483
|
+
toTokenAddress,
|
|
4484
|
+
toChainId,
|
|
4485
|
+
},
|
|
4486
|
+
)
|
|
4487
|
+
throw new Error("Destination token decimals not found")
|
|
4488
|
+
}
|
|
4489
|
+
const destinationTokenSymbol = destinationToken?.symbol ?? ""
|
|
4490
|
+
const originTokenSymbol = originToken?.symbol ?? ""
|
|
4491
|
+
|
|
4492
|
+
const options = {
|
|
4493
|
+
account: walletClient.account!,
|
|
4494
|
+
originTokenAddress: fromTokenAddress,
|
|
4495
|
+
originChainId: fromChainId,
|
|
4496
|
+
originTokenBalance: originTokenBalanceAmount,
|
|
4497
|
+
destinationChainId: toChainId,
|
|
4498
|
+
recipient: toRecipient,
|
|
4499
|
+
destinationTokenAddress: toTokenAddress,
|
|
4500
|
+
swapAmount: swapAmount.toString(),
|
|
4501
|
+
tradeType: tradeType ?? TradeType.EXACT_OUTPUT,
|
|
4502
|
+
originTokenSymbol: originTokenSymbol,
|
|
4503
|
+
destinationTokenSymbol: destinationTokenSymbol,
|
|
4504
|
+
destinationCalldata: toCalldata as string,
|
|
4505
|
+
client: walletClient,
|
|
4506
|
+
apiClient,
|
|
4507
|
+
trailsClient,
|
|
4508
|
+
originRelayer,
|
|
4509
|
+
destinationRelayer,
|
|
4510
|
+
sourceTokenDecimals,
|
|
4511
|
+
destinationTokenDecimals,
|
|
4512
|
+
fee: "0",
|
|
4513
|
+
dryMode: false,
|
|
4514
|
+
onTransactionStateChange: onStatusUpdate ?? (() => {}),
|
|
4515
|
+
slippageTolerance: slippageTolerance?.toString(),
|
|
4516
|
+
quoteProvider: quoteProvider,
|
|
4517
|
+
gasless: gasless ?? false,
|
|
4518
|
+
paymasterUrl: paymasterUrl,
|
|
4519
|
+
selectedFeeToken: selectedFeeToken ?? undefined,
|
|
4520
|
+
}
|
|
4348
4521
|
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4522
|
+
logger.console.log("[trails-sdk] options", options)
|
|
4523
|
+
|
|
4524
|
+
const { quote: prepareSendQuote, send } = await prepareSend(options)
|
|
4525
|
+
|
|
4526
|
+
const quote = {
|
|
4527
|
+
fromAmount: prepareSendQuote.originAmount,
|
|
4528
|
+
toAmount: prepareSendQuote.destinationAmount,
|
|
4529
|
+
fromAmountMin: prepareSendQuote.originAmountMin,
|
|
4530
|
+
toAmountMin: prepareSendQuote.destinationAmountMin,
|
|
4531
|
+
originToken: prepareSendQuote.originToken,
|
|
4532
|
+
destinationToken: prepareSendQuote.destinationToken,
|
|
4533
|
+
originChain: prepareSendQuote.originChain,
|
|
4534
|
+
destinationChain: prepareSendQuote.destinationChain,
|
|
4535
|
+
fees: prepareSendQuote.fees,
|
|
4536
|
+
priceImpact: prepareSendQuote.priceImpact,
|
|
4537
|
+
completionEstimateSeconds: prepareSendQuote.completionEstimateSeconds,
|
|
4538
|
+
slippageTolerance: prepareSendQuote.slippageTolerance,
|
|
4539
|
+
transactionStates: prepareSendQuote.transactionStates,
|
|
4540
|
+
originTokenRate: prepareSendQuote.originTokenRate,
|
|
4541
|
+
destinationTokenRate: prepareSendQuote.destinationTokenRate,
|
|
4542
|
+
quoteProvider: prepareSendQuote.quoteProvider,
|
|
4543
|
+
fromAmountUsdDisplay:
|
|
4544
|
+
prepareSendQuote.originAmountUsdDisplay ?? undefined,
|
|
4545
|
+
toAmountUsdDisplay:
|
|
4546
|
+
prepareSendQuote.destinationAmountUsdDisplay ?? undefined,
|
|
4547
|
+
gasCostUsd: prepareSendQuote.gasCostUsd ?? undefined,
|
|
4548
|
+
gasCostUsdDisplay: prepareSendQuote.gasCostUsdDisplay ?? undefined,
|
|
4549
|
+
gasCost: prepareSendQuote.gasCost ?? undefined,
|
|
4550
|
+
gasCostFormatted: prepareSendQuote.gasCostFormatted ?? undefined,
|
|
4551
|
+
}
|
|
4355
4552
|
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4553
|
+
const swap = async (): Promise<SwapReturn> => {
|
|
4554
|
+
const {
|
|
4555
|
+
originUserTxReceipt,
|
|
4556
|
+
destinationMetaTxnReceipt,
|
|
4557
|
+
totalCompletionSeconds,
|
|
4558
|
+
} = await send({
|
|
4559
|
+
selectedFeeToken: selectedFeeToken ?? undefined,
|
|
4560
|
+
})
|
|
4561
|
+
|
|
4562
|
+
return {
|
|
4563
|
+
originTransaction: {
|
|
4564
|
+
transactionHash: originUserTxReceipt?.transactionHash,
|
|
4565
|
+
explorerUrl: getExplorerUrl({
|
|
4566
|
+
txHash: originUserTxReceipt?.transactionHash as string,
|
|
4567
|
+
chainId: fromChainId,
|
|
4568
|
+
}),
|
|
4569
|
+
receipt: originUserTxReceipt,
|
|
4570
|
+
},
|
|
4571
|
+
destinationTransaction: {
|
|
4572
|
+
transactionHash: destinationMetaTxnReceipt?.txnHash,
|
|
4573
|
+
explorerUrl: getExplorerUrl({
|
|
4574
|
+
txHash: destinationMetaTxnReceipt?.txnHash as string,
|
|
4575
|
+
chainId: toChainId,
|
|
4576
|
+
}),
|
|
4577
|
+
receipt: destinationMetaTxnReceipt,
|
|
4578
|
+
},
|
|
4579
|
+
totalCompletionSeconds,
|
|
4580
|
+
}
|
|
4374
4581
|
}
|
|
4375
|
-
}
|
|
4376
4582
|
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4583
|
+
return {
|
|
4584
|
+
quote,
|
|
4585
|
+
swap,
|
|
4586
|
+
}
|
|
4587
|
+
} catch (error) {
|
|
4588
|
+
logger.console.error(
|
|
4589
|
+
"[trails-sdk] [useQuote] Error getting quote:",
|
|
4590
|
+
error,
|
|
4591
|
+
)
|
|
4592
|
+
throw getFullErrorMessage(error)
|
|
4380
4593
|
}
|
|
4381
4594
|
},
|
|
4382
4595
|
// Prevent unnecessary refetching
|
|
@@ -4532,6 +4745,7 @@ export async function getNormalizedQuoteObject({
|
|
|
4532
4745
|
originNativeTokenPriceUsd,
|
|
4533
4746
|
quoteProvider,
|
|
4534
4747
|
noSufficientBalance,
|
|
4748
|
+
estimatedGasLimit,
|
|
4535
4749
|
}: {
|
|
4536
4750
|
originDepositAddress?: string
|
|
4537
4751
|
destinationDepositAddress?: string
|
|
@@ -4555,6 +4769,7 @@ export async function getNormalizedQuoteObject({
|
|
|
4555
4769
|
originNativeTokenPriceUsd?: number | null
|
|
4556
4770
|
quoteProvider?: string
|
|
4557
4771
|
noSufficientBalance?: boolean
|
|
4772
|
+
estimatedGasLimit?: bigint
|
|
4558
4773
|
}): Promise<PrepareSendQuote> {
|
|
4559
4774
|
if (!destinationChainId) {
|
|
4560
4775
|
throw new Error("Destination chain id is required")
|
|
@@ -4582,7 +4797,7 @@ export async function getNormalizedQuoteObject({
|
|
|
4582
4797
|
const destinationChain = getChainInfo(destinationChainId)
|
|
4583
4798
|
|
|
4584
4799
|
if (!originToken || !destinationToken || !originChain || !destinationChain) {
|
|
4585
|
-
console.error("[trails-sdk] Token or chain not found", {
|
|
4800
|
+
logger.console.error("[trails-sdk] Token or chain not found", {
|
|
4586
4801
|
originToken,
|
|
4587
4802
|
destinationToken,
|
|
4588
4803
|
originChain,
|
|
@@ -4656,17 +4871,52 @@ export async function getNormalizedQuoteObject({
|
|
|
4656
4871
|
|
|
4657
4872
|
let gasCostUsd: number = 0
|
|
4658
4873
|
let gasCostUsdDisplay: string = "0"
|
|
4874
|
+
let gasCost: string = "0"
|
|
4875
|
+
let gasCostFormatted: string = "0"
|
|
4659
4876
|
try {
|
|
4660
4877
|
if (originNativeTokenPriceUsd) {
|
|
4878
|
+
// Use the actual estimated gas limit if provided, otherwise use default
|
|
4879
|
+
// This ensures the quote gas cost matches what will be used in the actual transaction
|
|
4880
|
+
const gasLimitForCost = estimatedGasLimit || DEFAULT_MIN_GASLIMIT
|
|
4881
|
+
|
|
4882
|
+
logger.console.log(
|
|
4883
|
+
"[trails-sdk][gas-estimation] Calculating gas cost for quote with gasLimit:",
|
|
4884
|
+
gasLimitForCost,
|
|
4885
|
+
"(estimated:",
|
|
4886
|
+
estimatedGasLimit,
|
|
4887
|
+
"default:",
|
|
4888
|
+
DEFAULT_MIN_GASLIMIT,
|
|
4889
|
+
")",
|
|
4890
|
+
)
|
|
4891
|
+
|
|
4892
|
+
const gasCostWei = await estimateGasCost(publicClient, gasLimitForCost)
|
|
4893
|
+
gasCost = gasCostWei.toString()
|
|
4894
|
+
gasCostFormatted = formatUnits(gasCostWei, 18) // Native tokens always use 18 decimals
|
|
4895
|
+
|
|
4896
|
+
// Calculate USD value
|
|
4661
4897
|
gasCostUsd = await estimateGasCostUsd(
|
|
4662
4898
|
publicClient,
|
|
4663
4899
|
originNativeTokenPriceUsd,
|
|
4664
|
-
|
|
4900
|
+
gasLimitForCost,
|
|
4665
4901
|
)
|
|
4666
4902
|
gasCostUsdDisplay = formatUsdAmountDisplay(gasCostUsd)
|
|
4903
|
+
|
|
4904
|
+
logger.console.log(
|
|
4905
|
+
"[trails-sdk][gas-estimation] Quote gas cost calculated:",
|
|
4906
|
+
{
|
|
4907
|
+
gasCostWei,
|
|
4908
|
+
gasCost,
|
|
4909
|
+
gasCostFormatted,
|
|
4910
|
+
gasCostUsd,
|
|
4911
|
+
gasCostUsdDisplay,
|
|
4912
|
+
},
|
|
4913
|
+
)
|
|
4667
4914
|
}
|
|
4668
4915
|
} catch (error) {
|
|
4669
|
-
console.error(
|
|
4916
|
+
logger.console.error(
|
|
4917
|
+
"[trails-sdk][gas-estimation] Error estimating gas cost for quote display",
|
|
4918
|
+
error,
|
|
4919
|
+
)
|
|
4670
4920
|
}
|
|
4671
4921
|
|
|
4672
4922
|
// Calculate exchange rates
|
|
@@ -4742,6 +4992,8 @@ export async function getNormalizedQuoteObject({
|
|
|
4742
4992
|
transactionStates: transactionStates || [],
|
|
4743
4993
|
gasCostUsd,
|
|
4744
4994
|
gasCostUsdDisplay,
|
|
4995
|
+
gasCost,
|
|
4996
|
+
gasCostFormatted,
|
|
4745
4997
|
originTokenRate: exchangeRates.originTokenRate,
|
|
4746
4998
|
destinationTokenRate: exchangeRates.destinationTokenRate,
|
|
4747
4999
|
originAmountDisplay: formatAmountDisplay(originAmountFormatted),
|