Compare commits

..

3 Commits

Author SHA1 Message Date
3316f7640e
apply changes from pallet-slow-clap
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
2026-03-04 17:43:21 +03:00
18ba617a43
fix incorrect setAdjustment increase initial state
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
2026-03-04 14:52:14 +03:00
f7198b9e3f
make function modal fit into mobile version
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
2026-03-04 13:49:13 +03:00
11 changed files with 95 additions and 12 deletions

View File

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

View File

@ -34,6 +34,7 @@ const Select = ({
inputWidth,
renderValue = null,
width = "100%",
maxWidth = "100%"
}) => {
const theme = useTheme();
return (
@ -41,6 +42,7 @@ const Select = ({
display="flex"
flexDirection="column"
width={width}
maxWidth={maxWidth}
sx={{ backgroundColor: theme.colors.gray[750] }}
borderRadius="12px"
padding="15px"

View File

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

View File

@ -311,6 +311,7 @@ const TokenAndBooleansArguments = ({
value={selectedOption ?? ""}
onChange={handleChange}
options={possibleTokens}
maxWidth="calc(100vw - 70px)"
inputWidth="100%"
renderValue={(selected) => {
if (!selected || selected.length === 0) {

View File

@ -55,7 +55,7 @@ export const SetAdjustmentSteps = ({ chainId, toInitialStep, addCalldata, args }
const [rate, setRate] = useState(args?.at(0));
const [target, setTarget] = useState(args?.at(1));
const [increase, setIncrease] = useState(args?.at(1) ?? true);
const [increase, setIncrease] = useState(args === undefined ? true : args.at(2));
const handleProceed = () => {
addCalldata(prepareSetAdjustmentCalldata(chainId, rate, target, increase));

View File

@ -257,7 +257,6 @@ export const ArgumentInput = ({
)
}
// TODO: rename
export const ParsedCell = (props) => {
const [isCopied, setIsCopied] = useState(false);

View File

@ -8,15 +8,24 @@ import { useUnstableProvider } from "./UnstableProvider"
const MetadataProvider = createContext(null)
export const useMetadata = () => useContext(MetadataProvider)
const CACHE_VERSION = "v2"
export const MetadataProviderProvider = ({ children }) => {
const { client, chainId } = useUnstableProvider()
const { data: metadata } = useSWR(
client && chainId ? ["metadata", client, chainId] : null,
async ([_, client]) => {
const storageKey = `metadata-${chainId}`
const storageKey = `metadata-${chainId}-${CACHE_VERSION}`
const storedMetadata = sessionStorage.getItem(storageKey)
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) =>
client._request("state_getMetadata", [], {
onSuccess: resolve,

View File

@ -12,3 +12,5 @@ export * from "./useBlockCommitments";
export * from "./useApplauseDetails";
export * from "./useBabeSlots";
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 { useMetadata } from "./MetadataProvider"
export const useErasTotalStake = ({ eraIndex }) => {
export const useErasTotalStake = ({ epochIndex }) => {
const { chainHead$, chainId } = useUnstableProvider()
const metadata = useMetadata()
const { data: eraTotalStake } = useSWRSubscription(
chainHead$ && chainId && metadata
? ["eraTotalStake", chainHead$, eraIndex, chainId, metadata]
? ["eraTotalStake", chainHead$, epochIndex, chainId, metadata]
: null,
([_, chainHead$, eraIndex, chainId, metadata], { next }) => {
([_, chainHead$, epochIndex, chainId, metadata], { next }) => {
const { finalized$, storage$ } = chainHead$
const subscription = finalized$.pipe(
filter(Boolean),
@ -20,7 +20,7 @@ export const useErasTotalStake = ({ eraIndex }) => {
const builder = getDynamicBuilder(getLookupFn(metadata))
const eraTotalStake = builder.buildStorage("Staking", "ErasTotalStake")
return storage$(blockInfo?.hash, "value", () =>
eraTotalStake?.keys.enc(eraIndex)
eraTotalStake?.keys.enc(epochIndex)
).pipe(
filter(Boolean),
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;
}