Skip to content

Commit

Permalink
Merge pull request #652 from tonlabs/SilkovAlexander/account_for_boc
Browse files Browse the repository at this point in the history
Added --boc flag for account command
  • Loading branch information
SilkovAlexander authored May 13, 2022
2 parents 4245280 + 18edfa1 commit 4739f82
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 17 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

All notable changes to this project will be documented in this file.

## Version: 0.26.6

### New


## Version: 0.26.4

### New
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ license = 'Apache-2.0'
name = 'tonos-cli'
readme = 'README.md'
repository = 'https://github.com/tonlabs/tonos-cli'
version = '0.26.5'
version = '0.26.6'

[dependencies]
async-trait = '0.1.42'
Expand Down
28 changes: 22 additions & 6 deletions src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use ton_client::error::ClientError;
use ton_client::net::{ParamsOfQueryCollection, query_collection, ResultOfSubscription, ParamsOfSubscribeCollection};
use ton_client::utils::{calc_storage_fee, ParamsOfCalcStorageFee};
use ton_block::{Account, Deserializable, Serializable};
use crate::decode::print_account_data;

const ACCOUNT_FIELDS: &str = r#"
id
Expand Down Expand Up @@ -68,7 +69,22 @@ async fn query_accounts(config: &Config, addresses: Vec<String>, fields: &str) -
Ok(res)
}

