From 60de6a9219c520e5af0e5496754654eb2ab4287e Mon Sep 17 00:00:00 2001 From: rishflab Date: Fri, 26 Feb 2021 14:44:48 +1100 Subject: [PATCH 1/4] Remove intermediate structs in cli arguments These intermediate structs were creating unnecessary noise. The peer id and multiaddr fields are going to be removed in the future further reducing the need to have seperate structs for cancel, resume and refund. --- swap/src/bin/swap_cli.rs | 14 ++++----- swap/src/cli/command.rs | 65 ++++++++++++++++------------------------ 2 files changed, 33 insertions(+), 46 deletions(-) diff --git a/swap/src/bin/swap_cli.rs b/swap/src/bin/swap_cli.rs index 2fc2b64e..24f6b2b6 100644 --- a/swap/src/bin/swap_cli.rs +++ b/swap/src/bin/swap_cli.rs @@ -21,7 +21,7 @@ use swap::{ bitcoin, bitcoin::Amount, cli::{ - command::{Arguments, Cancel, Command, Refund, Resume}, + command::{Arguments, Command}, config::{read_config, Config}, }, database::Database, @@ -141,11 +141,11 @@ async fn main() -> Result<()> { // Print the table to stdout table.printstd(); } - Command::Resume(Resume::BuyXmr { + Command::Resume { swap_id, alice_peer_id, alice_addr, - }) => { + } => { let (bitcoin_wallet, monero_wallet) = init_wallets( config, bitcoin_network, @@ -171,12 +171,12 @@ async fn main() -> Result<()> { tokio::spawn(async move { event_loop.run().await }); bob::run(swap).await?; } - Command::Cancel(Cancel::BuyXmr { + Command::Cancel { swap_id, alice_peer_id, alice_addr, force, - }) => { + } => { // TODO: Optimization: Only init the Bitcoin wallet, Monero wallet unnecessary let (bitcoin_wallet, monero_wallet) = init_wallets( config, @@ -223,12 +223,12 @@ async fn main() -> Result<()> { } } } - Command::Refund(Refund::BuyXmr { + Command::Refund { swap_id, alice_peer_id, alice_addr, force, - }) => { + } => { let (bitcoin_wallet, monero_wallet) = init_wallets( config, bitcoin_network, diff --git a/swap/src/cli/command.rs b/swap/src/cli/command.rs index 7089949a..171349f8 100644 --- a/swap/src/cli/command.rs +++ b/swap/src/cli/command.rs @@ -26,37 +26,13 @@ pub enum Command { alice_peer_id: PeerId, #[structopt( - long = "connect-addr", - default_value = DEFAULT_ALICE_MULTIADDR + long = "connect-addr", + default_value = DEFAULT_ALICE_MULTIADDR )] alice_addr: Multiaddr, }, History, - Resume(Resume), - Cancel(Cancel), - Refund(Refund), -} - -#[derive(structopt::StructOpt, Debug)] -pub enum Resume { - BuyXmr { - #[structopt(long = "swap-id")] - swap_id: Uuid, - - #[structopt(long = "counterpart-peer-id", default_value = DEFAULT_ALICE_PEER_ID)] - alice_peer_id: PeerId, - - #[structopt( - long = "counterpart-addr", - default_value = DEFAULT_ALICE_MULTIADDR - )] - alice_addr: Multiaddr, - }, -} - -#[derive(structopt::StructOpt, Debug)] -pub enum Cancel { - BuyXmr { + Resume { #[structopt(long = "swap-id")] swap_id: Uuid, @@ -66,19 +42,12 @@ pub enum Cancel { alice_peer_id: PeerId, #[structopt( - long = "counterpart-addr", - default_value = DEFAULT_ALICE_MULTIADDR + long = "counterpart-addr", + default_value = DEFAULT_ALICE_MULTIADDR )] alice_addr: Multiaddr, - - #[structopt(short, long)] - force: bool, }, -} - -#[derive(structopt::StructOpt, Debug)] -pub enum Refund { - BuyXmr { + Cancel { #[structopt(long = "swap-id")] swap_id: Uuid, @@ -88,8 +57,26 @@ pub enum Refund { alice_peer_id: PeerId, #[structopt( - long = "counterpart-addr", - default_value = DEFAULT_ALICE_MULTIADDR + long = "counterpart-addr", + default_value = DEFAULT_ALICE_MULTIADDR + )] + alice_addr: Multiaddr, + + #[structopt(short, long)] + force: bool, + }, + Refund { + #[structopt(long = "swap-id")] + swap_id: Uuid, + + // TODO: Remove Alice peer-id/address, it should be saved in the database when running swap + // and loaded from the database when running resume/cancel/refund + #[structopt(long = "counterpart-peer-id", default_value = DEFAULT_ALICE_PEER_ID)] + alice_peer_id: PeerId, + + #[structopt( + long = "counterpart-addr", + default_value = DEFAULT_ALICE_MULTIADDR )] alice_addr: Multiaddr, From d6d67f62f193d21b257496fc8e8b4edac3a11838 Mon Sep 17 00:00:00 2001 From: rishflab Date: Fri, 26 Feb 2021 15:24:13 +1100 Subject: [PATCH 2/4] Swap cli executes BuyXmr path if subcommand is not given --- swap/src/bin/swap_cli.rs | 155 ++++++++++++++++++++++++++------------- swap/src/cli/command.rs | 6 +- 2 files changed, 106 insertions(+), 55 deletions(-) diff --git a/swap/src/bin/swap_cli.rs b/swap/src/bin/swap_cli.rs index 24f6b2b6..a97e4e5b 100644 --- a/swap/src/bin/swap_cli.rs +++ b/swap/src/bin/swap_cli.rs @@ -13,6 +13,7 @@ #![allow(non_snake_case)] use anyhow::{Context, Result}; +use libp2p::{core::Multiaddr, PeerId}; use prettytable::{row, Table}; use reqwest::Url; use std::{path::Path, sync::Arc, time::Duration}; @@ -21,12 +22,12 @@ use swap::{ bitcoin, bitcoin::Amount, cli::{ - command::{Arguments, Command}, + command::{Arguments, Command, DEFAULT_ALICE_MULTIADDR, DEFAULT_ALICE_PEER_ID}, config::{read_config, Config}, }, database::Database, execution_params, - execution_params::GetExecutionParams, + execution_params::{ExecutionParams, GetExecutionParams}, monero, monero::{CreateWallet, OpenWallet}, protocol::{ @@ -80,56 +81,44 @@ async fn main() -> Result<()> { .await?; match opt.cmd { - Command::BuyXmr { + Some(Command::BuyXmr { alice_peer_id, alice_addr, - } => { - let (bitcoin_wallet, monero_wallet) = init_wallets( - config, - bitcoin_network, - &wallet_data_dir, - monero_network, - seed, - monero_wallet_rpc_process.endpoint(), - ) - .await?; - - // TODO: Also wait for more funds if balance < dust - if bitcoin_wallet.balance().await? == Amount::ZERO { - debug!( - "Waiting for BTC at address {}", - bitcoin_wallet.new_address().await? - ); - - while bitcoin_wallet.balance().await? == Amount::ZERO { - bitcoin_wallet.sync_wallet().await?; - - tokio::time::sleep(Duration::from_secs(1)).await; - } - - debug!("Received {}", bitcoin_wallet.balance().await?); - } - - let send_bitcoin = bitcoin_wallet.max_giveable().await?; - - info!("Swapping {} ...", send_bitcoin); - - let bob_factory = Builder::new( - seed, - db, - Uuid::new_v4(), - Arc::new(bitcoin_wallet), - Arc::new(monero_wallet), + }) => { + buy_xmr( alice_addr, alice_peer_id, + config, + bitcoin_network, + monero_network, + &wallet_data_dir, + seed, + monero_wallet_rpc_process.endpoint(), + db, execution_params, - ); - let (swap, event_loop) = bob_factory.with_init_params(send_bitcoin).build().await?; - - tokio::spawn(async move { event_loop.run().await }); - bob::run(swap).await?; + ) + .await?; } - Command::History => { + None => { + buy_xmr( + DEFAULT_ALICE_MULTIADDR + .parse() + .expect("default alice multiaddr str is a valid Multiaddr>"), + DEFAULT_ALICE_PEER_ID + .parse() + .expect("default alice peer id str is a valid PeerId"), + config, + bitcoin_network, + monero_network, + &wallet_data_dir, + seed, + monero_wallet_rpc_process.endpoint(), + db, + execution_params, + ) + .await?; + } + Some(Command::History) => { let mut table = Table::new(); table.add_row(row!["SWAP ID", "STATE"]); @@ -141,11 +130,11 @@ async fn main() -> Result<()> { // Print the table to stdout table.printstd(); } - Command::Resume { + Some(Command::Resume { swap_id, alice_peer_id, alice_addr, - } => { + }) => { let (bitcoin_wallet, monero_wallet) = init_wallets( config, bitcoin_network, @@ -171,12 +160,12 @@ async fn main() -> Result<()> { tokio::spawn(async move { event_loop.run().await }); bob::run(swap).await?; } - Command::Cancel { + Some(Command::Cancel { swap_id, alice_peer_id, alice_addr, force, - } => { + }) => { // TODO: Optimization: Only init the Bitcoin wallet, Monero wallet unnecessary let (bitcoin_wallet, monero_wallet) = init_wallets( config, @@ -223,12 +212,12 @@ async fn main() -> Result<()> { } } } - Command::Refund { + Some(Command::Refund { swap_id, alice_peer_id, alice_addr, force, - } => { + }) => { let (bitcoin_wallet, monero_wallet) = init_wallets( config, bitcoin_network, @@ -332,3 +321,65 @@ async fn init_wallets( Ok((bitcoin_wallet, monero_wallet)) } + +#[allow(clippy::too_many_arguments)] +async fn buy_xmr( + alice_addr: Multiaddr, + alice_peer_id: PeerId, + config: Config, + bitcoin_network: bitcoin::Network, + monero_network: monero::Network, + wallet_data_dir: &Path, + seed: Seed, + monero_wallet_rpc_url: Url, + db: Database, + execution_params: ExecutionParams, +) -> Result<()> { + let (bitcoin_wallet, monero_wallet) = init_wallets( + config, + bitcoin_network, + wallet_data_dir, + monero_network, + seed, + monero_wallet_rpc_url, + ) + .await?; + + let swap_id = Uuid::new_v4(); + + // TODO: Also wait for more funds if balance < dust + if bitcoin_wallet.balance().await? == Amount::ZERO { + debug!( + "Waiting for BTC at address {}", + bitcoin_wallet.new_address().await? + ); + + while bitcoin_wallet.balance().await? == Amount::ZERO { + bitcoin_wallet.sync_wallet().await?; + + tokio::time::sleep(Duration::from_secs(1)).await; + } + + debug!("Received {}", bitcoin_wallet.balance().await?); + } + + let send_bitcoin = bitcoin_wallet.max_giveable().await?; + + info!("Swapping {} ...", send_bitcoin); + + let bob_factory = Builder::new( + seed, + db, + swap_id, + Arc::new(bitcoin_wallet), + Arc::new(monero_wallet), + alice_addr, + alice_peer_id, + execution_params, + ); + let (swap, event_loop) = bob_factory.with_init_params(send_bitcoin).build().await?; + + tokio::spawn(async move { event_loop.run().await }); + bob::run(swap).await?; + Ok(()) +} diff --git a/swap/src/cli/command.rs b/swap/src/cli/command.rs index 171349f8..a263a0db 100644 --- a/swap/src/cli/command.rs +++ b/swap/src/cli/command.rs @@ -2,8 +2,8 @@ use libp2p::{core::Multiaddr, PeerId}; use std::path::PathBuf; use uuid::Uuid; -const DEFAULT_ALICE_MULTIADDR: &str = "/dns4/xmr-btc-asb.coblox.tech/tcp/9876"; -const DEFAULT_ALICE_PEER_ID: &str = "12D3KooWCdMKjesXMJz1SiZ7HgotrxuqhQJbP5sgBm2BwP1cqThi"; +pub const DEFAULT_ALICE_MULTIADDR: &str = "/dns4/xmr-btc-asb.coblox.tech/tcp/9876"; +pub const DEFAULT_ALICE_PEER_ID: &str = "12D3KooWCdMKjesXMJz1SiZ7HgotrxuqhQJbP5sgBm2BwP1cqThi"; #[derive(structopt::StructOpt, Debug)] pub struct Arguments { @@ -15,7 +15,7 @@ pub struct Arguments { pub config: Option, #[structopt(subcommand)] - pub cmd: Command, + pub cmd: Option, } #[derive(structopt::StructOpt, Debug)] From 9a82b572ec2ce9de95a3977a3180aaeddc384fbe Mon Sep 17 00:00:00 2001 From: rishflab Date: Mon, 1 Mar 2021 10:53:43 +1100 Subject: [PATCH 3/4] Default to buy xmr using default trait --- swap/src/bin/swap_cli.rs | 159 ++++++++++++++------------------------- swap/src/cli/command.rs | 13 ++++ 2 files changed, 68 insertions(+), 104 deletions(-) diff --git a/swap/src/bin/swap_cli.rs b/swap/src/bin/swap_cli.rs index a97e4e5b..c440c9b8 100644 --- a/swap/src/bin/swap_cli.rs +++ b/swap/src/bin/swap_cli.rs @@ -13,7 +13,6 @@ #![allow(non_snake_case)] use anyhow::{Context, Result}; -use libp2p::{core::Multiaddr, PeerId}; use prettytable::{row, Table}; use reqwest::Url; use std::{path::Path, sync::Arc, time::Duration}; @@ -22,12 +21,12 @@ use swap::{ bitcoin, bitcoin::Amount, cli::{ - command::{Arguments, Command, DEFAULT_ALICE_MULTIADDR, DEFAULT_ALICE_PEER_ID}, + command::{Arguments, Command}, config::{read_config, Config}, }, database::Database, execution_params, - execution_params::{ExecutionParams, GetExecutionParams}, + execution_params::GetExecutionParams, monero, monero::{CreateWallet, OpenWallet}, protocol::{ @@ -80,45 +79,59 @@ async fn main() -> Result<()> { .run(monero_network, "stagenet.community.xmr.to") .await?; - match opt.cmd { - Some(Command::BuyXmr { + match opt.cmd.unwrap_or_default() { + Command::BuyXmr { alice_peer_id, alice_addr, - }) => { - buy_xmr( + } => { + let (bitcoin_wallet, monero_wallet) = init_wallets( + config, + bitcoin_network, + &wallet_data_dir, + monero_network, + seed, + monero_wallet_rpc_process.endpoint(), + ) + .await?; + + let swap_id = Uuid::new_v4(); + + // TODO: Also wait for more funds if balance < dust + if bitcoin_wallet.balance().await? == Amount::ZERO { + debug!( + "Waiting for BTC at address {}", + bitcoin_wallet.new_address().await? + ); + + while bitcoin_wallet.balance().await? == Amount::ZERO { + bitcoin_wallet.sync_wallet().await?; + + tokio::time::sleep(Duration::from_secs(1)).await; + } + + debug!("Received {}", bitcoin_wallet.balance().await?); + } + + let send_bitcoin = bitcoin_wallet.max_giveable().await?; + + info!("Swapping {} ...", send_bitcoin); + + let bob_factory = Builder::new( + seed, + db, + swap_id, + Arc::new(bitcoin_wallet), + Arc::new(monero_wallet), alice_addr, alice_peer_id, - config, - bitcoin_network, - monero_network, - &wallet_data_dir, - seed, - monero_wallet_rpc_process.endpoint(), - db, execution_params, - ) - .await?; + ); + let (swap, event_loop) = bob_factory.with_init_params(send_bitcoin).build().await?; + + tokio::spawn(async move { event_loop.run().await }); + bob::run(swap).await?; } - None => { - buy_xmr( - DEFAULT_ALICE_MULTIADDR - .parse() - .expect("default alice multiaddr str is a valid Multiaddr>"), - DEFAULT_ALICE_PEER_ID - .parse() - .expect("default alice peer id str is a valid PeerId"), - config, - bitcoin_network, - monero_network, - &wallet_data_dir, - seed, - monero_wallet_rpc_process.endpoint(), - db, - execution_params, - ) - .await?; - } - Some(Command::History) => { + Command::History => { let mut table = Table::new(); table.add_row(row!["SWAP ID", "STATE"]); @@ -130,11 +143,11 @@ async fn main() -> Result<()> { // Print the table to stdout table.printstd(); } - Some(Command::Resume { + Command::Resume { swap_id, alice_peer_id, alice_addr, - }) => { + } => { let (bitcoin_wallet, monero_wallet) = init_wallets( config, bitcoin_network, @@ -160,12 +173,12 @@ async fn main() -> Result<()> { tokio::spawn(async move { event_loop.run().await }); bob::run(swap).await?; } - Some(Command::Cancel { + Command::Cancel { swap_id, alice_peer_id, alice_addr, force, - }) => { + } => { // TODO: Optimization: Only init the Bitcoin wallet, Monero wallet unnecessary let (bitcoin_wallet, monero_wallet) = init_wallets( config, @@ -212,12 +225,12 @@ async fn main() -> Result<()> { } } } - Some(Command::Refund { + Command::Refund { swap_id, alice_peer_id, alice_addr, force, - }) => { + } => { let (bitcoin_wallet, monero_wallet) = init_wallets( config, bitcoin_network, @@ -321,65 +334,3 @@ async fn init_wallets( Ok((bitcoin_wallet, monero_wallet)) } - -#[allow(clippy::too_many_arguments)] -async fn buy_xmr( - alice_addr: Multiaddr, - alice_peer_id: PeerId, - config: Config, - bitcoin_network: bitcoin::Network, - monero_network: monero::Network, - wallet_data_dir: &Path, - seed: Seed, - monero_wallet_rpc_url: Url, - db: Database, - execution_params: ExecutionParams, -) -> Result<()> { - let (bitcoin_wallet, monero_wallet) = init_wallets( - config, - bitcoin_network, - wallet_data_dir, - monero_network, - seed, - monero_wallet_rpc_url, - ) - .await?; - - let swap_id = Uuid::new_v4(); - - // TODO: Also wait for more funds if balance < dust - if bitcoin_wallet.balance().await? == Amount::ZERO { - debug!( - "Waiting for BTC at address {}", - bitcoin_wallet.new_address().await? - ); - - while bitcoin_wallet.balance().await? == Amount::ZERO { - bitcoin_wallet.sync_wallet().await?; - - tokio::time::sleep(Duration::from_secs(1)).await; - } - - debug!("Received {}", bitcoin_wallet.balance().await?); - } - - let send_bitcoin = bitcoin_wallet.max_giveable().await?; - - info!("Swapping {} ...", send_bitcoin); - - let bob_factory = Builder::new( - seed, - db, - swap_id, - Arc::new(bitcoin_wallet), - Arc::new(monero_wallet), - alice_addr, - alice_peer_id, - execution_params, - ); - let (swap, event_loop) = bob_factory.with_init_params(send_bitcoin).build().await?; - - tokio::spawn(async move { event_loop.run().await }); - bob::run(swap).await?; - Ok(()) -} diff --git a/swap/src/cli/command.rs b/swap/src/cli/command.rs index a263a0db..41880be2 100644 --- a/swap/src/cli/command.rs +++ b/swap/src/cli/command.rs @@ -84,3 +84,16 @@ pub enum Command { force: bool, }, } + +impl Default for Command { + fn default() -> Self { + Self::BuyXmr { + alice_peer_id: DEFAULT_ALICE_PEER_ID + .parse() + .expect("default alice peer id str is a valid Multiaddr>"), + alice_addr: DEFAULT_ALICE_MULTIADDR + .parse() + .expect("default alice multiaddr str is a valid PeerId"), + } + } +} From 975d604405f56e85942e01c26161e64c76cee933 Mon Sep 17 00:00:00 2001 From: rishflab Date: Mon, 1 Mar 2021 11:00:30 +1100 Subject: [PATCH 4/4] Test to ensure default alice peer id and multi addr is valid --- swap/src/cli/command.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/swap/src/cli/command.rs b/swap/src/cli/command.rs index 41880be2..ae859cf1 100644 --- a/swap/src/cli/command.rs +++ b/swap/src/cli/command.rs @@ -97,3 +97,28 @@ impl Default for Command { } } } + +#[cfg(test)] +mod tests { + use crate::cli::command::{Command, DEFAULT_ALICE_MULTIADDR, DEFAULT_ALICE_PEER_ID}; + use libp2p::{core::Multiaddr, PeerId}; + + #[test] + fn parse_default_alice_peer_id_success() { + DEFAULT_ALICE_PEER_ID + .parse::() + .expect("default alice peer id str is a valid PeerId"); + } + + #[test] + fn parse_default_alice_multiaddr_success() { + DEFAULT_ALICE_MULTIADDR + .parse::() + .expect("default alice multiaddr str is a valid Multiaddr>"); + } + + #[test] + fn default_command_success() { + Command::default(); + } +}