@reservoir0x/relay-kit-ui
Version:
Relay is the Fastest and Cheapest Way to Bridge and Transact Across Chains.
165 lines • 14.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const index_js_1 = require("../primitives/index.js");
const numbers_js_1 = require("../../utils/numbers.js");
const react_fontawesome_1 = require("@fortawesome/react-fontawesome");
const faGasPump_1 = require("@fortawesome/free-solid-svg-icons/faGasPump");
const faChevronDown_1 = require("@fortawesome/free-solid-svg-icons/faChevronDown");
const FetchingQuoteLoader_js_1 = tslib_1.__importDefault(require("../widgets/FetchingQuoteLoader.js"));
const SwapRouteSelector_js_1 = tslib_1.__importDefault(require("../widgets/SwapRouteSelector.js"));
const Collapsible_js_1 = require("../primitives/Collapsible.js");
const free_solid_svg_icons_1 = require("@fortawesome/free-solid-svg-icons");
const PriceImpactTooltip_js_1 = require("./PriceImpactTooltip.js");
const slippage_js_1 = require("../../utils/slippage.js");
const Tooltip_js_1 = tslib_1.__importDefault(require("../primitives/Tooltip.js"));
const react_2 = tslib_1.__importDefault(require("react"));
const formatSwapRate = (rate) => {
return rate >= 1 ? (0, numbers_js_1.formatBN)(rate, 2, 18, false) : (0, numbers_js_1.formatBN)(rate, 4, 18, false);
};
const FeeBreakdown = ({ feeBreakdown, isFetchingQuote, quote, toToken, fromToken, toChain, supportsExternalLiquidity, useExternalLiquidity, setUseExternalLiquidity, timeEstimate, canonicalTimeEstimate, isSingleChainLocked, fromChainWalletVMSupported, isAutoSlippage, slippageInputBps, error }) => {
const [isOpen, setIsOpen] = (0, react_1.useState)(false);
const swapRate = quote?.details?.rate;
const originGasFee = feeBreakdown?.breakdown?.find((fee) => fee.id === 'origin-gas');
const originGasFeeFormatted = (0, numbers_js_1.formatDollar)(Math.abs(originGasFee?.usd.value ?? 0));
const [rateMode, setRateMode] = (0, react_1.useState)('input');
const isHighPriceImpact = Number(quote?.details?.totalImpact?.percent) < -3.5;
const isSameChain = toToken?.chainId === fromToken?.chainId;
const originSlippageTolerance = quote?.details?.slippageTolerance?.origin?.percent;
const destinationSlippageTolerance = quote?.details?.slippageTolerance?.destination?.percent;
const quoteSlippage = (isSameChain
? destinationSlippageTolerance === '0'
? originSlippageTolerance
: destinationSlippageTolerance
: destinationSlippageTolerance) ?? '0';
const slippageInputNumber = Number((Number(slippageInputBps ?? '0') / 100).toFixed(2));
const slippage = `${Math.max(Number(quoteSlippage), slippageInputNumber)}`;
const slippageRating = (0, slippage_js_1.getSlippageRating)(slippage);
const slippageRatingColor = slippage_js_1.ratingToColor[slippageRating];
const minimumAmountFormatted = quote?.details?.currencyOut?.minimumAmount
? (0, numbers_js_1.formatBN)(quote.details.currencyOut.minimumAmount, 6, toToken?.decimals, false)
: undefined;
const breakdown = [
{
title: 'Estimated time',
value: ((0, jsx_runtime_1.jsxs)(index_js_1.Flex, { align: "center", css: {
gap: '1',
color: timeEstimate && timeEstimate.time <= 30
? '{colors.green.9}'
: '{colors.amber.9}'
}, children: [(0, jsx_runtime_1.jsx)(react_fontawesome_1.FontAwesomeIcon, { icon: free_solid_svg_icons_1.faClock, width: 16 }), (0, jsx_runtime_1.jsxs)(index_js_1.Text, { style: "subtitle2", children: ["~ ", timeEstimate?.formattedTime] })] }))
},
{
title: 'Network cost',
value: ((0, jsx_runtime_1.jsxs)(index_js_1.Flex, { align: "center", css: { gap: '1' }, children: [(0, jsx_runtime_1.jsx)(react_fontawesome_1.FontAwesomeIcon, { icon: faGasPump_1.faGasPump, width: 16, style: { color: '#C1C8CD' } }), (0, jsx_runtime_1.jsx)(index_js_1.Text, { style: "subtitle2", children: originGasFeeFormatted })] }))
},
{
title: 'Price Impact',
value: ((0, jsx_runtime_1.jsx)(PriceImpactTooltip_js_1.PriceImpactTooltip, { feeBreakdown: feeBreakdown, tooltipProps: { side: 'top', align: 'end' }, children: (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsxs)(index_js_1.Flex, { align: "center", css: { gap: '1', color: 'gray8' }, children: [(0, jsx_runtime_1.jsx)(index_js_1.Text, { style: "subtitle2", css: {
color: isHighPriceImpact ? 'red11' : undefined
}, children: feeBreakdown?.totalFees?.priceImpactPercentage }), (0, jsx_runtime_1.jsx)(react_fontawesome_1.FontAwesomeIcon, { icon: free_solid_svg_icons_1.faInfoCircle, width: 14, height: 14, style: {
display: 'inline-block',
marginLeft: 4
} })] }) }) }))
},
{
title: 'Max Slippage',
value: ((0, jsx_runtime_1.jsxs)(index_js_1.Flex, { align: "center", css: { gap: '1' }, children: [isAutoSlippage ? ((0, jsx_runtime_1.jsx)(index_js_1.Text, { style: "subtitle3", css: { py: '1px', px: '4px', bg: 'gray3', borderRadius: 100 }, children: "Auto" })) : null, (0, jsx_runtime_1.jsx)(Tooltip_js_1.default, { side: "top", align: "end", content: minimumAmountFormatted ? ((0, jsx_runtime_1.jsxs)(index_js_1.Flex, { direction: "row", css: { gap: '2' }, children: [(0, jsx_runtime_1.jsx)(index_js_1.Text, { style: "subtitle2", color: "subtle", children: "Min. received" }), (0, jsx_runtime_1.jsxs)(index_js_1.Text, { style: "subtitle2", children: [minimumAmountFormatted, " ", toToken?.symbol] })] })) : null, children: (0, jsx_runtime_1.jsxs)(index_js_1.Text, { style: "subtitle2", css: { color: slippageRatingColor }, children: [slippage, "%"] }) })] }))
}
];
if (!isSingleChainLocked && fromChainWalletVMSupported) {
breakdown.unshift({
title: 'Route',
value: ((0, jsx_runtime_1.jsx)(SwapRouteSelector_js_1.default, { chain: toChain, supportsExternalLiquidity: supportsExternalLiquidity, externalLiquidtySelected: useExternalLiquidity, onExternalLiquidityChange: (selected) => {
setUseExternalLiquidity(selected);
}, canonicalTimeEstimate: canonicalTimeEstimate?.formattedTime, error: error, trigger: (0, jsx_runtime_1.jsx)(index_js_1.Button, { color: "ghost", size: "none", children: (0, jsx_runtime_1.jsxs)(index_js_1.Flex, { css: { gap: '2', alignItems: 'center' }, children: [(0, jsx_runtime_1.jsx)(index_js_1.Text, { style: "subtitle2", children: useExternalLiquidity ? 'Native' : 'Relay' }), supportsExternalLiquidity || useExternalLiquidity ? ((0, jsx_runtime_1.jsx)(index_js_1.Box, { css: { color: 'gray11', width: 14, flexShrink: 0 }, children: (0, jsx_runtime_1.jsx)(react_fontawesome_1.FontAwesomeIcon, { icon: free_solid_svg_icons_1.faChevronRight, width: 14 }) })) : null] }) }) }))
});
}
if (!feeBreakdown) {
if (isFetchingQuote) {
return ((0, jsx_runtime_1.jsx)(index_js_1.Box, { id: 'fee-breakdown-section', css: {
borderRadius: 'widget-card-border-radius',
backgroundColor: 'widget-background',
border: 'widget-card-border',
overflow: 'hidden',
mb: 'widget-card-section-gutter'
}, children: (0, jsx_runtime_1.jsx)(FetchingQuoteLoader_js_1.default, { isLoading: isFetchingQuote, containerCss: {
mt: 0,
mb: 0,
px: '4',
py: '3',
width: '100%',
justifyContent: 'center'
} }) }));
}
else {
return null;
}
}
return ((0, jsx_runtime_1.jsxs)(Collapsible_js_1.CollapsibleRoot, { open: isOpen, onOpenChange: setIsOpen, css: { mb: 'widget-card-section-gutter' }, children: [(0, jsx_runtime_1.jsx)(Collapsible_js_1.CollapsibleTrigger, { css: {
borderRadius: 'widget-card-border-radius',
borderBottomRadius: isOpen ? '0' : 'widget-card-border-radius',
backgroundColor: 'widget-background',
border: 'widget-card-border',
borderBottom: isOpen ? 'none' : 'widget-card-border',
overflow: 'hidden',
transition: 'border-radius 300ms, border-bottom 0s',
transitionDelay: isOpen ? '0s, 0s' : '0s, 300ms'
}, id: 'fee-breakdown-section', children: (0, jsx_runtime_1.jsxs)(index_js_1.Flex, { justify: "between", align: "center", css: {
flexDirection: 'row',
gap: '2',
width: '100%',
p: '3'
}, children: [(0, jsx_runtime_1.jsx)("span", { style: {
cursor: 'pointer',
flexShrink: 1,
overflow: 'hidden',
height: 21
}, onClick: (e) => {
setRateMode(rateMode === 'input' ? 'output' : 'input');
e.preventDefault();
}, children: (0, jsx_runtime_1.jsx)(ConversionRate, { fromToken: fromToken, toToken: toToken, rate: Number(swapRate), isInputMode: rateMode === 'input' }) }), (0, jsx_runtime_1.jsxs)(index_js_1.Flex, { css: {
gap: '2',
color: timeEstimate && timeEstimate.time <= 30
? '{colors.green.9}'
: '{colors.amber.9}',
flexShrink: 0
}, align: "center", children: [!isOpen && timeEstimate && timeEstimate?.time !== 0 ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_fontawesome_1.FontAwesomeIcon, { icon: free_solid_svg_icons_1.faClock, width: 16 }), (0, jsx_runtime_1.jsxs)(index_js_1.Text, { style: "subtitle2", css: { flexShrink: 0 }, children: ["~ ", timeEstimate?.formattedTime] }), (0, jsx_runtime_1.jsx)(index_js_1.Flex, { justify: "center", align: "center", css: { color: 'gray6', height: 4 }, children: "\u2022" })] })) : null, !isOpen && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_fontawesome_1.FontAwesomeIcon, { icon: faGasPump_1.faGasPump, width: 16, style: { color: '#C1C8CD' } }), (0, jsx_runtime_1.jsx)(index_js_1.Text, { style: "subtitle2", css: { flexShrink: 0 }, children: originGasFeeFormatted })] })), (0, jsx_runtime_1.jsx)(index_js_1.Box, { css: {
marginLeft: '2',
transition: 'transform 300ms',
transform: isOpen ? 'rotate(-180deg)' : 'rotate(0)',
color: 'gray9'
}, children: (0, jsx_runtime_1.jsx)(react_fontawesome_1.FontAwesomeIcon, { icon: faChevronDown_1.faChevronDown, width: 12 }) })] })] }) }), (0, jsx_runtime_1.jsx)(Collapsible_js_1.CollapsibleContent, { css: {
borderRadius: '0 0 12px 12px',
border: 'widget-card-border',
borderTop: 'none'
}, children: (0, jsx_runtime_1.jsx)(index_js_1.Flex, { direction: "column", css: {
px: '3',
pb: '3',
pt: '0',
gap: '2',
backgroundColor: 'widget-background'
}, children: breakdown.map((item) => {
const showNativeBridgeWarning = item.title === 'Estimated time' &&
useExternalLiquidity &&
timeEstimate?.time &&
timeEstimate?.time > 86400;
return ((0, jsx_runtime_1.jsxs)(react_2.default.Fragment, { children: [(0, jsx_runtime_1.jsxs)(index_js_1.Flex, { justify: "between", align: "center", css: { width: '100%', gap: '4' }, children: [(0, jsx_runtime_1.jsx)(index_js_1.Text, { style: "subtitle2", color: showNativeBridgeWarning ? 'warningSecondary' : 'subtle', css: { alignSelf: 'flex-start' }, children: item.title }), item.value] }), showNativeBridgeWarning ? ((0, jsx_runtime_1.jsx)(index_js_1.Flex, { align: "center", css: {
gap: '2',
py: '2',
px: '3',
backgroundColor: 'amber2',
borderRadius: 12
}, children: (0, jsx_runtime_1.jsxs)(index_js_1.Text, { style: "subtitle3", css: { color: 'amber12' }, children: ["Native bridge routes are expected to take", ' ', timeEstimate.formattedTime, " but could be longer due to unexpected delays"] }) })) : null] }, item.title));
}) }) })] }));
};
exports.default = FeeBreakdown;
const ConversionRate = ({ fromToken, toToken, rate, isInputMode }) => {
const displayRate = isInputMode ? rate : 1 / rate;
const fromSymbol = isInputMode ? fromToken?.symbol : toToken?.symbol;
const toSymbol = isInputMode ? toToken?.symbol : fromToken?.symbol;
return ((0, jsx_runtime_1.jsx)(Tooltip_js_1.default, { content: (0, jsx_runtime_1.jsxs)(index_js_1.Text, { style: "subtitle2", children: ["1 ", fromSymbol, " = ", formatSwapRate(displayRate), " ", toSymbol] }), asChild: true, children: (0, jsx_runtime_1.jsx)("div", { style: { width: '100%', minWidth: 0 }, children: (0, jsx_runtime_1.jsxs)(index_js_1.Text, { style: "subtitle2", ellipsify: true, children: ["1 ", fromSymbol, " = ", formatSwapRate(displayRate), " ", toSymbol] }) }) }));
};
//# sourceMappingURL=FeeBreakdown.js.map