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,7 +1,10 @@
1
- import { ChevronLeft } from "lucide-react"
1
+ import { ChevronLeft, X } from "lucide-react"
2
2
  import type React from "react"
3
- import { useAccount } from "wagmi"
3
+ import { useConnections } from "wagmi"
4
4
  import AccountActionsDropdown from "./AccountActionsDropdown.js"
5
+ import AccountIntentTransactionHistoryButton from "./AccountIntentTransactionHistoryButton.js"
6
+ import { useWidgetProps } from "../hooks/useWidgetProps.js"
7
+ import { useModal } from "../widget.js"
5
8
 
6
9
  interface ScreenHeaderProps {
7
10
  onBack?: () => void
@@ -19,42 +22,67 @@ export const ScreenHeader: React.FC<ScreenHeaderProps> = ({
19
22
  headerContentAlign = "left",
20
23
  showAccountActions = false,
21
24
  }) => {
22
- const { isConnected } = useAccount()
25
+ const connections = useConnections()
26
+ const { renderInline } = useWidgetProps()
27
+ const { closeModal, isModalOpen } = useModal()
28
+
29
+ // Check if there are any connected accounts across all connectors
30
+ const isConnected = connections.length > 0
31
+
32
+ // Show close button when in modal mode (not renderInline) and modal is open
33
+ const showCloseButton = !renderInline && isModalOpen
23
34
  return (
24
- <div className="relative w-full mb-4">
25
- {/* Left side - Back button (absolute positioned) */}
26
- {onBack && (
27
- <button
28
- type="button"
29
- onClick={onBack}
30
- className="absolute -left-2 top-1/2 -translate-y-1/2 -translate-x-0 w-6 h-6 flex-shrink-0 rounded-full transition-colors cursor-pointer text-gray-400 z-10 flex items-center justify-center hover:bg-gray-100 dark:hover:bg-gray-800"
35
+ <div className="flex items-center justify-between w-full mb-4">
36
+ {/* Left side - Back button */}
37
+ <div className="flex items-center">
38
+ {onBack && (
39
+ <button
40
+ type="button"
41
+ onClick={onBack}
42
+ className="flex h-8 w-8 justify-center items-center 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 mr-2"
43
+ title="Back"
44
+ >
45
+ <ChevronLeft className="h-4 w-4" />
46
+ </button>
47
+ )}
48
+
49
+ {/* Header content */}
50
+ <h2
51
+ className={`text-lg font-semibold ${
52
+ headerContentAlign === "center" ? "text-center" : "text-left"
53
+ } text-gray-900 dark:text-white`}
31
54
  >
32
- <ChevronLeft className="h-4 w-4" />
33
- </button>
34
- )}
55
+ {headerContent}
56
+ </h2>
57
+ </div>
35
58
 
36
- {/* Center - Header content */}
37
- <h2
38
- className={`text-lg font-semibold ${
39
- headerContentAlign === "left"
40
- ? onBack
41
- ? "text-left ml-8" // Add margin when back button exists to prevent overlap
42
- : "text-left" // No margin when no back button
43
- : "text-center" // Perfect center when center-aligned
44
- } ${"text-gray-900 dark:text-white"}`}
45
- >
46
- {headerContent}
47
- </h2>
59
+ {/* Right side - Content, Account Actions, and Close button */}
60
+ <div className="flex items-center gap-2">
61
+ {/* Right side content and Account Actions */}
62
+ {rightSideContent && (
63
+ <div className="text-right max-w-[280px]">{rightSideContent}</div>
64
+ )}
65
+ {isConnected && showAccountActions && (
66
+ <>
67
+ <div className="m-0">
68
+ <AccountIntentTransactionHistoryButton />
69
+ </div>
70
+ <AccountActionsDropdown />
71
+ </>
72
+ )}
48
73
 
49
- {/* Right side - Optional content and Account Actions */}
50
- {(rightSideContent || (isConnected && showAccountActions)) && (
51
- <div className="absolute right-0 top-1/2 -translate-y-1/2 -translate-x-0 flex items-center gap-2 z-10">
52
- {rightSideContent && (
53
- <div className="text-right max-w-[280px]">{rightSideContent}</div>
54
- )}
55
- {isConnected && showAccountActions && <AccountActionsDropdown />}
56
- </div>
57
- )}
74
+ {/* Close button (always rightmost) */}
75
+ {showCloseButton && (
76
+ <button
77
+ type="button"
78
+ onClick={closeModal}
79
+ className="flex h-8 w-8 justify-center items-center 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"
80
+ title="Close"
81
+ >
82
+ <X className="h-4 w-4" />
83
+ </button>
84
+ )}
85
+ </div>
58
86
  </div>
59
87
  )
60
88
  }
@@ -142,7 +142,8 @@ export const SlippageToleranceSettings: React.FC<
142
142
  onBlur={handleInputBlur}
143
143
  onKeyDown={handleKeyDown}
144
144
  placeholder="5"
145
- className="w-full px-2 py-1.5 text-sm border border-solid border-gray-200 dark:border-gray-700 trails-border-radius-input focus:ring-2 focus:ring-blue-500 focus:border-blue-500 trails-input pr-6"
145
+ className="w-full px-2 py-1.5 text-sm border border-solid border-gray-200 dark:border-gray-700 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 trails-input pr-6"
146
+ style={{ borderRadius: "10px" }}
146
147
  />
147
148
  <div className="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
148
149
  <span className="text-xs text-gray-500 dark:text-gray-400">%</span>
@@ -1,15 +1,11 @@
1
1
  import type React from "react"
2
- import { useEffect } from "react"
3
2
  import type { Account, WalletClient } from "viem"
4
3
  import type { TransactionState } from "../../transactions.js"
5
4
  import type { OnCompleteProps, Token } from "../hooks/useSendForm.js"
6
5
  import type { SupportedToken } from "../../tokens.js"
7
6
  import type { CheckoutOnHandlers } from "../hooks/useCheckout.js"
8
7
  import type { PrepareSendQuote } from "../../prepareSend.js"
9
- import { SimpleSwap } from "./SimpleSwap.js"
10
8
  import { ClassicSwap } from "./ClassicSwap.js"
11
- import { useSwapSettings } from "../hooks/useSwapSettings.js"
12
- import { useWidgetProps } from "../hooks/useWidgetProps.js"
13
9
 
14
10
  interface SwapProps {
15
11
  selectedToken: Token | null
@@ -17,13 +13,13 @@ interface SwapProps {
17
13
  onBack?: () => void
18
14
  onConfirm: () => void
19
15
  onComplete: (result: OnCompleteProps) => void
20
- account: Account
16
+ account?: Account
21
17
  toRecipient?: string
22
18
  toAmount?: string
23
19
  toChainId?: number
24
20
  toToken?: string
25
21
  toCalldata?: string
26
- walletClient: WalletClient
22
+ walletClient?: WalletClient
27
23
  onTransactionStateChange: (transactionStates: TransactionState[]) => void
28
24
  onError: (error: Error | string | null) => void
29
25
  onWaitingForWalletConfirm: (props: PrepareSendQuote) => void
@@ -46,48 +42,11 @@ interface SwapProps {
46
42
  recentTokens?: SupportedToken[]
47
43
  onRecentTokenSelect?: (token: SupportedToken) => void
48
44
  onTrackToken?: (token: any) => void
45
+ isSequenceWallet?: boolean
49
46
  }
50
47
 
51
48
  export const Swap: React.FC<SwapProps> = (props) => {
52
- const { swapMode } = useWidgetProps()
53
- const {
54
- isSimpleSwapMode: isSimpleMode,
55
- setIsSimpleSwapMode: setIsSimpleMode,
56
- } = useSwapSettings()
57
-
58
- // Update isSimpleMode when swapMode changes
59
- useEffect(() => {
60
- if (swapMode === "simple") {
61
- setIsSimpleMode(true)
62
- }
63
- }, [swapMode, setIsSimpleMode])
64
-
65
- // Render SimpleSwap or ClassicSwap based on mode
66
- if (isSimpleMode) {
67
- return (
68
- <SimpleSwap
69
- onBack={props.onBack}
70
- account={props.account}
71
- walletClient={props.walletClient}
72
- onTransactionStateChange={props.onTransactionStateChange}
73
- onError={props.onError}
74
- onWaitingForWalletConfirm={props.onWaitingForWalletConfirm}
75
- onConfirm={props.onConfirm}
76
- onComplete={props.onComplete}
77
- onSend={props.onSend}
78
- paymasterUrls={props.paymasterUrls}
79
- gasless={props.gasless}
80
- setWalletConfirmRetryHandler={props.setWalletConfirmRetryHandler}
81
- quoteProvider={props.quoteProvider}
82
- fundMethod={props.fundMethod}
83
- checkoutOnHandlers={props.checkoutOnHandlers}
84
- showHeader={true}
85
- onTokenSelectorVisibilityChange={() => {}}
86
- />
87
- )
88
- }
89
-
90
- // Default to ClassicSwap
49
+ // Always render ClassicSwap
91
50
  return <ClassicSwap {...props} />
92
51
  }
93
52
 
@@ -3,10 +3,8 @@ import type React from "react"
3
3
  import { useEffect, useRef, useState } from "react"
4
4
  // import { SwapDisplayMode } from "./SwapDisplayMode.js"
5
5
  import { SlippageToleranceSettings } from "./SlippageToleranceSettings.js"
6
- // import { useSwapSettings } from "../hooks/useSwapSettings.js"
7
6
 
8
7
  export const SwapSettings: React.FC = () => {
9
- //const { isSimpleSwapMode, setIsSimpleSwapModeWithStorage } = useSwapSettings()
10
8
  const [isSettingsDropdownOpen, setIsSettingsDropdownOpen] = useState(false)
11
9
  const settingsDropdownRef = useRef<HTMLDivElement>(null)
12
10
 
@@ -27,13 +25,8 @@ export const SwapSettings: React.FC = () => {
27
25
  }
28
26
  }, [isSettingsDropdownOpen])
29
27
 
30
- // const handleModeSelect = (isSimple: boolean) => {
31
- // setIsSimpleSwapModeWithStorage(isSimple)
32
- // setIsSettingsDropdownOpen(false)
33
- // }
34
-
35
28
  return (
36
- <div className="relative" ref={settingsDropdownRef}>
29
+ <div ref={settingsDropdownRef}>
37
30
  <button
38
31
  type="button"
39
32
  onClick={() => setIsSettingsDropdownOpen(!isSettingsDropdownOpen)}
@@ -47,12 +40,7 @@ export const SwapSettings: React.FC = () => {
47
40
  {isSettingsDropdownOpen && (
48
41
  <div className="absolute right-0 top-full mt-2 w-80 trails-bg-card rounded-lg shadow-lg border trails-border-primary z-20">
49
42
  <div className="p-4 space-y-4">
50
- {/* <SwapDisplayMode
51
- isSimpleMode={isSimpleSwapMode}
52
- onModeChange={handleModeSelect}
53
- /> */}
54
-
55
- <div className="border-t border-gray-200 dark:border-gray-700 pt-4">
43
+ <div>
56
44
  <SlippageToleranceSettings />
57
45
  </div>
58
46
  </div>
@@ -3,6 +3,7 @@ import { createContext, useContext, useEffect, useState } from "react"
3
3
  import type { Theme } from "../../theme.js"
4
4
  import { ThemeProvider as DesignSystemThemeProvider } from "@0xsequence/design-system"
5
5
  import { logger } from "../../logger.js"
6
+ import { DEFAULT_THEME } from "../../constants.js"
6
7
 
7
8
  interface ThemeContextType {
8
9
  theme: Theme
@@ -31,7 +32,7 @@ const getIsDark = (theme: Theme): boolean => {
31
32
 
32
33
  export const ThemeProvider: React.FC<ThemeProviderProps> = ({
33
34
  children,
34
- initialTheme = "auto",
35
+ initialTheme = DEFAULT_THEME,
35
36
  }) => {
36
37
  const [theme, setTheme] = useState<Theme>(initialTheme)
37
38
  const [isDark, setIsDark] = useState(getIsDark(initialTheme))
@@ -0,0 +1,40 @@
1
+ import type React from "react"
2
+ import { TokenImage } from "./TokenImage.js"
3
+
4
+ interface TokenDisplayNonSelectableProps {
5
+ symbol: string
6
+ imageUrl?: string
7
+ chainId: number
8
+ contractAddress: string
9
+ chainName?: string
10
+ }
11
+
12
+ export const TokenDisplayNonSelectable: React.FC<
13
+ TokenDisplayNonSelectableProps
14
+ > = ({ symbol, imageUrl, chainId, contractAddress, chainName }) => {
15
+ return (
16
+ <div className="relative max-w-[120px]">
17
+ <div className="flex items-center space-x-1.5 trails-bg-card trails-border-radius-input px-2.5 py-1.5 border trails-border-primary">
18
+ <div className="flex items-center flex-shrink-0">
19
+ <TokenImage
20
+ symbol={symbol}
21
+ imageUrl={imageUrl}
22
+ chainId={chainId}
23
+ contractAddress={contractAddress}
24
+ size={28}
25
+ />
26
+ </div>
27
+ <div className="flex flex-col items-start min-w-0 overflow-hidden">
28
+ <span className="font-bold trails-text-primary text-sm leading-tight truncate max-w-full text-left">
29
+ {symbol}
30
+ </span>
31
+ {chainName && (
32
+ <span className="text-xs trails-text-muted leading-tight truncate max-w-full text-left">
33
+ {chainName}
34
+ </span>
35
+ )}
36
+ </div>
37
+ </div>
38
+ </div>
39
+ )
40
+ }
@@ -1,19 +1,28 @@
1
1
  import React, { useMemo } from "react"
2
2
  import { ChainImage } from "./ChainImage.js"
3
3
  import { getCommonTokenImageUrl } from "../../tokens.js"
4
+ import { logger } from "../../logger.js"
4
5
 
5
6
  function normalizeImageUrl(
6
7
  imageUrl?: string | null,
7
8
  symbol?: string | null,
8
9
  chainId?: number | null,
10
+ contractAddress?: string | null,
9
11
  ) {
10
12
  if (symbol === "ETH") {
11
13
  return "https://assets.sequence.info/images/tokens/large/1/0x0000000000000000000000000000000000000000.webp"
12
14
  }
15
+ const commonImageUrl = getCommonTokenImageUrl({
16
+ symbol,
17
+ chainId,
18
+ contractAddress,
19
+ })
20
+ if (commonImageUrl) {
21
+ return commonImageUrl
22
+ }
23
+
13
24
  if (imageUrl) {
14
25
  return imageUrl.replace("/small/", "/large/")
15
- } else if (symbol) {
16
- return getCommonTokenImageUrl({ symbol, chainId })
17
26
  }
18
27
 
19
28
  return null
@@ -23,6 +32,7 @@ interface TokenImageProps {
23
32
  imageUrl?: string | null
24
33
  symbol?: string | null
25
34
  chainId?: number | null
35
+ contractAddress?: string | null
26
36
  size?: number
27
37
  }
28
38
 
@@ -30,12 +40,19 @@ export const TokenImage: React.FC<TokenImageProps> = ({
30
40
  imageUrl,
31
41
  symbol,
32
42
  chainId,
43
+ contractAddress,
33
44
  size = 24,
34
45
  }) => {
35
46
  const [imageError, setImageError] = React.useState(false)
36
47
  const effectiveImageUrl = useMemo(() => {
37
- return normalizeImageUrl(imageUrl, symbol, chainId)
38
- }, [imageUrl, symbol, chainId])
48
+ logger.console.log("[TokenImage] normalizeImageUrl", {
49
+ imageUrl,
50
+ symbol,
51
+ chainId,
52
+ contractAddress,
53
+ })
54
+ return normalizeImageUrl(imageUrl, symbol, chainId, contractAddress)
55
+ }, [imageUrl, symbol, chainId, contractAddress])
39
56
 
40
57
  const displaySymbol = symbol?.[0]?.toUpperCase() || "?"
41
58
 
@@ -47,7 +64,7 @@ export const TokenImage: React.FC<TokenImageProps> = ({
47
64
 
48
65
  return (
49
66
  <div
50
- className={`rounded-full flex items-center justify-center text-sm relative ${
67
+ className={`rounded-full flex items-center justify-center text-sm relative m-0 ${
51
68
  symbol !== "ETH" ? "bg-gray-400 dark:bg-gray-900" : ""
52
69
  }`}
53
70
  style={{
@@ -72,7 +72,6 @@ export const TokenList: React.FC<TokenListProps> = ({
72
72
  <div className="space-y-2">
73
73
  <ScreenHeader
74
74
  onBack={mode !== "fund" ? onBack : undefined}
75
- showAccountActions={true}
76
75
  headerContent={
77
76
  mode === "fund"
78
77
  ? "Fund with any token"
@@ -2,6 +2,7 @@ import { ChevronLeft, Copy } from "lucide-react"
2
2
  import type React from "react"
3
3
  import { useState, useMemo } from "react"
4
4
  import { AnimatePresence, motion } from "framer-motion"
5
+ import { zeroAddress } from "viem"
5
6
  import type { Token, TokenFormatted } from "../hooks/useTokenList.js"
6
7
  import { useTokenList } from "../hooks/useTokenList.js"
7
8
  import { useChainFilter } from "../hooks/useChainFilter.js"
@@ -14,6 +15,7 @@ import { ChainFilterDropdown } from "./ChainFilterDropdown.js"
14
15
  import { SearchInputField } from "./SearchInputField.js"
15
16
  import { truncateAddress } from "../../utils.js"
16
17
  import { logger } from "../../logger.js"
18
+ import { useAccount } from "wagmi"
17
19
 
18
20
  interface TokenSelectorProps {
19
21
  onTokenSelect: (selectedToken: Token) => void
@@ -55,6 +57,7 @@ export const TokenSelector: React.FC<TokenSelectorProps> = ({
55
57
  }) => {
56
58
  const [copiedAddress, setCopiedAddress] = useState<string | null>(null)
57
59
  const { isBalanceVisible } = useBalanceVisible()
60
+ const { address } = useAccount()
58
61
 
59
62
  const {
60
63
  searchQuery,
@@ -224,7 +227,9 @@ export const TokenSelector: React.FC<TokenSelectorProps> = ({
224
227
  ? "No tokens found matching your search."
225
228
  : fundMethod === "qr-code" || fundMethod === "exchange"
226
229
  ? ""
227
- : "No available tokens found"}
230
+ : address
231
+ ? "No available tokens found"
232
+ : ""}
228
233
  </p>
229
234
  </div>
230
235
  )}
@@ -295,6 +300,7 @@ export const TokenSelector: React.FC<TokenSelectorProps> = ({
295
300
  symbol={symbol}
296
301
  imageUrl={imageUrl}
297
302
  chainId={chainId}
303
+ contractAddress={contractAddress}
298
304
  size={32}
299
305
  />
300
306
  ) : (
@@ -329,7 +335,9 @@ export const TokenSelector: React.FC<TokenSelectorProps> = ({
329
335
  {/* Default state: show symbol */}
330
336
  <div
331
337
  className={`flex items-center transition-all duration-300 ease-in-out ${
332
- contractAddress
338
+ contractAddress &&
339
+ contractAddress.toLowerCase() !==
340
+ zeroAddress.toLowerCase()
333
341
  ? "group-hover:opacity-0 group-hover:transform group-hover:-translate-x-2"
334
342
  : ""
335
343
  } ${
@@ -345,58 +353,60 @@ export const TokenSelector: React.FC<TokenSelectorProps> = ({
345
353
  </span>
346
354
  </div>
347
355
 
348
- {/* Hover state: show address with copy button */}
349
- {contractAddress && (
350
- <div
351
- className={`absolute top-0 left-0 flex items-center transition-all duration-300 ease-in-out opacity-0 transform translate-x-2 ${
352
- !isSufficientBalance &&
353
- fundMethod !== "qr-code" &&
354
- fundMethod !== "exchange"
355
- ? "group-hover:opacity-70"
356
- : "group-hover:opacity-100"
357
- } group-hover:translate-x-0`}
358
- >
359
- <span className="text-xs text-gray-500 dark:text-gray-400 whitespace-nowrap">
360
- {truncateAddress(contractAddress)}
361
- </span>
362
- <button
363
- type="button"
364
- onClick={(e) =>
365
- handleCopyAddress(contractAddress, e)
366
- }
367
- className={`ml-1 p-0.5 rounded transition-all duration-200 cursor-pointer ${
368
- copiedAddress === contractAddress
369
- ? "bg-green-100 dark:bg-green-900/30"
370
- : "hover:bg-gray-200 dark:hover:bg-gray-600"
371
- }`}
372
- title={
373
- copiedAddress === contractAddress
374
- ? "Copied!"
375
- : "Copy full address"
376
- }
356
+ {/* Hover state: show address with copy button (only for non-zero addresses) */}
357
+ {contractAddress &&
358
+ contractAddress.toLowerCase() !==
359
+ zeroAddress.toLowerCase() && (
360
+ <div
361
+ className={`absolute top-0 left-0 flex items-center transition-all duration-300 ease-in-out opacity-0 transform translate-x-2 ${
362
+ !isSufficientBalance &&
363
+ fundMethod !== "qr-code" &&
364
+ fundMethod !== "exchange"
365
+ ? "group-hover:opacity-70"
366
+ : "group-hover:opacity-100"
367
+ } group-hover:translate-x-0`}
377
368
  >
378
- {copiedAddress === contractAddress ? (
379
- <svg
380
- className="w-3 h-3 text-green-600 dark:text-green-400"
381
- fill="none"
382
- viewBox="0 0 24 24"
383
- stroke="currentColor"
384
- aria-label="Copied"
385
- >
386
- <title>Copied</title>
387
- <path
388
- strokeLinecap="round"
389
- strokeLinejoin="round"
390
- strokeWidth={2}
391
- d="M5 13l4 4L19 7"
392
- />
393
- </svg>
394
- ) : (
395
- <Copy className="w-3 h-3 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300" />
396
- )}
397
- </button>
398
- </div>
399
- )}
369
+ <span className="text-xs text-gray-500 dark:text-gray-400 whitespace-nowrap">
370
+ {truncateAddress(contractAddress)}
371
+ </span>
372
+ <button
373
+ type="button"
374
+ onClick={(e) =>
375
+ handleCopyAddress(contractAddress, e)
376
+ }
377
+ className={`ml-1 p-0.5 rounded transition-all duration-200 cursor-pointer ${
378
+ copiedAddress === contractAddress
379
+ ? "bg-green-100 dark:bg-green-900/30"
380
+ : "hover:bg-gray-200 dark:hover:bg-gray-600"
381
+ }`}
382
+ title={
383
+ copiedAddress === contractAddress
384
+ ? "Copied!"
385
+ : "Copy full address"
386
+ }
387
+ >
388
+ {copiedAddress === contractAddress ? (
389
+ <svg
390
+ className="w-3 h-3 text-green-600 dark:text-green-400"
391
+ fill="none"
392
+ viewBox="0 0 24 24"
393
+ stroke="currentColor"
394
+ aria-label="Copied"
395
+ >
396
+ <title>Copied</title>
397
+ <path
398
+ strokeLinecap="round"
399
+ strokeLinejoin="round"
400
+ strokeWidth={2}
401
+ d="M5 13l4 4L19 7"
402
+ />
403
+ </svg>
404
+ ) : (
405
+ <Copy className="w-3 h-3 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300" />
406
+ )}
407
+ </button>
408
+ </div>
409
+ )}
400
410
  </div>
401
411
  </div>
402
412
 
@@ -0,0 +1,98 @@
1
+ import { ChevronRight } from "lucide-react"
2
+ import type React from "react"
3
+ import { useMemo } from "react"
4
+ import { useConnections } from "wagmi"
5
+ import { TokenImage } from "./TokenImage.js"
6
+ import { getChainInfo } from "../../chains.js"
7
+ import { useCurrentScreen } from "../hooks/useCurrentScreen.js"
8
+ import { useSelectedFundMethod } from "../hooks/useSelectedFundMethod.js"
9
+
10
+ interface TokenSelectorButtonProps {
11
+ token?: {
12
+ symbol: string
13
+ imageUrl?: string
14
+ contractAddress?: string
15
+ chainId?: number | null
16
+ } | null
17
+ chainId?: number | null
18
+ onSelect: () => void
19
+ className?: string
20
+ unselectable?: boolean
21
+ }
22
+
23
+ export const TokenSelectorButton: React.FC<TokenSelectorButtonProps> = ({
24
+ token,
25
+ chainId,
26
+ onSelect,
27
+ className = "flex items-center space-x-1.5 trails-border-radius-input px-2.5 py-1.5 border transition-all duration-200",
28
+ unselectable = false,
29
+ }) => {
30
+ const connections = useConnections()
31
+ const { setCurrentScreen } = useCurrentScreen()
32
+ const { selectedFundMethod } = useSelectedFundMethod()
33
+ const displayChainId = token?.chainId || chainId
34
+
35
+ // Check if there are any connected accounts across all connectors
36
+ const isConnected = connections.length > 0
37
+
38
+ const chainInfo = useMemo(() => {
39
+ return displayChainId ? getChainInfo(displayChainId) : null
40
+ }, [displayChainId])
41
+
42
+ const handleClick = () => {
43
+ if (unselectable) return
44
+
45
+ // If no wallet connected and fund method is "wallet", redirect to connect screen
46
+ if (!isConnected && selectedFundMethod === "wallet") {
47
+ setCurrentScreen("connect")
48
+ return
49
+ }
50
+
51
+ onSelect()
52
+ }
53
+
54
+ return (
55
+ <button
56
+ type="button"
57
+ onClick={handleClick}
58
+ disabled={unselectable}
59
+ className={`${className} ${token ? "max-w-[120px]" : ""} ${
60
+ token
61
+ ? "bg-white dark:bg-gray-900 border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-800 hover:border-gray-300 dark:hover:border-gray-600"
62
+ : "bg-blue-500 hover:bg-blue-600 border-blue-500 text-white"
63
+ } ${unselectable ? "cursor-default" : "cursor-pointer"}`}
64
+ >
65
+ {token ? (
66
+ <>
67
+ <div className="flex items-center flex-shrink-0">
68
+ <TokenImage
69
+ symbol={token.symbol}
70
+ imageUrl={token.imageUrl}
71
+ chainId={displayChainId}
72
+ contractAddress={token.contractAddress}
73
+ size={28}
74
+ />
75
+ </div>
76
+ <div className="flex flex-col items-start min-w-0 overflow-hidden">
77
+ <span className="font-bold trails-text-primary text-sm leading-tight truncate max-w-full text-left">
78
+ {token.symbol}
79
+ </span>
80
+ {chainInfo && (
81
+ <span className="text-xs trails-text-muted leading-tight truncate max-w-full text-left">
82
+ {chainInfo.name}
83
+ </span>
84
+ )}
85
+ </div>
86
+ {!unselectable && (
87
+ <ChevronRight className="w-3.5 h-3.5 trails-text-muted flex-shrink-0" />
88
+ )}
89
+ </>
90
+ ) : (
91
+ <>
92
+ <span className="font-medium text-sm text-white">Select Token</span>
93
+ {!unselectable && <ChevronRight className="w-3.5 h-3.5 text-white" />}
94
+ </>
95
+ )}
96
+ </button>
97
+ )
98
+ }