From f0ac3310eed91bd4f72811136b685b4a80a06c45 Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Tue, 28 May 2024 19:18:33 +1200 Subject: [PATCH 1/8] new reference doc for custom rpc --- docs/sdk/src/reference_docs/custom_rpc.rs | 52 +++++++++++++++++++++++ docs/sdk/src/reference_docs/mod.rs | 3 ++ 2 files changed, 55 insertions(+) create mode 100644 docs/sdk/src/reference_docs/custom_rpc.rs diff --git a/docs/sdk/src/reference_docs/custom_rpc.rs b/docs/sdk/src/reference_docs/custom_rpc.rs new file mode 100644 index 000000000000..600ba4204b75 --- /dev/null +++ b/docs/sdk/src/reference_docs/custom_rpc.rs @@ -0,0 +1,52 @@ +//! # Substrate Custom RPC do's and don'ts +//! +//! **TLDR:** don't +//! +//! ## Background +//! +//! Substrate offers the ability to query and subscribe storages directly. However what Substrate did not have is [view functions](https://github.com/paritytech/polkadot-sdk/issues/216). This is an essential feature to avoid duplicated logic between runtime and the client SDK. Custom RPC was used as a solution. It allow the RPC node to expose new RPCs that clients can be used to query computed properties. +//! +//! ## Problems with Custom RPC +//! +//! Unfortunately, custom RPC comes with many problems. To list a few: +//! +//! - It is offchain logic executed by the RPC node and therefore the client has to trust the RPC node. +//! - To upgrade or add a new RPC logic, the RPC node has to be upgraded. This can cause significant trouble when the RPC infrastructure is decentralized as we will need to coordinate multiple parties to upgrade the RPC nodes. +//! - A lot of boilerplate code are required to add custom RPC. +//! - It prevents the dApp to use a light client or alternative client. +//! - It makes ecosystem tooling integration much more complicated. For example, the dApp will not be able to use Chopsticks for testing as Chopsticks will not have the custom RPC implemenation. +//! - Poorly implemented custom RPC can be a DoS vector. +//! +//! Hence, we should avoid custom RPC +//! +//! ## Alternatives +//! +//! Generally, `state_call` should be used instead of custom RPC. +//! +//! Usually, each custom RPC comes with a coresponding runtime API which implements the business logic. So instead of invoke the custom RPC, we can use `state_call` to invoke the runtime API directly. This is a trivial change on the dApp and no change on the runtime side. We may remove the custom RPC from the node side if wanted. +//! +//! There are some other cases that a simple runtime API is not enough. For example, implementation of Ethereum RPC requires an addiontal offchain database to index transactions. In this particular case, we can have the RPC implemented on another client. +//! +//! For example, the Acala EVM+ RPC are implemented by [eth-rpc-adapter](https://github.com/AcalaNetwork/bodhi.js/tree/master/packages/eth-rpc-adapter). This have a few advantages: +//! +//! - It is easy for testing. We can launch an instance of eth-rpc-adapter have it connected to a Chopsticks instance and be able to test EVM stack using Chopsticks to do things like revert block, replay transaction, etc. +//! - No additional overhead for non RPC node as they don't need to storage the extra data that only used by the custom RPC logic. +//! - Decouple the runtime, node, and custom RPC logic. This means we can upgrade each of them indenpendly providing the runtime API remains compatible. +//! - Fully compatible with omni-node or other ecosystem tools such as Chopsticks and smoldot +//! +//! ## Future +//! +//! [XCQ](https://forum.polkadot.network/t/cross-consensus-query-language-xcq/7583) will be a good solution for most of the query needs. +//! +//! ## Create a new Runtime API +//! +//! TODO: reference to the runtime API docs +//! +//! ## Create a new custom RPC +//! +//! TODO: how to create a new RPC implementation +//! +//! ## Add a new RPC to the node +//! +//! TODO: how to add a new RPC to the node +//! \ No newline at end of file diff --git a/docs/sdk/src/reference_docs/mod.rs b/docs/sdk/src/reference_docs/mod.rs index 6fa25bf36e1b..f18995d0af1c 100644 --- a/docs/sdk/src/reference_docs/mod.rs +++ b/docs/sdk/src/reference_docs/mod.rs @@ -109,3 +109,6 @@ pub mod frame_pallet_coupling; /// Learn about the Polkadot Umbrella crate that re-exports all other crates. pub mod umbrella_crate; + +/// Learn about how to create custom RPC endpoints. +pub mod custom_rpc; From bb9ce339a982b7e2577aba990541bd2d63b99602 Mon Sep 17 00:00:00 2001 From: kianenigma Date: Fri, 31 May 2024 11:56:50 +0800 Subject: [PATCH 2/8] update from kian --- Cargo.lock | 3 + docs/sdk/src/reference_docs/custom_rpc.rs | 52 ------------ .../reference_docs/custom_runtime_api_rpc.rs | 81 +++++++++++++++++++ docs/sdk/src/reference_docs/mod.rs | 4 +- .../frame/system/rpc/runtime-api/Cargo.toml | 1 + substrate/utils/frame/rpc/system/Cargo.toml | 9 ++- substrate/utils/frame/rpc/system/src/lib.rs | 1 + templates/minimal/node/Cargo.toml | 1 + templates/minimal/node/src/rpc.rs | 3 +- 9 files changed, 98 insertions(+), 57 deletions(-) delete mode 100644 docs/sdk/src/reference_docs/custom_rpc.rs create mode 100644 docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs diff --git a/Cargo.lock b/Cargo.lock index 3d6cbc9e83f9..aac1dc11be70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6022,6 +6022,7 @@ dependencies = [ name = "frame-system-rpc-runtime-api" version = "26.0.0" dependencies = [ + "docify", "parity-scale-codec", "sp-api", ] @@ -8339,6 +8340,7 @@ name = "minimal-template-node" version = "0.0.0" dependencies = [ "clap 4.5.3", + "docify", "futures", "futures-timer", "jsonrpsee", @@ -20909,6 +20911,7 @@ name = "substrate-frame-rpc-system" version = "28.0.0" dependencies = [ "assert_matches", + "docify", "frame-system-rpc-runtime-api", "futures", "jsonrpsee", diff --git a/docs/sdk/src/reference_docs/custom_rpc.rs b/docs/sdk/src/reference_docs/custom_rpc.rs deleted file mode 100644 index 600ba4204b75..000000000000 --- a/docs/sdk/src/reference_docs/custom_rpc.rs +++ /dev/null @@ -1,52 +0,0 @@ -//! # Substrate Custom RPC do's and don'ts -//! -//! **TLDR:** don't -//! -//! ## Background -//! -//! Substrate offers the ability to query and subscribe storages directly. However what Substrate did not have is [view functions](https://github.com/paritytech/polkadot-sdk/issues/216). This is an essential feature to avoid duplicated logic between runtime and the client SDK. Custom RPC was used as a solution. It allow the RPC node to expose new RPCs that clients can be used to query computed properties. -//! -//! ## Problems with Custom RPC -//! -//! Unfortunately, custom RPC comes with many problems. To list a few: -//! -//! - It is offchain logic executed by the RPC node and therefore the client has to trust the RPC node. -//! - To upgrade or add a new RPC logic, the RPC node has to be upgraded. This can cause significant trouble when the RPC infrastructure is decentralized as we will need to coordinate multiple parties to upgrade the RPC nodes. -//! - A lot of boilerplate code are required to add custom RPC. -//! - It prevents the dApp to use a light client or alternative client. -//! - It makes ecosystem tooling integration much more complicated. For example, the dApp will not be able to use Chopsticks for testing as Chopsticks will not have the custom RPC implemenation. -//! - Poorly implemented custom RPC can be a DoS vector. -//! -//! Hence, we should avoid custom RPC -//! -//! ## Alternatives -//! -//! Generally, `state_call` should be used instead of custom RPC. -//! -//! Usually, each custom RPC comes with a coresponding runtime API which implements the business logic. So instead of invoke the custom RPC, we can use `state_call` to invoke the runtime API directly. This is a trivial change on the dApp and no change on the runtime side. We may remove the custom RPC from the node side if wanted. -//! -//! There are some other cases that a simple runtime API is not enough. For example, implementation of Ethereum RPC requires an addiontal offchain database to index transactions. In this particular case, we can have the RPC implemented on another client. -//! -//! For example, the Acala EVM+ RPC are implemented by [eth-rpc-adapter](https://github.com/AcalaNetwork/bodhi.js/tree/master/packages/eth-rpc-adapter). This have a few advantages: -//! -//! - It is easy for testing. We can launch an instance of eth-rpc-adapter have it connected to a Chopsticks instance and be able to test EVM stack using Chopsticks to do things like revert block, replay transaction, etc. -//! - No additional overhead for non RPC node as they don't need to storage the extra data that only used by the custom RPC logic. -//! - Decouple the runtime, node, and custom RPC logic. This means we can upgrade each of them indenpendly providing the runtime API remains compatible. -//! - Fully compatible with omni-node or other ecosystem tools such as Chopsticks and smoldot -//! -//! ## Future -//! -//! [XCQ](https://forum.polkadot.network/t/cross-consensus-query-language-xcq/7583) will be a good solution for most of the query needs. -//! -//! ## Create a new Runtime API -//! -//! TODO: reference to the runtime API docs -//! -//! ## Create a new custom RPC -//! -//! TODO: how to create a new RPC implementation -//! -//! ## Add a new RPC to the node -//! -//! TODO: how to add a new RPC to the node -//! \ No newline at end of file diff --git a/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs b/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs new file mode 100644 index 000000000000..85276dabf926 --- /dev/null +++ b/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs @@ -0,0 +1,81 @@ +//! # Custom RPC do's and don'ts +//! +//! > Authors: @xlc, @kianenigma +//! +//! **TLDR:** don't create new custom RPCs. Instead, rely on custom Runtime APIs, combined with +//! `state_call` +//! +//! ## Background +//! +//! Polkadot-SDK offers the ability to query and subscribe storages directly. However what it did +//! not have is [view functions](https://github.com/paritytech/polkadot-sdk/issues/216). This is an +//! essential feature to avoid duplicated logic between runtime and the client SDK. Custom RPC was +//! used as a solution. It allow the RPC node to expose new RPCs that clients can be used to query +//! computed properties. +//! +//! ## Problems with Custom RPC +//! +//! Unfortunately, custom RPC comes with many problems. To list a few: +//! +//! - It is offchain logic executed by the RPC node and therefore the client has to trust the RPC +//! node. +//! - To upgrade or add a new RPC logic, the RPC node has to be upgraded. This can cause significant +//! trouble when the RPC infrastructure is decentralized as we will need to coordinate multiple +//! parties to upgrade the RPC nodes. +//! - A lot of boilerplate code are required to add custom RPC. +//! - It prevents the dApp to use a light client or alternative client. +//! - It makes ecosystem tooling integration much more complicated. For example, the dApp will not +//! be able to use [Chopsticks](https://github.com/AcalaNetwork/chopsticks) for testing as +//! Chopsticks will not have the custom RPC implementation. +//! - Poorly implemented custom RPC can be a DoS vector. +//! +//! Hence, we should avoid custom RPC. +//! +//! ## Alternatives +//! +//! Generally, [`sc_rpc::state::StateBackend::call`] aka. `state_call` should be used instead of +//! custom RPC. +//! +//! Usually, each custom RPC comes with a corresponding runtime API which implements the business +//! logic. So instead of invoke the custom RPC, we can use `state_call` to invoke the runtime API +//! directly. This is a trivial change on the dApp and no change on the runtime side. We may remove +//! the custom RPC from the node side if wanted. +//! +//! There are some other cases that a simple runtime API is not enough. For example, implementation +//! of Ethereum RPC requires an additional offchain database to index transactions. In this +//! particular case, we can have the RPC implemented on another client. +//! +//! For example, the Acala EVM+ RPC are implemented by +//! [eth-rpc-adapter](https://github.com/AcalaNetwork/bodhi.js/tree/master/packages/eth-rpc-adapter). +//! Alternatively, the [Frontier](https://github.com/polkadot-evm/frontier) project also provided +//! Ethereum RPC compatibility directly in the node-side software. +//! +//! ## Create a new Runtime API +//! +//! For example, let's take a look a the process through which the account nonce can be queried +//! through an RPC. First, a new runtime-api needs to be declared: +//! +#![doc = docify::embed("../../substrate/frame/system/rpc/runtime-api/src/lib.rs", AccountNonceApi)] +//! +//! This API is implemented at the runtime level, always inside [`sp_api::impl_runtime_api!`]. +//! +//! As noted, this is already enough to make this API usable via `state_call`. +//! +//! ## Create a new custom RPC +//! +//! Should you wish to implement the legacy approach of exposing this runtime-api as a custom +//! RPC-api, then a custom RPC server has to be defined. +//! +#![doc = docify::embed("../../substrate/utils/frame/rpc/system/src/lib.rs", SystemApi)] +//! +//! ## Add a new RPC to the node +//! +//! Finally, this custom RPC needs to be integrated into the node side. This is usually done in a +//! `rpc.rs` in a typical template, as follows: +//! +#![doc = docify::embed("../../templates/minimal/node/src/rpc.rs", create_full)] +//! +//! ## Future +//! +//! [XCQ](https://forum.polkadot.network/t/cross-consensus-query-language-xcq/7583) will be a good +//! solution for most of the query needs. diff --git a/docs/sdk/src/reference_docs/mod.rs b/docs/sdk/src/reference_docs/mod.rs index f18995d0af1c..0be33597461f 100644 --- a/docs/sdk/src/reference_docs/mod.rs +++ b/docs/sdk/src/reference_docs/mod.rs @@ -110,5 +110,5 @@ pub mod frame_pallet_coupling; /// Learn about the Polkadot Umbrella crate that re-exports all other crates. pub mod umbrella_crate; -/// Learn about how to create custom RPC endpoints. -pub mod custom_rpc; +/// Learn about how to create custom RPC endpoints and runtime APIs. +pub mod custom_runtime_api_rpc; diff --git a/substrate/frame/system/rpc/runtime-api/Cargo.toml b/substrate/frame/system/rpc/runtime-api/Cargo.toml index b134cc3b6173..8b71ca2a1395 100644 --- a/substrate/frame/system/rpc/runtime-api/Cargo.toml +++ b/substrate/frame/system/rpc/runtime-api/Cargo.toml @@ -18,6 +18,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } sp-api = { path = "../../../../primitives/api", default-features = false } +docify = "0.2.0" [features] default = ["std"] diff --git a/substrate/utils/frame/rpc/system/Cargo.toml b/substrate/utils/frame/rpc/system/Cargo.toml index 6829d753ed71..75d24e8e210f 100644 --- a/substrate/utils/frame/rpc/system/Cargo.toml +++ b/substrate/utils/frame/rpc/system/Cargo.toml @@ -16,9 +16,14 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.6.12" } -jsonrpsee = { version = "0.22.5", features = ["client-core", "macros", "server-core"] } futures = "0.3.30" +codec = { package = "parity-scale-codec", version = "3.6.12" } +docify = "0.2.0" +jsonrpsee = { version = "0.22.5", features = [ + "client-core", + "macros", + "server-core", +] } log = { workspace = true, default-features = true } frame-system-rpc-runtime-api = { path = "../../../../frame/system/rpc/runtime-api" } sc-rpc-api = { path = "../../../../client/rpc-api" } diff --git a/substrate/utils/frame/rpc/system/src/lib.rs b/substrate/utils/frame/rpc/system/src/lib.rs index bb0592599b2a..8cb7b785bc7c 100644 --- a/substrate/utils/frame/rpc/system/src/lib.rs +++ b/substrate/utils/frame/rpc/system/src/lib.rs @@ -37,6 +37,7 @@ use sp_runtime::{legacy, traits}; pub use frame_system_rpc_runtime_api::AccountNonceApi; /// System RPC methods. +#[docify::export] #[rpc(client, server)] pub trait SystemApi { /// Returns the next valid index (aka nonce) for given account. diff --git a/templates/minimal/node/Cargo.toml b/templates/minimal/node/Cargo.toml index 606fd0580356..14e2b340187f 100644 --- a/templates/minimal/node/Cargo.toml +++ b/templates/minimal/node/Cargo.toml @@ -17,6 +17,7 @@ workspace = true targets = ["x86_64-unknown-linux-gnu"] [dependencies] +docify = "0.2.0" clap = { version = "4.5.3", features = ["derive"] } futures = { version = "0.3.30", features = ["thread-pool"] } futures-timer = "3.0.1" diff --git a/templates/minimal/node/src/rpc.rs b/templates/minimal/node/src/rpc.rs index d0c417a93d7a..4b283bb2a66f 100644 --- a/templates/minimal/node/src/rpc.rs +++ b/templates/minimal/node/src/rpc.rs @@ -27,7 +27,6 @@ use runtime::interface::{AccountId, Nonce, OpaqueBlock}; use sc_transaction_pool_api::TransactionPool; use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; use std::sync::Arc; -use substrate_frame_rpc_system::{System, SystemApiServer}; pub use sc_rpc_api::DenyUnsafe; @@ -41,6 +40,7 @@ pub struct FullDeps { pub deny_unsafe: DenyUnsafe, } +#[docify::export] /// Instantiate all full RPC extensions. pub fn create_full( deps: FullDeps, @@ -57,6 +57,7 @@ where C::Api: substrate_frame_rpc_system::AccountNonceApi, P: TransactionPool + 'static, { + use substrate_frame_rpc_system::{System, SystemApiServer}; let mut module = RpcModule::new(()); let FullDeps { client, pool, deny_unsafe } = deps; From c60feba1e49c766694ac3b408a14764df4cf9eae Mon Sep 17 00:00:00 2001 From: kianenigma Date: Fri, 31 May 2024 12:02:37 +0800 Subject: [PATCH 3/8] update --- docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs | 8 ++++---- substrate/frame/system/rpc/runtime-api/src/lib.rs | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs b/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs index 85276dabf926..c35653b1359f 100644 --- a/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs +++ b/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs @@ -55,9 +55,9 @@ //! For example, let's take a look a the process through which the account nonce can be queried //! through an RPC. First, a new runtime-api needs to be declared: //! -#![doc = docify::embed("../../substrate/frame/system/rpc/runtime-api/src/lib.rs", AccountNonceApi)] +#![doc = docify::embed!("../../substrate/frame/system/rpc/runtime-api/src/lib.rs", AccountNonceApi)] //! -//! This API is implemented at the runtime level, always inside [`sp_api::impl_runtime_api!`]. +//! This API is implemented at the runtime level, always inside [`sp_api::impl_runtime_apis!`]. //! //! As noted, this is already enough to make this API usable via `state_call`. //! @@ -66,14 +66,14 @@ //! Should you wish to implement the legacy approach of exposing this runtime-api as a custom //! RPC-api, then a custom RPC server has to be defined. //! -#![doc = docify::embed("../../substrate/utils/frame/rpc/system/src/lib.rs", SystemApi)] +#![doc = docify::embed!("../../substrate/utils/frame/rpc/system/src/lib.rs", SystemApi)] //! //! ## Add a new RPC to the node //! //! Finally, this custom RPC needs to be integrated into the node side. This is usually done in a //! `rpc.rs` in a typical template, as follows: //! -#![doc = docify::embed("../../templates/minimal/node/src/rpc.rs", create_full)] +#![doc = docify::embed!("../../templates/minimal/node/src/rpc.rs", create_full)] //! //! ## Future //! diff --git a/substrate/frame/system/rpc/runtime-api/src/lib.rs b/substrate/frame/system/rpc/runtime-api/src/lib.rs index f59988d818f0..67adeb5cb9da 100644 --- a/substrate/frame/system/rpc/runtime-api/src/lib.rs +++ b/substrate/frame/system/rpc/runtime-api/src/lib.rs @@ -23,6 +23,7 @@ #![cfg_attr(not(feature = "std"), no_std)] +#[docify::export(AccountNonceApi)] sp_api::decl_runtime_apis! { /// The API to query account nonce. pub trait AccountNonceApi where From 1ebba687dc7999ae8dbb06a74ce56c6a067f1efa Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Sat, 1 Jun 2024 10:05:41 +0800 Subject: [PATCH 4/8] Update docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bastian Köcher --- docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs b/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs index c35653b1359f..784bf8e9f85f 100644 --- a/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs +++ b/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs @@ -1,7 +1,5 @@ //! # Custom RPC do's and don'ts //! -//! > Authors: @xlc, @kianenigma -//! //! **TLDR:** don't create new custom RPCs. Instead, rely on custom Runtime APIs, combined with //! `state_call` //! From 7e2f5a48558bec22b9be0e9c0f068c55794b1ef5 Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Fri, 7 Jun 2024 15:11:20 +0800 Subject: [PATCH 5/8] Update docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs --- docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs b/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs index 784bf8e9f85f..8ed64a56c959 100644 --- a/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs +++ b/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs @@ -75,5 +75,6 @@ //! //! ## Future //! -//! [XCQ](https://forum.polkadot.network/t/cross-consensus-query-language-xcq/7583) will be a good +//! - [XCQ](https://forum.polkadot.network/t/cross-consensus-query-language-xcq/7583) will be a good //! solution for most of the query needs. +//! - [New JSON-RPC Specification](https://github.com/paritytech/json-rpc-interface-spec) From 5eb51b70b12012b1785ee1d31b5d56aeebeef18d Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Fri, 7 Jun 2024 18:57:31 +0800 Subject: [PATCH 6/8] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Gonçalo Pestana --- docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs b/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs index 8ed64a56c959..f4c7e3685100 100644 --- a/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs +++ b/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs @@ -5,7 +5,7 @@ //! //! ## Background //! -//! Polkadot-SDK offers the ability to query and subscribe storages directly. However what it did +//! Polkadot-SDK offers the ability to query and subscribe storages directly. However what it does //! not have is [view functions](https://github.com/paritytech/polkadot-sdk/issues/216). This is an //! essential feature to avoid duplicated logic between runtime and the client SDK. Custom RPC was //! used as a solution. It allow the RPC node to expose new RPCs that clients can be used to query From 09fc779ec7e7b8f45a9e3d64ed0f5daf46c960ce Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Fri, 7 Jun 2024 18:59:22 +0800 Subject: [PATCH 7/8] mark as legacy --- docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs b/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs index f4c7e3685100..dc7053ffb906 100644 --- a/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs +++ b/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs @@ -59,14 +59,14 @@ //! //! As noted, this is already enough to make this API usable via `state_call`. //! -//! ## Create a new custom RPC +//! ## Create a new custom RPC (Legacy) //! //! Should you wish to implement the legacy approach of exposing this runtime-api as a custom //! RPC-api, then a custom RPC server has to be defined. //! #![doc = docify::embed!("../../substrate/utils/frame/rpc/system/src/lib.rs", SystemApi)] //! -//! ## Add a new RPC to the node +//! ## Add a new RPC to the node (Legacy) //! //! Finally, this custom RPC needs to be integrated into the node side. This is usually done in a //! `rpc.rs` in a typical template, as follows: From c64271f2d1c1e23186cbea61e029f8aabbf7933d Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Fri, 7 Jun 2024 11:04:04 +0000 Subject: [PATCH 8/8] ".git/.scripts/commands/fmt/fmt.sh" --- docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs b/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs index dc7053ffb906..83a70606cb8d 100644 --- a/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs +++ b/docs/sdk/src/reference_docs/custom_runtime_api_rpc.rs @@ -52,7 +52,6 @@ //! //! For example, let's take a look a the process through which the account nonce can be queried //! through an RPC. First, a new runtime-api needs to be declared: -//! #![doc = docify::embed!("../../substrate/frame/system/rpc/runtime-api/src/lib.rs", AccountNonceApi)] //! //! This API is implemented at the runtime level, always inside [`sp_api::impl_runtime_apis!`]. @@ -63,14 +62,12 @@ //! //! Should you wish to implement the legacy approach of exposing this runtime-api as a custom //! RPC-api, then a custom RPC server has to be defined. -//! #![doc = docify::embed!("../../substrate/utils/frame/rpc/system/src/lib.rs", SystemApi)] //! //! ## Add a new RPC to the node (Legacy) //! //! Finally, this custom RPC needs to be integrated into the node side. This is usually done in a //! `rpc.rs` in a typical template, as follows: -//! #![doc = docify::embed!("../../templates/minimal/node/src/rpc.rs", create_full)] //! //! ## Future