0xtrails 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analytics.d.ts +8 -3
- package/dist/analytics.d.ts.map +1 -1
- package/dist/{ccip-DhEkQ6QC.js → ccip-Dw5AN7oU.js} +1 -1
- package/dist/cctp.d.ts +0 -149
- package/dist/cctp.d.ts.map +1 -1
- package/dist/chains.d.ts +28 -3
- package/dist/chains.d.ts.map +1 -1
- package/dist/config.d.ts +11 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/contractUtils.d.ts.map +1 -1
- package/dist/estimate.d.ts.map +1 -1
- package/dist/fees.d.ts.map +1 -1
- package/dist/gasless.d.ts +12 -0
- package/dist/gasless.d.ts.map +1 -1
- package/dist/{index-MhD2DA7_.js → index-BtVUTbEZ.js} +30984 -38945
- package/dist/index.d.ts +7 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +108 -107
- package/dist/indexerClient.d.ts +2 -2
- package/dist/intents.d.ts +0 -17
- package/dist/intents.d.ts.map +1 -1
- package/dist/mutations.d.ts.map +1 -1
- package/dist/paymasterSend.d.ts.map +1 -1
- package/dist/prepareSend.d.ts +1 -1
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/sendUserOp.d.ts +0 -18
- package/dist/sendUserOp.d.ts.map +1 -1
- package/dist/tokenBalances.d.ts.map +1 -1
- package/dist/tokens.d.ts +10 -8
- package/dist/tokens.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts +4 -5
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/gaslessDeposit.d.ts +4 -5
- package/dist/transactionIntent/deposits/gaslessDeposit.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/standardDeposit.d.ts +2 -2
- package/dist/transactionIntent/deposits/standardDeposit.d.ts.map +1 -1
- package/dist/transactionIntent/execution/transactionState.d.ts +2 -2
- package/dist/transactionIntent/execution/transactionState.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/crossChain.d.ts +4 -4
- package/dist/transactionIntent/handlers/crossChain.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/index.d.ts +0 -1
- package/dist/transactionIntent/handlers/index.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts +4 -34
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts.map +1 -1
- package/dist/transactionIntent/quote/normalizeQuote.d.ts.map +1 -1
- package/dist/transactionIntent/quote/quoteHelpers.d.ts +2 -1
- package/dist/transactionIntent/quote/quoteHelpers.d.ts.map +1 -1
- package/dist/transactionIntent/types.d.ts +6 -19
- package/dist/transactionIntent/types.d.ts.map +1 -1
- package/dist/transactionIntent/utils/index.d.ts +0 -1
- package/dist/transactionIntent/utils/index.d.ts.map +1 -1
- package/dist/transactions.d.ts +2 -20
- package/dist/transactions.d.ts.map +1 -1
- package/dist/utils.d.ts +8 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/walletUtils.d.ts +21 -0
- package/dist/walletUtils.d.ts.map +1 -0
- package/dist/wallets.d.ts +33 -240
- package/dist/wallets.d.ts.map +1 -1
- package/dist/widget/components/AccountIntentTransactionHistory.d.ts.map +1 -1
- package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
- package/dist/widget/components/FeeOption.d.ts +8 -13
- package/dist/widget/components/FeeOption.d.ts.map +1 -1
- package/dist/widget/components/FeeOptions.d.ts +11 -5
- package/dist/widget/components/FeeOptions.d.ts.map +1 -1
- package/dist/widget/components/NativeGasOption.d.ts.map +1 -1
- package/dist/widget/components/Pay.d.ts.map +1 -1
- package/dist/widget/components/PoolDeposit.d.ts.map +1 -1
- package/dist/widget/components/QRCodeDeposit.d.ts +5 -0
- package/dist/widget/components/QRCodeDeposit.d.ts.map +1 -1
- package/dist/widget/components/QRCodeWalletSelect.d.ts +13 -0
- package/dist/widget/components/QRCodeWalletSelect.d.ts.map +1 -0
- package/dist/widget/components/QrCode.d.ts.map +1 -1
- package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
- package/dist/widget/components/Receipt.d.ts.map +1 -1
- package/dist/widget/components/ScreenHeader.d.ts +1 -1
- package/dist/widget/components/ScreenHeader.d.ts.map +1 -1
- package/dist/widget/components/Toast.d.ts.map +1 -1
- package/dist/widget/components/TokenImage.d.ts.map +1 -1
- package/dist/widget/css/compiled.css +1 -1
- package/dist/widget/hooks/useCheckout.d.ts +15 -1
- package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
- package/dist/widget/hooks/useCurrentScreen.d.ts +1 -1
- package/dist/widget/hooks/useCurrentScreen.d.ts.map +1 -1
- package/dist/widget/hooks/useDebugScreens.d.ts +1 -1
- package/dist/widget/hooks/useDebugScreens.d.ts.map +1 -1
- package/dist/widget/hooks/useIntentTransactionHistory.d.ts.map +1 -1
- package/dist/widget/hooks/useIsConnectedWalletSmartContract.d.ts +7 -0
- package/dist/widget/hooks/useIsConnectedWalletSmartContract.d.ts.map +1 -0
- package/dist/widget/hooks/useIsSequenceWallet.d.ts +6 -0
- package/dist/widget/hooks/useIsSequenceWallet.d.ts.map +1 -0
- package/dist/widget/hooks/useQuote.d.ts +5 -8
- package/dist/widget/hooks/useQuote.d.ts.map +1 -1
- package/dist/widget/hooks/useRecentTokens.d.ts.map +1 -1
- package/dist/widget/hooks/useSelectedFeeOption.d.ts +30 -0
- package/dist/widget/hooks/useSelectedFeeOption.d.ts.map +1 -0
- package/dist/widget/hooks/useSendForm.d.ts +6 -15
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
- package/dist/widget/index.js +1 -1
- package/dist/widget/providers/TrailsProvider.d.ts +23 -12
- package/dist/widget/providers/TrailsProvider.d.ts.map +1 -1
- package/dist/widget/widget.d.ts +11 -0
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/analytics.ts +53 -21
- package/src/cctp.ts +0 -1016
- package/src/chains.ts +93 -39
- package/src/config.ts +24 -6
- package/src/constants.ts +1 -4
- package/src/contractUtils.ts +6 -6
- package/src/estimate.ts +3 -6
- package/src/fees.ts +5 -10
- package/src/gasless.ts +45 -0
- package/src/index.ts +7 -6
- package/src/indexerClient.ts +2 -2
- package/src/intents.ts +52 -206
- package/src/mutations.ts +3 -2
- package/src/paymasterSend.ts +2 -5
- package/src/prepareSend.ts +9 -12
- package/src/sendUserOp.ts +3 -64
- package/src/tokenBalances.ts +2 -1
- package/src/tokens.ts +62 -133
- package/src/trailsClient.ts +1 -1
- package/src/transactionIntent/deposits/depositOrchestrator.ts +14 -15
- package/src/transactionIntent/deposits/gaslessDeposit.ts +70 -100
- package/src/transactionIntent/deposits/standardDeposit.ts +22 -28
- package/src/transactionIntent/execution/transactionState.ts +2 -2
- package/src/transactionIntent/handlers/crossChain.ts +165 -385
- package/src/transactionIntent/handlers/index.ts +0 -1
- package/src/transactionIntent/handlers/sameChainSameToken.ts +228 -94
- package/src/transactionIntent/quote/normalizeQuote.ts +4 -6
- package/src/transactionIntent/quote/quoteHelpers.ts +35 -3
- package/src/transactionIntent/types.ts +6 -27
- package/src/transactionIntent/utils/index.ts +0 -1
- package/src/transactions.ts +6 -203
- package/src/umd.tsx +1 -3
- package/src/utils.ts +28 -8
- package/src/walletUtils.ts +42 -0
- package/src/wallets.ts +361 -203
- package/src/widget/compiled.css +1 -1
- package/src/widget/components/AccountIntentTransactionHistory.tsx +73 -4
- package/src/widget/components/AccountSettings.tsx +17 -17
- package/src/widget/components/ChainList.tsx +3 -3
- package/src/widget/components/ClassicSwap.tsx +19 -10
- package/src/widget/components/ConfigDisplay.tsx +1 -1
- package/src/widget/components/FeeOption.tsx +63 -20
- package/src/widget/components/FeeOptions.tsx +54 -123
- package/src/widget/components/NativeGasOption.tsx +3 -1
- package/src/widget/components/Pay.tsx +18 -11
- package/src/widget/components/PoolDeposit.tsx +23 -10
- package/src/widget/components/QRCodeDeposit.tsx +50 -30
- package/src/widget/components/QRCodeWalletSelect.tsx +77 -0
- package/src/widget/components/QrCode.tsx +188 -233
- package/src/widget/components/QuoteDetails.tsx +48 -2
- package/src/widget/components/Receipt.tsx +5 -2
- package/src/widget/components/ScreenHeader.tsx +10 -8
- package/src/widget/components/Toast.tsx +10 -0
- package/src/widget/components/TokenImage.tsx +56 -13
- package/src/widget/hooks/useCheckout.ts +71 -0
- package/src/widget/hooks/useCurrentScreen.tsx +1 -0
- package/src/widget/hooks/useDebugScreens.ts +5 -0
- package/src/widget/hooks/useIntentTransactionHistory.ts +788 -418
- package/src/widget/hooks/useIsConnectedWalletSmartContract.ts +43 -0
- package/src/widget/hooks/useIsSequenceWallet.ts +17 -0
- package/src/widget/hooks/useQuote.ts +16 -17
- package/src/widget/hooks/useRecentTokens.ts +2 -1
- package/src/widget/hooks/useSelectedFeeOption.tsx +257 -0
- package/src/widget/hooks/useSendForm.ts +172 -47
- package/src/widget/hooks/useTokenList.ts +15 -2
- package/src/widget/providers/TrailsProvider.tsx +53 -25
- package/src/widget/widget.tsx +119 -48
- package/dist/cctpqueue.d.ts +0 -18
- package/dist/cctpqueue.d.ts.map +0 -1
- package/dist/preconditions.d.ts +0 -12
- package/dist/preconditions.d.ts.map +0 -1
- package/dist/transactionIntent/handlers/sameChainDifferentToken.d.ts +0 -62
- package/dist/transactionIntent/handlers/sameChainDifferentToken.d.ts.map +0 -1
- package/dist/transactionIntent/utils/lifiHelpers.d.ts +0 -10
- package/dist/transactionIntent/utils/lifiHelpers.d.ts.map +0 -1
- package/dist/widget/hooks/useSelectedFeeToken.d.ts +0 -33
- package/dist/widget/hooks/useSelectedFeeToken.d.ts.map +0 -1
- package/src/cctpqueue.ts +0 -69
- package/src/preconditions.ts +0 -47
- package/src/transactionIntent/handlers/sameChainDifferentToken.ts +0 -323
- package/src/transactionIntent/utils/lifiHelpers.ts +0 -68
- package/src/widget/hooks/useSelectedFeeToken.tsx +0 -288
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { Account, Chain, WalletClient, TransactionReceipt } from "viem"
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import type {
|
|
2
|
+
import { formatUnits } from "viem"
|
|
3
|
+
import { getPublicRpcClient } from "../../chains.js"
|
|
4
|
+
import type { FeeOption, TrailsApi } from "@0xsequence/trails-api"
|
|
5
|
+
import type { PrepareSendReturn, SendReturn } from "../types.js"
|
|
6
|
+
import type { IntentTransaction } from "@0xsequence/trails-api"
|
|
5
7
|
import type { TransactionState } from "../../transactions.js"
|
|
6
8
|
import type { CheckoutOnHandlers } from "../../widget/hooks/useCheckout.js"
|
|
7
9
|
import type {
|
|
@@ -10,7 +12,6 @@ import type {
|
|
|
10
12
|
DepositSignature,
|
|
11
13
|
ExecuteIntentResponse,
|
|
12
14
|
} from "@0xsequence/trails-api"
|
|
13
|
-
import type { SelectedFeeToken } from "../types.js"
|
|
14
15
|
import { logger } from "../../logger.js"
|
|
15
16
|
import {
|
|
16
17
|
isTestnetDebugMode,
|
|
@@ -36,39 +37,10 @@ import { getChainInfo } from "../../chains.js"
|
|
|
36
37
|
import { getTransactionStateFromReceipt } from "../execution/transactionState.js"
|
|
37
38
|
import { calcAmountUsdPrice } from "../../prices.js"
|
|
38
39
|
import { pollIntentReceipt } from "../../intentReceiptPoller.js"
|
|
39
|
-
import {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
* This handler manages simple same-chain token transfers (e.g., using USDC to transact with USDC on the same chain).
|
|
44
|
-
* It supports both standard transfers and custom calldata execution.
|
|
45
|
-
*
|
|
46
|
-
* Key characteristics:
|
|
47
|
-
* - Uses the Trails API with getIntent and commitIntent for setup
|
|
48
|
-
* - Single transaction leg (user transfer)
|
|
49
|
-
* - No cross-chain bridging or token swapping required
|
|
50
|
-
* - Direct transaction submission via attemptUserDepositTx (simpler than cross-chain polling)
|
|
51
|
-
* - Supports both gasless and standard fee payment modes
|
|
52
|
-
*
|
|
53
|
-
* Transaction Flow:
|
|
54
|
-
* 1. Get intent via getIntent (Intent object with validation)
|
|
55
|
-
* 2. Commit intent via commitIntent (Record created in backend)
|
|
56
|
-
* 3. User submits transaction via attemptUserDepositTx (handles both gasless and standard)
|
|
57
|
-
* 4. Wait for transaction receipt (direct receipt polling, not via waitIntentReceipt API)
|
|
58
|
-
* 5. Update transaction state and invoke callbacks
|
|
59
|
-
*
|
|
60
|
-
* Error Handling:
|
|
61
|
-
* - Balance validation before transaction submission
|
|
62
|
-
* - Gas estimation for accurate fee calculation
|
|
63
|
-
* - Proper error propagation with checkout error callbacks
|
|
64
|
-
* - Fallback logging for debugging
|
|
65
|
-
*
|
|
66
|
-
* State Management:
|
|
67
|
-
* - transactionStates[0]: User transfer transaction
|
|
68
|
-
* - Updates propagated via onTransactionStateChange callback
|
|
69
|
-
* - Analytics tracking for payment completion or errors
|
|
70
|
-
* - Support for gasless fee options via gasFeeOptions
|
|
71
|
-
*/
|
|
40
|
+
import { isNativeToken } from "../../utils.js"
|
|
41
|
+
import { getAccountTransactionHistory } from "../../transactions.js"
|
|
42
|
+
import { POLLING_INTERVALS } from "../constants.js"
|
|
43
|
+
|
|
72
44
|
export async function handleSameChainSameToken({
|
|
73
45
|
mainSignerAddress,
|
|
74
46
|
originTokenAddress,
|
|
@@ -93,12 +65,13 @@ export async function handleSameChainSameToken({
|
|
|
93
65
|
mode,
|
|
94
66
|
fundMethod,
|
|
95
67
|
paymasterUrl,
|
|
96
|
-
selectedFeeToken,
|
|
97
68
|
walletId,
|
|
98
69
|
trailsClient,
|
|
99
70
|
abortSignal,
|
|
100
71
|
commitIntentFn,
|
|
101
72
|
executeIntentFn,
|
|
73
|
+
sequenceProjectAccessKey,
|
|
74
|
+
sequenceIndexerUrl,
|
|
102
75
|
}: {
|
|
103
76
|
mainSignerAddress: string
|
|
104
77
|
originTokenAddress: string
|
|
@@ -124,7 +97,6 @@ export async function handleSameChainSameToken({
|
|
|
124
97
|
mode?: "pay" | "fund" | "earn" | "swap" | "receive"
|
|
125
98
|
fundMethod?: string
|
|
126
99
|
paymasterUrl?: string
|
|
127
|
-
selectedFeeToken?: SelectedFeeToken
|
|
128
100
|
walletId?: string
|
|
129
101
|
trailsClient: TrailsApi
|
|
130
102
|
abortSignal?: AbortSignal
|
|
@@ -134,6 +106,8 @@ export async function handleSameChainSameToken({
|
|
|
134
106
|
depositTransactionHash?: string
|
|
135
107
|
depositSignature?: DepositSignature
|
|
136
108
|
}) => Promise<ExecuteIntentResponse>
|
|
109
|
+
sequenceProjectAccessKey?: string
|
|
110
|
+
sequenceIndexerUrl?: string
|
|
137
111
|
}): Promise<PrepareSendReturn> {
|
|
138
112
|
logger.console.log("[trails-sdk] isToSameToken && isToSameChain")
|
|
139
113
|
const testnet = isTestnetDebugMode()
|
|
@@ -142,10 +116,7 @@ export async function handleSameChainSameToken({
|
|
|
142
116
|
const effectiveOriginTokenAddress = testnet
|
|
143
117
|
? getTestnetOriginTokenAddress(effectiveOriginChainId)
|
|
144
118
|
: originTokenAddress
|
|
145
|
-
const effectivePublicClient =
|
|
146
|
-
chain: effectiveOriginChain,
|
|
147
|
-
transport: http(),
|
|
148
|
-
})
|
|
119
|
+
const effectivePublicClient = getPublicRpcClient(effectiveOriginChain)
|
|
149
120
|
|
|
150
121
|
let noSufficientBalance = false
|
|
151
122
|
|
|
@@ -163,8 +134,8 @@ export async function handleSameChainSameToken({
|
|
|
163
134
|
const hasCustomCalldata = getIsCustomCalldata(destinationCalldata)
|
|
164
135
|
|
|
165
136
|
// For same-chain transactions, use Intent flow to support gasless deposits
|
|
166
|
-
const
|
|
167
|
-
const intentArgs = getIntentArgs(
|
|
137
|
+
const salt = Date.now().toString()
|
|
138
|
+
const intentArgs = await getIntentArgs(
|
|
168
139
|
mainSignerAddress,
|
|
169
140
|
effectiveOriginChainId,
|
|
170
141
|
effectiveOriginTokenAddress,
|
|
@@ -174,10 +145,12 @@ export async function handleSameChainSameToken({
|
|
|
174
145
|
"0", // destinationTokenAmount (exact input)
|
|
175
146
|
recipient,
|
|
176
147
|
destinationCalldata,
|
|
177
|
-
|
|
148
|
+
salt,
|
|
178
149
|
slippageTolerance,
|
|
179
150
|
TradeType.EXACT_INPUT,
|
|
180
151
|
quoteProvider || "",
|
|
152
|
+
undefined, // connector - not available in this context
|
|
153
|
+
walletId, // walletId - use this to check for Sequence wallets
|
|
181
154
|
)
|
|
182
155
|
|
|
183
156
|
logger.console.log(
|
|
@@ -198,7 +171,7 @@ export async function handleSameChainSameToken({
|
|
|
198
171
|
logger.console.log("[trails-sdk] Quote intent:", intent)
|
|
199
172
|
logger.console.log("[trails-sdk] Quote intent gasFeeOptions:", gasFeeOptions)
|
|
200
173
|
|
|
201
|
-
if (!intent.
|
|
174
|
+
if (!intent.originPrecondition || !intent.originCalls) {
|
|
202
175
|
throw new Error("Invalid intent")
|
|
203
176
|
}
|
|
204
177
|
|
|
@@ -279,36 +252,29 @@ export async function handleSameChainSameToken({
|
|
|
279
252
|
feeOptions: gasFeeOptions,
|
|
280
253
|
send: async ({
|
|
281
254
|
onOriginSend,
|
|
282
|
-
|
|
255
|
+
selectedFeeOption: runtimeSelectedFeeOption,
|
|
283
256
|
}: {
|
|
284
257
|
onOriginSend?: () => void
|
|
285
|
-
|
|
258
|
+
selectedFeeOption?: FeeOption | null
|
|
286
259
|
}): Promise<SendReturn> => {
|
|
287
|
-
// Use runtime
|
|
288
|
-
const
|
|
289
|
-
runtimeSelectedFeeToken ?? selectedFeeToken
|
|
260
|
+
// Use runtime selectedFeeOption (passed at execution time, always up-to-date)
|
|
261
|
+
const effectiveSelectedFeeOption = runtimeSelectedFeeOption
|
|
290
262
|
// Check if gasless flow is enabled:
|
|
291
|
-
// -
|
|
263
|
+
// - selectedFeeOption must exist and not be null/undefined
|
|
292
264
|
// - tokenAddress must not be native token (zeroAddress or ethAddress)
|
|
293
265
|
// - walletId must not be sequence-waas
|
|
294
266
|
const effectiveGasless =
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
effectiveSelectedFeeToken.tokenAddress.toLowerCase() !==
|
|
301
|
-
zeroAddress.toLowerCase() &&
|
|
302
|
-
effectiveSelectedFeeToken.tokenAddress !== ethAddress &&
|
|
303
|
-
effectiveSelectedFeeToken.tokenAddress.toLowerCase() !==
|
|
304
|
-
ethAddress.toLowerCase() &&
|
|
267
|
+
effectiveSelectedFeeOption !== null &&
|
|
268
|
+
effectiveSelectedFeeOption !== undefined &&
|
|
269
|
+
effectiveSelectedFeeOption.tokenAddress !== undefined &&
|
|
270
|
+
effectiveSelectedFeeOption.tokenAddress !== null &&
|
|
271
|
+
!isNativeToken(effectiveSelectedFeeOption.tokenAddress) &&
|
|
305
272
|
walletId !== "sequence-waas"
|
|
306
273
|
logger.console.log(
|
|
307
274
|
"[trails-sdk] [FEE-SELECT] [GASLESS-FLOW] send() called for same-chain:",
|
|
308
275
|
{
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
effectiveSelectedFeeToken,
|
|
276
|
+
runtimeSelectedFeeOption,
|
|
277
|
+
effectiveSelectedFeeOption,
|
|
312
278
|
effectiveGasless,
|
|
313
279
|
},
|
|
314
280
|
)
|
|
@@ -365,8 +331,8 @@ export async function handleSameChainSameToken({
|
|
|
365
331
|
logger.console.log("[trails-sdk] origin call params", originCallParams)
|
|
366
332
|
|
|
367
333
|
let depositUserTxnReceipt: TransactionReceipt | null = null
|
|
368
|
-
|
|
369
|
-
const
|
|
334
|
+
let originIntentTransaction: IntentTransaction | null = null
|
|
335
|
+
const destinationIntentTransaction: IntentTransaction | null = null
|
|
370
336
|
|
|
371
337
|
// Commit the intent
|
|
372
338
|
const commitIntentFnToUse =
|
|
@@ -444,7 +410,7 @@ export async function handleSameChainSameToken({
|
|
|
444
410
|
paymasterUrl,
|
|
445
411
|
chain: effectiveOriginChain,
|
|
446
412
|
account,
|
|
447
|
-
|
|
413
|
+
depositAmount: swapAmount,
|
|
448
414
|
originIntentAddress: intent.originIntentAddress,
|
|
449
415
|
onOriginSend,
|
|
450
416
|
publicClient: effectivePublicClient,
|
|
@@ -464,7 +430,7 @@ export async function handleSameChainSameToken({
|
|
|
464
430
|
depositAmountUsd,
|
|
465
431
|
feeOptions: gasFeeOptions,
|
|
466
432
|
trailsClient,
|
|
467
|
-
|
|
433
|
+
selectedFeeOption: effectiveSelectedFeeOption,
|
|
468
434
|
walletId,
|
|
469
435
|
abortSignal,
|
|
470
436
|
checkoutOnHandlers,
|
|
@@ -482,8 +448,187 @@ export async function handleSameChainSameToken({
|
|
|
482
448
|
isGasless: effectiveGasless,
|
|
483
449
|
})
|
|
484
450
|
|
|
485
|
-
// For
|
|
486
|
-
|
|
451
|
+
// For QR code mode, we need to detect the deposit first, call executeIntent, then start polling
|
|
452
|
+
// For gasless flows, we can start polling immediately
|
|
453
|
+
if (fundMethod === "qr-code" || fundMethod === "exchange") {
|
|
454
|
+
logger.console.log(
|
|
455
|
+
"[trails-sdk] QR code mode: waiting for deposit transaction before starting polling",
|
|
456
|
+
)
|
|
457
|
+
// Use the same approach as cross-chain: check for deposit via indexer
|
|
458
|
+
const checkForDepositTx = async () => {
|
|
459
|
+
while (true) {
|
|
460
|
+
// Check if we should abort
|
|
461
|
+
if (abortSignal?.aborted) {
|
|
462
|
+
logger.console.log(
|
|
463
|
+
"[trails-sdk] Aborting deposit tx check due to abort signal",
|
|
464
|
+
)
|
|
465
|
+
return null
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
try {
|
|
469
|
+
if (!sequenceIndexerUrl) {
|
|
470
|
+
throw new Error(
|
|
471
|
+
"sequenceIndexerUrl is required for QR code mode",
|
|
472
|
+
)
|
|
473
|
+
}
|
|
474
|
+
if (!sequenceProjectAccessKey) {
|
|
475
|
+
throw new Error(
|
|
476
|
+
"sequenceProjectAccessKey is required for QR code mode",
|
|
477
|
+
)
|
|
478
|
+
}
|
|
479
|
+
const response = await getAccountTransactionHistory({
|
|
480
|
+
chainId: effectiveOriginChainId,
|
|
481
|
+
accountAddress: intent.originIntentAddress,
|
|
482
|
+
abortSignal,
|
|
483
|
+
apiKey: sequenceProjectAccessKey,
|
|
484
|
+
indexerUrl: sequenceIndexerUrl,
|
|
485
|
+
})
|
|
486
|
+
logger.console.log(
|
|
487
|
+
"[trails-sdk] getAccountTransactionHistory response",
|
|
488
|
+
response,
|
|
489
|
+
)
|
|
490
|
+
if (response.transactions.length > 0) {
|
|
491
|
+
const tx = response.transactions[0]
|
|
492
|
+
if (!tx?.txnHash) {
|
|
493
|
+
await new Promise((resolve) =>
|
|
494
|
+
setTimeout(
|
|
495
|
+
resolve,
|
|
496
|
+
POLLING_INTERVALS.TRANSACTION_HISTORY,
|
|
497
|
+
),
|
|
498
|
+
)
|
|
499
|
+
continue
|
|
500
|
+
}
|
|
501
|
+
const depositTxReceipt =
|
|
502
|
+
await effectivePublicClient.getTransactionReceipt({
|
|
503
|
+
hash: tx.txnHash as `0x${string}`,
|
|
504
|
+
})
|
|
505
|
+
|
|
506
|
+
depositUserTxnReceipt = depositTxReceipt
|
|
507
|
+
|
|
508
|
+
localTransactionStates[0] = getTransactionStateFromReceipt(
|
|
509
|
+
depositTxReceipt,
|
|
510
|
+
effectiveOriginChainId,
|
|
511
|
+
localTransactionStates[0]?.label,
|
|
512
|
+
)
|
|
513
|
+
onTransactionStateChange(localTransactionStates)
|
|
514
|
+
if (checkoutOnHandlers?.triggerCheckoutStatusUpdate) {
|
|
515
|
+
checkoutOnHandlers.triggerCheckoutStatusUpdate(
|
|
516
|
+
localTransactionStates,
|
|
517
|
+
)
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// Call executeIntent after detecting deposit transaction (for QR code mode)
|
|
521
|
+
// This triggers the backend to start executing the intent
|
|
522
|
+
// Must be called BEFORE waitIntentReceipt polling starts
|
|
523
|
+
if (
|
|
524
|
+
depositTxReceipt.status === "success" &&
|
|
525
|
+
intent.intentId
|
|
526
|
+
) {
|
|
527
|
+
logger.console.log(
|
|
528
|
+
"[trails-sdk] Calling executeIntent with detected deposit transaction hash (QR code mode)",
|
|
529
|
+
{
|
|
530
|
+
intentId: intent.intentId,
|
|
531
|
+
txHash: depositTxReceipt.transactionHash,
|
|
532
|
+
fundMethod,
|
|
533
|
+
},
|
|
534
|
+
)
|
|
535
|
+
try {
|
|
536
|
+
const executeIntentFnToUse =
|
|
537
|
+
executeIntentFn ||
|
|
538
|
+
trailsClient.executeIntent.bind(trailsClient)
|
|
539
|
+
await executeIntentFnToUse({
|
|
540
|
+
intentId: intent.intentId,
|
|
541
|
+
depositTransactionHash:
|
|
542
|
+
depositTxReceipt.transactionHash,
|
|
543
|
+
})
|
|
544
|
+
logger.console.log(
|
|
545
|
+
"[trails-sdk] executeIntent completed successfully (QR code mode)",
|
|
546
|
+
)
|
|
547
|
+
|
|
548
|
+
// Now start polling for intent receipt
|
|
549
|
+
break
|
|
550
|
+
} catch (error) {
|
|
551
|
+
logger.console.error(
|
|
552
|
+
"[trails-sdk] Error calling executeIntent (QR code mode):",
|
|
553
|
+
error,
|
|
554
|
+
)
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
if (onOriginSend) {
|
|
559
|
+
onOriginSend()
|
|
560
|
+
}
|
|
561
|
+
break
|
|
562
|
+
}
|
|
563
|
+
} catch (error) {
|
|
564
|
+
logger.console.error("Error checking for deposit tx", error)
|
|
565
|
+
}
|
|
566
|
+
await new Promise((resolve) =>
|
|
567
|
+
setTimeout(resolve, POLLING_INTERVALS.TRANSACTION_HISTORY),
|
|
568
|
+
)
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// Wait for deposit and executeIntent
|
|
573
|
+
await checkForDepositTx()
|
|
574
|
+
|
|
575
|
+
// Now start polling for intent receipt after executeIntent has been called
|
|
576
|
+
logger.console.log(
|
|
577
|
+
"[trails-sdk] Starting polling for intent receipt after executeIntent (QR code mode)",
|
|
578
|
+
)
|
|
579
|
+
try {
|
|
580
|
+
await pollIntentReceipt({
|
|
581
|
+
intentId: intent.intentId,
|
|
582
|
+
trailsClient,
|
|
583
|
+
callbacks: {
|
|
584
|
+
onOriginTransactionFound: async (originTxHash) => {
|
|
585
|
+
logger.console.log(
|
|
586
|
+
"[trails-sdk] Origin intent transaction discovered for same-chain QR code flow",
|
|
587
|
+
{ originTxHash },
|
|
588
|
+
)
|
|
589
|
+
|
|
590
|
+
if (localTransactionStates[1]) {
|
|
591
|
+
try {
|
|
592
|
+
const originTxReceipt =
|
|
593
|
+
await effectivePublicClient.getTransactionReceipt({
|
|
594
|
+
hash: originTxHash as `0x${string}`,
|
|
595
|
+
})
|
|
596
|
+
|
|
597
|
+
localTransactionStates[1] =
|
|
598
|
+
getTransactionStateFromReceipt(
|
|
599
|
+
originTxReceipt,
|
|
600
|
+
effectiveOriginChainId,
|
|
601
|
+
localTransactionStates[1]?.label,
|
|
602
|
+
)
|
|
603
|
+
onTransactionStateChange(localTransactionStates)
|
|
604
|
+
if (checkoutOnHandlers?.triggerCheckoutStatusUpdate) {
|
|
605
|
+
checkoutOnHandlers.triggerCheckoutStatusUpdate(
|
|
606
|
+
localTransactionStates,
|
|
607
|
+
)
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
originIntentTransaction = {
|
|
611
|
+
txnHash: originTxHash,
|
|
612
|
+
} as IntentTransaction
|
|
613
|
+
} catch (error) {
|
|
614
|
+
logger.console.error(
|
|
615
|
+
"[trails-sdk] Error fetching origin transaction receipt:",
|
|
616
|
+
error,
|
|
617
|
+
)
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
},
|
|
621
|
+
},
|
|
622
|
+
maxWaitTime: 120000, // 120 seconds max wait
|
|
623
|
+
})
|
|
624
|
+
} catch (error) {
|
|
625
|
+
logger.console.error(
|
|
626
|
+
"[trails-sdk] Error polling for intent receipt (QR code mode):",
|
|
627
|
+
error,
|
|
628
|
+
)
|
|
629
|
+
}
|
|
630
|
+
} else if (effectiveGasless && !depositUserTxnReceipt) {
|
|
631
|
+
// For gasless flows (non-QR code), start polling immediately
|
|
487
632
|
logger.console.log(
|
|
488
633
|
"[trails-sdk] Starting unified polling for gasless same-chain transaction with 2 states",
|
|
489
634
|
)
|
|
@@ -504,14 +649,6 @@ export async function handleSameChainSameToken({
|
|
|
504
649
|
await effectivePublicClient.getTransactionReceipt({
|
|
505
650
|
hash: txHash as `0x${string}`,
|
|
506
651
|
})
|
|
507
|
-
logger.console.log(
|
|
508
|
-
"[trails-sdk] Deposit transaction receipt fetched",
|
|
509
|
-
{
|
|
510
|
-
txHash,
|
|
511
|
-
blockNumber: depositTxReceipt?.blockNumber,
|
|
512
|
-
status: depositTxReceipt?.status,
|
|
513
|
-
},
|
|
514
|
-
)
|
|
515
652
|
|
|
516
653
|
localTransactionStates[0] =
|
|
517
654
|
getTransactionStateFromReceipt(
|
|
@@ -520,12 +657,13 @@ export async function handleSameChainSameToken({
|
|
|
520
657
|
localTransactionStates[0]?.label,
|
|
521
658
|
)
|
|
522
659
|
onTransactionStateChange(localTransactionStates)
|
|
523
|
-
// Also trigger checkout status update if handler is provided
|
|
524
660
|
if (checkoutOnHandlers?.triggerCheckoutStatusUpdate) {
|
|
525
661
|
checkoutOnHandlers.triggerCheckoutStatusUpdate(
|
|
526
662
|
localTransactionStates,
|
|
527
663
|
)
|
|
528
664
|
}
|
|
665
|
+
|
|
666
|
+
depositUserTxnReceipt = depositTxReceipt
|
|
529
667
|
} catch (error) {
|
|
530
668
|
logger.console.error(
|
|
531
669
|
"[trails-sdk] Error fetching deposit transaction receipt:",
|
|
@@ -540,21 +678,12 @@ export async function handleSameChainSameToken({
|
|
|
540
678
|
{ originTxHash },
|
|
541
679
|
)
|
|
542
680
|
|
|
543
|
-
// For same-chain gasless, localTransactionStates[1] is the origin intent transaction
|
|
544
681
|
if (localTransactionStates[1]) {
|
|
545
682
|
try {
|
|
546
683
|
const originTxReceipt =
|
|
547
684
|
await effectivePublicClient.getTransactionReceipt({
|
|
548
685
|
hash: originTxHash as `0x${string}`,
|
|
549
686
|
})
|
|
550
|
-
logger.console.log(
|
|
551
|
-
"[trails-sdk] Origin transaction receipt fetched",
|
|
552
|
-
{
|
|
553
|
-
originTxHash,
|
|
554
|
-
blockNumber: originTxReceipt?.blockNumber,
|
|
555
|
-
status: originTxReceipt?.status,
|
|
556
|
-
},
|
|
557
|
-
)
|
|
558
687
|
|
|
559
688
|
localTransactionStates[1] =
|
|
560
689
|
getTransactionStateFromReceipt(
|
|
@@ -563,12 +692,15 @@ export async function handleSameChainSameToken({
|
|
|
563
692
|
localTransactionStates[1]?.label,
|
|
564
693
|
)
|
|
565
694
|
onTransactionStateChange(localTransactionStates)
|
|
566
|
-
// Also trigger checkout status update if handler is provided
|
|
567
695
|
if (checkoutOnHandlers?.triggerCheckoutStatusUpdate) {
|
|
568
696
|
checkoutOnHandlers.triggerCheckoutStatusUpdate(
|
|
569
697
|
localTransactionStates,
|
|
570
698
|
)
|
|
571
699
|
}
|
|
700
|
+
|
|
701
|
+
originIntentTransaction = {
|
|
702
|
+
txnHash: originTxHash,
|
|
703
|
+
} as IntentTransaction
|
|
572
704
|
} catch (error) {
|
|
573
705
|
logger.console.error(
|
|
574
706
|
"[trails-sdk] Error fetching origin transaction receipt:",
|
|
@@ -588,7 +720,9 @@ export async function handleSameChainSameToken({
|
|
|
588
720
|
}
|
|
589
721
|
}
|
|
590
722
|
|
|
591
|
-
|
|
723
|
+
// For non-gasless flows, update the transaction state with the deposit receipt
|
|
724
|
+
// For gasless flows, skip this as localTransactionStates is already maintained by polling
|
|
725
|
+
if (depositUserTxnReceipt && !effectiveGasless) {
|
|
592
726
|
try {
|
|
593
727
|
const updatedStates = [
|
|
594
728
|
getTransactionStateFromReceipt(
|
|
@@ -718,8 +852,8 @@ export async function handleSameChainSameToken({
|
|
|
718
852
|
|
|
719
853
|
return {
|
|
720
854
|
depositUserTxnReceipt,
|
|
721
|
-
|
|
722
|
-
|
|
855
|
+
originIntentTransaction,
|
|
856
|
+
destinationIntentTransaction,
|
|
723
857
|
totalCompletionSeconds: 0,
|
|
724
858
|
}
|
|
725
859
|
} catch (error) {
|
|
@@ -2,10 +2,10 @@ import type { Intent } from "@0xsequence/trails-api"
|
|
|
2
2
|
import type { TransactionState } from "../../transactions.js"
|
|
3
3
|
import type { PrepareSendQuote, PrepareSendFees } from "../types.js"
|
|
4
4
|
import type { QuoteProviderInfo } from "../../widget/hooks/useQuote.js"
|
|
5
|
-
import {
|
|
5
|
+
import { formatUnits } from "viem"
|
|
6
6
|
import { mainnet } from "viem/chains"
|
|
7
7
|
import { getTokenInfo } from "../../tokens.js"
|
|
8
|
-
import { getChainInfo } from "../../chains.js"
|
|
8
|
+
import { getChainInfo, getPublicRpcClient } from "../../chains.js"
|
|
9
9
|
import { logger } from "../../logger.js"
|
|
10
10
|
import {
|
|
11
11
|
formatRawAmount,
|
|
@@ -186,10 +186,7 @@ export async function getNormalizedQuoteObject({
|
|
|
186
186
|
|
|
187
187
|
const hasCustomCalldata = getIsCustomCalldata(destinationCalldata)
|
|
188
188
|
|
|
189
|
-
const publicClient =
|
|
190
|
-
chain: originChain,
|
|
191
|
-
transport: http(),
|
|
192
|
-
})
|
|
189
|
+
const publicClient = getPublicRpcClient(originChain)
|
|
193
190
|
|
|
194
191
|
let gasCostUsd: number = 0
|
|
195
192
|
let gasCostUsdDisplay: string = "0"
|
|
@@ -291,6 +288,7 @@ export async function getNormalizedQuoteObject({
|
|
|
291
288
|
destinationDepositAddress: destinationDepositAddress || "",
|
|
292
289
|
destinationAddress: destinationAddress || "",
|
|
293
290
|
destinationCalldata: hasCustomCalldata ? destinationCalldata || "" : "",
|
|
291
|
+
intentId: intent?.intentId ?? null,
|
|
294
292
|
originAmount: originAmount || "0",
|
|
295
293
|
originAmountMin: originAmountMin || originAmount || "0",
|
|
296
294
|
originAmountMinUsdFormatted: originAmountMinUsdFormatted || "0",
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import type { QuoteIntentRequest } from "@0xsequence/trails-api"
|
|
2
|
+
import type { Connector } from "wagmi"
|
|
2
3
|
import { getIsCustomCalldata } from "../../contractUtils.js"
|
|
4
|
+
import {
|
|
5
|
+
isSequenceWallet,
|
|
6
|
+
isSequenceWalletById,
|
|
7
|
+
isSmartContractWallet,
|
|
8
|
+
} from "../../walletUtils.js"
|
|
3
9
|
import type { TradeType } from "../types.js"
|
|
10
|
+
import { logger } from "../../logger.js"
|
|
4
11
|
|
|
5
|
-
export function getIntentArgs(
|
|
12
|
+
export async function getIntentArgs(
|
|
6
13
|
mainSignerAddress: string,
|
|
7
14
|
originChainId: number,
|
|
8
15
|
originTokenAddress: string,
|
|
@@ -16,7 +23,9 @@ export function getIntentArgs(
|
|
|
16
23
|
slippageTolerance: string, // 0.03 = 3%
|
|
17
24
|
tradeType: TradeType,
|
|
18
25
|
provider?: string | null,
|
|
19
|
-
|
|
26
|
+
connector?: Connector | undefined,
|
|
27
|
+
walletId?: string | undefined,
|
|
28
|
+
): Promise<QuoteIntentRequest> {
|
|
20
29
|
const hasCustomCalldata = getIsCustomCalldata(destinationCalldata)
|
|
21
30
|
|
|
22
31
|
let effectiveProvider = provider
|
|
@@ -24,6 +33,28 @@ export function getIntentArgs(
|
|
|
24
33
|
effectiveProvider = undefined
|
|
25
34
|
}
|
|
26
35
|
|
|
36
|
+
// Check if wallet is Sequence wallet (via connector or walletId)
|
|
37
|
+
const isSequence = connector
|
|
38
|
+
? isSequenceWallet(connector)
|
|
39
|
+
: isSequenceWalletById(walletId)
|
|
40
|
+
|
|
41
|
+
// Check if wallet is smart contract wallet
|
|
42
|
+
const isSmartContract = await isSmartContractWallet(
|
|
43
|
+
mainSignerAddress,
|
|
44
|
+
originChainId,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
// Set onlyNativeGasFee to true if wallet is Sequence or smart contract
|
|
48
|
+
const onlyNativeGasFee = isSequence || isSmartContract
|
|
49
|
+
|
|
50
|
+
logger.console.log("[trails-sdk] Wallet check for onlyNativeGasFee:", {
|
|
51
|
+
isSequence,
|
|
52
|
+
isSmartContract,
|
|
53
|
+
onlyNativeGasFee,
|
|
54
|
+
walletId,
|
|
55
|
+
connectorName: connector?.name,
|
|
56
|
+
})
|
|
57
|
+
|
|
27
58
|
const intentArgs: QuoteIntentRequest = {
|
|
28
59
|
ownerAddress: mainSignerAddress,
|
|
29
60
|
originChainId,
|
|
@@ -34,7 +65,8 @@ export function getIntentArgs(
|
|
|
34
65
|
destinationTokenAddress: destinationTokenAddress,
|
|
35
66
|
destinationTokenAmount: BigInt(destinationTokenAmount),
|
|
36
67
|
destinationCallData: hasCustomCalldata ? destinationCalldata : "0x",
|
|
37
|
-
destinationCallValue: "0",
|
|
68
|
+
destinationCallValue: BigInt("0"),
|
|
69
|
+
onlyNativeGasFee,
|
|
38
70
|
options: {
|
|
39
71
|
slippageTolerance: Number(slippageTolerance),
|
|
40
72
|
quoteProvider: effectiveProvider || undefined,
|
|
@@ -15,28 +15,6 @@ import type { QuoteProviderInfo } from "../widget/hooks/useQuote.js"
|
|
|
15
15
|
import type { TrailsFeeBreakdown } from "../fees.js"
|
|
16
16
|
import type { IntentTransaction } from "@0xsequence/trails-api"
|
|
17
17
|
|
|
18
|
-
// Use native IntentTransaction from trails-api instead of deprecated MetaTxnReceipt
|
|
19
|
-
export type MetaTxnReceipt = IntentTransaction
|
|
20
|
-
|
|
21
|
-
// Flexible fee token type that accepts both full FeeOption and minimal fee token objects
|
|
22
|
-
// Also accepts objects with amountUSD for widget components
|
|
23
|
-
export type SelectedFeeToken =
|
|
24
|
-
| FeeOption
|
|
25
|
-
| {
|
|
26
|
-
tokenAddress: string
|
|
27
|
-
tokenSymbol?: string
|
|
28
|
-
}
|
|
29
|
-
| {
|
|
30
|
-
tokenAddress: string
|
|
31
|
-
tokenSymbol: string
|
|
32
|
-
tokenDecimals: number
|
|
33
|
-
amount: string
|
|
34
|
-
amountUSD: number
|
|
35
|
-
notEnoughBalance?: boolean
|
|
36
|
-
tokenImageUrl?: string
|
|
37
|
-
chainId?: number
|
|
38
|
-
}
|
|
39
|
-
|
|
40
18
|
export enum TradeType {
|
|
41
19
|
EXACT_INPUT = "EXACT_INPUT",
|
|
42
20
|
EXACT_OUTPUT = "EXACT_OUTPUT",
|
|
@@ -75,7 +53,7 @@ export type PrepareSendOptions = {
|
|
|
75
53
|
mode?: "pay" | "fund" | "earn" | "swap" | "receive"
|
|
76
54
|
checkoutOnHandlers?: Partial<CheckoutOnHandlers>
|
|
77
55
|
refundAddress?: string
|
|
78
|
-
|
|
56
|
+
selectedFeeOption?: FeeOption | null
|
|
79
57
|
walletId?: string
|
|
80
58
|
abortSignal?: AbortSignal
|
|
81
59
|
// Optional mutation callbacks for React Query integration
|
|
@@ -99,6 +77,7 @@ export type PrepareSendQuote = {
|
|
|
99
77
|
destinationDepositAddress: string
|
|
100
78
|
destinationAddress: string
|
|
101
79
|
destinationCalldata: string
|
|
80
|
+
intentId?: string | null
|
|
102
81
|
originChain: Chain
|
|
103
82
|
destinationChain: Chain
|
|
104
83
|
originAmount: string
|
|
@@ -143,16 +122,16 @@ export type PrepareSendReturn = {
|
|
|
143
122
|
feeOptions?: GasFeeOptions
|
|
144
123
|
send: ({
|
|
145
124
|
onOriginSend,
|
|
146
|
-
|
|
125
|
+
selectedFeeOption,
|
|
147
126
|
}: {
|
|
148
127
|
onOriginSend?: () => void
|
|
149
|
-
|
|
128
|
+
selectedFeeOption?: FeeOption | null
|
|
150
129
|
}) => Promise<SendReturn>
|
|
151
130
|
}
|
|
152
131
|
|
|
153
132
|
export type SendReturn = {
|
|
154
133
|
depositUserTxnReceipt: TransactionReceipt | null
|
|
155
|
-
|
|
156
|
-
|
|
134
|
+
originIntentTransaction: IntentTransaction | null
|
|
135
|
+
destinationIntentTransaction: IntentTransaction | null
|
|
157
136
|
totalCompletionSeconds?: number
|
|
158
137
|
}
|