Skip to content

Commit c088da8

Browse files
Tburmzhyd1997platschi
authored
add stats page (Kwenta#1485)
* feat: stats page. + feat: setup stats route. * fix: set stats page as internal page. - reverted: stats page route. * feat: initialized stats page. * feat: mobile stats page title. * build: added 'echarts' and 'next-transpile-modules' deps. * build: refactored next config file. - build: disabled optimizedImages temporarily. * feat: customized echarts to generate initial bar charts. * feat: added i18n stats titles. + feat: more responsive stats page. + feat: more stats charts. + feat: added subtitle and styles. + feat: added additional 'title', 'subtext', 'subtextStyle' and 'legend' parameters. * refactor: enhanced bar chart type definitions. + feat: added chart title and legend style. - fix: removed 'normal' fontStyle because it's default value in echarts. * feat: added 'xAxisData' and 'richTextXAxisLabel' parameters. * feat: init TimeRangeSwitcher component. * feat: integrated TimeRangeSwitcher with ChartsWrapper. + fix: Trades and Traders has no width in PC. * chore: removed package-lock.json 'dev' true. * chore: updated package-lock.json * fix: merged next.config.js * refactor: passed all charts parameters into 'option'. * refactor: echarts chaining. * fix: more responsive stats page. + fix: supported tvl chart horizental scrollable. * feat: added line chart. fix: removed redundant border-radius of range switcher button. fix: expanded scrollable wrapper width to 100% in large screen. * chore: fixed lint issue. * build: extended next config file to enable 'optimizedImages' plugin. * fix: fetch volume, trades and open interest data from api. refactor: code splitting. * fix: typo. * fix: fetched traders data from api. * fix: return in advance in useEffect hook. * feat: active time swticher UI. * fix: show 24h data by default. * fix: imported assets from config instead of hard-coded. feat: basic time switch utils. * build: removed extend import from next-compose-plugins. * simplify stats page styles * remove unused style * fix styling * fix containers * remove title * add a stats context * make chart hook * fix fonts import * apply default styling * add context to charts * styling and aggregations * clean up open interest labels * add timeframe switcher component * combine aggregations * add timeframe filter * chart styling and loading state * update routing * add padding * mobile styling * simplify routing * fix error message * simplify cumulative calc * fix routing * fix package.json conflicts * fix package-lock conflict Co-authored-by: Yadong Zhang <[email protected]> Co-authored-by: platschi <[email protected]>
1 parent 0b7c928 commit c088da8

37 files changed

+1251
-173
lines changed

Diff for: components/Loader/Loader.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,8 @@ Loader.defaultProps = {
2626
inline: false,
2727
};
2828

29+
export const MiniLoader = () => {
30+
return <Loader inline height="11px" width="11px" style={{ marginLeft: '10px' }} />;
31+
};
32+
2933
export default Loader;

Diff for: components/Loader/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export { default } from './Loader';
1+
export { default, MiniLoader } from './Loader';

Diff for: components/Webp/Webp.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import * as React from 'react';
1+
import React from 'react';
22
import { DefaultTheme, StyledComponent } from 'styled-components';
33

44
type WebpProps = {

Diff for: constants/routes.ts

+6-7
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,12 @@ export const formatUrl = (route: string, params: Record<string, string>) => {
1313
export const ROUTES = {
1414
Home: {
1515
Root: '/',
16-
Overview: normalizeRoute('/dashboard', 'overview', 'tab'),
17-
History: normalizeRoute('/dashboard', 'history', 'tab'),
18-
Markets: normalizeRoute('/dashboard', 'markets', 'tab'),
1916
},
2017
Dashboard: {
2118
Home: '/dashboard',
22-
Convert: normalizeRoute('/dashboard', 'convert', 'tab'),
23-
SynthBalances: normalizeRoute('/dashboard', 'synth-balances', 'tab'),
24-
Transactions: normalizeRoute('/dashboard', 'transactions', 'tab'),
25-
Deprecated: normalizeRoute('/dashboard', 'deprecated', 'tab'),
19+
Overview: normalizeRoute('/dashboard', 'overview', 'tab'),
20+
History: normalizeRoute('/dashboard', 'history', 'tab'),
21+
Markets: normalizeRoute('/dashboard', 'markets', 'tab'),
2622
},
2723
Exchange: {
2824
Home: '/exchange',
@@ -47,6 +43,9 @@ export const ROUTES = {
4743
Transfers: (asset: FuturesMarketAsset, accountType: FuturesAccountType) =>
4844
formatUrl('/market', { asset, accountType, tab: 'transfers' }),
4945
},
46+
Stats: {
47+
Home: '/stats',
48+
},
5049
Leaderboard: {
5150
Home: '/leaderboard',
5251
Trader: (trader: string) => `/leaderboard/?trader=${trader}`,

Diff for: contexts/StatsContext.tsx

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import React from 'react';
2+
3+
import useStatsData from 'hooks/useStatsData';
4+
5+
export const StatsContext = React.createContext<ReturnType<typeof useStatsData> | undefined>(
6+
undefined
7+
);
8+
9+
export const useStatsContext = () => {
10+
const statsContext = React.useContext(StatsContext);
11+
12+
if (!statsContext) throw new Error('Stats context not defined yet.');
13+
14+
return statsContext;
15+
};

Diff for: hooks/useExchange.ts

+2-7
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,10 @@ import { normalizeGasLimit, getTransactionPrice } from 'utils/network';
6565

6666
import useIsL2 from './useIsL2';
6767

68-
type ExchangeCardProps = {
69-
showNoSynthsCard?: boolean;
70-
};
71-
7268
type ExchangeModal = 'settle' | 'confirm' | 'approve' | 'redeem' | 'base-select' | 'quote-select';
7369
export type SwapRatio = 25 | 50 | 75 | 100;
7470

75-
const useExchange = ({ showNoSynthsCard = false }: ExchangeCardProps) => {
71+
const useExchange = () => {
7672
const { t } = useTranslation();
7773
const { monitorTransaction } = TransactionNotifier.useContainer();
7874

@@ -415,7 +411,7 @@ const useExchange = ({ showNoSynthsCard = false }: ExchangeCardProps) => {
415411
oneInchQuoteQuery,
416412
]);
417413

418-
const noSynths = synthsWalletBalancesQuery.data?.balances.length === 0;
414+
const noSynths = true;
419415

420416
const routeToMarketPair = useCallback(
421417
(baseCurrencyKey: string, quoteCurrencyKey: string) =>
@@ -1029,7 +1025,6 @@ const useExchange = ({ showNoSynthsCard = false }: ExchangeCardProps) => {
10291025
exchangeFeeRate,
10301026
oneInchQuoteQuery,
10311027
numEntries,
1032-
showNoSynthsCard,
10331028
quoteCurrencyBalance,
10341029
quotePriceRate,
10351030
baseFeeRate,

Diff for: hooks/useStatsData.ts

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { useMemo } from 'react';
2+
import { useRecoilState, useRecoilValue } from 'recoil';
3+
4+
import useGetFuturesMarkets from 'queries/futures/useGetFuturesMarkets';
5+
import { useGetFuturesTradersStats } from 'queries/futures/useGetFuturesTradersStats';
6+
import { useGetStatsVolumes } from 'queries/futures/useGetStatsVolumes';
7+
import { futuresMarketsState } from 'store/futures';
8+
import { selectedTimeframeState } from 'store/stats';
9+
10+
export type StatsTimeframe = '1M' | '1Y' | 'MAX';
11+
12+
const useStatsData = () => {
13+
const [selectedTimeframe, setSelectedTimeframe] = useRecoilState(selectedTimeframeState);
14+
const futuresMarkets = useRecoilValue(futuresMarketsState);
15+
16+
// run queries
17+
useGetFuturesMarkets();
18+
const { data: volumeData, isLoading: volumeIsLoading } = useGetStatsVolumes();
19+
const { data: tradersData, isLoading: tradersIsLoading } = useGetFuturesTradersStats();
20+
21+
const openInterestData = useMemo(() => {
22+
return futuresMarkets.map(({ asset, marketSize, price }) => {
23+
return {
24+
asset,
25+
openInterest: marketSize.mul(price).toNumber(),
26+
};
27+
});
28+
}, [futuresMarkets]);
29+
30+
return {
31+
volumeData,
32+
volumeIsLoading,
33+
tradersData,
34+
tradersIsLoading,
35+
openInterestData,
36+
selectedTimeframe,
37+
setSelectedTimeframe,
38+
};
39+
};
40+
41+
export default useStatsData;

Diff for: next.config.js

+74-69
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,79 @@ function interceptStdout(text) {
2020
// Intercept in dev and prod
2121
intercept(interceptStdout);
2222

23-
const withPlugins = require('next-compose-plugins');
23+
const { withPlugins } = require('next-compose-plugins');
2424
const optimizedImages = require('next-optimized-images');
25+
const transpile = require('next-transpile-modules');
26+
const withTM = [transpile(['echarts', 'zrender'])];
27+
28+
const baseConfig = {
29+
env: {
30+
GIT_HASH_ID: gitRevision,
31+
},
32+
images: {
33+
disableStaticImages: true,
34+
},
35+
webpack: (config, options) => {
36+
config.resolve.mainFields = ['module', 'browser', 'main'];
37+
38+
config.module.rules.push(
39+
{
40+
test: /\.svg$/,
41+
loader: '@svgr/webpack',
42+
options: {
43+
prettier: false,
44+
svgo: true,
45+
svgoConfig: {
46+
plugins: [
47+
{
48+
name: 'preset-default',
49+
params: {
50+
overrides: {
51+
removeViewBox: false,
52+
cleanupIDs: false,
53+
},
54+
},
55+
},
56+
],
57+
},
58+
titleProp: true,
59+
},
60+
},
61+
{
62+
test: /\.png/,
63+
type: 'asset/resource',
64+
}
65+
);
66+
67+
return config;
68+
},
69+
trailingSlash: true,
70+
compiler: {
71+
// ssr and displayName are configured by default
72+
styledComponents: true,
73+
},
74+
experimental: { images: { unoptimized: true } },
75+
async redirects() {
76+
return [
77+
{
78+
source: '/dashboard/overview',
79+
destination: '/dashboard',
80+
permanent: true,
81+
},
82+
{
83+
source: '/market/:key',
84+
destination: '/market/?asset=:key',
85+
permanent: true,
86+
},
87+
{
88+
source: '/exchange/:base-:quote',
89+
destination: '/exchange/?quote=:quote&base=:base',
90+
permanent: true,
91+
},
92+
];
93+
},
94+
productionBrowserSourceMaps: true,
95+
};
2596

2697
module.exports = withPlugins([
2798
[
@@ -33,72 +104,6 @@ module.exports = withPlugins([
33104
imageOutputPath: '/static/images',
34105
},
35106
],
36-
{
37-
env: {
38-
GIT_HASH_ID: gitRevision,
39-
},
40-
images: {
41-
disableStaticImages: true,
42-
},
43-
webpack: (config, options) => {
44-
config.resolve.mainFields = ['module', 'browser', 'main'];
45-
46-
config.module.rules.push(
47-
{
48-
test: /\.svg$/,
49-
loader: '@svgr/webpack',
50-
options: {
51-
prettier: false,
52-
svgo: true,
53-
svgoConfig: {
54-
plugins: [
55-
{
56-
name: 'preset-default',
57-
params: {
58-
overrides: {
59-
removeViewBox: false,
60-
cleanupIDs: false,
61-
},
62-
},
63-
},
64-
],
65-
},
66-
titleProp: true,
67-
},
68-
},
69-
{
70-
test: /\.png/,
71-
type: 'asset/resource',
72-
}
73-
);
74-
75-
return config;
76-
},
77-
trailingSlash: true,
78-
compiler: {
79-
// ssr and displayName are configured by default
80-
styledComponents: true,
81-
},
82-
experimental: { images: { unoptimized: true } },
83-
async redirects() {
84-
return [
85-
{
86-
source: '/dashboard/overview',
87-
destination: '/dashboard',
88-
permanent: true,
89-
},
90-
{
91-
source: '/market/:key',
92-
destination: '/market/?asset=:key',
93-
permanent: true,
94-
},
95-
{
96-
source: '/exchange/:base-:quote',
97-
destination: '/exchange/?quote=:quote&base=:base',
98-
permanent: true,
99-
},
100-
];
101-
},
102-
productionBrowserSourceMaps: true,
103-
},
107+
baseConfig,
108+
...withTM,
104109
]);

0 commit comments

Comments
 (0)