From f3ae84f91c2028d8e53da0d096867c8cf13a54c4 Mon Sep 17 00:00:00 2001 From: edouardparis Date: Thu, 24 Apr 2025 11:28:25 +0200 Subject: [PATCH] Move keys service to its own submodule --- liana-gui/src/app/settings.rs | 4 +- liana-gui/src/installer/descriptor.rs | 2 +- liana-gui/src/installer/message.rs | 4 +- liana-gui/src/installer/mod.rs | 2 +- .../installer/step/descriptor/editor/key.rs | 2 +- .../installer/step/descriptor/editor/mod.rs | 2 +- liana-gui/src/installer/step/mod.rs | 4 +- liana-gui/src/installer/view/editor/mod.rs | 6 +- liana-gui/src/services/{ => keys}/api.rs | 0 liana-gui/src/services/keys/mod.rs | 97 ++++++++++++++++++ liana-gui/src/services/mod.rs | 98 +------------------ 11 files changed, 111 insertions(+), 110 deletions(-) rename liana-gui/src/services/{ => keys}/api.rs (100%) create mode 100644 liana-gui/src/services/keys/mod.rs diff --git a/liana-gui/src/app/settings.rs b/liana-gui/src/app/settings.rs index b2b5aba7..a9e08812 100644 --- a/liana-gui/src/app/settings.rs +++ b/liana-gui/src/app/settings.rs @@ -143,8 +143,8 @@ impl From for Provider { } } -impl From for Provider { - fn from(provider: services::api::Provider) -> Self { +impl From for Provider { + fn from(provider: services::keys::api::Provider) -> Self { Self { uuid: provider.uuid, name: provider.name, diff --git a/liana-gui/src/installer/descriptor.rs b/liana-gui/src/installer/descriptor.rs index 7fa05941..f39342e5 100644 --- a/liana-gui/src/installer/descriptor.rs +++ b/liana-gui/src/installer/descriptor.rs @@ -2,7 +2,7 @@ use async_hwi::{DeviceKind, Version}; use liana::miniscript::{bitcoin::bip32::Fingerprint, descriptor::DescriptorPublicKey}; use crate::{ - app::settings::ProviderKey, hw::is_compatible_with_tapminiscript, services::api::KeyKind, + app::settings::ProviderKey, hw::is_compatible_with_tapminiscript, services::keys::api::KeyKind, }; /// Whether to enable cosigner keys on all paths (excluding safety net paths). diff --git a/liana-gui/src/installer/message.rs b/liana-gui/src/installer/message.rs index b00fdc52..615228a8 100644 --- a/liana-gui/src/installer/message.rs +++ b/liana-gui/src/installer/message.rs @@ -52,7 +52,7 @@ pub enum Message { MnemonicWord(usize, String), ImportMnemonic(bool), RedeemNextKey, - KeyRedeemed(ProviderKey, Result<(), services::Error>), + KeyRedeemed(ProviderKey, Result<(), services::keys::Error>), AllKeysRedeemed, BackupWallet, ExportWallet(Result), @@ -176,7 +176,7 @@ pub enum ImportKeyModal { NameEdited(String), ManuallyImportXpub, ConfirmXpub, - UseToken(services::api::KeyKind), + UseToken(services::keys::api::KeyKind), TokenEdited(String), ConfirmToken, SelectKey(usize), diff --git a/liana-gui/src/installer/mod.rs b/liana-gui/src/installer/mod.rs index b012dead..b60a3607 100644 --- a/liana-gui/src/installer/mod.rs +++ b/liana-gui/src/installer/mod.rs @@ -719,7 +719,7 @@ pub enum Error { // DaemonError does not implement Clone. // TODO: maybe Arc is overkill Backend(Arc), - Services(services::Error), + Services(services::keys::Error), Settings(SettingsError), Bitcoind(String), Electrum(String), diff --git a/liana-gui/src/installer/step/descriptor/editor/key.rs b/liana-gui/src/installer/step/descriptor/editor/key.rs index 98234742..3fbac98e 100644 --- a/liana-gui/src/installer/step/descriptor/editor/key.rs +++ b/liana-gui/src/installer/step/descriptor/editor/key.rs @@ -406,7 +406,7 @@ impl super::DescriptorEditModal for EditXpubModal { message::ImportKeyModal::ConfirmToken => { // We have checked that the token has not already been fetched and saved. let token = self.form_token.value.clone(); - let client = services::Client::new(); + let client = services::keys::Client::new(); return Task::perform( async move { (token.clone(), client.get_key_by_token(token).await) }, |(token, res)| { diff --git a/liana-gui/src/installer/step/descriptor/editor/mod.rs b/liana-gui/src/installer/step/descriptor/editor/mod.rs index 13c761fe..fdd47bf7 100644 --- a/liana-gui/src/installer/step/descriptor/editor/mod.rs +++ b/liana-gui/src/installer/step/descriptor/editor/mod.rs @@ -30,7 +30,7 @@ use crate::{ step::{Context, Step}, view, }, - services::api::KeyKind, + services::keys::api::KeyKind, signer::Signer, }; diff --git a/liana-gui/src/installer/step/mod.rs b/liana-gui/src/installer/step/mod.rs index a6b7b082..3f4384d1 100644 --- a/liana-gui/src/installer/step/mod.rs +++ b/liana-gui/src/installer/step/mod.rs @@ -68,7 +68,7 @@ pub struct Final { internal_bitcoind: Option, warning: Option, config_path: Option, - key_redemptions: HashMap>>, + key_redemptions: HashMap>>, } impl Final { @@ -109,7 +109,7 @@ impl Step for Final { match message { Message::RedeemNextKey => { if let Some((pk, _)) = self.key_redemptions.iter().find(|(_, v)| v.is_none()) { - let client = services::Client::new(); + let client = services::keys::Client::new(); let pk = pk.clone(); return Task::perform( async move { (pk.clone(), client.redeem_key(pk.uuid, pk.token).await) }, diff --git a/liana-gui/src/installer/view/editor/mod.rs b/liana-gui/src/installer/view/editor/mod.rs index caeb8d67..6a15deb5 100644 --- a/liana-gui/src/installer/view/editor/mod.rs +++ b/liana-gui/src/installer/view/editor/mod.rs @@ -265,7 +265,7 @@ fn maybe_key_from_token<'a>( has_chosen_signer: bool, form_token: &form::Value, form_token_warning: Option<&'a String>, - key_kind: services::api::KeyKind, + key_kind: services::keys::api::KeyKind, ) -> Option> { if !path_kind.can_choose_key_source_kind(&KeySourceKind::Token(key_kind)) { None @@ -448,8 +448,8 @@ pub fn edit_key_modal<'a>( )) } ) - .push_maybe(maybe_key_from_token(path_kind, form_key_source_kind, chosen_signer.is_some(), form_token, form_token_warning, services::api::KeyKind::SafetyNet)) - .push_maybe(maybe_key_from_token(path_kind, form_key_source_kind, chosen_signer.is_some(), form_token, form_token_warning, services::api::KeyKind::Cosigner)) + .push_maybe(maybe_key_from_token(path_kind, form_key_source_kind, chosen_signer.is_some(), form_token, form_token_warning, services::keys::api::KeyKind::SafetyNet)) + .push_maybe(maybe_key_from_token(path_kind, form_key_source_kind, chosen_signer.is_some(), form_token, form_token_warning, services::keys::api::KeyKind::Cosigner)) .width(Length::Fill), ) .push_maybe( diff --git a/liana-gui/src/services/api.rs b/liana-gui/src/services/keys/api.rs similarity index 100% rename from liana-gui/src/services/api.rs rename to liana-gui/src/services/keys/api.rs diff --git a/liana-gui/src/services/keys/mod.rs b/liana-gui/src/services/keys/mod.rs new file mode 100644 index 00000000..340ff684 --- /dev/null +++ b/liana-gui/src/services/keys/mod.rs @@ -0,0 +1,97 @@ +pub mod api; + +use reqwest::{self, IntoUrl, Method, RequestBuilder}; +use serde_json::json; + +const KEYS_API_URL: &str = "https://keys.wizardsardine.com"; + +#[derive(Debug, Clone)] +pub enum Error { + Http(Option, String), +} + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::Http(kind, e) => write!(f, "Http error: [{:?}] {}", kind, e), + } + } +} + +impl From for Error { + fn from(error: reqwest::Error) -> Self { + Self::Http(None, error.to_string()) + } +} + +async fn check_response_status(response: reqwest::Response) -> Result { + if !response.status().is_success() { + return Err(Error::Http( + Some(response.status().into()), + response.text().await?, + )); + } + Ok(response) +} + +fn request( + http: &reqwest::Client, + method: reqwest::Method, + url: U, +) -> reqwest::RequestBuilder { + let req = http + .request(method, url) + .header("Content-Type", "application/json") + .header("API-Version", "0.1"); + tracing::debug!("Sending http request: {:?}", req); + req +} + +#[derive(Debug, Clone)] +pub struct Client(reqwest::Client); + +impl Default for Client { + fn default() -> Self { + Self::new() + } +} + +impl Client { + pub fn new() -> Self { + let http = reqwest::Client::new(); + Client(http) + } + + async fn request(&self, method: Method, url: U) -> RequestBuilder { + request(&self.0, method, url) + } + + pub async fn get_key_by_token(&self, token: String) -> Result { + let response = self + .request(Method::GET, &format!("{}/v1/keys", KEYS_API_URL)) + .await + .query(&[("token", token)]) + .send() + .await?; + let response = check_response_status(response).await?; + let key = response.json().await?; + Ok(key) + } + + pub async fn redeem_key(&self, uuid: String, token: String) -> Result { + let response = self + .request( + Method::POST, + &format!("{}/v1/keys/{}/redeem", KEYS_API_URL, uuid), + ) + .await + .json(&json!({ + "token": token, + })) + .send() + .await?; + let response = check_response_status(response).await?; + let key = response.json().await?; + Ok(key) + } +} diff --git a/liana-gui/src/services/mod.rs b/liana-gui/src/services/mod.rs index 340ff684..703bc087 100644 --- a/liana-gui/src/services/mod.rs +++ b/liana-gui/src/services/mod.rs @@ -1,97 +1 @@ -pub mod api; - -use reqwest::{self, IntoUrl, Method, RequestBuilder}; -use serde_json::json; - -const KEYS_API_URL: &str = "https://keys.wizardsardine.com"; - -#[derive(Debug, Clone)] -pub enum Error { - Http(Option, String), -} - -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - match self { - Self::Http(kind, e) => write!(f, "Http error: [{:?}] {}", kind, e), - } - } -} - -impl From for Error { - fn from(error: reqwest::Error) -> Self { - Self::Http(None, error.to_string()) - } -} - -async fn check_response_status(response: reqwest::Response) -> Result { - if !response.status().is_success() { - return Err(Error::Http( - Some(response.status().into()), - response.text().await?, - )); - } - Ok(response) -} - -fn request( - http: &reqwest::Client, - method: reqwest::Method, - url: U, -) -> reqwest::RequestBuilder { - let req = http - .request(method, url) - .header("Content-Type", "application/json") - .header("API-Version", "0.1"); - tracing::debug!("Sending http request: {:?}", req); - req -} - -#[derive(Debug, Clone)] -pub struct Client(reqwest::Client); - -impl Default for Client { - fn default() -> Self { - Self::new() - } -} - -impl Client { - pub fn new() -> Self { - let http = reqwest::Client::new(); - Client(http) - } - - async fn request(&self, method: Method, url: U) -> RequestBuilder { - request(&self.0, method, url) - } - - pub async fn get_key_by_token(&self, token: String) -> Result { - let response = self - .request(Method::GET, &format!("{}/v1/keys", KEYS_API_URL)) - .await - .query(&[("token", token)]) - .send() - .await?; - let response = check_response_status(response).await?; - let key = response.json().await?; - Ok(key) - } - - pub async fn redeem_key(&self, uuid: String, token: String) -> Result { - let response = self - .request( - Method::POST, - &format!("{}/v1/keys/{}/redeem", KEYS_API_URL, uuid), - ) - .await - .json(&json!({ - "token": token, - })) - .send() - .await?; - let response = check_response_status(response).await?; - let key = response.json().await?; - Ok(key) - } -} +pub mod keys;