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
|
@@ -2,10 +2,13 @@ import { ExternalLink } from "lucide-react"
|
|
|
2
2
|
import type React from "react"
|
|
3
3
|
import { useEffect, useState } from "react"
|
|
4
4
|
import type { TransactionState } from "../../transactions.js"
|
|
5
|
-
import { TokenImage } from "./TokenImage.js"
|
|
6
5
|
import type { PrepareSendQuote } from "../../prepareSend.js"
|
|
7
6
|
import { QuoteDetails } from "./QuoteDetails.js"
|
|
8
7
|
import { formatElapsed } from "../../utils.js"
|
|
8
|
+
import { SwapDisplay } from "./SwapDisplay.js"
|
|
9
|
+
import { OriginTransferInformation } from "./OriginTransferInformation.js"
|
|
10
|
+
import { ScreenHeader } from "./ScreenHeader.js"
|
|
11
|
+
import { ChevronRight } from "lucide-react"
|
|
9
12
|
|
|
10
13
|
// Checkmark icon for completed steps
|
|
11
14
|
const CheckmarkIcon = () => (
|
|
@@ -37,6 +40,23 @@ const XIcon = () => (
|
|
|
37
40
|
</svg>
|
|
38
41
|
)
|
|
39
42
|
|
|
43
|
+
const AlertIcon = () => (
|
|
44
|
+
<svg
|
|
45
|
+
className="w-4 h-4 text-white"
|
|
46
|
+
fill="none"
|
|
47
|
+
viewBox="0 0 24 24"
|
|
48
|
+
stroke="currentColor"
|
|
49
|
+
>
|
|
50
|
+
<title>An internal meta tx failure occurred</title>
|
|
51
|
+
<path
|
|
52
|
+
strokeLinecap="round"
|
|
53
|
+
strokeLinejoin="round"
|
|
54
|
+
strokeWidth={2}
|
|
55
|
+
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"
|
|
56
|
+
/>
|
|
57
|
+
</svg>
|
|
58
|
+
)
|
|
59
|
+
|
|
40
60
|
// Spinner icon for active steps
|
|
41
61
|
const SpinnerIcon = () => (
|
|
42
62
|
<svg
|
|
@@ -65,6 +85,8 @@ interface TransferPendingProps {
|
|
|
65
85
|
transactionStates: TransactionState[]
|
|
66
86
|
quote?: PrepareSendQuote | null
|
|
67
87
|
timestamp?: number
|
|
88
|
+
mode?: "pay" | "fund" | "earn" | "swap" | "receive"
|
|
89
|
+
onContinue?: () => void
|
|
68
90
|
}
|
|
69
91
|
|
|
70
92
|
export const TransferPending: React.FC<TransferPendingProps> = ({
|
|
@@ -72,6 +94,8 @@ export const TransferPending: React.FC<TransferPendingProps> = ({
|
|
|
72
94
|
transactionStates,
|
|
73
95
|
quote,
|
|
74
96
|
timestamp,
|
|
97
|
+
mode,
|
|
98
|
+
onContinue,
|
|
75
99
|
}) => {
|
|
76
100
|
const [showContent, setShowContent] = useState(false)
|
|
77
101
|
const [activePendingIndex, setActivePendingIndex] = useState(-1)
|
|
@@ -80,6 +104,15 @@ export const TransferPending: React.FC<TransferPendingProps> = ({
|
|
|
80
104
|
const [showTimeoutWarning, setShowTimeoutWarning] = useState(false)
|
|
81
105
|
const [activePendingTimer, setActivePendingTimer] = useState(0)
|
|
82
106
|
|
|
107
|
+
const showContinueButton =
|
|
108
|
+
(transactionStates?.some((tx) => tx.state === "failed") ||
|
|
109
|
+
transactionStates?.some((tx) =>
|
|
110
|
+
tx?.decodedGuestModuleEvents?.some(
|
|
111
|
+
(event) => event.type === "CallFailed",
|
|
112
|
+
),
|
|
113
|
+
)) &&
|
|
114
|
+
onContinue
|
|
115
|
+
|
|
83
116
|
useEffect(() => {
|
|
84
117
|
const timeoutTimer = setTimeout(() => {
|
|
85
118
|
setShowTimeoutWarning(true)
|
|
@@ -200,30 +233,6 @@ export const TransferPending: React.FC<TransferPendingProps> = ({
|
|
|
200
233
|
onElapsedTime(elapsedSeconds)
|
|
201
234
|
}, [onElapsedTime, elapsedSeconds])
|
|
202
235
|
|
|
203
|
-
// Calculate time difference
|
|
204
|
-
const getTimeAgo = () => {
|
|
205
|
-
if (!timestamp) return "Sent just now"
|
|
206
|
-
|
|
207
|
-
const now = Date.now()
|
|
208
|
-
const diffInSeconds = Math.floor((now - timestamp) / 1000)
|
|
209
|
-
|
|
210
|
-
if (diffInSeconds < 1) return "Sent just now"
|
|
211
|
-
if (diffInSeconds === 1) return "Sent 1 second ago"
|
|
212
|
-
if (diffInSeconds < 60) return `Sent ${diffInSeconds} seconds ago`
|
|
213
|
-
|
|
214
|
-
const diffInMinutes = Math.floor(diffInSeconds / 60)
|
|
215
|
-
if (diffInMinutes === 1) return "Sent 1 minute ago"
|
|
216
|
-
if (diffInMinutes < 60) return `Sent ${diffInMinutes} minutes ago`
|
|
217
|
-
|
|
218
|
-
const diffInHours = Math.floor(diffInMinutes / 60)
|
|
219
|
-
if (diffInHours === 1) return "Sent 1 hour ago"
|
|
220
|
-
if (diffInHours < 24) return `Sent ${diffInHours} hours ago`
|
|
221
|
-
|
|
222
|
-
const diffInDays = Math.floor(diffInHours / 24)
|
|
223
|
-
if (diffInDays === 1) return "Sent 1 day ago"
|
|
224
|
-
return `Sent ${diffInDays} days ago`
|
|
225
|
-
}
|
|
226
|
-
|
|
227
236
|
// Compute effective states: a tx is only confirmed if all previous are confirmed, else pending
|
|
228
237
|
const effectiveStates: TransactionState[] = []
|
|
229
238
|
let foundUnconfirmed = false
|
|
@@ -244,13 +253,27 @@ export const TransferPending: React.FC<TransferPendingProps> = ({
|
|
|
244
253
|
const isCompleted = tx.state === "confirmed"
|
|
245
254
|
const isFailed = tx.state === "failed"
|
|
246
255
|
|
|
256
|
+
// Check if this transaction has meta tx errors
|
|
257
|
+
const hasMetaTxError = tx?.decodedGuestModuleEvents?.some(
|
|
258
|
+
(event) => event.type === "CallFailed",
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
// Check if any previous transaction has failed (to disable spinners after failure)
|
|
262
|
+
const hasPreviousFailure = transactionStates
|
|
263
|
+
.slice(0, index)
|
|
264
|
+
.some((prevTx) =>
|
|
265
|
+
prevTx?.decodedGuestModuleEvents?.some(
|
|
266
|
+
(event) => event.type === "CallFailed",
|
|
267
|
+
),
|
|
268
|
+
)
|
|
269
|
+
|
|
247
270
|
// Determine step state
|
|
248
271
|
let stepState: "completed" | "active" | "pending" | "failed"
|
|
249
272
|
if (isFailed) {
|
|
250
273
|
stepState = "failed"
|
|
251
274
|
} else if (isCompleted) {
|
|
252
275
|
stepState = "completed"
|
|
253
|
-
} else if (isActivePending) {
|
|
276
|
+
} else if (isActivePending && !hasPreviousFailure) {
|
|
254
277
|
stepState = "active"
|
|
255
278
|
} else {
|
|
256
279
|
stepState = "pending"
|
|
@@ -263,6 +286,9 @@ export const TransferPending: React.FC<TransferPendingProps> = ({
|
|
|
263
286
|
|
|
264
287
|
switch (stepState) {
|
|
265
288
|
case "completed":
|
|
289
|
+
if (hasMetaTxError) {
|
|
290
|
+
return `${baseStyles} bg-orange-500 scale-100`
|
|
291
|
+
}
|
|
266
292
|
return `${baseStyles} bg-green-600 dark:bg-green-500 scale-100`
|
|
267
293
|
case "active":
|
|
268
294
|
return `${baseStyles} bg-blue-600 dark:bg-blue-500 scale-110`
|
|
@@ -287,7 +313,8 @@ export const TransferPending: React.FC<TransferPendingProps> = ({
|
|
|
287
313
|
{/* Circle with state indicator */}
|
|
288
314
|
<div className="flex-shrink-0">
|
|
289
315
|
<div className={getCircleStyles()}>
|
|
290
|
-
{stepState === "completed" && <CheckmarkIcon />}
|
|
316
|
+
{stepState === "completed" && !hasMetaTxError && <CheckmarkIcon />}
|
|
317
|
+
{stepState === "completed" && hasMetaTxError && <AlertIcon />}
|
|
291
318
|
{stepState === "failed" && <XIcon />}
|
|
292
319
|
{stepState === "active" && <SpinnerIcon />}
|
|
293
320
|
</div>
|
|
@@ -331,99 +358,38 @@ export const TransferPending: React.FC<TransferPendingProps> = ({
|
|
|
331
358
|
}
|
|
332
359
|
|
|
333
360
|
return (
|
|
334
|
-
<div className="space-y-
|
|
335
|
-
<h2
|
|
336
|
-
className={`text-2xl font-bold transition-all duration-500 ease-out ${
|
|
337
|
-
showContent ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"
|
|
338
|
-
} text-gray-900 dark:text-white`}
|
|
339
|
-
>
|
|
340
|
-
Transaction Status
|
|
341
|
-
</h2>
|
|
342
|
-
|
|
343
|
-
{/* Transfer Information */}
|
|
361
|
+
<div className="space-y-2 flex flex-col items-center justify-center py-8">
|
|
344
362
|
<div
|
|
345
|
-
className={`w-full max-w-sm
|
|
363
|
+
className={`w-full max-w-sm transition-all duration-500 ease-out ${
|
|
346
364
|
showContent ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"
|
|
347
|
-
}
|
|
365
|
+
}`}
|
|
348
366
|
>
|
|
349
|
-
<
|
|
350
|
-
{
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
<TokenImage
|
|
356
|
-
imageUrl={quote?.originToken.imageUrl}
|
|
357
|
-
symbol={quote?.originToken.symbol}
|
|
358
|
-
chainId={quote?.originChain.id}
|
|
359
|
-
size={24}
|
|
360
|
-
/>
|
|
361
|
-
</div>
|
|
362
|
-
<div className="flex flex-col">
|
|
363
|
-
<span className="text-xs font-medium text-left text-gray-900 dark:text-white">
|
|
364
|
-
{quote?.originToken.name}
|
|
365
|
-
</span>
|
|
366
|
-
<span className="text-xs text-gray-500 dark:text-gray-400 flex items-center">
|
|
367
|
-
{getTimeAgo()}
|
|
368
|
-
<span
|
|
369
|
-
className="ml-1 font-mono animate-pulse text-gray-500 dark:text-gray-400"
|
|
370
|
-
title="Elapsed time"
|
|
371
|
-
>
|
|
372
|
-
{formatElapsed(elapsedSeconds)}
|
|
373
|
-
</span>
|
|
374
|
-
</span>
|
|
375
|
-
</div>
|
|
376
|
-
</div>
|
|
377
|
-
</div>
|
|
378
|
-
|
|
379
|
-
{/* Right side - USD value and amount */}
|
|
380
|
-
<div className="text-right">
|
|
381
|
-
<div className="text-xs font-medium text-right text-gray-900 dark:text-white">
|
|
382
|
-
{quote?.originAmountUsdDisplay}
|
|
383
|
-
</div>
|
|
384
|
-
<div className="text-xs text-gray-600 dark:text-gray-400">
|
|
385
|
-
{quote?.originAmountFormatted} {quote?.originToken.symbol}
|
|
386
|
-
</div>
|
|
387
|
-
</div>
|
|
388
|
-
</div>
|
|
367
|
+
<ScreenHeader
|
|
368
|
+
headerContent={
|
|
369
|
+
mode === "swap" ? "Swap in progress" : "Transaction Status"
|
|
370
|
+
}
|
|
371
|
+
headerContentAlign="center"
|
|
372
|
+
/>
|
|
389
373
|
</div>
|
|
390
374
|
|
|
391
|
-
{/*
|
|
392
|
-
{
|
|
375
|
+
{/* Transfer Information Display */}
|
|
376
|
+
{quote && (
|
|
393
377
|
<div
|
|
394
|
-
className={`w-full max-w-sm transition-all duration-500 ease-out delay-
|
|
378
|
+
className={`w-full max-w-sm transition-all duration-500 ease-out delay-100 ${
|
|
395
379
|
showContent
|
|
396
380
|
? "opacity-100 translate-y-0"
|
|
397
381
|
: "opacity-0 translate-y-4"
|
|
398
382
|
}`}
|
|
399
383
|
>
|
|
400
|
-
|
|
401
|
-
<
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
<path
|
|
410
|
-
strokeLinecap="round"
|
|
411
|
-
strokeLinejoin="round"
|
|
412
|
-
strokeWidth={2}
|
|
413
|
-
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"
|
|
414
|
-
/>
|
|
415
|
-
</svg>
|
|
416
|
-
<div>
|
|
417
|
-
<p className="font-medium text-yellow-800 dark:text-yellow-300">
|
|
418
|
-
Transaction taking longer than expected
|
|
419
|
-
</p>
|
|
420
|
-
<p className="mt-1 text-xs text-yellow-700 dark:text-yellow-400">
|
|
421
|
-
This transaction is taking longer than expected. Please reach
|
|
422
|
-
out to support for help if the issue persists.
|
|
423
|
-
</p>
|
|
424
|
-
</div>
|
|
425
|
-
</div>
|
|
426
|
-
</div>
|
|
384
|
+
{mode === "swap" ? (
|
|
385
|
+
<SwapDisplay quote={quote} elapsedSeconds={elapsedSeconds} />
|
|
386
|
+
) : (
|
|
387
|
+
<OriginTransferInformation
|
|
388
|
+
quote={quote}
|
|
389
|
+
elapsedSeconds={elapsedSeconds}
|
|
390
|
+
timestamp={timestamp}
|
|
391
|
+
/>
|
|
392
|
+
)}
|
|
427
393
|
</div>
|
|
428
394
|
)}
|
|
429
395
|
|
|
@@ -435,19 +401,44 @@ export const TransferPending: React.FC<TransferPendingProps> = ({
|
|
|
435
401
|
className={`absolute left-2.5 top-5 bottom-5 w-0.5 transition-all duration-500 ease-out bg-gray-300 dark:bg-gray-700 ${showLine ? "animate-line-grow" : "h-0"}`}
|
|
436
402
|
/>
|
|
437
403
|
|
|
438
|
-
{/* Progress line for completed steps */}
|
|
404
|
+
{/* Progress line for completed steps (excluding those with meta tx errors) */}
|
|
439
405
|
{activePendingIndex > 0 && showLine && (
|
|
440
406
|
<div
|
|
441
407
|
className="absolute left-2.5 top-5 w-0.5 bg-green-500 transition-all duration-1000 ease-out"
|
|
442
408
|
style={{
|
|
443
|
-
height: `${(
|
|
409
|
+
height: `${(() => {
|
|
410
|
+
// Find the last step that was completed without meta tx errors
|
|
411
|
+
let lastGoodStepIndex = -1
|
|
412
|
+
for (let i = 0; i < transactionStates.length; i++) {
|
|
413
|
+
const tx = transactionStates[i]
|
|
414
|
+
if (
|
|
415
|
+
tx &&
|
|
416
|
+
tx.state === "confirmed" &&
|
|
417
|
+
!tx?.decodedGuestModuleEvents?.some(
|
|
418
|
+
(event) => event.type === "CallFailed",
|
|
419
|
+
)
|
|
420
|
+
) {
|
|
421
|
+
lastGoodStepIndex = i
|
|
422
|
+
} else if (
|
|
423
|
+
tx?.decodedGuestModuleEvents?.some(
|
|
424
|
+
(event) => event.type === "CallFailed",
|
|
425
|
+
)
|
|
426
|
+
) {
|
|
427
|
+
// Stop at first failure
|
|
428
|
+
break
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
return lastGoodStepIndex >= 0
|
|
432
|
+
? (lastGoodStepIndex / (transactionStates.length - 1)) * 80
|
|
433
|
+
: 0
|
|
434
|
+
})()}%`,
|
|
444
435
|
maxHeight: "calc(100% - 20px)",
|
|
445
436
|
}}
|
|
446
437
|
/>
|
|
447
438
|
)}
|
|
448
439
|
|
|
449
440
|
{/* Steps */}
|
|
450
|
-
<div className="space-y-6">
|
|
441
|
+
<div className="space-y-6 mt-4">
|
|
451
442
|
{effectiveStates.map((tx, index) => (
|
|
452
443
|
<div
|
|
453
444
|
key={`${tx.transactionHash}-${index}`}
|
|
@@ -465,6 +456,26 @@ export const TransferPending: React.FC<TransferPendingProps> = ({
|
|
|
465
456
|
</div>
|
|
466
457
|
</div>
|
|
467
458
|
|
|
459
|
+
{/* Continue Button - Show only when there are failures */}
|
|
460
|
+
{showContinueButton && (
|
|
461
|
+
<div
|
|
462
|
+
className={`w-full max-w-sm transition-all duration-500 ease-out delay-150 mt-4 flex justify-center ${
|
|
463
|
+
showContent
|
|
464
|
+
? "opacity-100 translate-y-0"
|
|
465
|
+
: "opacity-0 translate-y-4"
|
|
466
|
+
}`}
|
|
467
|
+
>
|
|
468
|
+
<button
|
|
469
|
+
type="button"
|
|
470
|
+
onClick={onContinue}
|
|
471
|
+
className="inline-flex items-center gap-1 px-4 py-2 trails-border-radius-button font-medium transition-colors cursor-pointer bg-blue-500 hover:bg-blue-600 text-white dark:bg-blue-600 dark:hover:bg-blue-700"
|
|
472
|
+
>
|
|
473
|
+
Continue
|
|
474
|
+
<ChevronRight className="w-4 h-4" />
|
|
475
|
+
</button>
|
|
476
|
+
</div>
|
|
477
|
+
)}
|
|
478
|
+
|
|
468
479
|
{/* Details Section */}
|
|
469
480
|
<div
|
|
470
481
|
className={`w-full max-w-sm transition-all duration-500 ease-out delay-200 ${
|
|
@@ -475,6 +486,45 @@ export const TransferPending: React.FC<TransferPendingProps> = ({
|
|
|
475
486
|
<QuoteDetails quote={quote} showContent={true} />
|
|
476
487
|
</div>
|
|
477
488
|
</div>
|
|
489
|
+
|
|
490
|
+
{/* Timeout Warning */}
|
|
491
|
+
{showTimeoutWarning && !showContinueButton && (
|
|
492
|
+
<div
|
|
493
|
+
className={`w-full max-w-sm transition-all duration-500 ease-out delay-250 ${
|
|
494
|
+
showContent
|
|
495
|
+
? "opacity-100 translate-y-0"
|
|
496
|
+
: "opacity-0 translate-y-4"
|
|
497
|
+
}`}
|
|
498
|
+
>
|
|
499
|
+
<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">
|
|
500
|
+
<div className="flex items-start space-x-3">
|
|
501
|
+
<svg
|
|
502
|
+
className="w-5 h-5 mt-0.5 flex-shrink-0 text-yellow-600 dark:text-yellow-400"
|
|
503
|
+
fill="none"
|
|
504
|
+
viewBox="0 0 24 24"
|
|
505
|
+
stroke="currentColor"
|
|
506
|
+
>
|
|
507
|
+
<title>Warning</title>
|
|
508
|
+
<path
|
|
509
|
+
strokeLinecap="round"
|
|
510
|
+
strokeLinejoin="round"
|
|
511
|
+
strokeWidth={2}
|
|
512
|
+
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"
|
|
513
|
+
/>
|
|
514
|
+
</svg>
|
|
515
|
+
<div>
|
|
516
|
+
<p className="font-medium text-yellow-800 dark:text-yellow-300">
|
|
517
|
+
Transaction taking longer than expected
|
|
518
|
+
</p>
|
|
519
|
+
<p className="mt-1 text-xs text-yellow-700 dark:text-yellow-400">
|
|
520
|
+
This transaction is taking longer than expected. Please reach
|
|
521
|
+
out to support for help if the issue persists.
|
|
522
|
+
</p>
|
|
523
|
+
</div>
|
|
524
|
+
</div>
|
|
525
|
+
</div>
|
|
526
|
+
</div>
|
|
527
|
+
)}
|
|
478
528
|
</div>
|
|
479
529
|
)
|
|
480
530
|
}
|
|
@@ -5,7 +5,7 @@ import { QrCode } from "./QrCode.js"
|
|
|
5
5
|
import { TruncatedAddress } from "./TruncatedAddress.js"
|
|
6
6
|
import { getWalletConnectProjectId } from "../../config.js"
|
|
7
7
|
import { ScreenHeader } from "./ScreenHeader.js"
|
|
8
|
-
import {
|
|
8
|
+
import { getWalletIcon, getWalletName } from "../../wallets.js"
|
|
9
9
|
|
|
10
10
|
export interface WalletConnectProps {
|
|
11
11
|
onBack: () => void
|
|
@@ -186,7 +186,7 @@ export const WalletConnectScreen: React.FC<WalletConnectProps> = ({
|
|
|
186
186
|
|
|
187
187
|
const title = useMemo(() => {
|
|
188
188
|
const walletName = getWalletName(selectedWalletId)
|
|
189
|
-
if (walletName) {
|
|
189
|
+
if (walletName && walletName !== "WalletConnect") {
|
|
190
190
|
return `Scan code to connect to ${walletName}`
|
|
191
191
|
}
|
|
192
192
|
|
|
@@ -265,10 +265,10 @@ export const WalletConnectScreen: React.FC<WalletConnectProps> = ({
|
|
|
265
265
|
<div className="flex flex-col items-center">
|
|
266
266
|
<QrCode
|
|
267
267
|
url={wcUri}
|
|
268
|
-
size={
|
|
268
|
+
size={300}
|
|
269
269
|
imageUrl={
|
|
270
|
-
|
|
271
|
-
|
|
270
|
+
getWalletIcon(selectedWalletId) ||
|
|
271
|
+
getWalletIcon("walletconnect")
|
|
272
272
|
}
|
|
273
273
|
/>
|
|
274
274
|
<button
|
|
@@ -298,7 +298,7 @@ export const WalletConnectScreen: React.FC<WalletConnectProps> = ({
|
|
|
298
298
|
</div>
|
|
299
299
|
) : (
|
|
300
300
|
<div className="flex flex-col items-center">
|
|
301
|
-
<div className="w-[
|
|
301
|
+
<div className="w-[300px] h-[300px] bg-gray-200 dark:bg-gray-700 rounded-lg flex items-center justify-center trails-border-radius-container">
|
|
302
302
|
<div className="text-center">
|
|
303
303
|
<div className="animate-spin rounded-full h-8 w-8 border-solid border-b-2 border-blue-600 mx-auto mb-2"></div>
|
|
304
304
|
<p className="text-sm text-gray-600 dark:text-gray-400">
|
|
@@ -310,7 +310,9 @@ export const WalletConnectScreen: React.FC<WalletConnectProps> = ({
|
|
|
310
310
|
)}
|
|
311
311
|
|
|
312
312
|
<div className="mt-3 text-xs text-gray-600 dark:text-gray-400">
|
|
313
|
-
{status === "pending" &&
|
|
313
|
+
{status === "pending" && wcUri && (
|
|
314
|
+
<span>Waiting for confirmation…</span>
|
|
315
|
+
)}
|
|
314
316
|
</div>
|
|
315
317
|
</>
|
|
316
318
|
)}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { ChevronLeft } from "lucide-react"
|
|
2
|
+
import type React from "react"
|
|
3
|
+
import { useEffect, useState } from "react"
|
|
4
|
+
import { useWallets } from "../../wallets.js"
|
|
5
|
+
|
|
6
|
+
interface WalletConnectionPendingProps {
|
|
7
|
+
onBack: () => void
|
|
8
|
+
onRetry: () => void
|
|
9
|
+
selectedWalletId: string
|
|
10
|
+
isConnecting: boolean
|
|
11
|
+
error: string | null
|
|
12
|
+
showRetry?: boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const WalletConnectionPending: React.FC<
|
|
16
|
+
WalletConnectionPendingProps
|
|
17
|
+
> = ({
|
|
18
|
+
onBack,
|
|
19
|
+
onRetry,
|
|
20
|
+
selectedWalletId,
|
|
21
|
+
isConnecting,
|
|
22
|
+
error,
|
|
23
|
+
showRetry = false,
|
|
24
|
+
}) => {
|
|
25
|
+
const [showContent, setShowContent] = useState(false)
|
|
26
|
+
const [showTimeoutWarning, setShowTimeoutWarning] = useState(false)
|
|
27
|
+
const { wallets: allWallets } = useWallets()
|
|
28
|
+
|
|
29
|
+
const walletConfig = allWallets.find((w) => w.id === selectedWalletId)
|
|
30
|
+
const walletName = walletConfig?.name || selectedWalletId
|
|
31
|
+
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
setShowContent(true)
|
|
34
|
+
}, [])
|
|
35
|
+
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
const timer = setTimeout(
|
|
38
|
+
() => {
|
|
39
|
+
if (isConnecting && !error) {
|
|
40
|
+
setShowTimeoutWarning(true)
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
2 * 60 * 1000,
|
|
44
|
+
) // 2 minutes
|
|
45
|
+
|
|
46
|
+
return () => clearTimeout(timer)
|
|
47
|
+
}, [isConnecting, error])
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<div className="space-y-6">
|
|
51
|
+
<div className="flex items-center relative">
|
|
52
|
+
<button
|
|
53
|
+
type="button"
|
|
54
|
+
onClick={onBack}
|
|
55
|
+
className="absolute left-0 top-0 p-2 rounded-full transition-colors cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800 hover:trails-hover-bg text-gray-600 dark:text-gray-400"
|
|
56
|
+
>
|
|
57
|
+
<ChevronLeft className="h-6 w-6" />
|
|
58
|
+
</button>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<div className="flex flex-col justify-center min-h-full space-y-6 pt-8">
|
|
62
|
+
<div className="text-center">
|
|
63
|
+
<div
|
|
64
|
+
className={`mx-auto flex items-center justify-center transition-all duration-500 ease-out relative mb-4 ${showContent ? "transform -translate-y-8" : ""}`}
|
|
65
|
+
>
|
|
66
|
+
{error ? (
|
|
67
|
+
<div className={`h-24 w-24`} />
|
|
68
|
+
) : (
|
|
69
|
+
<div className="animate-spin rounded-full h-24 w-24 border-solid border-b-2 border-blue-500 dark:border-blue-400" />
|
|
70
|
+
)}
|
|
71
|
+
|
|
72
|
+
<div className="absolute">
|
|
73
|
+
{walletConfig?.icon && typeof walletConfig.icon === "string" ? (
|
|
74
|
+
<img
|
|
75
|
+
src={walletConfig.icon}
|
|
76
|
+
alt={walletName}
|
|
77
|
+
className="h-16 w-16"
|
|
78
|
+
/>
|
|
79
|
+
) : (
|
|
80
|
+
<div className="h-16 w-16 rounded-full bg-gray-200 dark:bg-gray-700 flex items-center justify-center">
|
|
81
|
+
<span className="text-2xl font-bold text-gray-600 dark:text-gray-400">
|
|
82
|
+
{walletName.charAt(0).toUpperCase()}
|
|
83
|
+
</span>
|
|
84
|
+
</div>
|
|
85
|
+
)}
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<div
|
|
90
|
+
className={`mb-2 transition-all duration-500 ease-out ${showContent ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"}`}
|
|
91
|
+
>
|
|
92
|
+
<h2 className="text-xl font-bold text-gray-900 dark:text-white">
|
|
93
|
+
{error ? "Connection failed" : `Waiting for ${walletName}…`}
|
|
94
|
+
</h2>
|
|
95
|
+
<p className="mt-2 text-sm text-gray-600 dark:text-gray-300">
|
|
96
|
+
{error
|
|
97
|
+
? "There was an issue connecting to your wallet. Please try again."
|
|
98
|
+
: "Please approve the connection request in your wallet"}
|
|
99
|
+
</p>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
{/* Timeout Warning */}
|
|
104
|
+
{showTimeoutWarning && !error && (
|
|
105
|
+
<div
|
|
106
|
+
className={`transition-all duration-500 ease-out delay-150 ${showContent ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"}`}
|
|
107
|
+
>
|
|
108
|
+
<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">
|
|
109
|
+
<div className="flex items-start space-x-3">
|
|
110
|
+
<svg
|
|
111
|
+
className="w-5 h-5 mt-0.5 flex-shrink-0 text-yellow-600 dark:text-yellow-400"
|
|
112
|
+
fill="none"
|
|
113
|
+
viewBox="0 0 24 24"
|
|
114
|
+
stroke="currentColor"
|
|
115
|
+
>
|
|
116
|
+
<title>Warning</title>
|
|
117
|
+
<path
|
|
118
|
+
strokeLinecap="round"
|
|
119
|
+
strokeLinejoin="round"
|
|
120
|
+
strokeWidth={2}
|
|
121
|
+
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"
|
|
122
|
+
/>
|
|
123
|
+
</svg>
|
|
124
|
+
<div>
|
|
125
|
+
<p className="font-medium text-yellow-800 dark:text-yellow-300">
|
|
126
|
+
Connection is taking longer than expected
|
|
127
|
+
</p>
|
|
128
|
+
<p className="mt-1 text-xs text-yellow-700 dark:text-yellow-400">
|
|
129
|
+
This connection request is taking longer than expected.
|
|
130
|
+
Please reach out to support for help if the issue persists.
|
|
131
|
+
</p>
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
)}
|
|
137
|
+
|
|
138
|
+
{/* Retry Button */}
|
|
139
|
+
{(error || showRetry) && (
|
|
140
|
+
<div
|
|
141
|
+
className={`mb-2 transition-all duration-500 ease-out delay-300 ${showContent ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"}`}
|
|
142
|
+
>
|
|
143
|
+
<button
|
|
144
|
+
type="button"
|
|
145
|
+
onClick={onRetry}
|
|
146
|
+
className="w-full px-4 py-2 trails-border-radius-button font-medium transition-colors cursor-pointer bg-blue-500 hover:bg-blue-600 text-white dark:bg-blue-600 dark:hover:bg-blue-700"
|
|
147
|
+
>
|
|
148
|
+
Try Again
|
|
149
|
+
</button>
|
|
150
|
+
</div>
|
|
151
|
+
)}
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export default WalletConnectionPending
|
|
@@ -3,7 +3,7 @@ import type React from "react"
|
|
|
3
3
|
import { ChevronRight, Search } from "lucide-react"
|
|
4
4
|
import { Wallet } from "lucide-react"
|
|
5
5
|
import { ScreenHeader } from "./ScreenHeader.js"
|
|
6
|
-
import {
|
|
6
|
+
import { topShownWallets } from "../../wallets.js"
|
|
7
7
|
import type { WalletConfig } from "../../wallets.js"
|
|
8
8
|
|
|
9
9
|
export interface WalletListProps {
|
|
@@ -23,8 +23,8 @@ export const WalletList: React.FC<WalletListProps> = ({
|
|
|
23
23
|
return walletOptions
|
|
24
24
|
.filter((wallet) => wallet.id !== "injected")
|
|
25
25
|
.sort((a, b) => {
|
|
26
|
-
const aIndex =
|
|
27
|
-
const bIndex =
|
|
26
|
+
const aIndex = topShownWallets.indexOf(a.id)
|
|
27
|
+
const bIndex = topShownWallets.indexOf(b.id)
|
|
28
28
|
|
|
29
29
|
// If both are featured, maintain featured order
|
|
30
30
|
if (aIndex !== -1 && bIndex !== -1) {
|
|
@@ -84,14 +84,15 @@ export const WalletList: React.FC<WalletListProps> = ({
|
|
|
84
84
|
<button
|
|
85
85
|
type="button"
|
|
86
86
|
key={wallet.id}
|
|
87
|
+
data-wallet-id={wallet.id}
|
|
87
88
|
onClick={() => handleWalletSelect(wallet.id)}
|
|
88
89
|
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"
|
|
89
90
|
>
|
|
90
91
|
<div className="flex items-center space-x-3">
|
|
91
|
-
{wallet.
|
|
92
|
+
{wallet.icon ? (
|
|
92
93
|
<>
|
|
93
94
|
<img
|
|
94
|
-
src={wallet.
|
|
95
|
+
src={wallet.icon}
|
|
95
96
|
alt={wallet.name}
|
|
96
97
|
className="h-6 w-6"
|
|
97
98
|
/>
|