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,6 +1,6 @@
1
1
  import { ChevronDown, ExternalLink } from "lucide-react"
2
2
  import type React from "react"
3
- import { useCallback, useRef } from "react"
3
+ import { useCallback, useRef, useState } from "react"
4
4
  import { formatUnits, getAddress } from "viem"
5
5
  import { getExplorerUrlForAddress } from "../../explorer.js"
6
6
  import { logger } from "../../logger.js"
@@ -13,7 +13,6 @@ import { QrCode } from "./QrCode.js"
13
13
  import { QuoteDetails } from "./QuoteDetails.js"
14
14
  import { ScreenHeader } from "./ScreenHeader.js"
15
15
  import TokenImage from "./TokenImage.js"
16
- import { removeStoredIntent } from "../../intentStorage.js"
17
16
 
18
17
  interface DirectTransferProps {
19
18
  onBack?: () => void
@@ -22,16 +21,6 @@ interface DirectTransferProps {
22
21
  use681QrCode?: boolean
23
22
  selectedWalletId?: string | null
24
23
  walletOptions?: QRCodeWalletOption[]
25
- sendFn?:
26
- | ((options?: {
27
- selectedFeeOption?: any | null
28
- onOriginSend?: () => void
29
- depositTransactionHash?: string
30
- skipCommit?: boolean
31
- commitOnly?: boolean
32
- skipIntentMonitoring?: boolean
33
- }) => Promise<any>)
34
- | null
35
24
  onIntentExecuted?: () => void
36
25
  }
37
26
 
@@ -42,12 +31,12 @@ export const DirectTransfer: React.FC<DirectTransferProps> = ({
42
31
  use681QrCode,
43
32
  selectedWalletId,
44
33
  walletOptions,
45
- sendFn,
46
34
  onIntentExecuted,
47
35
  }) => {
48
36
  const defaultQrCodeWallets = useQRCodeWallets()
49
37
  const defaultWalletOptions = walletOptions || defaultQrCodeWallets
50
38
  const hasTriggeredExecuteRef = useRef(false)
39
+ const [isAmountCopied, setIsAmountCopied] = useState(false)
51
40
  const selectedWalletOption =
52
41
  defaultWalletOptions.find((option) => option.id === selectedWalletId) ??
53
42
  defaultWalletOptions[0]
@@ -75,66 +64,58 @@ export const DirectTransfer: React.FC<DirectTransferProps> = ({
75
64
  const qrCodeUrl = shouldUseEip681 ? eip681Url : eip631Url
76
65
 
77
66
  const walletIcon = selectedWalletOption?.icon
67
+ const formattedOriginAmount = quote
68
+ ? formatUnits(BigInt(quote.originAmount), quote.originToken.decimals)
69
+ : ""
70
+ const originTokenExplorerUrl =
71
+ quote && tokenAddress
72
+ ? getExplorerUrlForAddress({
73
+ address: tokenAddress,
74
+ chainId: quote.originChain.id,
75
+ })
76
+ : ""
78
77
 
79
- const handleDepositComplete = useCallback(
80
- async (lastTransactionHash: string | null) => {
81
- logger.console.log("[DirectTransfer] handleDepositComplete called", {
82
- lastTransactionHash,
83
- })
84
- if (
85
- !sendFn ||
86
- !quote?.intentId ||
87
- hasTriggeredExecuteRef.current ||
88
- !lastTransactionHash
89
- ) {
90
- return
91
- }
78
+ const handleDepositComplete = useCallback(async () => {
79
+ logger.console.log("[DirectTransfer] handleDepositComplete called")
80
+ if (!quote?.intentId || hasTriggeredExecuteRef.current) {
81
+ return
82
+ }
92
83
 
93
- hasTriggeredExecuteRef.current = true
94
- let didNavigateToPending = false
84
+ hasTriggeredExecuteRef.current = true
95
85
 
96
- try {
97
- logger.console.log(
98
- "[DirectTransfer] Deposit complete, executing intent with skipCommit",
99
- {
100
- intentId: quote.intentId,
101
- originDepositAddress: quote.originDepositAddress,
102
- },
103
- )
86
+ try {
87
+ logger.console.log(
88
+ "[DirectTransfer] Deposit complete after commit/execute",
89
+ {
90
+ intentId: quote.intentId,
91
+ originDepositAddress: quote.originDepositAddress,
92
+ },
93
+ )
94
+ onIntentExecuted?.()
95
+ } catch (error) {
96
+ hasTriggeredExecuteRef.current = false
97
+ logger.console.error(
98
+ "[DirectTransfer] Failed to advance after deposit completion:",
99
+ error,
100
+ )
101
+ }
102
+ }, [quote, onIntentExecuted])
104
103
 
105
- await sendFn({
106
- skipCommit: true,
107
- depositTransactionHash: lastTransactionHash,
108
- onOriginSend: () => {
109
- if (didNavigateToPending) return
110
- didNavigateToPending = true
111
- onIntentExecuted?.()
112
- },
113
- })
114
-
115
- if (!didNavigateToPending) {
116
- onIntentExecuted?.()
117
- }
118
- } catch (error) {
119
- hasTriggeredExecuteRef.current = false
120
- logger.console.error(
121
- "[DirectTransfer] Failed to execute intent after deposit completion:",
122
- error,
123
- )
124
- }
125
- },
126
- [sendFn, quote, onIntentExecuted],
127
- )
104
+ const handleCopyAmount = useCallback(async () => {
105
+ if (!quote) return
106
+ try {
107
+ await navigator.clipboard.writeText(formattedOriginAmount)
108
+ setIsAmountCopied(true)
109
+ setTimeout(() => setIsAmountCopied(false), 2000)
110
+ } catch (error) {
111
+ logger.console.error("[DirectTransfer] Failed to copy amount:", error)
112
+ }
113
+ }, [quote, formattedOriginAmount])
128
114
 
129
115
  return (
130
116
  <div className="flex flex-col min-h-full">
131
117
  <ScreenHeader
132
- onBack={() => {
133
- if (quote?.intentId) {
134
- removeStoredIntent(quote.intentId)
135
- }
136
- onBack?.()
137
- }}
118
+ onBack={onBack}
138
119
  headerContent="Deposit"
139
120
  headerContentAlign="left"
140
121
  rightSideContent={
@@ -146,15 +127,26 @@ export const DirectTransfer: React.FC<DirectTransferProps> = ({
146
127
  size={30}
147
128
  />
148
129
  <div className="flex flex-col items-start">
149
- <span className="text-xs font-bold text-gray-900 dark:text-white">
150
- {parseFloat(
151
- formatUnits(
152
- BigInt(quote?.originAmount ?? 0),
153
- quote?.originToken.decimals ?? 0,
154
- ),
155
- ).toLocaleString(undefined, { maximumFractionDigits: 4 })}{" "}
156
- {quote?.originToken.symbol}
157
- </span>
130
+ <div className="flex items-center gap-1">
131
+ <span className="text-xs font-bold text-gray-900 dark:text-white">
132
+ {parseFloat(
133
+ formatUnits(
134
+ BigInt(quote?.originAmount ?? 0),
135
+ quote?.originToken.decimals ?? 0,
136
+ ),
137
+ ).toLocaleString(undefined, {
138
+ maximumFractionDigits: 4,
139
+ })}{" "}
140
+ <a
141
+ href={originTokenExplorerUrl}
142
+ target="_blank"
143
+ rel="noopener noreferrer"
144
+ className="inline-flex items-center gap-0.5 underline decoration-dotted underline-offset-2 hover:opacity-80 transition-opacity"
145
+ >
146
+ {quote?.originToken.symbol}
147
+ </a>
148
+ </span>
149
+ </div>
158
150
  <a
159
151
  href={getExplorerUrlForAddress({
160
152
  address: quote?.originDepositAddress ?? "",
@@ -211,7 +203,7 @@ export const DirectTransfer: React.FC<DirectTransferProps> = ({
211
203
  <div className="flex justify-center">
212
204
  <div className="flex flex-col items-start">
213
205
  <span className="text-sm font-medium text-black dark:text-white mb-2">
214
- Copy address
206
+ Copy the one-time deposit address
215
207
  </span>
216
208
  <div className="flex items-center">
217
209
  <CopyButton
@@ -255,16 +247,27 @@ export const DirectTransfer: React.FC<DirectTransferProps> = ({
255
247
  </div>
256
248
  <div className="flex flex-col">
257
249
  <span className="text-sm font-bold" style={{ color: "#FF6900" }}>
258
- Deposit exactly{" "}
259
- {formatUnits(
260
- BigInt(quote.originAmount),
261
- quote.originToken.decimals,
262
- )}{" "}
250
+ Deposit exactly
251
+ <button
252
+ type="button"
253
+ className={`cursor-pointer underline inline-flex items-center rounded px-1 transition-colors ${
254
+ isAmountCopied
255
+ ? "bg-green-100 dark:bg-green-900/30"
256
+ : "hover:bg-orange-100/60 dark:hover:bg-orange-900/20"
257
+ }`}
258
+ onClick={handleCopyAmount}
259
+ >
260
+ {formatUnits(
261
+ BigInt(quote.originAmount),
262
+ quote.originToken.decimals,
263
+ )}{" "}
264
+ </button>
263
265
  {quote.originToken.symbol} on {quote.originChain.name}
264
266
  </span>
265
267
  <span className="text-xs text-black dark:text-white mt-1">
266
268
  Deposited funds in excess of the requested amount cannot be
267
- refunded.
269
+ refunded. Do not use the same deposit address for other
270
+ deposits.
268
271
  </span>
269
272
  </div>
270
273
  </div>
@@ -280,9 +283,7 @@ export const DirectTransfer: React.FC<DirectTransferProps> = ({
280
283
  tokenSymbol={quote.originToken.symbol}
281
284
  tokenDecimals={quote.originToken.decimals}
282
285
  chainId={quote.originChain.id}
283
- onDepositComplete={(lastTransactionHash) => {
284
- handleDepositComplete(lastTransactionHash)
285
- }}
286
+ onDepositComplete={handleDepositComplete}
286
287
  />
287
288
  </div>
288
289
  )}
@@ -6,7 +6,7 @@ import type { PrepareSendQuote } from "../../prepareSend.js"
6
6
  import type { Token } from "../../tokens.js"
7
7
  import type { FundMethod } from "../../transactionIntent/types.js"
8
8
  import type { TransactionState } from "../../transactions.js"
9
- import { useBack } from "../hooks/useBack.js"
9
+ import { useViewManager } from "../hooks/useViewManager.js"
10
10
  import type { CheckoutOnHandlers } from "../hooks/useCheckout.js"
11
11
  import type { OnCompleteProps } from "../hooks/useSendForm.js"
12
12
  import { useSwapState } from "../hooks/useSwapState.js"
@@ -62,7 +62,7 @@ export const Earn: React.FC<EarnProps> = ({
62
62
  }) => {
63
63
  const [activeTab, setActiveTab] = useState<"deposit" | "withdraw">("deposit")
64
64
  const [isShowingPoolSelector, setIsShowingPoolSelector] = useState(false) // Track if pool selector is shown
65
- const { setCurrentScreenWithBack } = useBack()
65
+ const { navigate } = useViewManager()
66
66
  const { enterFormMode } = useSwapState()
67
67
 
68
68
  // Register form mode so switching from Earn to other modes resets the swap state
@@ -81,7 +81,7 @@ export const Earn: React.FC<EarnProps> = ({
81
81
  customActions={
82
82
  <button
83
83
  type="button"
84
- onClick={() => setCurrentScreenWithBack("swap", "earn")}
84
+ onClick={() => navigate("swap", { backTarget: "earn" })}
85
85
  className="flex h-8 px-3 justify-center items-center gap-1.5 rounded-full bg-gray-50 dark:bg-gray-700 cursor-pointer transition-colors text-gray-900 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-600"
86
86
  title="Swap"
87
87
  >
@@ -17,16 +17,14 @@ import { useSupportedTokens, type Token } from "../../tokens.js"
17
17
  import type { FundMethod } from "../../transactionIntent/types.js"
18
18
  import { isPassthroughEligible } from "../../utils/passthrough.js"
19
19
  import { useWidgetProps } from "../hooks/useWidgetProps.js"
20
- import { useBack } from "../hooks/useBack.js"
21
- import type { Screen } from "../hooks/useCurrentScreen.js"
22
- import { useCurrentScreen } from "../hooks/useCurrentScreen.js"
20
+ import type { Screen } from "../hooks/useViewManager.js"
21
+ import { useViewManager } from "../hooks/useViewManager.js"
23
22
  import { useDefaultDestinationToken } from "../hooks/useDefaultDestinationToken.js"
24
23
  import { useDefaultOriginToken } from "../hooks/useDefaultOriginToken.js"
25
24
  import { useDestinationSelectedToken } from "../hooks/useDestinationSelectedToken.js"
26
25
  import { useExchangeRate } from "../../query/fiat.hooks.js"
27
26
  import { useFiatOnRampCurrencies } from "../hooks/useFiatOnRampCurrencies.js"
28
27
  import { useFiatSelectedCurrency } from "../hooks/useFiatSelectedCurrency.js"
29
- import { useMode } from "../hooks/useMode.js"
30
28
  import { useOnRampCountryDefaults } from "../hooks/useOnRampCountryDefaults.js"
31
29
  import { useOnRampProviderWidget } from "../hooks/useOnRampProviderWidget.js"
32
30
  import type { OnrampQuote } from "../hooks/useOnRampQuote.js"
@@ -103,10 +101,8 @@ const Fund: React.FC<FundProps> = ({
103
101
  exactInputOnly = true, // Fund mode is always exact input only
104
102
  defaultInputMode,
105
103
  }) => {
106
- const { mode } = useMode()
104
+ const { mode, navigate } = useViewManager()
107
105
  const { fundOptions } = useWidgetProps()
108
- const { setCurrentScreen } = useCurrentScreen()
109
- const { setCurrentScreenWithBack } = useBack()
110
106
  const {
111
107
  selectedToken: originToken,
112
108
  setSelectedToken: setOriginToken,
@@ -242,6 +238,59 @@ const Fund: React.FC<FundProps> = ({
242
238
  setSelectedFiatCurrency,
243
239
  ])
244
240
 
241
+ const lastAppliedConfiguredFiatRef = useRef<string | null>(null)
242
+ useEffect(() => {
243
+ if (!isMeldOnRampActive) {
244
+ lastAppliedConfiguredFiatRef.current = null
245
+ }
246
+ }, [isMeldOnRampActive])
247
+
248
+ useEffect(() => {
249
+ if (!isMeldOnRampActive || isLoadingFiatCurrencies) return
250
+ if (fiatCurrencies.length === 0) return
251
+ const configuredFiatCurrency = fundOptions?.fiatCurrency?.trim() || ""
252
+ const configuredFiatAmount = fundOptions?.fiatAmount?.trim() || ""
253
+ const configKey = `${configuredFiatCurrency.toUpperCase()}|${configuredFiatAmount}`
254
+ if (lastAppliedConfiguredFiatRef.current === configKey) return
255
+ lastAppliedConfiguredFiatRef.current = configKey
256
+
257
+ if (configuredFiatCurrency) {
258
+ const match = fiatCurrencies.find(
259
+ (c) =>
260
+ c.currencyCode.toUpperCase() === configuredFiatCurrency.toUpperCase(),
261
+ )
262
+ if (match) {
263
+ setSelectedFiatCurrency(match)
264
+ setHasManualFiatSelection(true)
265
+ }
266
+ }
267
+
268
+ if (configuredFiatAmount) {
269
+ setSellFiatAmount(configuredFiatAmount)
270
+ setInputDisplayValue(configuredFiatAmount)
271
+ }
272
+ }, [
273
+ isMeldOnRampActive,
274
+ isLoadingFiatCurrencies,
275
+ fiatCurrencies,
276
+ fundOptions?.fiatCurrency,
277
+ fundOptions?.fiatAmount,
278
+ setSelectedFiatCurrency,
279
+ setHasManualFiatSelection,
280
+ setSellFiatAmount,
281
+ ])
282
+
283
+ const normalizedConfiguredFiatCurrency =
284
+ fundOptions?.fiatCurrency?.trim().toUpperCase() || null
285
+ const isConfiguredFiatCurrencyApplied =
286
+ !!normalizedConfiguredFiatCurrency &&
287
+ !!selectedFiatCurrency &&
288
+ selectedFiatCurrency.currencyCode.toUpperCase() ===
289
+ normalizedConfiguredFiatCurrency
290
+ const isFiatCurrencyLocked =
291
+ isMeldOnRampActive && isConfiguredFiatCurrencyApplied
292
+ const isFiatAmountLocked = isMeldOnRampActive && !!fundOptions?.fiatAmount
293
+
245
294
  // Use a ref to track user actions to prevent race conditions with async state updates
246
295
  const userActionRef = useRef({
247
296
  hasManualDestinationSelection: false,
@@ -444,6 +493,9 @@ const Fund: React.FC<FundProps> = ({
444
493
  const selectedOnrampProviderQuote =
445
494
  selectedOnrampProvider || autoSelectedOnrampQuote
446
495
 
496
+ const shouldValidateFeeOption =
497
+ fundMethod !== "direct-transfer" && fundMethod !== "onramp-mesh"
498
+
447
499
  const isAwaitingTrailsQuote =
448
500
  isMeldOnRampActive && !!selectedOnrampProviderQuote && !prepareSendQuote
449
501
 
@@ -1205,7 +1257,7 @@ const Fund: React.FC<FundProps> = ({
1205
1257
  return (
1206
1258
  <div className="space-y-2">
1207
1259
  <ScreenHeader
1208
- onBack={() => setCurrentScreen("fund-methods")}
1260
+ onBack={() => navigate("fund-methods")}
1209
1261
  headerContent="Fund"
1210
1262
  headerContentAlign="left"
1211
1263
  showAccountActions={true}
@@ -1213,7 +1265,7 @@ const Fund: React.FC<FundProps> = ({
1213
1265
  fundOptions?.hideSwap ? undefined : (
1214
1266
  <button
1215
1267
  type="button"
1216
- onClick={() => setCurrentScreenWithBack("swap", "fund-form")}
1268
+ onClick={() => navigate("swap", { backTarget: "fund-form" })}
1217
1269
  className="flex h-8 px-3 justify-center items-center gap-1.5 rounded-full bg-gray-50 dark:bg-gray-700 cursor-pointer transition-colors text-gray-900 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-600"
1218
1270
  title="Swap"
1219
1271
  >
@@ -1361,7 +1413,6 @@ const Fund: React.FC<FundProps> = ({
1361
1413
  selectedOnrampProviderQuote.paymentMethodType,
1362
1414
  },
1363
1415
  externalSessionId,
1364
- sendFn, // Pass sendFn so it can be used in OnrampProviderConfirmation
1365
1416
  popup,
1366
1417
  )
1367
1418
  }
@@ -1395,6 +1446,7 @@ const Fund: React.FC<FundProps> = ({
1395
1446
  <DynamicSizeInputField
1396
1447
  ref={inputRef}
1397
1448
  value={inputDisplayValue}
1449
+ disabled={isFiatAmountLocked}
1398
1450
  onChange={(e) => {
1399
1451
  const value = e.target.value
1400
1452
 
@@ -1544,6 +1596,7 @@ const Fund: React.FC<FundProps> = ({
1544
1596
  <div className="flex justify-center">
1545
1597
  <button
1546
1598
  type="button"
1599
+ disabled={isFiatAmountLocked}
1547
1600
  onClick={() => {
1548
1601
  // When toggling USD mode, convert the current display value
1549
1602
  const newMode = !isEnteringFiat
@@ -1571,7 +1624,11 @@ const Fund: React.FC<FundProps> = ({
1571
1624
  }
1572
1625
  }
1573
1626
  }}
1574
- className="text-xs text-blue-500 hover:text-blue-600 transition-colors cursor-pointer flex items-center gap-1"
1627
+ className={`text-xs transition-colors flex items-center gap-1 ${
1628
+ isFiatAmountLocked
1629
+ ? "text-gray-400 cursor-not-allowed"
1630
+ : "text-blue-500 hover:text-blue-600 cursor-pointer"
1631
+ }`}
1575
1632
  title={
1576
1633
  selectedFiatCurrency
1577
1634
  ? `${selectedFiatCurrency.currencyCode}`
@@ -1849,7 +1906,12 @@ const Fund: React.FC<FundProps> = ({
1849
1906
  <div className="mt-3 flex justify-center items-center space-x-2">
1850
1907
  <button
1851
1908
  type="button"
1852
- className="py-0.5 px-1.5 text-xs font-medium rounded-full transition-colors cursor-pointer trails-bg-percentage-button trails-text-percentage-button trails-hover-percentage-button"
1909
+ disabled={isFiatAmountLocked}
1910
+ className={`py-0.5 px-1.5 text-xs font-medium rounded-full transition-colors trails-bg-percentage-button trails-text-percentage-button ${
1911
+ isFiatAmountLocked
1912
+ ? "opacity-50 cursor-not-allowed"
1913
+ : "cursor-pointer trails-hover-percentage-button"
1914
+ }`}
1853
1915
  onClick={() => {
1854
1916
  if (selectedFiatCurrency?.currencyCode === "USD") {
1855
1917
  setSellFiatAmount("25")
@@ -1872,7 +1934,12 @@ const Fund: React.FC<FundProps> = ({
1872
1934
  </button>
1873
1935
  <button
1874
1936
  type="button"
1875
- className="py-0.5 px-1.5 text-xs font-medium rounded-full transition-colors cursor-pointer trails-bg-percentage-button trails-text-percentage-button trails-hover-percentage-button"
1937
+ disabled={isFiatAmountLocked}
1938
+ className={`py-0.5 px-1.5 text-xs font-medium rounded-full transition-colors trails-bg-percentage-button trails-text-percentage-button ${
1939
+ isFiatAmountLocked
1940
+ ? "opacity-50 cursor-not-allowed"
1941
+ : "cursor-pointer trails-hover-percentage-button"
1942
+ }`}
1876
1943
  onClick={() => {
1877
1944
  if (selectedFiatCurrency?.currencyCode === "USD") {
1878
1945
  setSellFiatAmount("50")
@@ -1895,7 +1962,12 @@ const Fund: React.FC<FundProps> = ({
1895
1962
  </button>
1896
1963
  <button
1897
1964
  type="button"
1898
- className="py-0.5 px-1.5 text-xs font-medium rounded-full transition-colors cursor-pointer trails-bg-percentage-button trails-text-percentage-button trails-hover-percentage-button"
1965
+ disabled={isFiatAmountLocked}
1966
+ className={`py-0.5 px-1.5 text-xs font-medium rounded-full transition-colors trails-bg-percentage-button trails-text-percentage-button ${
1967
+ isFiatAmountLocked
1968
+ ? "opacity-50 cursor-not-allowed"
1969
+ : "cursor-pointer trails-hover-percentage-button"
1970
+ }`}
1899
1971
  onClick={() => {
1900
1972
  if (selectedFiatCurrency?.currencyCode === "USD") {
1901
1973
  setSellFiatAmount("100")
@@ -2022,7 +2094,7 @@ const Fund: React.FC<FundProps> = ({
2022
2094
  Receiving
2023
2095
  </span>
2024
2096
  ) : (
2025
- <RecipientSelectorButton />
2097
+ <RecipientSelectorButton selectedRecipient={selectedRecipient} />
2026
2098
  )}
2027
2099
  </div>
2028
2100
 
@@ -2034,6 +2106,7 @@ const Fund: React.FC<FundProps> = ({
2034
2106
  <FiatSelectorButton
2035
2107
  currency={selectedFiatCurrency}
2036
2108
  onSelect={() => setShowFiatSelector(true)}
2109
+ unselectable={isFiatCurrencyLocked}
2037
2110
  />
2038
2111
  ) : prepareSendQuote?.noSufficientBalance ? (
2039
2112
  // Show "Add funds" button when user has insufficient balance
@@ -2041,7 +2114,7 @@ const Fund: React.FC<FundProps> = ({
2041
2114
  type="button"
2042
2115
  onClick={() => {
2043
2116
  // Navigate to payment selection screen
2044
- setCurrentScreen("fund-methods")
2117
+ navigate("fund-methods")
2045
2118
  }}
2046
2119
  className="w-full flex items-center justify-center space-x-1.5 trails-border-radius-input px-2.5 py-1.5 border transition-all duration-200 bg-blue-500 hover:bg-blue-600 border-blue-500 text-white cursor-pointer"
2047
2120
  >
@@ -2261,7 +2334,7 @@ const Fund: React.FC<FundProps> = ({
2261
2334
  (!isMeldOnRampActive &&
2262
2335
  fundMethod !== "direct-transfer" &&
2263
2336
  prepareSendQuote?.noSufficientBalance) ||
2264
- (fundMethod !== "direct-transfer" &&
2337
+ (shouldValidateFeeOption &&
2265
2338
  (selectedFeeOption
2266
2339
  ? isFeeOptionDisabled(
2267
2340
  selectedFeeOption as ProcessedFeeOption,