Add initial swap binary crate
In preparation for writing a fully fledged XMR/BTC swap client add a new crate and initial binary with basic structopt cli implementation. With this applied we can run the swap as Alice with `swap --as-alice` and run the swap as Bob with `swap --sats 10000000`.pull/10/head
parent
911ff396db
commit
330bd1f22c
@ -1,2 +1,2 @@
|
||||
[workspace]
|
||||
members = ["monero-harness", "xmr-btc"]
|
||||
members = ["monero-harness", "xmr-btc", "swap"]
|
||||
|
@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "swap"
|
||||
version = "0.1.0"
|
||||
authors = ["CoBloX developers <team@coblox.tech>"]
|
||||
edition = "2018"
|
||||
description = "XMR/BTC trustless atomic swaps."
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
bitcoin = "0.25" # TODO: Upgrade other crates in this repo to use this version.
|
||||
monero = "0.9"
|
||||
structopt = "0.3"
|
||||
tokio = { version = "0.2", features = ["rt-threaded", "macros"] }
|
||||
xmr-btc = { path = "../xmr-btc" }
|
@ -0,0 +1,13 @@
|
||||
//! Run an XMR/BTC swap in the role of Alice.
|
||||
//! Alice holds XMR and wishes receive BTC.
|
||||
|
||||
use anyhow::Result;
|
||||
use std::thread;
|
||||
|
||||
/// Entrypoint for an XMR/BTC swap in the role of Alice.
|
||||
pub fn swap() -> Result<()> {
|
||||
// Bob initiates the swap via network communication.
|
||||
thread::park();
|
||||
|
||||
Ok(())
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
//! Run an XMR/BTC swap in the role of Bob.
|
||||
//! Bob holds BTC and wishes receive XMR.
|
||||
|
||||
use crate::SwapParams;
|
||||
use anyhow::Result;
|
||||
use xmr_btc::monero;
|
||||
|
||||
/// Request to swap `btc` with Alice.
|
||||
///
|
||||
/// Connects to a node running an instance in the role of Alice and requests to
|
||||
/// swap `btc` i.e., this gets the rate from Alice for `btc`.
|
||||
pub async fn request_swap_btc(_btc: ::bitcoin::Amount) -> Result<SwapParams> {
|
||||
todo!("Get rate from Alice for this many btc")
|
||||
}
|
||||
|
||||
/// Request to swap `xmr` with Alice.
|
||||
///
|
||||
/// Connects to a node running an instance in the role of Alice and requests to
|
||||
/// swap `xmr` i.e., this gets the rate from Alice for `xmr`.
|
||||
pub async fn request_swap_xmr(_xmr: monero::Amount) -> Result<SwapParams> {
|
||||
todo!("Get rate from Alice for this many xmr")
|
||||
}
|
||||
|
||||
/// XMR/BTC swap in the role of Bob.
|
||||
pub fn swap(_: SwapParams) -> Result<()> {
|
||||
todo!("Run the swap as Bob")
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
#[derive(structopt::StructOpt, Debug)]
|
||||
pub struct Options {
|
||||
/// Run the swap as Alice.
|
||||
#[structopt(long = "as-alice")]
|
||||
pub as_alice: bool,
|
||||
|
||||
/// Run the swap as Bob and try to swap this many XMR (in piconero).
|
||||
#[structopt(long = "picos")]
|
||||
pub piconeros: Option<u64>,
|
||||
|
||||
/// Run the swap as Bob and try to swap this many BTC (in satoshi).
|
||||
#[structopt(long = "sats")]
|
||||
pub satoshis: Option<u64>,
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
use xmr_btc::monero;
|
||||
|
||||
pub mod alice;
|
||||
pub mod bob;
|
||||
|
||||
/// XMR/BTC swap parameters.
|
||||
pub struct SwapParams {
|
||||
/// Amount of BTC to swap.
|
||||
pub btc: bitcoin::Amount,
|
||||
/// Amount of XMR to swap.
|
||||
pub xmr: monero::Amount,
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
#![warn(
|
||||
unused_extern_crates,
|
||||
missing_debug_implementations,
|
||||
missing_copy_implementations,
|
||||
rust_2018_idioms,
|
||||
clippy::cast_possible_truncation,
|
||||
clippy::cast_sign_loss,
|
||||
clippy::fallible_impl_from,
|
||||
clippy::cast_precision_loss,
|
||||
clippy::cast_possible_wrap,
|
||||
clippy::dbg_macro
|
||||
)]
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
mod cli;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use structopt::StructOpt;
|
||||
|
||||
use cli::Options;
|
||||
use swap::{alice, bob, SwapParams};
|
||||
use xmr_btc::monero;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
let opt = Options::from_args();
|
||||
|
||||
if opt.as_alice {
|
||||
swap_as_alice(opt)?;
|
||||
} else {
|
||||
swap_as_bob(opt).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn swap_as_alice(opt: Options) -> Result<()> {
|
||||
println!("running swap as Alice ...");
|
||||
|
||||
if opt.piconeros.is_some() || opt.satoshis.is_some() {
|
||||
bail!("Alice cannot set the amount to swap via the cli");
|
||||
}
|
||||
|
||||
let _ = alice::swap()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn swap_as_bob(opt: Options) -> Result<()> {
|
||||
println!("running swap as Bob ...");
|
||||
|
||||
match (opt.piconeros, opt.satoshis) {
|
||||
(Some(_), Some(_)) => bail!("Please supply only a single amount to swap"),
|
||||
(None, None) => bail!("Please supply an amount to swap"),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
assert_connection_to_alice()?;
|
||||
|
||||
let params = match (opt.piconeros, opt.satoshis) {
|
||||
(Some(picos), _) => {
|
||||
let xmr = monero::Amount::from_piconero(picos);
|
||||
let params = bob::request_swap_xmr(xmr).await?;
|
||||
|
||||
confirm_amounts_with_user(params)?
|
||||
}
|
||||
(None, Some(sats)) => {
|
||||
let btc = bitcoin::Amount::from_sat(sats);
|
||||
let params = bob::request_swap_btc(btc).await?;
|
||||
|
||||
confirm_amounts_with_user(params)?
|
||||
}
|
||||
_ => unreachable!("error path done above"),
|
||||
};
|
||||
|
||||
bob::swap(params)
|
||||
}
|
||||
|
||||
fn assert_connection_to_alice() -> Result<()> {
|
||||
todo!("assert connection to Alice")
|
||||
}
|
||||
|
||||
fn confirm_amounts_with_user(_: SwapParams) -> Result<SwapParams> {
|
||||
todo!("get user confirmation");
|
||||
}
|
Loading…
Reference in New Issue