Repository: keep-starknet-strange/beerus
Pull request #268 (2023-03-12 01:18:40)

feat: add test starknet_getBlockTransactionCount RPC
<!--- Please provide a general summary of your changes in the title above -->
* Implemented test for RPC
# Pull Request type

<!-- Please try to limit your pull request to one type; submit multiple pull requests if needed. -->

Please check the type of change your PR introduces:

- [ ] Bugfix
- [ ] Feature
- [ ] Code style update (formatting, renaming)
- [ ] Refactoring (no functional changes, no API changes)
- [ ] Build-related changes
- [ ] Documentation content changes
- [x] Testing
- [ ] Other (please describe):

# What is the current behavior?

<!-- Please describe the current behavior that you are modifying, or link to a relevant issue. -->

Issue Number: #267 

# What is the new behavior?

<!-- Please describe the behavior or changes that are being added by this PR. -->

# Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this does introduce a breaking change, please describe the impact and migration path for existing applications below. -->

# Other information

<!-- Any other information that is important to this PR, such as screenshots of how the component looks before and after the change. -->



Patch:
diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml
index e41d72e..12dd16f 100644
--- a/.github/workflows/check.yml
+++ b/.github/workflows/check.yml
@@ -8,8 +8,8 @@ concurrency:
 
 # TODO: add back llvm codecov when we beerus-rpc testing 
 jobs:
-  check:
-    name: check
+  test:
+    name: test
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v3
@@ -17,11 +17,12 @@ jobs:
         run: |
           rustup set profile minimal
           rustup update --no-self-update stable
-          rustup default stable
-          rustup component add rustfmt
-
+          
       - uses: Swatinem/rust-cache@v2
-      - run: cargo fmt --check
+        with:
+          cache-on-failure: true
+          
+      - run: cargo test -- -q --test-threads=2
 
   clippy:
     name: clippy
@@ -32,16 +33,17 @@ jobs:
         run: |
           rustup set profile minimal
           rustup update --no-self-update stable
-          rustup default stable
-          rustup component add clippy
 
       - uses: Swatinem/rust-cache@v2
+        with:
+          cache-on-failure: true
+          
       # TODO: cleanup for
       # cargo clippy --all-features and --all-targets -- -D warnings
       - run: cargo clippy -- -D warnings
 
-  test:
-    name: test
+  check:
+    name: check
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v3
@@ -49,7 +51,9 @@ jobs:
         run: |
           rustup set profile minimal
           rustup update --no-self-update stable
-          rustup default stable
-          
+
       - uses: Swatinem/rust-cache@v2
-      - run: cargo test
+        with:
+          cache-on-failure: true
+
+      - run: cargo fmt --check
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index e0fe0d4..e2da8bc 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -28,10 +28,11 @@ jobs:
         run: |
           rustup set profile minimal
           rustup update --no-self-update stable
-          rustup default stable
           
       - name: Cache Deps
         uses: Swatinem/rust-cache@v2
+        with:
+          cache-on-failure: true
 
       - name: Build
         run: cargo build --release --locked
diff --git a/Cargo.lock b/Cargo.lock
index dc665d2..2af92af 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -494,6 +494,7 @@ dependencies = [
 name = "beerus-rpc"
 version = "0.1.0"
 dependencies = [
+ "anyhow",
  "beerus-core",
  "dotenv",
  "env_logger",
diff --git a/crates/beerus-core/src/lightclient/beerus.rs b/crates/beerus-core/src/lightclient/beerus.rs
index 1264333..2da7a0c 100644
--- a/crates/beerus-core/src/lightclient/beerus.rs
+++ b/crates/beerus-core/src/lightclient/beerus.rs
@@ -16,7 +16,8 @@ use starknet::{
         BlockHashAndNumber, BlockId, BlockStatus, BlockTag as StarknetBlockTag, BlockWithTxHashes,
         BlockWithTxs, BroadcastedTransaction, DeclareTransaction, DeployAccountTransaction,
         DeployTransaction, FeeEstimate, FunctionCall, InvokeTransaction, L1HandlerTransaction,
-        MaybePendingBlockWithTxHashes, MaybePendingBlockWithTxs, Transaction,
+        MaybePendingBlockWithTxHashes, MaybePendingBlockWithTxs, MaybePendingTransactionReceipt,
+        Transaction,
     },
 };
 
@@ -474,6 +475,36 @@ impl BeerusLightClient {
         }
     }
 
