Merge pull request #4565 from nymtech/bugfix/delegations
Bug fix: wallet delegations list is empty when RPC node doesn't hold block
This commit is contained in:
@@ -50,7 +50,7 @@ pub struct DelegationWithEverything {
|
||||
pub accumulated_by_delegates: Option<DecCoin>,
|
||||
pub accumulated_by_operator: Option<DecCoin>,
|
||||
pub block_height: u64,
|
||||
pub delegated_on_iso_datetime: String,
|
||||
pub delegated_on_iso_datetime: Option<String>,
|
||||
pub cost_params: Option<MixNodeCostParams>,
|
||||
pub avg_uptime_percent: Option<u8>,
|
||||
|
||||
@@ -60,6 +60,8 @@ pub struct DelegationWithEverything {
|
||||
pub uses_vesting_contract_tokens: bool,
|
||||
pub unclaimed_rewards: Option<DecCoin>,
|
||||
|
||||
pub errors: Option<String>,
|
||||
|
||||
// DEPRECATED, IF POSSIBLE TRY TO DISCONTINUE USE OF IT!
|
||||
pub pending_events: Vec<DelegationEvent>,
|
||||
pub mixnode_is_unbonding: Option<bool>,
|
||||
|
||||
Generated
+3
-1
@@ -3005,6 +3005,7 @@ dependencies = [
|
||||
"schemars",
|
||||
"serde",
|
||||
"tendermint",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3442,7 +3443,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym_wallet"
|
||||
version = "1.2.12"
|
||||
version = "1.2.13"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"base64 0.13.1",
|
||||
@@ -3476,6 +3477,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"serde_repr",
|
||||
"strum 0.23.0",
|
||||
"tap",
|
||||
"tauri",
|
||||
"tauri-build",
|
||||
"tauri-codegen",
|
||||
|
||||
@@ -37,6 +37,7 @@ serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
serde_repr = "0.1"
|
||||
strum = { version = "0.23", features = ["derive"] }
|
||||
tap = "1"
|
||||
tauri = { version = "=1.2.3", features = ["clipboard-all", "shell-open", "updater", "window-maximize", "window-print"] }
|
||||
#tendermint-rpc = "0.23.0"
|
||||
time = { version = "0.3.17", features = ["local-offset"] }
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
use crate::error::BackendError;
|
||||
use crate::state::WalletState;
|
||||
use crate::vesting::delegate::vesting_undelegate_from_mixnode;
|
||||
use nym_mixnet_contract_common::mixnode::StakeSaturationResponse;
|
||||
use nym_mixnet_contract_common::MixId;
|
||||
use nym_types::currency::DecCoin;
|
||||
use nym_types::delegation::{Delegation, DelegationWithEverything, DelegationsSummaryResponse};
|
||||
@@ -18,6 +19,7 @@ use nym_validator_client::nyxd::contract_traits::{
|
||||
MixnetQueryClient, MixnetSigningClient, NymContractsProvider, PagedMixnetQueryClient,
|
||||
};
|
||||
use nym_validator_client::nyxd::Fee;
|
||||
use tap::TapFallible;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_pending_delegation_events(
|
||||
@@ -165,10 +167,21 @@ pub async fn get_all_mix_delegations(
|
||||
.expect("vesting contract address is not available");
|
||||
|
||||
log::info!(" >>> Get delegations");
|
||||
let delegations = client.nyxd.get_all_delegator_delegations(&address).await?;
|
||||
let delegations = client
|
||||
.nyxd
|
||||
.get_all_delegator_delegations(&address)
|
||||
.await
|
||||
.tap_err(|err| {
|
||||
log::error!(" <<< Failed to get delegations. Error: {}", err);
|
||||
})?;
|
||||
log::info!(" <<< {} delegations", delegations.len());
|
||||
|
||||
let pending_events_for_account = get_pending_delegation_events(state.clone()).await?;
|
||||
let pending_events_for_account =
|
||||
get_pending_delegation_events(state.clone())
|
||||
.await
|
||||
.tap_err(|err| {
|
||||
log::error!(" <<< Failed to get pending delegations. Error: {}", err);
|
||||
})?;
|
||||
|
||||
log::info!(
|
||||
" <<< {} pending delegation events for account",
|
||||
@@ -178,7 +191,16 @@ pub async fn get_all_mix_delegations(
|
||||
let mut with_everything: Vec<DelegationWithEverything> = Vec::with_capacity(delegations.len());
|
||||
|
||||
for delegation in delegations {
|
||||
let d = Delegation::from_mixnet_contract(delegation, reg)?;
|
||||
let mut error_strings: Vec<String> = vec![];
|
||||
|
||||
let d = Delegation::from_mixnet_contract(delegation.clone(), reg).tap_err(|err| {
|
||||
log::error!(
|
||||
" <<< Failed to get delegation for mix id {} from contract. Error: {}",
|
||||
delegation.mix_id,
|
||||
err
|
||||
);
|
||||
})?;
|
||||
|
||||
let uses_vesting_contract_tokens = d
|
||||
.proxy
|
||||
.as_ref()
|
||||
@@ -194,7 +216,15 @@ pub async fn get_all_mix_delegations(
|
||||
let mixnode = client
|
||||
.nyxd
|
||||
.get_mixnode_details(d.mix_id)
|
||||
.await?
|
||||
.await
|
||||
.tap_err(|err| {
|
||||
let str_err = format!(
|
||||
"Failed to get mixnode details for mix_id = {}. Error: {}",
|
||||
d.mix_id, err
|
||||
);
|
||||
log::error!(" <<< {}", str_err);
|
||||
error_strings.push(str_err);
|
||||
})?
|
||||
.mixnode_details;
|
||||
|
||||
let accumulated_by_operator = mixnode
|
||||
@@ -202,14 +232,32 @@ pub async fn get_all_mix_delegations(
|
||||
.map(|m| {
|
||||
guard.display_coin_from_base_decimal(&base_mix_denom, m.rewarding_details.operator)
|
||||
})
|
||||
.transpose()?;
|
||||
.transpose()
|
||||
.tap_err(|err| {
|
||||
let str_err = format!(
|
||||
"Failed to get operator rewards as a display coin for mix_id = {}. Error: {}",
|
||||
d.mix_id, err
|
||||
);
|
||||
log::error!(" <<< {}", str_err);
|
||||
error_strings.push(str_err);
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
let accumulated_by_delegates = mixnode
|
||||
.as_ref()
|
||||
.map(|m| {
|
||||
guard.display_coin_from_base_decimal(&base_mix_denom, m.rewarding_details.delegates)
|
||||
})
|
||||
.transpose()?;
|
||||
.transpose()
|
||||
.tap_err(|err| {
|
||||
let str_err = format!(
|
||||
"Failed to get delegator rewards as a display coin for mix_id = {}. Error: {}",
|
||||
d.mix_id, err
|
||||
);
|
||||
log::error!(" <<< {}", str_err);
|
||||
error_strings.push(str_err);
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
let cost_params = mixnode
|
||||
.as_ref()
|
||||
@@ -219,19 +267,48 @@ pub async fn get_all_mix_delegations(
|
||||
reg,
|
||||
)
|
||||
})
|
||||
.transpose()?;
|
||||
.transpose()
|
||||
.tap_err(|err| {
|
||||
let str_err = format!(
|
||||
"Failed to mixnode cost params for mix_id = {}. Error: {}",
|
||||
d.mix_id, err
|
||||
);
|
||||
log::error!(" <<< {}", str_err);
|
||||
error_strings.push(str_err);
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
log::trace!(" >>> Get accumulated rewards: address = {}", address);
|
||||
let pending_reward = client
|
||||
.nyxd
|
||||
.get_pending_delegator_reward(&address, d.mix_id, d.proxy.clone())
|
||||
.await?;
|
||||
.await
|
||||
.tap_err(|err| {
|
||||
let str_err = format!(
|
||||
"Failed to get accumulated rewards for mix_id = {}. Error: {}",
|
||||
d.mix_id, err
|
||||
);
|
||||
log::error!(" <<< {}", str_err);
|
||||
error_strings.push(str_err);
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
let accumulated_rewards = match &pending_reward.amount_earned {
|
||||
Some(reward) => {
|
||||
let amount = guard.attempt_convert_to_display_dec_coin(reward.clone().into())?;
|
||||
log::trace!(" <<< rewards = {:?}, amount = {}", pending_reward, amount);
|
||||
Some(amount)
|
||||
let amount = guard
|
||||
.attempt_convert_to_display_dec_coin(reward.clone().into())
|
||||
.tap_err(|err| {
|
||||
let str_err = format!("Failed to get convert reward to a display coin for mix_id = {}. Error: {}", d.mix_id, err);
|
||||
log::error!(" <<< {}", str_err);
|
||||
error_strings.push(str_err);
|
||||
})
|
||||
.ok();
|
||||
log::trace!(
|
||||
" <<< rewards = {:?}, amount = {:?}",
|
||||
pending_reward,
|
||||
amount
|
||||
);
|
||||
amount
|
||||
}
|
||||
None => {
|
||||
log::trace!(" <<< no rewards waiting");
|
||||
@@ -240,7 +317,23 @@ pub async fn get_all_mix_delegations(
|
||||
};
|
||||
|
||||
log::trace!(" >>> Get stake saturation: mix_id = {}", d.mix_id);
|
||||
let stake_saturation = client.nyxd.get_mixnode_stake_saturation(d.mix_id).await?;
|
||||
let stake_saturation = client
|
||||
.nyxd
|
||||
.get_mixnode_stake_saturation(d.mix_id)
|
||||
.await
|
||||
.tap_err(|err| {
|
||||
let str_err = format!(
|
||||
"Failed to get stake saturation for mix_id = {}. Error: {}",
|
||||
d.mix_id, err
|
||||
);
|
||||
log::error!(" <<< {}", str_err);
|
||||
error_strings.push(str_err);
|
||||
})
|
||||
.unwrap_or(StakeSaturationResponse {
|
||||
mix_id: d.mix_id,
|
||||
uncapped_saturation: None,
|
||||
current_saturation: None,
|
||||
});
|
||||
log::trace!(" <<< {:?}", stake_saturation);
|
||||
|
||||
log::trace!(
|
||||
@@ -251,6 +344,14 @@ pub async fn get_all_mix_delegations(
|
||||
.nym_api
|
||||
.get_mixnode_avg_uptime(d.mix_id)
|
||||
.await
|
||||
.tap_err(|err| {
|
||||
let str_err = format!(
|
||||
"Failed to get average uptime percentage for mix_id = {}. Error: {}",
|
||||
d.mix_id, err
|
||||
);
|
||||
log::error!(" <<< {}", str_err);
|
||||
error_strings.push(str_err);
|
||||
})
|
||||
.ok()
|
||||
.map(|r| r.avg_uptime);
|
||||
log::trace!(" <<< {:?}", avg_uptime_percent);
|
||||
@@ -262,8 +363,13 @@ pub async fn get_all_mix_delegations(
|
||||
let timestamp = client
|
||||
.nyxd
|
||||
.get_block_timestamp(Some(d.height as u32))
|
||||
.await?;
|
||||
let delegated_on_iso_datetime = timestamp.to_rfc3339();
|
||||
.await
|
||||
.tap_err(|err| {
|
||||
let str_err = format!("Failed to get block timestamp for height = {} for delegation to mix_id = {}. Error: {}", d.height, d.mix_id, err);
|
||||
log::error!(" <<< {}", str_err);
|
||||
error_strings.push(str_err);
|
||||
}).ok();
|
||||
let delegated_on_iso_datetime = timestamp.map(|ts| ts.to_rfc3339());
|
||||
log::trace!(
|
||||
" <<< timestamp = {:?}, delegated_on_iso_datetime = {:?}",
|
||||
timestamp,
|
||||
@@ -301,6 +407,11 @@ pub async fn get_all_mix_delegations(
|
||||
unclaimed_rewards: accumulated_rewards,
|
||||
pending_events,
|
||||
mixnode_is_unbonding,
|
||||
errors: if error_strings.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(error_strings.join("\n"))
|
||||
},
|
||||
})
|
||||
}
|
||||
log::trace!("<<< {:?}", with_everything);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React from 'react';
|
||||
import { Chip, IconButton, TableCell, TableRow, Tooltip, Typography } from '@mui/material';
|
||||
import { Box, Chip, IconButton, TableCell, TableRow, Tooltip, Typography } from '@mui/material';
|
||||
import { Link } from '@nymproject/react/link/Link';
|
||||
import { decimalToPercentage, DelegationWithEverything } from '@nymproject/types';
|
||||
import { LockOutlined } from '@mui/icons-material';
|
||||
import { isDelegation } from 'src/context/delegations';
|
||||
import { LockOutlined, WarningAmberOutlined } from '@mui/icons-material';
|
||||
import { isDelegation, useDelegationContext } from 'src/context/delegations';
|
||||
import { toPercentIntegerString } from 'src/utils';
|
||||
import { format } from 'date-fns';
|
||||
import { Undelegate } from 'src/svg-icons';
|
||||
@@ -29,6 +29,8 @@ export const DelegationItem = ({
|
||||
nodeIsUnbonded: boolean;
|
||||
onItemActionClick?: (item: DelegationWithEverything, action: DelegationListItemActions) => void;
|
||||
}) => {
|
||||
const { setDelegationItemErrors } = useDelegationContext();
|
||||
|
||||
const operatingCost = isDelegation(item) && item.cost_params?.interval_operating_cost;
|
||||
|
||||
const tooltipText = () => {
|
||||
@@ -45,13 +47,26 @@ export const DelegationItem = ({
|
||||
{nodeIsUnbonded ? (
|
||||
'-'
|
||||
) : (
|
||||
<Link
|
||||
target="_blank"
|
||||
href={`${explorerUrl}/network-components/mixnode/${item.mix_id}`}
|
||||
text={`${item.node_identity.slice(0, 6)}...${item.node_identity.slice(-6)}`}
|
||||
color="text.primary"
|
||||
noIcon
|
||||
/>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
||||
{item.errors && (
|
||||
<Tooltip title="Open to view a list of errors that occurred">
|
||||
<IconButton
|
||||
sx={{ mr: 1 }}
|
||||
size="small"
|
||||
onClick={() => setDelegationItemErrors({ nodeId: item.node_identity, errors: item.errors! })}
|
||||
>
|
||||
<WarningAmberOutlined color="warning" fontSize="small" />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Link
|
||||
target="_blank"
|
||||
href={`${explorerUrl}/network-components/mixnode/${item.mix_id}`}
|
||||
text={`${item.node_identity.slice(0, 6)}...${item.node_identity.slice(-6)}`}
|
||||
color="text.primary"
|
||||
noIcon
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell sx={{ color: 'inherit' }}>
|
||||
@@ -70,7 +85,7 @@ export const DelegationItem = ({
|
||||
</TableCell>
|
||||
<TableCell sx={{ color: 'inherit' }}>{getStakeSaturation(item)}</TableCell>
|
||||
<TableCell sx={{ color: 'inherit' }}>
|
||||
{format(new Date(item.delegated_on_iso_datetime), 'dd/MM/yyyy')}
|
||||
{item.delegated_on_iso_datetime && format(new Date(item.delegated_on_iso_datetime), 'dd/MM/yyyy')}
|
||||
</TableCell>
|
||||
<TableCell sx={{ color: 'inherit' }}>
|
||||
<Typography style={{ textTransform: 'uppercase', fontSize: 'inherit' }}>
|
||||
|
||||
@@ -34,6 +34,7 @@ export const items: DelegationWithEverything[] = [
|
||||
uses_vesting_contract_tokens: false,
|
||||
pending_events: [],
|
||||
mixnode_is_unbonding: true,
|
||||
errors: null,
|
||||
},
|
||||
{
|
||||
mix_id: 2,
|
||||
@@ -57,6 +58,7 @@ export const items: DelegationWithEverything[] = [
|
||||
uses_vesting_contract_tokens: true,
|
||||
pending_events: [],
|
||||
mixnode_is_unbonding: true,
|
||||
errors: null,
|
||||
},
|
||||
{
|
||||
mix_id: 3,
|
||||
@@ -80,6 +82,7 @@ export const items: DelegationWithEverything[] = [
|
||||
uses_vesting_contract_tokens: true,
|
||||
pending_events: [],
|
||||
mixnode_is_unbonding: true,
|
||||
errors: null,
|
||||
},
|
||||
{
|
||||
mix_id: 4,
|
||||
@@ -103,6 +106,7 @@ export const items: DelegationWithEverything[] = [
|
||||
uses_vesting_contract_tokens: true,
|
||||
pending_events: [],
|
||||
mixnode_is_unbonding: true,
|
||||
errors: null,
|
||||
},
|
||||
{
|
||||
mix_id: 5,
|
||||
@@ -126,6 +130,7 @@ export const items: DelegationWithEverything[] = [
|
||||
uses_vesting_contract_tokens: true,
|
||||
pending_events: [],
|
||||
mixnode_is_unbonding: true,
|
||||
errors: null,
|
||||
},
|
||||
{
|
||||
mix_id: 6,
|
||||
@@ -149,6 +154,7 @@ export const items: DelegationWithEverything[] = [
|
||||
uses_vesting_contract_tokens: true,
|
||||
pending_events: [],
|
||||
mixnode_is_unbonding: true,
|
||||
errors: null,
|
||||
},
|
||||
{
|
||||
mix_id: 7,
|
||||
@@ -172,6 +178,7 @@ export const items: DelegationWithEverything[] = [
|
||||
uses_vesting_contract_tokens: false,
|
||||
pending_events: [],
|
||||
mixnode_is_unbonding: true,
|
||||
errors: null,
|
||||
},
|
||||
{
|
||||
mix_id: 8,
|
||||
@@ -195,6 +202,7 @@ export const items: DelegationWithEverything[] = [
|
||||
uses_vesting_contract_tokens: true,
|
||||
pending_events: [],
|
||||
mixnode_is_unbonding: true,
|
||||
errors: null,
|
||||
},
|
||||
{
|
||||
mix_id: 9,
|
||||
@@ -218,6 +226,7 @@ export const items: DelegationWithEverything[] = [
|
||||
uses_vesting_contract_tokens: true,
|
||||
pending_events: [],
|
||||
mixnode_is_unbonding: true,
|
||||
errors: null,
|
||||
},
|
||||
{
|
||||
mix_id: 10,
|
||||
@@ -241,6 +250,7 @@ export const items: DelegationWithEverything[] = [
|
||||
uses_vesting_contract_tokens: true,
|
||||
pending_events: [],
|
||||
mixnode_is_unbonding: true,
|
||||
errors: null,
|
||||
},
|
||||
{
|
||||
mix_id: 11,
|
||||
@@ -264,6 +274,7 @@ export const items: DelegationWithEverything[] = [
|
||||
uses_vesting_contract_tokens: true,
|
||||
pending_events: [],
|
||||
mixnode_is_unbonding: true,
|
||||
errors: null,
|
||||
},
|
||||
{
|
||||
mix_id: 12,
|
||||
@@ -287,6 +298,7 @@ export const items: DelegationWithEverything[] = [
|
||||
uses_vesting_contract_tokens: true,
|
||||
pending_events: [],
|
||||
mixnode_is_unbonding: true,
|
||||
errors: null,
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ import { DelegationListItemActions } from './DelegationActions';
|
||||
import { DelegationItem } from './DelegationItem';
|
||||
import { PendingDelegationItem } from './PendingDelegationItem';
|
||||
import { LoadingModal } from '../Modals/LoadingModal';
|
||||
import { isDelegation, isPendingDelegation, TDelegations } from '../../context/delegations';
|
||||
import { isDelegation, isPendingDelegation, TDelegations, useDelegationContext } from '../../context/delegations';
|
||||
import { ErrorModal } from '../Modals/ErrorModal';
|
||||
|
||||
export type Order = 'asc' | 'desc';
|
||||
type AdditionalTypes = { profit_margin_percent: number; operating_cost: number };
|
||||
@@ -94,6 +95,8 @@ export const DelegationList: FCWithChildren<{
|
||||
const [order, setOrder] = React.useState<Order>('asc');
|
||||
const [orderBy, setOrderBy] = React.useState<SortingKeys>('delegated_on_iso_datetime');
|
||||
|
||||
const { delegationItemErrors, setDelegationItemErrors } = useDelegationContext();
|
||||
|
||||
const handleRequestSort = (_: React.MouseEvent<unknown>, property: any) => {
|
||||
const isAsc = orderBy === property && order === 'asc';
|
||||
setOrder(isAsc ? 'desc' : 'asc');
|
||||
@@ -105,6 +108,12 @@ export const DelegationList: FCWithChildren<{
|
||||
return (
|
||||
<TableContainer>
|
||||
{isLoading && <LoadingModal text="Please wait. Refreshing..." />}
|
||||
<ErrorModal
|
||||
open={Boolean(delegationItemErrors)}
|
||||
title={`Delegation errors for Node ID ${delegationItemErrors?.nodeId || 'unknown'}`}
|
||||
message={delegationItemErrors?.errors || 'oops'}
|
||||
onClose={() => setDelegationItemErrors(undefined)}
|
||||
/>
|
||||
<Table sx={{ width: '100%' }}>
|
||||
<EnhancedTableHead order={order} orderBy={orderBy} onRequestSort={handleRequestSort} />
|
||||
<TableBody>
|
||||
|
||||
@@ -20,6 +20,7 @@ import { decCoinToDisplay } from 'src/utils';
|
||||
import { Console } from 'src/utils/console';
|
||||
|
||||
export type TDelegationContext = {
|
||||
delegationItemErrors?: { nodeId: string; errors: string };
|
||||
isLoading: boolean;
|
||||
delegations?: TDelegations;
|
||||
pendingDelegations?: WrappedDelegationEvent[];
|
||||
@@ -34,6 +35,7 @@ export type TDelegationContext = {
|
||||
) => Promise<TransactionExecuteResult>;
|
||||
undelegate: (mix_id: number, fee?: Fee) => Promise<TransactionExecuteResult>;
|
||||
undelegateVesting: (mix_id: number) => Promise<TransactionExecuteResult>;
|
||||
setDelegationItemErrors: (data: { nodeId: string; errors: string } | undefined) => void;
|
||||
};
|
||||
|
||||
export type TDelegationTransaction = {
|
||||
@@ -61,6 +63,7 @@ export const DelegationContext = createContext<TDelegationContext>({
|
||||
undelegateVesting: () => {
|
||||
throw new Error('Not implemented');
|
||||
},
|
||||
setDelegationItemErrors: () => undefined,
|
||||
});
|
||||
|
||||
export const DelegationContextProvider: FC<{
|
||||
@@ -69,6 +72,7 @@ export const DelegationContextProvider: FC<{
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
}> = ({ network, children }) => {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [delegationItemErrors, setDelegationItemErrors] = useState<{ nodeId: string; errors: string }>();
|
||||
const [delegations, setDelegations] = useState<undefined | TDelegations>();
|
||||
const [totalDelegations, setTotalDelegations] = useState<undefined | string>();
|
||||
const [totalRewards, setTotalRewards] = useState<undefined | string>();
|
||||
@@ -130,6 +134,7 @@ export const DelegationContextProvider: FC<{
|
||||
|
||||
const memoizedValue = useMemo(
|
||||
() => ({
|
||||
delegationItemErrors,
|
||||
isLoading,
|
||||
delegations,
|
||||
pendingDelegations,
|
||||
@@ -137,11 +142,20 @@ export const DelegationContextProvider: FC<{
|
||||
totalRewards,
|
||||
totalDelegationsAndRewards,
|
||||
refresh,
|
||||
setDelegationItemErrors,
|
||||
addDelegation,
|
||||
undelegate: undelegateFromMixnode,
|
||||
undelegateVesting: vestingUndelegateFromMixnode,
|
||||
}),
|
||||
[isLoading, delegations, pendingDelegations, totalDelegations, totalRewards, totalDelegationsAndRewards],
|
||||
[
|
||||
isLoading,
|
||||
delegations,
|
||||
delegationItemErrors,
|
||||
pendingDelegations,
|
||||
totalDelegations,
|
||||
totalRewards,
|
||||
totalDelegationsAndRewards,
|
||||
],
|
||||
);
|
||||
|
||||
return <DelegationContext.Provider value={memoizedValue}>{children}</DelegationContext.Provider>;
|
||||
|
||||
@@ -37,6 +37,7 @@ let mockDelegations: DelegationWithEverything[] = [
|
||||
uses_vesting_contract_tokens: false,
|
||||
pending_events: [],
|
||||
mixnode_is_unbonding: false,
|
||||
errors: null,
|
||||
},
|
||||
{
|
||||
mix_id: 5678,
|
||||
@@ -60,6 +61,7 @@ let mockDelegations: DelegationWithEverything[] = [
|
||||
uses_vesting_contract_tokens: true,
|
||||
pending_events: [],
|
||||
mixnode_is_unbonding: false,
|
||||
errors: null,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -69,6 +71,7 @@ export const MockDelegationContextProvider: FCWithChildren = ({ children }) => {
|
||||
const [error, setError] = useState<string>();
|
||||
const [delegations, setDelegations] = useState<undefined | DelegationWithEverything[]>();
|
||||
const [totalDelegations, setTotalDelegations] = useState<undefined | string>();
|
||||
const [delegationItemErrors, setDelegationItemErrors] = useState<{ nodeId: string; errors: string }>();
|
||||
|
||||
const triggerStateUpdate = () => setTrigger(new Date());
|
||||
|
||||
@@ -230,6 +233,8 @@ export const MockDelegationContextProvider: FCWithChildren = ({ children }) => {
|
||||
|
||||
const memoizedValue = useMemo(
|
||||
() => ({
|
||||
delegationItemErrors,
|
||||
setDelegationItemErrors,
|
||||
isLoading,
|
||||
error,
|
||||
delegations,
|
||||
|
||||
@@ -101,7 +101,7 @@ export const Delegation: FC<{ isStorybook?: boolean }> = ({ isStorybook }) => {
|
||||
|
||||
// Refresh the rewards and delegations periodically when page is mounted
|
||||
useEffect(() => {
|
||||
const timer = setInterval(refreshWithIntervalUpdate, 1 * 60 * 1000); // every 1 minute
|
||||
const timer = setInterval(refreshWithIntervalUpdate, 5 * 60 * 1000); // every 5 minutes
|
||||
return () => clearInterval(timer);
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ export interface DelegationWithEverything {
|
||||
accumulated_by_delegates: DecCoin | null;
|
||||
accumulated_by_operator: DecCoin | null;
|
||||
block_height: bigint;
|
||||
delegated_on_iso_datetime: string;
|
||||
delegated_on_iso_datetime: string | null;
|
||||
cost_params: MixNodeCostParams | null;
|
||||
avg_uptime_percent: number | null;
|
||||
stake_saturation: string | null;
|
||||
@@ -19,4 +19,5 @@ export interface DelegationWithEverything {
|
||||
unclaimed_rewards: DecCoin | null;
|
||||
pending_events: Array<DelegationEvent>;
|
||||
mixnode_is_unbonding: boolean | null;
|
||||
errors: string | null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user