Extract `determine_btc_to_swap` function and test it

We also instantiate tracing in to order to quickly validate, what
the output for the different scenarios looks like.
pull/268/head
Thomas Eizinger 3 years ago
parent 601bf07255
commit 14dcd150af
No known key found for this signature in database
GPG Key ID: 651AC83A6C6C8B96

@ -16,6 +16,7 @@ use anyhow::{bail, Context, Result};
use prettytable::{row, Table};
use reqwest::Url;
use std::cmp::min;
use std::future::Future;
use std::path::Path;
use std::sync::Arc;
use std::time::Duration;
@ -25,6 +26,7 @@ use swap::cli::command::{Arguments, Command};
use swap::cli::config::{read_config, Config};
use swap::database::Database;
use swap::execution_params::GetExecutionParams;
use swap::network::quote::BidQuote;
use swap::protocol::bob;
use swap::protocol::bob::cancel::CancelError;
use swap::protocol::bob::{Builder, EventLoop};
@ -124,39 +126,22 @@ async fn main() -> Result<()> {
)?;
let handle = tokio::spawn(event_loop.run());
let bid_quote = event_loop_handle
.request_quote()
.await
.context("failed to request quote")?;
let send_bitcoin = determine_btc_to_swap(
event_loop_handle.request_quote(),
bitcoin_wallet.balance(),
bitcoin_wallet.new_address(),
async {
while bitcoin_wallet.balance().await? == Amount::ZERO {
bitcoin_wallet.sync_wallet().await?;
info!("Received quote: 1 XMR ~ {}", bid_quote.price);
tokio::time::sleep(Duration::from_secs(1)).await;
}
// TODO: Also wait for more funds if balance < dust
if bitcoin_wallet.balance().await? == Amount::ZERO {
info!(
"Please deposit the BTC you want to swap to {} (max {})",
bitcoin_wallet.new_address().await?,
bid_quote.max_quantity
);
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?);
} else {
info!(
"Still got {} left in wallet, swapping ...",
bitcoin_wallet.balance().await?
);
}
let max_giveable = bitcoin_wallet.max_giveable(TxLock::script_size()).await?;
let max_accepted = bid_quote.max_quantity;
let send_bitcoin = min(max_giveable, max_accepted);
bitcoin_wallet.balance().await
},
bitcoin_wallet.max_giveable(TxLock::script_size()),
)
.await?;
let swap = Builder::new(
db,
@ -320,3 +305,133 @@ async fn init_monero_wallet(
Ok(monero_wallet)
}
async fn determine_btc_to_swap(
request_quote: impl Future<Output = Result<BidQuote>>,
initial_balance: impl Future<Output = Result<bitcoin::Amount>>,
get_new_address: impl Future<Output = Result<bitcoin::Address>>,
wait_for_deposit: impl Future<Output = Result<bitcoin::Amount>>,
max_giveable: impl Future<Output = Result<bitcoin::Amount>>,
) -> Result<bitcoin::Amount> {
debug!("Requesting quote");
let bid_quote = request_quote.await.context("failed to request quote")?;
info!("Received quote: 1 XMR ~ {}", bid_quote.price);
// TODO: Also wait for more funds if balance < dust
let initial_balance = initial_balance.await?;
if initial_balance == Amount::ZERO {
info!(
"Please deposit the BTC you want to swap to {} (max {})",
get_new_address.await?,
bid_quote.max_quantity
);
let new_balance = wait_for_deposit.await?;
info!("Received {}", new_balance);
} else {
info!("Found {} in wallet", initial_balance);
}
let max_giveable = max_giveable.await?;
let max_accepted = bid_quote.max_quantity;
if max_giveable > max_accepted {
info!(
"Max giveable amount {} exceeds max accepted amount {}!",
max_giveable, max_accepted
);
}
Ok(min(max_giveable, max_accepted))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::determine_btc_to_swap;
use ::bitcoin::Amount;
use tracing::subscriber;
#[tokio::test]
async fn given_no_balance_and_transfers_less_than_max_swaps_max_giveable() {
let _guard = subscriber::set_default(tracing_subscriber::fmt().with_test_writer().finish());
let amount = determine_btc_to_swap(
async { Ok(quote_with_max(0.01)) },
async { Ok(Amount::ZERO) },
get_dummy_address(),
async { Ok(Amount::from_btc(0.0001)?) },
async { Ok(Amount::from_btc(0.00009)?) },
)
.await
.unwrap();
assert_eq!(amount, Amount::from_btc(0.00009).unwrap())
}
#[tokio::test]
async fn given_no_balance_and_transfers_more_then_swaps_max_quantity_from_quote() {
let _guard = subscriber::set_default(tracing_subscriber::fmt().with_test_writer().finish());
let amount = determine_btc_to_swap(
async { Ok(quote_with_max(0.01)) },
async { Ok(Amount::ZERO) },
get_dummy_address(),
async { Ok(Amount::from_btc(0.1)?) },
async { Ok(Amount::from_btc(0.09)?) },
)
.await
.unwrap();
assert_eq!(amount, Amount::from_btc(0.01).unwrap())
}
#[tokio::test]
async fn given_initial_balance_below_max_quantity_swaps_max_givable() {
let _guard = subscriber::set_default(tracing_subscriber::fmt().with_test_writer().finish());
let amount = determine_btc_to_swap(
async { Ok(quote_with_max(0.01)) },
async { Ok(Amount::from_btc(0.005)?) },
async { panic!("should not request new address when initial balance is > 0") },
async { panic!("should not wait for deposit when initial balance > 0") },
async { Ok(Amount::from_btc(0.0049)?) },
)
.await
.unwrap();
assert_eq!(amount, Amount::from_btc(0.0049).unwrap())
}
#[tokio::test]
async fn given_initial_balance_above_max_quantity_swaps_max_quantity() {
let _guard = subscriber::set_default(tracing_subscriber::fmt().with_test_writer().finish());
let amount = determine_btc_to_swap(
async { Ok(quote_with_max(0.01)) },
async { Ok(Amount::from_btc(0.1)?) },
async { panic!("should not request new address when initial balance is > 0") },
async { panic!("should not wait for deposit when initial balance > 0") },
async { Ok(Amount::from_btc(0.09)?) },
)
.await
.unwrap();
assert_eq!(amount, Amount::from_btc(0.01).unwrap())
}
fn quote_with_max(btc: f64) -> BidQuote {
BidQuote {
price: Amount::from_btc(0.001).unwrap(),
max_quantity: Amount::from_btc(btc).unwrap(),
}
}
async fn get_dummy_address() -> Result<bitcoin::Address> {
Ok("1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6".parse()?)
}
}

@ -23,10 +23,10 @@ pub mod database;
pub mod execution_params;
pub mod fs;
pub mod monero;
pub mod network;
pub mod protocol;
pub mod seed;
pub mod trace;
mod monero_ext;
mod network;
mod serde_peer_id;

Loading…
Cancel
Save