0xtrails 0.2.4 → 0.2.6

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 (212) hide show
  1. package/dist/aave.d.ts +8 -0
  2. package/dist/aave.d.ts.map +1 -1
  3. package/dist/abortController.d.ts +8 -0
  4. package/dist/abortController.d.ts.map +1 -0
  5. package/dist/{ccip-BlV1Mry3.js → ccip-Xjh9d1gb.js} +7 -7
  6. package/dist/config.d.ts +1 -1
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/constants.d.ts +3 -0
  9. package/dist/constants.d.ts.map +1 -1
  10. package/dist/error.d.ts +1 -0
  11. package/dist/error.d.ts.map +1 -1
  12. package/dist/estimate.d.ts +52 -0
  13. package/dist/estimate.d.ts.map +1 -1
  14. package/dist/fees.d.ts +19 -0
  15. package/dist/fees.d.ts.map +1 -0
  16. package/dist/{index-BNWCIGfQ.js → index-BnhdZ8Ho.js} +76406 -75798
  17. package/dist/index.js +726 -520
  18. package/dist/intents.d.ts +40 -0
  19. package/dist/intents.d.ts.map +1 -1
  20. package/dist/metaTxnMonitor.d.ts +3 -3
  21. package/dist/metaTxnMonitor.d.ts.map +1 -1
  22. package/dist/metaTxns.d.ts +3 -3
  23. package/dist/metaTxns.d.ts.map +1 -1
  24. package/dist/morpho.d.ts +8 -0
  25. package/dist/morpho.d.ts.map +1 -1
  26. package/dist/prepareSend.d.ts +19 -75
  27. package/dist/prepareSend.d.ts.map +1 -1
  28. package/dist/queryParams.d.ts.map +1 -1
  29. package/dist/relayer.d.ts +6 -6
  30. package/dist/relayer.d.ts.map +1 -1
  31. package/dist/sequenceWallet.d.ts +2 -2
  32. package/dist/sequenceWallet.d.ts.map +1 -1
  33. package/dist/tokens.d.ts.map +1 -1
  34. package/dist/transactions.d.ts +4 -2
  35. package/dist/transactions.d.ts.map +1 -1
  36. package/dist/wallets.d.ts.map +1 -1
  37. package/dist/widget/components/AccountActionsDropdown.d.ts.map +1 -1
  38. package/dist/widget/components/AccountIntentTransactionHistoryButton.d.ts +4 -0
  39. package/dist/widget/components/AccountIntentTransactionHistoryButton.d.ts.map +1 -0
  40. package/dist/widget/components/AccountSettings.d.ts.map +1 -1
  41. package/dist/widget/components/ChainFilterDropdown.d.ts.map +1 -1
  42. package/dist/widget/components/ClassicSwap.d.ts +4 -2
  43. package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
  44. package/dist/widget/components/ConnectWallet.d.ts.map +1 -1
  45. package/dist/widget/components/ConnectedWallets.d.ts +4 -0
  46. package/dist/widget/components/ConnectedWallets.d.ts.map +1 -1
  47. package/dist/widget/components/DynamicInputStyles.d.ts +18 -0
  48. package/dist/widget/components/DynamicInputStyles.d.ts.map +1 -0
  49. package/dist/widget/components/Earn.d.ts +2 -2
  50. package/dist/widget/components/Earn.d.ts.map +1 -1
  51. package/dist/widget/components/ErrorAnimationIcon.d.ts +2 -0
  52. package/dist/widget/components/ErrorAnimationIcon.d.ts.map +1 -0
  53. package/dist/widget/components/FeeBreakdown.d.ts +9 -0
  54. package/dist/widget/components/FeeBreakdown.d.ts.map +1 -0
  55. package/dist/widget/components/Fund.d.ts +2 -2
  56. package/dist/widget/components/Fund.d.ts.map +1 -1
  57. package/dist/widget/components/FundMethods.d.ts.map +1 -1
  58. package/dist/widget/components/{FundSendForm.d.ts → FundSwap.d.ts} +13 -7
  59. package/dist/widget/components/FundSwap.d.ts.map +1 -0
  60. package/dist/widget/components/FundingMethodSelectorButton.d.ts +4 -0
  61. package/dist/widget/components/FundingMethodSelectorButton.d.ts.map +1 -0
  62. package/dist/widget/components/Identicon.d.ts.map +1 -1
  63. package/dist/widget/components/MeshConnectExchanges.d.ts +0 -3
  64. package/dist/widget/components/MeshConnectExchanges.d.ts.map +1 -1
  65. package/dist/widget/components/Modal.d.ts.map +1 -1
  66. package/dist/widget/components/Pay.d.ts +2 -2
  67. package/dist/widget/components/Pay.d.ts.map +1 -1
  68. package/dist/widget/components/PercentageMaxButtons.d.ts +12 -0
  69. package/dist/widget/components/PercentageMaxButtons.d.ts.map +1 -0
  70. package/dist/widget/components/{PaySendForm.d.ts → PoolDeposit.d.ts} +14 -36
  71. package/dist/widget/components/PoolDeposit.d.ts.map +1 -0
  72. package/dist/widget/components/{SimpleSwap.d.ts → PoolWithdraw.d.ts} +19 -10
  73. package/dist/widget/components/PoolWithdraw.d.ts.map +1 -0
  74. package/dist/widget/components/QuoteDetails.d.ts +1 -0
  75. package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
  76. package/dist/widget/components/Receipt.d.ts.map +1 -1
  77. package/dist/widget/components/Receive.d.ts.map +1 -1
  78. package/dist/widget/components/RecipientSelectorButton.d.ts +4 -0
  79. package/dist/widget/components/RecipientSelectorButton.d.ts.map +1 -0
  80. package/dist/widget/components/Recipients.d.ts.map +1 -1
  81. package/dist/widget/components/RequiredPropsError.d.ts +8 -0
  82. package/dist/widget/components/RequiredPropsError.d.ts.map +1 -0
  83. package/dist/widget/components/ScreenHeader.d.ts.map +1 -1
  84. package/dist/widget/components/SlippageToleranceSettings.d.ts.map +1 -1
  85. package/dist/widget/components/Swap.d.ts +3 -2
  86. package/dist/widget/components/Swap.d.ts.map +1 -1
  87. package/dist/widget/components/SwapSettings.d.ts.map +1 -1
  88. package/dist/widget/components/ThemeProvider.d.ts.map +1 -1
  89. package/dist/widget/components/TokenDisplayNonSelectable.d.ts +11 -0
  90. package/dist/widget/components/TokenDisplayNonSelectable.d.ts.map +1 -0
  91. package/dist/widget/components/TokenImage.d.ts +1 -0
  92. package/dist/widget/components/TokenImage.d.ts.map +1 -1
  93. package/dist/widget/components/TokenList.d.ts.map +1 -1
  94. package/dist/widget/components/TokenSelector.d.ts.map +1 -1
  95. package/dist/widget/components/TokenSelectorButton.d.ts +16 -0
  96. package/dist/widget/components/TokenSelectorButton.d.ts.map +1 -0
  97. package/dist/widget/components/Tooltip.d.ts +9 -0
  98. package/dist/widget/components/Tooltip.d.ts.map +1 -0
  99. package/dist/widget/components/UserPreferences.d.ts.map +1 -1
  100. package/dist/widget/components/WaasFeeOptions.d.ts +9 -0
  101. package/dist/widget/components/WaasFeeOptions.d.ts.map +1 -0
  102. package/dist/widget/components/WalletConfirmation.d.ts.map +1 -1
  103. package/dist/widget/components/WalletConnect.d.ts.map +1 -1
  104. package/dist/widget/components/WalletList.d.ts.map +1 -1
  105. package/dist/widget/css/compiled.css +2 -0
  106. package/dist/widget/css/index.css +554 -0
  107. package/dist/widget/hooks/useBack.d.ts +1 -0
  108. package/dist/widget/hooks/useBack.d.ts.map +1 -1
  109. package/dist/widget/hooks/useCheckout.d.ts +1 -1
  110. package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
  111. package/dist/widget/hooks/useCurrentScreen.d.ts +1 -1
  112. package/dist/widget/hooks/useCurrentScreen.d.ts.map +1 -1
  113. package/dist/widget/hooks/useDefaultTokenSelection.d.ts +3 -3
  114. package/dist/widget/hooks/useDefaultTokenSelection.d.ts.map +1 -1
  115. package/dist/widget/hooks/usePayMessage.d.ts.map +1 -1
  116. package/dist/widget/hooks/useQuote.d.ts +83 -0
  117. package/dist/widget/hooks/useQuote.d.ts.map +1 -0
  118. package/dist/widget/hooks/useSelectedFundMethod.d.ts +12 -0
  119. package/dist/widget/hooks/useSelectedFundMethod.d.ts.map +1 -0
  120. package/dist/widget/hooks/useSelectedRecipient.d.ts.map +1 -1
  121. package/dist/widget/hooks/useSendForm.d.ts +2 -2
  122. package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
  123. package/dist/widget/index.js +2 -2
  124. package/dist/widget/widget.d.ts +9 -4
  125. package/dist/widget/widget.d.ts.map +1 -1
  126. package/package.json +18 -12
  127. package/src/aave.ts +32 -0
  128. package/src/abortController.ts +35 -0
  129. package/src/config.ts +12 -4
  130. package/src/constants.ts +5 -0
  131. package/src/error.ts +19 -1
  132. package/src/estimate.ts +416 -5
  133. package/src/fees.ts +199 -0
  134. package/src/intents.ts +161 -11
  135. package/src/metaTxnMonitor.ts +3 -3
  136. package/src/metaTxns.ts +3 -5
  137. package/src/morpho.ts +32 -0
  138. package/src/prepareSend.ts +714 -550
  139. package/src/queryParams.ts +2 -1
  140. package/src/relayer.ts +11 -11
  141. package/src/sequenceWallet.ts +2 -2
  142. package/src/tokens.ts +7 -1
  143. package/src/trails.ts +3 -3
  144. package/src/transactions.ts +62 -18
  145. package/src/wallets.ts +8 -0
  146. package/src/widget/compiled.css +2 -2
  147. package/src/widget/components/AccountActionsDropdown.tsx +3 -13
  148. package/src/widget/components/AccountIntentTransactionHistoryButton.tsx +22 -0
  149. package/src/widget/components/AccountSettings.tsx +48 -54
  150. package/src/widget/components/ChainFilterDropdown.tsx +24 -3
  151. package/src/widget/components/ClassicSwap.tsx +131 -213
  152. package/src/widget/components/ConnectWallet.tsx +8 -38
  153. package/src/widget/components/ConnectedWallets.tsx +132 -77
  154. package/src/widget/components/DynamicInputStyles.tsx +76 -0
  155. package/src/widget/components/Earn.tsx +82 -593
  156. package/src/widget/components/ErrorAnimationIcon.tsx +130 -0
  157. package/src/widget/components/FeeBreakdown.tsx +155 -0
  158. package/src/widget/components/Fund.tsx +41 -108
  159. package/src/widget/components/FundMethods.tsx +82 -159
  160. package/src/widget/components/FundSwap.tsx +52 -0
  161. package/src/widget/components/FundingMethodSelectorButton.tsx +70 -0
  162. package/src/widget/components/Identicon.tsx +164 -95
  163. package/src/widget/components/MeshConnectExchanges.tsx +2 -15
  164. package/src/widget/components/Modal.tsx +0 -8
  165. package/src/widget/components/Pay.tsx +214 -237
  166. package/src/widget/components/PercentageMaxButtons.tsx +77 -0
  167. package/src/widget/components/PoolDeposit.tsx +569 -0
  168. package/src/widget/components/PoolWithdraw.tsx +884 -0
  169. package/src/widget/components/PriceImpactWarning.tsx +1 -1
  170. package/src/widget/components/QuoteDetails.tsx +43 -12
  171. package/src/widget/components/Receipt.tsx +16 -2
  172. package/src/widget/components/Receive.tsx +0 -2
  173. package/src/widget/components/RecipientSelectorButton.tsx +44 -0
  174. package/src/widget/components/Recipients.tsx +63 -157
  175. package/src/widget/components/RequiredPropsError.tsx +33 -0
  176. package/src/widget/components/ScreenHeader.tsx +62 -34
  177. package/src/widget/components/SlippageToleranceSettings.tsx +2 -1
  178. package/src/widget/components/Swap.tsx +4 -45
  179. package/src/widget/components/SwapSettings.tsx +2 -14
  180. package/src/widget/components/ThemeProvider.tsx +2 -1
  181. package/src/widget/components/TokenDisplayNonSelectable.tsx +40 -0
  182. package/src/widget/components/TokenImage.tsx +22 -5
  183. package/src/widget/components/TokenList.tsx +0 -1
  184. package/src/widget/components/TokenSelector.tsx +63 -53
  185. package/src/widget/components/TokenSelectorButton.tsx +98 -0
  186. package/src/widget/components/Tooltip.tsx +51 -0
  187. package/src/widget/components/TransferPendingVertical.tsx +1 -1
  188. package/src/widget/components/UserPreferences.tsx +6 -24
  189. package/src/widget/components/WaasFeeOptions.tsx +450 -0
  190. package/src/widget/components/WalletConfirmation.tsx +76 -14
  191. package/src/widget/components/WalletConnect.tsx +93 -29
  192. package/src/widget/components/WalletList.tsx +4 -2
  193. package/src/widget/hooks/useBack.tsx +2 -0
  194. package/src/widget/hooks/useCheckout.ts +36 -20
  195. package/src/widget/hooks/useCurrentScreen.tsx +1 -0
  196. package/src/widget/hooks/useDefaultTokenSelection.tsx +104 -28
  197. package/src/widget/hooks/usePayMessage.tsx +86 -11
  198. package/src/widget/hooks/useQuote.ts +413 -0
  199. package/src/widget/hooks/useSelectedFundMethod.tsx +41 -0
  200. package/src/widget/hooks/useSelectedRecipient.tsx +10 -0
  201. package/src/widget/hooks/useSendForm.ts +32 -6
  202. package/src/widget/index.css +27 -0
  203. package/src/widget/widget.tsx +326 -283
  204. package/dist/widget/components/FundSendForm.d.ts.map +0 -1
  205. package/dist/widget/components/PaySendForm.d.ts.map +0 -1
  206. package/dist/widget/components/SimpleSwap.d.ts.map +0 -1
  207. package/dist/widget/hooks/useSwapSettings.d.ts +0 -16
  208. package/dist/widget/hooks/useSwapSettings.d.ts.map +0 -1
  209. package/src/widget/components/FundSendForm.tsx +0 -903
  210. package/src/widget/components/PaySendForm.tsx +0 -869
  211. package/src/widget/components/SimpleSwap.tsx +0 -983
  212. package/src/widget/hooks/useSwapSettings.tsx +0 -100
