1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
use crate::errors::{ProtocolError, Result};
use bigdecimal::BigDecimal;
use nash_mpc::rust_bigint::traits::Converter;
use nash_mpc::rust_bigint::BigInt;
use sha3::{Digest, Keccak256};
use std::str::FromStr;
use std::time::{SystemTime, UNIX_EPOCH};
#[cfg(feature = "num_bigint")]
use num_traits::Num;
pub fn bigint_to_nash_sig(num: BigInt) -> String {
format!("{:0>1024}", num.to_hex())
}
pub fn bigint_to_nash_r(r: BigInt) -> String {
format!("{:0>66}", r.to_hex())
}
pub fn hash_eth_message(msg: &[u8]) -> BigInt {
const ETH_PREFIX: &[u8] = b"\x19Ethereum Signed Message:\n32";
let msg_hash =
Keccak256::digest(&[Ð_PREFIX[..], &Keccak256::digest(&msg).to_vec()].concat());
BigInt::from_bytes(&msg_hash)
}
pub fn hash_neo_message(msg: &[u8]) -> BigInt {
let msg_hash_once = sha2::Sha256::digest(msg);
let msg_hash_twice = sha2::Sha256::digest(&msg_hash_once[..]);
BigInt::from_str_radix(&hex::encode(msg_hash_twice), 16).unwrap()
}
pub fn hash_message(message: &str) -> BigInt {
let hash = sha2::Sha256::digest(message.as_bytes());
BigInt::from_str_radix(&hex::encode(hash), 16).unwrap()
}
pub fn der_encode_sig(r: &BigInt, s: &BigInt) -> Vec<u8> {
let r_bytes = der_encode_sig_value(r);
let s_bytes = der_encode_sig_value(s);
let mut der_bytes = Vec::new();
der_bytes.push(0x30);
der_bytes.push((r_bytes.len() + s_bytes.len()) as u8);
for byte in r_bytes {
der_bytes.push(byte);
}
for byte in s_bytes {
der_bytes.push(byte)
}
der_bytes
}
fn der_encode_sig_value(r_or_s: &BigInt) -> Vec<u8> {
let mut bytes = r_or_s.to_bytes();
if bytes[0] >= 0b1000_0000 {
bytes.insert(0, 0x00);
}
bytes.insert(0, bytes.len() as u8);
bytes.insert(0, 0x02);
bytes
}
pub fn current_time_as_i64() -> i64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_millis() as i64
}
pub fn decode_hexstr(hex_str: &str) -> Result<Vec<u8>> {
Ok(hex::decode(hex_str).map_err(|_| ProtocolError("Could not decode hex string"))?)
}
pub fn pad_zeros(str_num: &str, precision: u32) -> Result<String> {
let components: Vec<&str> = str_num.split('.').collect();
match components.len() {
1 => {
let mut zeros = ".".to_string();
for _ in 0..precision {
zeros += "0"
}
Ok(str_num.to_string() + &zeros)
}
2 => {
let mut zeros = "".to_string();
let existing_count = components[1].len();
if existing_count as u32 > precision {
let num_zeros_to_subtract = existing_count as u32 - precision;
let reduced_prec = &str_num[..(str_num.len() - (num_zeros_to_subtract as usize))];
Ok(reduced_prec.to_string())
} else {
for _ in 0..(precision - existing_count as u32) {
zeros += "0"
}
Ok(str_num.to_string() + &zeros)
}
}
_ => Err(ProtocolError(
"String was not a valid number for zero padding",
)),
}
}
pub fn convert_at_price(amount: &str, price: &str) -> Result<String> {
let amount_bd = BigDecimal::from_str(amount)
.map_err(|_| ProtocolError("Could not convert amount to bigdecimal"))?;
let price_bd = BigDecimal::from_str(price)
.map_err(|_| ProtocolError("Could not convert price to bigdecimal"))?;
let convert = amount_bd * price_bd.inverse();
Ok(convert.to_string())
}