Skip to content

Commit d4ccf78

Browse files
authored
Merge pull request #355 from pendulum-chain/scroll-fee-compare
Scroll to beginning of the comparison table.
2 parents ed95ba2 + 8467926 commit d4ccf78

File tree

2 files changed

+71
-77
lines changed

2 files changed

+71
-77
lines changed
Lines changed: 70 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import Big from 'big.js';
2-
import { useMemo } from 'preact/hooks';
3-
import { useEffect, useRef } from 'preact/compat';
2+
import { useEffect, useRef, useMemo } from 'preact/hooks';
43
import { useQuery } from '@tanstack/react-query';
54
import { ChevronDownIcon } from '@heroicons/react/20/solid';
65

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

13-
type FeeProviderRowProps = FeeComparisonProps & { provider: QuoteProvider };
12+
interface BaseComparisonProps {
13+
amount: Big;
14+
sourceAssetSymbol: string;
15+
targetAssetSymbol: string;
16+
vortexPrice: Big;
17+
network: Networks;
18+
}
1419

15-
function VortexRow({
16-
targetAssetSymbol,
17-
vortexPrice,
18-
}: Omit<FeeProviderRowProps, 'provider' | 'sourceAssetSymbol' | 'amount'>) {
20+
interface FeeComparisonProps extends BaseComparisonProps {
21+
enabled: boolean;
22+
}
23+
24+
type VortexRowProps = Pick<BaseComparisonProps, 'targetAssetSymbol' | 'vortexPrice'>;
25+
26+
function VortexRow({ targetAssetSymbol, vortexPrice }: VortexRowProps) {
1927
return (
2028
<div className="flex items-center justify-between w-full">
2129
<div className="flex items-center w-full gap-4 ml-4 grow">
2230
<img src={vortexIcon} className="h-10 w-36" alt="Vortex" />
2331
</div>
2432
<div className="flex items-center justify-center w-full gap-4 grow">
2533
<div className="flex flex-col items-center">
26-
<span className="font-bold text-md">{vortexPrice.toFixed(2) + ' ' + targetAssetSymbol}</span>
34+
<span className="font-bold text-md">{`${vortexPrice.toFixed(2)} ${targetAssetSymbol}`}</span>
2735
</div>
2836
</div>
2937
</div>
3038
);
3139
}
3240

41+
interface FeeProviderRowProps extends BaseComparisonProps {
42+
provider: QuoteProvider;
43+
}
44+
3345
function FeeProviderRow({
3446
provider,
3547
amount,
@@ -39,6 +51,9 @@ function FeeProviderRow({
3951
network,
4052
}: FeeProviderRowProps) {
4153
const { scheduleQuote } = useEventsContext();
54+
// The vortex price is sometimes lagging behind the amount (as it first has to be calculated asynchronously)
55+
// We keep a reference to the previous vortex price to avoid spamming the server with the same quote.
56+
const prevVortexPrice = useRef<Big>();
4257

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

5668
const priceDiff = useMemo(() => {
57-
if (isLoading || error || !providerPrice) {
58-
return undefined;
59-
}
60-
69+
if (isLoading || error || !providerPrice) return undefined;
6170
return providerPrice.minus(vortexPrice);
6271
}, [isLoading, error, providerPrice, vortexPrice]);
6372

6473
useEffect(() => {
65-
if (!isLoading && (providerPrice || error)) {
66-
const parameters: OfframpingParameters = {
67-
from_amount: amount.toFixed(2),
68-
from_asset: sourceAssetSymbol,
69-
to_amount: vortexPrice.toFixed(2),
70-
to_asset: targetAssetSymbol,
71-
};
72-
if (!prevVortexPrice.current || vortexPrice !== prevVortexPrice.current) {
73-
scheduleQuote(provider.name, providerPrice ? providerPrice.toFixed(2, 0) : '-1', parameters);
74-
prevVortexPrice.current = vortexPrice;
75-
}
76-
}
74+
if (isLoading || (!providerPrice && !error)) return;
75+
76+
const parameters: OfframpingParameters = {
77+
from_amount: amount.toFixed(2),
78+
from_asset: sourceAssetSymbol,
79+
to_amount: vortexPrice.toFixed(2),
80+
to_asset: targetAssetSymbol,
81+
};
82+
83+
if (prevVortexPrice.current?.eq(vortexPrice)) return;
84+
85+
scheduleQuote(provider.name, providerPrice ? providerPrice.toFixed(2, 0) : '-1', parameters);
86+
prevVortexPrice.current = vortexPrice;
7787
}, [
7888
amount,
7989
provider.name,
@@ -97,12 +107,12 @@ function FeeProviderRow({
97107
) : (
98108
<div className="flex flex-col items-center">
99109
<span className="font-bold text-md">
100-
{error || !providerPrice ? 'N/A' : providerPrice.toFixed(2) + ' ' + targetAssetSymbol}
110+
{error || !providerPrice ? 'N/A' : `${providerPrice.toFixed(2)} ${targetAssetSymbol}`}
101111
</span>
102112
{priceDiff && (
103113
<span className={`flex items-center ${priceDiff.gt(0) ? 'text-green-600' : 'text-red-600'}`}>
104-
<ChevronDownIcon className={`w-5 h-5 ${priceDiff.gt(0) ? 'rotate-180' : ''}`} /> {priceDiff.toFixed(2)}{' '}
105-
{targetAssetSymbol}
114+
<ChevronDownIcon className={`w-5 h-5 ${priceDiff.gt(0) ? 'rotate-180' : ''}`} />
115+
{`${priceDiff.toFixed(2)} ${targetAssetSymbol}`}
106116
</span>
107117
)}
108118
</div>
@@ -112,15 +122,9 @@ function FeeProviderRow({
112122
);
113123
}
114124

115-
type FeeComparisonTableProps = FeeComparisonProps;
125+
function FeeComparisonTable(props: BaseComparisonProps) {
126+
const { amount, sourceAssetSymbol, network, targetAssetSymbol, vortexPrice } = props;
116127

117-
function FeeComparisonTable({
118-
amount,
119-
sourceAssetSymbol,
120-
targetAssetSymbol,
121-
vortexPrice,
122-
network,
123-
}: FeeComparisonTableProps) {
124128
return (
125129
<div className="w-full p-4 grow rounded-3xl shadow-custom">
126130
<div className="flex items-center justify-center w-full mb-3">
@@ -146,42 +150,41 @@ function FeeComparisonTable({
146150
</div>
147151
</div>
148152
<div className="w-full my-4 border-b border-gray-200" />
149-
<VortexRow targetAssetSymbol={targetAssetSymbol} vortexPrice={vortexPrice} network={network} />
150-
{quoteProviders.map((provider, index) => (
151-
<>
153+
<VortexRow targetAssetSymbol={targetAssetSymbol} vortexPrice={vortexPrice} />
154+
{quoteProviders.map((provider) => (
155+
<div key={provider.name}>
152156
<div className="w-full my-4 border-b border-gray-200" />
153-
<FeeProviderRow
154-
key={index}
155-
amount={amount}
156-
provider={provider}
157-
sourceAssetSymbol={sourceAssetSymbol}
158-
targetAssetSymbol={targetAssetSymbol}
159-
vortexPrice={vortexPrice}
160-
network={network}
161-
/>
162-
</>
157+
<FeeProviderRow {...props} provider={provider} />
158+
</div>
163159
))}
164160
</div>
165161
);
166162
}
167163

168-
interface FeeComparisonProps {
169-
amount: Big;
170-
sourceAssetSymbol: string;
171-
targetAssetSymbol: string;
172-
vortexPrice: Big;
173-
network: Networks;
174-
}
164+
export function FeeComparison({ enabled, ...props }: FeeComparisonProps) {
165+
const feeComparisonRef = useRef<HTMLDivElement>(null);
166+
167+
useEffect(() => {
168+
if (!enabled) return;
169+
if (!feeComparisonRef.current) return;
170+
171+
const timer = setTimeout(() => {
172+
window.scrollTo({
173+
top: feeComparisonRef.current!.offsetTop,
174+
behavior: 'smooth',
175+
});
176+
}, 300);
177+
178+
return () => clearTimeout(timer);
179+
}, [enabled]);
180+
181+
if (!enabled) return null;
175182

176-
export function FeeComparison({
177-
amount,
178-
sourceAssetSymbol,
179-
targetAssetSymbol,
180-
vortexPrice,
181-
network,
182-
}: FeeComparisonProps) {
183183
return (
184-
<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">
184+
<div
185+
ref={feeComparisonRef}
186+
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"
187+
>
185188
<div className="w-full gap-6 overflow-auto grow">
186189
<h1 className="text-2xl font-bold">Save on exchange rate markups</h1>
187190
<p className="mt-4 text-lg">
@@ -190,13 +193,7 @@ export function FeeComparison({
190193
</p>
191194
<p className="mt-4 text-lg">At Vortex, we’ll never do that and show our fees upfront.</p>
192195
</div>
193-
<FeeComparisonTable
194-
amount={amount}
195-
sourceAssetSymbol={sourceAssetSymbol}
196-
targetAssetSymbol={targetAssetSymbol}
197-
vortexPrice={vortexPrice}
198-
network={network}
199-
/>
196+
<FeeComparisonTable {...props} />
200197
</div>
201198
);
202199
}

src/pages/swap/index.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -426,10 +426,6 @@ export const SwapPage = () => {
426426
onClick={(e) => {
427427
e.preventDefault();
428428
setShowCompareFees(!showCompareFees);
429-
// Smooth scroll to bottom of page
430-
setTimeout(() => {
431-
window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' });
432-
}, 300);
433429
}}
434430
>
435431
Compare fees
@@ -466,6 +462,7 @@ export const SwapPage = () => {
466462
targetAssetSymbol={toToken.fiat.symbol}
467463
vortexPrice={vortexPrice}
468464
network={selectedNetwork}
465+
enabled={showCompareFees}
469466
/>
470467
)}
471468
<TrustedBy />

0 commit comments

Comments
 (0)