Passing -v/--verbose to solana confirm now displays the full transaction

This commit is contained in:
Michael Vines
2020-04-15 20:51:05 -07:00
parent 4ac15e68cf
commit 7e7cbec8a1
9 changed files with 239 additions and 113 deletions

View File

@ -40,6 +40,7 @@ solana-runtime = { path = "../runtime", version = "1.2.0" }
solana-sdk = { path = "../sdk", version = "1.2.0" }
solana-stake-program = { path = "../programs/stake", version = "1.2.0" }
solana-storage-program = { path = "../programs/storage", version = "1.2.0" }
solana-transaction-status = { path = "../transaction-status", version = "1.2.0" }
solana-vote-program = { path = "../programs/vote", version = "1.2.0" }
solana-vote-signer = { path = "../vote-signer", version = "1.2.0" }
thiserror = "1.0.15"

View File

@ -1165,12 +1165,48 @@ fn process_balance(
}
}
fn process_confirm(rpc_client: &RpcClient, signature: &Signature) -> ProcessResult {
match rpc_client.get_signature_status(&signature) {
fn process_confirm(
rpc_client: &RpcClient,
config: &CliConfig,
signature: &Signature,
) -> ProcessResult {
match rpc_client.get_signature_status_with_commitment_and_history(
&signature,
CommitmentConfig::max(),
true,
) {
Ok(status) => {
if let Some(result) = status {
match result {
Ok(_) => Ok("Confirmed".to_string()),
Ok(_) => {
if config.verbose {
match rpc_client.get_confirmed_transaction(
signature,
solana_transaction_status::TransactionEncoding::Binary,
) {
Ok(confirmed_transaction) => {
println!("\nTransaction:");
crate::display::println_transaction(
&confirmed_transaction
.transaction
.transaction
.decode()
.expect("Successful decode"),
&confirmed_transaction.transaction.meta,
" ",
);
println!();
Ok(format!("Confirmed in slot {}", confirmed_transaction.slot))
}
Err(err) => Ok(format!(
"Confirmed. Unable to get confirmed transaction details: {}",
err
)),
}
} else {
Ok("Confirmed".to_string())
}
}
Err(err) => Ok(format!("Transaction failed with error: {}", err)),
}
} else {
@ -2063,7 +2099,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
// Cancel a contract by contract Pubkey
CliCommand::Cancel(pubkey) => process_cancel(&rpc_client, config, &pubkey),
// Confirm the last client transaction by signature
CliCommand::Confirm(signature) => process_confirm(&rpc_client, signature),
CliCommand::Confirm(signature) => process_confirm(&rpc_client, config, signature),
// If client has positive balance, pay lamports to another address
CliCommand::Pay(PayCommand {
lamports,

View File

@ -1,6 +1,10 @@
use crate::cli::SettingType;
use console::style;
use solana_sdk::hash::Hash;
use solana_sdk::{
hash::Hash, native_token::lamports_to_sol, program_utils::limited_deserialize,
transaction::Transaction,
};
use solana_transaction_status::RpcTransactionStatusMeta;
use std::fmt;
// Pretty print a "name value"
@ -59,3 +63,106 @@ pub fn println_signers(
}
println!();
}
pub fn println_transaction(
transaction: &Transaction,
transaction_status: &Option<RpcTransactionStatusMeta>,
prefix: &str,
) {
let message = &transaction.message;
println!("{}Recent Blockhash: {:?}", prefix, message.recent_blockhash);
for (signature_index, signature) in transaction.signatures.iter().enumerate() {
println!("{}Signature {}: {:?}", prefix, signature_index, signature);
}
println!("{}{:?}", prefix, message.header);
for (account_index, account) in message.account_keys.iter().enumerate() {
println!("{}Account {}: {:?}", prefix, account_index, account);
}
for (instruction_index, instruction) in message.instructions.iter().enumerate() {
let program_pubkey = message.account_keys[instruction.program_id_index as usize];
println!("{}Instruction {}", prefix, instruction_index);
println!(
"{} Program: {} ({})",
prefix, program_pubkey, instruction.program_id_index
);
for (account_index, account) in instruction.accounts.iter().enumerate() {
let account_pubkey = message.account_keys[*account as usize];
println!(
"{} Account {}: {} ({})",
prefix, account_index, account_pubkey, account
);
}
let mut raw = true;
if program_pubkey == solana_vote_program::id() {
if let Ok(vote_instruction) = limited_deserialize::<
solana_vote_program::vote_instruction::VoteInstruction,
>(&instruction.data)
{
println!("{} {:?}", prefix, vote_instruction);
raw = false;
}
} else if program_pubkey == solana_stake_program::id() {
if let Ok(stake_instruction) = limited_deserialize::<
solana_stake_program::stake_instruction::StakeInstruction,
>(&instruction.data)
{
println!("{} {:?}", prefix, stake_instruction);
raw = false;
}
} else if program_pubkey == solana_sdk::system_program::id() {
if let Ok(system_instruction) = limited_deserialize::<
solana_sdk::system_instruction::SystemInstruction,
>(&instruction.data)
{
println!("{} {:?}", prefix, system_instruction);
raw = false;
}
}
if raw {
println!("{} Data: {:?}", prefix, instruction.data);
}
}
if let Some(transaction_status) = transaction_status {
println!(
"{}Status: {}",
prefix,
match &transaction_status.status {
Ok(_) => "Ok".into(),
Err(err) => err.to_string(),
}
);
println!("{} Fee: {}", prefix, transaction_status.fee);
assert_eq!(
transaction_status.pre_balances.len(),
transaction_status.post_balances.len()
);
for (i, (pre, post)) in transaction_status
.pre_balances
.iter()
.zip(transaction_status.post_balances.iter())
.enumerate()
{
if pre == post {
println!(
"{} Account {} balance: {} SOL",
prefix,
i,
lamports_to_sol(*pre)
);
} else {
println!(
"{} Account {} balance: {} SOL -> {} SOL",
prefix,
i,
lamports_to_sol(*pre),
lamports_to_sol(*post)
);
}
}
} else {
println!("{}Status: Unavailable", prefix);
}
}