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.
Files changed (189) hide show
  1. package/dist/analytics.d.ts +8 -3
  2. package/dist/analytics.d.ts.map +1 -1
  3. package/dist/{ccip-DhEkQ6QC.js → ccip-Dw5AN7oU.js} +1 -1
  4. package/dist/cctp.d.ts +0 -149
  5. package/dist/cctp.d.ts.map +1 -1
  6. package/dist/chains.d.ts +28 -3
  7. package/dist/chains.d.ts.map +1 -1
  8. package/dist/config.d.ts +11 -0
  9. package/dist/config.d.ts.map +1 -1
  10. package/dist/constants.d.ts +1 -1
  11. package/dist/constants.d.ts.map +1 -1
  12. package/dist/contractUtils.d.ts.map +1 -1
  13. package/dist/estimate.d.ts.map +1 -1
  14. package/dist/fees.d.ts.map +1 -1
  15. package/dist/gasless.d.ts +12 -0
  16. package/dist/gasless.d.ts.map +1 -1
  17. package/dist/{index-MhD2DA7_.js → index-BtVUTbEZ.js} +30984 -38945
  18. package/dist/index.d.ts +7 -5
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +108 -107
  21. package/dist/indexerClient.d.ts +2 -2
  22. package/dist/intents.d.ts +0 -17
  23. package/dist/intents.d.ts.map +1 -1
  24. package/dist/mutations.d.ts.map +1 -1
  25. package/dist/paymasterSend.d.ts.map +1 -1
  26. package/dist/prepareSend.d.ts +1 -1
  27. package/dist/prepareSend.d.ts.map +1 -1
  28. package/dist/sendUserOp.d.ts +0 -18
  29. package/dist/sendUserOp.d.ts.map +1 -1
  30. package/dist/tokenBalances.d.ts.map +1 -1
  31. package/dist/tokens.d.ts +10 -8
  32. package/dist/tokens.d.ts.map +1 -1
  33. package/dist/transactionIntent/deposits/depositOrchestrator.d.ts +4 -5
  34. package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -1
  35. package/dist/transactionIntent/deposits/gaslessDeposit.d.ts +4 -5
  36. package/dist/transactionIntent/deposits/gaslessDeposit.d.ts.map +1 -1
  37. package/dist/transactionIntent/deposits/standardDeposit.d.ts +2 -2
  38. package/dist/transactionIntent/deposits/standardDeposit.d.ts.map +1 -1
  39. package/dist/transactionIntent/execution/transactionState.d.ts +2 -2
  40. package/dist/transactionIntent/execution/transactionState.d.ts.map +1 -1
  41. package/dist/transactionIntent/handlers/crossChain.d.ts +4 -4
  42. package/dist/transactionIntent/handlers/crossChain.d.ts.map +1 -1
  43. package/dist/transactionIntent/handlers/index.d.ts +0 -1
  44. package/dist/transactionIntent/handlers/index.d.ts.map +1 -1
  45. package/dist/transactionIntent/handlers/sameChainSameToken.d.ts +4 -34
  46. package/dist/transactionIntent/handlers/sameChainSameToken.d.ts.map +1 -1
  47. package/dist/transactionIntent/quote/normalizeQuote.d.ts.map +1 -1
  48. package/dist/transactionIntent/quote/quoteHelpers.d.ts +2 -1
  49. package/dist/transactionIntent/quote/quoteHelpers.d.ts.map +1 -1
  50. package/dist/transactionIntent/types.d.ts +6 -19
  51. package/dist/transactionIntent/types.d.ts.map +1 -1
  52. package/dist/transactionIntent/utils/index.d.ts +0 -1
  53. package/dist/transactionIntent/utils/index.d.ts.map +1 -1
  54. package/dist/transactions.d.ts +2 -20
  55. package/dist/transactions.d.ts.map +1 -1
  56. package/dist/utils.d.ts +8 -2
  57. package/dist/utils.d.ts.map +1 -1
  58. package/dist/walletUtils.d.ts +21 -0
  59. package/dist/walletUtils.d.ts.map +1 -0
  60. package/dist/wallets.d.ts +33 -240
  61. package/dist/wallets.d.ts.map +1 -1
  62. package/dist/widget/components/AccountIntentTransactionHistory.d.ts.map +1 -1
  63. package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
  64. package/dist/widget/components/FeeOption.d.ts +8 -13
  65. package/dist/widget/components/FeeOption.d.ts.map +1 -1
  66. package/dist/widget/components/FeeOptions.d.ts +11 -5
  67. package/dist/widget/components/FeeOptions.d.ts.map +1 -1
  68. package/dist/widget/components/NativeGasOption.d.ts.map +1 -1
  69. package/dist/widget/components/Pay.d.ts.map +1 -1
  70. package/dist/widget/components/PoolDeposit.d.ts.map +1 -1
  71. package/dist/widget/components/QRCodeDeposit.d.ts +5 -0
  72. package/dist/widget/components/QRCodeDeposit.d.ts.map +1 -1
  73. package/dist/widget/components/QRCodeWalletSelect.d.ts +13 -0
  74. package/dist/widget/components/QRCodeWalletSelect.d.ts.map +1 -0
  75. package/dist/widget/components/QrCode.d.ts.map +1 -1
  76. package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
  77. package/dist/widget/components/Receipt.d.ts.map +1 -1
  78. package/dist/widget/components/ScreenHeader.d.ts +1 -1
  79. package/dist/widget/components/ScreenHeader.d.ts.map +1 -1
  80. package/dist/widget/components/Toast.d.ts.map +1 -1
  81. package/dist/widget/components/TokenImage.d.ts.map +1 -1
  82. package/dist/widget/css/compiled.css +1 -1
  83. package/dist/widget/hooks/useCheckout.d.ts +15 -1
  84. package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
  85. package/dist/widget/hooks/useCurrentScreen.d.ts +1 -1
  86. package/dist/widget/hooks/useCurrentScreen.d.ts.map +1 -1
  87. package/dist/widget/hooks/useDebugScreens.d.ts +1 -1
  88. package/dist/widget/hooks/useDebugScreens.d.ts.map +1 -1
  89. package/dist/widget/hooks/useIntentTransactionHistory.d.ts.map +1 -1
  90. package/dist/widget/hooks/useIsConnectedWalletSmartContract.d.ts +7 -0
  91. package/dist/widget/hooks/useIsConnectedWalletSmartContract.d.ts.map +1 -0
  92. package/dist/widget/hooks/useIsSequenceWallet.d.ts +6 -0
  93. package/dist/widget/hooks/useIsSequenceWallet.d.ts.map +1 -0
  94. package/dist/widget/hooks/useQuote.d.ts +5 -8
  95. package/dist/widget/hooks/useQuote.d.ts.map +1 -1
  96. package/dist/widget/hooks/useRecentTokens.d.ts.map +1 -1
  97. package/dist/widget/hooks/useSelectedFeeOption.d.ts +30 -0
  98. package/dist/widget/hooks/useSelectedFeeOption.d.ts.map +1 -0
  99. package/dist/widget/hooks/useSendForm.d.ts +6 -15
  100. package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
  101. package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
  102. package/dist/widget/index.js +1 -1
  103. package/dist/widget/providers/TrailsProvider.d.ts +23 -12
  104. package/dist/widget/providers/TrailsProvider.d.ts.map +1 -1
  105. package/dist/widget/widget.d.ts +11 -0
  106. package/dist/widget/widget.d.ts.map +1 -1
  107. package/package.json +8 -8
  108. package/src/analytics.ts +53 -21
  109. package/src/cctp.ts +0 -1016
  110. package/src/chains.ts +93 -39
  111. package/src/config.ts +24 -6
  112. package/src/constants.ts +1 -4
  113. package/src/contractUtils.ts +6 -6
  114. package/src/estimate.ts +3 -6
  115. package/src/fees.ts +5 -10
  116. package/src/gasless.ts +45 -0
  117. package/src/index.ts +7 -6
  118. package/src/indexerClient.ts +2 -2
  119. package/src/intents.ts +52 -206
  120. package/src/mutations.ts +3 -2
  121. package/src/paymasterSend.ts +2 -5
  122. package/src/prepareSend.ts +9 -12
  123. package/src/sendUserOp.ts +3 -64
  124. package/src/tokenBalances.ts +2 -1
  125. package/src/tokens.ts +62 -133
  126. package/src/trailsClient.ts +1 -1
  127. package/src/transactionIntent/deposits/depositOrchestrator.ts +14 -15
  128. package/src/transactionIntent/deposits/gaslessDeposit.ts +70 -100
  129. package/src/transactionIntent/deposits/standardDeposit.ts +22 -28
  130. package/src/transactionIntent/execution/transactionState.ts +2 -2
  131. package/src/transactionIntent/handlers/crossChain.ts +165 -385
  132. package/src/transactionIntent/handlers/index.ts +0 -1
  133. package/src/transactionIntent/handlers/sameChainSameToken.ts +228 -94
  134. package/src/transactionIntent/quote/normalizeQuote.ts +4 -6
  135. package/src/transactionIntent/quote/quoteHelpers.ts +35 -3
  136. package/src/transactionIntent/types.ts +6 -27
  137. package/src/transactionIntent/utils/index.ts +0 -1
  138. package/src/transactions.ts +6 -203
  139. package/src/umd.tsx +1 -3
  140. package/src/utils.ts +28 -8
  141. package/src/walletUtils.ts +42 -0
  142. package/src/wallets.ts +361 -203
  143. package/src/widget/compiled.css +1 -1
  144. package/src/widget/components/AccountIntentTransactionHistory.tsx +73 -4
  145. package/src/widget/components/AccountSettings.tsx +17 -17
  146. package/src/widget/components/ChainList.tsx +3 -3
  147. package/src/widget/components/ClassicSwap.tsx +19 -10
  148. package/src/widget/components/ConfigDisplay.tsx +1 -1
  149. package/src/widget/components/FeeOption.tsx +63 -20
  150. package/src/widget/components/FeeOptions.tsx +54 -123
  151. package/src/widget/components/NativeGasOption.tsx +3 -1
  152. package/src/widget/components/Pay.tsx +18 -11
  153. package/src/widget/components/PoolDeposit.tsx +23 -10
  154. package/src/widget/components/QRCodeDeposit.tsx +50 -30
  155. package/src/widget/components/QRCodeWalletSelect.tsx +77 -0
  156. package/src/widget/components/QrCode.tsx +188 -233
  157. package/src/widget/components/QuoteDetails.tsx +48 -2
  158. package/src/widget/components/Receipt.tsx +5 -2
  159. package/src/widget/components/ScreenHeader.tsx +10 -8
  160. package/src/widget/components/Toast.tsx +10 -0
  161. package/src/widget/components/TokenImage.tsx +56 -13
  162. package/src/widget/hooks/useCheckout.ts +71 -0
  163. package/src/widget/hooks/useCurrentScreen.tsx +1 -0
  164. package/src/widget/hooks/useDebugScreens.ts +5 -0
  165. package/src/widget/hooks/useIntentTransactionHistory.ts +788 -418
  166. package/src/widget/hooks/useIsConnectedWalletSmartContract.ts +43 -0
  167. package/src/widget/hooks/useIsSequenceWallet.ts +17 -0
  168. package/src/widget/hooks/useQuote.ts +16 -17
  169. package/src/widget/hooks/useRecentTokens.ts +2 -1
  170. package/src/widget/hooks/useSelectedFeeOption.tsx +257 -0
  171. package/src/widget/hooks/useSendForm.ts +172 -47
  172. package/src/widget/hooks/useTokenList.ts +15 -2
  173. package/src/widget/providers/TrailsProvider.tsx +53 -25
  174. package/src/widget/widget.tsx +119 -48
  175. package/dist/cctpqueue.d.ts +0 -18
  176. package/dist/cctpqueue.d.ts.map +0 -1
  177. package/dist/preconditions.d.ts +0 -12
  178. package/dist/preconditions.d.ts.map +0 -1
  179. package/dist/transactionIntent/handlers/sameChainDifferentToken.d.ts +0 -62
  180. package/dist/transactionIntent/handlers/sameChainDifferentToken.d.ts.map +0 -1
  181. package/dist/transactionIntent/utils/lifiHelpers.d.ts +0 -10
  182. package/dist/transactionIntent/utils/lifiHelpers.d.ts.map +0 -1
  183. package/dist/widget/hooks/useSelectedFeeToken.d.ts +0 -33
  184. package/dist/widget/hooks/useSelectedFeeToken.d.ts.map +0 -1
  185. package/src/cctpqueue.ts +0 -69
  186. package/src/preconditions.ts +0 -47
  187. package/src/transactionIntent/handlers/sameChainDifferentToken.ts +0 -323
  188. package/src/transactionIntent/utils/lifiHelpers.ts +0 -68
  189. package/src/widget/hooks/useSelectedFeeToken.tsx +0 -288
