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 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 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 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 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 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 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 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 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 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 let payload = &raw_txn["payload"];
127 let payload_bytes = serialize_payload_bcs(payload)?;
128 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
151pub mod address {
153
154 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 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 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 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 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 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 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 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 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 pub fn parse_type_string(type_str: &str) -> Result<Vec<u8>, String> {
250 let trimmed = type_str.trim();
251 if let Some(basic_type) = parse_basic_type(trimmed) {
253 return Ok(basic_type);
254 }
255 if let Some(generic_type) = parse_generic_type(trimmed) {
257 return Ok(generic_type);
258 }
259 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 fn parse_basic_type(type_str: &str) -> Option<Vec<u8>> {
268 let basic_types: HashMap<&str, Vec<u8>> = [
269 ("bool", vec![0x00]), ("u8", vec![0x01]), ("u64", vec![0x02]), ("u128", vec![0x03]), ("address", vec![0x04]), ("signer", vec![0x05]), ("vector", vec![0x06]), ]
277 .iter()
278 .cloned()
279 .collect();
280 basic_types.get(type_str).cloned()
281 }
282
283 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]; result.extend_from_slice(&inner_bytes);
290 return Some(result);
291 }
292 }
293 None
294 }
295
296 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]; if let Ok(address_bytes) = address_to_bytes(address) {
301 result.extend_from_slice(&address_bytes);
302 } else {
303 return None;
304 }
305 if let Some((module_name, struct_name, type_params)) =
307 parse_struct_components(remainder)
308 {
309 let module_bytes = module_name.as_bytes();
311 result.push(module_bytes.len() as u8);
312 result.extend_from_slice(module_bytes);
313 let struct_bytes = struct_name.as_bytes();
315 result.push(struct_bytes.len() as u8);
316 result.extend_from_slice(struct_bytes);
317 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(¶m_bytes);
322 } else {
323 return None;
324 }
325 }
326 return Some(result);
327 }
328 }
329 None
330 }
331
332 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 fn parse_struct_components(remainder: &str) -> Option<(String, String, Vec<String>)> {
347 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 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 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 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 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 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 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}