Skip to content

Commit 71ade1b

Browse files
refactor(rpc): util for creating HttpClient (#88)
* refactor(rpc): util for creating `HttpClient` * fix(rpc): add missing client and cors features for jsonrpsee and tower-http Co-Authored-By: karii@cartridge.gg <evergreenkary@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
1 parent 8ee2d63 commit 71ade1b

File tree

8 files changed

+39
-36
lines changed

8 files changed

+39
-36
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/rpc/rpc/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ katana-tasks.workspace = true
2323
anyhow.workspace = true
2424
futures.workspace = true
2525
http.workspace = true
26-
jsonrpsee = { workspace = true, features = [ "server" ] }
26+
jsonrpsee = { workspace = true, features = [ "server", "client" ] }
2727
metrics.workspace = true
2828
serde_json.workspace = true
2929
starknet.workspace = true
3030
thiserror.workspace = true
3131
tokio.workspace = true
3232
tower.workspace = true
33-
tower-http = { workspace = true, features = [ "trace" ] }
33+
tower-http = { workspace = true, features = [ "trace", "cors" ] }
3434
tracing.workspace = true
3535
url.workspace = true
3636

@@ -82,3 +82,4 @@ cartridge = [
8282
"katana-rpc-api/cartridge",
8383
]
8484
explorer = [ "dep:katana-explorer" ]
85+
client = [ "jsonrpsee/client", "katana-rpc-api/client" ]

crates/rpc/rpc/src/lib.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ mod logger;
2929
mod utils;
3030
use cors::Cors;
3131
use health::HealthCheck;
32+
#[cfg(feature = "client")]
33+
pub use jsonrpsee::http_client::HttpClient;
34+
pub use katana_rpc_api as api;
3235
use metrics::RpcServerMetricsLayer;
3336

3437
/// The default maximum number of concurrent RPC connections.
@@ -44,9 +47,6 @@ pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(20);
4447

4548
#[derive(Debug, thiserror::Error)]
4649
pub enum Error {
47-
#[error(transparent)]
48-
Jsonrpsee(#[from] jsonrpsee::types::ErrorObjectOwned),
49-
5050
#[error(transparent)]
5151
Io(#[from] std::io::Error),
5252

@@ -55,6 +55,9 @@ pub enum Error {
5555

5656
#[error("RPC server has already been stopped")]
5757
AlreadyStopped,
58+
59+
#[error(transparent)]
60+
Client(#[from] jsonrpsee::core::ClientError),
5861
}
5962

6063
/// The RPC server handle.
@@ -81,6 +84,14 @@ impl RpcServerHandle {
8184
pub fn addr(&self) -> &SocketAddr {
8285
&self.addr
8386
}
87+
88+
/// Returns a HTTP client associated with the server.
89+
#[cfg(feature = "client")]
90+
pub fn http_client(&self) -> Result<HttpClient, Error> {
91+
use jsonrpsee::http_client::HttpClientBuilder;
92+
let url = format!("http://{}", self.addr);
93+
Ok(HttpClientBuilder::default().build(url)?)
94+
}
8495
}
8596

8697
#[derive(Debug)]

crates/rpc/rpc/tests/dev.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
use jsonrpsee::http_client::HttpClientBuilder;
21
use katana_provider::traits::block::{BlockNumberProvider, BlockProvider};
32
use katana_provider::traits::env::BlockEnvProvider;
4-
use katana_rpc_api::dev::DevApiClient;
3+
use katana_rpc::api::dev::DevApiClient;
54
use katana_utils::TestNode;
65

76
#[tokio::test]
@@ -11,8 +10,7 @@ async fn test_next_block_timestamp_in_past() {
1110
let provider = backend.blockchain.provider();
1211

1312
// Create a jsonrpsee client for the DevApi
14-
let url = format!("http://{}", sequencer.rpc_addr());
15-
let client = HttpClientBuilder::default().build(url).unwrap();
13+
let client = sequencer.rpc_http_client();
1614

1715
let block_num = provider.latest_number().unwrap();
1816
let mut block_env = provider.block_env_at(block_num.into()).unwrap().unwrap();
@@ -39,8 +37,7 @@ async fn test_set_next_block_timestamp_in_future() {
3937
let provider = backend.blockchain.provider();
4038

4139
// Create a jsonrpsee client for the DevApi
42-
let url = format!("http://{}", sequencer.rpc_addr());
43-
let client = HttpClientBuilder::default().build(url).unwrap();
40+
let client = sequencer.rpc_http_client();
4441

4542
let block_num = provider.latest_number().unwrap();
4643
let mut block_env = provider.block_env_at(block_num.into()).unwrap().unwrap();
@@ -68,8 +65,7 @@ async fn test_increase_next_block_timestamp() {
6865
let provider = backend.blockchain.provider();
6966

7067
// Create a jsonrpsee client for the DevApi
71-
let url = format!("http://{}", sequencer.rpc_addr());
72-
let client = HttpClientBuilder::default().build(url).unwrap();
68+
let client = sequencer.rpc_http_client();
7369

7470
let block_num = provider.latest_number().unwrap();
7571
let mut block_env = provider.block_env_at(block_num.into()).unwrap().unwrap();
@@ -101,8 +97,7 @@ async fn test_increase_next_block_timestamp() {
10197
async fn test_dev_api_enabled() {
10298
let sequencer = TestNode::new().await;
10399

104-
let url = format!("http://{}", sequencer.rpc_addr());
105-
let client = HttpClientBuilder::default().build(url).unwrap();
100+
let client = sequencer.rpc_http_client();
106101

107102
let accounts = client.predeployed_accounts().await.unwrap();
108103
assert!(!accounts.is_empty(), "predeployed accounts should not be empty");

crates/rpc/rpc/tests/proofs.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use std::path::PathBuf;
22

33
use assert_matches::assert_matches;
44
use jsonrpsee::core::ClientError;
5-
use jsonrpsee::http_client::HttpClientBuilder;
65
use katana_chain_spec::ChainSpec;
76
use katana_node::config::rpc::DEFAULT_RPC_MAX_PROOF_KEYS;
87
use katana_primitives::block::BlockIdOrTag;
@@ -30,8 +29,7 @@ async fn proofs_limit() {
3029
let sequencer = TestNode::new().await;
3130

3231
// We need to use the jsonrpsee client because `starknet-rs` doesn't yet support RPC 0
33-
let url = format!("http://{}", sequencer.rpc_addr());
34-
let client = HttpClientBuilder::default().build(url).unwrap();
32+
let client = sequencer.rpc_http_client();
3533

3634
// Because we're using the default configuration for instantiating the node, the RPC limit is
3735
// set to 100. The total keys is 35 + 35 + 35 = 105.
@@ -83,8 +81,7 @@ async fn genesis_states() {
8381
let genesis_states = chain_spec.state_updates();
8482

8583
// We need to use the jsonrpsee client because `starknet-rs` doesn't yet support RPC 0.8.0
86-
let url = format!("http://{}", sequencer.rpc_addr());
87-
let client = HttpClientBuilder::default().build(url).unwrap();
84+
let client = sequencer.rpc_http_client();
8885

8986
// Check class declarations
9087
let genesis_classes =
@@ -198,8 +195,7 @@ async fn classes_proofs() {
198195
declare(&account, "tests/test_data/test_sierra_contract.json").await;
199196

200197
// We need to use the jsonrpsee client because `starknet-rs` doesn't yet support RPC 0.8.0
201-
let url = format!("http://{}", sequencer.rpc_addr());
202-
let client = HttpClientBuilder::default().build(url).unwrap();
198+
let client = sequencer.rpc_http_client();
203199

204200
{
205201
let class_hash = class_hash1;

crates/rpc/rpc/tests/starknet.rs

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use assert_matches::assert_matches;
66
use cainome::rs::{abigen, abigen_legacy};
77
use common::split_felt;
88
use indexmap::IndexSet;
9-
use jsonrpsee::http_client::HttpClientBuilder;
109
use katana_primitives::event::ContinuationToken;
1110
use katana_primitives::genesis::constant::{
1211
DEFAULT_ACCOUNT_CLASS_HASH, DEFAULT_ETH_FEE_TOKEN_ADDRESS, DEFAULT_PREFUNDED_ACCOUNT_BALANCE,
@@ -638,8 +637,7 @@ async fn get_events_no_pending() -> Result<()> {
638637
let sequencer = TestNode::new_with_config(config).await;
639638

640639
// create a json rpc client to interact with the dev api.
641-
let url = format!("http://{}", sequencer.rpc_addr());
642-
let client = HttpClientBuilder::default().build(url).unwrap();
640+
let client = sequencer.rpc_http_client();
643641

644642
let provider = sequencer.starknet_provider();
645643
let account = sequencer.account();
@@ -725,8 +723,7 @@ async fn get_events_with_pending() -> Result<()> {
725723
let sequencer = TestNode::new_with_config(config).await;
726724

727725
// create a json rpc client to interact with the dev api.
728-
let url = format!("http://{}", sequencer.rpc_addr());
729-
let client = HttpClientBuilder::default().build(url).unwrap();
726+
let client = sequencer.rpc_http_client();
730727

731728
let provider = sequencer.starknet_provider();
732729
let account = sequencer.account();
@@ -817,8 +814,7 @@ async fn trace() -> Result<()> {
817814

818815
let provider = sequencer.starknet_provider();
819816
let account = sequencer.account();
820-
let url = format!("http://{}", sequencer.rpc_addr());
821-
let rpc_client = HttpClientBuilder::default().build(url).unwrap();
817+
let rpc_client = sequencer.rpc_http_client();
822818

823819
// setup contract to interact with (can be any existing contract that can be interacted with)
824820
let contract = Erc20Contract::new(DEFAULT_ETH_FEE_TOKEN_ADDRESS.into(), &account);
@@ -868,9 +864,7 @@ async fn block_traces() -> Result<()> {
868864

869865
let provider = sequencer.starknet_provider();
870866
let account = sequencer.account();
871-
872-
let url = format!("http://{}", sequencer.rpc_addr());
873-
let rpc_client = HttpClientBuilder::default().build(url)?;
867+
let rpc_client = sequencer.rpc_http_client();
874868

875869
// setup contract to interact with (can be any existing contract that can be interacted with)
876870
let contract = Erc20Contract::new(DEFAULT_ETH_FEE_TOKEN_ADDRESS.into(), &account);
@@ -991,8 +985,7 @@ async fn fetch_pending_blocks() {
991985
let sequencer = TestNode::new_with_config(config).await;
992986

993987
// create a json rpc client to interact with the dev api.
994-
let url = format!("http://{}", sequencer.rpc_addr());
995-
let dev_client = HttpClientBuilder::default().build(url).unwrap();
988+
let dev_client = sequencer.rpc_http_client();
996989
let provider = sequencer.starknet_provider();
997990
let account = sequencer.account();
998991

@@ -1094,8 +1087,7 @@ async fn fetch_pending_blocks_in_instant_mode() {
10941087
let sequencer = TestNode::new().await;
10951088

10961089
// create a json rpc client to interact with the dev api.
1097-
let url = format!("http://{}", sequencer.rpc_addr());
1098-
let dev_client = HttpClientBuilder::default().build(url).unwrap();
1090+
let dev_client = sequencer.rpc_http_client();
10991091
let provider = sequencer.starknet_provider();
11001092
let account = sequencer.account();
11011093

crates/utils/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ katana-executor.workspace = true
1212
katana-node = { workspace = true, features = [ "explorer" ] }
1313
katana-primitives.workspace = true
1414
katana-provider.workspace = true
15+
katana-rpc = { workspace = true, features = [ "client" ] }
1516

1617
anyhow.workspace = true
1718
assert_matches.workspace = true

crates/utils/src/node.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use katana_node::{LaunchedNode, Node};
1313
use katana_primitives::chain::ChainId;
1414
use katana_primitives::{address, ContractAddress};
1515
use katana_provider::BlockchainProvider;
16+
use katana_rpc::HttpClient;
1617
use starknet::accounts::{ExecutionEncoding, SingleOwnerAccount};
1718
use starknet::core::types::BlockTag;
1819
pub use starknet::core::types::StarknetError;
@@ -90,6 +91,11 @@ impl TestNode {
9091

9192
account
9293
}
94+
95+
/// Returns a HTTP client to the JSON-RPC server.
96+
pub fn rpc_http_client(&self) -> HttpClient {
97+
self.handle().rpc().http_client().expect("failed to get http client for the rpc server")
98+
}
9399
}
94100

95101
pub fn test_config() -> Config {

0 commit comments

Comments
 (0)