0xtrails 0.2.5 → 0.3.0
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/aave.d.ts +2 -0
- package/dist/aave.d.ts.map +1 -1
- package/dist/abortController.d.ts +8 -0
- package/dist/abortController.d.ts.map +1 -0
- package/dist/{ccip-CXlshvBY.js → ccip-BMB3uDZt.js} +1 -1
- package/dist/config.d.ts +0 -5
- package/dist/config.d.ts.map +1 -1
- package/dist/constants.d.ts +4 -4
- package/dist/constants.d.ts.map +1 -1
- package/dist/error.d.ts +4 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/fees.d.ts +19 -0
- package/dist/fees.d.ts.map +1 -0
- package/dist/{index-_QuyGrjU.js → index-QXPUrZVv.js} +48719 -50852
- package/dist/index.d.ts +9 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +811 -784
- package/dist/intentReceiptMonitor.d.ts +24 -0
- package/dist/intentReceiptMonitor.d.ts.map +1 -0
- package/dist/intentReceiptPoller.d.ts +69 -0
- package/dist/intentReceiptPoller.d.ts.map +1 -0
- package/dist/intents.d.ts +15 -11
- package/dist/intents.d.ts.map +1 -1
- package/dist/morpho.d.ts +6 -5
- package/dist/morpho.d.ts.map +1 -1
- package/dist/mutations.d.ts +16 -0
- package/dist/mutations.d.ts.map +1 -0
- package/dist/preconditions.d.ts +5 -4
- package/dist/preconditions.d.ts.map +1 -1
- package/dist/prepareSend.d.ts +7 -258
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/prices.d.ts +9 -6
- package/dist/prices.d.ts.map +1 -1
- package/dist/sequenceWallet.d.ts +3 -16
- package/dist/sequenceWallet.d.ts.map +1 -1
- package/dist/tokenBalances.d.ts +17 -13
- package/dist/tokenBalances.d.ts.map +1 -1
- package/dist/trails.d.ts +24 -40
- package/dist/trails.d.ts.map +1 -1
- package/dist/transactionIntent/constants.d.ts +7 -0
- package/dist/transactionIntent/constants.d.ts.map +1 -0
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts +44 -0
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -0
- package/dist/transactionIntent/deposits/gaslessDeposit.d.ts +30 -0
- package/dist/transactionIntent/deposits/gaslessDeposit.d.ts.map +1 -0
- package/dist/transactionIntent/deposits/index.d.ts +4 -0
- package/dist/transactionIntent/deposits/index.d.ts.map +1 -0
- package/dist/transactionIntent/deposits/standardDeposit.d.ts +30 -0
- package/dist/transactionIntent/deposits/standardDeposit.d.ts.map +1 -0
- package/dist/transactionIntent/execution/index.d.ts +2 -0
- package/dist/transactionIntent/execution/index.d.ts.map +1 -0
- package/dist/transactionIntent/execution/transactionState.d.ts +5 -0
- package/dist/transactionIntent/execution/transactionState.d.ts.map +1 -0
- package/dist/transactionIntent/handlers/crossChain.d.ts +82 -0
- package/dist/transactionIntent/handlers/crossChain.d.ts.map +1 -0
- package/dist/transactionIntent/handlers/index.d.ts +4 -0
- package/dist/transactionIntent/handlers/index.d.ts.map +1 -0
- package/dist/transactionIntent/handlers/sameChainDifferentToken.d.ts +62 -0
- package/dist/transactionIntent/handlers/sameChainDifferentToken.d.ts.map +1 -0
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts +72 -0
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts.map +1 -0
- package/dist/transactionIntent/index.d.ts +9 -0
- package/dist/transactionIntent/index.d.ts.map +1 -0
- package/dist/transactionIntent/quote/feeExtractors.d.ts +17 -0
- package/dist/transactionIntent/quote/feeExtractors.d.ts.map +1 -0
- package/dist/transactionIntent/quote/index.d.ts +4 -0
- package/dist/transactionIntent/quote/index.d.ts.map +1 -0
- package/dist/transactionIntent/quote/normalizeQuote.d.ts +34 -0
- package/dist/transactionIntent/quote/normalizeQuote.d.ts.map +1 -0
- package/dist/transactionIntent/quote/quoteHelpers.d.ts +5 -0
- package/dist/transactionIntent/quote/quoteHelpers.d.ts.map +1 -0
- package/dist/transactionIntent/types.d.ts +131 -0
- package/dist/transactionIntent/types.d.ts.map +1 -0
- package/dist/transactionIntent/utils/balanceChecker.d.ts +18 -0
- package/dist/transactionIntent/utils/balanceChecker.d.ts.map +1 -0
- package/dist/transactionIntent/utils/index.d.ts +4 -0
- package/dist/transactionIntent/utils/index.d.ts.map +1 -0
- package/dist/transactionIntent/utils/lifiHelpers.d.ts +10 -0
- package/dist/transactionIntent/utils/lifiHelpers.d.ts.map +1 -0
- package/dist/transactionIntent/utils/testnetHelpers.d.ts +3 -0
- package/dist/transactionIntent/utils/testnetHelpers.d.ts.map +1 -0
- package/dist/transactionIntent/validators.d.ts +6 -0
- package/dist/transactionIntent/validators.d.ts.map +1 -0
- package/dist/transactions.d.ts +6 -3
- package/dist/transactions.d.ts.map +1 -1
- package/dist/widget/components/AccountIntentTransactionHistoryButton.d.ts +4 -0
- package/dist/widget/components/AccountIntentTransactionHistoryButton.d.ts.map +1 -0
- package/dist/widget/components/AccountSettings.d.ts.map +1 -1
- package/dist/widget/components/ChainFilterDropdown.d.ts.map +1 -1
- package/dist/widget/components/ClassicSwap.d.ts +2 -3
- package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
- package/dist/widget/components/ConfigDisplay.d.ts.map +1 -1
- package/dist/widget/components/ConnectWallet.d.ts.map +1 -1
- package/dist/widget/components/ConnectedWallets.d.ts.map +1 -1
- package/dist/widget/components/DynamicInputStyles.d.ts +18 -0
- package/dist/widget/components/DynamicInputStyles.d.ts.map +1 -0
- package/dist/widget/components/DynamicSizeInputField.d.ts +13 -0
- package/dist/widget/components/DynamicSizeInputField.d.ts.map +1 -0
- package/dist/widget/components/Earn.d.ts +2 -3
- package/dist/widget/components/Earn.d.ts.map +1 -1
- package/dist/widget/components/ErrorAnimationIcon.d.ts +2 -0
- package/dist/widget/components/ErrorAnimationIcon.d.ts.map +1 -0
- package/dist/widget/components/FeeBreakdown.d.ts +9 -0
- package/dist/widget/components/FeeBreakdown.d.ts.map +1 -0
- package/dist/widget/components/FeeOptions.d.ts +5 -13
- package/dist/widget/components/FeeOptions.d.ts.map +1 -1
- package/dist/widget/components/Fund.d.ts +2 -3
- package/dist/widget/components/Fund.d.ts.map +1 -1
- package/dist/widget/components/FundMethods.d.ts.map +1 -1
- package/dist/widget/components/FundSwap.d.ts +2 -3
- package/dist/widget/components/FundSwap.d.ts.map +1 -1
- package/dist/widget/components/FundingMethodSelectorButton.d.ts.map +1 -1
- package/dist/widget/components/Identicon.d.ts.map +1 -1
- package/dist/widget/components/MeshConnectExchanges.d.ts +0 -3
- package/dist/widget/components/MeshConnectExchanges.d.ts.map +1 -1
- package/dist/widget/components/Modal.d.ts.map +1 -1
- package/dist/widget/components/Pay.d.ts +2 -3
- package/dist/widget/components/Pay.d.ts.map +1 -1
- package/dist/widget/components/PoolDeposit.d.ts +3 -3
- package/dist/widget/components/PoolDeposit.d.ts.map +1 -1
- package/dist/widget/components/PoolWithdraw.d.ts +3 -20
- package/dist/widget/components/PoolWithdraw.d.ts.map +1 -1
- package/dist/widget/components/QuoteDetails.d.ts +2 -0
- package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
- package/dist/widget/components/Receipt.d.ts.map +1 -1
- package/dist/widget/components/RecipientSelectorButton.d.ts.map +1 -1
- package/dist/widget/components/ScreenHeader.d.ts.map +1 -1
- package/dist/widget/components/Swap.d.ts +2 -3
- package/dist/widget/components/Swap.d.ts.map +1 -1
- package/dist/widget/components/ThemeProvider.d.ts.map +1 -1
- package/dist/widget/components/TokenDisplayNonSelectable.d.ts +11 -0
- package/dist/widget/components/TokenDisplayNonSelectable.d.ts.map +1 -0
- package/dist/widget/components/TokenSelector.d.ts.map +1 -1
- package/dist/widget/components/TokenSelectorButton.d.ts.map +1 -1
- package/dist/widget/components/Tooltip.d.ts +9 -0
- package/dist/widget/components/Tooltip.d.ts.map +1 -0
- package/dist/widget/components/TransferPendingVertical.d.ts.map +1 -1
- package/dist/widget/components/WaasFeeOptions.d.ts +1 -0
- package/dist/widget/components/WaasFeeOptions.d.ts.map +1 -1
- package/dist/widget/components/WalletConfirmation.d.ts.map +1 -1
- package/dist/widget/components/WalletConnect.d.ts.map +1 -1
- package/dist/widget/css/compiled.css +2 -2
- package/dist/widget/hooks/useCheckout.d.ts +17 -4
- package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
- package/dist/widget/hooks/useDefaultTokenSelection.d.ts.map +1 -1
- package/dist/widget/hooks/useQuote.d.ts +82 -0
- package/dist/widget/hooks/useQuote.d.ts.map +1 -0
- package/dist/widget/hooks/useSelectedFeeToken.d.ts +1 -0
- package/dist/widget/hooks/useSelectedFeeToken.d.ts.map +1 -1
- package/dist/widget/hooks/useSendForm.d.ts +5 -6
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
- package/dist/widget/hooks/useWalletConnectionContext.d.ts +25 -0
- package/dist/widget/hooks/useWalletConnectionContext.d.ts.map +1 -0
- package/dist/widget/index.js +2 -2
- package/dist/widget/widget.d.ts +17 -7
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +19 -21
- package/src/aave.ts +54 -1
- package/src/abortController.ts +35 -0
- package/src/config.ts +57 -58
- package/src/constants.ts +11 -9
- package/src/error.ts +21 -3
- package/src/fees.ts +210 -0
- package/src/index.ts +35 -13
- package/src/intentReceiptMonitor.ts +102 -0
- package/src/intentReceiptPoller.ts +299 -0
- package/src/intents.ts +205 -171
- package/src/morpho.ts +58 -9
- package/src/mutations.ts +129 -0
- package/src/preconditions.ts +16 -21
- package/src/prepareSend.ts +92 -4699
- package/src/prices.ts +26 -22
- package/src/relaySdk.ts +2 -2
- package/src/sequenceWallet.ts +6 -73
- package/src/tokenBalances.ts +175 -69
- package/src/trails.ts +230 -722
- package/src/transactionIntent/constants.ts +11 -0
- package/src/transactionIntent/deposits/depositOrchestrator.ts +210 -0
- package/src/transactionIntent/deposits/gaslessDeposit.ts +588 -0
- package/src/transactionIntent/deposits/index.ts +3 -0
- package/src/transactionIntent/deposits/standardDeposit.ts +379 -0
- package/src/transactionIntent/execution/index.ts +1 -0
- package/src/transactionIntent/execution/transactionState.ts +35 -0
- package/src/transactionIntent/handlers/crossChain.ts +1707 -0
- package/src/transactionIntent/handlers/index.ts +3 -0
- package/src/transactionIntent/handlers/sameChainDifferentToken.ts +323 -0
- package/src/transactionIntent/handlers/sameChainSameToken.ts +712 -0
- package/src/transactionIntent/index.ts +9 -0
- package/src/transactionIntent/quote/feeExtractors.ts +81 -0
- package/src/transactionIntent/quote/index.ts +3 -0
- package/src/transactionIntent/quote/normalizeQuote.ts +367 -0
- package/src/transactionIntent/quote/quoteHelpers.ts +53 -0
- package/src/transactionIntent/types.ts +157 -0
- package/src/transactionIntent/utils/balanceChecker.ts +96 -0
- package/src/transactionIntent/utils/index.ts +3 -0
- package/src/transactionIntent/utils/lifiHelpers.ts +68 -0
- package/src/transactionIntent/utils/testnetHelpers.ts +10 -0
- package/src/transactionIntent/validators.ts +57 -0
- package/src/transactions.ts +98 -71
- package/src/widget/compiled.css +2 -2
- package/src/widget/components/AccountIntentTransactionHistory.tsx +36 -36
- package/src/widget/components/AccountIntentTransactionHistoryButton.tsx +22 -0
- package/src/widget/components/AccountSettings.tsx +70 -41
- package/src/widget/components/ChainFilterDropdown.tsx +24 -3
- package/src/widget/components/ClassicSwap.tsx +44 -107
- package/src/widget/components/ConfigDisplay.tsx +0 -11
- package/src/widget/components/ConnectWallet.tsx +4 -1
- package/src/widget/components/ConnectedWallets.tsx +51 -25
- package/src/widget/components/DynamicInputStyles.tsx +76 -0
- package/src/widget/components/DynamicSizeInputField.tsx +109 -0
- package/src/widget/components/Earn.tsx +34 -45
- package/src/widget/components/ErrorAnimationIcon.tsx +130 -0
- package/src/widget/components/FeeBreakdown.tsx +155 -0
- package/src/widget/components/FeeOption.tsx +2 -2
- package/src/widget/components/FeeOptions.tsx +151 -112
- package/src/widget/components/Fund.tsx +10 -29
- package/src/widget/components/FundMethods.tsx +4 -3
- package/src/widget/components/FundSwap.tsx +2 -3
- package/src/widget/components/FundingMethodSelectorButton.tsx +24 -14
- package/src/widget/components/Identicon.tsx +164 -95
- package/src/widget/components/MeshConnectExchanges.tsx +2 -15
- package/src/widget/components/Modal.tsx +0 -12
- package/src/widget/components/Pay.tsx +72 -75
- package/src/widget/components/PoolDeposit.tsx +221 -242
- package/src/widget/components/PoolWithdraw.tsx +347 -469
- package/src/widget/components/PriceImpactWarning.tsx +1 -1
- package/src/widget/components/QuoteDetails.tsx +906 -484
- package/src/widget/components/Receipt.tsx +16 -2
- package/src/widget/components/RecipientSelectorButton.tsx +7 -5
- package/src/widget/components/Recipients.tsx +1 -1
- package/src/widget/components/ScreenHeader.tsx +60 -36
- package/src/widget/components/Swap.tsx +2 -3
- package/src/widget/components/ThemeProvider.tsx +2 -1
- package/src/widget/components/TokenDisplayNonSelectable.tsx +40 -0
- package/src/widget/components/TokenImage.tsx +1 -1
- package/src/widget/components/TokenSelector.tsx +62 -53
- package/src/widget/components/TokenSelectorButton.tsx +38 -15
- package/src/widget/components/Tooltip.tsx +51 -0
- package/src/widget/components/TransferPendingVertical.tsx +12 -8
- package/src/widget/components/WaasFeeOptions.tsx +139 -4
- package/src/widget/components/WalletConfirmation.tsx +23 -13
- package/src/widget/components/WalletConnect.tsx +93 -29
- package/src/widget/hooks/useAmountUsd.ts +9 -9
- package/src/widget/hooks/useCheckout.ts +97 -9
- package/src/widget/hooks/useDefaultTokenSelection.tsx +27 -21
- package/src/widget/hooks/useQuote.ts +466 -0
- package/src/widget/hooks/useSelectedFeeToken.tsx +32 -37
- package/src/widget/hooks/useSendForm.ts +45 -51
- package/src/widget/hooks/useTokenList.ts +34 -26
- package/src/widget/hooks/useWalletConnectionContext.tsx +128 -0
- package/src/widget/widget.tsx +365 -390
- package/dist/apiClient.d.ts +0 -9
- package/dist/apiClient.d.ts.map +0 -1
- package/dist/intentEntrypoint.d.ts +0 -114
- package/dist/intentEntrypoint.d.ts.map +0 -1
- package/dist/metaTxnMonitor.d.ts +0 -15
- package/dist/metaTxnMonitor.d.ts.map +0 -1
- package/dist/metaTxns.d.ts +0 -11
- package/dist/metaTxns.d.ts.map +0 -1
- package/dist/relayer.d.ts +0 -43
- package/dist/relayer.d.ts.map +0 -1
- package/src/apiClient.ts +0 -35
- package/src/intentEntrypoint.ts +0 -203
- package/src/metaTxnMonitor.ts +0 -171
- package/src/metaTxns.ts +0 -45
- package/src/relayer.ts +0 -289
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { TokenImage } from "./TokenImage.js"
|
|
2
|
-
import {
|
|
2
|
+
import { ChainImage } from "./ChainImage.js"
|
|
3
|
+
import { InfoIcon } from "@0xsequence/design-system"
|
|
4
|
+
import { Tooltip } from "./Tooltip.js"
|
|
3
5
|
import type React from "react"
|
|
4
6
|
import { getExplorerUrlForAddress } from "../../explorer.js"
|
|
5
7
|
import type { PrepareSendQuote } from "../../prepareSend.js"
|
|
@@ -7,6 +9,7 @@ import { useState, useEffect, useRef } from "react"
|
|
|
7
9
|
import { truncateAddress } from "../../utils.js"
|
|
8
10
|
import { PriceImpactWarning } from "./PriceImpactWarning.js"
|
|
9
11
|
import { usePriceImpactWarning } from "../hooks/usePriceImpactWarning.js"
|
|
12
|
+
import { formatUsdAmountDisplay } from "../../tokenBalances.js"
|
|
10
13
|
|
|
11
14
|
interface QuoteDetailsProps {
|
|
12
15
|
quote?: PrepareSendQuote | null
|
|
@@ -14,6 +17,8 @@ interface QuoteDetailsProps {
|
|
|
14
17
|
children?: React.ReactNode
|
|
15
18
|
onExpand?: (isExpanded: boolean) => void
|
|
16
19
|
swapMode?: boolean
|
|
20
|
+
compact?: boolean
|
|
21
|
+
isRefetching?: boolean
|
|
17
22
|
}
|
|
18
23
|
|
|
19
24
|
// Helper function to format completion time
|
|
@@ -44,12 +49,16 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
44
49
|
children,
|
|
45
50
|
onExpand,
|
|
46
51
|
swapMode,
|
|
52
|
+
compact = false,
|
|
53
|
+
isRefetching = false,
|
|
47
54
|
}) => {
|
|
48
55
|
const [showCalldata, setShowCalldata] = useState(false)
|
|
49
56
|
const [showOriginRate, setShowOriginRate] = useState(true)
|
|
50
57
|
const [isExpanded, setIsExpanded] = useState(false)
|
|
58
|
+
const [showMoreInfo, setShowMoreInfo] = useState(false)
|
|
51
59
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
52
60
|
const calldataRef = useRef<HTMLDivElement>(null)
|
|
61
|
+
const moreInfoRef = useRef<HTMLDivElement>(null)
|
|
53
62
|
|
|
54
63
|
const priceImpactConfig = usePriceImpactWarning()
|
|
55
64
|
|
|
@@ -72,7 +81,9 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
72
81
|
if (!showContent) return null
|
|
73
82
|
|
|
74
83
|
return (
|
|
75
|
-
<div
|
|
84
|
+
<div
|
|
85
|
+
className={`relative transition-opacity duration-300 ${isRefetching ? "opacity-50" : ""}`}
|
|
86
|
+
>
|
|
76
87
|
{/* Price Impact Warning - always visible when conditions are met */}
|
|
77
88
|
<PriceImpactWarning
|
|
78
89
|
quote={quote}
|
|
@@ -81,6 +92,35 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
81
92
|
fallbackBridgeUrl={priceImpactConfig.fallbackBridgeUrl}
|
|
82
93
|
/>
|
|
83
94
|
|
|
95
|
+
{/* Insufficient Balance Warning - always visible when conditions are met */}
|
|
96
|
+
{quote?.noSufficientBalance && (
|
|
97
|
+
<div className="flex justify-between items-center mb-2 p-2 bg-amber-50 dark:bg-amber-900/20 rounded-lg">
|
|
98
|
+
<span className="text-xs text-amber-600 dark:text-amber-400 flex items-center gap-1">
|
|
99
|
+
Balance Status:
|
|
100
|
+
<Tooltip message="Your wallet does not have sufficient balance to complete this transaction">
|
|
101
|
+
<InfoIcon className="w-3 h-3 text-amber-500 dark:text-amber-400 cursor-pointer" />
|
|
102
|
+
</Tooltip>
|
|
103
|
+
</span>
|
|
104
|
+
<span className="font-medium text-xs text-amber-600 dark:text-amber-400 flex items-center gap-1">
|
|
105
|
+
<svg
|
|
106
|
+
className="w-3 h-3"
|
|
107
|
+
fill="none"
|
|
108
|
+
stroke="currentColor"
|
|
109
|
+
viewBox="0 0 24 24"
|
|
110
|
+
aria-hidden="true"
|
|
111
|
+
>
|
|
112
|
+
<path
|
|
113
|
+
strokeLinecap="round"
|
|
114
|
+
strokeLinejoin="round"
|
|
115
|
+
strokeWidth={2}
|
|
116
|
+
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"
|
|
117
|
+
/>
|
|
118
|
+
</svg>
|
|
119
|
+
Insufficient Balance
|
|
120
|
+
</span>
|
|
121
|
+
</div>
|
|
122
|
+
)}
|
|
123
|
+
|
|
84
124
|
{/* More Details Button - only visible when collapsed */}
|
|
85
125
|
{!isExpanded && (
|
|
86
126
|
<div className={`flex justify-center`}>
|
|
@@ -88,7 +128,7 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
88
128
|
<button
|
|
89
129
|
type="button"
|
|
90
130
|
onClick={() => setIsExpanded(true)}
|
|
91
|
-
className="w-full flex items-center justify-between py-2 px-4 trails-border-radius-button transition-colors cursor-pointer text-xs
|
|
131
|
+
className="w-full flex items-center justify-between py-2 px-4 trails-border-radius-button transition-colors cursor-pointer text-xs"
|
|
92
132
|
aria-label="Show more details"
|
|
93
133
|
>
|
|
94
134
|
<div className="flex items-center gap-2 text-gray-600 dark:text-gray-400 whitespace-nowrap max-w-48 truncate">
|
|
@@ -161,7 +201,7 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
161
201
|
<button
|
|
162
202
|
type="button"
|
|
163
203
|
onClick={() => setIsExpanded(true)}
|
|
164
|
-
className=
|
|
204
|
+
className={`w-full max-w-md flex items-center ${compact ? "justify-center" : "justify-between"} gap-2 py-1 px-1 trails-border-radius-button transition-colors cursor-pointer text-xs text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300`}
|
|
165
205
|
aria-label="Show transaction details"
|
|
166
206
|
>
|
|
167
207
|
<span>Transaction details</span>
|
|
@@ -195,9 +235,7 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
195
235
|
className={`text-sm ${swapMode ? "p-2 space-y-2" : "p-4 rounded-lg space-y-4 trails-bg-secondary"}`}
|
|
196
236
|
>
|
|
197
237
|
{/* Close Button - only visible when expanded, at top center */}
|
|
198
|
-
<div
|
|
199
|
-
className={`flex justify-center ${swapMode ? "mb-2 -mt-1" : "mb-4 -mt-2"}`}
|
|
200
|
-
>
|
|
238
|
+
<div className={`flex justify-center mb-4 -mt-2`}>
|
|
201
239
|
{swapMode ? (
|
|
202
240
|
<button
|
|
203
241
|
type="button"
|
|
@@ -246,54 +284,7 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
246
284
|
)}
|
|
247
285
|
</div>
|
|
248
286
|
<div className="space-y-3">
|
|
249
|
-
{/*
|
|
250
|
-
{quote?.noSufficientBalance && (
|
|
251
|
-
<div className="flex justify-between items-center">
|
|
252
|
-
<span className="text-xs text-amber-600 dark:text-amber-400 flex items-center gap-1">
|
|
253
|
-
Balance Status:
|
|
254
|
-
<Tooltip message="Your wallet does not have sufficient balance to complete this transaction">
|
|
255
|
-
<InfoIcon className="w-3 h-3 text-amber-500 dark:text-amber-400 cursor-pointer" />
|
|
256
|
-
</Tooltip>
|
|
257
|
-
</span>
|
|
258
|
-
<span className="font-medium text-xs text-amber-600 dark:text-amber-400 flex items-center gap-1">
|
|
259
|
-
<svg
|
|
260
|
-
className="w-3 h-3"
|
|
261
|
-
fill="none"
|
|
262
|
-
stroke="currentColor"
|
|
263
|
-
viewBox="0 0 24 24"
|
|
264
|
-
aria-hidden="true"
|
|
265
|
-
>
|
|
266
|
-
<path
|
|
267
|
-
strokeLinecap="round"
|
|
268
|
-
strokeLinejoin="round"
|
|
269
|
-
strokeWidth={2}
|
|
270
|
-
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"
|
|
271
|
-
/>
|
|
272
|
-
</svg>
|
|
273
|
-
Insufficient Balance
|
|
274
|
-
</span>
|
|
275
|
-
</div>
|
|
276
|
-
)}
|
|
277
|
-
|
|
278
|
-
{quote?.originTokenRate && quote?.destinationTokenRate && (
|
|
279
|
-
<div className="flex justify-between items-center">
|
|
280
|
-
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
281
|
-
Exchange Rate:
|
|
282
|
-
<Tooltip message="The current exchange rate between the origin and destination tokens">
|
|
283
|
-
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
284
|
-
</Tooltip>
|
|
285
|
-
</span>
|
|
286
|
-
<button
|
|
287
|
-
type="button"
|
|
288
|
-
onClick={() => setShowOriginRate(!showOriginRate)}
|
|
289
|
-
className="font-medium text-xs hover:underline cursor-pointer text-gray-900 hover:text-gray-700 dark:text-white dark:hover:text-gray-300"
|
|
290
|
-
>
|
|
291
|
-
{showOriginRate
|
|
292
|
-
? quote.originTokenRate
|
|
293
|
-
: quote.destinationTokenRate}
|
|
294
|
-
</button>
|
|
295
|
-
</div>
|
|
296
|
-
)}
|
|
287
|
+
{/* Estimated Time */}
|
|
297
288
|
{quote?.completionEstimateSeconds != null && (
|
|
298
289
|
<div className="flex justify-between items-center">
|
|
299
290
|
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
@@ -322,465 +313,896 @@ export const QuoteDetails: React.FC<QuoteDetailsProps> = ({
|
|
|
322
313
|
</div>
|
|
323
314
|
)}
|
|
324
315
|
|
|
325
|
-
{
|
|
326
|
-
|
|
327
|
-
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
328
|
-
Network Cost:
|
|
329
|
-
<Tooltip message="The estimated gas cost for executing this transaction on the origin chain">
|
|
330
|
-
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
331
|
-
</Tooltip>
|
|
332
|
-
</span>
|
|
333
|
-
<span className="font-medium text-xs text-gray-900 dark:text-white flex items-center gap-1">
|
|
334
|
-
<svg
|
|
335
|
-
aria-hidden="true"
|
|
336
|
-
focusable="false"
|
|
337
|
-
data-prefix="fas"
|
|
338
|
-
data-icon="gas-pump"
|
|
339
|
-
className="svg-inline--fa fa-gas-pump "
|
|
340
|
-
role="img"
|
|
341
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
342
|
-
viewBox="0 0 512 512"
|
|
343
|
-
width="12"
|
|
344
|
-
>
|
|
345
|
-
<path
|
|
346
|
-
fill="currentColor"
|
|
347
|
-
d="M32 64C32 28.7 60.7 0 96 0H256c35.3 0 64 28.7 64 64V256h8c48.6 0 88 39.4 88 88v32c0 13.3 10.7 24 24 24s24-10.7 24-24V222c-27.6-7.1-48-32.2-48-62V96L384 64c-8.8-8.8-8.8-23.2 0-32s23.2-8.8 32 0l77.3 77.3c12 12 18.7 28.3 18.7 45.3V168v24 32V376c0 39.8-32.2 72-72 72s-72-32.2-72-72V344c0-22.1-17.9-40-40-40h-8V448c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32V64zM96 80v96c0 8.8 7.2 16 16 16H240c8.8 0 16-7.2 16-16V80c0-8.8-7.2-16-16-16H112c-8.8 0-16 7.2-16 16z"
|
|
348
|
-
></path>
|
|
349
|
-
</svg>
|
|
350
|
-
{quote.gasCostUsdDisplay}
|
|
351
|
-
</span>
|
|
352
|
-
</div>
|
|
353
|
-
)}
|
|
316
|
+
{/* Spacer */}
|
|
317
|
+
<div className="h-2" />
|
|
354
318
|
|
|
355
|
-
{
|
|
356
|
-
|
|
357
|
-
quote?.
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
319
|
+
{/* Gas Costs Section */}
|
|
320
|
+
{quote?.trailsFeeBreakdown &&
|
|
321
|
+
(quote?.trailsFeeBreakdown.originRelayFee ||
|
|
322
|
+
quote?.trailsFeeBreakdown.destinationRelayFee) && (
|
|
323
|
+
<>
|
|
324
|
+
{/* Origin Gas */}
|
|
325
|
+
{quote.trailsFeeBreakdown.originRelayFee && (
|
|
326
|
+
<div className="flex justify-between items-center">
|
|
327
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
328
|
+
Origin Gas
|
|
329
|
+
<ChainImage chainId={quote.originChain.id} size={16} />:
|
|
330
|
+
<Tooltip message="Gas fee for executing the transaction on the origin chain">
|
|
331
|
+
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
332
|
+
</Tooltip>
|
|
333
|
+
</span>
|
|
334
|
+
<span className="font-medium text-xs text-gray-900 dark:text-white">
|
|
335
|
+
{quote.trailsFeeBreakdown.originRelayFee.usdValue}
|
|
336
|
+
</span>
|
|
337
|
+
</div>
|
|
338
|
+
)}
|
|
339
|
+
|
|
340
|
+
{/* Destination Gas */}
|
|
341
|
+
{quote.trailsFeeBreakdown.destinationRelayFee && (
|
|
342
|
+
<div className="flex justify-between items-center">
|
|
343
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
344
|
+
Destination Gas
|
|
345
|
+
<ChainImage
|
|
346
|
+
chainId={quote.destinationChain.id}
|
|
347
|
+
size={16}
|
|
348
|
+
/>
|
|
349
|
+
:
|
|
350
|
+
<Tooltip message="Gas fee for executing the transaction on the destination chain">
|
|
351
|
+
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
352
|
+
</Tooltip>
|
|
353
|
+
</span>
|
|
354
|
+
<span className="font-medium text-xs text-gray-900 dark:text-white">
|
|
355
|
+
{quote.trailsFeeBreakdown.destinationRelayFee.usdValue}
|
|
356
|
+
</span>
|
|
357
|
+
</div>
|
|
358
|
+
)}
|
|
359
|
+
|
|
360
|
+
{/* All Gas Costs */}
|
|
361
|
+
{(quote.trailsFeeBreakdown.originRelayFee ||
|
|
362
|
+
quote.trailsFeeBreakdown.destinationRelayFee) && (
|
|
363
|
+
<div className="flex justify-between items-center">
|
|
364
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
365
|
+
All gas costs:
|
|
366
|
+
<Tooltip message="Total gas costs for executing transactions on both origin and destination chains">
|
|
367
|
+
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
368
|
+
</Tooltip>
|
|
369
|
+
</span>
|
|
370
|
+
<span className="font-medium text-xs text-gray-900 dark:text-white flex items-center gap-1 pt-2 border-t border-gray-200 dark:border-gray-700">
|
|
371
|
+
<svg
|
|
372
|
+
aria-hidden="true"
|
|
373
|
+
focusable="false"
|
|
374
|
+
data-prefix="fas"
|
|
375
|
+
data-icon="gas-pump"
|
|
376
|
+
className="svg-inline--fa fa-gas-pump"
|
|
377
|
+
role="img"
|
|
378
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
379
|
+
viewBox="0 0 512 512"
|
|
380
|
+
width="12"
|
|
381
|
+
>
|
|
382
|
+
<path
|
|
383
|
+
fill="currentColor"
|
|
384
|
+
d="M32 64C32 28.7 60.7 0 96 0H256c35.3 0 64 28.7 64 64V256h8c48.6 0 88 39.4 88 88v32c0 13.3 10.7 24 24 24s24-10.7 24-24V222c-27.6-7.1-48-32.2-48-62V96L384 64c-8.8-8.8-8.8-23.2 0-32s23.2-8.8 32 0l77.3 77.3c12 12 18.7 28.3 18.7 45.3V168v24 32V376c0 39.8-32.2 72-72 72s-72-32.2-72-72V344c0-22.1-17.9-40-40-40h-8V448c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32V64zM96 80v96c0 8.8 7.2 16 16 16H240c8.8 0 16-7.2 16-16V80c0-8.8-7.2-16-16-16H112c-8.8 0-16 7.2-16 16z"
|
|
376
385
|
/>
|
|
377
|
-
|
|
386
|
+
</svg>
|
|
387
|
+
{(() => {
|
|
388
|
+
const originGasUsd = parseFloat(
|
|
389
|
+
quote.trailsFeeBreakdown.originRelayFee?.usdValue?.replace(
|
|
390
|
+
/[^0-9.-]/g,
|
|
391
|
+
"",
|
|
392
|
+
) || "0",
|
|
393
|
+
)
|
|
394
|
+
const destGasUsd = parseFloat(
|
|
395
|
+
quote.trailsFeeBreakdown.destinationRelayFee?.usdValue?.replace(
|
|
396
|
+
/[^0-9.-]/g,
|
|
397
|
+
"",
|
|
398
|
+
) || "0",
|
|
399
|
+
)
|
|
400
|
+
const totalGasUsd = originGasUsd + destGasUsd
|
|
401
|
+
return formatUsdAmountDisplay(totalGasUsd)
|
|
402
|
+
})()}
|
|
403
|
+
</span>
|
|
404
|
+
</div>
|
|
405
|
+
)}
|
|
406
|
+
|
|
407
|
+
{/* Spacer */}
|
|
408
|
+
<div className="h-2" />
|
|
409
|
+
</>
|
|
410
|
+
)}
|
|
411
|
+
|
|
412
|
+
{/* Provider Costs Section */}
|
|
413
|
+
{(() => {
|
|
414
|
+
if (!quote?.trailsFeeBreakdown) return null
|
|
415
|
+
|
|
416
|
+
// Check if provider fee is non-zero
|
|
417
|
+
const hasProviderFee =
|
|
418
|
+
quote.trailsFeeBreakdown.providerFee &&
|
|
419
|
+
parseFloat(
|
|
420
|
+
quote.trailsFeeBreakdown.providerFee.usdValue?.replace(
|
|
421
|
+
/[^0-9.-]/g,
|
|
422
|
+
"",
|
|
423
|
+
) || "0",
|
|
424
|
+
) !== 0
|
|
425
|
+
|
|
426
|
+
// Check if trails fee is non-zero
|
|
427
|
+
const hasTrailsFee =
|
|
428
|
+
quote.trailsFeeBreakdown.trailsFee &&
|
|
429
|
+
parseFloat(
|
|
430
|
+
quote.trailsFeeBreakdown.trailsFee.usdValue?.replace(
|
|
431
|
+
/[^0-9.-]/g,
|
|
432
|
+
"",
|
|
433
|
+
) || "0",
|
|
434
|
+
) !== 0
|
|
435
|
+
|
|
436
|
+
if (!hasProviderFee && !hasTrailsFee) return null
|
|
437
|
+
|
|
438
|
+
return (
|
|
439
|
+
<>
|
|
440
|
+
{/* Bridge/Swap Provider Fee */}
|
|
441
|
+
{hasProviderFee &&
|
|
442
|
+
quote.trailsFeeBreakdown.providerFee &&
|
|
443
|
+
(() => {
|
|
444
|
+
const providerFee = quote.trailsFeeBreakdown.providerFee
|
|
445
|
+
const isCrossChain =
|
|
446
|
+
quote.originChain.id !== quote.destinationChain.id
|
|
447
|
+
const providerName = quote.quoteProvider?.name || ""
|
|
448
|
+
|
|
449
|
+
return (
|
|
450
|
+
<div className="flex justify-between items-center">
|
|
451
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
452
|
+
{isCrossChain ? (
|
|
453
|
+
providerName ? (
|
|
454
|
+
<>
|
|
455
|
+
Bridge (
|
|
456
|
+
<a
|
|
457
|
+
href={quote.quoteProvider?.url}
|
|
458
|
+
target="_blank"
|
|
459
|
+
rel="noopener noreferrer"
|
|
460
|
+
className="hover:underline flex items-center gap-0.5"
|
|
461
|
+
>
|
|
462
|
+
{providerName}
|
|
463
|
+
<svg
|
|
464
|
+
className="w-3 h-3"
|
|
465
|
+
fill="none"
|
|
466
|
+
stroke="currentColor"
|
|
467
|
+
viewBox="0 0 24 24"
|
|
468
|
+
aria-hidden="true"
|
|
469
|
+
>
|
|
470
|
+
<path
|
|
471
|
+
strokeLinecap="round"
|
|
472
|
+
strokeLinejoin="round"
|
|
473
|
+
strokeWidth={2}
|
|
474
|
+
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
475
|
+
/>
|
|
476
|
+
</svg>
|
|
477
|
+
</a>
|
|
478
|
+
):
|
|
479
|
+
</>
|
|
480
|
+
) : (
|
|
481
|
+
<>Bridge:</>
|
|
482
|
+
)
|
|
483
|
+
) : providerName ? (
|
|
484
|
+
<>
|
|
485
|
+
Liquidity Provider (
|
|
486
|
+
<a
|
|
487
|
+
href={quote.quoteProvider?.url}
|
|
488
|
+
target="_blank"
|
|
489
|
+
rel="noopener noreferrer"
|
|
490
|
+
className="hover:underline flex items-center gap-0.5"
|
|
491
|
+
>
|
|
492
|
+
{providerName}
|
|
493
|
+
<svg
|
|
494
|
+
className="w-3 h-3"
|
|
495
|
+
fill="none"
|
|
496
|
+
stroke="currentColor"
|
|
497
|
+
viewBox="0 0 24 24"
|
|
498
|
+
aria-hidden="true"
|
|
499
|
+
>
|
|
500
|
+
<path
|
|
501
|
+
strokeLinecap="round"
|
|
502
|
+
strokeLinejoin="round"
|
|
503
|
+
strokeWidth={2}
|
|
504
|
+
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
505
|
+
/>
|
|
506
|
+
</svg>
|
|
507
|
+
</a>
|
|
508
|
+
):
|
|
509
|
+
</>
|
|
510
|
+
) : (
|
|
511
|
+
<>Liquidity Provider:</>
|
|
512
|
+
)}
|
|
513
|
+
<Tooltip message="Fee charged by the bridge/swap provider for executing the transaction">
|
|
514
|
+
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
515
|
+
</Tooltip>
|
|
516
|
+
</span>
|
|
517
|
+
<span className="font-medium text-xs text-gray-900 dark:text-white">
|
|
518
|
+
{providerFee.usdValue}
|
|
519
|
+
</span>
|
|
378
520
|
</div>
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
521
|
+
)
|
|
522
|
+
})()}
|
|
523
|
+
|
|
524
|
+
{/* Swap Fees (implicit costs) */}
|
|
525
|
+
{(() => {
|
|
526
|
+
// Calculate swap fees: (originAmount - destinationAmount) - totalFees
|
|
527
|
+
const originUsd = parseFloat(
|
|
528
|
+
quote.originAmountUsdDisplay?.replace(/[^0-9.-]/g, "") ||
|
|
529
|
+
"0",
|
|
530
|
+
)
|
|
531
|
+
const destUsd = parseFloat(
|
|
532
|
+
quote.destinationAmountUsdDisplay?.replace(
|
|
533
|
+
/[^0-9.-]/g,
|
|
534
|
+
"",
|
|
535
|
+
) || "0",
|
|
536
|
+
)
|
|
537
|
+
const totalFeesUsd = parseFloat(
|
|
538
|
+
quote.fees?.totalFeeAmountUsdDisplay?.replace(
|
|
539
|
+
/[^0-9.-]/g,
|
|
540
|
+
"",
|
|
541
|
+
) || "0",
|
|
542
|
+
)
|
|
543
|
+
|
|
544
|
+
const swapFeesUsd = originUsd - destUsd - totalFeesUsd
|
|
545
|
+
|
|
546
|
+
// Only show if swap fees > 0
|
|
547
|
+
if (swapFeesUsd <= 0) return null
|
|
548
|
+
|
|
549
|
+
return (
|
|
550
|
+
<div className="flex justify-between items-center">
|
|
551
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
552
|
+
Swap:
|
|
553
|
+
<Tooltip message="Implicit costs including DEX fees, liquidity provider fees, and routing costs">
|
|
554
|
+
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
555
|
+
</Tooltip>
|
|
556
|
+
</span>
|
|
557
|
+
<span className="font-medium text-xs text-gray-900 dark:text-white">
|
|
558
|
+
{formatUsdAmountDisplay(swapFeesUsd)}
|
|
559
|
+
</span>
|
|
560
|
+
</div>
|
|
561
|
+
)
|
|
562
|
+
})()}
|
|
563
|
+
|
|
564
|
+
{/* Trails Platform Fee */}
|
|
565
|
+
{hasTrailsFee &&
|
|
566
|
+
quote.trailsFeeBreakdown.trailsFee &&
|
|
567
|
+
(() => {
|
|
568
|
+
const trailsFee = quote.trailsFeeBreakdown.trailsFee
|
|
569
|
+
|
|
570
|
+
return (
|
|
571
|
+
<div className="flex justify-between items-center">
|
|
572
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
573
|
+
Trails:
|
|
574
|
+
<Tooltip message="Platform fee for using the Trails service">
|
|
575
|
+
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
576
|
+
</Tooltip>
|
|
577
|
+
</span>
|
|
578
|
+
<span className="font-medium text-xs text-gray-900 dark:text-white">
|
|
579
|
+
{trailsFee.usdValue}
|
|
580
|
+
</span>
|
|
581
|
+
</div>
|
|
582
|
+
)
|
|
583
|
+
})()}
|
|
584
|
+
|
|
585
|
+
{/* All Provider Costs */}
|
|
586
|
+
{(hasProviderFee || hasTrailsFee) &&
|
|
587
|
+
(() => {
|
|
588
|
+
const providerUsd = parseFloat(
|
|
589
|
+
quote.trailsFeeBreakdown.providerFee?.usdValue?.replace(
|
|
590
|
+
/[^0-9.-]/g,
|
|
591
|
+
"",
|
|
592
|
+
) || "0",
|
|
593
|
+
)
|
|
594
|
+
const trailsUsd = parseFloat(
|
|
595
|
+
quote.trailsFeeBreakdown.trailsFee?.usdValue?.replace(
|
|
596
|
+
/[^0-9.-]/g,
|
|
597
|
+
"",
|
|
598
|
+
) || "0",
|
|
599
|
+
)
|
|
600
|
+
|
|
601
|
+
// Calculate swap fees
|
|
602
|
+
const originUsd = parseFloat(
|
|
603
|
+
quote.originAmountUsdDisplay?.replace(
|
|
604
|
+
/[^0-9.-]/g,
|
|
605
|
+
"",
|
|
606
|
+
) || "0",
|
|
607
|
+
)
|
|
608
|
+
const destUsd = parseFloat(
|
|
609
|
+
quote.destinationAmountUsdDisplay?.replace(
|
|
610
|
+
/[^0-9.-]/g,
|
|
611
|
+
"",
|
|
612
|
+
) || "0",
|
|
613
|
+
)
|
|
614
|
+
const totalFeesUsd = parseFloat(
|
|
615
|
+
quote.fees?.totalFeeAmountUsdDisplay?.replace(
|
|
616
|
+
/[^0-9.-]/g,
|
|
617
|
+
"",
|
|
618
|
+
) || "0",
|
|
619
|
+
)
|
|
620
|
+
const swapFeesUsd = Math.max(
|
|
621
|
+
0,
|
|
622
|
+
originUsd - destUsd - totalFeesUsd,
|
|
623
|
+
)
|
|
624
|
+
|
|
625
|
+
const totalProviderUsd =
|
|
626
|
+
providerUsd + trailsUsd + swapFeesUsd
|
|
627
|
+
|
|
628
|
+
return (
|
|
629
|
+
<div className="flex justify-between items-center">
|
|
630
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
631
|
+
All provider costs:
|
|
632
|
+
<Tooltip message="Total fees charged by providers, including bridge/swap, platform fees, and implicit swap costs">
|
|
633
|
+
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
634
|
+
</Tooltip>
|
|
635
|
+
</span>
|
|
636
|
+
<span className="font-medium text-xs text-gray-900 dark:text-white pt-2 border-t border-gray-200 dark:border-gray-700">
|
|
637
|
+
{formatUsdAmountDisplay(totalProviderUsd)}
|
|
638
|
+
</span>
|
|
639
|
+
</div>
|
|
640
|
+
)
|
|
641
|
+
})()}
|
|
642
|
+
|
|
643
|
+
{/* Spacer */}
|
|
644
|
+
<div className="h-2" />
|
|
645
|
+
|
|
646
|
+
{/* Total Fees */}
|
|
647
|
+
{(() => {
|
|
648
|
+
// Calculate total gas costs
|
|
649
|
+
const originGasUsd = parseFloat(
|
|
650
|
+
quote.trailsFeeBreakdown?.originRelayFee?.usdValue?.replace(
|
|
651
|
+
/[^0-9.-]/g,
|
|
652
|
+
"",
|
|
653
|
+
) || "0",
|
|
654
|
+
)
|
|
655
|
+
const destGasUsd = parseFloat(
|
|
656
|
+
quote.trailsFeeBreakdown?.destinationRelayFee?.usdValue?.replace(
|
|
657
|
+
/[^0-9.-]/g,
|
|
658
|
+
"",
|
|
659
|
+
) || "0",
|
|
660
|
+
)
|
|
661
|
+
const totalGasUsd = originGasUsd + destGasUsd
|
|
662
|
+
|
|
663
|
+
// Calculate total provider costs (including swap fees)
|
|
664
|
+
const providerUsd = parseFloat(
|
|
665
|
+
quote.trailsFeeBreakdown?.providerFee?.usdValue?.replace(
|
|
666
|
+
/[^0-9.-]/g,
|
|
667
|
+
"",
|
|
668
|
+
) || "0",
|
|
669
|
+
)
|
|
670
|
+
const trailsUsd = parseFloat(
|
|
671
|
+
quote.trailsFeeBreakdown?.trailsFee?.usdValue?.replace(
|
|
672
|
+
/[^0-9.-]/g,
|
|
673
|
+
"",
|
|
674
|
+
) || "0",
|
|
675
|
+
)
|
|
676
|
+
const originUsd = parseFloat(
|
|
677
|
+
quote.originAmountUsdDisplay?.replace(/[^0-9.-]/g, "") ||
|
|
678
|
+
"0",
|
|
679
|
+
)
|
|
680
|
+
const destUsd = parseFloat(
|
|
681
|
+
quote.destinationAmountUsdDisplay?.replace(
|
|
682
|
+
/[^0-9.-]/g,
|
|
683
|
+
"",
|
|
684
|
+
) || "0",
|
|
685
|
+
)
|
|
686
|
+
const totalFeesUsd = parseFloat(
|
|
687
|
+
quote.fees?.totalFeeAmountUsdDisplay?.replace(
|
|
688
|
+
/[^0-9.-]/g,
|
|
689
|
+
"",
|
|
690
|
+
) || "0",
|
|
691
|
+
)
|
|
692
|
+
const swapFeesUsd = Math.max(
|
|
693
|
+
0,
|
|
694
|
+
originUsd - destUsd - totalFeesUsd,
|
|
695
|
+
)
|
|
696
|
+
const totalProviderUsd =
|
|
697
|
+
providerUsd + trailsUsd + swapFeesUsd
|
|
698
|
+
|
|
699
|
+
// Sum of all gas costs and all provider costs
|
|
700
|
+
const grandTotalUsd = totalGasUsd + totalProviderUsd
|
|
701
|
+
|
|
702
|
+
if (grandTotalUsd <= 0) return null
|
|
703
|
+
|
|
704
|
+
return (
|
|
705
|
+
<div className="flex justify-between items-center">
|
|
706
|
+
<span className="text-xs font-semibold text-gray-700 dark:text-gray-300 flex items-center gap-1">
|
|
707
|
+
Total fees:
|
|
708
|
+
<Tooltip message="The total fees for this transaction, including gas costs and all provider fees">
|
|
709
|
+
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
710
|
+
</Tooltip>
|
|
711
|
+
</span>
|
|
712
|
+
<span className="font-semibold text-xs text-gray-900 dark:text-white">
|
|
713
|
+
≈ {formatUsdAmountDisplay(grandTotalUsd)}
|
|
714
|
+
</span>
|
|
715
|
+
</div>
|
|
716
|
+
)
|
|
717
|
+
})()}
|
|
718
|
+
|
|
719
|
+
{/* Spacer */}
|
|
720
|
+
<div className="h-2" />
|
|
721
|
+
</>
|
|
722
|
+
)
|
|
723
|
+
})()}
|
|
724
|
+
|
|
725
|
+
{/* Transaction Details Section */}
|
|
726
|
+
{(() => {
|
|
727
|
+
const hasSlippage =
|
|
728
|
+
quote?.slippageTolerance != null &&
|
|
729
|
+
Number(quote.slippageTolerance) !== 0
|
|
730
|
+
const hasPriceImpact =
|
|
731
|
+
quote?.priceImpact != null && Number(quote.priceImpact) !== 0
|
|
732
|
+
const showSection = hasSlippage || hasPriceImpact
|
|
733
|
+
|
|
734
|
+
if (!showSection) return null
|
|
735
|
+
|
|
736
|
+
return (
|
|
737
|
+
<>
|
|
738
|
+
<div className="text-xs font-semibold text-gray-700 dark:text-gray-300 mb-2 text-center">
|
|
739
|
+
Transaction details
|
|
740
|
+
</div>
|
|
741
|
+
|
|
742
|
+
{/* Max Slippage */}
|
|
743
|
+
{hasSlippage && (
|
|
744
|
+
<div className="flex justify-between items-center">
|
|
745
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
746
|
+
Max slippage:
|
|
747
|
+
<Tooltip message="The maximum percentage by which the exchange rate can change before the transaction fails. Higher slippage means more tolerance for price changes but potentially worse rates.">
|
|
748
|
+
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
749
|
+
</Tooltip>
|
|
750
|
+
</span>
|
|
751
|
+
<span className="font-medium text-xs text-gray-900 dark:text-white">
|
|
752
|
+
{quote.slippageTolerance}%
|
|
753
|
+
</span>
|
|
754
|
+
</div>
|
|
755
|
+
)}
|
|
756
|
+
|
|
757
|
+
{/* Price Impact */}
|
|
758
|
+
{hasPriceImpact && (
|
|
759
|
+
<div className="space-y-1">
|
|
760
|
+
<div className="flex justify-between items-center">
|
|
761
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
762
|
+
Price impact:
|
|
763
|
+
<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.">
|
|
764
|
+
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
765
|
+
</Tooltip>
|
|
766
|
+
</span>
|
|
767
|
+
<span
|
|
768
|
+
className={`font-medium text-xs flex items-center gap-1 ${
|
|
769
|
+
Math.abs(Number(quote.priceImpact)) > 5
|
|
770
|
+
? "text-red-600 dark:text-red-400"
|
|
771
|
+
: Math.abs(Number(quote.priceImpact)) > 0.5
|
|
772
|
+
? "text-orange-600 dark:text-orange-400"
|
|
773
|
+
: "text-gray-900 dark:text-white"
|
|
774
|
+
}`}
|
|
395
775
|
>
|
|
396
|
-
|
|
397
|
-
<
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
776
|
+
{Math.abs(Number(quote.priceImpact)) > 0.5 && (
|
|
777
|
+
<span title="High price impact">
|
|
778
|
+
<svg
|
|
779
|
+
className="w-3 h-3"
|
|
780
|
+
fill="none"
|
|
781
|
+
stroke="currentColor"
|
|
782
|
+
viewBox="0 0 24 24"
|
|
783
|
+
aria-hidden="true"
|
|
784
|
+
>
|
|
785
|
+
<path
|
|
786
|
+
strokeLinecap="round"
|
|
787
|
+
strokeLinejoin="round"
|
|
788
|
+
strokeWidth={2}
|
|
789
|
+
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"
|
|
790
|
+
/>
|
|
791
|
+
</svg>
|
|
792
|
+
</span>
|
|
793
|
+
)}
|
|
794
|
+
{quote.priceImpact}%
|
|
795
|
+
</span>
|
|
796
|
+
</div>
|
|
797
|
+
{quote.priceImpactUsdDisplay && (
|
|
798
|
+
<div className="text-right">
|
|
799
|
+
<span className="text-xs text-gray-500 dark:text-gray-400">
|
|
800
|
+
≈ {quote.priceImpactUsdDisplay}
|
|
801
|
+
</span>
|
|
802
|
+
</div>
|
|
803
|
+
)}
|
|
804
|
+
</div>
|
|
805
|
+
)}
|
|
806
|
+
</>
|
|
807
|
+
)
|
|
808
|
+
})()}
|
|
809
|
+
|
|
810
|
+
{/* More Info Section */}
|
|
811
|
+
<div className="space-y-2">
|
|
812
|
+
<button
|
|
813
|
+
type="button"
|
|
814
|
+
onClick={() => {
|
|
815
|
+
setShowMoreInfo(!showMoreInfo)
|
|
816
|
+
if (!showMoreInfo) {
|
|
817
|
+
setTimeout(() => {
|
|
818
|
+
if (moreInfoRef.current) {
|
|
819
|
+
moreInfoRef.current.scrollIntoView({
|
|
820
|
+
behavior: "smooth",
|
|
821
|
+
block: "nearest",
|
|
822
|
+
})
|
|
823
|
+
}
|
|
824
|
+
}, 150)
|
|
825
|
+
}
|
|
826
|
+
}}
|
|
827
|
+
className="flex items-center gap-1 text-xs hover:underline cursor-pointer transition-colors duration-200 text-gray-600 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300"
|
|
828
|
+
aria-label={showMoreInfo ? "Hide more info" : "Show more info"}
|
|
829
|
+
>
|
|
830
|
+
<span>More</span>
|
|
831
|
+
<svg
|
|
832
|
+
className={`w-3 h-3 transition-transform duration-300 ease-out ${
|
|
833
|
+
showMoreInfo ? "rotate-180" : ""
|
|
834
|
+
}`}
|
|
835
|
+
fill="none"
|
|
836
|
+
stroke="currentColor"
|
|
837
|
+
viewBox="0 0 24 24"
|
|
838
|
+
aria-hidden="true"
|
|
839
|
+
>
|
|
840
|
+
<path
|
|
841
|
+
strokeLinecap="round"
|
|
842
|
+
strokeLinejoin="round"
|
|
843
|
+
strokeWidth={2}
|
|
844
|
+
d="M19 9l-7 7-7-7"
|
|
845
|
+
/>
|
|
846
|
+
</svg>
|
|
847
|
+
</button>
|
|
848
|
+
|
|
849
|
+
<div
|
|
850
|
+
ref={moreInfoRef}
|
|
851
|
+
className={`overflow-hidden transition-all duration-300 ease-out ${
|
|
852
|
+
showMoreInfo
|
|
853
|
+
? "max-h-[500px] opacity-100"
|
|
854
|
+
: "max-h-0 opacity-0"
|
|
855
|
+
}`}
|
|
856
|
+
>
|
|
857
|
+
<div className="space-y-3 pt-2">
|
|
858
|
+
{/* Exchange Rate */}
|
|
859
|
+
{quote?.originTokenRate && quote?.destinationTokenRate && (
|
|
860
|
+
<div className="flex justify-between items-center">
|
|
861
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
862
|
+
Exchange Rate:
|
|
863
|
+
<Tooltip message="The current exchange rate between the origin and destination tokens">
|
|
864
|
+
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
865
|
+
</Tooltip>
|
|
866
|
+
</span>
|
|
867
|
+
<button
|
|
868
|
+
type="button"
|
|
869
|
+
onClick={() => setShowOriginRate(!showOriginRate)}
|
|
870
|
+
className="font-medium text-xs hover:underline cursor-pointer text-gray-900 hover:text-gray-700 dark:text-white dark:hover:text-gray-300"
|
|
871
|
+
>
|
|
872
|
+
{showOriginRate
|
|
873
|
+
? quote.originTokenRate
|
|
874
|
+
: quote.destinationTokenRate}
|
|
875
|
+
</button>
|
|
876
|
+
</div>
|
|
877
|
+
)}
|
|
878
|
+
|
|
879
|
+
{/* Origin Transfer Amount */}
|
|
880
|
+
{quote?.originAmount &&
|
|
881
|
+
quote?.originToken.symbol &&
|
|
882
|
+
quote?.originChain.id && (
|
|
883
|
+
<div className="flex justify-between items-start">
|
|
884
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
885
|
+
Origin Transfer Amount:
|
|
886
|
+
<Tooltip message="The amount of tokens you will send from the origin chain">
|
|
887
|
+
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
888
|
+
</Tooltip>
|
|
889
|
+
</span>
|
|
890
|
+
<div className="text-right">
|
|
891
|
+
{quote.originToken.contractAddress ===
|
|
892
|
+
"0x0000000000000000000000000000000000000000" ? (
|
|
893
|
+
<>
|
|
894
|
+
<div className="font-medium text-xs text-gray-900 dark:text-white flex items-center gap-1 justify-end">
|
|
895
|
+
<TokenImage
|
|
896
|
+
imageUrl={quote.originToken.imageUrl}
|
|
897
|
+
symbol={quote.originToken.symbol}
|
|
898
|
+
chainId={quote.originChain.id}
|
|
899
|
+
contractAddress={
|
|
900
|
+
quote.originToken.contractAddress
|
|
901
|
+
}
|
|
902
|
+
size={16}
|
|
903
|
+
/>
|
|
904
|
+
{quote.originAmountDisplay}{" "}
|
|
905
|
+
{quote.originToken.symbol}
|
|
906
|
+
</div>
|
|
907
|
+
{quote.originAmountUsdDisplay && (
|
|
908
|
+
<div className="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
|
|
909
|
+
≈ {quote.originAmountUsdDisplay}
|
|
910
|
+
</div>
|
|
911
|
+
)}
|
|
912
|
+
</>
|
|
913
|
+
) : (
|
|
914
|
+
<>
|
|
915
|
+
<a
|
|
916
|
+
href={getExplorerUrlForAddress({
|
|
917
|
+
address: quote.originToken.contractAddress,
|
|
918
|
+
chainId: quote.originChain.id,
|
|
919
|
+
})}
|
|
920
|
+
target="_blank"
|
|
921
|
+
rel="noopener noreferrer"
|
|
922
|
+
className="hover:underline cursor-pointer"
|
|
923
|
+
>
|
|
924
|
+
<div className="font-medium text-xs text-gray-900 dark:text-white flex items-center gap-1 justify-end">
|
|
925
|
+
<TokenImage
|
|
926
|
+
imageUrl={quote.originToken.imageUrl}
|
|
927
|
+
symbol={quote.originToken.symbol}
|
|
928
|
+
chainId={quote.originChain.id}
|
|
929
|
+
contractAddress={
|
|
930
|
+
quote.originToken.contractAddress
|
|
931
|
+
}
|
|
932
|
+
size={16}
|
|
933
|
+
/>
|
|
934
|
+
{quote.originAmountDisplay}{" "}
|
|
935
|
+
{quote.originToken.symbol}
|
|
936
|
+
</div>
|
|
937
|
+
</a>
|
|
938
|
+
{quote.originAmountUsdDisplay && (
|
|
939
|
+
<div className="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
|
|
940
|
+
≈ {quote.originAmountUsdDisplay}
|
|
941
|
+
</div>
|
|
942
|
+
)}
|
|
943
|
+
</>
|
|
944
|
+
)}
|
|
945
|
+
</div>
|
|
946
|
+
</div>
|
|
416
947
|
)}
|
|
417
|
-
</div>
|
|
418
|
-
</div>
|
|
419
|
-
)}
|
|
420
948
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
949
|
+
{/* Destination Target Amount */}
|
|
950
|
+
{quote?.destinationToken.symbol &&
|
|
951
|
+
quote?.destinationAmount &&
|
|
952
|
+
quote?.destinationAmountUsdDisplay &&
|
|
953
|
+
quote?.destinationChain.id && (
|
|
954
|
+
<div className="flex justify-between items-start">
|
|
955
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
956
|
+
Destination Target Amount:
|
|
957
|
+
<Tooltip message="The amount of tokens you will receive on the destination chain after the swap and/or bridge">
|
|
958
|
+
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
959
|
+
</Tooltip>
|
|
960
|
+
</span>
|
|
961
|
+
<div className="text-right">
|
|
962
|
+
{quote.destinationToken.contractAddress ===
|
|
963
|
+
"0x0000000000000000000000000000000000000000" ? (
|
|
964
|
+
<>
|
|
965
|
+
<div className="font-medium text-xs text-gray-900 dark:text-white flex items-center gap-1 justify-end">
|
|
966
|
+
<TokenImage
|
|
967
|
+
imageUrl={quote.destinationToken.imageUrl}
|
|
968
|
+
symbol={quote.destinationToken.symbol}
|
|
969
|
+
chainId={quote.destinationChain.id}
|
|
970
|
+
contractAddress={
|
|
971
|
+
quote.destinationToken.contractAddress
|
|
972
|
+
}
|
|
973
|
+
size={16}
|
|
974
|
+
/>
|
|
975
|
+
{quote.destinationAmountDisplay}{" "}
|
|
976
|
+
{quote.destinationToken.symbol}
|
|
977
|
+
</div>
|
|
978
|
+
{quote.destinationAmountUsdDisplay && (
|
|
979
|
+
<div className="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
|
|
980
|
+
≈ {quote.destinationAmountUsdDisplay}
|
|
981
|
+
</div>
|
|
982
|
+
)}
|
|
983
|
+
</>
|
|
984
|
+
) : (
|
|
985
|
+
<>
|
|
986
|
+
<a
|
|
987
|
+
href={getExplorerUrlForAddress({
|
|
988
|
+
address:
|
|
989
|
+
quote.destinationToken.contractAddress,
|
|
990
|
+
chainId: quote.destinationChain.id,
|
|
991
|
+
})}
|
|
992
|
+
target="_blank"
|
|
993
|
+
rel="noopener noreferrer"
|
|
994
|
+
className="hover:underline cursor-pointer"
|
|
995
|
+
>
|
|
996
|
+
<div className="font-medium text-xs text-gray-900 dark:text-white flex items-center gap-1 justify-end">
|
|
997
|
+
<TokenImage
|
|
998
|
+
imageUrl={quote.destinationToken.imageUrl}
|
|
999
|
+
symbol={quote.destinationToken.symbol}
|
|
1000
|
+
chainId={quote.destinationChain.id}
|
|
1001
|
+
contractAddress={
|
|
1002
|
+
quote.destinationToken.contractAddress
|
|
1003
|
+
}
|
|
1004
|
+
size={16}
|
|
1005
|
+
/>
|
|
1006
|
+
{quote.destinationAmountDisplay}{" "}
|
|
1007
|
+
{quote.destinationToken.symbol}
|
|
1008
|
+
</div>
|
|
1009
|
+
</a>
|
|
1010
|
+
{quote.destinationAmountUsdDisplay && (
|
|
1011
|
+
<div className="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
|
|
1012
|
+
≈ {quote.destinationAmountUsdDisplay}
|
|
1013
|
+
</div>
|
|
1014
|
+
)}
|
|
1015
|
+
</>
|
|
1016
|
+
)}
|
|
448
1017
|
</div>
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
1018
|
+
</div>
|
|
1019
|
+
)}
|
|
1020
|
+
|
|
1021
|
+
{/* Origin Deposit Address */}
|
|
1022
|
+
{quote?.originDepositAddress && (
|
|
1023
|
+
<div className="flex justify-between items-center">
|
|
1024
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
1025
|
+
Origin Deposit Address:
|
|
1026
|
+
<Tooltip message="This is the intent address to deposit to that will then execute the swap and/or bridge">
|
|
1027
|
+
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
1028
|
+
</Tooltip>
|
|
1029
|
+
</span>
|
|
1030
|
+
<a
|
|
1031
|
+
href={getExplorerUrlForAddress({
|
|
1032
|
+
address: quote.originDepositAddress,
|
|
1033
|
+
chainId: quote.originChain.id,
|
|
1034
|
+
})}
|
|
1035
|
+
target="_blank"
|
|
1036
|
+
rel="noopener noreferrer"
|
|
1037
|
+
className="font-mono text-xs hover:underline flex items-center gap-1 text-gray-700 dark:text-gray-300"
|
|
1038
|
+
>
|
|
1039
|
+
{truncateAddress(quote.originDepositAddress)}
|
|
1040
|
+
<svg
|
|
1041
|
+
className="w-3 h-3"
|
|
1042
|
+
fill="none"
|
|
1043
|
+
stroke="currentColor"
|
|
1044
|
+
viewBox="0 0 24 24"
|
|
1045
|
+
aria-hidden="true"
|
|
1046
|
+
>
|
|
1047
|
+
<path
|
|
1048
|
+
strokeLinecap="round"
|
|
1049
|
+
strokeLinejoin="round"
|
|
1050
|
+
strokeWidth={2}
|
|
1051
|
+
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
1052
|
+
/>
|
|
1053
|
+
</svg>
|
|
1054
|
+
</a>
|
|
1055
|
+
</div>
|
|
1056
|
+
)}
|
|
1057
|
+
|
|
1058
|
+
{/* Destination Deposit Address */}
|
|
1059
|
+
{quote?.destinationDepositAddress &&
|
|
1060
|
+
quote?.destinationDepositAddress !==
|
|
1061
|
+
quote?.originDepositAddress && (
|
|
1062
|
+
<div className="flex justify-between items-center">
|
|
1063
|
+
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
1064
|
+
Destination Deposit Address:
|
|
1065
|
+
<Tooltip message="This is the address that will receive the tokens after any swap and/or bridge from the origin chain">
|
|
1066
|
+
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
1067
|
+
</Tooltip>
|
|
1068
|
+
</span>
|
|
457
1069
|
<a
|
|
458
1070
|
href={getExplorerUrlForAddress({
|
|
459
|
-
address: quote.
|
|
1071
|
+
address: quote.destinationDepositAddress,
|
|
460
1072
|
chainId: quote.destinationChain.id,
|
|
461
1073
|
})}
|
|
462
1074
|
target="_blank"
|
|
463
1075
|
rel="noopener noreferrer"
|
|
464
|
-
className="hover:underline
|
|
1076
|
+
className="font-mono text-xs hover:underline flex items-center gap-1 text-gray-700 dark:text-gray-300"
|
|
465
1077
|
>
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
1078
|
+
{truncateAddress(quote.destinationDepositAddress)}
|
|
1079
|
+
<svg
|
|
1080
|
+
className="w-3 h-3"
|
|
1081
|
+
fill="none"
|
|
1082
|
+
stroke="currentColor"
|
|
1083
|
+
viewBox="0 0 24 24"
|
|
1084
|
+
aria-hidden="true"
|
|
1085
|
+
>
|
|
1086
|
+
<path
|
|
1087
|
+
strokeLinecap="round"
|
|
1088
|
+
strokeLinejoin="round"
|
|
1089
|
+
strokeWidth={2}
|
|
1090
|
+
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
475
1091
|
/>
|
|
476
|
-
|
|
477
|
-
{quote.destinationToken.symbol}
|
|
478
|
-
</div>
|
|
1092
|
+
</svg>
|
|
479
1093
|
</a>
|
|
480
|
-
|
|
481
|
-
<div className="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
|
|
482
|
-
≈ {quote.destinationAmountUsdDisplay}
|
|
483
|
-
</div>
|
|
484
|
-
)}
|
|
485
|
-
</>
|
|
1094
|
+
</div>
|
|
486
1095
|
)}
|
|
487
|
-
</div>
|
|
488
|
-
</div>
|
|
489
|
-
)}
|
|
490
|
-
|
|
491
|
-
{quote?.originDepositAddress && (
|
|
492
|
-
<div className="flex justify-between items-center">
|
|
493
|
-
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
494
|
-
Origin Deposit Address:
|
|
495
|
-
<Tooltip message="This is the intent address to deposit to that will then execute the swap and/or bridge">
|
|
496
|
-
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
497
|
-
</Tooltip>
|
|
498
|
-
</span>
|
|
499
|
-
<a
|
|
500
|
-
href={getExplorerUrlForAddress({
|
|
501
|
-
address: quote.originDepositAddress,
|
|
502
|
-
chainId: quote.originChain.id,
|
|
503
|
-
})}
|
|
504
|
-
target="_blank"
|
|
505
|
-
rel="noopener noreferrer"
|
|
506
|
-
className="font-mono text-xs hover:underline flex items-center gap-1 text-gray-700 dark:text-gray-300"
|
|
507
|
-
>
|
|
508
|
-
{truncateAddress(quote.originDepositAddress)}
|
|
509
|
-
<svg
|
|
510
|
-
className="w-3 h-3"
|
|
511
|
-
fill="none"
|
|
512
|
-
stroke="currentColor"
|
|
513
|
-
viewBox="0 0 24 24"
|
|
514
|
-
aria-hidden="true"
|
|
515
|
-
>
|
|
516
|
-
<path
|
|
517
|
-
strokeLinecap="round"
|
|
518
|
-
strokeLinejoin="round"
|
|
519
|
-
strokeWidth={2}
|
|
520
|
-
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
521
|
-
/>
|
|
522
|
-
</svg>
|
|
523
|
-
</a>
|
|
524
|
-
</div>
|
|
525
|
-
)}
|
|
526
|
-
|
|
527
|
-
{quote?.destinationDepositAddress &&
|
|
528
|
-
quote?.destinationDepositAddress !==
|
|
529
|
-
quote?.originDepositAddress && (
|
|
530
|
-
<div className="flex justify-between items-center">
|
|
531
|
-
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
532
|
-
Destination Deposit Address:
|
|
533
|
-
<Tooltip message="This is the address that will receive the tokens after any swap and/or bridge from the origin chain">
|
|
534
|
-
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
535
|
-
</Tooltip>
|
|
536
|
-
</span>
|
|
537
|
-
<a
|
|
538
|
-
href={getExplorerUrlForAddress({
|
|
539
|
-
address: quote.destinationDepositAddress,
|
|
540
|
-
chainId: quote.destinationChain.id,
|
|
541
|
-
})}
|
|
542
|
-
target="_blank"
|
|
543
|
-
rel="noopener noreferrer"
|
|
544
|
-
className="font-mono text-xs hover:underline flex items-center gap-1 text-gray-700 dark:text-gray-300"
|
|
545
|
-
>
|
|
546
|
-
{truncateAddress(quote.destinationDepositAddress)}
|
|
547
|
-
<svg
|
|
548
|
-
className="w-3 h-3"
|
|
549
|
-
fill="none"
|
|
550
|
-
stroke="currentColor"
|
|
551
|
-
viewBox="0 0 24 24"
|
|
552
|
-
aria-hidden="true"
|
|
553
|
-
>
|
|
554
|
-
<path
|
|
555
|
-
strokeLinecap="round"
|
|
556
|
-
strokeLinejoin="round"
|
|
557
|
-
strokeWidth={2}
|
|
558
|
-
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
559
|
-
/>
|
|
560
|
-
</svg>
|
|
561
|
-
</a>
|
|
562
|
-
</div>
|
|
563
|
-
)}
|
|
564
|
-
|
|
565
|
-
{quote?.destinationAddress && (
|
|
566
|
-
<div className="flex justify-between items-center">
|
|
567
|
-
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
568
|
-
Destination Target Address:
|
|
569
|
-
<Tooltip message="This is the final execution address or recipient address">
|
|
570
|
-
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
571
|
-
</Tooltip>
|
|
572
|
-
</span>
|
|
573
|
-
<a
|
|
574
|
-
href={getExplorerUrlForAddress({
|
|
575
|
-
address: quote.destinationAddress,
|
|
576
|
-
chainId: quote.destinationChain.id,
|
|
577
|
-
})}
|
|
578
|
-
target="_blank"
|
|
579
|
-
rel="noopener noreferrer"
|
|
580
|
-
className="font-mono text-xs hover:underline flex items-center gap-1 text-gray-700 dark:text-gray-300"
|
|
581
|
-
>
|
|
582
|
-
{truncateAddress(quote.destinationAddress)}
|
|
583
|
-
<svg
|
|
584
|
-
className="w-3 h-3"
|
|
585
|
-
fill="none"
|
|
586
|
-
stroke="currentColor"
|
|
587
|
-
viewBox="0 0 24 24"
|
|
588
|
-
aria-hidden="true"
|
|
589
|
-
>
|
|
590
|
-
<path
|
|
591
|
-
strokeLinecap="round"
|
|
592
|
-
strokeLinejoin="round"
|
|
593
|
-
strokeWidth={2}
|
|
594
|
-
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
595
|
-
/>
|
|
596
|
-
</svg>
|
|
597
|
-
</a>
|
|
598
|
-
</div>
|
|
599
|
-
)}
|
|
600
1096
|
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
604
|
-
Max Slippage:
|
|
605
|
-
<Tooltip message="The maximum percentage by which the exchange rate can change before the transaction fails. Higher slippage means more tolerance for price changes but potentially worse rates.">
|
|
606
|
-
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
607
|
-
</Tooltip>
|
|
608
|
-
</span>
|
|
609
|
-
<span className="font-medium text-xs text-gray-900 dark:text-white">
|
|
610
|
-
{quote.slippageTolerance}%
|
|
611
|
-
</span>
|
|
612
|
-
</div>
|
|
613
|
-
)}
|
|
614
|
-
|
|
615
|
-
{quote?.priceImpact != null &&
|
|
616
|
-
(() => {
|
|
617
|
-
const priceImpactNum = Math.abs(Number(quote.priceImpact))
|
|
618
|
-
return (
|
|
619
|
-
<div className="space-y-1">
|
|
1097
|
+
{/* Destination Target Address */}
|
|
1098
|
+
{quote?.destinationAddress && (
|
|
620
1099
|
<div className="flex justify-between items-center">
|
|
621
1100
|
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
622
|
-
|
|
623
|
-
<Tooltip message="
|
|
1101
|
+
Destination Target Address:
|
|
1102
|
+
<Tooltip message="This is the final execution address or recipient address">
|
|
624
1103
|
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
625
1104
|
</Tooltip>
|
|
626
1105
|
</span>
|
|
627
|
-
<
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
1106
|
+
<a
|
|
1107
|
+
href={getExplorerUrlForAddress({
|
|
1108
|
+
address: quote.destinationAddress,
|
|
1109
|
+
chainId: quote.destinationChain.id,
|
|
1110
|
+
})}
|
|
1111
|
+
target="_blank"
|
|
1112
|
+
rel="noopener noreferrer"
|
|
1113
|
+
className="font-mono text-xs hover:underline flex items-center gap-1 text-gray-700 dark:text-gray-300"
|
|
635
1114
|
>
|
|
636
|
-
{
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
</span>
|
|
653
|
-
)}
|
|
654
|
-
{quote.priceImpact}%
|
|
655
|
-
</span>
|
|
1115
|
+
{truncateAddress(quote.destinationAddress)}
|
|
1116
|
+
<svg
|
|
1117
|
+
className="w-3 h-3"
|
|
1118
|
+
fill="none"
|
|
1119
|
+
stroke="currentColor"
|
|
1120
|
+
viewBox="0 0 24 24"
|
|
1121
|
+
aria-hidden="true"
|
|
1122
|
+
>
|
|
1123
|
+
<path
|
|
1124
|
+
strokeLinecap="round"
|
|
1125
|
+
strokeLinejoin="round"
|
|
1126
|
+
strokeWidth={2}
|
|
1127
|
+
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
1128
|
+
/>
|
|
1129
|
+
</svg>
|
|
1130
|
+
</a>
|
|
656
1131
|
</div>
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
1132
|
+
)}
|
|
1133
|
+
|
|
1134
|
+
{/* Custom Calldata */}
|
|
1135
|
+
{quote?.destinationCalldata && (
|
|
1136
|
+
<div className="space-y-2">
|
|
1137
|
+
<button
|
|
1138
|
+
type="button"
|
|
1139
|
+
onClick={() => {
|
|
1140
|
+
setShowCalldata(!showCalldata)
|
|
1141
|
+
// Auto-scroll to calldata when expanding
|
|
1142
|
+
if (!showCalldata) {
|
|
1143
|
+
setTimeout(() => {
|
|
1144
|
+
if (calldataRef.current) {
|
|
1145
|
+
calldataRef.current.scrollIntoView({
|
|
1146
|
+
behavior: "smooth",
|
|
1147
|
+
block: "nearest",
|
|
1148
|
+
})
|
|
1149
|
+
}
|
|
1150
|
+
}, 150) // Delay to let the expansion animation start
|
|
1151
|
+
}
|
|
1152
|
+
}}
|
|
1153
|
+
className="flex items-center gap-1 text-xs hover:underline cursor-pointer transition-colors duration-200 text-gray-600 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300"
|
|
1154
|
+
aria-label={
|
|
1155
|
+
showCalldata
|
|
1156
|
+
? "Hide custom calldata"
|
|
1157
|
+
: "Show custom calldata"
|
|
1158
|
+
}
|
|
1159
|
+
>
|
|
1160
|
+
<span className="text-[10px]">
|
|
1161
|
+
Includes custom destination calldata
|
|
661
1162
|
</span>
|
|
1163
|
+
<svg
|
|
1164
|
+
className={`w-3 h-3 transition-transform duration-300 ease-out ${
|
|
1165
|
+
showCalldata ? "rotate-180" : ""
|
|
1166
|
+
}`}
|
|
1167
|
+
fill="none"
|
|
1168
|
+
stroke="currentColor"
|
|
1169
|
+
viewBox="0 0 24 24"
|
|
1170
|
+
aria-hidden="true"
|
|
1171
|
+
>
|
|
1172
|
+
<path
|
|
1173
|
+
strokeLinecap="round"
|
|
1174
|
+
strokeLinejoin="round"
|
|
1175
|
+
strokeWidth={2}
|
|
1176
|
+
d="M19 9l-7 7-7-7"
|
|
1177
|
+
/>
|
|
1178
|
+
</svg>
|
|
1179
|
+
</button>
|
|
1180
|
+
<div
|
|
1181
|
+
ref={calldataRef}
|
|
1182
|
+
className={`overflow-hidden transition-all duration-300 ease-out ${
|
|
1183
|
+
showCalldata
|
|
1184
|
+
? "max-h-32 opacity-100"
|
|
1185
|
+
: "max-h-0 opacity-0"
|
|
1186
|
+
}`}
|
|
1187
|
+
>
|
|
1188
|
+
<div className="mt-2">
|
|
1189
|
+
<textarea
|
|
1190
|
+
value={quote.destinationCalldata}
|
|
1191
|
+
readOnly
|
|
1192
|
+
className={`w-full p-2 text-xs font-mono rounded border border-solid resize-none transition-all duration-200 bg-gray-100 dark:bg-gray-700 border-gray-300 dark:border-gray-600 text-gray-800 dark:text-gray-200`}
|
|
1193
|
+
rows={4}
|
|
1194
|
+
placeholder="No custom calldata"
|
|
1195
|
+
/>
|
|
1196
|
+
</div>
|
|
662
1197
|
</div>
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
)
|
|
666
|
-
})()}
|
|
667
|
-
|
|
668
|
-
{quote?.fees?.totalFeeAmountUsd != null && (
|
|
669
|
-
<div className="flex justify-between items-center">
|
|
670
|
-
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
671
|
-
Total Fees:
|
|
672
|
-
<Tooltip message="The total fees charged for this transaction, including gas fees, bridge fees, and any platform fees. These fees are deducted from your transaction.">
|
|
673
|
-
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
674
|
-
</Tooltip>
|
|
675
|
-
</span>
|
|
676
|
-
<span className="font-medium text-xs text-gray-900 dark:text-white">
|
|
677
|
-
{quote.fees.totalFeeAmountUsdDisplay}
|
|
678
|
-
</span>
|
|
679
|
-
</div>
|
|
680
|
-
)}
|
|
681
|
-
|
|
682
|
-
{quote?.quoteProvider?.name && (
|
|
683
|
-
<div className="flex justify-between items-center">
|
|
684
|
-
<span className="text-xs text-gray-600 dark:text-gray-400 flex items-center gap-1">
|
|
685
|
-
{quote.originChain.id === quote.destinationChain.id
|
|
686
|
-
? "Swap Provider"
|
|
687
|
-
: "Bridge"}
|
|
688
|
-
:
|
|
689
|
-
<Tooltip message="The service that fullfils the swap and/or bridge">
|
|
690
|
-
<InfoIcon className="w-3 h-3 text-gray-500 dark:text-gray-400 cursor-pointer" />
|
|
691
|
-
</Tooltip>
|
|
692
|
-
</span>
|
|
693
|
-
<a
|
|
694
|
-
href={quote.quoteProvider?.url}
|
|
695
|
-
target="_blank"
|
|
696
|
-
rel="noopener noreferrer"
|
|
697
|
-
className="font-medium text-xs text-gray-900 dark:text-white hover:underline flex items-center gap-1"
|
|
698
|
-
>
|
|
699
|
-
{quote.quoteProvider?.name}
|
|
700
|
-
<svg
|
|
701
|
-
className="w-3 h-3"
|
|
702
|
-
fill="none"
|
|
703
|
-
stroke="currentColor"
|
|
704
|
-
viewBox="0 0 24 24"
|
|
705
|
-
aria-hidden="true"
|
|
706
|
-
>
|
|
707
|
-
<path
|
|
708
|
-
strokeLinecap="round"
|
|
709
|
-
strokeLinejoin="round"
|
|
710
|
-
strokeWidth={2}
|
|
711
|
-
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
712
|
-
/>
|
|
713
|
-
</svg>
|
|
714
|
-
</a>
|
|
715
|
-
</div>
|
|
716
|
-
)}
|
|
1198
|
+
</div>
|
|
1199
|
+
)}
|
|
717
1200
|
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
<button
|
|
721
|
-
type="button"
|
|
722
|
-
onClick={() => {
|
|
723
|
-
setShowCalldata(!showCalldata)
|
|
724
|
-
// Auto-scroll to calldata when expanding
|
|
725
|
-
if (!showCalldata) {
|
|
726
|
-
setTimeout(() => {
|
|
727
|
-
if (calldataRef.current) {
|
|
728
|
-
calldataRef.current.scrollIntoView({
|
|
729
|
-
behavior: "smooth",
|
|
730
|
-
block: "nearest",
|
|
731
|
-
})
|
|
732
|
-
}
|
|
733
|
-
}, 150) // Delay to let the expansion animation start
|
|
734
|
-
}
|
|
735
|
-
}}
|
|
736
|
-
className="flex items-center gap-1 text-xs hover:underline cursor-pointer transition-colors duration-200 text-gray-600 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300"
|
|
737
|
-
aria-label={
|
|
738
|
-
showCalldata
|
|
739
|
-
? "Hide custom calldata"
|
|
740
|
-
: "Show custom calldata"
|
|
741
|
-
}
|
|
742
|
-
>
|
|
743
|
-
<span className="text-[10px]">
|
|
744
|
-
Includes custom destination calldata
|
|
745
|
-
</span>
|
|
746
|
-
<svg
|
|
747
|
-
className={`w-3 h-3 transition-transform duration-300 ease-out ${
|
|
748
|
-
showCalldata ? "rotate-180" : ""
|
|
749
|
-
}`}
|
|
750
|
-
fill="none"
|
|
751
|
-
stroke="currentColor"
|
|
752
|
-
viewBox="0 0 24 24"
|
|
753
|
-
aria-hidden="true"
|
|
754
|
-
>
|
|
755
|
-
<path
|
|
756
|
-
strokeLinecap="round"
|
|
757
|
-
strokeLinejoin="round"
|
|
758
|
-
strokeWidth={2}
|
|
759
|
-
d="M19 9l-7 7-7-7"
|
|
760
|
-
/>
|
|
761
|
-
</svg>
|
|
762
|
-
</button>
|
|
763
|
-
<div
|
|
764
|
-
ref={calldataRef}
|
|
765
|
-
className={`overflow-hidden transition-all duration-300 ease-out ${
|
|
766
|
-
showCalldata ? "max-h-32 opacity-100" : "max-h-0 opacity-0"
|
|
767
|
-
}`}
|
|
768
|
-
>
|
|
769
|
-
<div className="mt-2">
|
|
770
|
-
<textarea
|
|
771
|
-
value={quote.destinationCalldata}
|
|
772
|
-
readOnly
|
|
773
|
-
className={`w-full p-2 text-xs font-mono rounded border border-solid resize-none transition-all duration-200 bg-gray-100 dark:bg-gray-700 border-gray-300 dark:border-gray-600 text-gray-800 dark:text-gray-200`}
|
|
774
|
-
rows={4}
|
|
775
|
-
placeholder="No custom calldata"
|
|
776
|
-
/>
|
|
777
|
-
</div>
|
|
1201
|
+
{/* Children content */}
|
|
1202
|
+
{children && <div className="mb-0">{children}</div>}
|
|
778
1203
|
</div>
|
|
779
1204
|
</div>
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
{/* Children content */}
|
|
783
|
-
{children && <div className="mb-0">{children}</div>}
|
|
1205
|
+
</div>
|
|
784
1206
|
</div>
|
|
785
1207
|
</div>
|
|
786
1208
|
</div>
|