Repository: scs/substrate-api-client (language: rust)

Issue:
`cargo check --no-default-features --features std,tungstenite` results in compiler error
Not sure if this is combination is intended to be used, but I think it should:

```
src/api/api_client.rs:183:51
    |
183 |         let (genesis_hash, metadata, runtime_version) = futures::future::try_join3(
    |                                                         ^^^^^^^ use of undeclared crate or module `futures`

error[E0433]: failed to resolve: use of undeclared crate or module `futures`
   --> src/api/api_client.rs:243:4
    |
243 |             futures::future::try_join(metadata_future, runtime_version_future).await?;
    |             ^^^^^^^ use of undeclared crate or module `futures`

```

Observed on https://github.com/scs/substrate-api-client/tree/polkadot-v0.9.42-tag-v0.14.0


Discussion / hints:
Ah, ok I see it needs the feature `sync-api` maybe this should be documented
Which features were you using?
Exactly as in the title ;)
Ah, I read everything but the title 😊 

Not sure about the docs - where would you expect that? We already tried to have quite some elaborate doc in the Cargo.toml:
https://github.com/scs/substrate-api-client/blob/master/Cargo.toml. 

Either way: The included features represent exactly the  `tungstenite-client = ["std", "tungstenite"]` feature [here](https://github.com/scs/substrate-api-client/blob/master/Cargo.toml#L82C1-L82C44). If this does not compile as standalone we should fix the feautre import accordingly.

Also I'd vote for having a compile error that explains what's happening and how to fix it, in case it's unavoidable to have possible feature clashes. Just like [here](https://github.com/integritee-network/worker/blob/1b05e7b5817acd2cb0b10a161f03c17c91a37dc3/core-primitives/substrate-sgx/sp-io/src/lib.rs#L35-L36).

Alright, yeah I think now that the documentation is fine, however I do geth the above compiler error locally also with:

```rust
 cargo check --no-default-features --features tungstenite-client 
```

On the current master: d5809757fdb56d4efd95fa7bbe57e2ffbd041909

Fix patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9f940d378..a654e219f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -41,6 +41,16 @@ jobs:
                 cargo build --release -p test-no-std --features node-api,
                 cargo build --release -p test-no-std --features primitives,
 
+                 # Check build of stand-alone features.
+                cargo check --no-default-features,
+                cargo check --no-default-features --features sync-api,
+                cargo check --no-default-features --features jsonrpsee-client,
+                cargo check --no-default-features --features tungstenite-client,
+                cargo check --no-default-features --features ws-client,
+                cargo check --no-default-features --features staking-xt,
+                cargo check --no-default-features --features contracts-xt,
+                cargo check --no-default-features --features std,
+
                 # Test for 32 bit and wasm32-unknown-unknown compatibility
                 cargo build --target wasm32-unknown-unknown --no-default-features --features sync-api,
 
diff --git a/Cargo.lock b/Cargo.lock
index cd9679fe2..b91eb53fa 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6340,6 +6340,7 @@ dependencies = [
  "frame-metadata",
  "frame-support",
  "futures",
+ "futures-util",
  "hex",
  "jsonrpsee",
  "kitchensink-runtime",
diff --git a/Cargo.toml b/Cargo.toml
index 133b475f7..847705dec 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -28,12 +28,14 @@ async-trait = "0.1.68"
 codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ['derive'] }
 derive_more = { version = "0.99.5" }
 frame-metadata = { version = "16.0", default-features = false, features = ["current", "serde_full", "decode"] }
+futures-util = { version = "0.3", default-features = false }
 hex = { version = "0.4.3", default-features = false, features = ["alloc"] }
 log = { version = "0.4.14", default-features = false }
 maybe-async = { version = "0.2.7" }
 serde = { version = "1.0.136", default-features = false, features = ["derive"] }
 serde_json = { version = "1.0.79", default-features = false }
 
+
 # crates.io std only
 url = { version = "2.0.0", optional = true }
 
@@ -71,27 +73,35 @@ default = ["std", "jsonrpsee-client", "sync-api"]
 disable_target_static_assertions = [
     "sp-runtime-interface/disable_target_static_assertions",
 ]
-# If this is active all the code compiles in synchronous mode. Otherwise `async` is supported.
+
+# If this is active all the code compiles in synchronous mode. If not selected, code will compile to async mode.
 sync-api = ["ac-compose-macros/sync-api", "maybe-async/is_sync"]
+
 # Use the `jsonrpsee` crate for websocket communication. Does provide sync and async support but needs a tokio runtime.
 # Provides convenience functions such as subscription callbacks.
 # Most examples use the `jsonrpsee` feature and can be used for reference.
 jsonrpsee-client = ["std", "jsonrpsee", "futures"]
+
 # Use the `tungstenite` crate for websocket communication. No async support but has some reconnection capabilities.
 # See the example `transfer_with_tungstenite_client` on how to use it.
-tungstenite-client = ["std", "tungstenite"]
+tungstenite-client = ["std", "tungstenite", "sync-api"]
+
 # Use the `ws` crate for websocket communication. No async support.
 # Establishes a new connection for each request and therefore is limited in terms of performance.
 # See the example `transfer_with_ws_client` on how to use it.
-ws-client = ["std", "ws"]
+ws-client = ["std", "ws", "sync-api"]
+
 # Enables functionality that helps to create extrinsics for `pallet-staking`.
 # See the `StakingExtrinsics` trait and the `staking_batch_payout` example to get an understanding
 # of the functionality this feature provides
 staking-xt = ["std", "ac-primitives/staking-xt"]
+
 # Enables functionality that helps to create extrinsics for `pallet-contracts`.
 # See the `ContractsExtrinsics` trait and the `contract_instantiate_with_code` example to get an understanding
 # of the functionality this feature provides.
 contracts-xt = ["std", "ac-primitives/contracts-xt"]
+
+# Enables all std features of dependencies in case of std build.
 std = [
     # crates.io no_std
     "codec/std",
@@ -100,6 +110,7 @@ std = [
     "log/std",
     "serde/std",
     "serde_json/std",
+    "futures-util/std",
     # crates.io std only
     "url",
     # substrate no_std
diff --git a/examples/Cargo.toml b/examples/Cargo.toml
index 97a9f83c5..df98e70d3 100644
--- a/examples/Cargo.toml
+++ b/examples/Cargo.toml
@@ -27,11 +27,16 @@ sp-version = { git = "https://github.com/paritytech/polkadot-sdk.git", branch =
 sp-weights = { default-features = false, features = ["serde"], git = "https://github.com/paritytech/polkadot-sdk.git", branch = "master" }
 
 # local deps
-substrate-api-client = { path = "..", default-features = false, features = ["jsonrpsee-client", "tungstenite-client", "ws-client", "staking-xt", "contracts-xt"] }
+substrate-api-client = { path = "..", default-features = false, features = ["jsonrpsee-client", "staking-xt", "contracts-xt"] }
 
 [features]
 default = ["sync-examples"]
-sync-examples = ["substrate-api-client/std", "substrate-api-client/sync-api"]
+sync-examples = [
+    "substrate-api-client/std",
+    "substrate-api-client/sync-api",
+    "substrate-api-client/tungstenite-client",
+    "substrate-api-client/ws-client",
+]
 
 [dependencies]
 tokio-util = "0.7.8"
diff --git a/src/api/api_client.rs b/src/api/api_client.rs
index ec90d6008..98a94d494 100644
--- a/src/api/api_client.rs
+++ b/src/api/api_client.rs
@@ -19,13 +19,14 @@ use crate::{
 use ac_compose_macros::rpc_params;
 use ac_node_api::metadata::Metadata;
 use ac_primitives::{Config, ExtrinsicParams, SignExtrinsic};
+#[cfg(not(feature = "sync-api"))]
+use alloc::boxed::Box;
 use codec::Decode;
 use core::convert::TryFrom;
 use frame_metadata::RuntimeMetadataPrefixed;
 use log::{debug, info};
 use sp_core::Bytes;
 use sp_version::RuntimeVersion;
-
 /// Api to talk with substrate-nodes
 ///
 /// It is generic over the `Request` trait, so you can use any rpc-backend you like.
@@ -180,7 +181,7 @@ where
 		let metadata_future = Self::get_metadata(&client);
 		let runtime_version_future = Self::get_runtime_version(&client);
 
-		let (genesis_hash, metadata, runtime_version) = futures::future::try_join3(
+		let (genesis_hash, metadata, runtime_version) = futures_util::future::try_join3(
 			genesis_hash_future,
 			metadata_future,
 			runtime_version_future,
@@ -240,7 +241,7 @@ where
 		let runtime_version_future = Self::get_runtime_version(&self.client);
 
 		let (metadata, runtime_version) =
-			futures::future::try_join(metadata_future, runtime_version_future).await?;
+			futures_util::future::try_join(metadata_future, runtime_version_future).await?;
 
 		debug!("Metadata: {:?}", metadata);
 		info!("Runtime Version: {:?}", runtime_version);
diff --git a/src/api/rpc_api/author.rs b/src/api/rpc_api/author.rs
index 011b4a02f..1177fb2dc 100644
--- a/src/api/rpc_api/author.rs
+++ b/src/api/rpc_api/author.rs
@@ -20,6 +20,8 @@ use crate::{
 };
 use ac_compose_macros::rpc_params;
 use ac_primitives::{config::Config, UncheckedExtrinsicV4};
+#[cfg(not(feature = "sync-api"))]
+use alloc::boxed::Box;
 use codec::{Decode, Encode};
 use log::*;
 use serde::de::DeserializeOwned;
diff --git a/src/api/rpc_api/chain.rs b/src/api/rpc_api/chain.rs
index 4452af5bd..f0b0ed385 100644
--- a/src/api/rpc_api/chain.rs
+++ b/src/api/rpc_api/chain.rs
@@ -18,6 +18,8 @@ use crate::{
 };
 use ac_compose_macros::rpc_params;
 use ac_primitives::config::Config;
+#[cfg(not(feature = "sync-api"))]
+use alloc::boxed::Box;
 use alloc::vec::Vec;
 use log::*;
 use serde::de::DeserializeOwned;
diff --git a/src/api/rpc_api/events.rs b/src/api/rpc_api/events.rs
index a6796bc6f..fe53bb5f0 100644
--- a/src/api/rpc_api/events.rs
+++ b/src/api/rpc_api/events.rs
@@ -19,6 +19,8 @@ use crate::{
 use ac_compose_macros::rpc_params;
 use ac_node_api::{metadata::Metadata, EventDetails, EventRecord, Events, Phase};
 use ac_primitives::config::Config;
+#[cfg(not(feature = "sync-api"))]
+use alloc::boxed::Box;
 use alloc::{vec, vec::Vec};
 use codec::Decode;
 use core::marker::PhantomData;
diff --git a/src/api/rpc_api/frame_system.rs b/src/api/rpc_api/frame_system.rs
index e87b3510e..0b057ac75 100644
--- a/src/api/rpc_api/frame_system.rs
+++ b/src/api/rpc_api/frame_system.rs
@@ -19,6 +19,8 @@ use crate::{
 };
 use ac_compose_macros::rpc_params;
 use ac_primitives::{config::Config, AccountInfo};
+#[cfg(not(feature = "sync-api"))]
+use alloc::boxed::Box;
 use alloc::{string::String, vec::Vec};
 use log::*;
 use sp_storage::StorageKey;
diff --git a/src/api/rpc_api/pallet_balances.rs b/src/api/rpc_api/pallet_balances.rs
index af3b88a8d..3196fa376 100644
--- a/src/api/rpc_api/pallet_balances.rs
+++ b/src/api/rpc_api/pallet_balances.rs
@@ -15,6 +15,8 @@ use crate::{
 	rpc::Request,
 };
 use ac_primitives::config::Config;
+#[cfg(not(feature = "sync-api"))]
+use alloc::boxed::Box;
 
 /// Interface to common calls of the substrate balances pallet.
 #[maybe_async::maybe_async(?Send)]
diff --git a/src/api/rpc_api/pallet_transaction_payment.rs b/src/api/rpc_api/pallet_transaction_payment.rs
index bdfe13984..3fcc2eb5e 100644
--- a/src/api/rpc_api/pallet_transaction_payment.rs
+++ b/src/api/rpc_api/pallet_transaction_payment.rs
@@ -16,9 +16,10 @@ use crate::{
 };
 use ac_compose_macros::rpc_params;
 use ac_primitives::{config::Config, FeeDetails, InclusionFee, NumberOrHex, RuntimeDispatchInfo};
+#[cfg(not(feature = "sync-api"))]
+use alloc::boxed::Box;
 use core::str::FromStr;
 use sp_core::Bytes;
-
 /// Interface to common calls of the substrate transaction payment pallet.
 #[maybe_async::maybe_async(?Send)]
 pub trait GetTransactionPayment {
diff --git a/src/api/rpc_api/state.rs b/src/api/rpc_api/state.rs
index 224e4d636..3f51224e9 100644
--- a/src/api/rpc_api/state.rs
+++ b/src/api/rpc_api/state.rs
@@ -18,6 +18,8 @@ use crate::{
 use ac_compose_macros::rpc_params;
 use ac_node_api::MetadataError;
 use ac_primitives::config::Config;
+#[cfg(not(feature = "sync-api"))]
+use alloc::boxed::Box;
 use alloc::{borrow::ToOwned, string::String, vec, vec::Vec};
 use codec::{Decode, Encode};
 use core::cmp;
diff --git a/src/extrinsic/balances.rs b/src/extrinsic/balances.rs
index 3ce2a3c98..ae673437a 100644
--- a/src/extrinsic/balances.rs
+++ b/src/extrinsic/balances.rs
@@ -25,6 +25,8 @@ use ac_primitives::{
 	UncheckedExtrinsicV4,
 };
 use alloc::borrow::ToOwned;
+#[cfg(not(feature = "sync-api"))]
+use alloc::boxed::Box;
 use codec::{Compact, Encode};
 
 pub const BALANCES_MODULE: &str = "Balances";
diff --git a/src/extrinsic/utility.rs b/src/extrinsic/utility.rs
index 2a3168dfd..e385bd3d3 100644
--- a/src/extrinsic/utility.rs
+++ b/src/extrinsic/utility.rs
@@ -24,6 +24,8 @@ use ac_primitives::{
 	config::Config, extrinsic_params::ExtrinsicParams, extrinsics::CallIndex, SignExtrinsic,
 	UncheckedExtrinsicV4,
 };
+#[cfg(not(feature = "sync-api"))]
+use alloc::boxed::Box;
 use alloc::{borrow::ToOwned, vec::Vec};
 use codec::{Decode, Encode};
 
diff --git a/src/rpc/mod.rs b/src/rpc/mod.rs
index ff79acdea..dbe8e1883 100644
--- a/src/rpc/mod.rs
+++ b/src/rpc/mod.rs
@@ -16,6 +16,8 @@
 */
 
 use ac_primitives::RpcParams;
+#[cfg(not(feature = "sync-api"))]
+use alloc::boxed::Box;
 use alloc::string::{String, ToString};
 use serde::de::DeserializeOwned;
 


Test patch: