1- //! Integration tests for the Starknet gRPC server.
2- //!
3- //! All tests share a single TestNode instance that is created and migrated
4- //! once. Each test creates its own gRPC and JSON-RPC clients to the shared
5- //! node, then compares results from both endpoints.
6- //!
7- //! Requirements:
8- //! - `git`, `asdf`, `scarb`, and `sozo` must be installed and properly configured
9- //! - Run with `cargo nextest run -p katana-grpc --features grpc`
10-
11- use std:: net:: SocketAddr ;
12- use std:: sync:: OnceLock ;
13-
141use katana_grpc:: proto:: {
152 BlockHashAndNumberRequest , BlockNumberRequest , BlockTag , ChainIdRequest , GetBlockRequest ,
163 GetClassAtRequest , GetClassHashAtRequest , GetEventsRequest , GetNonceRequest ,
@@ -25,65 +12,25 @@ use starknet::providers::jsonrpc::HttpTransport;
2512use starknet:: providers:: { JsonRpcClient , Provider , Url } ;
2613use tonic:: Request ;
2714
28- /// Shared test context initialized once for all tests.
29- struct TestContext {
30- /// Keeps the tokio runtime (and thus the node) alive for the test suite.
31- _runtime : tokio:: runtime:: Runtime ,
32- grpc_addr : SocketAddr ,
33- rpc_addr : SocketAddr ,
34- genesis_address : Felt ,
35- chain_id : Felt ,
36- }
37-
38- static TEST_CTX : OnceLock < TestContext > = OnceLock :: new ( ) ;
39-
40- fn test_context ( ) -> & ' static TestContext {
41- TEST_CTX . get_or_init ( || {
42- // Spawn initialization on a separate thread to avoid "cannot start a
43- // runtime from within a runtime" when called from #[tokio::test].
44- std:: thread:: spawn ( || {
45- let runtime = tokio:: runtime:: Builder :: new_multi_thread ( ) . enable_all ( ) . build ( ) . unwrap ( ) ;
46-
47- let ( grpc_addr, rpc_addr, genesis_address, chain_id) = runtime. block_on ( async {
48- let node = TestNode :: new ( ) . await ;
49- node. migrate_spawn_and_move ( ) . await . expect ( "migration failed" ) ;
50-
51- let grpc_addr = * node. grpc_addr ( ) . expect ( "grpc not enabled" ) ;
52- let rpc_addr = * node. rpc_addr ( ) ;
53- let ( address, _) = node
54- . backend ( )
55- . chain_spec
56- . genesis ( )
57- . accounts ( )
58- . next ( )
59- . expect ( "must have genesis account" ) ;
60- let genesis_address: Felt = ( * address) . into ( ) ;
61- let chain_id = node. backend ( ) . chain_spec . id ( ) . id ( ) ;
62-
63- // Leak the node so the servers stay alive for the entire test suite.
64- std:: mem:: forget ( node) ;
65-
66- ( grpc_addr, rpc_addr, genesis_address, chain_id)
67- } ) ;
68-
69- TestContext { _runtime : runtime, grpc_addr, rpc_addr, genesis_address, chain_id }
70- } )
71- . join ( )
72- . expect ( "test context initialization thread panicked" )
73- } )
74- }
15+ async fn setup ( ) -> ( TestNode , GrpcClient , JsonRpcClient < HttpTransport > ) {
16+ let node = TestNode :: new_with_spawn_and_move_db ( ) . await ;
7517
76- async fn setup ( ) -> ( GrpcClient , JsonRpcClient < HttpTransport > ) {
77- let ctx = test_context ( ) ;
78-
79- let grpc = GrpcClient :: connect ( format ! ( "http://{}" , ctx. grpc_addr) )
18+ let grpc_addr = * node. grpc_addr ( ) . expect ( "grpc not enabled" ) ;
19+ let grpc = GrpcClient :: connect ( format ! ( "http://{grpc_addr}" ) )
8020 . await
8121 . expect ( "failed to connect to gRPC server" ) ;
8222
83- let url = Url :: parse ( & format ! ( "http://{}" , ctx. rpc_addr) ) . expect ( "failed to parse url" ) ;
23+ let rpc_addr = * node. rpc_addr ( ) ;
24+ let url = Url :: parse ( & format ! ( "http://{rpc_addr}" ) ) . expect ( "failed to parse url" ) ;
8425 let rpc = JsonRpcClient :: new ( HttpTransport :: new ( url) ) ;
8526
86- ( grpc, rpc)
27+ ( node, grpc, rpc)
28+ }
29+
30+ fn genesis_address ( node : & TestNode ) -> Felt {
31+ let ( address, _) =
32+ node. backend ( ) . chain_spec . genesis ( ) . accounts ( ) . next ( ) . expect ( "must have genesis account" ) ;
33+ ( * address) . into ( )
8734}
8835
8936fn felt_to_proto ( felt : Felt ) -> katana_grpc:: proto:: Felt {
@@ -108,8 +55,9 @@ fn grpc_block_id_latest() -> Option<katana_grpc::proto::BlockId> {
10855
10956#[ tokio:: test]
11057async fn test_chain_id ( ) {
111- let ( mut grpc, rpc) = setup ( ) . await ;
112- let ctx = test_context ( ) ;
58+ let ( node, mut grpc, rpc) = setup ( ) . await ;
59+
60+ let chain_id = node. backend ( ) . chain_spec . id ( ) . id ( ) ;
11361
11462 let rpc_chain_id = rpc. chain_id ( ) . await . expect ( "rpc chain_id failed" ) ;
11563
@@ -120,13 +68,13 @@ async fn test_chain_id() {
12068 . into_inner ( )
12169 . chain_id ;
12270
123- assert_eq ! ( rpc_chain_id, ctx . chain_id) ;
124- assert_eq ! ( grpc_chain_id, format!( "{:#x}" , ctx . chain_id) ) ;
71+ assert_eq ! ( rpc_chain_id, chain_id) ;
72+ assert_eq ! ( grpc_chain_id, format!( "{:#x}" , chain_id) ) ;
12573}
12674
12775#[ tokio:: test]
12876async fn test_block_number ( ) {
129- let ( mut grpc, rpc) = setup ( ) . await ;
77+ let ( _node , mut grpc, rpc) = setup ( ) . await ;
13078
13179 let rpc_block_number = rpc. block_number ( ) . await . expect ( "rpc block_number failed" ) ;
13280
@@ -143,7 +91,7 @@ async fn test_block_number() {
14391
14492#[ tokio:: test]
14593async fn test_block_hash_and_number ( ) {
146- let ( mut grpc, rpc) = setup ( ) . await ;
94+ let ( _node , mut grpc, rpc) = setup ( ) . await ;
14795
14896 let rpc_result = rpc. block_hash_and_number ( ) . await . expect ( "rpc block_hash_and_number failed" ) ;
14997
@@ -160,7 +108,7 @@ async fn test_block_hash_and_number() {
160108
161109#[ tokio:: test]
162110async fn test_get_block_with_txs ( ) {
163- let ( mut grpc, rpc) = setup ( ) . await ;
111+ let ( _node , mut grpc, rpc) = setup ( ) . await ;
164112
165113 let rpc_block = rpc. get_block_with_txs ( BlockId :: Number ( 0 ) ) . await . expect ( "rpc failed" ) ;
166114
@@ -191,7 +139,7 @@ async fn test_get_block_with_txs() {
191139
192140#[ tokio:: test]
193141async fn test_get_block_with_tx_hashes ( ) {
194- let ( mut grpc, rpc) = setup ( ) . await ;
142+ let ( _node , mut grpc, rpc) = setup ( ) . await ;
195143
196144 let rpc_block = rpc. get_block_with_tx_hashes ( BlockId :: Number ( 0 ) ) . await . expect ( "rpc failed" ) ;
197145
@@ -230,7 +178,7 @@ async fn test_get_block_with_tx_hashes() {
230178
231179#[ tokio:: test]
232180async fn test_get_block_with_txs_latest ( ) {
233- let ( mut grpc, rpc) = setup ( ) . await ;
181+ let ( _node , mut grpc, rpc) = setup ( ) . await ;
234182
235183 let rpc_block =
236184 rpc. get_block_with_txs ( BlockId :: Tag ( StarknetBlockTag :: Latest ) ) . await . expect ( "rpc failed" ) ;
@@ -258,18 +206,18 @@ async fn test_get_block_with_txs_latest() {
258206
259207#[ tokio:: test]
260208async fn test_get_class_at ( ) {
261- let ( mut grpc, rpc) = setup ( ) . await ;
262- let ctx = test_context ( ) ;
209+ let ( node , mut grpc, rpc) = setup ( ) . await ;
210+ let address = genesis_address ( & node ) ;
263211
264212 let rpc_class = rpc
265- . get_class_at ( BlockId :: Tag ( StarknetBlockTag :: Latest ) , ctx . genesis_address )
213+ . get_class_at ( BlockId :: Tag ( StarknetBlockTag :: Latest ) , address )
266214 . await
267215 . expect ( "rpc get_class_at failed" ) ;
268216
269217 let grpc_result = grpc
270218 . get_class_at ( Request :: new ( GetClassAtRequest {
271219 block_id : grpc_block_id_latest ( ) ,
272- contract_address : Some ( felt_to_proto ( ctx . genesis_address ) ) ,
220+ contract_address : Some ( felt_to_proto ( address ) ) ,
273221 } ) )
274222 . await
275223 . expect ( "grpc get_class_at failed" )
@@ -291,18 +239,18 @@ async fn test_get_class_at() {
291239
292240#[ tokio:: test]
293241async fn test_get_class_hash_at ( ) {
294- let ( mut grpc, rpc) = setup ( ) . await ;
295- let ctx = test_context ( ) ;
242+ let ( node , mut grpc, rpc) = setup ( ) . await ;
243+ let address = genesis_address ( & node ) ;
296244
297245 let rpc_class_hash = rpc
298- . get_class_hash_at ( BlockId :: Tag ( StarknetBlockTag :: Latest ) , ctx . genesis_address )
246+ . get_class_hash_at ( BlockId :: Tag ( StarknetBlockTag :: Latest ) , address )
299247 . await
300248 . expect ( "rpc get_class_hash_at failed" ) ;
301249
302250 let grpc_result = grpc
303251 . get_class_hash_at ( Request :: new ( GetClassHashAtRequest {
304252 block_id : grpc_block_id_latest ( ) ,
305- contract_address : Some ( felt_to_proto ( ctx . genesis_address ) ) ,
253+ contract_address : Some ( felt_to_proto ( address ) ) ,
306254 } ) )
307255 . await
308256 . expect ( "grpc get_class_hash_at failed" )
@@ -314,18 +262,18 @@ async fn test_get_class_hash_at() {
314262
315263#[ tokio:: test]
316264async fn test_get_storage_at ( ) {
317- let ( mut grpc, rpc) = setup ( ) . await ;
318- let ctx = test_context ( ) ;
265+ let ( node , mut grpc, rpc) = setup ( ) . await ;
266+ let address = genesis_address ( & node ) ;
319267
320268 let rpc_value = rpc
321- . get_storage_at ( ctx . genesis_address , Felt :: ZERO , BlockId :: Tag ( StarknetBlockTag :: Latest ) )
269+ . get_storage_at ( address , Felt :: ZERO , BlockId :: Tag ( StarknetBlockTag :: Latest ) )
322270 . await
323271 . expect ( "rpc get_storage_at failed" ) ;
324272
325273 let grpc_result = grpc
326274 . get_storage_at ( Request :: new ( GetStorageAtRequest {
327275 block_id : grpc_block_id_latest ( ) ,
328- contract_address : Some ( felt_to_proto ( ctx . genesis_address ) ) ,
276+ contract_address : Some ( felt_to_proto ( address ) ) ,
329277 key : Some ( felt_to_proto ( Felt :: ZERO ) ) ,
330278 } ) )
331279 . await
@@ -338,18 +286,18 @@ async fn test_get_storage_at() {
338286
339287#[ tokio:: test]
340288async fn test_get_nonce ( ) {
341- let ( mut grpc, rpc) = setup ( ) . await ;
342- let ctx = test_context ( ) ;
289+ let ( node , mut grpc, rpc) = setup ( ) . await ;
290+ let address = genesis_address ( & node ) ;
343291
344292 let rpc_nonce = rpc
345- . get_nonce ( BlockId :: Tag ( StarknetBlockTag :: Latest ) , ctx . genesis_address )
293+ . get_nonce ( BlockId :: Tag ( StarknetBlockTag :: Latest ) , address )
346294 . await
347295 . expect ( "rpc get_nonce failed" ) ;
348296
349297 let grpc_result = grpc
350298 . get_nonce ( Request :: new ( GetNonceRequest {
351299 block_id : grpc_block_id_latest ( ) ,
352- contract_address : Some ( felt_to_proto ( ctx . genesis_address ) ) ,
300+ contract_address : Some ( felt_to_proto ( address ) ) ,
353301 } ) )
354302 . await
355303 . expect ( "grpc get_nonce failed" )
@@ -362,7 +310,7 @@ async fn test_get_nonce() {
362310
363311#[ tokio:: test]
364312async fn test_spec_version ( ) {
365- let ( mut grpc, rpc) = setup ( ) . await ;
313+ let ( _node , mut grpc, rpc) = setup ( ) . await ;
366314
367315 let rpc_version = rpc. spec_version ( ) . await . expect ( "rpc spec_version failed" ) ;
368316
@@ -378,7 +326,7 @@ async fn test_spec_version() {
378326
379327#[ tokio:: test]
380328async fn test_syncing ( ) {
381- let ( mut grpc, rpc) = setup ( ) . await ;
329+ let ( _node , mut grpc, rpc) = setup ( ) . await ;
382330
383331 let rpc_syncing = rpc. syncing ( ) . await . expect ( "rpc syncing failed" ) ;
384332
@@ -403,7 +351,7 @@ async fn test_syncing() {
403351
404352#[ tokio:: test]
405353async fn test_get_block_transaction_count ( ) {
406- let ( mut grpc, rpc) = setup ( ) . await ;
354+ let ( _node , mut grpc, rpc) = setup ( ) . await ;
407355
408356 let rpc_count = rpc
409357 . get_block_transaction_count ( BlockId :: Number ( 0 ) )
@@ -424,7 +372,7 @@ async fn test_get_block_transaction_count() {
424372
425373#[ tokio:: test]
426374async fn test_get_state_update ( ) {
427- let ( mut grpc, rpc) = setup ( ) . await ;
375+ let ( _node , mut grpc, rpc) = setup ( ) . await ;
428376
429377 let rpc_state =
430378 rpc. get_state_update ( BlockId :: Number ( 0 ) ) . await . expect ( "rpc get_state_update failed" ) ;
@@ -461,7 +409,7 @@ async fn test_get_state_update() {
461409
462410#[ tokio:: test]
463411async fn test_get_events ( ) {
464- let ( mut grpc, rpc) = setup ( ) . await ;
412+ let ( _node , mut grpc, rpc) = setup ( ) . await ;
465413
466414 let rpc_events = rpc
467415 . get_events (
@@ -512,7 +460,7 @@ async fn test_get_events() {
512460
513461#[ tokio:: test]
514462async fn test_get_transaction_by_hash ( ) {
515- let ( mut grpc, rpc) = setup ( ) . await ;
463+ let ( _node , mut grpc, rpc) = setup ( ) . await ;
516464
517465 // Get a transaction hash from block 1
518466 let rpc_block =
@@ -548,7 +496,7 @@ async fn test_get_transaction_by_hash() {
548496
549497#[ tokio:: test]
550498async fn test_get_transaction_receipt ( ) {
551- let ( mut grpc, rpc) = setup ( ) . await ;
499+ let ( _node , mut grpc, rpc) = setup ( ) . await ;
552500
553501 // Get a transaction hash from block 1
554502 let rpc_block =
0 commit comments