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
@@ -1,17 +1,9 @@
1
- import { useEffect, useState, useMemo } from "react"
1
+ import { useEffect, useState } from "react"
2
2
  import { SECOND_MS } from "../../utils/time.js"
3
- import { useAccountTransactionHistory } from "../../transactions.js"
4
3
  import { checkAccountBalance } from "../../transactionIntent/utils/balanceChecker.js"
5
4
  import { getChainRpcClient } from "../../chains.js"
6
5
  import type { Account } from "viem"
7
- import { formatUnits } from "viem"
8
6
  import { logger } from "../../logger.js"
9
-
10
- import {
11
- addressEqual,
12
- isNativeToken,
13
- normalizeAddress,
14
- } from "../../utils/address.js"
15
7
  export interface UseDepositMonitorParams {
16
8
  chainId?: number
17
9
  depositAddress?: string
@@ -22,17 +14,15 @@ export interface UseDepositMonitorParams {
22
14
 
23
15
  export interface UseDepositMonitorReturn {
24
16
  hasSufficientDeposit: boolean
25
- isMonitoring: boolean
26
17
  depositBalance: string | null
27
18
  depositBalanceFormatted: string | null
28
19
  percentageComplete: number
29
- lastTransactionHash: string | null
30
20
  }
31
21
 
32
22
  /**
33
23
  * Hook to monitor deposits at a specific address and check if sufficient balance is available.
34
- * Uses both current balance AND recent transaction history to detect deposits that may have
35
- * already been forwarded (e.g., by intent execution).
24
+ * Uses current balance only. External funding flows are committed/executed
25
+ * before this hook is used, so monitoring is strictly for progress and UI state.
36
26
  */
37
27
  export function useDepositMonitor({
38
28
  chainId,
@@ -47,93 +37,8 @@ export function useDepositMonitor({
47
37
  string | null
48
38
  >(null)
49
39
  const [percentageComplete, setPercentageComplete] = useState(0)
50
- const [detectedDepositTxHash, setDetectedDepositTxHash] = useState<
51
- string | null
52
- >(null)
53
-
54
- // Monitor transaction history at the deposit address with polling
55
- // Fetch more transactions to catch deposits that may have been quickly forwarded
56
- const { data: transactionData, isLoading: isLoadingTransactions } =
57
- useAccountTransactionHistory({
58
- chainId: enabled ? chainId : null,
59
- accountAddress: enabled ? depositAddress : null,
60
- pageSize: 10, // Fetch more transactions to find incoming deposits
61
- includeMetadata: true,
62
- refetchInterval: enabled ? 5 * SECOND_MS : false, // Poll every 5 seconds when enabled
63
- })
64
-
65
- // Check for incoming deposits in transaction history
66
- // This catches deposits even if funds have already been forwarded
67
- useEffect(() => {
68
- if (
69
- !enabled ||
70
- !transactionData?.transactions ||
71
- !depositAddress ||
72
- !tokenAddress ||
73
- !requiredAmount
74
- ) {
75
- return
76
- }
77
-
78
- const normalizedDepositAddress = normalizeAddress(depositAddress)
79
- const normalizedTokenAddress = normalizeAddress(tokenAddress)
80
- const isNativeTokenDeposit = isNativeToken(tokenAddress)
81
-
82
- // Look for RECEIVE transfers to this address for the target token
83
- for (const tx of transactionData.transactions) {
84
- if (!tx.transfers) continue
85
-
86
- for (const transfer of tx.transfers) {
87
- const isReceive = transfer.transferType === "RECEIVE"
88
- const isToDepositAddress = addressEqual(
89
- transfer.to,
90
- normalizedDepositAddress,
91
- )
92
- const isTargetToken = isNativeTokenDeposit
93
- ? transfer.contractType === "NATIVE"
94
- : addressEqual(transfer.contractAddress, normalizedTokenAddress)
95
-
96
- if (isReceive && isToDepositAddress && isTargetToken) {
97
- // Found an incoming deposit - check if amount is sufficient
98
- const depositAmountRaw = transfer.amounts?.[0] || "0"
99
- const depositAmount = BigInt(depositAmountRaw)
100
- const required = BigInt(requiredAmount)
101
-
102
- const decimals = transfer.contractInfo?.decimals || 18
103
- const depositFormatted = formatUnits(depositAmount, decimals)
104
40
 
105
- logger.console.log(
106
- "[useDepositMonitor] Found incoming deposit in transaction history",
107
- {
108
- txHash: tx.txnHash,
109
- depositAddress,
110
- tokenAddress,
111
- depositAmount: depositFormatted,
112
- requiredAmount: formatUnits(required, decimals),
113
- sufficient: depositAmount >= required,
114
- },
115
- )
116
-
117
- if (depositAmount >= required) {
118
- setHasSufficientDeposit(true)
119
- setDepositBalance(depositAmount.toString())
120
- setDepositBalanceFormatted(depositFormatted)
121
- setPercentageComplete(100)
122
- setDetectedDepositTxHash(tx.txnHash)
123
- return // Found sufficient deposit, stop searching
124
- }
125
- }
126
- }
127
- }
128
- }, [enabled, transactionData, depositAddress, tokenAddress, requiredAmount])
129
-
130
- // Also check current balance as fallback (for cases where deposit hasn't been forwarded yet)
131
41
  useEffect(() => {
132
- // Skip balance check if we already found sufficient deposit in tx history
133
- if (hasSufficientDeposit) {
134
- return
135
- }
136
-
137
42
  if (
138
43
  !enabled ||
139
44
  !chainId ||
@@ -164,21 +69,17 @@ export function useDepositMonitor({
164
69
  publicClient,
165
70
  })
166
71
 
167
- // Only update if we haven't already detected sufficient deposit from tx history
168
- if (!hasSufficientDeposit) {
169
- setHasSufficientDeposit(balanceCheck.hasEnoughBalance)
170
- setDepositBalance(balanceCheck.balance?.toString() || null)
171
- setDepositBalanceFormatted(balanceCheck.balanceFormatted)
72
+ setHasSufficientDeposit(balanceCheck.hasEnoughBalance)
73
+ setDepositBalance(balanceCheck.balance?.toString() || null)
74
+ setDepositBalanceFormatted(balanceCheck.balanceFormatted)
172
75
 
173
- // Calculate percentage complete
174
- const percentage =
175
- balanceCheck.balance && balanceCheck.requiredAmount
176
- ? (Number(balanceCheck.balance) /
177
- Number(balanceCheck.requiredAmount)) *
178
- 100
179
- : 0
180
- setPercentageComplete(Math.min(percentage, 100))
181
- }
76
+ const percentage =
77
+ balanceCheck.balance && balanceCheck.requiredAmount
78
+ ? (Number(balanceCheck.balance) /
79
+ Number(balanceCheck.requiredAmount)) *
80
+ 100
81
+ : 0
82
+ setPercentageComplete(Math.min(percentage, 100))
182
83
 
183
84
  logger.console.log("[useDepositMonitor] Balance check result", {
184
85
  depositAddress,
@@ -206,48 +107,12 @@ export function useDepositMonitor({
206
107
  const interval = setInterval(checkBalance, 15 * SECOND_MS) // Check every 15 seconds
207
108
 
208
109
  return () => clearInterval(interval)
209
- }, [
210
- enabled,
211
- chainId,
212
- depositAddress,
213
- tokenAddress,
214
- requiredAmount,
215
- hasSufficientDeposit,
216
- ])
217
-
218
- // Get latest transaction hash - prefer the deposit tx if we found one
219
- const lastTransactionHash = useMemo(() => {
220
- // If we detected the deposit tx from history, use that
221
- if (detectedDepositTxHash) {
222
- return detectedDepositTxHash
223
- }
224
-
225
- // Fallback to latest transaction
226
- if (
227
- transactionData?.transactions &&
228
- transactionData.transactions.length > 0
229
- ) {
230
- const latestTx = transactionData.transactions[0]
231
- if (latestTx?.txnHash) {
232
- logger.console.log(
233
- "[useDepositMonitor] Latest transaction from indexer",
234
- {
235
- txnHash: latestTx.txnHash,
236
- depositAddress,
237
- },
238
- )
239
- return latestTx.txnHash
240
- }
241
- }
242
- return null
243
- }, [transactionData, depositAddress, detectedDepositTxHash])
110
+ }, [enabled, chainId, depositAddress, tokenAddress, requiredAmount])
244
111
 
245
112
  return {
246
113
  hasSufficientDeposit,
247
- isMonitoring: enabled && !isLoadingTransactions,
248
114
  depositBalance,
249
115
  depositBalanceFormatted,
250
116
  percentageComplete,
251
- lastTransactionHash,
252
117
  }
253
118
  }
@@ -0,0 +1,79 @@
1
+ import { useEffect, type Dispatch, type SetStateAction } from "react"
2
+ import { useIntentReceiptMonitor } from "../../intentReceiptMonitor.js"
3
+ import { logger } from "../../logger.js"
4
+ import {
5
+ applyIntentReceiptToTransactionStates,
6
+ hasIntentReceiptObservedFundingProgress,
7
+ } from "../../transactionIntent/helpers/transactionStateHelpers.js"
8
+ import type { TransactionState } from "../../transactions.js"
9
+ import { useTrailsClient } from "../../trailsClient.js"
10
+
11
+ export function useExternalFundingReceiptSync(params: {
12
+ enabled: boolean
13
+ intentId?: string
14
+ fallbackTransactionStates?: TransactionState[]
15
+ setTransactionStates: Dispatch<SetStateAction<TransactionState[]>>
16
+ onStatusUpdate?: (transactionStates: TransactionState[]) => void
17
+ onFundingObserved?: () => void
18
+ }): void {
19
+ const {
20
+ enabled,
21
+ intentId,
22
+ fallbackTransactionStates,
23
+ setTransactionStates,
24
+ onStatusUpdate,
25
+ onFundingObserved,
26
+ } = params
27
+ const trailsClient = useTrailsClient()
28
+ const { intentReceipt } = useIntentReceiptMonitor(
29
+ enabled ? intentId : undefined,
30
+ trailsClient,
31
+ )
32
+
33
+ useEffect(() => {
34
+ if (!intentReceipt) {
35
+ return
36
+ }
37
+
38
+ setTransactionStates((currentStates) => {
39
+ const baseStates =
40
+ currentStates.length > 0
41
+ ? currentStates
42
+ : (fallbackTransactionStates ?? [])
43
+
44
+ if (baseStates.length === 0) {
45
+ return currentStates
46
+ }
47
+
48
+ const { transactionStates, changed } =
49
+ applyIntentReceiptToTransactionStates({
50
+ currentStates: baseStates,
51
+ receipt: intentReceipt,
52
+ })
53
+
54
+ if (changed) {
55
+ logger.console.log(
56
+ "[trails-sdk] External funding receipt sync updated transaction states",
57
+ {
58
+ intentId,
59
+ status: intentReceipt.status,
60
+ },
61
+ )
62
+ onStatusUpdate?.(transactionStates)
63
+ }
64
+
65
+ return changed ? transactionStates : currentStates
66
+ })
67
+
68
+ if (hasIntentReceiptObservedFundingProgress(intentReceipt)) {
69
+ onFundingObserved?.()
70
+ }
71
+ }, [
72
+ fallbackTransactionStates,
73
+ intentId,
74
+ intentReceipt,
75
+ onFundingObserved,
76
+ onStatusUpdate,
77
+ setTransactionStates,
78
+ ])
79
+ }
@@ -0,0 +1,141 @@
1
+ import { useMemo } from "react"
2
+ import { useQuery } from "@tanstack/react-query"
3
+ import { logger } from "../../logger.js"
4
+ import { formatRawAmount } from "../../utils/format.js"
5
+ import { useTrailsClient } from "../../trailsClient.js"
6
+ import { useTrails } from "../providers/TrailsProvider.js"
7
+ import type {
8
+ RecoverableChainGroup,
9
+ RecoverableToken,
10
+ } from "../components/ReceiptRecoverableFunds.js"
11
+
12
+ interface UseIntentReceiptBalancesParams {
13
+ intentId?: string
14
+ ownerAddress?: string
15
+ enabled?: boolean
16
+ }
17
+
18
+ interface UseIntentReceiptBalancesResult {
19
+ chainGroups: RecoverableChainGroup[]
20
+ hasRecoverableFunds: boolean
21
+ isLoading: boolean
22
+ error: Error | null
23
+ refetch: () => void
24
+ }
25
+
26
+ type HistoryBalanceGroup = {
27
+ intentAddress: string
28
+ chainId: number
29
+ tokens: Array<{
30
+ contractAddress: string
31
+ balance: string
32
+ decimals: number
33
+ chainId: number
34
+ symbol: string
35
+ }>
36
+ }
37
+
38
+ const RECEIPT_BALANCE_POLL_INTERVAL_MS = 30_000
39
+ const MAX_RECEIPT_BALANCE_POLLS = 5
40
+
41
+ function mapTokens(tokens: HistoryBalanceGroup["tokens"]): RecoverableToken[] {
42
+ return tokens
43
+ .filter((token) => {
44
+ try {
45
+ return BigInt(token.balance || "0") > 0n
46
+ } catch {
47
+ return false
48
+ }
49
+ })
50
+ .map((token) => ({
51
+ chainId: token.chainId,
52
+ contractAddress: token.contractAddress,
53
+ symbol: token.symbol,
54
+ decimals: token.decimals,
55
+ rawBalance: token.balance,
56
+ formattedBalance: formatRawAmount(token.balance, token.decimals),
57
+ }))
58
+ }
59
+
60
+ export function useIntentReceiptBalances({
61
+ intentId,
62
+ ownerAddress,
63
+ enabled = true,
64
+ }: UseIntentReceiptBalancesParams): UseIntentReceiptBalancesResult {
65
+ const trailsConfig = useTrails()
66
+ const trailsClient = useTrailsClient()
67
+
68
+ const { data, isLoading, error, refetch } = useQuery({
69
+ queryKey: ["receiptIntentBalances", intentId, ownerAddress],
70
+ enabled:
71
+ enabled &&
72
+ !!intentId &&
73
+ !!ownerAddress &&
74
+ !!trailsConfig.trailsApiKey &&
75
+ !!trailsConfig.trailsApiUrl,
76
+ queryFn: async () => {
77
+ const response = await trailsClient.getIntentHistory({
78
+ byOwnerAddress: ownerAddress,
79
+ includeBalances: true,
80
+ page: { pageSize: 5 },
81
+ })
82
+
83
+ const normalizedIntentId = intentId?.toLowerCase()
84
+ const matchedIntent = (response.intents || []).find(
85
+ (item) => item.intentId?.toLowerCase() === normalizedIntentId,
86
+ )
87
+
88
+ if (!matchedIntent) {
89
+ return {
90
+ hasBalance: false,
91
+ balances: [] as HistoryBalanceGroup[],
92
+ }
93
+ }
94
+
95
+ logger.console.log("[trails-sdk] receipt balance intent match", {
96
+ intentId,
97
+ hasBalance: matchedIntent.hasBalance,
98
+ balanceGroupCount: (matchedIntent.balances || []).length,
99
+ })
100
+
101
+ return {
102
+ hasBalance: !!matchedIntent.hasBalance,
103
+ balances: (matchedIntent.balances || []) as HistoryBalanceGroup[],
104
+ }
105
+ },
106
+ staleTime: 0,
107
+ gcTime: 10 * 60 * 1000,
108
+ refetchInterval: (query) => {
109
+ return query.state.dataUpdateCount >= MAX_RECEIPT_BALANCE_POLLS
110
+ ? false
111
+ : RECEIPT_BALANCE_POLL_INTERVAL_MS
112
+ },
113
+ refetchIntervalInBackground: false,
114
+ refetchOnWindowFocus: false,
115
+ refetchOnReconnect: false,
116
+ refetchOnMount: false,
117
+ })
118
+
119
+ const chainGroups = useMemo<RecoverableChainGroup[]>(() => {
120
+ const balances = data?.balances || []
121
+ if (balances.length === 0) return []
122
+
123
+ return balances
124
+ .map((group) => ({
125
+ intentAddress: group.intentAddress,
126
+ chainId: group.chainId,
127
+ tokens: mapTokens(group.tokens || []),
128
+ }))
129
+ .filter((group) => group.tokens.length > 0)
130
+ }, [data?.balances])
131
+
132
+ return {
133
+ chainGroups,
134
+ hasRecoverableFunds: (data?.hasBalance ?? false) && chainGroups.length > 0,
135
+ isLoading,
136
+ error: (error as Error) || null,
137
+ refetch: () => {
138
+ void refetch()
139
+ },
140
+ }
141
+ }
@@ -280,10 +280,6 @@ export type SendOptions = {
280
280
  depositTransactionHash?: string
281
281
  /** Skip committing the intent (used when intent is already committed). */
282
282
  skipCommit?: boolean
283
- /** Only commit the intent without executing (used for onramp-meld flow). */
284
- commitOnly?: boolean
285
- /** Skip adding committed intent to worker monitoring storage cache. */
286
- skipIntentMonitoring?: boolean
287
283
  }
288
284
 
289
285
  export type UseQuoteReturn = {
@@ -950,11 +946,8 @@ export function useQuote({
950
946
  selectedFeeOption: selectedFeeOption ?? null,
951
947
  abortSignal: combinedAbortSignal,
952
948
  originNativeTokenPriceUsd: originNativeTokenPriceUsd,
953
- commitIntentFn: (intent, options) =>
954
- commitIntentMutation.mutateAsync({
955
- intent,
956
- skipIntentMonitoring: options?.skipIntentMonitoring,
957
- }),
949
+ commitIntentFn: (intent) =>
950
+ commitIntentMutation.mutateAsync(intent),
958
951
  executeIntentFn: executeIntentMutation.mutateAsync,
959
952
  checkoutOnHandlers,
960
953
  sequenceIndexerUrl,
@@ -1126,8 +1119,6 @@ export function useQuote({
1126
1119
  onOriginSend: options?.onOriginSend,
1127
1120
  depositTransactionHash: options?.depositTransactionHash,
1128
1121
  skipCommit: options?.skipCommit,
1129
- commitOnly: options?.commitOnly,
1130
- skipIntentMonitoring: options?.skipIntentMonitoring,
1131
1122
  })
1132
1123
 
1133
1124
  return {
@@ -1164,11 +1155,11 @@ export function useQuote({
1164
1155
  clearTimeout(timeoutId)
1165
1156
  }
1166
1157
  } catch (error) {
1158
+ const isAbortError =
1159
+ error instanceof Error && error.name === "AbortError"
1160
+
1167
1161
  // Check if this was aborted due to timeout
1168
- if (
1169
- (error as any)?.name === "AbortError" ||
1170
- abortControllerRef.current.signal.aborted
1171
- ) {
1162
+ if (isAbortError || abortControllerRef.current.signal.aborted) {
1172
1163
  logger.console.error(
1173
1164
  "[trails-sdk] [useQuote] Quote request timed out:",
1174
1165
  error,
@@ -1180,7 +1171,7 @@ export function useQuote({
1180
1171
  "[trails-sdk] [useQuote] Error getting quote:",
1181
1172
  error,
1182
1173
  )
1183
- throw getFullErrorMessage(error)
1174
+ throw new Error(getFullErrorMessage(error))
1184
1175
  }
1185
1176
  },
1186
1177
  // Prevent unnecessary refetching
@@ -0,0 +1,14 @@
1
+ import { useEffect } from "react"
2
+ import { trackWidgetScreen } from "../../analytics.js"
3
+ import { useViewManager } from "./useViewManager.js"
4
+
5
+ export function useScreenTracking(userAddress?: string) {
6
+ const { screen } = useViewManager()
7
+
8
+ useEffect(() => {
9
+ trackWidgetScreen({
10
+ screen,
11
+ userAddress,
12
+ })
13
+ }, [screen, userAddress])
14
+ }
@@ -4,10 +4,8 @@ import type { FundMethod } from "../../transactionIntent/types.js"
4
4
 
5
5
  interface SelectedFundMethodContextType {
6
6
  selectedFundMethod: FundMethod
7
- isOnRamp: boolean
8
7
  paymentMethod: { id: string; name: string }
9
8
  setSelectedFundMethod: (method: FundMethod) => void
10
- setIsMeldOnRamp: (isOnRamp: boolean) => void
11
9
  setPaymentMethod: (paymentMethod: { id: string; name: string }) => void
12
10
  }
13
11
 
@@ -24,7 +22,6 @@ export const SelectedFundMethodProvider = ({
24
22
  }: SelectedFundMethodProviderProps) => {
25
23
  const [selectedFundMethod, setSelectedFundMethod] =
26
24
  useState<FundMethod>("wallet")
27
- const [isOnRamp, setIsMeldOnRamp] = useState<boolean>(false)
28
25
  const [paymentMethod, setPaymentMethod] = useState<{
29
26
  id: string
30
27
  name: string
@@ -32,9 +29,7 @@ export const SelectedFundMethodProvider = ({
32
29
 
33
30
  const value: SelectedFundMethodContextType = {
34
31
  selectedFundMethod,
35
- isOnRamp,
36
32
  paymentMethod,
37
- setIsMeldOnRamp,
38
33
  setSelectedFundMethod,
39
34
  setPaymentMethod,
40
35
  }
@@ -51,6 +51,7 @@ import { useCustomTokens } from "../../customTokens.js"
51
51
  import { useQuote } from "./useQuote.js"
52
52
  import type { OnrampTrackingData } from "../types/analytics.js"
53
53
  import type { FundMethod } from "../../transactionIntent/types.js"
54
+ import { isExternalFundingMethod } from "../../transactionIntent/types.js"
54
55
  import { addressEqual } from "../../utils/address.js"
55
56
 
56
57
  type ChainInfo = {
@@ -89,8 +90,6 @@ export type UseSendProps = {
89
90
  onOriginSend?: () => void
90
91
  depositTransactionHash?: string
91
92
  skipCommit?: boolean
92
- commitOnly?: boolean
93
- skipIntentMonitoring?: boolean
94
93
  }) => Promise<any>)
95
94
  | null,
96
95
  ) => void
@@ -142,8 +141,6 @@ export type UseSendReturn = {
142
141
  onOriginSend?: () => void
143
142
  depositTransactionHash?: string
144
143
  skipCommit?: boolean
145
- commitOnly?: boolean
146
- skipIntentMonitoring?: boolean
147
144
  }) => Promise<any>)
148
145
  | null
149
146
  handleSubmit: (e: React.FormEvent) => Promise<void>
@@ -1041,7 +1038,6 @@ export function useSendForm({
1041
1038
  const sendResult = await sendFn!({
1042
1039
  selectedFeeOption: selectedFeeOption ?? null,
1043
1040
  onOriginSend, // Called when wallet signature is confirmed, before tx completes
1044
- commitOnly: fundMethod === "onramp-meld", // we need to commit first since there's a timeout on trails api side
1045
1041
  })
1046
1042
  logger.console.log("[trails-sdk] sendFn() completed:", sendResult)
1047
1043
 
@@ -1052,15 +1048,10 @@ export function useSendForm({
1052
1048
  }
1053
1049
 
1054
1050
  // Handle exchange/direct-transfer fund methods - don't call handleSend immediately
1055
- if (
1056
- fundMethod === "onramp-mesh" ||
1057
- fundMethod === "onramp-meld" ||
1058
- fundMethod === "direct-transfer"
1059
- ) {
1060
- // For direct-transfer, the intent commit happens via sendFn({ commitOnly: true })
1061
- // called from widget.tsx handleWaitingForWalletConfirm. The DirectTransfer component
1062
- // will monitor the deposit address and call sendFn({ depositTransactionHash, skipCommit: true })
1063
- // when sufficient funds arrive. Don't call handleSend here.
1051
+ if (isExternalFundingMethod(fundMethod)) {
1052
+ // External funding flows commit and execute before navigating away from
1053
+ // the funding form. Their follow-up screens only monitor deposit balance
1054
+ // and should not call handleSend again.
1064
1055
  if (fundMethod === "direct-transfer") {
1065
1056
  logger.console.log(
1066
1057
  "[trails-sdk] Direct-transfer fund method detected, deferring send until deposit confirmed",
@@ -411,16 +411,8 @@ export function useTokenList({
411
411
  error: hasSufficientBalanceUsdError,
412
412
  } = useHasSufficientBalanceUsd(address as Address.Address, targetAmountUsd)
413
413
  const showContinueButton = false
414
- const { data: supportedToChains = [] } = useSupportedChains()
415
-
416
414
  // Note: Supported tokens are now fetched via useSupportedTokens hook with caching
417
415
 
418
- // Memoize supportedChainIds to prevent recreation on every render
419
- const supportedChainIds = useMemo(
420
- () => new Set(supportedToChains.map((c) => c.id)),
421
- [supportedToChains],
422
- )
423
-
424
416
  // Map chain-filtered token list results to Token format
425
417
  // Used when a chain is selected for destination token list
426
418
  const chainFilteredApiTokens = useMemo(() => {
@@ -604,16 +596,11 @@ export function useTokenList({
604
596
  return mergedTokens
605
597
  }
606
598
 
607
- // Default behavior: use account-specific tokens (already Token[])
608
- return allSortedTokens.filter((token: Token) => {
609
- if (!supportedChainIds.has(token.chainId || 0)) {
610
- return false
611
- }
612
- return true
613
- })
599
+ // Default behavior: use account-specific tokens (already Token[]). Chain
600
+ // filtering is applied in useTokenBalances with fail-open fallback.
601
+ return allSortedTokens
614
602
  }, [
615
603
  allSortedTokens,
616
- supportedChainIds,
617
604
  fundMethod,
618
605
  supportedTokens,
619
606
  supportedTokenPrices,
@@ -486,11 +486,7 @@ export function useTrailsSendTransaction(
486
486
  originNativeTokenPriceUsd,
487
487
  swapProvider: params?.swapProvider,
488
488
  bridgeProvider: params?.bridgeProvider,
489
- commitIntentFn: (intent, options) =>
490
- commitIntentMutation.mutateAsync({
491
- intent,
492
- skipIntentMonitoring: options?.skipIntentMonitoring,
493
- }),
489
+ commitIntentFn: (intent) => commitIntentMutation.mutateAsync(intent),
494
490
  executeIntentFn: executeIntentMutation.mutateAsync,
495
491
  checkoutOnHandlers: params?.checkoutOnHandlers,
496
492
  sequenceIndexerUrl,