Skip to content

Commit

Permalink
feat: add node geo distribution chart (#283)
Browse files Browse the repository at this point in the history
  • Loading branch information
Keith-CY authored Apr 9, 2024
1 parent 144d752 commit c80170c
Show file tree
Hide file tree
Showing 12 changed files with 308 additions and 49 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"@ckb-lumos/base": "0.21.0-next.1",
"@microlink/react-json-view": "1.23.0",
"@nervosnetwork/ckb-sdk-utils": "0.109.1",
"@rgbpp-sdk/ckb": "0.0.0-snap-20240408100333",
"@sentry/react": "7.94.1",
"@sentry/tracing": "7.94.1",
"@spore-sdk/core": "0.2.0-beta.3",
Expand All @@ -22,6 +23,7 @@
"dayjs": "1.11.10",
"default-passive-events": "2.0.0",
"echarts": "4.9.0",
"echarts-gl": "1.1.2",
"history": "5.3.0",
"i18next": "20.6.1",
"jsbi": "3.2.5",
Expand Down
Binary file added public/images/chart/dark.webp
Binary file not shown.
Binary file added public/images/chart/earth.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/chart/geo_cover_mainnet.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/chart/geo_cover_testnet.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@
"city": "City",
"node_count": "Node Count",
"node_distribution": "Node Distribution",
"node_geo_distribution": "Node Geo Distribution",
"total_supply": "Total Supply",
"circulating_supply": "Circulating Supply",
"burnt": "Burnt",
Expand Down
1 change: 1 addition & 0 deletions src/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@
"city": "城市",
"node_count": "节点数量",
"node_distribution": "节点分布",
"node_geo_distribution": "节点地理分布",
"total_supply": "总供给量",
"circulating_supply": "总流通量",
"burnt": "销毁量",
Expand Down
6 changes: 6 additions & 0 deletions src/pages/StatisticsChart/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { LiquidityChart } from './monetary/Liquidity'
import { MinerAddressDistributionChart } from './mining/MinerAddressDistribution'
import { MinerVersionDistributionChart } from './mining/MinerVersionDistribution'
import { NodeCountryDistributionChart } from './mining/NodeCountryDistribution'
import NodeGeoDistributionChart from './mining/NodeGeoDistribution'
import { useIsMobile } from '../../hooks'
import { HelpTip } from '../../components/HelpTip'
import { Link } from '../../components/Link'
Expand Down Expand Up @@ -138,6 +139,11 @@ const useChartsData = () => {
chart: <NodeCountryDistributionChart isThumbnail />,
path: '/charts/node-country-distribution',
},
{
title: `${t('statistic.node_geo_distribution')}`,
chart: <NodeGeoDistributionChart isThumbnail />,
path: '/charts/node-geo-distribution',
},
],
},
{
Expand Down
174 changes: 174 additions & 0 deletions src/pages/StatisticsChart/mining/NodeGeoDistribution.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import { useEffect, useRef } from 'react'
import { useQuery } from '@tanstack/react-query'
import 'echarts/lib/component/tooltip'
import 'echarts-gl'
import echarts from 'echarts/lib/echarts'
import Loading from '../../../components/Loading/SmallLoading'
import { getPeers, RawPeer } from '../../../services/NodeProbService'
import { getPrimaryColor, IS_MAINNET } from '../../../constants/common'

const LAUNCH_TIME_OF_MAINNET = 0x16e70e6985c

type Point = [long: number, lat: number, city: string]
type Line = [Point, Point]

const fetchData = async (): Promise<{ lines: Line[]; points: Point[] }> => {
const list: RawPeer[] = await getPeers()
const points: Point[] = list.map(peer => [peer.longitude, peer.latitude, peer.city])
const lines: Line[] = []
for (let i = 0; i < points.length - 1; i++) {
for (let j = i + 1; j < points.length; j++) {
const p1: Point = points[i]
const p2: Point = points[j]
lines.push([p1, p2])
}
}

return { lines, points }
}

const option = {
backgroundColor: '#000',
tooltip: {
show: true,
formatter: (params: { data: Point }) => {
return params.data[2]
},
},
globe: {
environment: '/images/chart/dark.webp',
baseTexture: '/images/chart/earth.jpg',
heightTexture: '/images/chart/earth.jpg',
displacementScale: 0.04,
displacementQuality: 'high',
shading: 'realistic',
realisticMaterial: {
roughness: 0.9,
metalness: 0,
},
temporalSuperSampling: {
enable: true,
},
postEffect: {
enable: true,
depthOfField: {
enable: false,
focalDistance: 150,
},
},
light: {
main: {
intensity: 10,
shadow: true,
time: new Date(LAUNCH_TIME_OF_MAINNET),
},
},
viewControl: {
autoRotate: true,
autoRotateSpeed: 1,
distance: 800,
},
silent: true,
},
}

const color = getPrimaryColor()

export const NodeGeoDistribution = ({ isThumbnail = false }: { isThumbnail?: boolean }) => {
const containerRef = useRef<HTMLDivElement | null>(null)
const { data, isLoading } = useQuery(['node distribution'], fetchData, { enabled: !isThumbnail })

useEffect(() => {
if (!containerRef.current) return
if (!data) return
let ins = echarts.getInstanceByDom(containerRef.current)
if (!ins) {
ins = echarts.init(containerRef.current)
}

const series = [
{
type: 'lines3D',
name: 'blocks',
coordinateSystem: 'globe',
blendMode: 'lighter',
symbolSize: 2,
itemStyle: {
color,
opacity: 0.1,
},
effect: {
show: true,
trailWidth: 1,
trailLength: 0.15,
trailOpacity: 0.1,
constantSpeed: 10,
},
lineStyle: {
width: 1,
color,
opacity: 0.02,
},
data: data.lines,
},
{
type: 'scatter3D',
coordinateSystem: 'globe',
blendMode: 'lighter',
symbolSize: 10,
itemStyle: {
color,
opacity: 0.2,
},
label: {
show: true,
formatter: '{b}',
},
data: data.points,
},
]

ins.setOption({
...option,
series,
} as any)
}, [data])

useEffect(() => {
if (!containerRef.current) return
const ins = echarts.getInstanceByDom(containerRef.current)
const handleResize = () => {
if (ins) {
ins.resize()
}
}
window.addEventListener('resize', handleResize)
return () => {
window.removeEventListener('resize', handleResize)
}
})

if (isThumbnail) {
return (
<div
style={{
width: 280,
height: 200,
background: `center / cover url(/images/chart/geo_cover_${IS_MAINNET ? 'mainnet' : 'testnet'}.png)`,
}}
/>
)
}

if (isLoading) {
return <Loading />
}

if (!data) {
return <div>Fail to load data</div>
}

return <div style={{ width: '100vw', height: '100vh' }} ref={containerRef} />
}

export default NodeGeoDistribution
5 changes: 5 additions & 0 deletions src/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const UncleRateChart = lazy(() => import('../pages/StatisticsChart/mining/UncleR
const MinerAddressDistributionChart = lazy(() => import('../pages/StatisticsChart/mining/MinerAddressDistribution'))
const MinerVersionDistributionChart = lazy(() => import('../pages/StatisticsChart/mining/MinerVersionDistribution'))
const NodeCountryDistributionChart = lazy(() => import('../pages/StatisticsChart/mining/NodeCountryDistribution'))
const NodeGeoDistributionChart = lazy(() => import('../pages/StatisticsChart/mining/NodeGeoDistribution'))
const TransactionCountChart = lazy(() => import('../pages/StatisticsChart/activities/TransactionCount'))
const AddressCountChart = lazy(() => import('../pages/StatisticsChart/activities/AddressCount'))
const CellCountChart = lazy(() => import('../pages/StatisticsChart/activities/CellCount'))
Expand Down Expand Up @@ -189,6 +190,10 @@ const routes: RouteProps[] = [
path: '/charts/node-country-distribution',
component: NodeCountryDistributionChart,
},
{
path: '/charts/node-geo-distribution',
component: NodeGeoDistributionChart,
},
{
path: '/charts/transaction-count',
component: TransactionCountChart,
Expand Down
20 changes: 5 additions & 15 deletions src/utils/rgbpp.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,14 @@
import { toBigEndian } from '@nervosnetwork/ckb-sdk-utils'
import { blockchain } from '@ckb-lumos/base'
import { BTCTimeLock } from '@rgbpp-sdk/ckb'

export const parseBtcTimeLockArgs = (args: string) => {
// btc time lock: https://github.com/ckb-cell/RGBPlusPlus-design/blob/main/docs/locscript-design-prd-cn.md#btc_time_lock
const OFFSET_END = 8 * 4
const LOCK_SCRIPT_LEN = 178
const AFTER_LEN = 8
const TXID_LEN = 64
const LOCK_SCRIPT_END = 2 + LOCK_SCRIPT_LEN
const AFTER_END = LOCK_SCRIPT_END + AFTER_LEN
const TXID_END = AFTER_END + TXID_LEN

const script = args.slice(2 + OFFSET_END, LOCK_SCRIPT_END)
const after = args.slice(LOCK_SCRIPT_END, AFTER_END)
const btcTx = args.slice(AFTER_END, TXID_END)
const { lockScript, after, btcTxid } = BTCTimeLock.unpack(args)

const res = {
script: blockchain.Script.unpack(`0x${script}`),
after: Number(toBigEndian(`0x${after}`)),
txid: toBigEndian(`0x${btcTx}`).slice(2),
script: lockScript,
after,
txid: btcTxid.slice(2).match(/\w{2}/g)?.reverse().join(''),
}

return res
Expand Down
Loading

0 comments on commit c80170c

Please sign in to comment.