diff --git a/src/app/errors/payment_error.rs b/src/app/errors/payment_error.rs index 298618f..bf2748a 100644 --- a/src/app/errors/payment_error.rs +++ b/src/app/errors/payment_error.rs @@ -1,4 +1,3 @@ -use csv::StringRecord; use thiserror::Error; #[derive(Error, Debug)] @@ -16,8 +15,6 @@ pub enum PaymentError { #[error("Failed to collect records from CSV file.")] FailedToGetRecords, #[error("No username found for the record {:?}", 0)] - NoUsernameFound(StringRecord), - #[error("Username {0} does not exist")] UsernameDoesNotExist(String), #[error("Insufficient balance in the sender's wallet")] InsufficientBalance, diff --git a/src/app/operations/batch.rs b/src/app/operations/batch.rs index c5fb155..7250a22 100644 --- a/src/app/operations/batch.rs +++ b/src/app/operations/batch.rs @@ -55,7 +55,7 @@ impl QueryMeMe { } pub fn get_default_wallet_currency(&self) -> Option<&WalletCurrency> { - let default_wallet_id = &self.default_account.default_wallet_id; + let default_wallet_id = &self.default_account.id; self.default_account .wallets .iter() @@ -173,8 +173,8 @@ pub fn validate_csv( } let currency = match currency { - "SATS" => AmountCurrency::SATS, - "USD" => AmountCurrency::USD, + "SATS" => AmountCurrency::Sats, + "USD" => AmountCurrency::Usd, _ => return Err(PaymentError::IncorrectCSVFormat), }; @@ -186,14 +186,14 @@ pub fn validate_csv( //amount for SATS will be whole number and for USD max 2 decimals let formatted_amount = match currency { - AmountCurrency::SATS => amount.round_dp(0), - AmountCurrency::USD => { + AmountCurrency::Sats => amount.round_dp(0), + AmountCurrency::Usd => { amount.round_dp_with_strategy(2, RoundingStrategy::MidpointAwayFromZero) } }; //if currency is SATS then wallet should be BTC - if currency == AmountCurrency::SATS && wallet_currency != WalletCurrency::BTC { + if currency == AmountCurrency::Sats && wallet_currency != WalletCurrency::BTC { return Err(PaymentError::IncorrectCSVFormat); } @@ -339,11 +339,11 @@ impl App { let currency = &record.currency; let wallet_type = &record.wallet_currency; - if currency == &AmountCurrency::SATS && wallet_type == &WalletCurrency::BTC { + if currency == &AmountCurrency::Sats && wallet_type == &WalletCurrency::BTC { total_amount_payable.btc_wallet.sats += amount; - } else if currency == &AmountCurrency::USD && wallet_type == &WalletCurrency::BTC { + } else if currency == &AmountCurrency::Usd && wallet_type == &WalletCurrency::BTC { total_amount_payable.btc_wallet.usd += amount; - } else if currency == &AmountCurrency::USD && wallet_type == &WalletCurrency::USD { + } else if currency == &AmountCurrency::Usd && wallet_type == &WalletCurrency::USD { total_amount_payable.usd_wallet.usd += amount; } @@ -423,7 +423,7 @@ impl App { } WalletCurrency::BTC => { let mut final_amount = amount; - if currency == AmountCurrency::USD { + if currency == AmountCurrency::Usd { final_amount = convert_usd_to_btc_sats(amount, &btc_sat_price); } self.client diff --git a/src/app/operations/request_code.rs b/src/app/operations/request_code.rs index d8697f8..00d02b3 100644 --- a/src/app/operations/request_code.rs +++ b/src/app/operations/request_code.rs @@ -2,7 +2,7 @@ use anyhow::Context; use std::net::TcpListener; use webbrowser; -use crate::app::{file_manager, server::server::run, App}; +use crate::app::{file_manager, server::run, App}; const PORT: u16 = 42909; diff --git a/src/app/operations/wallet.rs b/src/app/operations/wallet.rs index 51ab865..491034b 100644 --- a/src/app/operations/wallet.rs +++ b/src/app/operations/wallet.rs @@ -61,7 +61,7 @@ impl App { wallet_ids: Vec, ) -> anyhow::Result<()> { let me = self.client.me().await?; - let default_wallet_id = me.default_account.default_wallet_id; + let default_wallet_id = me.default_account.id; let wallets = &me.default_account.wallets; let wallet_ids_set: HashSet<_> = wallet_ids.into_iter().collect(); diff --git a/src/app/server/mod.rs b/src/app/server/mod.rs index 74f47ad..adc97af 100644 --- a/src/app/server/mod.rs +++ b/src/app/server/mod.rs @@ -1 +1,121 @@ -pub mod server; +use actix_web::{web, App, HttpResponse, HttpServer, Responder}; +use mime_guess::from_path; +use rust_embed::RustEmbed; +use serde::{Deserialize, Serialize}; +use tera::{Context, Tera}; + +use graphql_client::reqwest::post_graphql; +use reqwest::Client; + +use std::net::TcpListener; + +use crate::client::queries::{captcha_request_auth_code, CaptchaChallenge, CaptchaRequestAuthCode}; + +struct AppData { + tera: Tera, + phone: String, + api: String, + captcha_challenge_result: CaptchaChallenge, +} + +#[actix_web::get("/login")] +async fn login(appdata: web::Data) -> impl Responder { + let mut ctx = Context::new(); + + ctx.insert("id", &appdata.captcha_challenge_result.id); + ctx.insert("new_captcha", &appdata.captcha_challenge_result.new_captcha); + ctx.insert( + "failback_mode", + &appdata.captcha_challenge_result.failback_mode, + ); + ctx.insert( + "challenge_code", + &appdata.captcha_challenge_result.challenge_code, + ); + + let rendered = appdata.tera.render("login.tera.html", &ctx).unwrap(); + HttpResponse::Ok().body(rendered) +} + +#[derive(Debug, Serialize, Deserialize)] +struct GeetestResponse { + geetest_challenge: String, + geetest_seccode: String, + geetest_validate: String, +} + +#[actix_web::post("/solve")] +async fn solve(r: web::Json, appdata: web::Data) -> impl Responder { + println!("Captcha Solved, you may close the browser and return to the CLI."); + + let client = Client::builder().build().expect("Can't build client"); + + let input = captcha_request_auth_code::CaptchaRequestAuthCodeInput { + challenge_code: r.geetest_challenge.clone(), + phone: appdata.phone.clone(), + sec_code: r.geetest_seccode.clone(), + validation_code: r.geetest_validate.clone(), + channel: None, + }; + let variables = captcha_request_auth_code::Variables { input }; + + let response_body = + post_graphql::(&client, appdata.api.clone(), variables).await; + + match response_body { + Ok(_) => println!("Phone Code sent successfully to {}", appdata.phone), + Err(_) => { + println!("Phone Code couldn't be send.") + } + }; + + tokio::spawn(async { + std::process::exit(0); + }); + + HttpResponse::Ok() +} + +#[derive(RustEmbed)] +#[folder = "src/app/server/public/"] +struct Asset; + +#[actix_web::get("/static/{_:.*}")] +async fn static_dir(path: web::Path) -> impl Responder { + match Asset::get(&path) { + Some(content) => HttpResponse::Ok() + .content_type(from_path(path.as_str()).first_or_octet_stream().as_ref()) + .body(content.data.into_owned()), + None => HttpResponse::NotFound().body("404 Not Found"), + } +} + +pub async fn run( + listener: TcpListener, + phone: String, + api: String, + captcha_challenge_result: CaptchaChallenge, +) -> anyhow::Result<()> { + let mut tera = Tera::default(); + tera.add_raw_template("login.tera.html", include_str!("./public/login.tera.html"))?; + + let appdata = web::Data::new(AppData { + tera, + phone, + api, + captcha_challenge_result, + }); + + let server = HttpServer::new(move || { + App::new() + .service(static_dir) + .service(login) + .service(solve) + .app_data(appdata.clone()) + }) + .listen(listener)? + .run(); + + server.await?; + Ok(()) +} diff --git a/src/app/server/server.rs b/src/app/server/server.rs deleted file mode 100644 index 78d11ff..0000000 --- a/src/app/server/server.rs +++ /dev/null @@ -1,122 +0,0 @@ -use actix_web::{web, App, HttpResponse, HttpServer, Responder}; -use anyhow; -use mime_guess::from_path; -use rust_embed::RustEmbed; -use serde::{Deserialize, Serialize}; -use tera::{Context, Tera}; - -use graphql_client::reqwest::post_graphql; -use reqwest::Client; - -use std::net::TcpListener; - -use crate::client::queries::{captcha_request_auth_code, CaptchaChallenge, CaptchaRequestAuthCode}; - -struct AppData { - tera: Tera, - phone: String, - api: String, - captcha_challenge_result: CaptchaChallenge, -} - -#[actix_web::get("/login")] -async fn login(appdata: web::Data) -> impl Responder { - let mut ctx = Context::new(); - - ctx.insert("id", &appdata.captcha_challenge_result.id); - ctx.insert("new_captcha", &appdata.captcha_challenge_result.new_captcha); - ctx.insert( - "failback_mode", - &appdata.captcha_challenge_result.failback_mode, - ); - ctx.insert( - "challenge_code", - &appdata.captcha_challenge_result.challenge_code, - ); - - let rendered = appdata.tera.render("login.tera.html", &ctx).unwrap(); - HttpResponse::Ok().body(rendered) -} - -#[derive(Debug, Serialize, Deserialize)] -struct GeetestResponse { - geetest_challenge: String, - geetest_seccode: String, - geetest_validate: String, -} - -#[actix_web::post("/solve")] -async fn solve(r: web::Json, appdata: web::Data) -> impl Responder { - println!("Captcha Solved, you may close the browser and return to the CLI."); - - let client = Client::builder().build().expect("Can't build client"); - - let input = captcha_request_auth_code::CaptchaRequestAuthCodeInput { - challenge_code: r.geetest_challenge.clone(), - phone: appdata.phone.clone(), - sec_code: r.geetest_seccode.clone(), - validation_code: r.geetest_validate.clone(), - channel: None, - }; - let variables = captcha_request_auth_code::Variables { input }; - - let response_body = - post_graphql::(&client, appdata.api.clone(), variables).await; - - match response_body { - Ok(_) => println!("Phone Code sent successfully to {}", appdata.phone), - Err(_) => { - println!("Phone Code couldn't be send.") - } - }; - - tokio::spawn(async { - std::process::exit(0); - }); - - HttpResponse::Ok() -} - -#[derive(RustEmbed)] -#[folder = "src/app/server/public/"] -struct Asset; - -#[actix_web::get("/static/{_:.*}")] -async fn static_dir(path: web::Path) -> impl Responder { - match Asset::get(&path) { - Some(content) => HttpResponse::Ok() - .content_type(from_path(path.as_str()).first_or_octet_stream().as_ref()) - .body(content.data.into_owned()), - None => HttpResponse::NotFound().body("404 Not Found"), - } -} - -pub async fn run( - listener: TcpListener, - phone: String, - api: String, - captcha_challenge_result: CaptchaChallenge, -) -> anyhow::Result<()> { - let mut tera = Tera::default(); - tera.add_raw_template("login.tera.html", include_str!("./public/login.tera.html"))?; - - let appdata = web::Data::new(AppData { - tera, - phone, - api, - captcha_challenge_result, - }); - - let server = HttpServer::new(move || { - App::new() - .service(static_dir) - .service(login) - .service(solve) - .app_data(appdata.clone()) - }) - .listen(listener)? - .run(); - - server.await?; - Ok(()) -} diff --git a/src/client/queries.rs b/src/client/queries.rs index 245fd3f..1dd6aa0 100644 --- a/src/client/queries.rs +++ b/src/client/queries.rs @@ -66,7 +66,7 @@ impl TryFrom for CaptchaChallenge { fn try_from(response: ResponseData) -> Result { let result = response.captcha_create_challenge.result; - let challenge = result.ok_or_else(|| CaptchaError::EmptyCaptcha)?; + let challenge = result.ok_or(CaptchaError::EmptyCaptcha)?; let (id, challenge_code, new_captcha, failback_mode) = ( challenge.id, diff --git a/src/client/requests/default_wallet.rs b/src/client/requests/default_wallet.rs index 7610db0..a14563d 100644 --- a/src/client/requests/default_wallet.rs +++ b/src/client/requests/default_wallet.rs @@ -55,9 +55,9 @@ impl GaloyClient { .collect::>() .join(", "); - return Err(ClientError::ApiError(ApiError::RequestFailedWithError( + Err(ClientError::ApiError(ApiError::RequestFailedWithError( error_string, - ))); + ))) } else { Ok(()) } diff --git a/src/client/requests/intraledger.rs b/src/client/requests/intraledger.rs index b14ac52..d083d5e 100644 --- a/src/client/requests/intraledger.rs +++ b/src/client/requests/intraledger.rs @@ -44,9 +44,9 @@ impl GaloyClient { .collect::>() .join(", "); - return Err(ClientError::ApiError(ApiError::RequestFailedWithError( + Err(ClientError::ApiError(ApiError::RequestFailedWithError( error_string, - ))); + ))) } else { Ok(()) } @@ -91,9 +91,9 @@ impl GaloyClient { .collect::>() .join(", "); - return Err(ClientError::ApiError(ApiError::RequestFailedWithError( + Err(ClientError::ApiError(ApiError::RequestFailedWithError( error_string, - ))); + ))) } else { Ok(()) } diff --git a/src/client/requests/onchain.rs b/src/client/requests/onchain.rs index 75518a8..b72ee61 100644 --- a/src/client/requests/onchain.rs +++ b/src/client/requests/onchain.rs @@ -66,9 +66,9 @@ impl GaloyClient { .collect::>() .join(", "); - return Err(ClientError::ApiError(ApiError::RequestFailedWithError( + Err(ClientError::ApiError(ApiError::RequestFailedWithError( error_string, - ))); + ))) } else { Ok(()) } diff --git a/src/client/requests/set_username.rs b/src/client/requests/set_username.rs index 873f8e1..e6d582a 100644 --- a/src/client/requests/set_username.rs +++ b/src/client/requests/set_username.rs @@ -28,9 +28,9 @@ impl GaloyClient { .collect::>() .join(", "); - return Err(ClientError::ApiError(ApiError::RequestFailedWithError( + Err(ClientError::ApiError(ApiError::RequestFailedWithError( error_string, - ))); + ))) } else { Ok(()) } diff --git a/src/client/types.rs b/src/client/types.rs index 92f6088..5f43796 100644 --- a/src/client/types.rs +++ b/src/client/types.rs @@ -9,8 +9,8 @@ pub enum Wallet { #[derive(Debug, Clone, clap::ValueEnum, PartialEq, Eq)] pub enum AmountCurrency { - SATS, - USD, + Sats, + Usd, } #[derive(Debug, Serialize)]