Refund Command

This commit is contained in:
Daniel Karzel 2021-02-01 16:25:33 +11:00
parent 0600a7048e
commit ad2aefc2a5
4 changed files with 102 additions and 4 deletions

View File

@ -51,6 +51,7 @@ pub enum Command {
History, History,
Resume(Resume), Resume(Resume),
Cancel(Cancel), Cancel(Cancel),
Refund(Refund),
} }
#[derive(structopt::StructOpt, Debug)] #[derive(structopt::StructOpt, Debug)]
@ -98,6 +99,24 @@ pub enum Cancel {
}, },
} }
#[derive(structopt::StructOpt, Debug)]
pub enum Refund {
BuyXmr {
#[structopt(long = "swap-id")]
swap_id: Uuid,
// TODO: Remove Alice peer-id/address, it should be saved in the database when running swap
// and loaded from the database when running resume/cancel/refund
#[structopt(long = "counterpart-peer-id")]
alice_peer_id: PeerId,
#[structopt(long = "counterpart-addr")]
alice_addr: Multiaddr,
#[structopt(flatten)]
config: Config,
},
}
#[derive(structopt::StructOpt, Debug)] #[derive(structopt::StructOpt, Debug)]
pub struct Config { pub struct Config {
#[structopt( #[structopt(

View File

@ -13,7 +13,7 @@
#![allow(non_snake_case)] #![allow(non_snake_case)]
use crate::{ use crate::{
cli::{Cancel, Command, Options, Resume}, cli::{Cancel, Command, Options, Refund, Resume},
config::{ config::{
initial_setup, query_user_for_initial_testnet_config, read_config, ConfigNotInitialized, initial_setup, query_user_for_initial_testnet_config, read_config, ConfigNotInitialized,
}, },
@ -235,10 +235,48 @@ async fn main() -> Result<()> {
tokio::spawn(async move { event_loop.run().await }); tokio::spawn(async move { event_loop.run().await });
match bob::cancel(swap.swap_id, swap.state, swap.bitcoin_wallet, swap.db).await? { match bob::cancel(swap.swap_id, swap.state, swap.bitcoin_wallet, swap.db).await? {
Ok((txid, _)) => { info!("Cancel transaction successfully published with id {}", txid)}, Ok((txid, _)) => {
Err(CancelError::CancelTimelockNotExpiredYet) => {info!("The Cancel Transaction cannot be published yet, because the timelock has not expired. Please try again later.")}, info!("Cancel transaction successfully published with id {}", txid)
Err(CancelError::CancelTxAlreadyPublished) => {info!("The Cancel Transaction has already been published.")}
} }
Err(CancelError::CancelTimelockNotExpiredYet) => {
info!("The Cancel Transaction cannot be published yet, because the timelock has not expired. Please try again later.")
}
Err(CancelError::CancelTxAlreadyPublished) => {
info!("The Cancel Transaction has already been published.")
}
}
}
Command::Refund(Refund::BuyXmr {
swap_id,
alice_peer_id,
alice_addr,
config,
}) => {
let (bitcoin_wallet, monero_wallet) =
init_wallets(config.path, bitcoin_network, monero_network).await?;
// TODO: Optimize to only use the Bitcoin wallet, Monero wallet is unnecessary
let bob_factory = Builder::new(
seed,
db_path,
swap_id,
Arc::new(bitcoin_wallet),
Arc::new(monero_wallet),
alice_addr,
alice_peer_id,
execution_params,
);
let (swap, event_loop) = bob_factory.build().await?;
tokio::spawn(async move { event_loop.run().await });
bob::refund(
swap.swap_id,
swap.state,
swap.execution_params,
swap.bitcoin_wallet,
swap.db,
)
.await??;
} }
}; };

View File

@ -23,6 +23,7 @@ pub use self::{
cancel::cancel, cancel::cancel,
encrypted_signature::EncryptedSignature, encrypted_signature::EncryptedSignature,
event_loop::{EventLoop, EventLoopHandle}, event_loop::{EventLoop, EventLoopHandle},
refund::refund,
state::*, state::*,
swap::{run, run_until}, swap::{run, run_until},
swap_request::*, swap_request::*,
@ -34,6 +35,7 @@ pub mod cancel;
mod encrypted_signature; mod encrypted_signature;
pub mod event_loop; pub mod event_loop;
mod execution_setup; mod execution_setup;
pub mod refund;
pub mod state; pub mod state;
pub mod swap; pub mod swap;
mod swap_request; mod swap_request;

View File

@ -0,0 +1,39 @@
use crate::{
bitcoin::Wallet,
database::{Database, Swap},
execution_params::ExecutionParams,
protocol::bob::BobState,
};
use anyhow::Result;
use std::sync::Arc;
use uuid::Uuid;
#[derive(thiserror::Error, Debug, Clone, Copy)]
#[error("Cannot refund because swap {0} was not cancelled yet. Make sure to cancel the swap before trying to refund.")]
pub struct SwapNotCancelledYet(Uuid);
pub async fn refund(
swap_id: Uuid,
state: BobState,
execution_params: ExecutionParams,
bitcoin_wallet: Arc<Wallet>,
db: Database,
) -> Result<Result<BobState, SwapNotCancelledYet>> {
let state4 = match state {
BobState::BtcCancelled(state4) => state4,
_ => {
return Ok(Err(SwapNotCancelledYet(swap_id)));
}
};
state4
.refund_btc(bitcoin_wallet.as_ref(), execution_params)
.await?;
let state = BobState::BtcRefunded(state4);
let db_state = state.clone().into();
db.insert_latest_state(swap_id, Swap::Bob(db_state)).await?;
Ok(Ok(state))
}