From 5f692acc841c4fd9d3e326b2e837b4a5378dfa8c Mon Sep 17 00:00:00 2001 From: Niklas Date: Thu, 10 Feb 2022 17:37:09 +0100 Subject: [PATCH] add remaining RPCs --- examples/examples/fetch_remote.rs | 16 +++- examples/examples/transfer_subscribe.rs | 14 ++- subxt/src/client.rs | 38 ++++++-- subxt/src/config.rs | 3 +- subxt/src/rpc.rs | 120 ++++++------------------ 5 files changed, 87 insertions(+), 104 deletions(-) diff --git a/examples/examples/fetch_remote.rs b/examples/examples/fetch_remote.rs index 7b41dc1862..8465934f9e 100644 --- a/examples/examples/fetch_remote.rs +++ b/examples/examples/fetch_remote.rs @@ -15,11 +15,17 @@ // along with subxt. If not, see . use subxt::{ + rpc::SubxtRpcApiClient, ClientBuilder, + Config, DefaultConfig, DefaultExtra, }; +type Hash = ::Hash; +type Header = ::Header; +type Extrinsic = ::Header; + #[subxt::subxt(runtime_metadata_path = "examples/polkadot_metadata.scale")] pub mod polkadot {} @@ -35,11 +41,11 @@ async fn main() -> Result<(), Box> { let block_number = 1; - let block_hash = api - .client - .rpc() - .block_hash(Some(block_number.into())) - .await?; + let block_hash = SubxtRpcApiClient::::block_hash( + api.client.rpc().inner(), + Some(block_number.into()), + ) + .await?; if let Some(hash) = block_hash { println!("Block hash for block number {}: {}", block_number, hash); diff --git a/examples/examples/transfer_subscribe.rs b/examples/examples/transfer_subscribe.rs index 316d27248b..ae7feb383d 100644 --- a/examples/examples/transfer_subscribe.rs +++ b/examples/examples/transfer_subscribe.rs @@ -24,13 +24,20 @@ use sp_keyring::AccountKeyring; use subxt::{ + rpc::SubxtRpcApiClient, ClientBuilder, + Config, DefaultConfig, DefaultExtra, + EventStorageSubscription, EventSubscription, PairSigner, }; +type Hash = ::Hash; +type Header = ::Header; +type Extrinsic = ::Header; + #[subxt::subxt(runtime_metadata_path = "examples/polkadot_metadata.scale")] pub mod polkadot {} @@ -46,7 +53,12 @@ async fn main() -> Result<(), Box> { .await? .to_runtime_api::>>(); - let sub = api.client.rpc().subscribe_events().await?; + let sub = SubxtRpcApiClient::::subscribe_events( + api.client.rpc().inner(), + ) + .await?; + + let sub = EventStorageSubscription::Imported(sub); let decoder = api.client.events_decoder(); let mut sub = EventSubscription::::new(sub, decoder); sub.filter_event::(); diff --git a/subxt/src/client.rs b/subxt/src/client.rs index 8cdd980e4f..bee3d70507 100644 --- a/subxt/src/client.rs +++ b/subxt/src/client.rs @@ -41,7 +41,10 @@ use crate::{ Config, Metadata, }; -use codec::Decode; +use codec::{ + Decode, + Encode, +}; use derivative::Derivative; use std::sync::Arc; @@ -91,13 +94,16 @@ impl ClientBuilder { }; let rpc = Rpc::new(client); let (metadata_bytes, genesis_hash, runtime_version, properties) = future::join4( - SubxtRpcApiClient::::metadata(&*rpc), - SubxtRpcApiClient::::genesis_hash(&*rpc), + SubxtRpcApiClient::::metadata(rpc.inner()), + SubxtRpcApiClient::::genesis_hash( + rpc.inner(), + ), SubxtRpcApiClient::::runtime_version( - &*rpc, None, + rpc.inner(), + None, ), SubxtRpcApiClient::::system_properties( - &*rpc, + rpc.inner(), ), ) .await; @@ -238,8 +244,14 @@ where // Get a hash of the extrinsic (we'll need this later). let ext_hash = T::Hashing::hash_of(&extrinsic); + let bytes = extrinsic.encode().into(); + // Submit and watch for transaction progress. - let sub = self.client.rpc().watch_extrinsic(extrinsic).await?; + let sub = SubxtRpcApiClient::::watch_extrinsic( + self.client.rpc().inner(), + bytes, + ) + .await?; Ok(TransactionProgress::new(sub, self.client, ext_hash)) } @@ -262,8 +274,18 @@ where ::AccountId: From<::AccountId>, ::Index: Into<::Index>, { - let extrinsic = self.create_signed(signer, Default::default()).await?; - self.client.rpc().submit_extrinsic(extrinsic).await + let bytes = self + .create_signed(signer, Default::default()) + .await? + .encode() + .into(); + + SubxtRpcApiClient::::submit_extrinsic( + self.client.rpc().inner(), + bytes, + ) + .await + .map_err(Into::into) } /// Creates a signed extrinsic. diff --git a/subxt/src/config.rs b/subxt/src/config.rs index 15ed084795..eec63f128e 100644 --- a/subxt/src/config.rs +++ b/subxt/src/config.rs @@ -78,7 +78,8 @@ pub trait Config: 'static { type Signature: Verify + Encode + Send + Sync + 'static; /// Extrinsic type within blocks. - // TODO(niklasad1): I have no idea if this ok or not ^^ + // TODO(niklasad1): I have no idea if this ok or not ^^ => won't work otherwise + // because `jsonrpsee` requires `Deserialize + Send + Sync` for the return types. type Extrinsic: Parameter + Extrinsic + Debug diff --git a/subxt/src/rpc.rs b/subxt/src/rpc.rs index ede7b83db9..7322f3148f 100644 --- a/subxt/src/rpc.rs +++ b/subxt/src/rpc.rs @@ -23,7 +23,6 @@ use std::{ collections::HashMap, - ops::Deref, sync::Arc, }; @@ -32,11 +31,9 @@ use crate::{ subscription::{ EventStorageSubscription, FinalizedEventStorageSubscription, - SystemEvents, }, Config, }; -use codec::Encode; use core::marker::PhantomData; use jsonrpsee::core::RpcResult; pub use jsonrpsee::{ @@ -205,6 +202,33 @@ pub trait SubxtRpcApi { /// Returns `true` if a private key could be found. #[method(name = "author_hasKey")] async fn has_key(&self, public_key: Bytes, key_type: String) -> RpcResult; + + /// Subscribe to System Events that are imported into blocks. + /// + /// *WARNING* these may not be included in the finalized chain, use + /// `subscribe_finalized_events` to ensure events are finalized. + #[subscription(name = "state_subscribeStorage", item = StorageChangeSet)] + fn subscribe_events(&self) -> RpcResult<()>; + + /// Subscribe to blocks. + #[subscription(name = "chain_subscribeNewHeads", item = Header)] + fn subscribe_blocks(&self) -> RpcResult<()>; + + /// Subscribe to finalized blocks. + #[subscription(name = "chain_subscribeFinalizedHeads", item = Header)] + fn subscribe_finalized_blocks(&self) -> RpcResult<()>; + + /// Create and submit an extrinsic and return a subscription to the events triggered. + #[subscription( + name = "author_submitAndWatchExtrinsic", + unsubscribe_aliases = ["author_unwatchExtrinsic"], + item = SubstrateTransactionStatus + )] + fn watch_extrinsic(&self, xt: Bytes) -> RpcResult<()>; + + /// Create and submit an extrinsic and return corresponding Hash if successful + #[method(name = "author_submitExtrinsic")] + async fn submit_extrinsic(&self, extrinsic: Bytes) -> RpcResult; } /// A number type that can be serialized both as a number or a string that encodes a number in a @@ -348,14 +372,6 @@ impl Clone for Rpc { } } -impl Deref for Rpc { - type Target = RpcClient; - - fn deref(&self) -> &Self::Target { - &*self.client - } -} - impl Rpc { /// Create a new [`Rpc`] pub fn new(client: RpcClient) -> Self { @@ -365,21 +381,9 @@ impl Rpc { } } - /// Subscribe to System Events that are imported into blocks. - /// - /// *WARNING* these may not be included in the finalized chain, use - /// `subscribe_finalized_events` to ensure events are finalized. - pub async fn subscribe_events( - &self, - ) -> Result, BasicError> { - let keys = Some(vec![StorageKey::from(SystemEvents::new())]); - let params = rpc_params![keys]; - - let subscription = self - .client - .subscribe("state_subscribeStorage", params, "state_unsubscribeStorage") - .await?; - Ok(EventStorageSubscription::Imported(subscription)) + /// Get a reference to the client make calls. + pub fn inner(&self) -> &RpcClient { + &*self.client } /// Subscribe to finalized events. @@ -389,72 +393,10 @@ impl Rpc { Ok(EventStorageSubscription::Finalized( FinalizedEventStorageSubscription::new( self.clone(), - self.subscribe_finalized_blocks().await?, + SubxtRpcApiClient::::subscribe_finalized_blocks(&*self.client).await?, ), )) } - - /// Subscribe to blocks. - pub async fn subscribe_blocks(&self) -> Result, BasicError> { - let subscription = self - .client - .subscribe( - "chain_subscribeNewHeads", - rpc_params![], - "chain_unsubscribeNewHeads", - ) - .await?; - - Ok(subscription) - } - - /// Subscribe to finalized blocks. - pub async fn subscribe_finalized_blocks( - &self, - ) -> Result, BasicError> { - let subscription = self - .client - .subscribe( - "chain_subscribeFinalizedHeads", - rpc_params![], - "chain_unsubscribeFinalizedHeads", - ) - .await?; - Ok(subscription) - } - - /// Create and submit an extrinsic and return corresponding Hash if successful - pub async fn submit_extrinsic( - &self, - extrinsic: X, - ) -> Result { - let bytes: Bytes = extrinsic.encode().into(); - let params = rpc_params![bytes]; - let xt_hash = self - .client - .request("author_submitExtrinsic", params) - .await?; - Ok(xt_hash) - } - - /// Create and submit an extrinsic and return a subscription to the events triggered. - pub async fn watch_extrinsic( - &self, - extrinsic: X, - ) -> Result>, BasicError> - { - let bytes: Bytes = extrinsic.encode().into(); - let params = rpc_params![bytes]; - let subscription = self - .client - .subscribe( - "author_submitAndWatchExtrinsic", - params, - "author_unwatchExtrinsic", - ) - .await?; - Ok(subscription) - } } /// Build WS RPC client from URL