nash_protocol/types/blockchain/
mod.rs1pub mod btc;
6pub mod eth;
7pub mod neo;
8
9use crate::errors::{ProtocolError, Result};
10use crate::types::{Asset, Blockchain};
11use bigdecimal::{BigDecimal, ToPrimitive};
12use std::convert::TryFrom;
13
14pub fn bigdecimal_to_nash_u64(num: &BigDecimal, precision: u32) -> Result<u64> {
17 let num = bigdecimal_to_nash_prec(num, precision);
18 let multiplier = BigDecimal::from(u64::pow(10, precision));
19 (num * multiplier)
20 .with_scale(0)
21 .to_u64()
22 .ok_or(ProtocolError("Result does not fit into u64."))
23}
24
25pub fn nash_u64_to_bigdecimal(num: u64, precision: u32) -> BigDecimal {
26 let num = BigDecimal::from(num);
27 let divider = BigDecimal::from(u64::pow(10, precision));
28 num / divider
29}
30
31pub fn bigdecimal_to_nash_prec(num: &BigDecimal, precision: u32) -> BigDecimal {
34 let scale = BigDecimal::from(u64::pow(10, precision));
35 let scaled = (num * &scale).with_scale(0);
36 &scaled / &scale
37}
38
39#[derive(Clone, Debug, PartialEq)]
45pub enum Prefix {
46 SyncState,
47 FillOrder,
48 Deposit,
49 Withdrawal,
50}
51
52impl Prefix {
53 pub fn to_bytes(&self) -> [u8; 1] {
54 match self {
55 Self::SyncState => [0x00],
56 Self::FillOrder => [0x01],
57 Self::Deposit => [0x02],
58 Self::Withdrawal => [0x03],
59 }
60 }
61 pub fn from_bytes(bytes: [u8; 1]) -> Result<Self> {
62 match bytes {
63 [0x00] => Ok(Self::SyncState),
64 [0x01] => Ok(Self::FillOrder),
65 [0x02] => Ok(Self::Deposit),
66 [0x03] => Ok(Self::Withdrawal),
67 _ => Err(ProtocolError("Invalid prefix byte")),
68 }
69 }
70}
71
72#[derive(Clone, Debug, PartialEq)]
73pub enum Address {
74 Ethereum(eth::Address),
75 Bitcoin(btc::Address),
76 NEO(neo::Address),
77}
78
79impl Address {
80 pub fn new(chain: Blockchain, hex_str: &str) -> Result<Self> {
81 match chain {
82 Blockchain::Bitcoin => Ok(Self::Bitcoin(btc::Address::new(hex_str)?)),
83 Blockchain::Ethereum => Ok(Self::Ethereum(eth::Address::new(hex_str)?)),
84 Blockchain::NEO => Ok(Self::NEO(neo::Address::new(hex_str)?)),
85 }
86 }
87}
88
89impl TryFrom<Address> for eth::Address {
90 type Error = ProtocolError;
91
92 fn try_from(address: Address) -> Result<Self> {
93 match address {
94 Address::Ethereum(address) => Ok(address),
95 _ => Err(ProtocolError(
96 "Tried to convert from something that is not an ETH address",
97 )),
98 }
99 }
100}
101
102impl TryFrom<Address> for neo::Address {
103 type Error = ProtocolError;
104
105 fn try_from(address: Address) -> Result<Self> {
106 match address {
107 Address::NEO(address) => Ok(address),
108 _ => Err(ProtocolError(
109 "Tried to convert from something that is not an NEO address",
110 )),
111 }
112 }
113}
114
115impl TryFrom<Address> for btc::Address {
116 type Error = ProtocolError;
117
118 fn try_from(address: Address) -> Result<Self> {
119 match address {
120 Address::Bitcoin(address) => Ok(address),
121 _ => Err(ProtocolError(
122 "Tried to convert from something that is not an ETH address",
123 )),
124 }
125 }
126}
127
128#[derive(Clone, Debug, PartialEq)]
132pub enum AssetOrCrosschain {
133 Asset(Asset),
134 Crosschain,
135}
136
137#[derive(Clone, Debug, PartialEq)]
138pub enum PublicKey {
139 Bitcoin(btc::PublicKey),
140 Ethereum(eth::PublicKey),
141 NEO(neo::PublicKey),
142}
143
144impl PublicKey {
145 pub fn new(chain: Blockchain, hex_str: &str) -> Result<Self> {
146 Ok(match chain {
147 Blockchain::Bitcoin => Self::Bitcoin(btc::PublicKey::new(hex_str)?),
148 Blockchain::Ethereum => Self::Ethereum(eth::PublicKey::new(hex_str)?),
149 Blockchain::NEO => Self::NEO(neo::PublicKey::new(hex_str)?),
150 })
151 }
152
153 pub fn to_hex_str(&self) -> String {
154 match self {
155 Self::Bitcoin(key) => key.to_hex(),
156 Self::Ethereum(key) => key.to_hex(),
157 Self::NEO(key) => key.to_hex(),
158 }
159 }
160
161 pub fn to_address(&self) -> Result<Address> {
162 Ok(match self {
163 Self::Bitcoin(key) => Address::Bitcoin(key.to_address()?),
164 Self::Ethereum(key) => Address::Ethereum(key.to_address()),
165 Self::NEO(key) => Address::NEO(key.to_address()),
166 })
167 }
168}
169
170impl TryFrom<PublicKey> for eth::PublicKey {
171 type Error = ProtocolError;
172
173 fn try_from(address: PublicKey) -> Result<Self> {
174 match address {
175 PublicKey::Ethereum(pub_key) => Ok(pub_key),
176 _ => Err(ProtocolError(
177 "Tried to convert from something that is not an ETH public key",
178 )),
179 }
180 }
181}
182
183impl TryFrom<PublicKey> for neo::PublicKey {
184 type Error = ProtocolError;
185
186 fn try_from(address: PublicKey) -> Result<Self> {
187 match address {
188 PublicKey::NEO(pub_key) => Ok(pub_key),
189 _ => Err(ProtocolError(
190 "Tried to convert from something that is not an NEO public key",
191 )),
192 }
193 }
194}
195
196impl TryFrom<PublicKey> for btc::PublicKey {
197 type Error = ProtocolError;
198
199 fn try_from(address: PublicKey) -> Result<Self> {
200 match address {
201 PublicKey::Bitcoin(pub_key) => Ok(pub_key),
202 _ => Err(ProtocolError(
203 "Tried to convert from something that is not an BTC public key",
204 )),
205 }
206 }
207}
208
209#[derive(PartialEq)]
211pub enum MovementType {
212 Deposit,
213 Withdrawal,
214}
215
216impl MovementType {
217 pub fn to_prefix(&self) -> Prefix {
219 match self {
220 Self::Deposit => Prefix::Deposit,
221 Self::Withdrawal => Prefix::Withdrawal,
222 }
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use super::{bigdecimal_to_nash_prec, bigdecimal_to_nash_u64};
229 use bigdecimal::BigDecimal;
230 use std::str::FromStr;
231
232 #[test]
233 fn nash_precision() {
234 let num = BigDecimal::from_str("1.55555").unwrap();
235 let prec_num = bigdecimal_to_nash_prec(&num, 4);
236 assert_eq!(prec_num.to_string(), "1.5555");
237 }
238
239 #[test]
240 fn bd_test() {
241 let bd_1 = BigDecimal::from_str("0.03451").unwrap();
242 let bd_2 = BigDecimal::from_str("0.03454").unwrap();
243 println!("Good: {}", bd_1.inverse());
244 println!("Bad: {}", bd_2.inverse());
245 let step1_1 = bigdecimal_to_nash_prec(&bd_1.inverse(), 8);
246 let step1_2 = bigdecimal_to_nash_prec(&bd_2.inverse(), 8);
247 println!("Good: {}", step1_1);
248 println!("Bad: {}", step1_2);
249 let converted_1 = bigdecimal_to_nash_u64(&bd_1.inverse(), 8).unwrap();
250 let converted_2 = bigdecimal_to_nash_u64(&bd_2.inverse(), 8).unwrap();
251 println!("Good: {}", converted_1);
252 println!("Bad: {}", converted_2);
253 }
254}