Contractless/src/bin/lookup_transaction.rs

168 lines
5.6 KiB
Rust

use blockchain::blocks::collateral::CollateralClaimTransaction;
use blockchain::blocks::genesis::GenesisTransaction;
use blockchain::blocks::loan_payment::ContractPaymentTransaction;
use blockchain::blocks::loans::LoanContractTransaction;
use blockchain::blocks::marketing::MarketingTransaction;
use blockchain::blocks::nft::CreateNftTransaction;
use blockchain::blocks::rewards::RewardsTransaction;
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, prompt_wallet_path};
use blockchain::common::network_startup::get_connections;
use blockchain::common::types::{
BORROWER_TYPE, COLLATERAL_TYPE, CREATE_NFT_TYPE, CREATE_TOKEN_TYPE, GENESIS_TYPE, LENDER_TYPE,
MARKETING_TYPE, REWARDS_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;
#[tokio::main]
async fn main() {
let hashmap_key = generate_uid();
// set the rpc command number
let rpc_command = 17;
// Get command-line arguments
let args: Vec<String> = env::args().collect();
// Check if a command-line argument is provided
if args.len() != 2 {
println!("Usage: ./lookup_transaction <transaction_hash>");
return;
}
// Extract the block number from the command-line argument
let block_hash = match args[1].parse::<String>() {
Ok(num) => num,
Err(_) => {
println!("Please enter a hash");
return;
}
};
// Extract the encryption ley from the command-line argument
let wallet_path = prompt_wallet_path().await;
let encryption_key = prompt_hidden_nonempty(
"What is your wallet decryption key? ",
"Wallet key cannot be empty. Please try again.",
)
.await;
let json = block_hash.to_string();
let connections = get_connections().await;
let mut connected: bool = false;
// Iterate over the returned Vec and print each connection
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,
json.clone(),
rpc_command,
handshake::HandshakeWallet::WalletKey {
encryption_key: encryption_key.clone(),
wallet_path: wallet_path.clone(),
},
hashmap_key,
)
.await;
match result {
Ok(response) => {
if let Some(transaction_json) = decode_transaction_to_json(&response).await {
println!("{transaction_json}");
connected = true;
} else {
let response_text = String::from_utf8_lossy(&response);
let trimmed = response_text.trim();
if !trimmed.is_empty() {
println!("{trimmed}");
connected = true;
} else if !response.is_empty() {
println!("{}", hex::encode(response));
connected = true;
}
}
}
Err(_) => connected = false,
}
}
if !connected {
eprintln!("failed to connect");
}
}
async fn decode_transaction_to_json(response: &[u8]) -> Option<String> {
if response.len() < 5 {
return None;
}
let block_number = u32::from_le_bytes(response[0..4].try_into().ok()?);
let txtype = response[4];
let body = &response[5..];
let json = match txtype {
GENESIS_TYPE => {
to_string_pretty(&GenesisTransaction::from_bytes(txtype, body).await.ok()?).ok()?
}
REWARDS_TYPE => {
to_string_pretty(&RewardsTransaction::from_bytes(txtype, body).await.ok()?).ok()?
}
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()?,
VANITY_ADDRESS_TYPE => to_string_pretty(
&VanityAddressTransaction::from_bytes(txtype, body)
.await
.ok()?,
)
.ok()?,
_ => return None,
};
Some(format!("block: {block_number}\n{json}"))
}