+    /// Return transaction receipt of a transaction.
+    /// # Arguments
+    /// * `tx_hash` - The transaction hash as String.
+    /// # Returns
+    /// `Ok(MaybePendingTransactionReceipt)` if the operation was successful.
+    /// `Err(eyre::Report)` if the operation failed.
+    pub async fn starknet_get_transaction_receipt(
+        &self,
+        tx_hash: String,
+    ) -> Result<MaybePendingTransactionReceipt> {
+        let cloned_node = self.node.read().await;
+        let state_root = self
+            .ethereum_lightclient
+            .read()
+            .await
+            .starknet_state_root()
+            .await?
+            .to_string();
+
+        if cloned_node.state_root != state_root {
+            return Err(eyre::eyre!("State root mismatch"));
+        }
+
+        let tx_hash_felt = FieldElement::from_hex_be(&tx_hash).unwrap();
+        let tx_receipt = self
+            .starknet_lightclient
+            .get_transaction_receipt(tx_hash_felt)
+            .await?;
+        Ok(tx_receipt)
+    }
     /// Return block with transaction hashes.
     /// See https://github.com/starknet-io/starknet-addresses for the StarkNet core contract address on different networks.
     /// # Arguments
diff --git a/crates/beerus-rpc/Cargo.toml b/crates/beerus-rpc/Cargo.toml
index d86ca1b..bf9fc06 100644
--- a/crates/beerus-rpc/Cargo.toml
+++ b/crates/beerus-rpc/Cargo.toml
@@ -19,6 +19,7 @@ tokio = { version = "1.8.1", features = ["full"] }
 log = "0.4.14"
 serde_json = "1.0.64"
 env_logger = "0.10.0"
+anyhow = "1.0.69"
 wiremock = "0.5.17"
 serde = "1.0.152"
 reqwest = "0.11.13"
diff --git a/crates/beerus-rpc/example_rpc_calls/starknet_getBlockWithTxs.hurl b/crates/beerus-rpc/example_rpc_calls/starknet_getBlockWithTxs.hurl
new file mode 100644
index 0000000..d83a6e5
--- /dev/null
+++ b/crates/beerus-rpc/example_rpc_calls/starknet_getBlockWithTxs.hurl
@@ -0,0 +1,7 @@
+POST http://0.0.0.0:3030
+Content-Type: application/json
+{
+    "jsonrpc":"2.0","method":"starknet_getBlockWithTxs","params":[
+        "tag", "pending"
+    ],"id":1
+}
diff --git a/crates/beerus-rpc/src/server.rs b/crates/beerus-rpc/src/server.rs
index 3aa1057..b9e64cd 100644
--- a/crates/beerus-rpc/src/server.rs
+++ b/crates/beerus-rpc/src/server.rs
@@ -5,15 +5,15 @@ use beerus_core::lightclient::beerus::BeerusLightClient;
 use jsonrpsee::{
     core::{async_trait, RpcResult as Result},
     proc_macros::rpc,
+    types::error::CallError,
 };
 
 use beerus_core::starknet_helper::block_id_string_to_block_id_type;
 use ethers::types::U256;
