Contractless/src/bin/lookup_mempool_tx_by_signat...

110 lines
4.8 KiB
Rust
Raw Normal View History

2026-05-24 17:56:57 +00:00
use blockchain::blocks::burn::BurnTransaction;
use blockchain::blocks::collateral::CollateralClaimTransaction;
use blockchain::blocks::issue_token::IssueTokenTransaction;
use blockchain::blocks::loan_payment::ContractPaymentTransaction;
use blockchain::blocks::loans::LoanContractTransaction;
use blockchain::blocks::marketing::MarketingTransaction;
use blockchain::blocks::nft::CreateNftTransaction;
use blockchain::blocks::swap::SwapTransaction;
use blockchain::blocks::token::CreateTokenTransaction;
use blockchain::blocks::transfer::TransferTransaction;
use blockchain::blocks::vanity::VanityAddressTransaction;
use blockchain::common::cli_prompts::prompt_hidden_nonempty;
use blockchain::common::network_startup::get_connections;
use blockchain::common::types::{
BORROWER_TYPE, BURN_TYPE, COLLATERAL_TYPE, CREATE_NFT_TYPE, CREATE_TOKEN_TYPE,
ISSUE_TOKEN_TYPE, LENDER_TYPE, MARKETING_TYPE, SWAP_TYPE, TRANSFER_TYPE, VANITY_ADDRESS_TYPE,
};
use blockchain::env;
use blockchain::records::memory::response_channels::generate_uid;
use blockchain::standalone_tools::connections::handshake;
use blockchain::to_string_pretty;
async fn decode_mempool_transaction(response: &[u8]) -> Option<String> {
// Mempool transaction replies are the original transaction bytes,
// starting with the transaction type byte and no block-height prefix.
let txtype = *response.first()?;
let body = &response[1..];
match txtype {
TRANSFER_TYPE => to_string_pretty(&TransferTransaction::from_bytes(txtype, body).await.ok()?).ok(),
CREATE_TOKEN_TYPE => to_string_pretty(&CreateTokenTransaction::from_bytes(txtype, body).await.ok()?).ok(),
CREATE_NFT_TYPE => to_string_pretty(&CreateNftTransaction::from_bytes(txtype, body).await.ok()?).ok(),
MARKETING_TYPE => to_string_pretty(&MarketingTransaction::from_bytes(txtype, body).await.ok()?).ok(),
SWAP_TYPE => to_string_pretty(&SwapTransaction::from_bytes(txtype, body).await.ok()?).ok(),
LENDER_TYPE => to_string_pretty(&LoanContractTransaction::from_bytes(txtype, body).await.ok()?).ok(),
BORROWER_TYPE => to_string_pretty(&ContractPaymentTransaction::from_bytes(txtype, body).await.ok()?).ok(),
COLLATERAL_TYPE => to_string_pretty(&CollateralClaimTransaction::from_bytes(txtype, body).await.ok()?).ok(),
BURN_TYPE => to_string_pretty(&BurnTransaction::from_bytes(txtype, body).await.ok()?).ok(),
ISSUE_TOKEN_TYPE => to_string_pretty(&IssueTokenTransaction::from_bytes(txtype, body).await.ok()?).ok(),
VANITY_ADDRESS_TYPE => to_string_pretty(&VanityAddressTransaction::from_bytes(txtype, body).await.ok()?).ok(),
_ => None,
}
}
#[tokio::main]
async fn main() {
// Command 14 asks a peer for one unprocessed mempool transaction by signature.
let rpc_command = 14;
// The signature is passed as hex and converted into raw signature bytes by sending_request.
let args: Vec<String> = env::args().collect();
if args.len() != 2 {
println!("Usage: ./lookup_mempool_tx_by_signature <signature>");
return;
}
let signature = args[1].trim().to_string();
let encryption_key = prompt_hidden_nonempty(
"What is your wallet decryption key? ",
"Wallet key cannot be empty. Please try again.",
)
.await;
let connections = get_connections().await;
let mut connected = false;
for conn in connections {
if connected {
break;
}
let socket_address = conn.parse().expect("Failed to parse the socket address");
let result = handshake::connect_and_handshake(
socket_address,
signature.clone(),
rpc_command,
handshake::HandshakeWallet::WalletKey(encryption_key.clone()),
generate_uid(),
)
.await;
match result {
Ok(response) => {
if response.is_empty() {
println!("Transaction not found in mempool.");
connected = true;
} else if let Some(transaction_json) = decode_mempool_transaction(&response).await {
println!("{transaction_json}");
connected = true;
} else {
// Text errors are printed directly; unknown binary is shown as hex for inspection.
let response_text = String::from_utf8_lossy(&response);
let trimmed = response_text.trim();
if !trimmed.is_empty() {
println!("{trimmed}");
} else {
println!("{}", hex::encode(response));
}
connected = true;
}
}
Err(_) => connected = false,
}
}
if !connected {
eprintln!("failed to connect");
}
}