From 63dd26ca1ba2af3e1db4d53ab4ab760529317b01 Mon Sep 17 00:00:00 2001 From: Drazen Urch Date: Fri, 18 Mar 2022 15:44:26 +0100 Subject: [PATCH] Add Query endpoints for calculating rewards (#1152) --- .../validator-client/src/client.rs | 22 +++++++++++++ .../validator-client/src/nymd/mod.rs | 27 ++++++++++++++++ .../mixnet-contract/src/msg.rs | 7 +++++ contracts/mixnet/src/contract.rs | 11 +++++++ contracts/mixnet/src/mixnodes/storage.rs | 2 +- contracts/mixnet/src/rewards/queries.rs | 31 +++++++++++++++++++ contracts/mixnet/src/rewards/transactions.rs | 4 +-- nym-wallet/src-tauri/src/main.rs | 2 ++ .../src-tauri/src/operations/mixnet/bond.rs | 9 ++++++ .../src/operations/mixnet/delegate.rs | 17 ++++++++-- validator-api/src/nymd_client.rs | 27 ++++++++++++++++ 11 files changed, 154 insertions(+), 5 deletions(-) diff --git a/common/client-libs/validator-client/src/client.rs b/common/client-libs/validator-client/src/client.rs index 6e1b599ea8..e5abf46c9e 100644 --- a/common/client-libs/validator-client/src/client.rs +++ b/common/client-libs/validator-client/src/client.rs @@ -248,6 +248,28 @@ impl Client { Ok(self.nymd.get_contract_settings().await?) } + pub async fn get_operator_rewards(&self, address: String) -> Result + where + C: CosmWasmClient + Sync, + { + Ok(self.nymd.get_operator_rewards(address).await?.u128()) + } + + pub async fn get_delegator_rewards( + &self, + address: String, + mix_identity: IdentityKey, + ) -> Result + where + C: CosmWasmClient + Sync, + { + Ok(self + .nymd + .get_delegator_rewards(address, mix_identity) + .await? + .u128()) + } + pub async fn get_current_epoch(&self) -> Result, ValidatorClientError> where C: CosmWasmClient + Sync, diff --git a/common/client-libs/validator-client/src/nymd/mod.rs b/common/client-libs/validator-client/src/nymd/mod.rs index 96e75928e5..ea17b57b12 100644 --- a/common/client-libs/validator-client/src/nymd/mod.rs +++ b/common/client-libs/validator-client/src/nymd/mod.rs @@ -290,6 +290,33 @@ impl NymdClient { .await } + pub async fn get_operator_rewards(&self, address: String) -> Result + where + C: CosmWasmClient + Sync, + { + let request = QueryMsg::QueryOperatorReward { address }; + self.client + .query_contract_smart(self.mixnet_contract_address()?, &request) + .await + } + + pub async fn get_delegator_rewards( + &self, + address: String, + mix_identity: IdentityKey, + ) -> Result + where + C: CosmWasmClient + Sync, + { + let request = QueryMsg::QueryDelegatorReward { + address, + mix_identity, + }; + self.client + .query_contract_smart(self.mixnet_contract_address()?, &request) + .await + } + pub async fn get_current_epoch(&self) -> Result, NymdError> where C: CosmWasmClient + Sync, diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs index dbb1b0c4fb..1605fb4b89 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs @@ -169,6 +169,13 @@ pub enum QueryMsg { GetRewardedSetRefreshBlocks {}, GetCurrentEpoch {}, GetEpochsInInterval {}, + QueryOperatorReward { + address: String, + }, + QueryDelegatorReward { + address: String, + mix_identity: IdentityKey, + }, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] diff --git a/contracts/mixnet/src/contract.rs b/contracts/mixnet/src/contract.rs index c39e49b80b..717527d08a 100644 --- a/contracts/mixnet/src/contract.rs +++ b/contracts/mixnet/src/contract.rs @@ -359,6 +359,17 @@ pub fn query(deps: Deps<'_>, env: Env, msg: QueryMsg) -> Result to_binary(&crate::constants::EPOCHS_IN_INTERVAL), QueryMsg::GetCurrentEpoch {} => to_binary(&query_current_epoch(deps.storage)?), + QueryMsg::QueryOperatorReward { address } => to_binary( + &crate::rewards::queries::query_operator_reward(deps, address)?, + ), + QueryMsg::QueryDelegatorReward { + address, + mix_identity, + } => to_binary(&crate::rewards::queries::query_delegator_reward( + deps, + address, + mix_identity, + )?), }; Ok(query_res?) diff --git a/contracts/mixnet/src/mixnodes/storage.rs b/contracts/mixnet/src/mixnodes/storage.rs index 8c10e22f52..83452af46d 100644 --- a/contracts/mixnet/src/mixnodes/storage.rs +++ b/contracts/mixnet/src/mixnodes/storage.rs @@ -54,7 +54,7 @@ pub(crate) fn mixnodes<'a>( } #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub(crate) struct StoredMixnodeBond { +pub struct StoredMixnodeBond { pub pledge_amount: Coin, pub owner: Addr, pub layer: Layer, diff --git a/contracts/mixnet/src/rewards/queries.rs b/contracts/mixnet/src/rewards/queries.rs index c33c5c01bd..1e0388a711 100644 --- a/contracts/mixnet/src/rewards/queries.rs +++ b/contracts/mixnet/src/rewards/queries.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use super::storage; +use crate::error::ContractError; use cosmwasm_std::Uint128; use cosmwasm_std::{Deps, StdResult}; use mixnet_contract_common::{IdentityKey, MixnodeRewardingStatusResponse}; @@ -24,6 +25,36 @@ pub(crate) fn query_rewarding_status( Ok(MixnodeRewardingStatusResponse { status }) } +pub fn query_operator_reward(deps: Deps, owner: String) -> Result { + let owner_address = deps.api.addr_validate(&owner)?; + let bond = match crate::mixnodes::storage::mixnodes() + .idx + .owner + .item(deps.storage, owner_address.clone())? + { + Some(record) => record.1, + None => { + // Return if bond does not exist + return Ok(Uint128::zero()); + } + }; + + super::transactions::calculate_operator_reward(deps.storage, &owner_address, &bond) +} + +pub fn query_delegator_reward( + deps: Deps, + owner: String, + mix_identity: IdentityKey, +) -> Result { + let owner_address = deps.api.addr_validate(&owner)?; + super::transactions::calculate_delegator_reward( + deps.storage, + owner_address.as_str(), + &mix_identity, + ) +} + #[cfg(test)] pub(crate) mod tests { use super::*; diff --git a/contracts/mixnet/src/rewards/transactions.rs b/contracts/mixnet/src/rewards/transactions.rs index cf3e5a4772..c3373bbd72 100644 --- a/contracts/mixnet/src/rewards/transactions.rs +++ b/contracts/mixnet/src/rewards/transactions.rs @@ -90,7 +90,7 @@ pub fn _try_compound_operator_reward( Ok(reward) } -fn calculate_operator_reward( +pub fn calculate_operator_reward( storage: &dyn Storage, owner: &Addr, bond: &StoredMixnodeBond, @@ -233,7 +233,7 @@ pub fn _try_compound_delegator_reward( // TODO: Test // + last_reward_claimed_height is updated // + last_reward_claimed height is correctly used -fn calculate_delegator_reward( +pub fn calculate_delegator_reward( storage: &dyn Storage, owner_address: &str, mix_identity: &str, diff --git a/nym-wallet/src-tauri/src/main.rs b/nym-wallet/src-tauri/src/main.rs index 42fd4dcbff..300515b195 100644 --- a/nym-wallet/src-tauri/src/main.rs +++ b/nym-wallet/src-tauri/src/main.rs @@ -45,11 +45,13 @@ fn main() { mixnet::bond::bond_gateway, mixnet::bond::bond_mixnode, mixnet::bond::gateway_bond_details, + mixnet::bond::get_operator_rewards, mixnet::bond::mixnode_bond_details, mixnet::bond::unbond_gateway, mixnet::bond::unbond_mixnode, mixnet::bond::update_mixnode, mixnet::delegate::delegate_to_mixnode, + mixnet::delegate::get_delegator_rewards, mixnet::delegate::get_reverse_mix_delegations_paged, mixnet::delegate::undelegate_from_mixnode, mixnet::send::send, diff --git a/nym-wallet/src-tauri/src/operations/mixnet/bond.rs b/nym-wallet/src-tauri/src/operations/mixnet/bond.rs index 7118ee8a8f..fc024075a9 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/bond.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/bond.rs @@ -3,6 +3,7 @@ use crate::error::BackendError; use crate::nymd_client; use crate::state::State; use crate::{Gateway, MixNode}; +use cosmwasm_std::Uint128; use mixnet_contract_common::{GatewayBond, MixNodeBond}; use std::sync::Arc; use tokio::sync::RwLock; @@ -83,3 +84,11 @@ pub async fn gateway_bond_details( let bond = client.nymd.owns_gateway(client.nymd.address()).await?; Ok(bond) } + +#[tauri::command] +pub async fn get_operator_rewards( + address: String, + state: tauri::State<'_, Arc>>, +) -> Result { + Ok(nymd_client!(state).get_operator_rewards(address).await?) +} diff --git a/nym-wallet/src-tauri/src/operations/mixnet/delegate.rs b/nym-wallet/src-tauri/src/operations/mixnet/delegate.rs index d29917ab2e..b4e5bb0129 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/delegate.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/delegate.rs @@ -3,8 +3,8 @@ use crate::error::BackendError; use crate::nymd_client; use crate::state::State; use crate::utils::DelegationResult; -use cosmwasm_std::Coin as CosmWasmCoin; -use mixnet_contract_common::PagedDelegatorDelegationsResponse; +use cosmwasm_std::{Coin as CosmWasmCoin, Uint128}; +use mixnet_contract_common::{IdentityKey, PagedDelegatorDelegationsResponse}; use std::sync::Arc; use tokio::sync::RwLock; @@ -51,3 +51,16 @@ pub async fn get_reverse_mix_delegations_paged( .await?, ) } + +#[tauri::command] +pub async fn get_delegator_rewards( + address: String, + mix_identity: IdentityKey, + state: tauri::State<'_, Arc>>, +) -> Result { + Ok( + nymd_client!(state) + .get_delegator_rewards(address, mix_identity) + .await?, + ) +} diff --git a/validator-api/src/nymd_client.rs b/validator-api/src/nymd_client.rs index 2b8a591e89..cb873f2135 100644 --- a/validator-api/src/nymd_client.rs +++ b/validator-api/src/nymd_client.rs @@ -140,6 +140,33 @@ impl Client { self.0.read().await.get_contract_settings().await } + #[allow(dead_code)] + pub(crate) async fn get_operator_rewards( + &self, + address: String, + ) -> Result + where + C: CosmWasmClient + Sync, + { + self.0.read().await.get_operator_rewards(address).await + } + + #[allow(dead_code)] + pub(crate) async fn get_delegator_rewards( + &self, + address: String, + mix_identity: IdentityKey, + ) -> Result + where + C: CosmWasmClient + Sync, + { + self.0 + .read() + .await + .get_delegator_rewards(address, mix_identity) + .await + } + pub(crate) async fn get_current_epoch(&self) -> Result, ValidatorClientError> where C: CosmWasmClient + Sync,