Skip to content

Commit

Permalink
gateway
Browse files Browse the repository at this point in the history
  • Loading branch information
jbcaron committed Sep 9, 2024
1 parent d50814a commit 4220b60
Show file tree
Hide file tree
Showing 41 changed files with 1,368 additions and 39 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Next release

- feat: new crate gateway client & server
- refactor: class import from FGW
- code docs: documented how get_storage_at is implemented
- fix: L1 rpc <=> network mismatch
Expand Down
80 changes: 76 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"crates/client/sync",
"crates/client/eth",
"crates/client/rpc",
"crates/client/gateway",
"crates/client/telemetry",
"crates/client/metrics",
"crates/client/mempool",
Expand All @@ -14,6 +15,7 @@ members = [
"crates/primitives/convert",
"crates/primitives/transactions",
"crates/primitives/class",
"crates/primitives/gateway",
"crates/primitives/receipt",
"crates/primitives/state_update",
"crates/primitives/chain_config",
Expand All @@ -27,6 +29,7 @@ default-members = [
"crates/client/exec",
"crates/client/sync",
"crates/client/eth",
"crates/client/gateway",
"crates/client/rpc",
"crates/client/telemetry",
"crates/client/metrics",
Expand All @@ -37,6 +40,7 @@ default-members = [
"crates/primitives/convert",
"crates/primitives/transactions",
"crates/primitives/class",
"crates/primitives/gateway",
"crates/primitives/receipt",
"crates/primitives/state_update",
"crates/primitives/chain_config",
Expand Down Expand Up @@ -86,6 +90,7 @@ mp-block = { path = "crates/primitives/block", default-features = false }
mp-convert = { path = "crates/primitives/convert", default-features = false }
mp-transactions = { path = "crates/primitives/transactions", default-features = false }
mp-class = { path = "crates/primitives/class", default-features = false }
mp-gateway = { path = "crates/primitives/gateway", default-features = false }
mp-receipt = { path = "crates/primitives/receipt", default-features = false }
mp-state-update = { path = "crates/primitives/state_update", default-features = false }
mp-utils = { path = "crates/primitives/utils", default-features = false }
Expand All @@ -96,6 +101,7 @@ mc-telemetry = { path = "crates/client/telemetry" }
mc-db = { path = "crates/client/db" }
mc-exec = { path = "crates/client/exec" }
mc-rpc = { path = "crates/client/rpc" }
mc-gateway = { path = "crates/client/gateway" }
mc-sync = { path = "crates/client/sync" }
mc-eth = { path = "crates/client/eth" }
mc-metrics = { path = "crates/client/metrics" }
Expand Down Expand Up @@ -154,6 +160,7 @@ rand = "0.8"
reqwest = { version = "0.12", features = ["json"] }
rstest = "0.18"
serde = { version = "1.0", default-features = false, features = ["std"] }
serde_with = "3.9"
serde_json = { version = "1.0", default-features = false, features = ["std"] }
thiserror = "1.0"
tokio = { version = "1.34", features = ["signal"] }
Expand Down
40 changes: 40 additions & 0 deletions crates/client/gateway/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[package]
description = "Madara client rpc service"
name = "mc-gateway"
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
version.workspace = true
homepage.workspace = true

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]

# Deoxys
mc-db = { workspace = true }
mp-block = { workspace = true }
mp-gateway = { workspace = true }
mp-state-update = { workspace = true }
mp-transactions = { workspace = true }
mp-utils = { workspace = true }

# Starknet
starknet-core = { workspace = true }
starknet-types-core = { workspace = true }

# Other
anyhow = { workspace = true }
hyper = { workspace = true }
log = { workspace = true }
reqwest = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
thiserror = { workspace = true }
tokio = { workspace = true }
url = { workspace = true }

[dev-dependencies]
tokio = { workspace = true }
45 changes: 45 additions & 0 deletions crates/client/gateway/src/client/builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use std::collections::HashMap;

use reqwest::Client;
use url::Url;

#[derive(Debug, Clone)]
pub struct FeederClient {
pub(crate) client: Client,
pub(crate) gateway_url: Url,
pub(crate) feeder_gateway_url: Url,
pub(crate) headers: HashMap<String, String>,
}

impl FeederClient {
pub fn new(gateway_url: Url, feeder_gateway_url: Url) -> Self {
Self { client: Client::new(), gateway_url, feeder_gateway_url, headers: HashMap::new() }
}

pub fn new_with_headers(gateway_url: Url, feeder_gateway_url: Url, headers: &[(String, String)]) -> Self {
let headers = headers.iter().cloned().collect();
Self { client: Client::new(), gateway_url, feeder_gateway_url, headers }
}

pub fn add_header(&mut self, key: &str, value: &str) {
self.headers.insert(key.to_string(), value.to_string());
}

pub fn remove_header(&mut self, key: &str) -> Option<String> {
self.headers.remove(key)
}

pub fn starknet_alpha_mainnet() -> Self {
Self::new(
Url::parse("https://alpha-mainnet.starknet.io/gateway/").unwrap(),
Url::parse("https://alpha-mainnet.starknet.io/feeder_gateway/").unwrap(),
)
}

pub fn starknet_alpha_sepolia() -> Self {
Self::new(
Url::parse("https://alpha-sepolia.starknet.io/gateway/").unwrap(),
Url::parse("https://alpha-sepolia.starknet.io/feeder_gateway/").unwrap(),
)
}
}
90 changes: 90 additions & 0 deletions crates/client/gateway/src/client/methods.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
use mp_block::{BlockId, BlockTag};
use serde::{Deserialize, Serialize};

use crate::error::SequencerError;

use super::{builder::FeederClient, request_builder::RequestBuilder};

use mp_gateway::{
block::{BlockProvider, PendingBlockProvider, ProviderMaybePendingBlock},
state_update::{PendingStateUpdateProvider, ProviderMaybePendingStateUpdate, StateUpdateProvider},
};

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct StateUpdateWithBlock {
pub state_update: StateUpdateProvider,
pub block: BlockProvider,
}

impl FeederClient {
pub async fn get_block(&self, block_id: BlockId) -> Result<ProviderMaybePendingBlock, SequencerError> {
let request = RequestBuilder::new(&self.client, self.feeder_gateway_url.clone())
.add_uri_segment("get_block")
.unwrap()
.with_block_id(block_id);

match block_id {
BlockId::Tag(BlockTag::Pending) => {
Ok(ProviderMaybePendingBlock::Pending(request.send_get::<PendingBlockProvider>().await?))
}
_ => Ok(ProviderMaybePendingBlock::Block(request.send_get::<BlockProvider>().await?)),
}
}

pub async fn get_state_update(&self, block_id: BlockId) -> Result<ProviderMaybePendingStateUpdate, SequencerError> {
let request = RequestBuilder::new(&self.client, self.feeder_gateway_url.clone())
.add_uri_segment("get_state_update")
.unwrap()
.with_block_id(block_id);

match block_id {
BlockId::Tag(BlockTag::Pending) => {
Ok(ProviderMaybePendingStateUpdate::Pending(request.send_get::<PendingStateUpdateProvider>().await?))
}
_ => Ok(ProviderMaybePendingStateUpdate::Update(request.send_get::<StateUpdateProvider>().await?)),
}
}
}

#[cfg(test)]
mod tests {
use mp_block::BlockTag;
use starknet_core::types::Felt;

use super::*;

#[tokio::test]
async fn test_get_block() {
let client = FeederClient::starknet_alpha_mainnet();

let block = client.get_block(BlockId::Number(0)).await.unwrap();
println!("parent_block_hash: 0x{:x}", block.parent_block_hash());
let block = client
.get_block(BlockId::Hash(Felt::from_hex_unchecked(
"0x47c3637b57c2b079b93c61539950c17e868a28f46cdef28f88521067f21e943",
)))
.await
.unwrap();
println!("parent_block_hash: 0x{:x}", block.parent_block_hash());
let block = client.get_block(BlockId::Tag(BlockTag::Latest)).await.unwrap();
println!("parent_block_hash: 0x{:x}", block.parent_block_hash());
let block = client.get_block(BlockId::Tag(BlockTag::Pending)).await.unwrap();
println!("parent_block_hash: 0x{:x}", block.parent_block_hash());
}

#[tokio::test]
async fn test_get_state_update() {
let client = FeederClient::starknet_alpha_mainnet();

let block = client.get_state_update(BlockId::Number(0)).await.unwrap();
let block = client
.get_state_update(BlockId::Hash(Felt::from_hex_unchecked(
"0x47c3637b57c2b079b93c61539950c17e868a28f46cdef28f88521067f21e943",
)))
.await
.unwrap();
let block = client.get_state_update(BlockId::Tag(BlockTag::Latest)).await.unwrap();
let block = client.get_state_update(BlockId::Tag(BlockTag::Pending)).await.unwrap();
}
}
3 changes: 3 additions & 0 deletions crates/client/gateway/src/client/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod builder;
mod methods;
mod request_builder;
Loading

0 comments on commit 4220b60

Please sign in to comment.