+use starknet::core::types::FieldElement;
 use starknet::providers::jsonrpc::models::{
-    BlockHashAndNumber, ContractClass, MaybePendingBlockWithTxHashes, StateUpdate, SyncStatusType,
-};
-use starknet::{
-    core::types::FieldElement, providers::jsonrpc::models::MaybePendingTransactionReceipt,
+    BlockHashAndNumber, ContractClass, MaybePendingBlockWithTxHashes, MaybePendingBlockWithTxs,
+    MaybePendingTransactionReceipt, StateUpdate, SyncStatusType,
 };
 
 pub struct BeerusRpc {
@@ -59,6 +59,13 @@ trait BeerusApi {
         block_id: String,
     ) -> Result<MaybePendingBlockWithTxHashes>;
 
+    #[method(name = "starknet_getBlockWithTxs")]
+    async fn starknet_get_block_with_txs(
+        &self,
+        block_id_type: &str,
+        block_id: &str,
+    ) -> Result<MaybePendingBlockWithTxs>;
+
     #[method(name = "starknet_getStateUpdate")]
     async fn starknet_get_state_update(
         &self,
@@ -177,6 +184,29 @@ impl BeerusApiServer for BeerusRpc {
             .unwrap())
     }
 
+    async fn starknet_get_block_with_txs(
+        &self,
+        block_id_type: &str,
+        block_id: &str,
+    ) -> Result<MaybePendingBlockWithTxs> {
+        let block_id =
+            beerus_core::starknet_helper::block_id_string_to_block_id_type(block_id_type, block_id)
+                .map_err(|e| {
+                    jsonrpsee::core::Error::Call(CallError::InvalidParams(anyhow::anyhow!(
+                        e.to_string()
+                    )))
+                })?;
+        let result = self
+            ._beerus
+            .starknet_lightclient
+            .get_block_with_txs(&block_id)
+            .await
+            .map_err(|e| {
+                jsonrpsee::core::Error::Call(CallError::Failed(anyhow::anyhow!(e.to_string())))
+            })?;
+        Ok(result)
+    }
+
     async fn starknet_get_state_update(
         &self,
         block_id_type: String,
diff --git a/crates/beerus-rpc/src/utils/data/blocks/starknet_getBlockTransactionCount.json b/crates/beerus-rpc/src/utils/data/blocks/starknet_getBlockTransactionCount.json
new file mode 100644
index 0000000..28bda56
--- /dev/null
+++ b/crates/beerus-rpc/src/utils/data/blocks/starknet_getBlockTransactionCount.json
@@ -0,0 +1,5 @@
+{
+    "jsonrpc": "2.0",
+    "result": 90,
+    "id": 1
+}
diff --git a/crates/beerus-rpc/src/utils/wiremock.rs b/crates/beerus-rpc/src/utils/wiremock.rs
index d00ff5e..8f12202 100644
--- a/crates/beerus-rpc/src/utils/wiremock.rs
+++ b/crates/beerus-rpc/src/utils/wiremock.rs
@@ -1,5 +1,6 @@
 use reqwest::StatusCode;
 use serde::{Deserialize, Serialize};
+use starknet::providers::jsonrpc::models::{BlockId, BlockTag};
 use wiremock::{
     matchers::{body_json, method},
     Mock, MockServer, ResponseTemplate,
@@ -29,11 +30,21 @@ impl<'a, StarknetParams> StarknetRpcBaseData<'a, StarknetParams> {
             params,
         }
     }
+
+    pub const fn starknet_get_block_transaction_count(params: StarknetParams) -> Self {
+        Self {
+            id: 1,
+            jsonrpc: "2.0",
+            method: "starknet_getBlockTransactionCount",
+            params,
+        }
+    }
 }
 
 pub async fn setup_wiremock() -> String {
     let mock_server = MockServer::start().await;
     mock_block_number().mount(&mock_server).await;
+    mock_get_block_transaction_count().mount(&mock_server).await;
     mock_server.uri()
 }
 
@@ -46,6 +57,18 @@ fn mock_block_number() -> Mock {
         ))
 }
 
+fn mock_get_block_transaction_count() -> Mock {
+    let latest_block = BlockId::Tag(BlockTag::Latest);
+    Mock::given(method("POST"))
+        .and(body_json(
+            StarknetRpcBaseData::starknet_get_block_transaction_count([&latest_block]),
+        ))
+        .respond_with(response_template_with_status(StatusCode::OK).set_body_raw(
+            include_str!("data/blocks/starknet_getBlockTransactionCount.json"),
+            "application/json",
+        ))
+}
+
 fn response_template_with_status(status_code: StatusCode) -> ResponseTemplate {
     ResponseTemplate::new(status_code)
         .append_header("vary", "Accept-Encoding")


Test patch:
diff --git a/crates/beerus-rpc/tests/rpc.rs b/crates/beerus-rpc/tests/rpc.rs
index 0be02c7..843f4bb 100644
--- a/crates/beerus-rpc/tests/rpc.rs
+++ b/crates/beerus-rpc/tests/rpc.rs
@@ -11,4 +11,16 @@ mod tests {
         let block_number = beerus_rpc.starknet_block_number().await.unwrap();
         assert_eq!(block_number, 19640);
     }
+
+    #[tokio::test]
+    async fn test_get_block_transaction_count_is_ok() {
+        let beerus_rpc = setup_beerus_rpc().await;
+        let block_id_type = "tag".to_string();
+        let block_id = "latest".to_string();
+        let transaction_count = beerus_rpc
+            .starknet_get_block_transaction_count(block_id_type, block_id)
+            .await
+            .unwrap();
+        assert_eq!(transaction_count, 90);
+    }
 }