mirror of
https://github.com/luxfi/explore.git
synced 2026-07-27 05:54:15 +00:00
fix(validators): use weight field and correct uptime format for P-chain validators
- P-chain API returns weight not stakeAmount; fallback to weight when stakeAmount absent - uptime from API is already 0-100 percentage, not 0-1 fraction; remove double-multiply - mark connected and stakeAmount as optional to match actual API response shape
This commit is contained in:
@@ -20,12 +20,12 @@ export interface PChainValidator {
|
||||
readonly txID: string;
|
||||
readonly startTime: string;
|
||||
readonly endTime: string;
|
||||
readonly stakeAmount: string;
|
||||
readonly stakeAmount?: string; // may be absent; use weight instead
|
||||
readonly nodeID: string;
|
||||
readonly weight: string;
|
||||
readonly delegationFee: string;
|
||||
readonly potentialReward: string;
|
||||
readonly connected: boolean;
|
||||
readonly connected?: boolean;
|
||||
readonly uptime: string;
|
||||
readonly delegators: ReadonlyArray<PChainDelegator> | null;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import { getPChain } from './client';
|
||||
|
||||
const VALIDATORS_STALE_TIME_MS = 60_000;
|
||||
const VALIDATORS_QUERY_KEY = 'pchain:currentValidators' as const;
|
||||
const UPTIME_PERCENTAGE_SCALE = 100;
|
||||
const ZERO = BigInt(0);
|
||||
|
||||
function computeValidatorStats(
|
||||
@@ -27,7 +26,7 @@ function computeValidatorStats(
|
||||
let uptimeSum = 0;
|
||||
|
||||
for (const v of validators) {
|
||||
totalStake += BigInt(v.stakeAmount);
|
||||
totalStake += BigInt(v.stakeAmount ?? v.weight);
|
||||
|
||||
if (v.connected) {
|
||||
connectedCount += 1;
|
||||
@@ -43,8 +42,9 @@ function computeValidatorStats(
|
||||
}
|
||||
}
|
||||
|
||||
// uptime values from the API are already in percentage (0–100); no scaling needed
|
||||
const averageUptime = validators.length > 0 ?
|
||||
(uptimeSum / validators.length) * UPTIME_PERCENTAGE_SCALE :
|
||||
uptimeSum / validators.length :
|
||||
0;
|
||||
|
||||
return {
|
||||
|
||||
@@ -99,8 +99,8 @@ interface ActiveValidatorsTableProps {
|
||||
const ActiveValidatorsTable = ({ validators, isLoading }: ActiveValidatorsTableProps) => {
|
||||
const sorted = React.useMemo(
|
||||
() => [ ...validators ].sort((a, b) => {
|
||||
const aStake = BigInt(a.stakeAmount);
|
||||
const bStake = BigInt(b.stakeAmount);
|
||||
const aStake = BigInt(a.stakeAmount ?? a.weight);
|
||||
const bStake = BigInt(b.stakeAmount ?? b.weight);
|
||||
if (bStake > aStake) return 1;
|
||||
if (bStake < aStake) return -1;
|
||||
return 0;
|
||||
@@ -181,14 +181,14 @@ const ActiveValidatorsTable = ({ validators, isLoading }: ActiveValidatorsTableP
|
||||
{ truncateNodeId(v.nodeID) }
|
||||
</Box>
|
||||
<Box flex={ 1 } fontSize="sm" color="text.primary" textAlign={{ base: 'left', lg: 'right' }}>
|
||||
{ formatStake(v.stakeAmount) } LUX
|
||||
{ formatStake(v.stakeAmount ?? v.weight) } LUX
|
||||
</Box>
|
||||
<Box w={{ base: 'auto', lg: '120px' }} flexShrink={ 0 } fontSize="sm" color="text.secondary" textAlign={{ base: 'left', lg: 'right' }}>
|
||||
{ v.delegationFee }%
|
||||
</Box>
|
||||
<Flex w={{ base: 'auto', lg: '80px' }} flexShrink={ 0 } justifyContent={{ base: 'flex-start', lg: 'center' }} alignItems="center">
|
||||
<Box
|
||||
bgColor={ v.connected ? 'green.400' : 'red.400' }
|
||||
bgColor={ v.connected !== false ? 'green.400' : 'red.400' }
|
||||
borderRadius="full"
|
||||
boxSize="8px"
|
||||
/>
|
||||
|
||||
@@ -33,8 +33,8 @@ const ValidatorsList = ({ validators, isLoading }: ValidatorsListProps) => {
|
||||
// Sort by stake desc, then filter by search
|
||||
const filtered = React.useMemo(() => {
|
||||
const sorted = [ ...validators ].sort((a, b) => {
|
||||
const aStake = BigInt(a.stakeAmount);
|
||||
const bStake = BigInt(b.stakeAmount);
|
||||
const aStake = BigInt(a.stakeAmount ?? a.weight);
|
||||
const bStake = BigInt(b.stakeAmount ?? b.weight);
|
||||
if (bStake > aStake) return 1;
|
||||
if (bStake < aStake) return -1;
|
||||
return 0;
|
||||
@@ -158,7 +158,7 @@ const ValidatorsList = ({ validators, isLoading }: ValidatorsListProps) => {
|
||||
{ truncateNodeId(v.nodeID) }
|
||||
</Box>
|
||||
<Box flex={ 1 } fontSize="sm" color="text.primary" textAlign={{ base: 'left', lg: 'right' }}>
|
||||
{ formatStake(v.stakeAmount) } LUX
|
||||
{ formatStake(v.stakeAmount ?? v.weight) } LUX
|
||||
</Box>
|
||||
<Box w={{ base: 'auto', lg: '120px' }} flexShrink={ 0 } fontSize="sm" color="text.secondary" textAlign={{ base: 'left', lg: 'right' }}>
|
||||
{ v.delegationFee }%
|
||||
@@ -168,7 +168,7 @@ const ValidatorsList = ({ validators, isLoading }: ValidatorsListProps) => {
|
||||
</Box>
|
||||
<Flex w={{ base: 'auto', lg: '80px' }} flexShrink={ 0 } justifyContent={{ base: 'flex-start', lg: 'center' }} alignItems="center">
|
||||
<Box
|
||||
bgColor={ v.connected ? 'green.400' : 'red.400' }
|
||||
bgColor={ v.connected !== false ? 'green.400' : 'red.400' }
|
||||
borderRadius="full"
|
||||
boxSize="8px"
|
||||
/>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
const LUX_DECIMALS = 9;
|
||||
const TRUNCATE_PREFIX_LEN = 12;
|
||||
const TRUNCATE_SUFFIX_LEN = 6;
|
||||
const UPTIME_PERCENTAGE_SCALE = 100;
|
||||
const UPTIME_FRACTION_DIGITS = 2;
|
||||
const STAKE_FRACTION_DIGITS = 2;
|
||||
|
||||
@@ -14,7 +13,8 @@ export function formatStake(nanoLux: bigint | string): string {
|
||||
}
|
||||
|
||||
export function formatUptime(uptime: string): string {
|
||||
return `${ (parseFloat(uptime) * UPTIME_PERCENTAGE_SCALE).toFixed(UPTIME_FRACTION_DIGITS) }%`;
|
||||
// uptime is already in percentage format (0–100), no scaling needed
|
||||
return `${ parseFloat(uptime).toFixed(UPTIME_FRACTION_DIGITS) }%`;
|
||||
}
|
||||
|
||||
export function truncateNodeId(nodeId: string): string {
|
||||
|
||||
Reference in New Issue
Block a user