Skip to main content

nym_validator_client/nyxd/
mod.rs

1// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
2// SPDX-License-Identifier: Apache-2.0
3
4// TEMPORARY WORKAROUND:
5// those features are expected as the below should only get activated whenever
6// the corresponding features in tendermint-rpc are enabled transitively
7#![allow(unexpected_cfgs)]
8
9use crate::nyxd::contract_traits::{NymContractsProvider, TypedNymContracts};
10use crate::nyxd::cosmwasm_client::types::{
11    ChangeAdminResult, ContractCodeId, ExecuteResult, InstantiateOptions, InstantiateResult,
12    MigrateResult, SequenceResponse, SimulateResponse, UploadResult,
13};
14use crate::nyxd::cosmwasm_client::MaybeSigningClient;
15use crate::nyxd::error::NyxdError;
16use crate::nyxd::fee::DEFAULT_SIMULATED_GAS_MULTIPLIER;
17use crate::signing::direct_wallet::DirectSecp256k1HdWallet;
18use crate::signing::signer::NoSigner;
19use crate::signing::signer::OfflineSigner;
20use crate::signing::tx_signer::TxSigner;
21use crate::signing::AccountData;
22use crate::{DirectSigningReqwestRpcNyxdClient, QueryReqwestRpcNyxdClient};
23use async_trait::async_trait;
24use cosmrs::tendermint::{abci, evidence::Evidence, Genesis};
25use cosmrs::tx::{Raw, SignDoc};
26use cosmwasm_std::Addr;
27use nym_contracts_common::build_information::CONTRACT_BUILD_INFO_STORAGE_KEY;
28use nym_contracts_common::ContractBuildInformation;
29use nym_network_defaults::{ChainDetails, NymNetworkDetails};
30use serde::{de::DeserializeOwned, Serialize};
31use std::fmt::Debug;
32use std::time::SystemTime;
33use tendermint_rpc::endpoint::*;
34use tendermint_rpc::{Error as TendermintRpcError, Order};
35use url::Url;
36
37pub use crate::nyxd::{
38    cosmwasm_client::{
39        client_traits::{CosmWasmClient, SigningCosmWasmClient},
40        module_traits::{self, StakingQueryClient},
41    },
42    fee::Fee,
43};
44pub use crate::rpc::TendermintRpcClient;
45pub use bip39;
46pub use coin::Coin;
47pub use cosmrs::{
48    bank::MsgSend,
49    bip32, cosmwasm,
50    crypto::PublicKey,
51    query::{PageRequest, PageResponse},
52    tendermint::{
53        abci::{response::DeliverTx, types::ExecTxResult, Event, EventAttribute},
54        block::Height,
55        hash::{self, Algorithm, Hash},
56        validator::Info as TendermintValidatorInfo,
57        Time as TendermintTime,
58    },
59    tx::{self, Msg},
60    AccountId, Any, Coin as CosmosCoin, Denom, Gas,
61};
62pub use cosmwasm_std::Coin as CosmWasmCoin;
63pub use cw2;
64pub use cw3;
65pub use cw4;
66pub use cw_controllers;
67pub use fee::{gas_price::GasPrice, GasAdjustable, GasAdjustment};
68pub use prost::Name;
69pub use tendermint_rpc::endpoint::block::Response as BlockResponse;
70pub use tendermint_rpc::{
71    endpoint::{tx::Response as TxResponse, validators::Response as ValidatorResponse},
72    query::Query,
73    Paging, Request, Response, SimpleRequest,
74};
75
76pub use nym_ecash_contract_common;
77pub use nym_mixnet_contract_common;
78pub use nym_multisig_contract_common;
79pub use nym_network_monitors_contract_common;
80pub use nym_performance_contract_common;
81pub use nym_vesting_contract_common;
82
83#[cfg(feature = "http-client")]
84use crate::http_client;
85#[cfg(feature = "http-client")]
86use crate::{DirectSigningHttpRpcNyxdClient, QueryHttpRpcNyxdClient};
87#[cfg(feature = "http-client")]
88use cosmrs::rpc::{HttpClient, HttpClientUrl};
89
90pub mod coin;
91pub mod contract_traits;
92pub mod cosmwasm_client;
93pub mod error;
94pub mod fee;
95pub mod helpers;
96
97#[derive(Debug, Clone)]
98pub struct Config {
99    pub(crate) chain_details: ChainDetails,
100    pub(crate) contracts: TypedNymContracts,
101    pub(crate) gas_price: GasPrice,
102    pub(crate) simulated_gas_multiplier: f32,
103}
104
105impl Config {
106    pub fn chain_details(&self) -> &ChainDetails {
107        &self.chain_details
108    }
109
110    pub fn contracts(&self) -> &TypedNymContracts {
111        &self.contracts
112    }
113}
114
115impl Config {
116    pub fn try_from_nym_network_details(details: &NymNetworkDetails) -> Result<Self, NyxdError> {
117        Ok(Config {
118            chain_details: details.chain_details.clone(),
119            contracts: TypedNymContracts::try_from(details.contracts.clone())?,
120            gas_price: details.try_into()?,
121            simulated_gas_multiplier: DEFAULT_SIMULATED_GAS_MULTIPLIER,
122        })
123    }
124
125    pub fn with_simulated_gas_multplier(mut self, simulated_gas_multiplier: f32) -> Self {
126        self.simulated_gas_multiplier = simulated_gas_multiplier;
127        self
128    }
129}
130
131impl TryFrom<NymNetworkDetails> for Config {
132    type Error = NyxdError;
133
134    fn try_from(value: NymNetworkDetails) -> Result<Self, Self::Error> {
135        Config::try_from_nym_network_details(&value)
136    }
137}
138
139#[derive(Debug)]
140pub struct NyxdClient<C, S = NoSigner> {
141    client: MaybeSigningClient<C, S>,
142    config: Config,
143}
144
145// terrible name, but can't really change it because it will break so many uses
146#[cfg(feature = "http-client")]
147impl NyxdClient<HttpClient> {
148    pub fn connect<U>(config: Config, endpoint: U) -> Result<QueryHttpRpcNyxdClient, NyxdError>
149    where
150        U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
151    {
152        let client = http_client(endpoint)?;
153
154        Ok(NyxdClient {
155            client: MaybeSigningClient::new(client, (&config).into()),
156            config,
157        })
158    }
159
160    pub fn connect_with_network_details<U>(
161        endpoint: U,
162        network_details: NymNetworkDetails,
163    ) -> Result<QueryHttpRpcNyxdClient, NyxdError>
164    where
165        U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
166    {
167        let config = Config::try_from_nym_network_details(&network_details)?;
168        Self::connect(config, endpoint)
169    }
170
171    pub fn connect_to_default_env<U>(endpoint: U) -> Result<QueryHttpRpcNyxdClient, NyxdError>
172    where
173        U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
174    {
175        Self::connect_with_network_details(endpoint, NymNetworkDetails::new_from_env())
176    }
177}
178
179#[allow(deprecated)]
180impl NyxdClient<crate::ReqwestRpcClient> {
181    pub fn connect_reqwest(
182        config: Config,
183        endpoint: Url,
184    ) -> Result<QueryReqwestRpcNyxdClient, NyxdError> {
185        let client = crate::ReqwestRpcClient::new(endpoint);
186
187        Ok(NyxdClient {
188            client: MaybeSigningClient::new(client, (&config).into()),
189            config,
190        })
191    }
192}
193
194impl<C> NyxdClient<C> {
195    pub fn new(config: Config, client: C) -> Self {
196        NyxdClient {
197            client: MaybeSigningClient::new(client, (&config).into()),
198            config,
199        }
200    }
201}
202
203// terrible name, but can't really change it because it will break so many uses
204#[cfg(feature = "http-client")]
205impl NyxdClient<HttpClient, DirectSecp256k1HdWallet> {
206    pub fn connect_with_mnemonic<U>(
207        config: Config,
208        endpoint: U,
209        mnemonic: bip39::Mnemonic,
210    ) -> Result<DirectSigningHttpRpcNyxdClient, NyxdError>
211    where
212        U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
213    {
214        let client = http_client(endpoint)?;
215
216        let prefix = &config.chain_details.bech32_account_prefix;
217        let wallet = DirectSecp256k1HdWallet::checked_from_mnemonic(prefix, mnemonic)?;
218        Ok(Self::connect_with_signer(config, client, wallet))
219    }
220
221    pub fn connect_with_mnemonic_and_network_details<U>(
222        endpoint: U,
223        network_details: NymNetworkDetails,
224        mnemonic: bip39::Mnemonic,
225    ) -> Result<DirectSigningHttpRpcNyxdClient, NyxdError>
226    where
227        U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
228    {
229        let config = Config::try_from_nym_network_details(&network_details)?;
230        Self::connect_with_mnemonic(config, endpoint, mnemonic)
231    }
232}
233
234#[allow(deprecated)]
235impl NyxdClient<crate::ReqwestRpcClient, DirectSecp256k1HdWallet> {
236    pub fn connect_reqwest_with_mnemonic(
237        config: Config,
238        endpoint: Url,
239        mnemonic: bip39::Mnemonic,
240    ) -> DirectSigningReqwestRpcNyxdClient {
241        let client = crate::ReqwestRpcClient::new(endpoint);
242
243        let prefix = &config.chain_details.bech32_account_prefix;
244        let wallet = DirectSecp256k1HdWallet::from_mnemonic(prefix, mnemonic);
245        Self::connect_with_signer(config, client, wallet)
246    }
247}
248
249impl<C, S> NyxdClient<C, S>
250where
251    S: OfflineSigner,
252{
253    pub fn connect_with_signer(config: Config, client: C, signer: S) -> NyxdClient<C, S> {
254        NyxdClient {
255            client: MaybeSigningClient::new_signing(client, signer, (&config).into()),
256            config,
257        }
258    }
259}
260
261#[cfg(feature = "http-client")]
262impl<S> NyxdClient<HttpClient, S> {
263    pub fn change_endpoint<U>(&mut self, new_endpoint: U) -> Result<(), NyxdError>
264    where
265        U: TryInto<HttpClientUrl, Error = TendermintRpcError>,
266    {
267        self.client.change_endpoint(new_endpoint)
268    }
269}
270
271// no trait bounds
272impl<C, S> NyxdClient<C, S> {
273    pub fn new_signing(config: Config, client: C, signer: S) -> Self
274    where
275        S: OfflineSigner,
276    {
277        NyxdClient {
278            client: MaybeSigningClient::new_signing(client, signer, (&config).into()),
279            config,
280        }
281    }
282
283    pub fn clone_query_client(&self) -> NyxdClient<C>
284    where
285        C: Clone,
286    {
287        NyxdClient {
288            client: self.client.clone_query_client(),
289            config: self.config.clone(),
290        }
291    }
292
293    pub fn current_config(&self) -> &Config {
294        &self.config
295    }
296
297    pub fn current_chain_details(&self) -> &ChainDetails {
298        &self.config.chain_details
299    }
300
301    pub fn set_mixnet_contract_address(&mut self, address: AccountId) {
302        self.config.contracts.mixnet_contract_address = Some(address);
303    }
304
305    pub fn set_vesting_contract_address(&mut self, address: AccountId) {
306        self.config.contracts.vesting_contract_address = Some(address);
307    }
308
309    pub fn set_ecash_contract_address(&mut self, address: AccountId) {
310        self.config.contracts.ecash_contract_address = Some(address);
311    }
312
313    pub fn set_multisig_contract_address(&mut self, address: AccountId) {
314        self.config.contracts.multisig_contract_address = Some(address);
315    }
316
317    pub fn set_node_families_contract_address(&mut self, address: AccountId) {
318        self.config.contracts.node_families_contract_address = Some(address);
319    }
320
321    pub fn set_simulated_gas_multiplier(&mut self, multiplier: f32) {
322        self.config.simulated_gas_multiplier = multiplier;
323    }
324
325    pub fn get_nym_contracts(&self) -> TypedNymContracts {
326        self.config.contracts.clone()
327    }
328
329    pub fn get_chain_details(&self) -> ChainDetails {
330        self.config.chain_details.clone()
331    }
332}
333
334impl<C, S> NymContractsProvider for NyxdClient<C, S> {
335    fn mixnet_contract_address(&self) -> Option<&AccountId> {
336        self.config.contracts.mixnet_contract_address.as_ref()
337    }
338
339    fn vesting_contract_address(&self) -> Option<&AccountId> {
340        self.config.contracts.vesting_contract_address.as_ref()
341    }
342
343    fn performance_contract_address(&self) -> Option<&AccountId> {
344        self.config.contracts.performance_contract_address.as_ref()
345    }
346    fn network_monitors_contract_address(&self) -> Option<&AccountId> {
347        self.config
348            .contracts
349            .network_monitors_contract_address
350            .as_ref()
351    }
352
353    fn node_families_contract_address(&self) -> Option<&AccountId> {
354        self.config
355            .contracts
356            .node_families_contract_address
357            .as_ref()
358    }
359
360    fn ecash_contract_address(&self) -> Option<&AccountId> {
361        self.config.contracts.ecash_contract_address.as_ref()
362    }
363
364    fn dkg_contract_address(&self) -> Option<&AccountId> {
365        self.config.contracts.coconut_dkg_contract_address.as_ref()
366    }
367
368    fn group_contract_address(&self) -> Option<&AccountId> {
369        self.config.contracts.group_contract_address.as_ref()
370    }
371
372    fn multisig_contract_address(&self) -> Option<&AccountId> {
373        self.config.contracts.multisig_contract_address.as_ref()
374    }
375}
376
377// queries
378impl<C, S> NyxdClient<C, S>
379where
380    C: TendermintRpcClient + Send + Sync,
381    S: Send + Sync,
382{
383    pub async fn get_account_public_key(
384        &self,
385        address: &AccountId,
386    ) -> Result<Option<cosmrs::crypto::PublicKey>, NyxdError> {
387        if let Some(account) = self.client.get_account(address).await? {
388            let base_account = account.try_get_base_account()?;
389            return Ok(base_account.pubkey);
390        }
391
392        Ok(None)
393    }
394
395    pub async fn get_current_block_timestamp(&self) -> Result<TendermintTime, NyxdError> {
396        self.get_block_timestamp(None).await
397    }
398
399    pub async fn get_block_timestamp(
400        &self,
401        height: Option<u32>,
402    ) -> Result<TendermintTime, NyxdError> {
403        Ok(self.client.get_block(height).await?.block.header.time)
404    }
405
406    pub async fn get_block(&self, height: Option<u32>) -> Result<BlockResponse, NyxdError> {
407        self.client.get_block(height).await
408    }
409
410    pub async fn get_current_block_height(&self) -> Result<Height, NyxdError> {
411        self.client.get_height().await
412    }
413
414    /// Obtains the hash of a block specified by the provided height.
415    ///
416    /// # Arguments
417    ///
418    /// * `height`: height of the block for which we want to obtain the hash.
419    pub async fn get_block_hash(&self, height: u32) -> Result<Hash, NyxdError> {
420        self.client
421            .get_block(Some(height))
422            .await
423            .map(|block| block.block_id.hash)
424    }
425
426    pub async fn try_get_cw2_contract_version(
427        &self,
428        contract_address: &AccountId,
429    ) -> Option<cw2::ContractVersion> {
430        let raw_info = self
431            .query_contract_raw(contract_address, b"contract_info".to_vec())
432            .await
433            .ok()?;
434
435        serde_json::from_slice(&raw_info).ok()
436    }
437
438    pub async fn try_get_contract_build_information(
439        &self,
440        contract_address: &AccountId,
441    ) -> Option<ContractBuildInformation> {
442        let raw_info = self
443            .query_contract_raw(
444                contract_address,
445                CONTRACT_BUILD_INFO_STORAGE_KEY.as_bytes().to_vec(),
446            )
447            .await
448            .ok()?;
449
450        serde_json::from_slice(&raw_info).ok()
451    }
452}
453
454// signing
455impl<C, S> NyxdClient<C, S>
456where
457    C: TendermintRpcClient + Send + Sync,
458    S: OfflineSigner + Send + Sync,
459    NyxdError: From<<S as OfflineSigner>::Error>,
460{
461    pub fn signing_account(&self) -> Result<&AccountData, NyxdError> {
462        Ok(self.find_account(&self.address())?)
463    }
464
465    pub fn address(&self) -> AccountId {
466        self.client.signer_addresses()[0].clone()
467    }
468
469    pub fn mix_coin(&self, amount: u128) -> Coin {
470        Coin::new(amount, &self.config.chain_details.mix_denom.base)
471    }
472
473    pub fn mix_coins(&self, amount: u128) -> Vec<Coin> {
474        vec![self.mix_coin(amount)]
475    }
476
477    pub fn cw_address(&self) -> Addr {
478        // the call to unchecked is fine here as we're converting directly from `AccountId`
479        // which must have been a valid bech32 address
480        Addr::unchecked(self.address().as_ref())
481    }
482
483    pub async fn account_sequence(&self) -> Result<SequenceResponse, NyxdError> {
484        self.client.get_sequence(&self.address()).await
485    }
486
487    pub fn wrap_contract_execute_message<M>(
488        &self,
489        contract_address: &AccountId,
490        msg: &M,
491        funds: Vec<Coin>,
492    ) -> Result<cosmwasm::MsgExecuteContract, NyxdError>
493    where
494        M: ?Sized + Serialize,
495    {
496        Ok(cosmwasm::MsgExecuteContract {
497            sender: self.address(),
498            contract: contract_address.clone(),
499            msg: serde_json::to_vec(msg)?,
500            funds: funds.into_iter().map(Into::into).collect(),
501        })
502    }
503
504    pub async fn simulate<I, M>(
505        &self,
506        messages: I,
507        memo: impl Into<String> + Send + 'static,
508    ) -> Result<SimulateResponse, NyxdError>
509    where
510        I: IntoIterator<Item = M> + Send,
511        M: Msg,
512    {
513        self.client
514            .simulate(
515                &self.address(),
516                messages
517                    .into_iter()
518                    .map(|msg| msg.into_any())
519                    .collect::<Result<Vec<_>, _>>()
520                    .map_err(|_| {
521                        NyxdError::SerializationError("custom simulate messages".to_owned())
522                    })?,
523                memo,
524            )
525            .await
526    }
527
528    /// Send funds from one address to another
529    pub async fn send(
530        &self,
531        recipient: &AccountId,
532        amount: Vec<Coin>,
533        memo: impl Into<String> + Send + 'static,
534        fee: Option<Fee>,
535    ) -> Result<TxResponse, NyxdError> {
536        let fee = fee.unwrap_or(Fee::Auto(Some(self.config.simulated_gas_multiplier)));
537        self.client
538            .send_tokens(&self.address(), recipient, amount, fee, memo)
539            .await
540    }
541
542    /// Send funds from one address to multiple others
543    pub async fn send_multiple(
544        &self,
545        msgs: Vec<(AccountId, Vec<Coin>)>,
546        memo: impl Into<String> + Send + 'static,
547        fee: Option<Fee>,
548    ) -> Result<TxResponse, NyxdError> {
549        let fee = fee.unwrap_or(Fee::Auto(Some(self.config.simulated_gas_multiplier)));
550        self.client
551            .send_tokens_multiple(&self.address(), msgs, fee, memo)
552            .await
553    }
554
555    /// Grant a fee allowance from one address to another
556    pub async fn grant_allowance(
557        &self,
558        grantee: &AccountId,
559        spend_limit: Vec<Coin>,
560        expiration: Option<SystemTime>,
561        allowed_messages: Vec<String>,
562        memo: impl Into<String> + Send + 'static,
563        fee: Option<Fee>,
564    ) -> Result<TxResponse, NyxdError> {
565        let fee = fee.unwrap_or(Fee::Auto(Some(self.config.simulated_gas_multiplier)));
566        self.client
567            .grant_allowance(
568                &self.address(),
569                grantee,
570                spend_limit,
571                expiration,
572                allowed_messages,
573                fee,
574                memo,
575            )
576            .await
577    }
578
579    /// Revoke a fee allowance from one address to another
580    pub async fn revoke_allowance(
581        &self,
582        grantee: &AccountId,
583        memo: impl Into<String> + Send + 'static,
584        fee: Option<Fee>,
585    ) -> Result<TxResponse, NyxdError> {
586        let fee = fee.unwrap_or(Fee::Auto(Some(self.config.simulated_gas_multiplier)));
587        self.client
588            .revoke_allowance(&self.address(), grantee, fee, memo)
589            .await
590    }
591
592    pub async fn execute<M>(
593        &self,
594        contract_address: &AccountId,
595        msg: &M,
596        fee: Option<Fee>,
597        memo: impl Into<String> + Send + 'static,
598        funds: Vec<Coin>,
599    ) -> Result<ExecuteResult, NyxdError>
600    where
601        M: ?Sized + Serialize + Sync,
602    {
603        let fee = fee.unwrap_or(Fee::Auto(Some(self.config.simulated_gas_multiplier)));
604        self.client
605            .execute(&self.address(), contract_address, msg, fee, memo, funds)
606            .await
607    }
608
609    pub async fn execute_multiple<I, M>(
610        &self,
611        contract_address: &AccountId,
612        msgs: I,
613        fee: Option<Fee>,
614        memo: impl Into<String> + Send + 'static,
615    ) -> Result<ExecuteResult, NyxdError>
616    where
617        I: IntoIterator<Item = (M, Vec<Coin>)> + Send,
618        M: Serialize,
619    {
620        let fee = fee.unwrap_or(Fee::Auto(Some(self.config.simulated_gas_multiplier)));
621        self.client
622            .execute_multiple(&self.address(), contract_address, msgs, fee, memo)
623            .await
624    }
625
626    pub async fn upload(
627        &self,
628        wasm_code: Vec<u8>,
629        memo: impl Into<String> + Send + 'static,
630        fee: Option<Fee>,
631    ) -> Result<UploadResult, NyxdError> {
632        let fee = fee.unwrap_or(Fee::Auto(Some(self.config.simulated_gas_multiplier)));
633        self.client
634            .upload(&self.address(), wasm_code, fee, memo)
635            .await
636    }
637
638    pub async fn instantiate<M>(
639        &self,
640        code_id: ContractCodeId,
641        msg: &M,
642        label: String,
643        memo: impl Into<String> + Send + 'static,
644        options: Option<InstantiateOptions>,
645        fee: Option<Fee>,
646    ) -> Result<InstantiateResult, NyxdError>
647    where
648        M: ?Sized + Serialize + Sync,
649    {
650        let fee = fee.unwrap_or(Fee::Auto(Some(self.config.simulated_gas_multiplier)));
651        self.client
652            .instantiate(&self.address(), code_id, msg, label, fee, memo, options)
653            .await
654    }
655
656    pub async fn update_admin(
657        &self,
658        contract_address: &AccountId,
659        new_admin: &AccountId,
660        memo: impl Into<String> + Send + 'static,
661        fee: Option<Fee>,
662    ) -> Result<ChangeAdminResult, NyxdError> {
663        let fee = fee.unwrap_or(Fee::Auto(Some(self.config.simulated_gas_multiplier)));
664        self.client
665            .update_admin(&self.address(), contract_address, new_admin, fee, memo)
666            .await
667    }
668
669    pub async fn clear_admin(
670        &self,
671        contract_address: &AccountId,
672        memo: impl Into<String> + Send + 'static,
673        fee: Option<Fee>,
674    ) -> Result<ChangeAdminResult, NyxdError> {
675        let fee = fee.unwrap_or(Fee::Auto(Some(self.config.simulated_gas_multiplier)));
676        self.client
677            .clear_admin(&self.address(), contract_address, fee, memo)
678            .await
679    }
680
681    pub async fn migrate<M>(
682        &self,
683        contract_address: &AccountId,
684        code_id: ContractCodeId,
685        msg: &M,
686        memo: impl Into<String> + Send + 'static,
687        fee: Option<Fee>,
688    ) -> Result<MigrateResult, NyxdError>
689    where
690        M: ?Sized + Serialize + Sync,
691    {
692        let fee = fee.unwrap_or(Fee::Auto(Some(self.config.simulated_gas_multiplier)));
693        self.client
694            .migrate(&self.address(), contract_address, code_id, fee, msg, memo)
695            .await
696    }
697}
698
699// ugh. is there a way to avoid that nasty trait implementation?
700
701#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
702#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
703impl<C, S> TendermintRpcClient for NyxdClient<C, S>
704where
705    C: TendermintRpcClient + Send + Sync,
706    S: Send + Sync,
707{
708    async fn abci_info(&self) -> Result<abci::response::Info, TendermintRpcError> {
709        self.client.abci_info().await
710    }
711
712    async fn abci_query<V>(
713        &self,
714        path: Option<String>,
715        data: V,
716        height: Option<Height>,
717        prove: bool,
718    ) -> Result<abci_query::AbciQuery, TendermintRpcError>
719    where
720        V: Into<Vec<u8>> + Send,
721    {
722        self.client.abci_query(path, data, height, prove).await
723    }
724
725    async fn block<H>(&self, height: H) -> Result<block::Response, TendermintRpcError>
726    where
727        H: Into<Height> + Send,
728    {
729        self.client.block(height).await
730    }
731
732    async fn block_by_hash(
733        &self,
734        hash: Hash,
735    ) -> Result<block_by_hash::Response, TendermintRpcError> {
736        self.client.block_by_hash(hash).await
737    }
738
739    async fn latest_block(&self) -> Result<block::Response, TendermintRpcError> {
740        self.client.latest_block().await
741    }
742
743    async fn header<H>(&self, height: H) -> Result<header::Response, TendermintRpcError>
744    where
745        H: Into<Height> + Send,
746    {
747        self.client.header(height).await
748    }
749
750    async fn header_by_hash(
751        &self,
752        hash: Hash,
753    ) -> Result<header_by_hash::Response, TendermintRpcError> {
754        self.client.header_by_hash(hash).await
755    }
756
757    async fn block_results<H>(
758        &self,
759        height: H,
760    ) -> Result<block_results::Response, TendermintRpcError>
761    where
762        H: Into<Height> + Send,
763    {
764        self.client.block_results(height).await
765    }
766
767    async fn latest_block_results(&self) -> Result<block_results::Response, TendermintRpcError> {
768        self.client.latest_block_results().await
769    }
770
771    async fn block_search(
772        &self,
773        query: Query,
774        page: u32,
775        per_page: u8,
776        order: Order,
777    ) -> Result<block_search::Response, TendermintRpcError> {
778        self.client.block_search(query, page, per_page, order).await
779    }
780
781    async fn blockchain<H>(
782        &self,
783        min: H,
784        max: H,
785    ) -> Result<blockchain::Response, TendermintRpcError>
786    where
787        H: Into<Height> + Send,
788    {
789        self.client.blockchain(min, max).await
790    }
791
792    async fn broadcast_tx_async<T>(
793        &self,
794        tx: T,
795    ) -> Result<broadcast::tx_async::Response, TendermintRpcError>
796    where
797        T: Into<Vec<u8>> + Send,
798    {
799        TendermintRpcClient::broadcast_tx_async(&self.client, tx).await
800    }
801
802    async fn broadcast_tx_sync<T>(
803        &self,
804        tx: T,
805    ) -> Result<broadcast::tx_sync::Response, TendermintRpcError>
806    where
807        T: Into<Vec<u8>> + Send,
808    {
809        TendermintRpcClient::broadcast_tx_sync(&self.client, tx).await
810    }
811
812    async fn broadcast_tx_commit<T>(
813        &self,
814        tx: T,
815    ) -> Result<broadcast::tx_commit::Response, TendermintRpcError>
816    where
817        T: Into<Vec<u8>> + Send,
818    {
819        TendermintRpcClient::broadcast_tx_commit(&self.client, tx).await
820    }
821
822    async fn commit<H>(&self, height: H) -> Result<commit::Response, TendermintRpcError>
823    where
824        H: Into<Height> + Send,
825    {
826        self.client.commit(height).await
827    }
828
829    async fn consensus_params<H>(
830        &self,
831        height: H,
832    ) -> Result<consensus_params::Response, TendermintRpcError>
833    where
834        H: Into<Height> + Send,
835    {
836        self.client.consensus_params(height).await
837    }
838
839    async fn consensus_state(&self) -> Result<consensus_state::Response, TendermintRpcError> {
840        self.client.consensus_state().await
841    }
842
843    async fn validators<H>(
844        &self,
845        height: H,
846        paging: Paging,
847    ) -> Result<validators::Response, TendermintRpcError>
848    where
849        H: Into<Height> + Send,
850    {
851        TendermintRpcClient::validators(&self.client, height, paging).await
852    }
853
854    async fn latest_consensus_params(
855        &self,
856    ) -> Result<consensus_params::Response, TendermintRpcError> {
857        self.client.latest_consensus_params().await
858    }
859
860    async fn latest_commit(&self) -> Result<commit::Response, TendermintRpcError> {
861        self.client.latest_commit().await
862    }
863
864    async fn health(&self) -> Result<(), TendermintRpcError> {
865        self.client.health().await
866    }
867
868    async fn genesis<AppState>(&self) -> Result<Genesis<AppState>, TendermintRpcError>
869    where
870        AppState: Debug + Serialize + DeserializeOwned + Send,
871    {
872        self.client.genesis().await
873    }
874
875    async fn net_info(&self) -> Result<net_info::Response, TendermintRpcError> {
876        self.client.net_info().await
877    }
878
879    async fn status(&self) -> Result<status::Response, TendermintRpcError> {
880        self.client.status().await
881    }
882
883    async fn broadcast_evidence(
884        &self,
885        e: Evidence,
886    ) -> Result<evidence::Response, TendermintRpcError> {
887        self.client.broadcast_evidence(e).await
888    }
889
890    async fn tx(&self, hash: Hash, prove: bool) -> Result<TxResponse, TendermintRpcError> {
891        self.client.tx(hash, prove).await
892    }
893
894    async fn tx_search(
895        &self,
896        query: Query,
897        prove: bool,
898        page: u32,
899        per_page: u8,
900        order: Order,
901    ) -> Result<tx_search::Response, TendermintRpcError> {
902        self.client
903            .tx_search(query, prove, page, per_page, order)
904            .await
905    }
906
907    #[cfg(any(
908        feature = "tendermint-rpc-http-client",
909        feature = "tendermint-rpc-websocket-client"
910    ))]
911    async fn wait_until_healthy<T>(&self, timeout: T) -> Result<(), TendermintRpcError>
912    where
913        T: Into<core::time::Duration> + Send,
914    {
915        self.client.wait_until_healthy(timeout).await
916    }
917
918    async fn perform<R>(&self, request: R) -> Result<R::Output, TendermintRpcError>
919    where
920        R: SimpleRequest,
921    {
922        self.client.perform(request).await
923    }
924}
925
926impl<C, S> OfflineSigner for NyxdClient<C, S>
927where
928    S: OfflineSigner,
929{
930    type Error = S::Error;
931
932    fn get_accounts(&self) -> &[AccountData] {
933        self.client.get_accounts()
934    }
935
936    fn sign_direct_with_account(
937        &self,
938        signer: &AccountData,
939        sign_doc: SignDoc,
940    ) -> Result<Raw, Self::Error> {
941        self.client.sign_direct_with_account(signer, sign_doc)
942    }
943}
944
945#[async_trait]
946impl<C, S> SigningCosmWasmClient for NyxdClient<C, S>
947where
948    C: TendermintRpcClient + Send + Sync,
949    S: TxSigner + Send + Sync,
950    NyxdError: From<S::Error>,
951{
952    fn gas_price(&self) -> &GasPrice {
953        self.client.gas_price()
954    }
955
956    fn simulated_gas_multiplier(&self) -> f32 {
957        self.client.simulated_gas_multiplier()
958    }
959}