feat: add RPC logic and config yaml parsing

This commit is contained in:
Thales Lima
2025-03-10 18:05:38 -03:00
committed by Tamara
parent 8b6beb0214
commit 0bc39aee55
3 changed files with 208 additions and 0 deletions

118
protocol-testing/src/rpc.rs Normal file
View File

@@ -0,0 +1,118 @@
use alloy::{
contract::{ContractInstance, Interface},
dyn_abi::DynSolValue,
eips::eip1898::BlockId,
primitives::{address, Address, U256},
providers::{Provider, ProviderBuilder},
transports::http::reqwest::Url,
};
const NATIVE_ALIASES: &[Address] = &[
address!("0x0000000000000000000000000000000000000000"),
address!("0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"),
];
const ERC_20_ABI: &str = r#"[{"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"}]"#;
struct RPCProvider {
url: Url,
}
impl RPCProvider {
fn new(url: String) -> RPCProvider {
let url = url.as_str().parse().unwrap();
RPCProvider { url }
}
async fn get_token_balance(
self,
token_address: Address,
wallet_address: Address,
block_number: u64,
) -> U256 {
let provider = ProviderBuilder::new().on_http(self.url);
let block_id: BlockId = BlockId::from(block_number);
match NATIVE_ALIASES.contains(&token_address) {
true => provider
.get_balance(wallet_address)
.block_id(block_id)
.await
.expect("Failed to fetch token balance"),
false => {
let abi = serde_json::from_str(ERC_20_ABI).expect("invalid ABI");
let contract = ContractInstance::new(token_address, provider, Interface::new(abi));
let wallet_addr = DynSolValue::from(wallet_address);
let result_value = contract
.function("balanceOf", &[wallet_addr])
.expect("Failed to build function call")
.block(block_id)
.call()
.await
.expect("Failed to fetch ERC-20 Balance");
let result: U256 = result_value
.first()
.unwrap()
.as_uint()
.unwrap()
.0;
result
}
}
}
async fn get_block_header(self, block_number: u64) {
// TODO: Implement
// let provider = ProviderBuilder::new().on_http(self.url);
// let block_id: BlockId = BlockId::from(block_number);
//
// let block = provider.get_block(block_id)
}
}
#[cfg(test)]
mod tests {
use std::{env, str::FromStr};
use alloy::primitives::address;
use super::*;
#[tokio::test]
async fn get_token_balance_native_token() {
let eth_rpc_url = env::var("ETH_RPC_URL").expect("Missing ETH_RPC_URL in environment");
let rpc_provider = RPCProvider::new(eth_rpc_url);
let token_address = address!("0x0000000000000000000000000000000000000000");
let wallet_address = address!("0x787B8840100d9BaAdD7463f4a73b5BA73B00C6cA");
let block_number = 21998530;
let balance = rpc_provider
.get_token_balance(token_address, wallet_address, block_number)
.await;
assert_eq!(
balance,
U256::from_str("1070041574684539264153").expect("Failed to convert ETH value")
);
}
#[tokio::test]
async fn get_token_balance_erc20_token() {
let eth_rpc_url = env::var("ETH_RPC_URL").expect("Missing ETH_RPC_URL in environment");
let rpc_provider = RPCProvider::new(eth_rpc_url);
let token_address = address!("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48");
let wallet_address = address!("0x787B8840100d9BaAdD7463f4a73b5BA73B00C6cA");
let block_number = 21998530;
let balance = rpc_provider
.get_token_balance(token_address, wallet_address, block_number)
.await;
assert_eq!(balance, U256::from(717250938432_u64));
}
}