diff --git a/CHANGELOG.md b/CHANGELOG.md index a6c0c6a5..eaea6a7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 2. Buy amount sent by CLI exceeds maximum buy amount accepted by ASB 3. ASB is running in resume-only mode and does not accept incoming swap requests +### Changed + +- The ASB's `--max-buy` and `ask-spread` parameter were removed in favour of entries in the config file. + The initial setup includes setting these two values now. + ## [0.5.0] - 2021-04-17 ### Changed diff --git a/swap/Cargo.toml b/swap/Cargo.toml index a8819fb4..b236c334 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -40,7 +40,7 @@ proptest = "1" rand = "0.7" rand_chacha = "0.2" reqwest = { version = "0.11", features = [ "rustls-tls", "stream", "socks" ], default-features = false } -rust_decimal = "1" +rust_decimal = { version = "1", features = [ "serde-float" ] } rust_decimal_macros = "1" serde = { version = "1", features = [ "derive" ] } serde_cbor = "0.11" diff --git a/swap/src/asb/command.rs b/swap/src/asb/command.rs index 4ad8e118..3f641653 100644 --- a/swap/src/asb/command.rs +++ b/swap/src/asb/command.rs @@ -1,7 +1,5 @@ use crate::bitcoin::Amount; -use bitcoin::util::amount::ParseAmountError; -use bitcoin::{Address, Denomination}; -use rust_decimal::Decimal; +use bitcoin::Address; use std::path::PathBuf; use uuid::Uuid; @@ -28,15 +26,6 @@ pub struct Arguments { pub enum Command { #[structopt(about = "Main command to run the ASB.")] Start { - #[structopt(long = "max-buy-btc", help = "The maximum amount of BTC the ASB is willing to buy.", default_value = "0.005", parse(try_from_str = parse_btc))] - max_buy: Amount, - #[structopt( - long = "ask-spread", - help = "The spread in percent that should be applied to the asking price.", - default_value = "0.02" - )] - ask_spread: Decimal, - #[structopt( long = "resume-only", help = "For maintenance only. When set, no new swap requests will be accepted, but existing unfinished swaps will be resumed." @@ -124,7 +113,3 @@ pub struct RecoverCommandParams { )] pub force: bool, } - -fn parse_btc(s: &str) -> Result { - Amount::from_str_in(s, Denomination::Bitcoin) -} diff --git a/swap/src/asb/config.rs b/swap/src/asb/config.rs index accec056..c8859f7e 100644 --- a/swap/src/asb/config.rs +++ b/swap/src/asb/config.rs @@ -1,10 +1,12 @@ use crate::fs::{ensure_directory_exists, system_config_dir, system_data_dir}; use crate::tor::{DEFAULT_CONTROL_PORT, DEFAULT_SOCKS5_PORT}; -use anyhow::{Context, Result}; +use anyhow::{bail, Context, Result}; use config::ConfigError; use dialoguer::theme::ColorfulTheme; use dialoguer::Input; use libp2p::core::Multiaddr; +use rust_decimal::prelude::FromPrimitive; +use rust_decimal::Decimal; use serde::{Deserialize, Serialize}; use std::ffi::OsStr; use std::fs; @@ -18,6 +20,9 @@ const DEFAULT_ELECTRUM_RPC_URL: &str = "ssl://electrum.blockstream.info:60002"; const DEFAULT_MONERO_WALLET_RPC_TESTNET_URL: &str = "http://127.0.0.1:38083/json_rpc"; const DEFAULT_BITCOIN_CONFIRMATION_TARGET: usize = 3; +const DEFAULT_MAX_BUY_AMOUNT: f64 = 0.02f64; +const DEFAULT_SPREAD: f64 = 0.02f64; + #[derive(Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq)] pub struct Config { pub data: Data, @@ -25,6 +30,7 @@ pub struct Config { pub bitcoin: Bitcoin, pub monero: Monero, pub tor: TorConf, + pub maker: Maker, } impl Config { @@ -72,6 +78,14 @@ pub struct TorConf { pub socks5_port: u16, } +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct Maker { + #[serde(with = "::bitcoin::util::amount::serde::as_btc")] + pub max_buy_btc: bitcoin::Amount, + pub ask_spread: Decimal, +} + impl Default for TorConf { fn default() -> Self { Self { @@ -186,6 +200,21 @@ pub fn query_user_for_initial_testnet_config() -> Result { .default(DEFAULT_SOCKS5_PORT.to_owned()) .interact_text()?; + let max_buy = Input::with_theme(&ColorfulTheme::default()) + .with_prompt("Enter maximum Bitcoin amount you are willing to accept per swap or hit enter to use default.") + .default(DEFAULT_MAX_BUY_AMOUNT) + .interact_text()?; + let max_buy = bitcoin::Amount::from_btc(max_buy)?; + + let ask_spread = Input::with_theme(&ColorfulTheme::default()) + .with_prompt("Enter spread (in percent; value between 0.x and 1.0) to be used on top of the market rate or hit enter to use default.") + .default(DEFAULT_SPREAD) + .interact_text()?; + if !(0.0..=1.0).contains(&ask_spread) { + bail!(format!("Invalid spread {}. For the spread value floating point number in interval [0..1] are allowed.", ask_spread)) + } + let ask_spread = Decimal::from_f64(ask_spread).context("Unable to parse spread")?; + println!(); Ok(Config { @@ -204,6 +233,10 @@ pub fn query_user_for_initial_testnet_config() -> Result { control_port: tor_control_port, socks5_port: tor_socks5_port, }, + maker: Maker { + max_buy_btc: max_buy, + ask_spread, + }, }) } @@ -237,6 +270,10 @@ mod tests { wallet_rpc_url: Url::from_str(DEFAULT_MONERO_WALLET_RPC_TESTNET_URL).unwrap(), }, tor: Default::default(), + maker: Maker { + max_buy_btc: bitcoin::Amount::from_btc(DEFAULT_MAX_BUY_AMOUNT).unwrap(), + ask_spread: Decimal::from_f64(DEFAULT_SPREAD).unwrap(), + }, }; initial_setup(config_path.clone(), || Ok(expected.clone())).unwrap(); diff --git a/swap/src/bin/asb.rs b/swap/src/bin/asb.rs index 55158343..927403fd 100644 --- a/swap/src/bin/asb.rs +++ b/swap/src/bin/asb.rs @@ -79,11 +79,7 @@ async fn main() -> Result<()> { let env_config = env::Testnet::get_config(); match opt.cmd { - Command::Start { - max_buy, - ask_spread, - resume_only, - } => { + Command::Start { resume_only } => { let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?; let monero_wallet = init_monero_wallet(&config, env_config).await?; @@ -122,12 +118,12 @@ async fn main() -> Result<()> { let current_balance = monero_wallet.get_balance().await?; let lock_fee = monero_wallet.static_tx_fee_estimate(); - let kraken_rate = KrakenRate::new(ask_spread, kraken_price_updates); + let kraken_rate = KrakenRate::new(config.maker.ask_spread, kraken_price_updates); let mut swarm = swarm::alice( &seed, current_balance, lock_fee, - max_buy, + config.maker.max_buy_btc, kraken_rate.clone(), resume_only, )?; @@ -144,7 +140,7 @@ async fn main() -> Result<()> { Arc::new(monero_wallet), Arc::new(db), kraken_rate, - max_buy, + config.maker.max_buy_btc, ) .unwrap();