From 59916d04a575e92d9d9f1c409f56e650a918155f Mon Sep 17 00:00:00 2001 From: yadudevpro Date: Fri, 8 Dec 2023 12:35:54 +0530 Subject: [PATCH] feat(bos-components): add charts and statistics --- apps/app/src/data/bos-components.ts | 2 + apps/app/src/pages/charts/addresses.tsx | 12 + apps/app/src/pages/charts/blocks.tsx | 10 + apps/app/src/pages/charts/index.tsx | 10 + apps/app/src/pages/charts/market-cap.tsx | 12 + apps/app/src/pages/charts/near-price.tsx | 12 + apps/app/src/pages/charts/near-supply.tsx | 12 + apps/app/src/pages/charts/txn-fee.tsx | 10 + apps/app/src/pages/charts/txn-volume.tsx | 12 + apps/app/src/pages/charts/txns.tsx | 10 + apps/bos-components/src/components/Charts.tsx | 487 ++++++++++++++++++ 11 files changed, 589 insertions(+) create mode 100644 apps/app/src/pages/charts/addresses.tsx create mode 100644 apps/app/src/pages/charts/blocks.tsx create mode 100644 apps/app/src/pages/charts/index.tsx create mode 100644 apps/app/src/pages/charts/market-cap.tsx create mode 100644 apps/app/src/pages/charts/near-price.tsx create mode 100644 apps/app/src/pages/charts/near-supply.tsx create mode 100644 apps/app/src/pages/charts/txn-fee.tsx create mode 100644 apps/app/src/pages/charts/txn-volume.tsx create mode 100644 apps/app/src/pages/charts/txns.tsx create mode 100644 apps/bos-components/src/components/Charts.tsx diff --git a/apps/app/src/data/bos-components.ts b/apps/app/src/data/bos-components.ts index b065bee3b..220e96b1d 100644 --- a/apps/app/src/data/bos-components.ts +++ b/apps/app/src/data/bos-components.ts @@ -9,6 +9,7 @@ type NetworkComponents = { latestTransactions: string; transactionOverview: string; sponsoredText: string; + charts: string; }; const ComponentUrl = { @@ -20,6 +21,7 @@ const ComponentUrl = { latestTransactions: `${process.env.NEXT_PUBLIC_ACCOUNT_ID}/widget/bos-components.components.Transactions.Latest`, transactionOverview: `${process.env.NEXT_PUBLIC_ACCOUNT_ID}/widget/bos-components.components.Transactions.Overview`, sponsoredText: `${process.env.NEXT_PUBLIC_ACCOUNT_ID}/widget/bos-components.components.Shared.SponsoredText`, + charts: `${process.env.NEXT_PUBLIC_ACCOUNT_ID}/widget/bos-components.components.Charts`, }; export const componentsByNetworkId: Record< diff --git a/apps/app/src/pages/charts/addresses.tsx b/apps/app/src/pages/charts/addresses.tsx new file mode 100644 index 000000000..12fe06d4e --- /dev/null +++ b/apps/app/src/pages/charts/addresses.tsx @@ -0,0 +1,12 @@ +import { VmComponent } from '@/components/vm/VmComponent'; +import { useBosComponents } from '@/hooks/useBosComponents'; + +const AddressesChart = () => { + const components = useBosComponents(); + + return ( + + ); +}; + +export default AddressesChart; diff --git a/apps/app/src/pages/charts/blocks.tsx b/apps/app/src/pages/charts/blocks.tsx new file mode 100644 index 000000000..f5f895d79 --- /dev/null +++ b/apps/app/src/pages/charts/blocks.tsx @@ -0,0 +1,10 @@ +import { VmComponent } from '@/components/vm/VmComponent'; +import { useBosComponents } from '@/hooks/useBosComponents'; + +const BlocksChart = () => { + const components = useBosComponents(); + + return ; +}; + +export default BlocksChart; diff --git a/apps/app/src/pages/charts/index.tsx b/apps/app/src/pages/charts/index.tsx new file mode 100644 index 000000000..e3a67369f --- /dev/null +++ b/apps/app/src/pages/charts/index.tsx @@ -0,0 +1,10 @@ +import { VmComponent } from '@/components/vm/VmComponent'; +import { useBosComponents } from '@/hooks/useBosComponents'; + +const Charts = () => { + const components = useBosComponents(); + + return ; +}; + +export default Charts; diff --git a/apps/app/src/pages/charts/market-cap.tsx b/apps/app/src/pages/charts/market-cap.tsx new file mode 100644 index 000000000..cefcaa6dd --- /dev/null +++ b/apps/app/src/pages/charts/market-cap.tsx @@ -0,0 +1,12 @@ +import { VmComponent } from '@/components/vm/VmComponent'; +import { useBosComponents } from '@/hooks/useBosComponents'; + +const MarketCapChart = () => { + const components = useBosComponents(); + + return ( + + ); +}; + +export default MarketCapChart; diff --git a/apps/app/src/pages/charts/near-price.tsx b/apps/app/src/pages/charts/near-price.tsx new file mode 100644 index 000000000..b5448dce3 --- /dev/null +++ b/apps/app/src/pages/charts/near-price.tsx @@ -0,0 +1,12 @@ +import { VmComponent } from '@/components/vm/VmComponent'; +import { useBosComponents } from '@/hooks/useBosComponents'; + +const NearPriceChart = () => { + const components = useBosComponents(); + + return ( + + ); +}; + +export default NearPriceChart; diff --git a/apps/app/src/pages/charts/near-supply.tsx b/apps/app/src/pages/charts/near-supply.tsx new file mode 100644 index 000000000..67dcf18e9 --- /dev/null +++ b/apps/app/src/pages/charts/near-supply.tsx @@ -0,0 +1,12 @@ +import { VmComponent } from '@/components/vm/VmComponent'; +import { useBosComponents } from '@/hooks/useBosComponents'; + +const NearSupplyChart = () => { + const components = useBosComponents(); + + return ( + + ); +}; + +export default NearSupplyChart; diff --git a/apps/app/src/pages/charts/txn-fee.tsx b/apps/app/src/pages/charts/txn-fee.tsx new file mode 100644 index 000000000..74e753a07 --- /dev/null +++ b/apps/app/src/pages/charts/txn-fee.tsx @@ -0,0 +1,10 @@ +import { VmComponent } from '@/components/vm/VmComponent'; +import { useBosComponents } from '@/hooks/useBosComponents'; + +const TxnFeeChart = () => { + const components = useBosComponents(); + + return ; +}; + +export default TxnFeeChart; diff --git a/apps/app/src/pages/charts/txn-volume.tsx b/apps/app/src/pages/charts/txn-volume.tsx new file mode 100644 index 000000000..9f72ec410 --- /dev/null +++ b/apps/app/src/pages/charts/txn-volume.tsx @@ -0,0 +1,12 @@ +import { VmComponent } from '@/components/vm/VmComponent'; +import { useBosComponents } from '@/hooks/useBosComponents'; + +const TxnVolumeChart = () => { + const components = useBosComponents(); + + return ( + + ); +}; + +export default TxnVolumeChart; diff --git a/apps/app/src/pages/charts/txns.tsx b/apps/app/src/pages/charts/txns.tsx new file mode 100644 index 000000000..b42c7acde --- /dev/null +++ b/apps/app/src/pages/charts/txns.tsx @@ -0,0 +1,10 @@ +import { VmComponent } from '@/components/vm/VmComponent'; +import { useBosComponents } from '@/hooks/useBosComponents'; + +const TxnsChart = () => { + const components = useBosComponents(); + + return ; +}; + +export default TxnsChart; diff --git a/apps/bos-components/src/components/Charts.tsx b/apps/bos-components/src/components/Charts.tsx new file mode 100644 index 000000000..352150494 --- /dev/null +++ b/apps/bos-components/src/components/Charts.tsx @@ -0,0 +1,487 @@ +/** + * Component: Charts + * Author: Nearblocks Pte Ltd + * License: Business Source License 1.1 + * Description: Dynamic data visualization on NearBlocks. + * @interface Props + * @param {string} [chart] - Determine which chart to be shown. + * @param {boolean} [fetchStyles] - Use Nearblock styles. + */ + +interface Props { + chart: string; + fetchStyles?: boolean; +} + +import Skelton from '@/includes/Common/Skelton'; +import { getConfig, yoctoToNear } from '@/includes/libs'; +import { ChartConfig, ChartStat, ChartTypeInfo } from '@/includes/types'; + +export default function (props: Props) { + const [css, setCss] = useState({}); + const [data, setData] = useState([]); + const [chartConfig, setChartConfig] = useState(null); + const [chartInfo, setChartInfo] = useState({ + title: '', + description: '', + }); + + const config = getConfig(context.networkId); + + const charts = [ + { + link: '/charts/near-price', + text: 'Near Daily Price (USD) Chart', + image: `${config.appUrl}images/charts/near-price.svg`, + exclude: `${context.networkId}` === 'testnet', + }, + { + link: '/charts/market-cap', + text: 'Near Market Capitalization Chart', + image: `${config.appUrl}images/charts/market-cap.svg`, + exclude: `${context.networkId}` === 'testnet', + }, + { + link: '/charts/near-supply', + text: 'Near Supply Growth Chart', + image: `${config.appUrl}images/charts/near-supply.svg`, + exclude: false, + }, + { + link: '/charts/txns', + text: 'Near Daily Transactions Chart', + image: `${config.appUrl}images/charts/txns.svg`, + exclude: false, + }, + { + link: '/charts/blocks', + text: 'Near Block Count', + image: `${config.appUrl}images/charts/blocks.svg`, + exclude: false, + }, + { + link: '/charts/addresses', + text: 'Near Unique Accounts Chart', + image: `${config.appUrl}images/charts/addresses.svg`, + exclude: false, + }, + { + link: '/charts/txn-fee', + text: 'Transaction Fee Chart', + image: `${config.appUrl}images/charts/txn-fee.svg`, + exclude: `${context.networkId}` === 'testnet', + }, + { + link: '/charts/txn-volume', + text: 'Transaction Volume Chart', + image: `${config.appUrl}images/charts/txn-volume.svg`, + exclude: `${context.networkId}` === 'testnet', + }, + ]; + + /** + * Fetches styles asynchronously from a nearblocks gateway. + */ + function fetchStyles() { + asyncFetch('https://beta.nearblocks.io/common.css').then( + (res: { body: string }) => { + if (res?.body) { + setCss(res.body); + } + }, + ); + } + + const chartData = useMemo(() => { + try { + const chartTypeMappings = { + txns: (stat: ChartStat) => ({ + x: new Date(stat.date).valueOf(), + y: Number(stat.txns), + date: stat.date, + blocks: stat.blocks, + addresses: stat.addresses, + }), + 'market-cap': (stat: ChartStat) => ({ + x: new Date(stat.date).valueOf(), + y: Number(stat.market_cap), + date: stat.date, + price: Number(stat.near_price), + }), + 'near-supply': (stat: ChartStat) => ({ + x: new Date(stat.date).valueOf(), + y: Number(yoctoToNear(Number(stat.total_supply), false)), + date: stat.date, + }), + blocks: (stat: ChartStat) => ({ + x: new Date(stat.date).valueOf(), + y: Number(stat.blocks), + date: stat.date, + }), + addresses: (stat: ChartStat) => ({ + x: new Date(stat.date).valueOf(), + y: Number(stat.total_addresses), + date: stat.date, + addresses: stat.addresses, + }), + 'txn-fee': (stat: ChartStat) => ({ + x: new Date(stat.date).valueOf(), + y: Number(stat.txn_fee_usd), + date: stat.date, + fee: stat.txn_fee, + }), + 'txn-volume': (stat: ChartStat) => ({ + x: new Date(stat.date).valueOf(), + y: Number(stat.txn_volume_usd), + date: stat.date, + volume: stat.txn_volume, + }), + 'near-price': (stat: ChartStat) => ({ + x: new Date(stat.date).valueOf(), + y: Number(stat.near_price), + date: stat.date, + }), + }; + + const mappingFunction = + chartTypeMappings[props.chart as keyof typeof chartTypeMappings]; + if (mappingFunction) { + return data.map(mappingFunction); + } else { + return []; + } + } catch (error) { + return []; + } + }, [data, props.chart]); + + useEffect(() => { + function fetchChartData() { + asyncFetch(`${config.backendUrl}charts`).then( + (res: { body: { charts: ChartStat[] } }) => { + if (res?.body) { + setData(res.body?.charts as ChartStat[]); + } + }, + ); + } + + if (props?.fetchStyles) { + fetchStyles(); + } + + fetchChartData(); + }, [props?.fetchStyles, config.backendUrl]); + + useEffect(() => { + const fetchData = () => { + let titleText = ''; + let yLabel = ''; + let description = ''; + switch (props.chart) { + case 'market-cap': + titleText = 'Near Market Capitalization Chart'; + yLabel = 'Near Market Cap (USD)'; + description = + 'tNear Market Capitalization chart shows the historical breakdown of Near daily market capitalization and price.'; + break; + case 'txns': + titleText = 'Near Daily Transactions Chart'; + yLabel = 'Transactions per Day'; + description = + 'Near Supply Growth Chart shows a breakdown of daily and the total Near supply.'; + break; + case 'near-supply': + titleText = 'Near Supply Growth Chart'; + yLabel = 'Near Supply'; + description = + 'Near Supply Growth Chart shows a breakdown of daily and the total Near supply.'; + break; + case 'blocks': + titleText = 'Near Block Count'; + yLabel = 'Blocks per Day'; + description = + 'Near Block Count Chart shows the historical number of blocks produced daily on Near blockchain.'; + break; + case 'addresses': + titleText = 'Near Unique Accounts Chart'; + yLabel = 'Near Cumulative Accounts Growth'; + description = + 'The chart shows the total distinct numbers of accounts on Near blockchain and the increase in the number of account daily.'; + break; + case 'txn-fee': + titleText = 'Transaction Fee Chart'; + yLabel = 'Transaction Fee (USD)'; + description = + 'The chart shows the daily amount in USD spent per transaction on Near blockchain.'; + break; + case 'txn-volume': + titleText = 'Transaction Volume Chart'; + yLabel = 'Transaction Volume (USD)'; + description = + 'The chart shows the daily amount in USD spent per transaction on Near blockchain. '; + break; + case 'near-price': + titleText = 'Near Daily Price (USD) Chart'; + yLabel = 'Near Price (USD)'; + description = + 'Near Daily Price (USD) chart shows the daily historical price for Near in USD.'; + break; + default: + } + setChartInfo({ + title: titleText, + description: description, + }); + + const fetchedData = { + chart: { + height: 430, + zoomType: 'x', + }, + title: { + text: titleText, + }, + subtitle: { + text: 'Source: NearBlocks.io', + }, + xAxis: { + type: 'datetime', + }, + yAxis: { + title: { + text: yLabel, + }, + }, + legend: { + enabled: false, + }, + series: [ + { + type: 'area', + data: chartData, + color: 'rgba(3, 63, 64, 1)', + }, + ], + credits: { + enabled: false, + }, + plotOptions: { + area: { + fillColor: { + linearGradient: { + x1: 0, + y1: 0, + x2: 0, + y2: 1, + }, + stops: [ + [0, 'rgba(3, 63, 64, 0.8)'], + [1, 'rgba(3, 63, 64, 0)'], + ], + }, + marker: { + enabled: false, + }, + lineWidth: 1, + states: { + hover: { + lineWidth: 1, + }, + }, + threshold: null, + turboThreshold: 3650, + }, + }, + exporting: { + buttons: { + contextButton: { + menuItems: [ + 'viewFullscreen', + 'printChart', + 'separator', + 'downloadPNG', + 'downloadJPEG', + 'downloadPDF', + 'downloadSVG', + 'separator', + 'embed', + ], + }, + }, + }, + }; + setChartConfig(fetchedData); + }; + + fetchData(); + }, [chartData, props.chart]); + + const iframeSrc = ` + + + + + + + + +
+ + + +`; + const Theme = styled.div` + ${css} + `; + + return ( + +
+
+
+

+ {props.chart ? chartInfo.title : 'Near Charts & Statistics'} +

+
+
+
+ {props.chart && ( +
+

+ {chartInfo?.description} +

+
+ {chartData?.length ? ( +