mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-05-02 14:56:10 -04:00
refactor(cli): Builder pattern for constructing Context
This commit is contained in:
parent
015c956273
commit
c562e352f2
3 changed files with 202 additions and 130 deletions
|
@ -1,14 +1,14 @@
|
|||
use std::result::Result;
|
||||
use std::sync::Arc;
|
||||
use swap::{
|
||||
cli::api::{
|
||||
use swap::cli::{
|
||||
api::{
|
||||
request::{
|
||||
BalanceArgs, BuyXmrArgs, GetHistoryArgs, ResumeSwapArgs, SuspendCurrentSwapArgs,
|
||||
WithdrawBtcArgs,
|
||||
},
|
||||
Context,
|
||||
Context, ContextBuilder,
|
||||
},
|
||||
cli::command::{Bitcoin, Monero},
|
||||
command::{Bitcoin, Monero},
|
||||
};
|
||||
use tauri::{Manager, RunEvent};
|
||||
|
||||
|
@ -63,25 +63,20 @@ tauri_command!(suspend_current_swap, SuspendCurrentSwapArgs);
|
|||
|
||||
fn setup<'a>(app: &'a mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
|
||||
tauri::async_runtime::block_on(async {
|
||||
let context = Context::build(
|
||||
Some(Bitcoin {
|
||||
let context = ContextBuilder::new(true)
|
||||
.with_bitcoin(Bitcoin {
|
||||
bitcoin_electrum_rpc_url: None,
|
||||
bitcoin_target_block: None,
|
||||
}),
|
||||
Some(Monero {
|
||||
})
|
||||
.with_monero(Monero {
|
||||
monero_daemon_address: None,
|
||||
}),
|
||||
None,
|
||||
None,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.with_tauri_handle(app.app_handle().to_owned());
|
||||
|
||||
})
|
||||
.with_json(true)
|
||||
.with_debug(true)
|
||||
.with_tauri(app.app_handle().to_owned())
|
||||
.build()
|
||||
.await
|
||||
.expect("failed to create context");
|
||||
app.manage(Arc::new(context));
|
||||
});
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ use anyhow::{anyhow, bail, Context as AnyContext, Error, Result};
|
|||
use futures::future::try_join_all;
|
||||
use std::fmt;
|
||||
use std::future::Future;
|
||||
use std::net::SocketAddr;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{Arc, Mutex as SyncMutex, Once};
|
||||
use tauri::AppHandle;
|
||||
|
@ -28,7 +27,6 @@ static START: Once = Once::new();
|
|||
pub struct Config {
|
||||
tor_socks5_port: u16,
|
||||
namespace: XmrBtcNamespace,
|
||||
server_address: Option<SocketAddr>,
|
||||
pub env_config: EnvConfig,
|
||||
seed: Option<Seed>,
|
||||
debug: bool,
|
||||
|
@ -184,32 +182,109 @@ pub struct Context {
|
|||
monero_rpc_process: Option<Arc<SyncMutex<monero::WalletRpcProcess>>>,
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
impl Context {
|
||||
pub async fn build(
|
||||
bitcoin: Option<Bitcoin>,
|
||||
monero: Option<Monero>,
|
||||
tor: Option<Tor>,
|
||||
data: Option<PathBuf>,
|
||||
is_testnet: bool,
|
||||
debug: bool,
|
||||
json: bool,
|
||||
server_address: Option<SocketAddr>,
|
||||
) -> Result<Context> {
|
||||
let data_dir = data::data_dir_from(data, is_testnet)?;
|
||||
let env_config = env_config_from(is_testnet);
|
||||
/// A conveniant builder struct for [`Context`].
|
||||
#[derive(Debug)]
|
||||
#[must_use = "ContextBuilder must be built to be useful"]
|
||||
pub struct ContextBuilder {
|
||||
monero: Option<Monero>,
|
||||
bitcoin: Option<Bitcoin>,
|
||||
tor: Option<Tor>,
|
||||
data: Option<PathBuf>,
|
||||
is_testnet: bool,
|
||||
debug: bool,
|
||||
json: bool,
|
||||
tauri_handle: Option<AppHandle>,
|
||||
}
|
||||
|
||||
impl ContextBuilder {
|
||||
/// Start building a context
|
||||
pub fn new(is_testnet: bool) -> Self {
|
||||
if is_testnet {
|
||||
Self::testnet()
|
||||
} else {
|
||||
Self::mainnet()
|
||||
}
|
||||
}
|
||||
|
||||
/// Basic builder with default options for mainnet
|
||||
pub fn mainnet() -> Self {
|
||||
ContextBuilder {
|
||||
monero: None,
|
||||
bitcoin: None,
|
||||
tor: None,
|
||||
data: None,
|
||||
is_testnet: false,
|
||||
debug: false,
|
||||
json: false,
|
||||
tauri_handle: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Basic builder with default options for testnet
|
||||
pub fn testnet() -> Self {
|
||||
let mut builder = Self::mainnet();
|
||||
builder.is_testnet = true;
|
||||
builder
|
||||
}
|
||||
|
||||
/// Configures the Context to initialize a Monero wallet with the given configuration.
|
||||
pub fn with_monero(mut self, monero: impl Into<Option<Monero>>) -> Self {
|
||||
self.monero = monero.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the Context to initialize a Bitcoin wallet with the given configuration.
|
||||
pub fn with_bitcoin(mut self, bitcoin: impl Into<Option<Bitcoin>>) -> Self {
|
||||
self.bitcoin = bitcoin.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the Context to use Tor with the given configuration.
|
||||
pub fn with_tor(mut self, tor: impl Into<Option<Tor>>) -> Self {
|
||||
self.tor = tor.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Attach a handle to Tauri to the Context for emitting events etc.
|
||||
pub fn with_tauri(mut self, tauri: impl Into<Option<AppHandle>>) -> Self {
|
||||
self.tauri_handle = tauri.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures where the data and logs are saved in the filesystem
|
||||
pub fn with_data_dir(mut self, data: impl Into<Option<PathBuf>>) -> Self {
|
||||
self.data = data.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Whether to include debug level logging messages (default false)
|
||||
pub fn with_debug(mut self, debug: bool) -> Self {
|
||||
self.debug = debug;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set logging format to json (default false)
|
||||
pub fn with_json(mut self, json: bool) -> Self {
|
||||
self.json = json;
|
||||
self
|
||||
}
|
||||
|
||||
/// Takes the builder, initializes the context by initializing the wallets and other components and returns the Context.
|
||||
pub async fn build(self) -> Result<Context> {
|
||||
let data_dir = data::data_dir_from(self.data, self.is_testnet)?;
|
||||
let env_config = env_config_from(self.is_testnet);
|
||||
|
||||
START.call_once(|| {
|
||||
let _ = cli::tracing::init(debug, json, data_dir.join("logs"));
|
||||
let _ = cli::tracing::init(self.debug, self.json, data_dir.join("logs"));
|
||||
});
|
||||
|
||||
let seed = Seed::from_file_or_generate(data_dir.as_path())
|
||||
.context("Failed to read seed in file")?;
|
||||
|
||||
let bitcoin_wallet = {
|
||||
if let Some(bitcoin) = bitcoin {
|
||||
if let Some(bitcoin) = self.bitcoin {
|
||||
let (bitcoin_electrum_rpc_url, bitcoin_target_block) =
|
||||
bitcoin.apply_defaults(is_testnet)?;
|
||||
bitcoin.apply_defaults(self.is_testnet)?;
|
||||
Some(Arc::new(
|
||||
init_bitcoin_wallet(
|
||||
bitcoin_electrum_rpc_url,
|
||||
|
@ -226,8 +301,8 @@ impl Context {
|
|||
};
|
||||
|
||||
let (monero_wallet, monero_rpc_process) = {
|
||||
if let Some(monero) = monero {
|
||||
let monero_daemon_address = monero.apply_defaults(is_testnet);
|
||||
if let Some(monero) = self.monero {
|
||||
let monero_daemon_address = monero.apply_defaults(self.is_testnet);
|
||||
let (wlt, prc) =
|
||||
init_monero_wallet(data_dir.clone(), monero_daemon_address, env_config).await?;
|
||||
(Some(Arc::new(wlt)), Some(Arc::new(SyncMutex::new(prc))))
|
||||
|
@ -236,7 +311,7 @@ impl Context {
|
|||
}
|
||||
};
|
||||
|
||||
let tor_socks5_port = tor.map_or(9050, |tor| tor.tor_socks5_port);
|
||||
let tor_socks5_port = self.tor.map_or(9050, |tor| tor.tor_socks5_port);
|
||||
|
||||
let context = Context {
|
||||
db: open_db(data_dir.join("sqlite")).await?,
|
||||
|
@ -245,23 +320,24 @@ impl Context {
|
|||
monero_rpc_process,
|
||||
config: Config {
|
||||
tor_socks5_port,
|
||||
namespace: XmrBtcNamespace::from_is_testnet(is_testnet),
|
||||
namespace: XmrBtcNamespace::from_is_testnet(self.is_testnet),
|
||||
env_config,
|
||||
seed: Some(seed),
|
||||
server_address,
|
||||
debug,
|
||||
json,
|
||||
is_testnet,
|
||||
debug: self.debug,
|
||||
json: self.json,
|
||||
is_testnet: self.is_testnet,
|
||||
data_dir,
|
||||
},
|
||||
swap_lock: Arc::new(SwapLock::new()),
|
||||
tasks: Arc::new(PendingTaskList::default()),
|
||||
tauri_handle: None,
|
||||
tauri_handle: self.tauri_handle.map(TauriHandle::new),
|
||||
};
|
||||
|
||||
Ok(context)
|
||||
}
|
||||
}
|
||||
|
||||
impl Context {
|
||||
pub fn with_tauri_handle(mut self, tauri_handle: AppHandle) -> Self {
|
||||
self.tauri_handle = Some(TauriHandle::new(tauri_handle));
|
||||
|
||||
|
@ -394,7 +470,6 @@ impl Config {
|
|||
Self {
|
||||
tor_socks5_port: 9050,
|
||||
namespace: XmrBtcNamespace::from_is_testnet(false),
|
||||
server_address: None,
|
||||
env_config,
|
||||
seed: Some(seed),
|
||||
debug: false,
|
||||
|
|
|
@ -18,6 +18,8 @@ use structopt::{clap, StructOpt};
|
|||
use url::Url;
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::api::ContextBuilder;
|
||||
|
||||
// See: https://moneroworld.com/
|
||||
pub const DEFAULT_MONERO_DAEMON_ADDRESS: &str = "node.community.rino.io:18081";
|
||||
pub const DEFAULT_MONERO_DAEMON_ADDRESS_STAGENET: &str = "stagenet.community.rino.io:38081";
|
||||
|
@ -79,17 +81,15 @@ where
|
|||
bitcoin_address::validate_is_testnet(bitcoin_change_address, is_testnet)?;
|
||||
|
||||
let context = Arc::new(
|
||||
Context::build(
|
||||
Some(bitcoin),
|
||||
Some(monero),
|
||||
Some(tor),
|
||||
data,
|
||||
is_testnet,
|
||||
debug,
|
||||
json,
|
||||
None,
|
||||
)
|
||||
.await?,
|
||||
ContextBuilder::new(is_testnet)
|
||||
.with_bitcoin(bitcoin)
|
||||
.with_monero(monero)
|
||||
.with_tor(tor)
|
||||
.with_data_dir(data)
|
||||
.with_debug(debug)
|
||||
.with_json(json)
|
||||
.build()
|
||||
.await?,
|
||||
);
|
||||
|
||||
BuyXmrArgs {
|
||||
|
@ -104,7 +104,12 @@ where
|
|||
}
|
||||
CliCommand::History => {
|
||||
let context = Arc::new(
|
||||
Context::build(None, None, None, data, is_testnet, debug, json, None).await?,
|
||||
ContextBuilder::new(is_testnet)
|
||||
.with_data_dir(data)
|
||||
.with_debug(debug)
|
||||
.with_json(json)
|
||||
.build()
|
||||
.await?,
|
||||
);
|
||||
|
||||
GetHistoryArgs {}.request(context.clone()).await?;
|
||||
|
@ -113,7 +118,12 @@ where
|
|||
}
|
||||
CliCommand::Config => {
|
||||
let context = Arc::new(
|
||||
Context::build(None, None, None, data, is_testnet, debug, json, None).await?,
|
||||
ContextBuilder::new(is_testnet)
|
||||
.with_data_dir(data)
|
||||
.with_debug(debug)
|
||||
.with_json(json)
|
||||
.build()
|
||||
.await?,
|
||||
);
|
||||
|
||||
GetConfigArgs {}.request(context.clone()).await?;
|
||||
|
@ -122,17 +132,13 @@ where
|
|||
}
|
||||
CliCommand::Balance { bitcoin } => {
|
||||
let context = Arc::new(
|
||||
Context::build(
|
||||
Some(bitcoin),
|
||||
None,
|
||||
None,
|
||||
data,
|
||||
is_testnet,
|
||||
debug,
|
||||
json,
|
||||
None,
|
||||
)
|
||||
.await?,
|
||||
ContextBuilder::new(is_testnet)
|
||||
.with_bitcoin(bitcoin)
|
||||
.with_data_dir(data)
|
||||
.with_debug(debug)
|
||||
.with_json(json)
|
||||
.build()
|
||||
.await?,
|
||||
);
|
||||
|
||||
BalanceArgs {
|
||||
|
@ -150,17 +156,15 @@ where
|
|||
tor,
|
||||
} => {
|
||||
let context = Arc::new(
|
||||
Context::build(
|
||||
Some(bitcoin),
|
||||
Some(monero),
|
||||
Some(tor),
|
||||
data,
|
||||
is_testnet,
|
||||
debug,
|
||||
json,
|
||||
server_address,
|
||||
)
|
||||
.await?,
|
||||
ContextBuilder::new(is_testnet)
|
||||
.with_bitcoin(bitcoin)
|
||||
.with_monero(monero)
|
||||
.with_tor(tor)
|
||||
.with_data_dir(data)
|
||||
.with_debug(debug)
|
||||
.with_json(json)
|
||||
.build()
|
||||
.await?,
|
||||
);
|
||||
|
||||
StartDaemonArgs { server_address }
|
||||
|
@ -177,17 +181,13 @@ where
|
|||
let address = bitcoin_address::validate_is_testnet(address, is_testnet)?;
|
||||
|
||||
let context = Arc::new(
|
||||
Context::build(
|
||||
Some(bitcoin),
|
||||
None,
|
||||
None,
|
||||
data,
|
||||
is_testnet,
|
||||
debug,
|
||||
json,
|
||||
None,
|
||||
)
|
||||
.await?,
|
||||
ContextBuilder::new(is_testnet)
|
||||
.with_bitcoin(bitcoin)
|
||||
.with_data_dir(data)
|
||||
.with_debug(debug)
|
||||
.with_json(json)
|
||||
.build()
|
||||
.await?,
|
||||
);
|
||||
|
||||
WithdrawBtcArgs { amount, address }
|
||||
|
@ -203,17 +203,15 @@ where
|
|||
tor,
|
||||
} => {
|
||||
let context = Arc::new(
|
||||
Context::build(
|
||||
Some(bitcoin),
|
||||
Some(monero),
|
||||
Some(tor),
|
||||
data,
|
||||
is_testnet,
|
||||
debug,
|
||||
json,
|
||||
None,
|
||||
)
|
||||
.await?,
|
||||
ContextBuilder::new(is_testnet)
|
||||
.with_bitcoin(bitcoin)
|
||||
.with_monero(monero)
|
||||
.with_tor(tor)
|
||||
.with_data_dir(data)
|
||||
.with_debug(debug)
|
||||
.with_json(json)
|
||||
.build()
|
||||
.await?,
|
||||
);
|
||||
|
||||
ResumeSwapArgs { swap_id }.request(context.clone()).await?;
|
||||
|
@ -226,17 +224,14 @@ where
|
|||
tor,
|
||||
} => {
|
||||
let context = Arc::new(
|
||||
Context::build(
|
||||
Some(bitcoin),
|
||||
None,
|
||||
Some(tor),
|
||||
data,
|
||||
is_testnet,
|
||||
debug,
|
||||
json,
|
||||
None,
|
||||
)
|
||||
.await?,
|
||||
ContextBuilder::new(is_testnet)
|
||||
.with_bitcoin(bitcoin)
|
||||
.with_tor(tor)
|
||||
.with_data_dir(data)
|
||||
.with_debug(debug)
|
||||
.with_json(json)
|
||||
.build()
|
||||
.await?,
|
||||
);
|
||||
|
||||
CancelAndRefundArgs { swap_id }
|
||||
|
@ -250,7 +245,13 @@ where
|
|||
tor,
|
||||
} => {
|
||||
let context = Arc::new(
|
||||
Context::build(None, None, Some(tor), data, is_testnet, debug, json, None).await?,
|
||||
ContextBuilder::new(is_testnet)
|
||||
.with_tor(tor)
|
||||
.with_data_dir(data)
|
||||
.with_debug(debug)
|
||||
.with_json(json)
|
||||
.build()
|
||||
.await?,
|
||||
);
|
||||
|
||||
ListSellersArgs { rendezvous_point }
|
||||
|
@ -261,17 +262,13 @@ where
|
|||
}
|
||||
CliCommand::ExportBitcoinWallet { bitcoin } => {
|
||||
let context = Arc::new(
|
||||
Context::build(
|
||||
Some(bitcoin),
|
||||
None,
|
||||
None,
|
||||
data,
|
||||
is_testnet,
|
||||
debug,
|
||||
json,
|
||||
None,
|
||||
)
|
||||
.await?,
|
||||
ContextBuilder::new(is_testnet)
|
||||
.with_bitcoin(bitcoin)
|
||||
.with_data_dir(data)
|
||||
.with_debug(debug)
|
||||
.with_json(json)
|
||||
.build()
|
||||
.await?,
|
||||
);
|
||||
|
||||
ExportBitcoinWalletArgs {}.request(context.clone()).await?;
|
||||
|
@ -282,7 +279,12 @@ where
|
|||
swap_id: SwapId { swap_id },
|
||||
} => {
|
||||
let context = Arc::new(
|
||||
Context::build(None, None, None, data, is_testnet, debug, json, None).await?,
|
||||
ContextBuilder::new(is_testnet)
|
||||
.with_data_dir(data)
|
||||
.with_debug(debug)
|
||||
.with_json(json)
|
||||
.build()
|
||||
.await?,
|
||||
);
|
||||
|
||||
MoneroRecoveryArgs { swap_id }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue