Skip to content

Commit

Permalink
Merge branch 'main' into 1036-on-account-details-show-balance-history…
Browse files Browse the repository at this point in the history
…-as-the-first-tabs
  • Loading branch information
marc-aurele-besner authored Dec 19, 2024
2 parents 6b248f1 + 80e2916 commit 1182cc3
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 50 deletions.
85 changes: 50 additions & 35 deletions explorer/src/components/Consensus/Account/AccountLatestRewards.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { StatusIcon } from '@/components/common/StatusIcon'
import { Tooltip } from '@/components/common/Tooltip'
import { INTERNAL_ROUTES } from 'constants/routes'
import { AccountByIdQuery } from 'gql/graphql'
import useIndexers from 'hooks/useIndexers'
import Link from 'next/link'
import { useParams, useRouter } from 'next/navigation'
import { FC } from 'react'
import { useConsensusStates } from 'states/consensus'
import { AccountIdParam } from 'types/app'
import { bigNumberToNumber } from 'utils/number'

Expand All @@ -15,6 +18,7 @@ interface AccountLatestRewardsProps {
export const AccountLatestRewards: FC<AccountLatestRewardsProps> = ({ rewards }) => {
const { network, section, tokenSymbol } = useIndexers()
const { accountId } = useParams<AccountIdParam>()
const lastBlockNumber = useConsensusStates((state) => state.lastBlockNumber)
const { push } = useRouter()

return (
Expand All @@ -33,42 +37,53 @@ export const AccountLatestRewards: FC<AccountLatestRewardsProps> = ({ rewards })
</div>
<div className='w-full'>
<ol className='relative w-full border-l border-purpleLight dark:border-purpleLighterAccent'>
{rewards.map(({ id, rewardType, blockHeight, amount }, index) => (
<li
key={`${id}-account-rewards-block`}
className={`flex w-full justify-between ${
index !== rewards.length - 1 && 'mb-[26px]'
}`}
>
<div className='w-full flex-1 grow'>
<div
className={`absolute -left-1.5 size-3 rounded-full ${
index === 0
? 'bg-primaryAccent dark:bg-primaryAccent'
: 'bg-purpleLight dark:bg-purpleLighterAccent'
}`}
></div>
<div className='-mt-1 ml-4 flex-1 grow text-[13px] font-normal text-grayDark dark:text-white '>
<Link
key={`${id}-account-index`}
className='hover:text-primaryAccent'
href={INTERNAL_ROUTES.blocks.id.page(network, section, blockHeight)}
>
{blockHeight}
</Link>
{rewards.map(({ id, rewardType, blockHeight, amount }, index) => {
const confirmations = lastBlockNumber ? Math.max(0, lastBlockNumber - blockHeight) : 0
return (
<li
key={`${id}-account-rewards-block`}
className={`flex w-full justify-between ${
index !== rewards.length - 1 && 'mb-[26px]'
}`}
>
<div className='w-full flex-1 grow'>
<div
className={`absolute -left-1.5 size-3 rounded-full ${
index === 0
? 'bg-primaryAccent dark:bg-primaryAccent'
: 'bg-purpleLight dark:bg-purpleLighterAccent'
}`}
></div>
<div className='-mt-1 ml-4 flex flex-1 grow items-center gap-2 text-[13px] font-normal text-grayDark dark:text-white'>
<Link
key={`${id}-account-index`}
className='hover:text-primaryAccent'
href={INTERNAL_ROUTES.blocks.id.page(network, section, blockHeight)}
>
{blockHeight}
</Link>
<Tooltip
text={
<span className='whitespace-nowrap'>{`${confirmations} confirmations`}</span>
}
direction='top'
>
<StatusIcon status={confirmations >= 10} isPending={confirmations < 10} />
</Tooltip>
</div>
</div>
</div>
<div className='-mt-1 w-full flex-1 grow text-center text-[13px] font-normal text-grayDark dark:text-white'>
{rewardType
.split('.')[1]
.split(/(?=[A-Z])/)
.join(' ')}
</div>
<div className='-mt-1 w-full flex-1 grow text-end text-[13px] font-normal text-grayDark dark:text-white'>
{bigNumberToNumber(amount)} {tokenSymbol}
</div>
</li>
))}
<div className='-mt-1 w-full flex-1 grow text-center text-[13px] font-normal text-grayDark dark:text-white'>
{rewardType
.split('.')[1]
.split(/(?=[A-Z])/)
.join(' ')}
</div>
<div className='-mt-1 w-full flex-1 grow text-end text-[13px] font-normal text-grayDark dark:text-white'>
{bigNumberToNumber(amount)} {tokenSymbol}
</div>
</li>
)
})}
</ol>
</div>
</div>
Expand Down
27 changes: 25 additions & 2 deletions explorer/src/components/Consensus/Account/AccountRewardList.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use client'

import { StatusIcon } from '@/components/common/StatusIcon'
import { useApolloClient } from '@apollo/client'
import { shortString } from '@autonomys/auto-utils'
import { sendGAEvent } from '@next/third-parties/google'
Expand All @@ -22,6 +23,7 @@ import Link from 'next/link'
import { useParams } from 'next/navigation'
import { FC, useCallback, useEffect, useMemo, useState } from 'react'
import { useInView } from 'react-intersection-observer'
import { useConsensusStates } from 'states/consensus'
import { hasValue, isLoading, useQueryStates } from 'states/query'
import { AccountIdParam } from 'types/app'
import type { Cell } from 'types/table'
Expand All @@ -48,7 +50,7 @@ export const AccountRewardList: FC = () => {
const isLargeLaptop = useMediaQuery('(min-width: 1440px)')
const { accountId } = useParams<AccountIdParam>()
const inFocus = useWindowFocus()

const lastBlockNumber = useConsensusStates((state) => state.lastBlockNumber)
const orderBy = useMemo(
() =>
sorting && sorting.length > 0
Expand Down Expand Up @@ -171,8 +173,29 @@ export const AccountRewardList: FC = () => {
</div>
),
},
{
accessorKey: 'block_height',
header: 'Confirmation',
enableSorting: true,
cell: ({ row }: Cell<Row>) => {
const confirmations = lastBlockNumber
? Math.max(0, lastBlockNumber - row.original.block_height)
: 0
return (
<div
key={`${row.original.id}-account-confirmation`}
className='flex items-center gap-2'
>
<StatusIcon status={confirmations >= 10} isPending={confirmations < 10} />
<span className={confirmations < 10 ? 'text-orange-500' : 'text-green-500'}>
{confirmations}
</span>
</div>
)
},
},
],
[network, section, isLargeLaptop, tokenSymbol],
[network, section, isLargeLaptop, tokenSymbol, lastBlockNumber],
)

const pageCount = useMemo(
Expand Down
36 changes: 24 additions & 12 deletions explorer/src/components/common/OutOfSyncBanner.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { useQuery } from '@apollo/client'
import { blockNumber } from '@autonomys/auto-consensus'
import { activate, NetworkId } from '@autonomys/auto-utils'
import { EXTERNAL_ROUTES } from 'constants/routes'
import { LastBlockQuery } from 'gql/graphql'
import useIndexers from 'hooks/useIndexers'
import Link from 'next/link'
import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'
import React, { FC, useCallback, useEffect, useMemo } from 'react'
import { useConsensusStates } from 'states/consensus'
import { LAST_BLOCK } from './query'

const NORMAL_BLOCKS_DIVERGENCE = 120
const POLL_INTERVAL = 12000

const OutOfSyncBanner: FC = () => {
const { network } = useIndexers()
Expand Down Expand Up @@ -47,35 +50,44 @@ const OutOfSyncBanner: FC = () => {

export const useOutOfSyncBanner = () => {
const { network } = useIndexers()
const [lastChainBlock, setLastChainBlock] = useState<number | null>(null)

const lastBlockNumber = useConsensusStates((state) => state.lastBlockNumber)
const setLastBlockNumber = useConsensusStates((state) => state.setLastBlockNumber)

const { data } = useQuery<LastBlockQuery>(LAST_BLOCK, {
pollInterval: 30000,
pollInterval: POLL_INTERVAL,
})

const getChainLastBlock = useCallback(async () => {
const api = await activate({ networkId: network })

const block = await api.rpc.chain.getBlock()

setLastChainBlock(block.block.header.number.toNumber())
}, [network])
try {
const api = await activate({ networkId: network })
setLastBlockNumber(await blockNumber(api))
await api.disconnect()
} catch (error) {
console.error('Error getting chain last block', error)
}
}, [network, setLastBlockNumber])

const lastBlock = useMemo(() => data && parseInt(data.lastBlock[0].height), [data])

const outOfSyncBanner = useMemo(
() =>
data &&
lastBlock &&
lastChainBlock !== null &&
lastBlock + NORMAL_BLOCKS_DIVERGENCE < lastChainBlock ? (
lastBlockNumber !== null &&
lastBlock + NORMAL_BLOCKS_DIVERGENCE < lastBlockNumber ? (
<OutOfSyncBanner />
) : null,
[data, lastBlock, lastChainBlock],
[data, lastBlock, lastBlockNumber],
)

useEffect(() => {
getChainLastBlock()
const interval = setInterval(() => {
getChainLastBlock()
}, POLL_INTERVAL)

return () => clearInterval(interval)
}, [getChainLastBlock])

return outOfSyncBanner
Expand Down
10 changes: 9 additions & 1 deletion explorer/src/states/consensus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ interface ConsensusDefaultState {
successfulBundles: SuccessfulBundle[]
deposits: Deposit[]
withdrawals: Withdrawal[]

// last block number
lastBlockNumber: number | null
}

interface ConsensusState extends ConsensusDefaultState {
Expand All @@ -63,6 +66,7 @@ interface ConsensusState extends ConsensusDefaultState {
setSuccessfulBundles: (successfulBundles: SuccessfulBundle[]) => void
setDeposits: (deposits: Deposit[]) => void
setWithdrawals: (withdrawals: Withdrawal[]) => void
setLastBlockNumber: (lastBlockNumber: number) => void
clear: () => void
}

Expand All @@ -89,6 +93,9 @@ const initialState: ConsensusDefaultState = {
successfulBundles: [],
deposits: [],
withdrawals: [],

// last block number
lastBlockNumber: null,
}

export const useConsensusStates = create<ConsensusState>()(
Expand Down Expand Up @@ -116,11 +123,12 @@ export const useConsensusStates = create<ConsensusState>()(
setSuccessfulBundles: (successfulBundles) => set(() => ({ successfulBundles })),
setDeposits: (deposits) => set(() => ({ deposits })),
setWithdrawals: (withdrawals) => set(() => ({ withdrawals })),
setLastBlockNumber: (lastBlockNumber) => set(() => ({ lastBlockNumber })),
clear: () => set(() => ({ ...initialState })),
}),
{
name: 'consensus-storage',
version: 2,
version: 3,
storage: createJSONStorage(() => localStorage),
serialize: (state) => JSON.stringify(state, bigIntSerializer),
deserialize: (str) => JSON.parse(str, bigIntDeserializer),
Expand Down

0 comments on commit 1182cc3

Please sign in to comment.