aptos_network_tool/
lib.rs

1#[derive(serde::Serialize)]
2pub struct EntryFunctionPayload {
3    pub module_address: Vec<u8>,
4    pub module_name: Vec<u8>,
5    pub function_name: Vec<u8>,
6    pub type_arguments: Vec<Vec<u8>>,
7    pub arguments: Vec<Vec<u8>>,
8}
9
10#[derive(serde::Serialize)]
11pub struct RawTransactionForSigning {
12    pub sender: Vec<u8>,
13    pub sequence_number: u64,
14    pub payload: Vec<u8>,
15    pub max_gas_amount: u64,
16    pub gas_unit_price: u64,
17    pub expiration_timestamp_secs: u64,
18    pub chain_id: u8,
19}
20
21pub mod signature {
22    use serde_json::Value;
23
24    use crate::{EntryFunctionPayload, RawTransactionForSigning, move_type::parse_standard_type};
25
26    /// serialize payload bcs model
27    fn serialize_payload_bcs(payload: &Value) -> Result<Vec<u8>, String> {
28        let payload_type = payload["type"]
29            .as_str()
30            .ok_or("Missing payload_type field")?;
31        match payload_type {
32            "entry_function_payload" => impl_serialize_payload_bcs(payload),
33            _ => Err(format!("Not a payload type {:?}", payload_type)),
34        }
35    }
36
37    /// serialize payload implement bcs model
38    fn impl_serialize_payload_bcs(payload: &Value) -> Result<Vec<u8>, String> {
39        let function = payload["function"]
40            .as_str()
41            .ok_or("Missing function field")?;
42        let type_arguments = payload["type_arguments"]
43            .as_array()
44            .ok_or("Missing type_arguments field")?;
45        let arguments = payload["arguments"]
46            .as_array()
47            .ok_or("Missing arguments field")?;
48        // handle function address、module、function name
49        let parts: Vec<&str> = function.split("::").collect();
50        if parts.len() != 3 {
51            return Err("Function format is incorrect, address::module::function".to_string());
52        }
53        let module_address = hex::decode(parts[0].trim_start_matches("0x"))
54            .map_err(|e| format!("module address decode error: {:?}", e))?;
55        let module_name = parts[1].as_bytes().to_vec();
56        let function_name = parts[2].as_bytes().to_vec();
57        // serialized type args
58        let mut serialized_type_args = Vec::new();
59        for type_arg in type_arguments {
60            let type_str = type_arg.as_str().ok_or("type args is not string")?;
61            // parse move type
62            let move_type = parse_standard_type(type_str)
63                .map_err(|e| format!("parse move type error: {:?}", e))
64                .unwrap();
65            serialized_type_args.push(move_type);
66        }
67        // serialized args
68        let mut serialized_args = Vec::new();
69        for arg in arguments {
70            let arg_bytes = serialize_arg_bcs(arg)?;
71            serialized_args.push(arg_bytes);
72        }
73        // create EntryFunctionPayload
74        let entry_function = EntryFunctionPayload {
75            module_address,
76            module_name,
77            function_name,
78            type_arguments: serialized_type_args,
79            arguments: serialized_args,
80        };
81        bcs::to_bytes(&entry_function).map_err(|e| format!("EntryFunction BCS 序列化失败: {}", e))
82    }
83
84    /// serialize argument bcs
85    fn serialize_arg_bcs(arg: &Value) -> Result<Vec<u8>, String> {
86        match arg {
87            Value::String(s) => {
88                if s.starts_with("0x") {
89                    hex::decode(s.trim_start_matches("0x"))
90                        .map_err(|e| format!("Address parameter decoding failed: {:?}", e))
91                } else {
92                    Ok(s.as_bytes().to_vec())
93                }
94            }
95            Value::Number(n) => {
96                if let Some(i) = n.as_u64() {
97                    bcs::to_bytes(&i)
98                        .map_err(|e| format!("Serialization of numeric parameters failed: {}", e))
99                } else {
100                    Err("Unsupported value type".to_string())
101                }
102            }
103            _ => Err(format!("Unsupported parameter type: {:?}", arg)),
104        }
105    }
106
107    /// serialize transaction and sign
108    pub fn serialize_transaction_and_sign(raw_txn: &Value) -> Result<Vec<u8>, String> {
109        let sender = raw_txn["sender"].as_str().ok_or("Missing sender field")?;
110        let sequence_number = raw_txn["sequence_number"]
111            .as_str()
112            .ok_or("Missing sequence_number field")?;
113        let max_gas_amount = raw_txn["max_gas_amount"]
114            .as_str()
115            .ok_or("Missing max_gas_amount field")?;
116        let gas_unit_price = raw_txn["gas_unit_price"]
117            .as_str()
118            .ok_or("Missing gas_unit_price field")?;
119        let expiration_timestamp_secs = raw_txn["expiration_timestamp_secs"]
120            .as_str()
121            .ok_or("Missing expiration_timestamp_secs field")?;
122        let chain_id = raw_txn["chain_id"]
123            .as_u64()
124            .ok_or("Missing chain_id field")? as u8;
125        // parse payload
126        let payload = &raw_txn["payload"];
127        let payload_bytes = serialize_payload_bcs(payload)?;
128        // build RawTransactionForSigning
129        let raw_txn_data = RawTransactionForSigning {
130            sender: hex::decode(sender.trim_start_matches("0x"))
131                .map_err(|e| format!("sender decode error: {:?}", e))?,
132            sequence_number: sequence_number
133                .parse::<u64>()
134                .map_err(|e| format!("sequence_number parse error: {:?}", e))?,
135            payload: payload_bytes,
136            max_gas_amount: max_gas_amount
137                .parse::<u64>()
138                .map_err(|e| format!("max_gas_amount parse error: {:?}", e))?,
139            gas_unit_price: gas_unit_price
140                .parse::<u64>()
141                .map_err(|e| format!("gas_unit_price parse error: {:?}", e))?,
142            expiration_timestamp_secs: expiration_timestamp_secs
143                .parse::<u64>()
144                .map_err(|e| format!("expiration_timestamp_secs parse error: {:?}", e))?,
145            chain_id,
146        };
147        Ok(bcs::to_bytes(&raw_txn_data).unwrap())
148    }
149}
150
151/// address related tool module
152pub mod address {
153
154    /// bytes to address (0x)
155    pub fn bytes_to_address(address_bytes: &[u8]) -> Result<String, String> {
156        if address_bytes.len() != 32 {
157            return Err(format!("The address byte array length must be 32"));
158        }
159        let hex_string = hex::encode(address_bytes);
160        Ok(format!("0x{}", hex_string))
161    }
162
163    /// address to bytes
164    pub fn address_to_bytes(address: &str) -> Result<[u8; 32], String> {
165        let address_clean = address.trim_start_matches("0x");
166        if address_clean.len() != 64 {
167            return Err(format!("The address string must be 64 characters long"));
168        }
169        let bytes =
170            hex::decode(address_clean).map_err(|e| format!("Address decoding failed: {:?}", e))?;
171        let mut result = [0u8; 32];
172        result.copy_from_slice(&bytes);
173        Ok(result)
174    }
175
176    /// address string to vec
177    pub fn address_to_vec(address: &str) -> Result<Vec<u8>, String> {
178        let address_clean = address.trim_start_matches("0x");
179        hex::decode(address_clean).map_err(|e| format!("Address decoding failed: {:}", e))
180    }
181
182    /// verify address format
183    pub fn verify_address_format(address: &str) -> bool {
184        let address_clean = address.trim_start_matches("0x");
185        if address_clean.len() != 64 {
186            return false;
187        }
188        hex::decode(address_clean).is_ok()
189    }
190
191    /// public key to auth key
192    pub fn public_key_to_auth_key(public_key: &[u8]) -> Result<String, String> {
193        use sha3::{Digest, Sha3_256};
194        if public_key.len() != 32 {
195            return Err(format!("The public key must be 32 bytes long"));
196        }
197        let mut hasher = Sha3_256::new();
198        hasher.update(public_key);
199        hasher.update(&[0u8]);
200        let result = hasher.finalize();
201        Ok(format!("0x{}", hex::encode(result)))
202    }
203
204    /// private key to address
205    pub fn private_key_to_address(private_key: &[u8]) -> Result<String, String> {
206        use ring::signature::{Ed25519KeyPair, KeyPair};
207        if private_key.len() != 32 {
208            return Err(format!("The public key must be 32 bytes long"));
209        }
210        let keypair = Ed25519KeyPair::from_seed_unchecked(private_key)
211            .map_err(|e| format!("Key pair generation failed: {:?}", e))?;
212        let public_key = keypair.public_key().as_ref();
213        public_key_to_auth_key(public_key)
214    }
215
216    /// Standardized address format
217    pub fn normalize_address(address: &str) -> String {
218        if address.starts_with("0x") {
219            address.to_lowercase()
220        } else {
221            format!("0x{}", address.to_lowercase())
222        }
223    }
224
225    /// Verify address validity
226    pub fn is_valid_address(address: &str) -> bool {
227        if !address.starts_with("0x") {
228            return false;
229        }
230        let hex_part = &address[2..];
231        hex_part.len() == 64 && hex_part.chars().all(|c| c.is_ascii_hexdigit())
232    }
233
234    /// show short address
235    pub fn show_short_address(address: &str) -> String {
236        if address.len() <= 10 {
237            address.to_string()
238        } else {
239            format!("{}...{}", &address[0..6], &address[address.len() - 4..])
240        }
241    }
242}
243
244pub mod move_type {
245    use crate::address::{address_to_bytes, verify_address_format};
246    use std::collections::HashMap;
247
248    /// Parse type string into BCS serialization format
249    pub fn parse_type_string(type_str: &str) -> Result<Vec<u8>, String> {
250        let trimmed = type_str.trim();
251        // basic types
252        if let Some(basic_type) = parse_basic_type(trimmed) {
253            return Ok(basic_type);
254        }
255        // generic types
256        if let Some(generic_type) = parse_generic_type(trimmed) {
257            return Ok(generic_type);
258        }
259        // Structure type
260        if let Some(struct_type) = parse_struct_type(trimmed) {
261            return Ok(struct_type);
262        }
263        Err(format!("Unresolved type: {:?}", type_str))
264    }
265
266    /// parsing basic types
267    fn parse_basic_type(type_str: &str) -> Option<Vec<u8>> {
268        let basic_types: HashMap<&str, Vec<u8>> = [
269            ("bool", vec![0x00]),    // bool
270            ("u8", vec![0x01]),      // u8
271            ("u64", vec![0x02]),     // u64
272            ("u128", vec![0x03]),    // u128
273            ("address", vec![0x04]), // address
274            ("signer", vec![0x05]),  // signer
275            ("vector", vec![0x06]),  // vector
276        ]
277        .iter()
278        .cloned()
279        .collect();
280        basic_types.get(type_str).cloned()
281    }
282
283    /// parse generic type
284    fn parse_generic_type(type_str: &str) -> Option<Vec<u8>> {
285        if type_str.starts_with("vector<") && type_str.ends_with('>') {
286            let inner_type = &type_str[7..type_str.len() - 1];
287            if let Ok(inner_bytes) = parse_type_string(inner_type) {
288                let mut result = vec![0x06]; // vector tag
289                result.extend_from_slice(&inner_bytes);
290                return Some(result);
291            }
292        }
293        None
294    }
295
296    /// parse struct type
297    fn parse_struct_type(type_str: &str) -> Option<Vec<u8>> {
298        if let Some((address, remainder)) = split_struct_parts(type_str) {
299            let mut result = vec![0x07]; // struct tag
300            if let Ok(address_bytes) = address_to_bytes(address) {
301                result.extend_from_slice(&address_bytes);
302            } else {
303                return None;
304            }
305            // Parsing module and structure names
306            if let Some((module_name, struct_name, type_params)) =
307                parse_struct_components(remainder)
308            {
309                // Serialization module name
310                let module_bytes = module_name.as_bytes();
311                result.push(module_bytes.len() as u8);
312                result.extend_from_slice(module_bytes);
313                // Serialized structure name
314                let struct_bytes = struct_name.as_bytes();
315                result.push(struct_bytes.len() as u8);
316                result.extend_from_slice(struct_bytes);
317                // Serialization type parameters
318                result.push(type_params.len() as u8);
319                for type_param in type_params {
320                    if let Ok(param_bytes) = parse_type_string(&type_param) {
321                        result.extend_from_slice(&param_bytes);
322                    } else {
323                        return None;
324                    }
325                }
326                return Some(result);
327            }
328        }
329        None
330    }
331
332    /// Split the address and remainder of the structure type
333    fn split_struct_parts(type_str: &str) -> Option<(&str, &str)> {
334        if let Some(pos) = type_str.find("::") {
335            let address = &type_str[..pos];
336            let remainder = &type_str[pos + 2..];
337
338            if verify_address_format(address) {
339                return Some((address, remainder));
340            }
341        }
342        None
343    }
344
345    /// Parsing structure components: module name, structure name, type parameters
346    fn parse_struct_components(remainder: &str) -> Option<(String, String, Vec<String>)> {
347        // Finding the boundaries between structure names and type parameters
348        let angle_bracket_pos = remainder.find('<');
349        let (name_part, type_params_part) = if let Some(pos) = angle_bracket_pos {
350            (&remainder[..pos], &remainder[pos..])
351        } else {
352            (remainder, "")
353        };
354        let parts: Vec<&str> = name_part.split("::").collect();
355        if parts.len() != 2 {
356            return None;
357        }
358        let module_name = parts[0].to_string();
359        let struct_name = parts[1].to_string();
360        let type_params = if !type_params_part.is_empty() {
361            parse_type_parameters(type_params_part).unwrap_or_default()
362        } else {
363            Vec::new()
364        };
365        Some((module_name, struct_name, type_params))
366    }
367
368    /// parse type parameters
369    fn parse_type_parameters(type_params_str: &str) -> Result<Vec<String>, String> {
370        if !type_params_str.starts_with('<') || !type_params_str.ends_with('>') {
371            return Err(format!(
372                "Type parameter format error: {:?}",
373                type_params_str
374            ));
375        }
376        let inner = &type_params_str[1..type_params_str.len() - 1];
377        let params: Vec<String> = inner
378            .split(',')
379            .map(|s| s.trim().to_string())
380            .filter(|s| !s.is_empty())
381            .collect();
382        Ok(params)
383    }
384
385    /// parse standard type
386    pub fn parse_standard_type(type_str: &str) -> Result<Vec<u8>, String> {
387        match type_str {
388            "bool" => Ok(vec![0x00]),
389            "u8" => Ok(vec![0x01]),
390            "u64" => Ok(vec![0x02]),
391            "u128" => Ok(vec![0x03]),
392            "address" => Ok(vec![0x04]),
393            "signer" => Ok(vec![0x05]),
394            "vector<u8>" => Ok(vec![0x06, 0x01]),
395            "vector<address>" => Ok(vec![0x06, 0x04]),
396            "0x1::string::String" => parse_struct_type(type_str)
397                .ok_or_else(|| format!("Unable to resolve standard type: {:?}", type_str)),
398            "0x1::object::Object" => parse_struct_type(type_str)
399                .ok_or_else(|| format!("Unable to resolve standard type: {:?}", type_str)),
400            "0x1::coin::Coin" => parse_struct_type(type_str)
401                .ok_or_else(|| format!("Unable to resolve standard type: {:?}", type_str)),
402            _ => parse_type_string(type_str),
403        }
404    }
405
406    /// batch parse type arguments
407    pub fn batch_parse_type_arguments(type_args: &[String]) -> Result<Vec<Vec<u8>>, String> {
408        let mut result = Vec::new();
409        for type_arg in type_args {
410            let parsed = parse_standard_type(type_arg)
411                .map_err(|e| format!("parse type arguments '{:?}' error: {:?}", type_arg, e))?;
412            result.push(parsed);
413        }
414        Ok(result)
415    }
416}
417
418pub mod codec {
419    use serde_json::Value;
420
421    /// bcs encode
422    pub fn bcs_encode<T: serde::Serialize>(value: &T) -> Result<Vec<u8>, String> {
423        bcs::to_bytes(value).map_err(|e| format!("BCS encoding failed: {}", e))
424    }
425
426    /// bcs decode
427    pub fn bcs_decode<T: serde::de::DeserializeOwned>(bytes: &[u8]) -> Result<T, String> {
428        bcs::from_bytes(bytes).map_err(|e| format!("BCS decoding failed: {}", e))
429    }
430
431    /// encode move arguments
432    pub fn encode_move_arguments(args: &[Value]) -> Result<Vec<Vec<u8>>, String> {
433        let mut encoded = Vec::new();
434        for arg in args {
435            if let Some(str_val) = arg.as_str() {
436                encoded.push(str_val.as_bytes().to_vec());
437            } else {
438                return Err("Only string arguments are supported".to_string());
439            }
440        }
441        Ok(encoded)
442    }
443}