0xtrails 0.2.4 → 0.2.5

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 (161) hide show
  1. package/dist/aave.d.ts +8 -0
  2. package/dist/aave.d.ts.map +1 -1
  3. package/dist/{ccip-BlV1Mry3.js → ccip-CXlshvBY.js} +1 -1
  4. package/dist/config.d.ts +1 -1
  5. package/dist/config.d.ts.map +1 -1
  6. package/dist/constants.d.ts +1 -0
  7. package/dist/constants.d.ts.map +1 -1
  8. package/dist/error.d.ts +1 -0
  9. package/dist/error.d.ts.map +1 -1
  10. package/dist/estimate.d.ts +52 -0
  11. package/dist/estimate.d.ts.map +1 -1
  12. package/dist/{index-BNWCIGfQ.js → index-_QuyGrjU.js} +72332 -72246
  13. package/dist/index.js +2 -2
  14. package/dist/intents.d.ts +40 -0
  15. package/dist/intents.d.ts.map +1 -1
  16. package/dist/metaTxnMonitor.d.ts +3 -3
  17. package/dist/metaTxnMonitor.d.ts.map +1 -1
  18. package/dist/metaTxns.d.ts +3 -3
  19. package/dist/metaTxns.d.ts.map +1 -1
  20. package/dist/morpho.d.ts +8 -0
  21. package/dist/morpho.d.ts.map +1 -1
  22. package/dist/prepareSend.d.ts +16 -6
  23. package/dist/prepareSend.d.ts.map +1 -1
  24. package/dist/queryParams.d.ts.map +1 -1
  25. package/dist/relayer.d.ts +6 -6
  26. package/dist/relayer.d.ts.map +1 -1
  27. package/dist/sequenceWallet.d.ts +2 -2
  28. package/dist/sequenceWallet.d.ts.map +1 -1
  29. package/dist/tokens.d.ts.map +1 -1
  30. package/dist/wallets.d.ts.map +1 -1
  31. package/dist/widget/components/AccountActionsDropdown.d.ts.map +1 -1
  32. package/dist/widget/components/AccountSettings.d.ts.map +1 -1
  33. package/dist/widget/components/ClassicSwap.d.ts +2 -0
  34. package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
  35. package/dist/widget/components/ConnectWallet.d.ts.map +1 -1
  36. package/dist/widget/components/ConnectedWallets.d.ts +4 -0
  37. package/dist/widget/components/ConnectedWallets.d.ts.map +1 -1
  38. package/dist/widget/components/Earn.d.ts.map +1 -1
  39. package/dist/widget/components/Fund.d.ts.map +1 -1
  40. package/dist/widget/components/FundMethods.d.ts.map +1 -1
  41. package/dist/widget/components/{FundSendForm.d.ts → FundSwap.d.ts} +11 -5
  42. package/dist/widget/components/FundSwap.d.ts.map +1 -0
  43. package/dist/widget/components/FundingMethodSelectorButton.d.ts +4 -0
  44. package/dist/widget/components/FundingMethodSelectorButton.d.ts.map +1 -0
  45. package/dist/widget/components/Modal.d.ts.map +1 -1
  46. package/dist/widget/components/Pay.d.ts.map +1 -1
  47. package/dist/widget/components/PercentageMaxButtons.d.ts +12 -0
  48. package/dist/widget/components/PercentageMaxButtons.d.ts.map +1 -0
  49. package/dist/widget/components/{PaySendForm.d.ts → PoolDeposit.d.ts} +11 -34
  50. package/dist/widget/components/PoolDeposit.d.ts.map +1 -0
  51. package/dist/widget/components/{SimpleSwap.d.ts → PoolWithdraw.d.ts} +16 -8
  52. package/dist/widget/components/PoolWithdraw.d.ts.map +1 -0
  53. package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
  54. package/dist/widget/components/Receive.d.ts.map +1 -1
  55. package/dist/widget/components/RecipientSelectorButton.d.ts +4 -0
  56. package/dist/widget/components/RecipientSelectorButton.d.ts.map +1 -0
  57. package/dist/widget/components/Recipients.d.ts.map +1 -1
  58. package/dist/widget/components/RequiredPropsError.d.ts +8 -0
  59. package/dist/widget/components/RequiredPropsError.d.ts.map +1 -0
  60. package/dist/widget/components/ScreenHeader.d.ts.map +1 -1
  61. package/dist/widget/components/SlippageToleranceSettings.d.ts.map +1 -1
  62. package/dist/widget/components/Swap.d.ts +1 -0
  63. package/dist/widget/components/Swap.d.ts.map +1 -1
  64. package/dist/widget/components/SwapSettings.d.ts.map +1 -1
  65. package/dist/widget/components/TokenImage.d.ts +1 -0
  66. package/dist/widget/components/TokenImage.d.ts.map +1 -1
  67. package/dist/widget/components/TokenList.d.ts.map +1 -1
  68. package/dist/widget/components/TokenSelector.d.ts.map +1 -1
  69. package/dist/widget/components/TokenSelectorButton.d.ts +16 -0
  70. package/dist/widget/components/TokenSelectorButton.d.ts.map +1 -0
  71. package/dist/widget/components/UserPreferences.d.ts.map +1 -1
  72. package/dist/widget/components/WaasFeeOptions.d.ts +8 -0
  73. package/dist/widget/components/WaasFeeOptions.d.ts.map +1 -0
  74. package/dist/widget/components/WalletConfirmation.d.ts.map +1 -1
  75. package/dist/widget/components/WalletList.d.ts.map +1 -1
  76. package/dist/widget/css/compiled.css +2 -0
  77. package/dist/widget/css/index.css +554 -0
  78. package/dist/widget/hooks/useBack.d.ts +1 -0
  79. package/dist/widget/hooks/useBack.d.ts.map +1 -1
  80. package/dist/widget/hooks/useCheckout.d.ts +1 -1
  81. package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
  82. package/dist/widget/hooks/useCurrentScreen.d.ts +1 -1
  83. package/dist/widget/hooks/useCurrentScreen.d.ts.map +1 -1
  84. package/dist/widget/hooks/useDefaultTokenSelection.d.ts +3 -3
  85. package/dist/widget/hooks/useDefaultTokenSelection.d.ts.map +1 -1
  86. package/dist/widget/hooks/usePayMessage.d.ts.map +1 -1
  87. package/dist/widget/hooks/useSelectedFundMethod.d.ts +12 -0
  88. package/dist/widget/hooks/useSelectedFundMethod.d.ts.map +1 -0
  89. package/dist/widget/hooks/useSelectedRecipient.d.ts.map +1 -1
  90. package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
  91. package/dist/widget/index.js +1 -1
  92. package/dist/widget/widget.d.ts +4 -4
  93. package/dist/widget/widget.d.ts.map +1 -1
  94. package/package.json +18 -12
  95. package/src/aave.ts +32 -0
  96. package/src/config.ts +12 -4
  97. package/src/constants.ts +2 -0
  98. package/src/error.ts +19 -1
  99. package/src/estimate.ts +416 -5
  100. package/src/intents.ts +161 -11
  101. package/src/metaTxnMonitor.ts +3 -3
  102. package/src/metaTxns.ts +3 -5
  103. package/src/morpho.ts +32 -0
  104. package/src/prepareSend.ts +503 -166
  105. package/src/queryParams.ts +2 -1
  106. package/src/relayer.ts +11 -11
  107. package/src/sequenceWallet.ts +2 -2
  108. package/src/tokens.ts +7 -1
  109. package/src/wallets.ts +8 -0
  110. package/src/widget/compiled.css +2 -2
  111. package/src/widget/components/AccountActionsDropdown.tsx +3 -13
  112. package/src/widget/components/AccountSettings.tsx +6 -24
  113. package/src/widget/components/ClassicSwap.tsx +111 -155
  114. package/src/widget/components/ConnectWallet.tsx +4 -37
  115. package/src/widget/components/ConnectedWallets.tsx +113 -58
  116. package/src/widget/components/Earn.tsx +73 -589
  117. package/src/widget/components/Fund.tsx +31 -82
  118. package/src/widget/components/FundMethods.tsx +82 -159
  119. package/src/widget/components/FundSwap.tsx +52 -0
  120. package/src/widget/components/FundingMethodSelectorButton.tsx +60 -0
  121. package/src/widget/components/Modal.tsx +6 -2
  122. package/src/widget/components/Pay.tsx +183 -208
  123. package/src/widget/components/PercentageMaxButtons.tsx +77 -0
  124. package/src/widget/components/PoolDeposit.tsx +593 -0
  125. package/src/widget/components/PoolWithdraw.tsx +903 -0
  126. package/src/widget/components/QuoteDetails.tsx +22 -8
  127. package/src/widget/components/Receive.tsx +0 -2
  128. package/src/widget/components/RecipientSelectorButton.tsx +42 -0
  129. package/src/widget/components/Recipients.tsx +62 -156
  130. package/src/widget/components/RequiredPropsError.tsx +33 -0
  131. package/src/widget/components/ScreenHeader.tsx +5 -1
  132. package/src/widget/components/SlippageToleranceSettings.tsx +2 -1
  133. package/src/widget/components/Swap.tsx +2 -43
  134. package/src/widget/components/SwapSettings.tsx +2 -14
  135. package/src/widget/components/TokenImage.tsx +21 -4
  136. package/src/widget/components/TokenList.tsx +0 -1
  137. package/src/widget/components/TokenSelector.tsx +1 -0
  138. package/src/widget/components/TokenSelectorButton.tsx +75 -0
  139. package/src/widget/components/UserPreferences.tsx +6 -24
  140. package/src/widget/components/WaasFeeOptions.tsx +331 -0
  141. package/src/widget/components/WalletConfirmation.tsx +55 -3
  142. package/src/widget/components/WalletList.tsx +4 -2
  143. package/src/widget/hooks/useBack.tsx +2 -0
  144. package/src/widget/hooks/useCheckout.ts +36 -20
  145. package/src/widget/hooks/useCurrentScreen.tsx +1 -0
  146. package/src/widget/hooks/useDefaultTokenSelection.tsx +104 -28
  147. package/src/widget/hooks/usePayMessage.tsx +86 -11
  148. package/src/widget/hooks/useSelectedFundMethod.tsx +41 -0
  149. package/src/widget/hooks/useSelectedRecipient.tsx +10 -0
  150. package/src/widget/hooks/useSendForm.ts +24 -2
  151. package/src/widget/index.css +27 -0
  152. package/src/widget/widget.tsx +169 -111
  153. package/dist/widget/components/FundSendForm.d.ts.map +0 -1
  154. package/dist/widget/components/PaySendForm.d.ts.map +0 -1
  155. package/dist/widget/components/SimpleSwap.d.ts.map +0 -1
  156. package/dist/widget/hooks/useSwapSettings.d.ts +0 -16
  157. package/dist/widget/hooks/useSwapSettings.d.ts.map +0 -1
  158. package/src/widget/components/FundSendForm.tsx +0 -903
  159. package/src/widget/components/PaySendForm.tsx +0 -869
  160. package/src/widget/components/SimpleSwap.tsx +0 -983
  161. package/src/widget/hooks/useSwapSettings.tsx +0 -100
