diff --git a/node/src/lib.rs b/node/src/lib.rs index 70b5c20f9..4ae22bd5e 100644 --- a/node/src/lib.rs +++ b/node/src/lib.rs @@ -7,4 +7,4 @@ pub mod cli; pub mod rpc; pub mod service; -pub const NODE_VERSION: &str = "2.3.2"; +pub const NODE_VERSION: &str = "2.3.3"; diff --git a/rpc/kate-rpc/src/justifications.rs b/rpc/kate-rpc/src/justifications.rs index 1072164ea..fc5e88705 100644 --- a/rpc/kate-rpc/src/justifications.rs +++ b/rpc/kate-rpc/src/justifications.rs @@ -172,7 +172,7 @@ impl serde::Serialize for Signature { where S: serde::Serializer, { - serializer.serialize_str(&const_hex::encode(&self.0)) + serializer.serialize_str(&const_hex::encode_prefixed(&self.0)) } } @@ -181,8 +181,9 @@ impl<'de> serde::Deserialize<'de> for Signature { where D: serde::Deserializer<'de>, { - let signature_hex = const_hex::decode(&String::deserialize(deserializer)?) - .map_err(|e| serde::de::Error::custom(format!("{:?}", e)))?; + let signature_hex = + const_hex::decode(String::deserialize(deserializer)?.trim_start_matches("0x")) + .map_err(|e| serde::de::Error::custom(format!("{:?}", e)))?; let signature: [u8; 64usize] = signature_hex .try_into() .map_err(|e| serde::de::Error::custom(format!("{:?}", e)))?; diff --git a/rpc/kate-rpc/src/system.rs b/rpc/kate-rpc/src/system.rs index 30a128866..4fa4bdd7f 100644 --- a/rpc/kate-rpc/src/system.rs +++ b/rpc/kate-rpc/src/system.rs @@ -8,6 +8,7 @@ use jsonrpsee::{ }; use sc_client_api::BlockBackend; use sp_api::ProvideRuntimeApi; +use sp_blockchain::HeaderBackend; use sp_core::{Blake2Hasher, Hasher, H256}; use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; use std::{ @@ -30,6 +31,15 @@ pub trait Api { block_id: fetch_extrinsics_v1::BlockId, options: Option, ) -> RpcResult; + + #[method(name = "system_latestBlockInfo")] + async fn latest_block_info(&self, use_best_block: Option) -> RpcResult; + + #[method(name = "system_latestChainInfo")] + async fn latest_chain_info(&self) -> RpcResult; + + #[method(name = "system_getBlockNumber")] + async fn block_get_block_number(&self, hash: H256) -> RpcResult>; } pub struct Rpc @@ -45,6 +55,7 @@ where impl Rpc where C: ProvideRuntimeApi + Send + Sync + 'static, + C: HeaderBackend, C::Api: frame_system_rpc_runtime_api::SystemEventsApi, Block: BlockT, ::Hash: From, @@ -92,10 +103,12 @@ impl<'a, C, Block> ApiServer for Rpc where C: ProvideRuntimeApi + Send + Sync + 'static, C: BlockBackend, + C: HeaderBackend, C::Api: frame_system_rpc_runtime_api::SystemEventsApi, Block: BlockT, ::Hash: From + Into, <::Header as HeaderT>::Number: From, + <::Header as HeaderT>::Number: Into, { async fn fetch_events_v1( &self, @@ -221,6 +234,143 @@ where Ok(found_extrinsics) } + + async fn latest_block_info(&self, use_best_block: Option) -> RpcResult { + let info = self.client.info(); + let use_best_block = use_best_block.unwrap_or(true); + if use_best_block { + return Ok(types::BlockInfo { + hash: info.best_hash.into(), + height: info.best_number.into(), + }); + } + + Ok(types::BlockInfo { + hash: info.finalized_hash.into(), + height: info.finalized_number.into(), + }) + } + + async fn latest_chain_info(&self) -> RpcResult { + let info = self.client.info(); + return Ok(types::ChainInfo { + best_hash: info.best_hash.into(), + best_height: info.best_number.into(), + finalized_hash: info.finalized_hash.into(), + finalized_height: info.finalized_number.into(), + genesis_hash: info.genesis_hash.into(), + }); + } + + async fn block_get_block_number(&self, hash: H256) -> RpcResult> { + let result = self + .client + .block_number_from_id(&sp_runtime::generic::BlockId::Hash(hash.into())) + .map_err(|err| Error::Other.into_error_object(err.to_string()))?; + Ok(result.map(|x| x.into())) + } +} + +pub mod types { + use super::*; + + #[derive(Clone, serde::Serialize, serde::Deserialize)] + #[cfg_attr(feature = "ts", derive(ts_rs::TS))] + #[cfg_attr(feature = "ts", ts(export, export_to = "Types.ts"))] + pub struct BlockInfo { + #[cfg_attr(feature = "ts", ts(as = "String"))] + pub hash: H256, + pub height: u32, + } + + #[derive(Clone, serde::Serialize, serde::Deserialize)] + #[cfg_attr(feature = "ts", derive(ts_rs::TS))] + #[cfg_attr(feature = "ts", ts(export, export_to = "Types.ts"))] + pub struct ChainInfo { + #[cfg_attr(feature = "ts", ts(as = "String"))] + pub best_hash: H256, + pub best_height: u32, + #[cfg_attr(feature = "ts", ts(as = "String"))] + pub finalized_hash: H256, + pub finalized_height: u32, + #[cfg_attr(feature = "ts", ts(as = "String"))] + pub genesis_hash: H256, + } + + #[cfg(feature = "ts")] + pub mod ts_types { + use super::*; + + #[allow(dead_code)] + #[cfg_attr(feature = "ts", derive(ts_rs::TS))] + #[cfg_attr(feature = "ts", ts(export, export_to = "Types.ts"))] + struct RpcRequestBlockInfo { + id: u32, + jsonrpc: String, + method: String, + params: (bool,), + } + + #[allow(dead_code)] + #[cfg_attr(feature = "ts", derive(ts_rs::TS))] + #[cfg_attr(feature = "ts", ts(export, export_to = "Types.ts"))] + struct RpcResponseBlockInfo { + jsonrpc: String, + result: Option, + error: Option, + id: u32, + } + + #[allow(dead_code)] + #[cfg_attr(feature = "ts", derive(ts_rs::TS))] + #[cfg_attr(feature = "ts", ts(export, export_to = "Types.ts"))] + struct RpcRequestChainInfo { + id: u32, + jsonrpc: String, + method: String, + params: (), + } + + #[allow(dead_code)] + #[cfg_attr(feature = "ts", derive(ts_rs::TS))] + #[cfg_attr(feature = "ts", ts(export, export_to = "Types.ts"))] + struct RpcResponseChainInfo { + jsonrpc: String, + result: Option, + error: Option, + id: u32, + } + + #[allow(dead_code)] + #[cfg_attr(feature = "ts", derive(ts_rs::TS))] + #[cfg_attr(feature = "ts", ts(export, export_to = "Types.ts"))] + struct RpcRequestBlockNumber { + id: u32, + jsonrpc: String, + method: String, + #[cfg_attr(feature = "ts", ts(as = "(String,)"))] + params: (H256,), + } + + #[allow(dead_code)] + #[cfg_attr(feature = "ts", derive(ts_rs::TS))] + #[cfg_attr(feature = "ts", ts(export, export_to = "Types.ts"))] + struct RpcResponseBlockNumber { + jsonrpc: String, + result: Option, + error: Option, + id: u32, + } + + #[allow(dead_code)] + #[cfg_attr(feature = "ts", derive(ts_rs::TS))] + #[cfg_attr(feature = "ts", ts(export, export_to = "Types.ts"))] + pub struct Error { + code: i32, + message: String, + data: Option, + } + } } pub mod fetch_events_v1 { @@ -230,15 +380,31 @@ pub mod fetch_events_v1 { }; pub type ApiResult = Vec; - #[allow(dead_code)] - #[cfg_attr(feature = "ts", derive(ts_rs::TS))] - #[cfg_attr(feature = "ts", ts(export, export_to = "FetchEvents.ts"))] - struct ApiResultTS(pub Vec); - - #[allow(dead_code)] - #[cfg_attr(feature = "ts", derive(ts_rs::TS))] - #[cfg_attr(feature = "ts", ts(export, export_to = "FetchEvents.ts"))] - struct ApiParamsTS((String, Option)); + #[cfg(feature = "ts")] + pub mod ts_types { + use super::super::types::ts_types::Error; + use super::*; + + #[allow(dead_code)] + #[cfg_attr(feature = "ts", derive(ts_rs::TS))] + #[cfg_attr(feature = "ts", ts(export, export_to = "FetchEvents.ts"))] + struct RpcRequest { + id: u32, + jsonrpc: String, + method: String, + params: (String, Option), + } + + #[allow(dead_code)] + #[cfg_attr(feature = "ts", derive(ts_rs::TS))] + #[cfg_attr(feature = "ts", ts(export, export_to = "FetchEvents.ts"))] + struct RpcResponse { + jsonrpc: String, + result: Option>, + error: Option, + id: u32, + } + } #[derive(Clone, serde::Serialize, serde::Deserialize)] #[cfg_attr(feature = "ts", derive(ts_rs::TS))] @@ -300,15 +466,31 @@ pub mod fetch_extrinsics_v1 { pub type ApiResult = Vec; - #[allow(dead_code)] - #[cfg_attr(feature = "ts", derive(ts_rs::TS))] - #[cfg_attr(feature = "ts", ts(export, export_to = "FetchExtrinsics.ts"))] - struct ApiResultTS(pub Vec); - - #[allow(dead_code)] - #[cfg_attr(feature = "ts", derive(ts_rs::TS))] - #[cfg_attr(feature = "ts", ts(export, export_to = "FetchExtrinsics.ts"))] - struct ApiParamsTS(pub (BlockId, Option)); + #[cfg(feature = "ts")] + pub mod ts_types { + use super::super::types::ts_types::Error; + use super::*; + + #[allow(dead_code)] + #[cfg_attr(feature = "ts", derive(ts_rs::TS))] + #[cfg_attr(feature = "ts", ts(export, export_to = "FetchExtrinsics.ts"))] + struct RpcRequest { + id: u32, + jsonrpc: String, + method: String, + params: (BlockId, Option), + } + + #[allow(dead_code)] + #[cfg_attr(feature = "ts", derive(ts_rs::TS))] + #[cfg_attr(feature = "ts", ts(export, export_to = "FetchExtrinsics.ts"))] + struct RpcResponse { + jsonrpc: String, + result: Option>, + error: Option, + id: u32, + } + } #[derive(Clone, Serialize, Deserialize)] #[cfg_attr(feature = "ts", derive(ts_rs::TS))]