Skip to content
This repository has been archived by the owner on Jan 13, 2025. It is now read-only.

Commit

Permalink
Passing -v/--verbose to solana confirm now displays the full transa…
Browse files Browse the repository at this point in the history
…ction

(cherry picked from commit 7e7cbec)

# Conflicts:
#	Cargo.lock
#	cli/Cargo.toml
#	ledger-tool/Cargo.toml
  • Loading branch information
mvines authored and mergify-bot committed Apr 16, 2020
1 parent 0073448 commit 9fe515c
Show file tree
Hide file tree
Showing 9 changed files with 300 additions and 112 deletions.
35 changes: 35 additions & 0 deletions Cargo.lock

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

21 changes: 21 additions & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pretty-hex = "0.1.1"
reqwest = { version = "0.10.4", default-features = false, features = ["blocking", "rustls-tls", "json"] }
serde = "1.0.105"
serde_derive = "1.0.103"
<<<<<<< HEAD
serde_json = "1.0.48"
solana-budget-program = { path = "../programs/budget", version = "1.1.4" }
solana-clap-utils = { path = "../clap-utils", version = "1.1.4" }
Expand All @@ -43,6 +44,26 @@ solana-storage-program = { path = "../programs/storage", version = "1.1.4" }
solana-vote-program = { path = "../programs/vote", version = "1.1.4" }
solana-vote-signer = { path = "../vote-signer", version = "1.1.4" }
thiserror = "1.0.13"
=======
serde_json = "1.0.51"
solana-budget-program = { path = "../programs/budget", version = "1.2.0" }
solana-clap-utils = { path = "../clap-utils", version = "1.2.0" }
solana-cli-config = { path = "../cli-config", version = "1.2.0" }
solana-client = { path = "../client", version = "1.2.0" }
solana-config-program = { path = "../programs/config", version = "1.2.0" }
solana-faucet = { path = "../faucet", version = "1.2.0" }
solana-logger = { path = "../logger", version = "1.2.0" }
solana-net-utils = { path = "../net-utils", version = "1.2.0" }
solana-remote-wallet = { path = "../remote-wallet", version = "1.2.0" }
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"
>>>>>>> 7e7cbec8a... Passing -v/--verbose to `solana confirm` now displays the full transaction
url = "2.1.1"

[dev-dependencies]
Expand Down
44 changes: 40 additions & 4 deletions cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down
109 changes: 108 additions & 1 deletion cli/src/display.rs
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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);
}
}
64 changes: 63 additions & 1 deletion client/src/rpc_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ use solana_sdk::{
signers::Signers,
transaction::{self, Transaction, TransactionError},
};
use solana_transaction_status::{ConfirmedBlock, TransactionEncoding, TransactionStatus};
use solana_transaction_status::{
ConfirmedBlock, ConfirmedTransaction, TransactionEncoding, TransactionStatus,
};
use solana_vote_program::vote_state::MAX_LOCKOUT_HISTORY;
use std::{
error,
Expand Down Expand Up @@ -158,6 +160,28 @@ impl RpcClient {
.map(|status_meta| status_meta.status))
}

pub fn get_signature_status_with_commitment_and_history(
&self,
signature: &Signature,
commitment_config: CommitmentConfig,
search_transaction_history: bool,
) -> ClientResult<Option<transaction::Result<()>>> {
let signature_status = self.client.send(
&RpcRequest::GetSignatureStatuses,
json!([[signature.to_string()], {
"searchTransactionHistory": search_transaction_history
}]),
5,
)?;
let result: Response<Vec<Option<TransactionStatus>>> =
serde_json::from_value(signature_status)
.map_err(|err| ClientError::new_with_command(err.into(), "GetSignatureStatuses"))?;
Ok(result.value[0]
.clone()
.filter(|result| result.satisfies_commitment(commitment_config))
.map(|status_meta| status_meta.status))
}

pub fn get_slot(&self) -> ClientResult<Slot> {
self.get_slot_with_commitment(CommitmentConfig::default())
}
Expand Down Expand Up @@ -255,6 +279,44 @@ impl RpcClient {
.map_err(|err| ClientError::new_with_command(err.into(), "GetConfirmedBlocks"))
}

pub fn get_confirmed_signatures_for_address(
&self,
address: &Pubkey,
start_slot: Slot,
end_slot: Slot,
) -> ClientResult<Vec<Signature>> {
let response = self
.client
.send(
&RpcRequest::GetConfirmedSignaturesForAddress,
json!([address, start_slot, end_slot]),
0,
)
.map_err(|err| err.into_with_command("GetConfirmedSignaturesForAddress"))?;

serde_json::from_value(response).map_err(|err| {
ClientError::new_with_command(err.into(), "GetConfirmedSignaturesForAddress")
})
}

pub fn get_confirmed_transaction(
&self,
signature: &Signature,
encoding: TransactionEncoding,
) -> ClientResult<ConfirmedTransaction> {
let response = self
.client
.send(
&RpcRequest::GetConfirmedTransaction,
json!([signature.to_string(), encoding]),
0,
)
.map_err(|err| err.into_with_command("GetConfirmedTransaction"))?;

serde_json::from_value(response)
.map_err(|err| ClientError::new_with_command(err.into(), "GetConfirmedTransaction"))
}

pub fn get_block_time(&self, slot: Slot) -> ClientResult<UnixTimestamp> {
let response = self
.client
Expand Down
4 changes: 4 additions & 0 deletions client/src/rpc_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub enum RpcRequest {
GetClusterNodes,
GetConfirmedBlock,
GetConfirmedBlocks,
GetConfirmedSignaturesForAddress,
GetConfirmedTransaction,
GetEpochInfo,
GetEpochSchedule,
GetGenesisHash,
Expand Down Expand Up @@ -52,6 +54,8 @@ impl RpcRequest {
RpcRequest::GetClusterNodes => "getClusterNodes",
RpcRequest::GetConfirmedBlock => "getConfirmedBlock",
RpcRequest::GetConfirmedBlocks => "getConfirmedBlocks",
RpcRequest::GetConfirmedSignaturesForAddress => "getConfirmedSignaturesForAddress",
RpcRequest::GetConfirmedTransaction => "getConfirmedTransaction",
RpcRequest::GetEpochInfo => "getEpochInfo",
RpcRequest::GetEpochSchedule => "getEpochSchedule",
RpcRequest::GetGenesisHash => "getGenesisHash",
Expand Down
Loading

0 comments on commit 9fe515c

Please sign in to comment.