diff --git a/libwallet/examples/persisted_in_keyring.rs b/libwallet/examples/persisted_in_keyring.rs index d3a1840..c8cbd6c 100644 --- a/libwallet/examples/persisted_in_keyring.rs +++ b/libwallet/examples/persisted_in_keyring.rs @@ -14,7 +14,6 @@ async fn main() -> Result<(), Box> { let vault = vault::OSKeyring::::new(TEST_USER, Language::default()); let mut wallet = Wallet::new(vault); - wallet.unlock(None, pin).await?; diff --git a/libwallet/src/vault/os.rs b/libwallet/src/vault/os.rs index c647103..7134326 100644 --- a/libwallet/src/vault/os.rs +++ b/libwallet/src/vault/os.rs @@ -3,8 +3,8 @@ use core::marker::PhantomData; use crate::{ mnemonic::{Language, Mnemonic}, util::{seed_from_entropy, Pin}, + vault::utils::{AccountSigner, RootAccount}, Vault, - vault::utils::{ RootAccount, AccountSigner } }; use arrayvec::ArrayVec; use keyring; @@ -16,7 +16,7 @@ pub struct OSKeyring { entry: keyring::Entry, root: Option, auto_generate: Option, - _phantom: PhantomData + _phantom: PhantomData, } impl OSKeyring { @@ -28,7 +28,7 @@ impl OSKeyring { entry: keyring::Entry::new(SERVICE, &uname), root: None, auto_generate: lang.into(), - _phantom: PhantomData::default() + _phantom: PhantomData::default(), } } @@ -119,7 +119,7 @@ impl> Vault for OSKeyring { .and_then(|l| self.generate(pin, l)) }) .map(|r| { - let acc = AccountSigner::new(account.as_ref().map(|x| x.as_ref())).unlock(&r); + let acc = AccountSigner::new(account.as_ref().map(|x| x.as_ref())).unlock(&r); self.root = Some(r); acc }) diff --git a/sube/examples/pallet_communities.rs b/sube/examples/pallet_communities.rs index b49c057..2630016 100644 --- a/sube/examples/pallet_communities.rs +++ b/sube/examples/pallet_communities.rs @@ -10,14 +10,20 @@ async fn main() -> Result<()> { if let Response::ValueSet(value) = response { let data = serde_json::to_value(&value).expect("to be serializable"); - println!("Collection {}", serde_json::to_string_pretty(&data).expect("it must return an str")); + println!( + "Collection {}", + serde_json::to_string_pretty(&data).expect("it must return an str") + ); } let result = sube!("https://kreivo.io/system/account/0x12840f0626ac847d41089c4e05cf0719c5698af1e3bb87b66542de70b2de4b2b").await?; if let Response::Value(value) = result { let data = serde_json::to_value(&value).expect("to be serializable"); - println!("Account info: {}", serde_json::to_string_pretty(&data).expect("it must return an str")); + println!( + "Account info: {}", + serde_json::to_string_pretty(&data).expect("it must return an str") + ); } Ok(()) diff --git a/sube/examples/query_at_block.rs b/sube/examples/query_at_block.rs new file mode 100644 index 0000000..735a169 --- /dev/null +++ b/sube/examples/query_at_block.rs @@ -0,0 +1,20 @@ +use env_logger; +use serde_json; +use sube::{sube, ExtrinsicBody, Response, Result, SubeBuilder}; + +#[async_std::main] +async fn main() -> Result<()> { + env_logger::init(); + + let result = sube!("ws://127.0.0.1:12281/system/account/0x12840f0626ac847d41089c4e05cf0719c5698af1e3bb87b66542de70b2de4b2b?at=2067321").await?; + + if let Response::Value(value) = result { + let data = serde_json::to_value(&value).expect("to be serializable"); + println!( + "Account info: {}", + serde_json::to_string_pretty(&data).expect("it must return an str") + ); + } + + Ok(()) +} diff --git a/sube/examples/query_membership.rs b/sube/examples/query_membership.rs index ab17b69..cd8fa17 100644 --- a/sube/examples/query_membership.rs +++ b/sube/examples/query_membership.rs @@ -9,10 +9,9 @@ async fn main() -> sube::Result<()> { let query = format!( "ws://127.0.0.1:12281/communityMemberships/account/{}/{}", - "0x12840f0626ac847d41089c4e05cf0719c5698af1e3bb87b66542de70b2de4b2b", - 1 + "0x12840f0626ac847d41089c4e05cf0719c5698af1e3bb87b66542de70b2de4b2b", 1 ); - + let r = sube!(&query).await?; if let Response::ValueSet(ref v) = r { @@ -23,4 +22,4 @@ async fn main() -> sube::Result<()> { } Ok(()) -} \ No newline at end of file +} diff --git a/sube/examples/query_preimage.rs b/sube/examples/query_preimage.rs index 7d41929..4c72fbe 100644 --- a/sube/examples/query_preimage.rs +++ b/sube/examples/query_preimage.rs @@ -9,10 +9,9 @@ async fn main() -> sube::Result<()> { let query = format!( "ws://127.0.0.1:12281/preimage/preimageFor/{}/{}", - "0x6b172c3695dca229e71c0bca790f5991b68f8eee96334e842312a0a7d4a46c6c", - 30 + "0x6b172c3695dca229e71c0bca790f5991b68f8eee96334e842312a0a7d4a46c6c", 30 ); - + let r = sube!(&query).await?; if let Response::Value(ref v) = r { @@ -23,4 +22,4 @@ async fn main() -> sube::Result<()> { } Ok(()) -} \ No newline at end of file +} diff --git a/sube/examples/query_referendum_info.rs b/sube/examples/query_referendum_info.rs index 350a915..ef037e7 100644 --- a/sube/examples/query_referendum_info.rs +++ b/sube/examples/query_referendum_info.rs @@ -16,7 +16,10 @@ async fn main() -> Result<()> { if let Response::Value(ref v) = r { let json_value = serde_json::to_value(v).expect("it must to be an valid Value"); println!("Raw JSON value: {:?}", json_value); - println!("Info: {}", serde_json::to_string_pretty(&json_value).expect("it must return an str")); + println!( + "Info: {}", + serde_json::to_string_pretty(&json_value).expect("it must return an str") + ); } Ok(()) } diff --git a/sube/src/builder.rs b/sube/src/builder.rs index c6c7c37..7ec1af5 100644 --- a/sube/src/builder.rs +++ b/sube/src/builder.rs @@ -6,9 +6,9 @@ use crate::rpc::RpcClient; use crate::ws::Backend as WSBackend; use crate::{ meta::BlockInfo, Backend, Error, ExtrinsicBody, Metadata, Response, Result as SubeResult, - Signer, StorageKey, + Signer, }; -use crate::{prelude::*, Offline, StorageChangeSet}; +use crate::{prelude::*, Offline, RawKey, RawValue}; use core::future::{Future, IntoFuture}; use url::Url; @@ -62,6 +62,12 @@ impl<'a> SubeBuilder<'a, (), ()> { let Self { url, metadata, .. } = self; let url = chain_string_to_url(url.ok_or(Error::BadInput)?)?; + + let block = url + .query_pairs() + .find(|(k, _)| k == "at") + .map(|(_, v)| v.parse::().expect("at query params must be a number")); + let path = url.path(); log::trace!("building the backend for {}", url); @@ -71,7 +77,7 @@ impl<'a> SubeBuilder<'a, (), ()> { Ok(match path { "_meta" => Response::Meta(meta), "_meta/registry" => Response::Registry(&meta.types), - _ => crate::query(&backend, meta, path).await?, + _ => crate::query(&backend, meta, path, block).await?, }) } } @@ -270,26 +276,38 @@ enum AnyBackend { } impl Backend for &AnyBackend { - async fn query_storage_at( + async fn get_storage_items( &self, - keys: Vec, - block: Option, - ) -> crate::Result> { + keys: Vec, + block: Option, + ) -> crate::Result> { + let result: Box> = match self { + #[cfg(any(feature = "http", feature = "http-web"))] + AnyBackend::Http(b) => Box::new(b.get_storage_items(keys, block).await?), + #[cfg(feature = "ws")] + AnyBackend::Ws(b) => Box::new(b.get_storage_items(keys, block).await?), + AnyBackend::_Offline(b) => Box::new(b.get_storage_items(keys, block).await?), + }; + + Ok(result) + } + + async fn get_storage_item(&self, key: RawKey, block: Option) -> crate::Result> { match self { #[cfg(any(feature = "http", feature = "http-web"))] - AnyBackend::Http(b) => b.query_storage_at(keys, block).await, + AnyBackend::Http(b) => b.get_storage_item(key, block).await, #[cfg(feature = "ws")] - AnyBackend::Ws(b) => b.query_storage_at(keys, block).await, - AnyBackend::_Offline(b) => b.query_storage_at(keys, block).await, + AnyBackend::Ws(b) => b.get_storage_item(key, block).await, + AnyBackend::_Offline(b) => b.get_storage_item(key, block).await, } } async fn get_keys_paged( &self, - from: &StorageKey, + from: RawKey, size: u16, - to: Option<&StorageKey>, - ) -> crate::Result> { + to: Option, + ) -> crate::Result> { match self { #[cfg(any(feature = "http", feature = "http-web"))] AnyBackend::Http(b) => b.get_keys_paged(from, size, to).await, @@ -328,16 +346,6 @@ impl Backend for &AnyBackend { AnyBackend::_Offline(b) => b.block_info(at).await, } } - - async fn query_storage(&self, key: &StorageKey) -> SubeResult> { - match self { - #[cfg(any(feature = "http", feature = "http-web"))] - AnyBackend::Http(b) => b.query_storage(key).await, - #[cfg(feature = "ws")] - AnyBackend::Ws(b) => b.query_storage(key).await, - AnyBackend::_Offline(b) => b.query_storage(key).await, - } - } } #[macro_export] diff --git a/sube/src/http.rs b/sube/src/http.rs index 377108a..67d8bbd 100644 --- a/sube/src/http.rs +++ b/sube/src/http.rs @@ -40,7 +40,7 @@ impl Rpc for Backend { }) .send() .await - .map_err(|err| rpc::Error::Transport(Box::new(err)))?; + .map_err(|err| rpc::error::Error::Transport(Box::new(err)))?; let status = res.status(); let res = if status.is_success() { diff --git a/sube/src/lib.rs b/sube/src/lib.rs index e36dbb3..b4a0b67 100644 --- a/sube/src/lib.rs +++ b/sube/src/lib.rs @@ -18,6 +18,8 @@ extern crate alloc; pub use codec; use codec::Encode; pub use core::fmt::Display; +use core::iter::Empty; + pub use frame_metadata::RuntimeMetadataPrefixed; pub use signer::{Signer, SignerFn}; @@ -70,13 +72,17 @@ pub fn sube(url: &str) -> builder::SubeBuilder<(), ()> { } pub type Result = core::result::Result; -async fn query<'m>(chain: &impl Backend, meta: &'m Metadata, path: &str) -> Result> { +async fn query<'m>( + chain: &impl Backend, + meta: &'m Metadata, + path: &str, + block: Option, +) -> Result> { let (pallet, item_or_call, mut keys) = parse_uri(path).ok_or(Error::BadInput)?; - log::info!("pallet {}", pallet); let pallet = meta .pallet_by_name(&pallet) .ok_or_else(|| Error::PalletNotFound(pallet))?; - + if item_or_call == "_constants" { let const_name = keys.pop().ok_or_else(|| Error::MissingConstantName)?; let const_meta = pallet @@ -95,52 +101,37 @@ async fn query<'m>(chain: &impl Backend, meta: &'m Metadata, path: &str) -> Resu if let Ok(key_res) = StorageKey::build_with_registry(&meta.types, pallet, &item_or_call, &keys) { if !key_res.is_partial() { - log::info!("is not partial"); - let res = chain.query_storage(&key_res).await?; + let res = chain.get_storage_item(key_res.key(), block).await?; return Ok(Response::Value(Value::new(res, key_res.ty, &meta.types))); } - let res = chain.get_keys_paged(&key_res, 1000, None).await?; - let result = chain.query_storage_at(res, None).await?; - - if let [storage_change, ..] = &result[..] { - let value = storage_change - .changes - .iter() - .map(|[key, data]| { - let key = key.replace(&hex::encode(&key_res.pallet), ""); - let key = key.replace(&hex::encode(&key_res.call), ""); - let mut pointer = 2 + 32; // + 0x - let keys = key_res - .args - .iter() - .map(|arg| match arg { - KeyValue::Empty(type_id) | KeyValue::Value((type_id, _, _, _)) => { - let hashed = &key[pointer..]; - let value = Value::new( - hex::decode(hashed).expect("hello world"), - *type_id, - &meta.types, - ); - pointer += (value.size() * 2) + 32; - value - } - }) - .collect::>>(); - - let value = Value::new( - hex::decode(&data[2..]).expect("it to be a byte str"), - key_res.ty, - &meta.types, - ); - (keys, value) - }) - .collect::>(); - - Ok(Response::ValueSet(value)) - } else { - Ok(Response::Void) - } + let res = chain.get_keys_paged(key_res.key(), 1000, None).await?; + let result = chain.get_storage_items(res, block).await?; + + let value = result + .into_iter() + .map(|(key, data)| { + let key = &key[(key_res.pallet.len() + key_res.call.len())..]; + let mut offset = 16; // TODO it depends on the hasher used to encode the key, then the size could change + let keys = key_res + .args + .iter() + .map(|arg| match arg { + KeyValue::Empty(type_id) | KeyValue::Value((type_id, _, _, _)) => { + let hashed = &key[offset..]; + let value = Value::new(hashed.to_vec(), *type_id, &meta.types); + offset += value.size() + 16; + value + } + }) + .collect::>>(); + + let value = Value::new(data.to_vec(), key_res.ty, &meta.types); + (keys, value) + }) + .collect::>(); + + Ok(Response::ValueSet(value)) } else { Err(Error::ChainUnavailable) } @@ -215,16 +206,15 @@ where &chain, meta, &format!("system/account/0x{}", hex::encode(from_account.as_ref())), + None, ) .await?; match response { Response::Value(value) => { - log::info!("{:?}", serde_json::to_string(&value)); let str = serde_json::to_string(&value).expect("wrong account info"); let account_info: AccountInfo = serde_json::from_str(&str).expect("it must serialize"); - log::info!("{}", &account_info.nonce); Ok(account_info.nonce) } _ => Err(Error::AccountNotFound), @@ -366,24 +356,6 @@ fn parse_uri(uri: &str) -> Option<(String, String, Vec)> { Some((pallet, item, map_keys)) } -// struct PalletCall { -// pallet_idx: u8, -// ty: u32, -// } - -// impl PalletCall { -// fn new(pallet: &PalletMeta, reg: &PortableRegistry, _call: &str) -> Result { -// let calls = &pallet -// .calls -// .as_ref() -// .and_then(|c| reg.resolve(c.ty.id)) -// .ok_or_else(|| Error::CallNotFound)? -// .type_def; -// log::debug!("{:?}", calls); -// let pallet_idx = pallet.index; -// Ok(PalletCall { pallet_idx, ty: 0 }) -// } -// } #[derive(Deserialize, Serialize, Debug)] pub struct StorageChangeSet { @@ -391,6 +363,9 @@ pub struct StorageChangeSet { changes: Vec<[String; 2]>, } +pub type RawKey = Vec; +pub type RawValue = Vec; + /// Generic definition of a blockchain backend /// /// ```rust,ignore @@ -405,21 +380,27 @@ pub struct StorageChangeSet { /// } /// ``` pub trait Backend { - async fn query_storage_at( + async fn get_storage_items( &self, - keys: Vec, - block: Option, - ) -> crate::Result>; + keys: Vec, + block: Option, + ) -> crate::Result>; + + async fn get_storage_item(&self, key: RawKey, block: Option) -> crate::Result { + let res = self.get_storage_items(vec![key], block).await?; + + res.into_iter() + .next() + .map(|(_, v)| v) + .ok_or(Error::StorageKeyNotFound) + } async fn get_keys_paged( &self, - from: &StorageKey, + from: RawKey, size: u16, - to: Option<&StorageKey>, - ) -> crate::Result>; - - /// Get raw storage items form the blockchain - async fn query_storage(&self, key: &StorageKey) -> Result>; + to: Option, + ) -> crate::Result>; /// Send a signed extrinsic to the blockchain async fn submit(&self, ext: impl AsRef<[u8]>) -> Result<()>; @@ -433,24 +414,20 @@ pub trait Backend { pub struct Offline(pub Metadata); impl Backend for Offline { - async fn query_storage_at( + async fn get_storage_items( &self, - _keys: Vec, - _block: Option, - ) -> crate::Result> { - Err(Error::ChainUnavailable) + _keys: Vec, + _block: Option, + ) -> crate::Result, Vec)>> { + Err::, _>(Error::ChainUnavailable) } async fn get_keys_paged( &self, - _from: &StorageKey, + _from: RawKey, _size: u16, - _to: Option<&StorageKey>, - ) -> crate::Result> { - Err(Error::ChainUnavailable) - } - - async fn query_storage(&self, _key: &StorageKey) -> Result> { + _to: Option, + ) -> crate::Result> { Err(Error::ChainUnavailable) } @@ -492,6 +469,7 @@ pub enum Error { CantDecodeReponseForMeta, CantDecodeRawQueryResponse, CantFindMethodInPallet, + BadBlockNumber } impl fmt::Display for Error { diff --git a/sube/src/meta_ext.rs b/sube/src/meta_ext.rs index d7b0178..c533f7e 100644 --- a/sube/src/meta_ext.rs +++ b/sube/src/meta_ext.rs @@ -128,7 +128,14 @@ impl StorageKey { .as_ref() .and_then(|s| s.entries.iter().find(|e| e.name == item)) .ok_or(crate::Error::CantFindMethodInPallet)?; - log::trace!("map_keys={}", map_keys.iter().map(|x| x.as_ref()).collect::>().join(", ")); + log::trace!( + "map_keys={}", + map_keys + .iter() + .map(|x| x.as_ref()) + .collect::>() + .join(", ") + ); entry.ty.key(registry, &meta.name, &entry.name, map_keys) } } @@ -181,7 +188,7 @@ pub trait EntryTy { } else { vec![] }; - + if type_call_ids.len() == hashers.len() { log::trace!("type_call_ids={:?}", type_call_ids); let storage_key = StorageKey::new( @@ -192,51 +199,52 @@ pub trait EntryTy { .into_iter() .enumerate() .map(|(i, type_id)| { - log::info!("type_call_ids.i={} type_call_ids.type_id={}", i, type_id); + log::trace!("type_call_ids.i={} type_call_ids.type_id={}", i, type_id); let k = map_keys.get(i); let hasher = hashers.get(i).expect("hasher not found"); - + if k.is_none() { return KeyValue::Empty(type_id); } - + let k = k.expect("it must exist").as_ref(); - + let hasher = hasher.borrow(); let mut out = vec![]; - + if let Some(k) = k.strip_prefix("0x") { let value = hex::decode(k).expect("str must be encoded"); - let _ = to_bytes_with_info(&mut out, &value, Some((portable_reg, type_id))); + let _ = + to_bytes_with_info(&mut out, &value, Some((portable_reg, type_id))); } else { let _ = to_bytes_with_info(&mut out, &k, Some((portable_reg, type_id))); } - + let hash = hash(hasher, &out); KeyValue::Value((type_id, hash, out, hasher.clone())) }) .collect(), ); - + Ok(storage_key) } else if hashers.len() == 1 { log::trace!("treating touple as argument for hasher"); let touple_hex: Vec = type_call_ids - .into_iter() - .enumerate() - .flat_map(|(i, type_id)| { - let k = map_keys.get(i).expect("to exist in map_keys").as_ref(); - let mut out = vec![]; - if let Some(k) = k.strip_prefix("0x") { - let value = hex::decode(k).expect("str must be hex encoded"); - let _ = to_bytes_with_info(&mut out, &value, Some((portable_reg, type_id))); - } else { - let _ = to_bytes_with_info(&mut out, &k, Some((portable_reg, type_id))); - } - out - }) - .collect(); + .into_iter() + .enumerate() + .flat_map(|(i, type_id)| { + let k = map_keys.get(i).expect("to exist in map_keys").as_ref(); + let mut out = vec![]; + if let Some(k) = k.strip_prefix("0x") { + let value = hex::decode(k).expect("str must be hex encoded"); + let _ = to_bytes_with_info(&mut out, &value, Some((portable_reg, type_id))); + } else { + let _ = to_bytes_with_info(&mut out, &k, Some((portable_reg, type_id))); + } + out + }) + .collect(); let hasher = hashers.first().expect("hasher not found"); let hasher = hasher.borrow(); @@ -246,12 +254,19 @@ pub trait EntryTy { value_ty_id, hash(&Hasher::Twox128, pallet_item.0), hash(&Hasher::Twox128, pallet_item.1), - vec![KeyValue::Value((key_ty_id.expect("must key id must work"), hashed_value, touple_hex, hasher.clone()))] + vec![KeyValue::Value(( + key_ty_id.expect("must key id must work"), + hashed_value, + touple_hex, + hasher.clone(), + ))], ); - + Ok(storage_key) } else { - Err(crate::Error::Encode("Wrong number of hashers vs map_keys".into())) + Err(crate::Error::Encode( + "Wrong number of hashers vs map_keys".into(), + )) } } } @@ -282,7 +297,7 @@ impl EntryTy for EntryType { map_keys, hashers, ) - }, + } } } } diff --git a/sube/src/rpc.rs b/sube/src/rpc.rs index bdda6ad..a84facc 100644 --- a/sube/src/rpc.rs +++ b/sube/src/rpc.rs @@ -1,11 +1,12 @@ use core::convert::TryInto; use jsonrpc::serde_json::value::RawValue; -pub use jsonrpc::{error, Error, Request, Response}; +pub use jsonrpc::{error, Request, Response}; use serde::Deserialize; use crate::meta::{self, Metadata}; -use crate::{prelude::*, StorageChangeSet}; -use crate::{Backend, StorageKey}; +use crate::Backend; +use crate::Error; +use crate::{prelude::*, RawKey, StorageChangeSet}; use meta::from_bytes; pub type RpcResult = Result; @@ -29,20 +30,34 @@ pub trait Rpc { pub struct RpcClient(pub R); impl Backend for RpcClient { - async fn query_storage_at( + async fn get_storage_items( &self, - keys: Vec, - block: Option, - ) -> crate::Result> { - let keys = serde_json::to_string(&keys).expect("it to be a valid json"); - let params: Vec = if let Some(block_hash) = block { - vec![keys, block_hash] + keys: Vec, + block: Option, + ) -> crate::Result, Vec)>> { + let keys = serde_json::to_string( + &keys + .iter() + .map(|v| format!("0x{}", hex::encode(v))) + .collect::>(), + ) + .expect("it to be a valid json"); + + let params: Vec = if let Some(block_number) = block { + let info = self + .block_info(Some(block_number)) + .await + .map_err(|_| Error::BadBlockNumber)?; + + vec![keys, format!("\"0x{}\"", hex::encode(info.hash))] } else { vec![keys] }; - self.0 - .rpc( + + let result = self + .0 + .rpc::>( "state_queryStorageAt", params .iter() @@ -54,23 +69,40 @@ impl Backend for RpcClient { .map_err(|err| { log::error!("error state_queryStorageAt {:?}", err); crate::Error::StorageKeyNotFound - }) + })?; + + if let Some(change_set) = result.into_iter().next() { + let keys_response = change_set.changes.into_iter().map(|[k, v]| { + log::info!("key: {} value: {}", k, v); + + ( + hex::decode(&k[2..]).expect("to be an hex"), + hex::decode(&v[2..]).expect("to be an hex"), + ) + }); + + Ok(keys_response) + } else { + Err(crate::Error::StorageKeyNotFound) + } } async fn get_keys_paged( &self, - from: &StorageKey, + from: RawKey, size: u16, - to: Option<&StorageKey>, - ) -> crate::Result> { - let r: Vec = self + to: Option, + ) -> crate::Result> { + let result: Vec = self .0 .rpc( "state_getKeysPaged", &[ - &format!("\"{}\"", &from), + &format!("\"0x{}\"", hex::encode(&from)), &size.to_string(), - &to.or(Some(from)).map(|f| format!("\"{}\"", &f)).unwrap(), + &to.or(Some(from)) + .map(|f| format!("\"0x{}\"", hex::encode(f))) + .unwrap(), ], ) .await @@ -78,27 +110,11 @@ impl Backend for RpcClient { log::error!("error paged {:?}", err); crate::Error::StorageKeyNotFound })?; - log::info!("rpc call {:?}", r); - Ok(r) - } - - async fn query_storage(&self, key: &StorageKey) -> crate::Result> { - let key = key.to_string(); - log::debug!("StorageKey encoded: {}", key); - - let res: String = self - .0 - .rpc("state_getStorage", &[&format!("\"{}\"", &key)]) - .await - .map_err(|e| { - log::error!("RPC failure: {}", e); - // NOTE it could fail for more reasons - crate::Error::StorageKeyNotFound - })?; - - let response = hex::decode(&res[2..]).map_err(|_err| crate::Error::CantDecodeRawQueryResponse)?; - - Ok(response) + log::info!("rpc call {:?}", result); + Ok(result + .into_iter() + .map(|k| hex::decode(&k[2..]).expect("to be an hex")) + .collect()) } async fn submit(&self, ext: impl AsRef<[u8]>) -> crate::Result<()> { @@ -119,7 +135,8 @@ impl Backend for RpcClient { .rpc("state_getMetadata", &[]) .await .map_err(|e| crate::Error::Node(e.to_string()))?; - let response = hex::decode(&res[2..]).map_err(|_err| crate::Error::CantDecodeReponseForMeta)?; + let response = + hex::decode(&res[2..]).map_err(|_err| crate::Error::CantDecodeReponseForMeta)?; let meta = from_bytes(&mut response.as_slice()).map_err(|_| crate::Error::BadMetadata)?; log::trace!("Metadata {:#?}", meta); Ok(meta) @@ -128,9 +145,12 @@ impl Backend for RpcClient { async fn block_info(&self, at: Option) -> crate::Result { #[inline] async fn block_info(s: &impl Rpc, params: &[&str]) -> crate::Result> { - s.rpc("chain_getBlockHash", params) + let f = s + .rpc::("chain_getBlockHash", params) .await - .map_err(|e| crate::Error::Node(e.to_string())) + .map_err(|e| crate::Error::Node(e.to_string())); + + Ok(hex::decode(&f?.as_str()[2..]).expect("to be an valid hex")) } let block_hash = if let Some(block_number) = at { diff --git a/sube/src/ws.rs b/sube/src/ws.rs index 2a0e807..d5cb16c 100644 --- a/sube/src/ws.rs +++ b/sube/src/ws.rs @@ -1,9 +1,9 @@ use alloc::{collections::BTreeMap, sync::Arc}; -use no_std_async::Mutex; use ewebsock::{WsEvent, WsMessage as Message, WsReceiver as Rx, WsSender as Tx}; use futures_channel::{mpsc, oneshot}; use futures_util::StreamExt as _; +use no_std_async::Mutex; // use futures_util::StreamExt; use jsonrpc::{ error::{result_to_response, standard_error, StandardError}, @@ -92,7 +92,7 @@ impl Backend { let (tx, rx) = ewebsock::connect(url, ewebsock::Options::default()).map_err(Error::Platform)?; - + let (sender, recv) = mpsc::channel::(MAX_BUFFER); let backend = Backend { @@ -139,7 +139,6 @@ impl Backend { ().into(), ) }); - // log::info!("res {:?}", res); if res.id.is_u64() { let id = res.id.as_u64().unwrap() as Id; log::trace!("Answering request {}", id);