0xtrails 0.1.3 → 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 +18 -0
- 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-CWd4g9uZ.js → ccip-dLSEJjCf.js} +55 -55
- package/dist/cctpqueue.d.ts +1 -1
- package/dist/cctpqueue.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 +6 -0
- package/dist/ens.d.ts.map +1 -1
- package/dist/error.d.ts +7 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/{index-BTUBzx4R.js → index-BXbaLmtt.js} +25694 -24507
- package/dist/index.js +2 -2
- package/dist/intents.d.ts +4 -4
- package/dist/intents.d.ts.map +1 -1
- 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 +30 -24
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/prices.d.ts +1 -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/tokenBalances.d.ts +1 -1
- package/dist/tokenBalances.d.ts.map +1 -1
- package/dist/tokens.d.ts.map +1 -1
- package/dist/trails.d.ts +1 -1
- 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/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 +1 -1
- 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 +1 -1
- package/dist/widget/components/PaySendForm.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/Swap.d.ts +5 -1
- package/dist/widget/components/Swap.d.ts.map +1 -1
- package/dist/widget/components/SwapDisplay.d.ts +9 -0
- package/dist/widget/components/SwapDisplay.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/YellowWarningAnimation.d.ts +2 -0
- package/dist/widget/components/YellowWarningAnimation.d.ts.map +1 -0
- 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 +7 -3
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- 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 +16 -15
- package/src/address.ts +3 -0
- package/src/analytics.ts +105 -4
- package/src/apiClient.ts +1 -1
- package/src/cctpqueue.ts +1 -1
- package/src/constants.ts +3 -0
- package/src/decoders.ts +310 -0
- package/src/ens.ts +16 -1
- package/src/error.ts +86 -1
- package/src/intents.ts +10 -2
- package/src/metaTxns.ts +1 -1
- package/src/mode.ts +1 -1
- package/src/preconditions.ts +1 -1
- package/src/prepareSend.ts +432 -114
- package/src/prices.ts +5 -1
- package/src/proxyCaller.ts +2 -14
- package/src/tokenBalances.ts +21 -17
- package/src/tokens.ts +62 -3
- package/src/trails.ts +2 -2
- package/src/transactions.ts +35 -18
- package/src/utils.ts +28 -0
- package/src/widget/compiled.css +2 -2
- package/src/widget/components/DebugScreensDropdown.tsx +3 -0
- package/src/widget/components/ErrorDisplay.tsx +150 -0
- package/src/widget/components/FundSendForm.tsx +62 -9
- package/src/widget/components/OriginTransferInformation.tsx +59 -0
- package/src/widget/components/PaySendForm.tsx +65 -12
- package/src/widget/components/QRCodeDeposit.tsx +5 -5
- package/src/widget/components/QrCode.tsx +1 -1
- 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/Swap.tsx +206 -85
- package/src/widget/components/SwapDisplay.tsx +68 -0
- package/src/widget/components/TokenSelector.tsx +1 -1
- package/src/widget/components/TransferPendingVertical.tsx +162 -112
- package/src/widget/components/YellowWarningAnimation.tsx +146 -0
- package/src/widget/hooks/useDebugScreens.ts +583 -0
- package/src/widget/hooks/useSendForm.ts +46 -4
- package/src/widget/hooks/useTokenList.ts +8 -27
- package/src/widget/widget.tsx +201 -484
|
@@ -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"
|
|
@@ -16,6 +16,7 @@ import { TradeType } from "../../prepareSend.js"
|
|
|
16
16
|
import type { PrepareSendQuote } from "../../prepareSend.js"
|
|
17
17
|
import { formatAmount, formatUsdAmountDisplay } from "../../tokenBalances.js"
|
|
18
18
|
import { ScreenHeader } from "./ScreenHeader.js"
|
|
19
|
+
import { ErrorDisplay } from "./ErrorDisplay.js"
|
|
19
20
|
|
|
20
21
|
interface FundSendFormProps {
|
|
21
22
|
selectedToken: Token
|
|
@@ -38,7 +39,7 @@ interface FundSendFormProps {
|
|
|
38
39
|
setWalletConfirmRetryHandler: (handler: () => Promise<void>) => void
|
|
39
40
|
quoteProvider?: string
|
|
40
41
|
fundMethod?: string
|
|
41
|
-
mode?: "pay" | "fund" | "earn" | "swap"
|
|
42
|
+
mode?: "pay" | "fund" | "earn" | "swap" | "receive"
|
|
42
43
|
onNavigateToMeshConnect?: (
|
|
43
44
|
props: {
|
|
44
45
|
toTokenSymbol: string
|
|
@@ -78,6 +79,7 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
78
79
|
}) => {
|
|
79
80
|
// Local state for fund-specific functionality
|
|
80
81
|
const [isInputTypeUsd, setIsInputTypeUsd] = useState(false)
|
|
82
|
+
const [refetchTrigger, setRefetchTrigger] = useState(0)
|
|
81
83
|
// const [isRefundAddressOpen, setIsRefundAddressOpen] = useState(false)
|
|
82
84
|
// const [refundAddress, setRefundAddress] = useState<string>(account.address)
|
|
83
85
|
|
|
@@ -122,6 +124,9 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
122
124
|
setSelectedDestinationChain,
|
|
123
125
|
setSelectedDestToken,
|
|
124
126
|
prepareSendQuote,
|
|
127
|
+
quoteError,
|
|
128
|
+
quoteErrorPrettified,
|
|
129
|
+
isSameTokenWithoutCustomCalldata,
|
|
125
130
|
} = useSendForm({
|
|
126
131
|
account,
|
|
127
132
|
// Don't pass toAmount for fund form - user enters input amount
|
|
@@ -147,6 +152,7 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
147
152
|
mode,
|
|
148
153
|
onNavigateToMeshConnect,
|
|
149
154
|
checkoutOnHandlers,
|
|
155
|
+
refetchTrigger,
|
|
150
156
|
})
|
|
151
157
|
|
|
152
158
|
// Get source token price for USD conversions
|
|
@@ -344,6 +350,11 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
344
350
|
}, 0)
|
|
345
351
|
}, [tokenAmountForBackend, isInputTypeUsd, sourceTokenPrice])
|
|
346
352
|
|
|
353
|
+
// Handle manual quote refetch
|
|
354
|
+
const handleRefetchQuote = useCallback(() => {
|
|
355
|
+
setRefetchTrigger((prev) => prev + 1)
|
|
356
|
+
}, [])
|
|
357
|
+
|
|
347
358
|
// Dynamic font size based on input length
|
|
348
359
|
const inputStyles = useMemo(() => {
|
|
349
360
|
const inputLength = displayAmount.length
|
|
@@ -501,7 +512,7 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
501
512
|
<div className="mb-4">
|
|
502
513
|
<label
|
|
503
514
|
htmlFor="destination-chain"
|
|
504
|
-
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"
|
|
505
516
|
>
|
|
506
517
|
Destination Chain
|
|
507
518
|
</label>
|
|
@@ -564,7 +575,7 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
564
575
|
<div className="mb-4">
|
|
565
576
|
<label
|
|
566
577
|
htmlFor="token"
|
|
567
|
-
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"
|
|
568
579
|
>
|
|
569
580
|
Receive Token
|
|
570
581
|
</label>
|
|
@@ -630,10 +641,37 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
630
641
|
|
|
631
642
|
{/* Receive Section */}
|
|
632
643
|
<div className="space-y-1">
|
|
633
|
-
<div
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
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>
|
|
637
675
|
</div>
|
|
638
676
|
|
|
639
677
|
<div className="p-2">
|
|
@@ -703,6 +741,18 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
703
741
|
/> */}
|
|
704
742
|
|
|
705
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
|
+
)}
|
|
706
756
|
{prepareSendQuote?.noSufficientBalance ? (
|
|
707
757
|
<div className="px-2 py-3 rounded-lg bg-amber-500/10 border border-solid border-amber-500/30">
|
|
708
758
|
<div className="flex items-center space-x-2">
|
|
@@ -760,7 +810,8 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
760
810
|
!isValidRecipient ||
|
|
761
811
|
buttonText === "No quote available" ||
|
|
762
812
|
buttonText === "Getting quote..." ||
|
|
763
|
-
prepareSendQuote?.noSufficientBalance
|
|
813
|
+
prepareSendQuote?.noSufficientBalance ||
|
|
814
|
+
isSameTokenWithoutCustomCalldata
|
|
764
815
|
}
|
|
765
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`}
|
|
766
817
|
>
|
|
@@ -769,6 +820,8 @@ export const FundSendForm: React.FC<FundSendFormProps> = ({
|
|
|
769
820
|
<Loader2 className="w-5 h-5 animate-spin mr-2 text-white dark:text-gray-400" />
|
|
770
821
|
<span>{buttonText}</span>
|
|
771
822
|
</div>
|
|
823
|
+
) : isSameTokenWithoutCustomCalldata ? (
|
|
824
|
+
"Select Different Tokens"
|
|
772
825
|
) : prepareSendQuote?.noSufficientBalance ? (
|
|
773
826
|
"Insufficient Balance"
|
|
774
827
|
) : !tokenAmountForBackend ||
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type React from "react"
|
|
2
|
+
import { TokenImage } from "./TokenImage.js"
|
|
3
|
+
import type { PrepareSendQuote } from "../../prepareSend.js"
|
|
4
|
+
import { getTimeAgo } from "../../utils.js"
|
|
5
|
+
|
|
6
|
+
interface OriginTransferInformationProps {
|
|
7
|
+
quote: PrepareSendQuote
|
|
8
|
+
elapsedSeconds: number
|
|
9
|
+
timestamp?: number
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const OriginTransferInformation: React.FC<
|
|
13
|
+
OriginTransferInformationProps
|
|
14
|
+
> = ({ quote, elapsedSeconds, timestamp }) => {
|
|
15
|
+
return (
|
|
16
|
+
<div className="w-full max-w-sm p-3 trails-border-radius-container trails-bg-secondary trails-text-secondary">
|
|
17
|
+
<div className="flex items-start justify-between">
|
|
18
|
+
{/* Left side - Chain and Token images with token name */}
|
|
19
|
+
<div className="flex items-start space-x-2">
|
|
20
|
+
{/* Token Image and Name */}
|
|
21
|
+
<div className="flex items-center space-x-2">
|
|
22
|
+
<div style={{ width: "24px", height: "24px" }}>
|
|
23
|
+
<TokenImage
|
|
24
|
+
imageUrl={quote.originToken.imageUrl}
|
|
25
|
+
symbol={quote.originToken.symbol}
|
|
26
|
+
chainId={quote.originChain.id}
|
|
27
|
+
size={24}
|
|
28
|
+
/>
|
|
29
|
+
</div>
|
|
30
|
+
<div className="flex flex-col">
|
|
31
|
+
<span className="text-xs font-medium text-left text-gray-900 dark:text-white">
|
|
32
|
+
{quote.originToken.name}
|
|
33
|
+
</span>
|
|
34
|
+
<span className="text-xs text-gray-500 dark:text-gray-400 flex items-center">
|
|
35
|
+
{getTimeAgo(timestamp)}
|
|
36
|
+
<span
|
|
37
|
+
className="ml-1 font-mono animate-pulse text-gray-500 dark:text-gray-400"
|
|
38
|
+
title="Elapsed time"
|
|
39
|
+
>
|
|
40
|
+
{elapsedSeconds}s
|
|
41
|
+
</span>
|
|
42
|
+
</span>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
{/* Right side - USD value and amount */}
|
|
48
|
+
<div className="text-right">
|
|
49
|
+
<div className="text-xs font-medium text-right text-gray-900 dark:text-white">
|
|
50
|
+
{quote.originAmountUsdDisplay}
|
|
51
|
+
</div>
|
|
52
|
+
<div className="text-xs text-gray-600 dark:text-gray-400">
|
|
53
|
+
{quote.originAmountFormatted} {quote.originToken.symbol}
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ChevronDown, Loader2, TrendingUp } from "lucide-react"
|
|
1
|
+
import { ChevronDown, Loader2, RefreshCcw, TrendingUp } from "lucide-react"
|
|
2
2
|
import type React from "react"
|
|
3
|
-
import { useCallback, useEffect, useRef } from "react"
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from "react"
|
|
4
4
|
import type { Account, WalletClient } from "viem"
|
|
5
5
|
import { isAddress } from "viem"
|
|
6
6
|
import type { TransactionState } from "../../transactions.js"
|
|
@@ -21,6 +21,7 @@ import morphoLogo from "../assets/morpho.svg"
|
|
|
21
21
|
import { formatUsdAmountDisplay } from "../../tokenBalances.js"
|
|
22
22
|
import { MINIMUM_USD_AMOUNT_FOR_SWAP } from "../../constants.js"
|
|
23
23
|
import { ScreenHeader } from "./ScreenHeader.js"
|
|
24
|
+
import { ErrorDisplay } from "./ErrorDisplay.js"
|
|
24
25
|
|
|
25
26
|
interface PaySendFormProps {
|
|
26
27
|
selectedToken: Token
|
|
@@ -53,7 +54,7 @@ interface PaySendFormProps {
|
|
|
53
54
|
quote?: PrepareSendQuote | null,
|
|
54
55
|
) => void
|
|
55
56
|
onAmountUpdate?: (amount: string) => void
|
|
56
|
-
mode?: "pay" | "fund" | "earn" | "swap"
|
|
57
|
+
mode?: "pay" | "fund" | "earn" | "swap" | "receive"
|
|
57
58
|
selectedPool?: {
|
|
58
59
|
id: string
|
|
59
60
|
name: string
|
|
@@ -105,6 +106,7 @@ export const PaySendForm: React.FC<PaySendFormProps> = ({
|
|
|
105
106
|
}) => {
|
|
106
107
|
// const [isRefundAddressOpen, setIsRefundAddressOpen] = useState(false)
|
|
107
108
|
// const [refundAddress, setRefundAddress] = useState<string>(account.address)
|
|
109
|
+
const [refetchTrigger, setRefetchTrigger] = useState(0)
|
|
108
110
|
const {
|
|
109
111
|
amount,
|
|
110
112
|
amountRaw,
|
|
@@ -141,6 +143,9 @@ export const PaySendForm: React.FC<PaySendFormProps> = ({
|
|
|
141
143
|
supportedChains,
|
|
142
144
|
isValidCustomToken,
|
|
143
145
|
prepareSendQuote,
|
|
146
|
+
quoteError,
|
|
147
|
+
quoteErrorPrettified,
|
|
148
|
+
isSameTokenWithoutCustomCalldata,
|
|
144
149
|
} = useSendForm({
|
|
145
150
|
account,
|
|
146
151
|
toAmount,
|
|
@@ -166,6 +171,7 @@ export const PaySendForm: React.FC<PaySendFormProps> = ({
|
|
|
166
171
|
mode,
|
|
167
172
|
onNavigateToMeshConnect,
|
|
168
173
|
checkoutOnHandlers,
|
|
174
|
+
refetchTrigger,
|
|
169
175
|
})
|
|
170
176
|
|
|
171
177
|
// Handle amount input changes with decimal validation
|
|
@@ -181,6 +187,11 @@ export const PaySendForm: React.FC<PaySendFormProps> = ({
|
|
|
181
187
|
[setAmount],
|
|
182
188
|
)
|
|
183
189
|
|
|
190
|
+
// Handle manual quote refetch
|
|
191
|
+
const handleRefetchQuote = useCallback(() => {
|
|
192
|
+
setRefetchTrigger((prev) => prev + 1)
|
|
193
|
+
}, [])
|
|
194
|
+
|
|
184
195
|
// Call onAmountUpdate when amountRaw changes
|
|
185
196
|
useEffect(() => {
|
|
186
197
|
if (onAmountUpdate) {
|
|
@@ -377,7 +388,7 @@ export const PaySendForm: React.FC<PaySendFormProps> = ({
|
|
|
377
388
|
<div className="mb-4">
|
|
378
389
|
<label
|
|
379
390
|
htmlFor="destination-chain"
|
|
380
|
-
className="block text-sm font-medium mb-1 text-gray-700 dark:text-gray-300"
|
|
391
|
+
className="block text-sm font-medium mb-1 text-gray-700 dark:text-gray-300 text-left"
|
|
381
392
|
>
|
|
382
393
|
Destination Chain
|
|
383
394
|
</label>
|
|
@@ -440,7 +451,7 @@ export const PaySendForm: React.FC<PaySendFormProps> = ({
|
|
|
440
451
|
<div className="mb-4">
|
|
441
452
|
<label
|
|
442
453
|
htmlFor="token"
|
|
443
|
-
className="block text-sm font-medium mb-1 text-gray-700 dark:text-gray-300"
|
|
454
|
+
className="block text-sm font-medium mb-1 text-gray-700 dark:text-gray-300 text-left"
|
|
444
455
|
>
|
|
445
456
|
Receive Token
|
|
446
457
|
</label>
|
|
@@ -509,7 +520,7 @@ export const PaySendForm: React.FC<PaySendFormProps> = ({
|
|
|
509
520
|
<div className="mb-2">
|
|
510
521
|
<label
|
|
511
522
|
htmlFor="amount"
|
|
512
|
-
className="block text-sm font-medium mb-1 text-gray-700 dark:text-gray-300"
|
|
523
|
+
className="block text-sm font-medium mb-1 text-gray-700 dark:text-gray-300 text-left"
|
|
513
524
|
>
|
|
514
525
|
Amount to {mode === "earn" ? "Deposit" : "Receive"}
|
|
515
526
|
</label>
|
|
@@ -530,7 +541,7 @@ export const PaySendForm: React.FC<PaySendFormProps> = ({
|
|
|
530
541
|
</div>
|
|
531
542
|
{amountUsdDisplay && selectedDestToken?.symbol && (
|
|
532
543
|
<div className="h-6 mt-1">
|
|
533
|
-
<div className="text-sm text-gray-400">
|
|
544
|
+
<div className="text-sm text-gray-400 text-left">
|
|
534
545
|
≈ {amountUsdDisplay}
|
|
535
546
|
</div>
|
|
536
547
|
</div>
|
|
@@ -541,10 +552,37 @@ export const PaySendForm: React.FC<PaySendFormProps> = ({
|
|
|
541
552
|
{/* Receive Section - Similar to FundSendForm */}
|
|
542
553
|
{(toAmount || toChainId || toToken) && (
|
|
543
554
|
<div className="space-y-1">
|
|
544
|
-
<div
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
555
|
+
<div className="flex items-center justify-between">
|
|
556
|
+
<div
|
|
557
|
+
className={`text-lg font-semibold text-left ${"text-gray-900 dark:text-white"}`}
|
|
558
|
+
>
|
|
559
|
+
{mode === "earn" ? "Deposit" : "Receive"}
|
|
560
|
+
</div>
|
|
561
|
+
<button
|
|
562
|
+
type="button"
|
|
563
|
+
onClick={handleRefetchQuote}
|
|
564
|
+
disabled={
|
|
565
|
+
isLoadingQuote ||
|
|
566
|
+
!amount ||
|
|
567
|
+
!selectedDestToken ||
|
|
568
|
+
!selectedDestinationChain ||
|
|
569
|
+
!isValidRecipient
|
|
570
|
+
}
|
|
571
|
+
className={`p-2 rounded-md transition-colors cursor-pointer ${
|
|
572
|
+
isLoadingQuote ||
|
|
573
|
+
!amount ||
|
|
574
|
+
!selectedDestToken ||
|
|
575
|
+
!selectedDestinationChain ||
|
|
576
|
+
!isValidRecipient
|
|
577
|
+
? "opacity-50 cursor-not-allowed text-gray-400 dark:text-gray-500"
|
|
578
|
+
: "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"
|
|
579
|
+
}`}
|
|
580
|
+
title="Refetch quote"
|
|
581
|
+
>
|
|
582
|
+
<RefreshCcw
|
|
583
|
+
className={`h-4 w-4 ${isLoadingQuote ? "animate-spin" : ""}`}
|
|
584
|
+
/>
|
|
585
|
+
</button>
|
|
548
586
|
</div>
|
|
549
587
|
|
|
550
588
|
<div className="p-2">
|
|
@@ -675,6 +713,18 @@ export const PaySendForm: React.FC<PaySendFormProps> = ({
|
|
|
675
713
|
/>
|
|
676
714
|
|
|
677
715
|
{/* Warning Messages - Show only one at a time */}
|
|
716
|
+
{isSameTokenWithoutCustomCalldata ? (
|
|
717
|
+
<ErrorDisplay
|
|
718
|
+
errorPrettified="Cannot swap to the same token on the same chain without custom calldata. Please select a different destination token."
|
|
719
|
+
severity="error"
|
|
720
|
+
/>
|
|
721
|
+
) : (
|
|
722
|
+
<ErrorDisplay
|
|
723
|
+
errorPrettified={quoteErrorPrettified}
|
|
724
|
+
error={quoteError}
|
|
725
|
+
severity="warning"
|
|
726
|
+
/>
|
|
727
|
+
)}
|
|
678
728
|
{prepareSendQuote?.noSufficientBalance ? (
|
|
679
729
|
<div className="px-2 py-3 rounded-lg bg-amber-500/10 border border-solid border-amber-500/30">
|
|
680
730
|
<div className="flex items-center space-x-2">
|
|
@@ -733,7 +783,8 @@ export const PaySendForm: React.FC<PaySendFormProps> = ({
|
|
|
733
783
|
!isValidCustomToken ||
|
|
734
784
|
isLoadingQuote ||
|
|
735
785
|
!prepareSendQuote ||
|
|
736
|
-
prepareSendQuote?.noSufficientBalance
|
|
786
|
+
prepareSendQuote?.noSufficientBalance ||
|
|
787
|
+
isSameTokenWithoutCustomCalldata
|
|
737
788
|
}
|
|
738
789
|
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`}
|
|
739
790
|
>
|
|
@@ -744,6 +795,8 @@ export const PaySendForm: React.FC<PaySendFormProps> = ({
|
|
|
744
795
|
/>
|
|
745
796
|
<span>{buttonText}</span>
|
|
746
797
|
</div>
|
|
798
|
+
) : isSameTokenWithoutCustomCalldata ? (
|
|
799
|
+
"Select Different Tokens"
|
|
747
800
|
) : prepareSendQuote?.noSufficientBalance ? (
|
|
748
801
|
"Insufficient Balance"
|
|
749
802
|
) : (
|
|
@@ -23,12 +23,12 @@ export const QRCodeDeposit: React.FC<QRCodeDepositProps> = ({
|
|
|
23
23
|
|
|
24
24
|
const eip631Url = useMemo(() => {
|
|
25
25
|
if (!quote) return ""
|
|
26
|
-
return `ethereum:${quote.
|
|
26
|
+
return `ethereum:${quote.originDepositAddress}@${quote.originChain.id}`
|
|
27
27
|
}, [quote])
|
|
28
28
|
|
|
29
29
|
const eip681Url = useMemo(() => {
|
|
30
30
|
if (!quote) return ""
|
|
31
|
-
return `ethereum:${quote.originToken.contractAddress}@${quote.originChain.id}/transfer?address=${quote.
|
|
31
|
+
return `ethereum:${quote.originToken.contractAddress}@${quote.originChain.id}/transfer?address=${quote.originDepositAddress}&uint256=${quote.originAmount}`
|
|
32
32
|
}, [quote])
|
|
33
33
|
|
|
34
34
|
return (
|
|
@@ -114,7 +114,7 @@ export const QRCodeDeposit: React.FC<QRCodeDepositProps> = ({
|
|
|
114
114
|
</span>
|
|
115
115
|
<a
|
|
116
116
|
href={getExplorerUrlForAddress({
|
|
117
|
-
address: quote.
|
|
117
|
+
address: quote.originDepositAddress,
|
|
118
118
|
chainId: quote.originChain.id,
|
|
119
119
|
})}
|
|
120
120
|
target="_blank"
|
|
@@ -122,8 +122,8 @@ export const QRCodeDeposit: React.FC<QRCodeDepositProps> = ({
|
|
|
122
122
|
className="flex items-center gap-1 text-xs text-gray-500 dark:text-gray-400 hover:underline transition-all"
|
|
123
123
|
>
|
|
124
124
|
<span>
|
|
125
|
-
{quote.
|
|
126
|
-
{quote.
|
|
125
|
+
{quote.originDepositAddress.slice(0, 6)}...
|
|
126
|
+
{quote.originDepositAddress.slice(-4)}
|
|
127
127
|
</span>
|
|
128
128
|
<ExternalLink className="w-3 h-3" />
|
|
129
129
|
</a>
|
|
@@ -292,7 +292,7 @@ export const QrCode: React.FC<QrCodeProps> = ({
|
|
|
292
292
|
width={size}
|
|
293
293
|
height={size}
|
|
294
294
|
viewBox={`0 0 ${size} ${size}`}
|
|
295
|
-
className="rounded-lg
|
|
295
|
+
className="rounded-lg bg-white"
|
|
296
296
|
/>
|
|
297
297
|
</div>
|
|
298
298
|
)
|
|
@@ -390,7 +390,7 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
390
390
|
</div>
|
|
391
391
|
)}
|
|
392
392
|
|
|
393
|
-
{quote?.
|
|
393
|
+
{quote?.originDepositAddress && (
|
|
394
394
|
<div className="flex justify-between items-center">
|
|
395
395
|
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
396
396
|
Origin Deposit Address:
|
|
@@ -400,14 +400,14 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
400
400
|
</span>
|
|
401
401
|
<a
|
|
402
402
|
href={getExplorerUrlForAddress({
|
|
403
|
-
address: quote.
|
|
403
|
+
address: quote.originDepositAddress,
|
|
404
404
|
chainId: quote.originChain.id,
|
|
405
405
|
})}
|
|
406
406
|
target="_blank"
|
|
407
407
|
rel="noopener noreferrer"
|
|
408
408
|
className="font-mono text-xs hover:underline flex items-center gap-1 text-gray-700 dark:text-gray-300"
|
|
409
409
|
>
|
|
410
|
-
{truncateAddress(quote.
|
|
410
|
+
{truncateAddress(quote.originDepositAddress)}
|
|
411
411
|
<svg
|
|
412
412
|
className="w-3 h-3"
|
|
413
413
|
fill="none"
|
|
@@ -426,11 +426,49 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
426
426
|
</div>
|
|
427
427
|
)}
|
|
428
428
|
|
|
429
|
+
{quote?.destinationDepositAddress &&
|
|
430
|
+
quote?.destinationDepositAddress !==
|
|
431
|
+
quote?.originDepositAddress && (
|
|
432
|
+
<div className="flex justify-between items-center">
|
|
433
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
434
|
+
Destination Deposit Address:
|
|
435
|
+
<Tooltip message="This is the address that will receive the tokens after any swap and/or bridge from the origin chain">
|
|
436
|
+
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
437
|
+
</Tooltip>
|
|
438
|
+
</span>
|
|
439
|
+
<a
|
|
440
|
+
href={getExplorerUrlForAddress({
|
|
441
|
+
address: quote.destinationDepositAddress,
|
|
442
|
+
chainId: quote.destinationChain.id,
|
|
443
|
+
})}
|
|
444
|
+
target="_blank"
|
|
445
|
+
rel="noopener noreferrer"
|
|
446
|
+
className="font-mono text-xs hover:underline flex items-center gap-1 text-gray-700 dark:text-gray-300"
|
|
447
|
+
>
|
|
448
|
+
{truncateAddress(quote.destinationDepositAddress)}
|
|
449
|
+
<svg
|
|
450
|
+
className="w-3 h-3"
|
|
451
|
+
fill="none"
|
|
452
|
+
stroke="currentColor"
|
|
453
|
+
viewBox="0 0 24 24"
|
|
454
|
+
aria-hidden="true"
|
|
455
|
+
>
|
|
456
|
+
<path
|
|
457
|
+
strokeLinecap="round"
|
|
458
|
+
strokeLinejoin="round"
|
|
459
|
+
strokeWidth={2}
|
|
460
|
+
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
461
|
+
/>
|
|
462
|
+
</svg>
|
|
463
|
+
</a>
|
|
464
|
+
</div>
|
|
465
|
+
)}
|
|
466
|
+
|
|
429
467
|
{quote?.destinationAddress && (
|
|
430
468
|
<div className="flex justify-between items-center">
|
|
431
469
|
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
432
470
|
Destination Target Address:
|
|
433
|
-
<Tooltip message="This is the
|
|
471
|
+
<Tooltip message="This is the final execution address or recipient address">
|
|
434
472
|
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
435
473
|
</Tooltip>
|
|
436
474
|
</span>
|
|
@@ -476,28 +514,58 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
476
514
|
</div>
|
|
477
515
|
)}
|
|
478
516
|
|
|
479
|
-
{quote?.priceImpact != null &&
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
<
|
|
485
|
-
<
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
517
|
+
{quote?.priceImpact != null &&
|
|
518
|
+
(() => {
|
|
519
|
+
const priceImpactNum = Math.abs(Number(quote.priceImpact))
|
|
520
|
+
return (
|
|
521
|
+
<div className="space-y-1">
|
|
522
|
+
<div className="flex justify-between items-center">
|
|
523
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
524
|
+
Price Impact:
|
|
525
|
+
<Tooltip message="The percentage change in the token price caused by your trade. Higher impact means your trade affects the market price more, potentially resulting in worse rates.">
|
|
526
|
+
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
527
|
+
</Tooltip>
|
|
528
|
+
</span>
|
|
529
|
+
<span
|
|
530
|
+
className={`font-medium text-xs flex items-center gap-1 ${
|
|
531
|
+
priceImpactNum > 5
|
|
532
|
+
? "text-red-600 dark:text-red-400"
|
|
533
|
+
: priceImpactNum > 0.5
|
|
534
|
+
? "text-orange-600 dark:text-orange-400"
|
|
535
|
+
: "text-gray-900 dark:text-white"
|
|
536
|
+
}`}
|
|
537
|
+
>
|
|
538
|
+
{priceImpactNum > 0.5 && (
|
|
539
|
+
<span title="High price impact">
|
|
540
|
+
<svg
|
|
541
|
+
className="w-3 h-3"
|
|
542
|
+
fill="none"
|
|
543
|
+
stroke="currentColor"
|
|
544
|
+
viewBox="0 0 24 24"
|
|
545
|
+
aria-hidden="true"
|
|
546
|
+
>
|
|
547
|
+
<path
|
|
548
|
+
strokeLinecap="round"
|
|
549
|
+
strokeLinejoin="round"
|
|
550
|
+
strokeWidth={2}
|
|
551
|
+
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"
|
|
552
|
+
/>
|
|
553
|
+
</svg>
|
|
554
|
+
</span>
|
|
555
|
+
)}
|
|
556
|
+
{quote.priceImpact}%
|
|
557
|
+
</span>
|
|
558
|
+
</div>
|
|
559
|
+
{quote.priceImpactUsdDisplay && (
|
|
560
|
+
<div className="text-right">
|
|
561
|
+
<span className="text-xs text-gray-500 dark:text-gray-400">
|
|
562
|
+
≈ {quote.priceImpactUsdDisplay}
|
|
563
|
+
</span>
|
|
564
|
+
</div>
|
|
565
|
+
)}
|
|
497
566
|
</div>
|
|
498
|
-
)
|
|
499
|
-
|
|
500
|
-
)}
|
|
567
|
+
)
|
|
568
|
+
})()}
|
|
501
569
|
|
|
502
570
|
{quote?.fees?.totalFeeAmountUsd != null && (
|
|
503
571
|
<div className="flex justify-between items-center">
|