substrate-api-client is a library written in Rust for connecting to the substrate's RPC interface via WebSockets allowing to
no_std
builds. Only the rpc-client is std only. For no_std
builds, a custom rpc client needs to be implemented.In order to build the substrate-api-client and the examples, Rust and the wasm target are needed. For Linux: ```bash curl https://sh.rustup.rs -sSf | sh
rustup show ```
To execute the examples, a running substrate node is needed. You can download a node artifact from substrate directly: https://github.com/paritytech/substrate or run the kitchensink-node with docker:
docker run -p 9944:9944 -p 9933:9933 -p 30333:30333 parity/substrate:latest --dev --ws-external --rpc-external
For more information, please refer to the substrate repository.
To run an example, clone the substrate-api-client
repository and run the desired example directly with the cargo command:
bash
git clone https://github.com/scs/substrate-api-client.git
cd substrate-api-client
cargo run -p ac-examples --example get_storage
or download the already built binaries from GitHub Actions and run them without any previous building:
```bash
chmod +x
./
Set the output verbosity by prepending RUST_LOG=info
or RUST_LOG=debug
.
The following examples can be found in the examples folder:
no_std
buildAlmost everything in the api-client, except for the rpc-clients and a few additional features, is no_std
compatible.
Many helpful features, such as extrinsic and call creation (see the macros), metadata and event types (see the node-api and primitives) are available in no_std
right away. However, to directly connect to a Substrate node a RPC client is necessary. Because websocket connection features are often hardware dependent, a generic no_std
RPC client implementation is hardly possible. So for most use cases a self-implemented RPC client is required. To make this as simple as possible, the interface between the Api
, which provides all the features, and the RPC client, providing the node connection, is kept very basic. Check out the following explanations for more info.
To import the api-client in no_std
make sure the default features are turned off and disable_target_static_assertions
is enabled:
```toml
substrate-api-client = { git = "https://github.com/scs/substrate-api-client.git", default-features = false, features = ["disabletargetstatic_assertions"] }
```
Depending on the usage, there are two traits that the RPC Client needs to implement.
For simple requests (send one request and receive one answer) the trait Request
is required:
rust
/// Trait to be implemented by the ws-client for sending rpc requests and extrinsic.
pub trait Request {
/// Sends a RPC request to the substrate node and returns the answer as string.
fn request<R: DeserializeOwned>(&self, method: &str, params: RpcParams) -> Result<R>;
}
By implementing this trait with a custom RPC client, most basic functionalities of the Api
can already be used.
Currently, there is no no_std
example available. But the tungstenite_client
provides a relatively simple std
example. If a websocket library is available in your no_std
environment, then your implementation may look similar.
A little more complex is the second trait Subscribe
, which does not only send a subscription request to the node, it also keeps listening and updating accordingly.
Two traits need to be implemented for this feature.
The Subscribe
trait itself:
```rust
/// Trait to be implemented by the ws-client for subscribing to the substrate node.
pub trait Subscribe {
type Subscription
fn subscribe<Notification: DeserializeOwned>(
&self,
sub: &str,
params: RpcParams,
unsub: &str,
) -> Result<Self::Subscription<Notification>>;
}
and the [`HandleSubscription`](https://github.com/scs/substrate-api-client/blob/d0a875e70f688c8ae2ce641935189c6374bc0ced/src/rpc/mod.rs#L64-L78) trait, which is returned by the `subscribe` function:
rust
/// Trait to use the full functionality of jsonrpseee Subscription type
/// without actually enforcing it.
pub trait HandleSubscriptionNone
if the subscription has been terminated,
/// which may happen if the channel becomes full or is dropped.
fn next(&mut self) -> Option
/// Unsubscribe and consume the subscription.
fn unsubscribe(self) -> Result<()>;
}
``
Refering to the
stdexample of the tungstenite, the
HandleSubscriptionimpl can be looked up [here](https://github.com/scs/substrate-api-client/blob/d0a875e70f688c8ae2ce641935189c6374bc0ced/src/rpc/tungstenite_client/subscription.rs#L23-L54). It implements a simple channel receiver, waiting for the sender of the websocket client to send something.
The
Subscribe` implementation can be found here.
A more complex RPC client, but also with more functionalities, is the jsonrpsee client.
There have been some breaking API changes as of late to catch up with the newer Substrate versions and to fully support different Substrate nodes. An example project on how to upgrade from older tags can be found in the Integritee worker repository: - tag v0.7.0 -> v0.9.0 (Upgrade to tag v0.8.0 is not recommended, directly upgrading to v0.9.0 saves you some extra work). - tag v0.9.0 -> v0.10.0
If you still experience issues during upgrading, do not hesitate to create an issue for support.
Parity offers a Rust client with similar functionality: https://github.com/paritytech/subxt
The development of substrate-api-client is financed by web3 foundation's grant programme.
We also thank the teams at
If you intend to or are using substrate-api-client, please add your project here
In alphabetical order