From e89f4d10c3e73b2347d10f02104fd26822fd10a0 Mon Sep 17 00:00:00 2001
From: tradermohamed <110409704+tradermohamed@users.noreply.github.com>
Date: Thu, 3 Aug 2023 04:44:26 +0900
Subject: [PATCH] Merge mobile changes (#12)
* updated bar charts and colors
* put coin selector sort in a util file
---
components/common/chartWrapper/index.tsx | 6 +-
components/home/charts/cumulative-inflow.tsx | 5 +-
components/home/charts/cumulative-users.tsx | 10 ++-
components/home/charts/fees.tsx | 6 +-
components/home/charts/funding-rate.tsx | 41 +++----------
components/home/charts/hlp.tsx | 46 ++++++++------
components/home/charts/liquidator.tsx | 64 ++++++++++----------
components/home/charts/liquidity.tsx | 55 ++++++-----------
components/home/charts/open-interest.tsx | 15 +++--
components/home/charts/retail-volume.tsx | 57 +++++++++--------
components/home/charts/trader-profit.tsx | 10 ++-
components/home/charts/unique-users-coin.tsx | 64 +++++++++-----------
components/home/charts/volume-num-trades.tsx | 57 +++++++++--------
components/home/charts/volume-total.tsx | 46 +++++++-------
constants/tokens.ts | 53 ++++++----------
helpers/utils.ts | 52 ++++++++++++++++
hooks/isMobile.ts | 13 ++++
package-lock.json | 22 +++++++
package.json | 2 +
19 files changed, 331 insertions(+), 293 deletions(-)
create mode 100644 helpers/utils.ts
create mode 100644 hooks/isMobile.ts
diff --git a/components/common/chartWrapper/index.tsx b/components/common/chartWrapper/index.tsx
index 2302d16..496a9f3 100644
--- a/components/common/chartWrapper/index.tsx
+++ b/components/common/chartWrapper/index.tsx
@@ -33,7 +33,7 @@ const Loader = () => (
);
function ChartWrapper(props: any) {
- const [isMobile] = useMediaQuery('(max-width: 700px)');
+ let isMobile = props.isMobile;
const { title, loading, controls, zIndex, coinSelectors } = props;
const controlButtons =
controls &&
@@ -92,9 +92,7 @@ function ChartWrapper(props: any) {
{controlButtons}
) : (
-
- {controlButtons}
-
+ {controlButtons}
)}
)}
diff --git a/components/home/charts/cumulative-inflow.tsx b/components/home/charts/cumulative-inflow.tsx
index 2acf73d..d4fe2e2 100644
--- a/components/home/charts/cumulative-inflow.tsx
+++ b/components/home/charts/cumulative-inflow.tsx
@@ -22,11 +22,12 @@ import {
tooltipFormatterDate,
} from '../../../helpers';
import { daily_inflow, cumulative_inflow } from '../../../constants/api';
+import { useIsMobile } from '@/hooks/isMobile';
const REQUESTS = [daily_inflow, cumulative_inflow];
export default function CumulativeInflow() {
- const [isMobile] = useMediaQuery('(max-width: 700px)');
+ const [isMobile] = useIsMobile();
const [formattedData, setFormattedData] = useState([]);
const [dataDailyInflow, loadingDailyInflow, errorDailyInflow] = useRequest(
@@ -99,7 +100,7 @@ export default function CumulativeInflow() {
}, [loading, errorDailyInflow]);
return (
-
+
diff --git a/components/home/charts/cumulative-users.tsx b/components/home/charts/cumulative-users.tsx
index f09b5e0..3003ffe 100644
--- a/components/home/charts/cumulative-users.tsx
+++ b/components/home/charts/cumulative-users.tsx
@@ -11,6 +11,7 @@ import {
} from 'recharts';
import { useEffect, useState } from 'react';
import { useRequest } from '@/hooks/useRequest';
+import { useIsMobile } from '@/hooks/isMobile';
import { useMediaQuery } from '@chakra-ui/react';
import ChartWrapper from '../../common/chartWrapper';
import { CHART_HEIGHT, YAXIS_WIDTH, BRIGHT_GREEN, GREEN } from '../../../constants';
@@ -29,7 +30,7 @@ import {
const REQUESTS = [cumulative_new_users, daily_unique_users, daily_unique_users_by_coin];
export default function CumulativeUsers() {
- const [isMobile] = useMediaQuery('(max-width: 700px)');
+ const [isMobile] = useIsMobile();
const [formattedData, setFormattedData] = useState([]);
@@ -74,7 +75,12 @@ export default function CumulativeUsers() {
}, [loading, error]);
return (
-
+
diff --git a/components/home/charts/fees.tsx b/components/home/charts/fees.tsx
index c56e652..a893645 100644
--- a/components/home/charts/fees.tsx
+++ b/components/home/charts/fees.tsx
@@ -11,6 +11,7 @@ import {
} from 'recharts';
import { useEffect, useState } from 'react';
import { useRequest } from '@/hooks/useRequest';
+import { useIsMobile } from '@/hooks/isMobile';
import { useMediaQuery } from '@chakra-ui/react';
import ChartWrapper from '../../common/chartWrapper';
import { CHART_HEIGHT, YAXIS_WIDTH, BRIGHT_GREEN, GREEN } from '../../../constants';
@@ -25,7 +26,8 @@ import { total_accrued_fees } from '../../../constants/api';
const REQUESTS = [total_accrued_fees];
export default function Fees() {
- const [isMobile] = useMediaQuery('(max-width: 700px)');
+ const [isMobile] = useIsMobile();
+
const [formattedData, setFormattedData] = useState([]);
const [dailyFeesAccrued, loading, error] = useRequest(REQUESTS[0], [], 'chart_data');
@@ -68,7 +70,7 @@ export default function Fees() {
}, [loading, error]);
return (
-
+
diff --git a/components/home/charts/funding-rate.tsx b/components/home/charts/funding-rate.tsx
index 2ca2999..190f37b 100644
--- a/components/home/charts/funding-rate.tsx
+++ b/components/home/charts/funding-rate.tsx
@@ -11,6 +11,7 @@ import {
import { useMediaQuery } from '@chakra-ui/react';
import { useEffect, useState } from 'react';
import { useRequest } from '@/hooks/useRequest';
+import { useIsMobile } from '@/hooks/isMobile';
import ChartWrapper, { CoinSelector } from '../../common/chartWrapper';
import { CHART_HEIGHT } from '../../../constants';
import {
@@ -19,13 +20,15 @@ import {
formatterPercent,
tooltipFormatterDate,
} from '../../../helpers';
-import { getTokenHex } from '../../../constants/tokens';
+import { createCoinSelectors } from "../../../helpers/utils";
+
+import { getTokenColor, initialTokensSelected } from '../../../constants/tokens';
import { funding_rate } from '../../../constants/api';
const REQUESTS = [funding_rate];
export default function FundingRate() {
- const [isMobile] = useMediaQuery('(max-width: 700px)');
+ const [isMobile] = useIsMobile();
const [coinKeys, setCoinKeys] = useState([]);
const [formattedData, setFormattedData] = useState([]);
@@ -34,7 +37,7 @@ export default function FundingRate() {
[],
'chart_data'
);
- const [coinsSelected, setCoinsSelected] = useState(['ETH', 'BTC', 'ARB']);
+ const [coinsSelected, setCoinsSelected] = useState(initialTokensSelected);
const loading = loadingFundingRate;
const error = errorFundingRate;
@@ -113,34 +116,7 @@ export default function FundingRate() {
}
}, [loading, coinsSelected]);
- const coinSelectorsSort = (a: CoinSelector, b: CoinSelector) => {
- if (a.isChecked !== b.isChecked) {
- return a.isChecked ? -1 : 1;
- }
- return a.name.localeCompare(b.name);
- };
-
- const coinSelectors = coinKeys
- .map((coinKey: string) => {
- return {
- name: coinKey,
- event: () =>
- setCoinsSelected((coinsSelected) => {
- let newCoinsSelected = coinsSelected;
- if (coinsSelected.includes(coinKey)) {
- newCoinsSelected = coinsSelected.filter((e) => {
- return e !== coinKey;
- });
- } else {
- newCoinsSelected.push(coinKey);
- }
- formatData();
- return newCoinsSelected;
- }),
- isChecked: coinsSelected.includes(coinKey),
- };
- })
- .sort((a: CoinSelector, b: CoinSelector) => coinSelectorsSort(a, b));
+ const coinSelectors = createCoinSelectors(coinKeys, coinsSelected, setCoinsSelected, formatData)
return (
@@ -189,7 +166,7 @@ export default function FundingRate() {
dataKey={coinName.toString()}
dot={false}
name={coinName.toString()}
- stroke={getTokenHex(coinName.toString())}
+ stroke={getTokenColor(coinName.toString())}
key={'funding-rate-line-' + i}
/>
);
diff --git a/components/home/charts/hlp.tsx b/components/home/charts/hlp.tsx
index 6682717..d58eb8b 100644
--- a/components/home/charts/hlp.tsx
+++ b/components/home/charts/hlp.tsx
@@ -13,6 +13,8 @@ import {
import { Box, Text, useMediaQuery } from '@chakra-ui/react';
import { useEffect, useState } from 'react';
import { useRequest } from '@/hooks/useRequest';
+import { useIsMobile } from '@/hooks/isMobile';
+
import ChartWrapper from '../../common/chartWrapper';
import { BLUE, BRIGHT_GREEN, CHART_HEIGHT, GREEN, ORANGE, RED } from '../../../constants';
import {
@@ -22,14 +24,16 @@ import {
yaxisFormatter,
tooltipFormatterLongShort,
} from '../../../helpers';
-import { getTokenHex } from '@/constants/tokens';
+
+import { getTokenColor } from '@/constants/tokens';
import { asset_ctxs, hlp_liquidator_pnl, hlp_positions } from '@/constants/api';
const REQUESTS = [hlp_positions, asset_ctxs, hlp_liquidator_pnl];
const DAY = 60 * 60 * 24 * 1000;
export default function Hlp() {
- const [isMobile] = useMediaQuery('(max-width: 700px)');
+ const [isMobile] = useIsMobile();
+
const [dataMode, setDataMode] = useState<'COINS' | 'NET' | 'PNL' | 'HEDGED'>('PNL');
const [coins, setCoins] = useState([]);
const [dataHlpPositions, loadingDataHlpPositions, errorDataHlpPositions] = useRequest(
@@ -82,7 +86,7 @@ export default function Hlp() {
const getOraclePxs = (assetCtxs: AssetCtx[]): Map => {
const map = new Map();
assetCtxs.forEach((item) => {
- map.set(item.coin + item.time, item.first_oracle_px);
+ map.set(item.coin + item.time, item.first_oracle_px);
});
return map;
};
@@ -128,7 +132,7 @@ export default function Hlp() {
let { time, coin, daily_ntl } = item;
if (!map.has(time)) {
const pnl = hlpPnL.get(time)?.pnl || 0;
- hedgedCumulativePnl += pnl;
+ hedgedCumulativePnl += pnl;
map.set(time, {
time: new Date(time),
daily_ntl: 0,
@@ -144,12 +148,12 @@ export default function Hlp() {
existingEntry.daily_ntl += daily_ntl;
const oraclePx = oraclePxs.get(coin + time);
- let hedgedPnl = 0;
+ let hedgedPnl = 0;
const nextTime = getNextTime(time);
let oraclePxNext = oraclePxs.get(coin + nextTime);
-
- let prevTimeData = prevTime ? map.get(prevTime) : null;
- let prevDayNtlPosition = prevTimeData ? prevTimeData[`${coin}`] : null;
+
+ let prevTimeData = prevTime ? map.get(prevTime) : null;
+ let prevDayNtlPosition = prevTimeData ? prevTimeData[`${coin}`] : null;
if (oraclePxNext && oraclePx && prevDayNtlPosition) {
const pxChange = 1 - oraclePx / oraclePxNext;
@@ -157,9 +161,9 @@ export default function Hlp() {
hedgedPnl += pnl;
}
- existingEntry.hedged_pnl += hedgedPnl;
+ existingEntry.hedged_pnl += hedgedPnl;
hedgedCumulativePnl += hedgedPnl;
- existingEntry.hedged_cumulative_pnl = hedgedCumulativePnl;
+ existingEntry.hedged_cumulative_pnl = hedgedCumulativePnl;
});
map.forEach((entry) => {
@@ -237,7 +241,13 @@ export default function Hlp() {
}, [loading, error, hlpPnL]);
return (
-
+
@@ -295,7 +305,7 @@ export default function Hlp() {
dataKey={coin}
stackId='a'
name={coin.toString()}
- fill={getTokenHex(coin.toString())}
+ fill={getTokenColor(coin.toString())}
key={i}
maxBarSize={20}
/>
@@ -356,21 +366,19 @@ export default function Hlp() {
)}
- {dataMode === 'PNL' && (
- PNL over time
- )}
+ {dataMode === 'PNL' && PNL over time}
{dataMode === 'HEDGED' && (
- Hedged PNL over time. Hedge the previous day's position and add to today's PNL.
+
+ Hedged PNL over time. Hedge the previous day's position and add to today's PNL.
+
)}
- {dataMode === 'NET' && (
- Net notional position over time
- )}
+ {dataMode === 'NET' && Net notional position over time}
);
diff --git a/components/home/charts/liquidator.tsx b/components/home/charts/liquidator.tsx
index d6a88aa..b34f45a 100644
--- a/components/home/charts/liquidator.tsx
+++ b/components/home/charts/liquidator.tsx
@@ -12,8 +12,9 @@ import {
} from 'recharts';
import { useEffect, useState } from 'react';
import { useRequest } from '@/hooks/useRequest';
+import { useIsMobile } from '@/hooks/isMobile';
import { Box, Text, useMediaQuery } from '@chakra-ui/react';
-import ChartWrapper from '../../common/chartWrapper';
+import ChartWrapper, { CoinSelector } from '../../common/chartWrapper';
import {
CHART_HEIGHT,
YAXIS_WIDTH,
@@ -30,7 +31,9 @@ import {
tooltipFormatterCurrency,
tooltipFormatterDate,
} from '../../../helpers';
-import { getTokenHex } from '../../../constants/tokens';
+import { createCoinSelectorsWithFormatArg } from "../../../helpers/utils";
+
+import { getTokenColor, initialTokensSelectedWithOther } from '../../../constants/tokens';
import {
cumulative_liquidated_notional,
daily_notional_liquidated_total,
@@ -50,9 +53,10 @@ const REQUESTS = [
];
export default function LiquidatorChart() {
- const [isMobile] = useMediaQuery('(max-width: 700px)');
+ const [isMobile] = useIsMobile();
const [dataMode, setDataMode] = useState<'COINS' | 'MARGIN' | 'PNL'>('COINS');
+ const [coinsSelected, setCoinsSelected] = useState(initialTokensSelectedWithOther);
const [formattedDataCoins, setFormattedDataCoins] = useState([]);
const [formattedDataMargin, setFormattedDataMargin] = useState([]);
@@ -168,6 +172,7 @@ export default function LiquidatorChart() {
type FormattedCoinTradesData = any[];
const formatDailyTradesByCoins = (
+ CoinsSelected: string[],
dataDailyTradesByCoin: { time: string; coin: string; daily_notional_liquidated: number }[],
formattedCumulativeByTime: { [key: string]: number }
): FormattedCoinTradesData[] => {
@@ -180,25 +185,21 @@ export default function LiquidatorChart() {
temp[data.time].all += data.daily_notional_liquidated;
}
- const sortAndSliceTop10 = (obj: { [coin: string]: number }) => {
- const sortedEntries = Object.entries(obj).sort(
- ([, aVolume], [, bVolume]) => bVolume - aVolume
- );
- const top10Entries = sortedEntries.slice(0, 10);
- const otherEntries = sortedEntries.slice(10);
-
+ const selectedCoinData = (obj: { [coin: string]: number }) => {
+ const selectedEntries = Object.entries(obj).filter(([coin]) => CoinsSelected.includes(coin) || coin==="all");
+ const otherEntries = Object.entries(obj).filter(([coin]) => (!(CoinsSelected.includes(coin))) && (coin !== "all"));
const otherVolume = otherEntries.reduce((total, [, volume]) => total + volume, 0);
return {
- ...Object.fromEntries(top10Entries),
+ ...Object.fromEntries(selectedEntries),
Other: otherVolume,
};
};
const result: any[] = Object.entries(temp).map(([time, volumes]) => {
- const top10Volumes = sortAndSliceTop10(volumes);
+ const selectedVolumes = selectedCoinData(volumes);
return {
time: new Date(time),
- ...top10Volumes,
+ ...selectedVolumes,
cumulative: formattedCumulativeByTime[time as any],
unit: '',
};
@@ -206,25 +207,17 @@ export default function LiquidatorChart() {
return result;
};
- const extractUniqueCoins = (formattedData: any[]): string[] => {
+ const extractUniqueCoins = (coinData: any[]): string[] => {
const coinSet = new Set();
- for (const data of formattedData) {
- Object.keys(data).forEach((coin) => {
- if (coin !== 'time' && coin !== 'unit' && coin !== 'cumulative' && coin !== 'all') {
- coinSet.add(coin);
+ for (const data of coinData) {
+ if (data.coin !== 'time' && data.coin !== 'unit' && data.coin !== 'cumulative' && data.coin !== 'all') {
+ coinSet.add(data.coin);
}
- });
- }
- const coinsArray = Array.from(coinSet);
- if (coinsArray.includes('Other')) {
- const index = coinsArray.indexOf('Other');
- coinsArray.splice(index, 1);
- coinsArray.push('Other');
}
- return coinsArray;
+ return Array.from(coinSet);
};
- const formatData = () => {
+ const formatData = (CoinsSelected: string[]) => {
const formattedCumulativeLiquidatedByTime =
formatCumulativeLiquidatedByTime(dataCumulativeLiquidated);
const formattedVolumeByMargin = formatLiquidatedByMargin(
@@ -232,6 +225,7 @@ export default function LiquidatorChart() {
formattedCumulativeLiquidatedByTime
);
const formattedDailyTradesByCoins = formatDailyTradesByCoins(
+ CoinsSelected,
dataDailyLiquidatedByCoins,
formattedCumulativeLiquidatedByTime
);
@@ -240,7 +234,7 @@ export default function LiquidatorChart() {
dataLiquidatorCumulativePnl
);
setFormattedLiquidatorPnl(newFormattedLiquidatorPnl);
- setCoinKeys(extractUniqueCoins(formattedDailyTradesByCoins));
+ setCoinKeys(extractUniqueCoins(dataDailyLiquidatedByCoins));
setFormattedDataMargin(formattedVolumeByMargin);
setFormattedDataCoins(formattedDailyTradesByCoins);
console.log('dev formattedDailyTradesByCoins', formattedDailyTradesByCoins);
@@ -268,7 +262,7 @@ export default function LiquidatorChart() {
useEffect(() => {
if (!loading && !error) {
- formatData();
+ formatData(coinsSelected);
}
}, [loading, error]);
@@ -297,6 +291,10 @@ export default function LiquidatorChart() {
return [-1 * Math.abs(maxCumulativePnl) * 1.1, Math.abs(maxCumulativePnl) * 1.1];
};
+
+ const coinSelectors = createCoinSelectorsWithFormatArg(coinKeys, coinsSelected, setCoinsSelected, formatData)
+
+
return (
@@ -334,8 +334,8 @@ export default function LiquidatorChart() {
{dataMode === 'COINS' && (
<>
- {coinKeys &&
- coinKeys.map((coinName, i) => {
+ {
+ coinsSelected.map((coinName, i) => {
return (
diff --git a/components/home/charts/liquidity.tsx b/components/home/charts/liquidity.tsx
index 0bc7e92..128d18e 100644
--- a/components/home/charts/liquidity.tsx
+++ b/components/home/charts/liquidity.tsx
@@ -12,6 +12,7 @@ import { useEffect, useState } from 'react';
import { Box, Text, useMediaQuery } from '@chakra-ui/react';
import { useRequest } from '@/hooks/useRequest';
import ChartWrapper, { CoinSelector } from '../../common/chartWrapper';
+import { useIsMobile } from '@/hooks/isMobile';
import { CHART_HEIGHT } from '../../../constants';
import {
tooltipFormatter,
@@ -19,13 +20,16 @@ import {
xAxisFormatter,
formatterPercent,
} from '../../../helpers';
-import { getTokenHex } from '../../../constants/tokens';
+import { createCoinSelectors } from "../../../helpers/utils";
+
+import { getTokenColor, initialTokensSelected } from '../../../constants/tokens';
import { liquidity_by_coin } from '../../../constants/api';
const REQUESTS = [liquidity_by_coin];
export default function Liquidity() {
- const [isMobile] = useMediaQuery('(max-width: 700px)');
+ const [isMobile] = useIsMobile();
+
const [formattedData0, setFormattedData0] = useState([]);
const [formattedData1000, setFormattedData1000] = useState([]);
const [formattedData3000, setFormattedData3000] = useState([]);
@@ -38,7 +42,7 @@ export default function Liquidity() {
const [coinKeys10000, setCoinKeys10000] = useState([]);
const [dataMode, setDataMode] = useState<'0' | '1000' | '3000' | '10000'>('0');
- const [coinsSelected, setCoinsSelected] = useState(['ETH', 'BTC', 'ARB']);
+ const [coinsSelected, setCoinsSelected] = useState(initialTokensSelected);
const [dataLiqudity, loadingLiqudity, errorLiqudity] = useRequest(REQUESTS[0], [], 'chart_data');
const loading = loadingLiqudity;
@@ -87,12 +91,12 @@ export default function Liquidity() {
};
const extractCoins = (data: InputData): string[] => {
- let coins = [];
+ let coins = [];
for (let coin of Object.keys(data)) {
- coins.push(coin);
+ coins.push(coin);
}
- return coins;
- }
+ return coins;
+ };
const transformData = (data: InputData): OutputData => {
// Filter data for each category by top 10 coins
@@ -171,8 +175,8 @@ export default function Liquidity() {
};
const formatData = () => {
- const extractedCoinKeys = extractCoins(dataLiqudity);
- setCoinKeys(extractedCoinKeys);
+ const extractedCoinKeys = extractCoins(dataLiqudity);
+ setCoinKeys(extractedCoinKeys);
const formattedData = transformData(dataLiqudity);
setFormattedData0(formattedData.median_slippage_0);
setFormattedData1000(formattedData.median_slippage_1000);
@@ -182,7 +186,7 @@ export default function Liquidity() {
const formattedUniqueCoinKeys1000 = extractUniqueCoins(formattedData.median_slippage_1000);
const formattedUniqueCoinKeys3000 = extractUniqueCoins(formattedData.median_slippage_3000);
const formattedUniqueCoinKeys10000 = extractUniqueCoins(formattedData.median_slippage_10000);
-
+
setCoinKeys0(formattedUniqueCoinKeys0);
setCoinKeys1000(formattedUniqueCoinKeys1000);
setCoinKeys3000(formattedUniqueCoinKeys3000);
@@ -213,34 +217,8 @@ export default function Liquidity() {
? coinKeys3000
: coinKeys10000;
- const coinSelectorsSort = (a: CoinSelector, b: CoinSelector) => {
- if (a.isChecked !== b.isChecked) {
- return a.isChecked ? -1 : 1;
- }
- return a.name.localeCompare(b.name);
- };
+ const coinSelectors = createCoinSelectors(coinKeys, coinsSelected, setCoinsSelected, formatData);
- const coinSelectors = coinKeys
- .map((coinKey: string) => {
- return {
- name: coinKey,
- event: () =>
- setCoinsSelected((coinsSelected) => {
- let newCoinsSelected = coinsSelected;
- if (coinsSelected.includes(coinKey)) {
- newCoinsSelected = coinsSelected.filter((e) => {
- return e !== coinKey;
- });
- } else {
- newCoinsSelected.push(coinKey);
- }
- formatData();
- return newCoinsSelected;
- }),
- isChecked: coinsSelected.includes(coinKey),
- };
- })
- .sort((a: CoinSelector, b: CoinSelector) => coinSelectorsSort(a, b));
return (
@@ -289,7 +268,7 @@ export default function Liquidity() {
type='monotone'
dataKey={`${coinName}`}
name={coinName.toString()}
- stroke={getTokenHex(coinName.toString())}
+ stroke={getTokenColor(coinName.toString())}
key={i}
dot={false}
/>
diff --git a/components/home/charts/open-interest.tsx b/components/home/charts/open-interest.tsx
index 585ad34..f00bd61 100644
--- a/components/home/charts/open-interest.tsx
+++ b/components/home/charts/open-interest.tsx
@@ -11,7 +11,7 @@ import {
import { useEffect, useState } from 'react';
import { Box, Text, useMediaQuery } from '@chakra-ui/react';
import { useRequest } from '@/hooks/useRequest';
-import ChartWrapper from '../../common/chartWrapper';
+import ChartWrapper, { CoinSelector } from '../../common/chartWrapper';
import { BRIGHT_GREEN, CHART_HEIGHT, GREEN, YAXIS_WIDTH } from '../../../constants';
import {
xAxisFormatter,
@@ -20,15 +20,18 @@ import {
tooltipFormatterCurrency,
tooltipFormatterDate,
} from '../../../helpers';
-import { getTokenHex } from '../../../constants/tokens';
+
+import { getTokenColor } from '../../../constants/tokens';
import { open_interest } from '../../../constants/api';
+import { useIsMobile } from '@/hooks/isMobile';
const REQUESTS = [open_interest];
export default function VolumeChart() {
- const [isMobile] = useMediaQuery('(max-width: 700px)');
-
+ const [isMobile] = useIsMobile();
+ const [hasSetCoinsSelected, setHasSetCoinsSelected] = useState(false);
const [coinKeys, setCoinKeys] = useState([]);
+
const [formattedData, setFormattedData] = useState([]);
const [dataOpenInterest, loadingOpenInterest, errorOpenInterest] = useRequest(
REQUESTS[0],
@@ -125,7 +128,7 @@ export default function VolumeChart() {
}, [loading]);
return (
-
+
@@ -168,7 +171,7 @@ export default function VolumeChart() {
dataKey={coinName}
dot={false}
name={coinName.toString()}
- stroke={getTokenHex(coinName.toString())}
+ stroke={getTokenColor(coinName.toString())}
key={'open-i-rate-line-' + i}
/>
);
diff --git a/components/home/charts/retail-volume.tsx b/components/home/charts/retail-volume.tsx
index ce0dc3e..69ae99f 100644
--- a/components/home/charts/retail-volume.tsx
+++ b/components/home/charts/retail-volume.tsx
@@ -12,7 +12,7 @@ import {
import { useEffect, useState } from 'react';
import { Box, Text, useMediaQuery } from '@chakra-ui/react';
import { useRequest } from '@/hooks/useRequest';
-import ChartWrapper from '../../common/chartWrapper';
+import ChartWrapper, { CoinSelector } from '../../common/chartWrapper';
import {
CHART_HEIGHT,
YAXIS_WIDTH,
@@ -26,7 +26,9 @@ import {
yaxisFormatter,
xAxisFormatter,
} from '../../../helpers';
-import { getTokenHex } from '../../../constants/tokens';
+import { createCoinSelectorsWithFormatArg } from "../../../helpers/utils";
+
+import { getTokenColor, initialTokensSelectedWithOther } from '../../../constants/tokens';
import {
cumulative_usd_volume,
daily_usd_volume,
@@ -34,6 +36,7 @@ import {
daily_usd_volume_by_crossed,
daily_usd_volume_by_user,
} from '../../../constants/api';
+import { useIsMobile } from '@/hooks/isMobile';
const REQUESTS = [
cumulative_usd_volume,
@@ -44,10 +47,12 @@ const REQUESTS = [
];
export default function RetailVolumeChart() {
- const [isMobile] = useMediaQuery('(max-width: 700px)');
+ const [isMobile] = useIsMobile();
+
const [dataMode, setDataMode] = useState<'COINS' | 'MARGIN'>('COINS');
const [formattedDataCoins, setFormattedDataCoins] = useState([]);
const [formattedDataMargin, setFormattedDataMargin] = useState([]);
+ const [coinsSelected, setCoinsSelected] = useState(initialTokensSelectedWithOther);
const [coinKeys, setCoinKeys] = useState([]);
const [dataCumulativeUsdVolume, loadingCumulativeUsdVolume, errorCumulativeUsdVolume] =
useRequest(REQUESTS[0], [], 'chart_data');
@@ -107,6 +112,7 @@ export default function RetailVolumeChart() {
type FormattedVolumeData = any[]; //{ time: string, all: number, [coin: string]: number };
const formatVolumeByCoins = (
+ CoinsSelected: string[],
dataDailyUsdVolumeByCoin: VolumeData[],
formattedCumulativeUsdVolume: { [key: string]: number },
formattedDailyVolumeByTime: { [key: string]: number }
@@ -120,25 +126,21 @@ export default function RetailVolumeChart() {
temp[data.time].all += data.daily_usd_volume;
}
- const sortAndSliceTop10 = (obj: { [coin: string]: number }) => {
- const sortedEntries = Object.entries(obj).sort(
- ([, aVolume], [, bVolume]) => bVolume - aVolume
- );
- const top10Entries = sortedEntries.slice(0, 10);
- const otherEntries = sortedEntries.slice(10);
-
+ const selectedCoinData = (obj: { [coin: string]: number }) => {
+ const selectedEntries = Object.entries(obj).filter(([coin]) => CoinsSelected.includes(coin) && coin !== "all");
+ const otherEntries = Object.entries(obj).filter(([coin]) => (!(CoinsSelected.includes(coin))) && (coin !== "all"));
const otherVolume = otherEntries.reduce((total, [, volume]) => total + volume, 0);
return {
- ...Object.fromEntries(top10Entries),
+ ...Object.fromEntries(selectedEntries),
Other: otherVolume,
};
};
const result: any[] = Object.entries(temp).map(([time, volumes]) => {
- const top10Volumes = sortAndSliceTop10(volumes);
+ const selectedVolumes = selectedCoinData(volumes);
return {
time: new Date(time),
- ...top10Volumes,
+ ...selectedVolumes,
cumulative: formattedCumulativeUsdVolume[time as any],
all: formattedDailyVolumeByTime[time as any],
unit: '$',
@@ -148,20 +150,10 @@ export default function RetailVolumeChart() {
return result;
};
- const extractUniqueCoins = (formattedVolumeData: FormattedVolumeData[]): string[] => {
+ const extractUniqueCoins = (formattedVolumeData: VolumeData[]): string[] => {
const coinSet = new Set();
for (const data of formattedVolumeData) {
- Object.keys(data).forEach((coin) => {
- if (
- coin !== 'all' &&
- coin !== 'cumulative' &&
- coin !== 'time' &&
- coin !== 'other' &&
- coin !== 'unit'
- ) {
- coinSet.add(coin);
- }
- });
+ coinSet.add(data.coin);
}
const coinsArray = Array.from(coinSet);
if (coinsArray.includes('Other')) {
@@ -209,10 +201,11 @@ export default function RetailVolumeChart() {
return result;
};
- const formatData = () => {
+ const formatData = (CoinsSelected: string[]) => {
const formattedCumulativeVolumeByTime = formatCumulativeVolumeByTime(dataCumulativeUsdVolume);
const formattedDailyVolumeByTime = formatDailyVolumeByTime(dataDailyUsdVolume);
const formattedVolumeByCoins = formatVolumeByCoins(
+ CoinsSelected,
dataDailyUsdVolumeByCoin,
formattedCumulativeVolumeByTime,
formattedDailyVolumeByTime
@@ -222,7 +215,7 @@ export default function RetailVolumeChart() {
formattedCumulativeVolumeByTime,
formattedDailyVolumeByTime
);
- setCoinKeys(extractUniqueCoins(formattedVolumeByCoins));
+ setCoinKeys(extractUniqueCoins(dataDailyUsdVolumeByCoin));
setFormattedDataCoins(formattedVolumeByCoins);
setFormattedDataMargin(formattedVolumeByCrossed);
};
@@ -244,10 +237,12 @@ export default function RetailVolumeChart() {
useEffect(() => {
if (!loading || error) {
- formatData();
+ formatData(coinsSelected);
}
}, [loading, error]);
+ const coinSelectors = createCoinSelectorsWithFormatArg(coinKeys, coinsSelected, setCoinsSelected, formatData);
+
return (
{dataMode === 'COINS' && (
<>
- {coinKeys.map((coinName, i) => {
+ {coinsSelected.map((coinName, i) => {
return (
diff --git a/components/home/charts/trader-profit.tsx b/components/home/charts/trader-profit.tsx
index 8f6c60e..11d6687 100644
--- a/components/home/charts/trader-profit.tsx
+++ b/components/home/charts/trader-profit.tsx
@@ -23,11 +23,12 @@ import {
tooltipFormatterCurrency,
tooltipFormatterDate,
} from '../../../helpers';
+import { useIsMobile } from '@/hooks/isMobile';
const REQUESTS = [cumulative_user_pnl, user_pnl];
export default function TradersProfitLossChart() {
- const [isMobile] = useMediaQuery('(max-width: 700px)');
+ const [isMobile] = useIsMobile();
const [data, setData] = useState(null);
const [dataCumulativeUserPNL, loadingCumulativeUserPNL, errorCumulativeUserPNL] = useRequest(
@@ -101,7 +102,12 @@ export default function TradersProfitLossChart() {
}, [loading, error]);
return (
-
+
diff --git a/components/home/charts/unique-users-coin.tsx b/components/home/charts/unique-users-coin.tsx
index 4ef7e44..b8f4768 100644
--- a/components/home/charts/unique-users-coin.tsx
+++ b/components/home/charts/unique-users-coin.tsx
@@ -12,7 +12,9 @@ import {
import { useEffect, useState } from 'react';
import { Box, Text, useMediaQuery } from '@chakra-ui/react';
import { useRequest } from '@/hooks/useRequest';
-import ChartWrapper from '../../common/chartWrapper';
+import { useIsMobile } from '@/hooks/isMobile';
+
+import ChartWrapper, { CoinSelector } from '../../common/chartWrapper';
import { CHART_HEIGHT, YAXIS_WIDTH, BRIGHT_GREEN } from '../../../constants';
import {
tooltipFormatter,
@@ -21,7 +23,9 @@ import {
yaxisFormatterNumber,
yaxisFormatterPercent,
} from '../../../helpers';
-import { getTokenHex } from '../../../constants/tokens';
+import { createCoinSelectorsWithFormatArg } from "../../../helpers/utils";
+
+import { getTokenColor, initialTokensSelectedWithOther } from '../../../constants/tokens';
import {
cumulative_new_users,
daily_unique_users,
@@ -68,7 +72,8 @@ type TempGroupedTradeData = {
const REQUESTS = [cumulative_new_users, daily_unique_users, daily_unique_users_by_coin];
export default function UniqueUsers() {
- const [isMobile] = useMediaQuery('(max-width: 700px)');
+ const [isMobile] = useIsMobile();
+ const [coinsSelected, setCoinsSelected] = useState(initialTokensSelectedWithOther);
const [formattedData, setFormattedData] = useState([]);
const [coinKeys, setCoinKeys] = useState([]);
@@ -91,6 +96,7 @@ export default function UniqueUsers() {
const error = errorCumulativeNewUsers || errorDailyUniqueUsers || errorDailyUniqueUsersByCoin;
const formatTradesByCoinAndTime = (
+ CoinsSelected: string[],
dataDailyUniqueUsersByCoin: DailyUniqueUsersByCoin[],
uniqueUserTradeData: UniqueUserTradeData[],
dataCumulativeNewUsers: CumulativeNewUsersData[]
@@ -123,15 +129,12 @@ export default function UniqueUsers() {
}
);
- const sortAndSliceTop10 = (obj: { [coin: string]: number }) => {
- const sortedEntries = Object.entries(obj).sort(
- ([, aVolume], [, bVolume]) => bVolume - aVolume
- );
- const top10Entries = sortedEntries.slice(0, 10);
- const otherEntries = sortedEntries.slice(10);
+ const selectedCoinData = (obj: { [coin: string]: number }) => {
+ const selectedEntries = Object.entries(obj).filter(([coin]) => CoinsSelected.includes(coin) || coin==="all");
+ const otherEntries = Object.entries(obj).filter(([coin]) => (!(CoinsSelected.includes(coin))) && (coin !== "all"));
const otherVolume = otherEntries.reduce((total, [, volume]) => total + volume, 0);
return {
- ...Object.fromEntries(top10Entries),
+ ...Object.fromEntries(selectedEntries),
Other: otherVolume,
};
};
@@ -139,63 +142,50 @@ export default function UniqueUsers() {
return Object.values(temp).map(({ time, coins, ...rest }) => {
return {
time: new Date(time),
- ...sortAndSliceTop10(coins),
+ ...selectedCoinData(coins),
...rest,
unit: '%',
};
});
};
- const extractUniqueCoins = (formattedVolumeData: GroupedTradeData[]): string[] => {
+ const extractUniqueCoins = (CoinData: any): string[] => {
const coinSet = new Set();
- for (const data of formattedVolumeData) {
- Object.keys(data).forEach((coin) => {
- if (
- coin !== 'all' &&
- coin !== 'cumulative' &&
- coin !== 'time' &&
- coin !== 'other' &&
- coin !== 'unit' &&
- coin !== 'daily_unique_users' &&
- coin !== 'cumulative_unique_users' &&
- !coin.includes('daily_unique_users')
- ) {
- coinSet.add(coin);
- }
- });
+ for (const data of CoinData) {
+ coinSet.add(data.coin);
}
const coinsArray = Array.from(coinSet);
- if (coinsArray.includes('Other')) {
- const index = coinsArray.indexOf('Other');
- coinsArray.splice(index, 1);
- coinsArray.push('Other');
- }
return coinsArray;
};
- const formatData = () => {
+ const formatData = (CoinsSelector: string[]) => {
const formattedData = formatTradesByCoinAndTime(
+ CoinsSelector,
dataDailyUniqueUsersByCoin,
dataDailyUniqueUsers,
dataCumulativeNewUsers
);
- const formattedUniqueCoinKeys = extractUniqueCoins(formattedData);
+ const formattedUniqueCoinKeys = extractUniqueCoins(dataDailyUniqueUsersByCoin);
setFormattedData(formattedData);
setCoinKeys(formattedUniqueCoinKeys);
};
useEffect(() => {
if (!loading && !error) {
- formatData();
+ formatData(coinsSelected);
}
}, [loading]);
+ const coinSelectors = createCoinSelectorsWithFormatArg(coinKeys, coinsSelected, setCoinsSelected, formatData);
+
return (
@@ -239,7 +229,7 @@ export default function UniqueUsers() {
}}
/>
- {coinKeys.map((coinName, i) => {
+ {coinsSelected.map((coinName, i) => {
return (
diff --git a/components/home/charts/volume-num-trades.tsx b/components/home/charts/volume-num-trades.tsx
index 3f76a84..28e990b 100644
--- a/components/home/charts/volume-num-trades.tsx
+++ b/components/home/charts/volume-num-trades.tsx
@@ -13,7 +13,9 @@ import {
import { Box, Text, useMediaQuery } from '@chakra-ui/react';
import { useEffect, useState } from 'react';
import { useRequest } from '@/hooks/useRequest';
-import ChartWrapper from '../../common/chartWrapper';
+import { useIsMobile } from '@/hooks/isMobile';
+
+import ChartWrapper, { CoinSelector } from '../../common/chartWrapper';
import {
CHART_HEIGHT,
YAXIS_WIDTH,
@@ -27,7 +29,9 @@ import {
yaxisFormatterNumber,
xAxisFormatter,
} from '../../../helpers';
-import { getTokenHex } from '../../../constants/tokens';
+import { createCoinSelectorsWithFormatArg } from "../../../helpers/utils";
+
+import { getTokenColor, initialTokensSelectedWithOther } from '../../../constants/tokens';
import {
cumulative_trades,
daily_trades,
@@ -45,7 +49,8 @@ const REQUESTS = [
];
export default function VolumeChart() {
- const [isMobile] = useMediaQuery('(max-width: 700px)');
+ const [isMobile] = useIsMobile();
+ const [coinsSelected, setCoinsSelected] = useState(initialTokensSelectedWithOther);
const [dataMode, setDataMode] = useState<'COINS' | 'MARGIN' | 'USER'>('COINS');
const [formattedDataCoins, setFormattedDataCoins] = useState([]);
@@ -108,6 +113,7 @@ export default function VolumeChart() {
type FormattedCoinTradesData = any[]; //{ time: string, all: number, [coin: string]: number };
const formatDailyTradesByCoins = (
+ CoinsSelected: string[],
dataDailyTradesByCoin: { coin: string; daily_trades: number; time: string }[],
formattedCumulativeTradesByTime: { [key: string]: number }
): FormattedCoinTradesData[] => {
@@ -120,22 +126,18 @@ export default function VolumeChart() {
temp[data.time].all += data.daily_trades;
}
- const sortAndSliceTop10 = (obj: { [coin: string]: number }) => {
- const sortedEntries = Object.entries(obj).sort(
- ([, aVolume], [, bVolume]) => bVolume - aVolume
- );
- const top10Entries = sortedEntries.slice(0, 10);
- const otherEntries = sortedEntries.slice(10);
-
+ const selectedCoinData = (obj: { [coin: string]: number }) => {
+ const selectedEntries = Object.entries(obj).filter(([coin]) => CoinsSelected.includes(coin) || coin==="all");
+ const otherEntries = Object.entries(obj).filter(([coin]) => (!(CoinsSelected.includes(coin))) && (coin !== "all"));
const otherVolume = otherEntries.reduce((total, [, volume]) => total + volume, 0);
return {
- ...Object.fromEntries(top10Entries),
+ ...Object.fromEntries(selectedEntries),
Other: otherVolume,
};
};
const result: any[] = Object.entries(temp).map(([time, volumes]) => {
- const top10Volumes = sortAndSliceTop10(volumes);
+ const top10Volumes = selectedCoinData(volumes);
return {
time: new Date(time),
...top10Volumes,
@@ -146,21 +148,12 @@ export default function VolumeChart() {
return result;
};
- const extractUniqueCoins = (formattedCoinTradesData: FormattedCoinTradesData[]): string[] => {
+ const extractUniqueCoins = (CoinData: any): string[] => {
const coinSet = new Set();
- for (const data of formattedCoinTradesData) {
- Object.keys(data).forEach((coin) => {
- if (coin !== 'all' && coin !== 'cumulative' && coin !== 'time' && coin !== 'unit') {
- coinSet.add(coin);
- }
- });
+ for (const data of CoinData) {
+ coinSet.add(data.coin);
}
const coinsArray = Array.from(coinSet);
- if (coinsArray.includes('Other')) {
- const index = coinsArray.indexOf('Other');
- coinsArray.splice(index, 1);
- coinsArray.push('Other');
- }
return coinsArray;
};
@@ -204,9 +197,10 @@ export default function VolumeChart() {
return Object.values(groupedByTime);
};
- const formatData = () => {
+ const formatData = (CoinsSelected: string[]) => {
const formattedCumulativeTradesByTime = formatTradesByTime(dataCumulativeTrades);
const formattedTradesByCoins = formatDailyTradesByCoins(
+ CoinsSelected,
dataDailyTradesByCoin,
formattedCumulativeTradesByTime
);
@@ -215,7 +209,7 @@ export default function VolumeChart() {
formattedCumulativeTradesByTime
);
setMaxAllValueUser(maxAllValueUser);
- setCoinKeys(extractUniqueCoins(formattedTradesByCoins));
+ setCoinKeys(extractUniqueCoins(dataDailyTradesByCoin));
setFormattedDataCoins(formattedTradesByCoins);
setFormattedDataMarin(formattedTradesByMargin);
};
@@ -237,10 +231,13 @@ export default function VolumeChart() {
useEffect(() => {
if (!loading && !error) {
- formatData();
+ formatData(coinsSelected);
}
}, [loading, dataMode]);
+
+ const coinSelectors = createCoinSelectorsWithFormatArg(coinKeys, coinsSelected, setCoinsSelected, formatData);
+
return (
- {coinKeys.map((coinName, i) => {
+ {coinsSelected.map((coinName, i) => {
return (
diff --git a/components/home/charts/volume-total.tsx b/components/home/charts/volume-total.tsx
index ad286c2..52dd4b0 100644
--- a/components/home/charts/volume-total.tsx
+++ b/components/home/charts/volume-total.tsx
@@ -11,8 +11,10 @@ import {
} from 'recharts';
import { useEffect, useState } from 'react';
import { useRequest } from '@/hooks/useRequest';
+import { useIsMobile } from '@/hooks/isMobile';
+
import { Box, Text, useMediaQuery } from '@chakra-ui/react';
-import ChartWrapper from '../../common/chartWrapper';
+import ChartWrapper, { CoinSelector } from '../../common/chartWrapper';
import { BRIGHT_GREEN, CHART_HEIGHT, YAXIS_WIDTH } from '../../../constants';
import {
yaxisFormatter,
@@ -20,14 +22,17 @@ import {
tooltipFormatterCurrency,
tooltipLabelFormatter,
} from '../../../helpers';
+import { createCoinSelectorsWithFormatArg } from "../../../helpers/utils";
+
import { total_volume } from '../../../constants/api';
-import { getTokenHex } from '@/constants/tokens';
+import { getTokenColor, initialTokensSelectedWithOther } from '@/constants/tokens';
const REQUESTS = [total_volume];
export default function TotalVolumeChart() {
- const [isMobile] = useMediaQuery('(max-width: 700px)');
+ const [isMobile] = useIsMobile();
const [formattedData, setFormattedData] = useState([]);
+ const [coinsSelected, setCoinsSelected] = useState(initialTokensSelectedWithOther);
const [coins, setCoins] = useState([]);
const [dataTotalVolume, loading, error] = useRequest(REQUESTS[0], [], 'chart_data');
@@ -46,9 +51,9 @@ export default function TotalVolumeChart() {
Other: number;
}
- const makeFormattedData = (dataTotalVolume: TotalVolume[]): [MergedData[], string[]] => {
+ const makeFormattedData = (CoinsSelected: string[], dataTotalVolume: TotalVolume[]): [MergedData[], string[]] => {
const map = new Map();
- const uniqueTopCoins = new Set();
+ const uniqueCoins = new Set();
let cumulative = 0;
dataTotalVolume.forEach((item: TotalVolume) => {
@@ -78,43 +83,40 @@ export default function TotalVolumeChart() {
key !== 'total' &&
key !== 'cumulative' &&
key !== 'other' &&
- key !== 'unit'
+ key !== 'unit' &&
+ key !== 'Other'
);
- const sortedCoinEntries = coinEntries.sort(
- (a, b) => Math.abs(Number(b[1])) - Math.abs(Number(a[1]))
- );
- const topCoins = sortedCoinEntries.slice(0, 10).map(([coin]) => coin);
- const otherCoins = sortedCoinEntries.slice(10);
+ const otherCoins = coinEntries.filter(([coin]) => (!(CoinsSelected.includes(coin))) && (coin !== "all"));
- topCoins.forEach((coin) => uniqueTopCoins.add(coin));
+ coinEntries.forEach(([coin]) => uniqueCoins.add(coin));
let otherTotal = 0;
- otherCoins.forEach(([coin, value]) => {
+ otherCoins.forEach(([_, value]) => {
otherTotal += value;
- delete entry[coin];
});
entry.Other = otherTotal;
});
const result = Array.from(map.values());
- uniqueTopCoins.add('Other');
- return [result, Array.from(uniqueTopCoins)];
+ return [result, Array.from(uniqueCoins)];
};
- const formatData = () => {
- const [newFormattedData, coins] = makeFormattedData(dataTotalVolume);
+ const formatData = (CoinsSelected: string[]) => {
+ const [newFormattedData, coins] = makeFormattedData(CoinsSelected, dataTotalVolume);
setCoins(coins);
setFormattedData(newFormattedData);
};
useEffect(() => {
if (!loading && !error) {
- formatData();
+ formatData(coinsSelected);
}
}, [loading, error]);
+ const coinSelectors = createCoinSelectorsWithFormatArg(coins, coinsSelected, setCoinsSelected, formatData);
+
return (
-
+
@@ -142,7 +144,7 @@ export default function TotalVolumeChart() {
tick={{ fill: '#f9f9f9', fontSize: isMobile ? 14 : 15 }}
/>
- {coins.map((coin, i) => {
+ {coinsSelected.map((coin, i) => {
return (
diff --git a/constants/tokens.ts b/constants/tokens.ts
index d42bcc4..8da4f1a 100644
--- a/constants/tokens.ts
+++ b/constants/tokens.ts
@@ -1,37 +1,18 @@
-const TOKEN_COLORS: any = {
- BNB: '#ebc509',
- BTC: '#F2A900',
- DOGE: '#cb9800',
- ETH: '#8A94B1',
- INJ: '#0386FA',
- KPEPE: '#509844',
- MATIC: '#8C35D5',
- Other: '#BBBAC6',
- SOL: '#C867F0',
- AVAX: '#e74242',
- LTC: '#CCCCCC',
- ARB: '#FCA100',
- LINK: '#81D2FD',
- APE: '#4087BE',
- ATOM: '#FCA100',
- CFX: '#F3654E',
- CRV: '#850087',
- DYDX: '#BE586C',
- FTM: '#568EC0',
- GMX: '#59C782',
- LDO: '#DB6ED7',
- OP: '#7F0182',
- RNDR: '#FFA300',
- SNX: '#498548',
- STX: '#578374',
- SUI: '#6A807A',
-};
+import * as CryptoJS from 'crypto-js';
-export const getTokenHex = (token: string) => {
- const symbol = token.toUpperCase();
- if (TOKEN_COLORS[symbol]) {
- return TOKEN_COLORS[symbol];
- } else {
- return 'pink';
- }
-};
+
+export const initialTokensSelected = ['ETH', 'BTC', 'ARB', 'APE', 'ATOM', 'AVAX', 'BNB', 'COMP', 'CRV', 'DOGE'];
+export const initialTokensSelectedWithOther = ['ETH', 'BTC', 'ARB', 'APE', 'ATOM', 'AVAX', 'BNB', 'COMP', 'CRV', 'DOGE','Other'];
+
+export function getTokenColor(inputString: string): string {
+ if (inputString == "Other") {
+ return "pink";
+ }
+ // Use the CryptoJS library to get the MD5 hash of the string
+ let hash = CryptoJS.MD5("col"+inputString);
+
+ // Convert the hash into a hex string
+ let color = hash.toString(CryptoJS.enc.Hex).substr(0, 6);
+
+ return "#" + color;
+}
diff --git a/helpers/utils.ts b/helpers/utils.ts
new file mode 100644
index 0000000..5228178
--- /dev/null
+++ b/helpers/utils.ts
@@ -0,0 +1,52 @@
+import { SetStateAction } from 'react';
+import { CoinSelector } from '../components/common/chartWrapper';
+
+const coinSelectorsSort = (a: CoinSelector, b: CoinSelector) => {
+ if (a.isChecked !== b.isChecked) {
+ return a.isChecked ? -1 : 1;
+ }
+ return a.name.localeCompare(b.name);
+ };
+
+
+export const createCoinSelectors = (coinKeys: string[], coinsSelected: string[], setCoinsSelected: (arg: string[]) => any, formatData: () => any) => {
+ return coinKeys.map((coinKey: string) => {
+ return {
+ name: coinKey,
+ event: () => {
+ let newCoinsSelected = coinsSelected;
+ if (coinsSelected.includes(coinKey)) {
+ newCoinsSelected = coinsSelected.filter((e) => {
+ return e !== coinKey;
+ });
+ } else {
+ newCoinsSelected.push(coinKey);
+ }
+ formatData();
+ setCoinsSelected(newCoinsSelected);
+ },
+ isChecked: coinsSelected.includes(coinKey),
+ };
+ }).sort((a: CoinSelector, b: CoinSelector) => coinSelectorsSort(a, b));
+}
+
+export const createCoinSelectorsWithFormatArg = (coinKeys: string[], coinsSelected: string[], setCoinsSelected: (arg: string[]) => any, formatData: (arg: string[]) => any) => {
+ return coinKeys.map((coinKey: string) => {
+ return {
+ name: coinKey,
+ event: () => {
+ let newCoinsSelected = coinsSelected;
+ if (coinsSelected.includes(coinKey)) {
+ newCoinsSelected = coinsSelected.filter((e) => {
+ return e !== coinKey;
+ });
+ } else {
+ newCoinsSelected.push(coinKey);
+ }
+ formatData(newCoinsSelected);
+ setCoinsSelected(newCoinsSelected);
+ },
+ isChecked: coinsSelected.includes(coinKey),
+ };
+ }).sort((a: CoinSelector, b: CoinSelector) => coinSelectorsSort(a, b));
+}
\ No newline at end of file
diff --git a/hooks/isMobile.ts b/hooks/isMobile.ts
new file mode 100644
index 0000000..f9cdffa
--- /dev/null
+++ b/hooks/isMobile.ts
@@ -0,0 +1,13 @@
+import { useEffect, useState } from 'react';
+
+export function useIsMobile() {
+ if (typeof window === "undefined") {
+ return [false];
+ }
+ let [isMobile, setIsMobile] = useState(window.innerWidth < 700);
+ useEffect(() => {
+ setIsMobile(window.innerWidth < 700);
+ }, [window.innerWidth]);
+
+ return [isMobile];
+}
diff --git a/package-lock.json b/package-lock.json
index ed29c88..48aec2d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,11 +14,13 @@
"@emotion/react": "^11.11.0",
"@emotion/styled": "^11.11.0",
"@svgr/webpack": "^8.0.1",
+ "@types/crypto-js": "^4.1.1",
"@types/node": "20.2.5",
"@types/react": "18.2.7",
"@types/react-dom": "18.2.4",
"@types/strftime": "^0.9.4",
"axios": "^1.4.0",
+ "crypto-js": "^4.1.1",
"eslint": "8.41.0",
"eslint-config-next": "13.4.4",
"ethers": "^5.7.2",
@@ -4400,6 +4402,11 @@
"integrity": "sha512-TnhDAntcJthcCMrR3OAKAUjgHyQgoms1yaBJepGv+BtXi8PLf8aX2L/NMCfofRTpVqW0bLklpGTsuqmUSCR2Uw==",
"dev": true
},
+ "node_modules/@types/crypto-js": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.1.1.tgz",
+ "integrity": "sha512-BG7fQKZ689HIoc5h+6D2Dgq1fABRa0RbBWKBd9SP/MVRVXROflpm5fhwyATX5duFmbStzyzyycPB8qUYKDH3NA=="
+ },
"node_modules/@types/d3-array": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.0.5.tgz",
@@ -5246,6 +5253,11 @@
"node": ">= 8"
}
},
+ "node_modules/crypto-js": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz",
+ "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw=="
+ },
"node_modules/css-box-model": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz",
@@ -12389,6 +12401,11 @@
"integrity": "sha512-TnhDAntcJthcCMrR3OAKAUjgHyQgoms1yaBJepGv+BtXi8PLf8aX2L/NMCfofRTpVqW0bLklpGTsuqmUSCR2Uw==",
"dev": true
},
+ "@types/crypto-js": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.1.1.tgz",
+ "integrity": "sha512-BG7fQKZ689HIoc5h+6D2Dgq1fABRa0RbBWKBd9SP/MVRVXROflpm5fhwyATX5duFmbStzyzyycPB8qUYKDH3NA=="
+ },
"@types/d3-array": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.0.5.tgz",
@@ -13028,6 +13045,11 @@
"which": "^2.0.1"
}
},
+ "crypto-js": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz",
+ "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw=="
+ },
"css-box-model": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz",
diff --git a/package.json b/package.json
index e056236..5f9ddb2 100644
--- a/package.json
+++ b/package.json
@@ -63,11 +63,13 @@
"@emotion/react": "^11.11.0",
"@emotion/styled": "^11.11.0",
"@svgr/webpack": "^8.0.1",
+ "@types/crypto-js": "^4.1.1",
"@types/node": "20.2.5",
"@types/react": "18.2.7",
"@types/react-dom": "18.2.4",
"@types/strftime": "^0.9.4",
"axios": "^1.4.0",
+ "crypto-js": "^4.1.1",
"eslint": "8.41.0",
"eslint-config-next": "13.4.4",
"ethers": "^5.7.2",