mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-12-17 17:44:02 -05:00
Check if binary is latest version
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.130 to 1.0.133. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.130...v1.0.133) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Add rfc3339 removal changelog entry Bump anyhow from 1.0.51 to 1.0.52 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.51 to 1.0.52. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.51...1.0.52) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Bump serde_json from 1.0.68 to 1.0.74 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.68 to 1.0.74. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.68...v1.0.74) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Fix failing CI tests due to deleted xmrto docker hub images Fix failing CI tests due to deleted xmrto docker hub images by moving to the docker images provided by melotools Bump tempfile from 3.2.0 to 3.3.0 Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/Stebalien/tempfile/releases) - [Changelog](https://github.com/Stebalien/tempfile/blob/master/NEWS) - [Commits](https://github.com/Stebalien/tempfile/compare/v3.2.0...v3.3.0) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Bump tempfile from 3.2.0 to 3.3.0 Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/Stebalien/tempfile/releases) - [Changelog](https://github.com/Stebalien/tempfile/blob/master/NEWS) - [Commits](https://github.com/Stebalien/tempfile/compare/v3.2.0...v3.3.0) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Always write logs as JSON to files Bump torut from 0.2.0 to 0.2.1 Bumps [torut](https://github.com/teawithsand/torut) from 0.2.0 to 0.2.1. - [Release notes](https://github.com/teawithsand/torut/releases) - [Commits](https://github.com/teawithsand/torut/commits) --- updated-dependencies: - dependency-name: torut dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Bump time from 0.3.3 to 0.3.7 Bumps [time](https://github.com/time-rs/time) from 0.3.3 to 0.3.7. - [Release notes](https://github.com/time-rs/time/releases) - [Changelog](https://github.com/time-rs/time/blob/main/CHANGELOG.md) - [Commits](https://github.com/time-rs/time/compare/v0.3.3...v0.3.7) --- updated-dependencies: - dependency-name: time dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Bump tokio from 1.12.0 to 1.16.1 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.12.0 to 1.16.1. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.12.0...tokio-1.16.1) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Bump dialoguer from 0.8.0 to 0.10.0 Bumps [dialoguer](https://github.com/mitsuhiko/dialoguer) from 0.8.0 to 0.10.0. - [Release notes](https://github.com/mitsuhiko/dialoguer/releases) - [Changelog](https://github.com/mitsuhiko/dialoguer/blob/master/CHANGELOG.md) - [Commits](https://github.com/mitsuhiko/dialoguer/compare/0.8.0...v0.10.0) --- updated-dependencies: - dependency-name: dialoguer dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Bump reqwest from 0.11.7 to 0.11.9 Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.11.7 to 0.11.9. - [Release notes](https://github.com/seanmonstar/reqwest/releases) - [Changelog](https://github.com/seanmonstar/reqwest/blob/master/CHANGELOG.md) - [Commits](https://github.com/seanmonstar/reqwest/compare/v0.11.7...v0.11.9) --- updated-dependencies: - dependency-name: reqwest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Bump actions/setup-python from 2.3.1 to 2.3.2 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2.3.1 to 2.3.2. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v2.3.1...v2.3.2) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Adjust quote based on Bitcoin balance Update dependencies and rust-toolchain to 1.59 This commit updates the rust-toolchain to the current stable version 1.59, and fixes a number of new clippy warnings from that change. Other changes: - updates backoff to 0.4 - updates swap to 2021 edition - updates comfy-table to 5.0 - updates monero-wallet to 2021 edition - updates moneor-harness to 2021 edition - updates bdk and rust_decimal - updates tokio-util to 0.7 - updates workflow to use actions/setup-python@3 - updates pem and serde_with - adds stable rust toolchain notice to readme Change to rino nodes Update dprint plugins to fix CI error Bump futures from 0.3.17 to 0.3.21 Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.17 to 0.3.21. - [Release notes](https://github.com/rust-lang/futures-rs/releases) - [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.17...0.3.21) --- updated-dependencies: - dependency-name: futures dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Bump structopt from 0.3.25 to 0.3.26 Bumps [structopt](https://github.com/TeXitoi/structopt) from 0.3.25 to 0.3.26. - [Release notes](https://github.com/TeXitoi/structopt/releases) - [Changelog](https://github.com/TeXitoi/structopt/blob/master/CHANGELOG.md) - [Commits](https://github.com/TeXitoi/structopt/compare/v0.3.25...v0.3.26) --- updated-dependencies: - dependency-name: structopt dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Bump serde from 1.0.133 to 1.0.136 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.133 to 1.0.136. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.133...v1.0.136) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Bump hyper from 0.14.16 to 0.14.18 Bumps [hyper](https://github.com/hyperium/hyper) from 0.14.16 to 0.14.18. - [Release notes](https://github.com/hyperium/hyper/releases) - [Changelog](https://github.com/hyperium/hyper/blob/master/CHANGELOG.md) - [Commits](https://github.com/hyperium/hyper/compare/v0.14.16...v0.14.18) --- updated-dependencies: - dependency-name: hyper dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Inform Bob that he has been punished Reduce required confirmations for Bitcoin transactions from 2 to 1 Don't wait for refund transaction to receive confirmations Don't wait for refund transaction to receive confirmations to mitigate a scenario where the swap is stuck in `BtcCancelled` because it's not resumable. Check if binary is latest version Check if binary is latest version
This commit is contained in:
parent
7d2edbcdb8
commit
8fc9b05a66
36 changed files with 625 additions and 301 deletions
|
|
@ -319,13 +319,46 @@ where
|
|||
min_buy: bitcoin::Amount,
|
||||
max_buy: bitcoin::Amount,
|
||||
) -> Result<BidQuote> {
|
||||
let rate = self
|
||||
let ask_price = self
|
||||
.latest_rate
|
||||
.latest_rate()
|
||||
.context("Failed to get latest rate")?;
|
||||
.context("Failed to get latest rate")?
|
||||
.ask()
|
||||
.context("Failed to compute asking price")?;
|
||||
|
||||
let max_bitcoin_for_monero = self
|
||||
.monero_wallet
|
||||
.get_balance()
|
||||
.await?
|
||||
.max_bitcoin_for_price(ask_price);
|
||||
|
||||
if min_buy > max_bitcoin_for_monero {
|
||||
tracing::warn!(
|
||||
"Your Monero balance is too low to initiate a swap, as your minimum swap amount is {}. You could at most swap {}",
|
||||
min_buy, max_bitcoin_for_monero
|
||||
);
|
||||
|
||||
return Ok(BidQuote {
|
||||
price: ask_price,
|
||||
min_quantity: bitcoin::Amount::ZERO,
|
||||
max_quantity: bitcoin::Amount::ZERO,
|
||||
});
|
||||
}
|
||||
|
||||
if max_buy > max_bitcoin_for_monero {
|
||||
tracing::warn!(
|
||||
"Your Monero balance is too low to initiate a swap with the maximum swap amount {} that you have specified in your config. You can at most swap {}",
|
||||
max_buy, max_bitcoin_for_monero
|
||||
);
|
||||
return Ok(BidQuote {
|
||||
price: ask_price,
|
||||
min_quantity: min_buy,
|
||||
max_quantity: max_bitcoin_for_monero,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(BidQuote {
|
||||
price: rate.ask().context("Failed to compute asking price")?,
|
||||
price: ask_price,
|
||||
min_quantity: min_buy,
|
||||
max_quantity: max_buy,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ use swap::cli::{list_sellers, EventLoop, SellerStatus};
|
|||
use swap::database::open_db;
|
||||
use swap::env::Config;
|
||||
use swap::libp2p_ext::MultiAddrExt;
|
||||
use swap::network::quote::BidQuote;
|
||||
use swap::network::quote::{BidQuote, ZeroQuoteReceived};
|
||||
use swap::network::swarm;
|
||||
use swap::protocol::bob;
|
||||
use swap::protocol::bob::{BobState, Swap};
|
||||
|
|
@ -47,7 +47,7 @@ async fn main() -> Result<()> {
|
|||
json,
|
||||
cmd,
|
||||
} = match parse_args_and_apply_defaults(env::args_os())? {
|
||||
ParseResult::Arguments(args) => args,
|
||||
ParseResult::Arguments(args) => *args,
|
||||
ParseResult::PrintAndExitZero { message } => {
|
||||
println!("{}", message);
|
||||
std::process::exit(0);
|
||||
|
|
@ -67,6 +67,12 @@ async fn main() -> Result<()> {
|
|||
let swap_id = Uuid::new_v4();
|
||||
|
||||
cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?;
|
||||
|
||||
match check_latest_version().await {
|
||||
Ok(()) => (),
|
||||
Err(error) => tracing::error!("{}", error),
|
||||
};
|
||||
|
||||
let db = open_db(data_dir.join("sqlite")).await?;
|
||||
let seed = Seed::from_file_or_generate(data_dir.as_path())
|
||||
.context("Failed to read in seed file")?;
|
||||
|
|
@ -95,11 +101,11 @@ async fn main() -> Result<()> {
|
|||
tracing::debug!(peer_id = %swarm.local_peer_id(), "Network layer initialized");
|
||||
|
||||
let (event_loop, mut event_loop_handle) =
|
||||
EventLoop::new(swap_id, swarm, seller_peer_id, env_config)?;
|
||||
EventLoop::new(swap_id, swarm, seller_peer_id)?;
|
||||
let event_loop = tokio::spawn(event_loop.run());
|
||||
|
||||
let max_givable = || bitcoin_wallet.max_giveable(TxLock::script_size());
|
||||
let (amount, fees) = determine_btc_to_swap(
|
||||
let (amount, fees) = match determine_btc_to_swap(
|
||||
json,
|
||||
event_loop_handle.request_quote(),
|
||||
bitcoin_wallet.new_address(),
|
||||
|
|
@ -107,7 +113,16 @@ async fn main() -> Result<()> {
|
|||
max_givable,
|
||||
|| bitcoin_wallet.sync(),
|
||||
)
|
||||
.await?;
|
||||
.await
|
||||
{
|
||||
Ok(val) => val,
|
||||
Err(error) => match error.downcast::<ZeroQuoteReceived>() {
|
||||
Ok(_) => {
|
||||
bail!("Seller's XMR balance is currently too low to initiate a swap, please try again later")
|
||||
}
|
||||
Err(other) => bail!(other),
|
||||
},
|
||||
};
|
||||
|
||||
tracing::info!(%amount, %fees, "Determined swap amount");
|
||||
|
||||
|
|
@ -140,6 +155,11 @@ async fn main() -> Result<()> {
|
|||
Command::History => {
|
||||
cli::tracing::init(debug, json, data_dir.join("logs"), None)?;
|
||||
|
||||
match check_latest_version().await {
|
||||
Ok(()) => (),
|
||||
Err(error) => tracing::error!("{}", error),
|
||||
};
|
||||
|
||||
let db = open_db(data_dir.join("sqlite")).await?;
|
||||
let swaps = db.all().await?;
|
||||
|
||||
|
|
@ -164,6 +184,11 @@ async fn main() -> Result<()> {
|
|||
Command::Config => {
|
||||
cli::tracing::init(debug, json, data_dir.join("logs"), None)?;
|
||||
|
||||
match check_latest_version().await {
|
||||
Ok(()) => (),
|
||||
Err(error) => tracing::error!("{}", error),
|
||||
};
|
||||
|
||||
tracing::info!(path=%data_dir.display(), "Data directory");
|
||||
tracing::info!(path=%format!("{}/logs", data_dir.display()), "Log files directory");
|
||||
tracing::info!(path=%format!("{}/sqlite", data_dir.display()), "Sqlite file location");
|
||||
|
|
@ -178,6 +203,12 @@ async fn main() -> Result<()> {
|
|||
address,
|
||||
} => {
|
||||
cli::tracing::init(debug, json, data_dir.join("logs"), None)?;
|
||||
|
||||
match check_latest_version().await {
|
||||
Ok(()) => (),
|
||||
Err(error) => tracing::error!("{}", error),
|
||||
};
|
||||
|
||||
let seed = Seed::from_file_or_generate(data_dir.as_path())
|
||||
.context("Failed to read in seed file")?;
|
||||
let bitcoin_wallet = init_bitcoin_wallet(
|
||||
|
|
@ -211,6 +242,12 @@ async fn main() -> Result<()> {
|
|||
bitcoin_target_block,
|
||||
} => {
|
||||
cli::tracing::init(debug, json, data_dir.join("logs"), None)?;
|
||||
|
||||
match check_latest_version().await {
|
||||
Ok(()) => (),
|
||||
Err(error) => tracing::error!("{}", error),
|
||||
};
|
||||
|
||||
let seed = Seed::from_file_or_generate(data_dir.as_path())
|
||||
.context("Failed to read in seed file")?;
|
||||
let bitcoin_wallet = init_bitcoin_wallet(
|
||||
|
|
@ -236,6 +273,12 @@ async fn main() -> Result<()> {
|
|||
tor_socks5_port,
|
||||
} => {
|
||||
cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?;
|
||||
|
||||
match check_latest_version().await {
|
||||
Ok(()) => (),
|
||||
Err(error) => tracing::error!("{}", error),
|
||||
};
|
||||
|
||||
let db = open_db(data_dir.join("sqlite")).await?;
|
||||
let seed = Seed::from_file_or_generate(data_dir.as_path())
|
||||
.context("Failed to read in seed file")?;
|
||||
|
|
@ -267,8 +310,7 @@ async fn main() -> Result<()> {
|
|||
.add_address(seller_peer_id, seller_address);
|
||||
}
|
||||
|
||||
let (event_loop, event_loop_handle) =
|
||||
EventLoop::new(swap_id, swarm, seller_peer_id, env_config)?;
|
||||
let (event_loop, event_loop_handle) = EventLoop::new(swap_id, swarm, seller_peer_id)?;
|
||||
let handle = tokio::spawn(event_loop.run());
|
||||
|
||||
let monero_receive_address = db.get_monero_address(swap_id).await?;
|
||||
|
|
@ -298,6 +340,12 @@ async fn main() -> Result<()> {
|
|||
bitcoin_target_block,
|
||||
} => {
|
||||
cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?;
|
||||
|
||||
match check_latest_version().await {
|
||||
Ok(()) => (),
|
||||
Err(error) => tracing::error!("{}", error),
|
||||
};
|
||||
|
||||
let db = open_db(data_dir.join("sqlite")).await?;
|
||||
let seed = Seed::from_file_or_generate(data_dir.as_path())
|
||||
.context("Failed to read in seed file")?;
|
||||
|
|
@ -320,6 +368,12 @@ async fn main() -> Result<()> {
|
|||
bitcoin_target_block,
|
||||
} => {
|
||||
cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?;
|
||||
|
||||
match check_latest_version().await {
|
||||
Ok(()) => (),
|
||||
Err(error) => tracing::error!("{}", error),
|
||||
};
|
||||
|
||||
let db = open_db(data_dir.join("sqlite")).await?;
|
||||
let seed = Seed::from_file_or_generate(data_dir.as_path())
|
||||
.context("Failed to read in seed file")?;
|
||||
|
|
@ -345,6 +399,11 @@ async fn main() -> Result<()> {
|
|||
.context("Rendezvous node address must contain peer ID")?;
|
||||
|
||||
cli::tracing::init(debug, json, data_dir.join("logs"), None)?;
|
||||
match check_latest_version().await {
|
||||
Ok(()) => (),
|
||||
Err(error) => tracing::error!("{}", error),
|
||||
};
|
||||
|
||||
let seed = Seed::from_file_or_generate(data_dir.as_path())
|
||||
.context("Failed to read in seed file")?;
|
||||
let identity = seed.derive_libp2p_identity();
|
||||
|
|
@ -425,6 +484,11 @@ async fn main() -> Result<()> {
|
|||
} => {
|
||||
cli::tracing::init(debug, json, data_dir.join("logs"), None)?;
|
||||
|
||||
match check_latest_version().await {
|
||||
Ok(()) => (),
|
||||
Err(error) => tracing::error!("{}", error),
|
||||
};
|
||||
|
||||
let seed = Seed::from_file_or_generate(data_dir.as_path())
|
||||
.context("Failed to read in seed file")?;
|
||||
let bitcoin_wallet = init_bitcoin_wallet(
|
||||
|
|
@ -439,6 +503,13 @@ async fn main() -> Result<()> {
|
|||
tracing::info!(descriptor=%wallet_export.to_string(), "Exported bitcoin wallet");
|
||||
}
|
||||
Command::MoneroRecovery { swap_id } => {
|
||||
cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?;
|
||||
|
||||
match check_latest_version().await {
|
||||
Ok(()) => (),
|
||||
Err(error) => tracing::error!("{}", error),
|
||||
};
|
||||
|
||||
let db = open_db(data_dir.join("sqlite")).await?;
|
||||
|
||||
let swap_state: BobState = db.get_state(swap_id).await?.try_into()?;
|
||||
|
|
@ -556,6 +627,11 @@ where
|
|||
{
|
||||
tracing::debug!("Requesting quote");
|
||||
let bid_quote = bid_quote.await?;
|
||||
|
||||
if bid_quote.max_quantity == bitcoin::Amount::ZERO {
|
||||
bail!(ZeroQuoteReceived)
|
||||
}
|
||||
|
||||
tracing::info!(
|
||||
price = %bid_quote.price,
|
||||
minimum_amount = %bid_quote.min_quantity,
|
||||
|
|
@ -616,10 +692,43 @@ where
|
|||
Ok((btc_swap_amount, fees))
|
||||
}
|
||||
|
||||
pub async fn check_latest_version() -> Result<()> {
|
||||
const GITHUB_LATEST_VERSION_URL: &str =
|
||||
"https://github.com/comit-network/xmr-btc-swap/releases/latest";
|
||||
|
||||
let response = match reqwest::get(GITHUB_LATEST_VERSION_URL).await {
|
||||
Ok(res) => res,
|
||||
Err(_) => bail!(
|
||||
"could not request the website {}",
|
||||
GITHUB_LATEST_VERSION_URL
|
||||
),
|
||||
};
|
||||
|
||||
let last_version_from_url: &str = match response.url().path_segments() {
|
||||
Some(split_segments) => match split_segments.last() {
|
||||
Some(seg) => seg,
|
||||
None => bail!("could not check the latest version"),
|
||||
},
|
||||
None => bail!("could not check the latest version"),
|
||||
};
|
||||
|
||||
let version_from_binary: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
if last_version_from_url != version_from_binary {
|
||||
tracing::warn!(
|
||||
"You are not on the lastest version {}, it's available on Github: {}",
|
||||
last_version_from_url,
|
||||
GITHUB_LATEST_VERSION_URL
|
||||
);
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::determine_btc_to_swap;
|
||||
use crate::{check_latest_version, determine_btc_to_swap};
|
||||
use ::bitcoin::Amount;
|
||||
use std::sync::Mutex;
|
||||
use swap::tracing_ext::capture_logs;
|
||||
|
|
@ -915,6 +1024,32 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn given_bid_quote_max_amount_0_return_errorq() {
|
||||
let givable = Arc::new(Mutex::new(MaxGiveable::new(vec![
|
||||
Amount::from_btc(0.0001).unwrap(),
|
||||
Amount::from_btc(0.01).unwrap(),
|
||||
])));
|
||||
|
||||
let determination_error = determine_btc_to_swap(
|
||||
true,
|
||||
async { Ok(quote_with_max(0.00)) },
|
||||
get_dummy_address(),
|
||||
|| async { Ok(Amount::from_btc(0.0101)?) },
|
||||
|| async {
|
||||
let mut result = givable.lock().unwrap();
|
||||
result.give()
|
||||
},
|
||||
|| async { Ok(()) },
|
||||
)
|
||||
.await
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string();
|
||||
|
||||
assert_eq!("Received quote of 0", determination_error);
|
||||
}
|
||||
|
||||
struct MaxGiveable {
|
||||
amounts: Vec<Amount>,
|
||||
call_counter: usize,
|
||||
|
|
@ -956,4 +1091,13 @@ mod tests {
|
|||
async fn get_dummy_address() -> Result<bitcoin::Address> {
|
||||
Ok("1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6".parse()?)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn check_correct_latest_version() {
|
||||
let writer = capture_logs(LevelFilter::INFO);
|
||||
|
||||
check_latest_version().await.unwrap();
|
||||
|
||||
assert_eq!(writer.captured(), r"");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ pub fn verify_sig(
|
|||
) -> Result<()> {
|
||||
let ecdsa = ECDSA::verify_only();
|
||||
|
||||
if ecdsa.verify(&verification_key.0, &transaction_sighash.into_inner(), &sig) {
|
||||
if ecdsa.verify(&verification_key.0, &transaction_sighash.into_inner(), sig) {
|
||||
Ok(())
|
||||
} else {
|
||||
bail!(InvalidSignature)
|
||||
|
|
@ -194,7 +194,7 @@ pub fn verify_encsig(
|
|||
&verification_key.0,
|
||||
&encryption_key.0,
|
||||
&digest.into_inner(),
|
||||
&encsig,
|
||||
encsig,
|
||||
) {
|
||||
Ok(())
|
||||
} else {
|
||||
|
|
@ -213,7 +213,7 @@ pub fn build_shared_output_descriptor(A: Point, B: Point) -> Descriptor<bitcoin:
|
|||
let A = ToHex::to_hex(&secp256k1::PublicKey::from(A));
|
||||
let B = ToHex::to_hex(&secp256k1::PublicKey::from(B));
|
||||
|
||||
let miniscript = MINISCRIPT_TEMPLATE.replace("A", &A).replace("B", &B);
|
||||
let miniscript = MINISCRIPT_TEMPLATE.replace('A', &A).replace('B', &B);
|
||||
|
||||
let miniscript =
|
||||
bdk::miniscript::Miniscript::<bitcoin::PublicKey, Segwitv0>::from_str(&miniscript)
|
||||
|
|
|
|||
|
|
@ -200,9 +200,10 @@ mod tests {
|
|||
#[tokio::test]
|
||||
async fn bob_can_fund_without_a_change_output() {
|
||||
let (A, B) = alice_and_bob();
|
||||
let fees = 610;
|
||||
let fees = 300;
|
||||
let agreed_amount = Amount::from_sat(10000);
|
||||
let wallet = WalletBuilder::new(agreed_amount.as_sat() + fees).build();
|
||||
let amount = agreed_amount.as_sat() + fees;
|
||||
let wallet = WalletBuilder::new(amount).build();
|
||||
|
||||
let psbt = bob_make_psbt(A, B, &wallet, agreed_amount).await;
|
||||
assert_eq!(
|
||||
|
|
@ -262,7 +263,7 @@ mod tests {
|
|||
amount: Amount,
|
||||
) -> PartiallySignedTransaction {
|
||||
let change = wallet.new_address().await.unwrap();
|
||||
TxLock::new(&wallet, amount, A, B, change)
|
||||
TxLock::new(wallet, amount, A, B, change)
|
||||
.await
|
||||
.unwrap()
|
||||
.into()
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ impl TxRedeem {
|
|||
|
||||
let sig = sigs
|
||||
.into_iter()
|
||||
.find(|sig| verify_sig(&B, &self.digest(), &sig).is_ok())
|
||||
.find(|sig| verify_sig(&B, &self.digest(), sig).is_ok())
|
||||
.context("Neither signature on witness stack verifies against B")?;
|
||||
|
||||
Ok(sig)
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ impl TxRefund {
|
|||
|
||||
let sig = sigs
|
||||
.into_iter()
|
||||
.find(|sig| verify_sig(&B, &self.digest(), &sig).is_ok())
|
||||
.find(|sig| verify_sig(&B, &self.digest(), sig).is_ok())
|
||||
.context("Neither signature on witness stack verifies against B")?;
|
||||
|
||||
Ok(sig)
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ impl Wallet {
|
|||
self.wallet
|
||||
.lock()
|
||||
.await
|
||||
.broadcast(transaction)
|
||||
.broadcast(&transaction)
|
||||
.with_context(|| {
|
||||
format!("Failed to broadcast Bitcoin {} transaction {}", kind, txid)
|
||||
})?;
|
||||
|
|
@ -152,13 +152,13 @@ impl Wallet {
|
|||
ScriptStatus::Retrying
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
if new_status != ScriptStatus::Retrying
|
||||
{
|
||||
last_status = Some(print_status_change(txid, last_status, new_status));
|
||||
|
||||
let all_receivers_gone = sender.send(new_status).is_err();
|
||||
|
||||
|
||||
if all_receivers_gone {
|
||||
tracing::debug!(%txid, "All receivers gone, removing subscription");
|
||||
client.lock().await.subscriptions.remove(&(txid, script));
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ use url::Url;
|
|||
use uuid::Uuid;
|
||||
|
||||
// See: https://moneroworld.com/
|
||||
pub const DEFAULT_MONERO_DAEMON_ADDRESS: &str = "node.melo.tools:18081";
|
||||
pub const DEFAULT_MONERO_DAEMON_ADDRESS_STAGENET: &str = "stagenet.melo.tools:38081";
|
||||
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";
|
||||
|
||||
// See: https://1209k.com/bitcoin-eye/ele.php?chain=btc
|
||||
const DEFAULT_ELECTRUM_RPC_URL: &str = "ssl://blockstream.info:700";
|
||||
|
|
@ -41,7 +41,7 @@ pub struct Arguments {
|
|||
#[derive(Debug, PartialEq)]
|
||||
pub enum ParseResult {
|
||||
/// The arguments we were invoked in.
|
||||
Arguments(Arguments),
|
||||
Arguments(Box<Arguments>),
|
||||
/// A flag or command was given that does not need further processing other
|
||||
/// than printing the provided message.
|
||||
///
|
||||
|
|
@ -260,7 +260,7 @@ where
|
|||
},
|
||||
};
|
||||
|
||||
Ok(ParseResult::Arguments(arguments))
|
||||
Ok(ParseResult::Arguments(Box::new(arguments)))
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
|
|
@ -693,7 +693,8 @@ mod tests {
|
|||
MULTI_ADDRESS,
|
||||
];
|
||||
|
||||
let expected_args = ParseResult::Arguments(Arguments::buy_xmr_mainnet_defaults());
|
||||
let expected_args =
|
||||
ParseResult::Arguments(Arguments::buy_xmr_mainnet_defaults().into_boxed());
|
||||
let args = parse_args_and_apply_defaults(raw_ars).unwrap();
|
||||
|
||||
assert_eq!(expected_args, args);
|
||||
|
|
@ -717,7 +718,7 @@ mod tests {
|
|||
|
||||
assert_eq!(
|
||||
args,
|
||||
ParseResult::Arguments(Arguments::buy_xmr_testnet_defaults())
|
||||
ParseResult::Arguments(Arguments::buy_xmr_testnet_defaults().into_boxed())
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -778,7 +779,7 @@ mod tests {
|
|||
|
||||
assert_eq!(
|
||||
args,
|
||||
ParseResult::Arguments(Arguments::resume_mainnet_defaults())
|
||||
ParseResult::Arguments(Arguments::resume_mainnet_defaults().into_boxed())
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -790,7 +791,7 @@ mod tests {
|
|||
|
||||
assert_eq!(
|
||||
args,
|
||||
ParseResult::Arguments(Arguments::resume_testnet_defaults())
|
||||
ParseResult::Arguments(Arguments::resume_testnet_defaults().into_boxed())
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -802,7 +803,7 @@ mod tests {
|
|||
|
||||
assert_eq!(
|
||||
args,
|
||||
ParseResult::Arguments(Arguments::cancel_mainnet_defaults())
|
||||
ParseResult::Arguments(Arguments::cancel_mainnet_defaults().into_boxed())
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -814,7 +815,7 @@ mod tests {
|
|||
|
||||
assert_eq!(
|
||||
args,
|
||||
ParseResult::Arguments(Arguments::cancel_testnet_defaults())
|
||||
ParseResult::Arguments(Arguments::cancel_testnet_defaults().into_boxed())
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -826,7 +827,7 @@ mod tests {
|
|||
|
||||
assert_eq!(
|
||||
args,
|
||||
ParseResult::Arguments(Arguments::refund_mainnet_defaults())
|
||||
ParseResult::Arguments(Arguments::refund_mainnet_defaults().into_boxed())
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -838,7 +839,7 @@ mod tests {
|
|||
|
||||
assert_eq!(
|
||||
args,
|
||||
ParseResult::Arguments(Arguments::refund_testnet_defaults())
|
||||
ParseResult::Arguments(Arguments::refund_testnet_defaults().into_boxed())
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -866,6 +867,7 @@ mod tests {
|
|||
ParseResult::Arguments(
|
||||
Arguments::buy_xmr_mainnet_defaults()
|
||||
.with_data_dir(PathBuf::from_str(data_dir).unwrap().join("mainnet"))
|
||||
.into_boxed()
|
||||
)
|
||||
);
|
||||
|
||||
|
|
@ -890,6 +892,7 @@ mod tests {
|
|||
ParseResult::Arguments(
|
||||
Arguments::buy_xmr_testnet_defaults()
|
||||
.with_data_dir(PathBuf::from_str(data_dir).unwrap().join("testnet"))
|
||||
.into_boxed()
|
||||
)
|
||||
);
|
||||
|
||||
|
|
@ -909,6 +912,7 @@ mod tests {
|
|||
ParseResult::Arguments(
|
||||
Arguments::resume_mainnet_defaults()
|
||||
.with_data_dir(PathBuf::from_str(data_dir).unwrap().join("mainnet"))
|
||||
.into_boxed()
|
||||
)
|
||||
);
|
||||
|
||||
|
|
@ -929,6 +933,7 @@ mod tests {
|
|||
ParseResult::Arguments(
|
||||
Arguments::resume_testnet_defaults()
|
||||
.with_data_dir(PathBuf::from_str(data_dir).unwrap().join("testnet"))
|
||||
.into_boxed()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
@ -950,7 +955,11 @@ mod tests {
|
|||
let args = parse_args_and_apply_defaults(raw_ars).unwrap();
|
||||
assert_eq!(
|
||||
args,
|
||||
ParseResult::Arguments(Arguments::buy_xmr_mainnet_defaults().with_debug())
|
||||
ParseResult::Arguments(
|
||||
Arguments::buy_xmr_mainnet_defaults()
|
||||
.with_debug()
|
||||
.into_boxed()
|
||||
)
|
||||
);
|
||||
|
||||
let raw_ars = vec![
|
||||
|
|
@ -969,7 +978,11 @@ mod tests {
|
|||
let args = parse_args_and_apply_defaults(raw_ars).unwrap();
|
||||
assert_eq!(
|
||||
args,
|
||||
ParseResult::Arguments(Arguments::buy_xmr_testnet_defaults().with_debug())
|
||||
ParseResult::Arguments(
|
||||
Arguments::buy_xmr_testnet_defaults()
|
||||
.with_debug()
|
||||
.into_boxed()
|
||||
)
|
||||
);
|
||||
|
||||
let raw_ars = vec![BINARY_NAME, "--debug", "resume", "--swap-id", SWAP_ID];
|
||||
|
|
@ -977,7 +990,11 @@ mod tests {
|
|||
let args = parse_args_and_apply_defaults(raw_ars).unwrap();
|
||||
assert_eq!(
|
||||
args,
|
||||
ParseResult::Arguments(Arguments::resume_mainnet_defaults().with_debug())
|
||||
ParseResult::Arguments(
|
||||
Arguments::resume_mainnet_defaults()
|
||||
.with_debug()
|
||||
.into_boxed()
|
||||
)
|
||||
);
|
||||
|
||||
let raw_ars = vec![
|
||||
|
|
@ -992,7 +1009,11 @@ mod tests {
|
|||
let args = parse_args_and_apply_defaults(raw_ars).unwrap();
|
||||
assert_eq!(
|
||||
args,
|
||||
ParseResult::Arguments(Arguments::resume_testnet_defaults().with_debug())
|
||||
ParseResult::Arguments(
|
||||
Arguments::resume_testnet_defaults()
|
||||
.with_debug()
|
||||
.into_boxed()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1013,7 +1034,11 @@ mod tests {
|
|||
let args = parse_args_and_apply_defaults(raw_ars).unwrap();
|
||||
assert_eq!(
|
||||
args,
|
||||
ParseResult::Arguments(Arguments::buy_xmr_mainnet_defaults().with_json())
|
||||
ParseResult::Arguments(
|
||||
Arguments::buy_xmr_mainnet_defaults()
|
||||
.with_json()
|
||||
.into_boxed()
|
||||
)
|
||||
);
|
||||
|
||||
let raw_ars = vec![
|
||||
|
|
@ -1032,7 +1057,11 @@ mod tests {
|
|||
let args = parse_args_and_apply_defaults(raw_ars).unwrap();
|
||||
assert_eq!(
|
||||
args,
|
||||
ParseResult::Arguments(Arguments::buy_xmr_testnet_defaults().with_json())
|
||||
ParseResult::Arguments(
|
||||
Arguments::buy_xmr_testnet_defaults()
|
||||
.with_json()
|
||||
.into_boxed()
|
||||
)
|
||||
);
|
||||
|
||||
let raw_ars = vec![BINARY_NAME, "--json", "resume", "--swap-id", SWAP_ID];
|
||||
|
|
@ -1040,7 +1069,11 @@ mod tests {
|
|||
let args = parse_args_and_apply_defaults(raw_ars).unwrap();
|
||||
assert_eq!(
|
||||
args,
|
||||
ParseResult::Arguments(Arguments::resume_mainnet_defaults().with_json())
|
||||
ParseResult::Arguments(
|
||||
Arguments::resume_mainnet_defaults()
|
||||
.with_json()
|
||||
.into_boxed()
|
||||
)
|
||||
);
|
||||
|
||||
let raw_ars = vec![
|
||||
|
|
@ -1055,7 +1088,11 @@ mod tests {
|
|||
let args = parse_args_and_apply_defaults(raw_ars).unwrap();
|
||||
assert_eq!(
|
||||
args,
|
||||
ParseResult::Arguments(Arguments::resume_testnet_defaults().with_json())
|
||||
ParseResult::Arguments(
|
||||
Arguments::resume_testnet_defaults()
|
||||
.with_json()
|
||||
.into_boxed()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1303,6 +1340,10 @@ mod tests {
|
|||
self.json = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn into_boxed(self) -> Box<Self> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
fn data_dir_path_cli() -> PathBuf {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use crate::bitcoin::EncryptedSignature;
|
||||
use crate::cli::behaviour::{Behaviour, OutEvent};
|
||||
use crate::monero;
|
||||
use crate::network::encrypted_signature;
|
||||
use crate::network::quote::BidQuote;
|
||||
use crate::network::swap_setup::bob::NewSwap;
|
||||
use crate::protocol::bob::State2;
|
||||
use crate::{env, monero};
|
||||
use anyhow::{Context, Result};
|
||||
use futures::future::{BoxFuture, OptionFuture};
|
||||
use futures::{FutureExt, StreamExt};
|
||||
|
|
@ -50,7 +50,6 @@ impl EventLoop {
|
|||
swap_id: Uuid,
|
||||
swarm: Swarm<Behaviour>,
|
||||
alice_peer_id: PeerId,
|
||||
env_config: env::Config,
|
||||
) -> Result<(Self, EventLoopHandle)> {
|
||||
let execution_setup = bmrng::channel_with_timeout(1, Duration::from_secs(60));
|
||||
let transfer_proof = bmrng::channel_with_timeout(1, Duration::from_secs(60));
|
||||
|
|
@ -76,7 +75,6 @@ impl EventLoop {
|
|||
transfer_proof: transfer_proof.1,
|
||||
encrypted_signature: encrypted_signature.0,
|
||||
quote: quote.0,
|
||||
env_config,
|
||||
};
|
||||
|
||||
Ok((event_loop, handle))
|
||||
|
|
@ -220,7 +218,6 @@ pub struct EventLoopHandle {
|
|||
transfer_proof: bmrng::RequestReceiver<monero::TransferProof, ()>,
|
||||
encrypted_signature: bmrng::RequestSender<EncryptedSignature, ()>,
|
||||
quote: bmrng::RequestSender<(), BidQuote>,
|
||||
env_config: env::Config,
|
||||
}
|
||||
|
||||
impl EventLoopHandle {
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@ impl EventLoop {
|
|||
QuoteStatus::Received(Status::Online(quote)) => {
|
||||
let address = self
|
||||
.reachable_asb_address
|
||||
.get(&peer_id)
|
||||
.get(peer_id)
|
||||
.expect("if we got a quote we must have stored an address");
|
||||
|
||||
Ok(Seller {
|
||||
|
|
@ -282,7 +282,7 @@ impl EventLoop {
|
|||
QuoteStatus::Received(Status::Unreachable) => {
|
||||
let address = self
|
||||
.unreachable_asb_address
|
||||
.get(&peer_id)
|
||||
.get(peer_id)
|
||||
.expect("if we got a quote we must have stored an address");
|
||||
|
||||
Ok(Seller {
|
||||
|
|
|
|||
|
|
@ -20,27 +20,22 @@ pub fn init(debug: bool, json: bool, dir: impl AsRef<Path>, swap_id: Option<Uuid
|
|||
|
||||
std::mem::forget(guard);
|
||||
|
||||
let file_logger = fmt::layer()
|
||||
.with_ansi(false)
|
||||
.with_target(false)
|
||||
.with_writer(appender);
|
||||
let file_logger = registry.with(
|
||||
fmt::layer()
|
||||
.with_ansi(false)
|
||||
.with_target(false)
|
||||
.json()
|
||||
.with_writer(appender),
|
||||
);
|
||||
|
||||
if json && debug {
|
||||
set_global_default(
|
||||
registry
|
||||
.with(file_logger.json())
|
||||
.with(debug_json_terminal_printer()),
|
||||
)?;
|
||||
set_global_default(file_logger.with(debug_json_terminal_printer()))?;
|
||||
} else if json && !debug {
|
||||
set_global_default(
|
||||
registry
|
||||
.with(file_logger.json())
|
||||
.with(info_json_terminal_printer()),
|
||||
)?;
|
||||
set_global_default(file_logger.with(info_json_terminal_printer()))?;
|
||||
} else if !json && debug {
|
||||
set_global_default(registry.with(file_logger).with(debug_terminal_printer()))?;
|
||||
set_global_default(file_logger.with(debug_terminal_printer()))?;
|
||||
} else {
|
||||
set_global_default(registry.with(file_logger).with(info_terminal_printer()))?;
|
||||
set_global_default(file_logger.with(info_terminal_printer()))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ impl GetConfig for Mainnet {
|
|||
Config {
|
||||
bitcoin_lock_mempool_timeout: 3.std_minutes(),
|
||||
bitcoin_lock_confirmed_timeout: 2.std_hours(),
|
||||
bitcoin_finality_confirmations: 2,
|
||||
bitcoin_finality_confirmations: 1,
|
||||
bitcoin_avg_block_time: 10.std_minutes(),
|
||||
bitcoin_cancel_timelock: CancelTimelock::new(72),
|
||||
bitcoin_punish_timelock: PunishTimelock::new(72),
|
||||
|
|
@ -65,7 +65,7 @@ impl GetConfig for Testnet {
|
|||
Config {
|
||||
bitcoin_lock_mempool_timeout: 3.std_minutes(),
|
||||
bitcoin_lock_confirmed_timeout: 1.std_hours(),
|
||||
bitcoin_finality_confirmations: 2,
|
||||
bitcoin_finality_confirmations: 1,
|
||||
bitcoin_avg_block_time: 10.std_minutes(),
|
||||
bitcoin_cancel_timelock: CancelTimelock::new(12),
|
||||
bitcoin_punish_timelock: PunishTimelock::new(6),
|
||||
|
|
@ -138,7 +138,7 @@ mod monero_network {
|
|||
Network::Stagenet => "stagenet",
|
||||
Network::Testnet => "testnet",
|
||||
};
|
||||
s.serialize_str(&str)
|
||||
s.serialize_str(str)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ pub fn connect(price_ticker_ws_url: Url) -> Result<PriceUpdates> {
|
|||
}
|
||||
}
|
||||
|
||||
Err(backoff::Error::Transient(anyhow!("stream ended")))
|
||||
Err(backoff::Error::transient(anyhow!("stream ended")))
|
||||
}
|
||||
},
|
||||
|error, next: Duration| {
|
||||
|
|
@ -108,8 +108,8 @@ fn to_backoff(e: connection::Error) -> backoff::Error<anyhow::Error> {
|
|||
|
||||
match e {
|
||||
// Connection closures and websocket errors will be retried
|
||||
connection::Error::ConnectionClosed => Transient(anyhow::Error::from(e)),
|
||||
connection::Error::WebSocket(_) => Transient(anyhow::Error::from(e)),
|
||||
connection::Error::ConnectionClosed => backoff::Error::transient(anyhow::Error::from(e)),
|
||||
connection::Error::WebSocket(_) => backoff::Error::transient(anyhow::Error::from(e)),
|
||||
|
||||
// Failures while parsing a message are permanent because they most likely present a
|
||||
// programmer error
|
||||
|
|
@ -275,8 +275,6 @@ mod wire {
|
|||
pub struct TickerData {
|
||||
#[serde(rename = "a")]
|
||||
ask: Vec<RateElement>,
|
||||
#[serde(rename = "b")]
|
||||
bid: Vec<RateElement>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
|
|
|
|||
|
|
@ -99,6 +99,20 @@ impl Amount {
|
|||
self.0
|
||||
}
|
||||
|
||||
pub fn max_bitcoin_for_price(&self, ask_price: bitcoin::Amount) -> bitcoin::Amount {
|
||||
let piconero_minus_fee = self.as_piconero().saturating_sub(MONERO_FEE.as_piconero());
|
||||
|
||||
if piconero_minus_fee == 0 {
|
||||
return bitcoin::Amount::ZERO;
|
||||
}
|
||||
|
||||
// There needs to be an offset for difference in zeroes beetween Piconeros and
|
||||
// Satoshis
|
||||
let piconero_calc = (piconero_minus_fee * ask_price.as_sat()) / PICONERO_OFFSET;
|
||||
|
||||
bitcoin::Amount::from_sat(piconero_calc)
|
||||
}
|
||||
|
||||
pub fn from_monero(amount: f64) -> Result<Self> {
|
||||
let decimal = Decimal::try_from(amount)?;
|
||||
Self::from_decimal(decimal)
|
||||
|
|
@ -360,6 +374,30 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn geting_max_bitcoin_to_trade() {
|
||||
let amount = Amount::parse_monero("10").unwrap();
|
||||
let bitcoin_price_sats = bitcoin::Amount::from_sat(382_900);
|
||||
|
||||
let monero_max_from_bitcoin = amount.max_bitcoin_for_price(bitcoin_price_sats);
|
||||
|
||||
assert_eq!(
|
||||
bitcoin::Amount::from_sat(3_828_988),
|
||||
monero_max_from_bitcoin
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn geting_max_bitcoin_to_trade_with_balance_smaller_than_locking_fee() {
|
||||
let monero = "0.00001";
|
||||
let amount = Amount::parse_monero(monero).unwrap();
|
||||
let bitcoin_price_sats = bitcoin::Amount::from_sat(382_900);
|
||||
|
||||
let monero_max_from_bitcoin = amount.max_bitcoin_for_price(bitcoin_price_sats);
|
||||
|
||||
assert_eq!(bitcoin::Amount::ZERO, monero_max_from_bitcoin);
|
||||
}
|
||||
|
||||
use rand::rngs::OsRng;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,10 @@ pub struct BidQuote {
|
|||
pub max_quantity: bitcoin::Amount,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, thiserror::Error)]
|
||||
#[error("Received quote of 0")]
|
||||
pub struct ZeroQuoteReceived;
|
||||
|
||||
/// Constructs a new instance of the `quote` behaviour to be used by the ASB.
|
||||
///
|
||||
/// The ASB is always listening and only supports inbound connections, i.e.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ pub mod ecdsa_fun {
|
|||
use ::ecdsa_fun::fun::{Point, Scalar, G};
|
||||
|
||||
pub fn point() -> impl Strategy<Value = Point> {
|
||||
scalar().prop_map(|mut scalar| Point::from_scalar_mul(&G, &mut scalar).mark::<Normal>())
|
||||
scalar().prop_map(|mut scalar| Point::from_scalar_mul(G, &mut scalar).mark::<Normal>())
|
||||
}
|
||||
|
||||
pub fn scalar() -> impl Strategy<Value = Scalar> {
|
||||
|
|
|
|||
|
|
@ -659,8 +659,7 @@ impl State6 {
|
|||
|
||||
pub async fn publish_refund_btc(&self, bitcoin_wallet: &bitcoin::Wallet) -> Result<()> {
|
||||
let signed_tx_refund = self.signed_refund_transaction()?;
|
||||
let (_, subscription) = bitcoin_wallet.broadcast(signed_tx_refund, "refund").await?;
|
||||
subscription.wait_until_final().await?;
|
||||
bitcoin_wallet.broadcast(signed_tx_refund, "refund").await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -278,9 +278,12 @@ async fn next_state(
|
|||
state.publish_refund_btc(bitcoin_wallet).await?;
|
||||
BobState::BtcRefunded(state)
|
||||
}
|
||||
ExpiredTimelocks::Punish => BobState::BtcPunished {
|
||||
tx_lock_id: state.tx_lock_id(),
|
||||
},
|
||||
ExpiredTimelocks::Punish => {
|
||||
tracing::info!("You have been punished for not refunding in time");
|
||||
BobState::BtcPunished {
|
||||
tx_lock_id: state.tx_lock_id(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BobState::BtcRefunded(state4) => BobState::BtcRefunded(state4),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue