nym-validator-client 1.21.4

Client for interacting with Nyx Cosmos SDK blockchain
Documentation
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0

use crate::nyxd::contract_traits::NymContractsProvider;
use crate::nyxd::cosmwasm_client::types::ExecuteResult;
use crate::nyxd::error::NyxdError;
use crate::nyxd::{Coin, Fee, SigningCosmWasmClient};
use crate::signing::signer::OfflineSigner;
use async_trait::async_trait;
use nym_ecash_contract_common::msg::ExecuteMsg as EcashExecuteMsg;

#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait EcashSigningClient {
    async fn execute_ecash_contract(
        &self,
        fee: Option<Fee>,
        msg: EcashExecuteMsg,
        memo: String,
        funds: Vec<Coin>,
    ) -> Result<ExecuteResult, NyxdError>;

    async fn make_ticketbook_deposit(
        &self,
        public_key: String,
        deposit_amount: Coin,
        fee: Option<Fee>,
    ) -> Result<ExecuteResult, NyxdError> {
        let req = EcashExecuteMsg::DepositTicketBookFunds {
            identity_key: public_key,
        };
        self.execute_ecash_contract(fee, req, "Ecash::Deposit".to_string(), vec![deposit_amount])
            .await
    }

    async fn request_ticket_redemption(
        &self,
        commitment_bs58: String,
        number_of_tickets: u16,
        fee: Option<Fee>,
    ) -> Result<ExecuteResult, NyxdError> {
        let req = EcashExecuteMsg::RequestRedemption {
            commitment_bs58,
            number_of_tickets,
        };
        self.execute_ecash_contract(fee, req, Default::default(), vec![])
            .await
    }

    async fn update_admin(
        &self,
        admin: String,
        fee: Option<Fee>,
    ) -> Result<ExecuteResult, NyxdError> {
        let req = EcashExecuteMsg::UpdateAdmin { admin };
        self.execute_ecash_contract(fee, req, "Ecash::UpdateAdmin".to_string(), vec![])
            .await
    }

    async fn update_deposit_value(
        &self,
        new_deposit: Coin,
        fee: Option<Fee>,
    ) -> Result<ExecuteResult, NyxdError> {
        let req = EcashExecuteMsg::UpdateDefaultDepositValue {
            new_deposit: new_deposit.into(),
        };
        self.execute_ecash_contract(fee, req, "Ecash::UpdateDepositValue".to_string(), vec![])
            .await
    }

    async fn set_reduced_deposit_price(
        &self,
        address: String,
        deposit: Coin,
        fee: Option<Fee>,
    ) -> Result<ExecuteResult, NyxdError> {
        let req = EcashExecuteMsg::SetReducedDepositPrice {
            address,
            deposit: deposit.into(),
        };
        self.execute_ecash_contract(
            fee,
            req,
            "Ecash::SetReducedDepositPrice".to_string(),
            vec![],
        )
        .await
    }

    async fn remove_reduced_deposit_price(
        &self,
        address: String,
        fee: Option<Fee>,
    ) -> Result<ExecuteResult, NyxdError> {
        let req = EcashExecuteMsg::RemoveReducedDepositPrice { address };
        self.execute_ecash_contract(
            fee,
            req,
            "Ecash::RemoveReducedDepositPrice".to_string(),
            vec![],
        )
        .await
    }

    async fn propose_for_blacklist(
        &self,
        public_key: String,
        fee: Option<Fee>,
    ) -> Result<ExecuteResult, NyxdError> {
        let req = EcashExecuteMsg::ProposeToBlacklist { public_key };
        self.execute_ecash_contract(fee, req, "Ecash::ProposeToBlacklist".to_string(), vec![])
            .await
    }
}

#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl<C> EcashSigningClient for C
where
    C: SigningCosmWasmClient + NymContractsProvider + Sync,
    NyxdError: From<<Self as OfflineSigner>::Error>,
{
    async fn execute_ecash_contract(
        &self,
        fee: Option<Fee>,
        msg: EcashExecuteMsg,
        memo: String,
        funds: Vec<Coin>,
    ) -> Result<ExecuteResult, NyxdError> {
        let ecash_contract_address = self
            .ecash_contract_address()
            .ok_or_else(|| NyxdError::unavailable_contract_address("coconut bandwidth contract"))?;

        let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier())));
        let signer_address = &self.signer_addresses()[0];

        self.execute(
            signer_address,
            ecash_contract_address,
            &msg,
            fee,
            memo,
            funds,
        )
        .await
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::nyxd::contract_traits::tests::{mock_coin, IgnoreValue};
    use nym_ecash_contract_common::msg::ExecuteMsg;

    // it's enough that this compiles and clippy is happy about it
    #[allow(dead_code)]
    fn all_execute_variants_are_covered<C: EcashSigningClient + Send + Sync>(
        client: C,
        msg: EcashExecuteMsg,
    ) {
        match msg {
            EcashExecuteMsg::DepositTicketBookFunds { identity_key } => client
                .make_ticketbook_deposit(identity_key.to_string(), mock_coin(), None)
                .ignore(),
            EcashExecuteMsg::AddToBlacklist { public_key: _ } => unimplemented!(), //no add to blacklist method on client
            EcashExecuteMsg::ProposeToBlacklist { public_key } => {
                client.propose_for_blacklist(public_key, None).ignore()
            }
            ExecuteMsg::RequestRedemption {
                commitment_bs58,
                number_of_tickets,
            } => client
                .request_ticket_redemption(commitment_bs58, number_of_tickets, None)
                .ignore(),
            ExecuteMsg::RedeemTickets { .. } => unimplemented!(), // no redeem tickets method for the client
            ExecuteMsg::UpdateAdmin { admin } => client.update_admin(admin, None).ignore(),
            ExecuteMsg::UpdateDefaultDepositValue { new_deposit } => client
                .update_deposit_value(new_deposit.into(), None)
                .ignore(),
            ExecuteMsg::SetReducedDepositPrice { address, deposit } => client
                .set_reduced_deposit_price(address, deposit.into(), None)
                .ignore(),
            ExecuteMsg::RemoveReducedDepositPrice { address } => {
                client.remove_reduced_deposit_price(address, None).ignore()
            }
        };
    }
}