Skip to content

Commit

Permalink
Merge pull request #1066 from rainlanguage/2024-12-11-ob-yaml-and-net…
Browse files Browse the repository at this point in the history
…work

Adding OrderbookYaml and implementing network logic
  • Loading branch information
hardyjosh authored Dec 15, 2024
2 parents 4b9a769 + 8d94d36 commit ea7c9cf
Show file tree
Hide file tree
Showing 16 changed files with 522 additions and 45 deletions.
4 changes: 2 additions & 2 deletions crates/cli/src/commands/order/orderbook_address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ impl Execute for OrderbookAddress {
let orderbook_address = if let Some(v) = &deployment_ref.order.orderbook {
v.address
} else {
let network_name = &deployment_ref.scenario.deployer.network.name;
let network_key = &deployment_ref.scenario.deployer.network.key;
order_config
.orderbooks
.iter()
.find(|(k, v)| *k == network_name || v.network.name == *network_name)
.find(|(k, v)| *k == network_key || v.network.key == *network_key)
.ok_or(anyhow!("specified orderbook is undefined!"))?
.1
.address
Expand Down
8 changes: 4 additions & 4 deletions crates/cli/src/commands/words/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ impl Execute for Words {
order
.config()
.metaboards
.get(&deployer.network.name)
.get(&deployer.network.key)
.map(|v| v.to_string())
})
.ok_or(anyhow!("undefined metaboard subgraph url"))?;
Expand All @@ -133,7 +133,7 @@ impl Execute for Words {
.ok_or(anyhow!("undefined scenario"))?
.deployer
.network
.name
.key
.clone();
order
.config_mut()
Expand Down Expand Up @@ -187,11 +187,11 @@ impl Execute for Words {

// set the cli given metaboard url into the config
if let Some(v) = &self.metaboard_subgraph {
let network_name = deployment.scenario.deployer.network.name.clone();
let network_key = deployment.scenario.deployer.network.key.clone();
order
.config_mut()
.metaboards
.insert(network_name.to_string(), Arc::new(Url::from_str(v)?));
.insert(network_key.to_string(), Arc::new(Url::from_str(v)?));
}
let result = order.get_all_words_for_scenario(&scenario).await?;
let mut words = vec![];
Expand Down
12 changes: 8 additions & 4 deletions crates/common/src/add_order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,8 @@ mod tests {
token::Token,
};
use rain_orderbook_test_fixtures::LocalEvm;
use std::sync::Arc;
use std::sync::{Arc, RwLock};
use strict_yaml_rust::StrictYaml;
use url::Url;

#[test]
Expand Down Expand Up @@ -428,7 +429,8 @@ price: 2e18;
#[tokio::test]
async fn test_add_order_random_vault_id_generation() {
let network = Network {
name: "test-network".to_string(),
document: Arc::new(RwLock::new(StrictYaml::String("".to_string()))),
key: "test-network".to_string(),
rpc: Url::parse("https://some-rpc.com").unwrap(),
chain_id: 137,
label: None,
Expand Down Expand Up @@ -526,7 +528,8 @@ _ _: 0 0;
async fn test_into_add_order_call() {
let local_evm = LocalEvm::new_with_tokens(2).await;
let network = Network {
name: "test-network".to_string(),
document: Arc::new(RwLock::new(StrictYaml::String("".to_string()))),
key: "test-network".to_string(),
rpc: Url::parse(&local_evm.url()).unwrap(),
chain_id: 137,
label: None,
Expand Down Expand Up @@ -658,7 +661,8 @@ _ _: 0 0;
#[tokio::test]
async fn test_add_order_post_action() {
let network = Network {
name: "test-network".to_string(),
document: Arc::new(RwLock::new(StrictYaml::String("".to_string()))),
key: "test-network".to_string(),
rpc: Url::parse("https://some-rpc.com").unwrap(),
chain_id: 137,
label: None,
Expand Down
2 changes: 1 addition & 1 deletion crates/common/src/dotrain_order/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ impl DotrainOrder {
// same scenario network name as any previously added network
for (chart_key, chart) in &self.config.charts {
if chart.scenario.name.split('.').nth(0).unwrap() == scenario_key
|| all_network_keys.contains(&chart.scenario.deployer.network.name.as_str())
|| all_network_keys.contains(&chart.scenario.deployer.network.key.as_str())
{
new_config_source.charts.insert(
chart_key.clone(),
Expand Down
4 changes: 2 additions & 2 deletions crates/common/src/dotrain_order/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,8 @@ impl DotrainOrder {
let metaboard = self
.config
.metaboards
.get(&network.name)
.ok_or_else(|| DotrainOrderError::MetaboardNotFound(network.name.clone()))?
.get(&network.key)
.ok_or_else(|| DotrainOrderError::MetaboardNotFound(network.key.clone()))?
.clone();
Ok(
AuthoringMetaV2::fetch_for_contract(address, rpc.to_string(), metaboard.to_string())
Expand Down
2 changes: 1 addition & 1 deletion crates/settings/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ mod tests {
Url::parse("https://mainnet.node").unwrap()
);
assert_eq!(mainnet_network.chain_id, 1);
assert_eq!(mainnet_network.name, "mainnet".to_string());
assert_eq!(mainnet_network.key, "mainnet".to_string());

// Verify subgraphs
assert_eq!(config.subgraphs.len(), 1);
Expand Down
1 change: 1 addition & 0 deletions crates/settings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub mod remote;
pub mod scenario;
pub mod token;
pub mod unit_test;
pub mod yaml;

pub(crate) use chart::*;
pub(crate) use config_source::*;
Expand Down
182 changes: 175 additions & 7 deletions crates/settings/src/network.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
use crate::config_source::*;
use crate::yaml::{optional_string, require_hash, require_string, YamlError, YamlParsableHash};
use serde::{Deserialize, Serialize};
use std::num::ParseIntError;
use std::collections::HashMap;
use std::{
num::ParseIntError,
sync::{Arc, RwLock},
};
use strict_yaml_rust::StrictYaml;
use thiserror::Error;
use typeshare::typeshare;
use url::{ParseError, Url};
Expand All @@ -9,11 +15,14 @@ use url::{ParseError, Url};
use rain_orderbook_bindings::{impl_all_wasm_traits, wasm_traits::prelude::*};

#[typeshare]
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
#[derive(Debug, Serialize, Deserialize, Clone)]
#[cfg_attr(target_family = "wasm", derive(Tsify))]
#[serde(rename_all = "kebab-case")]
#[serde(default)]
pub struct Network {
pub name: String,
#[serde(skip)]
pub document: Arc<RwLock<StrictYaml>>,
pub key: String,
#[typeshare(typescript(type = "string"))]
#[cfg_attr(target_family = "wasm", tsify(type = "string"))]
pub rpc: Url,
Expand All @@ -27,18 +36,135 @@ pub struct Network {
impl Network {
pub fn dummy() -> Self {
Network {
name: "".to_string(),
document: Arc::new(RwLock::new(StrictYaml::String("".to_string()))),
key: "".to_string(),
rpc: Url::parse("http://rpc.com").unwrap(),
chain_id: 1,
label: None,
network_id: None,
currency: None,
}
}

pub fn validate_rpc(value: &str) -> Result<Url, ParseNetworkConfigSourceError> {
Url::parse(value).map_err(ParseNetworkConfigSourceError::RpcParseError)
}
pub fn validate_chain_id(value: &str) -> Result<u64, ParseNetworkConfigSourceError> {
value
.parse::<u64>()
.map_err(ParseNetworkConfigSourceError::ChainIdParseError)
}
pub fn validate_network_id(value: &str) -> Result<u64, ParseNetworkConfigSourceError> {
value
.parse::<u64>()
.map_err(ParseNetworkConfigSourceError::NetworkIdParseError)
}

pub fn update_rpc(&mut self, rpc: &str) -> Result<Self, YamlError> {
let mut document = self
.document
.write()
.map_err(|_| YamlError::WriteLockError)?;

if let StrictYaml::Hash(ref mut document_hash) = *document {
if let Some(StrictYaml::Hash(ref mut networks)) =
document_hash.get_mut(&StrictYaml::String("networks".to_string()))
{
if let Some(StrictYaml::Hash(ref mut network)) =
networks.get_mut(&StrictYaml::String(self.key.to_string()))
{
network[&StrictYaml::String("rpc".to_string())] =
StrictYaml::String(rpc.to_string());
self.rpc = Network::validate_rpc(rpc)?;
} else {
return Err(YamlError::ParseError(format!(
"missing field: {} in networks",
self.key
)));
}
} else {
return Err(YamlError::ParseError("missing field: networks".to_string()));
}
} else {
return Err(YamlError::ParseError("document parse error".to_string()));
}

Ok(self.clone())
}
}
#[cfg(target_family = "wasm")]
impl_all_wasm_traits!(Network);

impl YamlParsableHash for Network {
fn parse_all_from_yaml(
document: Arc<RwLock<StrictYaml>>,
) -> Result<HashMap<String, Self>, YamlError> {
let document_read = document.read().map_err(|_| YamlError::ReadLockError)?;
let networks_hash = require_hash(
&document_read,
Some("networks"),
Some("missing field: networks".to_string()),
)?;

networks_hash
.into_iter()
.map(|(key_yaml, network_yaml)| {
let network_key = key_yaml.as_str().unwrap_or_default().to_string();

let rpc_url = Network::validate_rpc(&require_string(
network_yaml,
Some("rpc"),
Some(format!("rpc string missing in network: {network_key}")),
)?)?;

let chain_id = Network::validate_chain_id(&require_string(
network_yaml,
Some("chain-id"),
Some(format!(
"chain-id number as string missing in network: {network_key}"
)),
)?)?;

let label = optional_string(network_yaml, "label");

let network_id = optional_string(network_yaml, "network-id")
.map(|id| Network::validate_network_id(&id))
.transpose()?;

let currency = optional_string(network_yaml, "currency");

let network = Network {
document: document.clone(),
key: network_key.clone(),
rpc: rpc_url,
chain_id,
label,
network_id,
currency,
};

Ok((network_key, network))
})
.collect()
}
}

impl Default for Network {
fn default() -> Self {
Network::dummy()
}
}
impl PartialEq for Network {
fn eq(&self, other: &Self) -> bool {
self.key == other.key
&& self.rpc == other.rpc
&& self.chain_id == other.chain_id
&& self.label == other.label
&& self.network_id == other.network_id
&& self.currency == other.currency
}
}

#[derive(Error, Debug, PartialEq)]
pub enum ParseNetworkConfigSourceError {
#[error("Failed to parse rpc: {}", 0)]
Expand All @@ -50,9 +176,10 @@ pub enum ParseNetworkConfigSourceError {
}

impl NetworkConfigSource {
pub fn try_into_network(self, name: String) -> Result<Network, ParseNetworkConfigSourceError> {
pub fn try_into_network(self, key: String) -> Result<Network, ParseNetworkConfigSourceError> {
Ok(Network {
name,
document: Arc::new(RwLock::new(StrictYaml::String("".to_string()))),
key,
rpc: self.rpc,
chain_id: self.chain_id,
label: self.label,
Expand All @@ -65,6 +192,7 @@ impl NetworkConfigSource {
#[cfg(test)]
mod tests {
use super::*;
use strict_yaml_rust::StrictYamlLoader;
use url::Url;

#[test]
Expand All @@ -86,6 +214,46 @@ mod tests {
assert_eq!(network.network_id, Some(1));
assert_eq!(network.label, Some("Local Testnet".into()));
assert_eq!(network.currency, Some("ETH".into()));
assert_eq!(network.name, "local");
assert_eq!(network.key, "local");
}

fn get_document(yaml: &str) -> Arc<RwLock<StrictYaml>> {
let document = StrictYamlLoader::load_from_str(yaml).unwrap()[0].clone();
Arc::new(RwLock::new(document))
}

#[test]
fn test_parse_networks_from_yaml() {
let yaml = r#"
test: test
"#;
let error = Network::parse_all_from_yaml(get_document(yaml)).unwrap_err();
assert_eq!(
error,
YamlError::ParseError("missing field: networks".to_string())
);

let yaml = r#"
networks:
mainnet:
"#;
let error = Network::parse_all_from_yaml(get_document(yaml)).unwrap_err();
assert_eq!(
error,
YamlError::ParseError("rpc string missing in network: mainnet".to_string())
);

let yaml = r#"
networks:
mainnet:
rpc: https://mainnet.infura.io
"#;
let error = Network::parse_all_from_yaml(get_document(yaml)).unwrap_err();
assert_eq!(
error,
YamlError::ParseError(
"chain-id number as string missing in network: mainnet".to_string()
)
);
}
}
6 changes: 4 additions & 2 deletions crates/settings/src/test.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use crate::*;
use alloy::primitives::Address;
use std::sync::Arc;
use std::sync::{Arc, RwLock};
use strict_yaml_rust::StrictYaml;

// Helper function to create a mock network
pub fn mock_network() -> Arc<Network> {
Arc::new(Network {
name: "local".into(),
document: Arc::new(RwLock::new(StrictYaml::String("".to_string()))),
key: "local".into(),
rpc: ("http://127.0.0.1:8545").parse().unwrap(),
chain_id: 1,
label: Some("Local Testnet".into()),
Expand Down
Loading

0 comments on commit ea7c9cf

Please sign in to comment.