From a851da8e5ee95aabe8c3e81ee15696393e00047e Mon Sep 17 00:00:00 2001 From: Marko Petrlic Date: Sun, 3 Aug 2025 20:25:05 +0200 Subject: [PATCH 1/7] Added chaininfo rpc --- rpc/kate-rpc/src/system.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/rpc/kate-rpc/src/system.rs b/rpc/kate-rpc/src/system.rs index 30a128866..ac7592562 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,9 @@ pub trait Api { block_id: fetch_extrinsics_v1::BlockId, options: Option, ) -> RpcResult; + + #[method(name = "system_latestChainInfo")] + async fn fetch_latest_chain_info(&self) -> RpcResult; } pub struct Rpc @@ -45,6 +49,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 +97,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 +228,24 @@ where Ok(found_extrinsics) } + + async fn fetch_latest_chain_info(&self) -> RpcResult { + let info = self.client.info(); + Ok(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(), + }) + } +} + +#[derive(Clone, serde::Serialize, serde::Deserialize)] +pub struct ChainInfo { + pub best_hash: H256, + pub best_height: u32, + pub finalized_hash: H256, + pub finalized_height: u32, } pub mod fetch_events_v1 { From fccc175eef3d2f47a5a8fcd5e0ac59b7d7d9a034 Mon Sep 17 00:00:00 2001 From: Marko Petrlic Date: Sun, 3 Aug 2025 20:44:44 +0200 Subject: [PATCH 2/7] Added block number from hash rpc --- rpc/kate-rpc/src/system.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/rpc/kate-rpc/src/system.rs b/rpc/kate-rpc/src/system.rs index ac7592562..762d0a165 100644 --- a/rpc/kate-rpc/src/system.rs +++ b/rpc/kate-rpc/src/system.rs @@ -34,6 +34,9 @@ pub trait Api { #[method(name = "system_latestChainInfo")] async fn fetch_latest_chain_info(&self) -> RpcResult; + + #[method(name = "system_blockNumberFromHash")] + async fn block_number_from_hash(&self, hash: H256) -> RpcResult>; } pub struct Rpc @@ -238,6 +241,14 @@ where finalized_height: info.finalized_number.into(), }) } + + async fn block_number_from_hash(&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())) + } } #[derive(Clone, serde::Serialize, serde::Deserialize)] From 129a2d1d3931fbed1fceccfd038fd5c119f8313b Mon Sep 17 00:00:00 2001 From: Marko Petrlic Date: Tue, 12 Aug 2025 12:13:24 +0200 Subject: [PATCH 3/7] cleanup --- rpc/kate-rpc/src/system.rs | 176 +++++++++++++++++++++++++++++++------ 1 file changed, 150 insertions(+), 26 deletions(-) diff --git a/rpc/kate-rpc/src/system.rs b/rpc/kate-rpc/src/system.rs index 762d0a165..05be0ec01 100644 --- a/rpc/kate-rpc/src/system.rs +++ b/rpc/kate-rpc/src/system.rs @@ -32,8 +32,11 @@ pub trait Api { options: Option, ) -> RpcResult; + #[method(name = "system_latestBlockInfo")] + async fn latest_block_info(&self, use_best_block: bool) -> RpcResult; + #[method(name = "system_latestChainInfo")] - async fn fetch_latest_chain_info(&self) -> RpcResult; + async fn latest_chain_info(&self) -> RpcResult; #[method(name = "system_blockNumberFromHash")] async fn block_number_from_hash(&self, hash: H256) -> RpcResult>; @@ -232,14 +235,30 @@ where Ok(found_extrinsics) } - async fn fetch_latest_chain_info(&self) -> RpcResult { + async fn latest_block_info(&self, use_best_block: bool) -> RpcResult { + let info = self.client.info(); + 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(); - Ok(ChainInfo { + 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_number_from_hash(&self, hash: H256) -> RpcResult> { @@ -251,12 +270,85 @@ where } } -#[derive(Clone, serde::Serialize, serde::Deserialize)] -pub struct ChainInfo { - pub best_hash: H256, - pub best_height: u32, - pub finalized_hash: H256, - pub finalized_height: u32, +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"))] + pub struct Error { + code: i32, + message: String, + data: Option, + } + } } pub mod fetch_events_v1 { @@ -266,15 +358,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); + #[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 ApiParamsTS((String, Option)); + #[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))] @@ -336,15 +444,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); + #[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 ApiParamsTS(pub (BlockId, Option)); + #[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))] From 227d715c7451aac3b0c2f01df4949a8888826014 Mon Sep 17 00:00:00 2001 From: Marko Petrlic Date: Tue, 12 Aug 2025 12:16:06 +0200 Subject: [PATCH 4/7] added 0x prefix to signature --- rpc/kate-rpc/src/justifications.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) 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)))?; From c3338d3c5a87bbd5917765d4c3adf17d60ac8eb1 Mon Sep 17 00:00:00 2001 From: Marko Petrlic Date: Tue, 12 Aug 2025 12:46:25 +0200 Subject: [PATCH 5/7] Added TS types for block hash to number --- rpc/kate-rpc/src/system.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/rpc/kate-rpc/src/system.rs b/rpc/kate-rpc/src/system.rs index 05be0ec01..88c482ba3 100644 --- a/rpc/kate-rpc/src/system.rs +++ b/rpc/kate-rpc/src/system.rs @@ -340,6 +340,27 @@ pub mod types { 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"))] From d2f69179c06986842cb35474dc685ba045d340b4 Mon Sep 17 00:00:00 2001 From: Marko Petrlic Date: Wed, 13 Aug 2025 09:49:40 +0200 Subject: [PATCH 6/7] Renaming --- rpc/kate-rpc/src/system.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/rpc/kate-rpc/src/system.rs b/rpc/kate-rpc/src/system.rs index 88c482ba3..4fa4bdd7f 100644 --- a/rpc/kate-rpc/src/system.rs +++ b/rpc/kate-rpc/src/system.rs @@ -33,13 +33,13 @@ pub trait Api { ) -> RpcResult; #[method(name = "system_latestBlockInfo")] - async fn latest_block_info(&self, use_best_block: bool) -> RpcResult; + 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_blockNumberFromHash")] - async fn block_number_from_hash(&self, hash: H256) -> RpcResult>; + #[method(name = "system_getBlockNumber")] + async fn block_get_block_number(&self, hash: H256) -> RpcResult>; } pub struct Rpc @@ -235,8 +235,9 @@ where Ok(found_extrinsics) } - async fn latest_block_info(&self, use_best_block: bool) -> RpcResult { + 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(), @@ -261,7 +262,7 @@ where }); } - async fn block_number_from_hash(&self, hash: H256) -> RpcResult> { + 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())) From d45bf9f24092c42fd9cb0c8ed233525a63e9b194 Mon Sep 17 00:00:00 2001 From: Marko Petrlic Date: Wed, 13 Aug 2025 12:09:24 +0200 Subject: [PATCH 7/7] Bumped node version --- node/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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";