mirror of
https://github.com/lux-tel/websites.git
synced 2026-10-30 20:31:36 +00:00
165 lines
5.3 KiB
TypeScript
165 lines
5.3 KiB
TypeScript
import { STAKE_STATE, parseStakeState } from '@/components/StakedNode/state';
|
|
import { parseStakes } from '@/hooks/parseStakes';
|
|
import { BACKEND, BLOCK_TIME_MS, PREFERENCE, SESSION_NODE } from '@/lib/constants';
|
|
import { NEXT_PUBLIC_TESTNET } from '@/lib/env';
|
|
import logger from '@/lib/logger';
|
|
import { getStakedNodes } from '@/lib/queries/getStakedNodes';
|
|
import { useStakingBackendQueryWithParams } from '@/lib/staking-api-client';
|
|
import { useNodesWithConfirmations } from '@/lib/volatile-storage';
|
|
import { bigIntToNumber } from '@session/util-crypto/maths';
|
|
import { areHexesEqual } from '@session/util-crypto/string';
|
|
import { safeTrySyncWithFallback } from '@session/util-js/try';
|
|
import { useBlockNumber } from '@session/wallet/hooks/useBlockNumber';
|
|
import { useWallet } from '@session/wallet/hooks/useWallet';
|
|
import { useMemo } from 'react';
|
|
import { usePreferences } from 'usepref';
|
|
import type { Address } from 'viem';
|
|
import { arbitrum, arbitrumSepolia } from 'viem/chains';
|
|
|
|
/**
|
|
* Hook to get the stakes and related data for the connected wallet.
|
|
* @param overrideAddress - override address, this overrides the connected address
|
|
* @param overrideRefetchIntervalMs - override refetch interval
|
|
* @returns The stakes and related data for the connected wallet.
|
|
*/
|
|
export function useStakes(overrideAddress?: Address, overrideRefetchIntervalMs?: number) {
|
|
const { address: connectedAddress } = useWallet();
|
|
const address = overrideAddress ?? connectedAddress;
|
|
const { getItem } = usePreferences();
|
|
const enabled = !!address;
|
|
const autoRefresh = !getItem<boolean>(PREFERENCE.DISABLE_BACKEND_AUTO_REFRESH);
|
|
|
|
const { data: arbBlock } = useBlockNumber({
|
|
chainId: NEXT_PUBLIC_TESTNET ? arbitrumSepolia.id : arbitrum.id,
|
|
query: {
|
|
gcTime: overrideRefetchIntervalMs ?? BACKEND.NODE_TARGET_UPDATE_INTERVAL_SECONDS * 1000,
|
|
},
|
|
});
|
|
|
|
const { data, isLoading, isFetching, refetch, isError, status } =
|
|
useStakingBackendQueryWithParams(
|
|
getStakedNodes,
|
|
{
|
|
address: address!,
|
|
},
|
|
{
|
|
enabled,
|
|
refetchInterval: autoRefresh
|
|
? (overrideRefetchIntervalMs ?? BACKEND.NODE_TARGET_UPDATE_INTERVAL_SECONDS * 1000)
|
|
: undefined,
|
|
}
|
|
);
|
|
|
|
const {
|
|
nodes: { nodesConfirmingRegistration },
|
|
} = useNodesWithConfirmations();
|
|
|
|
const {
|
|
stakes,
|
|
vesting,
|
|
hiddenContractsWithStakes,
|
|
awaitingOperatorContracts,
|
|
networkContractIds,
|
|
visibleContracts,
|
|
networkBlsKeys,
|
|
joiningContracts,
|
|
network,
|
|
blockHeight,
|
|
networkTime,
|
|
} = useMemo(() => {
|
|
const [networkError, network] = safeTrySyncWithFallback(() => data?.network ?? null, null);
|
|
if (networkError) logger.error(networkError);
|
|
|
|
const [blockHeightError, blockHeight] = safeTrySyncWithFallback(
|
|
() => network?.block_height ?? 0,
|
|
0
|
|
);
|
|
if (blockHeightError) logger.error(blockHeightError);
|
|
|
|
const [networkTimeError, networkTime] = safeTrySyncWithFallback(
|
|
() => network?.block_timestamp ?? 0,
|
|
0
|
|
);
|
|
if (networkTimeError) logger.error(networkTimeError);
|
|
|
|
const [stakesError, stakes] = safeTrySyncWithFallback(() => data?.stakes ?? [], []);
|
|
if (stakesError) logger.error(stakesError);
|
|
|
|
const [addedBlsKeysSetsError, addedBlsKeys] = safeTrySyncWithFallback(
|
|
() => data?.added_bls_keys ?? {},
|
|
{}
|
|
);
|
|
if (addedBlsKeysSetsError) logger.error(addedBlsKeysSetsError);
|
|
|
|
const [vestingErr, vesting] = safeTrySyncWithFallback(() => data?.vesting ?? [], []);
|
|
if (vestingErr) logger.error(vestingErr);
|
|
|
|
const [contractsErr, contracts] = safeTrySyncWithFallback(() => data?.contracts ?? [], []);
|
|
if (contractsErr) logger.error(contractsErr);
|
|
|
|
// Minimum time in blocks that a node can go from "joining" to "exited"
|
|
const nodeMinLifespanArbBlocks =
|
|
(arbBlock ? bigIntToNumber(arbBlock, 0) : 0) -
|
|
SESSION_NODE.INITIAL_DOWNTIME_CREDITS_MS / BLOCK_TIME_MS.ARBITRUM;
|
|
|
|
return {
|
|
...parseStakes({
|
|
contracts,
|
|
address,
|
|
blockHeight,
|
|
addedBlsKeys,
|
|
nodeMinLifespanArbBlocks,
|
|
stakes,
|
|
vesting,
|
|
}),
|
|
network,
|
|
networkTime,
|
|
};
|
|
}, [data, address, arbBlock]);
|
|
|
|
const notFoundJoiningNodes = useMemo(
|
|
() =>
|
|
nodesConfirmingRegistration.filter((node) => {
|
|
return (
|
|
areHexesEqual(node.confirmationOwner, address) &&
|
|
!joiningContracts.some(
|
|
({ pubkey_bls, service_node_pubkey }) =>
|
|
pubkey_bls === node.pubkeyBls ||
|
|
areHexesEqual(service_node_pubkey, node.pubkeyEd25519)
|
|
) &&
|
|
!stakes.some((stake) => {
|
|
const state = parseStakeState(stake, blockHeight);
|
|
if (state === STAKE_STATE.DEREGISTERED) {
|
|
return false;
|
|
}
|
|
return (
|
|
stake.pubkey_bls === node.pubkeyBls || stake.pubkey_ed25519 === node.pubkeyEd25519
|
|
);
|
|
})
|
|
);
|
|
}),
|
|
[nodesConfirmingRegistration, stakes, joiningContracts, blockHeight, address]
|
|
);
|
|
|
|
return {
|
|
stakes,
|
|
visibleContracts,
|
|
joiningContracts,
|
|
notFoundJoiningNodes,
|
|
awaitingOperatorContracts,
|
|
vesting,
|
|
hiddenContractsWithStakes,
|
|
networkBlsKeys,
|
|
networkContractIds,
|
|
network,
|
|
blockHeight,
|
|
networkTime,
|
|
refetch,
|
|
isLoading,
|
|
isFetching,
|
|
isError,
|
|
status,
|
|
enabled,
|
|
};
|
|
}
|