143 lines
5.2 KiB
Rust
143 lines
5.2 KiB
Rust
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");
|
|
}
|
|
}
|