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//! 
10//! # NeoRust SDK v1.0.1
11//!
12//! A production-ready Rust SDK for the Neo N3 blockchain with enterprise-grade features.
13//!
14//! [](https://crates.io/crates/neo3)
15//! [](https://docs.rs/neo3)
16//! [](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;