neo3/neo_types/
mod.rs

1//! # Neo Types (v0.4.1)
2//!
3//! Core data types for the Neo N3 blockchain.
4//!
5//! ## Overview
6//!
7//! The neo_types module provides fundamental data types and structures for working with
8//! the Neo N3 blockchain. It includes:
9//!
10//! - Address and ScriptHash types for identifying accounts and contracts
11//! - Contract-related types (parameters, manifests, NEF files)
12//! - Neo Name Service (NNS) types
13//! - Numeric types with blockchain-specific operations
14//! - Serialization and deserialization utilities
15//! - Stack item representations for VM operations
16//! - Blockchain-specific enumerations (OpCode, VMState)
17//!
18//! This module forms the type foundation for the entire SDK, providing the core data structures
19//! that represent Neo N3 blockchain concepts.
20//!
21//! ## Examples
22//!
23//! ### Working with Neo N3 addresses and script hashes
24//!
25//! ```rust,no_run
26//! use neo3::prelude::*;
27//! use std::str::FromStr;
28//!
29//! // Create a script hash from a string
30//! let script_hash = ScriptHash::from_str("0xd2a4cff31913016155e38e474a2c06d08be276cf").unwrap();
31//! println!("Script hash: {}", script_hash);
32//!
33//! // Convert between address and script hash
34//! let address = script_hash.to_address();
35//! println!("Address: {}", address);
36//!
37//! let recovered_hash = ScriptHash::from_str(&address).unwrap();
38//! assert_eq!(script_hash, recovered_hash);
39//! ```
40//!
41//! ### Working with contract parameters
42//!
43//! ```rust,no_run
44//! use neo3::prelude::*;
45//! use std::str::FromStr;
46//!
47//! // Create different types of contract parameters
48//! let string_param = ContractParameter::string("Hello, Neo!".to_string());
49//! let integer_param = ContractParameter::integer(42);
50//! let bool_param = ContractParameter::bool(true);
51//!
52//! // Create a parameter array for a contract invocation
53//! let params = vec![string_param, integer_param, bool_param];
54//! ```
55//!
56//! ### Working with stack items
57//!
58//! ```ignore
59//! use neo3::neo_types::StackItem;
60//! use serde_json::json;
61//!
62//! // Create stack items of various types
63//! let int_item = StackItem::Integer { value: 123 };
64//! let bool_item = StackItem::Boolean { value: true };
65//! let bytes_item = StackItem::new_byte_string(b"Neo".to_vec());
66//!
67//! // Convert between stack items and JSON values
68//! let json_value = int_item.to_json_value();
69//! assert_eq!(json_value, json!(123));
70//! ```
71
72use crate::neo_crypto::utils::FromBase64String;
73use base64::{engine::general_purpose, Engine};
74pub use log::*;
75use primitive_types::H256;
76use serde_derive::{Deserialize, Serialize};
77
78// Re-export everything from these modules
79pub use address::*;
80pub use address_or_scripthash::*;
81pub use block::*;
82pub use bytes::*;
83pub use contract::*;
84pub use error::*;
85pub use nns::*;
86pub use numeric::*;
87pub use op_code::*;
88pub use path_or_string::*;
89pub use plugin_type::*;
90pub mod script_hash;
91pub use script_hash::{ScriptHash, ScriptHashExtension};
92pub use serde_value::*;
93pub use serde_with_utils::*;
94pub use stack_item::*;
95pub use string::*;
96pub use syncing::*;
97pub use tx_pool::*;
98pub use url_session::*;
99pub use util::*;
100pub use vm_state::*;
101
102// Make modules public for direct access
103pub mod contract;
104pub mod error;
105pub mod nns;
106pub mod serde_value;
107pub mod serde_with_utils;
108
109mod address;
110mod address_or_scripthash;
111mod block;
112mod bytes;
113mod numeric;
114mod op_code;
115mod path_or_string;
116mod plugin_type;
117mod stack_item;
118mod string;
119mod syncing;
120mod tx_pool;
121mod url_session;
122mod util;
123mod vm_state;
124
125pub type Byte = u8;
126pub type Bytes = Vec<u8>;
127pub type TxHash = H256;
128
129pub trait ExternBase64 {
130	fn to_base64(&self) -> String;
131}
132
133impl ExternBase64 for String {
134	fn to_base64(&self) -> String {
135		general_purpose::STANDARD.encode(self.as_bytes())
136	}
137}
138
139// ScryptParams
140#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
141pub struct ScryptParamsDef {
142	#[serde(rename = "n")]
143	pub log_n: u8,
144	#[serde(rename = "r")]
145	pub r: u32,
146	#[serde(rename = "p")]
147	pub p: u32,
148}
149
150impl Default for ScryptParamsDef {
151	fn default() -> Self {
152		Self { log_n: 14, r: 8, p: 8 }
153	}
154}
155
156// Extend Vec<u8> with a to_base64 method
157pub trait Base64Encode {
158	fn to_base64(&self) -> String;
159}
160
161impl Base64Encode for Vec<u8> {
162	fn to_base64(&self) -> String {
163		base64::encode(&self)
164	}
165}
166
167impl Base64Encode for &[u8] {
168	fn to_base64(&self) -> String {
169		base64::encode(&self)
170	}
171}
172
173impl Base64Encode for String {
174	fn to_base64(&self) -> String {
175		match hex::decode(self) {
176			Ok(bytes) => general_purpose::STANDARD.encode(&bytes),
177			Err(_) => {
178				// If hex decoding fails, return an empty string
179				// Professional error handling with logging for debugging
180				eprintln!("Failed to decode hex string: {}", self);
181				String::new()
182			},
183		}
184	}
185}
186
187// pub fn secret_key_to_script_hash(secret_key: &Secp256r1PrivateKey) -> ScriptHash {
188// 	let public_key = secret_key.to_public_key();
189// 	public_key_to_script_hash(&public_key)
190// }
191
192// pub fn public_key_to_script_hash(pubkey: &Secp256r1PublicKey) -> ScriptHash {
193// 	raw_public_key_to_script_hash(&pubkey.get_encoded(true)[1..])
194// }
195//
196// pub fn raw_public_key_to_script_hash<T: AsRef<[u8]>>(pubkey: T) -> ScriptHash {
197// 	let pubkey = pubkey.as_ref();
198// 	let script = format!(
199// 		"{}21{}{}{}{}",
200// 		OpCode::PushData1.to_string(),
201// 		"03",
202// 		pubkey.to_hex(),
203// 		OpCode::Syscall.to_string(),
204// 		InteropService::SystemCryptoCheckSig.hash()
205// 	)
206// 	.from_hex()
207// 	.unwrap();
208// 	let mut script = script.sha256_ripemd160();
209// 	script.reverse();
210// 	ScriptHash::from_slice(&script)
211// }
212
213pub fn to_checksum(addr: &ScriptHash, chain_id: Option<u8>) -> String {
214	// if !addr.is_valid_address(){
215	// 	panic!("invalid address");
216	// }
217	let prefixed_addr = match chain_id {
218		Some(chain_id) => format!("{chain_id}0x{addr:x}"),
219		None => format!("{addr:x}"),
220	};
221	let hash = hex::encode(prefixed_addr);
222	let hash = hash.as_bytes();
223
224	let addr_hex = hex::encode(addr.as_bytes());
225	let addr_hex = addr_hex.as_bytes();
226
227	addr_hex.iter().zip(hash).fold("0x".to_owned(), |mut encoded, (addr, hash)| {
228		encoded.push(if *hash >= 56 {
229			addr.to_ascii_uppercase() as char
230		} else {
231			addr.to_ascii_lowercase() as char
232		});
233		encoded
234	})
235}
236
237#[cfg(test)]
238mod tests {
239	use crate::neo_crypto::utils::FromBase64String;
240	use hex;
241
242	use super::*;
243
244	#[test]
245	fn test_base64_encode_bytes() {
246		let input = hex::decode("150c14242dbf5e2f6ac2568b59b7822278d571b75f17be0c14242dbf5e2f6ac2568b59b7822278d571b75f17be13c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b5238").unwrap();
247		let expected = "FQwUJC2/Xi9qwlaLWbeCInjVcbdfF74MFCQtv14vasJWi1m3giJ41XG3Xxe+E8AMCHRyYW5zZmVyDBSJdyDYzXb08Aq/o3wO3YicII/em0FifVtSOA==";
248
249		let encoded = input.to_base64();
250
251		assert_eq!(encoded, expected);
252	}
253
254	#[test]
255	fn test_base64_decode() {
256		let encoded = "FQwUJC2/Xi9qwlaLWbeCInjVcbdfF74MFCQtv14vasJWi1m3giJ41XG3Xxe+E8AMCHRyYW5zZmVyDBSJdyDYzXb08Aq/o3wO3YicII/em0FifVtSOA==";
257		let expected = "150c14242dbf5e2f6ac2568b59b7822278d571b75f17be0c14242dbf5e2f6ac2568b59b7822278d571b75f17be13c00c087472616e736665720c14897720d8cd76f4f00abfa37c0edd889c208fde9b41627d5b5238";
258
259		let decoded = encoded.from_base64_string().unwrap();
260		let decoded_hex = hex::encode(decoded);
261
262		assert_eq!(decoded_hex, expected);
263	}
264}
265
266// Re-export serialization functions from serde_with_utils
267pub use serde_with_utils::{
268	deserialize_h160, deserialize_h256, deserialize_script_hash, deserialize_u256, deserialize_u64,
269	deserialize_vec_h256, deserialize_vec_u256, deserialize_wildcard, serialize_h160,
270	serialize_h256, serialize_script_hash, serialize_u256, serialize_u64, serialize_vec_h256,
271	serialize_vec_u256, serialize_wildcard,
272};
273
274// Re-export ValueExtension trait
275pub use serde_value::ValueExtension;
276
277// Re-export address types
278pub use address::NameOrAddress;
279
280// Other re-exports
281pub use string::StringExt;
282pub use vm_state::VMState;