diff --git a/client/Cargo.toml b/client/Cargo.toml index a0574e8f2b..26e3795775 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -20,6 +20,7 @@ futures = "0.3.9" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee/", branch = "extract-async-client", features = ["client"] } log = "0.4.13" thiserror = "1.0.23" +serde_json = "1" sc-client-db = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } @@ -38,3 +39,5 @@ async-std = { version = "1.8.0", features = ["attributes"] } env_logger = "0.8.2" node-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } tempdir = "0.3.7" +subxt = { path = ".." } +test-runtime = { path = "../test-runtime" } diff --git a/client/src/lib.rs b/client/src/lib.rs index 3ea925662d..d3d82fb8f0 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -14,8 +14,13 @@ // You should have received a copy of the GNU General Public License // along with subxt. If not, see . +//! Client for embedding substrate nodes. + #![deny(missing_docs)] +#[cfg(test)] +mod tests; + use async_std::task; use futures::{ channel::mpsc, diff --git a/client/src/tests.rs b/client/src/tests.rs new file mode 100644 index 0000000000..e7eabc311c --- /dev/null +++ b/client/src/tests.rs @@ -0,0 +1,79 @@ +use node_cli::service::NewFullBase; +use sp_keyring::AccountKeyring; +use subxt::{ClientBuilder, PairSigner}; +use test_runtime::node_runtime::{self, system, DefaultConfig} +use crate::{ + DatabaseSource, + KeystoreConfig, + Role, + SubxtClient, + SubxtClientConfig, + WasmExecutionMethod, +}; +use tempdir::TempDir; + +#[async_std::test] +pub async fn test_embedded_client() { + let tmp = TempDir::new("subxt-").expect("failed to create tempdir"); + let config = SubxtClientConfig { + impl_name: "full-client", + impl_version: "0.0.1", + author: "", + copyright_start_year: 2020, + db: DatabaseSource::RocksDb { + path: tmp.path().join("db"), + cache_size: 16, + }, + keystore: KeystoreConfig::Path { + path: tmp.path().join("keystore"), + password: None, + }, + chain_spec: node_cli::chain_spec::development_config(), + role: Role::Authority(AccountKeyring::Alice), + telemetry: None, + wasm_method: WasmExecutionMethod::Compiled, + tokio_handle: tokio::runtime::Handle::current(), + }; + + let NewFullBase { + task_manager, + rpc_handlers, + .. + } = node_cli::service::new_full_base(config.into_service_config(), |_, _| ()) + .unwrap(); + + let client = SubxtClient::new(task_manager, rpc_handlers); + + let ext_client = ClientBuilder::new() + .set_client(client) + .build::() + .await + .unwrap(); + let api: node_runtime::RuntimeApi = + ext_client.clone().to_runtime_api(); + + // verify that we can read storage + api.storage() + .system() + .account(AccountKeyring::Alice.to_account_id().into(), None) + .await + .unwrap(); + + let alice = PairSigner::::new(AccountKeyring::Alice.pair()); + let bob_address = AccountKeyring::Bob.to_account_id().into(); + + // verify that we can call dispatchable functions + let result = api + .tx() + .balances() + .transfer(bob_address, 100_000_000_000_000_000) + .sign_and_submit_then_watch(&alice) + .await + .unwrap(); + + // verify that we receive events + let success = result + .find_event::() + .unwrap(); + assert!(success.is_some()); +}