@@ -1,13 +1,13 @@
1
- import { ChevronDown, Loader2, ArrowDown } from "lucide-react"
1
+ import { Loader2, ArrowDown } from "lucide-react"
2
2
  import type React from "react"
3
- import { useCallback, useEffect, useRef, useState, useMemo } from "react"
3
+ import { useCallback, useEffect, useRef, useState } from "react"
4
4
  import type { Account, WalletClient } from "viem"
5
+ import { zeroAddress } from "viem"
5
6
  import type { TransactionState } from "../../transactions.js"
6
7
  import type { OnCompleteProps, Token } from "../hooks/useSendForm.js"
7
8
  import type { SupportedToken } from "../../tokens.js"
8
9
  import { useSendForm } from "../hooks/useSendForm.js"
9
10
  import type { CheckoutOnHandlers } from "../hooks/useCheckout.js"
10
- import { TokenImage } from "./TokenImage.js"
11
11
  import { QuoteDetails } from "./QuoteDetails.js"
12
12
  import { type PrepareSendQuote, TradeType } from "../../prepareSend.js"
13
13
  import { getChainInfo } from "../../chains.js"
@@ -16,12 +16,19 @@ import { TokenSelector } from "./TokenSelector.js"
16
16
  import { ErrorDisplay } from "./ErrorDisplay.js"