@@ -5,11 +5,11 @@ import type {
5
5
  WalletClient,
6
6
  TransactionReceipt,
7
7
  } from "viem"
8
- import { createPublicClient, createWalletClient, http } from "viem"
9
- import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"
10
- import type { TrailsApi } from "@0xsequence/trails-api"
11
- import type { Attestation } from "../../cctp.js"
12
- import type { MetaTxnReceipt, PrepareSendReturn, SendReturn } from "../types.js"
8
+ import { JsonEncode } from "@0xsequence/trails-api"
9
+ import { getPublicRpcClient } from "../../chains.js"
10
+ import type { FeeOption, TrailsApi } from "@0xsequence/trails-api"
11
+ import type { IntentTransaction } from "@0xsequence/trails-api"
12
+ import type { PrepareSendReturn, SendReturn } from "../types.js"
13
13
  import type { TransactionState } from "../../transactions.js"
14
14
  import type { CheckoutOnHandlers } from "../../widget/hooks/useCheckout.js"
15
15
  import type {
@@ -18,42 +18,26 @@ import type {
18
18
  DepositSignature,
19
19
  ExecuteIntentResponse,
20
20
  } from "@0xsequence/trails-api"
21
- import { TradeType, type SelectedFeeToken } from "../types.js"
21
+ import { TradeType } from "../types.js"
22
22
  import { logger } from "../../logger.js"
23
23
  import {
24
24
  isTestnetDebugMode,
25
25
  getTestnetOriginTokenAddress,
26
26
  } from "../utils/testnetHelpers.js"
27
- import { shouldUseCctp, validateCctpDestinationToken } from "../validators.js"
28
- import { getQueryParam } from "../../queryParams.js"
29
- import { getIsCustomCalldata } from "../../contractUtils.js"
30
27
  import { getNormalizedQuoteObject } from "../quote/normalizeQuote.js"
31
- import {
32
- cctpTransfer,
33
- cctpTransferWithCustomCall,
34
- getCCTPRelayerCallData,
35
- getMintUSDCData,
36
- getMessageTransmitter,
37
- } from "../../cctp.js"
38
28
  import { getChainInfo, getTestnetChainInfo } from "../../chains.js"
39
29
  import { getTransactionStateFromReceipt } from "../execution/transactionState.js"
40
- import {
41
- simpleCreateSequenceWallet,
42
- sequenceSendTransaction,
43
- } from "../../sequenceWallet.js"
44
30
  import { getIntentArgs } from "../quote/quoteHelpers.js"
45
31
  import {
46
32
  quoteIntent,
47
33
  commitIntent,
48
34
  buildCrossChainDepositParams,
49
35
  } from "../../intents.js"
50
- import { findFirstPreconditionForChainId } from "../../preconditions.js"
51
36
  import {
52
37
  decodeTrailsTokenSweeperEvents,
53
38
  decodeGuestModuleEvents,
54
39
  } from "../../decoders.js"
55
40
  import { updatePersistentToast } from "../../toast.js"
56
- import { queueCCTPTransfer } from "../../cctpqueue.js"
57
41
  import { formatRawAmount } from "../../tokenBalances.js"
58
42
  import { calcAmountUsdPrice } from "../../prices.js"
59
43
  import { checkAccountBalance } from "../utils/balanceChecker.js"
@@ -63,16 +47,15 @@ import {
63
47
  getPriceImpactFromIntent,
64
48
  getPriceImpactUsdFromIntent,
65
49
  } from "../quote/feeExtractors.js"
66
- import { getNeedsLifiNativeFee } from "../utils/lifiHelpers.js"
67
50
  import { attemptUserDepositTx } from "../deposits/depositOrchestrator.js"
68
51
  import {
69
52
  getAccountTransactionHistory,
70
53
  getTxTimeDiff,
71
54
  } from "../../transactions.js"
72
55
  import { trackPaymentCompleted, trackPaymentError } from "../../analytics.js"
73
- import { POLLING_INTERVALS } from "../constants.js"
74
56
  import { pollIntentReceipt } from "../../intentReceiptPoller.js"
75
57
  import type { IntentReceipt } from "@0xsequence/trails-api"
58
+ import { POLLING_INTERVALS } from "../constants.js"
76
59
 
77
60
  /**
78
61
  * @description
@@ -140,7 +123,7 @@ export async function handleCrossChain({
140
123
  fundMethod,
141
124
  mode,
142
125
  checkoutOnHandlers,
143
- selectedFeeToken,
126
+ selectedFeeOption,
144
127
  walletId,
145
128
  abortSignal,
146
129
  commitIntentFn,
@@ -180,7 +163,7 @@ export async function handleCrossChain({
180
163
  fundMethod?: string
181
164
  mode?: "pay" | "fund" | "earn" | "swap" | "receive"
182
165
  checkoutOnHandlers?: Partial<CheckoutOnHandlers>
183
- selectedFeeToken?: SelectedFeeToken
166
+ selectedFeeOption?: FeeOption | null
184
167
  walletId?: string
185
168
  abortSignal?: AbortSignal
186
169
  commitIntentFn?: (intent: Intent) => Promise<CommitIntentResponse>
@@ -192,251 +175,9 @@ export async function handleCrossChain({
192
175
  sequenceProjectAccessKey?: string
193
176
  sequenceIndexerUrl?: string
194
177
  }): Promise<PrepareSendReturn> {
195
- const testnet = isTestnetDebugMode()
196
- const useCctp = shouldUseCctp(
197
- originTokenAddress,
198
- destinationTokenAddress,
199
- originChainId,
200
- destinationChainId,
201
- )
202
-
203
- const cctpFlag = getQueryParam("cctp") === "true"
204
- const hasCustomCalldata = getIsCustomCalldata(destinationCalldata)
205
-
206
- // Validate CCTP destination token requirement for explicit CCTP usage
207
- if (useCctp && cctpFlag) {
208
- validateCctpDestinationToken(
209
- destinationTokenAddress,
210
- destinationChainId,
211
- "cctp",
212
- )
213
- logger.console.log("[trails-sdk] using cctp")
214
-
215
- const quote = await getNormalizedQuoteObject({
216
- destinationAddress: recipient,
217
- destinationCalldata,
218
- originAmount: swapAmount,
219
- originTokenPriceUsd: sourceTokenPriceUsd?.toString() || null,
220
- destinationAmount: swapAmount,
221
- destinationTokenPriceUsd: destinationTokenPriceUsd?.toString() || null,
222
- originTokenAddress: originTokenAddress,
223
- destinationTokenAddress: destinationTokenAddress,
224
- originChainId,
225
- destinationChainId,
226
- transactionStates,
227
- originNativeTokenPriceUsd,
228
- slippageTolerance,
229
- quoteProvider: "cctp",
230
- })
231
-
232
- // Call onCheckoutQuote callback if provided
233
- if (checkoutOnHandlers?.triggerCheckoutQuote) {
234
- checkoutOnHandlers.triggerCheckoutQuote(quote)
235
- }
236
-
237
- return {
238
- quote,
239
- send: async ({
240
- onOriginSend,
241
- selectedFeeToken: runtimeSelectedFeeToken,
242
- }: {
243
- onOriginSend?: () => void
244
- selectedFeeToken?: SelectedFeeToken
245
- }): Promise<SendReturn> => {
246
- // Use runtime selectedFeeToken if provided, otherwise fall back to the one from prepareSend
247
- const effectiveSelectedFeeToken =
248
- runtimeSelectedFeeToken ?? selectedFeeToken
249
- logger.console.log(
250
- "[trails-sdk] [FEE-SELECT] [GASLESS-FLOW] send() called (LEGACY PATH):",
251
- {
252
- runtimeSelectedFeeToken,
253
- prepareTimeSelectedFeeToken: selectedFeeToken,
254
- effectiveSelectedFeeToken,
255
- },
256
- )
257
- const originChain = testnet ? getTestnetChainInfo(chain)! : chain
258
- const destinationChain = testnet
259
- ? getTestnetChainInfo(destinationChainId)!
260
- : getChainInfo(destinationChainId)
261
-
262
- if (!originChain || !destinationChain) {
263
- logger.console.error("[trails-sdk] Invalid chain", {
264
- originChain,
265
- destinationChain,
266
- originChainId,
267
- destinationChainId,
268
- chain,
269
- testnet,
270
- })
271
- throw new Error("Invalid chain")
272
- }
273
-
274
- logger.console.log("[trails-sdk] originChain", originChain)
275
- logger.console.log("[trails-sdk] destinationChain", destinationChain)
276
-
277
- const originPublicClient = createPublicClient({
278
- chain: originChain,
279
- transport: http(),
280
- })
281
-
282
- let txHash: `0x${string}`
283
- let waitForAttestation: () => Promise<Attestation>
284
-
285
- if (hasCustomCalldata) {
286
- const result = await cctpTransferWithCustomCall({
287
- walletClient,
288
- originChain,
289
- destinationChain,
290
- amount: BigInt(swapAmount),
291
- })
292
-
293
- txHash = result.txHash
294
- waitForAttestation = result.waitForAttestation
295
- } else {
296
- const result = await cctpTransfer({
297
- walletClient,
298
- originChain,
299
- destinationChain,
300
- amount: BigInt(swapAmount),
301
- })
302
-
303
- txHash = result.txHash
304
- waitForAttestation = result.waitForAttestation
305
- }
306
-
307
- if (onOriginSend) {
308
- onOriginSend()
309
- }
310
-
311
- logger.console.log("[trails-sdk] waiting for tx", txHash)
312
-
313
- const receipt = await originPublicClient.waitForTransactionReceipt({
314
- hash: txHash,
315
- })
316
-
317
- logger.console.log("[trails-sdk] tx receipt", receipt)
318
-
319
- transactionStates[0] = getTransactionStateFromReceipt(
320
- receipt,
321
- originChain.id,
322
- transactionStates[0]?.label,
323
- )
324
- transactionStates[1] = getTransactionStateFromReceipt(
325
- receipt,
326
- originChain.id,
327
- transactionStates[1]?.label,
328
- )
329
-
330
- onTransactionStateChange(transactionStates)
331
- // Also trigger checkout status update if handler is provided
332
- if (checkoutOnHandlers?.triggerCheckoutStatusUpdate) {
333
- checkoutOnHandlers.triggerCheckoutStatusUpdate(transactionStates)
334
- }
335
-
336
- const attestation = await waitForAttestation()
337
-
338
- if (!attestation) {
339
- throw new Error("Failed to retrieve attestation")
340
- }
341
-
342
- const tokenMessenger = getMessageTransmitter(destinationChain.id)!
343
-
344
- logger.console.log("[trails-sdk] tokenMessenger", tokenMessenger)
345
- const calls: {
346
- to: `0x${string}`
347
- data: `0x${string}`
348
- value: bigint
349
- }[] = []
350
-
351
- if (hasCustomCalldata) {
352
- calls.push(
353
- await getCCTPRelayerCallData({
354
- attestation,
355
- targetContract: recipient,
356
- calldata: destinationCalldata as `0x${string}`,
357
- gasLimit: 300000n,
358
- destinationChain,
359
- }),
360
- )
361
- } else {
362
- calls.push(
363
- await getMintUSDCData({
364
- tokenMessenger,
365
- attestation,
366
- }),
367
- )
368
- }
369
-
370
- logger.console.log("[trails-sdk] calls", calls)
371
- const delegatorPrivateKey = generatePrivateKey()
372
- const delegatorAccount = privateKeyToAccount(delegatorPrivateKey)
373
- const delegatorClient = createWalletClient({
374
- account: delegatorAccount,
375
- chain: destinationChain,
376
- transport: http(),
377
- })
378
- const destinationPublicClient = createPublicClient({
379
- chain: destinationChain,
380
- transport: http(),
381
- })
382
- logger.console.log("[trails-sdk] delegatorClient", delegatorClient)
383
-
384
- const sequenceWalletAddress = await simpleCreateSequenceWallet(
385
- delegatorAccount as any,
386
- )
387
- logger.console.log(
388
- "[trails-sdk] sequenceWalletAddress",
389
- sequenceWalletAddress,
390
- )
391
- if (!sequenceProjectAccessKey) {
392
- throw new Error("Trails api key is required")
393
- }
394
- const sequenceTxHash = await sequenceSendTransaction(
395
- sequenceWalletAddress,
396
- delegatorClient,
397
- destinationPublicClient,
398
- calls,
399
- destinationChain,
400
- sequenceProjectAccessKey,
401
- )
402
-
403
- const destinationReceipt =
404
- await destinationPublicClient.waitForTransactionReceipt({
405
- hash: sequenceTxHash as `0x${string}`,
406
- })
407
-
408
- logger.console.log(
409
- "[trails-sdk] destinationReceipt",
410
- destinationReceipt,
411
- )
412
-
413
- if (transactionStates[2]) {
414
- transactionStates[2] = getTransactionStateFromReceipt(
415
- destinationReceipt,
416
- destinationChain.id,
417
- transactionStates[2]?.label,
418
- )
419
- }
420
-
421
- onTransactionStateChange(transactionStates)
422
- // Also trigger checkout status update if handler is provided
423
- if (checkoutOnHandlers?.triggerCheckoutStatusUpdate) {
424
- checkoutOnHandlers.triggerCheckoutStatusUpdate(transactionStates)
425
- }
426
-
427
- return {
428
- depositUserTxnReceipt: receipt,
429
- originMetaTxnReceipt: null,
430
- destinationMetaTxnReceipt: null,
431
- totalCompletionSeconds: 0,
432
- }
433
- },
434
- }
435
- }
178
+ const salt = Date.now().toString()
436
179
 
437
- const destinationSalt = Date.now().toString()
438
-
439
- const intentArgs = getIntentArgs(
180
+ const intentArgs = await getIntentArgs(
440
181
  mainSignerAddress,
441
182
  originChainId,
442
183
  originTokenAddress,
@@ -446,13 +187,18 @@ export async function handleCrossChain({
446
187
  tradeType === TradeType.EXACT_OUTPUT ? swapAmount : "0", // destinationTokenAmount
447
188
  recipient,
448
189
  destinationCalldata,
449
- destinationSalt,
190
+ salt,
450
191
  slippageTolerance,
451
192
  tradeType,
452
193
  quoteProvider,
194
+ undefined, // connector - not available in this context
195
+ walletId, // walletId - use this to check for Sequence wallets
453
196
  )
454
197
 
455
- logger.console.log("[trails-sdk] Creating intent with args:", intentArgs)
198
+ logger.console.log(
199
+ "[trails-sdk] Creating intent for cross-chain with args:",
200
+ intentArgs,
201
+ )
456
202
 
457
203
  const { intent, gasFeeOptions } = await quoteIntent(
458
204
  trailsClient,
@@ -466,7 +212,7 @@ export async function handleCrossChain({
466
212
  logger.console.log("[trails-sdk] Quote intent:", intent)
467
213
  logger.console.log("[trails-sdk] Quote intent gasFeeOptions:", gasFeeOptions)
468
214
 
469
- if (!intent.preconditions?.length || !intent.calls?.length) {
215
+ if (!intent.originPrecondition || !intent.originCalls) {
470
216
  throw new Error("Invalid intent")
471
217
  }
472
218
 
@@ -476,17 +222,8 @@ export async function handleCrossChain({
476
222
  originIntentAddress.toString(),
477
223
  )
478
224
 
479
- const firstPrecondition = findFirstPreconditionForChainId(
480
- intent.preconditions,
481
- originChainId,
482
- )
483
-
484
- if (!firstPrecondition) {
485
- throw new Error("No precondition found for origin chain")
486
- }
487
-
488
- const firstPreconditionMin = firstPrecondition?.minAmount?.toString()
489
- const depositAmount = firstPreconditionMin
225
+ // Use depositTransaction amount - this is the actual amount to deposit
226
+ const depositAmount = intent.depositTransaction.amount?.toString()
490
227
 
491
228
  const quoteToAmount = intent.quote.toAmount
492
229
  const quoteToAmountMin = intent.quote.toAmountMin
@@ -551,7 +288,7 @@ export async function handleCrossChain({
551
288
  const originCallParamsForEstimate = buildCrossChainDepositParams({
552
289
  originTokenAddress,
553
290
  originIntentAddress,
554
- depositAmount: firstPreconditionMin,
291
+ depositAmount,
555
292
  fee,
556
293
  originChainId,
557
294
  chain,
@@ -622,8 +359,8 @@ export async function handleCrossChain({
622
359
  // Gasless fee options are now returned in QuoteIntentResponse.gasFeeOptions
623
360
  // and properly propagated from getIntent()
624
361
  const effectiveGasless =
625
- selectedFeeToken !== null &&
626
- selectedFeeToken !== undefined &&
362
+ selectedFeeOption !== null &&
363
+ selectedFeeOption !== undefined &&
627
364
  walletId !== "sequence-waas"
628
365
  if (effectiveGasless) {
629
366
  logger.console.log(
@@ -645,21 +382,19 @@ export async function handleCrossChain({
645
382
  feeOptions: gasFeeOptions,
646
383
  send: async ({
647
384
  onOriginSend,
648
- selectedFeeToken: runtimeSelectedFeeToken,
385
+ selectedFeeOption: runtimeSelectedFeeOption,
649
386
  }: {
650
387
  onOriginSend?: () => void
651
- selectedFeeToken?: SelectedFeeToken
388
+ selectedFeeOption?: FeeOption | null
652
389
  }): Promise<SendReturn> => {
653
390
  try {
654
- // Use runtime selectedFeeToken if provided, otherwise fall back to the one from prepareSend
655
- const effectiveSelectedFeeToken =
656
- runtimeSelectedFeeToken ?? selectedFeeToken
391
+ // Use runtime selectedFeeOption (passed at execution time, always up-to-date)
392
+ const effectiveSelectedFeeOption = runtimeSelectedFeeOption
657
393
  logger.console.log(
658
394
  "[trails-sdk] [FEE-SELECT] [GASLESS-FLOW] send() called with:",
659
395
  {
660
- runtimeSelectedFeeToken,
661
- prepareTimeSelectedFeeToken: selectedFeeToken,
662
- effectiveSelectedFeeToken,
396
+ runtimeSelectedFeeOption,
397
+ effectiveSelectedFeeOption,
663
398
  },
664
399
  )
665
400
  const commitIntentFnToUse =
@@ -685,20 +420,7 @@ export async function handleCrossChain({
685
420
  }
686
421
 
687
422
  logger.console.log("[trails-sdk] sending origin transaction")
688
- const usingLIfi = false
689
- let needsNativeFee = false
690
-
691
- if (usingLIfi) {
692
- needsNativeFee = getNeedsLifiNativeFee({
693
- originTokenAddress,
694
- destinationTokenAmount: swapAmount,
695
- destinationTokenDecimals,
696
- sourceTokenDecimals,
697
- sourceTokenPriceUsd: sourceTokenPriceUsd ?? null,
698
- destinationTokenPriceUsd: destinationTokenPriceUsd ?? null,
699
- depositAmount,
700
- })
701
- }
423
+ const needsNativeFee = false
702
424
 
703
425
  logger.console.log("[trails-sdk] needsNativeFee", needsNativeFee)
704
426
  logger.console.log(
@@ -719,8 +441,8 @@ export async function handleCrossChain({
719
441
  )
720
442
 
721
443
  let depositUserTxnReceipt: TransactionReceipt | null = null
722
- let originMetaTxnReceipt: MetaTxnReceipt | null = null
723
- let destinationMetaTxnReceipt: MetaTxnReceipt | null = null
444
+ let originIntentTransaction: IntentTransaction | null = null
445
+ let destinationIntentTransaction: IntentTransaction | null = null
724
446
 
725
447
  const testnet = isTestnetDebugMode()
726
448
  const effectiveOriginChain = testnet
@@ -732,10 +454,11 @@ export async function handleCrossChain({
732
454
 
733
455
  logger.console.log("[trails-sdk] testnet", testnet)
734
456
 
735
- const destinationPublicClient = createPublicClient({
736
- chain: getChainInfo(destinationChainId)!,
737
- transport: http(),
738
- })
457
+ const destinationChainInfo = getChainInfo(destinationChainId)
458
+ if (!destinationChainInfo) {
459
+ throw new Error(`Chain ${destinationChainId} not found`)
460
+ }
461
+ const destinationPublicClient = getPublicRpcClient(destinationChainInfo)
739
462
 
740
463
  const depositPromise = async () => {
741
464
  logger.console.log(
@@ -759,14 +482,14 @@ export async function handleCrossChain({
759
482
  paymasterUrl,
760
483
  chain: effectiveOriginChain.id,
761
484
  account: account.address,
762
- firstPreconditionMin,
485
+ depositAmount,
763
486
  originIntentAddress,
764
487
  fee,
765
488
  dryMode,
766
489
  feeOptions: gasFeeOptions,
767
- selectedFeeToken: effectiveSelectedFeeToken,
768
- selectedFeeTokenType: typeof effectiveSelectedFeeToken,
769
- selectedFeeTokenValue: JSON.stringify(effectiveSelectedFeeToken),
490
+ selectedFeeOption: effectiveSelectedFeeOption,
491
+ selectedFeeOptionType: typeof effectiveSelectedFeeOption,
492
+ selectedFeeOptionValue: JsonEncode(effectiveSelectedFeeOption),
770
493
  checkoutOnHandlers,
771
494
  },
772
495
  )
@@ -776,7 +499,7 @@ export async function handleCrossChain({
776
499
  paymasterUrl,
777
500
  chain: effectiveOriginChain,
778
501
  account,
779
- firstPreconditionMin,
502
+ depositAmount,
780
503
  originIntentAddress,
781
504
  onOriginSend,
782
505
  publicClient,
@@ -797,7 +520,7 @@ export async function handleCrossChain({
797
520
  feeOptions: gasFeeOptions,
798
521
  checkoutOnHandlers,
799
522
  trailsClient,
800
- selectedFeeToken: effectiveSelectedFeeToken,
523
+ selectedFeeOption: effectiveSelectedFeeOption,
801
524
  walletId,
802
525
  abortSignal,
803
526
  intentId: intent.intentId,
@@ -987,6 +710,52 @@ export async function handleCrossChain({
987
710
  )
988
711
  }
989
712
 
713
+ // Call executeIntent after detecting deposit transaction (for QR code mode)
714
+ // This triggers the backend to start executing the intent
715
+ // Must be called BEFORE waitIntentReceipt polling starts
716
+ if (
717
+ originDepositTxReceipt.status === "success" &&
718
+ intent.intentId &&
719
+ (fundMethod === "qr-code" || fundMethod === "exchange") &&
720
+ !executeIntentCalled
721
+ ) {
722
+ logger.console.log(
723
+ "[trails-sdk] Calling executeIntent with detected deposit transaction hash (QR code mode)",
724
+ {
725
+ intentId: intent.intentId,
726
+ txHash: originDepositTxReceipt.transactionHash,
727
+ fundMethod,
728
+ },
729
+ )
730
+ try {
731
+ const executeIntentFnToUse =
732
+ executeIntentFn ||
733
+ trailsClient.executeIntent.bind(trailsClient)
734
+ await executeIntentFnToUse({
735
+ intentId: intent.intentId,
736
+ depositTransactionHash:
737
+ originDepositTxReceipt.transactionHash,
738
+ })
739
+ executeIntentCalled = true
740
+ logger.console.log(
741
+ "[trails-sdk] executeIntent completed successfully (QR code mode)",
742
+ )
743
+
744
+ // Now that executeIntent has been called, start unified polling if not already started
745
+ if (!unifiedPollerPromise) {
746
+ logger.console.log(
747
+ "[trails-sdk] Starting unified polling after executeIntent (QR code mode)",
748
+ )
749
+ startUnifiedPolling()
750
+ }
751
+ } catch (error) {
752
+ logger.console.error(
753
+ "[trails-sdk] Error calling executeIntent (QR code mode):",
754
+ error,
755
+ )
756
+ }
757
+ }
758
+
990
759
  if (onOriginSend) {
991
760
  onOriginSend()
992
761
  }
@@ -1088,6 +857,7 @@ export async function handleCrossChain({
1088
857
  // Unified polling via shared poller instead of separate loops
1089
858
  let unifiedPollerAbortController: AbortController | null = null
1090
859
  let unifiedPollerPromise: Promise<IntentReceipt | null> | null = null
860
+ let executeIntentCalled = false // Track if executeIntent has been called (for QR code mode)
1091
861
 
1092
862
  // Helper function to start unified polling for both origin and destination transactions
1093
863
  const startUnifiedPolling = () => {
@@ -1226,7 +996,9 @@ export async function handleCrossChain({
1226
996
  )
1227
997
 
1228
998
  // Store the transaction hash
1229
- originMetaTxnReceipt = { txnHash: txHash } as MetaTxnReceipt
999
+ originIntentTransaction = {
1000
+ txnHash: txHash,
1001
+ } as IntentTransaction
1230
1002
 
1231
1003
  const originTxnReceipt =
1232
1004
  await publicClient.getTransactionReceipt({
@@ -1325,9 +1097,9 @@ export async function handleCrossChain({
1325
1097
  )
1326
1098
 
1327
1099
  // Store the transaction hash
1328
- destinationMetaTxnReceipt = {
1100
+ destinationIntentTransaction = {
1329
1101
  txnHash: txHash,
1330
- } as MetaTxnReceipt
1102
+ } as IntentTransaction
1331
1103
 
1332
1104
  const destinationTxnReceipt =
1333
1105
  await destinationPublicClient.getTransactionReceipt({
@@ -1442,15 +1214,17 @@ export async function handleCrossChain({
1442
1214
 
1443
1215
  // First phase: Send meta transactions and queue CCTP
1444
1216
  const originSendMetaTxnPromise = async () => {
1217
+ const originMeta = intent.originMetaTxn
1218
+ const originPre = intent.originPrecondition
1445
1219
  logger.console.log("[trails-sdk] Starting originSendMetaTxnPromise", {
1446
- hasMetaTxn: !!intent.metaTxns[0],
1447
- hasPrecondition: !!intent.preconditions[0],
1448
- metaTxnId: intent.metaTxns[0]?.id,
1449
- chainId: intent.metaTxns[0]?.chainId,
1220
+ hasMetaTxn: !!originMeta,
1221
+ hasPrecondition: !!originPre,
1222
+ metaTxnId: originMeta?.id,
1223
+ chainId: originMeta?.chainId,
1450
1224
  })
1451
1225
 
1452
- if (intent.metaTxns[0] && intent.preconditions[0]) {
1453
- const metaTxnId = intent.metaTxns[0].id
1226
+ if (originMeta && originPre) {
1227
+ const metaTxnId = originMeta.id
1454
1228
  const feeQuote = undefined
1455
1229
  logger.console.log("[trails-sdk] Processing origin meta txn", {
1456
1230
  metaTxnId,
@@ -1462,9 +1236,9 @@ export async function handleCrossChain({
1462
1236
  "[trails-sdk] NOTE: Client-side meta transaction submission deprecated",
1463
1237
  {
1464
1238
  metaTxnId,
1465
- chainId: intent.metaTxns[0].chainId,
1466
- walletAddress: intent.metaTxns[0].walletAddress,
1467
- contract: intent.metaTxns[0].contract,
1239
+ chainId: originMeta.chainId,
1240
+ walletAddress: originMeta.walletAddress,
1241
+ contract: originMeta.contract,
1468
1242
  message:
1469
1243
  "Transaction submission now handled by backend via executeIntent. Monitoring via WaitIntentReceipt API.",
1470
1244
  },
@@ -1482,21 +1256,23 @@ export async function handleCrossChain({
1482
1256
  logger.console.warn(
1483
1257
  "[trails-sdk] Skipping origin sendMetaTxn - missing metaTxn or precondition",
1484
1258
  {
1485
- hasMetaTxn: !!intent.metaTxns[0],
1486
- hasPrecondition: !!intent.preconditions[0],
1259
+ hasMetaTxn: !!intent.originMetaTxn,
1260
+ hasPrecondition: !!intent.originPrecondition,
1487
1261
  },
1488
1262
  )
1489
1263
  }
1490
1264
  }
1491
1265
 
1492
1266
  const destinationSendMetaTxnPromise = async () => {
1267
+ const destinationPre = intent.destinationPrecondition
1268
+ const destinationMeta = intent.destinationMetaTxn
1493
1269
  logger.console.log(
1494
1270
  "[trails-sdk] Starting destinationSendMetaTxnPromise",
1495
1271
  {
1496
1272
  quoteProvider: intent.quote.quoteProvider,
1497
1273
  hasQuoteProviderRequestId: !!intent.quote.quoteProviderRequestId,
1498
- hasPrecondition1: !!intent.preconditions[1],
1499
- hasMetaTxn1: !!intent.metaTxns[1],
1274
+ hasPrecondition1: !!destinationPre,
1275
+ hasMetaTxn1: !!destinationMeta,
1500
1276
  },
1501
1277
  )
1502
1278
 
@@ -1507,41 +1283,6 @@ export async function handleCrossChain({
1507
1283
  )
1508
1284
  }
1509
1285
 
1510
- let queueCctpPromise: (() => Promise<void>) | null = null
1511
-
1512
- const isCctp = intent.quote.quoteProvider === "cctp"
1513
- if (isCctp) {
1514
- queueCctpPromise = async () => {
1515
- while (true) {
1516
- // Check if we should abort
1517
- if (abortSignal?.aborted) {
1518
- logger.console.log(
1519
- "[trails-sdk] Aborting CCTP queue due to abort signal",
1520
- )
1521
- return
1522
- }
1523
-
1524
- const originMetaTxnHash = (
1525
- originMetaTxnReceipt as MetaTxnReceipt | null
1526
- )?.txnHash
1527
- if (originMetaTxnHash) {
1528
- await queueCCTPTransfer({
1529
- trailsClient,
1530
- sourceTxHash: originMetaTxnHash,
1531
- sourceChainId: originChainId,
1532
- destinationChainId: destinationChainId,
1533
- })
1534
- break
1535
- }
1536
- await new Promise((resolve) =>
1537
- setTimeout(resolve, POLLING_INTERVALS.CCTP_QUEUE),
1538
- )
1539
- }
1540
- }
1541
- } else {
1542
- queueCctpPromise = () => Promise.resolve()
1543
- }
1544
-
1545
1286
  // Only start polling for external deposits if needed:
1546
1287
  // - QR code or exchange funding (external deposits)
1547
1288
  // - Gasless flow (relayer-executed deposits)
@@ -1583,12 +1324,43 @@ export async function handleCrossChain({
1583
1324
  "[trails-sdk] Starting Phase 2: Waiting for receipts and executing deposit",
1584
1325
  )
1585
1326
 
1327
+ // Helper function to wait for unifiedPollerPromise to be created (for QR code mode)
1328
+ const waitForUnifiedPollerToStart = async () => {
1329
+ if (fundMethod !== "qr-code" && fundMethod !== "exchange") {
1330
+ return // No need to wait for non-QR code modes
1331
+ }
1332
+
1333
+ const maxWaitTime = 5 * 60 * 1000 // 5 minutes max wait
1334
+ const startTime = Date.now()
1335
+ // Wait for unifiedPollerPromise to be created (after executeIntent is called)
1336
+ while (!unifiedPollerPromise) {
1337
+ if (Date.now() - startTime > maxWaitTime) {
1338
+ logger.console.error(
1339
+ "[trails-sdk] Timeout waiting for unified poller to start (QR code mode)",
1340
+ )
1341
+ throw new Error(
1342
+ "Timeout waiting for deposit detection and executeIntent in QR code mode",
1343
+ )
1344
+ }
1345
+ await new Promise((resolve) => setTimeout(resolve, 100))
1346
+ // Check abort signal
1347
+ if (abortSignal?.aborted) {
1348
+ logger.console.log(
1349
+ "[trails-sdk] Aborting wait for unified poller due to abort signal",
1350
+ )
1351
+ return
1352
+ }
1353
+ }
1354
+ }
1355
+
1586
1356
  const waitForOriginMetaTxnReceiptPromise = async () => {
1587
1357
  logger.console.log(
1588
1358
  "[trails-sdk] Waiting for origin meta transaction receipt via unified poller",
1589
1359
  )
1590
1360
  // The unified poller handles origin transaction discovery and decoding via callbacks
1591
- // We just need to wait for it to complete
1361
+ // For QR code mode, wait for unifiedPollerPromise to be created first (after executeIntent is called)
1362
+ await waitForUnifiedPollerToStart()
1363
+
1592
1364
  if (unifiedPollerPromise) {
1593
1365
  try {
1594
1366
  await unifiedPollerPromise
@@ -1606,7 +1378,9 @@ export async function handleCrossChain({
1606
1378
  "[trails-sdk] Waiting for destination meta transaction receipt via unified poller",
1607
1379
  )
1608
1380
  // The unified poller handles destination transaction discovery and decoding via callbacks
1609
- // We just need to wait for it to complete
1381
+ // For QR code mode, wait for unifiedPollerPromise to be created first (after executeIntent is called)
1382
+ await waitForUnifiedPollerToStart()
1383
+
1610
1384
  if (unifiedPollerPromise) {
1611
1385
  try {
1612
1386
  await unifiedPollerPromise
@@ -1632,10 +1406,17 @@ export async function handleCrossChain({
1632
1406
 
1633
1407
  // Start unified polling after deposit transaction is submitted and executeIntent is called
1634
1408
  // This ensures the backend has received the executeIntent call before we start polling waitIntentReceipt
1635
- logger.console.log(
1636
- "[trails-sdk] Starting unified polling after executeIntent has been called",
1637
- )
1638
- startUnifiedPolling()
1409
+ // For QR code mode, unified polling will be started after executeIntent is called in checkForDepositTx
1410
+ if (fundMethod !== "qr-code" && fundMethod !== "exchange") {
1411
+ logger.console.log(
1412
+ "[trails-sdk] Starting unified polling after executeIntent has been called",
1413
+ )
1414
+ startUnifiedPolling()
1415
+ } else {
1416
+ logger.console.log(
1417
+ "[trails-sdk] Delaying unified polling for QR code mode - will start after executeIntent is called",
1418
+ )
1419
+ }
1639
1420
 
1640
1421
  // Now wait for all the receipts and CCTP processing
1641
1422
  logger.console.log(
@@ -1644,7 +1425,6 @@ export async function handleCrossChain({
1644
1425
  await Promise.all([
1645
1426
  waitForOriginMetaTxnReceiptPromise(),
1646
1427
  waitForDestinationMetaTxnReceiptPromise(),
1647
- queueCctpPromise(),
1648
1428
  ])
1649
1429
  logger.console.log("[trails-sdk] Phase 2 completed successfully")
1650
1430
 
@@ -1657,10 +1437,10 @@ export async function handleCrossChain({
1657
1437
  const hasRequiredReceipts =
1658
1438
  (depositUserTxnReceipt || effectiveGasless) &&
1659
1439
  (isDestinationCrossChain
1660
- ? destinationMetaTxnReceipt
1440
+ ? destinationIntentTransaction
1661
1441
  : isSameChain
1662
- ? originMetaTxnReceipt
1663
- : destinationMetaTxnReceipt)
1442
+ ? originIntentTransaction
1443
+ : destinationIntentTransaction)
1664
1444
 
1665
1445
  if (hasRequiredReceipts) {
1666
1446
  // Check if any transaction failed or was refunded
@@ -1681,7 +1461,7 @@ export async function handleCrossChain({
1681
1461
  ? (depositUserTxnReceipt as TransactionReceipt).transactionHash
1682
1462
  : undefined,
1683
1463
  destinationTxHash: (
1684
- destinationMetaTxnReceipt as unknown as MetaTxnReceipt
1464
+ destinationIntentTransaction as unknown as IntentTransaction
1685
1465
  )?.txnHash,
1686
1466
  originChainId,
1687
1467
  destinationChainId,
@@ -1755,8 +1535,8 @@ export async function handleCrossChain({
1755
1535
 
1756
1536
  return {
1757
1537
  depositUserTxnReceipt,
1758
- originMetaTxnReceipt,
1759
- destinationMetaTxnReceipt,
1538
+ originIntentTransaction,
1539
+ destinationIntentTransaction,
1760
1540
  totalCompletionSeconds: await getTxTimeDiff(
1761
1541
  transactionStates[0],
1762
1542
  transactionStates[2],