pub async fn get_account(config: &Config, addresses: Vec<String>, dumpfile: Option<&str>, dumpboc: Option<&str>) -> Result<(), String> {
pub async fn get_account(config: &Config, addresses: Vec<String>, dumptvc: Option<&str>, dumpboc: Option<&str>, is_boc: bool) -> Result<(), String> {
if is_boc {
let mut accounts = vec![];
for path in addresses {
let account = Account::construct_from_file(&path)
.map_err(|e| format!(" failed to load account from the boc file {}: {}", path, e))?;
accounts.push(account);
}
if !config.is_json {
println!("\nSucceeded.\n");
}
for account in accounts {
print_account_data(&account, dumptvc, config, false).await?;
}
return Ok(());
}
let accounts = query_accounts(&config, addresses.clone(), ACCOUNT_FIELDS).await?;
if !config.is_json {
println!("Succeeded.");
Expand Down Expand Up @@ -185,22 +201,22 @@ pub async fn get_account(config: &Config, addresses: Vec<String>, dumpfile: Opti
}
}

if dumpfile.is_some() || dumpboc.is_some() && addresses.len() == 1 && accounts.len() == 1 {
if dumptvc.is_some() || dumpboc.is_some() && addresses.len() == 1 && accounts.len() == 1 {
let acc = &accounts[0];
let boc = acc["boc"].as_str()
.ok_or("failed to get boc of the account".to_owned())?;
let account = Account::construct_from_base64(boc)
.map_err(|e| format!("failed to load account from the boc: {}", e))?;
if dumpfile.is_some() {
if dumptvc.is_some() {
if account.state_init().is_some() {
account.state_init().unwrap()
.write_to_file(dumpfile.unwrap())
.map_err(|e| format!("failed to write data to the file {}: {}", dumpfile.unwrap(), e))?;
.write_to_file(dumptvc.unwrap())
.map_err(|e| format!("failed to write data to the file {}: {}", dumptvc.unwrap(), e))?;
} else {
return Err("account doesn't contain state init.".to_owned());
}
if !config.is_json {
println!("Saved contract to file {}", &dumpfile.unwrap());
println!("Saved contract to file {}", &dumptvc.unwrap());
}
}
if dumpboc.is_some() {
Expand Down
13 changes: 8 additions & 5 deletions src/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,10 @@ async fn decode_account_from_boc(m: &ArgMatches<'_>, config: &Config) -> Result<
let account = Account::construct_from_file(boc.unwrap())
.map_err(|e| format!(" failed to load account from the boc file: {}", e))?;

print_account_data(&account, tvc_path, config).await
print_account_data(&account, tvc_path, config, true).await
}

pub async fn print_account_data(account: &Account, tvc_path: Option<&str>, config: &Config) -> Result<(), String> {
pub async fn print_account_data(account: &Account, tvc_path: Option<&str>, config: &Config, decode_stateinit: bool) -> Result<(), String> {
if account.is_none() {
if !config.is_json {
println!("\nAccount is None");
Expand Down Expand Up @@ -179,7 +179,7 @@ pub async fn print_account_data(account: &Account, tvc_path: Option<&str>, confi
};

let trans_lt = account.last_tr_time()
.map_or("Undefined".to_owned(), |v| format!("{}", v));
.map_or("Undefined".to_owned(), |v| format!("{:#x}", v));
let paid = format!("{}", account.last_paid());

let (si, code_hash) = match state_init {
Expand All @@ -198,16 +198,19 @@ pub async fn print_account_data(account: &Account, tvc_path: Option<&str>, confi
_ => ("Undefined".to_owned(), None)
};

let data = tree_of_cells_into_base64(account.get_data().as_ref())?;
let data = hex::encode(base64::decode(&data)
.map_err(|e| format!("Failed to decode base64: {}", e))?);
print_account(
&config,
Some(state),
Some(address),
Some(balance),
Some(paid),
Some(trans_lt),
None,
Some(data),
code_hash,
Some(si),
if decode_stateinit { Some(si) } else { None },
);

if tvc_path.is_some() && state_init.is_some() {
Expand Down
22 changes: 18 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -608,10 +608,11 @@ async fn main_internal() -> Result <(), String> {
.about("Obtains and prints account information.")
.version(&*version_string)
.author("TONLabs")
.arg(boc_flag.clone())
.arg(Arg::with_name("ADDRESS")
.required(true)
.takes_value(true)
.help("List of addresses.")
.help("List of addresses or file paths (if flag --boc is used).")
.multiple(true))
.arg(Arg::with_name("DUMPTVC")
.long("--dumptvc")
Expand All @@ -624,6 +625,7 @@ async fn main_internal() -> Result <(), String> {
.short("-b")
.takes_value(true)
.conflicts_with("DUMPTVC")
.conflicts_with("BOC")
.help("Dumps the whole account state boc to the specified file. Works only if one address was given. Use 'tonos-cli dump account` to dump several accounts."));

let account_wait_cmd = SubCommand::with_name("account-wait")
Expand Down Expand Up @@ -1498,18 +1500,30 @@ async fn genaddr_command(matches: &ArgMatches<'_>, config: &Config) -> Result<()

async fn account_command(matches: &ArgMatches<'_>, config: &Config) -> Result<(), String> {
let addresses_list = matches.values_of("ADDRESS").unwrap().collect::<Vec<_>>();
if addresses_list.len() > 1 &&
(matches.is_present("DUMPTVC") || matches.is_present("DUMPTVC")) {
return Err("`DUMPTVC` and `DUMPBOC` options are not applicable to a list of addresses.".to_string());
}
let is_boc = matches.is_present("BOC");
let mut formatted_list = vec![];
for address in addresses_list.iter() {
let formatted = load_ton_address(address, &config)?;
formatted_list.push(formatted);
if !is_boc {
let formatted = load_ton_address(address, &config)?;
formatted_list.push(formatted);
} else {
if !std::path::Path::new(address).exists() {
return Err(format!("File {} doesn't exist.", address));
}
formatted_list.push(address.to_string());
}
}
let tvcname = matches.value_of("DUMPTVC");
let bocname = matches.value_of("DUMPBOC");
let addresses = Some(formatted_list.join(", "));
if !config.is_json {
print_args!(addresses);
}
get_account(&config, formatted_list, tvcname, bocname).await
get_account(&config, formatted_list, tvcname, bocname, is_boc).await
}

async fn dump_accounts_command(matches: &ArgMatches<'_>, config: &Config) -> Result<(), String> {
Expand Down
14 changes: 14 additions & 0 deletions tests/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ fn set_config(config: &str, argument: &str) -> Result<(), Box<dyn std::error::Er
.success();
Ok(())
}

fn generate_public_key(seed: &str) -> Result<String, Box<dyn std::error::Error>> {
let mut cmd = Command::cargo_bin(BIN_NAME)?;
let out = cmd.arg("genpubkey")
Expand Down Expand Up @@ -826,6 +827,19 @@ fn test_account_command() -> Result<(), Box<dyn std::error::Error>> {
cmd.assert()
.success()
.stdout(predicate::str::contains("Account not found"));

let mut cmd = Command::cargo_bin(BIN_NAME)?;
cmd.arg("account")
.arg("--boc")
.arg("tests/account.boc");
cmd.assert()
.success()
.stdout(predicate::str::contains("acc_type: Active"))
.stdout(predicate::str::contains("balance:"))
.stdout(predicate::str::contains("last_paid:"))
.stdout(predicate::str::contains("last_trans_lt:"))
.stdout(predicate::str::contains("data(boc):"));

Ok(())
}

Expand Down

0 comments on commit 4739f82

Please sign in to comment.