@ -1,38 +1,236 @@
use crate ::env ::GetConfig ;
use crate ::fs ::system_data_dir ;
use crate ::{ env , monero } ;
use anyhow ::{ Context , Result } ;
use libp2p ::core ::Multiaddr ;
use libp2p ::PeerId ;
use std ::path ::{ Path , PathBuf } ;
use std ::ffi ::OsString ;
use std ::path ::PathBuf ;
use std ::str ::FromStr ;
use structopt ::StructOpt ;
use url ::Url ;
use uuid ::Uuid ;
pub const DEFAULT_STAGENET_MONERO_DAEMON_ADDRESS : & str = "monero-stagenet.exan.tech:38081" ;
// See: https://moneroworld.com/
pub const DEFAULT_MONERO_DAEMON_ADDRESS : & str = "node.moneroworld.com:18089" ;
pub const DEFAULT_MONERO_DAEMON_ADDRESS_STAGENET : & str = "monero-stagenet.exan.tech:38081" ;
const DEFAULT_ELECTRUM_RPC_URL : & str = "ssl://electrum.blockstream.info:60002" ;
const DEFAULT_BITCOIN_CONFIRMATION_TARGET : & str = "3" ;
// See: https://1209k.com/bitcoin-eye/ele.php?chain=btc
const DEFAULT_ELECTRUM_RPC_URL : & str = "ssl://electrum.blockstream.info:50002" ;
// See: https://1209k.com/bitcoin-eye/ele.php?chain=tbtc
pub const DEFAULT_ELECTRUM_RPC_URL_TESTNET : & str = "ssl://electrum.blockstream.info:60002" ;
const DEFAULT_BITCOIN_CONFIRMATION_TARGET : usize = 3 ;
const DEFAULT_BITCOIN_CONFIRMATION_TARGET_TESTNET : usize = 1 ;
const DEFAULT_TOR_SOCKS5_PORT : & str = "9050" ;
#[ derive(Debug, PartialEq) ]
pub struct Arguments {
pub env_config : env ::Config ,
pub debug : bool ,
pub data_dir : PathBuf ,
pub cmd : Command ,
}
pub fn parse_args_and_apply_defaults < I , T > ( raw_args : I ) -> Result < Arguments >
where
I : IntoIterator < Item = T > ,
T : Into < OsString > + Clone ,
{
let matches = RawArguments ::clap ( ) . get_matches_from_safe ( raw_args ) ? ;
let args = RawArguments ::from_clap ( & matches ) ;
let debug = args . debug ;
let is_testnet = args . testnet ;
let data = args . data ;
match args . cmd {
RawCommand ::BuyXmr {
seller_peer_id ,
seller_addr : SellerAddr { seller_addr } ,
bitcoin :
Bitcoin {
bitcoin_electrum_rpc_url ,
bitcoin_target_block ,
} ,
monero :
Monero {
monero_receive_address ,
monero_daemon_address ,
} ,
tor : Tor { tor_socks5_port } ,
} = > Ok ( Arguments {
env_config : env_config_from ( is_testnet ) ,
debug ,
data_dir : data ::data_dir_from ( data , is_testnet ) ? ,
cmd : Command ::BuyXmr {
seller_peer_id ,
seller_addr ,
bitcoin_electrum_rpc_url : bitcoin_electrum_rpc_url_from (
bitcoin_electrum_rpc_url ,
is_testnet ,
) ? ,
bitcoin_target_block : bitcoin_target_block_from ( bitcoin_target_block , is_testnet ) ,
monero_receive_address : validate_monero_address (
monero_receive_address ,
is_testnet ,
) ? ,
monero_daemon_address : monero_daemon_address_from (
monero_daemon_address ,
is_testnet ,
) ,
tor_socks5_port ,
} ,
} ) ,
RawCommand ::History = > Ok ( Arguments {
env_config : env_config_from ( is_testnet ) ,
debug ,
data_dir : data ::data_dir_from ( data , is_testnet ) ? ,
cmd : Command ::History ,
} ) ,
RawCommand ::Resume {
swap_id : SwapId { swap_id } ,
seller_addr : SellerAddr { seller_addr } ,
bitcoin :
Bitcoin {
bitcoin_electrum_rpc_url ,
bitcoin_target_block ,
} ,
monero :
Monero {
monero_receive_address ,
monero_daemon_address ,
} ,
tor : Tor { tor_socks5_port } ,
} = > Ok ( Arguments {
env_config : env_config_from ( is_testnet ) ,
debug ,
data_dir : data ::data_dir_from ( data , is_testnet ) ? ,
cmd : Command ::Resume {
swap_id ,
seller_addr ,
bitcoin_electrum_rpc_url : bitcoin_electrum_rpc_url_from (
bitcoin_electrum_rpc_url ,
is_testnet ,
) ? ,
bitcoin_target_block : bitcoin_target_block_from ( bitcoin_target_block , is_testnet ) ,
monero_receive_address ,
monero_daemon_address : monero_daemon_address_from (
monero_daemon_address ,
is_testnet ,
) ,
tor_socks5_port ,
} ,
} ) ,
RawCommand ::Cancel {
swap_id : SwapId { swap_id } ,
force ,
bitcoin :
Bitcoin {
bitcoin_electrum_rpc_url ,
bitcoin_target_block ,
} ,
} = > Ok ( Arguments {
env_config : env_config_from ( is_testnet ) ,
debug ,
data_dir : data ::data_dir_from ( data , is_testnet ) ? ,
cmd : Command ::Cancel {
swap_id ,
force ,
bitcoin_electrum_rpc_url : bitcoin_electrum_rpc_url_from (
bitcoin_electrum_rpc_url ,
is_testnet ,
) ? ,
bitcoin_target_block : bitcoin_target_block_from ( bitcoin_target_block , is_testnet ) ,
} ,
} ) ,
RawCommand ::Refund {
swap_id : SwapId { swap_id } ,
force ,
bitcoin :
Bitcoin {
bitcoin_electrum_rpc_url ,
bitcoin_target_block ,
} ,
} = > Ok ( Arguments {
env_config : env_config_from ( is_testnet ) ,
debug ,
data_dir : data ::data_dir_from ( data , is_testnet ) ? ,
cmd : Command ::Refund {
swap_id ,
force ,
bitcoin_electrum_rpc_url : bitcoin_electrum_rpc_url_from (
bitcoin_electrum_rpc_url ,
is_testnet ,
) ? ,
bitcoin_target_block : bitcoin_target_block_from ( bitcoin_target_block , is_testnet ) ,
} ,
} ) ,
}
}
#[ derive(Debug, PartialEq) ]
pub enum Command {
BuyXmr {
seller_peer_id : PeerId ,
seller_addr : Multiaddr ,
bitcoin_electrum_rpc_url : Url ,
bitcoin_target_block : usize ,
monero_receive_address : monero ::Address ,
monero_daemon_address : String ,
tor_socks5_port : u16 ,
} ,
History ,
Resume {
swap_id : Uuid ,
seller_addr : Multiaddr ,
bitcoin_electrum_rpc_url : Url ,
bitcoin_target_block : usize ,
monero_receive_address : monero ::Address ,
monero_daemon_address : String ,
tor_socks5_port : u16 ,
} ,
Cancel {
swap_id : Uuid ,
force : bool ,
bitcoin_electrum_rpc_url : Url ,
bitcoin_target_block : usize ,
} ,
Refund {
swap_id : Uuid ,
force : bool ,
bitcoin_electrum_rpc_url : Url ,
bitcoin_target_block : usize ,
} ,
}
#[ derive(structopt::StructOpt, Debug) ]
#[ structopt(name = " swap " , about = " CLI for swapping BTC for XMR " , author) ]
pub struct Arguments {
pub struct RawArguments {
// global is necessary to ensure that clap can match against testnet in subcommands
#[ structopt(
long ,
help = "Swap on testnet and assume testnet defaults for data-dir and the blockchain related parameters" ,
global = true
) ]
pub testnet : bool ,
#[ structopt(
long = "--data-dir" ,
help = "Provide the data directory path to be used to store application data" ,
default_value
help = "Provide the data directory path to be used to store application data using testnet and mainnet as subfolder"
) ]
pub data : Data ,
pub data : Option < PathBuf > ,
#[ structopt(long, help = " Activate debug logging. " ) ]
pub debug : bool ,
#[ structopt(subcommand) ]
pub cmd : Command ,
pub cmd : Raw Command,
}
#[ derive(structopt::StructOpt, Debug) ]
pub enum Command {
pub enum Raw Command {
/// Start a XMR for BTC swap
BuyXmr {
#[ structopt(long = " seller-peer-id " , help = " The seller's peer id " ) ]
@ -99,31 +297,34 @@ pub struct Monero {
help = "Provide the monero address where you would like to receive monero" ,
parse ( try_from_str = parse_monero_address )
) ]
pub receive_monero _address: monero ::Address ,
pub monero_ receive_address: monero ::Address ,
#[ structopt(
long = "monero-daemon-address" ,
help = "Specify to connect to a monero daemon of your choice: <host>:<port>" ,
default_value = DEFAULT_STAGENET_MONERO_DAEMON_ADDRESS
help = "Specify to connect to a monero daemon of your choice: <host>:<port>"
) ]
pub monero_daemon_address : String,
pub monero_daemon_address : Option< String> ,
}
#[ derive(structopt::StructOpt, Debug) ]
pub struct Bitcoin {
#[ structopt(long = " electrum-rpc " ,
help = "Provide the Bitcoin Electrum RPC URL" ,
default_value = DEFAULT_ELECTRUM_RPC_URL
) ]
pub electrum_rpc_url : Url ,
#[ structopt(long = " electrum-rpc " , help = " Provide the Bitcoin Electrum RPC URL " ) ]
pub bitcoin_electrum_rpc_url : Option < Url > ,
#[ structopt(long = " bitcoin-target-block " , help = " Within how many blocks should the Bitcoin transactions be confirmed. " , default_value = DEFAULT_BITCOIN_CONFIRMATION_TARGET) ]
pub bitcoin_target_block : usize ,
#[ structopt(
long = "bitcoin-target-block" ,
help = "Use for fee estimation, decides within how many blocks the Bitcoin transactions should be confirmed."
) ]
pub bitcoin_target_block : Option < usize > ,
}
#[ derive(structopt::StructOpt, Debug) ]
pub struct Tor {
#[ structopt(long = " tor-socks5-port " , help = " Your local Tor socks5 proxy port " , default_value = DEFAULT_TOR_SOCKS5_PORT) ]
#[ structopt(
long = "tor-socks5-port" ,
help = "Your local Tor socks5 proxy port" ,
default_value = DEFAULT_TOR_SOCKS5_PORT
) ]
pub tor_socks5_port : u16 ,
}
@ -142,39 +343,92 @@ pub struct SellerAddr {
pub seller_addr : Multiaddr ,
}
#[ derive(Clone, Debug) ]
pub struct Data ( pub PathBuf ) ;
mod data {
use super ::* ;
/// Default location for storing data for the CLI
// Takes the default system data-dir and adds a `/cli`
impl Default for Data {
fn default ( ) -> Self {
Data (
system_data_dir ( )
. map ( | proj_dir | Path ::join ( & proj_dir , "cli" ) )
. expect ( "computed valid path for data dir" ) ,
)
pub fn data_dir_from ( arg_dir : Option < PathBuf > , testnet : bool ) -> Result < PathBuf > {
let dir = if let Some ( dir ) = arg_dir {
dir
} else if testnet {
testnet_default ( ) ?
} else {
mainnet_default ( ) ?
} ;
Ok ( dir )
}
fn testnet_default ( ) -> Result < PathBuf > {
Ok ( os_default ( ) ? . join ( "testnet" ) )
}
fn mainnet_default ( ) -> Result < PathBuf > {
Ok ( os_default ( ) ? . join ( "mainnet" ) )
}
fn os_default ( ) -> Result < PathBuf > {
Ok ( system_data_dir ( ) ? . join ( "cli" ) )
}
}
impl FromStr for Data {
type Err = core ::convert ::Infallible ;
fn bitcoin_electrum_rpc_url_from ( url : Option < Url > , testnet : bool ) -> Result < Url > {
if let Some ( url ) = url {
Ok ( url )
} else if testnet {
Ok ( Url ::from_str ( DEFAULT_ELECTRUM_RPC_URL_TESTNET ) ? )
} else {
Ok ( Url ::from_str ( DEFAULT_ELECTRUM_RPC_URL ) ? )
}
}
fn bitcoin_target_block_from ( target_block : Option < usize > , testnet : bool ) -> usize {
if let Some ( target_block ) = target_block {
target_block
} else if testnet {
DEFAULT_BITCOIN_CONFIRMATION_TARGET_TESTNET
} else {
DEFAULT_BITCOIN_CONFIRMATION_TARGET
}
}
fn from_str ( s : & str ) -> Result < Self , Self ::Err > {
Ok ( Data ( PathBuf ::from_str ( s ) ? ) )
fn monero_daemon_address_from ( address : Option < String > , testnet : bool ) -> String {
if let Some ( address ) = address {
address
} else if testnet {
DEFAULT_MONERO_DAEMON_ADDRESS_STAGENET . to_string ( )
} else {
DEFAULT_MONERO_DAEMON_ADDRESS . to_string ( )
}
}
impl ToString for Data {
fn to_string ( & self ) -> String {
self . 0
. clone ( )
. into_os_string ( )
. into_string ( )
. expect ( "default datadir to be convertible to string" )
fn env_config_from ( testnet : bool ) -> env ::Config {
if testnet {
env ::Testnet ::get_config ( )
} else {
env ::Mainnet ::get_config ( )
}
}
fn validate_monero_address (
address : monero ::Address ,
testnet : bool ,
) -> Result < monero ::Address , MoneroAddressNetworkMismatch > {
let expected_network = if testnet {
monero ::Network ::Stagenet
} else {
monero ::Network ::Mainnet
} ;
if address . network ! = expected_network {
return Err ( MoneroAddressNetworkMismatch {
expected : expected_network ,
actual : address . network ,
} ) ;
}
Ok ( address )
}
fn parse_monero_address ( s : & str ) -> Result < monero ::Address > {
monero ::Address ::from_str ( s ) . with_context ( | | {
format! (
@ -183,3 +437,479 @@ fn parse_monero_address(s: &str) -> Result<monero::Address> {
)
} )
}
#[ derive(thiserror::Error, Debug, Clone, Copy, PartialEq) ]
#[ error( " Invalid monero address provided, expected address on network {expected:?} but address provided is on {actual:?} " ) ]
pub struct MoneroAddressNetworkMismatch {
expected : monero ::Network ,
actual : monero ::Network ,
}
#[ cfg(test) ]
mod tests {
use super ::* ;
use crate ::tor ::DEFAULT_SOCKS5_PORT ;
const BINARY_NAME : & str = "swap" ;
const TESTNET : & str = "testnet" ;
const MAINNET : & str = "mainnet" ;
const MONERO_STAGENET_ADDRESS : & str = "53gEuGZUhP9JMEBZoGaFNzhwEgiG7hwQdMCqFxiyiTeFPmkbt1mAoNybEUvYBKHcnrSgxnVWgZsTvRBaHBNXPa8tHiCU51a" ;
const MONERO_MAINNET_ADDRESS : & str = "44Ato7HveWidJYUAVw5QffEcEtSH1DwzSP3FPPkHxNAS4LX9CqgucphTisH978FLHE34YNEx7FcbBfQLQUU8m3NUC4VqsRa" ;
const MUTLI_ADDRESS : & str = "/ip4/127.0.0.1/tcp/9939" ;
const PEER_ID : & str = "12D3KooWCdMKjesXMJz1SiZ7HgotrxuqhQJbP5sgBm2BwP1cqThi" ;
const SWAP_ID : & str = "ea030832-3be9-454f-bb98-5ea9a788406b" ;
#[ test ]
fn given_buy_xmr_on_mainnet_then_defaults_to_mainnet ( ) {
let raw_ars = vec! [
BINARY_NAME ,
"buy-xmr" ,
"--receive-address" ,
MONERO_MAINNET_ADDRESS ,
"--seller-addr" ,
MUTLI_ADDRESS ,
"--seller-peer-id" ,
PEER_ID ,
] ;
let expected_args = Arguments ::buy_xmr_mainnet_defaults ( ) ;
let args = parse_args_and_apply_defaults ( raw_ars ) . unwrap ( ) ;
assert_eq! ( expected_args , args ) ;
}
#[ test ]
fn given_buy_xmr_on_testnet_then_defaults_to_testnet ( ) {
let raw_ars = vec! [
BINARY_NAME ,
"--testnet" ,
"buy-xmr" ,
"--receive-address" ,
MONERO_STAGENET_ADDRESS ,
"--seller-addr" ,
MUTLI_ADDRESS ,
"--seller-peer-id" ,
PEER_ID ,
] ;
let args = parse_args_and_apply_defaults ( raw_ars ) . unwrap ( ) ;
assert_eq! ( args , Arguments ::buy_xmr_testnet_defaults ( ) ) ;
}
#[ test ]
fn given_buy_xmr_on_mainnet_with_testnet_address_then_fails ( ) {
let raw_ars = vec! [
BINARY_NAME ,
"buy-xmr" ,
"--receive-address" ,
MONERO_STAGENET_ADDRESS ,
"--seller-addr" ,
MUTLI_ADDRESS ,
"--seller-peer-id" ,
PEER_ID ,
] ;
let err = parse_args_and_apply_defaults ( raw_ars ) . unwrap_err ( ) ;
assert_eq! (
err . downcast_ref ::< MoneroAddressNetworkMismatch > ( ) . unwrap ( ) ,
& MoneroAddressNetworkMismatch {
expected : monero ::Network ::Mainnet ,
actual : monero ::Network ::Stagenet
}
) ;
}
#[ test ]
fn given_buy_xmr_on_testnet_with_mainnet_address_then_fails ( ) {
let raw_ars = vec! [
BINARY_NAME ,
"--testnet" ,
"buy-xmr" ,
"--receive-address" ,
MONERO_MAINNET_ADDRESS ,
"--seller-addr" ,
MUTLI_ADDRESS ,
"--seller-peer-id" ,
PEER_ID ,
] ;
let err = parse_args_and_apply_defaults ( raw_ars ) . unwrap_err ( ) ;
assert_eq! (
err . downcast_ref ::< MoneroAddressNetworkMismatch > ( ) . unwrap ( ) ,
& MoneroAddressNetworkMismatch {
expected : monero ::Network ::Stagenet ,
actual : monero ::Network ::Mainnet
}
) ;
}
#[ test ]
fn given_resume_on_mainnet_then_defaults_to_mainnet ( ) {
let raw_ars = vec! [
BINARY_NAME ,
"resume" ,
"--swap-id" ,
SWAP_ID ,
"--receive-address" ,
MONERO_MAINNET_ADDRESS ,
"--seller-addr" ,
MUTLI_ADDRESS ,
] ;
let args = parse_args_and_apply_defaults ( raw_ars ) . unwrap ( ) ;
assert_eq! ( args , Arguments ::resume_mainnet_defaults ( ) ) ;
}
#[ test ]
fn given_resume_on_testnet_then_defaults_to_testnet ( ) {
let raw_ars = vec! [
BINARY_NAME ,
"--testnet" ,
"resume" ,
"--swap-id" ,
SWAP_ID ,
"--receive-address" ,
MONERO_STAGENET_ADDRESS ,
"--seller-addr" ,
MUTLI_ADDRESS ,
] ;
let args = parse_args_and_apply_defaults ( raw_ars ) . unwrap ( ) ;
assert_eq! ( args , Arguments ::resume_testnet_defaults ( ) ) ;
}
#[ test ]
fn given_cancel_on_mainnet_then_defaults_to_mainnet ( ) {
let raw_ars = vec! [ BINARY_NAME , "cancel" , "--swap-id" , SWAP_ID ] ;
let args = parse_args_and_apply_defaults ( raw_ars ) . unwrap ( ) ;
assert_eq! ( args , Arguments ::cancel_mainnet_defaults ( ) ) ;
}
#[ test ]
fn given_cancel_on_testnet_then_defaults_to_testnet ( ) {
let raw_ars = vec! [ BINARY_NAME , "--testnet" , "cancel" , "--swap-id" , SWAP_ID ] ;
let args = parse_args_and_apply_defaults ( raw_ars ) . unwrap ( ) ;
assert_eq! ( args , Arguments ::cancel_testnet_defaults ( ) ) ;
}
#[ test ]
fn given_refund_on_mainnet_then_defaults_to_mainnet ( ) {
let raw_ars = vec! [ BINARY_NAME , "refund" , "--swap-id" , SWAP_ID ] ;
let args = parse_args_and_apply_defaults ( raw_ars ) . unwrap ( ) ;
assert_eq! ( args , Arguments ::refund_mainnet_defaults ( ) ) ;
}
#[ test ]
fn given_refund_on_testnet_then_defaults_to_testnet ( ) {
let raw_ars = vec! [ BINARY_NAME , "--testnet" , "refund" , "--swap-id" , SWAP_ID ] ;
let args = parse_args_and_apply_defaults ( raw_ars ) . unwrap ( ) ;
assert_eq! ( args , Arguments ::refund_testnet_defaults ( ) ) ;
}
#[ test ]
fn given_with_data_dir_then_data_dir_set ( ) {
let data_dir = "/some/path/to/dir" ;
let raw_ars = vec! [
BINARY_NAME ,
"--data-dir" ,
data_dir ,
"buy-xmr" ,
"--receive-address" ,
MONERO_MAINNET_ADDRESS ,
"--seller-addr" ,
MUTLI_ADDRESS ,
"--seller-peer-id" ,
PEER_ID ,
] ;
let args = parse_args_and_apply_defaults ( raw_ars ) . unwrap ( ) ;
assert_eq! (
args ,
Arguments ::buy_xmr_mainnet_defaults ( )
. with_data_dir ( PathBuf ::from_str ( data_dir ) . unwrap ( ) )
) ;
let raw_ars = vec! [
BINARY_NAME ,
"--testnet" ,
"--data-dir" ,
data_dir ,
"buy-xmr" ,
"--receive-address" ,
MONERO_STAGENET_ADDRESS ,
"--seller-addr" ,
MUTLI_ADDRESS ,
"--seller-peer-id" ,
PEER_ID ,
] ;
let args = parse_args_and_apply_defaults ( raw_ars ) . unwrap ( ) ;
assert_eq! (
args ,
Arguments ::buy_xmr_testnet_defaults ( )
. with_data_dir ( PathBuf ::from_str ( data_dir ) . unwrap ( ) )
) ;
let raw_ars = vec! [
BINARY_NAME ,
"--data-dir" ,
data_dir ,
"resume" ,
"--swap-id" ,
SWAP_ID ,
"--receive-address" ,
MONERO_MAINNET_ADDRESS ,
"--seller-addr" ,
MUTLI_ADDRESS ,
] ;
let args = parse_args_and_apply_defaults ( raw_ars ) . unwrap ( ) ;
assert_eq! (
args ,
Arguments ::resume_mainnet_defaults ( )
. with_data_dir ( PathBuf ::from_str ( data_dir ) . unwrap ( ) )
) ;
let raw_ars = vec! [
BINARY_NAME ,
"--testnet" ,
"--data-dir" ,
data_dir ,
"resume" ,
"--swap-id" ,
SWAP_ID ,
"--receive-address" ,
MONERO_STAGENET_ADDRESS ,
"--seller-addr" ,
MUTLI_ADDRESS ,
] ;
let args = parse_args_and_apply_defaults ( raw_ars ) . unwrap ( ) ;
assert_eq! (
args ,
Arguments ::resume_testnet_defaults ( )
. with_data_dir ( PathBuf ::from_str ( data_dir ) . unwrap ( ) )
) ;
}
#[ test ]
fn given_with_debug_then_debug_set ( ) {
let raw_ars = vec! [
BINARY_NAME ,
"--debug" ,
"buy-xmr" ,
"--receive-address" ,
MONERO_MAINNET_ADDRESS ,
"--seller-addr" ,
MUTLI_ADDRESS ,
"--seller-peer-id" ,
PEER_ID ,
] ;
let args = parse_args_and_apply_defaults ( raw_ars ) . unwrap ( ) ;
assert_eq! ( args , Arguments ::buy_xmr_mainnet_defaults ( ) . with_debug ( ) ) ;
let raw_ars = vec! [
BINARY_NAME ,
"--testnet" ,
"--debug" ,
"buy-xmr" ,
"--receive-address" ,
MONERO_STAGENET_ADDRESS ,
"--seller-addr" ,
MUTLI_ADDRESS ,
"--seller-peer-id" ,
PEER_ID ,
] ;
let args = parse_args_and_apply_defaults ( raw_ars ) . unwrap ( ) ;
assert_eq! ( args , Arguments ::buy_xmr_testnet_defaults ( ) . with_debug ( ) ) ;
let raw_ars = vec! [
BINARY_NAME ,
"--debug" ,
"resume" ,
"--swap-id" ,
SWAP_ID ,
"--receive-address" ,
MONERO_MAINNET_ADDRESS ,
"--seller-addr" ,
MUTLI_ADDRESS ,
] ;
let args = parse_args_and_apply_defaults ( raw_ars ) . unwrap ( ) ;
assert_eq! ( args , Arguments ::resume_mainnet_defaults ( ) . with_debug ( ) ) ;
let raw_ars = vec! [
BINARY_NAME ,
"--testnet" ,
"--debug" ,
"resume" ,
"--swap-id" ,
SWAP_ID ,
"--receive-address" ,
MONERO_STAGENET_ADDRESS ,
"--seller-addr" ,
MUTLI_ADDRESS ,
] ;
let args = parse_args_and_apply_defaults ( raw_ars ) . unwrap ( ) ;
assert_eq! ( args , Arguments ::resume_testnet_defaults ( ) . with_debug ( ) ) ;
}
impl Arguments {
pub fn buy_xmr_testnet_defaults ( ) -> Self {
Self {
env_config : env ::Testnet ::get_config ( ) ,
debug : false ,
data_dir : data_dir_path_cli ( ) . join ( TESTNET ) ,
cmd : Command ::BuyXmr {
seller_peer_id : PeerId ::from_str ( PEER_ID ) . unwrap ( ) ,
seller_addr : Multiaddr ::from_str ( MUTLI_ADDRESS ) . unwrap ( ) ,
bitcoin_electrum_rpc_url : Url ::from_str ( DEFAULT_ELECTRUM_RPC_URL_TESTNET )
. unwrap ( ) ,
bitcoin_target_block : DEFAULT_BITCOIN_CONFIRMATION_TARGET_TESTNET ,
monero_receive_address : monero ::Address ::from_str ( MONERO_STAGENET_ADDRESS )
. unwrap ( ) ,
monero_daemon_address : DEFAULT_MONERO_DAEMON_ADDRESS_STAGENET . to_string ( ) ,
tor_socks5_port : DEFAULT_SOCKS5_PORT ,
} ,
}
}
pub fn buy_xmr_mainnet_defaults ( ) -> Self {
Self {
env_config : env ::Mainnet ::get_config ( ) ,
debug : false ,
data_dir : data_dir_path_cli ( ) . join ( MAINNET ) ,
cmd : Command ::BuyXmr {
seller_peer_id : PeerId ::from_str ( PEER_ID ) . unwrap ( ) ,
seller_addr : Multiaddr ::from_str ( MUTLI_ADDRESS ) . unwrap ( ) ,
bitcoin_electrum_rpc_url : Url ::from_str ( DEFAULT_ELECTRUM_RPC_URL ) . unwrap ( ) ,
bitcoin_target_block : DEFAULT_BITCOIN_CONFIRMATION_TARGET ,
monero_receive_address : monero ::Address ::from_str ( MONERO_MAINNET_ADDRESS )
. unwrap ( ) ,
monero_daemon_address : DEFAULT_MONERO_DAEMON_ADDRESS . to_string ( ) ,
tor_socks5_port : DEFAULT_SOCKS5_PORT ,
} ,
}
}
pub fn resume_testnet_defaults ( ) -> Self {
Self {
env_config : env ::Testnet ::get_config ( ) ,
debug : false ,
data_dir : data_dir_path_cli ( ) . join ( TESTNET ) ,
cmd : Command ::Resume {
swap_id : Uuid ::from_str ( SWAP_ID ) . unwrap ( ) ,
seller_addr : Multiaddr ::from_str ( MUTLI_ADDRESS ) . unwrap ( ) ,
bitcoin_electrum_rpc_url : Url ::from_str ( DEFAULT_ELECTRUM_RPC_URL_TESTNET )
. unwrap ( ) ,
bitcoin_target_block : DEFAULT_BITCOIN_CONFIRMATION_TARGET_TESTNET ,
monero_receive_address : monero ::Address ::from_str ( MONERO_STAGENET_ADDRESS )
. unwrap ( ) ,
monero_daemon_address : DEFAULT_MONERO_DAEMON_ADDRESS_STAGENET . to_string ( ) ,
tor_socks5_port : DEFAULT_SOCKS5_PORT ,
} ,
}
}
pub fn resume_mainnet_defaults ( ) -> Self {
Self {
env_config : env ::Mainnet ::get_config ( ) ,
debug : false ,
data_dir : data_dir_path_cli ( ) . join ( MAINNET ) ,
cmd : Command ::Resume {
swap_id : Uuid ::from_str ( SWAP_ID ) . unwrap ( ) ,
seller_addr : Multiaddr ::from_str ( MUTLI_ADDRESS ) . unwrap ( ) ,
bitcoin_electrum_rpc_url : Url ::from_str ( DEFAULT_ELECTRUM_RPC_URL ) . unwrap ( ) ,
bitcoin_target_block : DEFAULT_BITCOIN_CONFIRMATION_TARGET ,
monero_receive_address : monero ::Address ::from_str ( MONERO_MAINNET_ADDRESS )
. unwrap ( ) ,
monero_daemon_address : DEFAULT_MONERO_DAEMON_ADDRESS . to_string ( ) ,
tor_socks5_port : DEFAULT_SOCKS5_PORT ,
} ,
}
}
pub fn cancel_testnet_defaults ( ) -> Self {
Self {
env_config : env ::Testnet ::get_config ( ) ,
debug : false ,
data_dir : data_dir_path_cli ( ) . join ( TESTNET ) ,
cmd : Command ::Cancel {
swap_id : Uuid ::from_str ( SWAP_ID ) . unwrap ( ) ,
force : false ,
bitcoin_electrum_rpc_url : Url ::from_str ( DEFAULT_ELECTRUM_RPC_URL_TESTNET )
. unwrap ( ) ,
bitcoin_target_block : DEFAULT_BITCOIN_CONFIRMATION_TARGET_TESTNET ,
} ,
}
}
pub fn cancel_mainnet_defaults ( ) -> Self {
Self {
env_config : env ::Mainnet ::get_config ( ) ,
debug : false ,
data_dir : data_dir_path_cli ( ) . join ( MAINNET ) ,
cmd : Command ::Cancel {
swap_id : Uuid ::from_str ( SWAP_ID ) . unwrap ( ) ,
force : false ,
bitcoin_electrum_rpc_url : Url ::from_str ( DEFAULT_ELECTRUM_RPC_URL ) . unwrap ( ) ,
bitcoin_target_block : DEFAULT_BITCOIN_CONFIRMATION_TARGET ,
} ,
}
}
pub fn refund_testnet_defaults ( ) -> Self {
Self {
env_config : env ::Testnet ::get_config ( ) ,
debug : false ,
data_dir : data_dir_path_cli ( ) . join ( TESTNET ) ,
cmd : Command ::Refund {
swap_id : Uuid ::from_str ( SWAP_ID ) . unwrap ( ) ,
force : false ,
bitcoin_electrum_rpc_url : Url ::from_str ( DEFAULT_ELECTRUM_RPC_URL_TESTNET )
. unwrap ( ) ,
bitcoin_target_block : DEFAULT_BITCOIN_CONFIRMATION_TARGET_TESTNET ,
} ,
}
}
pub fn refund_mainnet_defaults ( ) -> Self {
Self {
env_config : env ::Mainnet ::get_config ( ) ,
debug : false ,
data_dir : data_dir_path_cli ( ) . join ( MAINNET ) ,
cmd : Command ::Refund {
swap_id : Uuid ::from_str ( SWAP_ID ) . unwrap ( ) ,
force : false ,
bitcoin_electrum_rpc_url : Url ::from_str ( DEFAULT_ELECTRUM_RPC_URL ) . unwrap ( ) ,
bitcoin_target_block : DEFAULT_BITCOIN_CONFIRMATION_TARGET ,
} ,
}
}
pub fn with_data_dir ( mut self , data_dir : PathBuf ) -> Self {
self . data_dir = data_dir ;
self
}
pub fn with_debug ( mut self ) -> Self {
self . debug = true ;
self
}
}
fn data_dir_path_cli ( ) -> PathBuf {
system_data_dir ( ) . unwrap ( ) . join ( "cli" )
}
}