Skip to content

Commit

Permalink
Merge pull request #1 from astraly-labs/feat/fetch-price-from-pragma
Browse files Browse the repository at this point in the history
Feat/fetch price from pragma
  • Loading branch information
azurwastaken authored Oct 24, 2024
2 parents b45bd6a + 2df3e5a commit 5b70d42
Show file tree
Hide file tree
Showing 13 changed files with 305 additions and 1 deletion.
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: fetch eth/strk price and sync strk gas price
- fix: contract 0 state diff fixed
- refactor(rpc): re-worked rpc tower server and added proper websocket support
- fix(network): added the FGW and gateway url to the chain config
Expand Down
29 changes: 29 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ 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 }
mp-chain-config = { path = "crates/primitives/chain_config", default-features = false }
mp-oracle = { path = "crates/primitives/oracle", default-features = false }

# Madara client
mc-telemetry = { path = "crates/client/telemetry" }
Expand Down
1 change: 1 addition & 0 deletions crates/client/eth/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ starknet_api = { workspace = true }
# Other
alloy = { workspace = true }
anyhow = "1.0.75"
bigdecimal = "0.4.5"
bitvec = { workspace = true }
blockifier = { workspace = true }
futures = { workspace = true, default-features = true }
Expand Down
16 changes: 16 additions & 0 deletions crates/client/eth/src/l1_gas_price.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::client::EthereumClient;
use alloy::eips::BlockNumberOrTag;
use alloy::providers::Provider;
use anyhow::Context;
use bigdecimal::BigDecimal;
use mc_mempool::{GasPriceProvider, L1DataProvider};
use std::time::{Duration, UNIX_EPOCH};

