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
217pub mod move_type {
218    use crate::address::{address_to_bytes, verify_address_format};
219    use std::collections::HashMap;
220
221    /// Parse type string into BCS serialization format
222    pub fn parse_type_string(type_str: &str) -> Result<Vec<u8>, String> {
223        let trimmed = type_str.trim();
224        // basic types
225        if let Some(basic_type) = parse_basic_type(trimmed) {
226            return Ok(basic_type);
227        }
228        // generic types
229        if let Some(generic_type) = parse_generic_type(trimmed) {
230            return Ok(generic_type);
231        }
232        // Structure type
233        if let Some(struct_type) = parse_struct_type(trimmed) {
234            return Ok(struct_type);
235        }
236        Err(format!("Unresolved type: {:?}", type_str))
237    }
238
239    /// parsing basic types
240    fn parse_basic_type(type_str: &str) -> Option<Vec<u8>> {
241        let basic_types: HashMap<&str, Vec<u8>> = [
242            ("bool", vec![0x00]),    // bool
243            ("u8", vec![0x01]),      // u8
244            ("u64", vec![0x02]),     // u64
245            ("u128", vec![0x03]),    // u128
246            ("address", vec![0x04]), // address
247            ("signer", vec![0x05]),  // signer
248            ("vector", vec![0x06]),  // vector
249        ]
250        .iter()
251        .cloned()
252        .collect();
253        basic_types.get(type_str).cloned()
254    }
255
256    /// parse generic type
257    fn parse_generic_type(type_str: &str) -> Option<Vec<u8>> {
258        if type_str.starts_with("vector<") && type_str.ends_with('>') {
259            let inner_type = &type_str[7..type_str.len() - 1];
260            if let Ok(inner_bytes) = parse_type_string(inner_type) {
261                let mut result = vec![0x06]; // vector tag
262                result.extend_from_slice(&inner_bytes);
263                return Some(result);
264            }
265        }
266        None
267    }
268
269    /// parse struct type
270    fn parse_struct_type(type_str: &str) -> Option<Vec<u8>> {
271        if let Some((address, remainder)) = split_struct_parts(type_str) {
272            let mut result = vec![0x07]; // struct tag
273            if let Ok(address_bytes) = address_to_bytes(address) {
274                result.extend_from_slice(&address_bytes);
275            } else {
276                return None;
277            }
278            // Parsing module and structure names
279            if let Some((module_name, struct_name, type_params)) =
280                parse_struct_components(remainder)
281            {
282                // Serialization module name
283                let module_bytes = module_name.as_bytes();
284                result.push(module_bytes.len() as u8);
285                result.extend_from_slice(module_bytes);
286                // Serialized structure name
287                let struct_bytes = struct_name.as_bytes();
288                result.push(struct_bytes.len() as u8);
289                result.extend_from_slice(struct_bytes);
290                // Serialization type parameters
291                result.push(type_params.len() as u8);
292                for type_param in type_params {
293                    if let Ok(param_bytes) = parse_type_string(&type_param) {
294                        result.extend_from_slice(&param_bytes);
295                    } else {
296                        return None;
297                    }
298                }
299                return Some(result);
300            }
301        }
302        None
303    }
304
305    /// Split the address and remainder of the structure type
306    fn split_struct_parts(type_str: &str) -> Option<(&str, &str)> {
307        if let Some(pos) = type_str.find("::") {
308            let address = &type_str[..pos];
309            let remainder = &type_str[pos + 2..];
310
311            if verify_address_format(address) {
312                return Some((address, remainder));
313            }
314        }
315        None
316    }
317
318    /// Parsing structure components: module name, structure name, type parameters
319    fn parse_struct_components(remainder: &str) -> Option<(String, String, Vec<String>)> {
320        // Finding the boundaries between structure names and type parameters
321        let angle_bracket_pos = remainder.find('<');
322        let (name_part, type_params_part) = if let Some(pos) = angle_bracket_pos {
323            (&remainder[..pos], &remainder[pos..])
324        } else {
325            (remainder, "")
326        };
327        let parts: Vec<&str> = name_part.split("::").collect();
328        if parts.len() != 2 {
329            return None;
330        }
331        let module_name = parts[0].to_string();
332        let struct_name = parts[1].to_string();
333        let type_params = if !type_params_part.is_empty() {
334            parse_type_parameters(type_params_part).unwrap_or_default()
335        } else {
336            Vec::new()
337        };
338        Some((module_name, struct_name, type_params))
339    }
340
341    /// parse type parameters
342    fn parse_type_parameters(type_params_str: &str) -> Result<Vec<String>, String> {
343        if !type_params_str.starts_with('<') || !type_params_str.ends_with('>') {
344            return Err(format!(
345                "Type parameter format error: {:?}",
346                type_params_str
347            ));
348        }
349        let inner = &type_params_str[1..type_params_str.len() - 1];
350        let params: Vec<String> = inner
351            .split(',')
352            .map(|s| s.trim().to_string())
353            .filter(|s| !s.is_empty())
354            .collect();
355        Ok(params)
356    }
357
358    /// parse standard type
359    pub fn parse_standard_type(type_str: &str) -> Result<Vec<u8>, String> {
360        match type_str {
361            "bool" => Ok(vec![0x00]),
362            "u8" => Ok(vec![0x01]),
363            "u64" => Ok(vec![0x02]),
364            "u128" => Ok(vec![0x03]),
365            "address" => Ok(vec![0x04]),
366            "signer" => Ok(vec![0x05]),
367            "vector<u8>" => Ok(vec![0x06, 0x01]),
368            "vector<address>" => Ok(vec![0x06, 0x04]),
369            "0x1::string::String" => parse_struct_type(type_str)
370                .ok_or_else(|| format!("Unable to resolve standard type: {:?}", type_str)),
371            "0x1::object::Object" => parse_struct_type(type_str)
372                .ok_or_else(|| format!("Unable to resolve standard type: {:?}", type_str)),
373            "0x1::coin::Coin" => parse_struct_type(type_str)
374                .ok_or_else(|| format!("Unable to resolve standard type: {:?}", type_str)),
375            _ => parse_type_string(type_str),
376        }
377    }
378
379    /// batch parse type arguments
380    pub fn batch_parse_type_arguments(type_args: &[String]) -> Result<Vec<Vec<u8>>, String> {
381        let mut result = Vec::new();
382        for type_arg in type_args {
383            let parsed = parse_standard_type(type_arg)
384                .map_err(|e| format!("parse type arguments '{:?}' error: {:?}", type_arg, e))?;
385            result.push(parsed);
386        }
387        Ok(result)
388    }
389}