Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scroll to beginning of the comparison table. #355

Merged
merged 4 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 70 additions & 73 deletions src/components/FeeComparison/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import Big from 'big.js';
import { useMemo } from 'preact/hooks';
import { useEffect, useRef } from 'preact/compat';
import { useEffect, useRef, useMemo } from 'preact/hooks';
import { useQuery } from '@tanstack/react-query';
import { ChevronDownIcon } from '@heroicons/react/20/solid';

Expand All @@ -10,26 +9,39 @@ import { Skeleton } from '../Skeleton';
import { QuoteProvider, quoteProviders } from './quoteProviders';
import { OfframpingParameters, useEventsContext } from '../../contexts/events';

type FeeProviderRowProps = FeeComparisonProps & { provider: QuoteProvider };
interface BaseComparisonProps {
amount: Big;
sourceAssetSymbol: string;
targetAssetSymbol: string;
vortexPrice: Big;
network: Networks;
}

function VortexRow({
targetAssetSymbol,
vortexPrice,
}: Omit<FeeProviderRowProps, 'provider' | 'sourceAssetSymbol' | 'amount'>) {
interface FeeComparisonProps extends BaseComparisonProps {
enabled: boolean;
}

type VortexRowProps = Pick<BaseComparisonProps, 'targetAssetSymbol' | 'vortexPrice'>;

function VortexRow({ targetAssetSymbol, vortexPrice }: VortexRowProps) {
return (
<div className="flex items-center justify-between w-full">
<div className="flex items-center w-full gap-4 ml-4 grow">
<img src={vortexIcon} className="h-10 w-36" alt="Vortex" />
</div>
<div className="flex items-center justify-center w-full gap-4 grow">
<div className="flex flex-col items-center">
<span className="font-bold text-md">{vortexPrice.toFixed(2) + ' ' + targetAssetSymbol}</span>
<span className="font-bold text-md">{`${vortexPrice.toFixed(2)} ${targetAssetSymbol}`}</span>
</div>
</div>
</div>
);
}

interface FeeProviderRowProps extends BaseComparisonProps {
provider: QuoteProvider;
}

function FeeProviderRow({
provider,
amount,
Expand All @@ -39,6 +51,9 @@ function FeeProviderRow({
network,
}: FeeProviderRowProps) {
const { scheduleQuote } = useEventsContext();
// The vortex price is sometimes lagging behind the amount (as it first has to be calculated asynchronously)
// We keep a reference to the previous vortex price to avoid spamming the server with the same quote.
const prevVortexPrice = useRef<Big>();

const {
isLoading,
Expand All @@ -49,31 +64,26 @@ function FeeProviderRow({
queryFn: () => provider.query(sourceAssetSymbol, targetAssetSymbol, amount, network),
retry: false, // We don't want to retry the request to avoid spamming the server
});
// The vortex price is sometimes lagging behind the amount (as it first has to be calculated asynchronously)
// We keep a reference to the previous vortex price to avoid spamming the server with the same quote.
const prevVortexPrice = useRef<Big | undefined>(undefined);

const priceDiff = useMemo(() => {
if (isLoading || error || !providerPrice) {
return undefined;
}

if (isLoading || error || !providerPrice) return undefined;
return providerPrice.minus(vortexPrice);
}, [isLoading, error, providerPrice, vortexPrice]);

useEffect(() => {
if (!isLoading && (providerPrice || error)) {
const parameters: OfframpingParameters = {
from_amount: amount.toFixed(2),
from_asset: sourceAssetSymbol,
to_amount: vortexPrice.toFixed(2),
to_asset: targetAssetSymbol,
};
if (!prevVortexPrice.current || vortexPrice !== prevVortexPrice.current) {
scheduleQuote(provider.name, providerPrice ? providerPrice.toFixed(2, 0) : '-1', parameters);
prevVortexPrice.current = vortexPrice;
}
}
if (isLoading || (!providerPrice && !error)) return;

const parameters: OfframpingParameters = {
from_amount: amount.toFixed(2),
from_asset: sourceAssetSymbol,
to_amount: vortexPrice.toFixed(2),
to_asset: targetAssetSymbol,
};

if (prevVortexPrice.current?.eq(vortexPrice)) return;

scheduleQuote(provider.name, providerPrice ? providerPrice.toFixed(2, 0) : '-1', parameters);
prevVortexPrice.current = vortexPrice;
}, [
amount,
provider.name,
Expand All @@ -97,12 +107,12 @@ function FeeProviderRow({
) : (
<div className="flex flex-col items-center">
<span className="font-bold text-md">
{error || !providerPrice ? 'N/A' : providerPrice.toFixed(2) + ' ' + targetAssetSymbol}
{error || !providerPrice ? 'N/A' : `${providerPrice.toFixed(2)} ${targetAssetSymbol}`}
</span>
{priceDiff && (
<span className={`flex items-center ${priceDiff.gt(0) ? 'text-green-600' : 'text-red-600'}`}>
<ChevronDownIcon className={`w-5 h-5 ${priceDiff.gt(0) ? 'rotate-180' : ''}`} /> {priceDiff.toFixed(2)}{' '}
{targetAssetSymbol}
<ChevronDownIcon className={`w-5 h-5 ${priceDiff.gt(0) ? 'rotate-180' : ''}`} />
{`${priceDiff.toFixed(2)} ${targetAssetSymbol}`}
</span>
)}
</div>
Expand All @@ -112,15 +122,9 @@ function FeeProviderRow({
);
}

type FeeComparisonTableProps = FeeComparisonProps;
function FeeComparisonTable(props: BaseComparisonProps) {
const { amount, sourceAssetSymbol, network, targetAssetSymbol, vortexPrice } = props;

function FeeComparisonTable({
amount,
sourceAssetSymbol,
targetAssetSymbol,
vortexPrice,
network,
}: FeeComparisonTableProps) {
return (
<div className="w-full p-4 grow rounded-3xl shadow-custom">
<div className="flex items-center justify-center w-full mb-3">
Expand All @@ -146,42 +150,41 @@ function FeeComparisonTable({
</div>
</div>
<div className="w-full my-4 border-b border-gray-200" />
<VortexRow targetAssetSymbol={targetAssetSymbol} vortexPrice={vortexPrice} network={network} />
{quoteProviders.map((provider, index) => (
<>
<VortexRow targetAssetSymbol={targetAssetSymbol} vortexPrice={vortexPrice} />
{quoteProviders.map((provider) => (
<div key={provider.name}>
<div className="w-full my-4 border-b border-gray-200" />
<FeeProviderRow
key={index}
amount={amount}
provider={provider}
sourceAssetSymbol={sourceAssetSymbol}
targetAssetSymbol={targetAssetSymbol}
vortexPrice={vortexPrice}
network={network}
/>
</>
<FeeProviderRow {...props} provider={provider} />
</div>
))}
</div>
);
}

interface FeeComparisonProps {
amount: Big;
sourceAssetSymbol: string;
targetAssetSymbol: string;
vortexPrice: Big;
network: Networks;
}
export function FeeComparison({ enabled, ...props }: FeeComparisonProps) {
const feeComparisonRef = useRef<HTMLDivElement>(null);

useEffect(() => {
if (!enabled) return;
if (!feeComparisonRef.current) return;

const timer = setTimeout(() => {
window.scrollTo({
top: feeComparisonRef.current!.offsetTop,
behavior: 'smooth',
});
}, 300);

return () => clearTimeout(timer);
}, [enabled]);

if (!enabled) return null;

export function FeeComparison({
amount,
sourceAssetSymbol,
targetAssetSymbol,
vortexPrice,
network,
}: FeeComparisonProps) {
return (
<div className="flex flex-col items-center max-w-4xl px-4 py-8 rounded-lg md:flex-row gap-x-8 gap-y-8 md:mx-auto md:w-3/4">
<div
ref={feeComparisonRef}
className="flex flex-col items-center max-w-4xl px-4 py-8 rounded-lg md:flex-row gap-x-8 gap-y-8 md:mx-auto md:w-3/4"
>
<div className="w-full gap-6 overflow-auto grow">
<h1 className="text-2xl font-bold">Save on exchange rate markups</h1>
<p className="mt-4 text-lg">
Expand All @@ -190,13 +193,7 @@ export function FeeComparison({
</p>
<p className="mt-4 text-lg">At Vortex, we’ll never do that and show our fees upfront.</p>
</div>
<FeeComparisonTable
amount={amount}
sourceAssetSymbol={sourceAssetSymbol}
targetAssetSymbol={targetAssetSymbol}
vortexPrice={vortexPrice}
network={network}
/>
<FeeComparisonTable {...props} />
</div>
);
}
5 changes: 1 addition & 4 deletions src/pages/swap/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -426,10 +426,6 @@ export const SwapPage = () => {
onClick={(e) => {
e.preventDefault();
setShowCompareFees(!showCompareFees);
// Smooth scroll to bottom of page
setTimeout(() => {
window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' });
}, 300);
}}
>
Compare fees
Expand Down Expand Up @@ -466,6 +462,7 @@ export const SwapPage = () => {
targetAssetSymbol={toToken.fiat.symbol}
vortexPrice={vortexPrice}
network={selectedNetwork}
enabled={showCompareFees}
/>
)}
<TrustedBy />
Expand Down
Loading