Expand Down Expand Up @@ -67,6 +68,21 @@ async fn update_gas_price(eth_client: &EthereumClient, l1_gas_provider: GasPrice
l1_gas_provider.update_eth_l1_gas_price(*eth_gas_price);
l1_gas_provider.update_eth_l1_data_gas_price(avg_blob_base_fee);

// fetch eth/strk price and update
if let Some(oracle_provider) = &l1_gas_provider.oracle_provider {
let (eth_strk_price, decimals) =
oracle_provider.fetch_eth_strk_price().await.expect("failed to retrieve ETH/STRK price");
let strk_gas_price = (BigDecimal::new((*eth_gas_price).into(), decimals.into())
/ BigDecimal::new(eth_strk_price.into(), decimals.into()))
.as_bigint_and_exponent();
let strk_data_gas_price = (BigDecimal::new(avg_blob_base_fee.into(), decimals.into())
/ BigDecimal::new(eth_strk_price.into(), decimals.into()))
.as_bigint_and_exponent();

l1_gas_provider.update_strk_l1_gas_price(strk_gas_price.0.to_str_radix(10).parse::<u128>()?);
l1_gas_provider.update_strk_l1_data_gas_price(strk_data_gas_price.0.to_str_radix(10).parse::<u128>()?);
}

l1_gas_provider.update_last_update_timestamp();

// Update block number separately to avoid holding the lock for too long
Expand Down
3 changes: 3 additions & 0 deletions crates/client/mempool/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ mp-receipt.workspace = true
mp-state-update.workspace = true
mp-transactions.workspace = true
mp-utils.workspace = true
mp-oracle.workspace = true

# Starknet
blockifier.workspace = true
Expand All @@ -56,5 +57,7 @@ starknet_api.workspace = true
anyhow.workspace = true
log.workspace = true
mockall = { workspace = true, optional = true }
reqwest.workspace = true
serde.workspace = true
thiserror.workspace = true
tokio.workspace = true
12 changes: 12 additions & 0 deletions crates/client/mempool/src/l1.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use mp_block::header::{GasPrices, L1DataAvailabilityMode};
use mp_oracle::Oracle;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use std::time::SystemTime;
Expand All @@ -11,6 +12,7 @@ pub struct GasPriceProvider {
data_gas_price_sync_enabled: Arc<AtomicBool>,
strk_gas_price_sync_enabled: Arc<AtomicBool>,
strk_data_gas_price_sync_enabled: Arc<AtomicBool>,
pub oracle_provider: Option<Arc<Oracle>>,
}

impl GasPriceProvider {
Expand All @@ -22,9 +24,19 @@ impl GasPriceProvider {
data_gas_price_sync_enabled: Arc::new(AtomicBool::new(true)),
strk_gas_price_sync_enabled: Arc::new(AtomicBool::new(true)),
strk_data_gas_price_sync_enabled: Arc::new(AtomicBool::new(true)),
oracle_provider: None,
}
}

pub fn is_oracle_needed(&self) -> bool {
self.strk_gas_price_sync_enabled.load(Ordering::Relaxed)
|| self.strk_data_gas_price_sync_enabled.load(Ordering::Relaxed)
}

pub fn set_oracle_provider(&mut self, oracle_provider: Oracle) {
self.oracle_provider = Some(Arc::new(oracle_provider));
}

pub fn set_gas_prices(&self, new_prices: GasPrices) {
self.update_eth_l1_gas_price(new_prices.eth_l1_gas_price);
self.update_strk_l1_gas_price(new_prices.strk_l1_gas_price);
Expand Down
1 change: 1 addition & 0 deletions crates/node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ mp-block.workspace = true
mp-chain-config.workspace = true
mp-convert.workspace = true
mp-utils.workspace = true
mp-oracle.workspace = true

# Starknet
blockifier.workspace = true
Expand Down
8 changes: 8 additions & 0 deletions crates/node/src/cli/l1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ pub struct L1SyncParams {
#[clap(env = "MADARA_STRK_DATA_GAS_PRICE", long, alias = "strk-blob-gas-price")]
pub strk_blob_gas_price: Option<u64>,

/// Oracle API url.
#[clap(env = "ORACLE_URL", long, alias = "oracle-url")]
pub oracle_url: Option<Url>,

/// Oracle API key.
#[clap(env = "ORACLE_API_KEY", long, alias = "oracle-api-key")]
pub oracle_api_key: Option<String>,

/// Time in which the gas price worker will fetch the gas price.
#[clap(
env = "MADARA_GAS_PRICE_POLL",
Expand Down
15 changes: 14 additions & 1 deletion crates/node/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use mc_metrics::MetricsService;
use mc_rpc::providers::{AddTransactionProvider, ForwardToProvider, MempoolAddTxProvider};
use mc_telemetry::{SysInfo, TelemetryService};
use mp_convert::ToFelt;
use mp_oracle::Oracle;
use mp_utils::service::{Service, ServiceGroup};
use service::{BlockProductionService, GatewayService, L1SyncService, RpcService, SyncService};
use starknet_providers::SequencerGatewayProvider;
Expand Down Expand Up @@ -89,7 +90,7 @@ async fn main() -> anyhow::Result<()> {
.context("Initializing importer service")?,
);

let l1_gas_setter = GasPriceProvider::new();
let mut l1_gas_setter = GasPriceProvider::new();

if let Some(fix_gas) = run_cmd.l1_sync_params.gas_price {
l1_gas_setter.update_eth_l1_gas_price(fix_gas as u128);
Expand All @@ -107,6 +108,18 @@ async fn main() -> anyhow::Result<()> {
l1_gas_setter.update_strk_l1_data_gas_price(strk_fix_blob_gas as u128);
l1_gas_setter.set_strk_data_gas_price_sync_enabled(false);
}
if let Some(ref oracle_url) = run_cmd.l1_sync_params.oracle_url {
if let Some(ref oracle_api_key) = run_cmd.l1_sync_params.oracle_api_key {
let oracle = Oracle::new("Pragma", oracle_url.to_string(), oracle_api_key.clone())?;
l1_gas_setter.set_oracle_provider(oracle);
}
}

if l1_gas_setter.is_oracle_needed() && l1_gas_setter.oracle_provider.is_none() {
log::error!("STRK gas is not fixed and oracle is not provided");
panic!();
}

let l1_data_provider: Arc<dyn L1DataProvider> = Arc::new(l1_gas_setter.clone());

// declare mempool here so that it can be used to process l1->l2 messages in the l1 service
Expand Down
24 changes: 24 additions & 0 deletions crates/primitives/oracle/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
description = "Madara primitive for Oracles"
name = "mp-oracle"
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
version.workspace = true
homepage.workspace = true

[lints]
workspace = true

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

[dependencies]

# Other
num-bigint = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
anyhow = { workspace = true }
reqwest = { workspace = true }
63 changes: 63 additions & 0 deletions crates/primitives/oracle/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use anyhow::bail;
use serde::{Deserialize, Serialize};

mod pragma;

use pragma::*;

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "oracle_name", content = "config")]
pub enum Oracle {
Pragma(PragmaOracle),
}

impl Oracle {
pub fn new(oracle_name: &str, url: String, key: String) -> anyhow::Result<Self> {
match oracle_name {
"Pragma" => Ok(Oracle::Pragma(PragmaOracle::new(url, key))),
_ => bail!("Unknown Oracle name"),
}
}

pub fn set_base_url(&mut self, url: String) {
match self {
Oracle::Pragma(pragma_oracle) => pragma_oracle.api_url = url,
}
}

pub async fn fetch_eth_strk_price(&self) -> anyhow::Result<(u128, u32)> {
match self {
Oracle::Pragma(pragma_oracle) => pragma_oracle.fetch_eth_strk_price().await,
}
}

pub fn set_api_key(&mut self, key: String) {
match self {
Oracle::Pragma(pragma_oracle) => pragma_oracle.api_key = key,
}
}

pub fn get_fetch_url(&self, base: String, quote: String) -> String {
match self {
Oracle::Pragma(pragma_oracle) => pragma_oracle.get_fetch_url(base, quote),
}
}

pub fn get_api_key(&self) -> &String {
match self {
Oracle::Pragma(oracle) => &oracle.api_key,
}
}

pub fn is_in_bounds(&self, price: u128) -> bool {
match self {
Oracle::Pragma(oracle) => oracle.price_bounds.low <= price && price <= oracle.price_bounds.high,
}
}
}

impl Default for Oracle {
fn default() -> Self {
Self::Pragma(PragmaOracle::default())
}
}
Loading

0 comments on commit 5b70d42

Please sign in to comment.