drk/
common.rs

1/* This file is part of DarkFi (https://dark.fi)
2 *
3 * Copyright (C) 2020-2025 Dyne.org foundation
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as
7 * published by the Free Software Foundation, either version 3 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 */
18
19use std::collections::HashMap;
20
21use darkfi::{util::parse::encode_base10, zk::halo2::Field};
22use darkfi_money_contract::{client::OwnCoin, model::TokenId};
23use darkfi_sdk::{
24    crypto::{
25        keypair::{Address, Network, PublicKey, SecretKey, StandardAddress},
26        BaseBlind, ContractId, FuncId,
27    },
28    pasta::pallas,
29};
30use darkfi_serial::serialize;
31use prettytable::{format, row, Table};
32
33use crate::money::BALANCE_BASE10_DECIMALS;
34
35pub fn prettytable_addrs(
36    network: Network,
37    addresses: &[(u64, PublicKey, SecretKey, u64)],
38) -> Table {
39    let mut table = Table::new();
40    table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
41    table.set_titles(row!["Key ID", "Address", "Public Key", "Secret Key", "Is Default"]);
42    for (key_id, public_key, secret_key, is_default) in addresses {
43        let is_default = match is_default {
44            1 => "*",
45            _ => "",
46        };
47
48        let address: Address = StandardAddress::from_public(network, *public_key).into();
49        table.add_row(row![key_id, address, public_key, secret_key, is_default]);
50    }
51
52    table
53}
54
55pub fn prettytable_balance(
56    balmap: &HashMap<String, u64>,
57    alimap: &HashMap<String, String>,
58) -> Table {
59    let mut table = Table::new();
60    table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
61    table.set_titles(row!["Token ID", "Aliases", "Balance"]);
62
63    for (token_id, balance) in balmap.iter() {
64        let alias = match alimap.get(token_id) {
65            Some(v) => v,
66            None => "-",
67        };
68
69        table.add_row(row![token_id, alias, encode_base10(*balance, BALANCE_BASE10_DECIMALS)]);
70    }
71
72    table
73}
74
75pub fn prettytable_coins(
76    coins: &[(OwnCoin, u32, bool, Option<u32>, String)],
77    alimap: &HashMap<String, String>,
78) -> Table {
79    let mut table = Table::new();
80    table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
81    table.set_titles(row![
82        "Coin",
83        "Token ID",
84        "Aliases",
85        "Value",
86        "Spend Hook",
87        "User Data",
88        "Creation Height",
89        "Spent",
90        "Spent Height",
91        "Spent TX",
92    ]);
93
94    for coin in coins {
95        let alias = match alimap.get(&coin.0.note.token_id.to_string()) {
96            Some(v) => v,
97            None => "-",
98        };
99
100        let spend_hook = if coin.0.note.spend_hook != FuncId::none() {
101            format!("{}", coin.0.note.spend_hook)
102        } else {
103            String::from("-")
104        };
105
106        let user_data = if coin.0.note.user_data != pallas::Base::ZERO {
107            bs58::encode(serialize(&coin.0.note.user_data)).into_string().to_string()
108        } else {
109            String::from("-")
110        };
111
112        let spent_height = match coin.3 {
113            Some(spent_height) => spent_height.to_string(),
114            None => String::from("-"),
115        };
116
117        table.add_row(row![
118            bs58::encode(&serialize(&coin.0.coin.inner())).into_string().to_string(),
119            coin.0.note.token_id,
120            alias,
121            format!(
122                "{} ({})",
123                coin.0.note.value,
124                encode_base10(coin.0.note.value, BALANCE_BASE10_DECIMALS)
125            ),
126            spend_hook,
127            user_data,
128            coin.1,
129            coin.2,
130            spent_height,
131            coin.4,
132        ]);
133    }
134
135    table
136}
137
138pub fn prettytable_tokenlist(
139    tokens: &[(TokenId, SecretKey, BaseBlind, bool, Option<u32>)],
140    alimap: &HashMap<String, String>,
141) -> Table {
142    let mut table = Table::new();
143    table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
144    table.set_titles(row![
145        "Token ID",
146        "Aliases",
147        "Mint Authority",
148        "Token Blind",
149        "Frozen",
150        "Freeze Height",
151    ]);
152
153    for (token_id, authority, blind, frozen, freeze_height) in tokens {
154        let alias = match alimap.get(&token_id.to_string()) {
155            Some(v) => v,
156            None => "-",
157        };
158
159        let freeze_height = match freeze_height {
160            Some(freeze_height) => freeze_height.to_string(),
161            None => String::from("-"),
162        };
163
164        table.add_row(row![token_id, alias, authority, blind, frozen, freeze_height]);
165    }
166
167    table
168}
169
170pub fn prettytable_contract_history(deploy_history: &[(String, String, u32)]) -> Table {
171    let mut table = Table::new();
172    table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
173    table.set_titles(row!["Transaction Hash", "Type", "Block Height"]);
174
175    for (tx_hash, tx_type, block_height) in deploy_history {
176        table.add_row(row![tx_hash, tx_type, block_height]);
177    }
178
179    table
180}
181
182pub fn prettytable_contract_auth(auths: &[(ContractId, SecretKey, bool, Option<u32>)]) -> Table {
183    let mut table = Table::new();
184    table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
185    table.set_titles(row!["Contract ID", "Secret Key", "Locked", "Lock Height"]);
186
187    for (contract_id, secret_key, is_locked, lock_height) in auths {
188        let lock_height = match lock_height {
189            Some(lock_height) => lock_height.to_string(),
190            None => String::from("-"),
191        };
192
193        table.add_row(row![contract_id, secret_key, is_locked, lock_height]);
194    }
195
196    table
197}
198
199pub fn prettytable_aliases(alimap: &HashMap<String, TokenId>) -> Table {
200    let mut table = Table::new();
201    table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
202    table.set_titles(row!["Alias", "Token ID"]);
203
204    for (alias, token_id) in alimap.iter() {
205        table.add_row(row![alias, token_id]);
206    }
207
208    table
209}
210
211pub fn prettytable_scanned_blocks(scanned_blocks: &[(u32, String, String)]) -> Table {
212    let mut table = Table::new();
213    table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
214    table.set_titles(row!["Height", "Hash", "Signing Key"]);
215    for (height, hash, signing_key) in scanned_blocks {
216        table.add_row(row![height, hash, signing_key]);
217    }
218
219    table
220}