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
@@ -2,11 +2,11 @@ import { ChevronRight, Send, ZapIcon } from "lucide-react"
2
2
  import type React from "react"
3
3
  import { useAccount, useConnections } from "wagmi"
4
4
  import { truncateAddress } from "../../utils/address.js"
5
- import { useBack } from "../hooks/useBack.js"
5
+ import { useViewManager } from "../hooks/useViewManager.js"
6
6
  import { useSelectedFundMethod } from "../hooks/useSelectedFundMethod.js"
7
7
  import { AddressWalletIcon } from "./AddressWalletIcon.js"
8
8
  import { useResolveEns } from "../../ens.js"
9
- import type { Screen } from "../hooks/useCurrentScreen.js"
9
+ import type { Screen } from "../hooks/useViewManager.js"
10
10
 
11
11
  export const FundingMethodSelectorButton: React.FC<{
12
12
  showWalletConnectorIcon?: boolean
@@ -20,9 +20,8 @@ export const FundingMethodSelectorButton: React.FC<{
20
20
  }) => {
21
21
  const connections = useConnections()
22
22
  const { address } = useAccount()
23
- const { setCurrentScreenWithBack } = useBack()
24
- const { selectedFundMethod, isOnRamp, paymentMethod } =
25
- useSelectedFundMethod()
23
+ const { navigate } = useViewManager()
24
+ const { selectedFundMethod, paymentMethod } = useSelectedFundMethod()
26
25
 
27
26
  // Check if there are any connected accounts across all connectors
28
27
  const isConnected = connections.length > 0
@@ -36,10 +35,10 @@ export const FundingMethodSelectorButton: React.FC<{
36
35
  const handleClick = () => {
37
36
  if (isConnected && activeAddress) {
38
37
  // If wallet is connected, go to fund methods
39
- setCurrentScreenWithBack(sendToScreen.screen, sendToScreen.backScreen)
38
+ navigate(sendToScreen.screen, { backTarget: sendToScreen.backScreen })
40
39
  } else {
41
40
  // If no wallet connected, go to connect wallet
42
- setCurrentScreenWithBack("connect")
41
+ navigate("connect")
43
42
  }
44
43
  }
45
44
 
@@ -58,15 +57,17 @@ export const FundingMethodSelectorButton: React.FC<{
58
57
  selectedFundMethod === "direct-transfer" ? (
59
58
  <>
60
59
  <ZapIcon className="w-4 h-4 mr-1" />
61
- <span className="text-sm font-medium m-0">Direct Transfer</span>
60
+ <span className="text-sm font-medium m-0">Crypto Transfer</span>
62
61
  </>
63
62
  ) : selectedFundMethod === "onramp-mesh" ? (
64
63
  <>
65
64
  <Send className="w-4 h-4 mr-1" />
66
65
  <span className="text-sm font-medium m-0">Exchange</span>
67
66
  </>
68
- ) : selectedFundMethod === "onramp-meld" && isOnRamp ? (
69
- <span className="text-sm font-medium m-0">{paymentMethod.name}</span>
67
+ ) : selectedFundMethod === "onramp-meld" ? (
68
+ <span className="text-sm font-medium m-0">
69
+ {paymentMethod.name || "Onramp"}
70
+ </span>
70
71
  ) : hasEns ? (
71
72
  <>
72
73
  <div className="flex items-center mr-1">
@@ -13,8 +13,10 @@ import type { Country, MeldQuote, MeldToken } from "../../meld/utils/meld.js"
13
13
  import { getMeldOnrampClient } from "../../meld/utils/meld.js"
14
14
  import { normalizeAddress, truncateAddress } from "../../utils/address.js"
15
15
  import { MINUTE_MS, SECOND_MS } from "../../utils/time.js"
16
- import { useCurrentScreen } from "../hooks/useCurrentScreen.js"
16
+ import { useViewManager } from "../hooks/useViewManager.js"
17
17
  import type { MeldTransaction } from "../hooks/useOnRampTransactionStatus.js"
18
+ import { useOriginSelectedToken } from "../hooks/useOriginSelectedToken.js"
19
+ import { useTokenList } from "../hooks/useTokenList.js"
18
20
  import { useTrails } from "../providers/TrailsProvider.js"
19
21
  import { MeldForm } from "./MeldForm.js"
20
22
  import { ScreenHeader } from "./ScreenHeader.js"
@@ -36,33 +38,12 @@ type Screen =
36
38
  const MELD_AMOUNT_STORAGE_KEY = "meld-form-amount"
37
39
  const MELD_CURRENCY_STORAGE_KEY = "meld-debug-currency"
38
40
 
39
- function parseStoredCountry(raw: string | null): Country | null {
40
- if (!raw) return null
41
-
42
- try {
43
- // TODO: Temporary legacy `{ code }` compatibility until storage migration is centralized.
44
- const parsed = JSON.parse(raw) as Partial<Country> & { code?: string }
45
- const countryCode =
46
- typeof parsed.countryCode === "string"
47
- ? parsed.countryCode
48
- : typeof parsed.code === "string"
49
- ? parsed.code
50
- : null
51
-
52
- if (!countryCode) return null
53
-
54
- return {
55
- countryCode,
56
- name: typeof parsed.name === "string" ? parsed.name : countryCode,
57
- }
58
- } catch {
59
- return null
60
- }
61
- }
62
-
63
41
  interface AmountInputScreenProps {
64
42
  onBack: (amount: string, currency: string) => void
65
43
  onContinue: (amount: string, currency: string) => void
44
+ _selectedCountry: Country | null
45
+ _selectedToken: MeldToken | null
46
+ _selectedPaymentMethod: MeldPaymentMethod | null
66
47
  initialAmount?: string
67
48
  initialCurrency?: string
68
49
  }
@@ -70,6 +51,9 @@ interface AmountInputScreenProps {
70
51
  const AmountInputScreen: React.FC<AmountInputScreenProps> = ({
71
52
  onBack,
72
53
  onContinue,
54
+ _selectedCountry,
55
+ _selectedToken,
56
+ _selectedPaymentMethod,
73
57
  initialAmount = "",
74
58
  initialCurrency = "USD",
75
59
  }) => {
@@ -178,7 +162,12 @@ export const MeldStepsFlow: React.FC<MeldStepsFlowProps> = ({
178
162
  onBack: _onBack,
179
163
  }) => {
180
164
  const trailsConfig = useTrails()
181
- const { setCurrentScreen: setGlobalScreen } = useCurrentScreen()
165
+ const { navigate: setGlobalScreen, goHome } = useViewManager()
166
+ const { setSelectedToken: setOriginToken } = useOriginSelectedToken()
167
+ const { filteredTokens } = useTokenList({
168
+ onContinue: () => {},
169
+ onError: () => {},
170
+ })
182
171
  const { address: walletAddress } = useAccount()
183
172
 
184
173
  // Create OnrampClient using trails API key from config
@@ -201,7 +190,12 @@ export const MeldStepsFlow: React.FC<MeldStepsFlowProps> = ({
201
190
 
202
191
  // Load from local storage on mount
203
192
  const [selectedCountry, setSelectedCountry] = useState<Country | null>(() => {
204
- return parseStoredCountry(localStorage.getItem("meld-debug-country"))
193
+ try {
194
+ const saved = localStorage.getItem("meld-debug-country")
195
+ return saved ? JSON.parse(saved) : null
196
+ } catch {
197
+ return null
198
+ }
205
199
  })
206
200
 
207
201
  const [selectedPaymentMethod, setSelectedPaymentMethod] =
@@ -247,8 +241,6 @@ export const MeldStepsFlow: React.FC<MeldStepsFlowProps> = ({
247
241
  }>({ status: "", message: "", type: null })
248
242
 
249
243
  // Check for transaction status from URL parameters (when user returns from Meld)
250
- // TODO: temporary ignore this Biome warning for now; do not refactor code in this pass.
251
- // biome-ignore lint/correctness/useExhaustiveDependencies: Preserve current dependency shape per requested no-code-change rollback.
252
244
  useEffect(() => {
253
245
  const urlParams = new URLSearchParams(window.location.search)
254
246
 
@@ -686,7 +678,7 @@ export const MeldStepsFlow: React.FC<MeldStepsFlowProps> = ({
686
678
  "[MeldStepsFlow] No transaction ID found in URL parameters",
687
679
  )
688
680
  }
689
- }, [trailsClient.searchMeldTransactions])
681
+ }, [trailsClient])
690
682
 
691
683
  // Function to check transaction status
692
684
  const checkTransactionStatus = useCallback(
@@ -949,6 +941,9 @@ export const MeldStepsFlow: React.FC<MeldStepsFlowProps> = ({
949
941
  "[MeldStepsFlow] Stored external session ID in localStorage",
950
942
  )
951
943
 
944
+ // Build redirect URL (current page URL without query params)
945
+ const _redirectUrl = window.location.origin + window.location.pathname
946
+
952
947
  logger.console.log("[MeldStepsFlow] Creating widget session with:", {
953
948
  countryCode: selectedCountry.countryCode,
954
949
  destinationCurrencyCode: selectedToken.code,
@@ -1065,6 +1060,42 @@ export const MeldStepsFlow: React.FC<MeldStepsFlowProps> = ({
1065
1060
  trailsClient,
1066
1061
  ])
1067
1062
 
1063
+ // Declare unused functions with underscore prefix to avoid linting warnings
1064
+ const _handleOpenWidget = useCallback(async () => {
1065
+ await generateWidgetUrl()
1066
+ if (
1067
+ widgetUrl &&
1068
+ !widgetUrl.startsWith("Error") &&
1069
+ !widgetUrl.startsWith("Please") &&
1070
+ !widgetUrl.startsWith("No")
1071
+ ) {
1072
+ window.open(widgetUrl, "_blank")
1073
+ }
1074
+ }, [widgetUrl, generateWidgetUrl])
1075
+
1076
+ const _handleContinue = useCallback(() => {
1077
+ if (!selectedToken) {
1078
+ return
1079
+ }
1080
+
1081
+ // Find the matching token in the widget's token list
1082
+ // Meld token has symbol (e.g., "USDC") and chainId
1083
+ // We need to match by symbol and chainId
1084
+ const matchingToken = filteredTokens.find((token) => {
1085
+ // Match by symbol and chainId
1086
+ return (
1087
+ token.symbol.toUpperCase() === selectedToken.symbol.toUpperCase() &&
1088
+ token.chainId === selectedToken.chainId
1089
+ )
1090
+ })
1091
+
1092
+ if (matchingToken) {
1093
+ // Set as origin token
1094
+ setOriginToken(matchingToken)
1095
+ goHome()
1096
+ }
1097
+ }, [selectedToken, filteredTokens, setOriginToken, goHome])
1098
+
1068
1099
  // Poll transaction status when we have a pending transaction
1069
1100
  useEffect(() => {
1070
1101
  logger.console.log("[MeldStepsFlow] Polling useEffect triggered:", {
@@ -1347,6 +1378,9 @@ export const MeldStepsFlow: React.FC<MeldStepsFlowProps> = ({
1347
1378
  setCurrentScreen("menu")
1348
1379
  }}
1349
1380
  onContinue={handleAmountContinue}
1381
+ _selectedCountry={selectedCountry}
1382
+ _selectedToken={selectedToken}
1383
+ _selectedPaymentMethod={selectedPaymentMethod}
1350
1384
  initialAmount={selectedAmount}
1351
1385
  initialCurrency={selectedCurrency}
1352
1386
  />
@@ -2,7 +2,6 @@ import { AlertCircle, RefreshCw } from "lucide-react"
2
2
  import type React from "react"
3
3
  import { useEffect, useState } from "react"
4
4
  import { ScreenHeader } from "./ScreenHeader.js"
5
- import { removeStoredIntent } from "../../intentStorage.js"
6
5
 
7
6
  interface OnrampErrorScreenProps {
8
7
  onTryAgain?: () => void
@@ -20,7 +19,6 @@ export const OnrampErrorScreen: React.FC<OnrampErrorScreenProps> = ({
20
19
  onTryAgain,
21
20
  onBack,
22
21
  onRetry,
23
- intentId,
24
22
  title,
25
23
  message,
26
24
  showAnimation = true,
@@ -83,15 +81,7 @@ export const OnrampErrorScreen: React.FC<OnrampErrorScreenProps> = ({
83
81
 
84
82
  return (
85
83
  <div className="space-y-6">
86
- <ScreenHeader
87
- onBack={() => {
88
- if (intentId) {
89
- removeStoredIntent(intentId)
90
- }
91
- onBack?.()
92
- }}
93
- headerContent={errorTitle}
94
- />
84
+ <ScreenHeader onBack={onBack} headerContent={errorTitle} />
95
85
 
96
86
  <div className="flex flex-col items-center justify-center min-h-[400px] space-y-6 px-4">
97
87
  {/* Error Icon */}
@@ -158,13 +148,7 @@ export const OnrampErrorScreen: React.FC<OnrampErrorScreenProps> = ({
158
148
  {onBack && (
159
149
  <button
160
150
  type="button"
161
- onClick={() => {
162
- // Remove the commited intent from pending intents, user cancelled
163
- if (intentId) {
164
- removeStoredIntent(intentId)
165
- }
166
- onBack()
167
- }}
151
+ onClick={onBack}
168
152
  className="flex-1 px-6 py-3 bg-gray-100 hover:bg-gray-200 dark:bg-gray-700 dark:hover:bg-gray-600 text-gray-700 dark:text-gray-300 font-medium rounded-lg transition-colors cursor-pointer"
169
153
  >
170
154
  Cancel
@@ -1,7 +1,7 @@
1
1
  import type React from "react"
2
2
  import { ChevronRight } from "lucide-react"
3
3
  import { ScreenHeader } from "./ScreenHeader.js"
4
- import { useCurrentScreen } from "../hooks/useCurrentScreen.js"
4
+ import { useViewManager } from "../hooks/useViewManager.js"
5
5
  import { useSelectedFundMethod } from "../hooks/useSelectedFundMethod.js"
6
6
  import {
7
7
  type PaymentMethod,
@@ -16,10 +16,9 @@ export interface OnrampPaymentMethodsProps {
16
16
  const OnrampPaymentMethods: React.FC<OnrampPaymentMethodsProps> = ({
17
17
  onBack,
18
18
  }) => {
19
- const { setCurrentScreen } = useCurrentScreen()
19
+ const { navigate } = useViewManager()
20
20
  const { isDark } = useTheme()
21
- const { setSelectedFundMethod, setIsMeldOnRamp, setPaymentMethod } =
22
- useSelectedFundMethod()
21
+ const { setSelectedFundMethod, setPaymentMethod } = useSelectedFundMethod()
23
22
 
24
23
  const { paymentMethods, isLoading, error } = useOnRampPaymentMethods({
25
24
  enabled: true,
@@ -51,12 +50,11 @@ const OnrampPaymentMethods: React.FC<OnrampPaymentMethodsProps> = ({
51
50
  type="button"
52
51
  onClick={() => {
53
52
  setSelectedFundMethod("onramp-meld")
54
- setIsMeldOnRamp(true)
55
53
  setPaymentMethod({
56
54
  id: method.paymentMethod,
57
55
  name: method.name,
58
56
  })
59
- setCurrentScreen("fund-form")
57
+ navigate("fund-form")
60
58
  }}
61
59
  className="w-full text-left px-4 py-3 flex items-center justify-between cursor-pointer transition-colors trails-hover-bg rounded-xl"
62
60
  >
@@ -1,7 +1,8 @@
1
1
  import { ChevronLeft } from "lucide-react"
2
2
  import type React from "react"
3
- import { useEffect, useState } from "react"
3
+ import { useEffect, useRef, useState } from "react"
4
4
  import { useAccount } from "wagmi"
5
+ import { trackOnrampPaymentCompleted } from "../../analytics.js"
5
6
  import { logger } from "../../logger.js"
6
7
  import type { PrepareSendQuote } from "../../prepareSend.js"
7
8
  import { truncateAddress } from "../../utils/address.js"
@@ -15,7 +16,6 @@ import { QuoteDetails } from "./QuoteDetails.js"
15
16
  import { SessionTimeoutScreen } from "./SessionTimeoutScreen.js"
16
17
  import { TokenImage } from "./TokenImage.js"
17
18
  import { TruncatedTransactionHash } from "./TruncatedTransactionHash.js"
18
- import { removeStoredIntent } from "../../intentStorage.js"
19
19
 
20
20
  // Helper to build tooltip text
21
21
  const buildTooltipText = (quote?: PrepareSendQuote | null): string => {
@@ -127,14 +127,6 @@ interface OnrampProviderConfirmationProps {
127
127
  params: WidgetCreationParams,
128
128
  ) => Promise<{ widgetUrl: string; id: string }>
129
129
  externalSessionId?: string | null // For monitoring transaction status
130
- sendFn?:
131
- | ((options?: {
132
- selectedFeeOption?: any | null
133
- onOriginSend?: () => void
134
- depositTransactionHash?: string // Added for onramp-meld to provide deposit hash
135
- skipCommit?: boolean
136
- }) => Promise<any>)
137
- | null // The send function from prepareSend
138
130
  popupWindowRef?: Window | null
139
131
  }
140
132
 
@@ -149,7 +141,6 @@ export const OnrampProviderConfirmation: React.FC<
149
141
  widgetCreationParams,
150
142
  onCreateWidgetSession,
151
143
  externalSessionId,
152
- sendFn,
153
144
  popupWindowRef,
154
145
  }) => {
155
146
  const [showContent, setShowContent] = useState(false)
@@ -159,6 +150,7 @@ export const OnrampProviderConfirmation: React.FC<
159
150
  const [hasExecutedWithDeposit, setHasExecutedWithDeposit] = useState(false)
160
151
  const [isCountingUp, setIsCountingUp] = useState(false) // Track if we're counting up
161
152
  const [timeElapsed, setTimeElapsed] = useState(0) // Time elapsed when counting up
153
+ const trackedOnrampCompletionKey = useRef<string | null>(null)
162
154
  const { address } = useAccount()
163
155
 
164
156
  // Check if this is a direct deposit flow (recipient is the deposit address)
@@ -197,18 +189,19 @@ export const OnrampProviderConfirmation: React.FC<
197
189
  }, [popupWindowRef, setWindowRef])
198
190
 
199
191
  // Monitor deposits at the origin intent address (only for intent-based flows)
192
+ const isIntentDepositMonitoringEnabled =
193
+ !!quote?.originDepositAddress && !isDirectDeposit
194
+
200
195
  const {
201
196
  hasSufficientDeposit: intentHasSufficientDeposit,
202
- isMonitoring: intentIsMonitoringDeposits,
203
197
  depositBalanceFormatted: intentDepositBalanceFormatted,
204
198
  percentageComplete: intentPercentageComplete,
205
- lastTransactionHash: intentLastTransactionHash,
206
199
  } = useDepositMonitor({
207
200
  chainId: quote?.originChain?.id,
208
201
  depositAddress: quote?.originDepositAddress,
209
202
  tokenAddress: quote?.originToken?.contractAddress,
210
203
  requiredAmount: quote?.originAmount,
211
- enabled: !!quote?.originDepositAddress && !isDirectDeposit, // Only monitor for intent-based flows
204
+ enabled: isIntentDepositMonitoringEnabled, // Only monitor for intent-based flows
212
205
  })
213
206
 
214
207
  // Use the appropriate monitoring data based on flow type
@@ -217,7 +210,7 @@ export const OnrampProviderConfirmation: React.FC<
217
210
  : intentHasSufficientDeposit
218
211
  const isMonitoringDeposits = isDirectDeposit
219
212
  ? !!externalSessionId
220
- : intentIsMonitoringDeposits
213
+ : isIntentDepositMonitoringEnabled
221
214
  const depositBalanceFormatted = isDirectDeposit
222
215
  ? meldSettledAmount || "0"
223
216
  : intentDepositBalanceFormatted
@@ -226,9 +219,7 @@ export const OnrampProviderConfirmation: React.FC<
226
219
  ? 100
227
220
  : 0
228
221
  : intentPercentageComplete
229
- const lastTransactionHash = isDirectDeposit
230
- ? meldTransactionHash
231
- : intentLastTransactionHash
222
+ const lastTransactionHash = isDirectDeposit ? meldTransactionHash : null
232
223
 
233
224
  const isPopupClosedDuringFlow =
234
225
  (windowClosed || meldStatusState === "window-closed") &&
@@ -260,6 +251,68 @@ export const OnrampProviderConfirmation: React.FC<
260
251
  meldSettledAmount,
261
252
  ])
262
253
 
254
+ useEffect(() => {
255
+ const completionKey = externalSessionId || quote?.intentId || "unknown"
256
+ if (
257
+ !isMeldSuccess ||
258
+ trackedOnrampCompletionKey.current === completionKey
259
+ ) {
260
+ return
261
+ }
262
+
263
+ trackedOnrampCompletionKey.current = completionKey
264
+
265
+ trackOnrampPaymentCompleted({
266
+ fundMethod: "onramp-meld",
267
+ userAddress: address,
268
+ intentId: quote?.intentId || undefined,
269
+ intentAddress: quote?.originDepositAddress,
270
+ externalSessionId: externalSessionId || undefined,
271
+ transactionId: transaction?.id,
272
+ transactionHash: meldTransactionHash || transaction?.transactionHash,
273
+ status: transaction?.status || "COMPLETED",
274
+ provider: transaction?.serviceProvider || onRampQuote?.serviceProvider,
275
+ sourceAmount:
276
+ transaction?.sourceAmount ?? onRampQuote?.sourceAmount?.toString(),
277
+ sourceCurrencyCode:
278
+ transaction?.sourceCurrencyCode || onRampQuote?.sourceCurrencyCode,
279
+ destinationAmount:
280
+ meldSettledAmount ||
281
+ transaction?.destinationAmount ||
282
+ onRampQuote?.destinationAmount?.toString(),
283
+ destinationCurrencyCode:
284
+ transaction?.destinationCurrencyCode ||
285
+ onRampQuote?.destinationCurrencyCode,
286
+ countryCode: onRampQuote?.countryCode,
287
+ paymentMethodType: onRampQuote?.paymentMethodType,
288
+ paymentMethod: transaction?.paymentMethod,
289
+ })
290
+ }, [
291
+ isMeldSuccess,
292
+ address,
293
+ quote?.intentId,
294
+ quote?.originDepositAddress,
295
+ onRampQuote?.serviceProvider,
296
+ onRampQuote?.sourceAmount,
297
+ onRampQuote?.sourceCurrencyCode,
298
+ onRampQuote?.destinationAmount,
299
+ onRampQuote?.destinationCurrencyCode,
300
+ onRampQuote?.countryCode,
301
+ onRampQuote?.paymentMethodType,
302
+ externalSessionId,
303
+ transaction?.id,
304
+ transaction?.transactionHash,
305
+ transaction?.status,
306
+ transaction?.serviceProvider,
307
+ transaction?.sourceAmount,
308
+ transaction?.sourceCurrencyCode,
309
+ transaction?.destinationAmount,
310
+ transaction?.destinationCurrencyCode,
311
+ transaction?.paymentMethod,
312
+ meldTransactionHash,
313
+ meldSettledAmount,
314
+ ])
315
+
263
316
  // Monitor transaction status for errors and SETTLING state
264
317
  useEffect(() => {
265
318
  if (isPopupClosedDuringFlow) {
@@ -287,98 +340,31 @@ export const OnrampProviderConfirmation: React.FC<
287
340
  setShowContent(true)
288
341
  }, [])
289
342
 
290
- // Call sendFn with the deposit transaction hash when deposit is detected
343
+ // Onramp flows commit and execute before this screen is shown.
344
+ // Deposit monitoring here is UI-only; do not re-enter sendFn with a
345
+ // client-detected deposit hash.
291
346
  useEffect(() => {
292
- const handleDepositDetected = async () => {
293
- // For direct deposits, we don't need to call sendFn (funds go directly to recipient)
294
- if (isDirectDeposit) {
295
- if (hasSufficientDeposit && onIntentExecuted) {
296
- logger.console.log(
297
- "[OnrampProviderConfirmation] Direct deposit completed, funds sent to recipient",
298
- {
299
- transactionHash: lastTransactionHash,
300
- amount: depositBalanceFormatted,
301
- },
302
- )
303
- }
304
- }
347
+ if (!hasSufficientDeposit || hasExecutedWithDeposit) {
348
+ return
349
+ }
305
350
 
306
- logger.console.log(
307
- "[OnrampProviderConfirmation] Checking conditions to call sendFn:",
308
- {
309
- hasSendFn: !!sendFn,
310
- hasIntentId: !!quote?.intentId,
311
- intentId: quote?.intentId,
312
- hasLastTransactionHash: !!lastTransactionHash,
313
- lastTransactionHash,
314
- hasSufficientDeposit,
315
- hasExecutedWithDeposit,
316
- isDirectDeposit,
317
- shouldExecute: !!(
318
- sendFn &&
319
- quote?.intentId &&
320
- lastTransactionHash &&
321
- hasSufficientDeposit &&
322
- !hasExecutedWithDeposit
323
- ),
324
- },
325
- )
351
+ logger.console.log(
352
+ "[OnrampProviderConfirmation] Deposit detected after commit/execute",
353
+ {
354
+ intentId: quote?.intentId,
355
+ transactionHash: lastTransactionHash,
356
+ amount: depositBalanceFormatted,
357
+ isDirectDeposit,
358
+ },
359
+ )
326
360
 
327
- // Only call send once we have a deposit transaction hash (for intent-based flows)
328
- if (
329
- sendFn &&
330
- (quote?.intentId || isDirectDeposit) &&
331
- lastTransactionHash &&
332
- hasSufficientDeposit &&
333
- !hasExecutedWithDeposit
334
- ) {
335
- logger.console.log(
336
- "[OnrampProviderConfirmation] Calling sendFn with deposit transaction hash",
337
- {
338
- intentId: quote.intentId,
339
- depositTransactionHash: lastTransactionHash,
340
- hasQuote: !!quote,
341
- hasSendFn: !!sendFn,
342
- originDepositAddress: quote.originDepositAddress,
343
- },
344
- )
345
-
346
- setHasExecutedWithDeposit(true) // Prevent multiple calls
347
-
348
- try {
349
- // Call send with the deposit transaction hash
350
- // This will skip the wallet deposit and use the provided hash
351
- await sendFn({
352
- depositTransactionHash: lastTransactionHash,
353
- skipCommit: true,
354
- onOriginSend: () => {
355
- logger.console.log(
356
- "[OnrampProviderConfirmation] Origin send callback triggered",
357
- )
358
- // Navigate to pending screen when intent is executed
359
- if (onIntentExecuted) {
360
- onIntentExecuted()
361
- }
362
- },
363
- })
364
-
365
- logger.console.log(
366
- "[OnrampProviderConfirmation] Successfully called sendFn with deposit hash",
367
- )
368
- } catch (error) {
369
- logger.console.error(
370
- "[OnrampProviderConfirmation] Error calling sendFn:",
371
- error,
372
- )
373
- // Don't reset hasSentTransaction on error to prevent infinite retries
374
- }
375
- }
376
- }
361
+ setHasExecutedWithDeposit(true)
377
362
 
378
- handleDepositDetected()
363
+ if (onIntentExecuted) {
364
+ onIntentExecuted()
365
+ }
379
366
  }, [
380
367
  quote,
381
- sendFn,
382
368
  hasExecutedWithDeposit,
383
369
  lastTransactionHash,
384
370
  hasSufficientDeposit,
@@ -956,12 +942,7 @@ export const OnrampProviderConfirmation: React.FC<
956
942
  <div className="flex items-center relative">
957
943
  <button
958
944
  type="button"
959
- onClick={() => {
960
- if (quote?.intentId) {
961
- removeStoredIntent(quote.intentId)
962
- }
963
- onBack?.()
964
- }}
945
+ onClick={onBack}
965
946
  className="absolute left-0 top-0 p-2 rounded-full transition-colors cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800 hover:trails-hover-bg text-gray-600 dark:text-gray-400"
966
947
  >
967
948
  <ChevronLeft className="h-6 w-6" />
@@ -1,7 +1,7 @@
1
1
  import type React from "react"
2
2
  import { TokenImage } from "./TokenImage.js"
3
3
  import type { PrepareSendQuote } from "../../prepareSend.js"
4
- import { timeAgo } from "../../utils/time.js"
4
+ import { formatDuration, timeAgo } from "../../utils/time.js"
5
5
 
6
6
  interface OriginTransferInformationProps {
7
7
  quote: PrepareSendQuote
@@ -37,7 +37,7 @@ export const OriginTransferInformation: React.FC<
37
37
  className="ml-1 font-mono animate-pulse text-gray-500 dark:text-gray-400"
38
38
  title="Elapsed time"
39
39
  >
40
- {elapsedSeconds}s
40
+ {formatDuration(elapsedSeconds)}
41
41
  </span>
42
42
  </span>
43
43
  </div>