Skip to content
Merged
43 changes: 34 additions & 9 deletions goCode/goApp/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ package main

// fetch_transactions je Rust funkcija koja vraca podatke o transakcijama iz poslednjeg bloka
char* fetch_transactions(const char* rpc_url);

// fetch_last_5_blocks je Rust funkcija koja vraca podatke o transakciji maksimalnog potrosenog gasa u poslednjih 5 blokova
char* fetch_last_5_blocks(const char* rpc_url);
*/
import "C"

import (
"encoding/json"
"fmt"
"unsafe"

Expand All @@ -21,28 +25,49 @@ import (

func main() {

rpcURL, recipientAddress, privateKeyHex := config.LoadEnv()
rpcTestnetURL, rpcMainnetURL, recipientAddress, privateKeyHex := config.LoadEnv()

blockNumber := rpc.GetLatestBlock(rpcURL)
blockNumber := rpc.GetLatestBlock(rpcTestnetURL)
fmt.Println(blockNumber)
fmt.Println()

fakeBalance := utilis.EthToHex(100) // 100 ETH
transaction.SetFakeBalance(rpcURL, recipientAddress, fakeBalance)
transaction.SetFakeBalance(rpcTestnetURL, recipientAddress, fakeBalance)

sendEth := 1
transaction.SendTransaction(rpcURL, recipientAddress, int64(sendEth), privateKeyHex)
transaction.SendTransaction(rpcTestnetURL, recipientAddress, int64(sendEth), privateKeyHex)

//---------------------------
// === Deo koji zove Rust FFI za transakcije ===
fmt.Println()

cRpcURL := C.CString(rpcURL)
defer C.free(unsafe.Pointer(cRpcURL))
cRpcTestnetURL := C.CString(rpcTestnetURL)
defer C.free(unsafe.Pointer(cRpcTestnetURL))

result := C.fetch_transactions(cRpcURL)
result := C.fetch_transactions(cRpcTestnetURL)
defer C.free(unsafe.Pointer(result))

goResult := C.GoString(result)
fmt.Println("Podaci o transakcijama iz poslednjeg bloka:\n", goResult)
fmt.Println("Rust FFI: Podaci o transakcijama iz poslednjeg bloka:\n", goResult)

// === Deo koji zove Rust FFI za 5 blokova ===
fmt.Println()

cRpcMainnetURL := C.CString(rpcMainnetURL)
defer C.free(unsafe.Pointer(cRpcMainnetURL))

resultArray := C.fetch_last_5_blocks(cRpcMainnetURL)
defer C.free(unsafe.Pointer(resultArray))
goArray := C.GoString(resultArray)

var summaries []rpc.TxSummary
err := json.Unmarshal([]byte(goArray), &summaries)
if err != nil {
fmt.Println("Greska pri parsiranju JSON-a iz Rust-a:", err)
return
}

for _, s := range summaries {
fmt.Printf("Blok %s | TX %s | Gas %d | %.3f%% u bloku\n",
s.BlockNumber, s.TxHash, s.GasUsed, s.PercentInBlock)
}
}
15 changes: 10 additions & 5 deletions goCode/internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,20 @@ import (
"github.com/joho/godotenv"
)

func LoadEnv() (string, string, string) {
func LoadEnv() (string, string, string, string) {
err := godotenv.Load("../.env")
if err != nil {
log.Fatal("Greska pri ucitavanju .env fajla")
}

rpcURL := os.Getenv("RPC_URL")
if rpcURL == "" {
log.Fatal("Nedostaje RPC_URL u .env fajlu")
rpcTestnetURL := os.Getenv("RPC_TESTNET_URL")
if rpcTestnetURL == "" {
log.Fatal("Nedostaje RPC_TESTNET_URL u .env fajlu")
}

rpcMainnetURL := os.Getenv("RPC_MAINNET_URL")
if rpcTestnetURL == "" {
log.Fatal("Nedostaje RPC_TESTNET_URL u .env fajlu")
}

recipient := os.Getenv("RECIPIENT_ADDRESS")
Expand All @@ -28,5 +33,5 @@ func LoadEnv() (string, string, string) {
log.Fatal("Nedostaje PRIVATE_KEY u .env fajlu")
}

return rpcURL, recipient, privateKeyHex
return rpcTestnetURL, rpcMainnetURL, recipient, privateKeyHex
}
3 changes: 2 additions & 1 deletion goCode/internal/rpc/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ func GetLatestBlock(rpcURL string) string {
log.Fatalf("Greska pri parsiranju JSON odgovora: %v", err)
}

fmt.Println("BLOCK Odgovor:", string(rpcResp.Result))
fmt.Println("sadrzaj BLOCK-a:\n", string(rpcResp.Result))
fmt.Println()

// Parsiramo blok
var block Block
Expand Down
7 changes: 7 additions & 0 deletions goCode/internal/rpc/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,10 @@ type Transaction struct {
Gas string `json:"gas"`
GasPrice string `json:"gasPrice"`
}

type TxSummary struct {
BlockNumber uint64 `json:"block_number"`
TxHash string `json:"tx_hash"`
GasUsed uint64 `json:"gas_used"`
PercentInBlock float64 `json:"percent_in_block"`
}
1 change: 1 addition & 0 deletions rustCode/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
reqwest = { version = "0.11", features = ["json"] }
dotenvy = "0.15"
futures = "0.3.31"
10 changes: 7 additions & 3 deletions rustCode/src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
use dotenvy::from_path;
use std::{env, path::Path};

pub fn load_env() {
pub fn load_testnet_env() {
let env_path = Path::new("../goCode/.env");
from_path(env_path).expect("Nije moguce ucitati .env fajl sa date putanje");
}

pub fn get_rpc_url() -> String {
env::var("RPC_URL").expect("RPC_URL nije definisan")
pub fn get_testnet_rpc_url() -> String {
env::var("RPC_TESTNET_URL").expect("RPC_URL nije definisan")
}

pub fn get_mainnet_rpc_url() -> String {
env::var("RPC_MAINNET_URL").expect("RPC_URL nije definisan")
}
24 changes: 21 additions & 3 deletions rustCode/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
pub mod models;
pub mod rpc;
pub mod utils;

use crate::rpc::fetch::fetch_latest_block;
use crate::rpc::fetch::{fetch_latest_block, fetch_last_5_blocks_and_receipts};
use std::ffi::CString;
use std::os::raw::c_char;
use crate::utils::hex_to_u64;

#[no_mangle]
pub extern "C" fn fetch_transactions(rpc_url: *const c_char) -> *mut c_char {
Expand All @@ -13,7 +15,7 @@ pub extern "C" fn fetch_transactions(rpc_url: *const c_char) -> *mut c_char {
// Pozivanje fetch_latest_block funkcije za dobijanje najnovijeg bloka
let future = tokio::runtime::Runtime::new()
.unwrap()
.block_on(fetch_latest_block(rpc_url_str));
.block_on(fetch_latest_block(rpc_url_str, true));

// Prikupljanje transakcija iz rezultata
let mut transaction_data = String::new();
Expand All @@ -30,6 +32,22 @@ pub extern "C" fn fetch_transactions(rpc_url: *const c_char) -> *mut c_char {

let c_str_result = CString::new(transaction_data).unwrap();

// Vracanje C stringa koji Go moye koristiti
// Vracanje C stringa koji Go moze koristiti
c_str_result.into_raw()
}

#[no_mangle]
pub extern "C" fn fetch_last_5_blocks(rpc_url: *const c_char) -> *mut c_char {
let c_rpc = unsafe { std::ffi::CStr::from_ptr(rpc_url) };
let rpc_url_str = c_rpc.to_str().unwrap();

let runtime = tokio::runtime::Runtime::new().unwrap();
let latest_block = runtime.block_on(fetch_latest_block(rpc_url_str, true));
let latest_block_number = hex_to_u64(&latest_block.number);

let summaries = runtime.block_on(fetch_last_5_blocks_and_receipts(rpc_url_str.to_string(), latest_block_number));

let json_str = serde_json::to_string(&summaries).unwrap();
let c_str_result = CString::new(json_str).unwrap();
c_str_result.into_raw()
}
67 changes: 41 additions & 26 deletions rustCode/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,51 @@
mod config;
mod models;
mod rpc;
mod utils;

use config::{get_rpc_url, load_env};
use models::SimpleBlock;
use rpc::fetch::fetch_latest_block;
use config::{get_testnet_rpc_url, get_mainnet_rpc_url, load_testnet_env};
use rpc::fetch::{fetch_latest_block, fetch_block_by_number, fetch_last_5_blocks_and_receipts};
use utils::{print_block_info, hex_to_u64, analyze_max_gas_transaction};
use tokio;

fn print_block_info(block: &SimpleBlock) {
println!("Blok broj: {}", block.number);
println!("Hash bloka: {}", block.hash);
println!("Timestamp: {}", block.timestamp);
println!("Gas used: {}", block.gas_used);
println!("Broj transakcija: {}", block.transactions.len());

for tx in &block.transactions {
println!("---");
println!("Tx hash: {}", tx.hash);
println!("From: {}", tx.from);
println!("To: {}", tx.to.clone().unwrap_or_else(|| "N/A".into()));
println!("Value: {}", tx.value);
println!("Gas: {}", tx.gas);
println!("Gas price: {}", tx.gas_price);
}
}

#[tokio::main]
async fn main() {
load_env();
load_testnet_env();

let testnet_rpc_url = get_testnet_rpc_url();
let mainnet_rpc_url = get_mainnet_rpc_url();


let (block_testnet, block_mainnet) = tokio::join!(
fetch_latest_block(&testnet_rpc_url, true),
fetch_block_by_number(&mainnet_rpc_url, "latest", true)
);

let rpc_url = get_rpc_url();
println!("Testnet blok:");
print_block_info(&block_testnet);
println!("----------------------");
println!("Mainnet blok:");
print_block_info(&block_mainnet);

let transactions = block_mainnet.transactions;
//print_transactions(&transactions);

analyze_max_gas_transaction(&mainnet_rpc_url, &transactions, &block_mainnet.gas_used).await;

println!();
println!("=======================");
println!("Fetchujem 5 poslednjih blokova i njihove max gas transakcije...");
println!("=======================\n");

let latest_block_number = hex_to_u64(&block_mainnet.number);
let summaries = fetch_last_5_blocks_and_receipts(mainnet_rpc_url, latest_block_number).await;

println!("\n===== REZIME 5 BLOKOVA =====");
for s in summaries {
println!(
"Blok {} | TX {} | Gas {} | {:.3}%",
s.block_number, s.tx_hash, s.gas_used, s.percent_in_block
);
}

let block = fetch_latest_block(&rpc_url).await;
print_block_info(&block);
}
}
27 changes: 26 additions & 1 deletion rustCode/src/models/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use serde::Deserialize;

#[derive(Debug, Deserialize)]
pub struct RPCResponse {
pub struct RPCResponseBlock {
pub result: SimpleBlock,
}

Expand All @@ -15,6 +15,7 @@ pub struct SimpleBlock {
pub transactions: Vec<SimpleTransaction>,
}

#[allow(dead_code)]
#[derive(Debug, Deserialize)]
pub struct SimpleTransaction {
pub hash: String,
Expand All @@ -26,3 +27,27 @@ pub struct SimpleTransaction {
#[serde(rename = "gasPrice")]
pub gas_price: String,
}

#[derive(Debug, Deserialize)]
pub struct RPCResponseReceipt {
pub result: TransactionReceipt,
}

#[allow(dead_code)]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TransactionReceipt {
pub block_hash: String,
pub block_number: String,
pub transaction_hash: String,
pub gas_used: String,
pub cumulative_gas_used: String,
}

#[derive(serde::Serialize)]
pub struct TxSummary {
pub block_number: String,
pub tx_hash: String,
pub gas_used: u64,
pub percent_in_block: f64,
}
Loading