diff --git a/client/src/client.rs b/client/src/client.rs index 6068987..b05d6d1 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -434,6 +434,18 @@ impl Client { .await } + pub async fn get_transaction_by_block_hash_and_index( + &self, + block_hash: &Vec, + index: usize, + ) -> Result> { + self.node + .read() + .await + .get_transaction_by_block_hash_and_index(block_hash, index) + .await + } + pub async fn chain_id(&self) -> u64 { self.node.read().await.chain_id() } diff --git a/client/src/node.rs b/client/src/node.rs index 7db7416..a78c7d4 100644 --- a/client/src/node.rs +++ b/client/src/node.rs @@ -217,6 +217,18 @@ impl Node { .await } + pub async fn get_transaction_by_block_hash_and_index( + &self, + hash: &Vec, + index: usize, + ) -> Result> { + let payload = self.get_payload_by_hash(hash)?; + + self.execution + .get_transaction_by_block_hash_and_index(payload.1, index) + .await + } + pub async fn get_logs(&self, filter: &Filter) -> Result> { self.execution.get_logs(filter, &self.payloads).await } diff --git a/client/src/rpc.rs b/client/src/rpc.rs index 34e9295..43b867d 100644 --- a/client/src/rpc.rs +++ b/client/src/rpc.rs @@ -97,6 +97,12 @@ trait EthRpc { ) -> Result, Error>; #[method(name = "getTransactionByHash")] async fn get_transaction_by_hash(&self, hash: &str) -> Result, Error>; + #[method(name = "getTransactionByBlockHashAndIndex")] + async fn get_transaction_by_block_hash_and_index( + &self, + hash: &str, + index: usize, + ) -> Result, Error>; #[method(name = "getLogs")] async fn get_logs(&self, filter: Filter) -> Result, Error>; #[method(name = "getStorageAt")] @@ -252,6 +258,18 @@ impl EthRpcServer for RpcInner { convert_err(node.get_transaction_by_hash(&hash).await) } + async fn get_transaction_by_block_hash_and_index( + &self, + hash: &str, + index: usize, + ) -> Result, Error> { + let hash = convert_err(hex_str_to_bytes(hash))?; + let node = self.node.read().await; + convert_err( + node.get_transaction_by_block_hash_and_index(&hash, index) + .await, + ) + } async fn get_logs(&self, filter: Filter) -> Result, Error> { let node = self.node.read().await; convert_err(node.get_logs(&filter).await) diff --git a/execution/src/execution.rs b/execution/src/execution.rs index 400d027..07858cc 100644 --- a/execution/src/execution.rs +++ b/execution/src/execution.rs @@ -179,6 +179,21 @@ impl ExecutionClient { }) } + pub async fn get_transaction_by_block_hash_and_index( + &self, + payload: &ExecutionPayload, + index: usize, + ) -> Result> { + let tx = payload.transactions[index].clone(); + let tx_hash = H256::from_slice(&keccak256(tx)); + let mut payloads = BTreeMap::new(); + payloads.insert(payload.block_number, payload.clone()); + let tx_option = self.get_transaction(&tx_hash, &payloads).await?; + let tx = tx_option.ok_or(eyre::eyre!("not reachable"))?; + + Ok(Some(tx)) + } + pub async fn get_transaction_receipt( &self, tx_hash: &H256, @@ -260,7 +275,6 @@ impl ExecutionClient { if !txs_encoded.contains(&tx_encoded) { return Err(ExecutionError::MissingTransaction(hash.to_string()).into()); } - Ok(Some(tx)) } diff --git a/execution/tests/execution.rs b/execution/tests/execution.rs index 5c95859..0994e22 100644 --- a/execution/tests/execution.rs +++ b/execution/tests/execution.rs @@ -200,3 +200,23 @@ async fn test_get_block() { assert_eq!(block.number, 12345); } + +#[tokio::test] +async fn test_get_tx_by_block_hash_and_index() { + let execution = get_client(); + let tx_hash = + H256::from_str("2dac1b27ab58b493f902dda8b63979a112398d747f1761c0891777c0983e591f").unwrap(); + + let mut payload = ExecutionPayload { + block_number: 7530933, + ..ExecutionPayload::default() + }; + payload.transactions.push(List::from_iter(hex_str_to_bytes("0x02f8b20583623355849502f900849502f91082ea6094326c977e6efc84e512bb9c30f76e30c160ed06fb80b844a9059cbb0000000000000000000000007daccf9b3c1ae2fa5c55f1c978aeef700bc83be0000000000000000000000000000000000000000000000001158e460913d00000c080a0e1445466b058b6f883c0222f1b1f3e2ad9bee7b5f688813d86e3fa8f93aa868ca0786d6e7f3aefa8fe73857c65c32e4884d8ba38d0ecfb947fbffb82e8ee80c167").unwrap())); + + let tx = execution + .get_transaction_by_block_hash_and_index(&payload, 0) + .await + .unwrap() + .unwrap(); + assert_eq!(tx.hash(), tx_hash); +}