From d36e349cc67d610ce47bfb72adebd6dc26460e08 Mon Sep 17 00:00:00 2001 From: Fouad Date: Thu, 27 Oct 2022 10:34:11 +0100 Subject: [PATCH] Display routing scores for bonded gateway (#1693) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * access gateway report from node status api * Create 4 response types for gateway and mixnode uptime and status * Add the three remaining validator-client functions * display gatways routing scores * handle undefined gateway report Co-authored-by: Jon Häggblad --- .../src/validator_api/routes.rs | 1 - nym-wallet/src-tauri/src/main.rs | 1 + .../src/operations/validator_api/status.rs | 13 +++++- .../src/components/Bonding/BondedGateway.tsx | 45 +++++++++++++------ nym-wallet/src/context/bonding.tsx | 18 +++++++- nym-wallet/src/context/mocks/bonding.tsx | 4 ++ .../bonding/node-settings/NodeSettings.tsx | 2 +- .../settings-pages/NodeUnbondPage.tsx | 20 ++++++--- nym-wallet/src/requests/queries.ts | 5 ++- nym-wallet/src/types/global.ts | 8 ++++ 10 files changed, 92 insertions(+), 25 deletions(-) diff --git a/common/client-libs/validator-client/src/validator_api/routes.rs b/common/client-libs/validator-client/src/validator_api/routes.rs index 5100f59e05..64aa1b8cd9 100644 --- a/common/client-libs/validator-client/src/validator_api/routes.rs +++ b/common/client-libs/validator-client/src/validator_api/routes.rs @@ -10,7 +10,6 @@ pub const GATEWAYS: &str = "gateways"; pub const DETAILED: &str = "detailed"; pub const ACTIVE: &str = "active"; pub const REWARDED: &str = "rewarded"; - pub const COCONUT_ROUTES: &str = "coconut"; pub const BANDWIDTH: &str = "bandwidth"; diff --git a/nym-wallet/src-tauri/src/main.rs b/nym-wallet/src-tauri/src/main.rs index db6795ff49..9bd44028c2 100644 --- a/nym-wallet/src-tauri/src/main.rs +++ b/nym-wallet/src-tauri/src/main.rs @@ -100,6 +100,7 @@ fn main() { validator_api::status::mixnode_reward_estimation, validator_api::status::mixnode_stake_saturation, validator_api::status::mixnode_status, + validator_api::status::gateway_report, vesting::rewards::vesting_claim_delegator_reward, vesting::rewards::vesting_claim_operator_reward, vesting::bond::vesting_bond_gateway, diff --git a/nym-wallet/src-tauri/src/operations/validator_api/status.rs b/nym-wallet/src-tauri/src/operations/validator_api/status.rs index aefca433ce..16c83cfb67 100644 --- a/nym-wallet/src-tauri/src/operations/validator_api/status.rs +++ b/nym-wallet/src-tauri/src/operations/validator_api/status.rs @@ -6,8 +6,9 @@ use crate::error::BackendError; use crate::state::WalletState; use mixnet_contract_common::{IdentityKeyRef, MixId}; use validator_client::models::{ - GatewayCoreStatusResponse, InclusionProbabilityResponse, MixnodeCoreStatusResponse, - MixnodeStatusResponse, RewardEstimationResponse, StakeSaturationResponse, + GatewayCoreStatusResponse, GatewayStatusReportResponse, InclusionProbabilityResponse, + MixnodeCoreStatusResponse, MixnodeStatusResponse, RewardEstimationResponse, + StakeSaturationResponse, }; #[tauri::command] @@ -32,6 +33,14 @@ pub async fn gateway_core_node_status( .await?) } +#[tauri::command] +pub async fn gateway_report( + identity: IdentityKeyRef<'_>, + state: tauri::State<'_, WalletState>, +) -> Result { + Ok(api_client!(state).get_gateway_report(identity).await?) +} + #[tauri::command] pub async fn mixnode_status( mix_id: MixId, diff --git a/nym-wallet/src/components/Bonding/BondedGateway.tsx b/nym-wallet/src/components/Bonding/BondedGateway.tsx index 15a5d26367..305d261cca 100644 --- a/nym-wallet/src/components/Bonding/BondedGateway.tsx +++ b/nym-wallet/src/components/Bonding/BondedGateway.tsx @@ -1,26 +1,37 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import { Stack, Typography } from '@mui/material'; import { Link } from '@nymproject/react/link/Link'; import { TBondedGateway, urls } from 'src/context'; import { NymCard } from 'src/components'; import { Network } from 'src/types'; import { IdentityKey } from 'src/components/IdentityKey'; +import { getGatewayReport } from 'src/requests'; import { Cell, Header, NodeTable } from './NodeTable'; import { BondedGatewayActions, TBondedGatwayActions } from './BondedGatewayAction'; +import { Console } from 'src/utils/console'; const headers: Header[] = [ - { - header: 'IP', - id: 'ip', - sx: { pl: 0 }, - }, { header: 'Bond', id: 'bond', }, + + { + header: 'Routing score', + id: 'routing-score', + tooltipText: 'Routing score', + }, + { + header: 'Average score', + id: 'average-score', + tooltipText: 'Average score', + }, + { + header: 'IP', + id: 'ip', + }, { id: 'menu-button', - sx: { width: 34, maxWidth: 34 }, }, ]; @@ -33,18 +44,26 @@ export const BondedGateway = ({ network?: Network; onActionSelect: (action: TBondedGatwayActions) => void; }) => { - const { name, bond, ip, identityKey } = gateway; + const { name, bond, ip, identityKey, routingScore } = gateway; const cells: Cell[] = [ - { - cell: ip, - id: 'ip-cell', - }, { cell: `${bond.amount} ${bond.denom}`, id: 'bond-cell', sx: { pl: 0 }, }, + { + cell: `${routingScore?.current || '- '}%`, + id: 'routing-score-cell', + }, + { + cell: `${routingScore?.average || '- '}%`, + id: 'average-score-cell', + }, + { + cell: ip, + id: 'ip-cell', + }, { cell: , id: 'actions-cell', @@ -73,7 +92,7 @@ export const BondedGateway = ({ {network && ( - Check more stats of your node on the{' '} + Check more stats of your gateway on the{' '} explorer diff --git a/nym-wallet/src/context/bonding.tsx b/nym-wallet/src/context/bonding.tsx index 6f87921db6..dcecd5bac2 100644 --- a/nym-wallet/src/context/bonding.tsx +++ b/nym-wallet/src/context/bonding.tsx @@ -32,6 +32,7 @@ import { getInclusionProbability, getMixnodeAvgUptime, getMixnodeRewardEstimation, + getGatewayReport, } from '../requests'; import { useCheckOwnership } from '../hooks/useCheckOwnership'; import { AppContext } from './main'; @@ -78,6 +79,10 @@ export interface TBondedGateway { mixPort: number; verlocPort: number; version: string; + routingScore?: { + current: number; + average: number; + }; } export type TokenPool = 'locked' | 'balance'; @@ -215,6 +220,16 @@ export const BondingContextProvider = ({ children }: { children?: React.ReactNod return stake; }; + const getGatewayReportDetails = async (identityKey: string) => { + try { + const report = await getGatewayReport(identityKey); + return { current: report.most_recent, average: report.last_day }; + } catch (e) { + Console.error(e); + return undefined; + } + }; + const refresh = useCallback(async () => { setIsLoading(true); @@ -282,7 +297,7 @@ export const BondingContextProvider = ({ children }: { children?: React.ReactNod const data = await getGatewayBondDetails(); if (data) { const nodeDescription = await getNodeDescription(data.gateway.host, data.gateway.clients_port); - + const routingScore = await getGatewayReportDetails(data.gateway.identity_key); setBondedNode({ name: nodeDescription?.name, identityKey: data.gateway.identity_key, @@ -290,6 +305,7 @@ export const BondingContextProvider = ({ children }: { children?: React.ReactNod location: data.gateway.location, bond: data.pledge_amount, proxy: data.proxy, + routingScore, } as TBondedGateway); } } catch (e: any) { diff --git a/nym-wallet/src/context/mocks/bonding.tsx b/nym-wallet/src/context/mocks/bonding.tsx index 6ab98ce490..a70501dbae 100644 --- a/nym-wallet/src/context/mocks/bonding.tsx +++ b/nym-wallet/src/context/mocks/bonding.tsx @@ -38,6 +38,10 @@ const bondedGatewayMock: TBondedGateway = { mixPort: 1789, verlocPort: 1790, version: '1.0.2', + routingScore: { + average: 100, + current: 100, + }, }; const TxResultMock: TransactionExecuteResult = { diff --git a/nym-wallet/src/pages/bonding/node-settings/NodeSettings.tsx b/nym-wallet/src/pages/bonding/node-settings/NodeSettings.tsx index c9bd51687f..0c6fc495f3 100644 --- a/nym-wallet/src/pages/bonding/node-settings/NodeSettings.tsx +++ b/nym-wallet/src/pages/bonding/node-settings/NodeSettings.tsx @@ -75,7 +75,7 @@ export const NodeSettings = () => { - Node Settings + {isMixnode(bondedNode) ? 'Node' : 'Gateway'} Settings diff --git a/nym-wallet/src/pages/bonding/node-settings/settings-pages/NodeUnbondPage.tsx b/nym-wallet/src/pages/bonding/node-settings/settings-pages/NodeUnbondPage.tsx index eb92fc2758..89efefb0a8 100644 --- a/nym-wallet/src/pages/bonding/node-settings/settings-pages/NodeUnbondPage.tsx +++ b/nym-wallet/src/pages/bonding/node-settings/settings-pages/NodeUnbondPage.tsx @@ -3,8 +3,10 @@ import { Box, Button, Typography, Grid, TextField } from '@mui/material'; import { TBondedMixnode, TBondedGateway } from 'src/context/bonding'; import { Error } from 'src/components/Error'; import { UnbondModal } from 'src/components/Bonding/modals/UnbondModal'; +import { isMixnode } from 'src/types'; interface Props { bondedNode: TBondedMixnode | TBondedGateway; + onConfirm: () => Promise; onError: (e: string) => void; } @@ -21,15 +23,21 @@ export const NodeUnbondPage = ({ bondedNode, onConfirm, onError }: Props) => { Unbond - - theme.palette.nym.text.muted }}> - If you unbond your node you will loose all delegations! - - + {isMixnode(bondedNode) && ( + + theme.palette.nym.text.muted }}> + If you unbond you will loose all delegations! + + + )} - + diff --git a/nym-wallet/src/requests/queries.ts b/nym-wallet/src/requests/queries.ts index 466c83efc1..5fba51beec 100644 --- a/nym-wallet/src/requests/queries.ts +++ b/nym-wallet/src/requests/queries.ts @@ -9,7 +9,7 @@ import { WrappedDelegationEvent, PendingIntervalEvent, } from '@nymproject/types'; -import { Interval, TNodeDescription } from 'src/types'; +import { Interval, TGatewayReport, TNodeDescription } from 'src/types'; import { invokeWrapper } from './wrapper'; export const getAllPendingDelegations = async () => @@ -48,3 +48,6 @@ export const getNodeDescription = async (host: string, port: number) => export const getPendingIntervalEvents = async () => invokeWrapper('get_pending_interval_events'); + +export const getGatewayReport = async (identity: string) => + invokeWrapper('gateway_report', { identity }); diff --git a/nym-wallet/src/types/global.ts b/nym-wallet/src/types/global.ts index 1bba38e24f..e2dc6a2af8 100644 --- a/nym-wallet/src/types/global.ts +++ b/nym-wallet/src/types/global.ts @@ -61,6 +61,14 @@ export type TAccount = { mnemonic: string; }; +export type TGatewayReport = { + identity: string; + owner: string; + last_day: number; + last_hour: number; + most_recent: number; +}; + export const isMixnode = (node: TBondedMixnode | TBondedGateway): node is TBondedMixnode => (node as TBondedMixnode).profitMargin !== undefined;