0xtrails 0.1.13 → 0.2.1

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 (256) hide show
  1. package/dist/aave.d.ts.map +1 -1
  2. package/dist/analytics.d.ts +12 -2
  3. package/dist/analytics.d.ts.map +1 -1
  4. package/dist/apiClient.d.ts +1 -1
  5. package/dist/apiClient.d.ts.map +1 -1
  6. package/dist/{ccip-D3gTQONK.js → ccip-BbfANth7.js} +12 -12
  7. package/dist/cctp.d.ts.map +1 -1
  8. package/dist/cctpqueue.d.ts +3 -3
  9. package/dist/cctpqueue.d.ts.map +1 -1
  10. package/dist/chains.d.ts.map +1 -1
  11. package/dist/config.d.ts +18 -5
  12. package/dist/config.d.ts.map +1 -1
  13. package/dist/constants.d.ts +6 -5
  14. package/dist/constants.d.ts.map +1 -1
  15. package/dist/contractUtils.d.ts +2 -0
  16. package/dist/contractUtils.d.ts.map +1 -1
  17. package/dist/customChains.d.ts +24 -0
  18. package/dist/customChains.d.ts.map +1 -0
  19. package/dist/gasless.d.ts +19 -7
  20. package/dist/gasless.d.ts.map +1 -1
  21. package/dist/{index-CnUM7lKf.js → index-WpIVoh3X.js} +36741 -31761
  22. package/dist/index.d.ts +5 -3
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +405 -394
  25. package/dist/indexerClient.d.ts +10 -0
  26. package/dist/indexerClient.d.ts.map +1 -1
  27. package/dist/intentEntrypoint.d.ts +122 -0
  28. package/dist/intentEntrypoint.d.ts.map +1 -0
  29. package/dist/intents.d.ts +5 -3
  30. package/dist/intents.d.ts.map +1 -1
  31. package/dist/metaTxnMonitor.d.ts.map +1 -1
  32. package/dist/morpho.d.ts.map +1 -1
  33. package/dist/pools.d.ts +3 -1
  34. package/dist/pools.d.ts.map +1 -1
  35. package/dist/prepareSend.d.ts +18 -9
  36. package/dist/prepareSend.d.ts.map +1 -1
  37. package/dist/prices.d.ts +1 -1
  38. package/dist/prices.d.ts.map +1 -1
  39. package/dist/relaySdk.d.ts.map +1 -1
  40. package/dist/relayer.d.ts.map +1 -1
  41. package/dist/toast.d.ts +9 -0
  42. package/dist/toast.d.ts.map +1 -0
  43. package/dist/tokenBalances.d.ts +6 -2
  44. package/dist/tokenBalances.d.ts.map +1 -1
  45. package/dist/tokens.d.ts.map +1 -1
  46. package/dist/trails.d.ts +6 -5
  47. package/dist/trails.d.ts.map +1 -1
  48. package/dist/trailsClient.d.ts +12 -0
  49. package/dist/trailsClient.d.ts.map +1 -0
  50. package/dist/trailsRouter.d.ts +22 -0
  51. package/dist/trailsRouter.d.ts.map +1 -0
  52. package/dist/transactions.d.ts +8 -1
  53. package/dist/transactions.d.ts.map +1 -1
  54. package/dist/wallets.d.ts.map +1 -1
  55. package/dist/widget/components/AccountActionsDropdown.d.ts.map +1 -1
  56. package/dist/widget/components/AccountIntentTransactionHistory.d.ts.map +1 -1
  57. package/dist/widget/components/AccountSettings.d.ts +7 -0
  58. package/dist/widget/components/AccountSettings.d.ts.map +1 -0
  59. package/dist/widget/components/ChainList.d.ts +0 -1
  60. package/dist/widget/components/ChainList.d.ts.map +1 -1
  61. package/dist/widget/components/ClassicSwap.d.ts +46 -0
  62. package/dist/widget/components/ClassicSwap.d.ts.map +1 -0
  63. package/dist/widget/components/ConfigDisplay.d.ts.map +1 -1
  64. package/dist/widget/components/ConnectWallet.d.ts.map +1 -1
  65. package/dist/widget/components/ConnectedWallets.d.ts +9 -0
  66. package/dist/widget/components/ConnectedWallets.d.ts.map +1 -0
  67. package/dist/widget/components/DebugMenu.d.ts.map +1 -1
  68. package/dist/widget/components/DebugScreensList.d.ts.map +1 -1
  69. package/dist/widget/components/DebugToast.d.ts +3 -0
  70. package/dist/widget/components/DebugToast.d.ts.map +1 -0
  71. package/dist/widget/components/Earn.d.ts.map +1 -1
  72. package/dist/widget/components/EarnPools.d.ts.map +1 -1
  73. package/dist/widget/components/FeeOption.d.ts +22 -0
  74. package/dist/widget/components/FeeOption.d.ts.map +1 -0
  75. package/dist/widget/components/FeeOptions.d.ts +13 -17
  76. package/dist/widget/components/FeeOptions.d.ts.map +1 -1
  77. package/dist/widget/components/Fund.d.ts +44 -0
  78. package/dist/widget/components/Fund.d.ts.map +1 -0
  79. package/dist/widget/components/FundMethods.d.ts +1 -1
  80. package/dist/widget/components/FundMethods.d.ts.map +1 -1
  81. package/dist/widget/components/FundSendForm.d.ts.map +1 -1
  82. package/dist/widget/components/Identicon.d.ts +9 -0
  83. package/dist/widget/components/Identicon.d.ts.map +1 -0
  84. package/dist/widget/components/MeshConnectExchanges.d.ts +5 -2
  85. package/dist/widget/components/MeshConnectExchanges.d.ts.map +1 -1
  86. package/dist/widget/components/MeshConnectFlow.d.ts +2 -0
  87. package/dist/widget/components/MeshConnectFlow.d.ts.map +1 -1
  88. package/dist/widget/components/NativeGasOption.d.ts +12 -0
  89. package/dist/widget/components/NativeGasOption.d.ts.map +1 -0
  90. package/dist/widget/components/Pay.d.ts +46 -0
  91. package/dist/widget/components/Pay.d.ts.map +1 -0
  92. package/dist/widget/components/PaySendForm.d.ts.map +1 -1
  93. package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
  94. package/dist/widget/components/Receive.d.ts.map +1 -1
  95. package/dist/widget/components/RecentTokens.d.ts.map +1 -1
  96. package/dist/widget/components/Recipients.d.ts +9 -0
  97. package/dist/widget/components/Recipients.d.ts.map +1 -0
  98. package/dist/widget/components/RefundWarning.d.ts +9 -0
  99. package/dist/widget/components/RefundWarning.d.ts.map +1 -0
  100. package/dist/widget/components/SimpleSwap.d.ts.map +1 -1
  101. package/dist/widget/components/Swap.d.ts.map +1 -1
  102. package/dist/widget/components/SwapSettings.d.ts +1 -5
  103. package/dist/widget/components/SwapSettings.d.ts.map +1 -1
  104. package/dist/widget/components/ThemeProvider.d.ts.map +1 -1
  105. package/dist/widget/components/ThemeSyncer.d.ts +6 -0
  106. package/dist/widget/components/ThemeSyncer.d.ts.map +1 -0
  107. package/dist/widget/components/Toast.d.ts +24 -0
  108. package/dist/widget/components/Toast.d.ts.map +1 -0
  109. package/dist/widget/components/TokenList.d.ts.map +1 -1
  110. package/dist/widget/components/TokenSelector.d.ts.map +1 -1
  111. package/dist/widget/components/TransactionDetails.d.ts.map +1 -1
  112. package/dist/widget/components/TruncatedAddress.d.ts +2 -0
  113. package/dist/widget/components/TruncatedAddress.d.ts.map +1 -1
  114. package/dist/widget/components/UserPreferences.d.ts +7 -0
  115. package/dist/widget/components/UserPreferences.d.ts.map +1 -0
  116. package/dist/widget/hooks/useBack.d.ts +2 -0
  117. package/dist/widget/hooks/useBack.d.ts.map +1 -1
  118. package/dist/widget/hooks/useBalanceVisible.d.ts +1 -0
  119. package/dist/widget/hooks/useBalanceVisible.d.ts.map +1 -1
  120. package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
  121. package/dist/widget/hooks/useCurrentScreen.d.ts +1 -1
  122. package/dist/widget/hooks/useCurrentScreen.d.ts.map +1 -1
  123. package/dist/widget/hooks/useDebugScreens.d.ts +1 -1
  124. package/dist/widget/hooks/useDebugScreens.d.ts.map +1 -1
  125. package/dist/widget/hooks/useDefaultTokenSelection.d.ts +54 -0
  126. package/dist/widget/hooks/useDefaultTokenSelection.d.ts.map +1 -0
  127. package/dist/widget/hooks/useIntentTransactionHistory.d.ts.map +1 -1
  128. package/dist/widget/hooks/usePayMessage.d.ts +34 -0
  129. package/dist/widget/hooks/usePayMessage.d.ts.map +1 -0
  130. package/dist/widget/hooks/useRecipients.d.ts +17 -0
  131. package/dist/widget/hooks/useRecipients.d.ts.map +1 -0
  132. package/dist/widget/hooks/useSelectedFeeToken.d.ts +32 -0
  133. package/dist/widget/hooks/useSelectedFeeToken.d.ts.map +1 -0
  134. package/dist/widget/hooks/useSelectedMeshExchange.d.ts +14 -0
  135. package/dist/widget/hooks/useSelectedMeshExchange.d.ts.map +1 -0
  136. package/dist/widget/hooks/useSelectedRecipient.d.ts +12 -0
  137. package/dist/widget/hooks/useSelectedRecipient.d.ts.map +1 -0
  138. package/dist/widget/hooks/useSendForm.d.ts +10 -13
  139. package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
  140. package/dist/widget/hooks/useSwapAmount.d.ts +13 -0
  141. package/dist/widget/hooks/useSwapAmount.d.ts.map +1 -0
  142. package/dist/widget/hooks/useSwapSettings.d.ts +16 -0
  143. package/dist/widget/hooks/useSwapSettings.d.ts.map +1 -0
  144. package/dist/widget/hooks/useTargetAmount.d.ts +5 -0
  145. package/dist/widget/hooks/useTargetAmount.d.ts.map +1 -0
  146. package/dist/widget/hooks/useTheme.d.ts +14 -0
  147. package/dist/widget/hooks/useTheme.d.ts.map +1 -0
  148. package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
  149. package/dist/widget/index.js +2 -2
  150. package/dist/widget/widget.d.ts +9 -0
  151. package/dist/widget/widget.d.ts.map +1 -1
  152. package/package.json +38 -36
  153. package/src/aave.ts +6 -1
  154. package/src/analytics.ts +109 -53
  155. package/src/apiClient.ts +1 -1
  156. package/src/cctp.ts +6 -2
  157. package/src/cctpqueue.ts +7 -7
  158. package/src/chains.ts +18 -0
  159. package/src/config.ts +63 -17
  160. package/src/constants.ts +20 -16
  161. package/src/contractUtils.ts +33 -2
  162. package/src/customChains.ts +24 -0
  163. package/src/gasless.ts +162 -109
  164. package/src/index.ts +11 -1
  165. package/src/indexerClient.ts +73 -1
  166. package/src/intentEntrypoint.ts +218 -0
  167. package/src/intents.ts +85 -54
  168. package/src/metaTxnMonitor.ts +1 -0
  169. package/src/morpho.ts +13 -2
  170. package/src/pools.ts +68 -86
  171. package/src/prepareSend.ts +1719 -967
  172. package/src/prices.ts +51 -7
  173. package/src/relaySdk.ts +6 -4
  174. package/src/relayer.ts +6 -3
  175. package/src/toast.ts +110 -0
  176. package/src/tokenBalances.ts +112 -20
  177. package/src/tokens.ts +70 -7
  178. package/src/trails.ts +81 -80
  179. package/src/trailsClient.ts +48 -0
  180. package/src/{proxyCaller.ts → trailsRouter.ts} +25 -20
  181. package/src/transactions.ts +30 -88
  182. package/src/umd.tsx +1 -1
  183. package/src/wallets.ts +2 -1
  184. package/src/widget/assets/sequence-logo.svg +15 -0
  185. package/src/widget/compiled.css +2 -2
  186. package/src/widget/components/AccountActionsDropdown.tsx +18 -159
  187. package/src/widget/components/AccountIntentTransactionHistory.tsx +346 -63
  188. package/src/widget/components/AccountSettings.tsx +102 -0
  189. package/src/widget/components/ChainFilterDropdown.tsx +1 -1
  190. package/src/widget/components/ChainList.tsx +10 -20
  191. package/src/widget/components/ClassicSwap.tsx +921 -0
  192. package/src/widget/components/ConfigDisplay.tsx +41 -5
  193. package/src/widget/components/ConnectWallet.tsx +168 -11
  194. package/src/widget/components/ConnectedWallets.tsx +342 -0
  195. package/src/widget/components/DebugMenu.tsx +2 -0
  196. package/src/widget/components/DebugScreensList.tsx +3 -0
  197. package/src/widget/components/DebugToast.tsx +63 -0
  198. package/src/widget/components/Earn.tsx +112 -143
  199. package/src/widget/components/EarnPools.tsx +2 -4
  200. package/src/widget/components/EarnPoolsFilters.tsx +6 -6
  201. package/src/widget/components/FeeOption.tsx +78 -0
  202. package/src/widget/components/FeeOptions.tsx +192 -127
  203. package/src/widget/components/Fund.tsx +1236 -0
  204. package/src/widget/components/FundMethods.tsx +4 -4
  205. package/src/widget/components/FundSendForm.tsx +1 -34
  206. package/src/widget/components/Identicon.tsx +158 -0
  207. package/src/widget/components/MeshConnectExchanges.tsx +32 -3
  208. package/src/widget/components/MeshConnectFlow.tsx +23 -4
  209. package/src/widget/components/NativeGasOption.tsx +99 -0
  210. package/src/widget/components/Pay.tsx +1092 -0
  211. package/src/widget/components/PaySendForm.tsx +1 -38
  212. package/src/widget/components/QuoteDetails.tsx +1 -30
  213. package/src/widget/components/Receipt.tsx +1 -1
  214. package/src/widget/components/Receive.tsx +4 -2
  215. package/src/widget/components/RecentTokens.tsx +2 -1
  216. package/src/widget/components/Recipients.tsx +448 -0
  217. package/src/widget/components/RefundWarning.tsx +61 -0
  218. package/src/widget/components/ScreenHeader.tsx +1 -1
  219. package/src/widget/components/SimpleSwap.tsx +74 -58
  220. package/src/widget/components/Swap.tsx +35 -853
  221. package/src/widget/components/SwapSettings.tsx +5 -11
  222. package/src/widget/components/ThemeProvider.tsx +32 -0
  223. package/src/widget/components/ThemeSyncer.tsx +47 -0
  224. package/src/widget/components/Toast.tsx +315 -0
  225. package/src/widget/components/TokenList.tsx +2 -34
  226. package/src/widget/components/TokenSelector.tsx +14 -3
  227. package/src/widget/components/TransactionDetails.tsx +153 -13
  228. package/src/widget/components/TransferPendingVertical.tsx +1 -1
  229. package/src/widget/components/TruncatedAddress.tsx +5 -1
  230. package/src/widget/components/UserPreferences.tsx +155 -0
  231. package/src/widget/components/WalletList.tsx +1 -1
  232. package/src/widget/hooks/useBack.tsx +4 -0
  233. package/src/widget/hooks/useBalanceVisible.tsx +40 -2
  234. package/src/widget/hooks/useCheckout.ts +13 -0
  235. package/src/widget/hooks/useCurrentScreen.tsx +4 -0
  236. package/src/widget/hooks/useDebugScreens.ts +12 -2
  237. package/src/widget/hooks/useDefaultTokenSelection.tsx +471 -0
  238. package/src/widget/hooks/useIntentTransactionHistory.ts +212 -0
  239. package/src/widget/hooks/usePayMessage.tsx +370 -0
  240. package/src/widget/hooks/useRecipients.ts +168 -0
  241. package/src/widget/hooks/useSelectedFeeToken.tsx +299 -0
  242. package/src/widget/hooks/useSelectedMeshExchange.tsx +46 -0
  243. package/src/widget/hooks/useSelectedRecipient.tsx +48 -0
  244. package/src/widget/hooks/useSendForm.ts +257 -49
  245. package/src/widget/hooks/useSwapAmount.tsx +50 -0
  246. package/src/widget/hooks/useSwapSettings.tsx +100 -0
  247. package/src/widget/hooks/useTargetAmount.ts +23 -0
  248. package/src/widget/hooks/useTheme.tsx +80 -0
  249. package/src/widget/hooks/useTokenList.ts +20 -11
  250. package/src/widget/index.css +45 -21
  251. package/src/widget/widget.tsx +294 -136
  252. package/dist/address.d.ts +0 -2
  253. package/dist/address.d.ts.map +0 -1
  254. package/dist/proxyCaller.d.ts +0 -21
  255. package/dist/proxyCaller.d.ts.map +0 -1
  256. package/src/address.ts +0 -6
