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,9 +1,12 @@
1
1
  import { TokenImage } from "./TokenImage.js"
2
+ import { ErrorAnimationIcon } from "./ErrorAnimationIcon.js"
2
3
  import { ChevronLeft } from "lucide-react"
3
4
  import type React from "react"
4
- import { useEffect, useState } from "react"
5
+ import { useEffect, useMemo, useState } from "react"
5
6
  import type { PrepareSendQuote } from "../../prepareSend.js"
6
7
  import { QuoteDetails } from "./QuoteDetails.js"
8
+ import { WaasFeeOptions } from "./WaasFeeOptions.js"
9
+ import { useAccount } from "wagmi"
7
10
 
8
11
  interface WalletConfirmationProps {
9
12
  onBack?: () => void
@@ -21,8 +24,13 @@ export const WalletConfirmation: React.FC<WalletConfirmationProps> = ({
21
24
  }) => {
22
25
  const [showContent, setShowContent] = useState(false)
23
26
  const [showTimeoutWarning, setShowTimeoutWarning] = useState(false)
27
+ const [isFeeOptionConfirmed, setIsFeeOptionConfirmed] = useState(false)
28
+ const [areFeeOptionsLoaded, setAreFeeOptionsLoaded] = useState(false)
29
+ const [feeOptionsError, setFeeOptionsError] = useState<boolean>(false)
30
+ const { connector } = useAccount()
24
31
 
25
32
  useEffect(() => {
33
+ setAreFeeOptionsLoaded(false)
26
34
  setShowContent(true)
27
35
  }, [])
28
36
 
@@ -39,6 +47,25 @@ export const WalletConfirmation: React.FC<WalletConfirmationProps> = ({
39
47
  return () => clearTimeout(timer)
40
48
  }, [retryEnabled])
41
49
 
50
+ const isSequenceWaas = useMemo(() => {
51
+ if (!connector) return false
52
+ const connectorName = connector.name?.toLowerCase() || ""
53
+ const connectorId = connector.id?.toLowerCase() || ""
54
+ const isSequenceWaas =
55
+ connectorName.includes("waas") ||
56
+ connectorId.includes("waas") ||
57
+ connectorId === "sequence-waas"
58
+
59
+ console.log("[trails-sdk] Sequence WaaS detection:", {
60
+ connectorName,
61
+ connectorId,
62
+ isSequenceWaas,
63
+ connector: connector.name,
64
+ })
65
+
66
+ return isSequenceWaas
67
+ }, [connector])
68
+
42
69
  return (
43
70
  <div className="space-y-6">
44
71
  <div className="flex items-center relative">
@@ -56,32 +83,67 @@ export const WalletConfirmation: React.FC<WalletConfirmationProps> = ({
56
83
  <div
57
84
  className={`mx-auto flex items-center justify-center transition-all duration-500 ease-out relative mb-4 ${showContent ? "transform -translate-y-8" : ""}`}
58
85
  >
59
- {retryEnabled ? (
86
+ {feeOptionsError === true ? (
87
+ <ErrorAnimationIcon />
88
+ ) : retryEnabled ? (
60
89
  <div className={`h-24 w-24`} />
61
90
  ) : (
62
91
  <div className="animate-spin rounded-full h-24 w-24 border-solid border-b-2 border-blue-500 dark:border-blue-400" />
63
92
  )}
64
93
 
65
- <div className="absolute">
66
- <TokenImage
67
- imageUrl={quote?.originToken.imageUrl}
68
- symbol={quote?.originToken.symbol}
69
- chainId={quote?.originChain.id}
70
- size={64}
71
- />
72
- </div>
94
+ {!feeOptionsError && (
95
+ <div className="absolute">
96
+ <TokenImage
97
+ imageUrl={quote?.originToken.imageUrl}
98
+ symbol={quote?.originToken.symbol}
99
+ chainId={quote?.originChain.id}
100
+ contractAddress={quote?.originToken.contractAddress}
101
+ size={64}
102
+ />
103
+ </div>
104
+ )}
73
105
  </div>
74
106
 
75
107
  <div
76
108
  className={`mb-2 transition-all duration-500 ease-out ${showContent ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"}`}
77
109
  >
78
110
  <h2 className="text-xl font-bold text-gray-900 dark:text-white">
79
- {retryEnabled ? "Try again" : "Waiting for wallet…"}
111
+ {retryEnabled
112
+ ? "Try again"
113
+ : !isSequenceWaas
114
+ ? "Waiting for wallet…"
115
+ : isFeeOptionConfirmed
116
+ ? "Waiting for wallet…"
117
+ : areFeeOptionsLoaded
118
+ ? "Waiting for fee selection…"
119
+ : feeOptionsError
120
+ ? "No fee token found"
121
+ : "Waiting for fee options…"}
80
122
  </h2>
81
123
  <p className="mt-2 text-sm text-gray-600 dark:text-gray-300">
82
- Please approve the request in your wallet
124
+ {!isSequenceWaas
125
+ ? "Please approve the request in your wallet"
126
+ : isFeeOptionConfirmed
127
+ ? "Please approve the request in your wallet"
128
+ : ""}
83
129
  </p>
84
130
  </div>
131
+
132
+ {isSequenceWaas && (
133
+ <div
134
+ className={`mb-2 mt-4 transition-all duration-500 ease-out ${showContent ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"}`}
135
+ >
136
+ <WaasFeeOptions
137
+ chainId={quote?.originChain.id}
138
+ setIsFeeOptionConfirmed={setIsFeeOptionConfirmed}
139
+ setIsError={setFeeOptionsError}
140
+ onFeeOptionsLoaded={() => {
141
+ console.log("[trails-sdk] Fee options loaded callback called")
142
+ setAreFeeOptionsLoaded(true)
143
+ }}
144
+ />
145
+ </div>
146
+ )}
85
147
  </div>
86
148
 
87
149
  {/* Timeout Warning */}
@@ -92,7 +154,7 @@ export const WalletConfirmation: React.FC<WalletConfirmationProps> = ({
92
154
  <div className="p-4 trails-border-radius-container text-sm bg-yellow-50 border border-solid border-yellow-200 dark:bg-yellow-900/20 dark:border-yellow-700/50">
93
155
  <div className="flex items-start space-x-3">
94
156
  <svg
95
- className="w-5 h-5 mt-0.5 flex-shrink-0 text-yellow-600 dark:text-yellow-400"
157
+ className="w-5 h-5 mt-0.5 shrink-0 text-yellow-600 dark:text-yellow-400"
96
158
  fill="none"
97
159
  viewBox="0 0 24 24"
98
160
  stroke="currentColor"
@@ -135,7 +197,7 @@ export const WalletConfirmation: React.FC<WalletConfirmationProps> = ({
135
197
  )}
136
198
 
137
199
  {/* Transaction Details */}
138
- <QuoteDetails quote={quote} showContent={true} />
200
+ <QuoteDetails quote={quote} showContent={true} compact={true} />
139
201
  </div>
140
202
  </div>
141
203
  )
@@ -44,6 +44,7 @@ export const WalletConnectScreen: React.FC<WalletConnectProps> = ({
44
44
  const { isConnected, address, connector } = useAccount()
45
45
  const [wcUri, setWcUri] = React.useState<string | null>(null)
46
46
  const [showUri, setShowUri] = React.useState(false)
47
+ const [copied, setCopied] = React.useState(false)
47
48
  const listenerRef = React.useRef<(() => void) | null>(null)
48
49
  const debounceTimeoutRef = useRef<NodeJS.Timeout | null>(null)
49
50
 
@@ -57,6 +58,21 @@ export const WalletConnectScreen: React.FC<WalletConnectProps> = ({
57
58
  setWcUri(uri)
58
59
  }, 500) // 300ms debounce delay
59
60
  }, [])
61
+
62
+ // Copy URI to clipboard
63
+ const handleCopyUri = useCallback(async () => {
64
+ if (!wcUri) return
65
+ try {
66
+ await navigator.clipboard.writeText(wcUri)
67
+ setCopied(true)
68
+ setTimeout(() => setCopied(false), 2000)
69
+ } catch (err) {
70
+ logger.console.error(
71
+ "[trails-sdk] [WalletConnect] Failed to copy URI",
72
+ err,
73
+ )
74
+ }
75
+ }, [wcUri])
60
76
  const isWalletConnectConnector = React.useMemo(() => {
61
77
  return connector?.name === "WalletConnect" && isConnected
62
78
  }, [connector, isConnected])
@@ -68,18 +84,13 @@ export const WalletConnectScreen: React.FC<WalletConnectProps> = ({
68
84
  (c.id || "").toLowerCase().includes("walletconnect"),
69
85
  )
70
86
 
71
- // Only auto-navigate back if we successfully connect a new wallet
87
+ // Only auto-navigate to home if we successfully connect a new wallet
72
88
  // Don't auto-navigate if user was already connected when they entered this screen
73
89
  useEffect(() => {
74
- if (
75
- isConnected &&
76
- status === "success" &&
77
- !wasConnectedOnMount.current &&
78
- onBack
79
- ) {
80
- onBack()
90
+ if (isConnected && status === "success" && !wasConnectedOnMount.current) {
91
+ onContinue()
81
92
  }
82
- }, [isConnected, status, onBack])
93
+ }, [isConnected, status, onContinue])
83
94
 
84
95
  const handleConnect = useCallback(
85
96
  async (force: boolean = false) => {
@@ -306,29 +317,82 @@ export const WalletConnectScreen: React.FC<WalletConnectProps> = ({
306
317
  getWalletIcon("walletconnect")
307
318
  }
308
319
  />
309
- <button
310
- onClick={() => setShowUri(!showUri)}
311
- className="mt-2 text-xs text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 hover:underline cursor-pointer flex items-center gap-1"
312
- >
313
- {showUri ? "Hide URI" : "Show URI"}
314
- <svg
315
- className={`w-3 h-3 transition-transform ${showUri ? "rotate-180" : ""}`}
316
- fill="none"
317
- stroke="currentColor"
318
- viewBox="0 0 24 24"
320
+ <div className="flex items-center justify-center gap-2 mt-2">
321
+ <button
322
+ type="button"
323
+ onClick={handleCopyUri}
324
+ className="text-xs text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 cursor-pointer flex items-center gap-1 hover:underline"
325
+ title="Copy URI to clipboard"
319
326
  >
320
- <path
321
- strokeLinecap="round"
322
- strokeLinejoin="round"
323
- strokeWidth={2}
324
- d="M19 9l-7 7-7-7"
325
- />
326
- </svg>
327
- </button>
327
+ {copied ? (
328
+ <>
329
+ <svg
330
+ className="w-3 h-3"
331
+ fill="none"
332
+ stroke="currentColor"
333
+ viewBox="0 0 24 24"
334
+ aria-hidden="true"
335
+ >
336
+ <path
337
+ strokeLinecap="round"
338
+ strokeLinejoin="round"
339
+ strokeWidth={2}
340
+ d="M5 13l4 4L19 7"
341
+ />
342
+ </svg>
343
+ Copied!
344
+ </>
345
+ ) : (
346
+ <>
347
+ <svg
348
+ className="w-3 h-3"
349
+ fill="none"
350
+ stroke="currentColor"
351
+ viewBox="0 0 24 24"
352
+ aria-hidden="true"
353
+ >
354
+ <path
355
+ strokeLinecap="round"
356
+ strokeLinejoin="round"
357
+ strokeWidth={2}
358
+ d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"
359
+ />
360
+ </svg>
361
+ Copy URI
362
+ </>
363
+ )}
364
+ </button>
365
+ <button
366
+ type="button"
367
+ onClick={() => setShowUri(!showUri)}
368
+ className="text-xs text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 hover:underline cursor-pointer flex items-center gap-1"
369
+ >
370
+ {showUri ? "Hide URI" : "Show URI"}
371
+ <svg
372
+ className={`w-3 h-3 transition-transform ${showUri ? "rotate-180" : ""}`}
373
+ fill="none"
374
+ stroke="currentColor"
375
+ viewBox="0 0 24 24"
376
+ aria-hidden="true"
377
+ >
378
+ <path
379
+ strokeLinecap="round"
380
+ strokeLinejoin="round"
381
+ strokeWidth={2}
382
+ d="M19 9l-7 7-7-7"
383
+ />
384
+ </svg>
385
+ </button>
386
+ </div>
328
387
  {showUri && (
329
- <p className="mt-2 text-xs text-gray-600 dark:text-gray-400 break-all">
388
+ <button
389
+ type="button"
390
+ className="mt-2 text-xs text-gray-600 dark:text-gray-400 break-all cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800 p-2 rounded transition-colors text-left w-full"
391
+ onClick={handleCopyUri}
392
+ title="Click to copy URI"
393
+ >
330
394
  {wcUri}
331
- </p>
395
+ </button>
332
396
  )}
333
397
  </div>
334
398
  ) : (
@@ -21,7 +21,9 @@ export const WalletList: React.FC<WalletListProps> = ({
21
21
 
22
22
  const prefilteredWalletOptions = useMemo(() => {
23
23
  return walletOptions
24
- .filter((wallet) => wallet.id !== "injected")
24
+ .filter(
25
+ (wallet) => wallet.id !== "injected" && wallet.id !== "sequence-waas",
26
+ )
25
27
  .sort((a, b) => {
26
28
  const aIndex = topShownWallets.indexOf(a.id)
27
29
  const bIndex = topShownWallets.indexOf(b.id)
@@ -61,7 +63,7 @@ export const WalletList: React.FC<WalletListProps> = ({
61
63
  return (
62
64
  <div className="space-y-6">
63
65
  <ScreenHeader
64
- headerContent="More Wallets"
66
+ headerContent="Connect a Wallet"
65
67
  headerContentAlign="left"
66
68
  onBack={onBack}
67
69
  />
@@ -20,6 +20,7 @@ interface BackContextType {
20
20
  setAccountSettingsSource: (screen: Screen) => void
21
21
  getAccountSettingsSource: () => Screen | null
22
22
  setCurrentScreenWithBack: (screen: Screen, backTo?: Screen) => void
23
+ getPreviousScreen: () => Screen | null
23
24
  }
24
25
 
25
26
  const BackContext = createContext<BackContextType | null>(null)
@@ -194,6 +195,7 @@ export function BackProvider({ children }: BackProviderProps) {
194
195
  setAccountSettingsSource: () => {}, // Deprecated, kept for compatibility
195
196
  getAccountSettingsSource: () => null, // Deprecated, kept for compatibility
196
197
  setCurrentScreenWithBack,
198
+ getPreviousScreen,
197
199
  }
198
200
 
199
201
  return <BackContext.Provider value={value}>{children}</BackContext.Provider>
@@ -2,6 +2,7 @@ import { useCallback, useRef } from "react"
2
2
  import { getSessionId } from "../../analytics.js"
3
3
  import { logger } from "../../logger.js"
4
4
  import { updatePersistentToast } from "../../toast.js"
5
+ import { getPrettifiedErrorMessage } from "../../error.js"
5
6
 
6
7
  export type CheckoutCallbacks = {
7
8
  onCheckoutStart?: (data: { sessionId: string }) => void
@@ -17,7 +18,7 @@ export type CheckoutCallbacks = {
17
18
  export type CheckoutOnHandlers = {
18
19
  triggerCheckoutStart: () => void
19
20
  triggerCheckoutQuote: (quote: any) => void
20
- triggerCheckoutComplete: () => void
21
+ triggerCheckoutComplete: (txStatus: "success" | "fail") => void
21
22
  triggerCheckoutError: (error: string) => void
22
23
  triggerCheckoutStatusUpdate: (transactionStates: any[]) => void
23
24
  }
@@ -81,26 +82,38 @@ export function useCheckout({
81
82
  [onCheckoutQuote],
82
83
  )
83
84
 
84
- const triggerCheckoutComplete = useCallback(() => {
85
- if (onCheckoutComplete && sessionIdRef.current) {
86
- try {
87
- onCheckoutComplete({
88
- sessionId: sessionIdRef.current,
89
- })
90
- } catch (error) {
91
- logger.console.error(
92
- "[trails-sdk] Error calling onCheckoutComplete:",
93
- error,
94
- )
85
+ const triggerCheckoutComplete = useCallback(
86
+ (txStatus: "success" | "fail") => {
87
+ if (onCheckoutComplete && sessionIdRef.current) {
88
+ try {
89
+ onCheckoutComplete({
90
+ sessionId: sessionIdRef.current,
91
+ })
92
+ } catch (error) {
93
+ logger.console.error(
94
+ "[trails-sdk] Error calling onCheckoutComplete:",
95
+ error,
96
+ )
97
+ }
95
98
  }
96
- }
97
99
 
98
- updatePersistentToast(
99
- "Transaction Complete",
100
- "Your transaction has been successfully processed",
101
- "success",
102
- )
103
- }, [onCheckoutComplete])
100
+ if (txStatus === "success") {
101
+ updatePersistentToast(
102
+ "Transaction Complete",
103
+ "Your transaction has been successfully processed",
104
+ "success",
105
+ )
106
+ } else {
107
+ // Default to error for any non-success status (including 'fail' and any unexpected values)
108
+ updatePersistentToast(
109
+ "Transaction Failed",
110
+ "Your transaction failed or was refunded",
111
+ "error",
112
+ )
113
+ }
114
+ },
115
+ [onCheckoutComplete],
116
+ )
104
117
 
105
118
  const triggerCheckoutError = useCallback(
106
119
  (error: string) => {
@@ -120,7 +133,10 @@ export function useCheckout({
120
133
 
121
134
  updatePersistentToast(
122
135
  "Transaction Failed",
123
- error || "An error occurred while processing your transaction",
136
+ getPrettifiedErrorMessage(
137
+ error,
138
+ "An error occurred while processing your transaction",
139
+ ),
124
140
  "error",
125
141
  )
126
142
  },
@@ -25,6 +25,7 @@ export type Screen =
25
25
  | "user-preferences"
26
26
  | "chain-list"
27
27
  | "disconnect"
28
+ | "home"
28
29
 
29
30
  interface CurrentScreenContextType {
30
31
  currentScreen: Screen
@@ -14,6 +14,7 @@ import { getChainInfo } from "../../chains.js"
14
14
  import { logger } from "../../logger.js"
15
15
 
16
16
  const MINIMUM_24H_VOLUME_USD = 1_000_000 // $1M
17
+ const MINIMUM_BALANCE_USD_FOR_PRIORITIZATION = 1 // $1
17
18
 
18
19
  /**
19
20
  * Hook for intelligent default token selection in 0xtrails widget.
@@ -33,9 +34,9 @@ const MINIMUM_24H_VOLUME_USD = 1_000_000 // $1M
33
34
  * - Fallback to any token with balance > 0
34
35
  *
35
36
  * Destination Token Logic (only when toToken/toChainId not provided):
36
- * - Matches origin token symbol on different chain when possible
37
- * - Default destination chain: Base (unless origin is Base, then Arbitrum)
38
- * - Fallback priority: USDC > ETH > first available token
37
+ * - Default destination chain: Base if origin is not Base, Arbitrum if origin is Base
38
+ * - Default destination token: USDC on destination chain
39
+ * - Fallback: Same symbol on destination chain > ETH on destination chain > first available token on destination chain
39
40
  *
40
41
  * @returns defaultOriginToken - Best origin token that can cover targetAmountUsd (if specified)
41
42
  * @returns defaultDestinationToken - Matching token on different chain (null if toToken/toChainId set)
@@ -231,8 +232,11 @@ function useDefaultTokenSelectionInternal(): UseDefaultTokenSelectionReturn {
231
232
  }
232
233
 
233
234
  // Helper to sort tokens by balance USD and volume
234
- const sortTokensByBalanceAndVolume = (tokens: TokenBalanceExtended[]) => {
235
- return [...tokens].sort((a, b) => {
235
+ const sortTokensByBalanceAndVolume = (
236
+ tokens: TokenBalanceExtended[],
237
+ targetAmount?: number,
238
+ ) => {
239
+ const sortedTokens = [...tokens].sort((a, b) => {
236
240
  const aVolume = getToken24hVolume(a)
237
241
  const bVolume = getToken24hVolume(b)
238
242
  const aHighVolume = aVolume >= MINIMUM_24H_VOLUME_USD
@@ -247,6 +251,56 @@ function useDefaultTokenSelectionInternal(): UseDefaultTokenSelectionReturn {
247
251
  const bBalanceUsd = b.balanceUsd ?? 0
248
252
  return bBalanceUsd - aBalanceUsd
249
253
  })
254
+
255
+ // After initial sorting, prioritize USDC and native tokens at the top
256
+ const effectiveTargetAmount =
257
+ targetAmount ?? MINIMUM_BALANCE_USD_FOR_PRIORITIZATION
258
+
259
+ const prioritizedTokens: TokenBalanceExtended[] = []
260
+ const remainingTokens: TokenBalanceExtended[] = []
261
+
262
+ // Separate tokens into prioritized and remaining
263
+ for (const token of sortedTokens) {
264
+ const balanceUsd = token.balanceUsd ?? 0
265
+ const isNative =
266
+ !("contractAddress" in token) || token.contractAddress === zeroAddress
267
+ const isUSDC =
268
+ !isNative && token.contractInfo?.symbol?.toUpperCase() === "USDC"
269
+
270
+ if ((isUSDC || isNative) && balanceUsd >= effectiveTargetAmount) {
271
+ prioritizedTokens.push(token)
272
+ } else {
273
+ remainingTokens.push(token)
274
+ }
275
+ }
276
+
277
+ // Sort prioritized tokens: USDC first, then native tokens
278
+ prioritizedTokens.sort((a, b) => {
279
+ const aIsNative =
280
+ !("contractAddress" in a) || a.contractAddress === zeroAddress
281
+ const bIsNative =
282
+ !("contractAddress" in b) || b.contractAddress === zeroAddress
283
+ const aIsUSDC =
284
+ !aIsNative && a.contractInfo?.symbol?.toUpperCase() === "USDC"
285
+ const bIsUSDC =
286
+ !bIsNative && b.contractInfo?.symbol?.toUpperCase() === "USDC"
287
+
288
+ // USDC comes first
289
+ if (aIsUSDC && !bIsUSDC) return -1
290
+ if (!aIsUSDC && bIsUSDC) return 1
291
+
292
+ // Then native tokens
293
+ if (aIsNative && !bIsNative) return -1
294
+ if (!aIsNative && bIsNative) return 1
295
+
296
+ // Within same type, sort by balance USD (highest first)
297
+ const aBalanceUsd = a.balanceUsd ?? 0
298
+ const bBalanceUsd = b.balanceUsd ?? 0
299
+ return bBalanceUsd - aBalanceUsd
300
+ })
301
+
302
+ // Return prioritized tokens first, then remaining tokens
303
+ return [...prioritizedTokens, ...remainingTokens]
250
304
  }
251
305
 
252
306
  // Find the best origin token using intelligent selection
@@ -281,7 +335,10 @@ function useDefaultTokenSelectionInternal(): UseDefaultTokenSelectionReturn {
281
335
  const sameChainTokens = tokensWithSufficientBalance.filter(
282
336
  (token) => token.chainId === targetChainId,
283
337
  )
284
- const sortedSameChain = sortTokensByBalanceAndVolume(sameChainTokens)
338
+ const sortedSameChain = sortTokensByBalanceAndVolume(
339
+ sameChainTokens,
340
+ effectiveTargetAmount,
341
+ )
285
342
  bestOriginToken = sortedSameChain[0] ?? null
286
343
  if (bestOriginToken) {
287
344
  logger.console.log(
@@ -296,7 +353,10 @@ function useDefaultTokenSelectionInternal(): UseDefaultTokenSelectionReturn {
296
353
  (token) =>
297
354
  tokenMatches(token, toToken) && token.chainId !== targetChainId,
298
355
  )
299
- const sortedSameToken = sortTokensByBalanceAndVolume(sameTokenDiffChain)
356
+ const sortedSameToken = sortTokensByBalanceAndVolume(
357
+ sameTokenDiffChain,
358
+ effectiveTargetAmount,
359
+ )
300
360
  bestOriginToken = sortedSameToken[0] ?? null
301
361
  if (bestOriginToken) {
302
362
  logger.console.log(
@@ -310,8 +370,10 @@ function useDefaultTokenSelectionInternal(): UseDefaultTokenSelectionReturn {
310
370
  const diffChainDiffToken = tokensWithSufficientBalance.filter(
311
371
  (token) => token.chainId !== targetChainId,
312
372
  )
313
- const sortedDiffChainDiffToken =
314
- sortTokensByBalanceAndVolume(diffChainDiffToken)
373
+ const sortedDiffChainDiffToken = sortTokensByBalanceAndVolume(
374
+ diffChainDiffToken,
375
+ effectiveTargetAmount,
376
+ )
315
377
  bestOriginToken = sortedDiffChainDiffToken[0] ?? null
316
378
  if (bestOriginToken) {
317
379
  logger.console.log(
@@ -322,7 +384,10 @@ function useDefaultTokenSelectionInternal(): UseDefaultTokenSelectionReturn {
322
384
 
323
385
  // Fallback: If no token can cover target amount, use any token (sorted by balance/volume)
324
386
  if (!bestOriginToken) {
325
- const allTokensSorted = sortTokensByBalanceAndVolume(tokensWithBalance)
387
+ const allTokensSorted = sortTokensByBalanceAndVolume(
388
+ tokensWithBalance,
389
+ effectiveTargetAmount,
390
+ )
326
391
  bestOriginToken = allTokensSorted[0] ?? null
327
392
  logger.console.log(
328
393
  "[trails-sdk] Fallback: No token can cover target amount, using highest balance token",
@@ -330,8 +395,10 @@ function useDefaultTokenSelectionInternal(): UseDefaultTokenSelectionReturn {
330
395
  }
331
396
  } else {
332
397
  // When no specific destination is set, select highest value token with good liquidity
333
- const sortedByBalanceAndVolume =
334
- sortTokensByBalanceAndVolume(tokensWithBalance)
398
+ const sortedByBalanceAndVolume = sortTokensByBalanceAndVolume(
399
+ tokensWithBalance,
400
+ MINIMUM_BALANCE_USD_FOR_PRIORITIZATION,
401
+ ) // Use minimum balance for prioritization
335
402
  bestOriginToken = sortedByBalanceAndVolume[0] ?? null
336
403
  logger.console.log(
337
404
  "[trails-sdk] No destination specified, selected highest value token with best liquidity",
@@ -358,30 +425,39 @@ function useDefaultTokenSelectionInternal(): UseDefaultTokenSelectionReturn {
358
425
  let destinationToken: DefaultToken | null = null
359
426
 
360
427
  if (shouldComputeDestination) {
361
- // Determine default destination chain: Base if origin is not Base, Arbitrum if origin is Base
428
+ // Determine destination chain: Base if origin is not Base, Arbitrum if origin is Base
362
429
  const defaultDestChainId =
363
430
  originToken.chainId === base.id ? arbitrum.id : base.id
364
431
 
365
- // Find matching token on destination chain (prefer same symbol)
366
- const destChainTokens = supportedTokens.filter(
367
- (token: any) => token.chainId === defaultDestChainId,
432
+ // Find USDC on destination chain first
433
+ const usdcOnDestChain = supportedTokens.find(
434
+ (token: any) =>
435
+ token.chainId === defaultDestChainId && token.symbol === "USDC",
368
436
  )
369
437
 
370
438
  let destToken: any = null
371
439
 
372
- // Try to find same symbol on dest chain
373
- const sameSymbolToken = destChainTokens.find((token: any) => {
374
- return token.symbol.toUpperCase() === originToken.symbol.toUpperCase()
375
- })
376
-
377
- if (sameSymbolToken) {
378
- destToken = sameSymbolToken
440
+ if (usdcOnDestChain) {
441
+ destToken = usdcOnDestChain
379
442
  } else {
380
- // Fallback: USDC > ETH > first available token
381
- destToken =
382
- destChainTokens.find((token: any) => token.symbol === "USDC") ||
383
- destChainTokens.find((token: any) => token.symbol === "ETH") ||
384
- destChainTokens[0]
443
+ // Fallback: Find matching token on destination chain
444
+ const destChainTokens = supportedTokens.filter(
445
+ (token: any) => token.chainId === defaultDestChainId,
446
+ )
447
+
448
+ // Try to find same symbol on destination chain first
449
+ const sameSymbolOnDestChain = destChainTokens.find((token: any) => {
450
+ return token.symbol.toUpperCase() === originToken.symbol.toUpperCase()
451
+ })
452
+
453
+ if (sameSymbolOnDestChain) {
454
+ destToken = sameSymbolOnDestChain
455
+ } else {
456
+ // Fallback: ETH on destination chain > first available token on destination chain
457
+ destToken =
458
+ destChainTokens.find((token: any) => token.symbol === "ETH") ||
459
+ destChainTokens[0]
460
+ }
385
461
  }
386
462
 
387
463
  const decimals = destToken?.decimals