neo3/
lib.rs

1#![allow(warnings)]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3
4//! ![Neo Logo](https://neo.org/images/neo-logo/NEO-logo.svg)
5//! # NeoRust SDK v0.4.1
6//!
7//! A comprehensive Rust library for building applications on the Neo N3 blockchain ecosystem.
8//!
9//! [![Crates.io](https://img.shields.io/crates/v/neo3.svg)](https://crates.io/crates/neo3)
10//! [![Documentation](https://docs.rs/neo3/badge.svg)](https://docs.rs/neo3)
11//!
12//! ## Features
13//!
14//! This crate provides several feature flags to customize functionality:
15//!
16//! - **futures**: Enables async/futures support for asynchronous blockchain operations. This is recommended
17//!   for most applications that need to interact with the Neo blockchain without blocking.
18//!
19//! - **ledger**: Enables hardware wallet support via Ledger devices. When enabled, you can use Ledger
20//!   hardware wallets for transaction signing and key management. This feature provides an additional
21//!   security layer by keeping private keys on dedicated hardware.
22//!
23//! - **aws**: ⚠️ **DISABLED in v0.4.1** due to security vulnerabilities in rusoto dependencies.
24//!   Will be re-enabled in a future version with modern AWS SDK. For AWS KMS integration,
25//!   please use v0.3.0 or wait for the next major release with updated AWS dependencies.
26//!
27//! To enable specific features in your project, modify your `Cargo.toml` as follows:
28//!
29//! ```toml
30//! [dependencies]
31//! neo3 = { version = "0.4.1", features = ["futures", "ledger"] }
32//! ```
33//!
34//! You can disable default features with:
35//!
36//! ```toml
37//! neo3 = { version = "0.4.1", default-features = false, features = ["futures"] }
38//! ```
39//!
40//! ## Overview
41//!
42//! NeoRust is a complete SDK designed to make Neo N3 blockchain development in Rust
43//! intuitive, type-safe, and productive. The library provides full support for all
44//! Neo N3 features and follows Rust best practices for reliability and performance.
45//!
46//! ## Core Modules
47//!
48//! NeoRust is organized into specialized modules, each handling specific aspects of Neo N3:
49//!
50//! - [**neo_builder**](neo_builder): Transaction construction and script building
51//! - [**neo_clients**](neo_clients): Neo node interaction and RPC client implementations
52//! - [**neo_codec**](neo_codec): Serialization and deserialization of Neo data structures
53//! - [**neo_config**](neo_config): Configuration for networks and client settings
54//! - [**neo_contract**](neo_contract): Smart contract interaction and token standards
55//! - [**neo_crypto**](neo_crypto): Cryptographic primitives and operations
56//! - [**neo_error**](neo_error): Unified error handling
57//! - [**neo_fs**](neo_fs): NeoFS distributed storage system integration
58//! - [**neo_protocol**](neo_protocol): Core blockchain protocol implementations
59//! - [**neo_types**](neo_types): Core data types and primitives for Neo N3
60//! - [**neo_utils**](neo_utils): General utility functions
61//! - [**neo_wallets**](neo_wallets): Wallet management for Neo N3
62//! - [**neo_x**](neo_x): Neo X EVM compatibility layer
63//!
64//! ## Quick Start
65//!
66//! Import all essential types and traits using the `prelude`:
67//!
68//! ```rust
69//! use neo3::prelude::*;
70//! ```
71//!
72//! ## Complete Example
73//!
74//! Here's a comprehensive example showcasing common operations with the NeoRust SDK:
75//!
76//! ```no_run
77//! use neo3::neo_protocol::{Account, AccountTrait};
78//! use neo3::neo_clients::{HttpProvider, RpcClient, APITrait};
79//!
80//! async fn neo_example() -> Result<(), Box<dyn std::error::Error>> {
81//!     // Connect to Neo TestNet
82//!     let provider = HttpProvider::new("https://testnet1.neo.org:443")?;
83//!     let client = RpcClient::new(provider);
84//!     
85//!     // Get basic blockchain information
86//!     let block_height = client.get_block_count().await?;
87//!     println!("Connected to Neo TestNet at height: {}", block_height);
88//!     
89//!     // Create a new wallet account
90//!     let account = Account::create()?;
91//!     println!("New account created:");
92//!     println!("  Address:     {}", account.get_address());
93//!     println!("  Script Hash: {}", account.get_script_hash());
94//!     
95//!     // Get version information
96//!     let version = client.get_version().await?;
97//!     println!("Node version: {}", version.user_agent);
98//!     
99//!     Ok(())
100//! }
101//! ```
102//!
103//! ## Usage Examples
104//!
105//! ### Connecting to a Neo N3 node
106//!
107//! ```no_run
108//! use neo3::neo_clients::{HttpProvider, RpcClient, APITrait};
109//!
110//! #[tokio::main]
111//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
112//!     // Connect to Neo N3 MainNet
113//!     let provider = HttpProvider::new("https://mainnet1.neo.org:443")?;
114//!     let client = RpcClient::new(provider);
115//!     
116//!     // Get basic blockchain information
117//!     let block_count = client.get_block_count().await?;
118//!     println!("Current block count: {}", block_count);
119//!     
120//!     let version = client.get_version().await?;
121//!     println!("Node version: {}", version.user_agent);
122//!     
123//!     Ok(())
124//! }
125//! ```
126//!
127//! ### Creating and sending a transaction
128//!
129//! ```no_run
130//! use neo3::neo_clients::{HttpProvider, RpcClient, APITrait};
131//! use neo3::neo_protocol::{Account, AccountTrait};
132//! use neo3::neo_types::{ScriptHash, ContractParameter, ScriptHashExtension};
133//! use neo3::neo_builder::{ScriptBuilder, TransactionBuilder, AccountSigner};
134//! use std::str::FromStr;
135//!
136//! #[tokio::main]
137//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
138//!     // Initialize the JSON-RPC provider
139//!     let provider = HttpProvider::new("https://testnet1.neo.org:443")?;
140//!     let client = RpcClient::new(provider);
141//!
142//!     // Create accounts for the sender and recipient
143//!     let sender = Account::from_wif("YOUR_SENDER_WIF_HERE")?;
144//!     let recipient = ScriptHash::from_address("NbTiM6h8r99kpRtb428XcsUk1TzKed2gTc")?;
145//!
146//!     // Get the GAS token contract
147//!     let gas_token_hash = ScriptHash::from_str("d2a4cff31913016155e38e474a2c06d08be276cf")?;
148//!     
149//!     // Build the transaction using the ScriptBuilder
150//!     let script = ScriptBuilder::new()
151//!         .contract_call(
152//!             &gas_token_hash,
153//!             "transfer",
154//!             &[
155//!                 ContractParameter::h160(&sender.get_script_hash()),
156//!                 ContractParameter::h160(&recipient),
157//!                 ContractParameter::integer(1_0000_0000), // 1 GAS (8 decimals)
158//!                 ContractParameter::any(),
159//!             ],
160//!             None,
161//!         )?
162//!         .to_bytes();
163//!     
164//!     // Create and configure the transaction
165//!     let mut tx_builder = TransactionBuilder::with_client(&client);
166//!     tx_builder
167//!         .set_script(Some(script))
168//!         .set_signers(vec![AccountSigner::called_by_entry(&sender)?.into()])?
169//!         .valid_until_block(client.get_block_count().await? + 5760)?; // Valid for ~1 day
170//!
171//!     // Sign the transaction
172//!     let mut tx = tx_builder.sign().await?;
173//!
174//!     // Send the transaction
175//!     let result = tx.send_tx().await?;
176//!     println!("Transaction sent: {}", result.hash);
177//!
178//!     // Wait for the transaction to be confirmed
179//!     println!("Waiting for confirmation...");
180//!     tx.track_tx(10).await?;
181//!     println!("Transaction confirmed!");
182//!
183//!     // Get the application log
184//!     let app_log = tx.get_application_log(&client).await?;
185//!     println!("Application log: {:?}", app_log);
186//!
187//!     Ok(())
188//! }
189//! ```
190//!
191//! ### Interacting with a smart contract
192//!
193//! ```no_run
194//! use neo3::neo_clients::{HttpProvider, RpcClient, APITrait};
195//! use std::str::FromStr;
196//!
197//! #[tokio::main]
198//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
199//!     // Connect to Neo N3 TestNet
200//!     let provider = HttpProvider::new("https://testnet1.neo.org:443")?;
201//!     let client = RpcClient::new(provider);
202//!     
203//!     // Get basic blockchain information
204//!     let block_count = client.get_block_count().await?;
205//!     println!("Block count: {}", block_count);
206//!     
207//!     // Get version information
208//!     let version = client.get_version().await?;
209//!     println!("Node version: {}", version.user_agent);
210//!     
211//!     Ok(())
212//! }
213//! ```
214//!
215//! ### Working with NEP-17 tokens
216//!
217//! ```no_run
218//! use neo3::neo_clients::{HttpProvider, RpcClient, APITrait};
219//! use neo3::neo_protocol::{Account, AccountTrait};
220//! use std::str::FromStr;
221//!
222//! #[tokio::main]
223//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
224//!     // Connect to Neo N3 TestNet
225//!     let provider = HttpProvider::new("https://testnet1.neo.org:443")?;
226//!     let client = RpcClient::new(provider);
227//!     
228//!     // Create an account
229//!     let account = Account::from_wif("YOUR_PRIVATE_KEY_WIF_HERE")?;
230//!     
231//!     // Get account information
232//!     println!("Account address: {}", account.get_address());
233//!     println!("Account script hash: {}", account.get_script_hash());
234//!     
235//!     Ok(())
236//! }
237//! ```
238//!
239//! ### Using the Neo Name Service (NNS)
240//!
241//! ```no_run
242//! use neo3::neo_clients::{HttpProvider, RpcClient, APITrait};
243//!
244//! #[tokio::main]
245//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
246//!     // Connect to Neo N3 TestNet
247//!     let provider = HttpProvider::new("https://testnet1.neo.org:443")?;
248//!     let client = RpcClient::new(provider);
249//!     
250//!     // Get blockchain information
251//!     let block_count = client.get_block_count().await?;
252//!     println!("Current block count: {}", block_count);
253//!     
254//!     Ok(())
255//! }
256//! ```
257//!
258//! For more usage examples, refer to the [`examples` directory](https://github.com/R3E-Network/NeoRust/tree/master/examples) in the repository.
259//!
260//! ## Project Structure
261//!
262//! ```text
263//! NeoRust
264//! ├── examples
265//! │   ├── neo_nodes          - Examples for connecting to Neo nodes
266//! │   ├── neo_transactions   - Examples for creating and sending transactions
267//! │   ├── neo_smart_contracts - Examples for interacting with smart contracts
268//! │   ├── neo_wallets        - Examples for wallet management
269//! │   ├── neo_nep17_tokens   - Examples for working with NEP-17 tokens
270//! │   └── neo_nns            - Examples for using the Neo Name Service
271//! └── src
272//!     ├── neo_builder        - Transaction and script building utilities
273//!     ├── neo_clients        - Neo node interaction clients (RPC and WebSocket)
274//!     ├── neo_codec          - Encoding and decoding for Neo-specific data structures
275//!     ├── neo_config         - Network and client configuration management
276//!     ├── neo_contract       - Smart contract interaction abstractions
277//!     ├── neo_crypto         - Neo-specific cryptographic operations
278//!     ├── neo_protocol       - Neo network protocol implementation
279//!     ├── neo_types          - Core Neo ecosystem data types
280//!     └── neo_wallets        - Neo asset and account management
281//! ```
282//!
283//! ## Module Overview
284//!
285//! - **neo_builder**: Transaction and script building utilities.
286//!   - Transaction construction and signing
287//!   - Script building for contract calls
288//!   - Network fee calculation
289//!
290//! - **neo_clients**: Neo node interaction clients.
291//!   - HTTP, WebSocket, and IPC providers
292//!   - JSON-RPC client implementation
293//!   - Event subscription and notification handling
294//!
295//! - **neo_codec**: Encoding and decoding for Neo-specific data structures.
296//!   - Binary serialization and deserialization
297//!   - Neo VM script encoding
298//!
299//! - **neo_config**: Network and client configuration management.
300//!   - Network magic numbers
301//!   - Client settings
302//!
303//! - **neo_contract**: Smart contract interaction abstractions.
304//!   - Contract invocation and deployment
305//!   - NEP-17 token standard implementation
306//!   - Native contracts (GAS, NEO, etc.)
307//!   - Neo Name Service (NNS) support
308//!
309//! - **neo_crypto**: Neo-specific cryptographic operations.
310//!   - Key generation and management
311//!   - Signing and verification
312//!   - Hashing functions
313//!
314//! - **neo_protocol**: Neo network protocol implementation.
315//!   - Account management
316//!   - Address formats and conversions
317//!
318//! - **neo_types**: Core Neo ecosystem data types.
319//!   - Script hashes
320//!   - Contract parameters
321//!   - Block and transaction types
322//!   - NNS name types
323//!
324//! - **neo_wallets**: Neo asset and account management.
325//!   - Wallet creation and management
326//!   - NEP-6 wallet standard support
327//!   - Account import/export
328//!   - Wallet backup and recovery
329//!
330//! For detailed information, consult the documentation of each module.
331
332#![warn(missing_debug_implementations, missing_docs, rust_2018_idioms, unreachable_pub)]
333// Only enable doc_cfg feature on nightly builds or when explicitly building docs
334#![cfg_attr(all(feature = "nightly", docsrs), feature(doc_cfg))]
335#![doc(test(no_crate_inject, attr(deny(rust_2018_idioms), allow(dead_code, unused_variables))))]
336
337// For macro expansions only, not public API.
338#[doc(hidden)]
339#[allow(unused_extern_crates)]
340extern crate self as neo3;
341
342// Core modules - always available
343pub mod neo_error;
344pub mod neo_types;
345pub mod neo_utils;
346
347// All modules unconditionally available
348pub mod neo_builder;
349pub mod neo_clients;
350pub mod neo_codec;
351pub mod neo_config;
352pub mod neo_contract;
353pub mod neo_crypto;
354pub mod neo_fs;
355pub mod neo_protocol;
356pub mod neo_wallets;
357pub mod neo_x;
358
359// Re-exports for convenience
360#[doc(inline)]
361pub use neo_builder as builder;
362#[doc(inline)]
363pub use neo_clients as providers;
364#[doc(inline)]
365pub use neo_codec as codec;
366#[doc(inline)]
367pub use neo_config as config;
368#[doc(inline)]
369pub use neo_crypto as crypto;
370#[doc(inline)]
371pub use neo_protocol as protocol;
372#[doc(inline)]
373pub use neo_wallets as wallets;
374#[doc(inline)]
375pub use neo_x as x;
376// No need to re-export specialized modules as they're already public with their full names
377
378// Re-export common types directly in lib.rs for easy access
379pub use crate::neo_types::{
380	deserialize_address_or_script_hash,
381	deserialize_h256,
382	deserialize_h256_option,
383	deserialize_hash_map_h160_account,
384	deserialize_script_hash,
385	deserialize_script_hash_option,
386	deserialize_url_option,
387	serialize_address_or_script_hash,
388	serialize_h256,
389	serialize_h256_option,
390	serialize_hash_map_h160_account,
391	// Serialization/deserialization helpers
392	serialize_script_hash,
393	serialize_script_hash_option,
394	serialize_url_option,
395	var_size,
396	vec_to_array32,
397	Address,
398	AddressOrScriptHash,
399	// Additional types
400	Base64Encode,
401	Bytes,
402	ContractIdentifiers,
403	// Contract types
404	ContractManifest,
405	ContractParameter,
406	ContractParameterType,
407	ContractState,
408	InvocationResult,
409	// NNS types
410	NNSName,
411	NefFile,
412	OpCode,
413	OperandSize,
414	ParameterValue,
415	ScriptHash,
416	ScriptHashExtension,
417	// Additional types
418	ScryptParamsDef,
419	StackItem,
420	StringExt,
421	TypeError,
422	VMState,
423};
424
425// Add direct re-exports for commonly used serde utils
426pub use crate::neo_types::serde_with_utils::{
427	deserialize_boolean_expression, deserialize_bytes, deserialize_h160, deserialize_hardforks,
428	deserialize_hashmap_address_u256, deserialize_hashmap_u256_hashset_h256,
429	deserialize_hashmap_u256_hashset_u256, deserialize_hashmap_u256_vec_u256,
430	deserialize_hashset_u256, deserialize_map, deserialize_private_key, deserialize_public_key,
431	deserialize_public_key_option, deserialize_scopes, deserialize_vec_script_hash,
432	deserialize_vec_script_hash_option, deserialize_wildcard, serialize_boolean_expression,
433	serialize_bytes, serialize_h160, serialize_hashmap_address_u256,
434	serialize_hashmap_u256_hashset_h256, serialize_hashmap_u256_hashset_u256,
435	serialize_hashmap_u256_vec_u256, serialize_hashset_u256, serialize_map, serialize_private_key,
436	serialize_public_key, serialize_public_key_option, serialize_scopes, serialize_vec_script_hash,
437	serialize_vec_script_hash_option, serialize_wildcard,
438};
439
440// Re-export additional contract types
441pub use crate::neo_types::contract::{
442	ContractMethodToken, ContractNef, NativeContractState, NeoVMStateType,
443};
444
445// Re-export value extension trait
446pub use crate::neo_types::serde_value::ValueExtension;
447
448/// Convenient imports for commonly used types and traits.
449///
450/// This prelude module provides a single import to access the most commonly used
451/// components of the NeoRust SDK. Import it with:
452///
453/// ```rust
454/// use neo3::prelude::*;
455/// ```
456pub mod prelude;
457
458#[cfg(all(test))]
459mod tests {
460	use super::prelude::*;
461	use primitive_types::H160;
462	use std::str::FromStr;
463
464	use tokio;
465
466	use crate::{
467		builder::{AccountSigner, ScriptBuilder, TransactionBuilder},
468		neo_clients::{APITrait, HttpProvider, RpcClient},
469		neo_protocol::{Account, AccountTrait},
470	};
471	use url::Url;
472
473	#[cfg(all(test))]
474	#[tokio::test]
475	#[ignore] // Ignoring this test as it requires a live Neo N3 node and real tokens
476	async fn test_create_and_send_transaction() -> Result<(), Box<dyn std::error::Error>> {
477		// Initialize the JSON-RPC provider - using TestNet for safer testing
478		let http_provider = HttpProvider::new("https://testnet1.neo.org:443")?;
479		let rpc_client = RpcClient::new(http_provider);
480
481		// Create accounts for the sender and recipient
482		let sender = Account::from_wif("L1WMhxazScMhUrdv34JqQb1HFSQmWeN2Kpc1R9JGKwL7CDNP21uR")?;
483		let recipient = Account::from_address("NbTiM6h8r99kpRtb428XcsUk1TzKed2gTc")?;
484
485		// Use the correct GAS token hash for Neo N3 TestNet
486		let gas_token_hash = "d2a4cff31913016155e38e474a2c06d08be276cf"; // GAS token on Neo N3
487
488		// Create a new TransactionBuilder
489		let mut tx_builder = TransactionBuilder::with_client(&rpc_client);
490
491		// Build the transaction
492		tx_builder
493			.set_script(Some(
494				ScriptBuilder::new()
495					.contract_call(
496						&H160::from_str(gas_token_hash)?,
497						"transfer",
498						&[
499							ContractParameter::h160(&sender.get_script_hash()),
500							ContractParameter::h160(&recipient.get_script_hash()),
501							ContractParameter::integer(1_0000_0000), // 1 GAS (8 decimals)
502							ContractParameter::any(),
503						],
504						None,
505					)
506					.map_err(|e| Box::new(e) as Box<dyn std::error::Error>)?
507					.to_bytes(),
508			))
509			.set_signers(vec![AccountSigner::called_by_entry(&sender)?.into()])
510			.map_err(|e| Box::new(e) as Box<dyn std::error::Error>)?
511			.valid_until_block(rpc_client.get_block_count().await? + 5760)?; // Valid for ~1 day
512
513		// Sign the transaction
514		let mut signed_tx = tx_builder.sign().await?;
515
516		// For testing purposes, we'll just verify that we can create and sign the transaction
517		// without actually sending it to the network
518		println!("Transaction created and signed successfully");
519		println!("Transaction size: {} bytes", signed_tx.size());
520		println!("System fee: {} GAS", signed_tx.sys_fee as f64 / 100_000_000.0);
521		println!("Network fee: {} GAS", signed_tx.net_fee as f64 / 100_000_000.0);
522
523		Ok(())
524	}
525}
526
527// Adding trait implementations for serde JSON serialization
528// These extensions will be used by the http-client feature
529pub mod extensions {
530	use serde_json::{Result as JsonResult, Value};
531
532	pub trait ToValue {
533		fn to_value(&self) -> Value;
534	}
535
536	impl ToValue for String {
537		fn to_value(&self) -> Value {
538			serde_json::Value::String(self.clone())
539		}
540	}
541
542	impl ToValue for &str {
543		fn to_value(&self) -> Value {
544			serde_json::Value::String((*self).to_string())
545		}
546	}
547
548	impl ToValue for u32 {
549		fn to_value(&self) -> Value {
550			serde_json::Value::Number(serde_json::Number::from(*self))
551		}
552	}
553
554	impl ToValue for i32 {
555		fn to_value(&self) -> Value {
556			serde_json::Value::Number(serde_json::Number::from(*self))
557		}
558	}
559
560	impl ToValue for bool {
561		fn to_value(&self) -> Value {
562			serde_json::Value::Bool(*self)
563		}
564	}
565}
566
567// Explicitly mark external dependencies with cfg_attr for docs.rs
568#[cfg(feature = "futures")]
569#[cfg_attr(docsrs, doc(cfg(feature = "futures")))]
570pub use futures;
571
572#[cfg(feature = "ledger")]
573#[cfg_attr(docsrs, doc(cfg(feature = "ledger")))]
574pub use coins_ledger;
575
576// AWS feature is disabled in v0.4.1 due to security vulnerabilities
577// #[cfg(feature = "aws")]
578// #[cfg_attr(docsrs, doc(cfg(feature = "aws")))]
579// pub use rusoto_core;
580//
581// #[cfg(feature = "aws")]
582// #[cfg_attr(docsrs, doc(cfg(feature = "aws")))]
583// pub use rusoto_kms;