diff --git a/common/client-libs/validator-client/Cargo.toml b/common/client-libs/validator-client/Cargo.toml index 6e8dd55772..d17b100672 100644 --- a/common/client-libs/validator-client/Cargo.toml +++ b/common/client-libs/validator-client/Cargo.toml @@ -20,6 +20,7 @@ nym-coconut-bandwidth-contract-common = { path = "../../cosmwasm-smart-contracts nym-ecash-contract-common = { path = "../../cosmwasm-smart-contracts/ecash-contract" } nym-multisig-contract-common = { path = "../../cosmwasm-smart-contracts/multisig-contract" } nym-group-contract-common = { path = "../../cosmwasm-smart-contracts/group-contract" } +nym-serde-helpers = { path = "../../serde-helpers", features = ["hex", "base64"] } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } nym-http-api-client = { path = "../../../common/http-api-client" } diff --git a/common/client-libs/validator-client/src/nyxd/cosmwasm_client/client_traits/query_client.rs b/common/client-libs/validator-client/src/nyxd/cosmwasm_client/client_traits/query_client.rs index 47859ea0d1..5cea0a1ba2 100644 --- a/common/client-libs/validator-client/src/nyxd/cosmwasm_client/client_traits/query_client.rs +++ b/common/client-libs/validator-client/src/nyxd/cosmwasm_client/client_traits/query_client.rs @@ -5,7 +5,7 @@ use crate::nyxd; use crate::nyxd::coin::Coin; use crate::nyxd::cosmwasm_client::helpers::{create_pagination, next_page_key}; use crate::nyxd::cosmwasm_client::types::{ - Account, CodeDetails, Contract, ContractCodeId, SequenceResponse, SimulateResponse, + Account, CodeDetails, Contract, ContractCodeId, Model, SequenceResponse, SimulateResponse, }; use crate::nyxd::error::NyxdError; use crate::nyxd::Query; @@ -21,11 +21,11 @@ use cosmrs::proto::cosmos::tx::v1beta1::{ SimulateRequest, SimulateResponse as ProtoSimulateResponse, }; use cosmrs::proto::cosmwasm::wasm::v1::{ - QueryCodeRequest, QueryCodeResponse, QueryCodesRequest, QueryCodesResponse, - QueryContractHistoryRequest, QueryContractHistoryResponse, QueryContractInfoRequest, - QueryContractInfoResponse, QueryContractsByCodeRequest, QueryContractsByCodeResponse, - QueryRawContractStateRequest, QueryRawContractStateResponse, QuerySmartContractStateRequest, - QuerySmartContractStateResponse, + QueryAllContractStateRequest, QueryAllContractStateResponse, QueryCodeRequest, + QueryCodeResponse, QueryCodesRequest, QueryCodesResponse, QueryContractHistoryRequest, + QueryContractHistoryResponse, QueryContractInfoRequest, QueryContractInfoResponse, + QueryContractsByCodeRequest, QueryContractsByCodeResponse, QueryRawContractStateRequest, + QueryRawContractStateResponse, QuerySmartContractStateRequest, QuerySmartContractStateResponse, }; use cosmrs::tendermint::{block, chain, Hash}; use cosmrs::{AccountId, Coin as CosmosCoin, Tx}; @@ -444,6 +444,38 @@ pub trait CosmWasmClient: TendermintRpcClient { .collect::>()?) } + async fn query_all_contract_state(&self, address: &AccountId) -> Result, NyxdError> { + let path = Some("/cosmwasm.wasm.v1.Query/AllContractState".to_owned()); + + let mut models = Vec::new(); + let mut pagination = None; + + loop { + let req = QueryAllContractStateRequest { + address: address.to_string(), + pagination, + }; + + let mut res = self + .make_abci_query::<_, QueryAllContractStateResponse>(path.clone(), req) + .await?; + + let empty_response = res.models.is_empty(); + models.append(&mut res.models); + + if empty_response { + break; + } + if let Some(next_key) = next_page_key(res.pagination) { + pagination = Some(create_pagination(next_key)) + } else { + break; + } + } + + Ok(models.into_iter().map(Into::into).collect()) + } + async fn query_contract_raw( &self, address: &AccountId, diff --git a/common/client-libs/validator-client/src/nyxd/cosmwasm_client/types.rs b/common/client-libs/validator-client/src/nyxd/cosmwasm_client/types.rs index 564a17441e..26003c1d29 100644 --- a/common/client-libs/validator-client/src/nyxd/cosmwasm_client/types.rs +++ b/common/client-libs/validator-client/src/nyxd/cosmwasm_client/types.rs @@ -27,13 +27,34 @@ use cosmrs::vesting::{ }; use cosmrs::{AccountId, Any, Coin as CosmosCoin}; use prost::Message; -use serde::Serialize; +use serde::{Deserialize, Serialize}; pub use cosmrs::abci::GasInfo; pub use cosmrs::abci::MsgResponse; pub type ContractCodeId = u64; +// yet another thing to put in cosmrs +#[derive(Serialize, Deserialize)] +pub struct Model { + #[serde(with = "nym_serde_helpers::hex")] + pub key: Vec, + + #[serde(with = "nym_serde_helpers::base64")] + pub value: Vec, +} + +// follow the cosmwasm serialisation format, i.e. hex for key and base64 for value + +impl From for Model { + fn from(model: cosmrs::proto::cosmwasm::wasm::v1::Model) -> Self { + Model { + key: model.key, + value: model.value, + } + } +} + #[derive(Serialize)] pub struct EmptyMsg {} diff --git a/common/serde-helpers/Cargo.toml b/common/serde-helpers/Cargo.toml index a45ed0afbd..bc9de1862e 100644 --- a/common/serde-helpers/Cargo.toml +++ b/common/serde-helpers/Cargo.toml @@ -13,11 +13,13 @@ license.workspace = true [dependencies] serde = { workspace = true } +hex = { workspace = true, optional = true } bs58 = { workspace = true, optional = true } base64 = { workspace = true, optional = true } time = { workspace = true, features = ["formatting", "parsing"], optional = true } [features] +hex = ["dep:hex"] bs58 = ["dep:bs58"] base64 = ["dep:base64"] date = ["time"] \ No newline at end of file diff --git a/common/serde-helpers/src/lib.rs b/common/serde-helpers/src/lib.rs index fd37be86b8..07ad83face 100644 --- a/common/serde-helpers/src/lib.rs +++ b/common/serde-helpers/src/lib.rs @@ -32,6 +32,20 @@ pub mod bs58 { } } +#[cfg(feature = "hex")] +pub mod hex { + use serde::{Deserialize, Deserializer, Serializer}; + + pub fn serialize(bytes: &[u8], serializer: S) -> Result { + serializer.serialize_str(&::hex::encode(bytes)) + } + + pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result, D::Error> { + let s = String::deserialize(deserializer)?; + ::hex::decode(&s).map_err(serde::de::Error::custom) + } +} + #[cfg(feature = "date")] pub mod date { use serde::ser::Error;