Reimplement transaction-history command with getConfirmedSignaturesForAddress2

This commit is contained in:
Michael Vines
2020-07-28 20:46:23 -07:00
parent 1b2276520b
commit 087fd32ce3
3 changed files with 63 additions and 69 deletions

View File

@ -231,8 +231,8 @@ pub enum CliCommand {
TotalSupply, TotalSupply,
TransactionHistory { TransactionHistory {
address: Pubkey, address: Pubkey,
end_slot: Option<Slot>, // None == latest slot start_after: Option<Signature>,
slot_limit: Option<u64>, // None == search full history limit: usize,
}, },
// Nonce commands // Nonce commands
AuthorizeNonceAccount { AuthorizeNonceAccount {
@ -1871,9 +1871,9 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
CliCommand::TotalSupply => process_total_supply(&rpc_client, config), CliCommand::TotalSupply => process_total_supply(&rpc_client, config),
CliCommand::TransactionHistory { CliCommand::TransactionHistory {
address, address,
end_slot, start_after,
slot_limit, limit,
} => process_transaction_history(&rpc_client, address, *end_slot, *slot_limit), } => process_transaction_history(&rpc_client, config, address, *start_after, *limit),
// Nonce Commands // Nonce Commands

View File

@ -13,7 +13,6 @@ use solana_client::{
pubsub_client::{PubsubClient, SlotInfoMessage}, pubsub_client::{PubsubClient, SlotInfoMessage},
rpc_client::RpcClient, rpc_client::RpcClient,
rpc_config::{RpcLargestAccountsConfig, RpcLargestAccountsFilter}, rpc_config::{RpcLargestAccountsConfig, RpcLargestAccountsFilter},
rpc_request::MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS_SLOT_RANGE,
}; };
use solana_remote_wallet::remote_wallet::RemoteWalletManager; use solana_remote_wallet::remote_wallet::RemoteWalletManager;
use solana_sdk::{ use solana_sdk::{
@ -24,6 +23,7 @@ use solana_sdk::{
message::Message, message::Message,
native_token::lamports_to_sol, native_token::lamports_to_sol,
pubkey::{self, Pubkey}, pubkey::{self, Pubkey},
signature::Signature,
system_instruction, system_program, system_instruction, system_program,
sysvar::{ sysvar::{
self, self,
@ -267,26 +267,22 @@ impl ClusterQuerySubCommands for App<'_, '_> {
.required(true), .required(true),
"Account address"), "Account address"),
) )
.arg(
Arg::with_name("end_slot")
.takes_value(false)
.value_name("SLOT")
.index(2)
.validator(is_slot)
.help(
"Slot to start from [default: latest slot at maximum commitment]"
),
)
.arg( .arg(
Arg::with_name("limit") Arg::with_name("limit")
.long("limit") .long("limit")
.takes_value(true) .takes_value(true)
.value_name("NUMBER OF SLOTS") .value_name("LIMIT")
.validator(is_slot) .validator(is_slot)
.help( .default_value("1000")
"Limit the search to this many slots" .help("Maximum number of transaction signatures to return"),
), )
), .arg(
Arg::with_name("after")
.long("after")
.value_name("TRANSACTION_SIGNATURE")
.takes_value(true)
.help("Start with the first signature older than this one"),
)
) )
} }
} }
@ -440,14 +436,22 @@ pub fn parse_transaction_history(
wallet_manager: &mut Option<Arc<RemoteWalletManager>>, wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
) -> Result<CliCommandInfo, CliError> { ) -> Result<CliCommandInfo, CliError> {
let address = pubkey_of_signer(matches, "address", wallet_manager)?.unwrap(); let address = pubkey_of_signer(matches, "address", wallet_manager)?.unwrap();
let end_slot = value_t!(matches, "end_slot", Slot).ok();
let slot_limit = value_t!(matches, "limit", u64).ok(); let start_after = match matches.value_of("after") {
Some(signature) => Some(
signature
.parse()
.map_err(|err| CliError::BadParameter(format!("Invalid signature: {}", err)))?,
),
None => None,
};
let limit = value_t_or_exit!(matches, "limit", usize);
Ok(CliCommandInfo { Ok(CliCommandInfo {
command: CliCommand::TransactionHistory { command: CliCommand::TransactionHistory {
address, address,
end_slot, start_after,
slot_limit, limit,
}, },
signers: vec![], signers: vec![],
}) })
@ -1305,41 +1309,36 @@ pub fn process_show_validators(
pub fn process_transaction_history( pub fn process_transaction_history(
rpc_client: &RpcClient, rpc_client: &RpcClient,
config: &CliConfig,
address: &Pubkey, address: &Pubkey,
end_slot: Option<Slot>, // None == use latest slot start_after: Option<Signature>,
slot_limit: Option<u64>, limit: usize,
) -> ProcessResult { ) -> ProcessResult {
let end_slot = { let results = rpc_client.get_confirmed_signatures_for_address2_with_config(
if let Some(end_slot) = end_slot {
end_slot
} else {
rpc_client.get_slot_with_commitment(CommitmentConfig::max())?
}
};
let mut start_slot = match slot_limit {
Some(slot_limit) => end_slot.saturating_sub(slot_limit),
None => rpc_client.minimum_ledger_slot()?,
};
println!(
"Transactions affecting {} within slots [{},{}]",
address, start_slot, end_slot
);
let mut transaction_count = 0;
while start_slot < end_slot {
let signatures = rpc_client.get_confirmed_signatures_for_address(
address, address,
start_slot, start_after,
(start_slot + MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS_SLOT_RANGE).min(end_slot), Some(limit),
)?; )?;
for signature in &signatures {
println!("{}", signature); let transactions_found = format!("{} transactions found", results.len());
for result in results {
if config.verbose {
println!(
"{} [slot={} status={}] {}",
result.signature,
result.slot,
match result.err {
None => "Confirmed".to_string(),
Some(err) => format!("Failed: {:?}", err),
},
result.memo.unwrap_or_else(|| "".to_string()),
);
} else {
println!("{}", result.signature);
} }
transaction_count += signatures.len();
start_slot += MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS_SLOT_RANGE;
} }
Ok(format!("{} transactions found", transaction_count)) Ok(transactions_found)
} }
#[cfg(test)] #[cfg(test)]

View File

@ -2161,20 +2161,15 @@ impl RpcSol for RpcSolImpl {
) -> Result<Vec<RpcConfirmedTransactionStatusWithSignature>> { ) -> Result<Vec<RpcConfirmedTransactionStatusWithSignature>> {
let address = verify_pubkey(address)?; let address = verify_pubkey(address)?;
let (start_after, limit) = let config = config.unwrap_or_default();
if let Some(RpcGetConfirmedSignaturesForAddress2Config { start_after, limit }) = config let start_after = if let Some(start_after) = config.start_after {
{
(
if let Some(start_after) = start_after {
Some(verify_signature(&start_after)?) Some(verify_signature(&start_after)?)
} else { } else {
None None
},
limit.unwrap_or(MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS2_LIMIT),
)
} else {
(None, MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS2_LIMIT)
}; };
let limit = config
.limit
.unwrap_or(MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS2_LIMIT);
if limit == 0 || limit > MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS2_LIMIT { if limit == 0 || limit > MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS2_LIMIT {
return Err(Error::invalid_params(format!( return Err(Error::invalid_params(format!(