diff --git a/src/bin/cashierd.rs b/src/bin/cashierd.rs index 52f20a3df..9ef19d6ff 100644 --- a/src/bin/cashierd.rs +++ b/src/bin/cashierd.rs @@ -20,8 +20,8 @@ use drk::{ rpcserver::{listen_and_serve, RequestHandler, RpcServerConfig}, }, serial::{deserialize, serialize}, - service::{bridge, bridge::Bridge, NetworkName}, - util::{expand_path, generate_id, join_config_path}, + service::{bridge, bridge::Bridge}, + util::{expand_path, generate_id, join_config_path, NetworkName}, wallet::{CashierDb, WalletDb}, Error, Result, }; @@ -392,9 +392,7 @@ impl Cashierd { let main_keypair: Keypair; - let main_keypairs = self - .cashier_wallet - .get_main_keys(&NetworkName::Solana)?; + let main_keypairs = self.cashier_wallet.get_main_keys(&NetworkName::Solana)?; if main_keypairs.is_empty() { main_keypair = Keypair::new(); @@ -416,9 +414,8 @@ impl Cashierd { // NOTE bitcoin is not implemented yet //let _main_keypair: BitcoinKeys; - let _main_keypairs = self - .cashier_wallet - .get_main_keys(&NetworkName::Bitcoin)?; + let _main_keypairs = + self.cashier_wallet.get_main_keys(&NetworkName::Bitcoin)?; // if main_keypairs.is_empty() { // //main_keypair = BitcoinKeys::new(bitcoin::network::constants::Network::Testnet)?; // } else { diff --git a/src/bin/darkfid.rs b/src/bin/darkfid.rs index a6f1fa290..cd29b870d 100644 --- a/src/bin/darkfid.rs +++ b/src/bin/darkfid.rs @@ -5,7 +5,6 @@ use serde_json::{json, Value}; use async_std::sync::{Arc, Mutex}; use std::path::PathBuf; -use std::str::FromStr; //use std::sync::Arc; use drk::{ @@ -18,17 +17,15 @@ use drk::{ rpcserver::{listen_and_serve, RequestHandler, RpcServerConfig}, }, serial::{deserialize, serialize}, - service::NetworkName, - util::{expand_path, generate_id, join_config_path}, + util::{expand_path, join_config_path, parse_network, parse_wrapped_token, search_id}, wallet::WalletDb, - Error, Result, + Result, }; #[derive(Clone)] struct Darkfid { config: DarkfidConfig, wallet: Arc, - tokenlist: Value, client: Arc>, } @@ -65,9 +62,7 @@ impl Darkfid { config.wallet_password.clone(), )?; debug!(target: "DARKFID", "INIT WALLET WITH PATH {}", config.wallet_path); - // TODO: FIXME - let file_contents = std::fs::read_to_string("token/solanatokenlist.json")?; - let tokenlist: Value = serde_json::from_str(&file_contents)?; + let rocks = Rocks::new(expand_path(&config.database_path.clone())?.as_path())?; let client = Client::new( @@ -87,7 +82,6 @@ impl Darkfid { Ok(Self { config, wallet, - tokenlist, client, }) } @@ -153,8 +147,8 @@ impl Darkfid { let symbol = symbol.unwrap(); let result: Result = async { - let token_id = self.search_id(symbol)?; - Ok(token_id) + let token_id = search_id(symbol)?; + Ok(json!(token_id)) } .await; @@ -164,20 +158,6 @@ impl Darkfid { } } - fn search_id(&self, symbol: &str) -> Result { - debug!(target: "DARKFID", "SEARCHING FOR {}", symbol); - let tokens = self.tokenlist["tokens"] - .as_array() - .ok_or_else(|| Error::TokenParseError)?; - for item in tokens { - if item["symbol"] == symbol.to_uppercase() { - let address = item["address"].clone(); - return Ok(address); - } - } - unreachable!(); - } - // --> {""method": "features", "params": []} // <-- {"result": { "network": ["btc", "sol"] } } async fn features(&self, id: Value, _params: Value) -> JsonResult { @@ -229,7 +209,7 @@ impl Darkfid { let network = network.as_str().unwrap(); - let token_id = match self.parse_network(&network, &token) { + let token_id = match parse_network(&network, &token) { Ok(t) => t, Err(_e) => { debug!(target: "DARKFID", "TOKEN ID IS ERR"); @@ -348,7 +328,7 @@ impl Darkfid { let amount = amount.as_f64().unwrap(); let result: Result<()> = async { - let token_id = self.parse_wrapped_token(token)?; + let token_id = parse_wrapped_token(token)?; let address = bs58::decode(&address).into_vec()?; let address: jubjub::SubgroupPoint = deserialize(&address)?; self.client @@ -365,75 +345,6 @@ impl Darkfid { Err(err) => JsonResult::Err(jsonerr(InternalError, Some(err.to_string()), json!(id))), } } - - fn parse_wrapped_token(&self, token: &str) -> Result { - match token.to_lowercase().as_str() { - "sol" => { - let id = "So11111111111111111111111111111111111111112"; - let token_id = generate_id(id)?; - Ok(token_id) - } - "btc" => Err(Error::TokenParseError), - tkn => { - let id = self.symbol_to_id(tkn)?; - let token_id = generate_id(id.as_str().unwrap())?; - Ok(token_id) - } - } - } - - fn parse_network(&self, network: &str, token: &str) -> Result { - match NetworkName::from_str(network)? { - NetworkName::Solana => match token.to_lowercase().as_str() { - "solana" | "sol" => { - let token_id = "So11111111111111111111111111111111111111112"; - Ok(json!(token_id)) - } - tkn => { - let id = self.symbol_to_id(tkn)?; - Ok(id) - } - }, - NetworkName::Bitcoin => Err(Error::NetworkParseError), - } - } - - // BTC has 8 decimals - // SOL uses conversion function soltolamport() - // or there are decimals in the token info - // TODO: how to organize these functions more logically w less repetition? - fn parse_params(&self, network: &str, token: &str, amount: u64 ) -> Result { - match NetworkName::from_str(network)? { - NetworkName::Solana => match token { - "solana" | "sol" => { - let token_id = "So11111111111111111111111111111111111111112"; - let amount_in_apo: u64 = amount * 10 ^ 8; - Ok(json![(token_id, amount_in_apo)]) - } - tkn => { - let token_id = self.symbol_to_id(tkn)?; - let amount_in_apo: u64 = amount * 10 ^ 8; - Ok(json![(token_id, amount_in_apo)]) - } - }, - NetworkName::Bitcoin => Err(Error::NetworkParseError), - } - } - - fn symbol_to_id(&self, token: &str) -> Result { - let vec: Vec = token.chars().collect(); - let mut counter = 0; - for c in vec { - if c.is_alphabetic() { - counter += 1; - } - } - if counter == token.len() { - self.search_id(token) - } else { - Ok(json!(token)) - } - } } #[async_std::main] diff --git a/src/bin/sol-test.rs b/src/bin/sol-test.rs index 3d90af61e..13c0af29c 100644 --- a/src/bin/sol-test.rs +++ b/src/bin/sol-test.rs @@ -22,7 +22,7 @@ async fn run() -> Result<()> { println!("main keypair {:?}", main_keypair.to_bytes()); println!("main pubkey {}", main_keypair.pubkey().to_string()); - let network = drk::service::NetworkName::Solana; + let network = drk::util::NetworkName::Solana; let sol_client = SolClient::new(serialize(&main_keypair), "devnet").await?; diff --git a/src/service/bridge.rs b/src/service/bridge.rs index 0be56c247..9166e6b3e 100644 --- a/src/service/bridge.rs +++ b/src/service/bridge.rs @@ -1,5 +1,5 @@ use crate::{Error, Result}; -use super::NetworkName; +use crate::util::NetworkName; use async_trait::async_trait; use futures::stream::FuturesUnordered; diff --git a/src/service/mod.rs b/src/service/mod.rs index c6e51a479..a955db5ef 100644 --- a/src/service/mod.rs +++ b/src/service/mod.rs @@ -15,53 +15,5 @@ pub use sol::{SolClient, SolFailed, SolResult}; pub use gateway::{GatewayClient, GatewayService, GatewaySlabsSubscriber}; -use crate::serial::{Decodable, Encodable}; -use crate::Result; -use std::str::FromStr; -#[derive(Debug, PartialEq, Eq, Hash, Clone)] -pub enum NetworkName { - Solana, - Bitcoin, -} -impl std::fmt::Display for NetworkName { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Solana => { - write!(f, "Solana") - } - Self::Bitcoin => { - write!(f, "Bitcoin") - } - } - } -} - -impl FromStr for NetworkName { - type Err = crate::Error; - - fn from_str(s: &str) -> std::result::Result { - match s.to_lowercase().as_str() { - "sol" | "solana" => Ok(NetworkName::Solana), - "btc" | "bitcoin" => Ok(NetworkName::Bitcoin), - _ => Err(crate::Error::NotSupportedNetwork), - } - } -} - -impl Encodable for NetworkName { - fn encode(&self, s: S) -> Result { - let name = self.to_string(); - let len = name.encode(s)?; - Ok(len) - } -} - -impl Decodable for NetworkName { - fn decode(mut d: D) -> Result { - let name: String = Decodable::decode(&mut d)?; - let name = NetworkName::from_str(&name)?; - Ok(name) - } -} diff --git a/src/util.rs b/src/util.rs index 052c5ad45..08ceb460d 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,11 +1,13 @@ +use crate::{ + serial::{deserialize, serialize, Decodable, Encodable}, + Error, Result, +}; + use log::debug; use sha2::{Digest, Sha256}; -use std::path::{Path, PathBuf}; -use crate::{ - serial::{deserialize, serialize}, - Result, -}; +use std::path::{Path, PathBuf}; +use std::str::FromStr; pub fn expand_path(path: &str) -> Result { let ret: PathBuf; @@ -37,6 +39,54 @@ pub fn join_config_path(file: &Path) -> Result { Ok(path) } + +#[derive(Debug, PartialEq, Eq, Hash, Clone)] +pub enum NetworkName { + Solana, + Bitcoin, +} + +impl std::fmt::Display for NetworkName { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Solana => { + write!(f, "Solana") + } + Self::Bitcoin => { + write!(f, "Bitcoin") + } + } + } +} + +impl FromStr for NetworkName { + type Err = crate::Error; + + fn from_str(s: &str) -> std::result::Result { + match s.to_lowercase().as_str() { + "sol" | "solana" => Ok(NetworkName::Solana), + "btc" | "bitcoin" => Ok(NetworkName::Bitcoin), + _ => Err(crate::Error::NotSupportedNetwork), + } + } +} + +impl Encodable for NetworkName { + fn encode(&self, s: S) -> Result { + let name = self.to_string(); + let len = name.encode(s)?; + Ok(len) + } +} + +impl Decodable for NetworkName { + fn decode(mut d: D) -> Result { + let name: String = Decodable::decode(&mut d)?; + let name = NetworkName::from_str(&name)?; + Ok(name) + } +} + // here we hash the alphanumeric token ID. if it fails, we change the last 4 bytes and hash it // again, and keep repeating until it works. pub fn generate_id(tkn_str: &str) -> Result { @@ -69,6 +119,92 @@ pub fn generate_id(tkn_str: &str) -> Result { } } +pub fn parse_wrapped_token(token: &str) -> Result { + match token.to_lowercase().as_str() { + "sol" => { + let id = "So11111111111111111111111111111111111111112"; + let token_id = generate_id(id)?; + Ok(token_id) + } + "btc" => Err(Error::TokenParseError), + tkn => { + let id = symbol_to_id(tkn)?; + let token_id = generate_id(&id)?; + Ok(token_id) + } + } +} + +pub fn parse_network(network: &str, token: &str) -> Result { + 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 => { + let id = symbol_to_id(tkn)?; + Ok(id) + } + }, + NetworkName::Bitcoin => Err(Error::NetworkParseError), + } +} + +// BTC has 8 decimals +// SOL uses conversion function soltolamport() +// or there are decimals in the token info +// TODO: how to organize these functions more logically w less repetition? +pub fn parse_params(network: &str, token: &str, amount: u64) -> Result<(String, u64)> { + match NetworkName::from_str(network)? { + NetworkName::Solana => match token { + "solana" | "sol" => { + let token_id = "So11111111111111111111111111111111111111112"; + let amount_in_apo: u64 = amount * 10 ^ 8; + Ok((token_id.to_string(), amount_in_apo)) + } + tkn => { + let token_id = symbol_to_id(tkn)?; + let amount_in_apo: u64 = amount * 10 ^ 8; + Ok((token_id.to_string(), amount_in_apo)) + } + }, + NetworkName::Bitcoin => Err(Error::NetworkParseError), + } +} + +pub fn symbol_to_id(token: &str) -> Result { + let vec: Vec = token.chars().collect(); + let mut counter = 0; + for c in vec { + if c.is_alphabetic() { + counter += 1; + } + } + if counter == token.len() { + search_id(token) + } else { + Ok(token.to_string()) + } +} + +pub fn search_id(symbol: &str) -> Result { + // TODO: FIXME + let file_contents = std::fs::read_to_string("token/solanatokenlist.json")?; + let tokenlist: serde_json::Value = serde_json::from_str(&file_contents)?; + let tokens = tokenlist["tokens"] + .as_array() + .ok_or_else(|| Error::TokenParseError)?; + for item in tokens { + if item["symbol"] == symbol.to_uppercase() { + let address = item["address"].clone(); + let address = address.as_str().ok_or_else(|| Error::TokenParseError)?; + return Ok(address.to_string()); + } + } + unreachable!(); +} + #[cfg(test)] mod tests { use crate::serial::{deserialize, serialize}; diff --git a/src/wallet/cashierdb.rs b/src/wallet/cashierdb.rs index 95f460eb8..24e940274 100644 --- a/src/wallet/cashierdb.rs +++ b/src/wallet/cashierdb.rs @@ -1,7 +1,7 @@ use super::{Keypair, WalletApi}; use crate::client::ClientFailed; use crate::{Error, Result}; -use crate::service::NetworkName; +use crate::util::NetworkName; use async_std::sync::{Arc, Mutex}; use log::*;