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), 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.")]

View file

@ -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; use swap::database::open_db;
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,17 +228,81 @@ async fn main() -> Result<()> {
event_loop.run().await; event_loop.run().await;
} }
Command::History => { Command::History { only_unfinished } => {
let mut table = Table::new(); 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? { if only_unfinished && is_complete(&latest_state) {
let state: AliceState = state.try_into()?; () // Skip finished swaps
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 = 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);
}
} }
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)?;

View file

@ -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)
} }
} }

View file

@ -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,

View file

@ -397,7 +397,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