Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge develop into testnet #1811

Merged
merged 3 commits into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions _typos.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ rd='rd'
th='th'
# typo in api, should be fixed later
toekn='toekn'
# echart config
metalness = 'metalness'
52 changes: 52 additions & 0 deletions src/components/ui/NumberTicker/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { useEffect, useRef, useState } from 'react'

interface NumberTickerProps {
value: number | null
duration?: number // duration in milliseconds
className?: string
}

export function NumberTicker({
value,
duration = 1000, // default animation duration: 1 second
className = '',
}: NumberTickerProps) {
const [displayValue, setDisplayValue] = useState(value)
const prevValueRef = useRef(value ?? 0) // Store the previous value
const animationFrame = useRef<number>()

useEffect(() => {
if (typeof value !== 'number') {
return
}
const startValue = prevValueRef.current // Previous value
const targetValue = value // New value
const startTime = performance.now()

const animate = (currentTime: number) => {
const elapsed = currentTime - startTime
const progress = Math.min(elapsed / duration, 1) // Progress between 0 and 1

// Calculate interpolated value
const interpolatedValue = Math.floor(startValue + (targetValue - startValue) * progress)
setDisplayValue(interpolatedValue)

if (progress < 1) {
animationFrame.current = requestAnimationFrame(animate)
}
}

// Start animation
if (animationFrame.current) cancelAnimationFrame(animationFrame.current)
animationFrame.current = requestAnimationFrame(animate)

// Update the previous value reference
prevValueRef.current = value

return () => {
if (animationFrame.current) cancelAnimationFrame(animationFrame.current)
}
}, [value, duration])

return <span className={className}>{displayValue?.toLocaleString('en') ?? '--,---,---'}</span>
}
22 changes: 22 additions & 0 deletions src/pages/Home/Banner/index.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ $backgroundColor: #232323;
background-repeat: no-repeat;
background-position: center center;
background-size: auto 100%;
color: white;
display: flex;
align-items: center;
justify-content: center;

@media (width <= $mobileBreakPoint) {
background-image: url('./ckb_explorer_banner_phone.svg');
Expand Down Expand Up @@ -121,3 +125,21 @@ $backgroundColor: #232323;
padding: 16px 24px;
}
}

.knowledgeBase {
text-align: center;
font-weight: bold;
font-optical-sizing: auto;
mix-blend-mode: difference;
line-height: 1.2;
font-size: 50px;

.ticker {
display: flex;
gap: 8px;
}

@media screen and (width <= 500px) {
font-size: 30px;
}
}
40 changes: 39 additions & 1 deletion src/pages/Home/Banner/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,41 @@
import { useQuery } from '@tanstack/react-query'
import config from '../../../config'
import styles from './index.module.scss'
import { getKnowledgeSize } from './utils'
import { NumberTicker } from '../../../components/ui/NumberTicker'

export default () => <div className={styles.root} />
const { BACKUP_NODES: backupNodes } = config

export default () => {
const { data: size } = useQuery(
['backup_nodes'],
async () => {
try {
if (backupNodes.length === 0) return null

const [size1, size2] = await Promise.race(backupNodes.map(getKnowledgeSize))
return size1 ?? size2
} catch {
return null
}
},
{ refetchInterval: 12 * 1000 },
)
return (
<div className={styles.root}>
<a
className={styles.knowledgeBase}
target="_blank"
rel="noopener noreferrer"
href="https://talk.nervos.org/t/how-to-get-the-average-occupied-bytes-per-live-cell-in-ckb/7138/2?u=keith"
>
<span>Knowledge Size</span>
<br />
<div className={styles.ticker}>
<NumberTicker value={size ? +size : null} />
<span>CKBytes</span>
</div>
</a>
</div>
)
}
30 changes: 30 additions & 0 deletions src/pages/Home/Banner/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import BigNumber from 'bignumber.js'

/**
* 6/10 of 7th output in the genesis should be excluded because they are expected to be burnt.
* ref: https://talk.nervos.org/t/how-to-get-the-average-occupied-bytes-per-live-cell-in-ckb/7138/2?u=keith
* */
const EXCLUDE = BigNumber('504000000000000000')

export const getKnowledgeSize = async (nodeUrl: string) => {
const header = await fetch(nodeUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
id: 1,
jsonrpc: '2.0',
method: 'get_tip_header',
params: [],
}),
})
.then(res => res.json())
.then(res => res.result)
const { dao } = header

const [, , , u] = dao
.slice(2)
.match(/\w{16}/g)
.map((i: string) => i.match(/\w{2}/g)?.reverse().join('') ?? '')
const total = BigNumber(`0x${u}`).minus(EXCLUDE).toFormat()
return total
}