Skip to content

Commit afac2da

Browse files
committed
feat(rpc): add async fetch_last_5_blocks_and_receipts and extract analyze_max_gas_transaction
- implemented parallel fetching of last 5 blocks using Tokio - moved transaction analysis logic into a separate function for reusability - improved modularity and readability of async RPC handling
1 parent 21894c1 commit afac2da

7 files changed

Lines changed: 124 additions & 32 deletions

File tree

rustCode/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ serde = { version = "1.0", features = ["derive"] }
1414
serde_json = "1.0"
1515
reqwest = { version = "0.11", features = ["json"] }
1616
dotenvy = "0.15"
17+
futures = "0.3.31"

rustCode/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pub mod models;
22
pub mod rpc;
3+
pub mod utils;
34

45
use crate::rpc::fetch::fetch_latest_block;
56
use std::ffi::CString;

rustCode/src/main.rs

Lines changed: 20 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ mod rpc;
44
mod utils;
55

66
use config::{get_testnet_rpc_url, get_mainnet_rpc_url, load_testnet_env};
7-
use rpc::fetch::{fetch_latest_block, fetch_block_by_number, fetch_transaction_receipt};
8-
use utils::{print_block_info, print_transactions, find_max_gas_transaction, hex_to_u64, calculate_gas_percentage, consume_and_calculate_gas};
7+
use rpc::fetch::{fetch_latest_block, fetch_block_by_number, fetch_last_5_blocks_and_receipts};
8+
use utils::{print_block_info, hex_to_u64, analyze_max_gas_transaction};
99
use tokio;
1010

1111
#[tokio::main]
@@ -28,35 +28,24 @@ async fn main() {
2828
print_block_info(&block_mainnet);
2929

3030
let transactions = block_mainnet.transactions;
31-
print_transactions(&transactions);
31+
//print_transactions(&transactions);
3232

33-
println!("----------------------");
34-
35-
if let Some(max_tx) = find_max_gas_transaction(&transactions){
36-
println!("Transakcija sa najvecim gas limitom: ");
37-
println!("Hash {}", max_tx.hash);
38-
println!("Gas limit: (hex): {}", max_tx.gas);
39-
println!();
40-
41-
let receipt = fetch_transaction_receipt(&mainnet_rpc_url, &max_tx.hash).await;
42-
//println!("{:?}", receipt); // OVO MOZE
43-
let tx_gas_used = hex_to_u64(&receipt.gas_used);
44-
let block_gas_used = hex_to_u64(&block_mainnet.gas_used);
45-
let percent_of_block = calculate_gas_percentage(tx_gas_used, block_gas_used);
33+
analyze_max_gas_transaction(&mainnet_rpc_url, &transactions, &block_mainnet.gas_used).await;
4634

47-
println!("Gas potrosen od ove transakcije: {}", tx_gas_used);
48-
println!("Gas potrosen u bloku: {}", block_gas_used);
49-
println!("Procenat potrosnje u bloku: {:.6}%", percent_of_block);
50-
println!();
51-
52-
println!("Funkcija uzima ownership");
53-
let percent_of_block1 = consume_and_calculate_gas(receipt, block_mainnet.gas_used);
54-
println!("Procenat potrosnje u bloku: {:.6}%", percent_of_block1);
55-
//println!("{:?}", receipt); //OVO NE MOZE jer je promenjen owner
56-
//println!("{}",block_response.gas_used);
57-
//let tx_gas_used1 = hex_to_u64(&receipt.gas_used);
58-
//let block_gas_used1 = hex_to_u64(&block_response.gas_used);
59-
} else {
60-
println!("Nema transakcija u ovom bloku");
35+
println!();
36+
println!("=======================");
37+
println!("Fetchujem 5 poslednjih blokova i njihove max gas transakcije...");
38+
println!("=======================\n");
39+
40+
let latest_block_number = hex_to_u64(&block_mainnet.number);
41+
let summaries = fetch_last_5_blocks_and_receipts(mainnet_rpc_url, latest_block_number).await;
42+
43+
println!("\n===== REZIME 5 BLOKOVA =====");
44+
for s in summaries {
45+
println!(
46+
"Blok {} | TX {} | Gas {} | {:.3}%",
47+
s.block_number, s.tx_hash, s.gas_used, s.percent_in_block
48+
);
6149
}
62-
}
50+
51+
}

rustCode/src/models/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub struct SimpleBlock {
1515
pub transactions: Vec<SimpleTransaction>,
1616
}
1717

