bugfix: [wallet] displaying delegations for native nymnodes (#5087)

* fixed return type for getting nymnode details

* fixed nym-api queries if using relative paths

* fixed queries for delegations of native nymnodes
This commit is contained in:
Jędrzej Stuczyński
2024-11-04 21:15:29 +00:00
committed by GitHub
parent 5cefa7fdd4
commit 2569deb080
5 changed files with 115 additions and 44 deletions
@@ -696,16 +696,32 @@ pub trait NymApiClientExt: ApiClient {
&self,
node_id: NodeId,
) -> Result<NodePerformanceResponse, NymAPIError> {
self.get_json_from(format!("/v1/nym-nodes/performance/{node_id}"))
.await
self.get_json(
&[
routes::API_VERSION,
"nym-nodes",
"performance",
&node_id.to_string(),
],
NO_PARAMS,
)
.await
}
async fn get_node_annotation(
&self,
node_id: NodeId,
) -> Result<AnnotationResponse, NymAPIError> {
self.get_json_from(format!("/v1/nym-nodes/annotation/{node_id}"))
.await
self.get_json(
&[
routes::API_VERSION,
"nym-nodes",
"annotation",
&node_id.to_string(),
],
NO_PARAMS,
)
.await
}
#[deprecated]
@@ -10,10 +10,10 @@ use cosmrs::AccountId;
use nym_contracts_common::signing::Nonce;
use nym_mixnet_contract_common::gateway::{PreassignedGatewayIdsResponse, PreassignedId};
use nym_mixnet_contract_common::nym_node::{
EpochAssignmentResponse, NodeDetailsByIdentityResponse, NodeOwnershipResponse,
NodeRewardingDetailsResponse, PagedNymNodeBondsResponse, PagedNymNodeDetailsResponse,
PagedUnbondedNymNodesResponse, Role, RolesMetadataResponse, StakeSaturationResponse,
UnbondedNodeResponse, UnbondedNymNode,
EpochAssignmentResponse, NodeDetailsByIdentityResponse, NodeDetailsResponse,
NodeOwnershipResponse, NodeRewardingDetailsResponse, PagedNymNodeBondsResponse,
PagedNymNodeDetailsResponse, PagedUnbondedNymNodesResponse, Role, RolesMetadataResponse,
StakeSaturationResponse, UnbondedNodeResponse, UnbondedNymNode,
};
use nym_mixnet_contract_common::reward_params::WorkFactor;
use nym_mixnet_contract_common::{
@@ -316,10 +316,7 @@ pub trait MixnetQueryClient {
.await
}
async fn get_nymnode_details(
&self,
node_id: NodeId,
) -> Result<NodeOwnershipResponse, NyxdError> {
async fn get_nymnode_details(&self, node_id: NodeId) -> Result<NodeDetailsResponse, NyxdError> {
self.query_mixnet_contract(MixnetQueryMsg::GetNymNodeDetails { node_id })
.await
}
+1
View File
@@ -315,6 +315,7 @@ impl Client {
parse_response(res, true).await
}
#[instrument(level = "debug", skip_all)]
pub async fn get_json_endpoint<T, S, E>(&self, endpoint: S) -> Result<T, HttpClientError<E>>
where
for<'a> T: Deserialize<'a>,
+9 -1
View File
@@ -3,7 +3,7 @@ use crate::deprecated::DelegationEvent;
use crate::error::TypesError;
use crate::mixnode::NodeCostParams;
use cosmwasm_std::Decimal;
use nym_mixnet_contract_common::{Delegation as MixnetContractDelegation, NodeId};
use nym_mixnet_contract_common::{Delegation as MixnetContractDelegation, NodeId, NodeRewarding};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
@@ -70,6 +70,14 @@ pub struct DelegationWithEverything {
pub mixnode_is_unbonding: Option<bool>,
}
pub struct NodeInformation {
pub owner: String,
pub mix_id: NodeId,
pub node_identity: String,
pub rewarding_details: NodeRewarding,
pub is_unbonding: bool,
}
#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
#[cfg_attr(
feature = "generate-ts",
@@ -7,7 +7,9 @@ use crate::vesting::delegate::vesting_undelegate_from_mixnode;
use nym_mixnet_contract_common::mixnode::MixStakeSaturationResponse;
use nym_mixnet_contract_common::NodeId;
use nym_types::currency::DecCoin;
use nym_types::delegation::{Delegation, DelegationWithEverything, DelegationsSummaryResponse};
use nym_types::delegation::{
Delegation, DelegationWithEverything, DelegationsSummaryResponse, NodeInformation,
};
use nym_types::deprecated::{
convert_to_delegation_events, DelegationEvent, WrappedDelegationEvent,
};
@@ -19,6 +21,7 @@ use nym_validator_client::nyxd::contract_traits::{
MixnetQueryClient, MixnetSigningClient, NymContractsProvider, PagedMixnetQueryClient,
};
use nym_validator_client::nyxd::Fee;
use nym_validator_client::DirectSigningHttpRpcValidatorClient;
use tap::TapFallible;
#[tauri::command]
@@ -141,6 +144,58 @@ pub async fn undelegate_all_from_mixnode(
Ok(res)
}
pub(crate) async fn get_node_information(
client: &DirectSigningHttpRpcValidatorClient,
node_id: NodeId,
error_strings: &mut Vec<String>,
) -> Result<Option<NodeInformation>, BackendError> {
let native_nymnode = client
.nyxd
.get_nymnode_details(node_id)
.await
.inspect_err(|err| {
let str_err =
format!("Failed to get nymnode details for node_id = {node_id}. Error: {err}");
log::error!(" <<< {str_err}",);
error_strings.push(str_err);
})?;
if let Some(native) = native_nymnode.details {
return Ok(Some(NodeInformation {
is_unbonding: native.is_unbonding(),
owner: native.bond_information.owner.to_string(),
mix_id: node_id,
node_identity: native.bond_information.node.identity_key,
rewarding_details: native.rewarding_details,
}));
}
let legacy_mixnode = client
.nyxd
.get_mixnode_details(node_id)
.await
.inspect_err(|err| {
let str_err = format!(
"Failed to get legacy mixnode details for node_id = {node_id}. Error: {err}",
);
log::error!(" <<< {}", str_err);
error_strings.push(str_err);
})?
.mixnode_details;
if let Some(legacy) = legacy_mixnode {
return Ok(Some(NodeInformation {
is_unbonding: legacy.is_unbonding(),
owner: legacy.bond_information.owner.to_string(),
mix_id: node_id,
node_identity: legacy.bond_information.mix_node.identity_key,
rewarding_details: legacy.rewarding_details,
}));
}
Ok(None)
}
// TODO: fix later (yeah...)
#[allow(deprecated)]
#[tauri::command]
@@ -208,21 +263,9 @@ pub async fn get_all_mix_delegations(
d.amount
);
let mixnode = client
.nyxd
.get_mixnode_details(d.mix_id)
.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 node_details = get_node_information(client, d.mix_id, &mut error_strings).await?;
let accumulated_by_operator = mixnode
let accumulated_by_operator = node_details
.as_ref()
.map(|m| {
guard.display_coin_from_base_decimal(&base_mix_denom, m.rewarding_details.operator)
@@ -238,10 +281,13 @@ pub async fn get_all_mix_delegations(
})
.unwrap_or_default();
let accumulated_by_delegates = mixnode
let accumulated_by_delegates = node_details
.as_ref()
.map(|m| {
guard.display_coin_from_base_decimal(&base_mix_denom, m.rewarding_details.delegates)
reg.attempt_create_display_coin_from_base_dec_amount(
&base_mix_denom,
m.rewarding_details.delegates,
)
})
.transpose()
.tap_err(|err| {
@@ -254,7 +300,7 @@ pub async fn get_all_mix_delegations(
})
.unwrap_or_default();
let cost_params = mixnode
let cost_params = node_details
.as_ref()
.map(|m| {
NodeCostParams::from_mixnet_contract_mixnode_cost_params(
@@ -335,21 +381,26 @@ pub async fn get_all_mix_delegations(
" >>> Get average uptime percentage: mix_iid = {}",
d.mix_id
);
let avg_uptime_percent = client
let current_performance = client
.nym_api
.get_mixnode_avg_uptime(d.mix_id)
.get_current_node_performance(d.mix_id)
.await
.tap_err(|err| {
.inspect_err(|err| {
let str_err = format!(
"Failed to get average uptime percentage for mix_id = {}. Error: {}",
d.mix_id, err
"Failed to get current node performance for node_id = {}. Error: {err}",
d.mix_id
);
log::error!(" <<< {}", str_err);
error_strings.push(str_err);
})
.ok()
.map(|r| r.avg_uptime);
log::trace!(" <<< {:?}", avg_uptime_percent);
.and_then(|r| r.performance);
// convert to old u8
let current_uptime = current_performance.map(|p| (p * 100.) as u8);
log::trace!(" <<< {:?}", current_uptime);
log::trace!(
" >>> Convert delegated on block height to timestamp: block_height = {}",
@@ -377,9 +428,9 @@ pub async fn get_all_mix_delegations(
pending_events.len()
);
let mixnode_is_unbonding = mixnode.as_ref().map(|m| m.is_unbonding());
let mixnode_is_unbonding = node_details.as_ref().map(|m| m.is_unbonding);
log::trace!(
" >>> mixnode with mix_id: {} is unbonding: {:?}",
" >>> node with mix_id: {} is unbonding: {:?}",
d.mix_id,
mixnode_is_unbonding
);
@@ -387,16 +438,14 @@ pub async fn get_all_mix_delegations(
with_everything.push(DelegationWithEverything {
owner: d.owner,
mix_id: d.mix_id,
node_identity: mixnode
.map(|m| m.bond_information.mix_node.identity_key)
.unwrap_or_default(),
node_identity: node_details.map(|m| m.node_identity).unwrap_or_default(),
amount: d.amount,
block_height: d.height,
uses_vesting_contract_tokens,
delegated_on_iso_datetime,
stake_saturation: stake_saturation.uncapped_saturation,
accumulated_by_operator,
avg_uptime_percent,
avg_uptime_percent: current_uptime,
accumulated_by_delegates,
cost_params,
unclaimed_rewards: accumulated_rewards,