velas_address_rust/
lib.rs1use basex_rs::{BaseX, Decode, Encode, BITCOIN};
14use bitcoin_hashes::sha256;
15use bitcoin_hashes::Hash;
16use hex;
17use regex::Regex;
18use std::str;
19
20fn hash_sha256(byte: &[u8]) -> String {
21 format!("{}", sha256::Hash::hash(byte))
22}
23
24pub fn eth_to_vlx(address: &str) -> Result<String, &str> {
34 if address.is_empty() {
35 return Err("Invalid address");
36 }
37
38 if !address.starts_with("0x") {
39 return Err("Invalid address");
40 }
41
42 let clear_addr = match address.get(2..address.len()) {
43 Some(addr) => addr.to_lowercase(),
44 None => return Err("Invalid address"),
45 };
46
47 let hash_big = hash_sha256(hash_sha256(clear_addr.as_bytes()).as_bytes());
48 let checksum = match hash_big.get(0..8) {
49 Some(hash) => hash,
50 None => return Err("Invalid address"),
51 };
52
53 let long_address = format!("{}{}", clear_addr, checksum);
54
55 let bytes = hex::decode(long_address).unwrap().to_vec();
56
57 let mut encode = BaseX::new(BITCOIN).encode(&bytes);
58
59 if encode.len() < 33 {
60 encode = format!("{}{}", "1".repeat(33 - encode.len()), encode);
61 }
62
63 Ok(format!("V{}", encode))
64}
65
66pub fn vlx_to_eth(address: &str) -> Result<String, &str> {
76 if address.is_empty() {
77 return Err("Invalid address");
78 }
79
80 if !address.starts_with("V") {
81 return Err("Invalid address");
82 }
83
84 let clear_addr = match address.get(1..address.len()) {
85 Some(addr) => addr,
86 None => return Err("Invalid address"),
87 };
88
89 let decode_addr = match BaseX::new(BITCOIN).decode(clear_addr.to_string()) {
90 Some(bytes) => bytes,
91 None => return Err("Invalid address"),
92 };
93
94 let hex = hex::encode(decode_addr);
95
96 let re = Regex::new(r"([0-9abcdef]+)([0-9abcdef]{8})").unwrap();
97
98 let caps = re.captures(&hex).unwrap();
99
100 if caps.len() != 3 as usize {
101 return Err("Invalid address");
102 }
103
104 let mut match_addr = &caps[1];
105
106 if match_addr.len() > 40 {
107 let len = match_addr.len() - 40;
108 if match_addr.starts_with(&"0".repeat(len)) {
109 match_addr = match match_addr.get(len..match_addr.len()) {
110 Some(addr) => addr,
111 None => return Err("Invalid address"),
112 }
113 } else {
114 return Err("Invalid address");
115 }
116 }
117
118 let hash_big = hash_sha256(hash_sha256(match_addr.as_bytes()).as_bytes());
119 let checksum = match hash_big.get(0..8) {
120 Some(hash) => hash,
121 None => return Err("Invalid address"),
122 };
123
124 if checksum != &caps[2] {
125 return Err("Invalid checksum");
126 }
127
128 Ok(format!("0x{}", match_addr))
129}
130
131#[cfg(test)]
132mod tests {
133 use super::*;
134
135 #[test]
136 fn it_works() {
137 let eth_addresses = [
138 "0x32Be343B94f860124dC4fEe278FDCBD38C102D88",
139 "0x000000000000000000000000000000000000000f",
140 "0xf000000000000000000000000000000000000000",
141 "0x0000000000000000000000000000000000000001",
142 "0x1000000000000000000000000000000000000000",
143 "0x0000000000000000000000000000000000000000",
144 "0xffffffffffffffffffffffffffffffffffffffff",
145 ];
146
147 let vlx_addresses = [
148 "V5dJeCa7bmkqmZF53TqjRbnB4fG6hxuu4f",
149 "V111111111111111111111111112jSS6vy",
150 "VNt1B3HD3MghPihCxhwMxNKRerBPPbiwvZ",
151 "V111111111111111111111111111CdXjnE",
152 "V2Tbp525fpnBRiSt4iPxXkxMyf5ZX7bGAJ",
153 "V1111111111111111111111111113iMDfC",
154 "VQLbz7JHiBTspS962RLKV8GndWFwdcRndD",
155 ];
156
157 for addr in eth_addresses.iter() {
158 let vlx_addr = eth_to_vlx(addr).unwrap();
159 let eth_addr = vlx_to_eth(&vlx_addr).unwrap();
160 assert_eq!(eth_addr.to_string(), addr.to_string().to_lowercase());
161 }
162
163 for addr in vlx_addresses.iter() {
164 let eth_addr = vlx_to_eth(addr).unwrap();
165 let vlx_addr = eth_to_vlx(ð_addr).unwrap();
166 assert_eq!(vlx_addr.to_string(), addr.to_string());
167 }
168 }
169}