@@ -0,0 +1,63 @@
1
+ import type React from "react"
2
+ import { useToast } from "./Toast.js"
3
+
4
+ export const DebugToast: React.FC = () => {
5
+ const { showToast } = useToast()
6
+
7
+ const handleShowSuccess = () => {
8
+ showToast(
9
+ "Transaction Complete",
10
+ "Your transaction has been successfully processed",
11
+ "success",
12
+ )
13
+ }
14
+
15
+ const handleShowInfo = () => {
16
+ showToast(
17
+ "Info Toast",
18
+ "This is an info message for testing purposes",
19
+ "info",
20
+ )
21
+ }
22
+
23
+ const handleShowError = () => {
24
+ showToast(
25
+ "Transaction Failed",
26
+ "An error occurred while processing your transaction",
27
+ "error",
28
+ )
29
+ }
30
+
31
+ return (
32
+ <div className="p-3 border-b border-gray-200 dark:border-gray-700">
33
+ <div className="flex items-center gap-2">
34
+ <div className="text-xs font-semibold text-gray-600 dark:text-gray-400">
35
+ Toast
36
+ </div>
37
+ <div className="flex gap-1 flex-1">
38
+ <button
39
+ type="button"
40
+ onClick={handleShowInfo}
41
+ className="px-2 py-1 text-xs font-medium rounded bg-blue-100 text-blue-700 hover:bg-blue-200 dark:bg-blue-900/30 dark:text-blue-400 dark:hover:bg-blue-900/50 transition-colors cursor-pointer"
42
+ >
43
+ info
44
+ </button>
45
+ <button
46
+ type="button"
47
+ onClick={handleShowSuccess}
48
+ className="px-2 py-1 text-xs font-medium rounded bg-green-100 text-green-700 hover:bg-green-200 dark:bg-green-900/30 dark:text-green-400 dark:hover:bg-green-900/50 transition-colors cursor-pointer"
49
+ >
50
+ success
51
+ </button>
52
+ <button
53
+ type="button"
54
+ onClick={handleShowError}
55
+ className="px-2 py-1 text-xs font-medium rounded bg-red-100 text-red-700 hover:bg-red-200 dark:bg-red-900/30 dark:text-red-400 dark:hover:bg-red-900/50 transition-colors cursor-pointer"
56
+ >
57
+ error
58
+ </button>
59
+ </div>
60
+ </div>
61
+ </div>
62
+ )
63
+ }
@@ -6,7 +6,7 @@ import {
6
6
  ChevronDown,
7
7
  Loader2,
8
8
  } from "lucide-react"
