-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: Add validators endpoint. Add validators collections job with ValidatorService. * feat: Add committee cache and validators/stats endpoint * feat: Add inCommittee flag to IValidatorsResponse * fix: Change stakers field to validators now that is fixed * feat: Add validator stats endpoint * feat: Fix validator stats computation * feat: Add Validators route/page (WiP) * feat: Add validators table (with hardcoded data) * feat: Update IValidatorsResponse to match api * feat: Remove hardcoded validator from page and rehook the hook * fix: Ignore eslint unresolved nova SDK import * chore: Ignore more eslint no-unsafe for SDK (CI) * feat: Align table columns with requirements * fix: Remove rank by stake computation (as Chronicle already returns results sorted by stake) * feat: Rename cumulative stake header to pool stake
- Loading branch information
Showing
6 changed files
with
229 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
@import "../../../scss/fonts"; | ||
@import "../../../scss/mixins"; | ||
@import "../../../scss/media-queries"; | ||
@import "../../../scss/variables"; | ||
|
||
.validators-page { | ||
display: flex; | ||
flex-direction: column; | ||
|
||
.wrapper { | ||
display: flex; | ||
justify-content: center; | ||
|
||
.inner { | ||
display: flex; | ||
flex: 1; | ||
flex-direction: column; | ||
max-width: $desktop-width; | ||
margin: 40px 25px; | ||
|
||
@include desktop-down { | ||
flex: unset; | ||
width: 100%; | ||
max-width: 100%; | ||
margin: 40px 24px; | ||
padding-right: 24px; | ||
padding-left: 24px; | ||
|
||
> .row { | ||
flex-direction: column; | ||
} | ||
} | ||
|
||
@include tablet-down { | ||
margin: 28px 0; | ||
} | ||
|
||
.validators-page__header { | ||
display: flex; | ||
flex-direction: column; | ||
align-items: flex-start; | ||
|
||
.header__title { | ||
margin-bottom: 8px; | ||
} | ||
} | ||
|
||
.all-validators__section { | ||
font-family: $metropolis; | ||
margin-top: 40px; | ||
background-color: $gray-1; | ||
border-radius: 8px; | ||
|
||
.all-validators__header { | ||
width: fit-content; | ||
margin: 0 auto; | ||
padding: 20px; | ||
} | ||
|
||
.all-validators__wrapper { | ||
margin: 0 20px 20px; | ||
|
||
.validator-item { | ||
display: grid; | ||
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr; | ||
margin: 0px 12px; | ||
align-items: center; | ||
line-height: 32px; | ||
justify-content: center; | ||
background-color: $gray-3; | ||
border-radius: 4px; | ||
|
||
&.table-header { | ||
background-color: $gray-5; | ||
} | ||
|
||
&:not(:last-child) { | ||
margin-bottom: 12px; | ||
} | ||
|
||
.validator-item__address, | ||
.validator-item__is-candidate, | ||
.validator-item__is-elected, | ||
.validator-item__fixed-cost, | ||
.validator-item__stake, | ||
.validator-item__cumulative-stake, | ||
.validator-item__delegators, | ||
.validator-item__rank { | ||
display: flex; | ||
margin: 0 auto; | ||
justify-content: center; | ||
} | ||
|
||
.validator-item__stake { | ||
text-align: center; | ||
line-height: 20px; | ||
} | ||
|
||
.validator-item__address { | ||
width: 120px; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import React from "react"; | ||
import TruncatedId from "~/app/components/stardust/TruncatedId"; | ||
import { useValidators } from "~/helpers/nova/hooks/useValidators"; | ||
import "./ValidatorsPage.scss"; | ||
|
||
const ValidatorsPage: React.FC = () => { | ||
const { validators, error } = useValidators(); | ||
|
||
return ( | ||
<section className="validators-page"> | ||
<div className="wrapper"> | ||
<div className="inner"> | ||
<div className="validators-page__header"> | ||
<div className="header__title row middle"> | ||
<h1>Validators</h1> | ||
</div> | ||
</div> | ||
|
||
{validators !== null && ( | ||
<div className="all-validators__section"> | ||
<h2 className="all-validators__header">All Validators</h2> | ||
<div className="all-validators__wrapper"> | ||
<div className="validator-item table-header"> | ||
<div className="validator-item__address">Address</div> | ||
<div className="validator-item__is-candidate">Candidate?</div> | ||
<div className="validator-item__is-elected">Elected?</div> | ||
<div className="validator-item__fixed-cost">Fixed cost</div> | ||
<div className="validator-item__stake">Stake (Own/Delegated)</div> | ||
<div className="validator-item__cumulative-stake">Pool stake</div> | ||
<div className="validator-item__delegators">Delegators</div> | ||
<div className="validator-item__rank">Rank by stake</div> | ||
</div> | ||
{validators.map((validatorResponse, idx) => { | ||
const validator = validatorResponse.validator; | ||
const inCommittee = validatorResponse.inCommittee; | ||
const delegatedStake = validator.poolStake - validator.validatorStake; | ||
|
||
return ( | ||
<div className="validator-item" key={`validator-${idx}`}> | ||
<div className="validator-item__address"> | ||
<TruncatedId id={validator.address} /> | ||
</div> | ||
<div className="validator-item__is-candidate">{(!inCommittee).toString()}</div> | ||
<div className="validator-item__is-elected">{inCommittee.toString()}</div> | ||
<div className="validator-item__fixed-cost">{validator.fixedCost.toString()}</div> | ||
<div className="validator-item__stake"> | ||
{`${validator.validatorStake.toString()} / ${delegatedStake}`} | ||
</div> | ||
<div className="validator-item__cumulative-stake">{validator.poolStake.toString()}</div> | ||
<div className="validator-item__delegators">???</div> | ||
<div className="validator-item__rank">{idx + 1}</div> | ||
</div> | ||
); | ||
})} | ||
</div> | ||
</div> | ||
)} | ||
|
||
{error && <p className="danger">Failed to retrieve validators. {error}</p>} | ||
</div> | ||
</div> | ||
</section> | ||
); | ||
}; | ||
|
||
export default ValidatorsPage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { useEffect, useState } from "react"; | ||
import { ServiceFactory } from "~/factories/serviceFactory"; | ||
import { useIsMounted } from "~/helpers/hooks/useIsMounted"; | ||
import { IValidator } from "~/models/api/nova/IValidatorsResponse"; | ||
import { NOVA } from "~/models/config/protocolVersion"; | ||
import { NovaApiClient } from "~/services/nova/novaApiClient"; | ||
import { useNetworkInfoNova } from "../networkInfo"; | ||
|
||
export function useValidators(): { validators: IValidator[] | null; error: string | null } { | ||
const isMounted = useIsMounted(); | ||
const { name: network } = useNetworkInfoNova((s) => s.networkInfo); | ||
const [apiClient] = useState(ServiceFactory.get<NovaApiClient>(`api-client-${NOVA}`)); | ||
const [validators, setValidators] = useState<IValidator[] | null>(null); | ||
const [error, setError] = useState<string | null>(null); | ||
|
||
useEffect(() => { | ||
(async () => { | ||
const validatorsResponse = await apiClient.getValidators({ network }); | ||
|
||
if (isMounted) { | ||
if ((validatorsResponse.validators ?? []).length > 0) { | ||
setValidators(validatorsResponse.validators ?? null); | ||
} | ||
|
||
if (validatorsResponse.error) { | ||
setError(validatorsResponse.error); | ||
} | ||
} | ||
})(); | ||
}, [network]); | ||
|
||
return { validators, error }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { ValidatorResponse } from "@iota/sdk-wasm-nova/web"; | ||
import { IResponse } from "./IResponse"; | ||
|
||
export interface IValidator { | ||
validator: ValidatorResponse; | ||
inCommittee: boolean; | ||
} | ||
|
||
export interface IValidatorsResponse extends IResponse { | ||
validators?: IValidator[]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters