neo3/
lib.rs

1#![allow(
2	clippy::result_large_err,
3	clippy::too_many_arguments,
4	clippy::wrong_self_convention,
5	clippy::module_inception,
6	clippy::type_complexity
7)]
8#![allow(unexpected_cfgs)]
9//! ![Neo Logo](https://neo.org/images/neo-logo/NEO-logo.svg)
10//! # NeoRust SDK v1.0.1
11//!
12//! A production-ready Rust SDK for the Neo N3 blockchain with enterprise-grade features.
13//!
14//! [![Crates.io](https://img.shields.io/crates/v/neo3.svg)](https://crates.io/crates/neo3)
15//! [![Documentation](https://docs.rs/neo3/badge.svg)](https://docs.rs/neo3)
16//! [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
17//!
18//! ## Features
19//!
20//! This crate provides several feature flags to customize functionality:
21//!
22//! - **futures**: Enables async/futures support for asynchronous blockchain operations. This is recommended
23//!   for most applications that need to interact with the Neo blockchain without blocking.
24//!
25//! - **ledger**: Enables hardware wallet support via Ledger devices. When enabled, you can use Ledger
26//!   hardware wallets for transaction signing and key management. This feature provides an additional
27//!   security layer by keeping private keys on dedicated hardware.
28//!
29//! - **aws**: ⚠️ **DISABLED in v1.0.1** due to security vulnerabilities in rusoto dependencies.
30//!   Will be re-enabled in a future 1.x release with the modern AWS SDK. For AWS KMS integration,
31//!   use the legacy v0.3.x line or wait for updated AWS SDK support.
32//!
33//! - **sgx**: Enables Intel SGX (Software Guard Extensions) support for running Neo operations
34//!   in secure enclaves. This feature enables `no_std` compilation and provides hardware-based
35//!   security for sensitive operations like key management and transaction signing.
36//!
37//! - **no_std**: Enables `no_std` compilation for embedded systems and SGX environments.
38//!   This feature removes dependencies on the standard library, allowing the SDK to run in
39//!   constrained environments with custom allocators.
40//!
41//! To enable specific features in your project, modify your `Cargo.toml` as follows:
42//!
43//! ```toml
44//! [dependencies]
45//! neo3 = { version = "1.0.1", features = ["futures", "ledger"] }
46//! ```
47//!
48//! You can disable default features with:
49//!
50//! ```toml
51//! neo3 = { version = "1.0.1", default-features = false, features = ["futures"] }
52//! ```
53//!
54//! ## Overview
55//!
56//! NeoRust is a complete SDK designed to make Neo N3 blockchain development in Rust
57//! intuitive, type-safe, and productive. The library provides full support for all
58//! Neo N3 features and follows Rust best practices for reliability and performance.
59//!
60//! ### New in v1.0.x
61//! - **WebSocket Support**: Real-time blockchain events with automatic reconnection
62//! - **HD Wallets (BIP-39/44)**: Deterministic wallet generation and derivation
63//! - **Transaction Simulation**: Preview fees, VM state, and state changes before sending
64//! - **High-Level SDK API**: Simplified entrypoint (`Neo`) for common operations
65//! - **Enhanced Error Handling**: Consistent `NeoError` with recovery suggestions
66//!
67//! ## Core Modules
68//!
69//! NeoRust is organized into specialized modules, each handling specific aspects of Neo N3:
70//!
71//! - [**neo_builder**](neo_builder): Transaction construction and script building
72//! - [**neo_clients**](neo_clients): Neo node interaction and RPC client implementations
73//! - [**neo_codec**](neo_codec): Serialization and deserialization of Neo data structures
74//! - [**neo_config**](neo_config): Configuration for networks and client settings
75//! - [**neo_contract**](neo_contract): Smart contract interaction and token standards
76//! - [**neo_crypto**](neo_crypto): Cryptographic primitives and operations
77//! - [**neo_error**](neo_error): Unified error handling
78//! - [**neo_fs**](neo_fs): NeoFS distributed storage system integration
79//! - [**neo_protocol**](neo_protocol): Core blockchain protocol implementations
80//! - [**neo_types**](neo_types): Core data types and primitives for Neo N3
81//! - [**neo_utils**](neo_utils): General utility functions
82//! - [**neo_wallets**](neo_wallets): Wallet management for Neo N3
83//! - [**neo_x**](neo_x): Neo X EVM compatibility layer
84//!
85//! ## Quick Start
86//!
87//! Import all essential types and traits using the `prelude`:
88//!
89//! ```rust
90//! use neo3::prelude::*;
91//! ```
92//!
93//! ## Complete Example
94//!
95//! Here's a comprehensive example showcasing common operations with the NeoRust SDK:
96//!
97//! ```no_run
98//! use neo3::neo_protocol::{Account, AccountTrait};
99//! use neo3::neo_clients::{HttpProvider, RpcClient, APITrait};
100//!
101//! async fn neo_example() -> Result<(), Box<dyn std::error::Error>> {
102//!     // Connect to Neo TestNet
103//!     let provider = HttpProvider::new("https://testnet1.neo.org:443")?;
104//!     let client = RpcClient::new(provider);
105//!     
106//!     // Get basic blockchain information
107//!     let block_height = client.get_block_count().await?;
108//!     println!("Connected to Neo TestNet at height: {}", block_height);
109//!     
110//!     // Create a new wallet account
111//!     let account = Account::create()?;
112//!     println!("New account created:");
113//!     println!("  Address:     {}", account.get_address());
114//!     println!("  Script Hash: {}", account.get_script_hash());
115//!     
116//!     // Get version information
117//!     let version = client.get_version().await?;
118//!     println!("Node version: {}", version.user_agent);
119//!     
120//!     Ok(())
121//! }
122//! ```
123//!
124//! ## Usage Examples
125//!
126//! ### Connecting to a Neo N3 node
127//!
128//! ```no_run
129//! use neo3::neo_clients::{HttpProvider, RpcClient, APITrait};
130//!
131//! #[tokio::main]
132//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
133//!     // Connect to Neo N3 MainNet
134//!     let provider = HttpProvider::new("https://mainnet1.neo.org:443")?;
135//!     let client = RpcClient::new(provider);
136//!     
137//!     // Get basic blockchain information
138//!     let block_count = client.get_block_count().await?;
139//!     println!("Current block count: {}", block_count);
140//!     
141//!     let version = client.get_version().await?;
142//!     println!("Node version: {}", version.user_agent);
143//!     
144//!     Ok(())
145//! }
146//! ```
147//!
148//! ### Creating and sending a transaction
149//!
150//! ```no_run
151//! use neo3::neo_clients::{HttpProvider, RpcClient, APITrait};
152//! use neo3::neo_protocol::{Account, AccountTrait};
153//! use neo3::neo_types::{ScriptHash, ContractParameter, ScriptHashExtension};
154//! use neo3::neo_builder::{ScriptBuilder, TransactionBuilder, AccountSigner};
155//! use std::str::FromStr;
156//!
157//! #[tokio::main]
158//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
159//!     // Initialize the JSON-RPC provider
160//!     let provider = HttpProvider::new("https://testnet1.neo.org:443")?;
161//!     let client = RpcClient::new(provider);
162//!
163//!     // Create accounts for the sender and recipient
164//!     // Load sender key from an environment variable to avoid hardcoding secrets.
165//!     let sender_wif = std::env::var("NEO_WIF")?;
166//!     let sender = Account::from_wif(&sender_wif)?;
167//!     let recipient = ScriptHash::from_address("NbTiM6h8r99kpRtb428XcsUk1TzKed2gTc")?;
168//!
169//!     // Get the GAS token contract
170//!     let gas_token_hash = ScriptHash::from_str("d2a4cff31913016155e38e474a2c06d08be276cf")?;
171//!     
172//!     // Build the transaction using the ScriptBuilder
173//!     let script = ScriptBuilder::new()
174//!         .contract_call(
175//!             &gas_token_hash,
176//!             "transfer",
177//!             &[
178//!                 ContractParameter::h160(&sender.get_script_hash()),
179//!                 ContractParameter::h160(&recipient),
180//!                 ContractParameter::integer(1_0000_0000), // 1 GAS (8 decimals)
181//!                 ContractParameter::any(),
182//!             ],
183//!             None,
184//!         )?
185//!         .to_bytes();
186//!     
187//!     // Create and configure the transaction
188//!     let mut tx_builder = TransactionBuilder::with_client(&client);
189//!     tx_builder
190//!         .set_script(Some(script))
191//!         .set_signers(vec![AccountSigner::called_by_entry(&sender)?.into()])?
192//!         .valid_until_block(client.get_block_count().await? + 5760)?; // Valid for ~1 day
193//!
194//!     // Sign the transaction
195//!     let mut tx = tx_builder.sign().await?;
196//!
197//!     // Send the transaction
198//!     let result = tx.send_tx().await?;
199//!     println!("Transaction sent: {}", result.hash);
200//!
201//!     // Wait for the transaction to be confirmed
202//!     println!("Waiting for confirmation...");
203//!     tx.track_tx(10).await?;
204//!     println!("Transaction confirmed!");
205//!
206//!     // Get the application log
207//!     let app_log = tx.get_application_log(&client).await?;
208//!     println!("Application log: {:?}", app_log);
209//!
210//!     Ok(())
211//! }
212//! ```
213//!
214//! ### Interacting with a smart contract
215//!
216//! ```no_run
217//! use neo3::neo_clients::{HttpProvider, RpcClient, APITrait};
218//! use neo3::neo_types::ScriptHash;
219//! use std::str::FromStr;
220//!
221//! #[tokio::main]
222//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
223//!     // Connect to Neo N3 TestNet
224//!     let provider = HttpProvider::new("https://testnet1.neo.org:443")?;
225//!     let client = RpcClient::new(provider);
226//!     
227//!     // Get the NEO token contract
228//!     let neo_token = ScriptHash::from_str("ef4073a0f2b305a38ec4050e4d3d28bc40ea63f5")?;
229//!     
230//!     // Call a read-only method (doesn't require signing)
231//!     let result = client
232//!         .invoke_function(&neo_token, "symbol".to_string(), vec![], None)
233//!         .await?;
234//!     
235//!     // Parse the result
236//!     if let Some(item) = result.stack.first() {
237//!         println!("NEO Token Symbol: {:?}", item);
238//!     }
239//!     
240//!     // Get the total supply
241//!     let supply_result = client
242//!         .invoke_function(&neo_token, "totalSupply".to_string(), vec![], None)
243//!         .await?;
244//!     
245//!     println!("Total Supply Result: {:?}", supply_result);
246//!     
247//!     Ok(())
248//! }
249//! ```
250//!
251//! ### Working with NEP-17 tokens
252//!
253//! ```no_run
254//! use neo3::neo_clients::{HttpProvider, RpcClient, APITrait};
255//! use neo3::neo_protocol::{Account, AccountTrait};
256//! use neo3::neo_types::{ScriptHash, ContractParameter};
257//! use std::str::FromStr;
258//!
259//! #[tokio::main]
260//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
261//!     // Connect to Neo N3 TestNet
262//!     let provider = HttpProvider::new("https://testnet1.neo.org:443")?;
263//!     let client = RpcClient::new(provider);
264//!     
265//!     // Create an account from WIF (Wallet Import Format)
266//!     let wif = std::env::var("NEO_WIF")?;
267//!     let account = Account::from_wif(&wif)?;
268//!     
269//!     // Get account information
270//!     println!("Account address: {}", account.get_address());
271//!     println!("Account script hash: {}", account.get_script_hash());
272//!     
273//!     // Get GAS token balance for the account
274//!     let gas_token = ScriptHash::from_str("d2a4cff31913016155e38e474a2c06d08be276cf")?;
275//!     
276//!     let balance_result = client
277//!         .invoke_function(
278//!             &gas_token,
279//!             "balanceOf".to_string(),
280//!             vec![ContractParameter::h160(&account.get_script_hash())],
281//!             None,
282//!         )
283//!         .await?;
284//!     
285//!     // Parse the balance result
286//!     if let Some(item) = balance_result.stack.first() {
287//!         println!("GAS Balance: {:?}", item);
288//!     }
289//!     
290//!     Ok(())
291//! }
292//! ```
293//!
294//! ### Using the Neo Name Service (NNS)
295//!
296//! ```no_run
297//! use neo3::neo_clients::{HttpProvider, RpcClient, APITrait};
298//! use neo3::neo_types::{ContractParameter, ScriptHash};
299//! use std::str::FromStr;
300//!
301//! #[tokio::main]
302//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
303//!     // Connect to Neo N3 TestNet
304//!     let provider = HttpProvider::new("https://testnet1.neo.org:443")?;
305//!     let client = RpcClient::new(provider);
306//!     
307//!     // NNS contract on TestNet (use MainNet hash for production)
308//!     let nns_contract = ScriptHash::from_str("50ac1c37690cc2cfc594472833cf57505d5f46de")?;
309//!     
310//!     // Check if a name is available
311//!     let available_result = client
312//!         .invoke_function(
313//!             &nns_contract,
314//!             "isAvailable".to_string(),
315//!             vec![ContractParameter::string("myname.neo".to_string())],
316//!             None,
317//!         )
318//!         .await?;
319//!     
320//!     if let Some(item) = available_result.stack.first() {
321//!         println!("Is 'myname.neo' available: {:?}", item);
322//!     }
323//!     
324//!     Ok(())
325//! }
326//! ```
327//!
328//! For more usage examples, refer to the [`examples` directory](https://github.com/R3E-Network/NeoRust/tree/master/examples) in the repository.
329//!
330//! ## Project Structure
331//!
332//! ```text
333//! NeoRust
334//! ├── examples
335//! │   ├── neo_nodes          - Examples for connecting to Neo nodes
336//! │   ├── neo_transactions   - Examples for creating and sending transactions
337//! │   ├── neo_smart_contracts - Examples for interacting with smart contracts
338//! │   ├── neo_wallets        - Examples for wallet management
339//! │   ├── neo_nep17_tokens   - Examples for working with NEP-17 tokens
340//! │   └── neo_nns            - Examples for using the Neo Name Service
341//! └── src
342//!     ├── neo_builder        - Transaction and script building utilities
343//!     ├── neo_clients        - Neo node interaction clients (RPC and WebSocket)
344//!     ├── neo_codec          - Encoding and decoding for Neo-specific data structures
345//!     ├── neo_config         - Network and client configuration management
346//!     ├── neo_contract       - Smart contract interaction abstractions
347//!     ├── neo_crypto         - Neo-specific cryptographic operations
348//!     ├── neo_protocol       - Neo network protocol implementation
349//!     ├── neo_sgx            - SGX support for secure enclave execution
350//!     ├── neo_types          - Core Neo ecosystem data types
351//!     └── neo_wallets        - Neo asset and account management
352//! ```
353//!
354//! ## Module Overview
355//!
356//! - **neo_builder**: Transaction and script building utilities.
357//!   - Transaction construction and signing
358//!   - Script building for contract calls
359//!   - Network fee calculation
360//!
361//! - **neo_clients**: Neo node interaction clients.
362//!   - HTTP, WebSocket, and IPC providers
363//!   - JSON-RPC client implementation
364//!   - Event subscription and notification handling
365//!
366//! - **neo_codec**: Encoding and decoding for Neo-specific data structures.
367//!   - Binary serialization and deserialization
368//!   - Neo VM script encoding
369//!
370//! - **neo_config**: Network and client configuration management.
371//!   - Network magic numbers
372//!   - Client settings
373//!
374//! - **neo_contract**: Smart contract interaction abstractions.
375//!   - Contract invocation and deployment
376//!   - NEP-17 token standard implementation
377//!   - Native contracts (GAS, NEO, etc.)
378//!   - Neo Name Service (NNS) support
379//!
380//! - **neo_crypto**: Neo-specific cryptographic operations.
381//!   - Key generation and management
382//!   - Signing and verification
383//!   - Hashing functions
384//!
385//! - **neo_protocol**: Neo network protocol implementation.
386//!   - Account management
387//!   - Address formats and conversions
388//!
389//! - **neo_types**: Core Neo ecosystem data types.
390//!   - Script hashes
391//!   - Contract parameters
392//!   - Block and transaction types
393//!   - NNS name types
394//!
395//! - **neo_wallets**: Neo asset and account management.
396//!   - Wallet creation and management
397//!   - NEP-6 wallet standard support
398//!   - Account import/export
399//!   - Wallet backup and recovery
400//!
401//! For detailed information, consult the documentation of each module.
402
403// Production-ready Neo N3 SDK - warnings are treated as errors in CI
404#![cfg_attr(all(feature = "sgx", target_env = "sgx"), no_std)]
405#![cfg_attr(all(feature = "sgx", target_env = "sgx"), feature(rustc_private))]
406#![allow(elided_lifetimes_in_paths, missing_docs, missing_debug_implementations)]
407#![warn(unreachable_pub)]
408#![doc(test(no_crate_inject, attr(deny(rust_2018_idioms), allow(dead_code, unused_variables))))]
409
410// SGX support (only when building for the SGX target)
411#[cfg(all(feature = "sgx", target_env = "sgx"))]
412extern crate sgx_tstd as std;
413
414// Required for no_std when targeting SGX
415#[cfg(all(feature = "sgx", target_env = "sgx"))]
416extern crate alloc;
417
418// For macro expansions only, not public API.
419#[doc(hidden)]
420#[allow(unused_extern_crates)]
421extern crate self as neo3;
422
423/// Current version of the `neo3` crate.
424pub const VERSION: &str = env!("CARGO_PKG_VERSION");
425
426// Core modules - always available
427pub mod constants;
428pub mod neo_error;
429pub mod neo_types;
430pub mod neo_utils;
431
432// All modules unconditionally available
433pub mod neo_builder;
434pub mod neo_clients;
435pub mod neo_codec;
436pub mod neo_config;
437pub mod neo_contract;
438pub mod neo_crypto;
439pub mod neo_fs;
440pub mod neo_protocol;
441#[cfg(all(feature = "sgx", target_env = "sgx"))]
442pub mod neo_sgx;
443pub mod neo_wallets;
444pub mod neo_x;
445
446// High-level SDK API (new in v1.0.x)
447pub mod sdk;
448
449// Re-exports for convenience
450#[doc(inline)]
451pub use neo_builder as builder;
452#[doc(inline)]
453pub use neo_clients as providers;
454#[doc(inline)]
455pub use neo_codec as codec;
456#[doc(inline)]
457pub use neo_config as config;
458#[doc(inline)]
459pub use neo_crypto as crypto;
460#[doc(inline)]
461pub use neo_protocol as protocol;
462#[doc(inline)]
463pub use neo_wallets as wallets;
464#[doc(inline)]
465pub use neo_x as x;
466// No need to re-export specialized modules as they're already public with their full names
467
468// Re-export common types directly in lib.rs for easy access
469pub use crate::neo_types::{
470	deserialize_address_or_script_hash,
471	deserialize_h256,
472	deserialize_h256_option,
473	deserialize_hash_map_h160_account,
474	deserialize_script_hash,
475	deserialize_script_hash_option,
476	deserialize_url_option,
477	serialize_address_or_script_hash,
478	serialize_h256,
479	serialize_h256_option,
480	serialize_hash_map_h160_account,
481	// Serialization/deserialization helpers
482	serialize_script_hash,
483	serialize_script_hash_option,
484	serialize_url_option,
485	var_size,
486	vec_to_array32,
487	Address,
488	AddressOrScriptHash,
489	// Additional types
490	Base64Encode,
491	Bytes,
492	ContractIdentifiers,
493	// Contract types
494	ContractManifest,
495	ContractParameter,
496	ContractParameterType,
497	ContractState,
498	InvocationResult,
499	// NNS types
500	NNSName,
501	NefFile,
502	OpCode,
503	OperandSize,
504	ParameterValue,
505	ScriptHash,
506	ScriptHashExtension,
507	// Additional types
508	ScryptParamsDef,
509	StackItem,
510	StringExt,
511	TypeError,
512	VMState,
513};
514
515// Add direct re-exports for commonly used serde utils
516pub use crate::neo_types::serde_with_utils::{
517	deserialize_boolean_expression, deserialize_bytes, deserialize_h160, deserialize_hardforks,
518	deserialize_hashmap_address_u256, deserialize_hashmap_u256_hashset_h256,
519	deserialize_hashmap_u256_hashset_u256, deserialize_hashmap_u256_vec_u256,
520	deserialize_hashset_u256, deserialize_map, deserialize_private_key, deserialize_public_key,
521	deserialize_public_key_option, deserialize_scopes, deserialize_vec_script_hash,
522	deserialize_vec_script_hash_option, deserialize_wildcard, serialize_boolean_expression,
523	serialize_bytes, serialize_h160, serialize_hashmap_address_u256,
524	serialize_hashmap_u256_hashset_h256, serialize_hashmap_u256_hashset_u256,
525	serialize_hashmap_u256_vec_u256, serialize_hashset_u256, serialize_map, serialize_private_key,
526	serialize_public_key, serialize_public_key_option, serialize_scopes, serialize_vec_script_hash,
527	serialize_vec_script_hash_option, serialize_wildcard,
528};
529
530// Re-export additional contract types
531pub use crate::neo_types::contract::{
532	ContractMethodToken, ContractNef, NativeContractState, NeoVMStateType,
533};
534
535// Re-export value extension trait
536pub use crate::neo_types::serde_value::ValueExtension;
537
538/// Convenient imports for commonly used types and traits.
539///
540/// This prelude module provides a single import to access the most commonly used
541/// components of the NeoRust SDK. Import it with:
542///
543/// ```rust
544/// use neo3::prelude::*;
545/// ```
546pub mod prelude;
547
548#[cfg(test)]
549mod tests {
550	use super::prelude::*;
551	use primitive_types::H160;
552	use std::{str::FromStr, sync::Arc};
553	use tokio::sync::Mutex;
554
555	use crate::{
556		builder::{AccountSigner, ScriptBuilder, TransactionBuilder},
557		neo_clients::{MockClient, MockProvider, RpcClient},
558		neo_config::TestConstants,
559		neo_protocol::{Account, AccountTrait},
560	};
561
562	#[cfg(test)]
563	#[tokio::test]
564	async fn test_create_and_send_transaction() -> Result<(), Box<dyn std::error::Error>> {
565		let (rpc_client, _mock_server) = setup_test_client().await?;
566
567		// Create accounts for the sender and recipient
568		let sender = Account::create()?;
569		let recipient = Account::create()?;
570
571		let gas_token_hash = TestConstants::GAS_TOKEN_HASH;
572
573		// Create a new TransactionBuilder
574		let mut tx_builder = TransactionBuilder::with_client(&rpc_client);
575
576		// Build the transaction
577		tx_builder
578			.set_script(Some(
579				ScriptBuilder::new()
580					.contract_call(
581						&H160::from_str(gas_token_hash)?,
582						"transfer",
583						&[
584							ContractParameter::h160(&sender.get_script_hash()),
585							ContractParameter::h160(&recipient.get_script_hash()),
586							ContractParameter::integer(1_0000_0000), // 1 GAS (8 decimals)
587							ContractParameter::any(),
588						],
589						None,
590					)
591					.map_err(|e| Box::new(e) as Box<dyn std::error::Error>)?
592					.to_bytes(),
593			))
594			.set_signers(vec![AccountSigner::called_by_entry(&sender)?.into()])
595			.map_err(|e| Box::new(e) as Box<dyn std::error::Error>)?
596			.valid_until_block(100)?; // Small mock block window
597
598		// Sign the transaction
599		let signed_tx = tx_builder.sign().await?;
600
601		assert_eq!(signed_tx.sys_fee, 30);
602		assert_eq!(signed_tx.net_fee, 1_230_610);
603
604		Ok(())
605	}
606
607	async fn setup_test_client(
608	) -> Result<(RpcClient<MockProvider>, Option<Arc<Mutex<MockClient>>>), Box<dyn std::error::Error>>
609	{
610		let mock_server = Arc::new(Mutex::new(MockClient::new().await));
611		{
612			let mut mock = mock_server.lock().await;
613			mock.mock_response_with_file_ignore_param(
614				"invokescript",
615				"invokescript_necessary_mock.json",
616			)
617			.await;
618			mock.mock_response_with_file_ignore_param(
619				"calculatenetworkfee",
620				"calculatenetworkfee.json",
621			)
622			.await;
623			mock.mock_response_ignore_param("getversion", serde_json::json!({})).await;
624			mock.mock_response_with_file_ignore_param(
625				"sendrawtransaction",
626				"sendrawtransaction.json",
627			)
628			.await;
629			mock.mount_mocks().await;
630		}
631
632		let rpc_client = {
633			let mock = mock_server.lock().await;
634			mock.into_client()
635		};
636
637		Ok((rpc_client, Some(mock_server)))
638	}
639}
640
641// Adding trait implementations for serde JSON serialization
642// These extensions will be used by the http-client feature
643pub mod extensions {
644	use serde_json::Value;
645
646	pub trait ToValue {
647		fn to_value(&self) -> Value;
648	}
649
650	impl ToValue for String {
651		fn to_value(&self) -> Value {
652			serde_json::Value::String(self.clone())
653		}
654	}
655
656	impl ToValue for &str {
657		fn to_value(&self) -> Value {
658			serde_json::Value::String((*self).to_string())
659		}
660	}
661
662	impl ToValue for u32 {
663		fn to_value(&self) -> Value {
664			serde_json::Value::Number(serde_json::Number::from(*self))
665		}
666	}
667
668	impl ToValue for i32 {
669		fn to_value(&self) -> Value {
670			serde_json::Value::Number(serde_json::Number::from(*self))
671		}
672	}
673
674	impl ToValue for bool {
675		fn to_value(&self) -> Value {
676			serde_json::Value::Bool(*self)
677		}
678	}
679}
680
681// Explicitly mark external dependencies with cfg_attr for docs.rs
682#[cfg(feature = "futures")]
683pub use futures;
684
685#[cfg(feature = "ledger")]
686pub use coins_ledger;
687
688// AWS feature is disabled in v1.0.1 due to security vulnerabilities
689// #[cfg(feature = "aws")]
690// #[cfg_attr(docsrs, doc(cfg(feature = "aws")))]
691// pub use rusoto_core;
692//
693// #[cfg(feature = "aws")]
694// #[cfg_attr(docsrs, doc(cfg(feature = "aws")))]
695// pub use rusoto_kms;