From 45bfbcd389ec7dab347efdaba8cdd23b2e9a8ae5 Mon Sep 17 00:00:00 2001 From: Trantorian Date: Wed, 10 Jan 2024 10:43:00 +0000 Subject: [PATCH 01/10] build(starknet-rs): :arrow_up: Updated starknet-rs to spec v0.5.1 --- Cargo.lock | 24 ++++++++++++------------ unit_tests/Cargo.toml | 6 +++--- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ec20607..b71e795 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2096,7 +2096,7 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "starknet" version = "0.7.0" -source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=a35ce22#a35ce22be52bf33b8e544d0df926031b0ec7d761" +source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=64ebc36#64ebc364c0c346e81b715c5b4a3b32ef37b055c8" dependencies = [ "starknet-accounts", "starknet-contract", @@ -2110,8 +2110,8 @@ dependencies = [ [[package]] name = "starknet-accounts" -version = "0.6.0" -source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=a35ce22#a35ce22be52bf33b8e544d0df926031b0ec7d761" +version = "0.6.1" +source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=64ebc36#64ebc364c0c346e81b715c5b4a3b32ef37b055c8" dependencies = [ "async-trait", "auto_impl", @@ -2124,7 +2124,7 @@ dependencies = [ [[package]] name = "starknet-contract" version = "0.6.0" -source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=a35ce22#a35ce22be52bf33b8e544d0df926031b0ec7d761" +source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=64ebc36#64ebc364c0c346e81b715c5b4a3b32ef37b055c8" dependencies = [ "serde", "serde_json", @@ -2138,7 +2138,7 @@ dependencies = [ [[package]] name = "starknet-core" version = "0.7.2" -source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=a35ce22#a35ce22be52bf33b8e544d0df926031b0ec7d761" +source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=64ebc36#64ebc364c0c346e81b715c5b4a3b32ef37b055c8" dependencies = [ "base64 0.21.5", "flate2", @@ -2155,7 +2155,7 @@ dependencies = [ [[package]] name = "starknet-crypto" version = "0.6.1" -source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=a35ce22#a35ce22be52bf33b8e544d0df926031b0ec7d761" +source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=64ebc36#64ebc364c0c346e81b715c5b4a3b32ef37b055c8" dependencies = [ "crypto-bigint", "hex", @@ -2174,7 +2174,7 @@ dependencies = [ [[package]] name = "starknet-crypto-codegen" version = "0.3.2" -source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=a35ce22#a35ce22be52bf33b8e544d0df926031b0ec7d761" +source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=64ebc36#64ebc364c0c346e81b715c5b4a3b32ef37b055c8" dependencies = [ "starknet-curve", "starknet-ff", @@ -2184,7 +2184,7 @@ dependencies = [ [[package]] name = "starknet-curve" version = "0.4.0" -source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=a35ce22#a35ce22be52bf33b8e544d0df926031b0ec7d761" +source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=64ebc36#64ebc364c0c346e81b715c5b4a3b32ef37b055c8" dependencies = [ "starknet-ff", ] @@ -2192,7 +2192,7 @@ dependencies = [ [[package]] name = "starknet-ff" version = "0.3.5" -source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=a35ce22#a35ce22be52bf33b8e544d0df926031b0ec7d761" +source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=64ebc36#64ebc364c0c346e81b715c5b4a3b32ef37b055c8" dependencies = [ "ark-ff", "bigdecimal", @@ -2205,7 +2205,7 @@ dependencies = [ [[package]] name = "starknet-macros" version = "0.1.4" -source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=a35ce22#a35ce22be52bf33b8e544d0df926031b0ec7d761" +source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=64ebc36#64ebc364c0c346e81b715c5b4a3b32ef37b055c8" dependencies = [ "starknet-core", "syn 2.0.46", @@ -2214,7 +2214,7 @@ dependencies = [ [[package]] name = "starknet-providers" version = "0.7.0" -source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=a35ce22#a35ce22be52bf33b8e544d0df926031b0ec7d761" +source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=64ebc36#64ebc364c0c346e81b715c5b4a3b32ef37b055c8" dependencies = [ "async-trait", "auto_impl", @@ -2233,7 +2233,7 @@ dependencies = [ [[package]] name = "starknet-signers" version = "0.5.0" -source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=a35ce22#a35ce22be52bf33b8e544d0df926031b0ec7d761" +source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=64ebc36#64ebc364c0c346e81b715c5b4a3b32ef37b055c8" dependencies = [ "async-trait", "auto_impl", diff --git a/unit_tests/Cargo.toml b/unit_tests/Cargo.toml index 5afc8cc..8d78d6d 100644 --- a/unit_tests/Cargo.toml +++ b/unit_tests/Cargo.toml @@ -13,9 +13,9 @@ serde_json = "1.0.110" tokio = { version = "1", features = ["full"] } url = "2.5.0" rpc_test = { path = "../rpc_test/" } -starknet = { git = "https://github.com/xJonathanLEI/starknet-rs.git", rev = "a35ce22", default-features = false } -starknet-core = { git = "https://github.com/xJonathanLEI/starknet-rs.git", rev = "a35ce22", default-features = false } -starknet-providers = { git = "https://github.com/xJonathanLEI/starknet-rs.git", rev = "a35ce22", default-features = false } +starknet = { git = "https://github.com/xJonathanLEI/starknet-rs.git", rev = "64ebc36", default-features = false } +starknet-core = { git = "https://github.com/xJonathanLEI/starknet-rs.git", rev = "64ebc36", default-features = false } +starknet-providers = { git = "https://github.com/xJonathanLEI/starknet-rs.git", rev = "64ebc36", default-features = false } [dev-dependencies] jsonrpsee = { version = "0.21.0", features = ["client"] } From 82fd4248710f631ffa42348ede0f8310f832c292 Mon Sep 17 00:00:00 2001 From: Trantorian Date: Wed, 10 Jan 2024 13:24:25 +0000 Subject: [PATCH 02/10] test(get_transaction_status): :white_check_mark: getTransactionStatus invalid transaction test --- .../tests/test_get_transaction_status.rs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 unit_tests/tests/test_get_transaction_status.rs diff --git a/unit_tests/tests/test_get_transaction_status.rs b/unit_tests/tests/test_get_transaction_status.rs new file mode 100644 index 0000000..ecfa7b4 --- /dev/null +++ b/unit_tests/tests/test_get_transaction_status.rs @@ -0,0 +1,32 @@ +#![feature(assert_matches)] + +mod common; +use std::{collections::HashMap, assert_matches::assert_matches}; + +use common::*; +use starknet_core::types::{FieldElement, StarknetError}; +use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider, StarknetErrorWithMessage, ProviderError, MaybeUnknownErrorCode}; + +/// +/// Unit test for `starknet_getTransactionStatus` +/// +/// purpose: call getTransactionStatus on non-existent transaction hash. +/// fail case: non-existent transaction hash. +/// +#[rstest] +#[tokio::test] +async fn fail_invalid_transaction(clients: HashMap>) { + let deoxys = &clients[DEOXYS]; + + let response_deoxys = deoxys.get_transaction_status( + FieldElement::ZERO + ).await.err(); + + assert_matches!( + response_deoxys, + Some(ProviderError::StarknetError(StarknetErrorWithMessage { + message: _, + code: MaybeUnknownErrorCode::Known(StarknetError::TransactionHashNotFound) + })) + ); +} \ No newline at end of file From 6428ad91bd1f5f52cfb51206d487e0e35343fbfb Mon Sep 17 00:00:00 2001 From: Trantorian Date: Wed, 10 Jan 2024 13:35:54 +0000 Subject: [PATCH 03/10] test(get_transaction_status): :white_check_mark: getTransactionStatus L1 accepted test --- .../tests/test_get_transaction_status.rs | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/unit_tests/tests/test_get_transaction_status.rs b/unit_tests/tests/test_get_transaction_status.rs index ecfa7b4..abee212 100644 --- a/unit_tests/tests/test_get_transaction_status.rs +++ b/unit_tests/tests/test_get_transaction_status.rs @@ -4,7 +4,7 @@ mod common; use std::{collections::HashMap, assert_matches::assert_matches}; use common::*; -use starknet_core::types::{FieldElement, StarknetError}; +use starknet_core::types::{FieldElement, StarknetError, TransactionStatus}; use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider, StarknetErrorWithMessage, ProviderError, MaybeUnknownErrorCode}; /// @@ -29,4 +29,25 @@ async fn fail_invalid_transaction(clients: HashMap>) { + let deoxys = &clients[DEOXYS]; + + let response_deoxys = deoxys.get_transaction_status( + FieldElement::from_hex_be(TRANSACTION_INVOKE).unwrap() + ).await.expect("Error waiting for response from Deoxys client"); + + assert_matches!( + response_deoxys, + TransactionStatus::AcceptedOnL1(_) + ); } \ No newline at end of file From 0e82b051ab16b71854cd8cb8d68fb2907a5732ab Mon Sep 17 00:00:00 2001 From: Trantorian Date: Wed, 10 Jan 2024 13:58:25 +0000 Subject: [PATCH 04/10] test(get_transaction_status): :white_check_mark: getTransactionStatus L2 test --- unit_tests/src/constants.rs | 5 +- .../tests/test_get_transaction_status.rs | 49 +++++++++++++++++-- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/unit_tests/src/constants.rs b/unit_tests/src/constants.rs index 8ef4d4b..7357869 100644 --- a/unit_tests/src/constants.rs +++ b/unit_tests/src/constants.rs @@ -126,4 +126,7 @@ pub const TEST_CONTRACT_CLASS_HASH: &str = ""; /// pub const ETHEREUM_ADDRESS: &str = ""; pub const INVALID_ETHEREUM_ADDRESS: &str = ""; -pub const SELECTOR_NAME: &str = ""; \ No newline at end of file +pub const SELECTOR_NAME: &str = ""; + +pub const ERR_DEOXYS: &str = "Error waiting for response from Deoxys client"; +pub const ERR_PATHFINDER: &str = "Error waiting for response from Pathfinder client"; \ No newline at end of file diff --git a/unit_tests/tests/test_get_transaction_status.rs b/unit_tests/tests/test_get_transaction_status.rs index abee212..a7c3c51 100644 --- a/unit_tests/tests/test_get_transaction_status.rs +++ b/unit_tests/tests/test_get_transaction_status.rs @@ -4,7 +4,7 @@ mod common; use std::{collections::HashMap, assert_matches::assert_matches}; use common::*; -use starknet_core::types::{FieldElement, StarknetError, TransactionStatus}; +use starknet_core::types::{FieldElement, StarknetError, TransactionStatus, TransactionExecutionStatus, BlockId, BlockTag}; use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider, StarknetErrorWithMessage, ProviderError, MaybeUnknownErrorCode}; /// @@ -39,15 +39,58 @@ async fn fail_invalid_transaction(clients: HashMap>) { +async fn work_transaction_accepted_on_l1(clients: HashMap>) { let deoxys = &clients[DEOXYS]; + let pathfinder = &clients[PATHFINDER]; let response_deoxys = deoxys.get_transaction_status( FieldElement::from_hex_be(TRANSACTION_INVOKE).unwrap() - ).await.expect("Error waiting for response from Deoxys client"); + ).await.expect(ERR_DEOXYS); + + let response_pathfinder = pathfinder.get_transaction_status( + FieldElement::from_hex_be(TRANSACTION_INVOKE).unwrap() + ).await.expect(ERR_PATHFINDER); assert_matches!( response_deoxys, TransactionStatus::AcceptedOnL1(_) ); + assert_eq!(response_deoxys, response_pathfinder); +} + +/// +/// Unit test for `starknet_getTransactionStatus` +/// +/// purpose: call getTransactionStatus on last transaction from the latest block. +/// success case: transaction is marked as accepted on L2. +/// +#[rstest] +#[tokio::test] +async fn work_transaction_accepted_on_l2(clients: HashMap>) { + let deoxys = &clients[DEOXYS]; + let pathfinder = &clients[PATHFINDER]; + + let transaction_count = deoxys.get_block_transaction_count( + BlockId::Tag(BlockTag::Latest) + ).await.expect(ERR_DEOXYS); + + let transaction = deoxys.get_transaction_by_block_id_and_index( + BlockId::Tag(BlockTag::Latest), + transaction_count - 1, + ).await.expect(ERR_DEOXYS); + + let response_deoxys = deoxys.get_transaction_status( + transaction.transaction_hash() + ).await.expect(ERR_DEOXYS); + + let response_pathfinder = pathfinder.get_transaction_status( + transaction.transaction_hash() + ).await.expect(ERR_PATHFINDER); + + // note that transaction is still accepted on L2 if it is reverted! + assert_matches!( + response_deoxys, + TransactionStatus::AcceptedOnL2(_) + ); + assert_eq!(response_deoxys, response_pathfinder); } \ No newline at end of file From 868d23b2e1b255c748c2f8c333b31044e9981542 Mon Sep 17 00:00:00 2001 From: Trantorian Date: Wed, 10 Jan 2024 13:58:59 +0000 Subject: [PATCH 05/10] test(get_transaction_status): :white_check_mark: getTransactionStatus reverted test --- .../tests/test_get_transaction_status.rs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/unit_tests/tests/test_get_transaction_status.rs b/unit_tests/tests/test_get_transaction_status.rs index a7c3c51..25d5656 100644 --- a/unit_tests/tests/test_get_transaction_status.rs +++ b/unit_tests/tests/test_get_transaction_status.rs @@ -74,6 +74,7 @@ async fn work_transaction_accepted_on_l2(clients: HashMap>) { + let deoxys = &clients[DEOXYS]; + let pathfinder = &clients[PATHFINDER]; + + let response_deoxys = deoxys.get_transaction_status( + FieldElement::from_hex_be(TRANSACTION_REVERTED).unwrap() + ).await.expect(ERR_DEOXYS); + + let response_pathfinder = pathfinder.get_transaction_status( + FieldElement::from_hex_be(TRANSACTION_REVERTED).unwrap() + ).await.expect(ERR_PATHFINDER); + + assert_matches!( + response_deoxys, + TransactionStatus::AcceptedOnL1(TransactionExecutionStatus::Reverted) + ); + assert_eq!(response_deoxys, response_pathfinder); } \ No newline at end of file From 46d5808cfc48bd6275c0a17ea487547656fb64e6 Mon Sep 17 00:00:00 2001 From: Trantorian Date: Wed, 10 Jan 2024 16:39:41 +0000 Subject: [PATCH 06/10] refactor(delete): :fire: REMOVED ALL MACRO CODE TO ADD MACRO CODE --- Cargo.lock | 264 +++++++++++++++++++++------------- Cargo.toml | 5 +- rpc_test/Cargo.toml | 14 -- rpc_test/src/lib.rs | 102 ------------- rpc_test/src/test_config.rs | 24 ---- rpc_test/src/test_data.rs | 35 ----- rpc_test_attribute/Cargo.toml | 11 -- rpc_test_attribute/src/lib.rs | 85 ----------- unit_tests/Cargo.toml | 4 +- 9 files changed, 167 insertions(+), 377 deletions(-) delete mode 100644 rpc_test/Cargo.toml delete mode 100644 rpc_test/src/lib.rs delete mode 100644 rpc_test/src/test_config.rs delete mode 100644 rpc_test/src/test_data.rs delete mode 100644 rpc_test_attribute/Cargo.toml delete mode 100644 rpc_test_attribute/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index ec20607..a7173ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -130,9 +130,9 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "async-lock" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7125e42787d53db9dd54261812ef17e937c95a51e4d291373b670342fa44310c" +checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" dependencies = [ "event-listener", "event-listener-strategy", @@ -141,13 +141,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.75" +version = "0.1.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdf6721fb0140e4f897002dd086c06f6c27775df19cfe1fccb21181a48fd2c98" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -191,9 +191,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.5" +version = "0.21.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "c79fed4cdb43e993fcdadc7e58a09fd0e3e649c4436fa11da71c9f1f3ee7feb9" [[package]] name = "beef" @@ -222,6 +222,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + [[package]] name = "bitvec" version = "1.0.1" @@ -299,10 +305,8 @@ checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ "android-tzdata", "iana-time-zone", - "js-sys", "num-traits", "serde", - "wasm-bindgen", "windows-targets 0.48.5", ] @@ -316,16 +320,6 @@ dependencies = [ "inout", ] -[[package]] -name = "colored" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" -dependencies = [ - "lazy_static", - "windows-sys 0.48.0", -] - [[package]] name = "concurrent-queue" version = "2.4.0" @@ -353,9 +347,9 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -371,12 +365,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.18" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crunchy" @@ -435,7 +426,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -446,7 +437,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -505,12 +496,35 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "env_logger" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + [[package]] name = "equivalent" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "eth-keystore" version = "0.5.0" @@ -562,9 +576,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "4.0.1" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f2cdcf274580f2d63697192d744727b3198894b1bf02923643bf59e2c26712" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" dependencies = [ "concurrent-queue", "parking", @@ -680,7 +694,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -735,9 +749,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "js-sys", @@ -890,6 +904,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "hyper" version = "0.14.28" @@ -1043,6 +1063,17 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "is-terminal" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" +dependencies = [ + "hermit-abi", + "rustix", + "windows-sys 0.52.0", +] + [[package]] name = "itertools" version = "0.10.5" @@ -1197,16 +1228,16 @@ dependencies = [ ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "libc" +version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] -name = "libc" -version = "0.2.151" +name = "linux-raw-sys" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "lock_api" @@ -1416,7 +1447,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -1492,9 +1523,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.74" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" dependencies = [ "unicode-ident", ] @@ -1550,7 +1581,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1594,7 +1625,7 @@ version = "0.11.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" dependencies = [ - "base64 0.21.5", + "base64 0.21.6", "bytes", "encoding_rs", "futures-core", @@ -1662,26 +1693,6 @@ dependencies = [ "rustc-hex", ] -[[package]] -name = "rpc_test" -version = "0.1.0" -dependencies = [ - "anyhow", - "chrono", - "colored", - "jsonrpsee", - "serde", - "serde_json", -] - -[[package]] -name = "rpc_test_attribute" -version = "0.1.0" -dependencies = [ - "quote", - "syn 2.0.46", -] - [[package]] name = "rstest" version = "0.18.2" @@ -1707,7 +1718,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.46", + "syn 2.0.48", "unicode-ident", ] @@ -1738,6 +1749,19 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.38.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + [[package]] name = "rustls" version = "0.21.10" @@ -1752,14 +1776,14 @@ dependencies = [ [[package]] name = "rustls" -version = "0.22.1" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe6b63262c9fcac8659abfaa96cac103d28166d3ff3eaf8f412e19f3ae9e5a48" +checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" dependencies = [ "log", "ring", "rustls-pki-types", - "rustls-webpki 0.102.0", + "rustls-webpki 0.102.1", "subtle", "zeroize", ] @@ -1795,7 +1819,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.5", + "base64 0.21.6", ] [[package]] @@ -1804,7 +1828,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35e4980fa29e4c4b212ffb3db068a564cbf560e51d3944b7c88bd8bf5bec64f4" dependencies = [ - "base64 0.21.5", + "base64 0.21.6", "rustls-pki-types", ] @@ -1826,9 +1850,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.0" +version = "0.102.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de2635c8bc2b88d367767c5de8ea1d8db9af3f6219eba28442242d9ab81d1b89" +checksum = "ef4ca26037c909dedb327b48c3327d0ba91d3dd3c4e05dad328f210ffb68e95b" dependencies = [ "ring", "rustls-pki-types", @@ -1893,7 +1917,7 @@ version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -1924,29 +1948,29 @@ checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" [[package]] name = "serde" -version = "1.0.194" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b114498256798c94a0689e1a15fec6005dee8ac1f41de56404b67afc2a4b773" +checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.194" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3385e45322e8f9931410f01b3031ec534c3947d0e94c18049af4d9f9907d4e0" +checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] name = "serde_json" -version = "1.0.110" +version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fbd975230bada99c8bb618e0c365c2eefa219158d5c6c29610fd09ff1833257" +checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" dependencies = [ "itoa", "ryu", @@ -2001,7 +2025,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -2140,7 +2164,7 @@ name = "starknet-core" version = "0.7.2" source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=a35ce22#a35ce22be52bf33b8e544d0df926031b0ec7d761" dependencies = [ - "base64 0.21.5", + "base64 0.21.6", "flate2", "hex", "serde", @@ -2178,7 +2202,7 @@ source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=a35ce22#a35ce2 dependencies = [ "starknet-curve", "starknet-ff", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -2208,7 +2232,7 @@ version = "0.1.4" source = "git+https://github.com/xJonathanLEI/starknet-rs.git?rev=a35ce22#a35ce22be52bf33b8e544d0df926031b0ec7d761" dependencies = [ "starknet-core", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -2276,9 +2300,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.46" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89456b690ff72fddcecf231caedbe615c59480c93358a93dfae7fc29e3ebbf0e" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -2291,7 +2315,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "system-configuration-sys", ] @@ -2312,24 +2336,33 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" -version = "1.0.52" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a48fd946b02c0a526b2e9481c8e2a17755e47039164a86c4070446e3a4614d" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.52" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7fbe9b594d6568a6a1443250a7e67d80b74e1e96f6d1715e1e21cc1888291d3" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -2412,7 +2445,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -2431,7 +2464,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ - "rustls 0.22.1", + "rustls 0.22.2", "rustls-pki-types", "tokio", ] @@ -2526,7 +2559,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] [[package]] @@ -2588,10 +2621,10 @@ name = "unit_tests" version = "0.1.0" dependencies = [ "anyhow", + "env_logger", "flate2", "jsonrpsee", - "rpc_test", - "rpc_test_attribute", + "log", "rstest", "serde", "serde_json", @@ -2671,7 +2704,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", "wasm-bindgen-shared", ] @@ -2705,7 +2738,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2741,6 +2774,37 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-core" version = "0.52.0" @@ -2927,5 +2991,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.48", ] diff --git a/Cargo.toml b/Cargo.toml index a5abf2d..daaddcc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,6 @@ [workspace] members = [ - "rpc_test", - "rpc_test_attribute", "unit_tests", ] default-members = ["unit_tests"] -resolver = "2" - +resolver = "2" \ No newline at end of file diff --git a/rpc_test/Cargo.toml b/rpc_test/Cargo.toml deleted file mode 100644 index 0f5bcfa..0000000 --- a/rpc_test/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "rpc_test" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -anyhow = "1.0.79" -chrono = "0.4.31" -colored = "2.1.0" -jsonrpsee = { version = "0.21.0", features = ["client"] } -serde = "1.0.194" -serde_json = "1.0.110" diff --git a/rpc_test/src/lib.rs b/rpc_test/src/lib.rs deleted file mode 100644 index ea4e1fa..0000000 --- a/rpc_test/src/lib.rs +++ /dev/null @@ -1,102 +0,0 @@ -pub mod test_config; -pub mod test_data; - -use std::fs::OpenOptions; -use std::io::Write; - -use anyhow::Context; -use chrono::Local; -use jsonrpsee::core::client::{ClientT, self}; -use jsonrpsee::http_client::HttpClient; -use colored::Colorize; -use jsonrpsee::core::DeserializeOwned; - -pub struct ClientInfo<'a> { - client: &'a HttpClient, - name: &'a str, - display_test: &'a str, - display_response: &'a str, - display_path: &'a str, -} - -impl <'a> ClientInfo<'a> { - pub fn new(client: &'a HttpClient, name: &'a str, test: &'a str, response: &'a str, path: &'a str) -> Self{ - ClientInfo { - client: client, - name: name, - display_test: test, - display_response: response, - display_path: path - } - } -} - -pub async fn client_response<'a, A>(client: &ClientInfo<'a>, cmd: &str, args: &Vec) -> anyhow::Result -where - A: DeserializeOwned -{ - let response: Result = client.client.request(cmd, args.clone()).await; - - match response { - Ok(response) => Ok(response), - Err(e) => handle_client_error(client, e), - } -} - -fn handle_client_error(client: &ClientInfo, e: client::Error) -> anyhow::Result -where - A: DeserializeOwned, -{ - if let Err(e) = log_error(client) { - println!("{}", e.to_string()); - } - - Err(e).with_context(|| err_context(client)) -} - -fn log_error(client: &ClientInfo) -> anyhow::Result<()> -{ - let err_log = err_log(client); - - let mut file = OpenOptions::new() - .append(true) - .create(true) - .open("./test.log") - .with_context(|| "Failed to open log file at ../../test/test.log")?; - - write!(file, "{}", err_log).with_context(|| "Failed to write to log file at ../../test/test.log") -} - -fn err_context(client: &ClientInfo) -> String { - let name = client.name; - let path = client.display_path; - let rpc_header = "RPC call".white().bold(); - let rpc = client.display_test; - let response_header = "Response format".white().bold(); - let response = client.display_response; - - format!( - "\ - Error waiting for rpc call response from {name} in test {path}\n\n\ - {rpc_header}: {rpc}\n\n\ - {response_header}: {response}\ - " - ) -} - -fn err_log(client: &ClientInfo) -> String { - let time = Local::now().format("%d-%m-%Y %H:%M:%S").to_string(); - let name = client.name; - let path = client.display_path; - let rpc = client.display_test; - let response = client.display_response; - - format!( - "\ - {time}\n\ - Error waiting for rpc call response from {name} in test {path}\n\n\ - RPC call: {rpc}\n\n\ - Response format: {response}\n\n\ - " - ) -} \ No newline at end of file diff --git a/rpc_test/src/test_config.rs b/rpc_test/src/test_config.rs deleted file mode 100644 index affb20e..0000000 --- a/rpc_test/src/test_config.rs +++ /dev/null @@ -1,24 +0,0 @@ -use anyhow::Context; -use serde::Deserialize; -use serde_json::from_str; -use std::{fs::File, io::Read}; - -#[derive(PartialEq, Debug, Deserialize)] -pub struct TestConfig { - pub pathfinder: String, - pub deoxys: String, -} - -impl TestConfig { - pub fn new(path: &str) -> anyhow::Result { - let mut file = File::open(path)?; - let mut content = String::new(); - - file.read_to_string(&mut content)?; - - let config: TestConfig = from_str(&content) - .with_context(|| format!("Could not deserialize test at {path} into Config"))?; - - Ok(config) - } -} \ No newline at end of file diff --git a/rpc_test/src/test_data.rs b/rpc_test/src/test_data.rs deleted file mode 100644 index 2aa17c1..0000000 --- a/rpc_test/src/test_data.rs +++ /dev/null @@ -1,35 +0,0 @@ -use anyhow::Context; -use serde::{Deserialize, Serialize}; -use std::{fs::File, io::Read}; - -#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)] -pub struct TestData { - pub tests: Vec -} - -#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)] -pub struct Unit { - pub cmd: String, - pub arg: Vec, - pub block_range: Option, -} - -#[derive(Deserialize, Serialize, Debug, PartialEq, Clone, Copy)] -pub struct BlockRange { - pub start_inclusive: u32, - pub stop_inclusive: u32, -} - -impl TestData { - pub fn new(path: &str) -> anyhow::Result { - let mut file = File::open(path)?; - let mut content = String::new(); - - file.read_to_string(&mut content)?; - - let test_data: TestData = serde_json::from_str(&content) - .with_context(|| format!("Could not deserialize test at into TestData"))?; - - Ok(test_data) - } -} \ No newline at end of file diff --git a/rpc_test_attribute/Cargo.toml b/rpc_test_attribute/Cargo.toml deleted file mode 100644 index 44b63ec..0000000 --- a/rpc_test_attribute/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "rpc_test_attribute" -version = "0.1.0" -edition = "2021" - -[lib] -proc-macro = true - -[dependencies] -quote = "1.0.35" -syn = "2.0.46" diff --git a/rpc_test_attribute/src/lib.rs b/rpc_test_attribute/src/lib.rs deleted file mode 100644 index b63b3bc..0000000 --- a/rpc_test_attribute/src/lib.rs +++ /dev/null @@ -1,85 +0,0 @@ -use proc_macro::TokenStream; -use quote::quote; -use syn::{parse_macro_input, ItemFn}; -use syn::parse::Parse; - -struct Args { - arg_struct: syn::Ident, - arg_test: syn::LitStr, -} - -impl Parse for Args { - fn parse(input: syn::parse::ParseStream) -> syn::Result { - let arg_struct = input.parse::()?; - input.parse::()?; - let arg_test = input.parse::()?; - - Ok(Args { - arg_struct: arg_struct, - arg_test: arg_test, - }) - } -} - -#[proc_macro_attribute] -pub fn rpc_test(args: TokenStream, input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as ItemFn); - let args = parse_macro_input!(args as Args); - - let name = input.sig.ident; - let arg_struct = args.arg_struct; - let arg_test = args.arg_test; - - let expression = quote! { - #[tokio::test] - async fn #name() { - // loads config and initializes RPC clients - let config = rpc_test::test_config::TestConfig::new("./secret.json").unwrap(); - let pathfinder = jsonrpsee::http_client::HttpClientBuilder::default().build(config.pathfinder) - .expect("Could not set up Pathfinder client"); - let deoxys = jsonrpsee::http_client::HttpClientBuilder::default().build(config.deoxys) - .expect("Could not set up Deoxys client"); - - // retrieves test parameters from json specification - // and generates a debug representation - let path = #arg_test; - let test_data = rpc_test::test_data::TestData::new(path) - .expect(&format!("Could not retrieve test data from {}", path)); - let display_response = serde_json::to_string_pretty(&#arg_struct::default()).unwrap(); - - for test in test_data.tests { - // test will be run over a variety of blocks - // TODO: actually implement passing block_number as RPC call parameter - let range = match test.block_range { - Some(range) => range.start_inclusive..=range.stop_inclusive, - None => 0..=1, - }; - let display_test = serde_json::to_string_pretty(&test).unwrap(); - let info_pathfinder = rpc_test::ClientInfo::new( - &pathfinder, - "Pathfinder", - &display_test, - &display_response, - &path - ); - let info_deoxys = rpc_test::ClientInfo::new( - &deoxys, - "Deoxys", - &display_test, - &display_response, - &path - ); - - for _ in range { - // RPC calls happen *here* - let response_pathfinder: #arg_struct = rpc_test::client_response(&info_pathfinder, &test.cmd, &test.arg).await.unwrap(); - let response_deoxys: #arg_struct = rpc_test::client_response(&info_deoxys, &test.cmd, &test.arg).await.unwrap(); - - assert_eq!(response_deoxys, response_pathfinder); - } - } - } - }; - - TokenStream::from(expression) -} \ No newline at end of file diff --git a/unit_tests/Cargo.toml b/unit_tests/Cargo.toml index 5afc8cc..a5bd9f6 100644 --- a/unit_tests/Cargo.toml +++ b/unit_tests/Cargo.toml @@ -12,13 +12,13 @@ serde = "1.0.194" serde_json = "1.0.110" tokio = { version = "1", features = ["full"] } url = "2.5.0" -rpc_test = { path = "../rpc_test/" } starknet = { git = "https://github.com/xJonathanLEI/starknet-rs.git", rev = "a35ce22", default-features = false } starknet-core = { git = "https://github.com/xJonathanLEI/starknet-rs.git", rev = "a35ce22", default-features = false } starknet-providers = { git = "https://github.com/xJonathanLEI/starknet-rs.git", rev = "a35ce22", default-features = false } +env_logger = "0.10.1" [dev-dependencies] jsonrpsee = { version = "0.21.0", features = ["client"] } tokio = { version = "1", features = ["full", "test-util"] } -rpc_test_attribute ={ path = "../rpc_test_attribute/" } flate2 = "1.0.28" +log = "0.4.20" From 2aa10b2e9879263a5accef6dfe6cb188fc801759 Mon Sep 17 00:00:00 2001 From: Trantorian Date: Thu, 11 Jan 2024 09:43:56 +0000 Subject: [PATCH 07/10] test(get_events): :white_check_mark: getEvents single selector Tested getEvents on a single selector. Multiple changes to project structure had to be made along the way, both to remove dead code, improve structure and resolve concurrency issues. --- Cargo.lock | 9 ++ Cargo.toml | 5 +- macros/Cargo.toml | 11 +++ macros/src/lib.rs | 16 ++++ unit_tests/Cargo.toml | 1 + unit_tests/src/constants.rs | 5 +- unit_tests/src/fixtures.rs | 25 +++-- unit_tests/src/lib.rs | 23 +++++ unit_tests/tests/common.rs | 7 +- unit_tests/tests/test_get_events.rs | 138 ++++++++++++++++++++++++++++ 10 files changed, 229 insertions(+), 11 deletions(-) create mode 100644 macros/Cargo.toml create mode 100644 macros/src/lib.rs create mode 100644 unit_tests/tests/test_get_events.rs diff --git a/Cargo.lock b/Cargo.lock index a7173ff..c8c0e46 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1255,6 +1255,14 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "macros" +version = "0.1.0" +dependencies = [ + "quote", + "syn 2.0.48", +] + [[package]] name = "memchr" version = "2.7.1" @@ -2625,6 +2633,7 @@ dependencies = [ "flate2", "jsonrpsee", "log", + "macros", "rstest", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index daaddcc..2547aab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] -members = [ +members = [ "macros", + "macros", "unit_tests", ] default-members = ["unit_tests"] -resolver = "2" \ No newline at end of file +resolver = "2" diff --git a/macros/Cargo.toml b/macros/Cargo.toml new file mode 100644 index 0000000..56499ba --- /dev/null +++ b/macros/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "macros" +version = "0.1.0" +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] +quote = "1.0.35" +syn = "2.0.48" diff --git a/macros/src/lib.rs b/macros/src/lib.rs new file mode 100644 index 0000000..7588e1b --- /dev/null +++ b/macros/src/lib.rs @@ -0,0 +1,16 @@ +use proc_macro::TokenStream; +use syn::{parse_macro_input, ItemFn}; +use quote::{quote, ToTokens}; + +#[proc_macro_attribute] +pub fn logging(_: TokenStream, input: TokenStream) -> TokenStream { + let mut input = parse_macro_input!(input as ItemFn); + + input.block.stmts.insert( + 0, + syn::parse(quote! { + env_logger::builder().is_test(true).try_init().err(); + }.into()).unwrap()); + + input.into_token_stream().into() +} \ No newline at end of file diff --git a/unit_tests/Cargo.toml b/unit_tests/Cargo.toml index a5bd9f6..f98c7c9 100644 --- a/unit_tests/Cargo.toml +++ b/unit_tests/Cargo.toml @@ -22,3 +22,4 @@ jsonrpsee = { version = "0.21.0", features = ["client"] } tokio = { version = "1", features = ["full", "test-util"] } flate2 = "1.0.28" log = "0.4.20" +macros = { path = "../macros/" } \ No newline at end of file diff --git a/unit_tests/src/constants.rs b/unit_tests/src/constants.rs index 8ef4d4b..7357869 100644 --- a/unit_tests/src/constants.rs +++ b/unit_tests/src/constants.rs @@ -126,4 +126,7 @@ pub const TEST_CONTRACT_CLASS_HASH: &str = ""; /// pub const ETHEREUM_ADDRESS: &str = ""; pub const INVALID_ETHEREUM_ADDRESS: &str = ""; -pub const SELECTOR_NAME: &str = ""; \ No newline at end of file +pub const SELECTOR_NAME: &str = ""; + +pub const ERR_DEOXYS: &str = "Error waiting for response from Deoxys client"; +pub const ERR_PATHFINDER: &str = "Error waiting for response from Pathfinder client"; \ No newline at end of file diff --git a/unit_tests/src/fixtures.rs b/unit_tests/src/fixtures.rs index bf0ddc1..2348073 100644 --- a/unit_tests/src/fixtures.rs +++ b/unit_tests/src/fixtures.rs @@ -1,23 +1,34 @@ use std::collections::HashMap; -use rpc_test::test_config::TestConfig; use rstest::fixture; use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport}; use url::Url; +use crate::TestConfig; use crate::constants::*; use crate::map; #[fixture] -pub fn clients() -> HashMap> { - let config = TestConfig::new("./secret.json").expect("'./secret.json' must contain correct node urls"); - let deoxys = JsonRpcClient::new(HttpTransport::new( +pub fn config() -> TestConfig { + TestConfig::new("./secret.json").expect("'./secret.json' must contain correct node urls") +} + +#[fixture] +pub fn deoxys(config: TestConfig) -> JsonRpcClient { + JsonRpcClient::new(HttpTransport::new( Url::parse(&config.deoxys).expect("Error parsing Deoxys node url") - )); - let pathfinder = JsonRpcClient::new(HttpTransport::new( + )) +} + +#[fixture] +pub fn pathfinder(config: TestConfig) -> JsonRpcClient { + JsonRpcClient::new(HttpTransport::new( Url::parse(&config.pathfinder).expect("Error parsing Deoxys node url") - )); + )) +} +#[fixture] +pub fn clients(deoxys: JsonRpcClient, pathfinder: JsonRpcClient) -> HashMap> { map!{ String::from(DEOXYS) => deoxys, String::from(PATHFINDER) => pathfinder, diff --git a/unit_tests/src/lib.rs b/unit_tests/src/lib.rs index bc80a16..7cc358c 100644 --- a/unit_tests/src/lib.rs +++ b/unit_tests/src/lib.rs @@ -1,12 +1,35 @@ #![feature(assert_matches)] +use std::{fs::File, io::Read}; + use constants::*; +use serde::Deserialize; use starknet_core::{types::{FieldElement, BroadcastedTransaction, BroadcastedInvokeTransaction}, utils::get_selector_from_name}; pub mod fixtures; pub mod constants; pub mod macros; +#[derive(PartialEq, Debug, Deserialize)] +pub struct TestConfig { + pub pathfinder: String, + pub deoxys: String, +} + +impl TestConfig { + pub fn new(path: &str) -> anyhow::Result { + let mut file = File::open(path)?; + let mut content = String::new(); + + file.read_to_string(&mut content)?; + + let config: TestConfig = serde_json::from_str(&content) + .expect("Could not deserialize test at {path} into Config"); + + Ok(config) + } +} + pub trait TransactionFactory { fn new(nonce: Option) -> BroadcastedTransaction; } diff --git a/unit_tests/tests/common.rs b/unit_tests/tests/common.rs index eef45be..868ef65 100644 --- a/unit_tests/tests/common.rs +++ b/unit_tests/tests/common.rs @@ -1,6 +1,11 @@ /* Common imports used throughout all unit tests */ +#[allow(unused_imports)] pub use rstest::*; +#[allow(unused_imports)] pub use unit_tests::fixtures::*; -pub use unit_tests::constants::*; \ No newline at end of file +#[allow(unused_imports)] +pub use unit_tests::constants::*; +#[allow(unused_imports)] +pub use macros::*; \ No newline at end of file diff --git a/unit_tests/tests/test_get_events.rs b/unit_tests/tests/test_get_events.rs new file mode 100644 index 0000000..52d9acf --- /dev/null +++ b/unit_tests/tests/test_get_events.rs @@ -0,0 +1,138 @@ +#![feature(assert_matches)] + +mod common; +use std::sync::Arc; + +use anyhow::anyhow; +use common::*; +use starknet::macros::{selector, felt_hex}; +use starknet_core::types::{EventFilter, BlockId, FieldElement}; +use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider}; +use tokio::task::JoinSet; + +/// +/// Test for RPC call `starknet_getEvents`. +/// +/// *What is an EVENT* +/// +/// An Event in the context of the Starknet blockchain is called a Cairo event. It can be emitted by smart +/// contract as a side effect marking steps in execution or internal state. These in turn can be observed +/// from the outside and reacted upon. Events are marked by a *key* and can also store *data. +/// +/// Ex: an authentication contract might emit an event upon successfully login in a user, or an error event +/// in case of invalid data. +/// +/// More documentation can be found in [the Starknet Book](https://www.starknetjs.com/docs/guides/events/) +/// + +// event type to retrieve +const EVENT_KEY: FieldElement = selector!("transaction_executed"); +const BLOCK_NU: u64 = 50000; +const BLOCK_HASH: FieldElement = felt_hex!("0x053315a56543737cd1b2dc40c60e84d03a9b10d712c9b29f488dc979f0cd56bd"); +const BLOCK_RANGE: u64 = 100; + +/// +/// Unit test for `starknet_getEvents` +/// +/// purpose: call getEvents on a valid block with a single selector. +/// success case: valid events format, events point to valid transactions. +/// +#[rstest] +#[tokio::test] +#[logging] +async fn work_valid_call_single_selector(deoxys: JsonRpcClient, pathfinder: JsonRpcClient) { + let response_deoxys = deoxys.get_events( + EventFilter { + // getEvents is a applied through a filter + // this filter consists of a block range... + from_block: Some(BlockId::Number(BLOCK_NU)), + to_block: Some(BlockId::Number(BLOCK_NU)), + // a beginning contract address... + address: None, + // and keys used to filter out events. Keys can include a hash of the event + // and even event return values for further filtering + keys: Some(vec![vec![EVENT_KEY]]) + }, + // in cases were a first search does not yield enough results, a continuation key + // can be used to keep searching from the point of the last getEvent search + None, + // chunk size marks the number of events to look through and filter + // this means that there cannot be more than chunk_size events returned by getEvents + BLOCK_RANGE + ).await.expect(ERR_DEOXYS); + + let response_pathfinder = pathfinder.get_events( + EventFilter { + from_block: Some(BlockId::Number(BLOCK_NU)), + to_block: Some(BlockId::Number(BLOCK_NU)), + address: None, + keys: Some(vec![vec![EVENT_KEY]]) + }, + None, + 100 + ).await.expect(ERR_PATHFINDER); + + // surface-level comparison with pathfinder node, not a guarantee of structure + assert_eq!(response_deoxys, response_pathfinder); + log::info!("Events at block {BLOCK_NU}: {}", serde_json::to_string_pretty(&response_deoxys).unwrap()); + + let mut task_set = JoinSet::new(); + let arc_deoxys = Arc::new(deoxys); + + // detailed comparisons are done in parallel as they are computationally expensive + for event in response_deoxys.events { + let arc_event = Arc::new(event); + + // TODO: simple comparisons are CPU bound, consider running this is Rayon + let clone_event = Arc::clone(&arc_event); + task_set.spawn(async move { + assert_eq!(clone_event.keys.len(), 1); + // first key is always event key + // further keys cannot be predicted without knowing event contract + assert_eq!(clone_event.keys.first().unwrap(), &EVENT_KEY); + assert_eq!(clone_event.block_hash, BLOCK_HASH); + assert_eq!(clone_event.block_number, BLOCK_NU); + + assert_ne!(clone_event.data.len(), 0); + // first data is always transaction hash, + // further data cannot be predicted without knowing event contract + assert_eq!(clone_event.data.first().unwrap(), &clone_event.transaction_hash); + + anyhow::Ok(()) + }); + + // to make sure the associated transactions retrieved by getEvents exists, we make + // a call to the blockchain to retrieve them. This is an io-bound operation + // and benefits greatly of parallelization through tokio + // + // Warning: this test is fast enough as to be rate-limited on certain nodes, + // make sure you are running your own instance or using a provider with rate limiting disabled + let clone_event = Arc::clone(&arc_event); + let clone_deoxys = Arc::clone(&arc_deoxys); + task_set.spawn(async move { + match clone_deoxys.get_transaction_by_hash(clone_event.transaction_hash).await { + Ok(_) => anyhow::Ok(()), + Err(e) => Err(anyhow!("{e}: transaction 0x{:064x} does not exist", clone_event.transaction_hash)), + } + }); + } + + // waits for all tasks to complete. Errors occur if an assertion fails + // or transaction cannot be found with getTransactionByHash + while let Some(res) = task_set.join_next().await { + match res { + // invalid result, could not find transaction + Ok(r) => { + if let Err(e) = r { + task_set.abort_all(); + panic!("{}", e); + } + }, + // thread execution error, stop all threads (invalid assertion or tokio error) + Err(e) => { + task_set.abort_all(); + panic!("JoinError: {}", e); + }, + } + } +} \ No newline at end of file From 50d23e4f638ea8e024b6385930a2e0c1260720b1 Mon Sep 17 00:00:00 2001 From: Trantorian Date: Thu, 11 Jan 2024 10:58:36 +0000 Subject: [PATCH 08/10] test(get_events): :white_check_mark: Covered pretty much all fail / use cases Might sill add event return value / data tests in the future but this is already pretty good --- unit_tests/tests/test_get_events.rs | 197 +++++++++++++++++++++++----- 1 file changed, 161 insertions(+), 36 deletions(-) diff --git a/unit_tests/tests/test_get_events.rs b/unit_tests/tests/test_get_events.rs index 52d9acf..ee7e959 100644 --- a/unit_tests/tests/test_get_events.rs +++ b/unit_tests/tests/test_get_events.rs @@ -1,13 +1,13 @@ #![feature(assert_matches)] mod common; -use std::sync::Arc; +use std::{sync::Arc, assert_matches::assert_matches}; use anyhow::anyhow; use common::*; use starknet::macros::{selector, felt_hex}; -use starknet_core::types::{EventFilter, BlockId, FieldElement}; -use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider}; +use starknet_core::types::{EventFilter, BlockId, FieldElement, EventsPage}; +use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider, ProviderError, StarknetErrorWithMessage, MaybeUnknownErrorCode}; use tokio::task::JoinSet; /// @@ -25,11 +25,100 @@ use tokio::task::JoinSet; /// More documentation can be found in [the Starknet Book](https://www.starknetjs.com/docs/guides/events/) /// -// event type to retrieve -const EVENT_KEY: FieldElement = selector!("transaction_executed"); -const BLOCK_NU: u64 = 50000; -const BLOCK_HASH: FieldElement = felt_hex!("0x053315a56543737cd1b2dc40c60e84d03a9b10d712c9b29f488dc979f0cd56bd"); -const BLOCK_RANGE: u64 = 100; +/// +/// Unit test for `starknet_getEvents` +/// +/// purpose: call getEvents on an invalid block number. +/// fail case: invalid block number (invalid param). +/// +#[rstest] +#[tokio::test] +#[logging] +async fn fail_invalid_block_number(deoxys: JsonRpcClient) { + let keys: Vec> = vec![vec![selector!("transaction_executed")]]; + let block_nu: u64 = u64::MAX; + let block_range: u64 = 100; + + let response_deoxys = get_events(&deoxys, &keys, block_nu, block_range).await.err(); + + assert_matches!( + response_deoxys, + Some(ProviderError::StarknetError(StarknetErrorWithMessage { + message: _, + code: MaybeUnknownErrorCode::Unknown(-32602) + })) + ) +} + +/// +/// Unit test for `starknet_getEvents` +/// +/// purpose: call getEvents on an invalid event selector. +/// fail case: invalid event selector. +/// +#[rstest] +#[tokio::test] +#[logging] +async fn fail_invalid_keys(deoxys: JsonRpcClient) { + let keys: Vec> = vec![vec![selector!("")]]; + let block_nu: u64 = 50000; + let block_range: u64 = 100; + + let response_deoxys = get_events(&deoxys, &keys, block_nu, block_range).await.expect(ERR_DEOXYS); + + log::info!("Events at block {block_nu}: {}", serde_json::to_string_pretty(&response_deoxys).unwrap()); + assert_eq!(response_deoxys.events.len(), 0); +} + +/// +/// Unit test for `starknet_getEvents` +/// +/// purpose: call getEvents on an invalid event selector. +/// fail case: invalid event selector. +/// +#[rstest] +#[tokio::test] +#[logging] +async fn fail_invalid_block_range(deoxys: JsonRpcClient) { + let keys: Vec> = vec![vec![selector!("")]]; + let block_nu: u64 = 50000; + let block_range: u64 = 0; + + let response_deoxys = get_events(&deoxys, &keys, block_nu, block_range).await.err(); + + // for some reason a block range of 0 results in an internal error + assert_matches!( + response_deoxys, + Some(ProviderError::StarknetError(StarknetErrorWithMessage { + message: _, + code: MaybeUnknownErrorCode::Unknown(-32603) + })) + ) +} + +/// +/// Unit test for `starknet_getEvents` +/// +/// purpose: call getEvents on a valid block with a no selector. +/// success case: retrieves the first 100 events of that block. +/// +#[rstest] +#[tokio::test] +#[logging] +async fn work_valid_call_no_selector(deoxys: JsonRpcClient, pathfinder: JsonRpcClient) { + let keys: Vec> = vec![vec![selector!("transaction_executed")]]; + let block_nu: u64 = 50000; + let block_hash: FieldElement = felt_hex!("0x053315a56543737cd1b2dc40c60e84d03a9b10d712c9b29f488dc979f0cd56bd"); + let block_range: u64 = 100; + + let response_deoxys = get_events(&deoxys, &keys, block_nu, block_range).await.expect(ERR_DEOXYS); + let response_pathfinder = get_events(&pathfinder, &keys, block_nu, block_range).await.expect(ERR_PATHFINDER); + + log::info!("Events at block {block_nu}: {}", serde_json::to_string_pretty(&response_deoxys).unwrap()); + assert_eq!(response_deoxys.events.len(), block_range as usize); + assert_eq!(response_deoxys, response_pathfinder); + deep_check_events(deoxys, response_deoxys, keys, block_hash, block_nu).await; +} /// /// Unit test for `starknet_getEvents` @@ -41,43 +130,81 @@ const BLOCK_RANGE: u64 = 100; #[tokio::test] #[logging] async fn work_valid_call_single_selector(deoxys: JsonRpcClient, pathfinder: JsonRpcClient) { - let response_deoxys = deoxys.get_events( + // event type to retrieve + let keys: Vec> = vec![vec![selector!("transaction_executed")]]; + let block_nu: u64 = 50000; + let block_hash: FieldElement = felt_hex!("0x053315a56543737cd1b2dc40c60e84d03a9b10d712c9b29f488dc979f0cd56bd"); + let block_range: u64 = 100; + + let response_deoxys = get_events(&deoxys, &keys, block_nu, block_range).await.expect(ERR_DEOXYS); + let response_pathfinder = get_events(&pathfinder, &keys, block_nu, block_range).await.expect(ERR_PATHFINDER); + + log::info!("Events at block {block_nu}: {}", serde_json::to_string_pretty(&response_deoxys).unwrap()); + assert_eq!(response_deoxys, response_pathfinder); + deep_check_events(deoxys, response_deoxys, keys, block_hash, block_nu).await; +} + +/// +/// Unit test for `starknet_getEvents` +/// +/// purpose: call getEvents on a valid block with a multiple selectors. +/// success case: retrieves all events matching the selector in the first 100 events of that block +/// + valid event format and valid transactions. +/// +#[rstest] +#[tokio::test] +#[logging] +async fn work_valid_call_multiple_selector(deoxys: JsonRpcClient, pathfinder: JsonRpcClient) { + let keys: Vec> = vec![vec![selector!("transaction_executed"), selector!("account_created")]]; + let block_nu: u64 = 50000; + let block_hash: FieldElement = felt_hex!("0x053315a56543737cd1b2dc40c60e84d03a9b10d712c9b29f488dc979f0cd56bd"); + let block_range: u64 = 100; + + let response_deoxys = get_events(&deoxys, &keys, block_nu, block_range).await.expect(ERR_DEOXYS); + let response_pathfinder = get_events(&pathfinder, &keys, block_nu, block_range).await.expect(ERR_PATHFINDER); + + log::info!("Events at block {block_nu}: {}", serde_json::to_string_pretty(&response_deoxys).unwrap()); + assert_eq!(response_deoxys, response_pathfinder); + deep_check_events(deoxys, response_deoxys, keys, block_hash, block_nu).await; +} + +async fn get_events( + client: &JsonRpcClient, + keys: &Vec>, + block_nu: u64, + block_range: u64 +) -> Result { + client.get_events( EventFilter { // getEvents is a applied through a filter // this filter consists of a block range... - from_block: Some(BlockId::Number(BLOCK_NU)), - to_block: Some(BlockId::Number(BLOCK_NU)), + from_block: Some(BlockId::Number(block_nu)), + to_block: Some(BlockId::Number(block_nu)), // a beginning contract address... address: None, // and keys used to filter out events. Keys can include a hash of the event // and even event return values for further filtering - keys: Some(vec![vec![EVENT_KEY]]) + keys: Some(keys.clone()) }, // in cases were a first search does not yield enough results, a continuation key // can be used to keep searching from the point of the last getEvent search None, // chunk size marks the number of events to look through and filter // this means that there cannot be more than chunk_size events returned by getEvents - BLOCK_RANGE - ).await.expect(ERR_DEOXYS); - - let response_pathfinder = pathfinder.get_events( - EventFilter { - from_block: Some(BlockId::Number(BLOCK_NU)), - to_block: Some(BlockId::Number(BLOCK_NU)), - address: None, - keys: Some(vec![vec![EVENT_KEY]]) - }, - None, - 100 - ).await.expect(ERR_PATHFINDER); - - // surface-level comparison with pathfinder node, not a guarantee of structure - assert_eq!(response_deoxys, response_pathfinder); - log::info!("Events at block {BLOCK_NU}: {}", serde_json::to_string_pretty(&response_deoxys).unwrap()); + block_range + ).await +} +async fn deep_check_events( + deoxys: JsonRpcClient, + response_deoxys: EventsPage, + keys: Vec>, + block_hash: FieldElement, + block_nu: u64 +) { let mut task_set = JoinSet::new(); let arc_deoxys = Arc::new(deoxys); + let arc_keys = Arc::new(keys); // detailed comparisons are done in parallel as they are computationally expensive for event in response_deoxys.events { @@ -85,18 +212,16 @@ async fn work_valid_call_single_selector(deoxys: JsonRpcClient, p // TODO: simple comparisons are CPU bound, consider running this is Rayon let clone_event = Arc::clone(&arc_event); + let clone_keys = Arc::clone(&arc_keys); + task_set.spawn(async move { assert_eq!(clone_event.keys.len(), 1); // first key is always event key // further keys cannot be predicted without knowing event contract - assert_eq!(clone_event.keys.first().unwrap(), &EVENT_KEY); - assert_eq!(clone_event.block_hash, BLOCK_HASH); - assert_eq!(clone_event.block_number, BLOCK_NU); - + assert!(clone_keys.first().unwrap().contains(clone_event.keys.first().unwrap())); + assert_eq!(clone_event.block_hash, block_hash); + assert_eq!(clone_event.block_number, block_nu); assert_ne!(clone_event.data.len(), 0); - // first data is always transaction hash, - // further data cannot be predicted without knowing event contract - assert_eq!(clone_event.data.first().unwrap(), &clone_event.transaction_hash); anyhow::Ok(()) }); From 64c4829d0cbd2466a69a3308d455b7165523ae8b Mon Sep 17 00:00:00 2001 From: Trantorian Date: Thu, 11 Jan 2024 13:12:35 +0000 Subject: [PATCH 09/10] refactor(fmt): :recycle: Formatted code to pass CI --- Cargo.lock | 40 --- Cargo.toml | 2 - rpc_test/Cargo.toml | 14 - rpc_test/src/lib.rs | 102 ------ rpc_test/src/test_config.rs | 24 -- rpc_test/src/test_data.rs | 35 --- rpc_test_attribute/Cargo.toml | 11 - rpc_test_attribute/src/lib.rs | 85 ----- unit_tests/Cargo.toml | 2 - unit_tests/src/constants.rs | 68 ++-- unit_tests/src/fixtures.rs | 15 +- unit_tests/src/lib.rs | 39 ++- unit_tests/src/macros.rs | 2 +- unit_tests/tests/common.rs | 3 +- .../tests/test_block_hash_and_number.rs | 26 +- unit_tests/tests/test_block_number.rs | 21 +- unit_tests/tests/test_call.rs | 297 ++++++++++-------- unit_tests/tests/test_chain_id.rs | 4 +- unit_tests/tests/test_estimate_fee.rs | 35 ++- unit_tests/tests/test_estimate_message_fee.rs | 2 +- .../tests/test_get_block_transaction_count.rs | 1 - .../tests/test_get_block_with_tx_hashes.rs | 64 ++-- unit_tests/tests/test_get_class.rs | 8 +- unit_tests/tests/test_get_class_at.rs | 118 ++++--- unit_tests/tests/test_get_class_hash_at.rs | 91 +++--- unit_tests/tests/test_get_nonce.rs | 123 +++++--- unit_tests/tests/test_get_state_update.rs | 2 +- unit_tests/tests/test_get_storage_at.rs | 90 +++--- ...t_get_transaction_by_block_id_and_index.rs | 175 ++++++----- .../tests/test_get_transaction_by_hash.rs | 100 +++--- .../tests/test_get_transaction_status.rs | 110 ++++--- unit_tests/tests/test_syncing.rs | 4 +- 32 files changed, 834 insertions(+), 879 deletions(-) delete mode 100644 rpc_test/Cargo.toml delete mode 100644 rpc_test/src/lib.rs delete mode 100644 rpc_test/src/test_config.rs delete mode 100644 rpc_test/src/test_data.rs delete mode 100644 rpc_test_attribute/Cargo.toml delete mode 100644 rpc_test_attribute/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index b71e795..150cb8b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -299,10 +299,8 @@ checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ "android-tzdata", "iana-time-zone", - "js-sys", "num-traits", "serde", - "wasm-bindgen", "windows-targets 0.48.5", ] @@ -316,16 +314,6 @@ dependencies = [ "inout", ] -[[package]] -name = "colored" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" -dependencies = [ - "lazy_static", - "windows-sys 0.48.0", -] - [[package]] name = "concurrent-queue" version = "2.4.0" @@ -1196,12 +1184,6 @@ dependencies = [ "cpufeatures", ] -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - [[package]] name = "libc" version = "0.2.151" @@ -1662,26 +1644,6 @@ dependencies = [ "rustc-hex", ] -[[package]] -name = "rpc_test" -version = "0.1.0" -dependencies = [ - "anyhow", - "chrono", - "colored", - "jsonrpsee", - "serde", - "serde_json", -] - -[[package]] -name = "rpc_test_attribute" -version = "0.1.0" -dependencies = [ - "quote", - "syn 2.0.46", -] - [[package]] name = "rstest" version = "0.18.2" @@ -2590,8 +2552,6 @@ dependencies = [ "anyhow", "flate2", "jsonrpsee", - "rpc_test", - "rpc_test_attribute", "rstest", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index a5abf2d..9dceb36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,5 @@ [workspace] members = [ - "rpc_test", - "rpc_test_attribute", "unit_tests", ] default-members = ["unit_tests"] diff --git a/rpc_test/Cargo.toml b/rpc_test/Cargo.toml deleted file mode 100644 index 0f5bcfa..0000000 --- a/rpc_test/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "rpc_test" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -anyhow = "1.0.79" -chrono = "0.4.31" -colored = "2.1.0" -jsonrpsee = { version = "0.21.0", features = ["client"] } -serde = "1.0.194" -serde_json = "1.0.110" diff --git a/rpc_test/src/lib.rs b/rpc_test/src/lib.rs deleted file mode 100644 index ea4e1fa..0000000 --- a/rpc_test/src/lib.rs +++ /dev/null @@ -1,102 +0,0 @@ -pub mod test_config; -pub mod test_data; - -use std::fs::OpenOptions; -use std::io::Write; - -use anyhow::Context; -use chrono::Local; -use jsonrpsee::core::client::{ClientT, self}; -use jsonrpsee::http_client::HttpClient; -use colored::Colorize; -use jsonrpsee::core::DeserializeOwned; - -pub struct ClientInfo<'a> { - client: &'a HttpClient, - name: &'a str, - display_test: &'a str, - display_response: &'a str, - display_path: &'a str, -} - -impl <'a> ClientInfo<'a> { - pub fn new(client: &'a HttpClient, name: &'a str, test: &'a str, response: &'a str, path: &'a str) -> Self{ - ClientInfo { - client: client, - name: name, - display_test: test, - display_response: response, - display_path: path - } - } -} - -pub async fn client_response<'a, A>(client: &ClientInfo<'a>, cmd: &str, args: &Vec) -> anyhow::Result -where - A: DeserializeOwned -{ - let response: Result = client.client.request(cmd, args.clone()).await; - - match response { - Ok(response) => Ok(response), - Err(e) => handle_client_error(client, e), - } -} - -fn handle_client_error(client: &ClientInfo, e: client::Error) -> anyhow::Result -where - A: DeserializeOwned, -{ - if let Err(e) = log_error(client) { - println!("{}", e.to_string()); - } - - Err(e).with_context(|| err_context(client)) -} - -fn log_error(client: &ClientInfo) -> anyhow::Result<()> -{ - let err_log = err_log(client); - - let mut file = OpenOptions::new() - .append(true) - .create(true) - .open("./test.log") - .with_context(|| "Failed to open log file at ../../test/test.log")?; - - write!(file, "{}", err_log).with_context(|| "Failed to write to log file at ../../test/test.log") -} - -fn err_context(client: &ClientInfo) -> String { - let name = client.name; - let path = client.display_path; - let rpc_header = "RPC call".white().bold(); - let rpc = client.display_test; - let response_header = "Response format".white().bold(); - let response = client.display_response; - - format!( - "\ - Error waiting for rpc call response from {name} in test {path}\n\n\ - {rpc_header}: {rpc}\n\n\ - {response_header}: {response}\ - " - ) -} - -fn err_log(client: &ClientInfo) -> String { - let time = Local::now().format("%d-%m-%Y %H:%M:%S").to_string(); - let name = client.name; - let path = client.display_path; - let rpc = client.display_test; - let response = client.display_response; - - format!( - "\ - {time}\n\ - Error waiting for rpc call response from {name} in test {path}\n\n\ - RPC call: {rpc}\n\n\ - Response format: {response}\n\n\ - " - ) -} \ No newline at end of file diff --git a/rpc_test/src/test_config.rs b/rpc_test/src/test_config.rs deleted file mode 100644 index affb20e..0000000 --- a/rpc_test/src/test_config.rs +++ /dev/null @@ -1,24 +0,0 @@ -use anyhow::Context; -use serde::Deserialize; -use serde_json::from_str; -use std::{fs::File, io::Read}; - -#[derive(PartialEq, Debug, Deserialize)] -pub struct TestConfig { - pub pathfinder: String, - pub deoxys: String, -} - -impl TestConfig { - pub fn new(path: &str) -> anyhow::Result { - let mut file = File::open(path)?; - let mut content = String::new(); - - file.read_to_string(&mut content)?; - - let config: TestConfig = from_str(&content) - .with_context(|| format!("Could not deserialize test at {path} into Config"))?; - - Ok(config) - } -} \ No newline at end of file diff --git a/rpc_test/src/test_data.rs b/rpc_test/src/test_data.rs deleted file mode 100644 index 2aa17c1..0000000 --- a/rpc_test/src/test_data.rs +++ /dev/null @@ -1,35 +0,0 @@ -use anyhow::Context; -use serde::{Deserialize, Serialize}; -use std::{fs::File, io::Read}; - -#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)] -pub struct TestData { - pub tests: Vec -} - -#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)] -pub struct Unit { - pub cmd: String, - pub arg: Vec, - pub block_range: Option, -} - -#[derive(Deserialize, Serialize, Debug, PartialEq, Clone, Copy)] -pub struct BlockRange { - pub start_inclusive: u32, - pub stop_inclusive: u32, -} - -impl TestData { - pub fn new(path: &str) -> anyhow::Result { - let mut file = File::open(path)?; - let mut content = String::new(); - - file.read_to_string(&mut content)?; - - let test_data: TestData = serde_json::from_str(&content) - .with_context(|| format!("Could not deserialize test at into TestData"))?; - - Ok(test_data) - } -} \ No newline at end of file diff --git a/rpc_test_attribute/Cargo.toml b/rpc_test_attribute/Cargo.toml deleted file mode 100644 index 44b63ec..0000000 --- a/rpc_test_attribute/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "rpc_test_attribute" -version = "0.1.0" -edition = "2021" - -[lib] -proc-macro = true - -[dependencies] -quote = "1.0.35" -syn = "2.0.46" diff --git a/rpc_test_attribute/src/lib.rs b/rpc_test_attribute/src/lib.rs deleted file mode 100644 index b63b3bc..0000000 --- a/rpc_test_attribute/src/lib.rs +++ /dev/null @@ -1,85 +0,0 @@ -use proc_macro::TokenStream; -use quote::quote; -use syn::{parse_macro_input, ItemFn}; -use syn::parse::Parse; - -struct Args { - arg_struct: syn::Ident, - arg_test: syn::LitStr, -} - -impl Parse for Args { - fn parse(input: syn::parse::ParseStream) -> syn::Result { - let arg_struct = input.parse::()?; - input.parse::()?; - let arg_test = input.parse::()?; - - Ok(Args { - arg_struct: arg_struct, - arg_test: arg_test, - }) - } -} - -#[proc_macro_attribute] -pub fn rpc_test(args: TokenStream, input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as ItemFn); - let args = parse_macro_input!(args as Args); - - let name = input.sig.ident; - let arg_struct = args.arg_struct; - let arg_test = args.arg_test; - - let expression = quote! { - #[tokio::test] - async fn #name() { - // loads config and initializes RPC clients - let config = rpc_test::test_config::TestConfig::new("./secret.json").unwrap(); - let pathfinder = jsonrpsee::http_client::HttpClientBuilder::default().build(config.pathfinder) - .expect("Could not set up Pathfinder client"); - let deoxys = jsonrpsee::http_client::HttpClientBuilder::default().build(config.deoxys) - .expect("Could not set up Deoxys client"); - - // retrieves test parameters from json specification - // and generates a debug representation - let path = #arg_test; - let test_data = rpc_test::test_data::TestData::new(path) - .expect(&format!("Could not retrieve test data from {}", path)); - let display_response = serde_json::to_string_pretty(&#arg_struct::default()).unwrap(); - - for test in test_data.tests { - // test will be run over a variety of blocks - // TODO: actually implement passing block_number as RPC call parameter - let range = match test.block_range { - Some(range) => range.start_inclusive..=range.stop_inclusive, - None => 0..=1, - }; - let display_test = serde_json::to_string_pretty(&test).unwrap(); - let info_pathfinder = rpc_test::ClientInfo::new( - &pathfinder, - "Pathfinder", - &display_test, - &display_response, - &path - ); - let info_deoxys = rpc_test::ClientInfo::new( - &deoxys, - "Deoxys", - &display_test, - &display_response, - &path - ); - - for _ in range { - // RPC calls happen *here* - let response_pathfinder: #arg_struct = rpc_test::client_response(&info_pathfinder, &test.cmd, &test.arg).await.unwrap(); - let response_deoxys: #arg_struct = rpc_test::client_response(&info_deoxys, &test.cmd, &test.arg).await.unwrap(); - - assert_eq!(response_deoxys, response_pathfinder); - } - } - } - }; - - TokenStream::from(expression) -} \ No newline at end of file diff --git a/unit_tests/Cargo.toml b/unit_tests/Cargo.toml index 8d78d6d..d93ef3d 100644 --- a/unit_tests/Cargo.toml +++ b/unit_tests/Cargo.toml @@ -12,7 +12,6 @@ serde = "1.0.194" serde_json = "1.0.110" tokio = { version = "1", features = ["full"] } url = "2.5.0" -rpc_test = { path = "../rpc_test/" } starknet = { git = "https://github.com/xJonathanLEI/starknet-rs.git", rev = "64ebc36", default-features = false } starknet-core = { git = "https://github.com/xJonathanLEI/starknet-rs.git", rev = "64ebc36", default-features = false } starknet-providers = { git = "https://github.com/xJonathanLEI/starknet-rs.git", rev = "64ebc36", default-features = false } @@ -20,5 +19,4 @@ starknet-providers = { git = "https://github.com/xJonathanLEI/starknet-rs.git", [dev-dependencies] jsonrpsee = { version = "0.21.0", features = ["client"] } tokio = { version = "1", features = ["full", "test-util"] } -rpc_test_attribute ={ path = "../rpc_test_attribute/" } flate2 = "1.0.28" diff --git a/unit_tests/src/constants.rs b/unit_tests/src/constants.rs index 7357869..e8efaec 100644 --- a/unit_tests/src/constants.rs +++ b/unit_tests/src/constants.rs @@ -14,107 +14,121 @@ pub const CONTRACT_KEY: &str = "0x00f920571b9f85bdd92a867cfdc73319d0f8836f0e69e0 /// /// Details concerning available methods can be found on [StarkScan](https://starkscan.co/contract/0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7#read-write-contract) /// -pub const STARKGATE_ETH_BRIDGE_ADDR: &str = "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"; +pub const STARKGATE_ETH_BRIDGE_ADDR: &str = + "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"; /// /// Contract address for Jediswap exchange. /// /// Details concerning available methods can be found on [StarkScan](https://starkscan.co/contract/0x041fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023#read-write-contract): /// -pub const JEDI_SWAP_ADDR: &str = "0x041fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023"; +pub const JEDI_SWAP_ADDR: &str = + "0x041fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023"; /// /// Contract address for Starkgate USDC on Starknet. /// /// Details concerning this coin can be found on [StarkScan](https://starkscan.co/token/0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8): /// -pub const STARKGATE_USDC: &str = "0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8"; +pub const STARKGATE_USDC: &str = + "0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8"; /// /// Contract address fpr Starkgate Ether on Starknet. /// /// Detail concerning this coin can be found on [StarkScan](https://starkscan.co/token/0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7): /// -pub const STARKGATE_ETHER: &str = "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"; +pub const STARKGATE_ETHER: &str = + "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"; /// /// Random ERC721 Starknet contract address. /// /// Details concerning this contract can be found on [StarkScan](https://starkscan.co/contract/0x07fa9a8eacb89fb6cd0c7fe557e71c42a4b181ba328a9a04958136e6469c4e00) /// -pub const CONTRACT_ERC721: &str = "0x07fa9a8eacb89fb6cd0c7fe557e71c42a4b181ba328a9a04958136e6469c4e00"; +pub const CONTRACT_ERC721: &str = + "0x07fa9a8eacb89fb6cd0c7fe557e71c42a4b181ba328a9a04958136e6469c4e00"; /// /// Random ERC20 Starknet contract address. /// /// Details concerning this contract can be found on [StarkScan](https://starkscan.co/contract/0x04a5fdce70877b77f03aea8a29259176f88d5bea9d0ad8c0118f5316425e6ba0) /// -pub const CONTRACT_ERC20: &str = "0x04a5fdce70877b77f03aea8a29259176f88d5bea9d0ad8c0118f5316425e6ba0"; +pub const CONTRACT_ERC20: &str = + "0x04a5fdce70877b77f03aea8a29259176f88d5bea9d0ad8c0118f5316425e6ba0"; /// /// Random ACCOUNT Starknet contract address. /// /// Details concerning this contract can be found on [StarkScan](https://starkscan.co/contract/0x05e1eee30e79b4f592f444132526b2e2c7f505698e888c659e5f5def5a458c1a) /// -pub const CONTRACT_ACCOUNT: &str = "0x05e1eee30e79b4f592f444132526b2e2c7f505698e888c659e5f5def5a458c1a"; +pub const CONTRACT_ACCOUNT: &str = + "0x05e1eee30e79b4f592f444132526b2e2c7f505698e888c659e5f5def5a458c1a"; /// /// Random PROXY ACCOUNT Starknet contract address. /// /// Details concerning this contract can be found on [StarkScan](https://starkscan.co/contract/0x05d7f4d55795b56ceb4dd93febe17954c7cfd5e15d7a79cb0cec067a713ac159) /// -pub const CONTRACT_ACCOUNT_PROXY: &str = "0x05d7f4d55795b56ceb4dd93febe17954c7cfd5e15d7a79cb0cec067a713ac159"; +pub const CONTRACT_ACCOUNT_PROXY: &str = + "0x05d7f4d55795b56ceb4dd93febe17954c7cfd5e15d7a79cb0cec067a713ac159"; /// /// Random legacy account using Cairo v0 -/// +/// /// Details concerning this contract can be found on [StarkScan](https://starkscan.co/contract/0x07076931c19d0ef52b847f9412c90a2ef999ff028f1005d2d069343061762fb7) -/// -pub const CONTRACT_LEGACY: &str = "0x07076931c19d0ef52b847f9412c90a2ef999ff028f1005d2d069343061762fb7"; +/// +pub const CONTRACT_LEGACY: &str = + "0x07076931c19d0ef52b847f9412c90a2ef999ff028f1005d2d069343061762fb7"; pub const BLOCK_LEGACY: u64 = 2891; /// /// INVOKE transaction accepted on L1, also transaction 1 at block 5000 -/// +/// /// Details concerning this transaction can be found on [StarkScan](https://starkscan.co/tx/0x0214840bad3099f95c40106097b8ef5fd16f06cb23efcdaec297398f77174597) -/// -pub const TRANSACTION_INVOKE: &str = "0x0214840bad3099f95c40106097b8ef5fd16f06cb23efcdaec297398f77174597"; +/// +pub const TRANSACTION_INVOKE: &str = + "0x0214840bad3099f95c40106097b8ef5fd16f06cb23efcdaec297398f77174597"; pub const TRANSACTION_INVOKE_INDEX: u64 = 1; pub const TRANSACTION_INVOKE_BLOCK_NB: u64 = 50000; /// /// L1_HANDLER transaction accepted on L1, also transaction 57 at block 50000 -/// +/// /// Details concerning this transaction can be found on [StarkScan](https://starkscan.co/tx/0x05ca6470c37e943b0ae172a11359f7a457054319e8ae8771af32a1f397c7c208) -/// -pub const TRANSACTION_L1_HANDLER: &str = "0x05ca6470c37e943b0ae172a11359f7a457054319e8ae8771af32a1f397c7c208"; +/// +pub const TRANSACTION_L1_HANDLER: &str = + "0x05ca6470c37e943b0ae172a11359f7a457054319e8ae8771af32a1f397c7c208"; pub const TRANSACTION_L1_HANDLER_INDEX: u64 = 57; pub const TRANSACTION_L1_HANDLER_BLOCK_NB: u64 = 50000; /// /// DECLARE transaction accepted on L1, also transaction 44 at block 49990 -/// +/// /// Details concerning this transaction can be found on [StarkScan](https://starkscan.co/tx/0x056c0723ef6cde62f589bbf7c5c40897b6e3d9c13e960c5e7f28276d8e9c3229) -/// -pub const TRANSACTION_DECLARE: &str = "0x056c0723ef6cde62f589bbf7c5c40897b6e3d9c13e960c5e7f28276d8e9c3229"; +/// +pub const TRANSACTION_DECLARE: &str = + "0x056c0723ef6cde62f589bbf7c5c40897b6e3d9c13e960c5e7f28276d8e9c3229"; pub const TRANSACTION_DECLARE_INDEX: u64 = 44; pub const TRANSACTION_DECLARE_BLOCK_NB: u64 = 49990; /// /// DEPLOY_ACCOUNT transaction accepted on L1, also transaction 0 at block 5000 -/// +/// /// Details concerning this transaction can be found on [StarkScan](https://starkscan.co/tx/0x0604e143591a6bff980f3141abdfc87f1ef3243785d251367cdaa7da5c337ba4) -/// -pub const TRANSACTION_DEPLOY_ACCOUNT: &str = "0x0604e143591a6bff980f3141abdfc87f1ef3243785d251367cdaa7da5c337ba4"; +/// +pub const TRANSACTION_DEPLOY_ACCOUNT: &str = + "0x0604e143591a6bff980f3141abdfc87f1ef3243785d251367cdaa7da5c337ba4"; pub const TRANSACTION_DEPLOY_ACCOUNT_INDEX: u64 = 0; pub const TRANSACTION_DEPLOY_ACCOUNT_BLOCK_NB: u64 = 50000; /// /// Random reverted Starknet transaction -/// +/// /// Details concerning this transaction can be found on [StarkScan](https://starkscan.co/tx/0x016ed559467c50c12f225f348ca8895d54b91a499ad6f856cb6086e317c120ca) -/// -pub const TRANSACTION_REVERTED: &str = "0x016ed559467c50c12f225f348ca8895d54b91a499ad6f856cb6086e317c120ca"; +/// +pub const TRANSACTION_REVERTED: &str = + "0x016ed559467c50c12f225f348ca8895d54b91a499ad6f856cb6086e317c120ca"; pub const ACCOUNT_CONTRACT: &str = ""; pub const TEST_CONTRACT_ADDRESS: &str = ""; @@ -129,4 +143,4 @@ pub const INVALID_ETHEREUM_ADDRESS: &str = ""; pub const SELECTOR_NAME: &str = ""; pub const ERR_DEOXYS: &str = "Error waiting for response from Deoxys client"; -pub const ERR_PATHFINDER: &str = "Error waiting for response from Pathfinder client"; \ No newline at end of file +pub const ERR_PATHFINDER: &str = "Error waiting for response from Pathfinder client"; diff --git a/unit_tests/src/fixtures.rs b/unit_tests/src/fixtures.rs index bf0ddc1..be2b5d8 100644 --- a/unit_tests/src/fixtures.rs +++ b/unit_tests/src/fixtures.rs @@ -1,25 +1,26 @@ use std::collections::HashMap; -use rpc_test::test_config::TestConfig; use rstest::fixture; -use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport}; +use starknet_providers::{jsonrpc::HttpTransport, JsonRpcClient}; use url::Url; use crate::constants::*; use crate::map; +use crate::TestConfig; #[fixture] pub fn clients() -> HashMap> { - let config = TestConfig::new("./secret.json").expect("'./secret.json' must contain correct node urls"); + let config = + TestConfig::new("./secret.json").expect("'./secret.json' must contain correct node urls"); let deoxys = JsonRpcClient::new(HttpTransport::new( - Url::parse(&config.deoxys).expect("Error parsing Deoxys node url") + Url::parse(&config.deoxys).expect("Error parsing Deoxys node url"), )); let pathfinder = JsonRpcClient::new(HttpTransport::new( - Url::parse(&config.pathfinder).expect("Error parsing Deoxys node url") + Url::parse(&config.pathfinder).expect("Error parsing Deoxys node url"), )); - map!{ + map! { String::from(DEOXYS) => deoxys, String::from(PATHFINDER) => pathfinder, } -} \ No newline at end of file +} diff --git a/unit_tests/src/lib.rs b/unit_tests/src/lib.rs index bc80a16..544e951 100644 --- a/unit_tests/src/lib.rs +++ b/unit_tests/src/lib.rs @@ -1,20 +1,47 @@ #![feature(assert_matches)] use constants::*; -use starknet_core::{types::{FieldElement, BroadcastedTransaction, BroadcastedInvokeTransaction}, utils::get_selector_from_name}; +use starknet_core::{ + types::{BroadcastedInvokeTransaction, BroadcastedTransaction, FieldElement}, + utils::get_selector_from_name, +}; -pub mod fixtures; pub mod constants; +pub mod fixtures; pub mod macros; +use anyhow::Context; +use serde::Deserialize; +use serde_json::from_str; +use std::{fs::File, io::Read}; + +#[derive(PartialEq, Debug, Deserialize)] +pub struct TestConfig { + pub pathfinder: String, + pub deoxys: String, +} + +impl TestConfig { + pub fn new(path: &str) -> anyhow::Result { + let mut file = File::open(path)?; + let mut content = String::new(); + + file.read_to_string(&mut content)?; + + let config: TestConfig = from_str(&content) + .with_context(|| format!("Could not deserialize test at {path} into Config"))?; + + Ok(config) + } +} pub trait TransactionFactory { - fn new(nonce: Option) -> BroadcastedTransaction; + fn build(nonce: Option) -> BroadcastedTransaction; } pub struct OkTransactionFactory; impl TransactionFactory for OkTransactionFactory { - fn new(nonce: Option) -> BroadcastedTransaction { + fn build(nonce: Option) -> BroadcastedTransaction { BroadcastedTransaction::Invoke(BroadcastedInvokeTransaction { max_fee: FieldElement::ZERO, signature: vec![], @@ -34,7 +61,7 @@ impl TransactionFactory for OkTransactionFactory { pub struct BadTransactionFactory; impl TransactionFactory for BadTransactionFactory { - fn new(_: Option) -> BroadcastedTransaction { + fn build(_: Option) -> BroadcastedTransaction { BroadcastedTransaction::Invoke(BroadcastedInvokeTransaction { max_fee: FieldElement::default(), nonce: FieldElement::ZERO, @@ -44,4 +71,4 @@ impl TransactionFactory for BadTransactionFactory { is_query: true, }) } -} \ No newline at end of file +} diff --git a/unit_tests/src/macros.rs b/unit_tests/src/macros.rs index 15c2cab..8b3501b 100644 --- a/unit_tests/src/macros.rs +++ b/unit_tests/src/macros.rs @@ -10,4 +10,4 @@ macro_rules! map { m } }; -} \ No newline at end of file +} diff --git a/unit_tests/tests/common.rs b/unit_tests/tests/common.rs index eef45be..509c03d 100644 --- a/unit_tests/tests/common.rs +++ b/unit_tests/tests/common.rs @@ -1,6 +1,5 @@ - /* Common imports used throughout all unit tests */ pub use rstest::*; +pub use unit_tests::constants::*; pub use unit_tests::fixtures::*; -pub use unit_tests::constants::*; \ No newline at end of file diff --git a/unit_tests/tests/test_block_hash_and_number.rs b/unit_tests/tests/test_block_hash_and_number.rs index 7883d96..90153f1 100644 --- a/unit_tests/tests/test_block_hash_and_number.rs +++ b/unit_tests/tests/test_block_hash_and_number.rs @@ -3,24 +3,36 @@ use common::*; use std::collections::HashMap; -use starknet_providers::{jsonrpc::{HttpTransport, JsonRpcClient}, Provider}; +use starknet_providers::{ + jsonrpc::{HttpTransport, JsonRpcClient}, + Provider, +}; /// /// Unit test for `starknet_BlockHashAndNumber` -/// +/// /// purpose: get block hash and number on latest block. /// success case: retrieves correct block hash and number. -/// +/// #[rstest] #[tokio::test] async fn work_latest_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.block_hash_and_number().await.expect("Error waiting for response from Deoxys node"); - let response_pathfinder = pathfinder.block_hash_and_number().await.expect("Error waiting for response from Deoxys node"); - let response_expected = deoxys.block_number().await.expect("Error waiting for response from Deoxys node"); + let response_deoxys = deoxys + .block_hash_and_number() + .await + .expect("Error waiting for response from Deoxys node"); + let response_pathfinder = pathfinder + .block_hash_and_number() + .await + .expect("Error waiting for response from Deoxys node"); + let response_expected = deoxys + .block_number() + .await + .expect("Error waiting for response from Deoxys node"); assert_eq!(response_deoxys.block_number, response_expected); assert_eq!(response_deoxys, response_pathfinder); -} \ No newline at end of file +} diff --git a/unit_tests/tests/test_block_number.rs b/unit_tests/tests/test_block_number.rs index d175c7c..c7721d7 100644 --- a/unit_tests/tests/test_block_number.rs +++ b/unit_tests/tests/test_block_number.rs @@ -3,23 +3,32 @@ use common::*; use std::collections::HashMap; -use starknet_providers::{jsonrpc::{HttpTransport, JsonRpcClient}, Provider}; +use starknet_providers::{ + jsonrpc::{HttpTransport, JsonRpcClient}, + Provider, +}; /// /// Unit test for `starknet_blockNumber` -/// +/// /// purpose: call blockNumber on latest block. /// success case: must return valid non-zero block number. -/// +/// #[rstest] #[tokio::test] async fn work_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.block_number().await.expect("Deoxys : Error while getting the block number"); - let response_pathfinder = pathfinder.block_number().await.expect("RPC : Error while getting the block number"); + let response_deoxys = deoxys + .block_number() + .await + .expect("Deoxys : Error while getting the block number"); + let response_pathfinder = pathfinder + .block_number() + .await + .expect("RPC : Error while getting the block number"); assert!(response_deoxys > 0); assert_eq!(response_deoxys, response_pathfinder); -} \ No newline at end of file +} diff --git a/unit_tests/tests/test_call.rs b/unit_tests/tests/test_call.rs index f64ebd4..832ce3e 100644 --- a/unit_tests/tests/test_call.rs +++ b/unit_tests/tests/test_call.rs @@ -1,16 +1,22 @@ #![feature(assert_matches)] mod common; -use std::{collections::HashMap, assert_matches::assert_matches}; +use std::{assert_matches::assert_matches, collections::HashMap}; use common::*; use starknet::macros::short_string; -use starknet_core::{types::{FunctionCall, BlockTag, BlockId, FieldElement, StarknetError}, utils::get_selector_from_name}; -use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider, ProviderError, StarknetErrorWithMessage, MaybeUnknownErrorCode}; +use starknet_core::{ + types::{BlockId, BlockTag, FieldElement, FunctionCall, StarknetError}, + utils::get_selector_from_name, +}; +use starknet_providers::{ + jsonrpc::HttpTransport, JsonRpcClient, MaybeUnknownErrorCode, Provider, ProviderError, + StarknetErrorWithMessage, +}; /// /// Unit test for `starknet_call` -/// +/// /// purpose: function request `name` to StarkGate ETH bridge contract /// fail case: invalid block /// @@ -19,14 +25,17 @@ use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider, Provid async fn fail_non_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.call( - FunctionCall { - contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), - entry_point_selector: get_selector_from_name("name").unwrap(), - calldata: vec![] - }, - BlockId::Hash(FieldElement::ZERO) - ).await.err(); + let response_deoxys = deoxys + .call( + FunctionCall { + contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), + entry_point_selector: get_selector_from_name("name").unwrap(), + calldata: vec![], + }, + BlockId::Hash(FieldElement::ZERO), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -39,7 +48,7 @@ async fn fail_non_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.call( - FunctionCall { - contract_address: FieldElement::ZERO, - entry_point_selector: get_selector_from_name("name").unwrap(), - calldata: vec![] - }, - BlockId::Tag(BlockTag::Latest) - ).await.err(); + let response_deoxys = deoxys + .call( + FunctionCall { + contract_address: FieldElement::ZERO, + entry_point_selector: get_selector_from_name("name").unwrap(), + calldata: vec![], + }, + BlockId::Tag(BlockTag::Latest), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -68,23 +80,28 @@ async fn fail_non_existing_contract(clients: HashMap>) { +async fn fail_invalid_contract_entry_point_selector( + clients: HashMap>, +) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.call( - FunctionCall { - contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), - entry_point_selector: FieldElement::ZERO, - calldata: vec![] - }, - BlockId::Tag(BlockTag::Latest) - ).await.err(); + let response_deoxys = deoxys + .call( + FunctionCall { + contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), + entry_point_selector: FieldElement::ZERO, + calldata: vec![], + }, + BlockId::Tag(BlockTag::Latest), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -97,7 +114,7 @@ async fn fail_invalid_contract_entry_point_selector(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.call( - FunctionCall { - contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), - entry_point_selector: get_selector_from_name("balanceOf").unwrap(), - calldata: vec![] - }, - BlockId::Tag(BlockTag::Latest) - ).await.err(); + let response_deoxys = deoxys + .call( + FunctionCall { + contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), + entry_point_selector: get_selector_from_name("balanceOf").unwrap(), + calldata: vec![], + }, + BlockId::Tag(BlockTag::Latest), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -126,7 +146,7 @@ async fn fail_missing_contract_call_data(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.call( - FunctionCall { - contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), - entry_point_selector: get_selector_from_name("balanceOf").unwrap(), - calldata: vec![ - FieldElement::ZERO - ] - }, - BlockId::Tag(BlockTag::Latest) - ).await.expect("Error waiting for response from Deoxys node"); - - assert_eq!(response_deoxys, vec![FieldElement::ZERO, FieldElement::ZERO]); + let response_deoxys = deoxys + .call( + FunctionCall { + contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), + entry_point_selector: get_selector_from_name("balanceOf").unwrap(), + calldata: vec![FieldElement::ZERO], + }, + BlockId::Tag(BlockTag::Latest), + ) + .await + .expect("Error waiting for response from Deoxys node"); + + assert_eq!( + response_deoxys, + vec![FieldElement::ZERO, FieldElement::ZERO] + ); } /// /// Unit test for `starknet_call` -/// +/// /// purpose: function request `name` to StarkGate ETH bridge contract /// fail case: too many arguments in call data /// @@ -160,16 +184,17 @@ async fn fail_invalid_contract_call_data(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.call( - FunctionCall { - contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), - entry_point_selector: get_selector_from_name("name").unwrap(), - calldata: vec![ - FieldElement::ZERO - ] - }, - BlockId::Tag(BlockTag::Latest) - ).await.err(); + let response_deoxys = deoxys + .call( + FunctionCall { + contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), + entry_point_selector: get_selector_from_name("name").unwrap(), + calldata: vec![FieldElement::ZERO], + }, + BlockId::Tag(BlockTag::Latest), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -182,7 +207,7 @@ async fn fail_too_many_call_data(clients: HashMap let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.call( - FunctionCall { - contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), - entry_point_selector: get_selector_from_name("name").unwrap(), - calldata: vec![] - }, - BlockId::Tag(BlockTag::Latest) - ).await.expect("Error waiting for response from Deoxys node"); - - let response_pathfinder = pathfinder.call( - FunctionCall { - contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), - entry_point_selector: get_selector_from_name("name").unwrap(), - calldata: vec![] - }, - BlockId::Tag(BlockTag::Latest) - ).await.expect("Error waiting for response from Pathfinder node"); + let response_deoxys = deoxys + .call( + FunctionCall { + contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), + entry_point_selector: get_selector_from_name("name").unwrap(), + calldata: vec![], + }, + BlockId::Tag(BlockTag::Latest), + ) + .await + .expect("Error waiting for response from Deoxys node"); + + let response_pathfinder = pathfinder + .call( + FunctionCall { + contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), + entry_point_selector: get_selector_from_name("name").unwrap(), + calldata: vec![], + }, + BlockId::Tag(BlockTag::Latest), + ) + .await + .expect("Error waiting for response from Pathfinder node"); let response_expected = short_string!("Ether"); @@ -218,7 +249,7 @@ async fn work_correct_call(clients: HashMap /// /// Unit test for `starknet_call` -/// +/// /// purpose: function request `balanceOf` to StarkGate ETH bridge contract /// success case: must return non-zero balance /// @@ -228,27 +259,29 @@ async fn work_correct_call_with_args(clients: HashMap>) { diff --git a/unit_tests/tests/test_estimate_fee.rs b/unit_tests/tests/test_estimate_fee.rs index 771a815..2d7846a 100644 --- a/unit_tests/tests/test_estimate_fee.rs +++ b/unit_tests/tests/test_estimate_fee.rs @@ -4,10 +4,13 @@ mod common; use common::*; use starknet_core::types::{BlockId, BlockTag, FieldElement, StarknetError}; -use starknet_providers::{jsonrpc::{HttpTransport, JsonRpcClient}, MaybeUnknownErrorCode, Provider, ProviderError, StarknetErrorWithMessage,}; -use unit_tests::{OkTransactionFactory, TransactionFactory, BadTransactionFactory}; +use starknet_providers::{ + jsonrpc::{HttpTransport, JsonRpcClient}, + MaybeUnknownErrorCode, Provider, ProviderError, StarknetErrorWithMessage, +}; use std::assert_matches::assert_matches; use std::collections::HashMap; +use unit_tests::{BadTransactionFactory, OkTransactionFactory, TransactionFactory}; #[rstest] #[tokio::test] @@ -15,7 +18,7 @@ use std::collections::HashMap; async fn fail_non_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let ok_invoke_transaction = OkTransactionFactory::new(Some(FieldElement::ZERO)); + let ok_invoke_transaction = OkTransactionFactory::build(Some(FieldElement::ZERO)); assert_matches!( deoxys.estimate_fee(&vec![ok_invoke_transaction], BlockId::Hash(FieldElement::ZERO)).await, @@ -26,11 +29,13 @@ async fn fail_non_existing_block(clients: HashMap>) { +async fn fail_if_one_txn_cannot_be_executed( + clients: HashMap>, +) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let bad_invoke_transaction = BadTransactionFactory::new(None); + let bad_invoke_transaction = BadTransactionFactory::build(None); let result_deoxys = deoxys .estimate_fee( @@ -56,13 +61,13 @@ async fn works_ok(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let ok_deoxys_invoke = OkTransactionFactory::new(Some(FieldElement::ZERO)); - let ok_deoxys_invoke_1 = OkTransactionFactory::new(Some(FieldElement::ONE)); - let ok_deoxys_invoke_2 = OkTransactionFactory::new(Some(FieldElement::TWO)); + let ok_deoxys_invoke = OkTransactionFactory::build(Some(FieldElement::ZERO)); + let ok_deoxys_invoke_1 = OkTransactionFactory::build(Some(FieldElement::ONE)); + let ok_deoxys_invoke_2 = OkTransactionFactory::build(Some(FieldElement::TWO)); - let ok_pathfinder_invoke = OkTransactionFactory::new(Some(FieldElement::ZERO)); - let ok_pathfinder_invoke_1 = OkTransactionFactory::new(Some(FieldElement::ONE)); - let ok_pathfinder_invoke_2 = OkTransactionFactory::new(Some(FieldElement::TWO)); + let ok_pathfinder_invoke = OkTransactionFactory::build(Some(FieldElement::ZERO)); + let ok_pathfinder_invoke_1 = OkTransactionFactory::build(Some(FieldElement::ONE)); + let ok_pathfinder_invoke_2 = OkTransactionFactory::build(Some(FieldElement::TWO)); let deoxys_estimates = deoxys .estimate_fee( @@ -74,11 +79,15 @@ async fn works_ok(clients: HashMap>) { let pathfinder_estimates = pathfinder .estimate_fee( - &vec![ok_pathfinder_invoke, ok_pathfinder_invoke_1, ok_pathfinder_invoke_2], + &vec![ + ok_pathfinder_invoke, + ok_pathfinder_invoke_1, + ok_pathfinder_invoke_2, + ], BlockId::Tag(BlockTag::Latest), ) .await .unwrap(); assert_eq!(deoxys_estimates, pathfinder_estimates); -} \ No newline at end of file +} diff --git a/unit_tests/tests/test_estimate_message_fee.rs b/unit_tests/tests/test_estimate_message_fee.rs index 8a177b3..b2c61ac 100644 --- a/unit_tests/tests/test_estimate_message_fee.rs +++ b/unit_tests/tests/test_estimate_message_fee.rs @@ -146,4 +146,4 @@ async fn estimate_message_fee_works_ok(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_block_with_tx_hashes(BlockId::Hash(FieldElement::ZERO)).await.err(); + let response_deoxys = deoxys + .get_block_with_tx_hashes(BlockId::Hash(FieldElement::ZERO)) + .await + .err(); assert_matches!( - response_deoxys, + response_deoxys, Some(ProviderError::StarknetError(StarknetErrorWithMessage { message: _, code: MaybeUnknownErrorCode::Known(StarknetError::BlockNotFound) - } - ))); + })) + ); } /// /// Unit test for `starknet_get_block_with_tx_hashes` -/// +/// /// purpose: call getBlockWithTxHashes on latest validated block. /// success case: retrieves valid block. -/// +/// #[rstest] #[tokio::test] async fn work_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.get_block_with_tx_hashes(BlockId::Tag(BlockTag::Latest)).await + let response_deoxys = deoxys + .get_block_with_tx_hashes(BlockId::Tag(BlockTag::Latest)) + .await .expect("Error waiting for response from Deoxys node"); - let response_pathfinder = pathfinder.get_block_with_tx_hashes(BlockId::Tag(BlockTag::Latest)).await + let response_pathfinder = pathfinder + .get_block_with_tx_hashes(BlockId::Tag(BlockTag::Latest)) + .await .expect("Error waiting for response from Deoxys node"); let block_deoxys = match response_deoxys { MaybePendingBlockWithTxHashes::Block(block) => block, - MaybePendingBlockWithTxHashes::PendingBlock(_) => panic!("Expected block, got pending block"), + MaybePendingBlockWithTxHashes::PendingBlock(_) => { + panic!("Expected block, got pending block") + } }; let block_pathfinder = match response_pathfinder { MaybePendingBlockWithTxHashes::Block(block) => block, - MaybePendingBlockWithTxHashes::PendingBlock(_) => panic!("Expected block, got pending block"), + MaybePendingBlockWithTxHashes::PendingBlock(_) => { + panic!("Expected block, got pending block") + } }; assert_eq!(block_deoxys, block_pathfinder); } /// /// Unit test for `starknet_get_block_with_tx_hashes` -/// +/// /// purpose: call getBlockWithTxHashes on pending block. /// success case: retrieves valid pending block. -/// +/// /// Note that this can fail at the last moments of a block being validated!!! -/// +/// #[rstest] #[tokio::test] #[ignore = "Pending fails some times when called on the cusp of being accepted, need virtual sequencer"] @@ -75,13 +89,15 @@ async fn work_pending_block(clients: HashMap panic!("Expected pending block, got block"), @@ -93,4 +109,4 @@ async fn work_pending_block(clients: HashMap>) { +async fn work_ok_retrieving_class_for_contract_version_0( + clients: HashMap>, +) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; @@ -78,7 +80,9 @@ async fn work_ok_retrieving_class_for_contract_version_0(clients: HashMap>) { +async fn work_ok_retrieving_class_for_contract_version_1( + clients: HashMap>, +) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; diff --git a/unit_tests/tests/test_get_class_at.rs b/unit_tests/tests/test_get_class_at.rs index 014c2dd..4515fad 100644 --- a/unit_tests/tests/test_get_class_at.rs +++ b/unit_tests/tests/test_get_class_at.rs @@ -1,84 +1,100 @@ #![feature(assert_matches)] mod common; -use std::{collections::HashMap, assert_matches::assert_matches, io::Read}; +use std::{assert_matches::assert_matches, collections::HashMap, io::Read}; use common::*; use flate2::read::GzDecoder; -use starknet_core::types::{FieldElement, BlockId, StarknetError, BlockTag, ContractClass, contract::legacy::LegacyProgram}; -use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider, StarknetErrorWithMessage, ProviderError, MaybeUnknownErrorCode}; +use starknet_core::types::{ + contract::legacy::LegacyProgram, BlockId, BlockTag, ContractClass, FieldElement, StarknetError, +}; +use starknet_providers::{ + jsonrpc::HttpTransport, JsonRpcClient, MaybeUnknownErrorCode, Provider, ProviderError, + StarknetErrorWithMessage, +}; /// /// unit test for `starknet_get_class_at` -/// +/// /// purpose: gets contract class for inexistent block. /// fail case: invalid block address. -/// +/// #[rstest] #[tokio::test] async fn fail_non_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_class_at( - BlockId::Hash(FieldElement::ZERO), - FieldElement::from_hex_be(CONTRACT_ACCOUNT).unwrap() - ).await.err(); + let response_deoxys = deoxys + .get_class_at( + BlockId::Hash(FieldElement::ZERO), + FieldElement::from_hex_be(CONTRACT_ACCOUNT).unwrap(), + ) + .await + .err(); assert_matches!( - response_deoxys, + response_deoxys, Some(ProviderError::StarknetError(StarknetErrorWithMessage { message: _, code: MaybeUnknownErrorCode::Known(StarknetError::BlockNotFound) - } - ))); + })) + ); } /// /// unit test for `starknet_get_class_at` -/// +/// /// purpose: gets contract class for inexistent contract. /// fail case: invalid contract address. -/// +/// #[rstest] #[tokio::test] async fn fail_non_existing_contract(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_class_at( - BlockId::Tag(BlockTag::Latest), - FieldElement::ZERO - ).await.err(); + let response_deoxys = deoxys + .get_class_at(BlockId::Tag(BlockTag::Latest), FieldElement::ZERO) + .await + .err(); assert_matches!( - response_deoxys, + response_deoxys, Some(ProviderError::StarknetError(StarknetErrorWithMessage { message: _, code: MaybeUnknownErrorCode::Known(StarknetError::ContractNotFound) - } - ))); + })) + ); } /// /// unit test for `starknet_get_class_at` -/// +/// /// purpose: gets legacy contract and extracts it's data. -/// success case: should retrieve contract and decompress it to a valid json string. -/// +/// success case: should retrieve contract and decompress it to a valid json string. +/// #[rstest] #[tokio::test] -async fn work_contract_v0(clients: HashMap>) -> anyhow::Result<()> { +async fn work_contract_v0( + clients: HashMap>, +) -> anyhow::Result<()> { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.get_class_at( - BlockId::Number(BLOCK_LEGACY), - FieldElement::from_hex_be(CONTRACT_LEGACY).unwrap() - ).await.expect("Error waiting for response from Deoxys client"); - - let response_pathfinder = pathfinder.get_class_at( - BlockId::Number(BLOCK_LEGACY), - FieldElement::from_hex_be(CONTRACT_LEGACY).unwrap() - ).await.expect("Error waiting for response from Pathfinder client"); + let response_deoxys = deoxys + .get_class_at( + BlockId::Number(BLOCK_LEGACY), + FieldElement::from_hex_be(CONTRACT_LEGACY).unwrap(), + ) + .await + .expect("Error waiting for response from Deoxys client"); + + let response_pathfinder = pathfinder + .get_class_at( + BlockId::Number(BLOCK_LEGACY), + FieldElement::from_hex_be(CONTRACT_LEGACY).unwrap(), + ) + .await + .expect("Error waiting for response from Pathfinder client"); let mut json_deoxys: String = String::new(); match &response_deoxys { @@ -89,7 +105,7 @@ async fn work_contract_v0(clients: HashMap> // makes sure json_deoxys is a valid json string serde_json::from_str::(&json_deoxys)?; - }, + } } let mut json_pathfinder = String::new(); @@ -98,7 +114,7 @@ async fn work_contract_v0(clients: HashMap> ContractClass::Legacy(contract) => { let mut decoder = GzDecoder::new(&contract.program[..]); decoder.read_to_string(&mut json_pathfinder)?; - }, + } } assert_eq!(json_deoxys, json_pathfinder); @@ -109,25 +125,31 @@ async fn work_contract_v0(clients: HashMap> /// /// unit test for `starknet_get_class_at` -/// +/// /// purpose: gets Cairo v1 contract and extracts it's data. /// success case: should retrieve contract correctly. -/// +/// #[rstest] #[tokio::test] async fn work_contract_v1(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.get_class_at( - BlockId::Tag(BlockTag::Latest), - FieldElement::from_hex_be(CONTRACT_ACCOUNT).unwrap() - ).await.expect("Error waiting for response from Deoxys client"); - - let response_pathfinder = pathfinder.get_class_at( - BlockId::Tag(BlockTag::Latest), - FieldElement::from_hex_be(CONTRACT_ACCOUNT).unwrap() - ).await.expect("Error waiting for response from Pathfinder client"); + let response_deoxys = deoxys + .get_class_at( + BlockId::Tag(BlockTag::Latest), + FieldElement::from_hex_be(CONTRACT_ACCOUNT).unwrap(), + ) + .await + .expect("Error waiting for response from Deoxys client"); + + let response_pathfinder = pathfinder + .get_class_at( + BlockId::Tag(BlockTag::Latest), + FieldElement::from_hex_be(CONTRACT_ACCOUNT).unwrap(), + ) + .await + .expect("Error waiting for response from Pathfinder client"); assert_eq!(response_deoxys, response_pathfinder); -} \ No newline at end of file +} diff --git a/unit_tests/tests/test_get_class_hash_at.rs b/unit_tests/tests/test_get_class_hash_at.rs index 26891d1..a597985 100644 --- a/unit_tests/tests/test_get_class_hash_at.rs +++ b/unit_tests/tests/test_get_class_hash_at.rs @@ -5,24 +5,30 @@ use common::*; use std::{assert_matches::assert_matches, collections::HashMap}; -use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider, ProviderError, StarknetErrorWithMessage, MaybeUnknownErrorCode}; -use starknet_core::types::{BlockId, FieldElement, StarknetError, BlockTag}; +use starknet_core::types::{BlockId, BlockTag, FieldElement, StarknetError}; +use starknet_providers::{ + jsonrpc::HttpTransport, JsonRpcClient, MaybeUnknownErrorCode, Provider, ProviderError, + StarknetErrorWithMessage, +}; /// /// Unit test for `starknet_getClassHashAt` -/// +/// /// purpose: call getClassHashAt on invalid block. /// fail case: invalid block hash. -/// +/// #[rstest] #[tokio::test] async fn fail_non_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_class_hash_at( - BlockId::Hash(FieldElement::ZERO), - FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap() - ).await.err(); + let response_deoxys = deoxys + .get_class_hash_at( + BlockId::Hash(FieldElement::ZERO), + FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap(), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -35,19 +41,22 @@ async fn fail_non_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_class_hash_at( - BlockId::Tag(BlockTag::Latest), - FieldElement::from_hex_be(INVALID_CONTRACT_ADDR).unwrap() - ).await.err(); + let response_deoxys = deoxys + .get_class_hash_at( + BlockId::Tag(BlockTag::Latest), + FieldElement::from_hex_be(INVALID_CONTRACT_ADDR).unwrap(), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -60,48 +69,60 @@ async fn fail_non_existing_contract(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let class_hash_deoxys = deoxys.get_class_hash_at( - BlockId::Tag(BlockTag::Latest), - FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap() - ).await.expect("Error waiting for response from Deoxys node"); - let class_hash_pathfinder = pathfinder.get_class_hash_at( - BlockId::Tag(BlockTag::Latest), - FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap() - ).await.expect("Error waiting for response from Pathfinder node"); + let class_hash_deoxys = deoxys + .get_class_hash_at( + BlockId::Tag(BlockTag::Latest), + FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap(), + ) + .await + .expect("Error waiting for response from Deoxys node"); + let class_hash_pathfinder = pathfinder + .get_class_hash_at( + BlockId::Tag(BlockTag::Latest), + FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap(), + ) + .await + .expect("Error waiting for response from Pathfinder node"); assert_eq!(class_hash_deoxys, class_hash_pathfinder); } /// /// Unit test for `starknet_getClassHashAt` -/// +/// /// purpose: call getClassHashAt on pending block. /// success case: retrieve valid class hash. -/// +/// #[rstest] #[tokio::test] async fn work_block_pending(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let class_hash_deoxys = deoxys.get_class_hash_at( - BlockId::Tag(BlockTag::Pending), - FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap() - ).await.expect("Error waiting for response from Deoxys node"); - let class_hash_pathfinder = pathfinder.get_class_hash_at( - BlockId::Tag(BlockTag::Pending), - FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap() - ).await.expect("Error waiting for response from Pathfinder node"); + let class_hash_deoxys = deoxys + .get_class_hash_at( + BlockId::Tag(BlockTag::Pending), + FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap(), + ) + .await + .expect("Error waiting for response from Deoxys node"); + let class_hash_pathfinder = pathfinder + .get_class_hash_at( + BlockId::Tag(BlockTag::Pending), + FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap(), + ) + .await + .expect("Error waiting for response from Pathfinder node"); assert_eq!(class_hash_deoxys, class_hash_pathfinder); -} \ No newline at end of file +} diff --git a/unit_tests/tests/test_get_nonce.rs b/unit_tests/tests/test_get_nonce.rs index dda1f91..bd42fa2 100644 --- a/unit_tests/tests/test_get_nonce.rs +++ b/unit_tests/tests/test_get_nonce.rs @@ -1,31 +1,34 @@ #![feature(assert_matches)] mod common; -use std::{collections::HashMap, assert_matches::assert_matches}; +use std::{assert_matches::assert_matches, collections::HashMap}; use common::*; -use starknet_core::types::{BlockId, FieldElement, StarknetError, BlockTag}; -use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider, ProviderError, StarknetErrorWithMessage, MaybeUnknownErrorCode}; +use starknet_core::types::{BlockId, BlockTag, FieldElement, StarknetError}; +use starknet_providers::{ + jsonrpc::HttpTransport, JsonRpcClient, MaybeUnknownErrorCode, Provider, ProviderError, + StarknetErrorWithMessage, +}; /// /// Test for RPC call starknet_getNonce. -/// +/// /// *What is a NONCE?* -/// +/// /// A nonce is a unique identifier attributed to a starknet transaction, guaranteeing it cannot be added to a /// block multiple times. As of writing this, Starknet nonces are **sequential**, which is to say that the nonce /// in a new transaction must follow that of the previous transaction from the same account. The concept of a /// nonce on Starknet should not be confused with how nonces are used on other blockchains such as Bitcoin as /// part of proof-of-work. -/// +/// /// More documentation can be found in [the Starknet Book](https://book.starknet.io/ch03-01-01-transactions-lifecycle.html#nonces-in-starknet) -/// +/// /// [Trantorian1](https://github.com/trantorian1) 09-01-2024 /// /// /// Unit test for `starknet_getNonce` -/// +/// /// purpose: call getNonce on invalid block. /// fail case: invalid block. /// @@ -34,10 +37,13 @@ use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider, Provid async fn fail_non_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_nonce( - BlockId::Hash(FieldElement::ZERO), - FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap() - ).await.err(); + let response_deoxys = deoxys + .get_nonce( + BlockId::Hash(FieldElement::ZERO), + FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap(), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -50,7 +56,7 @@ async fn fail_non_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_nonce( - BlockId::Tag(BlockTag::Latest), - FieldElement::from_hex_be(INVALID_CONTRACT_ADDR).unwrap() - ).await.err(); + let response_deoxys = deoxys + .get_nonce( + BlockId::Tag(BlockTag::Latest), + FieldElement::from_hex_be(INVALID_CONTRACT_ADDR).unwrap(), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -78,7 +87,7 @@ async fn fail_non_existing_contract(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_nonce( - BlockId::Tag(BlockTag::Latest), - FieldElement::from_hex_be(CONTRACT_ERC721).unwrap() - ).await.expect("Error waiting for response from Deoxys node"); + let response_deoxys = deoxys + .get_nonce( + BlockId::Tag(BlockTag::Latest), + FieldElement::from_hex_be(CONTRACT_ERC721).unwrap(), + ) + .await + .expect("Error waiting for response from Deoxys node"); assert_eq!(response_deoxys, FieldElement::ZERO); } /// /// Unit test for `starknet_getNonce` -/// +/// /// purpose: call getNonce on ERC20 contract. /// success case: must return a nonce of 0. /// @@ -106,17 +118,20 @@ async fn work_erc721_contract(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_nonce( - BlockId::Tag(BlockTag::Latest), - FieldElement::from_hex_be(CONTRACT_ERC20).unwrap() - ).await.expect("Error waiting for response from Deoxys node"); + let response_deoxys = deoxys + .get_nonce( + BlockId::Tag(BlockTag::Latest), + FieldElement::from_hex_be(CONTRACT_ERC20).unwrap(), + ) + .await + .expect("Error waiting for response from Deoxys node"); assert_eq!(response_deoxys, FieldElement::ZERO); } /// /// Unit test for `starknet_getNonce` -/// +/// /// purpose: call getNonce on account contract. /// success case: must return a non-zero nonce. /// @@ -126,15 +141,21 @@ async fn work_account_contract(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_storage_at( - FieldElement::from_hex_be(CONTRACT_ADDR).unwrap(), - FieldElement::from_hex_be(CONTRACT_KEY).unwrap(), - BlockId::Hash(FieldElement::ZERO) - ).await.err(); + let response_deoxys = deoxys + .get_storage_at( + FieldElement::from_hex_be(CONTRACT_ADDR).unwrap(), + FieldElement::from_hex_be(CONTRACT_KEY).unwrap(), + BlockId::Hash(FieldElement::ZERO), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -37,20 +43,23 @@ async fn fail_non_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_storage_at( - FieldElement::ZERO, - FieldElement::from_hex_be(CONTRACT_KEY).unwrap(), - BlockId::Tag(BlockTag::Latest) - ).await.err(); + let response_deoxys = deoxys + .get_storage_at( + FieldElement::ZERO, + FieldElement::from_hex_be(CONTRACT_KEY).unwrap(), + BlockId::Tag(BlockTag::Latest), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -63,30 +72,33 @@ async fn fail_non_existing_contract(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_storage_at( - FieldElement::from_hex_be(CONTRACT_ADDR).unwrap(), - FieldElement::ZERO, - BlockId::Tag(BlockTag::Latest) - ).await.expect("Error waiting for response from Deoxys client"); + let response_deoxys = deoxys + .get_storage_at( + FieldElement::from_hex_be(CONTRACT_ADDR).unwrap(), + FieldElement::ZERO, + BlockId::Tag(BlockTag::Latest), + ) + .await + .expect("Error waiting for response from Deoxys client"); assert_eq!(response_deoxys, FieldElement::ZERO); } /// /// Unit test for `starknet_getStorageAt` -/// +/// /// purpose: call getStorageAt with valid arguments. /// success case: retrieve valid storage. -/// +/// #[rstest] #[tokio::test] async fn work_get_storage(clients: HashMap>) { @@ -94,16 +106,22 @@ async fn work_get_storage(clients: HashMap> let pathfinder = &clients[PATHFINDER]; // TODO: get contract key from field name - let response_deoxys = deoxys.get_storage_at( - FieldElement::from_hex_be(CONTRACT_ADDR).unwrap(), - FieldElement::from_hex_be(CONTRACT_KEY).unwrap(), - BlockId::Tag(BlockTag::Latest) - ).await.expect("Error waiting for response from Deoxys client"); - let response_pathfinder = pathfinder.get_storage_at( - FieldElement::from_hex_be(CONTRACT_ADDR).unwrap(), - FieldElement::from_hex_be(CONTRACT_KEY).unwrap(), - BlockId::Tag(BlockTag::Latest) - ).await.expect("Error waiting for response from Pathfinder client"); + let response_deoxys = deoxys + .get_storage_at( + FieldElement::from_hex_be(CONTRACT_ADDR).unwrap(), + FieldElement::from_hex_be(CONTRACT_KEY).unwrap(), + BlockId::Tag(BlockTag::Latest), + ) + .await + .expect("Error waiting for response from Deoxys client"); + let response_pathfinder = pathfinder + .get_storage_at( + FieldElement::from_hex_be(CONTRACT_ADDR).unwrap(), + FieldElement::from_hex_be(CONTRACT_KEY).unwrap(), + BlockId::Tag(BlockTag::Latest), + ) + .await + .expect("Error waiting for response from Pathfinder client"); assert_eq!(response_deoxys, response_pathfinder); -} \ No newline at end of file +} diff --git a/unit_tests/tests/test_get_transaction_by_block_id_and_index.rs b/unit_tests/tests/test_get_transaction_by_block_id_and_index.rs index e911f76..c207583 100644 --- a/unit_tests/tests/test_get_transaction_by_block_id_and_index.rs +++ b/unit_tests/tests/test_get_transaction_by_block_id_and_index.rs @@ -1,27 +1,30 @@ #![feature(assert_matches)] mod common; -use std::{collections::HashMap, assert_matches::assert_matches}; +use std::{assert_matches::assert_matches, collections::HashMap}; use common::*; -use starknet_core::types::{FieldElement, BlockId, StarknetError}; -use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider, StarknetErrorWithMessage, ProviderError, MaybeUnknownErrorCode}; +use starknet_core::types::{BlockId, FieldElement, StarknetError}; +use starknet_providers::{ + jsonrpc::HttpTransport, JsonRpcClient, MaybeUnknownErrorCode, Provider, ProviderError, + StarknetErrorWithMessage, +}; /// /// Unit test for `starknet_getTransactionByBlockIdAndIndex` -/// +/// /// purpose: call on non-existent block. /// fail case: invalid block -/// +/// #[rstest] #[tokio::test] async fn fail_non_existent_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_transaction_by_block_id_and_index( - BlockId::Hash(FieldElement::ZERO), - 0 - ).await.err(); + let response_deoxys = deoxys + .get_transaction_by_block_id_and_index(BlockId::Hash(FieldElement::ZERO), 0) + .await + .err(); assert_matches!( response_deoxys, @@ -34,19 +37,19 @@ async fn fail_non_existent_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_transaction_by_block_id_and_index( - BlockId::Number(5000), - 389 - ).await.err(); + let response_deoxys = deoxys + .get_transaction_by_block_id_and_index(BlockId::Number(5000), 389) + .await + .err(); assert_matches!( response_deoxys, @@ -59,10 +62,10 @@ async fn fail_non_existent_block_index(clients: HashMap>) { @@ -70,20 +73,27 @@ async fn work_deploy_invoke(clients: HashMap>) { @@ -102,20 +112,27 @@ async fn work_deploy_l1_handler(clients: HashMap>) { @@ -134,20 +151,27 @@ async fn work_deploy_declare(clients: HashMap>) { @@ -166,21 +190,28 @@ async fn work_deploy_account(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_transaction_by_hash( - FieldElement::ZERO - ).await.err(); - + let response_deoxys = deoxys + .get_transaction_by_hash(FieldElement::ZERO) + .await + .err(); + assert_matches!( - response_deoxys, + response_deoxys, Some(ProviderError::StarknetError(StarknetErrorWithMessage { message: _, code: MaybeUnknownErrorCode::Known(StarknetError::TransactionHashNotFound) - } - ))); + })) + ); } /// /// Unit test for `starknet_getTransactionByHash` -/// +/// /// purpose: call getTransactionHash on INVOKE transaction. /// success case: retrieve correct INVOKE transaction. -/// +/// #[rstest] #[tokio::test] async fn work_transaction_invoke(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.get_transaction_by_hash( - FieldElement::from_hex_be(TRANSACTION_INVOKE).unwrap() - ).await.expect("Error waiting for response from Deoxys node"); + let response_deoxys = deoxys + .get_transaction_by_hash(FieldElement::from_hex_be(TRANSACTION_INVOKE).unwrap()) + .await + .expect("Error waiting for response from Deoxys node"); - let response_pathfinder = pathfinder.get_transaction_by_hash( - FieldElement::from_hex_be(TRANSACTION_INVOKE).unwrap() - ).await.expect("Error waiting for response from Pathfinder node"); + let response_pathfinder = pathfinder + .get_transaction_by_hash(FieldElement::from_hex_be(TRANSACTION_INVOKE).unwrap()) + .await + .expect("Error waiting for response from Pathfinder node"); assert_matches!(response_deoxys, Transaction::Invoke(_)); assert_eq!(response_deoxys, response_pathfinder); @@ -57,23 +63,25 @@ async fn work_transaction_invoke(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.get_transaction_by_hash( - FieldElement::from_hex_be(TRANSACTION_L1_HANDLER).unwrap() - ).await.expect("Error waiting for response from Deoxys node"); + let response_deoxys = deoxys + .get_transaction_by_hash(FieldElement::from_hex_be(TRANSACTION_L1_HANDLER).unwrap()) + .await + .expect("Error waiting for response from Deoxys node"); - let response_pathfinder = pathfinder.get_transaction_by_hash( - FieldElement::from_hex_be(TRANSACTION_L1_HANDLER).unwrap() - ).await.expect("Error waiting for response from Pathfinder node"); + let response_pathfinder = pathfinder + .get_transaction_by_hash(FieldElement::from_hex_be(TRANSACTION_L1_HANDLER).unwrap()) + .await + .expect("Error waiting for response from Pathfinder node"); assert_matches!(response_deoxys, Transaction::L1Handler(_)); assert_eq!(response_deoxys, response_pathfinder); @@ -81,23 +89,25 @@ async fn work_transaction_l1_handler(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.get_transaction_by_hash( - FieldElement::from_hex_be(TRANSACTION_DECLARE).unwrap() - ).await.expect("Error waiting for response from Deoxys node"); + let response_deoxys = deoxys + .get_transaction_by_hash(FieldElement::from_hex_be(TRANSACTION_DECLARE).unwrap()) + .await + .expect("Error waiting for response from Deoxys node"); - let response_pathfinder = pathfinder.get_transaction_by_hash( - FieldElement::from_hex_be(TRANSACTION_DECLARE).unwrap() - ).await.expect("Error waiting for response from Pathfinder node"); + let response_pathfinder = pathfinder + .get_transaction_by_hash(FieldElement::from_hex_be(TRANSACTION_DECLARE).unwrap()) + .await + .expect("Error waiting for response from Pathfinder node"); assert_matches!(response_deoxys, Transaction::Declare(_)); assert_eq!(response_deoxys, response_pathfinder); @@ -107,24 +117,26 @@ async fn work_transaction_declare(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.get_transaction_by_hash( - FieldElement::from_hex_be(TRANSACTION_DEPLOY_ACCOUNT).unwrap() - ).await.expect("Error waiting for response from Deoxys node"); + let response_deoxys = deoxys + .get_transaction_by_hash(FieldElement::from_hex_be(TRANSACTION_DEPLOY_ACCOUNT).unwrap()) + .await + .expect("Error waiting for response from Deoxys node"); - let response_pathfinder = pathfinder.get_transaction_by_hash( - FieldElement::from_hex_be(TRANSACTION_DEPLOY_ACCOUNT).unwrap() - ).await.expect("Error waiting for response from Pathfinder node"); + let response_pathfinder = pathfinder + .get_transaction_by_hash(FieldElement::from_hex_be(TRANSACTION_DEPLOY_ACCOUNT).unwrap()) + .await + .expect("Error waiting for response from Pathfinder node"); assert_matches!(response_deoxys, Transaction::DeployAccount(_)); assert_eq!(response_deoxys, response_pathfinder); -} \ No newline at end of file +} diff --git a/unit_tests/tests/test_get_transaction_status.rs b/unit_tests/tests/test_get_transaction_status.rs index 25d5656..8f74bb4 100644 --- a/unit_tests/tests/test_get_transaction_status.rs +++ b/unit_tests/tests/test_get_transaction_status.rs @@ -1,26 +1,32 @@ #![feature(assert_matches)] mod common; -use std::{collections::HashMap, assert_matches::assert_matches}; +use std::{assert_matches::assert_matches, collections::HashMap}; use common::*; -use starknet_core::types::{FieldElement, StarknetError, TransactionStatus, TransactionExecutionStatus, BlockId, BlockTag}; -use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider, StarknetErrorWithMessage, ProviderError, MaybeUnknownErrorCode}; +use starknet_core::types::{ + BlockId, BlockTag, FieldElement, StarknetError, TransactionExecutionStatus, TransactionStatus, +}; +use starknet_providers::{ + jsonrpc::HttpTransport, JsonRpcClient, MaybeUnknownErrorCode, Provider, ProviderError, + StarknetErrorWithMessage, +}; /// /// Unit test for `starknet_getTransactionStatus` -/// +/// /// purpose: call getTransactionStatus on non-existent transaction hash. /// fail case: non-existent transaction hash. -/// +/// #[rstest] #[tokio::test] async fn fail_invalid_transaction(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_transaction_status( - FieldElement::ZERO - ).await.err(); + let response_deoxys = deoxys + .get_transaction_status(FieldElement::ZERO) + .await + .err(); assert_matches!( response_deoxys, @@ -33,92 +39,96 @@ async fn fail_invalid_transaction(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.get_transaction_status( - FieldElement::from_hex_be(TRANSACTION_INVOKE).unwrap() - ).await.expect(ERR_DEOXYS); + let response_deoxys = deoxys + .get_transaction_status(FieldElement::from_hex_be(TRANSACTION_INVOKE).unwrap()) + .await + .expect(ERR_DEOXYS); - let response_pathfinder = pathfinder.get_transaction_status( - FieldElement::from_hex_be(TRANSACTION_INVOKE).unwrap() - ).await.expect(ERR_PATHFINDER); + let response_pathfinder = pathfinder + .get_transaction_status(FieldElement::from_hex_be(TRANSACTION_INVOKE).unwrap()) + .await + .expect(ERR_PATHFINDER); - assert_matches!( - response_deoxys, - TransactionStatus::AcceptedOnL1(_) - ); + assert_matches!(response_deoxys, TransactionStatus::AcceptedOnL1(_)); assert_eq!(response_deoxys, response_pathfinder); } /// /// Unit test for `starknet_getTransactionStatus` -/// +/// /// purpose: call getTransactionStatus on last transaction from the latest block. /// success case: transaction is marked as accepted on L2. -/// +/// #[rstest] #[tokio::test] async fn work_transaction_accepted_on_l2(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let transaction_count = deoxys.get_block_transaction_count( - BlockId::Tag(BlockTag::Latest) - ).await.expect(ERR_DEOXYS); + let transaction_count = deoxys + .get_block_transaction_count(BlockId::Tag(BlockTag::Latest)) + .await + .expect(ERR_DEOXYS); // last transaction of latest block - let transaction = deoxys.get_transaction_by_block_id_and_index( - BlockId::Tag(BlockTag::Latest), - transaction_count - 1, - ).await.expect(ERR_DEOXYS); - - let response_deoxys = deoxys.get_transaction_status( - transaction.transaction_hash() - ).await.expect(ERR_DEOXYS); - - let response_pathfinder = pathfinder.get_transaction_status( - transaction.transaction_hash() - ).await.expect(ERR_PATHFINDER); + let transaction = deoxys + .get_transaction_by_block_id_and_index( + BlockId::Tag(BlockTag::Latest), + transaction_count - 1, + ) + .await + .expect(ERR_DEOXYS); + + let response_deoxys = deoxys + .get_transaction_status(transaction.transaction_hash()) + .await + .expect(ERR_DEOXYS); + + let response_pathfinder = pathfinder + .get_transaction_status(transaction.transaction_hash()) + .await + .expect(ERR_PATHFINDER); // note that transaction is still accepted on L2 if it is reverted! - assert_matches!( - response_deoxys, - TransactionStatus::AcceptedOnL2(_) - ); + assert_matches!(response_deoxys, TransactionStatus::AcceptedOnL2(_)); assert_eq!(response_deoxys, response_pathfinder); } /// /// Unit test for `starknet_getTransactionStatus` -/// +/// /// purpose: call getTransactionStatus on reverted transaction. /// success case: transaction is marked as reverted on L1. -/// +/// #[rstest] #[tokio::test] async fn work_transaction_reverted(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.get_transaction_status( - FieldElement::from_hex_be(TRANSACTION_REVERTED).unwrap() - ).await.expect(ERR_DEOXYS); + let response_deoxys = deoxys + .get_transaction_status(FieldElement::from_hex_be(TRANSACTION_REVERTED).unwrap()) + .await + .expect(ERR_DEOXYS); - let response_pathfinder = pathfinder.get_transaction_status( - FieldElement::from_hex_be(TRANSACTION_REVERTED).unwrap() - ).await.expect(ERR_PATHFINDER); + let response_pathfinder = pathfinder + .get_transaction_status(FieldElement::from_hex_be(TRANSACTION_REVERTED).unwrap()) + .await + .expect(ERR_PATHFINDER); assert_matches!( response_deoxys, TransactionStatus::AcceptedOnL1(TransactionExecutionStatus::Reverted) ); assert_eq!(response_deoxys, response_pathfinder); -} \ No newline at end of file +} diff --git a/unit_tests/tests/test_syncing.rs b/unit_tests/tests/test_syncing.rs index 33adb13..9d51229 100644 --- a/unit_tests/tests/test_syncing.rs +++ b/unit_tests/tests/test_syncing.rs @@ -12,10 +12,10 @@ use std::collections::HashMap; /// /// Unit test for `starknet_syncing` -/// +/// /// purpose: returns starknet sync status /// success case: sync status matches between providers (NOT DETERMINISTIC) -/// +/// #[rstest] #[tokio::test] async fn syncing(clients: HashMap>) { From 9b30aa18689df4b901cf6418dd3c7ac5995cc4b2 Mon Sep 17 00:00:00 2001 From: Trantorian Date: Thu, 11 Jan 2024 13:31:39 +0000 Subject: [PATCH 10/10] refactor(fmt): :recycle: formatted code to pass CI --- macros/src/lib.rs | 15 +- unit_tests/src/constants.rs | 68 ++-- unit_tests/src/fixtures.rs | 17 +- unit_tests/src/lib.rs | 15 +- unit_tests/src/macros.rs | 2 +- unit_tests/tests/common.rs | 7 +- .../tests/test_block_hash_and_number.rs | 26 +- unit_tests/tests/test_block_number.rs | 21 +- unit_tests/tests/test_call.rs | 297 ++++++++++-------- unit_tests/tests/test_chain_id.rs | 4 +- unit_tests/tests/test_estimate_fee.rs | 35 ++- unit_tests/tests/test_estimate_message_fee.rs | 2 +- .../tests/test_get_block_transaction_count.rs | 1 - .../tests/test_get_block_with_tx_hashes.rs | 64 ++-- unit_tests/tests/test_get_class.rs | 8 +- unit_tests/tests/test_get_class_at.rs | 118 ++++--- unit_tests/tests/test_get_class_hash_at.rs | 91 +++--- unit_tests/tests/test_get_events.rs | 207 +++++++----- unit_tests/tests/test_get_nonce.rs | 123 +++++--- unit_tests/tests/test_get_state_update.rs | 2 +- unit_tests/tests/test_get_storage_at.rs | 90 +++--- ...t_get_transaction_by_block_id_and_index.rs | 175 ++++++----- .../tests/test_get_transaction_by_hash.rs | 100 +++--- unit_tests/tests/test_syncing.rs | 4 +- 24 files changed, 897 insertions(+), 595 deletions(-) diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 7588e1b..6a05815 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -1,6 +1,6 @@ use proc_macro::TokenStream; -use syn::{parse_macro_input, ItemFn}; use quote::{quote, ToTokens}; +use syn::{parse_macro_input, ItemFn}; #[proc_macro_attribute] pub fn logging(_: TokenStream, input: TokenStream) -> TokenStream { @@ -8,9 +8,14 @@ pub fn logging(_: TokenStream, input: TokenStream) -> TokenStream { input.block.stmts.insert( 0, - syn::parse(quote! { - env_logger::builder().is_test(true).try_init().err(); - }.into()).unwrap()); + syn::parse( + quote! { + env_logger::builder().is_test(true).try_init().err(); + } + .into(), + ) + .unwrap(), + ); input.into_token_stream().into() -} \ No newline at end of file +} diff --git a/unit_tests/src/constants.rs b/unit_tests/src/constants.rs index 7357869..e8efaec 100644 --- a/unit_tests/src/constants.rs +++ b/unit_tests/src/constants.rs @@ -14,107 +14,121 @@ pub const CONTRACT_KEY: &str = "0x00f920571b9f85bdd92a867cfdc73319d0f8836f0e69e0 /// /// Details concerning available methods can be found on [StarkScan](https://starkscan.co/contract/0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7#read-write-contract) /// -pub const STARKGATE_ETH_BRIDGE_ADDR: &str = "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"; +pub const STARKGATE_ETH_BRIDGE_ADDR: &str = + "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"; /// /// Contract address for Jediswap exchange. /// /// Details concerning available methods can be found on [StarkScan](https://starkscan.co/contract/0x041fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023#read-write-contract): /// -pub const JEDI_SWAP_ADDR: &str = "0x041fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023"; +pub const JEDI_SWAP_ADDR: &str = + "0x041fd22b238fa21cfcf5dd45a8548974d8263b3a531a60388411c5e230f97023"; /// /// Contract address for Starkgate USDC on Starknet. /// /// Details concerning this coin can be found on [StarkScan](https://starkscan.co/token/0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8): /// -pub const STARKGATE_USDC: &str = "0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8"; +pub const STARKGATE_USDC: &str = + "0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8"; /// /// Contract address fpr Starkgate Ether on Starknet. /// /// Detail concerning this coin can be found on [StarkScan](https://starkscan.co/token/0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7): /// -pub const STARKGATE_ETHER: &str = "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"; +pub const STARKGATE_ETHER: &str = + "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7"; /// /// Random ERC721 Starknet contract address. /// /// Details concerning this contract can be found on [StarkScan](https://starkscan.co/contract/0x07fa9a8eacb89fb6cd0c7fe557e71c42a4b181ba328a9a04958136e6469c4e00) /// -pub const CONTRACT_ERC721: &str = "0x07fa9a8eacb89fb6cd0c7fe557e71c42a4b181ba328a9a04958136e6469c4e00"; +pub const CONTRACT_ERC721: &str = + "0x07fa9a8eacb89fb6cd0c7fe557e71c42a4b181ba328a9a04958136e6469c4e00"; /// /// Random ERC20 Starknet contract address. /// /// Details concerning this contract can be found on [StarkScan](https://starkscan.co/contract/0x04a5fdce70877b77f03aea8a29259176f88d5bea9d0ad8c0118f5316425e6ba0) /// -pub const CONTRACT_ERC20: &str = "0x04a5fdce70877b77f03aea8a29259176f88d5bea9d0ad8c0118f5316425e6ba0"; +pub const CONTRACT_ERC20: &str = + "0x04a5fdce70877b77f03aea8a29259176f88d5bea9d0ad8c0118f5316425e6ba0"; /// /// Random ACCOUNT Starknet contract address. /// /// Details concerning this contract can be found on [StarkScan](https://starkscan.co/contract/0x05e1eee30e79b4f592f444132526b2e2c7f505698e888c659e5f5def5a458c1a) /// -pub const CONTRACT_ACCOUNT: &str = "0x05e1eee30e79b4f592f444132526b2e2c7f505698e888c659e5f5def5a458c1a"; +pub const CONTRACT_ACCOUNT: &str = + "0x05e1eee30e79b4f592f444132526b2e2c7f505698e888c659e5f5def5a458c1a"; /// /// Random PROXY ACCOUNT Starknet contract address. /// /// Details concerning this contract can be found on [StarkScan](https://starkscan.co/contract/0x05d7f4d55795b56ceb4dd93febe17954c7cfd5e15d7a79cb0cec067a713ac159) /// -pub const CONTRACT_ACCOUNT_PROXY: &str = "0x05d7f4d55795b56ceb4dd93febe17954c7cfd5e15d7a79cb0cec067a713ac159"; +pub const CONTRACT_ACCOUNT_PROXY: &str = + "0x05d7f4d55795b56ceb4dd93febe17954c7cfd5e15d7a79cb0cec067a713ac159"; /// /// Random legacy account using Cairo v0 -/// +/// /// Details concerning this contract can be found on [StarkScan](https://starkscan.co/contract/0x07076931c19d0ef52b847f9412c90a2ef999ff028f1005d2d069343061762fb7) -/// -pub const CONTRACT_LEGACY: &str = "0x07076931c19d0ef52b847f9412c90a2ef999ff028f1005d2d069343061762fb7"; +/// +pub const CONTRACT_LEGACY: &str = + "0x07076931c19d0ef52b847f9412c90a2ef999ff028f1005d2d069343061762fb7"; pub const BLOCK_LEGACY: u64 = 2891; /// /// INVOKE transaction accepted on L1, also transaction 1 at block 5000 -/// +/// /// Details concerning this transaction can be found on [StarkScan](https://starkscan.co/tx/0x0214840bad3099f95c40106097b8ef5fd16f06cb23efcdaec297398f77174597) -/// -pub const TRANSACTION_INVOKE: &str = "0x0214840bad3099f95c40106097b8ef5fd16f06cb23efcdaec297398f77174597"; +/// +pub const TRANSACTION_INVOKE: &str = + "0x0214840bad3099f95c40106097b8ef5fd16f06cb23efcdaec297398f77174597"; pub const TRANSACTION_INVOKE_INDEX: u64 = 1; pub const TRANSACTION_INVOKE_BLOCK_NB: u64 = 50000; /// /// L1_HANDLER transaction accepted on L1, also transaction 57 at block 50000 -/// +/// /// Details concerning this transaction can be found on [StarkScan](https://starkscan.co/tx/0x05ca6470c37e943b0ae172a11359f7a457054319e8ae8771af32a1f397c7c208) -/// -pub const TRANSACTION_L1_HANDLER: &str = "0x05ca6470c37e943b0ae172a11359f7a457054319e8ae8771af32a1f397c7c208"; +/// +pub const TRANSACTION_L1_HANDLER: &str = + "0x05ca6470c37e943b0ae172a11359f7a457054319e8ae8771af32a1f397c7c208"; pub const TRANSACTION_L1_HANDLER_INDEX: u64 = 57; pub const TRANSACTION_L1_HANDLER_BLOCK_NB: u64 = 50000; /// /// DECLARE transaction accepted on L1, also transaction 44 at block 49990 -/// +/// /// Details concerning this transaction can be found on [StarkScan](https://starkscan.co/tx/0x056c0723ef6cde62f589bbf7c5c40897b6e3d9c13e960c5e7f28276d8e9c3229) -/// -pub const TRANSACTION_DECLARE: &str = "0x056c0723ef6cde62f589bbf7c5c40897b6e3d9c13e960c5e7f28276d8e9c3229"; +/// +pub const TRANSACTION_DECLARE: &str = + "0x056c0723ef6cde62f589bbf7c5c40897b6e3d9c13e960c5e7f28276d8e9c3229"; pub const TRANSACTION_DECLARE_INDEX: u64 = 44; pub const TRANSACTION_DECLARE_BLOCK_NB: u64 = 49990; /// /// DEPLOY_ACCOUNT transaction accepted on L1, also transaction 0 at block 5000 -/// +/// /// Details concerning this transaction can be found on [StarkScan](https://starkscan.co/tx/0x0604e143591a6bff980f3141abdfc87f1ef3243785d251367cdaa7da5c337ba4) -/// -pub const TRANSACTION_DEPLOY_ACCOUNT: &str = "0x0604e143591a6bff980f3141abdfc87f1ef3243785d251367cdaa7da5c337ba4"; +/// +pub const TRANSACTION_DEPLOY_ACCOUNT: &str = + "0x0604e143591a6bff980f3141abdfc87f1ef3243785d251367cdaa7da5c337ba4"; pub const TRANSACTION_DEPLOY_ACCOUNT_INDEX: u64 = 0; pub const TRANSACTION_DEPLOY_ACCOUNT_BLOCK_NB: u64 = 50000; /// /// Random reverted Starknet transaction -/// +/// /// Details concerning this transaction can be found on [StarkScan](https://starkscan.co/tx/0x016ed559467c50c12f225f348ca8895d54b91a499ad6f856cb6086e317c120ca) -/// -pub const TRANSACTION_REVERTED: &str = "0x016ed559467c50c12f225f348ca8895d54b91a499ad6f856cb6086e317c120ca"; +/// +pub const TRANSACTION_REVERTED: &str = + "0x016ed559467c50c12f225f348ca8895d54b91a499ad6f856cb6086e317c120ca"; pub const ACCOUNT_CONTRACT: &str = ""; pub const TEST_CONTRACT_ADDRESS: &str = ""; @@ -129,4 +143,4 @@ pub const INVALID_ETHEREUM_ADDRESS: &str = ""; pub const SELECTOR_NAME: &str = ""; pub const ERR_DEOXYS: &str = "Error waiting for response from Deoxys client"; -pub const ERR_PATHFINDER: &str = "Error waiting for response from Pathfinder client"; \ No newline at end of file +pub const ERR_PATHFINDER: &str = "Error waiting for response from Pathfinder client"; diff --git a/unit_tests/src/fixtures.rs b/unit_tests/src/fixtures.rs index 2348073..7afd6b6 100644 --- a/unit_tests/src/fixtures.rs +++ b/unit_tests/src/fixtures.rs @@ -1,12 +1,12 @@ use std::collections::HashMap; use rstest::fixture; -use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport}; +use starknet_providers::{jsonrpc::HttpTransport, JsonRpcClient}; use url::Url; -use crate::TestConfig; use crate::constants::*; use crate::map; +use crate::TestConfig; #[fixture] pub fn config() -> TestConfig { @@ -16,21 +16,24 @@ pub fn config() -> TestConfig { #[fixture] pub fn deoxys(config: TestConfig) -> JsonRpcClient { JsonRpcClient::new(HttpTransport::new( - Url::parse(&config.deoxys).expect("Error parsing Deoxys node url") + Url::parse(&config.deoxys).expect("Error parsing Deoxys node url"), )) } #[fixture] pub fn pathfinder(config: TestConfig) -> JsonRpcClient { JsonRpcClient::new(HttpTransport::new( - Url::parse(&config.pathfinder).expect("Error parsing Deoxys node url") + Url::parse(&config.pathfinder).expect("Error parsing Deoxys node url"), )) } #[fixture] -pub fn clients(deoxys: JsonRpcClient, pathfinder: JsonRpcClient) -> HashMap> { - map!{ +pub fn clients( + deoxys: JsonRpcClient, + pathfinder: JsonRpcClient, +) -> HashMap> { + map! { String::from(DEOXYS) => deoxys, String::from(PATHFINDER) => pathfinder, } -} \ No newline at end of file +} diff --git a/unit_tests/src/lib.rs b/unit_tests/src/lib.rs index 7cc358c..4575435 100644 --- a/unit_tests/src/lib.rs +++ b/unit_tests/src/lib.rs @@ -4,10 +4,13 @@ use std::{fs::File, io::Read}; use constants::*; use serde::Deserialize; -use starknet_core::{types::{FieldElement, BroadcastedTransaction, BroadcastedInvokeTransaction}, utils::get_selector_from_name}; +use starknet_core::{ + types::{BroadcastedInvokeTransaction, BroadcastedTransaction, FieldElement}, + utils::get_selector_from_name, +}; -pub mod fixtures; pub mod constants; +pub mod fixtures; pub mod macros; #[derive(PartialEq, Debug, Deserialize)] @@ -31,13 +34,13 @@ impl TestConfig { } pub trait TransactionFactory { - fn new(nonce: Option) -> BroadcastedTransaction; + fn build(nonce: Option) -> BroadcastedTransaction; } pub struct OkTransactionFactory; impl TransactionFactory for OkTransactionFactory { - fn new(nonce: Option) -> BroadcastedTransaction { + fn build(nonce: Option) -> BroadcastedTransaction { BroadcastedTransaction::Invoke(BroadcastedInvokeTransaction { max_fee: FieldElement::ZERO, signature: vec![], @@ -57,7 +60,7 @@ impl TransactionFactory for OkTransactionFactory { pub struct BadTransactionFactory; impl TransactionFactory for BadTransactionFactory { - fn new(_: Option) -> BroadcastedTransaction { + fn build(_: Option) -> BroadcastedTransaction { BroadcastedTransaction::Invoke(BroadcastedInvokeTransaction { max_fee: FieldElement::default(), nonce: FieldElement::ZERO, @@ -67,4 +70,4 @@ impl TransactionFactory for BadTransactionFactory { is_query: true, }) } -} \ No newline at end of file +} diff --git a/unit_tests/src/macros.rs b/unit_tests/src/macros.rs index 15c2cab..8b3501b 100644 --- a/unit_tests/src/macros.rs +++ b/unit_tests/src/macros.rs @@ -10,4 +10,4 @@ macro_rules! map { m } }; -} \ No newline at end of file +} diff --git a/unit_tests/tests/common.rs b/unit_tests/tests/common.rs index 868ef65..219ff24 100644 --- a/unit_tests/tests/common.rs +++ b/unit_tests/tests/common.rs @@ -1,11 +1,10 @@ - /* Common imports used throughout all unit tests */ #[allow(unused_imports)] -pub use rstest::*; +pub use macros::*; #[allow(unused_imports)] -pub use unit_tests::fixtures::*; +pub use rstest::*; #[allow(unused_imports)] pub use unit_tests::constants::*; #[allow(unused_imports)] -pub use macros::*; \ No newline at end of file +pub use unit_tests::fixtures::*; diff --git a/unit_tests/tests/test_block_hash_and_number.rs b/unit_tests/tests/test_block_hash_and_number.rs index 7883d96..90153f1 100644 --- a/unit_tests/tests/test_block_hash_and_number.rs +++ b/unit_tests/tests/test_block_hash_and_number.rs @@ -3,24 +3,36 @@ use common::*; use std::collections::HashMap; -use starknet_providers::{jsonrpc::{HttpTransport, JsonRpcClient}, Provider}; +use starknet_providers::{ + jsonrpc::{HttpTransport, JsonRpcClient}, + Provider, +}; /// /// Unit test for `starknet_BlockHashAndNumber` -/// +/// /// purpose: get block hash and number on latest block. /// success case: retrieves correct block hash and number. -/// +/// #[rstest] #[tokio::test] async fn work_latest_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.block_hash_and_number().await.expect("Error waiting for response from Deoxys node"); - let response_pathfinder = pathfinder.block_hash_and_number().await.expect("Error waiting for response from Deoxys node"); - let response_expected = deoxys.block_number().await.expect("Error waiting for response from Deoxys node"); + let response_deoxys = deoxys + .block_hash_and_number() + .await + .expect("Error waiting for response from Deoxys node"); + let response_pathfinder = pathfinder + .block_hash_and_number() + .await + .expect("Error waiting for response from Deoxys node"); + let response_expected = deoxys + .block_number() + .await + .expect("Error waiting for response from Deoxys node"); assert_eq!(response_deoxys.block_number, response_expected); assert_eq!(response_deoxys, response_pathfinder); -} \ No newline at end of file +} diff --git a/unit_tests/tests/test_block_number.rs b/unit_tests/tests/test_block_number.rs index d175c7c..c7721d7 100644 --- a/unit_tests/tests/test_block_number.rs +++ b/unit_tests/tests/test_block_number.rs @@ -3,23 +3,32 @@ use common::*; use std::collections::HashMap; -use starknet_providers::{jsonrpc::{HttpTransport, JsonRpcClient}, Provider}; +use starknet_providers::{ + jsonrpc::{HttpTransport, JsonRpcClient}, + Provider, +}; /// /// Unit test for `starknet_blockNumber` -/// +/// /// purpose: call blockNumber on latest block. /// success case: must return valid non-zero block number. -/// +/// #[rstest] #[tokio::test] async fn work_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.block_number().await.expect("Deoxys : Error while getting the block number"); - let response_pathfinder = pathfinder.block_number().await.expect("RPC : Error while getting the block number"); + let response_deoxys = deoxys + .block_number() + .await + .expect("Deoxys : Error while getting the block number"); + let response_pathfinder = pathfinder + .block_number() + .await + .expect("RPC : Error while getting the block number"); assert!(response_deoxys > 0); assert_eq!(response_deoxys, response_pathfinder); -} \ No newline at end of file +} diff --git a/unit_tests/tests/test_call.rs b/unit_tests/tests/test_call.rs index f64ebd4..832ce3e 100644 --- a/unit_tests/tests/test_call.rs +++ b/unit_tests/tests/test_call.rs @@ -1,16 +1,22 @@ #![feature(assert_matches)] mod common; -use std::{collections::HashMap, assert_matches::assert_matches}; +use std::{assert_matches::assert_matches, collections::HashMap}; use common::*; use starknet::macros::short_string; -use starknet_core::{types::{FunctionCall, BlockTag, BlockId, FieldElement, StarknetError}, utils::get_selector_from_name}; -use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider, ProviderError, StarknetErrorWithMessage, MaybeUnknownErrorCode}; +use starknet_core::{ + types::{BlockId, BlockTag, FieldElement, FunctionCall, StarknetError}, + utils::get_selector_from_name, +}; +use starknet_providers::{ + jsonrpc::HttpTransport, JsonRpcClient, MaybeUnknownErrorCode, Provider, ProviderError, + StarknetErrorWithMessage, +}; /// /// Unit test for `starknet_call` -/// +/// /// purpose: function request `name` to StarkGate ETH bridge contract /// fail case: invalid block /// @@ -19,14 +25,17 @@ use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider, Provid async fn fail_non_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.call( - FunctionCall { - contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), - entry_point_selector: get_selector_from_name("name").unwrap(), - calldata: vec![] - }, - BlockId::Hash(FieldElement::ZERO) - ).await.err(); + let response_deoxys = deoxys + .call( + FunctionCall { + contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), + entry_point_selector: get_selector_from_name("name").unwrap(), + calldata: vec![], + }, + BlockId::Hash(FieldElement::ZERO), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -39,7 +48,7 @@ async fn fail_non_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.call( - FunctionCall { - contract_address: FieldElement::ZERO, - entry_point_selector: get_selector_from_name("name").unwrap(), - calldata: vec![] - }, - BlockId::Tag(BlockTag::Latest) - ).await.err(); + let response_deoxys = deoxys + .call( + FunctionCall { + contract_address: FieldElement::ZERO, + entry_point_selector: get_selector_from_name("name").unwrap(), + calldata: vec![], + }, + BlockId::Tag(BlockTag::Latest), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -68,23 +80,28 @@ async fn fail_non_existing_contract(clients: HashMap>) { +async fn fail_invalid_contract_entry_point_selector( + clients: HashMap>, +) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.call( - FunctionCall { - contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), - entry_point_selector: FieldElement::ZERO, - calldata: vec![] - }, - BlockId::Tag(BlockTag::Latest) - ).await.err(); + let response_deoxys = deoxys + .call( + FunctionCall { + contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), + entry_point_selector: FieldElement::ZERO, + calldata: vec![], + }, + BlockId::Tag(BlockTag::Latest), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -97,7 +114,7 @@ async fn fail_invalid_contract_entry_point_selector(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.call( - FunctionCall { - contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), - entry_point_selector: get_selector_from_name("balanceOf").unwrap(), - calldata: vec![] - }, - BlockId::Tag(BlockTag::Latest) - ).await.err(); + let response_deoxys = deoxys + .call( + FunctionCall { + contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), + entry_point_selector: get_selector_from_name("balanceOf").unwrap(), + calldata: vec![], + }, + BlockId::Tag(BlockTag::Latest), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -126,7 +146,7 @@ async fn fail_missing_contract_call_data(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.call( - FunctionCall { - contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), - entry_point_selector: get_selector_from_name("balanceOf").unwrap(), - calldata: vec![ - FieldElement::ZERO - ] - }, - BlockId::Tag(BlockTag::Latest) - ).await.expect("Error waiting for response from Deoxys node"); - - assert_eq!(response_deoxys, vec![FieldElement::ZERO, FieldElement::ZERO]); + let response_deoxys = deoxys + .call( + FunctionCall { + contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), + entry_point_selector: get_selector_from_name("balanceOf").unwrap(), + calldata: vec![FieldElement::ZERO], + }, + BlockId::Tag(BlockTag::Latest), + ) + .await + .expect("Error waiting for response from Deoxys node"); + + assert_eq!( + response_deoxys, + vec![FieldElement::ZERO, FieldElement::ZERO] + ); } /// /// Unit test for `starknet_call` -/// +/// /// purpose: function request `name` to StarkGate ETH bridge contract /// fail case: too many arguments in call data /// @@ -160,16 +184,17 @@ async fn fail_invalid_contract_call_data(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.call( - FunctionCall { - contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), - entry_point_selector: get_selector_from_name("name").unwrap(), - calldata: vec![ - FieldElement::ZERO - ] - }, - BlockId::Tag(BlockTag::Latest) - ).await.err(); + let response_deoxys = deoxys + .call( + FunctionCall { + contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), + entry_point_selector: get_selector_from_name("name").unwrap(), + calldata: vec![FieldElement::ZERO], + }, + BlockId::Tag(BlockTag::Latest), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -182,7 +207,7 @@ async fn fail_too_many_call_data(clients: HashMap let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.call( - FunctionCall { - contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), - entry_point_selector: get_selector_from_name("name").unwrap(), - calldata: vec![] - }, - BlockId::Tag(BlockTag::Latest) - ).await.expect("Error waiting for response from Deoxys node"); - - let response_pathfinder = pathfinder.call( - FunctionCall { - contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), - entry_point_selector: get_selector_from_name("name").unwrap(), - calldata: vec![] - }, - BlockId::Tag(BlockTag::Latest) - ).await.expect("Error waiting for response from Pathfinder node"); + let response_deoxys = deoxys + .call( + FunctionCall { + contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), + entry_point_selector: get_selector_from_name("name").unwrap(), + calldata: vec![], + }, + BlockId::Tag(BlockTag::Latest), + ) + .await + .expect("Error waiting for response from Deoxys node"); + + let response_pathfinder = pathfinder + .call( + FunctionCall { + contract_address: FieldElement::from_hex_be(STARKGATE_ETH_BRIDGE_ADDR).unwrap(), + entry_point_selector: get_selector_from_name("name").unwrap(), + calldata: vec![], + }, + BlockId::Tag(BlockTag::Latest), + ) + .await + .expect("Error waiting for response from Pathfinder node"); let response_expected = short_string!("Ether"); @@ -218,7 +249,7 @@ async fn work_correct_call(clients: HashMap /// /// Unit test for `starknet_call` -/// +/// /// purpose: function request `balanceOf` to StarkGate ETH bridge contract /// success case: must return non-zero balance /// @@ -228,27 +259,29 @@ async fn work_correct_call_with_args(clients: HashMap>) { diff --git a/unit_tests/tests/test_estimate_fee.rs b/unit_tests/tests/test_estimate_fee.rs index 771a815..2d7846a 100644 --- a/unit_tests/tests/test_estimate_fee.rs +++ b/unit_tests/tests/test_estimate_fee.rs @@ -4,10 +4,13 @@ mod common; use common::*; use starknet_core::types::{BlockId, BlockTag, FieldElement, StarknetError}; -use starknet_providers::{jsonrpc::{HttpTransport, JsonRpcClient}, MaybeUnknownErrorCode, Provider, ProviderError, StarknetErrorWithMessage,}; -use unit_tests::{OkTransactionFactory, TransactionFactory, BadTransactionFactory}; +use starknet_providers::{ + jsonrpc::{HttpTransport, JsonRpcClient}, + MaybeUnknownErrorCode, Provider, ProviderError, StarknetErrorWithMessage, +}; use std::assert_matches::assert_matches; use std::collections::HashMap; +use unit_tests::{BadTransactionFactory, OkTransactionFactory, TransactionFactory}; #[rstest] #[tokio::test] @@ -15,7 +18,7 @@ use std::collections::HashMap; async fn fail_non_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let ok_invoke_transaction = OkTransactionFactory::new(Some(FieldElement::ZERO)); + let ok_invoke_transaction = OkTransactionFactory::build(Some(FieldElement::ZERO)); assert_matches!( deoxys.estimate_fee(&vec![ok_invoke_transaction], BlockId::Hash(FieldElement::ZERO)).await, @@ -26,11 +29,13 @@ async fn fail_non_existing_block(clients: HashMap>) { +async fn fail_if_one_txn_cannot_be_executed( + clients: HashMap>, +) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let bad_invoke_transaction = BadTransactionFactory::new(None); + let bad_invoke_transaction = BadTransactionFactory::build(None); let result_deoxys = deoxys .estimate_fee( @@ -56,13 +61,13 @@ async fn works_ok(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let ok_deoxys_invoke = OkTransactionFactory::new(Some(FieldElement::ZERO)); - let ok_deoxys_invoke_1 = OkTransactionFactory::new(Some(FieldElement::ONE)); - let ok_deoxys_invoke_2 = OkTransactionFactory::new(Some(FieldElement::TWO)); + let ok_deoxys_invoke = OkTransactionFactory::build(Some(FieldElement::ZERO)); + let ok_deoxys_invoke_1 = OkTransactionFactory::build(Some(FieldElement::ONE)); + let ok_deoxys_invoke_2 = OkTransactionFactory::build(Some(FieldElement::TWO)); - let ok_pathfinder_invoke = OkTransactionFactory::new(Some(FieldElement::ZERO)); - let ok_pathfinder_invoke_1 = OkTransactionFactory::new(Some(FieldElement::ONE)); - let ok_pathfinder_invoke_2 = OkTransactionFactory::new(Some(FieldElement::TWO)); + let ok_pathfinder_invoke = OkTransactionFactory::build(Some(FieldElement::ZERO)); + let ok_pathfinder_invoke_1 = OkTransactionFactory::build(Some(FieldElement::ONE)); + let ok_pathfinder_invoke_2 = OkTransactionFactory::build(Some(FieldElement::TWO)); let deoxys_estimates = deoxys .estimate_fee( @@ -74,11 +79,15 @@ async fn works_ok(clients: HashMap>) { let pathfinder_estimates = pathfinder .estimate_fee( - &vec![ok_pathfinder_invoke, ok_pathfinder_invoke_1, ok_pathfinder_invoke_2], + &vec![ + ok_pathfinder_invoke, + ok_pathfinder_invoke_1, + ok_pathfinder_invoke_2, + ], BlockId::Tag(BlockTag::Latest), ) .await .unwrap(); assert_eq!(deoxys_estimates, pathfinder_estimates); -} \ No newline at end of file +} diff --git a/unit_tests/tests/test_estimate_message_fee.rs b/unit_tests/tests/test_estimate_message_fee.rs index 8a177b3..b2c61ac 100644 --- a/unit_tests/tests/test_estimate_message_fee.rs +++ b/unit_tests/tests/test_estimate_message_fee.rs @@ -146,4 +146,4 @@ async fn estimate_message_fee_works_ok(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_block_with_tx_hashes(BlockId::Hash(FieldElement::ZERO)).await.err(); + let response_deoxys = deoxys + .get_block_with_tx_hashes(BlockId::Hash(FieldElement::ZERO)) + .await + .err(); assert_matches!( - response_deoxys, + response_deoxys, Some(ProviderError::StarknetError(StarknetErrorWithMessage { message: _, code: MaybeUnknownErrorCode::Known(StarknetError::BlockNotFound) - } - ))); + })) + ); } /// /// Unit test for `starknet_get_block_with_tx_hashes` -/// +/// /// purpose: call getBlockWithTxHashes on latest validated block. /// success case: retrieves valid block. -/// +/// #[rstest] #[tokio::test] async fn work_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.get_block_with_tx_hashes(BlockId::Tag(BlockTag::Latest)).await + let response_deoxys = deoxys + .get_block_with_tx_hashes(BlockId::Tag(BlockTag::Latest)) + .await .expect("Error waiting for response from Deoxys node"); - let response_pathfinder = pathfinder.get_block_with_tx_hashes(BlockId::Tag(BlockTag::Latest)).await + let response_pathfinder = pathfinder + .get_block_with_tx_hashes(BlockId::Tag(BlockTag::Latest)) + .await .expect("Error waiting for response from Deoxys node"); let block_deoxys = match response_deoxys { MaybePendingBlockWithTxHashes::Block(block) => block, - MaybePendingBlockWithTxHashes::PendingBlock(_) => panic!("Expected block, got pending block"), + MaybePendingBlockWithTxHashes::PendingBlock(_) => { + panic!("Expected block, got pending block") + } }; let block_pathfinder = match response_pathfinder { MaybePendingBlockWithTxHashes::Block(block) => block, - MaybePendingBlockWithTxHashes::PendingBlock(_) => panic!("Expected block, got pending block"), + MaybePendingBlockWithTxHashes::PendingBlock(_) => { + panic!("Expected block, got pending block") + } }; assert_eq!(block_deoxys, block_pathfinder); } /// /// Unit test for `starknet_get_block_with_tx_hashes` -/// +/// /// purpose: call getBlockWithTxHashes on pending block. /// success case: retrieves valid pending block. -/// +/// /// Note that this can fail at the last moments of a block being validated!!! -/// +/// #[rstest] #[tokio::test] #[ignore = "Pending fails some times when called on the cusp of being accepted, need virtual sequencer"] @@ -75,13 +89,15 @@ async fn work_pending_block(clients: HashMap panic!("Expected pending block, got block"), @@ -93,4 +109,4 @@ async fn work_pending_block(clients: HashMap>) { +async fn work_ok_retrieving_class_for_contract_version_0( + clients: HashMap>, +) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; @@ -78,7 +80,9 @@ async fn work_ok_retrieving_class_for_contract_version_0(clients: HashMap>) { +async fn work_ok_retrieving_class_for_contract_version_1( + clients: HashMap>, +) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; diff --git a/unit_tests/tests/test_get_class_at.rs b/unit_tests/tests/test_get_class_at.rs index 014c2dd..4515fad 100644 --- a/unit_tests/tests/test_get_class_at.rs +++ b/unit_tests/tests/test_get_class_at.rs @@ -1,84 +1,100 @@ #![feature(assert_matches)] mod common; -use std::{collections::HashMap, assert_matches::assert_matches, io::Read}; +use std::{assert_matches::assert_matches, collections::HashMap, io::Read}; use common::*; use flate2::read::GzDecoder; -use starknet_core::types::{FieldElement, BlockId, StarknetError, BlockTag, ContractClass, contract::legacy::LegacyProgram}; -use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider, StarknetErrorWithMessage, ProviderError, MaybeUnknownErrorCode}; +use starknet_core::types::{ + contract::legacy::LegacyProgram, BlockId, BlockTag, ContractClass, FieldElement, StarknetError, +}; +use starknet_providers::{ + jsonrpc::HttpTransport, JsonRpcClient, MaybeUnknownErrorCode, Provider, ProviderError, + StarknetErrorWithMessage, +}; /// /// unit test for `starknet_get_class_at` -/// +/// /// purpose: gets contract class for inexistent block. /// fail case: invalid block address. -/// +/// #[rstest] #[tokio::test] async fn fail_non_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_class_at( - BlockId::Hash(FieldElement::ZERO), - FieldElement::from_hex_be(CONTRACT_ACCOUNT).unwrap() - ).await.err(); + let response_deoxys = deoxys + .get_class_at( + BlockId::Hash(FieldElement::ZERO), + FieldElement::from_hex_be(CONTRACT_ACCOUNT).unwrap(), + ) + .await + .err(); assert_matches!( - response_deoxys, + response_deoxys, Some(ProviderError::StarknetError(StarknetErrorWithMessage { message: _, code: MaybeUnknownErrorCode::Known(StarknetError::BlockNotFound) - } - ))); + })) + ); } /// /// unit test for `starknet_get_class_at` -/// +/// /// purpose: gets contract class for inexistent contract. /// fail case: invalid contract address. -/// +/// #[rstest] #[tokio::test] async fn fail_non_existing_contract(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_class_at( - BlockId::Tag(BlockTag::Latest), - FieldElement::ZERO - ).await.err(); + let response_deoxys = deoxys + .get_class_at(BlockId::Tag(BlockTag::Latest), FieldElement::ZERO) + .await + .err(); assert_matches!( - response_deoxys, + response_deoxys, Some(ProviderError::StarknetError(StarknetErrorWithMessage { message: _, code: MaybeUnknownErrorCode::Known(StarknetError::ContractNotFound) - } - ))); + })) + ); } /// /// unit test for `starknet_get_class_at` -/// +/// /// purpose: gets legacy contract and extracts it's data. -/// success case: should retrieve contract and decompress it to a valid json string. -/// +/// success case: should retrieve contract and decompress it to a valid json string. +/// #[rstest] #[tokio::test] -async fn work_contract_v0(clients: HashMap>) -> anyhow::Result<()> { +async fn work_contract_v0( + clients: HashMap>, +) -> anyhow::Result<()> { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.get_class_at( - BlockId::Number(BLOCK_LEGACY), - FieldElement::from_hex_be(CONTRACT_LEGACY).unwrap() - ).await.expect("Error waiting for response from Deoxys client"); - - let response_pathfinder = pathfinder.get_class_at( - BlockId::Number(BLOCK_LEGACY), - FieldElement::from_hex_be(CONTRACT_LEGACY).unwrap() - ).await.expect("Error waiting for response from Pathfinder client"); + let response_deoxys = deoxys + .get_class_at( + BlockId::Number(BLOCK_LEGACY), + FieldElement::from_hex_be(CONTRACT_LEGACY).unwrap(), + ) + .await + .expect("Error waiting for response from Deoxys client"); + + let response_pathfinder = pathfinder + .get_class_at( + BlockId::Number(BLOCK_LEGACY), + FieldElement::from_hex_be(CONTRACT_LEGACY).unwrap(), + ) + .await + .expect("Error waiting for response from Pathfinder client"); let mut json_deoxys: String = String::new(); match &response_deoxys { @@ -89,7 +105,7 @@ async fn work_contract_v0(clients: HashMap> // makes sure json_deoxys is a valid json string serde_json::from_str::(&json_deoxys)?; - }, + } } let mut json_pathfinder = String::new(); @@ -98,7 +114,7 @@ async fn work_contract_v0(clients: HashMap> ContractClass::Legacy(contract) => { let mut decoder = GzDecoder::new(&contract.program[..]); decoder.read_to_string(&mut json_pathfinder)?; - }, + } } assert_eq!(json_deoxys, json_pathfinder); @@ -109,25 +125,31 @@ async fn work_contract_v0(clients: HashMap> /// /// unit test for `starknet_get_class_at` -/// +/// /// purpose: gets Cairo v1 contract and extracts it's data. /// success case: should retrieve contract correctly. -/// +/// #[rstest] #[tokio::test] async fn work_contract_v1(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.get_class_at( - BlockId::Tag(BlockTag::Latest), - FieldElement::from_hex_be(CONTRACT_ACCOUNT).unwrap() - ).await.expect("Error waiting for response from Deoxys client"); - - let response_pathfinder = pathfinder.get_class_at( - BlockId::Tag(BlockTag::Latest), - FieldElement::from_hex_be(CONTRACT_ACCOUNT).unwrap() - ).await.expect("Error waiting for response from Pathfinder client"); + let response_deoxys = deoxys + .get_class_at( + BlockId::Tag(BlockTag::Latest), + FieldElement::from_hex_be(CONTRACT_ACCOUNT).unwrap(), + ) + .await + .expect("Error waiting for response from Deoxys client"); + + let response_pathfinder = pathfinder + .get_class_at( + BlockId::Tag(BlockTag::Latest), + FieldElement::from_hex_be(CONTRACT_ACCOUNT).unwrap(), + ) + .await + .expect("Error waiting for response from Pathfinder client"); assert_eq!(response_deoxys, response_pathfinder); -} \ No newline at end of file +} diff --git a/unit_tests/tests/test_get_class_hash_at.rs b/unit_tests/tests/test_get_class_hash_at.rs index 26891d1..a597985 100644 --- a/unit_tests/tests/test_get_class_hash_at.rs +++ b/unit_tests/tests/test_get_class_hash_at.rs @@ -5,24 +5,30 @@ use common::*; use std::{assert_matches::assert_matches, collections::HashMap}; -use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider, ProviderError, StarknetErrorWithMessage, MaybeUnknownErrorCode}; -use starknet_core::types::{BlockId, FieldElement, StarknetError, BlockTag}; +use starknet_core::types::{BlockId, BlockTag, FieldElement, StarknetError}; +use starknet_providers::{ + jsonrpc::HttpTransport, JsonRpcClient, MaybeUnknownErrorCode, Provider, ProviderError, + StarknetErrorWithMessage, +}; /// /// Unit test for `starknet_getClassHashAt` -/// +/// /// purpose: call getClassHashAt on invalid block. /// fail case: invalid block hash. -/// +/// #[rstest] #[tokio::test] async fn fail_non_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_class_hash_at( - BlockId::Hash(FieldElement::ZERO), - FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap() - ).await.err(); + let response_deoxys = deoxys + .get_class_hash_at( + BlockId::Hash(FieldElement::ZERO), + FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap(), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -35,19 +41,22 @@ async fn fail_non_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_class_hash_at( - BlockId::Tag(BlockTag::Latest), - FieldElement::from_hex_be(INVALID_CONTRACT_ADDR).unwrap() - ).await.err(); + let response_deoxys = deoxys + .get_class_hash_at( + BlockId::Tag(BlockTag::Latest), + FieldElement::from_hex_be(INVALID_CONTRACT_ADDR).unwrap(), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -60,48 +69,60 @@ async fn fail_non_existing_contract(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let class_hash_deoxys = deoxys.get_class_hash_at( - BlockId::Tag(BlockTag::Latest), - FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap() - ).await.expect("Error waiting for response from Deoxys node"); - let class_hash_pathfinder = pathfinder.get_class_hash_at( - BlockId::Tag(BlockTag::Latest), - FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap() - ).await.expect("Error waiting for response from Pathfinder node"); + let class_hash_deoxys = deoxys + .get_class_hash_at( + BlockId::Tag(BlockTag::Latest), + FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap(), + ) + .await + .expect("Error waiting for response from Deoxys node"); + let class_hash_pathfinder = pathfinder + .get_class_hash_at( + BlockId::Tag(BlockTag::Latest), + FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap(), + ) + .await + .expect("Error waiting for response from Pathfinder node"); assert_eq!(class_hash_deoxys, class_hash_pathfinder); } /// /// Unit test for `starknet_getClassHashAt` -/// +/// /// purpose: call getClassHashAt on pending block. /// success case: retrieve valid class hash. -/// +/// #[rstest] #[tokio::test] async fn work_block_pending(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let class_hash_deoxys = deoxys.get_class_hash_at( - BlockId::Tag(BlockTag::Pending), - FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap() - ).await.expect("Error waiting for response from Deoxys node"); - let class_hash_pathfinder = pathfinder.get_class_hash_at( - BlockId::Tag(BlockTag::Pending), - FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap() - ).await.expect("Error waiting for response from Pathfinder node"); + let class_hash_deoxys = deoxys + .get_class_hash_at( + BlockId::Tag(BlockTag::Pending), + FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap(), + ) + .await + .expect("Error waiting for response from Deoxys node"); + let class_hash_pathfinder = pathfinder + .get_class_hash_at( + BlockId::Tag(BlockTag::Pending), + FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap(), + ) + .await + .expect("Error waiting for response from Pathfinder node"); assert_eq!(class_hash_deoxys, class_hash_pathfinder); -} \ No newline at end of file +} diff --git a/unit_tests/tests/test_get_events.rs b/unit_tests/tests/test_get_events.rs index ee7e959..d72bd6c 100644 --- a/unit_tests/tests/test_get_events.rs +++ b/unit_tests/tests/test_get_events.rs @@ -1,36 +1,39 @@ #![feature(assert_matches)] mod common; -use std::{sync::Arc, assert_matches::assert_matches}; +use std::{assert_matches::assert_matches, sync::Arc}; use anyhow::anyhow; use common::*; -use starknet::macros::{selector, felt_hex}; -use starknet_core::types::{EventFilter, BlockId, FieldElement, EventsPage}; -use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider, ProviderError, StarknetErrorWithMessage, MaybeUnknownErrorCode}; +use starknet::macros::{felt_hex, selector}; +use starknet_core::types::{BlockId, EventFilter, EventsPage, FieldElement}; +use starknet_providers::{ + jsonrpc::HttpTransport, JsonRpcClient, MaybeUnknownErrorCode, Provider, ProviderError, + StarknetErrorWithMessage, +}; use tokio::task::JoinSet; /// /// Test for RPC call `starknet_getEvents`. -/// +/// /// *What is an EVENT* -/// +/// /// An Event in the context of the Starknet blockchain is called a Cairo event. It can be emitted by smart /// contract as a side effect marking steps in execution or internal state. These in turn can be observed /// from the outside and reacted upon. Events are marked by a *key* and can also store *data. -/// +/// /// Ex: an authentication contract might emit an event upon successfully login in a user, or an error event /// in case of invalid data. -/// +/// /// More documentation can be found in [the Starknet Book](https://www.starknetjs.com/docs/guides/events/) -/// +/// /// /// Unit test for `starknet_getEvents` -/// +/// /// purpose: call getEvents on an invalid block number. /// fail case: invalid block number (invalid param). -/// +/// #[rstest] #[tokio::test] #[logging] @@ -39,7 +42,9 @@ async fn fail_invalid_block_number(deoxys: JsonRpcClient) { let block_nu: u64 = u64::MAX; let block_range: u64 = 100; - let response_deoxys = get_events(&deoxys, &keys, block_nu, block_range).await.err(); + let response_deoxys = get_events(&deoxys, &keys, block_nu, block_range) + .await + .err(); assert_matches!( response_deoxys, @@ -52,10 +57,10 @@ async fn fail_invalid_block_number(deoxys: JsonRpcClient) { /// /// Unit test for `starknet_getEvents` -/// +/// /// purpose: call getEvents on an invalid event selector. /// fail case: invalid event selector. -/// +/// #[rstest] #[tokio::test] #[logging] @@ -64,18 +69,23 @@ async fn fail_invalid_keys(deoxys: JsonRpcClient) { let block_nu: u64 = 50000; let block_range: u64 = 100; - let response_deoxys = get_events(&deoxys, &keys, block_nu, block_range).await.expect(ERR_DEOXYS); + let response_deoxys = get_events(&deoxys, &keys, block_nu, block_range) + .await + .expect(ERR_DEOXYS); - log::info!("Events at block {block_nu}: {}", serde_json::to_string_pretty(&response_deoxys).unwrap()); + log::info!( + "Events at block {block_nu}: {}", + serde_json::to_string_pretty(&response_deoxys).unwrap() + ); assert_eq!(response_deoxys.events.len(), 0); } /// /// Unit test for `starknet_getEvents` -/// +/// /// purpose: call getEvents on an invalid event selector. /// fail case: invalid event selector. -/// +/// #[rstest] #[tokio::test] #[logging] @@ -84,7 +94,9 @@ async fn fail_invalid_block_range(deoxys: JsonRpcClient) { let block_nu: u64 = 50000; let block_range: u64 = 0; - let response_deoxys = get_events(&deoxys, &keys, block_nu, block_range).await.err(); + let response_deoxys = get_events(&deoxys, &keys, block_nu, block_range) + .await + .err(); // for some reason a block range of 0 results in an internal error assert_matches!( @@ -98,23 +110,34 @@ async fn fail_invalid_block_range(deoxys: JsonRpcClient) { /// /// Unit test for `starknet_getEvents` -/// +/// /// purpose: call getEvents on a valid block with a no selector. /// success case: retrieves the first 100 events of that block. -/// +/// #[rstest] #[tokio::test] #[logging] -async fn work_valid_call_no_selector(deoxys: JsonRpcClient, pathfinder: JsonRpcClient) { +async fn work_valid_call_no_selector( + deoxys: JsonRpcClient, + pathfinder: JsonRpcClient, +) { let keys: Vec> = vec![vec![selector!("transaction_executed")]]; let block_nu: u64 = 50000; - let block_hash: FieldElement = felt_hex!("0x053315a56543737cd1b2dc40c60e84d03a9b10d712c9b29f488dc979f0cd56bd"); + let block_hash: FieldElement = + felt_hex!("0x053315a56543737cd1b2dc40c60e84d03a9b10d712c9b29f488dc979f0cd56bd"); let block_range: u64 = 100; - let response_deoxys = get_events(&deoxys, &keys, block_nu, block_range).await.expect(ERR_DEOXYS); - let response_pathfinder = get_events(&pathfinder, &keys, block_nu, block_range).await.expect(ERR_PATHFINDER); + let response_deoxys = get_events(&deoxys, &keys, block_nu, block_range) + .await + .expect(ERR_DEOXYS); + let response_pathfinder = get_events(&pathfinder, &keys, block_nu, block_range) + .await + .expect(ERR_PATHFINDER); - log::info!("Events at block {block_nu}: {}", serde_json::to_string_pretty(&response_deoxys).unwrap()); + log::info!( + "Events at block {block_nu}: {}", + serde_json::to_string_pretty(&response_deoxys).unwrap() + ); assert_eq!(response_deoxys.events.len(), block_range as usize); assert_eq!(response_deoxys, response_pathfinder); deep_check_events(deoxys, response_deoxys, keys, block_hash, block_nu).await; @@ -122,48 +145,73 @@ async fn work_valid_call_no_selector(deoxys: JsonRpcClient, pathf /// /// Unit test for `starknet_getEvents` -/// +/// /// purpose: call getEvents on a valid block with a single selector. /// success case: valid events format, events point to valid transactions. -/// +/// #[rstest] #[tokio::test] #[logging] -async fn work_valid_call_single_selector(deoxys: JsonRpcClient, pathfinder: JsonRpcClient) { +async fn work_valid_call_single_selector( + deoxys: JsonRpcClient, + pathfinder: JsonRpcClient, +) { // event type to retrieve let keys: Vec> = vec![vec![selector!("transaction_executed")]]; let block_nu: u64 = 50000; - let block_hash: FieldElement = felt_hex!("0x053315a56543737cd1b2dc40c60e84d03a9b10d712c9b29f488dc979f0cd56bd"); + let block_hash: FieldElement = + felt_hex!("0x053315a56543737cd1b2dc40c60e84d03a9b10d712c9b29f488dc979f0cd56bd"); let block_range: u64 = 100; - let response_deoxys = get_events(&deoxys, &keys, block_nu, block_range).await.expect(ERR_DEOXYS); - let response_pathfinder = get_events(&pathfinder, &keys, block_nu, block_range).await.expect(ERR_PATHFINDER); + let response_deoxys = get_events(&deoxys, &keys, block_nu, block_range) + .await + .expect(ERR_DEOXYS); + let response_pathfinder = get_events(&pathfinder, &keys, block_nu, block_range) + .await + .expect(ERR_PATHFINDER); - log::info!("Events at block {block_nu}: {}", serde_json::to_string_pretty(&response_deoxys).unwrap()); + log::info!( + "Events at block {block_nu}: {}", + serde_json::to_string_pretty(&response_deoxys).unwrap() + ); assert_eq!(response_deoxys, response_pathfinder); deep_check_events(deoxys, response_deoxys, keys, block_hash, block_nu).await; } /// /// Unit test for `starknet_getEvents` -/// +/// /// purpose: call getEvents on a valid block with a multiple selectors. -/// success case: retrieves all events matching the selector in the first 100 events of that block +/// success case: retrieves all events matching the selector in the first 100 events of that block /// + valid event format and valid transactions. -/// +/// #[rstest] #[tokio::test] #[logging] -async fn work_valid_call_multiple_selector(deoxys: JsonRpcClient, pathfinder: JsonRpcClient) { - let keys: Vec> = vec![vec![selector!("transaction_executed"), selector!("account_created")]]; +async fn work_valid_call_multiple_selector( + deoxys: JsonRpcClient, + pathfinder: JsonRpcClient, +) { + let keys: Vec> = vec![vec![ + selector!("transaction_executed"), + selector!("account_created"), + ]]; let block_nu: u64 = 50000; - let block_hash: FieldElement = felt_hex!("0x053315a56543737cd1b2dc40c60e84d03a9b10d712c9b29f488dc979f0cd56bd"); + let block_hash: FieldElement = + felt_hex!("0x053315a56543737cd1b2dc40c60e84d03a9b10d712c9b29f488dc979f0cd56bd"); let block_range: u64 = 100; - let response_deoxys = get_events(&deoxys, &keys, block_nu, block_range).await.expect(ERR_DEOXYS); - let response_pathfinder = get_events(&pathfinder, &keys, block_nu, block_range).await.expect(ERR_PATHFINDER); + let response_deoxys = get_events(&deoxys, &keys, block_nu, block_range) + .await + .expect(ERR_DEOXYS); + let response_pathfinder = get_events(&pathfinder, &keys, block_nu, block_range) + .await + .expect(ERR_PATHFINDER); - log::info!("Events at block {block_nu}: {}", serde_json::to_string_pretty(&response_deoxys).unwrap()); + log::info!( + "Events at block {block_nu}: {}", + serde_json::to_string_pretty(&response_deoxys).unwrap() + ); assert_eq!(response_deoxys, response_pathfinder); deep_check_events(deoxys, response_deoxys, keys, block_hash, block_nu).await; } @@ -172,35 +220,37 @@ async fn get_events( client: &JsonRpcClient, keys: &Vec>, block_nu: u64, - block_range: u64 + block_range: u64, ) -> Result { - client.get_events( - EventFilter { - // getEvents is a applied through a filter - // this filter consists of a block range... - from_block: Some(BlockId::Number(block_nu)), - to_block: Some(BlockId::Number(block_nu)), - // a beginning contract address... - address: None, - // and keys used to filter out events. Keys can include a hash of the event - // and even event return values for further filtering - keys: Some(keys.clone()) - }, - // in cases were a first search does not yield enough results, a continuation key - // can be used to keep searching from the point of the last getEvent search - None, - // chunk size marks the number of events to look through and filter - // this means that there cannot be more than chunk_size events returned by getEvents - block_range - ).await + client + .get_events( + EventFilter { + // getEvents is a applied through a filter + // this filter consists of a block range... + from_block: Some(BlockId::Number(block_nu)), + to_block: Some(BlockId::Number(block_nu)), + // a beginning contract address... + address: None, + // and keys used to filter out events. Keys can include a hash of the event + // and even event return values for further filtering + keys: Some(keys.clone()), + }, + // in cases were a first search does not yield enough results, a continuation key + // can be used to keep searching from the point of the last getEvent search + None, + // chunk size marks the number of events to look through and filter + // this means that there cannot be more than chunk_size events returned by getEvents + block_range, + ) + .await } async fn deep_check_events( deoxys: JsonRpcClient, - response_deoxys: EventsPage, + response_deoxys: EventsPage, keys: Vec>, block_hash: FieldElement, - block_nu: u64 + block_nu: u64, ) { let mut task_set = JoinSet::new(); let arc_deoxys = Arc::new(deoxys); @@ -218,7 +268,10 @@ async fn deep_check_events( assert_eq!(clone_event.keys.len(), 1); // first key is always event key // further keys cannot be predicted without knowing event contract - assert!(clone_keys.first().unwrap().contains(clone_event.keys.first().unwrap())); + assert!(clone_keys + .first() + .unwrap() + .contains(clone_event.keys.first().unwrap())); assert_eq!(clone_event.block_hash, block_hash); assert_eq!(clone_event.block_number, block_nu); assert_ne!(clone_event.data.len(), 0); @@ -226,23 +279,29 @@ async fn deep_check_events( anyhow::Ok(()) }); - // to make sure the associated transactions retrieved by getEvents exists, we make - // a call to the blockchain to retrieve them. This is an io-bound operation + // to make sure the associated transactions retrieved by getEvents exists, we make + // a call to the blockchain to retrieve them. This is an io-bound operation // and benefits greatly of parallelization through tokio // - // Warning: this test is fast enough as to be rate-limited on certain nodes, + // Warning: this test is fast enough as to be rate-limited on certain nodes, // make sure you are running your own instance or using a provider with rate limiting disabled let clone_event = Arc::clone(&arc_event); let clone_deoxys = Arc::clone(&arc_deoxys); task_set.spawn(async move { - match clone_deoxys.get_transaction_by_hash(clone_event.transaction_hash).await { + match clone_deoxys + .get_transaction_by_hash(clone_event.transaction_hash) + .await + { Ok(_) => anyhow::Ok(()), - Err(e) => Err(anyhow!("{e}: transaction 0x{:064x} does not exist", clone_event.transaction_hash)), + Err(e) => Err(anyhow!( + "{e}: transaction 0x{:064x} does not exist", + clone_event.transaction_hash + )), } }); } - // waits for all tasks to complete. Errors occur if an assertion fails + // waits for all tasks to complete. Errors occur if an assertion fails // or transaction cannot be found with getTransactionByHash while let Some(res) = task_set.join_next().await { match res { @@ -252,12 +311,12 @@ async fn deep_check_events( task_set.abort_all(); panic!("{}", e); } - }, + } // thread execution error, stop all threads (invalid assertion or tokio error) Err(e) => { task_set.abort_all(); panic!("JoinError: {}", e); - }, + } } } -} \ No newline at end of file +} diff --git a/unit_tests/tests/test_get_nonce.rs b/unit_tests/tests/test_get_nonce.rs index dda1f91..bd42fa2 100644 --- a/unit_tests/tests/test_get_nonce.rs +++ b/unit_tests/tests/test_get_nonce.rs @@ -1,31 +1,34 @@ #![feature(assert_matches)] mod common; -use std::{collections::HashMap, assert_matches::assert_matches}; +use std::{assert_matches::assert_matches, collections::HashMap}; use common::*; -use starknet_core::types::{BlockId, FieldElement, StarknetError, BlockTag}; -use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider, ProviderError, StarknetErrorWithMessage, MaybeUnknownErrorCode}; +use starknet_core::types::{BlockId, BlockTag, FieldElement, StarknetError}; +use starknet_providers::{ + jsonrpc::HttpTransport, JsonRpcClient, MaybeUnknownErrorCode, Provider, ProviderError, + StarknetErrorWithMessage, +}; /// /// Test for RPC call starknet_getNonce. -/// +/// /// *What is a NONCE?* -/// +/// /// A nonce is a unique identifier attributed to a starknet transaction, guaranteeing it cannot be added to a /// block multiple times. As of writing this, Starknet nonces are **sequential**, which is to say that the nonce /// in a new transaction must follow that of the previous transaction from the same account. The concept of a /// nonce on Starknet should not be confused with how nonces are used on other blockchains such as Bitcoin as /// part of proof-of-work. -/// +/// /// More documentation can be found in [the Starknet Book](https://book.starknet.io/ch03-01-01-transactions-lifecycle.html#nonces-in-starknet) -/// +/// /// [Trantorian1](https://github.com/trantorian1) 09-01-2024 /// /// /// Unit test for `starknet_getNonce` -/// +/// /// purpose: call getNonce on invalid block. /// fail case: invalid block. /// @@ -34,10 +37,13 @@ use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider, Provid async fn fail_non_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_nonce( - BlockId::Hash(FieldElement::ZERO), - FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap() - ).await.err(); + let response_deoxys = deoxys + .get_nonce( + BlockId::Hash(FieldElement::ZERO), + FieldElement::from_hex_be(STARKGATE_ETH_CONTRACT_ADDR).unwrap(), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -50,7 +56,7 @@ async fn fail_non_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_nonce( - BlockId::Tag(BlockTag::Latest), - FieldElement::from_hex_be(INVALID_CONTRACT_ADDR).unwrap() - ).await.err(); + let response_deoxys = deoxys + .get_nonce( + BlockId::Tag(BlockTag::Latest), + FieldElement::from_hex_be(INVALID_CONTRACT_ADDR).unwrap(), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -78,7 +87,7 @@ async fn fail_non_existing_contract(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_nonce( - BlockId::Tag(BlockTag::Latest), - FieldElement::from_hex_be(CONTRACT_ERC721).unwrap() - ).await.expect("Error waiting for response from Deoxys node"); + let response_deoxys = deoxys + .get_nonce( + BlockId::Tag(BlockTag::Latest), + FieldElement::from_hex_be(CONTRACT_ERC721).unwrap(), + ) + .await + .expect("Error waiting for response from Deoxys node"); assert_eq!(response_deoxys, FieldElement::ZERO); } /// /// Unit test for `starknet_getNonce` -/// +/// /// purpose: call getNonce on ERC20 contract. /// success case: must return a nonce of 0. /// @@ -106,17 +118,20 @@ async fn work_erc721_contract(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_nonce( - BlockId::Tag(BlockTag::Latest), - FieldElement::from_hex_be(CONTRACT_ERC20).unwrap() - ).await.expect("Error waiting for response from Deoxys node"); + let response_deoxys = deoxys + .get_nonce( + BlockId::Tag(BlockTag::Latest), + FieldElement::from_hex_be(CONTRACT_ERC20).unwrap(), + ) + .await + .expect("Error waiting for response from Deoxys node"); assert_eq!(response_deoxys, FieldElement::ZERO); } /// /// Unit test for `starknet_getNonce` -/// +/// /// purpose: call getNonce on account contract. /// success case: must return a non-zero nonce. /// @@ -126,15 +141,21 @@ async fn work_account_contract(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_storage_at( - FieldElement::from_hex_be(CONTRACT_ADDR).unwrap(), - FieldElement::from_hex_be(CONTRACT_KEY).unwrap(), - BlockId::Hash(FieldElement::ZERO) - ).await.err(); + let response_deoxys = deoxys + .get_storage_at( + FieldElement::from_hex_be(CONTRACT_ADDR).unwrap(), + FieldElement::from_hex_be(CONTRACT_KEY).unwrap(), + BlockId::Hash(FieldElement::ZERO), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -37,20 +43,23 @@ async fn fail_non_existing_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_storage_at( - FieldElement::ZERO, - FieldElement::from_hex_be(CONTRACT_KEY).unwrap(), - BlockId::Tag(BlockTag::Latest) - ).await.err(); + let response_deoxys = deoxys + .get_storage_at( + FieldElement::ZERO, + FieldElement::from_hex_be(CONTRACT_KEY).unwrap(), + BlockId::Tag(BlockTag::Latest), + ) + .await + .err(); assert_matches!( response_deoxys, @@ -63,30 +72,33 @@ async fn fail_non_existing_contract(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_storage_at( - FieldElement::from_hex_be(CONTRACT_ADDR).unwrap(), - FieldElement::ZERO, - BlockId::Tag(BlockTag::Latest) - ).await.expect("Error waiting for response from Deoxys client"); + let response_deoxys = deoxys + .get_storage_at( + FieldElement::from_hex_be(CONTRACT_ADDR).unwrap(), + FieldElement::ZERO, + BlockId::Tag(BlockTag::Latest), + ) + .await + .expect("Error waiting for response from Deoxys client"); assert_eq!(response_deoxys, FieldElement::ZERO); } /// /// Unit test for `starknet_getStorageAt` -/// +/// /// purpose: call getStorageAt with valid arguments. /// success case: retrieve valid storage. -/// +/// #[rstest] #[tokio::test] async fn work_get_storage(clients: HashMap>) { @@ -94,16 +106,22 @@ async fn work_get_storage(clients: HashMap> let pathfinder = &clients[PATHFINDER]; // TODO: get contract key from field name - let response_deoxys = deoxys.get_storage_at( - FieldElement::from_hex_be(CONTRACT_ADDR).unwrap(), - FieldElement::from_hex_be(CONTRACT_KEY).unwrap(), - BlockId::Tag(BlockTag::Latest) - ).await.expect("Error waiting for response from Deoxys client"); - let response_pathfinder = pathfinder.get_storage_at( - FieldElement::from_hex_be(CONTRACT_ADDR).unwrap(), - FieldElement::from_hex_be(CONTRACT_KEY).unwrap(), - BlockId::Tag(BlockTag::Latest) - ).await.expect("Error waiting for response from Pathfinder client"); + let response_deoxys = deoxys + .get_storage_at( + FieldElement::from_hex_be(CONTRACT_ADDR).unwrap(), + FieldElement::from_hex_be(CONTRACT_KEY).unwrap(), + BlockId::Tag(BlockTag::Latest), + ) + .await + .expect("Error waiting for response from Deoxys client"); + let response_pathfinder = pathfinder + .get_storage_at( + FieldElement::from_hex_be(CONTRACT_ADDR).unwrap(), + FieldElement::from_hex_be(CONTRACT_KEY).unwrap(), + BlockId::Tag(BlockTag::Latest), + ) + .await + .expect("Error waiting for response from Pathfinder client"); assert_eq!(response_deoxys, response_pathfinder); -} \ No newline at end of file +} diff --git a/unit_tests/tests/test_get_transaction_by_block_id_and_index.rs b/unit_tests/tests/test_get_transaction_by_block_id_and_index.rs index e911f76..c207583 100644 --- a/unit_tests/tests/test_get_transaction_by_block_id_and_index.rs +++ b/unit_tests/tests/test_get_transaction_by_block_id_and_index.rs @@ -1,27 +1,30 @@ #![feature(assert_matches)] mod common; -use std::{collections::HashMap, assert_matches::assert_matches}; +use std::{assert_matches::assert_matches, collections::HashMap}; use common::*; -use starknet_core::types::{FieldElement, BlockId, StarknetError}; -use starknet_providers::{JsonRpcClient, jsonrpc::HttpTransport, Provider, StarknetErrorWithMessage, ProviderError, MaybeUnknownErrorCode}; +use starknet_core::types::{BlockId, FieldElement, StarknetError}; +use starknet_providers::{ + jsonrpc::HttpTransport, JsonRpcClient, MaybeUnknownErrorCode, Provider, ProviderError, + StarknetErrorWithMessage, +}; /// /// Unit test for `starknet_getTransactionByBlockIdAndIndex` -/// +/// /// purpose: call on non-existent block. /// fail case: invalid block -/// +/// #[rstest] #[tokio::test] async fn fail_non_existent_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_transaction_by_block_id_and_index( - BlockId::Hash(FieldElement::ZERO), - 0 - ).await.err(); + let response_deoxys = deoxys + .get_transaction_by_block_id_and_index(BlockId::Hash(FieldElement::ZERO), 0) + .await + .err(); assert_matches!( response_deoxys, @@ -34,19 +37,19 @@ async fn fail_non_existent_block(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_transaction_by_block_id_and_index( - BlockId::Number(5000), - 389 - ).await.err(); + let response_deoxys = deoxys + .get_transaction_by_block_id_and_index(BlockId::Number(5000), 389) + .await + .err(); assert_matches!( response_deoxys, @@ -59,10 +62,10 @@ async fn fail_non_existent_block_index(clients: HashMap>) { @@ -70,20 +73,27 @@ async fn work_deploy_invoke(clients: HashMap>) { @@ -102,20 +112,27 @@ async fn work_deploy_l1_handler(clients: HashMap>) { @@ -134,20 +151,27 @@ async fn work_deploy_declare(clients: HashMap>) { @@ -166,21 +190,28 @@ async fn work_deploy_account(clients: HashMap>) { let deoxys = &clients[DEOXYS]; - let response_deoxys = deoxys.get_transaction_by_hash( - FieldElement::ZERO - ).await.err(); - + let response_deoxys = deoxys + .get_transaction_by_hash(FieldElement::ZERO) + .await + .err(); + assert_matches!( - response_deoxys, + response_deoxys, Some(ProviderError::StarknetError(StarknetErrorWithMessage { message: _, code: MaybeUnknownErrorCode::Known(StarknetError::TransactionHashNotFound) - } - ))); + })) + ); } /// /// Unit test for `starknet_getTransactionByHash` -/// +/// /// purpose: call getTransactionHash on INVOKE transaction. /// success case: retrieve correct INVOKE transaction. -/// +/// #[rstest] #[tokio::test] async fn work_transaction_invoke(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.get_transaction_by_hash( - FieldElement::from_hex_be(TRANSACTION_INVOKE).unwrap() - ).await.expect("Error waiting for response from Deoxys node"); + let response_deoxys = deoxys + .get_transaction_by_hash(FieldElement::from_hex_be(TRANSACTION_INVOKE).unwrap()) + .await + .expect("Error waiting for response from Deoxys node"); - let response_pathfinder = pathfinder.get_transaction_by_hash( - FieldElement::from_hex_be(TRANSACTION_INVOKE).unwrap() - ).await.expect("Error waiting for response from Pathfinder node"); + let response_pathfinder = pathfinder + .get_transaction_by_hash(FieldElement::from_hex_be(TRANSACTION_INVOKE).unwrap()) + .await + .expect("Error waiting for response from Pathfinder node"); assert_matches!(response_deoxys, Transaction::Invoke(_)); assert_eq!(response_deoxys, response_pathfinder); @@ -57,23 +63,25 @@ async fn work_transaction_invoke(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.get_transaction_by_hash( - FieldElement::from_hex_be(TRANSACTION_L1_HANDLER).unwrap() - ).await.expect("Error waiting for response from Deoxys node"); + let response_deoxys = deoxys + .get_transaction_by_hash(FieldElement::from_hex_be(TRANSACTION_L1_HANDLER).unwrap()) + .await + .expect("Error waiting for response from Deoxys node"); - let response_pathfinder = pathfinder.get_transaction_by_hash( - FieldElement::from_hex_be(TRANSACTION_L1_HANDLER).unwrap() - ).await.expect("Error waiting for response from Pathfinder node"); + let response_pathfinder = pathfinder + .get_transaction_by_hash(FieldElement::from_hex_be(TRANSACTION_L1_HANDLER).unwrap()) + .await + .expect("Error waiting for response from Pathfinder node"); assert_matches!(response_deoxys, Transaction::L1Handler(_)); assert_eq!(response_deoxys, response_pathfinder); @@ -81,23 +89,25 @@ async fn work_transaction_l1_handler(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.get_transaction_by_hash( - FieldElement::from_hex_be(TRANSACTION_DECLARE).unwrap() - ).await.expect("Error waiting for response from Deoxys node"); + let response_deoxys = deoxys + .get_transaction_by_hash(FieldElement::from_hex_be(TRANSACTION_DECLARE).unwrap()) + .await + .expect("Error waiting for response from Deoxys node"); - let response_pathfinder = pathfinder.get_transaction_by_hash( - FieldElement::from_hex_be(TRANSACTION_DECLARE).unwrap() - ).await.expect("Error waiting for response from Pathfinder node"); + let response_pathfinder = pathfinder + .get_transaction_by_hash(FieldElement::from_hex_be(TRANSACTION_DECLARE).unwrap()) + .await + .expect("Error waiting for response from Pathfinder node"); assert_matches!(response_deoxys, Transaction::Declare(_)); assert_eq!(response_deoxys, response_pathfinder); @@ -107,24 +117,26 @@ async fn work_transaction_declare(clients: HashMap>) { let deoxys = &clients[DEOXYS]; let pathfinder = &clients[PATHFINDER]; - let response_deoxys = deoxys.get_transaction_by_hash( - FieldElement::from_hex_be(TRANSACTION_DEPLOY_ACCOUNT).unwrap() - ).await.expect("Error waiting for response from Deoxys node"); + let response_deoxys = deoxys + .get_transaction_by_hash(FieldElement::from_hex_be(TRANSACTION_DEPLOY_ACCOUNT).unwrap()) + .await + .expect("Error waiting for response from Deoxys node"); - let response_pathfinder = pathfinder.get_transaction_by_hash( - FieldElement::from_hex_be(TRANSACTION_DEPLOY_ACCOUNT).unwrap() - ).await.expect("Error waiting for response from Pathfinder node"); + let response_pathfinder = pathfinder + .get_transaction_by_hash(FieldElement::from_hex_be(TRANSACTION_DEPLOY_ACCOUNT).unwrap()) + .await + .expect("Error waiting for response from Pathfinder node"); assert_matches!(response_deoxys, Transaction::DeployAccount(_)); assert_eq!(response_deoxys, response_pathfinder); -} \ No newline at end of file +} diff --git a/unit_tests/tests/test_syncing.rs b/unit_tests/tests/test_syncing.rs index 33adb13..9d51229 100644 --- a/unit_tests/tests/test_syncing.rs +++ b/unit_tests/tests/test_syncing.rs @@ -12,10 +12,10 @@ use std::collections::HashMap; /// /// Unit test for `starknet_syncing` -/// +/// /// purpose: returns starknet sync status /// success case: sync status matches between providers (NOT DETERMINISTIC) -/// +/// #[rstest] #[tokio::test] async fn syncing(clients: HashMap>) {