feat: add eth_getTransactionByHash (#8)

* add eth_getTransactionByHash

* clean up imports
This commit is contained in:
Noah Citron 2022-09-01 23:28:37 -04:00 committed by GitHub
parent 11fd824b01
commit e0411e1e97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 5 deletions

View File

@ -2,7 +2,7 @@ use std::collections::HashMap;
use std::sync::Arc;
use ethers::prelude::{Address, U256};
use ethers::types::TransactionReceipt;
use ethers::types::{Transaction, TransactionReceipt};
use eyre::Result;
use config::Config;
@ -124,6 +124,12 @@ impl Client {
.await
}
pub async fn get_transaction_by_hash(&self, tx_hash: &Vec<u8>) -> Result<Option<Transaction>> {
self.execution
.get_transaction(tx_hash, &self.payloads)
.await
}
pub fn get_gas_price(&self) -> Result<U256> {
let payload = self.get_payload(&None)?;
let base_fee = U256::from_little_endian(&payload.base_fee_per_gas.to_bytes_le());

View File

@ -1,6 +1,6 @@
use ethers::{
abi::AbiEncode,
types::{Address, TransactionReceipt},
types::{Address, Transaction, TransactionReceipt},
};
use eyre::Result;
use std::{fmt::Display, net::SocketAddr, str::FromStr, sync::Arc};
@ -68,6 +68,8 @@ trait EthRpc {
async fn send_raw_transaction(&self, bytes: &str) -> Result<String, Error>;
#[method(name = "getTransactionReceipt")]
async fn get_transaction_receipt(&self, hash: &str) -> Result<TransactionReceipt, Error>;
#[method(name = "getTransactionByHash")]
async fn get_transaction_by_hash(&self, hash: &str) -> Result<Transaction, Error>;
}
#[rpc(client, server, namespace = "net")]
@ -179,6 +181,17 @@ impl EthRpcServer for RpcInner {
None => Err(Error::Custom("Receipt Not Found".to_string())),
}
}
async fn get_transaction_by_hash(&self, hash: &str) -> Result<Transaction, Error> {
let client = self.client.lock().await;
let hash = convert_err(hex_str_to_bytes(hash))?;
let tx = convert_err(client.get_transaction_by_hash(&hash).await)?;
match tx {
Some(tx) => Ok(tx),
None => Err(Error::Custom("Transaction Not Found".to_string())),
}
}
}
#[async_trait]

View File

@ -3,7 +3,7 @@ use std::str::FromStr;
use ethers::abi::AbiEncode;
use ethers::prelude::{Address, U256};
use ethers::types::{TransactionReceipt, H256};
use ethers::types::{Transaction, TransactionReceipt, H256};
use ethers::utils::keccak256;
use ethers::utils::rlp::{encode, RlpStream};
use eyre::Result;
@ -142,7 +142,6 @@ impl ExecutionClient {
tx_hash: &Vec<u8>,
payloads: &HashMap<u64, ExecutionPayload>,
) -> Result<Option<TransactionReceipt>> {
let receipt = self.rpc.get_transaction_receipt(tx_hash).await?;
if receipt.is_none() {
return Ok(None);
@ -188,6 +187,46 @@ impl ExecutionClient {
Ok(Some(receipt))
}
pub async fn get_transaction(
&self,
hash: &Vec<u8>,
payloads: &HashMap<u64, ExecutionPayload>,
) -> Result<Option<Transaction>> {
let tx = self.rpc.get_transaction(hash).await?;
if tx.is_none() {
return Ok(None);
}
let tx = tx.unwrap();
let block_number = tx.block_number;
if block_number.is_none() {
return Ok(None);
}
let block_number = block_number.unwrap();
let payload = payloads.get(&block_number.as_u64());
if payload.is_none() {
return Ok(None);
}
let payload = payload.unwrap();
let tx_encoded = tx.rlp().to_vec();
let txs_encoded = payload
.transactions
.iter()
.map(|tx| tx.to_vec())
.collect::<Vec<_>>();
if !txs_encoded.contains(&tx_encoded) {
return Err(eyre::eyre!("Transaction Proof Invalid"));
}
Ok(Some(tx))
}
}
fn encode_receipt(receipt: &TransactionReceipt) -> Vec<u8> {

View File

@ -1,7 +1,7 @@
use ethers::abi::AbiEncode;
use ethers::prelude::{Address, U256};
use ethers::providers::{Middleware, Provider};
use ethers::types::{TransactionReceipt, H256};
use ethers::types::{Transaction, TransactionReceipt, H256};
use eyre::Result;
use jsonrpsee::{
core::client::ClientT,
@ -64,6 +64,11 @@ impl Rpc {
.await?)
}
pub async fn get_transaction(&self, tx_hash: &Vec<u8>) -> Result<Option<Transaction>> {
let provider = Provider::try_from(&self.rpc)?;
Ok(provider.get_transaction(H256::from_slice(tx_hash)).await?)
}
fn client(&self) -> Result<HttpClient> {
Ok(HttpClientBuilder::default().build(&self.rpc)?)
}