0xtrails 0.1.2 → 0.1.3
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/analytics.d.ts +68 -1
- package/dist/analytics.d.ts.map +1 -1
- package/dist/{ccip-BmFTEOaB.js → ccip-CWd4g9uZ.js} +1 -1
- package/dist/chains.d.ts +9 -3
- package/dist/chains.d.ts.map +1 -1
- package/dist/ens.d.ts +7 -0
- package/dist/ens.d.ts.map +1 -0
- package/dist/error.d.ts +2 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/{index-BPsVj7zK.js → index-BTUBzx4R.js} +23624 -21770
- package/dist/index.js +2 -2
- package/dist/lifi.d.ts +4 -0
- package/dist/lifi.d.ts.map +1 -0
- package/dist/mode.d.ts +1 -1
- package/dist/mode.d.ts.map +1 -1
- package/dist/prepareSend.d.ts +3 -1
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/prices.d.ts +2 -0
- package/dist/prices.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.map +1 -1
- package/dist/tokens.d.ts +2 -1
- package/dist/tokens.d.ts.map +1 -1
- package/dist/trails.d.ts +3 -3
- package/dist/trails.d.ts.map +1 -1
- package/dist/transactions.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/FundSendForm.d.ts +2 -2
- package/dist/widget/components/FundSendForm.d.ts.map +1 -1
- 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/RefundAddressInput.d.ts +13 -0
- package/dist/widget/components/RefundAddressInput.d.ts.map +1 -0
- package/dist/widget/components/Swap.d.ts +43 -0
- package/dist/widget/components/Swap.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/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/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/useSendForm.d.ts +6 -4
- 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 +9 -6
- package/src/aave.ts +13 -13
- package/src/analytics.ts +87 -4
- package/src/chains.ts +45 -7
- package/src/constants.ts +4 -4
- package/src/ens.ts +17 -0
- package/src/error.ts +16 -1
- package/src/lifi.ts +58 -0
- package/src/mode.ts +1 -1
- package/src/morpho.ts +3 -3
- package/src/pools.ts +18 -18
- package/src/prepareSend.ts +35 -3
- package/src/prices.ts +21 -0
- package/src/relaySdk.ts +1 -0
- package/src/relayer.ts +8 -0
- package/src/tokenBalances.ts +3 -0
- package/src/tokens.ts +85 -19
- package/src/trails.ts +2 -2
- package/src/transactions.ts +1 -0
- package/src/wallets.ts +275 -35
- package/src/widget/compiled.css +1 -1
- 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 +3 -0
- package/src/widget/components/FundSendForm.tsx +17 -3
- package/src/widget/components/PaySendForm.tsx +16 -2
- package/src/widget/components/QRCodeDeposit.tsx +1 -1
- package/src/widget/components/QrCode.tsx +277 -16
- package/src/widget/components/Receipt.tsx +1 -1
- package/src/widget/components/RefundAddressInput.tsx +149 -0
- package/src/widget/components/Swap.tsx +648 -0
- package/src/widget/components/TokenList.tsx +27 -363
- package/src/widget/components/TokenSelector.tsx +405 -0
- 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/hooks/useAmountUsd.ts +3 -8
- package/src/widget/hooks/useCheckout.ts +3 -2
- package/src/widget/hooks/useSendForm.ts +66 -32
- package/src/widget/hooks/useTokenList.ts +158 -106
- package/src/widget/widget.tsx +335 -72
|
@@ -1,22 +1,14 @@
|
|
|
1
|
-
import type { SequenceIndexerGateway } from "@0xsequence/indexer"
|
|
2
|
-
import { Search, ChevronLeft } from "lucide-react"
|
|
3
1
|
import type React from "react"
|
|
4
|
-
import {
|
|
5
|
-
import { AnimatePresence, motion } from "framer-motion"
|
|
6
|
-
import type { Token, TokenFormatted } from "../hooks/useTokenList.js"
|
|
7
|
-
import { useTokenList } from "../hooks/useTokenList.js"
|
|
8
|
-
import { TokenImage } from "./TokenImage.js"
|
|
2
|
+
import type { Token } from "../hooks/useTokenList.js"
|
|
9
3
|
import type { Mode } from "../../mode.js"
|
|
10
4
|
import type { SupportedToken } from "../../tokens.js"
|
|
11
|
-
import { RecentTokens } from "./RecentTokens.js"
|
|
12
|
-
import { getChainInfo } from "../../chains.js"
|
|
13
|
-
import { ChainFilterDropdown } from "./ChainFilterDropdown.js"
|
|
14
5
|
import { ScreenHeader } from "./ScreenHeader.js"
|
|
6
|
+
import { TokenSelector } from "./TokenSelector.js"
|
|
7
|
+
import { useTokenList } from "../hooks/useTokenList.js"
|
|
15
8
|
|
|
16
9
|
interface TokenListProps {
|
|
17
10
|
onContinue: (selectedToken: Token) => void
|
|
18
11
|
onBack: () => void
|
|
19
|
-
indexerGatewayClient: SequenceIndexerGateway
|
|
20
12
|
targetAmountUsd?: number | null
|
|
21
13
|
targetAmountUsdFormatted?: string | null
|
|
22
14
|
onError: (error: Error | string | null) => void
|
|
@@ -31,7 +23,6 @@ interface TokenListProps {
|
|
|
31
23
|
export const TokenList: React.FC<TokenListProps> = ({
|
|
32
24
|
onContinue,
|
|
33
25
|
onBack,
|
|
34
|
-
indexerGatewayClient,
|
|
35
26
|
targetAmountUsd,
|
|
36
27
|
targetAmountUsdFormatted,
|
|
37
28
|
onError,
|
|
@@ -42,105 +33,14 @@ export const TokenList: React.FC<TokenListProps> = ({
|
|
|
42
33
|
renderInline = false,
|
|
43
34
|
onNavigateToFundMethods,
|
|
44
35
|
}) => {
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
}, [])
|
|
54
|
-
const {
|
|
55
|
-
searchQuery,
|
|
56
|
-
setSearchQuery,
|
|
57
|
-
handleTokenSelect,
|
|
58
|
-
filteredTokens,
|
|
59
|
-
isLoadingTokens,
|
|
60
|
-
isTokenSelected,
|
|
61
|
-
selectedToken,
|
|
62
|
-
showContinueButton,
|
|
63
|
-
filteredTokensFormatted: baseFilteredTokensFormatted,
|
|
64
|
-
totalBalanceUsd,
|
|
65
|
-
totalBalanceUsdFormatted,
|
|
66
|
-
showInsufficientBalance,
|
|
67
|
-
balanceError,
|
|
68
|
-
} = useTokenList({
|
|
69
|
-
onContinue,
|
|
70
|
-
targetAmountUsd,
|
|
71
|
-
indexerGatewayClient,
|
|
72
|
-
onError,
|
|
73
|
-
fundMethod,
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
// Apply chain filter to tokens
|
|
77
|
-
const filteredTokensFormatted = useMemo(() => {
|
|
78
|
-
if (filterByChainId === null) {
|
|
79
|
-
return baseFilteredTokensFormatted
|
|
80
|
-
}
|
|
81
|
-
return baseFilteredTokensFormatted.filter(
|
|
82
|
-
(token) => token.chainId === filterByChainId,
|
|
83
|
-
)
|
|
84
|
-
}, [baseFilteredTokensFormatted, filterByChainId])
|
|
85
|
-
|
|
86
|
-
// Get unique chains from all tokens (not filtered by chain)
|
|
87
|
-
const uniqueChains = useMemo(() => {
|
|
88
|
-
const chainIds = new Set(
|
|
89
|
-
baseFilteredTokensFormatted.map((token) => token.chainId),
|
|
90
|
-
)
|
|
91
|
-
return Array.from(chainIds)
|
|
92
|
-
.map((chainId) => {
|
|
93
|
-
const chainInfo = getChainInfo(chainId)
|
|
94
|
-
return {
|
|
95
|
-
chainId,
|
|
96
|
-
name: chainInfo?.name || `Chain ${chainId}`,
|
|
97
|
-
imageUrl: "", // We'll use TokenImage component for chain icons
|
|
98
|
-
}
|
|
99
|
-
})
|
|
100
|
-
.sort((a, b) => a.name.localeCompare(b.name))
|
|
101
|
-
}, [baseFilteredTokensFormatted])
|
|
102
|
-
|
|
103
|
-
// Filter recent tokens to only show ones that exist in the current token list and match search
|
|
104
|
-
const filteredRecentTokens = recentTokens.filter((recentToken) => {
|
|
105
|
-
// First check if this recent token exists in the current token list
|
|
106
|
-
const existsInTokenList = filteredTokensFormatted.some(
|
|
107
|
-
(token) =>
|
|
108
|
-
token.contractAddress.toLowerCase() ===
|
|
109
|
-
recentToken.contractAddress.toLowerCase() &&
|
|
110
|
-
token.chainId === recentToken.chainId,
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
if (!existsInTokenList) return false
|
|
114
|
-
|
|
115
|
-
// Then apply search filtering
|
|
116
|
-
if (!searchQuery.trim()) return true
|
|
117
|
-
|
|
118
|
-
const query = searchQuery.toLowerCase()
|
|
119
|
-
return (
|
|
120
|
-
recentToken.symbol.toLowerCase().includes(query) ||
|
|
121
|
-
recentToken.name.toLowerCase().includes(query) ||
|
|
122
|
-
recentToken.contractAddress.toLowerCase().includes(query)
|
|
123
|
-
)
|
|
124
|
-
})
|
|
125
|
-
|
|
126
|
-
// Handle recent token selection by finding the actual token from the list
|
|
127
|
-
const handleRecentTokenSelect = (recentToken: SupportedToken) => {
|
|
128
|
-
// Find the actual token from the filtered tokens list
|
|
129
|
-
const actualToken = filteredTokensFormatted.find(
|
|
130
|
-
(token) =>
|
|
131
|
-
token.contractAddress.toLowerCase() ===
|
|
132
|
-
recentToken.contractAddress.toLowerCase() &&
|
|
133
|
-
token.chainId === recentToken.chainId,
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
if (actualToken) {
|
|
137
|
-
// Use the actual token with balance info
|
|
138
|
-
handleTokenSelect(actualToken)
|
|
139
|
-
} else if (onRecentTokenSelect) {
|
|
140
|
-
// Fallback to the original handler if token not found in current list
|
|
141
|
-
onRecentTokenSelect(recentToken)
|
|
142
|
-
}
|
|
143
|
-
}
|
|
36
|
+
// Get the total balance and insufficient balance info from the hook
|
|
37
|
+
const { totalBalanceUsd, totalBalanceUsdFormatted, showInsufficientBalance } =
|
|
38
|
+
useTokenList({
|
|
39
|
+
onContinue,
|
|
40
|
+
targetAmountUsd,
|
|
41
|
+
onError,
|
|
42
|
+
fundMethod,
|
|
43
|
+
})
|
|
144
44
|
|
|
145
45
|
return (
|
|
146
46
|
<div className="space-y-2">
|
|
@@ -177,258 +77,22 @@ export const TokenList: React.FC<TokenListProps> = ({
|
|
|
177
77
|
}
|
|
178
78
|
/>
|
|
179
79
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
{
|
|
195
|
-
|
|
196
|
-
<ChainFilterDropdown
|
|
197
|
-
chains={uniqueChains}
|
|
198
|
-
selectedChainId={filterByChainId}
|
|
199
|
-
onChainSelect={setFilterByChainId}
|
|
200
|
-
/>
|
|
201
|
-
</div>
|
|
202
|
-
</div>
|
|
203
|
-
|
|
204
|
-
{/* Recent Tokens */}
|
|
205
|
-
<AnimatePresence>
|
|
206
|
-
{!isLoadingTokens && filteredRecentTokens.length > 0 && (
|
|
207
|
-
<motion.div
|
|
208
|
-
initial={{ opacity: 0, height: 0 }}
|
|
209
|
-
animate={{ opacity: 1, height: "auto" }}
|
|
210
|
-
exit={{ opacity: 0, height: 0 }}
|
|
211
|
-
transition={{ duration: 0.05, ease: "easeOut" }}
|
|
212
|
-
>
|
|
213
|
-
<RecentTokens
|
|
214
|
-
recentTokens={filteredRecentTokens}
|
|
215
|
-
onTokenSelect={handleRecentTokenSelect}
|
|
216
|
-
/>
|
|
217
|
-
</motion.div>
|
|
218
|
-
)}
|
|
219
|
-
</AnimatePresence>
|
|
220
|
-
|
|
221
|
-
{isLoadingTokens && (
|
|
222
|
-
<div className="text-center py-4">
|
|
223
|
-
<div className="animate-spin rounded-full h-8 w-8 border-b-2 mx-auto border-solid border-black dark:border-white"></div>
|
|
224
|
-
<p className="mt-2 text-gray-500 dark:text-gray-400">
|
|
225
|
-
Loading your token balances...
|
|
226
|
-
</p>
|
|
227
|
-
</div>
|
|
228
|
-
)}
|
|
229
|
-
|
|
230
|
-
{!isLoadingTokens && !balanceError && filteredTokens.length === 0 && (
|
|
231
|
-
<div className="text-center py-4 rounded-lg trails-bg-secondary">
|
|
232
|
-
<p className="text-gray-500 dark:text-gray-400">
|
|
233
|
-
{searchQuery.trim()
|
|
234
|
-
? "No tokens found matching your search."
|
|
235
|
-
: fundMethod === "qr-code" || fundMethod === "exchange"
|
|
236
|
-
? ""
|
|
237
|
-
: "No available tokens found"}
|
|
238
|
-
</p>
|
|
239
|
-
</div>
|
|
240
|
-
)}
|
|
241
|
-
|
|
242
|
-
{/* Token List */}
|
|
243
|
-
{filteredTokensFormatted.length > 0 && (
|
|
244
|
-
<div className="max-h-[35vh] overflow-y-auto trails-scrollbar space-y-1">
|
|
245
|
-
<AnimatePresence mode="popLayout">
|
|
246
|
-
{filteredTokensFormatted.map((token: TokenFormatted) => {
|
|
247
|
-
const {
|
|
248
|
-
symbol,
|
|
249
|
-
imageUrl,
|
|
250
|
-
chainId,
|
|
251
|
-
contractAddress,
|
|
252
|
-
balanceUsdFormatted,
|
|
253
|
-
tokenName,
|
|
254
|
-
priceUsd,
|
|
255
|
-
balanceFormatted,
|
|
256
|
-
isSufficientBalance,
|
|
257
|
-
} = token
|
|
258
|
-
|
|
259
|
-
return (
|
|
260
|
-
<motion.button
|
|
261
|
-
key={`${chainId}-${contractAddress}`}
|
|
262
|
-
layout
|
|
263
|
-
initial={{ opacity: 0, y: 20 }}
|
|
264
|
-
animate={{ opacity: 1, y: 0 }}
|
|
265
|
-
exit={{ opacity: 0, y: -20 }}
|
|
266
|
-
transition={{
|
|
267
|
-
duration: 0.05,
|
|
268
|
-
ease: "easeOut",
|
|
269
|
-
layout: { duration: 0.08, ease: "easeOut" },
|
|
270
|
-
}}
|
|
271
|
-
type="button"
|
|
272
|
-
onClick={() => handleTokenSelect(token)}
|
|
273
|
-
title={
|
|
274
|
-
!isSufficientBalance &&
|
|
275
|
-
fundMethod !== "qr-code" &&
|
|
276
|
-
fundMethod !== "exchange"
|
|
277
|
-
? "Insufficient balance for this token"
|
|
278
|
-
: undefined
|
|
279
|
-
}
|
|
280
|
-
className={`w-full py-2 px-4 flex items-center space-x-3 transition-all duration-200 trails-bg-secondary trails-hover-bg trails-border-radius-list-button ${
|
|
281
|
-
isTokenSelected(token) ? "trails-bg-card" : ""
|
|
282
|
-
} ${!isSufficientBalance && fundMethod !== "qr-code" && fundMethod !== "exchange" ? "opacity-75 cursor-not-allowed" : "cursor-pointer"}`}
|
|
283
|
-
>
|
|
284
|
-
<div className="relative flex-shrink-0 mr-2">
|
|
285
|
-
<div
|
|
286
|
-
className={`rounded-full flex items-center justify-center bg-gray-100 dark:bg-gray-700 ${
|
|
287
|
-
!isSufficientBalance &&
|
|
288
|
-
fundMethod !== "qr-code" &&
|
|
289
|
-
fundMethod !== "exchange"
|
|
290
|
-
? "opacity-80"
|
|
291
|
-
: ""
|
|
292
|
-
}`}
|
|
293
|
-
>
|
|
294
|
-
{contractAddress ? (
|
|
295
|
-
<TokenImage
|
|
296
|
-
symbol={symbol}
|
|
297
|
-
imageUrl={imageUrl}
|
|
298
|
-
chainId={chainId}
|
|
299
|
-
size={32}
|
|
300
|
-
/>
|
|
301
|
-
) : (
|
|
302
|
-
<span
|
|
303
|
-
className={`text-base font-medium text-gray-600 dark:text-gray-300 ${
|
|
304
|
-
!isSufficientBalance &&
|
|
305
|
-
fundMethod !== "qr-code" &&
|
|
306
|
-
fundMethod !== "exchange"
|
|
307
|
-
? "opacity-70"
|
|
308
|
-
: ""
|
|
309
|
-
}`}
|
|
310
|
-
>
|
|
311
|
-
{symbol}
|
|
312
|
-
</span>
|
|
313
|
-
)}
|
|
314
|
-
</div>
|
|
315
|
-
</div>
|
|
316
|
-
|
|
317
|
-
<div className="flex-1 min-w-0 text-left">
|
|
318
|
-
<h3
|
|
319
|
-
className={`text-sm font-medium truncate text-gray-900 dark:text-white ${
|
|
320
|
-
!isSufficientBalance &&
|
|
321
|
-
fundMethod !== "qr-code" &&
|
|
322
|
-
fundMethod !== "exchange"
|
|
323
|
-
? "opacity-70"
|
|
324
|
-
: ""
|
|
325
|
-
}`}
|
|
326
|
-
>
|
|
327
|
-
{tokenName}
|
|
328
|
-
</h3>
|
|
329
|
-
<p
|
|
330
|
-
className={`text-xs text-gray-500 dark:text-gray-400 ${
|
|
331
|
-
!isSufficientBalance &&
|
|
332
|
-
fundMethod !== "qr-code" &&
|
|
333
|
-
fundMethod !== "exchange"
|
|
334
|
-
? "opacity-70"
|
|
335
|
-
: ""
|
|
336
|
-
}`}
|
|
337
|
-
>
|
|
338
|
-
{symbol}
|
|
339
|
-
</p>
|
|
340
|
-
</div>
|
|
341
|
-
|
|
342
|
-
{fundMethod !== "qr-code" && fundMethod !== "exchange" && (
|
|
343
|
-
<div className="text-right flex-shrink-0">
|
|
344
|
-
{priceUsd > 0 ? (
|
|
345
|
-
<>
|
|
346
|
-
<p
|
|
347
|
-
className={`text-sm font-medium text-gray-900 dark:text-white ${
|
|
348
|
-
!isSufficientBalance &&
|
|
349
|
-
fundMethod !== "qr-code" &&
|
|
350
|
-
fundMethod !== "exchange"
|
|
351
|
-
? "opacity-70"
|
|
352
|
-
: ""
|
|
353
|
-
}`}
|
|
354
|
-
>
|
|
355
|
-
{balanceUsdFormatted}
|
|
356
|
-
</p>
|
|
357
|
-
<p
|
|
358
|
-
className={`text-xs text-gray-500 dark:text-gray-400 ${
|
|
359
|
-
!isSufficientBalance &&
|
|
360
|
-
fundMethod !== "qr-code" &&
|
|
361
|
-
fundMethod !== "exchange"
|
|
362
|
-
? "opacity-70"
|
|
363
|
-
: ""
|
|
364
|
-
}`}
|
|
365
|
-
>
|
|
366
|
-
{balanceFormatted}
|
|
367
|
-
</p>
|
|
368
|
-
</>
|
|
369
|
-
) : (
|
|
370
|
-
<p
|
|
371
|
-
className={`text-sm font-medium text-gray-900 dark:text-white ${
|
|
372
|
-
!isSufficientBalance &&
|
|
373
|
-
fundMethod !== "qr-code" &&
|
|
374
|
-
fundMethod !== "exchange"
|
|
375
|
-
? "opacity-70"
|
|
376
|
-
: ""
|
|
377
|
-
}`}
|
|
378
|
-
>
|
|
379
|
-
{balanceFormatted}
|
|
380
|
-
</p>
|
|
381
|
-
)}
|
|
382
|
-
</div>
|
|
383
|
-
)}
|
|
384
|
-
</motion.button>
|
|
385
|
-
)
|
|
386
|
-
})}
|
|
387
|
-
</AnimatePresence>
|
|
388
|
-
</div>
|
|
389
|
-
)}
|
|
390
|
-
|
|
391
|
-
{showInsufficientBalance &&
|
|
392
|
-
fundMethod !== "qr-code" &&
|
|
393
|
-
fundMethod !== "exchange" && (
|
|
394
|
-
<div
|
|
395
|
-
className={`text-left py-3 px-4 rounded-lg ${"bg-amber-500/10 border border-solid border-amber-500/30"}`}
|
|
396
|
-
>
|
|
397
|
-
<p className={`text-xs font-medium ${"text-amber-400"}`}>
|
|
398
|
-
Insufficient balance
|
|
399
|
-
</p>
|
|
400
|
-
<p className={`text-xs mt-1 ${"text-amber-300"}`}>
|
|
401
|
-
You do not have enough funds to reach the target amount
|
|
402
|
-
</p>
|
|
403
|
-
</div>
|
|
404
|
-
)}
|
|
405
|
-
|
|
406
|
-
{showContinueButton && (
|
|
407
|
-
<div className="space-y-4">
|
|
408
|
-
<button
|
|
409
|
-
type="button"
|
|
410
|
-
onClick={() => selectedToken && onContinue(selectedToken)}
|
|
411
|
-
disabled={!selectedToken}
|
|
412
|
-
className={`w-full font-semibold py-3 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`}
|
|
413
|
-
>
|
|
414
|
-
Continue
|
|
415
|
-
</button>
|
|
416
|
-
</div>
|
|
417
|
-
)}
|
|
418
|
-
|
|
419
|
-
{/* Pay with another method button */}
|
|
420
|
-
{onNavigateToFundMethods && !isLoadingTokens && (
|
|
421
|
-
<div className="text-center pt-2 pb-1">
|
|
422
|
-
<button
|
|
423
|
-
type="button"
|
|
424
|
-
onClick={onNavigateToFundMethods}
|
|
425
|
-
className="inline-flex items-center justify-center space-x-2 px-4 py-2 text-sm font-medium trails-text-secondary trails-bg-secondary trails-hover-bg trails-border trails-border-radius-button transition-all duration-200 cursor-pointer"
|
|
426
|
-
>
|
|
427
|
-
<ChevronLeft className="h-4 w-4" />
|
|
428
|
-
<span>Pay with another method</span>
|
|
429
|
-
</button>
|
|
430
|
-
</div>
|
|
431
|
-
)}
|
|
80
|
+
<TokenSelector
|
|
81
|
+
onTokenSelect={onContinue}
|
|
82
|
+
targetAmountUsd={targetAmountUsd}
|
|
83
|
+
targetAmountUsdFormatted={targetAmountUsdFormatted}
|
|
84
|
+
onError={onError}
|
|
85
|
+
mode={mode}
|
|
86
|
+
recentTokens={recentTokens}
|
|
87
|
+
onRecentTokenSelect={onRecentTokenSelect}
|
|
88
|
+
fundMethod={fundMethod}
|
|
89
|
+
onNavigateToFundMethods={onNavigateToFundMethods}
|
|
90
|
+
showContinueButton={true}
|
|
91
|
+
onContinue={onContinue}
|
|
92
|
+
showInsufficientBalance={showInsufficientBalance}
|
|
93
|
+
totalBalanceUsd={totalBalanceUsd}
|
|
94
|
+
totalBalanceUsdFormatted={totalBalanceUsdFormatted}
|
|
95
|
+
/>
|
|
432
96
|
</div>
|
|
433
97
|
)
|
|
434
98
|
}
|