Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validators list #1621

Merged
merged 12 commits into from
Feb 19, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions configs/app/features/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ export { default as suave } from './suave';
export { default as swapButton } from './swapButton';
export { default as txInterpretation } from './txInterpretation';
export { default as userOps } from './userOps';
export { default as validators } from './validators';
export { default as verifiedTokens } from './verifiedTokens';
export { default as web3Wallet } from './web3Wallet';
29 changes: 29 additions & 0 deletions configs/app/features/validators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { Feature } from './types';
import { VALIDATORS_CHAIN_TYPE } from 'types/client/validators';
import type { ValidatorsChainType } from 'types/client/validators';

import { getEnvValue } from '../utils';

const chainType = ((): ValidatorsChainType | undefined => {
const envValue = getEnvValue('NEXT_PUBLIC_VALIDATORS_CHAIN_TYPE') as ValidatorsChainType | undefined;
return envValue && VALIDATORS_CHAIN_TYPE.includes(envValue) ? envValue : undefined;
})();

const title = 'Validators list';

const config: Feature<{ chainType: ValidatorsChainType }> = (() => {
if (chainType) {
return Object.freeze({
title,
isEnabled: true,
chainType,
});
}

return Object.freeze({
title,
isEnabled: false,
});
})();

export default config;
3 changes: 3 additions & 0 deletions deploy/tools/envs-validator/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import type { NavItemExternal, NavigationLinkId } from '../../../types/client/na
import { ROLLUP_TYPES } from '../../../types/client/rollup';
import type { BridgedTokenChain, TokenBridge } from '../../../types/client/token';
import { PROVIDERS as TX_INTERPRETATION_PROVIDERS } from '../../../types/client/txInterpretation';
import { VALIDATORS_CHAIN_TYPE } from '../../../types/client/validators';
import type { ValidatorsChainType } from '../../../types/client/validators';
import type { WalletType } from '../../../types/client/wallets';
import { SUPPORTED_WALLETS } from '../../../types/client/wallets';
import type { CustomLink, CustomLinksGroup } from '../../../types/footerLinks';
Expand Down Expand Up @@ -476,6 +478,7 @@ const schema = yup
NEXT_PUBLIC_IS_SUAVE_CHAIN: yup.boolean(),
NEXT_PUBLIC_HAS_USER_OPS: yup.boolean(),
NEXT_PUBLIC_SWAP_BUTTON_URL: yup.string(),
NEXT_PUBLIC_VALIDATORS_CHAIN_TYPE: yup.string<ValidatorsChainType>().oneOf(VALIDATORS_CHAIN_TYPE),

// 6. External services envs
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: yup.string(),
Expand Down
1 change: 1 addition & 0 deletions deploy/tools/envs-validator/test/.env.base
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,4 @@ NEXT_PUBLIC_VISUALIZE_API_HOST=https://example.com
NEXT_PUBLIC_WEB3_DISABLE_ADD_TOKEN_TO_WALLET=false
NEXT_PUBLIC_WEB3_WALLETS=['coinbase','metamask','token_pocket']
NEXT_PUBLIC_SWAP_BUTTON_URL=uniswap
NEXT_PUBLIC_VALIDATORS_CHAIN_TYPE=stability
3 changes: 2 additions & 1 deletion deploy/values/review/values.yaml.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ frontend:
NEXT_PUBLIC_FEATURED_NETWORKS: https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/featured-networks/eth-goerli.json
NEXT_PUBLIC_NETWORK_LOGO: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/goerli.svg
NEXT_PUBLIC_NETWORK_ICON: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/goerli.svg
NEXT_PUBLIC_API_HOST: eth-goerli.blockscout.com
NEXT_PUBLIC_API_HOST: stability-testnet.blockscout.com
tom2drum marked this conversation as resolved.
Show resolved Hide resolved
NEXT_PUBLIC_STATS_API_HOST: https://stats-goerli.k8s-dev.blockscout.com/
NEXT_PUBLIC_VISUALIZE_API_HOST: http://visualizer-svc.visualizer-testing.svc.cluster.local/
NEXT_PUBLIC_CONTRACT_INFO_API_HOST: https://contracts-info-test.k8s-dev.blockscout.com
Expand All @@ -77,6 +77,7 @@ frontend:
NEXT_PUBLIC_HAS_USER_OPS: true
NEXT_PUBLIC_CONTRACT_CODE_IDES: "[{'title':'Remix IDE','url':'https://remix.blockscout.com/?address={hash}&blockscout=eth-goerli.blockscout.com','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]"
NEXT_PUBLIC_SWAP_BUTTON_URL: uniswap
NEXT_PUBLIC_VALIDATORS_CHAIN_TYPE: stability
envFromSecret:
NEXT_PUBLIC_SENTRY_DSN: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_SENTRY_DSN
SENTRY_CSP_REPORT_URI: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/SENTRY_CSP_REPORT_URI
Expand Down
10 changes: 10 additions & 0 deletions docs/ENVS.md
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,16 @@ For blockchains that implement SUAVE architecture additional fields will be show

