0xtrails 0.12.2 → 0.13.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 (243) hide show
  1. package/dist/abis/trailsHydrate.d.ts.map +1 -1
  2. package/dist/analytics.d.ts +41 -0
  3. package/dist/analytics.d.ts.map +1 -1
  4. package/dist/{ccip-62W6LwH2.js → ccip-Cg9-lJ6K.js} +16 -16
  5. package/dist/chainSwitch.d.ts.map +1 -1
  6. package/dist/chains.d.ts +9 -3
  7. package/dist/chains.d.ts.map +1 -1
  8. package/dist/error.d.ts +1 -0
  9. package/dist/error.d.ts.map +1 -1
  10. package/dist/{index-C0QTNYIA.js → index-DEojZg7b.js} +50431 -50424
  11. package/dist/index.d.ts +1 -3
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +377 -421
  14. package/dist/intentReceiptPoller.d.ts.map +1 -1
  15. package/dist/intents.d.ts +1 -3
  16. package/dist/intents.d.ts.map +1 -1
  17. package/dist/mutations.d.ts +1 -4
  18. package/dist/mutations.d.ts.map +1 -1
  19. package/dist/prepareSend.d.ts.map +1 -1
  20. package/dist/query/balance.hooks.d.ts.map +1 -1
  21. package/dist/query/chains.hooks.d.ts.map +1 -1
  22. package/dist/query/chains.queries.d.ts +4 -1
  23. package/dist/query/chains.queries.d.ts.map +1 -1
  24. package/dist/queryParams.d.ts.map +1 -1
  25. package/dist/recover.d.ts.map +1 -1
  26. package/dist/tokens.d.ts.map +1 -1
  27. package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -1
  28. package/dist/transactionIntent/deposits/gaslessDeposit.d.ts.map +1 -1
  29. package/dist/transactionIntent/deposits/standardDeposit.d.ts +1 -7
  30. package/dist/transactionIntent/deposits/standardDeposit.d.ts.map +1 -1
  31. package/dist/transactionIntent/handlers/intentHandler.d.ts.map +1 -1
  32. package/dist/transactionIntent/helpers/transactionStateHelpers.d.ts +10 -1
  33. package/dist/transactionIntent/helpers/transactionStateHelpers.d.ts.map +1 -1
  34. package/dist/transactionIntent/types.d.ts +3 -6
  35. package/dist/transactionIntent/types.d.ts.map +1 -1
  36. package/dist/transactionIntent/utils/resilientDepositTracker.d.ts +3 -3
  37. package/dist/transactionIntent/utils/resilientDepositTracker.d.ts.map +1 -1
  38. package/dist/transactions.d.ts +2 -0
  39. package/dist/transactions.d.ts.map +1 -1
  40. package/dist/umd/trails.min.js +200 -200
  41. package/dist/walletUtils.d.ts +4 -0
  42. package/dist/walletUtils.d.ts.map +1 -1
  43. package/dist/wallets.d.ts +2 -1
  44. package/dist/wallets.d.ts.map +1 -1
  45. package/dist/widget/components/AccountActionsDropdown.d.ts.map +1 -1
  46. package/dist/widget/components/AccountIntentTransactionHistoryButton.d.ts.map +1 -1
  47. package/dist/widget/components/AccountSettings.d.ts.map +1 -1
  48. package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
  49. package/dist/widget/components/ConnectWallet.d.ts.map +1 -1
  50. package/dist/widget/components/ConnectedWallets.d.ts +5 -1
  51. package/dist/widget/components/ConnectedWallets.d.ts.map +1 -1
  52. package/dist/widget/components/DepositTracker.d.ts +1 -1
  53. package/dist/widget/components/DepositTracker.d.ts.map +1 -1
  54. package/dist/widget/components/DirectTransfer.d.ts +0 -8
  55. package/dist/widget/components/DirectTransfer.d.ts.map +1 -1
  56. package/dist/widget/components/Fund.d.ts +1 -1
  57. package/dist/widget/components/Fund.d.ts.map +1 -1
  58. package/dist/widget/components/FundMethods.d.ts.map +1 -1
  59. package/dist/widget/components/FundWalletSelection.d.ts +0 -8
  60. package/dist/widget/components/FundWalletSelection.d.ts.map +1 -1
  61. package/dist/widget/components/FundingMethodSelectorButton.d.ts +1 -1
  62. package/dist/widget/components/FundingMethodSelectorButton.d.ts.map +1 -1
  63. package/dist/widget/components/MeldStepsFlow.d.ts.map +1 -1
  64. package/dist/widget/components/OnrampErrorScreen.d.ts.map +1 -1
  65. package/dist/widget/components/OnrampPaymentMethods.d.ts.map +1 -1
  66. package/dist/widget/components/OnrampProviderConfirmation.d.ts +0 -6
  67. package/dist/widget/components/OnrampProviderConfirmation.d.ts.map +1 -1
  68. package/dist/widget/components/Pay.d.ts.map +1 -1
  69. package/dist/widget/components/QrCode.d.ts.map +1 -1
  70. package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
  71. package/dist/widget/components/Receipt.d.ts.map +1 -1
  72. package/dist/widget/components/ReceiptRecoverableFunds.d.ts +25 -0
  73. package/dist/widget/components/ReceiptRecoverableFunds.d.ts.map +1 -0
  74. package/dist/widget/components/RecipientSelectorButton.d.ts +3 -1
  75. package/dist/widget/components/RecipientSelectorButton.d.ts.map +1 -1
  76. package/dist/widget/components/Recipients.d.ts.map +1 -1
  77. package/dist/widget/components/Swap.d.ts +2 -16
  78. package/dist/widget/components/Swap.d.ts.map +1 -1
  79. package/dist/widget/components/TokenSelector.d.ts.map +1 -1
  80. package/dist/widget/components/TransactionDetails.d.ts.map +1 -1
  81. package/dist/widget/components/TransactionHistoryItem.d.ts.map +1 -1
  82. package/dist/widget/components/TransferPendingVertical.d.ts.map +1 -1
  83. package/dist/widget/components/TruncatedTransactionHash.d.ts.map +1 -1
  84. package/dist/widget/components/WalletConfirmation.d.ts.map +1 -1
  85. package/dist/widget/components/WalletConnect.d.ts.map +1 -1
  86. package/dist/widget/components/WidgetProviders.d.ts.map +1 -1
  87. package/dist/widget/components/Withdraw.d.ts.map +1 -1
  88. package/dist/widget/css/compiled.css +1 -1
  89. package/dist/widget/hooks/useClickTracking.d.ts.map +1 -1
  90. package/dist/widget/hooks/useDebugScreens.d.ts +1 -10
  91. package/dist/widget/hooks/useDebugScreens.d.ts.map +1 -1
  92. package/dist/widget/hooks/useDepositMonitor.d.ts +2 -4
  93. package/dist/widget/hooks/useDepositMonitor.d.ts.map +1 -1
  94. package/dist/widget/hooks/useExternalFundingReceiptSync.d.ts +11 -0
  95. package/dist/widget/hooks/useExternalFundingReceiptSync.d.ts.map +1 -0
  96. package/dist/widget/hooks/useIntentReceiptBalances.d.ts +16 -0
  97. package/dist/widget/hooks/useIntentReceiptBalances.d.ts.map +1 -0
  98. package/dist/widget/hooks/useQuote.d.ts +0 -4
  99. package/dist/widget/hooks/useQuote.d.ts.map +1 -1
  100. package/dist/widget/hooks/useScreenTracking.d.ts +2 -0
  101. package/dist/widget/hooks/useScreenTracking.d.ts.map +1 -0
  102. package/dist/widget/hooks/useSelectedFundMethod.d.ts +0 -2
  103. package/dist/widget/hooks/useSelectedFundMethod.d.ts.map +1 -1
  104. package/dist/widget/hooks/useSendForm.d.ts +0 -4
  105. package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
  106. package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
  107. package/dist/widget/hooks/useTrailsSendTransaction.d.ts.map +1 -1
  108. package/dist/widget/hooks/useViewManager.d.ts +89 -0
  109. package/dist/widget/hooks/useViewManager.d.ts.map +1 -0
  110. package/dist/widget/hooks/useWalletConnectUri.d.ts.map +1 -1
  111. package/dist/widget/hooks/useWalletConnectionContext.d.ts +1 -1
  112. package/dist/widget/hooks/useWalletConnectionContext.d.ts.map +1 -1
  113. package/dist/widget/index.d.ts +1 -1
  114. package/dist/widget/index.d.ts.map +1 -1
  115. package/dist/widget/index.js +7 -6
  116. package/dist/widget/providers/TrailsProvider.d.ts.map +1 -1
  117. package/dist/widget/types/commonProps.d.ts +1 -6
  118. package/dist/widget/types/commonProps.d.ts.map +1 -1
  119. package/dist/widget/utils/forexRateStore.d.ts.map +1 -1
  120. package/dist/widget/utils/fundMethodSwitchState.d.ts +10 -0
  121. package/dist/widget/utils/fundMethodSwitchState.d.ts.map +1 -0
  122. package/dist/widget/utils/localeStore.d.ts.map +1 -1
  123. package/dist/widget/utils/viewManagerGuards.d.ts +5 -0
  124. package/dist/widget/utils/viewManagerGuards.d.ts.map +1 -0
  125. package/dist/widget/widget.d.ts +23 -2
  126. package/dist/widget/widget.d.ts.map +1 -1
  127. package/package.json +2 -2
  128. package/src/abis/trailsHydrate.ts +2 -1
  129. package/src/analytics.ts +60 -0
  130. package/src/chainSwitch.ts +11 -8
  131. package/src/chains.ts +82 -37
  132. package/src/constants.ts +2 -2
  133. package/src/error.ts +8 -0
  134. package/src/index.ts +1 -12
  135. package/src/intentReceiptPoller.ts +27 -0
  136. package/src/intents.ts +36 -87
  137. package/src/mutations.ts +11 -102
  138. package/src/onramp-client/index.ts +3 -3
  139. package/src/prepareSend.ts +6 -2
  140. package/src/query/balance.hooks.ts +31 -10
  141. package/src/query/chains.hooks.ts +7 -1
  142. package/src/query/chains.queries.ts +8 -5
  143. package/src/queryParams.ts +8 -6
  144. package/src/recover.ts +9 -9
  145. package/src/tokens.ts +4 -2
  146. package/src/transactionIntent/deposits/depositOrchestrator.ts +0 -2
  147. package/src/transactionIntent/deposits/gaslessDeposit.ts +8 -0
  148. package/src/transactionIntent/deposits/standardDeposit.ts +25 -35
  149. package/src/transactionIntent/handlers/intentHandler.ts +234 -138
  150. package/src/transactionIntent/helpers/transactionStateHelpers.ts +108 -1
  151. package/src/transactionIntent/types.ts +14 -8
  152. package/src/transactionIntent/utils/resilientDepositTracker.ts +72 -183
  153. package/src/transactions.ts +16 -0
  154. package/src/walletUtils.ts +188 -1
  155. package/src/wallets.ts +50 -15
  156. package/src/widget/compiled.css +1 -1
  157. package/src/widget/components/AccountActionsDropdown.tsx +4 -6
  158. package/src/widget/components/AccountIntentTransactionHistoryButton.tsx +4 -6
  159. package/src/widget/components/AccountSettings.tsx +36 -22
  160. package/src/widget/components/ClassicSwap.tsx +67 -9
  161. package/src/widget/components/ConnectWallet.tsx +5 -7
  162. package/src/widget/components/ConnectedWallets.tsx +143 -82
  163. package/src/widget/components/DepositTracker.tsx +4 -5
  164. package/src/widget/components/DirectTransfer.tsx +85 -84
  165. package/src/widget/components/Earn.tsx +3 -3
  166. package/src/widget/components/Fund.tsx +90 -17
  167. package/src/widget/components/FundMethods.tsx +77 -43
  168. package/src/widget/components/FundWalletSelection.tsx +13 -397
  169. package/src/widget/components/FundingMethodSelectorButton.tsx +11 -10
  170. package/src/widget/components/MeldStepsFlow.tsx +64 -30
  171. package/src/widget/components/OnrampErrorScreen.tsx +2 -18
  172. package/src/widget/components/OnrampPaymentMethods.tsx +4 -6
  173. package/src/widget/components/OnrampProviderConfirmation.tsx +91 -110
  174. package/src/widget/components/OriginTransferInformation.tsx +2 -2
  175. package/src/widget/components/Pay.tsx +27 -7
  176. package/src/widget/components/PaymentMethods.tsx +10 -10
  177. package/src/widget/components/PoolDeposit.tsx +2 -2
  178. package/src/widget/components/QrCode.tsx +13 -11
  179. package/src/widget/components/QuoteDetails.tsx +16 -6
  180. package/src/widget/components/Receipt.tsx +66 -6
  181. package/src/widget/components/ReceiptRecoverableFunds.tsx +135 -0
  182. package/src/widget/components/RecipientSelectorButton.tsx +6 -17
  183. package/src/widget/components/Recipients.tsx +38 -29
  184. package/src/widget/components/Swap.tsx +2 -25
  185. package/src/widget/components/TokenList.tsx +2 -2
  186. package/src/widget/components/TokenSelector.tsx +11 -11
  187. package/src/widget/components/TokenSelectorButton.tsx +3 -3
  188. package/src/widget/components/TrailsHookModal.tsx +1 -1
  189. package/src/widget/components/TransactionDetails.tsx +43 -37
  190. package/src/widget/components/TransactionHistoryItem.tsx +1 -42
  191. package/src/widget/components/TransferPendingVertical.tsx +11 -4
  192. package/src/widget/components/TruncatedTransactionHash.tsx +5 -0
  193. package/src/widget/components/WalletConfirmation.tsx +5 -8
  194. package/src/widget/components/WalletConnect.tsx +6 -2
  195. package/src/widget/components/WidgetProviders.tsx +34 -43
  196. package/src/widget/components/Withdraw.tsx +25 -11
  197. package/src/widget/hooks/useClickTracking.ts +5 -0
  198. package/src/widget/hooks/useDebugScreens.ts +40 -86
  199. package/src/widget/hooks/useDepositMonitor.ts +14 -149
  200. package/src/widget/hooks/useExternalFundingReceiptSync.ts +79 -0
  201. package/src/widget/hooks/useIntentReceiptBalances.ts +141 -0
  202. package/src/widget/hooks/useQuote.ts +7 -16
  203. package/src/widget/hooks/useScreenTracking.ts +14 -0
  204. package/src/widget/hooks/useSelectedFundMethod.tsx +0 -5
  205. package/src/widget/hooks/useSendForm.ts +5 -14
  206. package/src/widget/hooks/useTokenList.ts +3 -16
  207. package/src/widget/hooks/useTrailsSendTransaction.ts +1 -5
  208. package/src/widget/hooks/useViewManager.tsx +505 -0
  209. package/src/widget/hooks/useWalletConnectUri.tsx +77 -18
  210. package/src/widget/hooks/useWalletConnectionContext.tsx +1 -1
  211. package/src/widget/index.tsx +1 -0
  212. package/src/widget/providers/TrailsProvider.tsx +0 -41
  213. package/src/widget/styles.ts +1 -1
  214. package/src/widget/types/commonProps.ts +0 -8
  215. package/src/widget/utils/forexRateStore.ts +0 -2
  216. package/src/widget/utils/fundMethodSwitchState.ts +25 -0
  217. package/src/widget/utils/localeStore.ts +0 -1
  218. package/src/widget/utils/viewManagerGuards.ts +49 -0
  219. package/src/widget/widget.tsx +405 -316
  220. package/dist/intentStorage.d.ts +0 -24
  221. package/dist/intentStorage.d.ts.map +0 -1
  222. package/dist/mode.d.ts +0 -2
  223. package/dist/mode.d.ts.map +0 -1
  224. package/dist/widget/hooks/useBack.d.ts +0 -22
  225. package/dist/widget/hooks/useBack.d.ts.map +0 -1
  226. package/dist/widget/hooks/useCurrentScreen.d.ts +0 -13
  227. package/dist/widget/hooks/useCurrentScreen.d.ts.map +0 -1
  228. package/dist/widget/hooks/useInitialRedirect.d.ts +0 -7
  229. package/dist/widget/hooks/useInitialRedirect.d.ts.map +0 -1
  230. package/dist/widget/hooks/useMode.d.ts +0 -20
  231. package/dist/widget/hooks/useMode.d.ts.map +0 -1
  232. package/dist/widget/hooks/usePreviousScreen.d.ts +0 -12
  233. package/dist/widget/hooks/usePreviousScreen.d.ts.map +0 -1
  234. package/dist/widget/workers/intentExecutionWorker.d.ts +0 -73
  235. package/dist/widget/workers/intentExecutionWorker.d.ts.map +0 -1
  236. package/src/intentStorage.ts +0 -106
  237. package/src/mode.ts +0 -1
  238. package/src/widget/hooks/useBack.tsx +0 -210
  239. package/src/widget/hooks/useCurrentScreen.tsx +0 -73
  240. package/src/widget/hooks/useInitialRedirect.tsx +0 -70
  241. package/src/widget/hooks/useMode.tsx +0 -51
  242. package/src/widget/hooks/usePreviousScreen.ts +0 -36
  243. package/src/widget/workers/intentExecutionWorker.ts +0 -502
