grin/wallet/src/display.rs
Gary Yu f645937a2b replace cyan and yellow which not easy to read on white background (#1903)
* replace cyan and yellow which not easy to read on white background

* wallet output color scheme configuration for terminal dark/white background

* use true for dark_background_color_scheme to make the default behavior same as before
2018-11-03 09:42:41 +01:00

308 lines
8.5 KiB
Rust
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use core::core::{self, amount_to_hr_string};
use libwallet::types::{AcctPathMapping, OutputData, OutputStatus, TxLogEntry, WalletInfo};
use libwallet::Error;
use prettytable;
use std::io::prelude::Write;
use term;
use util;
use util::secp::pedersen;
/// Display outputs in a pretty way
pub fn outputs(
account: &str,
cur_height: u64,
validated: bool,
outputs: Vec<(OutputData, pedersen::Commitment)>,
dark_background_color_scheme: bool,
) -> Result<(), Error> {
let title = format!(
"Wallet Outputs - Account '{}' - Block Height: {}",
account, cur_height
);
println!();
let mut t = term::stdout().unwrap();
t.fg(term::color::MAGENTA).unwrap();
writeln!(t, "{}", title).unwrap();
t.reset().unwrap();
let mut table = table!();
table.set_titles(row![
bMG->"Output Commitment",
bMG->"Block Height",
bMG->"Locked Until",
bMG->"Status",
bMG->"Coinbase?",
bMG->"# Confirms",
bMG->"Value",
bMG->"Tx"
]);
for (out, commit) in outputs {
let commit = format!("{}", util::to_hex(commit.as_ref().to_vec()));
let height = format!("{}", out.height);
let lock_height = format!("{}", out.lock_height);
let is_coinbase = format!("{}", out.is_coinbase);
// Mark unconfirmed coinbase outputs as "Mining" instead of "Unconfirmed"
let status = match out.status {
OutputStatus::Unconfirmed if out.is_coinbase => "Mining".to_string(),
_ => format!("{}", out.status),
};
let num_confirmations = format!("{}", out.num_confirmations(cur_height));
let value = format!("{}", core::amount_to_hr_string(out.value, false));
let tx = match out.tx_log_entry {
None => "".to_owned(),
Some(t) => t.to_string(),
};
if dark_background_color_scheme {
table.add_row(row![
bFC->commit,
bFB->height,
bFB->lock_height,
bFR->status,
bFY->is_coinbase,
bFB->num_confirmations,
bFG->value,
bFC->tx,
]);
} else {
table.add_row(row![
bFD->commit,
bFB->height,
bFB->lock_height,
bFR->status,
bFD->is_coinbase,
bFB->num_confirmations,
bFG->value,
bFD->tx,
]);
}
}
table.set_format(*prettytable::format::consts::FORMAT_NO_COLSEP);
table.printstd();
println!();
if !validated {
println!(
"\nWARNING: Wallet failed to verify data. \
The above is from local cache and possibly invalid! \
(is your `grin server` offline or broken?)"
);
}
Ok(())
}
/// Display transaction log in a pretty way
pub fn txs(
account: &str,
cur_height: u64,
validated: bool,
txs: Vec<TxLogEntry>,
include_status: bool,
dark_background_color_scheme: bool,
) -> Result<(), Error> {
let title = format!(
"Transaction Log - Account '{}' - Block Height: {}",
account, cur_height
);
println!();
let mut t = term::stdout().unwrap();
t.fg(term::color::MAGENTA).unwrap();
writeln!(t, "{}", title).unwrap();
t.reset().unwrap();
let mut table = table!();
table.set_titles(row![
bMG->"Id",
bMG->"Type",
bMG->"Shared Transaction Id",
bMG->"Creation Time",
bMG->"Confirmed?",
bMG->"Confirmation Time",
bMG->"Num. \nInputs",
bMG->"Num. \nOutputs",
bMG->"Amount \nCredited",
bMG->"Amount \nDebited",
bMG->"Fee",
bMG->"Net \nDifference",
bMG->"Tx \nData",
]);
for t in txs {
let id = format!("{}", t.id);
let slate_id = match t.tx_slate_id {
Some(m) => format!("{}", m),
None => "None".to_owned(),
};
let entry_type = format!("{}", t.tx_type);
let creation_ts = format!("{}", t.creation_ts.format("%Y-%m-%d %H:%M:%S"));
let confirmation_ts = match t.confirmation_ts {
Some(m) => format!("{}", m.format("%Y-%m-%d %H:%M:%S")),
None => "None".to_owned(),
};
let confirmed = format!("{}", t.confirmed);
let num_inputs = format!("{}", t.num_inputs);
let num_outputs = format!("{}", t.num_outputs);
let amount_debited_str = core::amount_to_hr_string(t.amount_debited, true);
let amount_credited_str = core::amount_to_hr_string(t.amount_credited, true);
let fee = match t.fee {
Some(f) => format!("{}", core::amount_to_hr_string(f, true)),
None => "None".to_owned(),
};
let net_diff = if t.amount_credited >= t.amount_debited {
core::amount_to_hr_string(t.amount_credited - t.amount_debited, true)
} else {
format!(
"-{}",
core::amount_to_hr_string(t.amount_debited - t.amount_credited, true)
)
};
let tx_data = match t.tx_hex {
Some(_) => format!("Exists"),
None => "None".to_owned(),
};
if dark_background_color_scheme {
table.add_row(row![
bFC->id,
bFC->entry_type,
bFC->slate_id,
bFB->creation_ts,
bFC->confirmed,
bFB->confirmation_ts,
bFC->num_inputs,
bFC->num_outputs,
bFG->amount_credited_str,
bFR->amount_debited_str,
bFR->fee,
bFY->net_diff,
bFb->tx_data,
]);
} else {
if t.confirmed {
table.add_row(row![
bFD->id,
bFb->entry_type,
bFD->slate_id,
bFB->creation_ts,
bFg->confirmed,
bFB->confirmation_ts,
bFD->num_inputs,
bFD->num_outputs,
bFG->amount_credited_str,
bFD->amount_debited_str,
bFD->fee,
bFG->net_diff,
bFB->tx_data,
]);
} else {
table.add_row(row![
bFD->id,
bFb->entry_type,
bFD->slate_id,
bFB->creation_ts,
bFR->confirmed,
bFB->confirmation_ts,
bFD->num_inputs,
bFD->num_outputs,
bFG->amount_credited_str,
bFD->amount_debited_str,
bFD->fee,
bFG->net_diff,
bFB->tx_data,
]);
}
}
}
table.set_format(*prettytable::format::consts::FORMAT_NO_COLSEP);
table.printstd();
println!();
if !validated && include_status {
println!(
"\nWARNING: Wallet failed to verify data. \
The above is from local cache and possibly invalid! \
(is your `grin server` offline or broken?)"
);
}
Ok(())
}
/// Display summary info in a pretty way
pub fn info(
account: &str,
wallet_info: &WalletInfo,
validated: bool,
dark_background_color_scheme: bool,
) {
println!(
"\n____ Wallet Summary Info - Account '{}' as of height {} ____\n",
account, wallet_info.last_confirmed_height
);
let mut table = if dark_background_color_scheme {
table!(
[bFG->"Total", FG->amount_to_hr_string(wallet_info.total, false)],
[bFY->"Awaiting Confirmation", FY->amount_to_hr_string(wallet_info.amount_awaiting_confirmation, false)],
[bFY->"Immature Coinbase", FY->amount_to_hr_string(wallet_info.amount_immature, false)],
[bFG->"Currently Spendable", FG->amount_to_hr_string(wallet_info.amount_currently_spendable, false)],
[Fw->"--------------------------------", Fw->"-------------"],
[Fr->"(Locked by previous transaction)", Fr->amount_to_hr_string(wallet_info.amount_locked, false)]
)
} else {
table!(
[bFG->"Total", FG->amount_to_hr_string(wallet_info.total, false)],
[bFB->"Awaiting Confirmation", FB->amount_to_hr_string(wallet_info.amount_awaiting_confirmation, false)],
[bFB->"Immature Coinbase", FB->amount_to_hr_string(wallet_info.amount_immature, false)],
[bFG->"Currently Spendable", FG->amount_to_hr_string(wallet_info.amount_currently_spendable, false)],
[Fw->"--------------------------------", Fw->"-------------"],
[Fr->"(Locked by previous transaction)", Fr->amount_to_hr_string(wallet_info.amount_locked, false)]
)
};
table.set_format(*prettytable::format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
table.printstd();
println!();
if !validated {
println!(
"\nWARNING: Wallet failed to verify data against a live chain. \
The above is from local cache and only valid up to the given height! \
(is your `grin server` offline or broken?)"
);
}
}
/// Display list of wallet accounts in a pretty way
pub fn accounts(acct_mappings: Vec<AcctPathMapping>) {
println!("\n____ Wallet Accounts ____\n",);
let mut table = table!();
table.set_titles(row![
mMG->"Name",
bMG->"Parent BIP-32 Derivation Path",
]);
for m in acct_mappings {
table.add_row(row![
bFC->m.label,
bGC->m.path.to_bip_32_string(),
]);
}
table.set_format(*prettytable::format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
table.printstd();
println!();
}