9
- import { useEffect, useState, useMemo, useRef } from "react"
9
+ import { useEffect, useState, useRef } from "react"
10
10
  import type React from "react"
11
11
  import type { Account, WalletClient } from "viem"
12
12
  import type { TransactionState } from "../../transactions.js"
@@ -26,10 +26,7 @@ import { ScreenHeader } from "./ScreenHeader.js"
26
26
  import { ChainList } from "./ChainList.js"
27
27
  import { QuoteDetails } from "./QuoteDetails.js"
28
28
  import { formatTvl } from "../../prices.js"
29
- import { getChainInfo } from "../../chains.js"
30
29
  import { getExplorerUrlForAddress } from "../../explorer.js"
31
- import { formatUsdAmountDisplay } from "../../tokenBalances.js"
32
- import { MINIMUM_USD_AMOUNT_FOR_SWAP } from "../../constants.js"
33
30
  import aaveLogo from "../assets/aave.svg"
34
31
  import morphoLogo from "../assets/morpho.svg"
35
32
  import type { PrepareSendQuote } from "../../prepareSend.js"
@@ -154,10 +151,13 @@ export const Earn: React.FC<EarnProps> = ({
154
151
  ) {
155
152
  const highestValueToken = filteredTokensFormatted[0] // First token is highest USD value
156
153
  if (highestValueToken && Number(highestValueToken.balanceUsd) > 0) {
154
+ const decimals =
155
+ highestValueToken.contractInfo?.decimals ??
156
+ (highestValueToken as any)?.decimals
157
157
  setOriginToken({
158
158
  ...highestValueToken,
159
159
  contractInfo: {
160
- decimals: highestValueToken.contractInfo?.decimals || 18,
160
+ decimals,
161
161
  contractAddress: highestValueToken.contractAddress,
162
162
  symbol: highestValueToken.symbol,
163
163
  name: highestValueToken.name,
@@ -174,25 +174,6 @@ export const Earn: React.FC<EarnProps> = ({
174
174
  }
175
175
  }, [])
176
176
 
177
- // Get unique chains from filtered tokens for chain list
178
- const uniqueChains = useMemo(() => {
179
- if (!filteredTokensFormatted?.length) return []
180
-
181
- const chainIds = new Set(
182
- filteredTokensFormatted.map((token) => token.chainId),
183
- )
184
- return Array.from(chainIds)
185
- .map((chainId) => {
186
- const chainInfo = getChainInfo(chainId)
187
- return {
188
- chainId,
189
- name: chainInfo?.name || `Chain ${chainId}`,
190
- imageUrl: "", // We'll use ChainImage component for chain icons
191
- }
192
- })
193
- .sort((a, b) => a.name.localeCompare(b.name))
194
- }, [filteredTokensFormatted])
195
-
196
177
  const handleAmountChange = (value: string) => {
197
178
  // Validate decimal places (max 8 decimals)
198
179
  const decimalMatch = value.match(/^\d*\.?\d{0,8}$/)
@@ -256,7 +237,6 @@ export const Earn: React.FC<EarnProps> = ({
256
237
  if (showOriginChainList) {
257
238
  return (
258
239
  <ChainList
259
- chains={uniqueChains}
260
240
  onBack={() => {
261
241
  setShowOriginChainList(false)
262
242
  setShowOriginTokenSelector(true)
@@ -313,7 +293,7 @@ export const Earn: React.FC<EarnProps> = ({
313
293
 
314
294
  <div className="space-y-1">
315
295
  {/* Origin Token Selection */}
316
- <div className="trails-bg-secondary trails-border-radius-container p-3 group transition-all duration-200 border border-transparent hover:!bg-white dark:hover:!bg-gray-800 hover:border-gray-400 dark:hover:border-gray-500">
296
+ <div className="trails-bg-secondary trails-bg-secondary-hover trails-border-radius-container p-3 group transition-all duration-200 border border-transparent focus-within:!bg-white dark:focus-within:!bg-gray-800 trails-focus-border-secondary">
317
297
  {/* Deposit Label and Percentage Buttons */}
318
298
  <div className="flex justify-between items-center mb-2">
319
299
  <div className="text-sm font-semibold trails-text-secondary text-left">
@@ -358,7 +338,10 @@ export const Earn: React.FC<EarnProps> = ({
358
338
  <div className="flex items-center space-x-2">
359
339
  {/* Amount Input */}
360
340
  <div className="flex-1">
361
- <div className="flex items-center justify-start">
341
+ <div
342
+ className="flex items-center justify-start cursor-text"
343
+ onClick={() => inputRef.current?.focus()}
344
+ >
362
345
  <div className="flex items-center">
363
346
  <input
364
347
  ref={inputRef}
@@ -372,14 +355,14 @@ export const Earn: React.FC<EarnProps> = ({
372
355
  style={{
373
356
  fontSize:
374
357
  amount.length > 12
375
- ? "1rem"
358
+ ? "0.875rem"
376
359
  : amount.length > 9
377
- ? "1.25rem"
360
+ ? "1rem"
378
361
  : amount.length > 6
379
- ? "1.5rem"
362
+ ? "1.125rem"
380
363
  : amount.length > 3
381
- ? "1.75rem"
382
- : "2rem",
364
+ ? "1.25rem"
365
+ : "1.5rem",
383
366
  width: `${Math.max((amount || "0").length, 1)}ch`,
384
367
  minWidth: "1ch",
385
368
  maxWidth: "270px",
@@ -394,15 +377,15 @@ export const Earn: React.FC<EarnProps> = ({
394
377
  style={{
395
378
  fontSize:
396
379
  amount.length > 12
397
- ? "1rem"
380
+ ? "0.875rem"
398
381
  : amount.length > 9
399
- ? "1.25rem"
382
+ ? "1rem"
400
383
  : amount.length > 6
401
- ? "1.5rem"
384
+ ? "1.125rem"
402
385
  : amount.length > 3
403
- ? "1.75rem"
404
- : "2rem",
405
- marginLeft: amount && amount !== "0" ? "0.2em" : "0.3em",
386
+ ? "1.25rem"
387
+ : "1.5rem",
388
+ marginLeft: "0.1em",
406
389
  padding: "0",
407
390
  transition: "all 0.2s ease-in-out",
408
391
  }}
@@ -486,110 +469,120 @@ export const Earn: React.FC<EarnProps> = ({
486
469
 
487
470
  {/* Arrow Down Between Sections */}
488
471
  <div className="relative">
489
- <div className="absolute left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 p-1.5 trails-border-radius-button trails-bg-tertiary transition-colors cursor-pointer border-2 border-white dark:border-gray-800">
490
- <ArrowDown className="w-4 h-4 trails-text-secondary" />
472
+ <div className="absolute left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 p-1.5 trails-border-radius-button trails-bg-tertiary transition-colors border-2 border-white dark:border-gray-800 z-1">
473
+ <ArrowDown
474
+ className="w-5 h-5 text-gray-900 dark:text-white"
475
+ strokeWidth={2.5}
476
+ />
491
477
  </div>
492
478
  </div>
493
479
 
494
480
  {/* Destination Vault Selection */}
495
481
  <div className="trails-bg-secondary trails-border-radius-container transition-all duration-200 border border-transparent hover:!bg-white dark:hover:!bg-white hover:border-gray-400 dark:hover:border-gray-500">
496
482
  {selectedPool ? (
497
- /* Pool Information Display */
498
- <div className="p-4 trails-border-radius-container trails-bg-secondary transition-all overflow-hidden">
499
- <div className="flex items-center justify-between">
500
- <div className="flex items-center space-x-3">
501
- <div style={{ width: "32px", height: "32px" }}>
502
- <a
503
- href={getExplorerUrlForAddress({
504
- address: selectedPool.token.address,
505
- chainId: selectedPool.chainId,
506
- })}
507
- target="_blank"
508
- rel="noopener noreferrer"
509
- className="cursor-pointer"
510
- >
511
- <TokenImage
512
- symbol={selectedPool.token.symbol}
513
- imageUrl={selectedPool.token.logoUrl}
514
- chainId={selectedPool.chainId}
515
- size={32}
516
- />
517
- </a>
518
- </div>
519
- <div>
520
- <h3 className="font-medium text-gray-900 dark:text-white text-sm">
521
- {selectedPool.poolUrl ? (
522
- <a
523
- href={selectedPool.poolUrl}
524
- target="_blank"
525
- rel="noopener noreferrer"
526
- className="hover:underline cursor-pointer"
527
- >
528
- {selectedPool.name}
529
- </a>
530
- ) : (
531
- selectedPool.name
532
- )}
533
- </h3>
534
- <div className="flex items-center space-x-2">
535
- <span className="text-xs text-gray-500 dark:text-gray-400 flex items-center">
536
- {selectedPool.protocol === "Aave" && (
537
- <img
538
- src={aaveLogo}
539
- alt="Aave"
540
- className="w-3 h-3 mr-1"
541
- />
542
- )}
543
- {selectedPool.protocol === "Morpho" && (
544
- <img
545
- src={morphoLogo}
546
- alt="Morpho"
547
- className="w-3 h-3 mr-1"
548
- />
549
- )}
550
- {selectedPool.protocolUrl ? (
483
+ <div className="p-3 trails-border-radius-container trails-bg-secondary transition-all overflow-hidden">
484
+ {/* Vault Label */}
485
+ <div className="flex justify-between items-center mb-2">
486
+ <div className="text-sm font-semibold trails-text-secondary text-left">
487
+ Vault
488
+ </div>
489
+ </div>
490
+
491
+ <div className="px-1">
492
+ <div className="flex items-center justify-between">
493
+ <div className="flex items-center space-x-3">
494
+ <div style={{ width: "32px", height: "32px" }}>
495
+ <a
496
+ href={getExplorerUrlForAddress({
497
+ address: selectedPool.token.address,
498
+ chainId: selectedPool.chainId,
499
+ })}
500
+ target="_blank"
501
+ rel="noopener noreferrer"
502
+ className="cursor-pointer"
503
+ >
504
+ <TokenImage
505
+ symbol={selectedPool.token.symbol}
506
+ imageUrl={selectedPool.token.logoUrl}
507
+ chainId={selectedPool.chainId}
508
+ size={32}
509
+ />
510
+ </a>
511
+ </div>
512
+ <div>
513
+ <h3 className="font-medium text-gray-900 dark:text-white text-sm">
514
+ {selectedPool.poolUrl ? (
551
515
  <a
552
- href={selectedPool.protocolUrl}
516
+ href={selectedPool.poolUrl}
553
517
  target="_blank"
554
518
  rel="noopener noreferrer"
555
519
  className="hover:underline cursor-pointer"
556
520
  >
557
- {selectedPool.protocol}
521
+ {selectedPool.name}
558
522
  </a>
559
523
  ) : (
560
- selectedPool.protocol
524
+ selectedPool.name
561
525
  )}
562
- </span>
526
+ </h3>
527
+ <div className="flex items-center space-x-2">
528
+ <span className="text-xs text-gray-500 dark:text-gray-400 flex items-center">
529
+ {selectedPool.protocol === "Aave" && (
530
+ <img
531
+ src={aaveLogo}
532
+ alt="Aave"
533
+ className="w-3 h-3 mr-1"
534
+ />
535
+ )}
536
+ {selectedPool.protocol === "Morpho" && (
537
+ <img
538
+ src={morphoLogo}
539
+ alt="Morpho"
540
+ className="w-3 h-3 mr-1"
541
+ />
542
+ )}
543
+ {selectedPool.protocolUrl ? (
544
+ <a
545
+ href={selectedPool.protocolUrl}
546
+ target="_blank"
547
+ rel="noopener noreferrer"
548
+ className="hover:underline cursor-pointer"
549
+ >
550
+ {selectedPool.protocol}
551
+ </a>
552
+ ) : (
553
+ selectedPool.protocol
554
+ )}
555
+ </span>
556
+ </div>
563
557
  </div>
564
558
  </div>
565
- </div>
566
- <button
567
- type="button"
568
- title="Select Vault"
569
- onClick={() => setShowEarnPools(true)}
570
- className="text-right flex items-center space-x-3 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700 rounded p-2 transition-colors"
571
- >
572
- <div>
573
- <div className="flex items-center justify-end space-x-1 text-green-600 dark:text-green-400 mb-1 whitespace-nowrap">
574
- <TrendingUp className="w-3 h-3" />
575
- <span className="font-semibold text-sm">
576
- {selectedPool.apy.toFixed(1)}% APY
577
- </span>
559
+ <button
560
+ type="button"
561
+ title="Select Vault"
562
+ onClick={() => setShowEarnPools(true)}
563
+ className="text-right flex items-center space-x-3 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700 rounded p-2 transition-colors"
564
+ >
565
+ <div>
566
+ <div className="flex items-center justify-end space-x-1 text-green-600 dark:text-green-400 mb-1 whitespace-nowrap">
567
+ <TrendingUp className="w-3 h-3" />
568
+ <span className="font-semibold text-sm">
569
+ {selectedPool.apy.toFixed(1)}% APY
570
+ </span>
571
+ </div>
572
+ <p className="text-xs text-gray-500 dark:text-gray-400 whitespace-nowrap">
573
+ TVL: {formatTvl(selectedPool.tvl)}
574
+ </p>
578
575
  </div>
579
- <p className="text-xs text-gray-500 dark:text-gray-400 whitespace-nowrap">
580
- TVL: {formatTvl(selectedPool.tvl)}
581
- </p>
582
- </div>
583
- <ChevronRight className="w-4 h-4 text-gray-400" />
584
- </button>
576
+ <ChevronRight className="w-4 h-4 text-gray-400" />
577
+ </button>
578
+ </div>
585
579
  </div>
586
580
  </div>
587
581
  ) : (
588
- /* Select Vault Button */
589
582
  <button
590
583
  type="button"
591
584
  onClick={() => setShowEarnPools(true)}
592
- className="w-full py-6 px-4 trails-bg-secondary trails-hover-bg trails-border-radius-container transition-all duration-200 cursor-pointer"
585
+ className="w-full py-6 px-4 trails-list-item trails-border-radius-container transition-all duration-200 cursor-pointer"
593
586
  >
594
587
  <div className="flex items-center justify-between">
595
588
  <div className="flex items-center space-x-3 flex-1">
@@ -631,30 +624,6 @@ export const Earn: React.FC<EarnProps> = ({
631
624
  </p>
632
625
  </div>
633
626
  </div>
634
- ) : prepareSendQuote?.minimumNotMet ? (
635
- <div className="px-2 py-3 rounded-lg bg-amber-500/10 border border-solid border-amber-500/30">
636
- <div className="flex items-center space-x-2">
637
- <svg
638
- className="w-4 h-4 text-amber-500 flex-shrink-0"
639
- fill="none"
640
- stroke="currentColor"
641
- viewBox="0 0 24 24"
642
- aria-hidden="true"
643
- >
644
- <path
645
- strokeLinecap="round"
646
- strokeLinejoin="round"
647
- strokeWidth={2}
648
- d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"
649
- />
650
- </svg>
651
- <p className="text-sm text-amber-600 dark:text-amber-400">
652
- Please enter an amount above{" "}
653
- {formatUsdAmountDisplay(MINIMUM_USD_AMOUNT_FOR_SWAP)} otherwise
654
- transfer may fail
655
- </p>
656
- </div>
657
- </div>
658
627
  ) : null}
659
628
 
660
629
  <form onSubmit={handleSubmit}>
@@ -147,9 +147,7 @@ export const EarnPools: React.FC<EarnPoolsProps> = ({
147
147
 
148
148
  // Show chain list screen
149
149
  if (showChainList) {
150
- return (
151
- <ChainList chains={uniqueChains} onBack={() => setShowChainList(false)} />
152
- )
150
+ return <ChainList onBack={() => setShowChainList(false)} />
153
151
  }
154
152
 
155
153
  return (
@@ -230,7 +228,7 @@ export const EarnPools: React.FC<EarnPoolsProps> = ({
230
228
  whileHover={{ scale: 1 }}
231
229
  whileTap={{ scale: 0.99 }}
232
230
  onClick={() => onPoolSelect(pool)}
233
- className="p-4 trails-border-radius-container trails-bg-secondary cursor-pointer hover:!bg-gray-200 dark:hover:!bg-gray-600 transition-all overflow-hidden"
231
+ className="p-4 trails-border-radius-container trails-list-item cursor-pointer transition-all overflow-hidden"
234
232
  >
235
233
  <div className="flex items-center justify-between">
236
234
  <div className="flex items-center space-x-3">
@@ -46,7 +46,7 @@ export const EarnPoolsFilters: React.FC<EarnPoolsFiltersProps> = ({
46
46
  e.stopPropagation()
47
47
  setIsProtocolDropdownOpen(!isProtocolDropdownOpen)
48
48
  }}
49
- className="flex items-center justify-between px-2 py-1.5 bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded-xl hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors cursor-pointer text-xs min-w-[100px]"
49
+ className="flex items-center justify-between px-2 py-1.5 trails-bg-secondary text-gray-700 dark:text-gray-300 rounded-xl hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors cursor-pointer text-xs min-w-[100px]"
50
50
  >
51
51
  <div className="flex items-center space-x-1">
52
52
  {selectedProtocol === "all" ? (
@@ -72,11 +72,11 @@ export const EarnPoolsFilters: React.FC<EarnPoolsFiltersProps> = ({
72
72
  {getProtocolDisplay(selectedProtocol)}
73
73
  </span>
74
74
  </div>
75
- <ChevronDown className="w-3 h-3 ml-1" />
75
+ <ChevronDown className="w-4 h-4 ml-1" />
76
76
  </button>
77
77
 
78
78
  {isProtocolDropdownOpen && (
79
- <div className="absolute top-full left-0 mt-0.5 w-full bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl shadow-lg z-20">
79
+ <div className="absolute top-full left-0 mt-0.5 w-full trails-bg-secondary border border-gray-200 dark:border-gray-700 rounded-xl shadow-lg z-20">
80
80
  {protocols.map((protocol) => (
81
81
  <button
82
82
  key={protocol}
@@ -115,14 +115,14 @@ export const EarnPoolsFilters: React.FC<EarnPoolsFiltersProps> = ({
115
115
  e.stopPropagation()
116
116
  setIsSortDropdownOpen(!isSortDropdownOpen)
117
117
  }}
118
- className="flex items-center justify-between px-2 py-1.5 bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded-xl hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors cursor-pointer text-xs min-w-[90px]"
118
+ className="flex items-center justify-between px-2 py-1.5 trails-bg-secondary text-gray-700 dark:text-gray-300 rounded-xl hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors cursor-pointer text-xs min-w-[90px]"
119
119
  >
120
120
  <span className="text-xs font-medium">{getSortDisplay(sortBy)}</span>
121
- <ChevronDown className="w-3 h-3 ml-1" />
121
+ <ChevronDown className="w-4 h-4 ml-1" />
122
122
  </button>
123
123
 
124
124
  {isSortDropdownOpen && (
125
- <div className="absolute top-full left-0 mt-0.5 w-full bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl shadow-lg z-20">
125
+ <div className="absolute top-full left-0 mt-0.5 w-full trails-bg-secondary border border-gray-200 dark:border-gray-700 rounded-xl shadow-lg z-20">
126
126
  <button
127
127
  type="button"
128
128
  onClick={(e) => {
@@ -0,0 +1,78 @@
1
+ import type React from "react"
2
+ import { TokenImage } from "./TokenImage.js"
3
+
4
+ export type FeeOption = {
5
+ tokenAddress: string
6
+ tokenSymbol: string
7
+ tokenDecimals: number
8
+ amount: string
9
+ amountUSD: number
10
+ amountFormatted: string
11
+ amountUsdDisplay: string
12
+ tokenImageUrl?: string
13
+ notEnoughBalance?: boolean
14
+ chainId?: number
15
+ }
16
+
17
+ interface FeeOptionProps {
18
+ option: FeeOption
19
+ isSelected: boolean
20
+ onClick: () => void
21
+ chainId?: number
22
+ }
23
+
24
+ export const FeeOption: React.FC<FeeOptionProps> = ({
25
+ option,
26
+ isSelected,
27
+ onClick,
28
+ chainId,
29
+ }) => {
30
+ return (
31
+ <button
32
+ type="button"
33
+ className={`w-full flex items-center justify-between p-1.5 trails-border-radius-input border transition-colors ${
34
+ option.notEnoughBalance
35
+ ? "cursor-not-allowed opacity-50 bg-gray-100 dark:bg-gray-800 border-gray-300 dark:border-gray-600"
36
+ : isSelected
37
+ ? "cursor-pointer trails-bg-primary/10 border-blue-500 bg-blue-50 dark:bg-blue-900/20"
38
+ : "cursor-pointer trails-bg-card trails-border-primary hover:trails-hover-bg"
39
+ }`}
40
+ onClick={option.notEnoughBalance ? undefined : onClick}
41
+ disabled={option.notEnoughBalance}
42
+ >
43
+ <div className="flex items-center space-x-2">
44
+ <TokenImage
45
+ imageUrl={option.tokenImageUrl}
46
+ symbol={option.tokenSymbol}
47
+ chainId={option.chainId || chainId}
48
+ size={16}
49
+ />
50
+ <div className="text-left">
51
+ <div
52
+ className={`text-xs font-medium ${
53
+ option.notEnoughBalance
54
+ ? "text-gray-400 dark:text-gray-500"
55
+ : "trails-text-primary"
56
+ }`}
57
+ >
58
+ {option.amountFormatted}
59
+ </div>
60
+ </div>
61
+ </div>
62
+
63
+ <div className="text-right">
64
+ <div
65
+ className={`text-xs font-medium ${
66
+ option.notEnoughBalance
67
+ ? "text-gray-400 dark:text-gray-500"
68
+ : "trails-text-primary"
69
+ }`}
70
+ >
71
+ {option.amountUsdDisplay}
72
+ </div>
73
+ </div>
74
+ </button>
75
+ )
76
+ }
77
+
78
+ export default FeeOption