0xtrails 0.1.2 → 0.1.4
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.
- package/dist/address.d.ts.map +1 -1
- package/dist/analytics.d.ts +86 -1
- package/dist/analytics.d.ts.map +1 -1
- package/dist/apiClient.d.ts +1 -1
- package/dist/apiClient.d.ts.map +1 -1
- package/dist/{ccip-BmFTEOaB.js → ccip-dLSEJjCf.js} +55 -55
- package/dist/cctpqueue.d.ts +1 -1
- package/dist/cctpqueue.d.ts.map +1 -1
- package/dist/chains.d.ts +9 -3
- package/dist/chains.d.ts.map +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/decoders.d.ts +58 -0
- package/dist/decoders.d.ts.map +1 -0
- package/dist/ens.d.ts +13 -0
- package/dist/ens.d.ts.map +1 -0
- package/dist/error.d.ts +9 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/{index-BPsVj7zK.js → index-BXbaLmtt.js} +28779 -25738
- package/dist/index.js +2 -2
- package/dist/intents.d.ts +4 -4
- package/dist/intents.d.ts.map +1 -1
- package/dist/lifi.d.ts +4 -0
- package/dist/lifi.d.ts.map +1 -0
- package/dist/metaTxns.d.ts +1 -1
- package/dist/metaTxns.d.ts.map +1 -1
- package/dist/mode.d.ts +1 -1
- package/dist/mode.d.ts.map +1 -1
- package/dist/preconditions.d.ts +1 -1
- package/dist/preconditions.d.ts.map +1 -1
- package/dist/prepareSend.d.ts +32 -24
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/prices.d.ts +3 -1
- package/dist/prices.d.ts.map +1 -1
- package/dist/proxyCaller.d.ts +0 -1
- package/dist/proxyCaller.d.ts.map +1 -1
- package/dist/relaySdk.d.ts.map +1 -1
- package/dist/relayer.d.ts.map +1 -1
- package/dist/tokenBalances.d.ts +1 -1
- package/dist/tokenBalances.d.ts.map +1 -1
- package/dist/tokens.d.ts +2 -1
- package/dist/tokens.d.ts.map +1 -1
- package/dist/trails.d.ts +4 -4
- package/dist/trails.d.ts.map +1 -1
- package/dist/transactions.d.ts +4 -0
- package/dist/transactions.d.ts.map +1 -1
- package/dist/utils.d.ts +6 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/wallets.d.ts +247 -5
- package/dist/wallets.d.ts.map +1 -1
- package/dist/widget/components/ChainFilterDropdown.d.ts +2 -0
- package/dist/widget/components/ChainFilterDropdown.d.ts.map +1 -1
- package/dist/widget/components/ConnectWallet.d.ts +1 -0
- package/dist/widget/components/ConnectWallet.d.ts.map +1 -1
- package/dist/widget/components/DebugScreensDropdown.d.ts.map +1 -1
- package/dist/widget/components/ErrorDisplay.d.ts +9 -0
- package/dist/widget/components/ErrorDisplay.d.ts.map +1 -0
- package/dist/widget/components/FundSendForm.d.ts +2 -2
- package/dist/widget/components/FundSendForm.d.ts.map +1 -1
- package/dist/widget/components/OriginTransferInformation.d.ts +10 -0
- package/dist/widget/components/OriginTransferInformation.d.ts.map +1 -0
- package/dist/widget/components/PaySendForm.d.ts +2 -2
- package/dist/widget/components/PaySendForm.d.ts.map +1 -1
- package/dist/widget/components/QrCode.d.ts +1 -1
- package/dist/widget/components/QrCode.d.ts.map +1 -1
- package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
- package/dist/widget/components/Receipt.d.ts.map +1 -1
- package/dist/widget/components/Receive.d.ts +12 -0
- package/dist/widget/components/Receive.d.ts.map +1 -0
- package/dist/widget/components/RefundAddressInput.d.ts +13 -0
- package/dist/widget/components/RefundAddressInput.d.ts.map +1 -0
- package/dist/widget/components/Swap.d.ts +47 -0
- package/dist/widget/components/Swap.d.ts.map +1 -0
- package/dist/widget/components/SwapDisplay.d.ts +9 -0
- package/dist/widget/components/SwapDisplay.d.ts.map +1 -0
- package/dist/widget/components/TokenList.d.ts +0 -2
- package/dist/widget/components/TokenList.d.ts.map +1 -1
- package/dist/widget/components/TokenSelector.d.ts +26 -0
- package/dist/widget/components/TokenSelector.d.ts.map +1 -0
- package/dist/widget/components/TransferPendingVertical.d.ts +2 -0
- package/dist/widget/components/TransferPendingVertical.d.ts.map +1 -1
- package/dist/widget/components/WalletConnect.d.ts.map +1 -1
- package/dist/widget/components/WalletConnectionPending.d.ts +12 -0
- package/dist/widget/components/WalletConnectionPending.d.ts.map +1 -0
- package/dist/widget/components/WalletList.d.ts.map +1 -1
- package/dist/widget/components/YellowWarningAnimation.d.ts +2 -0
- package/dist/widget/components/YellowWarningAnimation.d.ts.map +1 -0
- package/dist/widget/hooks/useAmountUsd.d.ts +1 -3
- package/dist/widget/hooks/useAmountUsd.d.ts.map +1 -1
- package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
- package/dist/widget/hooks/useDebugScreens.d.ts +22 -0
- package/dist/widget/hooks/useDebugScreens.d.ts.map +1 -0
- package/dist/widget/hooks/useSendForm.d.ts +12 -6
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- package/dist/widget/hooks/useTokenList.d.ts +2 -3
- package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
- package/dist/widget/index.js +1 -1
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +19 -15
- package/src/aave.ts +13 -13
- package/src/address.ts +3 -0
- package/src/analytics.ts +192 -8
- package/src/apiClient.ts +1 -1
- package/src/cctpqueue.ts +1 -1
- package/src/chains.ts +45 -7
- package/src/constants.ts +7 -4
- package/src/decoders.ts +310 -0
- package/src/ens.ts +32 -0
- package/src/error.ts +101 -1
- package/src/intents.ts +10 -2
- package/src/lifi.ts +58 -0
- package/src/metaTxns.ts +1 -1
- package/src/mode.ts +1 -1
- package/src/morpho.ts +3 -3
- package/src/pools.ts +18 -18
- package/src/preconditions.ts +1 -1
- package/src/prepareSend.ts +463 -113
- package/src/prices.ts +26 -1
- package/src/proxyCaller.ts +2 -14
- package/src/relaySdk.ts +1 -0
- package/src/relayer.ts +8 -0
- package/src/tokenBalances.ts +24 -17
- package/src/tokens.ts +147 -22
- package/src/trails.ts +4 -4
- package/src/transactions.ts +35 -17
- package/src/utils.ts +28 -0
- package/src/wallets.ts +275 -35
- package/src/widget/compiled.css +2 -2
- package/src/widget/components/ChainFilterDropdown.tsx +42 -33
- package/src/widget/components/ChainImage.tsx +1 -1
- package/src/widget/components/ConnectWallet.tsx +92 -128
- package/src/widget/components/DebugScreensDropdown.tsx +6 -0
- package/src/widget/components/ErrorDisplay.tsx +150 -0
- package/src/widget/components/FundSendForm.tsx +78 -11
- package/src/widget/components/OriginTransferInformation.tsx +59 -0
- package/src/widget/components/PaySendForm.tsx +80 -13
- package/src/widget/components/QRCodeDeposit.tsx +6 -6
- package/src/widget/components/QrCode.tsx +278 -17
- package/src/widget/components/QuoteDetails.tsx +93 -25
- package/src/widget/components/Receipt.tsx +296 -103
- package/src/widget/components/Receive.tsx +146 -0
- package/src/widget/components/RecentTokens.tsx +1 -1
- package/src/widget/components/RefundAddressInput.tsx +149 -0
- package/src/widget/components/Swap.tsx +769 -0
- package/src/widget/components/SwapDisplay.tsx +68 -0
- package/src/widget/components/TokenList.tsx +27 -363
- package/src/widget/components/TokenSelector.tsx +405 -0
- package/src/widget/components/TransferPendingVertical.tsx +162 -112
- package/src/widget/components/WalletConnect.tsx +9 -7
- package/src/widget/components/WalletConnectionPending.tsx +157 -0
- package/src/widget/components/WalletList.tsx +6 -5
- package/src/widget/components/YellowWarningAnimation.tsx +146 -0
- package/src/widget/hooks/useAmountUsd.ts +3 -8
- package/src/widget/hooks/useCheckout.ts +3 -2
- package/src/widget/hooks/useDebugScreens.ts +583 -0
- package/src/widget/hooks/useSendForm.ts +111 -35
- package/src/widget/hooks/useTokenList.ts +155 -122
- package/src/widget/widget.tsx +503 -523
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import React, { useEffect, useState } from "react"
|
|
2
2
|
import { ChevronRight, Copy, LogOut } from "lucide-react"
|
|
3
3
|
import { useAccount, useDisconnect } from "wagmi"
|
|
4
|
-
import MetaMaskFox from "../assets/MetaMask-icon-fox.svg"
|
|
5
|
-
import WalletConnectLogoWhite from "../assets/WalletConnect-logo-white.svg"
|
|
6
4
|
import { AlignJustify, Wallet } from "lucide-react"
|
|
7
5
|
import { ScreenHeader } from "./ScreenHeader.js"
|
|
6
|
+
import { useWallets, wagmiConnectorToWalletId } from "../../wallets.js"
|
|
8
7
|
|
|
9
8
|
export interface WalletOption {
|
|
10
9
|
id: string
|
|
@@ -18,6 +17,7 @@ export interface ConnectWalletProps {
|
|
|
18
17
|
onContinue: () => void
|
|
19
18
|
onError: (error: Error) => void
|
|
20
19
|
walletOptions: WalletOption[]
|
|
20
|
+
lastClickedWallet?: string | null
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export const ConnectWallet: React.FC<ConnectWalletProps> = ({
|
|
@@ -25,25 +25,12 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = ({
|
|
|
25
25
|
onDisconnect,
|
|
26
26
|
onContinue,
|
|
27
27
|
onError,
|
|
28
|
-
|
|
28
|
+
lastClickedWallet,
|
|
29
29
|
}) => {
|
|
30
30
|
const { isConnected, address, connector } = useAccount()
|
|
31
31
|
const { disconnect } = useDisconnect()
|
|
32
|
+
const { wallets: allWallets } = useWallets()
|
|
32
33
|
const [error, setError] = useState<string | null>(null)
|
|
33
|
-
const [lastClickedWallet, setLastClickedWallet] = useState<string | null>(
|
|
34
|
-
() => {
|
|
35
|
-
// Initialize from localStorage if available
|
|
36
|
-
if (typeof window !== "undefined") {
|
|
37
|
-
try {
|
|
38
|
-
return localStorage.getItem("trails-last-wallet") || null
|
|
39
|
-
} catch (error) {
|
|
40
|
-
console.error("[trails-sdk] Failed to read from localStorage:", error)
|
|
41
|
-
return null
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return null
|
|
45
|
-
},
|
|
46
|
-
)
|
|
47
34
|
const [showCopied, setShowCopied] = useState(false)
|
|
48
35
|
|
|
49
36
|
useEffect(() => {
|
|
@@ -55,15 +42,6 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = ({
|
|
|
55
42
|
}, [error, onError])
|
|
56
43
|
|
|
57
44
|
const handleWalletConnect = (walletId: string) => {
|
|
58
|
-
setLastClickedWallet(walletId)
|
|
59
|
-
// Save to localStorage
|
|
60
|
-
if (typeof window !== "undefined") {
|
|
61
|
-
try {
|
|
62
|
-
localStorage.setItem("trails-last-wallet", walletId)
|
|
63
|
-
} catch (error) {
|
|
64
|
-
console.error("[trails-sdk] Failed to save to localStorage:", error)
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
45
|
onConnect(walletId)
|
|
68
46
|
}
|
|
69
47
|
|
|
@@ -92,24 +70,48 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = ({
|
|
|
92
70
|
}
|
|
93
71
|
}
|
|
94
72
|
|
|
95
|
-
// Get the wallet
|
|
96
|
-
const
|
|
97
|
-
if (!connector?.
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
if (name.includes("walletconnect")) return "walletconnect"
|
|
101
|
-
return "injected"
|
|
73
|
+
// Get the wallet config for the current connector
|
|
74
|
+
const getCurrentWalletConfig = () => {
|
|
75
|
+
if (!connector?.id) return null
|
|
76
|
+
const walletId = wagmiConnectorToWalletId(connector)
|
|
77
|
+
return allWallets.find((wallet) => wallet.id === walletId) || null
|
|
102
78
|
}
|
|
103
79
|
|
|
104
|
-
//
|
|
80
|
+
// Create wallet options from allWallets and always prepend recent wallet
|
|
105
81
|
const orderedWalletOptions = React.useMemo(() => {
|
|
106
|
-
|
|
82
|
+
// Convert allWallets to wallet options format
|
|
83
|
+
const walletOptionsFromAllWallets = allWallets.map((wallet) => ({
|
|
84
|
+
id: wallet.id,
|
|
85
|
+
name: wallet.name,
|
|
86
|
+
connector: () => wallet.connector?.connect?.(),
|
|
87
|
+
}))
|
|
107
88
|
|
|
108
|
-
const
|
|
109
|
-
const
|
|
89
|
+
const alwaysShowWallets = ["metamask", "walletconnect"]
|
|
90
|
+
const filteredWallets = walletOptionsFromAllWallets
|
|
91
|
+
.filter((wallet) => alwaysShowWallets.includes(wallet.id))
|
|
92
|
+
.sort((a, b) => {
|
|
93
|
+
const aIndex = alwaysShowWallets.indexOf(a.id)
|
|
94
|
+
const bIndex = alwaysShowWallets.indexOf(b.id)
|
|
95
|
+
return aIndex - bIndex
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
// Always prepend recent wallet if it exists, regardless of allowed list
|
|
99
|
+
if (lastClickedWallet) {
|
|
100
|
+
console.log("lastClickedWallet", lastClickedWallet)
|
|
101
|
+
const recentWallet = walletOptionsFromAllWallets.find(
|
|
102
|
+
(w) => w.id === lastClickedWallet,
|
|
103
|
+
)
|
|
104
|
+
const otherWallets = filteredWallets.filter(
|
|
105
|
+
(w) => w.id !== lastClickedWallet,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
if (recentWallet) {
|
|
109
|
+
return [recentWallet, ...otherWallets]
|
|
110
|
+
}
|
|
111
|
+
}
|
|
110
112
|
|
|
111
|
-
return
|
|
112
|
-
}, [
|
|
113
|
+
return filteredWallets
|
|
114
|
+
}, [lastClickedWallet, allWallets])
|
|
113
115
|
|
|
114
116
|
return (
|
|
115
117
|
<div className="space-y-6">
|
|
@@ -136,48 +138,30 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = ({
|
|
|
136
138
|
className="w-full flex items-center justify-between cursor-pointer font-semibold py-4 px-6 trails-border-radius-large-button transition-all duration-200 trails-bg-secondary trails-hover-bg trails-text-primary"
|
|
137
139
|
>
|
|
138
140
|
<div className="flex items-center space-x-3">
|
|
139
|
-
{
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
<div className="flex items-center space-x-2">
|
|
164
|
-
<span>WalletConnect</span>
|
|
165
|
-
<span className="text-xs bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 px-2 py-1 trails-border-radius-container font-normal">
|
|
166
|
-
Connected
|
|
167
|
-
</span>
|
|
168
|
-
</div>
|
|
169
|
-
</>
|
|
170
|
-
) : (
|
|
171
|
-
<>
|
|
172
|
-
<Wallet className="h-6 w-6 text-gray-600 dark:text-gray-400" />
|
|
173
|
-
<div className="flex items-center space-x-2">
|
|
174
|
-
<span>{connector?.name || "Wallet"}</span>
|
|
175
|
-
<span className="text-xs bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 px-2 py-1 trails-border-radius-container font-normal">
|
|
176
|
-
Connected
|
|
177
|
-
</span>
|
|
178
|
-
</div>
|
|
179
|
-
</>
|
|
180
|
-
)}
|
|
141
|
+
{(() => {
|
|
142
|
+
const walletConfig = getCurrentWalletConfig()
|
|
143
|
+
return (
|
|
144
|
+
<>
|
|
145
|
+
{typeof walletConfig?.icon === "string" ? (
|
|
146
|
+
<img
|
|
147
|
+
src={walletConfig?.icon}
|
|
148
|
+
alt={walletConfig?.name}
|
|
149
|
+
className="h-6 w-6"
|
|
150
|
+
/>
|
|
151
|
+
) : (
|
|
152
|
+
<Wallet className="h-6 w-6 text-gray-600 dark:text-gray-400" />
|
|
153
|
+
)}
|
|
154
|
+
<div className="flex items-center space-x-2">
|
|
155
|
+
<span>
|
|
156
|
+
{walletConfig?.name || connector?.name || "Wallet"}
|
|
157
|
+
</span>
|
|
158
|
+
<span className="text-xs bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200 px-2 py-1 trails-border-radius-container font-normal">
|
|
159
|
+
Connected
|
|
160
|
+
</span>
|
|
161
|
+
</div>
|
|
162
|
+
</>
|
|
163
|
+
)
|
|
164
|
+
})()}
|
|
181
165
|
</div>
|
|
182
166
|
|
|
183
167
|
<ChevronRight className="h-5 w-5 text-gray-400" />
|
|
@@ -246,64 +230,44 @@ export const ConnectWallet: React.FC<ConnectWalletProps> = ({
|
|
|
246
230
|
<button
|
|
247
231
|
type="button"
|
|
248
232
|
key={wallet.id}
|
|
233
|
+
data-wallet-id={wallet.id}
|
|
249
234
|
onClick={() => handleWalletConnect(wallet.id)}
|
|
250
235
|
className={`w-full flex items-center justify-between cursor-pointer font-semibold py-4 px-6 trails-border-radius-large-button transition-all duration-200 trails-bg-secondary trails-hover-bg trails-text-primary`}
|
|
251
236
|
>
|
|
252
237
|
<div className="flex items-center space-x-3">
|
|
253
|
-
{
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
</div>
|
|
268
|
-
</>
|
|
269
|
-
) : wallet.id === "walletconnect" ? (
|
|
270
|
-
<>
|
|
271
|
-
<div className="h-6 w-6 bg-[#3B99FC] rounded flex items-center justify-center">
|
|
272
|
-
<img
|
|
273
|
-
src={WalletConnectLogoWhite}
|
|
274
|
-
alt="WalletConnect"
|
|
275
|
-
className="h-4 w-4"
|
|
276
|
-
/>
|
|
277
|
-
</div>
|
|
278
|
-
<div className="flex items-center space-x-2">
|
|
279
|
-
<span>WalletConnect</span>
|
|
280
|
-
{lastClickedWallet === wallet.id && (
|
|
281
|
-
<span className="text-xs bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-300 px-2 py-1 trails-border-radius-container font-normal">
|
|
282
|
-
Recent
|
|
283
|
-
</span>
|
|
284
|
-
)}
|
|
285
|
-
</div>
|
|
286
|
-
</>
|
|
287
|
-
) : (
|
|
288
|
-
<>
|
|
289
|
-
<Wallet className="h-6 w-6 text-gray-600 dark:text-gray-400" />
|
|
290
|
-
<div className="flex items-center space-x-2">
|
|
291
|
-
<span>{wallet.name}</span>
|
|
292
|
-
{lastClickedWallet === wallet.id && (
|
|
293
|
-
<span className="text-xs bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-300 px-2 py-1 trails-border-radius-container font-normal">
|
|
294
|
-
Recent
|
|
295
|
-
</span>
|
|
238
|
+
{(() => {
|
|
239
|
+
const walletConfig = allWallets.find(
|
|
240
|
+
(w) => w.id === wallet.id,
|
|
241
|
+
)
|
|
242
|
+
return (
|
|
243
|
+
<>
|
|
244
|
+
{typeof walletConfig?.icon === "string" ? (
|
|
245
|
+
<img
|
|
246
|
+
src={walletConfig?.icon}
|
|
247
|
+
alt={walletConfig?.name}
|
|
248
|
+
className="h-6 w-6"
|
|
249
|
+
/>
|
|
250
|
+
) : (
|
|
251
|
+
<Wallet className="h-6 w-6 text-gray-600 dark:text-gray-400" />
|
|
296
252
|
)}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
253
|
+
<div className="flex items-center space-x-2">
|
|
254
|
+
<span>{walletConfig?.name || wallet.name}</span>
|
|
255
|
+
{lastClickedWallet === wallet.id && (
|
|
256
|
+
<span className="text-xs bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-300 px-2 py-1 trails-border-radius-container font-normal">
|
|
257
|
+
Recent
|
|
258
|
+
</span>
|
|
259
|
+
)}
|
|
260
|
+
</div>
|
|
261
|
+
</>
|
|
262
|
+
)
|
|
263
|
+
})()}
|
|
300
264
|
</div>
|
|
301
265
|
<ChevronRight className="h-5 w-5 text-gray-400" />
|
|
302
266
|
</button>
|
|
303
267
|
))}
|
|
304
268
|
|
|
305
269
|
{/* More Wallets Link - only show if more than 1 wallet option */}
|
|
306
|
-
{orderedWalletOptions.length >
|
|
270
|
+
{orderedWalletOptions.length > 0 && (
|
|
307
271
|
<button
|
|
308
272
|
type="button"
|
|
309
273
|
onClick={() => onConnect("wallet-list")}
|
|
@@ -13,10 +13,14 @@ const SCREENS = [
|
|
|
13
13
|
"Mesh Connect",
|
|
14
14
|
"Wallet Connect",
|
|
15
15
|
"Wallet List",
|
|
16
|
+
"Wallet Connection Pending",
|
|
17
|
+
"Wallet Connection Pending Retry",
|
|
16
18
|
"Tokens",
|
|
17
19
|
"Send Form",
|
|
18
20
|
"Fund Form",
|
|
19
21
|
"Earn Pools",
|
|
22
|
+
"Swap",
|
|
23
|
+
"Receive",
|
|
20
24
|
"Wallet Confirmation",
|
|
21
25
|
"Wallet Confirmation Retry",
|
|
22
26
|
"Pending 1-item-0-confirmed",
|
|
@@ -28,8 +32,10 @@ const SCREENS = [
|
|
|
28
32
|
"Pending 3-item-1-confirmed",
|
|
29
33
|
"Pending 3-item-2-confirmed",
|
|
30
34
|
"Pending 3-item-3-confirmed",
|
|
35
|
+
"Pending 3-item-2-confirmed-with-error",
|
|
31
36
|
"Receipt",
|
|
32
37
|
"Receipt Failed",
|
|
38
|
+
"Receipt Refunded",
|
|
33
39
|
] as const
|
|
34
40
|
|
|
35
41
|
export const DebugScreensDropdown: React.FC<DebugScreensDropdownProps> = ({
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import type React from "react"
|
|
2
|
+
import { useState, useEffect } from "react"
|
|
3
|
+
import { getPrettifiedErrorMessage } from "../../error.js"
|
|
4
|
+
|
|
5
|
+
interface ErrorDisplayProps {
|
|
6
|
+
errorPrettified?: string | null
|
|
7
|
+
error?: string | null
|
|
8
|
+
severity?: "warning" | "error" | "info"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const ErrorDisplay: React.FC<ErrorDisplayProps> = ({
|
|
12
|
+
errorPrettified,
|
|
13
|
+
error,
|
|
14
|
+
severity = "error",
|
|
15
|
+
}) => {
|
|
16
|
+
const [showFullError, setShowFullError] = useState(false)
|
|
17
|
+
const [computedErrorPrettified, setComputedErrorPrettified] = useState<
|
|
18
|
+
string | null
|
|
19
|
+
>(errorPrettified || null)
|
|
20
|
+
|
|
21
|
+
// If errorPrettified doesn't exist but error does, try to get a prettified version
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (!errorPrettified && error) {
|
|
24
|
+
const prettified = getPrettifiedErrorMessage(error)
|
|
25
|
+
if (prettified) {
|
|
26
|
+
setComputedErrorPrettified(prettified)
|
|
27
|
+
}
|
|
28
|
+
} else {
|
|
29
|
+
setComputedErrorPrettified(errorPrettified || null)
|
|
30
|
+
}
|
|
31
|
+
}, [errorPrettified, error])
|
|
32
|
+
|
|
33
|
+
// Get colors based on severity
|
|
34
|
+
const getSeverityColors = () => {
|
|
35
|
+
switch (severity) {
|
|
36
|
+
case "error":
|
|
37
|
+
return {
|
|
38
|
+
bg: "bg-red-500/10",
|
|
39
|
+
border: "border-red-500/30",
|
|
40
|
+
icon: "text-red-500",
|
|
41
|
+
text: "text-red-600 dark:text-red-400",
|
|
42
|
+
button:
|
|
43
|
+
"text-red-500 hover:text-red-600 dark:text-red-400 dark:hover:text-red-300",
|
|
44
|
+
expandable:
|
|
45
|
+
"bg-red-500/5 border-red-500/20 text-red-700 dark:text-red-300",
|
|
46
|
+
}
|
|
47
|
+
case "info":
|
|
48
|
+
return {
|
|
49
|
+
bg: "bg-blue-500/10",
|
|
50
|
+
border: "border-blue-500/30",
|
|
51
|
+
icon: "text-blue-500",
|
|
52
|
+
text: "text-blue-600 dark:text-blue-400",
|
|
53
|
+
button:
|
|
54
|
+
"text-blue-500 hover:text-blue-600 dark:text-blue-400 dark:hover:text-blue-300",
|
|
55
|
+
expandable:
|
|
56
|
+
"bg-blue-500/5 border-blue-500/20 text-blue-700 dark:text-blue-300",
|
|
57
|
+
}
|
|
58
|
+
case "warning":
|
|
59
|
+
return {
|
|
60
|
+
bg: "bg-amber-500/10",
|
|
61
|
+
border: "border-amber-500/30",
|
|
62
|
+
icon: "text-amber-500",
|
|
63
|
+
text: "text-amber-600 dark:text-amber-400",
|
|
64
|
+
button:
|
|
65
|
+
"text-amber-500 hover:text-amber-600 dark:text-amber-400 dark:hover:text-amber-300",
|
|
66
|
+
expandable:
|
|
67
|
+
"bg-amber-500/5 border-amber-500/20 text-amber-700 dark:text-amber-300",
|
|
68
|
+
}
|
|
69
|
+
default:
|
|
70
|
+
return {
|
|
71
|
+
bg: "bg-amber-500/10",
|
|
72
|
+
border: "border-amber-500/30",
|
|
73
|
+
icon: "text-amber-500",
|
|
74
|
+
text: "text-amber-600 dark:text-amber-400",
|
|
75
|
+
button:
|
|
76
|
+
"text-amber-500 hover:text-amber-600 dark:text-amber-400 dark:hover:text-amber-300",
|
|
77
|
+
expandable:
|
|
78
|
+
"bg-amber-500/5 border-amber-500/20 text-amber-700 dark:text-amber-300",
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const colors = getSeverityColors()
|
|
84
|
+
|
|
85
|
+
// Only show if we have a prettified error (either provided or computed)
|
|
86
|
+
if (!computedErrorPrettified) {
|
|
87
|
+
return null
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<div
|
|
92
|
+
className={`px-2 py-3 rounded-lg ${colors.bg} border border-solid ${colors.border}`}
|
|
93
|
+
>
|
|
94
|
+
<div className="flex items-start space-x-2">
|
|
95
|
+
<svg
|
|
96
|
+
className={`w-4 h-4 ${colors.icon} flex-shrink-0 mt-0.5`}
|
|
97
|
+
fill="none"
|
|
98
|
+
stroke="currentColor"
|
|
99
|
+
viewBox="0 0 24 24"
|
|
100
|
+
aria-hidden="true"
|
|
101
|
+
>
|
|
102
|
+
<path
|
|
103
|
+
strokeLinecap="round"
|
|
104
|
+
strokeLinejoin="round"
|
|
105
|
+
strokeWidth={2}
|
|
106
|
+
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"
|
|
107
|
+
/>
|
|
108
|
+
</svg>
|
|
109
|
+
<div className="flex-1 min-w-0">
|
|
110
|
+
<p className={`text-sm ${colors.text}`}>{computedErrorPrettified}</p>
|
|
111
|
+
{error && error !== computedErrorPrettified && (
|
|
112
|
+
<div className="mt-2">
|
|
113
|
+
<button
|
|
114
|
+
type="button"
|
|
115
|
+
onClick={() => setShowFullError(!showFullError)}
|
|
116
|
+
className={`flex items-center gap-1 text-xs ${colors.button} transition-colors cursor-pointer`}
|
|
117
|
+
aria-label="Show full error details"
|
|
118
|
+
>
|
|
119
|
+
<span>{showFullError ? "Hide" : "Show"} full error</span>
|
|
120
|
+
<svg
|
|
121
|
+
className={`w-3 h-3 transition-transform duration-300 ease-out ${
|
|
122
|
+
showFullError ? "rotate-180" : ""
|
|
123
|
+
}`}
|
|
124
|
+
fill="none"
|
|
125
|
+
stroke="currentColor"
|
|
126
|
+
viewBox="0 0 24 24"
|
|
127
|
+
aria-hidden="true"
|
|
128
|
+
>
|
|
129
|
+
<path
|
|
130
|
+
strokeLinecap="round"
|
|
131
|
+
strokeLinejoin="round"
|
|
132
|
+
strokeWidth={2}
|
|
133
|
+
d="M19 9l-7 7-7-7"
|
|
134
|
+
/>
|
|
135
|
+
</svg>
|
|
136
|
+
</button>
|
|
137
|
+
{showFullError && (
|
|
138
|
+
<div
|
|
139
|
+
className={`mt-2 p-2 ${colors.expandable} rounded text-xs font-mono max-h-[200px] overflow-y-auto overflow-x-auto`}
|
|
140
|
+
>
|
|
141
|
+
{error}
|
|
142
|
+
</div>
|
|
143
|
+
)}
|
|
144
|
+
</div>
|
|
145
|
+
)}
|
|
146
|
+
</div>
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
149
|
+
)
|
|
150
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChevronDown, Loader2 } from "lucide-react"
|
|
1
|
+
import { ChevronDown, Loader2, RefreshCcw } from "lucide-react"
|
|
2
2
|
import type React from "react"
|
|
3
3
|
import { useEffect, useRef, useState, useCallback, useMemo } from "react"
|
|
4
4
|
import type { Account, WalletClient } from "viem"
|
|
@@ -11,10 +11,12 @@ import { ChainImage } from "./ChainImage.js"
|
|
|
11
11
|
import { TokenImage } from "./TokenImage.js"
|
|
12
12
|
import { QuoteDetails } from "./QuoteDetails.js"
|
|
13
13
|
import { TruncatedAddress } from "./TruncatedAddress.js"
|
|
14
|
+
// import { RefundAddressInput } from "./RefundAddressInput.js"
|
|
14
15
|
import { TradeType } from "../../prepareSend.js"
|
|
15
16
|
import type { PrepareSendQuote } from "../../prepareSend.js"
|
|
16
17
|
import { formatAmount, formatUsdAmountDisplay } from "../../tokenBalances.js"
|
|
17
18
|
import { ScreenHeader } from "./ScreenHeader.js"
|
|
19
|
+
import { ErrorDisplay } from "./ErrorDisplay.js"
|
|
18
20
|
|
|
19
21
|
interface FundSendFormProps {
|
|
20
22
|
selectedToken: Token
|
|
@@ -36,8 +38,8 @@ interface FundSendFormProps {
|
|
|
36
38
|
gasless?: boolean
|
|
37
39
|
setWalletConfirmRetryHandler: (handler: () => Promise<void>) => void
|
|
38
40
|
quoteProvider?: string
|
|
39
|
-
fundMethod?: string
|
|
40
|
-
mode?: "pay" | "fund" | "earn"
|
|
41
|
+
fundMethod?: string
|
|
42
|
+
mode?: "pay" | "fund" | "earn" | "swap" | "receive"
|
|
41
43
|
onNavigateToMeshConnect?: (
|
|
42
44
|
props: {
|
|
43
45
|
toTokenSymbol: string
|
|
@@ -77,6 +79,9 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
77
79
|
}) => {
|
|
78
80
|
// Local state for fund-specific functionality
|
|
79
81
|
const [isInputTypeUsd, setIsInputTypeUsd] = useState(false)
|
|
82
|
+
const [refetchTrigger, setRefetchTrigger] = useState(0)
|
|
83
|
+
// const [isRefundAddressOpen, setIsRefundAddressOpen] = useState(false)
|
|
84
|
+
// const [refundAddress, setRefundAddress] = useState<string>(account.address)
|
|
80
85
|
|
|
81
86
|
const [tokenAmountForBackend, setTokenAmountForBackend] = useState("")
|
|
82
87
|
const [inputDisplayValue, setInputDisplayValue] = useState("")
|
|
@@ -119,6 +124,9 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
119
124
|
setSelectedDestinationChain,
|
|
120
125
|
setSelectedDestToken,
|
|
121
126
|
prepareSendQuote,
|
|
127
|
+
quoteError,
|
|
128
|
+
quoteErrorPrettified,
|
|
129
|
+
isSameTokenWithoutCustomCalldata,
|
|
122
130
|
} = useSendForm({
|
|
123
131
|
account,
|
|
124
132
|
// Don't pass toAmount for fund form - user enters input amount
|
|
@@ -126,6 +134,7 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
126
134
|
toChainId,
|
|
127
135
|
toToken,
|
|
128
136
|
toCalldata,
|
|
137
|
+
// refundAddress,
|
|
129
138
|
walletClient,
|
|
130
139
|
onTransactionStateChange,
|
|
131
140
|
onError,
|
|
@@ -143,6 +152,7 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
143
152
|
mode,
|
|
144
153
|
onNavigateToMeshConnect,
|
|
145
154
|
checkoutOnHandlers,
|
|
155
|
+
refetchTrigger,
|
|
146
156
|
})
|
|
147
157
|
|
|
148
158
|
// Get source token price for USD conversions
|
|
@@ -340,6 +350,11 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
340
350
|
}, 0)
|
|
341
351
|
}, [tokenAmountForBackend, isInputTypeUsd, sourceTokenPrice])
|
|
342
352
|
|
|
353
|
+
// Handle manual quote refetch
|
|
354
|
+
const handleRefetchQuote = useCallback(() => {
|
|
355
|
+
setRefetchTrigger((prev) => prev + 1)
|
|
356
|
+
}, [])
|
|
357
|
+
|
|
343
358
|
// Dynamic font size based on input length
|
|
344
359
|
const inputStyles = useMemo(() => {
|
|
345
360
|
const inputLength = displayAmount.length
|
|
@@ -479,7 +494,7 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
479
494
|
|
|
480
495
|
{/* Percentage Buttons */}
|
|
481
496
|
<div className="flex space-x-1 justify-center">
|
|
482
|
-
{[25, 50, 100].map((percentage) => (
|
|
497
|
+
{[25, 50, 75, 100].map((percentage) => (
|
|
483
498
|
<button
|
|
484
499
|
key={percentage}
|
|
485
500
|
type="button"
|
|
@@ -497,7 +512,7 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
497
512
|
<div className="mb-4">
|
|
498
513
|
<label
|
|
499
514
|
htmlFor="destination-chain"
|
|
500
|
-
className="block text-sm font-medium mb-1 text-gray-700 dark:text-gray-300"
|
|
515
|
+
className="block text-sm font-medium mb-1 text-gray-700 dark:text-gray-300 text-left"
|
|
501
516
|
>
|
|
502
517
|
Destination Chain
|
|
503
518
|
</label>
|
|
@@ -560,7 +575,7 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
560
575
|
<div className="mb-4">
|
|
561
576
|
<label
|
|
562
577
|
htmlFor="token"
|
|
563
|
-
className="block text-sm font-medium mb-1 text-gray-700 dark:text-gray-300"
|
|
578
|
+
className="block text-sm font-medium mb-1 text-gray-700 dark:text-gray-300 text-left"
|
|
564
579
|
>
|
|
565
580
|
Receive Token
|
|
566
581
|
</label>
|
|
@@ -626,10 +641,37 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
626
641
|
|
|
627
642
|
{/* Receive Section */}
|
|
628
643
|
<div className="space-y-1">
|
|
629
|
-
<div
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
644
|
+
<div className="flex items-center justify-between">
|
|
645
|
+
<div
|
|
646
|
+
className={`text-lg font-semibold text-left ${"text-gray-900 dark:text-white"}`}
|
|
647
|
+
>
|
|
648
|
+
Receive
|
|
649
|
+
</div>
|
|
650
|
+
<button
|
|
651
|
+
type="button"
|
|
652
|
+
onClick={handleRefetchQuote}
|
|
653
|
+
disabled={
|
|
654
|
+
isLoadingQuote ||
|
|
655
|
+
!tokenAmountForBackend ||
|
|
656
|
+
!selectedDestToken ||
|
|
657
|
+
!selectedDestinationChain ||
|
|
658
|
+
!isValidRecipient
|
|
659
|
+
}
|
|
660
|
+
className={`p-2 rounded-md transition-colors cursor-pointer ${
|
|
661
|
+
isLoadingQuote ||
|
|
662
|
+
!tokenAmountForBackend ||
|
|
663
|
+
!selectedDestToken ||
|
|
664
|
+
!selectedDestinationChain ||
|
|
665
|
+
!isValidRecipient
|
|
666
|
+
? "opacity-50 cursor-not-allowed text-gray-400 dark:text-gray-500"
|
|
667
|
+
: "text-gray-600 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 hover:text-gray-700 dark:hover:text-gray-200"
|
|
668
|
+
}`}
|
|
669
|
+
title="Refetch quote"
|
|
670
|
+
>
|
|
671
|
+
<RefreshCcw
|
|
672
|
+
className={`h-4 w-4 ${isLoadingQuote ? "animate-spin" : ""}`}
|
|
673
|
+
/>
|
|
674
|
+
</button>
|
|
633
675
|
</div>
|
|
634
676
|
|
|
635
677
|
<div className="p-2">
|
|
@@ -688,7 +730,29 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
688
730
|
</div>
|
|
689
731
|
)}
|
|
690
732
|
|
|
733
|
+
{/* Refund Address Input */}
|
|
734
|
+
{/* <RefundAddressInput
|
|
735
|
+
account={account}
|
|
736
|
+
isOpen={isRefundAddressOpen}
|
|
737
|
+
onToggle={() => setIsRefundAddressOpen(!isRefundAddressOpen)}
|
|
738
|
+
refundAddress={refundAddress}
|
|
739
|
+
onRefundAddressChange={setRefundAddress}
|
|
740
|
+
chainId={selectedDestinationChain.id}
|
|
741
|
+
/> */}
|
|
742
|
+
|
|
691
743
|
{/* Warning Messages - Show only one at a time */}
|
|
744
|
+
{isSameTokenWithoutCustomCalldata ? (
|
|
745
|
+
<ErrorDisplay
|
|
746
|
+
errorPrettified="Cannot swap to the same token on the same chain without custom calldata. Please select a different destination token."
|
|
747
|
+
severity="error"
|
|
748
|
+
/>
|
|
749
|
+
) : (
|
|
750
|
+
<ErrorDisplay
|
|
751
|
+
errorPrettified={quoteErrorPrettified}
|
|
752
|
+
error={quoteError}
|
|
753
|
+
severity="warning"
|
|
754
|
+
/>
|
|
755
|
+
)}
|
|
692
756
|
{prepareSendQuote?.noSufficientBalance ? (
|
|
693
757
|
<div className="px-2 py-3 rounded-lg bg-amber-500/10 border border-solid border-amber-500/30">
|
|
694
758
|
<div className="flex items-center space-x-2">
|
|
@@ -746,7 +810,8 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
746
810
|
!isValidRecipient ||
|
|
747
811
|
buttonText === "No quote available" ||
|
|
748
812
|
buttonText === "Getting quote..." ||
|
|
749
|
-
prepareSendQuote?.noSufficientBalance
|
|
813
|
+
prepareSendQuote?.noSufficientBalance ||
|
|
814
|
+
isSameTokenWithoutCustomCalldata
|
|
750
815
|
}
|
|
751
816
|
className={`w-full font-semibold py-4 px-4 trails-border-radius-button transition-colors bg-blue-500 hover:bg-blue-600 disabled:bg-gray-300 text-white disabled:text-gray-500 disabled:cursor-not-allowed cursor-pointer relative`}
|
|
752
817
|
>
|
|
@@ -755,6 +820,8 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
755
820
|
<Loader2 className="w-5 h-5 animate-spin mr-2 text-white dark:text-gray-400" />
|
|
756
821
|
<span>{buttonText}</span>
|
|
757
822
|
</div>
|
|
823
|
+
) : isSameTokenWithoutCustomCalldata ? (
|
|
824
|
+
"Select Different Tokens"
|
|
758
825
|
) : prepareSendQuote?.noSufficientBalance ? (
|
|
759
826
|
"Insufficient Balance"
|
|
760
827
|
) : !tokenAmountForBackend ||
|