apply changes from pallet-slow-clap

Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
Uncle Fatso 2026-03-04 17:43:21 +03:00
parent 18ba617a43
commit 3316f7640e
Signed by: f4ts0
GPG Key ID: 565F4F2860226EBB
7 changed files with 91 additions and 10 deletions

View File

@ -1,7 +1,7 @@
{ {
"name": "ghost-dao-interface", "name": "ghost-dao-interface",
"private": true, "private": true,
"version": "0.5.38", "version": "0.5.39",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View File

@ -10,6 +10,7 @@ import {
useMediaQuery, useMediaQuery,
} from "@mui/material"; } from "@mui/material";
import { decodeAddress } from "@polkadot/util-crypto"; import { decodeAddress } from "@polkadot/util-crypto";
import { fromHex } from "@polkadot-api/utils";
import { getBlockNumber } from "@wagmi/core"; import { getBlockNumber } from "@wagmi/core";
import { useTransaction } from "wagmi"; import { useTransaction } from "wagmi";
import { keccak256 } from "viem"; import { keccak256 } from "viem";
@ -42,6 +43,8 @@ import {
useCurrentSlot, useCurrentSlot,
useGenesisSlot, useGenesisSlot,
useErasTotalStake, useErasTotalStake,
useLatestBlockNumber,
useEraIndex,
} from "../../hooks/ghost"; } from "../../hooks/ghost";
import { ValidatorTable } from "./ValidatorTable"; import { ValidatorTable } from "./ValidatorTable";
@ -102,24 +105,28 @@ const Bridge = ({ chainId, address, config, connect }) => {
const networkIdEncoded = u64.enc(BigInt(chainId)); const networkIdEncoded = u64.enc(BigInt(chainId));
const amountEncoded = u128.enc(BigInt(watchTransaction.amount)); const amountEncoded = u128.enc(BigInt(watchTransaction.amount));
const addressEncoded = decodeAddress(watchTransaction.receiverAddress, false, 1996); const addressEncoded = decodeAddress(watchTransaction.receiverAddress, false, 1996);
const transactionHashEncoded = fromHex(watchTransaction.transactionHash);
const blockNumber = u64.enc(watchTransactionInfo?.blockNumber ?? 0n); const blockNumber = u64.enc(watchTransactionInfo?.blockNumber ?? 0n);
const clapArgsStr = new Uint8Array([ const clapArgsStr = new Uint8Array([
...addressEncoded, ...addressEncoded,
...amountEncoded, ...amountEncoded,
...blockNumber, ...blockNumber,
...transactionHashEncoded,
...networkIdEncoded ...networkIdEncoded
]); ]);
return keccak256(clapArgsStr) return keccak256(clapArgsStr)
}, [watchTransaction, watchTransactionInfo]) }, [watchTransaction, watchTransactionInfo])
const latestBlockNumber = useLatestBlockNumber();
const eraIndex = useEraIndex();
const currentSlot = useCurrentSlot(); const currentSlot = useCurrentSlot();
const genesisSlot = useGenesisSlot(); const genesisSlot = useGenesisSlot();
const currentSession = useCurrentIndex(); const currentSession = useCurrentIndex();
const applauseThreshold = useApplauseThreshold(); const applauseThreshold = useApplauseThreshold();
const evmNetwork = useEvmNetwork({ evmChainId: chainId }); const evmNetwork = useEvmNetwork({ evmChainId: chainId });
const totalStakedAmount = useErasTotalStake({ const totalStakedAmount = useErasTotalStake({
eraIndex: Math.floor((watchTransaction?.sessionIndex ?? currentSession) / 6) eraIndex: eraIndex?.index ?? 0,
}); });
const authorities = useAuthorities({ const authorities = useAuthorities({
currentSession: watchTransaction?.sessionIndex ?? currentSession currentSession: watchTransaction?.sessionIndex ?? currentSession
@ -205,16 +212,20 @@ const Bridge = ({ chainId, address, config, connect }) => {
const latestCommits = useMemo(() => { const latestCommits = useMemo(() => {
return validators?.map((validator, index) => { return validators?.map((validator, index) => {
const lastUpdatedNumber = Number(blockCommitments?.at(index)?.last_updated ?? 0);
const timestampDelta = (latestBlockNumber - lastUpdatedNumber) * 6000; // ideal 6 seconds for block
const lastUpdatedTimestamp = Math.floor(currentTime - timestampDelta);
return { return {
validator: validator, validator: validator,
lastActive: currentTime - Number(blockCommitments?.at(index)?.last_updated ?? 0), lastActive: timestampDelta,
lastUpdated: blockCommitments?.at(index)?.last_updated, lastUpdated: lastUpdatedTimestamp,
lastStoredBlock: blockCommitments?.at(index)?.last_stored_block, lastStoredBlock: blockCommitments?.at(index)?.last_stored_block,
storedBlockTime: (blockCommitments?.at(index)?.last_stored_block ?? 0n) * networkAvgBlockSpeed(chainId), storedBlockTime: (blockCommitments?.at(index)?.last_stored_block ?? 0n) * networkAvgBlockSpeed(chainId),
disabled: disabledValidators?.includes(index), disabled: disabledValidators?.includes(index),
} }
}) })
}, [blockCommitments, disabledValidators, validators, chainId]); }, [blockCommitments, disabledValidators, validators, latestBlockNumber, chainId]);
const latestUpdate = useMemo(() => { const latestUpdate = useMemo(() => {
const validCommits = latestCommits?.filter(commit => const validCommits = latestCommits?.filter(commit =>

View File

@ -8,15 +8,24 @@ import { useUnstableProvider } from "./UnstableProvider"
const MetadataProvider = createContext(null) const MetadataProvider = createContext(null)
export const useMetadata = () => useContext(MetadataProvider) export const useMetadata = () => useContext(MetadataProvider)
const CACHE_VERSION = "v2"
export const MetadataProviderProvider = ({ children }) => { export const MetadataProviderProvider = ({ children }) => {
const { client, chainId } = useUnstableProvider() const { client, chainId } = useUnstableProvider()
const { data: metadata } = useSWR( const { data: metadata } = useSWR(
client && chainId ? ["metadata", client, chainId] : null, client && chainId ? ["metadata", client, chainId] : null,
async ([_, client]) => { async ([_, client]) => {
const storageKey = `metadata-${chainId}` const storageKey = `metadata-${chainId}-${CACHE_VERSION}`
const storedMetadata = sessionStorage.getItem(storageKey) const storedMetadata = sessionStorage.getItem(storageKey)
if (storedMetadata) return unifyMetadata(decAnyMetadata(storedMetadata)) if (storedMetadata) return unifyMetadata(decAnyMetadata(storedMetadata))
Object.keys(sessionStorage).forEach(key => {
if (key.startsWith("metadata-")) {
sessionStorage.removeItem(key);
}
});
const metadata = await new Promise((resolve, reject) => const metadata = await new Promise((resolve, reject) =>
client._request("state_getMetadata", [], { client._request("state_getMetadata", [], {
onSuccess: resolve, onSuccess: resolve,

View File

@ -12,3 +12,5 @@ export * from "./useBlockCommitments";
export * from "./useApplauseDetails"; export * from "./useApplauseDetails";
export * from "./useBabeSlots"; export * from "./useBabeSlots";
export * from "./useErasTotalStaked"; export * from "./useErasTotalStaked";
export * from "./useLatestBlockNumber";
export * from "./useEraIndex";

View File

@ -0,0 +1,41 @@
import useSWRSubscription from "swr/subscription"
import { getDynamicBuilder, getLookupFn } from "@polkadot-api/metadata-builders"
import { distinct, filter, map, mergeMap } from "rxjs"
import { useUnstableProvider } from "./UnstableProvider"
import { useMetadata } from "./MetadataProvider"
export const useEraIndex = () => {
const { chainHead$, chainId } = useUnstableProvider()
const metadata = useMetadata()
const { data: eraIndex } = useSWRSubscription(
chainHead$ && chainId && metadata
? ["eraIndex", chainHead$, chainId, metadata]
: null,
([_, chainHead$, chainId, metadata], { next }) => {
const { finalized$, storage$ } = chainHead$
const subscription = finalized$.pipe(
filter(Boolean),
mergeMap((blockInfo) => {
const builder = getDynamicBuilder(getLookupFn(metadata))
const eraIndex = builder.buildStorage("Staking", "ActiveEra")
return storage$(blockInfo?.hash, "value", () =>
eraIndex?.keys.enc()
).pipe(
filter(Boolean),
distinct(),
map((value) => eraIndex?.value.dec(value))
)
}),
)
.subscribe({
next(eraIndex) {
next(null, eraIndex)
},
error: next,
})
return () => subscription.unsubscribe()
}
)
return eraIndex;
}

View File

@ -5,14 +5,14 @@ import { distinct, filter, map, mergeMap } from "rxjs"
import { useUnstableProvider } from "./UnstableProvider" import { useUnstableProvider } from "./UnstableProvider"
import { useMetadata } from "./MetadataProvider" import { useMetadata } from "./MetadataProvider"
export const useErasTotalStake = ({ eraIndex }) => { export const useErasTotalStake = ({ epochIndex }) => {
const { chainHead$, chainId } = useUnstableProvider() const { chainHead$, chainId } = useUnstableProvider()
const metadata = useMetadata() const metadata = useMetadata()
const { data: eraTotalStake } = useSWRSubscription( const { data: eraTotalStake } = useSWRSubscription(
chainHead$ && chainId && metadata chainHead$ && chainId && metadata
? ["eraTotalStake", chainHead$, eraIndex, chainId, metadata] ? ["eraTotalStake", chainHead$, epochIndex, chainId, metadata]
: null, : null,
([_, chainHead$, eraIndex, chainId, metadata], { next }) => { ([_, chainHead$, epochIndex, chainId, metadata], { next }) => {
const { finalized$, storage$ } = chainHead$ const { finalized$, storage$ } = chainHead$
const subscription = finalized$.pipe( const subscription = finalized$.pipe(
filter(Boolean), filter(Boolean),
@ -20,7 +20,7 @@ export const useErasTotalStake = ({ eraIndex }) => {
const builder = getDynamicBuilder(getLookupFn(metadata)) const builder = getDynamicBuilder(getLookupFn(metadata))
const eraTotalStake = builder.buildStorage("Staking", "ErasTotalStake") const eraTotalStake = builder.buildStorage("Staking", "ErasTotalStake")
return storage$(blockInfo?.hash, "value", () => return storage$(blockInfo?.hash, "value", () =>
eraTotalStake?.keys.enc(eraIndex) eraTotalStake?.keys.enc(epochIndex)
).pipe( ).pipe(
filter(Boolean), filter(Boolean),
distinct(), distinct(),

View File

@ -0,0 +1,18 @@
import { useState, useEffect } from "react";
import useSWRSubscription from "swr/subscription"
import { useUnstableProvider } from "./UnstableProvider"
export const useLatestBlockNumber = () => {
const { chainHead$ } = useUnstableProvider();
const [blockNumber, setBlockNumber] = useState(null);
useEffect(() => {
if (!chainHead$) return;
const subscription = chainHead$.best$.subscribe((block) => {
setBlockNumber(block.number);
});
return () => subscription.unsubscribe();
}, [chainHead$]);
return blockNumber;
}