mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2024-10-01 01:45:40 -04:00
feat: Enhance history command with more swap details (#1725)
This commit is contained in:
parent
b18ba95e8c
commit
cc854be8f4
@ -167,6 +167,7 @@ pub struct Context {
|
|||||||
pub swap_lock: Arc<SwapLock>,
|
pub swap_lock: Arc<SwapLock>,
|
||||||
pub config: Config,
|
pub config: Config,
|
||||||
pub tasks: Arc<PendingTaskList>,
|
pub tasks: Arc<PendingTaskList>,
|
||||||
|
pub is_daemon: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
@ -180,6 +181,7 @@ impl Context {
|
|||||||
debug: bool,
|
debug: bool,
|
||||||
json: bool,
|
json: bool,
|
||||||
server_address: Option<SocketAddr>,
|
server_address: Option<SocketAddr>,
|
||||||
|
is_daemon: bool,
|
||||||
) -> Result<Context> {
|
) -> Result<Context> {
|
||||||
let data_dir = data::data_dir_from(data, is_testnet)?;
|
let data_dir = data::data_dir_from(data, is_testnet)?;
|
||||||
let env_config = env_config_from(is_testnet);
|
let env_config = env_config_from(is_testnet);
|
||||||
@ -241,6 +243,7 @@ impl Context {
|
|||||||
},
|
},
|
||||||
swap_lock: Arc::new(SwapLock::new()),
|
swap_lock: Arc::new(SwapLock::new()),
|
||||||
tasks: Arc::new(PendingTaskList::default()),
|
tasks: Arc::new(PendingTaskList::default()),
|
||||||
|
is_daemon,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(context)
|
Ok(context)
|
||||||
@ -265,6 +268,7 @@ impl Context {
|
|||||||
monero_rpc_process: None,
|
monero_rpc_process: None,
|
||||||
swap_lock: Arc::new(SwapLock::new()),
|
swap_lock: Arc::new(SwapLock::new()),
|
||||||
tasks: Arc::new(PendingTaskList::default()),
|
tasks: Arc::new(PendingTaskList::default()),
|
||||||
|
is_daemon: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,9 +8,12 @@ use crate::protocol::bob::{BobState, Swap};
|
|||||||
use crate::protocol::{bob, State};
|
use crate::protocol::{bob, State};
|
||||||
use crate::{bitcoin, cli, monero, rpc};
|
use crate::{bitcoin, cli, monero, rpc};
|
||||||
use anyhow::{bail, Context as AnyContext, Result};
|
use anyhow::{bail, Context as AnyContext, Result};
|
||||||
|
use comfy_table::Table;
|
||||||
use libp2p::core::Multiaddr;
|
use libp2p::core::Multiaddr;
|
||||||
use qrcode::render::unicode;
|
use qrcode::render::unicode;
|
||||||
use qrcode::QrCode;
|
use qrcode::QrCode;
|
||||||
|
use rust_decimal::prelude::FromPrimitive;
|
||||||
|
use rust_decimal::Decimal;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
@ -638,14 +641,97 @@ impl Request {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
Method::History => {
|
Method::History => {
|
||||||
let swaps = context.db.all().await?;
|
let mut table = Table::new();
|
||||||
let mut vec: Vec<(Uuid, String)> = Vec::new();
|
table.set_header(vec![
|
||||||
for (swap_id, state) in swaps {
|
"Swap ID",
|
||||||
let state: BobState = state.try_into()?;
|
"Start Date",
|
||||||
vec.push((swap_id, state.to_string()));
|
"State",
|
||||||
|
"BTC Amount",
|
||||||
|
"XMR Amount",
|
||||||
|
"Exchange Rate",
|
||||||
|
"Trading Partner Peer ID",
|
||||||
|
]);
|
||||||
|
|
||||||
|
let all_swaps = context.db.all().await?;
|
||||||
|
let mut json_results = Vec::new();
|
||||||
|
|
||||||
|
for (swap_id, state) in all_swaps {
|
||||||
|
let result: Result<_> = async {
|
||||||
|
let latest_state: BobState = state.try_into()?;
|
||||||
|
let all_states = context.db.get_states(swap_id).await?;
|
||||||
|
let state3 = all_states
|
||||||
|
.iter()
|
||||||
|
.find_map(|s| {
|
||||||
|
if let State::Bob(BobState::BtcLocked { state3, .. }) = s {
|
||||||
|
Some(state3)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.context("Failed to get \"BtcLocked\" state")?;
|
||||||
|
|
||||||
|
let swap_start_date = context.db.get_swap_start_date(swap_id).await?;
|
||||||
|
let peer_id = context.db.get_peer_id(swap_id).await?;
|
||||||
|
let btc_amount = state3.tx_lock.lock_amount();
|
||||||
|
let xmr_amount = state3.xmr;
|
||||||
|
let exchange_rate = Decimal::from_f64(btc_amount.to_btc())
|
||||||
|
.ok_or_else(|| {
|
||||||
|
anyhow::anyhow!("Failed to convert BTC amount to Decimal")
|
||||||
|
})?
|
||||||
|
.checked_div(xmr_amount.as_xmr())
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("Division by zero or overflow"))?;
|
||||||
|
let exchange_rate = format!("{} XMR/BTC", exchange_rate.round_dp(8));
|
||||||
|
|
||||||
|
let swap_data = json!({
|
||||||
|
"swapId": swap_id.to_string(),
|
||||||
|
"startDate": swap_start_date.to_string(),
|
||||||
|
"state": latest_state.to_string(),
|
||||||
|
"btcAmount": btc_amount.to_string(),
|
||||||
|
"xmrAmount": xmr_amount.to_string(),
|
||||||
|
"exchangeRate": exchange_rate,
|
||||||
|
"tradingPartnerPeerId": peer_id.to_string()
|
||||||
|
});
|
||||||
|
|
||||||
|
if context.config.json {
|
||||||
|
tracing::info!(
|
||||||
|
swap_id = %swap_id,
|
||||||
|
swap_start_date = %swap_start_date,
|
||||||
|
latest_state = %latest_state,
|
||||||
|
btc_amount = %btc_amount,
|
||||||
|
xmr_amount = %xmr_amount,
|
||||||
|
exchange_rate = %exchange_rate,
|
||||||
|
trading_partner_peer_id = %peer_id,
|
||||||
|
"Found swap in database"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
table.add_row(vec![
|
||||||
|
swap_id.to_string(),
|
||||||
|
swap_start_date.to_string(),
|
||||||
|
latest_state.to_string(),
|
||||||
|
btc_amount.to_string(),
|
||||||
|
xmr_amount.to_string(),
|
||||||
|
exchange_rate,
|
||||||
|
peer_id.to_string(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(swap_data)
|
||||||
|
}
|
||||||
|
.await;
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(swap_data) => json_results.push(swap_data),
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!(swap_id = %swap_id, error = %e, "Failed to get swap details")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(json!({ "swaps": vec }))
|
if !context.config.json && !context.is_daemon {
|
||||||
|
println!("{}", table);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(json!({"swaps": json_results}))
|
||||||
}
|
}
|
||||||
Method::GetRawStates => {
|
Method::GetRawStates => {
|
||||||
let raw_history = context.db.raw_all().await?;
|
let raw_history = context.db.raw_all().await?;
|
||||||
|
@ -33,13 +33,13 @@ where
|
|||||||
env_config: env_config(testnet),
|
env_config: env_config(testnet),
|
||||||
cmd: Command::Start { resume_only },
|
cmd: Command::Start { resume_only },
|
||||||
},
|
},
|
||||||
RawCommand::History => Arguments {
|
RawCommand::History { only_unfinished } => Arguments {
|
||||||
testnet,
|
testnet,
|
||||||
json,
|
json,
|
||||||
disable_timestamp,
|
disable_timestamp,
|
||||||
config_path: config_path(config, testnet)?,
|
config_path: config_path(config, testnet)?,
|
||||||
env_config: env_config(testnet),
|
env_config: env_config(testnet),
|
||||||
cmd: Command::History,
|
cmd: Command::History { only_unfinished },
|
||||||
},
|
},
|
||||||
RawCommand::WithdrawBtc { amount, address } => Arguments {
|
RawCommand::WithdrawBtc { amount, address } => Arguments {
|
||||||
testnet,
|
testnet,
|
||||||
@ -195,7 +195,9 @@ pub enum Command {
|
|||||||
Start {
|
Start {
|
||||||
resume_only: bool,
|
resume_only: bool,
|
||||||
},
|
},
|
||||||
History,
|
History {
|
||||||
|
only_unfinished: bool,
|
||||||
|
},
|
||||||
Config,
|
Config,
|
||||||
WithdrawBtc {
|
WithdrawBtc {
|
||||||
amount: Option<Amount>,
|
amount: Option<Amount>,
|
||||||
@ -269,7 +271,13 @@ pub enum RawCommand {
|
|||||||
resume_only: bool,
|
resume_only: bool,
|
||||||
},
|
},
|
||||||
#[structopt(about = "Prints swap-id and the state of each swap ever made.")]
|
#[structopt(about = "Prints swap-id and the state of each swap ever made.")]
|
||||||
History,
|
History {
|
||||||
|
#[structopt(
|
||||||
|
long = "only-unfinished",
|
||||||
|
help = "If set, only unfinished swaps will be printed."
|
||||||
|
)]
|
||||||
|
only_unfinished: bool,
|
||||||
|
},
|
||||||
#[structopt(about = "Prints the current config")]
|
#[structopt(about = "Prints the current config")]
|
||||||
Config,
|
Config,
|
||||||
#[structopt(about = "Allows withdrawing BTC from the internal Bitcoin wallet.")]
|
#[structopt(about = "Allows withdrawing BTC from the internal Bitcoin wallet.")]
|
||||||
@ -387,7 +395,9 @@ mod tests {
|
|||||||
disable_timestamp: false,
|
disable_timestamp: false,
|
||||||
config_path: default_mainnet_conf_path,
|
config_path: default_mainnet_conf_path,
|
||||||
env_config: mainnet_env_config,
|
env_config: mainnet_env_config,
|
||||||
cmd: Command::History,
|
cmd: Command::History {
|
||||||
|
only_unfinished: false,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
let args = parse_args(raw_ars).unwrap();
|
let args = parse_args(raw_ars).unwrap();
|
||||||
assert_eq!(expected_args, args);
|
assert_eq!(expected_args, args);
|
||||||
@ -570,7 +580,9 @@ mod tests {
|
|||||||
disable_timestamp: false,
|
disable_timestamp: false,
|
||||||
config_path: default_testnet_conf_path,
|
config_path: default_testnet_conf_path,
|
||||||
env_config: testnet_env_config,
|
env_config: testnet_env_config,
|
||||||
cmd: Command::History,
|
cmd: Command::History {
|
||||||
|
only_unfinished: false,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
let args = parse_args(raw_ars).unwrap();
|
let args = parse_args(raw_ars).unwrap();
|
||||||
assert_eq!(expected_args, args);
|
assert_eq!(expected_args, args);
|
||||||
|
@ -18,6 +18,8 @@ use libp2p::core::multiaddr::Protocol;
|
|||||||
use libp2p::core::Multiaddr;
|
use libp2p::core::Multiaddr;
|
||||||
use libp2p::swarm::AddressScore;
|
use libp2p::swarm::AddressScore;
|
||||||
use libp2p::Swarm;
|
use libp2p::Swarm;
|
||||||
|
use rust_decimal::prelude::FromPrimitive;
|
||||||
|
use rust_decimal::Decimal;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
@ -33,7 +35,9 @@ use swap::common::check_latest_version;
|
|||||||
use swap::database::{open_db, AccessMode};
|
use swap::database::{open_db, AccessMode};
|
||||||
use swap::network::rendezvous::XmrBtcNamespace;
|
use swap::network::rendezvous::XmrBtcNamespace;
|
||||||
use swap::network::swarm;
|
use swap::network::swarm;
|
||||||
|
use swap::protocol::alice::swap::is_complete;
|
||||||
use swap::protocol::alice::{run, AliceState};
|
use swap::protocol::alice::{run, AliceState};
|
||||||
|
use swap::protocol::State;
|
||||||
use swap::seed::Seed;
|
use swap::seed::Seed;
|
||||||
use swap::tor::AuthenticatedClient;
|
use swap::tor::AuthenticatedClient;
|
||||||
use swap::{asb, bitcoin, kraken, monero, tor};
|
use swap::{asb, bitcoin, kraken, monero, tor};
|
||||||
@ -224,19 +228,87 @@ async fn main() -> Result<()> {
|
|||||||
|
|
||||||
event_loop.run().await;
|
event_loop.run().await;
|
||||||
}
|
}
|
||||||
Command::History => {
|
Command::History { only_unfinished } => {
|
||||||
let db = open_db(config.data.dir.join("sqlite"), AccessMode::ReadOnly).await?;
|
let db = open_db(config.data.dir.join("sqlite"), AccessMode::ReadOnly).await?;
|
||||||
|
let mut table: Table = Table::new();
|
||||||
|
|
||||||
let mut table = Table::new();
|
table.set_header(vec![
|
||||||
|
"Swap ID",
|
||||||
|
"Start Date",
|
||||||
|
"State",
|
||||||
|
"BTC Amount",
|
||||||
|
"XMR Amount",
|
||||||
|
"Exchange Rate",
|
||||||
|
"Trading Partner Peer ID",
|
||||||
|
"Completed",
|
||||||
|
]);
|
||||||
|
|
||||||
table.set_header(vec!["SWAP ID", "STATE"]);
|
let all_swaps = db.all().await?;
|
||||||
|
for (swap_id, state) in all_swaps {
|
||||||
|
if let Err(e) = async {
|
||||||
|
let latest_state: AliceState = state.try_into()?;
|
||||||
|
let is_completed = is_complete(&latest_state);
|
||||||
|
|
||||||
for (swap_id, state) in db.all().await? {
|
if only_unfinished && is_completed {
|
||||||
let state: AliceState = state.try_into()?;
|
return Ok::<_, anyhow::Error>(());
|
||||||
table.add_row(vec![swap_id.to_string(), state.to_string()]);
|
}
|
||||||
|
|
||||||
|
let all_states = db.get_states(swap_id).await?;
|
||||||
|
let state3 = all_states
|
||||||
|
.iter()
|
||||||
|
.find_map(|s| match s {
|
||||||
|
State::Alice(AliceState::BtcLockTransactionSeen { state3 }) => {
|
||||||
|
Some(state3)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.context("Failed to get \"BtcLockTransactionSeen\" state")?;
|
||||||
|
|
||||||
|
let swap_start_date = db.get_swap_start_date(swap_id).await?;
|
||||||
|
let peer_id = db.get_peer_id(swap_id).await?;
|
||||||
|
|
||||||
|
let exchange_rate = Decimal::from_f64(state3.btc.to_btc())
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("Failed to convert BTC amount to Decimal"))?
|
||||||
|
.checked_div(state3.xmr.as_xmr())
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("Division by zero or overflow"))?;
|
||||||
|
let exchange_rate = format!("{} XMR/BTC", exchange_rate.round_dp(8));
|
||||||
|
|
||||||
|
if json {
|
||||||
|
tracing::info!(
|
||||||
|
swap_id = %swap_id,
|
||||||
|
swap_start_date = %swap_start_date,
|
||||||
|
latest_state = %latest_state,
|
||||||
|
btc_amount = %state3.btc,
|
||||||
|
xmr_amount = %state3.xmr,
|
||||||
|
exchange_rate = %exchange_rate,
|
||||||
|
trading_partner_peer_id = %peer_id,
|
||||||
|
completed = is_completed,
|
||||||
|
"Found swap in database"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
table.add_row(vec![
|
||||||
|
swap_id.to_string(),
|
||||||
|
swap_start_date.to_string(),
|
||||||
|
latest_state.to_string(),
|
||||||
|
state3.btc.to_string(),
|
||||||
|
state3.xmr.to_string(),
|
||||||
|
exchange_rate,
|
||||||
|
peer_id.to_string(),
|
||||||
|
is_completed.to_string(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok::<_, anyhow::Error>(())
|
||||||
|
}
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
tracing::error!(swap_id = %swap_id, error = %e, "Failed to get swap details");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("{}", table);
|
if !json {
|
||||||
|
println!("{}", table);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Command::Config => {
|
Command::Config => {
|
||||||
let config_json = serde_json::to_string_pretty(&config)?;
|
let config_json = serde_json::to_string_pretty(&config)?;
|
||||||
|
@ -78,6 +78,7 @@ where
|
|||||||
debug,
|
debug,
|
||||||
json,
|
json,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@ -100,14 +101,16 @@ where
|
|||||||
let request = Request::new(Method::History);
|
let request = Request::new(Method::History);
|
||||||
|
|
||||||
let context =
|
let context =
|
||||||
Context::build(None, None, None, data, is_testnet, debug, json, None).await?;
|
Context::build(None, None, None, data, is_testnet, debug, json, None, false)
|
||||||
|
.await?;
|
||||||
(context, request)
|
(context, request)
|
||||||
}
|
}
|
||||||
CliCommand::Config => {
|
CliCommand::Config => {
|
||||||
let request = Request::new(Method::Config);
|
let request = Request::new(Method::Config);
|
||||||
|
|
||||||
let context =
|
let context =
|
||||||
Context::build(None, None, None, data, is_testnet, debug, json, None).await?;
|
Context::build(None, None, None, data, is_testnet, debug, json, None, false)
|
||||||
|
.await?;
|
||||||
(context, request)
|
(context, request)
|
||||||
}
|
}
|
||||||
CliCommand::Balance { bitcoin } => {
|
CliCommand::Balance { bitcoin } => {
|
||||||
@ -124,6 +127,7 @@ where
|
|||||||
debug,
|
debug,
|
||||||
json,
|
json,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
(context, request)
|
(context, request)
|
||||||
@ -145,6 +149,7 @@ where
|
|||||||
debug,
|
debug,
|
||||||
json,
|
json,
|
||||||
server_address,
|
server_address,
|
||||||
|
true,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
(context, request)
|
(context, request)
|
||||||
@ -166,6 +171,7 @@ where
|
|||||||
debug,
|
debug,
|
||||||
json,
|
json,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
(context, request)
|
(context, request)
|
||||||
@ -187,6 +193,7 @@ where
|
|||||||
debug,
|
debug,
|
||||||
json,
|
json,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
(context, request)
|
(context, request)
|
||||||
@ -207,6 +214,7 @@ where
|
|||||||
debug,
|
debug,
|
||||||
json,
|
json,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
(context, request)
|
(context, request)
|
||||||
@ -217,8 +225,18 @@ where
|
|||||||
} => {
|
} => {
|
||||||
let request = Request::new(Method::ListSellers { rendezvous_point });
|
let request = Request::new(Method::ListSellers { rendezvous_point });
|
||||||
|
|
||||||
let context =
|
let context = Context::build(
|
||||||
Context::build(None, None, Some(tor), data, is_testnet, debug, json, None).await?;
|
None,
|
||||||
|
None,
|
||||||
|
Some(tor),
|
||||||
|
data,
|
||||||
|
is_testnet,
|
||||||
|
debug,
|
||||||
|
json,
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
(context, request)
|
(context, request)
|
||||||
}
|
}
|
||||||
@ -234,6 +252,7 @@ where
|
|||||||
debug,
|
debug,
|
||||||
json,
|
json,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
(context, request)
|
(context, request)
|
||||||
@ -244,7 +263,8 @@ where
|
|||||||
let request = Request::new(Method::MoneroRecovery { swap_id });
|
let request = Request::new(Method::MoneroRecovery { swap_id });
|
||||||
|
|
||||||
let context =
|
let context =
|
||||||
Context::build(None, None, None, data, is_testnet, debug, json, None).await?;
|
Context::build(None, None, None, data, is_testnet, debug, json, None, false)
|
||||||
|
.await?;
|
||||||
|
|
||||||
(context, request)
|
(context, request)
|
||||||
}
|
}
|
||||||
|
@ -142,6 +142,14 @@ impl Amount {
|
|||||||
Decimal::from(self.as_piconero())
|
Decimal::from(self.as_piconero())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_xmr(&self) -> Decimal {
|
||||||
|
let mut decimal = Decimal::from(self.0);
|
||||||
|
decimal
|
||||||
|
.set_scale(12)
|
||||||
|
.expect("12 is smaller than max precision of 28");
|
||||||
|
decimal
|
||||||
|
}
|
||||||
|
|
||||||
fn from_decimal(amount: Decimal) -> Result<Self> {
|
fn from_decimal(amount: Decimal) -> Result<Self> {
|
||||||
let piconeros_dec =
|
let piconeros_dec =
|
||||||
amount.mul(Decimal::from_u64(PICONERO_OFFSET).expect("constant to fit into u64"));
|
amount.mul(Decimal::from_u64(PICONERO_OFFSET).expect("constant to fit into u64"));
|
||||||
@ -184,11 +192,8 @@ impl From<Amount> for u64 {
|
|||||||
|
|
||||||
impl fmt::Display for Amount {
|
impl fmt::Display for Amount {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let mut decimal = Decimal::from(self.0);
|
let xmr_value = self.as_xmr();
|
||||||
decimal
|
write!(f, "{} XMR", xmr_value)
|
||||||
.set_scale(12)
|
|
||||||
.expect("12 is smaller than max precision of 28");
|
|
||||||
write!(f, "{} XMR", decimal)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,8 +384,8 @@ pub struct State3 {
|
|||||||
S_b_bitcoin: bitcoin::PublicKey,
|
S_b_bitcoin: bitcoin::PublicKey,
|
||||||
pub v: monero::PrivateViewKey,
|
pub v: monero::PrivateViewKey,
|
||||||
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
||||||
btc: bitcoin::Amount,
|
pub btc: bitcoin::Amount,
|
||||||
xmr: monero::Amount,
|
pub xmr: monero::Amount,
|
||||||
pub cancel_timelock: CancelTimelock,
|
pub cancel_timelock: CancelTimelock,
|
||||||
pub punish_timelock: PunishTimelock,
|
pub punish_timelock: PunishTimelock,
|
||||||
refund_address: bitcoin::Address,
|
refund_address: bitcoin::Address,
|
||||||
|
@ -440,7 +440,7 @@ where
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_complete(state: &AliceState) -> bool {
|
pub fn is_complete(state: &AliceState) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
state,
|
state,
|
||||||
AliceState::XmrRefunded
|
AliceState::XmrRefunded
|
||||||
|
@ -369,7 +369,7 @@ pub struct State3 {
|
|||||||
S_a_monero: monero::PublicKey,
|
S_a_monero: monero::PublicKey,
|
||||||
S_a_bitcoin: bitcoin::PublicKey,
|
S_a_bitcoin: bitcoin::PublicKey,
|
||||||
v: monero::PrivateViewKey,
|
v: monero::PrivateViewKey,
|
||||||
xmr: monero::Amount,
|
pub xmr: monero::Amount,
|
||||||
pub cancel_timelock: CancelTimelock,
|
pub cancel_timelock: CancelTimelock,
|
||||||
punish_timelock: PunishTimelock,
|
punish_timelock: PunishTimelock,
|
||||||
refund_address: bitcoin::Address,
|
refund_address: bitcoin::Address,
|
||||||
|
@ -103,13 +103,26 @@ mod test {
|
|||||||
|
|
||||||
let (client, _, _) = setup_daemon(harness_ctx).await;
|
let (client, _, _) = setup_daemon(harness_ctx).await;
|
||||||
|
|
||||||
let response: HashMap<String, Vec<(Uuid, String)>> = client
|
let response: HashMap<String, Vec<Value>> = client
|
||||||
.request("get_history", ObjectParams::new())
|
.request("get_history", ObjectParams::new())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let swaps: Vec<(Uuid, String)> = vec![(bob_swap_id, "btc is locked".to_string())];
|
|
||||||
|
|
||||||
assert_eq!(response, HashMap::from([("swaps".to_string(), swaps)]));
|
let swaps = response.get("swaps").unwrap();
|
||||||
|
assert_eq!(swaps.len(), 1);
|
||||||
|
|
||||||
|
assert_has_keys_serde(
|
||||||
|
swaps[0].as_object().unwrap(),
|
||||||
|
&[
|
||||||
|
"swapId",
|
||||||
|
"startDate",
|
||||||
|
"state",
|
||||||
|
"btcAmount",
|
||||||
|
"xmrAmount",
|
||||||
|
"exchangeRate",
|
||||||
|
"tradingPartnerPeerId",
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
let response: HashMap<String, HashMap<Uuid, Vec<Value>>> = client
|
let response: HashMap<String, HashMap<Uuid, Vec<Value>>> = client
|
||||||
.request("get_raw_states", ObjectParams::new())
|
.request("get_raw_states", ObjectParams::new())
|
||||||
|
Loading…
Reference in New Issue
Block a user