| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- use crate::{
- serial::{deserialize, serialize},
- util::{NetworkName, TokenList},
- Error, Result,
- };
- use log::debug;
- use sha2::{Digest, Sha256};
- use std::str::FromStr;
- // hash the external token ID and NetworkName param.
- // if fails, change the last 4 bytes and hash it again. keep repeating until it works.
- pub fn generate_id(tkn_str: &str, network: &NetworkName) -> Result<jubjub::Fr> {
- let mut id_string = network.to_string();
- id_string.push_str(tkn_str);
- if bs58::decode(id_string.clone()).into_vec().is_err() {
- // TODO: make this an error
- debug!(target: "PARSE ID", "COULD NOT DECODE STR");
- }
- let mut data = bs58::decode(id_string).into_vec().unwrap();
- let token_id = match deserialize::<jubjub::Fr>(&data) {
- Ok(v) => v,
- Err(_) => {
- let mut counter = 0;
- loop {
- data.truncate(28);
- let serialized_counter = serialize(&counter);
- data.extend(serialized_counter.iter());
- let mut hasher = Sha256::new();
- hasher.update(&data);
- let hash = hasher.finalize();
- let token_id = deserialize::<jubjub::Fr>(&hash);
- if token_id.is_err() {
- counter += 1;
- continue;
- }
- debug!(target: "CASHIER", "DESERIALIZATION SUCCESSFUL");
- return Ok(token_id.unwrap());
- }
- }
- };
- Ok(token_id)
- }
- pub fn assign_id(network: &str, token: &str, tokenlist: TokenList) -> Result<String> {
- match NetworkName::from_str(network)? {
- NetworkName::Solana => match token.to_lowercase().as_str() {
- "solana" | "sol" => {
- let token_id = "So11111111111111111111111111111111111111112";
- Ok(token_id.to_string())
- }
- tkn => {
- // (== 44) can represent a Solana base58 token mint address
- let id = if token.len() == 44 {
- token.to_string()
- } else {
- symbol_to_id(tkn, tokenlist)?
- };
- Ok(id)
- }
- },
- NetworkName::Bitcoin => Err(Error::NetworkParseError),
- }
- }
- pub fn decimals(network: &str, token: &str, tokenlist: TokenList) -> Result<usize> {
- match NetworkName::from_str(network)? {
- NetworkName::Solana => match token {
- "solana" | "sol" => {
- let decimals = 9;
- Ok(decimals)
- }
- tkn => {
- let decimals = tokenlist.search_decimal(tkn)?;
- Ok(decimals)
- }
- },
- NetworkName::Bitcoin => Err(Error::NetworkParseError),
- }
- }
- pub fn to_apo(amount: f64, decimals: u32) -> Result<u64> {
- let apo = amount as u64 * u64::pow(10, decimals as u32);
- Ok(apo)
- }
- pub fn symbol_to_id(token: &str, tokenlist: TokenList) -> Result<String> {
- let vec: Vec<char> = token.chars().collect();
- let mut counter = 0;
- for c in vec {
- if c.is_alphabetic() {
- counter += 1;
- }
- }
- if counter == token.len() {
- tokenlist.search_id(token)
- } else {
- Ok(token.to_string())
- }
- }
- //pub fn decode_base10(amount: &str, decimals: usize) -> Result<u64> {
- // const RADIX: u32 = 10;
- //
- // let mut input_str = amount.to_string();
- //
- // // remove the decimal point
- // let mut amount: String = match input_str.find(".") {
- // Some(v) => {
- // input_str.remove(v);
- // input_str
- // }
- // None => input_str,
- // };
- //
- // // only digits should remain:
- // for c in amount.chars() {
- // if c.is_digit(RADIX) == false {
- // // TODO: Make this an error
- // println!("Amount is not valid digits!")
- // }
- // }
- //
- // // add digits to the end if there are too few
- // if amount.len() < decimals {
- // loop {
- // amount.push('0');
- //
- // if amount.len() == decimals {
- // break;
- // }
- // continue;
- // }
- // }
- //
- // // remove digits from the end if there are too many
- // if amount.len() > decimals {
- // loop {
- // amount.pop();
- //
- // if amount.len() == decimals {
- // break;
- // }
- // continue;
- // }
- // }
- //
- // println!("Resized amount: {}", amount);
- //
- // let amount_vec: Vec<u32> = vec![0; decimals];
- //
- // // convert to an integer
- // for i in amount.chars() {
- // let digit = i.to_digit(RADIX).unwrap();
- // amount_vec.push(digit);
- // }
- //
- // let amount: u64 = amount_vec.drain();
- // Ok(amount)
- //}
- mod tests {
- #[test]
- fn decode_base10() {
- const RADIX: u32 = 10;
- // TODO: this number varies per token
- let decimal_places = 10;
- let input = "2.5";
- println!("Initial input: {}", input);
- let mut input_str = input.to_string();
- // remove the decimal point
- let mut amount: String = match input_str.find(".") {
- Some(v) => {
- input_str.remove(v);
- input_str
- }
- None => {
- print!("Number isn't a float");
- input_str
- }
- };
- println!("Removed decimal point: {}", amount);
- // only digits should remain:
- for c in amount.chars() {
- if c.is_digit(RADIX) == false {
- println!("Amount is not valid digits!")
- }
- }
- // add digits to the end if there are too few
- if amount.len() < decimal_places {
- loop {
- amount.push('0');
- if amount.len() == decimal_places {
- break;
- }
- continue;
- }
- }
- // remove digits from the end if there are too many
- if amount.len() > decimal_places {
- loop {
- amount.pop();
- if amount.len() == decimal_places {
- break;
- }
- continue;
- }
- }
- println!("Resized amount: {}", amount);
- // convert to an integer
- for i in amount.chars() {
- let digit = i.to_digit(RADIX).unwrap();
- println!("Converted to integer: {}", digit);
- let u = u64::from(digit);
- }
- }
- #[test]
- fn encode_base10() {
- let input = 100000000;
- println!("Original input: {}", input);
- let mut input_str = input.to_string();
- input_str.insert(1, '.');
- let amount = input_str.trim_end_matches('0');
- let amount = if amount.ends_with('.') == true {
- let amount = amount.trim_end_matches('.');
- amount
- } else {
- amount
- };
- println!("Encoded output: {}", amount);
- }
- }
|