package/src/constants.ts CHANGED
@@ -35,8 +35,8 @@ type TrailsContracts = {
35
35
  export const TRAILS_CONTRACTS: TrailsContracts = {
36
36
  trailsUtilsAddress: "0x000000004f702C8398e158108937814d074cD74b",
37
37
  trailsIntentEntrypointAddress: "0x91E9e3Fe369CF005dB2857Ef24955A66d1E692Cf",
38
- trailsRouterAddress: "0xF8A739B9F24E297a98b7aba7A9cdFDBD457F6fF8",
39
- trailsRouterShimAddress: "0x1306aF05bA556839885B9B8c758f1d2F33d3571E",
38
+ trailsRouterAddress: "0xBaE357CBAA04a68cbfD5a560Ab06C4E9A3328A90",
39
+ trailsRouterShimAddress: "0xde04013becF982866A04d928A6df25e0D1FAaA71",
40
40
  }
41
41
 
42
42
  export const PROD_SEQUENCE_NODE_GATEWAY_URL = "https://nodes.sequence.app"
package/src/error.ts CHANGED
@@ -25,6 +25,14 @@ export function getIsAlreadyExecutingError(err: unknown): boolean {
25
25
  return getFullErrorMessage(err).includes("EXECUTING")
26
26
  }
27
27
 
28
+ export function getIntentStatusFromError(err: unknown): string | null {
29
+ const match = getFullErrorMessage(err).match(
30
+ /status=(COMMITTED|EXECUTING|SUCCEEDED|FAILED|REFUNDED|ABORTED|INVALID)/,
31
+ )
32
+
33
+ return match?.[1] ?? null
34
+ }
35
+
28
36
  export function getIsUserRejectionError(
29
37
  err: unknown,
30
38
  ): err is UserRejectionError {
package/src/index.ts CHANGED
@@ -3,17 +3,6 @@
3
3
  // Export version information
4
4
  export { SDK_VERSION, getVersion } from "./version.js"
5
5
 
6
- // Export the IntentExecutionWorker to ensure it's included in the build
7
- export { IntentExecutionWorker } from "./widget/workers/intentExecutionWorker.js"
8
-
9
- // Export intent storage utilities
10
- export {
11
- storeIntentForMonitoring,
12
- getStoredIntents,
13
- removeStoredIntent,
14
- clearAllStoredIntents,
15
- } from "./intentStorage.js"
16
-
17
6
  export {
18
7
  InsufficientBalanceError,
19
8
  UserRejectionError,
@@ -162,7 +151,7 @@ export {
162
151
  } from "./prices.js"
163
152
  export { getTxTimeDiff } from "./transactions.js"
164
153
  export { useCommitIntent, useExecuteIntent } from "./mutations.js"
165
- export type { Mode } from "./mode.js"
154
+ export type { Mode } from "./widget/hooks/useViewManager.js"
166
155
  export { TRAILS_ROUTER_PLACEHOLDER_AMOUNT } from "./placeholder.js"
167
156
  export * from "./widget/index.js"
168
157
  export { TrailsProvider, useTrails } from "./widget/providers/TrailsProvider.js"
@@ -260,6 +260,33 @@ export async function pollIntentReceipt(
260
260
  }
261
261
  }
262
262
 
263
+ // Defensive fallback for backend lag/inconsistency:
264
+ // if receipt status has not flipped to terminal yet, but destination
265
+ // transaction is already succeeded and we have a finished marker, treat
266
+ // the flow as complete to avoid indefinite pending UI.
267
+ const summary = (
268
+ receipt as unknown as { summary?: { finishedAt?: string | null } }
269
+ ).summary
270
+ const hasFinishedMarker = Boolean(
271
+ summary?.finishedAt ||
272
+ receipt.destinationTransaction?.txnMinedAt ||
273
+ receipt.destinationTransaction?.txnHash,
274
+ )
275
+ const destinationSucceeded =
276
+ receipt.destinationTransaction?.status === "SUCCEEDED"
277
+ if (destinationSucceeded && hasFinishedMarker) {
278
+ logger.console.warn(
279
+ "[trails-sdk] Treating receipt as complete via destination-success fallback",
280
+ {
281
+ intentId,
282
+ status: receipt.status,
283
+ destinationTxHash: receipt.destinationTransaction?.txnHash,
284
+ hasFinishedMarker,
285
+ },
286
+ )
287
+ return receipt
288
+ }
289
+
263
290
  // If intent is done, stop polling
264
291
  if (response.done) {
265
292
  logger.console.log("[trails-sdk] Intent receipt polling complete", {
package/src/intents.ts CHANGED
@@ -9,6 +9,7 @@ import type {
9
9
  GetIntentRequest,
10
10
  GetIntentResponse,
11
11
  Intent,
12
+ IntentStatus,
12
13
  IntentCalls,
13
14
  PassthroughInfo,
14
15
  QuoteIntentRequest,
@@ -16,10 +17,10 @@ import type {
16
17
  TrailsContracts,
17
18
  TransactionStateInfo,
18
19
  } from "@0xtrails/api"
19
- import { storeIntentForMonitoring } from "./intentStorage.js"
20
20
  import { logger } from "./logger.js"
21
21
  import { IntentProtocolVersion, IntentSource, JsonEncode } from "@0xtrails/api"
22
22
  import type { TrailsClient } from "./trailsClient.js"
23
+ import { getIntentStatusFromError } from "./error.js"
23
24
 
24
25
  import { Config, type Context, Payload } from "@0xsequence/wallet-primitives"
25
26
  import { Address, Bytes, ContractAddress, Hash, Hex } from "ox"
@@ -48,6 +49,7 @@ import { getFullErrorMessage } from "./error.js"
48
49
  import { GAS_BUFFER, getFeeData } from "./estimate.js"
49
50
  import { zeroAddress } from "viem"
50
51
  import { addressEqual, isNativeToken } from "./utils/address.js"
52
+ import { sendWalletTransaction } from "./walletUtils.js"
51
53
 
52
54
  export type IntentRequestParams = {
53
55
  userAddress: string
@@ -420,7 +422,7 @@ export async function calculateOriginAndDestinationIntentAddresses(
420
422
  if (originCalls.length !== 1) {
421
423
  // This should never happen
422
424
  logger.console.log("[trails-sdk] calls length incorrect")
423
- throw "origin calls length incorrect"
425
+ throw new Error("origin calls length incorrect")
424
426
  }
425
427
 
426
428
  const { address: originIntentAddress } =
@@ -442,7 +444,7 @@ export async function calculateOriginAndDestinationIntentAddresses(
442
444
  if (destinationCalls.length !== 1) {
443
445
  // This should never happen
444
446
  logger.console.log("[trails-sdk] destination calls length incorrect")
445
- throw "destination calls length incorrect"
447
+ throw new Error("destination calls length incorrect")
446
448
  }
447
449
  const { address } = await getIntentConfigurationFromCalls(
448
450
  trailsClient,
@@ -469,9 +471,6 @@ export async function commitIntent(
469
471
  trailsClient: TrailsClient,
470
472
  intent: Intent,
471
473
  additionalTrackingProps: Record<string, string> = {},
472
- options?: {
473
- skipIntentMonitoring?: boolean
474
- },
475
474
  ): Promise<CommitIntentResponse> {
476
475
  // Build arrays for logging
477
476
  const originIntentCalls = intent.originCalls
@@ -551,35 +550,6 @@ export async function commitIntent(
551
550
  })
552
551
 
553
552
  logger.console.log("[trails-sdk] commitIntent response:", response)
554
- if (!options?.skipIntentMonitoring) {
555
- // Store intent ID in localStorage for monitoring
556
- try {
557
- const intentIdToStore = response.intentId || intent.intentId
558
- if (intentIdToStore) {
559
- const storageKey = "trails_pending_intents"
560
- const stored = localStorage.getItem(storageKey)
561
- const intents = stored ? JSON.parse(stored) : []
562
-
563
- // Add if not already present
564
- if (!intents.find((i: any) => i.intentId === intentIdToStore)) {
565
- intents.push({
566
- intentId: intentIdToStore,
567
- timestamp: Date.now(),
568
- })
569
- localStorage.setItem(storageKey, JSON.stringify(intents))
570
- logger.console.log(
571
- `[trails-sdk] Stored intent ${intentIdToStore} in localStorage`,
572
- )
573
- }
574
- }
575
- } catch (error) {
576
- logger.console.error("[trails-sdk] Failed to store intent:", error)
577
- }
578
- } else {
579
- logger.console.log(
580
- "[trails-sdk] commitIntent: skipIntentMonitoring enabled, skipping localStorage monitoring cache write",
581
- )
582
- }
583
553
 
584
554
  // Track successful intent commit
585
555
  trackIntentCommitCompleted({
@@ -592,37 +562,6 @@ export async function commitIntent(
592
562
  ...additionalTrackingProps,
593
563
  })
594
564
 
595
- // Store the intent ID for monitoring by the worker
596
- // Use the response intentId if available, otherwise use the intent's intentId
597
- const intentIdToStore = response.intentId || intent.intentId
598
- logger.console.log("[trails-sdk] commitIntent: Response and intent IDs:", {
599
- responseIntentId: response.intentId,
600
- intentIntentId: intent.intentId,
601
- intentIdToStore,
602
- })
603
-
604
- if (intentIdToStore) {
605
- if (!options?.skipIntentMonitoring) {
606
- logger.console.log(
607
- `[trails-sdk] commitIntent: Calling storeIntentForMonitoring with intent ${intentIdToStore}`,
608
- )
609
-
610
- storeIntentForMonitoring(intentIdToStore)
611
-
612
- logger.console.log(
613
- `[trails-sdk] commitIntent: storeIntentForMonitoring call completed`,
614
- )
615
- } else {
616
- logger.console.log(
617
- `[trails-sdk] commitIntent: skipIntentMonitoring enabled, not storing intent ${intentIdToStore} for worker monitoring`,
618
- )
619
- }
620
- } else {
621
- logger.console.warn(
622
- "[trails-sdk] commitIntent: No intent ID available to store for monitoring",
623
- )
624
- }
625
-
626
565
  return response
627
566
  } catch (error) {
628
567
  // Track intent commit error
@@ -648,30 +587,42 @@ export async function executeIntent(
648
587
  ): Promise<ExecuteIntentResponse> {
649
588
  logger.console.log("[trails-sdk] executeIntent inputs:", {
650
589
  intentId,
651
- depositTransactionHash,
590
+ providedDepositTransactionHash: depositTransactionHash,
652
591
  hasDepositSignature: !!depositSignature,
653
592
  })
654
593
 
655
- // Validate that we have either traditional or gasless deposit params
656
- if (!depositTransactionHash && !depositSignature) {
657
- throw new Error(
658
- "[trails-sdk] Either depositTransactionHash or depositSignature must be provided",
659
- )
660
- }
661
-
662
594
  const request: ExecuteIntentRequest = {
663
595
  intentId,
664
- depositTransactionHash,
665
596
  depositSignature,
666
597
  }
667
598
 
668
599
  logger.console.log("[trails-sdk] executeIntent request:", request)
669
600
 
670
- // Call the actual API endpoint
671
- const response = await trailsClient.executeIntent(request)
672
- logger.console.log("[trails-sdk] executeIntent response:", response)
601
+ try {
602
+ const response = await trailsClient.executeIntent(request)
603
+ logger.console.log("[trails-sdk] executeIntent response:", response)
604
+
605
+ return response
606
+ } catch (error) {
607
+ const intentStatus = getIntentStatusFromError(error)
608
+
609
+ if (intentStatus) {
610
+ logger.console.log(
611
+ "[trails-sdk] executeIntent returned terminal/non-committed status, treating as current state",
612
+ {
613
+ intentId,
614
+ intentStatus,
615
+ },
616
+ )
617
+
618
+ return {
619
+ intentId,
620
+ intentStatus: intentStatus as IntentStatus,
621
+ }
622
+ }
673
623
 
674
- return response
624
+ throw error
625
+ }
675
626
  }
676
627
 
677
628
  export async function sendOriginTransaction(
@@ -762,10 +713,10 @@ export async function sendOriginTransaction(
762
713
  }
763
714
 
764
715
  logger.console.log(
765
- "[trails-sdk] sending origin tx with walletClient.sendTransaction()",
716
+ "[trails-sdk] sending origin tx with sendWalletTransaction()",
766
717
  )
767
718
  const id = Date.now()
768
- logger.console.time(`[trails-sdk] walletClient.sendTransaction-${id}`)
719
+ logger.console.time(`[trails-sdk] sendWalletTransaction-${id}`)
769
720
 
770
721
  try {
771
722
  // Build transaction parameters - EIP-1559 and legacy are mutually exclusive
@@ -788,8 +739,8 @@ export async function sendOriginTransaction(
788
739
  txParams.gasPrice = gasPrice
789
740
  }
790
741
 
791
- const hash = await walletClient.sendTransaction(txParams)
792
- logger.console.timeEnd(`[trails-sdk] walletClient.sendTransaction-${id}`)
742
+ const hash = await sendWalletTransaction(walletClient, txParams)
743
+ logger.console.timeEnd(`[trails-sdk] sendWalletTransaction-${id}`)
793
744
  logger.console.log("[trails-sdk] done sending, origin tx hash", hash)
794
745
 
795
746
  // Track successful transaction submission (pseudonymize() is called inside analytics)
@@ -801,14 +752,12 @@ export async function sendOriginTransaction(
801
752
  })
802
753
 
803
754
  if (!hash) {
804
- throw new Error(
805
- "No transaction hash returned from walletClient.sendTransaction",
806
- )
755
+ throw new Error("No transaction hash returned from sendWalletTransaction")
807
756
  }
808
757
 
809
758
  return hash
810
759
  } catch (error) {
811
- logger.console.timeEnd(`[trails-sdk] walletClient.sendTransaction-${id}`)
760
+ logger.console.timeEnd(`[trails-sdk] sendWalletTransaction-${id}`)
812
761
 
813
762
  // Track failed transaction
814
763
  trackTransactionError({
package/src/mutations.ts CHANGED
@@ -2,18 +2,13 @@ import { useMutation } from "@tanstack/react-query"
2
2
  import type { Intent, DepositSignature } from "@0xtrails/api"
3
3
  import { useTrailsClient } from "./trailsClient.js"
4
4
  import { logger } from "./logger.js"
5
- import { getFullErrorMessage } from "./error.js"
5
+ import { getFullErrorMessage, getIntentStatusFromError } from "./error.js"
6
6
  import {
7
7
  trackIntentCommitStarted,
8
8
  trackIntentCommitCompleted,
9
9
  trackIntentCommitError,
10
10
  } from "./analytics.js"
11
- import {
12
- type ExecuteIntentResponse,
13
- type IntentStatus,
14
- IntentStatusError,
15
- } from "@0xtrails/api"
16
- import { storeIntentForMonitoring } from "./intentStorage.js"
11
+ import type { ExecuteIntentResponse, IntentStatus } from "@0xtrails/api"
17
12
 
18
13
  /**
19
14
  * Hook for committing an intent to the Trails API
@@ -23,17 +18,10 @@ export function useCommitIntent() {
23
18
  const trailsClient = useTrailsClient()
24
19
 
25
20
  return useMutation({
26
- mutationFn: async (
27
- input: Intent | { intent: Intent; skipIntentMonitoring?: boolean },
28
- ) => {
29
- const intent = "intent" in input ? input.intent : input
30
- const skipIntentMonitoring =
31
- "intent" in input ? input.skipIntentMonitoring === true : false
32
-
21
+ mutationFn: async (intent: Intent) => {
33
22
  logger.console.log("[trails-sdk] useCommitIntent: mutationFn called", {
34
23
  intentId: intent.intentId,
35
24
  originIntentAddress: intent.originIntentAddress,
36
- skipIntentMonitoring,
37
25
  stackTrace: new Error().stack,
38
26
  })
39
27
 
@@ -42,36 +30,6 @@ export function useCommitIntent() {
42
30
  originIntentAddress: intent.originIntentAddress,
43
31
  })
44
32
 
45
- if (!skipIntentMonitoring) {
46
- // Store intent ID in localStorage for monitoring
47
- try {
48
- const intentIdToStore = intent.intentId
49
- if (intentIdToStore) {
50
- const storageKey = "trails_pending_intents"
51
- const stored = localStorage.getItem(storageKey)
52
- const intents = stored ? JSON.parse(stored) : []
53
-
54
- // Add if not already present
55
- if (!intents.find((i: any) => i.intentId === intentIdToStore)) {
56
- intents.push({
57
- intentId: intentIdToStore,
58
- timestamp: Date.now(),
59
- })
60
- localStorage.setItem(storageKey, JSON.stringify(intents))
61
- logger.console.log(
62
- `[trails-sdk] Stored intent ${intentIdToStore} in localStorage`,
63
- )
64
- }
65
- }
66
- } catch (error) {
67
- logger.console.error("[trails-sdk] Failed to store intent:", error)
68
- }
69
- } else {
70
- logger.console.log(
71
- "[trails-sdk] useCommitIntent: skipIntentMonitoring enabled, skipping localStorage monitoring cache write",
72
- )
73
- }
74
-
75
33
  const originChainIdStr = intent.quoteRequest.originChainId.toString()
76
34
  const destinationChainIdStr =
77
35
  intent.quoteRequest.destinationChainId.toString()
@@ -111,39 +69,6 @@ export function useCommitIntent() {
111
69
  : undefined,
112
70
  })
113
71
 
114
- // Store the intent ID for monitoring by the worker
115
- const intentIdToStore = response.intentId || intent.intentId
116
- logger.console.log(
117
- "[trails-sdk] useCommitIntent: Response and intent IDs:",
118
- {
119
- responseIntentId: response.intentId,
120
- intentIntentId: intent.intentId,
121
- intentIdToStore,
122
- },
123
- )
124
-
125
- if (intentIdToStore) {
126
- if (!skipIntentMonitoring) {
127
- logger.console.log(
128
- `[trails-sdk] useCommitIntent: Calling storeIntentForMonitoring with intent ${intentIdToStore}`,
129
- )
130
-
131
- storeIntentForMonitoring(intentIdToStore)
132
-
133
- logger.console.log(
134
- `[trails-sdk] useCommitIntent: storeIntentForMonitoring call completed`,
135
- )
136
- } else {
137
- logger.console.log(
138
- `[trails-sdk] useCommitIntent: skipIntentMonitoring enabled, not storing intent ${intentIdToStore} for worker monitoring`,
139
- )
140
- }
141
- } else {
142
- logger.console.warn(
143
- "[trails-sdk] useCommitIntent: No intent ID available to store for monitoring",
144
- )
145
- }
146
-
147
72
  return response
148
73
  } catch (error) {
149
74
  // Track intent commit error
@@ -183,23 +108,15 @@ export function useExecuteIntent() {
183
108
  }) => {
184
109
  logger.console.log("[trails-sdk] useExecuteIntent: Starting execution", {
185
110
  intentId,
186
- depositTransactionHash,
111
+ providedDepositTransactionHash: depositTransactionHash,
187
112
  hasDepositSignature: !!depositSignature,
188
113
  })
189
114
 
190
- // Validate that we have either traditional or gasless deposit params
191
- if (!depositTransactionHash && !depositSignature) {
192
- throw new Error(
193
- "[trails-sdk] Either depositTransactionHash or depositSignature must be provided",
194
- )
195
- }
196
-
197
115
  let response: ExecuteIntentResponse
198
116
 
199
117
  try {
200
118
  response = await trailsClient.executeIntent({
201
119
  intentId,
202
- depositTransactionHash,
203
120
  depositSignature,
204
121
  })
205
122
  } catch (error) {
@@ -211,28 +128,20 @@ export function useExecuteIntent() {
211
128
  errorJSON: JSON.stringify(error, null, 2),
212
129
  },
213
130
  )
214
- if (
215
- (error instanceof Error &&
216
- error?.message?.includes("status=SUCCEEDED")) ||
217
- (error instanceof Error &&
218
- (error?.cause as Error)?.message?.includes("status=SUCCEEDED")) ||
219
- (error instanceof Error &&
220
- JSON.stringify(error).includes("status=SUCCEEDED")) ||
221
- (error instanceof IntentStatusError &&
222
- error?.cause?.toString().includes("status=SUCCEEDED")) ||
223
- JSON.stringify(error).includes("status=SUCCEEDED")
224
- ) {
131
+ const intentStatus = getIntentStatusFromError(error)
132
+
133
+ if (intentStatus) {
225
134
  logger.console.error(
226
- "[trails-sdk] useExecuteIntent: Intent already succeeded, treating as success",
227
- { intentId },
135
+ "[trails-sdk] useExecuteIntent: Intent already advanced, treating as current state",
136
+ { intentId, intentStatus },
228
137
  )
229
138
  return {
230
139
  intentId,
231
- intentStatus: "SUCCEEDED" as IntentStatus,
140
+ intentStatus: intentStatus as IntentStatus,
232
141
  }
233
142
  } else {
234
143
  logger.console.error(
235
- "[trails-sdk] useExecuteIntent did not throw IntentStatusError and is not a SUCCEEDED intent",
144
+ "[trails-sdk] useExecuteIntent did not return an intent status",
236
145
  {
237
146
  intentId,
238
147
  error,
@@ -12,8 +12,8 @@ export interface TrailsOnrampOptions {
12
12
 
13
13
  export class TrailsOnramp extends BaseTrailsOnramp {
14
14
  static fromTrailsApiClient(client: TrailsApi): TrailsOnramp {
15
- const hostname = (client as any).getHostname?.() ?? (client as any).hostname
16
- const fetchFn = (client as any).getFetch?.() ?? (client as any).fetch
15
+ const hostname = client.getHostname()
16
+ const fetchFn = client.getFetch()
17
17
  return new BaseTrailsOnramp(hostname, fetchFn)
18
18
  }
19
19
 
@@ -24,7 +24,7 @@ export class TrailsOnramp extends BaseTrailsOnramp {
24
24
  ): Promise<Response> => {
25
25
  // automatically include jwt and access key auth header to requests
26
26
  // if its been set on the api client
27
- const headers: { [key: string]: any } = {}
27
+ const headers: Record<string, string> = {}
28
28
 
29
29
  if (options?.jwt && options?.jwt.length > 0) {
30
30
  headers.Authorization = `BEARER ${options?.jwt}`
@@ -13,7 +13,11 @@ import { IntentProtocolVersion, RouteProvider } from "@0xtrails/api"
13
13
  import { wrapCalldataWithTrailsRouterIfNeeded } from "./abis/trailsRouter.js"
14
14
  import { logger } from "./logger.js"
15
15
  import { getIsCustomCalldata } from "./contractUtils.js"
16
- import { getChainInfo, getChainRpcClient, isDevEnvironment } from "./chains.js"
16
+ import {
17
+ getChainInfo,
18
+ getChainRpcClient,
19
+ getShouldFetchVersions,
20
+ } from "./chains.js"
17
21
  import { TRAILS_CONTRACTS } from "./constants.js"
18
22
  import {
19
23
  TradeType,
@@ -220,7 +224,7 @@ export async function prepareSend(
220
224
  let intentProtocolVersion = IntentProtocolVersion.v1 // Default to v1
221
225
 
222
226
  // Only fetch supported versions when using dev trails API environments for now
223
- const shouldFetchVersions = isDevEnvironment()
227
+ const shouldFetchVersions = getShouldFetchVersions()
224
228
 
225
229
  if (shouldFetchVersions) {
226
230
  try {
@@ -14,6 +14,7 @@ import { addressEqual } from "../utils/address.js"
14
14
  import { useUserActivityContext } from "../widget/providers/UserActivityProvider.js"
15
15
  import { useSkipBalanceFetch } from "../widget/hooks/useSelectedFundMethod.js"
16
16
  import { balanceQueries } from "./balance.queries.js"
17
+ import { useSupportedChains } from "./chains.hooks.js"
17
18
  import {
18
19
  sortTokensByPriority,
19
20
  type FlatTokenBalancesData,
@@ -58,6 +59,7 @@ export function useTokenBalances(
58
59
  const trailsClient = useTrailsClient()
59
60
  const { isUserActive } = useUserActivityContext()
60
61
  const { shouldSkipBalanceFetch } = useSkipBalanceFetch()
62
+ const { data: supportedChains = [] } = useSupportedChains()
61
63
 
62
64
  const isDisabled =
63
65
  options?.disabled !== undefined ? options.disabled : shouldSkipBalanceFetch
@@ -68,6 +70,10 @@ export function useTokenBalances(
68
70
  const refetchInterval = isUserActive
69
71
  ? clampRefetchInterval(options?.refetchInterval)
70
72
  : false
73
+ const supportedChainIds =
74
+ supportedChains.length > 0
75
+ ? new Set(supportedChains.map((chain) => chain.id))
76
+ : null
71
77
 
72
78
  const {
73
79
  data: sortedTokens = [],
@@ -76,16 +82,31 @@ export function useTokenBalances(
76
82
  refetch,
77
83
  } = useQuery({
78
84
  ...balanceQueries.withPrices(effectiveAddress, indexerClient, trailsClient),
79
- select: ({ balances }: GetTokenBalancesWithPriceReturn) =>
80
- balances
81
- .filter((token) => {
82
- try {
83
- return token.balance && BigInt(token.balance) > 0n
84
- } catch {
85
- return false
86
- }
87
- })
88
- .sort(sortTokensByPriority),
85
+ select: ({ balances }: GetTokenBalancesWithPriceReturn) => {
86
+ const nonZeroBalanceTokens = balances.filter((token) => {
87
+ try {
88
+ return token.balance && BigInt(token.balance) > 0n
89
+ } catch {
90
+ return false
91
+ }
92
+ })
93
+
94
+ if (!supportedChainIds) {
95
+ return nonZeroBalanceTokens.sort(sortTokensByPriority)
96
+ }
97
+
98
+ const supportedTokens = nonZeroBalanceTokens.filter((token) =>
99
+ supportedChainIds.has(token.chainId || 0),
100
+ )
101
+
102
+ // Fail open: if chain filtering yields nothing, keep the user's full
103
+ // non-zero token list instead of showing empty balances.
104
+ if (supportedTokens.length === 0) {
105
+ return nonZeroBalanceTokens.sort(sortTokensByPriority)
106
+ }
107
+
108
+ return supportedTokens.sort(sortTokensByPriority)
109
+ },
89
110
  refetchOnWindowFocus: true,
90
111
  refetchOnReconnect: true,
91
112
  refetchInterval,
@@ -8,7 +8,13 @@ import { logger } from "../logger.js"
8
8
  import { chainQueries } from "./chains.queries.js"
9
9
 
10
10
  export function useSupportedChains() {
11
- return useQuery(chainQueries.supported())
11
+ const { trailsApiUrl, trailsApiKey } = useTrails()
12
+ return useQuery(
13
+ chainQueries.supported({
14
+ trailsApiUrl,
15
+ trailsApiKey,
16
+ }),
17
+ )
12
18
  }
13
19
 
14
20
  export function useChainRpcClient(chainId?: number): PublicClient | null {
@@ -2,18 +2,21 @@ import { queryOptions } from "@tanstack/react-query"
2
2
  import { HOUR_MS, DAY_MS } from "../utils/time.js"
3
3
  import { getSupportedChains, type Chain } from "../chains.js"
4
4
  import { STATIC_QUERY_OPTIONS } from "./helpers.js"
5
- import { queryPersister } from "./persister.js"
6
5
 
7
6
  export const chainQueries = {
8
7
  all: ["chains"] as const,
9
8
 
10
- supported: () =>
9
+ supported: (config?: { trailsApiUrl?: string; trailsApiKey?: string }) =>
11
10
  queryOptions<Chain[]>({
12
- queryKey: [...chainQueries.all, "supported"] as const,
13
- queryFn: () => getSupportedChains(),
11
+ queryKey: [
12
+ ...chainQueries.all,
13
+ "supported",
14
+ config?.trailsApiUrl || "default",
15
+ config?.trailsApiKey || "",
16
+ ] as const,
17
+ queryFn: () => getSupportedChains(config),
14
18
  staleTime: HOUR_MS,
15
19
  gcTime: DAY_MS,
16
20
  ...STATIC_QUERY_OPTIONS,
17
- persister: queryPersister.persisterFn,
18
21
  }),
19
22
  }
@@ -34,15 +34,17 @@ export function useQueryParams() {
34
34
  const originalPushState = window.history.pushState
35
35
  const originalReplaceState = window.history.replaceState
36
36
 
37
- window.history.pushState = function () {
38
- // biome-ignore lint/complexity/noArguments: TODO: To fix
39
- originalPushState.apply(this, arguments as any)
37
+ window.history.pushState = function (
38
+ ...args: Parameters<History["pushState"]>
39
+ ) {
40
+ originalPushState.apply(this, args)
40
41
  updateQueryParams()
41
42
  }
42
43
 
43
- window.history.replaceState = function () {
44
- // biome-ignore lint/complexity/noArguments: TODO: To fix
45
- originalReplaceState.apply(this, arguments as any)
44
+ window.history.replaceState = function (
45
+ ...args: Parameters<History["replaceState"]>
46
+ ) {
47
+ originalReplaceState.apply(this, args)
46
48
  updateQueryParams()
47
49
  }
48
50