@@ -83,7 +83,7 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
83
83
 
84
84
  {/* More Details Button - only visible when collapsed */}
85
85
  {!isExpanded && (
86
- <div className={`flex justify-center ${swapMode ? "" : "mb-4"}`}>
86
+ <div className={`flex justify-center`}>
87
87
  {swapMode ? (
88
88
  <button
89
89
  type="button"
@@ -161,10 +161,10 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
161
161
  <button
162
162
  type="button"
163
163
  onClick={() => setIsExpanded(true)}
164
- className="w-full flex items-center justify-center gap-2 py-1 px-4 trails-border-radius-button transition-colors cursor-pointer text-xs text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300"
165
- aria-label="Show more details"
164
+ className="w-full max-w-md flex items-center justify-between gap-2 py-1 px-1 trails-border-radius-button transition-colors cursor-pointer text-xs text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300"
165
+ aria-label="Show transaction details"
166
166
  >
167
- <span>More Details</span>
167
+ <span>Transaction details</span>
168
168
  <svg
169
169
  className="w-3 h-3 transition-transform duration-300 ease-out"
170
170
  fill="none"
@@ -191,9 +191,13 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
191
191
  isExpanded ? "max-h-[250px] opacity-100" : "max-h-0 opacity-0"
192
192
  }`}
193
193
  >
194
- <div className="p-4 rounded-lg text-sm space-y-4 trails-bg-secondary">
194
+ <div
195
+ className={`text-sm ${swapMode ? "p-2 space-y-2" : "p-4 rounded-lg space-y-4 trails-bg-secondary"}`}
196
+ >
195
197
  {/* Close Button - only visible when expanded, at top center */}
196
- <div className="flex justify-center mb-4 -mt-2">
198
+ <div
199
+ className={`flex justify-center ${swapMode ? "mb-2 -mt-1" : "mb-4 -mt-2"}`}
200
+ >
197
201
  {swapMode ? (
198
202
  <button
199
203
  type="button"
@@ -367,6 +371,7 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
367
371
  imageUrl={quote.originToken.imageUrl}
368
372
  symbol={quote.originToken.symbol}
369
373
  chainId={quote.originChain.id}
374
+ contractAddress={quote.originToken.contractAddress}
370
375
  size={16}
371
376
  />
372
377
  {quote.originAmountDisplay} {quote.originToken.symbol}
@@ -393,6 +398,9 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
393
398
  imageUrl={quote.originToken.imageUrl}
394
399
  symbol={quote.originToken.symbol}
395
400
  chainId={quote.originChain.id}
401
+ contractAddress={
402
+ quote.originToken.contractAddress
403
+ }
396
404
  size={16}
397
405
  />
398
406
  {quote.originAmountDisplay}{" "}
@@ -430,6 +438,9 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
430
438
  imageUrl={quote.destinationToken.imageUrl}
431
439
  symbol={quote.destinationToken.symbol}
432
440
  chainId={quote.destinationChain.id}
441
+ contractAddress={
442
+ quote.destinationToken.contractAddress
443
+ }
433
444
  size={16}
434
445
  />
435
446
  {quote.destinationAmountDisplay}{" "}
@@ -457,6 +468,9 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
457
468
  imageUrl={quote.destinationToken.imageUrl}
458
469
  symbol={quote.destinationToken.symbol}
459
470
  chainId={quote.destinationChain.id}
471
+ contractAddress={
472
+ quote.destinationToken.contractAddress
473
+ }
460
474
  size={16}
461
475
  />
462
476
  {quote.destinationAmountDisplay}{" "}
@@ -665,7 +679,7 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
665
679
  </div>
666
680
  )}
667
681
 
668
- {quote?.quoteProvider && (
682
+ {quote?.quoteProvider?.name && (
669
683
  <div className="flex justify-between items-center">
670
684
  <span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
671
685
  {quote.originChain.id === quote.destinationChain.id
@@ -766,7 +780,7 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
766
780
  )}
767
781
 
768
782
  {/* Children content */}
769
- {children && <div className="space-y-2">{children}</div>}
783
+ {children && <div className="mb-0">{children}</div>}
770
784
  </div>
771
785
  </div>
772
786
  </div>
@@ -60,7 +60,6 @@ export const Receive: React.FC<ReceiveProps> = ({
60
60
  onBack={onBack}
61
61
  headerContent="Receive"
62
62
  headerContentAlign="left"
63
- showAccountActions={true}
64
63
  />
65
64
 
66
65
  <div className="flex flex-col justify-center min-h-full space-y-6 pt-8">
@@ -97,7 +96,6 @@ export const Receive: React.FC<ReceiveProps> = ({
97
96
  onBack={onBack}
98
97
  headerContent={`Pay ${ensName ? ensName : truncateAddress(resolvedAddress)}`}
99
98
  headerContentAlign="left"
100
- showAccountActions={true}
101
99
  />
102
100
 
103
101
  <div className="flex flex-col justify-center min-h-full space-y-6 pt-2">
@@ -0,0 +1,42 @@
1
+ import { ChevronRight } from "lucide-react"
2
+ import type React from "react"
3
+ import { truncateAddress } from "../../utils.js"
4
+ import { Identicon } from "./Identicon.js"
5
+ import { useBack } from "../hooks/useBack.js"
6
+ import { useSelectedRecipient } from "../hooks/useSelectedRecipient.js"
7
+
8
+ export const RecipientSelectorButton: React.FC = () => {
9
+ const { setCurrentScreenWithBack } = useBack()
10
+ const { selectedRecipient } = useSelectedRecipient()
11
+
12
+ const handleClick = () => {
13
+ setCurrentScreenWithBack("recipients")
14
+ }
15
+
16
+ return (
17
+ <button
18
+ type="button"
19
+ onClick={handleClick}
20
+ className="flex items-center space-x-2 text-blue-500 hover:text-blue-600 transition-colors cursor-pointer bg-transparent border-none p-0"
21
+ title={
22
+ selectedRecipient
23
+ ? `Selected: ${selectedRecipient}`
24
+ : "Select recipient"
25
+ }
26
+ >
27
+ {selectedRecipient ? (
28
+ <>
29
+ <Identicon value={selectedRecipient} size={16} />
30
+ <span className="text-sm font-medium">
31
+ {truncateAddress(selectedRecipient, 4, 2)}
32
+ </span>
33
+ </>
34
+ ) : (
35
+ <span className="text-sm font-medium">Select Recipient</span>
36
+ )}
37
+ <ChevronRight className="w-4 h-4" />
38
+ </button>
39
+ )
40
+ }
41
+
42
+ export default RecipientSelectorButton
@@ -1,7 +1,7 @@
1
1
  import { useEffect, useState, useCallback } from "react"
2
2
  import type React from "react"
3
3
  import { isAddress } from "viem"
4
- import { Copy, RotateCcw } from "lucide-react"
4
+ import { Copy, RotateCcw, ChevronRight } from "lucide-react"
5
5
  import { useAccount, useConnections } from "wagmi"
6
6
  import { ScreenHeader } from "./ScreenHeader.js"
7
7
  import { SearchInputField } from "./SearchInputField.js"
@@ -12,8 +12,8 @@ import { useRecipients, type RecentRecipient } from "../hooks/useRecipients.js"
12
12
  import { useResolveEnsAddress, useResolveEnsName } from "../../ens.js"
13
13
  import { truncateAddress } from "../../utils.js"
14
14
  import { logger } from "../../logger.js"
15
- import { useMode } from "../hooks/useMode.js"
16
15
  import { useWallets, wagmiConnectorToWalletId } from "../../wallets.js"
16
+ import { ConnectedWallets } from "./ConnectedWallets.js"
17
17
 
18
18
  interface RecipientsProps {
19
19
  onBack?: () => void
@@ -26,7 +26,6 @@ export const Recipients: React.FC<RecipientsProps> = ({
26
26
  selectedRecipient = "",
27
27
  onRecipientSelect,
28
28
  }) => {
29
- const { mode } = useMode()
30
29
  const { setCurrentScreen } = useCurrentScreen()
31
30
  const { setSelectedRecipient } = useSelectedRecipient()
32
31
  const { recentRecipients, addRecentRecipient, clearRecentRecipients } =
@@ -136,9 +135,9 @@ export const Recipients: React.FC<RecipientsProps> = ({
136
135
  logger.console.log("[trails-sdk] Selected recent recipient:", recipient)
137
136
  setSelectedRecipient(recipient.address)
138
137
  onRecipientSelect?.(recipient.address)
139
- setCurrentScreen(mode === "pay" ? "send-form" : "fund-form")
138
+ setCurrentScreen("home")
140
139
  },
141
- [setSelectedRecipient, onRecipientSelect, setCurrentScreen, mode],
140
+ [setSelectedRecipient, onRecipientSelect, setCurrentScreen],
142
141
  )
143
142
 
144
143
  // Handle connected wallet selection
@@ -150,9 +149,9 @@ export const Recipients: React.FC<RecipientsProps> = ({
150
149
  )
151
150
  setSelectedRecipient(walletAddress)
152
151
  onRecipientSelect?.(walletAddress)
153
- setCurrentScreen(mode === "pay" ? "send-form" : "fund-form")
152
+ setCurrentScreen("home")
154
153
  },
155
- [setSelectedRecipient, onRecipientSelect, setCurrentScreen, mode],
154
+ [setSelectedRecipient, onRecipientSelect, setCurrentScreen],
156
155
  )
157
156
 
158
157
  // Handle copy to clipboard with success indication
@@ -202,7 +201,6 @@ export const Recipients: React.FC<RecipientsProps> = ({
202
201
  onBack={onBack}
203
202
  headerContent="Recipient address"
204
203
  headerContentAlign="left"
205
- showAccountActions={true}
206
204
  />
207
205
 
208
206
  <div className="space-y-4">
@@ -223,14 +221,23 @@ export const Recipients: React.FC<RecipientsProps> = ({
223
221
  )}
224
222
  </div>
225
223
 
224
+ {/* Connected Wallets - only show when no input */}
225
+ {connectedWallets.length > 0 && !recipientInput.trim() && (
226
+ <ConnectedWallets
227
+ showConnectNewWallet={true}
228
+ onWalletSelect={handleConnectedWalletSelect}
229
+ backScreen="recipients"
230
+ />
231
+ )}
232
+
226
233
  {/* Recent Recipients */}
227
234
  {recentRecipients.length > 0 && (
228
235
  <div className="space-y-2">
229
236
  <div className="text-sm font-medium text-gray-700 dark:text-gray-300 text-left">
230
- Recents
237
+ Recent wallets
231
238
  </div>
232
- <div className="space-y-1 max-h-48 overflow-y-auto trails-scrollbar">
233
- {recentRecipients.map((recipient) => {
239
+ <div className="trails-border-radius-container border trails-border-primary">
240
+ {recentRecipients.map((recipient, index) => {
234
241
  // Only highlight if search field contains a valid address that matches this recipient
235
242
  const searchQuery = recipientInput.trim()
236
243
  const isHighlighted =
@@ -240,53 +247,51 @@ export const Recipients: React.FC<RecipientsProps> = ({
240
247
  searchQuery.trim().toLowerCase()
241
248
 
242
249
  return (
243
- <button
244
- key={recipient.address}
245
- type="button"
246
- className={`w-full py-2 px-4 flex items-center space-x-3 transition-all duration-200 trails-border-radius-list-button cursor-pointer group ${
247
- isHighlighted
248
- ? "trails-list-item-selected border border-blue-200 dark:border-blue-800"
249
- : "trails-list-item"
250
- }`}
251
- onClick={() => handleRecentRecipientSelect(recipient)}
252
- onKeyDown={(e) => {
253
- if (e.key === "Enter" || e.key === " ") {
254
- e.preventDefault()
255
- handleRecentRecipientSelect(recipient)
256
- }
257
- }}
258
- aria-label={`Select recipient ${recipient.ensName || recipient.address}`}
259
- >
260
- {/* Identicon */}
261
- <div className="relative flex-shrink-0 mr-2">
262
- <Identicon
263
- value={recipient.address}
264
- size={32}
265
- className="flex-shrink-0"
266
- />
267
- </div>
268
-
269
- <div className="flex-1 min-w-0 text-left">
270
- <div className="flex items-start">
271
- <div className="flex-1">
272
- <div className="flex items-center">
273
- <span className="text-sm font-medium text-gray-900 dark:text-white">
250
+ <div key={recipient.address}>
251
+ <button
252
+ type="button"
253
+ className={`w-full text-left px-3 py-4 text-sm flex items-center justify-between cursor-pointer transition-colors ${
254
+ isHighlighted
255
+ ? "trails-list-item-selected border border-blue-200 dark:border-blue-800"
256
+ : "trails-text-primary trails-hover-bg"
257
+ }`}
258
+ onClick={() => handleRecentRecipientSelect(recipient)}
259
+ onKeyDown={(e) => {
260
+ if (e.key === "Enter" || e.key === " ") {
261
+ e.preventDefault()
262
+ handleRecentRecipientSelect(recipient)
263
+ }
264
+ }}
265
+ aria-label={`Select recipient ${recipient.ensName || recipient.address}`}
266
+ >
267
+ <div className="flex items-center gap-3">
268
+ <Identicon
269
+ value={recipient.address}
270
+ size={32}
271
+ className="flex-shrink-0"
272
+ />
273
+ <div className="text-left">
274
+ <div className="flex items-center space-x-1">
275
+ <span className="text-sm font-bold">
274
276
  {truncateAddress(recipient.address, 8, 4)}
275
277
  </span>
276
- <button
277
- type="button"
278
- onClick={(e) =>
278
+ <div
279
+ onClick={(e) => {
280
+ e.preventDefault()
281
+ e.stopPropagation()
279
282
  handleCopyAddress(recipient.address, e)
280
- }
281
- className={`ml-1 p-0.5 rounded opacity-0 group-hover:opacity-100 transition-all duration-200 cursor-pointer ${
283
+ }}
284
+ onMouseDown={(e) => e.stopPropagation()}
285
+ onMouseUp={(e) => e.stopPropagation()}
286
+ className={`p-0.5 rounded transition-all duration-200 cursor-pointer z-10 relative ${
282
287
  copiedAddress === recipient.address
283
- ? "bg-green-100 dark:bg-green-900/30 opacity-100"
288
+ ? "bg-green-100 dark:bg-green-900/30"
284
289
  : "hover:bg-gray-200 dark:hover:bg-gray-600"
285
290
  }`}
286
291
  title={
287
292
  copiedAddress === recipient.address
288
293
  ? "Copied!"
289
- : "Copy address"
294
+ : "Copy full address"
290
295
  }
291
296
  >
292
297
  {copiedAddress === recipient.address ? (
@@ -308,7 +313,7 @@ export const Recipients: React.FC<RecipientsProps> = ({
308
313
  ) : (
309
314
  <Copy className="w-3 h-3 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300" />
310
315
  )}
311
- </button>
316
+ </div>
312
317
  </div>
313
318
  {recipient.ensName && (
314
319
  <div className="text-xs text-gray-500 dark:text-gray-400">
@@ -317,112 +322,13 @@ export const Recipients: React.FC<RecipientsProps> = ({
317
322
  )}
318
323
  </div>
319
324
  </div>
320
- </div>
321
- </button>
322
- )
323
- })}
324
- </div>
325
- </div>
326
- )}
327
-
328
- {/* Connected Wallets - only show when no input */}
329
- {connectedWallets.length > 0 && !recipientInput.trim() && (
330
- <div className="space-y-2">
331
- <div className="flex items-center gap-2">
332
- <div className="text-sm font-medium text-gray-700 dark:text-gray-300 text-left">
333
- Connected Wallets
334
- </div>
335
- </div>
336
- <div className="space-y-1 max-h-48 overflow-y-auto trails-scrollbar">
337
- {connectedWallets.map((wallet) => {
338
- // Only highlight if search field contains a valid address that matches this wallet
339
- const searchQuery = recipientInput.trim()
340
- const isHighlighted =
341
- searchQuery &&
342
- isAddress(searchQuery) &&
343
- wallet.address.toLowerCase() ===
344
- searchQuery.trim().toLowerCase()
345
-
346
- return (
347
- <button
348
- key={wallet.address}
349
- type="button"
350
- className={`w-full py-2 px-4 flex items-center space-x-3 transition-all duration-200 trails-border-radius-list-button cursor-pointer group ${
351
- isHighlighted
352
- ? "trails-list-item-selected border border-blue-200 dark:border-blue-800"
353
- : "trails-list-item"
354
- }`}
355
- onClick={() => handleConnectedWalletSelect(wallet.address)}
356
- onKeyDown={(e) => {
357
- if (e.key === "Enter" || e.key === " ") {
358
- e.preventDefault()
359
- handleConnectedWalletSelect(wallet.address)
360
- }
361
- }}
362
- aria-label={`Select wallet ${wallet.walletConfig?.name || "Wallet"} - ${wallet.address}`}
363
- >
364
- {/* Identicon */}
365
- <div className="relative flex-shrink-0 mr-2">
366
- <Identicon
367
- value={wallet.address}
368
- size={32}
369
- className="flex-shrink-0"
370
- />
371
- </div>
372
-
373
- <div className="flex-1 min-w-0 text-left">
374
- <div className="flex items-start">
375
- <div className="flex-1">
376
- <div className="flex items-center">
377
- <span className="text-sm font-medium text-gray-900 dark:text-white">
378
- {truncateAddress(wallet.address, 8, 4)}
379
- </span>
380
- <button
381
- type="button"
382
- onClick={(e) =>
383
- handleCopyAddress(wallet.address, e)
384
- }
385
- className={`ml-1 p-0.5 rounded opacity-0 group-hover:opacity-100 transition-all duration-200 cursor-pointer ${
386
- copiedAddress === wallet.address
387
- ? "bg-green-100 dark:bg-green-900/30 opacity-100"
388
- : "hover:bg-gray-200 dark:hover:bg-gray-600"
389
- }`}
390
- title={
391
- copiedAddress === wallet.address
392
- ? "Copied!"
393
- : "Copy address"
394
- }
395
- >
396
- {copiedAddress === wallet.address ? (
397
- <svg
398
- className="w-3 h-3 text-green-600 dark:text-green-400"
399
- fill="none"
400
- viewBox="0 0 24 24"
401
- stroke="currentColor"
402
- aria-label="Copied"
403
- >
404
- <title>Copied</title>
405
- <path
406
- strokeLinecap="round"
407
- strokeLinejoin="round"
408
- strokeWidth={2}
409
- d="M5 13l4 4L19 7"
410
- />
411
- </svg>
412
- ) : (
413
- <Copy className="w-3 h-3 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300" />
414
- )}
415
- </button>
416
- </div>
417
- <div className="text-xs text-gray-500 dark:text-gray-400">
418
- {wallet.walletConfig?.name ||
419
- wallet.connector?.name ||
420
- "Wallet"}
421
- </div>
422
- </div>
423
- </div>
424
- </div>
425
- </button>
325
+ <ChevronRight className="w-5 h-5 text-gray-400" />
326
+ </button>
327
+ {/* Add divider between items */}
328
+ {index < recentRecipients.length - 1 && (
329
+ <div className="border-b border-gray-200 dark:border-gray-700"></div>
330
+ )}
331
+ </div>
426
332
  )
427
333
  })}
428
334
  </div>
@@ -0,0 +1,33 @@
1
+ import type React from "react"
2
+ import { ErrorDisplay } from "./ErrorDisplay.js"
3
+
4
+ interface RequiredPropsErrorProps {
5
+ missingProps: string[]
6
+ componentName: string
7
+ }
8
+
9
+ export const RequiredPropsError: React.FC<RequiredPropsErrorProps> = ({
10
+ missingProps,
11
+ componentName,
12
+ }) => {
13
+ if (missingProps.length === 0) {
14
+ return null
15
+ }
16
+
17
+ const isMultiple = missingProps.length > 1
18
+
19
+ const prettifiedMessage = `Missing required ${componentName} prop${isMultiple ? "s" : ""}`
20
+
21
+ const detailedMessage = `The following required props are missing for the ${componentName} component:
22
+ ${missingProps.map((prop) => `- ${prop}`).join("\n")}
23
+
24
+ Please ensure all required props are provided when rendering the ${componentName} component.`
25
+
26
+ return (
27
+ <ErrorDisplay
28
+ errorPrettified={prettifiedMessage}
29
+ error={detailedMessage}
30
+ severity="error"
31
+ />
32
+ )
33
+ }
@@ -2,6 +2,7 @@ import { ChevronLeft } from "lucide-react"
2
2
  import type React from "react"
3
3
  import { useAccount } from "wagmi"
4
4
  import AccountActionsDropdown from "./AccountActionsDropdown.js"
5
+ import { useWidgetProps } from "../hooks/useWidgetProps.js"
5
6
 
6
7
  interface ScreenHeaderProps {
7
8
  onBack?: () => void
@@ -20,6 +21,7 @@ export const ScreenHeader: React.FC<ScreenHeaderProps> = ({
20
21
  showAccountActions = false,
21
22
  }) => {
22
23
  const { isConnected } = useAccount()
24
+ const { renderInline } = useWidgetProps()
23
25
  return (
24
26
  <div className="relative w-full mb-4">
25
27
  {/* Left side - Back button (absolute positioned) */}
@@ -48,7 +50,9 @@ export const ScreenHeader: React.FC<ScreenHeaderProps> = ({
48
50
 
49
51
  {/* Right side - Optional content and Account Actions */}
50
52
  {(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">
53
+ <div
54
+ className={`absolute ${renderInline ? "right-0" : "right-8"} top-1/2 -translate-y-1/2 -translate-x-0 flex items-center gap-2 z-10`}
55
+ >
52
56
  {rightSideContent && (
53
57
  <div className="text-right max-w-[280px]">{rightSideContent}</div>
54
58
  )}
@@ -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
@@ -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>