&nbsp;

### Validators list

The feature enables the Validators page which provides detailed information about the validators of the PoS chains.

| Variable | Type| Description | Compulsoriness | Default value | Example value |
| --- | --- | --- | --- | --- | --- |
| NEXT_PUBLIC_VALIDATORS_CHAIN_TYPE | `'stability'` | Chain type | Required | - | `'stability'` |

&nbsp;

### Sentry error monitoring

| Variable | Type| Description | Compulsoriness | Default value | Example value |
Expand Down
3 changes: 3 additions & 0 deletions icons/validator.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 21 additions & 3 deletions lib/api/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ import type { TxInterpretationResponse } from 'types/api/txInterpretation';
import type { TTxsFilters } from 'types/api/txsFilters';
import type { TxStateChanges } from 'types/api/txStateChanges';
import type { UserOpsResponse, UserOp, UserOpsFilters, UserOpsAccount } from 'types/api/userOps';
import type { ValidatorsCountersResponse, ValidatorsFilters, ValidatorsResponse, ValidatorsSorting } from 'types/api/validators';
import type { VerifiedContractsSorting } from 'types/api/verifiedContracts';
import type { VisualizedContract } from 'types/api/visualization';
import type { WithdrawalsResponse, WithdrawalsCounters } from 'types/api/withdrawals';
Expand Down Expand Up @@ -615,6 +616,17 @@ export const RESOURCES = {
pathParams: [ 'hash' as const ],
},

// VALIDATORS
validators: {
path: '/api/v2/validators/:chainType',
pathParams: [ 'chainType' as const ],
filterFields: [ 'address_hash' as const, 'state' as const ],
},
validators_counters: {
path: '/api/v2/validators/:chainType/counters',
pathParams: [ 'chainType' as const ],
},