18+
#[allow(dead_code)]
1819
#[derive(Debug, Deserialize)]
1920
pub struct SimpleTransaction {
2021
pub hash: String,
@@ -36,7 +37,16 @@ pub struct RPCResponseReceipt {
3637
#[derive(Debug, Deserialize)]
3738
#[serde(rename_all = "camelCase")]
3839
pub struct TransactionReceipt {
40+
pub block_hash: String,
41+
pub block_number: String,
3942
pub transaction_hash: String,
4043
pub gas_used: String,
4144
pub cumulative_gas_used: String,
45+
}
46+
47+
pub struct TxSummary {
48+
pub block_number: String,
49+
pub tx_hash: String,
50+
pub gas_used: u64,
51+
pub percent_in_block: f64,
4252
}

rustCode/src/rpc/fetch.rs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
use crate::models::{RPCResponseBlock, RPCResponseReceipt, SimpleBlock, TransactionReceipt};
1+
use crate::models::{RPCResponseBlock, RPCResponseReceipt, SimpleBlock, TransactionReceipt, TxSummary};
22
use reqwest::Client;
33
use serde_json::json;
4+
use std::sync::Arc;
5+
use crate::utils::{find_max_gas_transaction, hex_to_u64, calculate_gas_percentage};
46

57
pub async fn fetch_latest_block(rpc_url: &str, transaction_bool: bool) -> SimpleBlock {
68
let req_body = json!( {
@@ -65,4 +67,53 @@ pub async fn fetch_transaction_receipt(rpc_url: &str, tx_hash: &str) -> Transact
6567
let receipt_resp: RPCResponseReceipt = resp.json().await.expect("Greska pri parsiranju odgovora");
6668

6769
receipt_resp.result
70+
}
71+
72+
pub async fn fetch_last_5_blocks_and_receipts(rpc_url: String, latest_block_number: u64)
73+
-> Vec<TxSummary> {
74+
let rpc_arc = Arc::new(rpc_url);
75+
76+
let mut tasks = Vec::new();
77+
78+
for i in 0..5 {
79+
let rpc = Arc::clone(&rpc_arc);
80+
let block_number = latest_block_number.saturating_sub(i); // da ne padne ispod 0
81+
82+
let task = tokio::spawn(async move {
83+
let block_number_hex = format!("0x{:x}", block_number);
84+
let block = fetch_block_by_number(&rpc, &block_number_hex, true).await;
85+
86+
if let Some(max_tx) = find_max_gas_transaction(&block.transactions) {
87+
let receipt = fetch_transaction_receipt(&rpc, &max_tx.hash).await;
88+
let tx_gas_used = hex_to_u64(&receipt.gas_used);
89+
let block_gas_used = hex_to_u64(&block.gas_used);
90+
let percent = calculate_gas_percentage(tx_gas_used, block_gas_used);
91+
92+
println!(
93+
"Blok {} | Max TX: {} | Gas: {} | %. u bloku: {:.3}%",
94+
block.number, max_tx.hash, tx_gas_used, percent
95+
);
96+
97+
Some(TxSummary {
98+
block_number: block.number.clone(),
99+
tx_hash: max_tx.hash.clone(),
100+
gas_used: tx_gas_used,
101+
percent_in_block: percent,
102+
})
103+
} else {
104+
println!("Blok {} nema transakcije.", block.number);
105+
None
106+
}
107+
});
108+
109+
tasks.push(task);
110+
}
111+
112+
let results = futures::future::join_all(tasks).await;
113+
114+
// filtriram samo uspesne
115+
results
116+
.into_iter()
117+
.filter_map(|res| res.ok().flatten())
118+
.collect()
68119
}

rustCode/src/utils/functions.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::models::{SimpleTransaction, TransactionReceipt};
2+
use crate::rpc::fetch::fetch_transaction_receipt;
23

34
pub fn find_max_gas_transaction(transactions: &[SimpleTransaction]) -> Option<&SimpleTransaction> {
45
transactions
@@ -21,4 +22,42 @@ pub fn consume_and_calculate_gas(receipt: TransactionReceipt, block_gas_used_hex
2122
let tx_gas_used = hex_to_u64(&receipt.gas_used);
2223
let block_gas_used = hex_to_u64(&block_gas_used_hex);
2324
calculate_gas_percentage(tx_gas_used, block_gas_used)
25+
}
26+
27+
pub async fn analyze_max_gas_transaction(
28+
mainnet_rpc_url: &str,
29+
transactions: &[SimpleTransaction],
30+
block_gas_used_hex: &str,
31+
) {
32+
println!("----------------------");
33+
34+
if let Some(max_tx) = find_max_gas_transaction(transactions) {
35+
println!("Transakcija sa najvecim gas limitom: ");
36+
println!("Hash {}", max_tx.hash);
37+
println!("Gas limit: {}", hex_to_u64(&max_tx.gas));
38+
println!();
39+
40+
let receipt = fetch_transaction_receipt(mainnet_rpc_url, &max_tx.hash).await;
41+
//println!("{:?}", receipt); // OVO MOZE
42+
let tx_gas_used = hex_to_u64(&receipt.gas_used);
43+
let block_gas_used = hex_to_u64(block_gas_used_hex);
44+
let percent_of_block = calculate_gas_percentage(tx_gas_used, block_gas_used);
45+
46+
println!("Gas potrosen od ove transakcije: {}", tx_gas_used);
47+
println!("Gas potrosen u bloku: {}", block_gas_used);
48+
println!("Procenat potrosnje u bloku: {:.6}%", percent_of_block);
49+
println!();
50+
51+
// Ownership primer
52+
println!("Ponovljeno izracunavanje preko dodele ownership-a");
53+
let percent_of_block1 = consume_and_calculate_gas(receipt, block_gas_used_hex.to_string());
54+
println!("Procenat potrosnje u bloku: {:.6}%", percent_of_block1);
55+
//println!("{:?}", receipt); //OVO NE MOZE jer je promenjen owner
56+
//println!("{}",block_mainnet.gas_used);
57+
//let tx_gas_used1 = hex_to_u64(&receipt.gas_used);
58+
//let block_gas_used1 = hex_to_u64(&block_mainnet.gas_used);
59+
60+
} else {
61+
println!("Nema transakcija u ovom bloku");
62+
}
2463
}

rustCode/src/utils/prints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub fn print_block_info(block: &SimpleBlock) {
88
println!("Broj transakcija: {}", block.transactions.len());
99
}
1010

11+
#[allow(dead_code)]
1112
pub fn print_transactions(transactions: &[SimpleTransaction]) {
1213
for tx in transactions {
1314
println!("---");

0 commit comments

Comments
 (0)