17
17
  import { useMode } from "../hooks/useMode.js"
18
18
  import { logger } from "../../logger.js"
19
- import { SwapSettings } from "./SwapSettings.js"
20
19
  import { useOriginSelectedToken } from "../hooks/useOriginSelectedToken.js"
21
20
  import { useDestinationSelectedToken } from "../hooks/useDestinationSelectedToken.js"
22
21
  import { useBalanceVisible } from "../hooks/useBalanceVisible.js"
23
22
  import { useDefaultTokenSelection } from "../hooks/useDefaultTokenSelection.js"
24
23
  import { ChainList } from "./ChainList.js"
24
+ import { PercentageMaxButtons } from "./PercentageMaxButtons.js"
25
+ import { TokenSelectorButton } from "./TokenSelectorButton.js"
26
+ import { FundingMethodSelectorButton } from "./FundingMethodSelectorButton.js"
27
+ import { RecipientSelectorButton } from "./RecipientSelectorButton.js"
28
+ import { RefundWarning } from "./RefundWarning.js"
29
+ import { Identicon } from "./Identicon.js"
30
+ import { truncateAddress } from "../../utils.js"
31
+ import { useDynamicInputStyles } from "./DynamicInputStyles.js"
25
32
 
26
33
  interface ClassicSwapProps {
27
34
  selectedToken: Token | null
@@ -29,13 +36,13 @@ interface ClassicSwapProps {
29
36
  onBack?: () => void
30
37
  onConfirm: () => void
31
38
  onComplete: (result: OnCompleteProps) => void
32
- account: Account
39
+ account?: Account
33
40
  toRecipient?: string
34
41
  toAmount?: string
35
42
  toChainId?: number
36
43
  toToken?: string
37
44
  toCalldata?: string
38
- walletClient: WalletClient
45
+ walletClient?: WalletClient
39
46
  onTransactionStateChange: (transactionStates: TransactionState[]) => void
40
47
  onError: (error: Error | string | null) => void
41
48
  onWaitingForWalletConfirm: (props: PrepareSendQuote) => void
@@ -58,6 +65,8 @@ interface ClassicSwapProps {
58
65
  recentTokens?: SupportedToken[]
59
66
  onRecentTokenSelect?: (token: SupportedToken) => void
60
67
  onTrackToken?: (token: any) => void
68
+ title?: string
69
+ isSequenceWallet?: boolean
61
70
  }
62
71
 
63
72
  export const ClassicSwap: React.FC<ClassicSwapProps> = ({
@@ -67,6 +76,7 @@ export const ClassicSwap: React.FC<ClassicSwapProps> = ({
67
76
  onConfirm,
68
77
  onComplete,
69
78
  account,
79
+ toRecipient,
70
80
  toAmount,
71
81
  toChainId,
72
82
  toToken,
@@ -85,6 +95,8 @@ export const ClassicSwap: React.FC<ClassicSwapProps> = ({
85
95
  checkoutOnHandlers,
86
96
  recentTokens,
87
97
  onTrackToken,
98
+ title = "Swap",
99
+ isSequenceWallet = false,
88
100
  }) => {
89
101
  const { mode } = useMode()
90
102
  const { isBalanceVisible } = useBalanceVisible()
@@ -135,7 +147,7 @@ export const ClassicSwap: React.FC<ClassicSwapProps> = ({
135
147
  } = useSendForm({
136
148
  account,
137
149
  toAmount: tradeType === TradeType.EXACT_OUTPUT ? buyAmount : toAmount,
138
- toRecipient: account.address,
150
+ toRecipient: toRecipient || account?.address,
139
151
  toChainId,
140
152
  toToken,
141
153
  toCalldata,
@@ -230,24 +242,6 @@ export const ClassicSwap: React.FC<ClassicSwapProps> = ({
230
242
  }
231
243
  }, [prepareSendQuote, tradeType])
232
244
 
233
- // Handle percentage button clicks
234
- const handlePercentageClick = useCallback(
235
- (percentage: number) => {
236
- if (!originToken || !balanceFormatted) return
237
-
238
- // Parse the balance and calculate percentage
239
- const balance = parseFloat(balanceFormatted)
240
- if (Number.isNaN(balance)) return
241
-
242
- const amount = (balance * percentage) / 100
243
- setTradeType(TradeType.EXACT_INPUT)
244
- setSellAmount(amount.toFixed(6))
245
- setBuyAmount("")
246
- setLastInputType("sell")
247
- },
248
- [originToken, balanceFormatted],
249
- )
250
-
251
245
  // Call onAmountUpdate when amountRaw changes
252
246
  useEffect(() => {
253
247
  if (onAmountUpdate) {
@@ -369,52 +363,13 @@ export const ClassicSwap: React.FC<ClassicSwapProps> = ({
369
363
  }
370
364
  }
371
365
 
372
- // Dynamic font size based on input length - matching SimpleSwap.tsx
373
- const sellInputStyles = useMemo(() => {
374
- const inputLength = sellAmount.length
375
- let fontSize: string
376
-
377
- if (inputLength > 12) {
378
- fontSize = "1rem"
379
- } else if (inputLength > 9) {
380
- fontSize = "1.25rem"
381
- } else if (inputLength > 6) {
382
- fontSize = "1.5rem"
383
- } else if (inputLength > 3) {
384
- fontSize = "1.75rem"
385
- } else {
386
- fontSize = "2rem"
387
- }
388
-
389
- return {
390
- fontSize,
391
- transition: "all 0.1s ease-in-out",
392
- }
393
- }, [sellAmount.length])
394
-
395
- const buyInputStyles = useMemo(() => {
396
- const inputValue =
397
- tradeType === TradeType.EXACT_OUTPUT ? buyAmount : toAmountDisplay || ""
398
- const inputLength = inputValue.length
399
- let fontSize: string
400
-
401
- if (inputLength > 12) {
402
- fontSize = "1rem"
403
- } else if (inputLength > 9) {
404
- fontSize = "1.25rem"
405
- } else if (inputLength > 6) {
406
- fontSize = "1.5rem"
407
- } else if (inputLength > 3) {
408
- fontSize = "1.75rem"
409
- } else {
410
- fontSize = "2rem"
411
- }
366
+ // Dynamic font size based on input length
367
+ const sellInputStyles = useDynamicInputStyles({ inputValue: sellAmount })
412
368
 
413
- return {
414
- fontSize,
415
- transition: "all 0.1s ease-in-out",
416
- }
417
- }, [tradeType, buyAmount, toAmountDisplay])
369
+ const buyInputStyles = useDynamicInputStyles({
370
+ inputValue:
371
+ tradeType === TradeType.EXACT_OUTPUT ? buyAmount : toAmountDisplay || "",
372
+ })
418
373
 
419
374
  // Handle source token selection from full-screen selector
420
375
  const handleSourceTokenSelectorSelect = useCallback(
@@ -429,13 +384,25 @@ export const ClassicSwap: React.FC<ClassicSwapProps> = ({
429
384
  name: token.name,
430
385
  },
431
386
  }
387
+
388
+ // Only reset input fields if the token symbol is different
389
+ const isDifferentToken =
390
+ !originToken || originToken.symbol !== token.symbol
391
+ if (isDifferentToken) {
392
+ setSellAmount("")
393
+ setBuyAmount("")
394
+ setTradeType(TradeType.EXACT_INPUT)
395
+ setLastInputType("sell")
396
+ }
397
+
432
398
  setOriginToken(formattedToken as any)
433
399
  setOriginChainId(token.chainId)
434
400
  setShowSourceTokenSelector(false)
401
+
435
402
  onTrackToken?.(token)
436
403
  logger.console.log("[trails-sdk] selected origin token", token)
437
404
  },
438
- [setOriginToken, onTrackToken],
405
+ [setOriginToken, onTrackToken, originToken],
439
406
  )
440
407
 
441
408
  // Handle destination token selection from full-screen selector
@@ -573,54 +540,20 @@ export const ClassicSwap: React.FC<ClassicSwapProps> = ({
573
540
  <div className="space-y-2">
574
541
  <ScreenHeader
575
542
  onBack={onBack}
576
- headerContent="Swap"
543
+ headerContent={title}
577
544
  headerContentAlign="left"
578
545
  showAccountActions={true}
579
- rightSideContent={<SwapSettings />}
580
546
  />
581
547
 
582
548
  <form onSubmit={handleSubmit} className="space-y-1">
583
549
  {/* Input Section - Amount + Token Selection */}
584
- <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 min-h-[120px] flex flex-col">
585
- {/* Sell Label and Percentage Buttons */}
586
- <div className="flex justify-between items-center mb-2">
587
- <div className="text-sm font-medium trails-text-secondary text-left">
588
- Sell
550
+ <div className="pt-4 pb-4 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 min-h-[120px] flex flex-col">
551
+ {/* Sell Label */}
552
+ <div className="mb-4 flex justify-between items-center">
553
+ <div className="text-sm font-medium trails-text-secondary text-left m-0">
554
+ {mode === "fund" ? "Payment method" : "Sell"}
589
555
  </div>
590
-
591
- {/* Percentage Buttons */}
592
- {originToken && (
593
- <div className="flex space-x-1 opacity-0 group-hover:opacity-100 transition-opacity duration-200">
594
- <button
595
- type="button"
596
- onClick={() => handlePercentageClick(25)}
597
- className="py-1 px-2 text-xs font-medium trails-border-radius-container border border-solid transition-colors cursor-pointer border-gray-300 text-gray-600 dark:border-gray-600 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 hover:trails-hover-bg hover:border-gray-400 dark:hover:border-gray-500"
598
- >
599
- 25%
600
- </button>
601
- <button
602
- type="button"
603
- onClick={() => handlePercentageClick(50)}
604
- className="py-1 px-2 text-xs font-medium trails-border-radius-container border border-solid transition-colors cursor-pointer border-gray-300 text-gray-600 dark:border-gray-600 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 hover:trails-hover-bg hover:border-gray-400 dark:hover:border-gray-500"
605
- >
606
- 50%
607
- </button>
608
- <button
609
- type="button"
610
- onClick={() => handlePercentageClick(75)}
611
- className="py-1 px-2 text-xs font-medium trails-border-radius-container border border-solid transition-colors cursor-pointer border-gray-300 text-gray-600 dark:border-gray-600 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 hover:trails-hover-bg hover:border-gray-400 dark:hover:border-gray-500"
612
- >
613
- 75%
614
- </button>
615
- <button
616
- type="button"
617
- onClick={() => handlePercentageClick(100)}
618
- className="py-1 px-2 text-xs font-medium trails-border-radius-container border border-solid transition-colors cursor-pointer border-gray-300 text-gray-600 dark:border-gray-600 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 hover:trails-hover-bg hover:border-gray-400 dark:hover:border-gray-500"
619
- >
620
- Max
621
- </button>
622
- </div>
623
- )}
556
+ <FundingMethodSelectorButton />
624
557
  </div>
625
558
 
626
559
  <div className="flex items-center space-x-2 flex-1">
@@ -633,7 +566,7 @@ export const ClassicSwap: React.FC<ClassicSwapProps> = ({
633
566
  type="text"
634
567
  value={sellAmount}
635
568
  onChange={(e) => handleSellAmountChange(e.target.value)}
636
- placeholder={`0 ${originToken?.symbol || ""}`}
569
+ placeholder={"0"}
637
570
  className={`w-full bg-transparent font-bold trails-text-primary placeholder:trails-text-muted border-none outline-none ${
638
571
  isLoadingQuote && tradeType === TradeType.EXACT_OUTPUT
639
572
  ? "animate-pulse"
@@ -652,45 +585,19 @@ export const ClassicSwap: React.FC<ClassicSwapProps> = ({
652
585
 
653
586
  {/* Token Selection Button */}
654
587
  <div className="relative">
655
- <button
656
- type="button"
657
- onClick={() => setShowSourceTokenSelector(true)}
658
- className={`flex items-center space-x-2 trails-border-radius-input px-2.5 py-1.5 border transition-colors cursor-pointer ${
659
- originToken
660
- ? "trails-bg-card hover:trails-hover-bg trails-border-primary"
661
- : "bg-blue-500 hover:bg-blue-600 border-blue-500 text-white"
662
- }`}
663
- >
664
- {originToken ? (
665
- <>
666
- <TokenImage
667
- symbol={originToken.symbol}
668
- imageUrl={originToken.imageUrl}
669
- chainId={originChainId}
670
- size={20}
671
- />
672
- <span className="font-medium trails-text-primary text-sm">
673
- {originToken.symbol}
674
- </span>
675
- <ChevronDown className="w-3.5 h-3.5 trails-text-muted" />
676
- </>
677
- ) : (
678
- <>
679
- <span className="font-medium text-sm text-white">
680
- Select Token
681
- </span>
682
- <ChevronDown className="w-3.5 h-3.5 text-white" />
683
- </>
684
- )}
685
- </button>
588
+ <TokenSelectorButton
589
+ token={originToken}
590
+ chainId={originChainId}
591
+ onSelect={() => setShowSourceTokenSelector(true)}
592
+ />
686
593
  </div>
687
594
  </div>
688
595
 
689
596
  {/* Bottom Info Row for sell */}
690
- <div className="mt-2 flex justify-between items-center">
597
+ <div className="mt-4 flex justify-between items-center">
691
598
  {/* USD Amount */}
692
599
  {originToken?.symbol && (
693
- <div className="text-xs trails-text-muted">
600
+ <div className="text-xs text-gray-500 dark:text-gray-400">
694
601
  ≈{" "}
695
602
  {tradeType === TradeType.EXACT_INPUT
696
603
  ? amountUsdDisplay || "$0.00"
@@ -700,25 +607,13 @@ export const ClassicSwap: React.FC<ClassicSwapProps> = ({
700
607
  </div>
701
608
  )}
702
609
 
703
- {/* Origin Token Balance */}
704
- {originToken && (
705
- <button
706
- type="button"
707
- className="text-xs trails-text-muted cursor-pointer hover:trails-hover-text transition-colors bg-transparent border-none p-0"
708
- onClick={() => {
709
- if (balanceFormatted) {
710
- const balance = parseFloat(balanceFormatted)
711
- if (!Number.isNaN(balance)) {
712
- setTradeType(TradeType.EXACT_INPUT)
713
- setSellAmount(balance.toFixed(6))
714
- setBuyAmount("")
715
- setLastInputType("sell")
716
- }
717
- }
718
- }}
719
- onKeyDown={(e) => {
720
- if (e.key === "Enter" || e.key === " ") {
721
- e.preventDefault()
610
+ {/* Origin Token Balance and Percentage Buttons */}
611
+ {originToken && balanceFormatted && (
612
+ <div className="flex items-center space-x-2">
613
+ <button
614
+ type="button"
615
+ className="text-xs text-gray-500 dark:text-gray-400 cursor-pointer hover:text-gray-700 dark:hover:text-gray-200 transition-colors bg-transparent border-none p-0"
616
+ onClick={() => {
722
617
  if (balanceFormatted) {
723
618
  const balance = parseFloat(balanceFormatted)
724
619
  if (!Number.isNaN(balance)) {
@@ -728,15 +623,42 @@ export const ClassicSwap: React.FC<ClassicSwapProps> = ({
728
623
  setLastInputType("sell")
729
624
  }
730
625
  }
731
- }
732
- }}
733
- title="Click to use full balance"
734
- >
735
- Balance:{" "}
736
- {isBalanceVisible
737
- ? `${balanceFormatted || "0.00"} ${originToken.symbol}`
738
- : "••••••"}
739
- </button>
626
+ }}
627
+ onKeyDown={(e) => {
628
+ if (e.key === "Enter" || e.key === " ") {
629
+ e.preventDefault()
630
+ if (balanceFormatted) {
631
+ const balance = parseFloat(balanceFormatted)
632
+ if (!Number.isNaN(balance)) {
633
+ setTradeType(TradeType.EXACT_INPUT)
634
+ setSellAmount(balance.toFixed(6))
635
+ setBuyAmount("")
636
+ setLastInputType("sell")
637
+ }
638
+ }
639
+ }
640
+ }}
641
+ title="Click to use full balance"
642
+ >
643
+ Balance:{" "}
644
+ {isBalanceVisible ? balanceFormatted || "0.00" : "••••••"}
645
+ </button>
646
+
647
+ {/* Percentage Buttons */}
648
+ <PercentageMaxButtons
649
+ userBalance={balanceFormatted}
650
+ isNativeToken={originToken.contractAddress === zeroAddress}
651
+ gasCostFormatted={prepareSendQuote?.gasCostFormatted}
652
+ chainId={originChainId || undefined}
653
+ onAmountSelect={(amount) => {
654
+ setTradeType(TradeType.EXACT_INPUT)
655
+ setSellAmount(amount)
656
+ setBuyAmount("")
657
+ setLastInputType("sell")
658
+ }}
659
+ className="opacity-100"
660
+ />
661
+ </div>
740
662
  )}
741
663
  </div>
742
664
  </div>
@@ -756,10 +678,22 @@ export const ClassicSwap: React.FC<ClassicSwapProps> = ({
756
678
  </div>
757
679
 
758
680
  {/* Output Section - Amount + Token Selection */}
759
- <div className="trails-bg-secondary trails-bg-secondary-hover trails-border-radius-container p-3 transition-all duration-200 border border-transparent focus-within:!bg-white dark:focus-within:!bg-gray-800 trails-focus-border-secondary min-h-[120px] flex flex-col">
681
+ <div className="pt-4 pb-4 trails-bg-secondary trails-bg-secondary-hover trails-border-radius-container p-3 transition-all duration-200 border border-transparent focus-within:!bg-white dark:focus-within:!bg-gray-800 trails-focus-border-secondary min-h-[120px] flex flex-col mb-4">
760
682
  {/* Buy Label */}
761
- <div className="text-sm font-medium trails-text-secondary mb-2 text-left">
762
- Buy
683
+ <div className="mb-4 flex justify-between items-center mb-2">
684
+ <div className="text-sm font-medium trails-text-secondary text-left m-0">
685
+ {mode === "fund" ? "Recipient" : "Buy"}
686
+ </div>
687
+ {toRecipient ? (
688
+ <div className="flex items-center space-x-2 text-black dark:text-white">
689
+ <Identicon value={toRecipient} size={16} />
690
+ <span className="text-sm font-medium">
691
+ {truncateAddress(toRecipient, 4, 2)}
692
+ </span>
693
+ </div>
694
+ ) : (
695
+ <RecipientSelectorButton />
696
+ )}
763
697
  </div>
764
698
 
765
699
  <div className="flex items-center space-x-2 flex-1">
@@ -775,7 +709,7 @@ export const ClassicSwap: React.FC<ClassicSwapProps> = ({
775
709
  }
776
710
  onChange={(e) => handleBuyAmountChange(e.target.value)}
777
711
  onFocus={handleBuyInputFocus}
778
- placeholder={`0 ${selectedDestToken?.symbol || ""}`}
712
+ placeholder={"0"}
779
713
  className={`w-full bg-transparent font-bold placeholder:trails-text-muted border-none outline-none ${
780
714
  !amount
781
715
  ? "text-gray-400 dark:text-gray-500"
@@ -783,7 +717,8 @@ export const ClassicSwap: React.FC<ClassicSwapProps> = ({
783
717
  } ${isLoadingQuote && tradeType === TradeType.EXACT_INPUT ? "animate-pulse" : ""}`}
784
718
  style={buyInputStyles}
785
719
  readOnly={
786
- tradeType === TradeType.EXACT_INPUT && isLoadingQuote
720
+ (tradeType === TradeType.EXACT_INPUT && isLoadingQuote) ||
721
+ !!toAmount
787
722
  }
788
723
  />
789
724
  {isLoadingQuote && tradeType === TradeType.EXACT_INPUT && (
@@ -794,46 +729,21 @@ export const ClassicSwap: React.FC<ClassicSwapProps> = ({
794
729
 
795
730
  {/* Destination Token Selection */}
796
731
  <div className="relative">
797
- <button
798
- type="button"
799
- onClick={() => setShowDestinationTokenSelector(true)}
800
- className={`flex items-center space-x-2 trails-border-radius-input px-2.5 py-1.5 border transition-colors cursor-pointer ${
801
- selectedDestToken
802
- ? "trails-bg-card hover:trails-hover-bg trails-border-primary"
803
- : "bg-blue-500 hover:bg-blue-600 border-blue-500 text-white"
804
- }`}
805
- >
806
- {selectedDestToken ? (
807
- <>
808
- <TokenImage
809
- symbol={selectedDestToken.symbol}
810
- imageUrl={selectedDestToken.imageUrl}
811
- chainId={(selectedDestToken as any)?.chainId}
812
- size={20}
813
- />
814
- <span className="font-medium trails-text-primary text-sm">
815
- {selectedDestToken.symbol}
816
- </span>
817
- <ChevronDown className="w-3.5 h-3.5 trails-text-muted" />
818
- </>
819
- ) : (
820
- <>
821
- <span className="font-medium text-sm text-white">
822
- Select Token
823
- </span>
824
- <ChevronDown className="w-3.5 h-3.5 text-white" />
825
- </>
826
- )}
827
- </button>
732
+ <TokenSelectorButton
733
+ token={selectedDestToken}
734
+ chainId={(selectedDestToken as any)?.chainId}
735
+ onSelect={() => setShowDestinationTokenSelector(true)}
736
+ unselectable={!!toToken}
737
+ />
828
738
  </div>
829
739
  </div>
830
740
 
831
741
  {/* Bottom Info Row */}
832
- <div className="mt-2 flex justify-between items-center">
742
+ <div className="mt-4 flex justify-between items-center">
833
743
  {/* Destination Amount USD from Quote */}
834
744
  {(prepareSendQuote?.destinationAmountUsdDisplay ||
835
745
  (isLoadingQuote && tradeType === TradeType.EXACT_INPUT)) && (
836
- <div className="text-xs trails-text-muted">
746
+ <div className="text-xs text-gray-500 dark:text-gray-400">
837
747
  ≈{" "}
838
748
  {isLoadingQuote && tradeType === TradeType.EXACT_INPUT
839
749
  ? "$0.00"
@@ -850,6 +760,14 @@ export const ClassicSwap: React.FC<ClassicSwapProps> = ({
850
760
  severity="warning"
851
761
  />
852
762
 
763
+ {/* Exchange/Contract Warning */}
764
+ <RefundWarning
765
+ fundMethod={fundMethod}
766
+ isSenderContractOnOrigin={false}
767
+ isSenderContractOnDestination={false}
768
+ isSequenceWallet={isSequenceWallet}
769
+ />
770
+
853
771
  {prepareSendQuote?.noSufficientBalance ? (
854
772
  <div className="px-2 py-3 rounded-lg bg-amber-500/10 border border-solid border-amber-500/30">
855
773
  <div className="flex items-center space-x-2">
@@ -877,7 +795,7 @@ export const ClassicSwap: React.FC<ClassicSwapProps> = ({
877
795
 
878
796
  {/* Quote Details */}
879
797
  {prepareSendQuote && (
880
- <div className="space-y-2">
798
+ <div className="mb-4">
881
799
  <QuoteDetails
882
800
  quote={prepareSendQuote}
883
801
  showContent={true}
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useState } from "react"
1
+ import React, { useEffect, useMemo, useState } from "react"
2
2
  import { ChevronRight, LogOut } from "lucide-react"
3
3
  import {
4
4
  useAccount,
@@ -36,7 +36,7 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = ({
36
36
  lastClickedWallet,
37
37
  showDisconnect = true,
38
38
  }) => {
39
- const { isConnected, address, connector } = useAccount()
39
+ const { address, connector } = useAccount()
40
40
  const connections = useConnections()
41
41
  const { switchAccount } = useSwitchAccount()
42
42
  const { setCurrentScreen } = useCurrentScreen()
@@ -45,6 +45,9 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = ({
45
45
  const connectors = useConnectors()
46
46
  const [error, setError] = useState<string | null>(null)
47
47
 
48
+ // Check if there are any connected accounts across all connectors
49
+ const isConnected = connections.length > 0
50
+
48
51
  useEffect(() => {
49
52
  if (error) {
50
53
  if (onError) {
@@ -105,13 +108,7 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = ({
105
108
  const connectedWallets = getConnectedWallets()
106
109
 
107
110
  // Get available browser wallets using EIP-6963 and injected providers
108
- const getAvailableBrowserWallets = (): Array<{
109
- connector: any
110
- walletId: string
111
- walletConfig: any
112
- name: string
113
- icon?: string
114
- }> => {
111
+ const allAvailableBrowserWallets = useMemo(() => {
115
112
  const filteredConnectors = connectors
116
113
  .filter((connector) => {
117
114
  // EIP-6963 compliant wallets will have type "injected" and be ready when installed
@@ -130,27 +127,6 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = ({
130
127
  (conn) => conn.connector.id === connector.id,
131
128
  )
132
129
 
133
- // Log for debugging EIP-6963 detection
134
- if (isInjected && isNotWalletConnect) {
135
- logger.console.log(
136
- "[trails-sdk] Detected browser wallet via EIP-6963:",
137
- {
138
- id: connector.id,
139
- name: connector.name,
140
- type: connector.type,
141
- uid: connector.uid,
142
- hasIcon: !!connector.icon,
143
- },
144
- )
145
- }
146
-
147
- // Log all connectors for debugging
148
- logger.console.log("[trails-sdk] All connector:", {
149
- id: connector.id,
150
- name: connector.name,
151
- type: connector.type,
152
- })
153
-
154
130
  return (
155
131
  isInjected &&
156
132
  isNotWalletConnect &&
@@ -181,9 +157,7 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = ({
181
157
  seenWalletIds.add(wallet.walletId)
182
158
  return true
183
159
  })
184
- }
185
-
186
- const allAvailableBrowserWallets = getAvailableBrowserWallets()
160
+ }, [connectors, allWallets, connections])
187
161
 
188
162
  // Handle switching to a different connected wallet
189
163
  const handleWalletSwitch = async (
@@ -259,11 +233,7 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = ({
259
233
 
260
234
  return (
261
235
  <div className="space-y-6">
262
- <ScreenHeader
263
- headerContent="Connect Wallet"
264
- headerContentAlign="left"
265
- showAccountActions={true}
266
- />
236
+ <ScreenHeader headerContent="Connect Wallet" headerContentAlign="left" />
267
237
 
268
238
  {isConnected ? (
269
239
  <div className="space-y-4">