// CONFIGS
config_backend_version: {
path: '/api/v2/config/backend-version',
Expand Down Expand Up @@ -687,7 +699,7 @@ export type PaginatedResources = 'blocks' | 'block_txs' |
'zkevm_l2_txn_batches' | 'zkevm_l2_txn_batch_txs' |
'withdrawals' | 'address_withdrawals' | 'block_withdrawals' |
'watchlist' | 'private_tags_address' | 'private_tags_tx' |
'domains_lookup' | 'addresses_lookup' | 'user_ops';
'domains_lookup' | 'addresses_lookup' | 'user_ops' | 'validators';

export type PaginatedResponse<Q extends PaginatedResources> = ResourcePayload<Q>;

Expand Down Expand Up @@ -805,15 +817,19 @@ never;
export type ResourcePayloadB<Q extends ResourceName> =
Q extends 'marketplace_dapps' ? Array<MarketplaceAppOverview> :
Q extends 'marketplace_dapp' ? MarketplaceAppOverview :
Q extends 'validators' ? ValidatorsResponse :
Q extends 'validators_counters' ? ValidatorsCountersResponse :
never;
/* eslint-enable @typescript-eslint/indent */

export type ResourcePayload<Q extends ResourceName> = ResourcePayloadA<Q> | ResourcePayloadB<Q>;

// Right now there is no paginated resources in B-part
// Add "| ResourcePayloadB<Q>[...]" if it is not true anymore
export type PaginatedResponseItems<Q extends ResourceName> = Q extends PaginatedResources ? ResourcePayloadA<Q>['items'] : never;
export type PaginatedResponseNextPageParams<Q extends ResourceName> = Q extends PaginatedResources ? ResourcePayloadA<Q>['next_page_params'] : never;
export type PaginatedResponseItems<Q extends ResourceName> = Q extends PaginatedResources ? ResourcePayloadA<Q>['items'] | ResourcePayloadB<Q>['items'] : never;
export type PaginatedResponseNextPageParams<Q extends ResourceName> = Q extends PaginatedResources ?
ResourcePayloadA<Q>['next_page_params'] | ResourcePayloadB<Q>['next_page_params'] :
never;

/* eslint-disable @typescript-eslint/indent */
export type PaginationFilters<Q extends PaginatedResources> =
Expand All @@ -834,6 +850,7 @@ Q extends 'verified_contracts' ? VerifiedContractsFilters :
Q extends 'addresses_lookup' ? EnsAddressLookupFilters :
Q extends 'domains_lookup' ? EnsDomainLookupFilters :
Q extends 'user_ops' ? UserOpsFilters :
Q extends 'validators' ? ValidatorsFilters :
never;
/* eslint-enable @typescript-eslint/indent */

Expand All @@ -845,5 +862,6 @@ Q extends 'verified_contracts' ? VerifiedContractsSorting :
Q extends 'address_txs' ? TransactionsSorting :
Q extends 'addresses_lookup' ? EnsLookupSorting :
Q extends 'domains_lookup' ? EnsLookupSorting :
Q extends 'validators' ? ValidatorsSorting :
never;
/* eslint-enable @typescript-eslint/indent */
9 changes: 9 additions & 0 deletions lib/hooks/useNavItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ export default function useNavItems(): ReturnType {
icon: 'ENS',
isActive: pathname === '/name-domains' || pathname === '/name-domains/[name]',
} : null;
const validators = config.features.validators.isEnabled ? {
text: 'Top validators',
nextRoute: { pathname: '/validators' as const },
icon: 'validator',
isActive: pathname === '/validators',
} : null;

const rollupFeature = config.features.rollup;

Expand All @@ -84,6 +90,7 @@ export default function useNavItems(): ReturnType {
].filter(Boolean),
[
topAccounts,
validators,
verifiedContracts,
ensLookup,
].filter(Boolean),
Expand All @@ -107,6 +114,7 @@ export default function useNavItems(): ReturnType {
[
userOps,
topAccounts,
validators,
verifiedContracts,
ensLookup,
].filter(Boolean),
Expand All @@ -117,6 +125,7 @@ export default function useNavItems(): ReturnType {
userOps,
blocks,
topAccounts,
validators,
verifiedContracts,
ensLookup,
config.features.beaconChain.isEnabled && {
Expand Down
1 change: 1 addition & 0 deletions lib/metadata/getPageOgType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const OG_TYPE_DICT: Record<Route['pathname'], OGPageType> = {
'/404': 'Regular page',
'/name-domains': 'Root page',
'/name-domains/[name]': 'Regular page',
'/validators': 'Root page',

// service routes, added only to make typescript happy
'/login': 'Regular page',
Expand Down
1 change: 1 addition & 0 deletions lib/metadata/templates/description.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/404': DEFAULT_TEMPLATE,
'/name-domains': DEFAULT_TEMPLATE,
'/name-domains/[name]': DEFAULT_TEMPLATE,
'/validators': DEFAULT_TEMPLATE,

// service routes, added only to make typescript happy
'/login': DEFAULT_TEMPLATE,
Expand Down
1 change: 1 addition & 0 deletions lib/metadata/templates/title.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = {
'/404': 'error - page not found',
'/name-domains': 'domains search and resolve',
'/name-domains/[name]': '%name% domain details',
'/validators': 'validators list',

// service routes, added only to make typescript happy
'/login': 'login',
Expand Down
1 change: 1 addition & 0 deletions lib/mixpanel/getPageType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export const PAGE_TYPE_DICT: Record<Route['pathname'], string> = {
'/404': '404',
'/name-domains': 'Domains search and resolve',
'/name-domains/[name]': 'Domain details',
'/validators': 'Validators list',

// service routes, added only to make typescript happy
'/login': 'Login',
Expand Down
33 changes: 33 additions & 0 deletions mocks/validators/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { Validator, ValidatorsCountersResponse, ValidatorsResponse } from 'types/api/validators';

import * as addressMock from '../address/address';

export const validator1: Validator = {
address: addressMock.withName,
blocks_validated_count: 7334224,
state: 'active',
};

export const validator2: Validator = {
address: addressMock.withEns,
blocks_validated_count: 8937453,
state: 'probation',
};

export const validator3: Validator = {
address: addressMock.withoutName,
blocks_validated_count: 1234,
state: 'inactive',
};

export const validatorsResponse: ValidatorsResponse = {
items: [ validator1, validator2, validator3 ],
next_page_params: null,
};

export const validatorsCountersResponse: ValidatorsCountersResponse = {
active_validators_counter: '42',
active_validators_percentage: 7.14,
new_validators_counter_24h: '11',
validators_counter: '140',
};
10 changes: 10 additions & 0 deletions nextjs/getServerSideProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,13 @@ export const userOps: GetServerSideProps<Props> = async(context) => {

return base(context);
};

export const validators: GetServerSideProps<Props> = async(context) => {
if (!config.features.validators.isEnabled) {
return {
notFound: true,
};
}

return base(context);
};
1 change: 1 addition & 0 deletions nextjs/nextjs-routes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ declare module "nextjs-routes" {
| DynamicRoute<"/tx/[hash]", { "hash": string }>
| StaticRoute<"/txs">
| DynamicRoute<"/txs/kettle/[hash]", { "hash": string }>
| StaticRoute<"/validators">
| StaticRoute<"/verified-contracts">
| StaticRoute<"/visualize/sol2uml">
| StaticRoute<"/withdrawals">;
Expand Down
19 changes: 19 additions & 0 deletions pages/validators.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import React from 'react';

import PageNextJs from 'nextjs/PageNextJs';

const Validators = dynamic(() => import('ui/pages/Validators'), { ssr: false });

const Page: NextPage = () => {
return (
<PageNextJs pathname="/validators">
<Validators/>
</PageNextJs>
);
};

export default Page;

export { validators as getServerSideProps } from 'nextjs/getServerSideProps';
3 changes: 3 additions & 0 deletions playwright/utils/configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ export const featureEnvs = {
userOps: [
{ name: 'NEXT_PUBLIC_HAS_USER_OPS', value: 'true' },
],
validators: [
{ name: 'NEXT_PUBLIC_VALIDATORS_CHAIN_TYPE', value: 'stability' },
],
};

export const viewsEnvs = {
Expand Down
1 change: 1 addition & 0 deletions public/icons/name.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@
| "uniswap"
| "user_op_slim"
| "user_op"
| "validator"
| "verified_token"
| "verified"
| "verify-contract"
Expand Down
9 changes: 8 additions & 1 deletion stubs/contract.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { SmartContract, SolidityscanReport } from 'types/api/contract';
import type { VerifiedContract } from 'types/api/contracts';
import type { VerifiedContract, VerifiedContractsCounters } from 'types/api/contracts';

import { ADDRESS_PARAMS } from './addressParams';

Expand Down Expand Up @@ -54,6 +54,13 @@ export const VERIFIED_CONTRACT_INFO: VerifiedContract = {
verified_at: '2023-04-10T13:16:33.884921Z',
};

export const VERIFIED_CONTRACTS_COUNTERS: VerifiedContractsCounters = {
smart_contracts: '123456789',
new_smart_contracts_24h: '12345',
verified_smart_contracts: '654321',
new_verified_smart_contracts_24h: '1234',
};

export const SOLIDITYSCAN_REPORT: SolidityscanReport = {
scan_report: {
scan_status: 'scan_done',
Expand Down
16 changes: 16 additions & 0 deletions stubs/validators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { Validator, ValidatorsCountersResponse } from 'types/api/validators';

import { ADDRESS_PARAMS } from './addressParams';

export const VALIDATOR: Validator = {
address: ADDRESS_PARAMS,
blocks_validated_count: 25987,
state: 'active',
};

export const VALIDATORS_COUNTERS: ValidatorsCountersResponse = {
active_validators_counter: '42',
active_validators_percentage: 7.14,
new_validators_counter_24h: '11',
validators_counter: '140',
};
Loading