Skip to content

Commit

Permalink
optimize: halving over logic
Browse files Browse the repository at this point in the history
  • Loading branch information
PainterPuppets committed Oct 10, 2023
1 parent 66580dd commit 030009a
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 53 deletions.
25 changes: 9 additions & 16 deletions src/components/Banner/HalvingBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import halvingSuccessAni from '../../assets/halving_success_ani.gif'
import SimpleButton from '../SimpleButton'
import { useCountdown, useHalving } from '../../utils/hook'
import i18n from '../../utils/i18n'
import { fetchCachedData } from '../../utils/cache'

function numberToOrdinal(number: number) {
switch (number) {
Expand All @@ -31,10 +30,8 @@ function numberToOrdinal(number: number) {
}

export const HalvingBanner = () => {
const { estimatedDate, nextHalvingCount } = useHalving()
const { estimatedDate, halvingCount, inCelebration } = useHalving()
const [days, hours, minutes, seconds] = useCountdown(estimatedDate)
const lastedHavingKey = `lasted-having-${nextHalvingCount - 1}`
const unreadLastedHaving = nextHalvingCount > 1 && fetchCachedData(lastedHavingKey) === null

const shortCountdown = () => {
if (days > 0) {
Expand All @@ -46,29 +43,25 @@ export const HalvingBanner = () => {
if (minutes > 0) {
return `${minutes}${i18n.t('symbol.char_space')}${i18n.t('unit.minutes')}`
}
if (seconds > 0) {
return `${seconds}${i18n.t('symbol.char_space')}${i18n.t('unit.seconds')}`
}
return `${i18n.t('halving.halving')}!`

return `${seconds}${i18n.t('symbol.char_space')}${i18n.t('unit.seconds')}`
}

return (
<div
className={classnames(styles.halvingBannerWrapper, { [styles.halvingBannerSuccess]: unreadLastedHaving })}
className={classnames(styles.halvingBannerWrapper, { [styles.halvingBannerSuccess]: inCelebration })}
style={{
backgroundImage: `url(${unreadLastedHaving ? halvingBannerSuccess : halvingBanner})`,
backgroundImage: `url(${inCelebration ? halvingBannerSuccess : halvingBanner})`,
}}
>
<div className={styles.halvingBannerShadow}>
<div className={classnames(styles.halvingBanner, 'container')}>
{unreadLastedHaving && (
<img className={styles.halvingBannerAnimation} src={halvingSuccessAni} alt="animation" />
)}
{unreadLastedHaving ? (
{inCelebration && <img className={styles.halvingBannerAnimation} src={halvingSuccessAni} alt="animation" />}
{inCelebration ? (
<div className={classnames(styles.halvingBannerText, styles.success)}>
{i18n
.t('halving.banner_congratulation', {
times: i18n.t(`ordinal.${numberToOrdinal(nextHalvingCount - 1)}`),
times: i18n.t(`ordinal.${numberToOrdinal(halvingCount)}`),
})
.toUpperCase()}
</div>
Expand All @@ -79,7 +72,7 @@ export const HalvingBanner = () => {
)}
<a href="/halving">
<SimpleButton className={styles.learnMoreButton}>
{unreadLastedHaving
{inCelebration
? i18n.t('halving.learn_more')
: `${i18n.t('halving.halving_countdown')} ${shortCountdown()}`}
</SimpleButton>
Expand Down
2 changes: 2 additions & 0 deletions src/constants/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export const EPOCH_HOURS = 4
export const ONE_DAY_SECOND = 24 * 60 * 60
export const ONE_HOUR_SECOND = 60 * 60
export const ONE_MINUTE_SECOND = 60
export const EPOCHS_PER_HALVING = 8760
export const THEORETICAL_EPOCH_TIME = 1000 * 60 * 60 * 4 // 4 hours
export const IS_MAINTAINING = process.env.REACT_APP_IS_MAINTAINING === 'true'

export function getPrimaryColor() {
Expand Down
39 changes: 14 additions & 25 deletions src/pages/Halving/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ import { HalvingInfo } from './HalvingInfo'
import { useStatistics } from '../../services/ExplorerService'
import { HalvingCountdown } from './HalvingCountdown'
import { useCountdown, useHalving, useIsMobile } from '../../utils/hook'
import { fetchCachedData, storeCachedData } from '../../utils/cache'
import { getPrimaryColor } from '../../constants/common'
import { getPrimaryColor, EPOCHS_PER_HALVING, THEORETICAL_EPOCH_TIME } from '../../constants/common'
import styles from './index.module.scss'

function numberToOrdinal(number: number) {
Expand Down Expand Up @@ -45,20 +44,12 @@ function numberToOrdinal(number: number) {
export const HalvingCountdownPage = () => {
const isMobile = useIsMobile()
const statistics = useStatistics()
const {
currentEpoch,
estimatedDate,
singleEpochAverageTime,
currentEpochUsedTime,
EPOCHS_PER_HALVING,
nextHalvingCount,
} = useHalving()
const { currentEpoch, estimatedDate, currentEpochUsedTime, halvingCount, inCelebration, skipCelebration } =
useHalving()

const lastedHavingKey = `lasted-having-${nextHalvingCount - 1}`
const unreadLastedHaving = nextHalvingCount > 1 && fetchCachedData(lastedHavingKey) === null
const percent =
(((currentEpoch % EPOCHS_PER_HALVING) * singleEpochAverageTime - currentEpochUsedTime) /
(EPOCHS_PER_HALVING * singleEpochAverageTime)) *
(((currentEpoch % EPOCHS_PER_HALVING) * THEORETICAL_EPOCH_TIME - currentEpochUsedTime) /
(EPOCHS_PER_HALVING * THEORETICAL_EPOCH_TIME)) *
100
const [days, hours, minutes, seconds] = useCountdown(estimatedDate)

Expand All @@ -76,7 +67,7 @@ export const HalvingCountdownPage = () => {
}

const shareText = i18n.t('halving.share_text', {
times: i18n.t(`ordinal.${numberToOrdinal(nextHalvingCount)}`),
times: i18n.t(`ordinal.${numberToOrdinal(halvingCount)}`),
date: estimatedDate.toUTCString(),
countdown: shortCountdown(),
})
Expand All @@ -90,7 +81,7 @@ export const HalvingCountdownPage = () => {
}

const renderHalvingPanel = () => {
if (unreadLastedHaving) {
if (inCelebration) {
return (
<div
className={styles.halvingPanel}
Expand All @@ -101,22 +92,20 @@ export const HalvingCountdownPage = () => {
<div className={styles.textCapitalize}>
{i18n.t('halving.the')}
{i18n.t('symbol.char_space')}
{i18n.t(`ordinal.${numberToOrdinal(nextHalvingCount - 1)}`)}
{i18n.t(`ordinal.${numberToOrdinal(halvingCount)}`)}
{i18n.t('symbol.char_space')}
{i18n.t('halving.halving')}
{i18n.t('halving.actived')}{' '}
<a className={styles.textPrimary} href={`/block/${getTargetBlockByHavingCount(nextHalvingCount - 1)}`}>
{new BigNumber(getTargetBlockByHavingCount(nextHalvingCount - 1)).toFormat()}.
<a className={styles.textPrimary} href={`/block/${getTargetBlockByHavingCount(halvingCount)}`}>
{new BigNumber(getTargetBlockByHavingCount(halvingCount)).toFormat()}.
</a>
</div>
</div>
<div className={styles.textCenter}>
<button
className={classnames(styles.halvingSuccessBtn, styles.textCapitalize)}
type="button"
onClick={() => {
storeCachedData(lastedHavingKey, true)
}}
onClick={() => skipCelebration()}
>
{i18n.t('halving.next')}
{i18n.t('symbol.char_space')}
Expand All @@ -130,16 +119,16 @@ export const HalvingCountdownPage = () => {
return (
<div className={styles.halvingPanel}>
<div className={classnames(styles.halvingPanelTitle, styles.textCapitalize)}>
{i18n.t(`ordinal.${numberToOrdinal(nextHalvingCount)}`)}
{i18n.t(`ordinal.${numberToOrdinal(halvingCount)}`)}
{i18n.t('symbol.char_space')}
{i18n.t('halving.halving')}

{nextHalvingCount > 1 && (
{halvingCount > 1 && (
<Popover
content={
<Table
pagination={false}
dataSource={new Array(nextHalvingCount - 1).fill({}).map((_, index) => ({
dataSource={new Array(halvingCount - 1).fill({}).map((_, index) => ({
key: index,
event: `${i18n.t(`ordinal.${numberToOrdinal(index + 1)}`)}
${i18n.t('symbol.char_space')}
Expand Down
40 changes: 28 additions & 12 deletions src/utils/hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { interval, share } from 'rxjs'
import { AppCachedKeys } from '../constants/cache'
import { deprecatedAddrToNewAddr } from './util'
import { startEndEllipsis } from './string'
import { ListPageParams, PageParams } from '../constants/common'
import { ListPageParams, PageParams, THEORETICAL_EPOCH_TIME, EPOCHS_PER_HALVING } from '../constants/common'
import {
fetchCachedData,
fetchDateChartCache,
Expand Down Expand Up @@ -601,32 +601,48 @@ export const useCountdown = (targetDate: Date) => {
return [days, hours, minutes, seconds]
}

export const useHalving = () => {
export const useSingleHalving = (_halvingCount = 1) => {
const halvingCount = Math.max(Math.floor(_halvingCount) || 1, 1) // halvingCount should be a positive integer greater than 1.
const statistics = useStatistics()
const celebrationSkipKey = `having-celebration-${halvingCount}`
const celebrationSkipped = fetchCachedData(celebrationSkipKey) !== null
function skipCelebration() {
storeCachedData(celebrationSkipKey, true)
}

const EPOCHS_PER_HALVING = 8760
const currentEpoch = Number(statistics.epochInfo.epochNumber)
const nextHalvingCount = Math.ceil(currentEpoch / EPOCHS_PER_HALVING)
const targetEpoch = EPOCHS_PER_HALVING * nextHalvingCount
const singleEpochAverageTime = 1000 * 60 * 60 * 4
const targetEpoch = EPOCHS_PER_HALVING * halvingCount
const currentEpochUsedTime =
(Number(statistics.epochInfo.index) / Number(statistics.epochInfo.epochLength)) * singleEpochAverageTime

const estimatedTime = (targetEpoch - currentEpoch) * singleEpochAverageTime - currentEpochUsedTime
(Number(statistics.epochInfo.index) / Number(statistics.epochInfo.epochLength)) * THEORETICAL_EPOCH_TIME

const estimatedTime = (targetEpoch - currentEpoch) * THEORETICAL_EPOCH_TIME - currentEpochUsedTime
const estimatedDate = useMemo(() => new Date(new Date().getTime() + estimatedTime), [estimatedTime])

const haveDone = currentEpoch >= targetEpoch || new Date().getTime() > estimatedDate.getTime()
const celebrationOverEpoch = targetEpoch + 30 * 6 // Every 6 epochs is theoretically 1 day.
const inCelebration = haveDone && currentEpoch < celebrationOverEpoch && !celebrationSkipped

return {
EPOCHS_PER_HALVING,
halvingCount,
currentEpoch,
targetEpoch,
nextHalvingCount,
singleEpochAverageTime,
inCelebration,
skipCelebration,
currentEpochUsedTime,
estimatedDate,
}
}

export const useHalving = () => {
const statistics = useStatistics()
const currentEpoch = Number(statistics.epochInfo.epochNumber)
const lastedHalvingCount = Math.ceil((currentEpoch + 1) / EPOCHS_PER_HALVING)
const lastedHalving = useSingleHalving(lastedHalvingCount)
const previousHalving = useSingleHalving(lastedHalvingCount - 1)

return previousHalving.inCelebration ? previousHalving : lastedHalving
}

export default {
useInterval,
useTimeout,
Expand Down

0 comments on commit 030009a

Please sign in to comment.