feat(asb): History command display start datetime, btc amount, xmr amount, exchange rate and peer id of trading partner

This commit is contained in:
binarybaron 2024-07-23 21:16:04 +02:00
parent ab273ee3f2
commit 97920628e5
No known key found for this signature in database
GPG key ID: 99B75D3E1476A26E
5 changed files with 99 additions and 18 deletions

View file

@ -33,13 +33,13 @@ where
env_config: env_config(testnet),
cmd: Command::Start { resume_only },
},
RawCommand::History => Arguments {
RawCommand::History { only_unfinished } => Arguments {
testnet,
json,
disable_timestamp,
config_path: config_path(config, testnet)?,
env_config: env_config(testnet),
cmd: Command::History,
cmd: Command::History { only_unfinished },
},
RawCommand::WithdrawBtc { amount, address } => Arguments {
testnet,
@ -195,7 +195,9 @@ pub enum Command {
Start {
resume_only: bool,
},
History,
History {
only_unfinished: bool,
},
Config,
WithdrawBtc {
amount: Option<Amount>,
@ -269,7 +271,13 @@ pub enum RawCommand {
resume_only: bool,
},
#[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")]
Config,
#[structopt(about = "Allows withdrawing BTC from the internal Bitcoin wallet.")]

View file

@ -18,6 +18,8 @@ use libp2p::core::multiaddr::Protocol;
use libp2p::core::Multiaddr;
use libp2p::swarm::AddressScore;
use libp2p::Swarm;
use rust_decimal::prelude::FromPrimitive;
use rust_decimal::Decimal;
use std::convert::TryInto;
use std::env;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
@ -33,7 +35,9 @@ use swap::common::check_latest_version;
use swap::database::open_db;
use swap::network::rendezvous::XmrBtcNamespace;
use swap::network::swarm;
use swap::protocol::alice::swap::is_complete;
use swap::protocol::alice::{run, AliceState};
use swap::protocol::State;
use swap::seed::Seed;
use swap::tor::AuthenticatedClient;
use swap::{asb, bitcoin, kraken, monero, tor};
@ -224,18 +228,82 @@ async fn main() -> Result<()> {
event_loop.run().await;
}
Command::History => {
Command::History { only_unfinished } => {
let mut table = Table::new();
table.set_header(vec![
"SWAP ID",
"START DATETIME",
"CURRENT STATE",
"BTC AMOUNT",
"XMR AMOUNT",
"EXCHANGE RATE",
"TRADING PARTNER PEER ID",
]);
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()?;
for (swap_id, state) in db.all().await? {
let state: AliceState = state.try_into()?;
table.add_row(vec![swap_id.to_string(), state.to_string()]);
if only_unfinished && is_complete(&latest_state) {
() // Skip finished swaps
}
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 = format!(
"{} XMR/BTC",
(Decimal::from_f64(state3.btc.to_btc()).unwrap() / state3.xmr.as_xmr())
.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,
"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(),
]);
}
Ok::<_, anyhow::Error>(())
}
.await
{
tracing::error!(swap_id = %swap_id, "{:#}", e);
}
}
if !json {
println!("{}", table);
}
}
Command::Config => {
let config_json = serde_json::to_string_pretty(&config)?;
println!("{}", config_json);

View file

@ -142,6 +142,14 @@ impl Amount {
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> {
let piconeros_dec =
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 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut decimal = Decimal::from(self.0);
decimal
.set_scale(12)
.expect("12 is smaller than max precision of 28");
write!(f, "{} XMR", decimal)
let xmr_value = self.as_xmr();
write!(f, "{} XMR", xmr_value)
}
}

View file

@ -384,8 +384,8 @@ pub struct State3 {
S_b_bitcoin: bitcoin::PublicKey,
pub v: monero::PrivateViewKey,
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
btc: bitcoin::Amount,
xmr: monero::Amount,
pub btc: bitcoin::Amount,
pub xmr: monero::Amount,
pub cancel_timelock: CancelTimelock,
pub punish_timelock: PunishTimelock,
refund_address: bitcoin::Address,

View file

@ -397,7 +397,7 @@ where
})
}
pub(crate) fn is_complete(state: &AliceState) -> bool {
pub fn is_complete(state: &AliceState) -> bool {
matches!(
state,
AliceState::XmrRefunded