From c3bbaab2c27cc9820524158d69d0ba3ef61a81d7 Mon Sep 17 00:00:00 2001 From: rouzwelt Date: Thu, 29 Aug 2024 05:28:11 +0000 Subject: [PATCH 1/6] init --- crates/common/src/dotrain_order.rs | 15 +- crates/common/src/frontmatter.rs | 522 +++++++++++++++++++++++++++ crates/settings/src/config_source.rs | 34 ++ 3 files changed, 568 insertions(+), 3 deletions(-) diff --git a/crates/common/src/dotrain_order.rs b/crates/common/src/dotrain_order.rs index 97ab18f25..e5c59a15a 100644 --- a/crates/common/src/dotrain_order.rs +++ b/crates/common/src/dotrain_order.rs @@ -15,10 +15,11 @@ use crate::{ rainlang::compose_to_rainlang, }; -#[derive(Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct DotrainOrder { pub config: Config, pub dotrain: String, + pub config_content: Option, } #[derive(Error, Debug)] @@ -52,19 +53,23 @@ pub enum DotrainOrderError { #[error(transparent)] ParserError(#[from] ParserError), + + #[error("{0}")] + ShakeOutError(String), } impl DotrainOrder { pub async fn new(dotrain: String, config: Option) -> Result { match config { Some(config) => { - let config_string = ConfigSource::try_from_string(config).await?; + let config_string = ConfigSource::try_from_string(config.clone()).await?; let frontmatter = RainDocument::get_front_matter(&dotrain).unwrap(); let mut frontmatter_config = ConfigSource::try_from_string(frontmatter.to_string()).await?; frontmatter_config.merge(config_string)?; Ok(Self { dotrain, + config_content: Some(config), config: frontmatter_config.try_into()?, }) } @@ -72,7 +77,11 @@ impl DotrainOrder { let frontmatter = RainDocument::get_front_matter(&dotrain).unwrap(); let config_string = ConfigSource::try_from_string(frontmatter.to_string()).await?; let config: Config = config_string.try_into()?; - Ok(Self { dotrain, config }) + Ok(Self { + dotrain, + config, + config_content: None, + }) } } } diff --git a/crates/common/src/frontmatter.rs b/crates/common/src/frontmatter.rs index 2c009b8b7..636bfaac4 100644 --- a/crates/common/src/frontmatter.rs +++ b/crates/common/src/frontmatter.rs @@ -1,4 +1,6 @@ +use crate::dotrain_order::{DotrainOrder, DotrainOrderError}; use dotrain::RainDocument; +pub use rain_metadata::types::authoring::v2::*; use rain_orderbook_app_settings::{config::ParseConfigSourceError, config_source::ConfigSource}; /// Parse dotrain frontmatter and merges it with top Config if given @@ -6,3 +8,523 @@ pub async fn parse_frontmatter(dotrain: String) -> Result, + deployments: &[&str], + ) -> Result { + Self::new(dotrain, config) + .await? + .filter_deployments(deployments) + .await + } + + pub async fn filter_deployments( + &self, + deployments: &[&str], + ) -> Result { + let frontmatter = RainDocument::get_front_matter(&self.dotrain).unwrap(); + let config_org = match &self.config_content { + Some(config) => { + let config_string = ConfigSource::try_from_string(config.clone()).await?; + let mut frontmatter_config = + ConfigSource::try_from_string(frontmatter.to_string()).await?; + frontmatter_config.merge(config_string)?; + frontmatter_config + } + None => ConfigSource::try_from_string(frontmatter.to_string()).await?, + }; + let mut new_config = ConfigSource::default(); + for deployment in deployments { + let deployment_ref = self.config.deployments.get(*deployment).ok_or( + DotrainOrderError::ShakeOutError(format!("undefined deployment: {}", deployment)), + )?; + new_config.deployments.insert( + deployment.to_string(), + config_org + .deployments + .get(*deployment) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined deployment: {}", + deployment + )))? + .clone(), + ); + let (scenario_key, scenario) = self + .config + .scenarios + .iter() + .find(|(_, v)| *v == &deployment_ref.scenario) + .map(|(k, v)| (k.split('.').nth(0).unwrap(), v)) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined deployment scenario: {}", + deployment + )))?; + new_config.scenarios.insert( + scenario_key.to_string(), + config_org + .scenarios + .get(scenario_key) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined scenario: {}", + scenario_key + )))? + .clone(), + ); + for (chart_key, chart) in &self.config.charts { + if &chart.scenario == scenario { + new_config.charts.insert( + chart_key.clone(), + config_org + .charts + .get(chart_key) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined chart: {}", + chart_key + )))? + .clone(), + ); + } + } + let (order_key, order) = self + .config + .orders + .iter() + .find(|(_, v)| *v == &deployment_ref.order) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined deployment order: {}", + deployment + )))?; + new_config.orders.insert( + order_key.clone(), + config_org + .orders + .get(order_key) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined order: {}", + order_key + )))? + .clone(), + ); + let (deployer_key, deployer) = self + .config + .deployers + .iter() + .find(|(_, v)| *v == &scenario.deployer) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined scenario deployer: {}", + scenario_key + )))?; + new_config.deployers.insert( + deployer_key.clone(), + config_org + .deployers + .get(deployer_key) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined deployer: {}", + deployer_key + )))? + .clone(), + ); + let (network_key, _) = self + .config + .networks + .iter() + .find(|(_, v)| *v == &deployer.network) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined scenario deployer network: {}", + scenario_key + )))?; + new_config.networks.insert( + network_key.clone(), + config_org + .networks + .get(network_key) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined network: {}", + network_key + )))? + .clone(), + ); + let (network_key, _) = self + .config + .networks + .iter() + .find(|(_, v)| *v == &order.network) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined order network: {}", + order_key + )))?; + new_config.networks.insert( + network_key.clone(), + config_org + .networks + .get(network_key) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined network: {}", + network_key + )))? + .clone(), + ); + if let Some(deployer_ref) = &order.deployer { + let (deployer_key, deployer) = self + .config + .deployers + .iter() + .find(|(_, v)| *v == deployer_ref) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined order deployer: {}", + order_key + )))?; + new_config.deployers.insert( + deployer_key.clone(), + config_org + .deployers + .get(deployer_key) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined order deployer: {}", + order_key + )))? + .clone(), + ); + let (network_key, _) = self + .config + .networks + .iter() + .find(|(_, v)| *v == &deployer.network) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined order deployer network: {}", + order_key + )))?; + new_config.networks.insert( + network_key.clone(), + config_org + .networks + .get(network_key) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined network: {}", + network_key + )))? + .clone(), + ); + } + if let Some(orderbook_ref) = &order.orderbook { + let (orderbook_key, orderbook) = self + .config + .orderbooks + .iter() + .find(|(_, v)| *v == orderbook_ref) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined order orderbook: {}", + order_key + )))?; + new_config.orderbooks.insert( + orderbook_key.clone(), + config_org + .orderbooks + .get(orderbook_key) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined orderbook: {}", + orderbook_key + )))? + .clone(), + ); + let (sg_key, _) = self + .config + .subgraphs + .iter() + .find(|(_, v)| *v == &orderbook_ref.subgraph) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined order orderbook subgraph: {}", + order_key + )))?; + new_config.subgraphs.insert( + sg_key.clone(), + config_org + .subgraphs + .get(sg_key) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined subgraph: {}", + sg_key + )))? + .clone(), + ); + let (network_key, _) = self + .config + .networks + .iter() + .find(|(_, v)| *v == &orderbook.network) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined order orderbook network: {}", + order_key + )))?; + new_config.networks.insert( + network_key.clone(), + config_org + .networks + .get(network_key) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined network: {}", + network_key + )))? + .clone(), + ); + } + for io in &order.inputs { + let (token_key, token) = self + .config + .tokens + .iter() + .find(|(_, v)| *v == &io.token) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined order input token: {}", + order_key + )))?; + new_config.tokens.insert( + token_key.clone(), + config_org + .tokens + .get(token_key) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined token: {}", + token_key + )))? + .clone(), + ); + let (network_key, _) = self + .config + .networks + .iter() + .find(|(_, v)| *v == &token.network) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined order input token network: {}", + token_key + )))?; + new_config.networks.insert( + network_key.clone(), + config_org + .networks + .get(network_key) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined network: {}", + network_key + )))? + .clone(), + ); + } + for io in &order.outputs { + let (token_key, token) = self + .config + .tokens + .iter() + .find(|(_, v)| *v == &io.token) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined order output token: {}", + order_key + )))?; + new_config.tokens.insert( + token_key.clone(), + config_org + .tokens + .get(token_key) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined token: {}", + token_key + )))? + .clone(), + ); + let (network_key, _) = self + .config + .networks + .iter() + .find(|(_, v)| *v == &token.network) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined order output token network: {}", + token_key + )))?; + new_config.networks.insert( + network_key.clone(), + config_org + .networks + .get(network_key) + .ok_or(DotrainOrderError::ShakeOutError(format!( + "undefined network: {}", + network_key + )))? + .clone(), + ); + } + } + let mut new_dotrain = serde_yaml::to_string(&new_config) + .map_err(|e| DotrainOrderError::ShakeOutError(e.to_string()))?; + new_dotrain.push_str("\n---\n"); + new_dotrain.push_str(self.dotrain.split("---").nth(1).unwrap()); + + Self::new(new_dotrain, None).await + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn test_dotrain_filter_deployments() { + let dotrain = " +networks: + some-network: + rpc: https://abcd.com + chain-id: 123 + network-id: 123 + currency: ETH + n2: + rpc: https://efgh.com + chain-id: 44 + network-id: 44 + currency: RRR + +subgraphs: + some-sg: https://www.some-sg.com + sg2: https://www.sg2.com + +deployers: + some-deployer: + network: some-network + address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba + d2: + network: some-network + address: 0xF14E09601A47552De6aBd3A0B165607FaFd22134 + +orderbooks: + some-orderbook: + address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 + network: some-network + subgraph: some-sg + ob2: + address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 + network: n2 + subgraph: sg2 + +tokens: + token1: + network: some-network + address: 0xc2132d05d31c914a87c6611c10748aeb04b58e8f + decimals: 6 + label: T1 + symbol: T1 + token2: + network: some-network + address: 0x8f3cf7ad23cd3cadbd9735aff958023239c6a063 + decimals: 18 + label: T2 + symbol: T2 + token3: + network: some-network + address: 0x8f3cf7ad23cd3cadbd9735aff958023239c6a063 + decimals: 77 + label: T3 + symbol: T3 + +scenarios: + some-scenario: + network: some-network + deployer: some-deployer + s2: + network: some-network + deployer: some-deployer + +orders: + some-order: + inputs: + - token: token1 + vault-id: 1 + outputs: + - token: token2 + vault-id: 1 + deployer: some-deployer + orderbook: some-orderbook + +deployments: + some-deployment: + scenario: some-scenario + order: some-order +--- +#calculate-io +_ _: 0 0; +#handle-io +:; +#handle-add-order +:;"; + + let result = DotrainOrder::new_with_filtered_deployments( + dotrain.to_string(), + None, + &["some-deployment"], + ) + .await + .unwrap(); + + let expected_dotrain = "networks: + some-network: + rpc: https://abcd.com/ + chain-id: 123 + network-id: 123 + currency: ETH +subgraphs: + some-sg: https://www.some-sg.com/ +orderbooks: + some-orderbook: + address: 0xc95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a6 + network: some-network + subgraph: some-sg +tokens: + token1: + network: some-network + address: 0xc2132d05d31c914a87c6611c10748aeb04b58e8f + decimals: 6 + label: T1 + symbol: T1 + token2: + network: some-network + address: 0x8f3cf7ad23cd3cadbd9735aff958023239c6a063 + decimals: 18 + label: T2 + symbol: T2 +deployers: + some-deployer: + address: 0xf14e09601a47552de6abd3a0b165607fafd2b5ba + network: some-network +orders: + some-order: + inputs: + - token: token1 + vault-id: '0x1' + outputs: + - token: token2 + vault-id: '0x1' + deployer: some-deployer + orderbook: some-orderbook +scenarios: + some-scenario: + deployer: some-deployer +deployments: + some-deployment: + scenario: some-scenario + order: some-order + +--- + +#calculate-io +_ _: 0 0; +#handle-io +:; +#handle-add-order +:;"; + let expected = DotrainOrder::new(expected_dotrain.to_string(), None) + .await + .unwrap(); + assert_eq!(result, expected); + } +} diff --git a/crates/settings/src/config_source.rs b/crates/settings/src/config_source.rs index a3322b28a..aefae4348 100644 --- a/crates/settings/src/config_source.rs +++ b/crates/settings/src/config_source.rs @@ -13,27 +13,39 @@ use url::Url; #[serde(rename_all = "kebab-case")] pub struct ConfigSource { #[serde(default)] + #[serde(skip_serializing_if = "HashMap::is_empty")] pub using_networks_from: HashMap, #[serde(default)] + #[serde(skip_serializing_if = "HashMap::is_empty")] pub networks: HashMap, #[serde(default)] + #[serde(skip_serializing_if = "HashMap::is_empty")] pub subgraphs: HashMap, #[serde(default)] + #[serde(skip_serializing_if = "HashMap::is_empty")] pub orderbooks: HashMap, #[serde(default)] + #[serde(skip_serializing_if = "HashMap::is_empty")] pub tokens: HashMap, #[serde(default)] + #[serde(skip_serializing_if = "HashMap::is_empty")] pub deployers: HashMap, #[serde(default)] + #[serde(skip_serializing_if = "HashMap::is_empty")] pub orders: HashMap, #[serde(default)] + #[serde(skip_serializing_if = "HashMap::is_empty")] pub scenarios: HashMap, #[serde(default)] + #[serde(skip_serializing_if = "HashMap::is_empty")] pub charts: HashMap, #[serde(default)] + #[serde(skip_serializing_if = "HashMap::is_empty")] pub deployments: HashMap, #[serde(default)] + #[serde(skip_serializing_if = "HashMap::is_empty")] pub metaboards: HashMap, + #[serde(skip_serializing_if = "Option::is_none")] pub sentry: Option, } @@ -68,9 +80,12 @@ pub struct NetworkConfigSource { pub rpc: Url, #[typeshare(typescript(type = "number"))] pub chain_id: u64, + #[serde(skip_serializing_if = "Option::is_none")] pub label: Option, #[typeshare(typescript(type = "number"))] + #[serde(skip_serializing_if = "Option::is_none")] pub network_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub currency: Option, } @@ -87,8 +102,11 @@ pub struct RemoteNetworksConfigSource { #[serde(rename_all = "kebab-case")] pub struct OrderbookConfigSource { pub address: Address, + #[serde(skip_serializing_if = "Option::is_none")] pub network: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub subgraph: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub label: Option, } @@ -98,8 +116,11 @@ pub struct OrderbookConfigSource { pub struct TokenConfigSource { pub network: NetworkRef, pub address: Address, + #[serde(skip_serializing_if = "Option::is_none")] pub decimals: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub label: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub symbol: Option, } @@ -108,7 +129,9 @@ pub struct TokenConfigSource { #[serde(rename_all = "kebab-case")] pub struct DeployerConfigSource { pub address: Address, + #[serde(skip_serializing_if = "Option::is_none")] pub network: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub label: Option, } @@ -126,6 +149,7 @@ pub struct DeploymentConfigSource { pub struct IOString { pub token: TokenRef, #[typeshare(typescript(type = "bigint"))] + #[serde(skip_serializing_if = "Option::is_none")] pub vault_id: Option, } @@ -135,7 +159,9 @@ pub struct IOString { pub struct OrderConfigSource { pub inputs: Vec, pub outputs: Vec, + #[serde(skip_serializing_if = "Option::is_none")] pub deployer: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub orderbook: Option, } @@ -144,12 +170,17 @@ pub struct OrderConfigSource { #[serde(rename_all = "kebab-case")] pub struct ScenarioConfigSource { #[serde(default)] + #[serde(skip_serializing_if = "HashMap::is_empty")] pub bindings: HashMap, #[typeshare(typescript(type = "number"))] + #[serde(skip_serializing_if = "Option::is_none")] pub runs: Option, #[typeshare(skip)] + #[serde(skip_serializing_if = "Option::is_none")] pub blocks: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub deployer: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub scenarios: Option>, } @@ -157,8 +188,11 @@ pub struct ScenarioConfigSource { #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(rename_all = "kebab-case")] pub struct ChartConfigSource { + #[serde(skip_serializing_if = "Option::is_none")] pub scenario: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub plots: Option>, + #[serde(skip_serializing_if = "Option::is_none")] pub metrics: Option>, } From 1eedbc2cf54b1972cde1e00fc476dad890027334 Mon Sep 17 00:00:00 2001 From: rouzwelt Date: Fri, 30 Aug 2024 03:19:11 +0000 Subject: [PATCH 2/6] add cli command --- crates/cli/src/commands/order/cleanup.rs | 179 ++++++++++++++++++++ crates/cli/src/commands/order/mod.rs | 6 + crates/common/src/frontmatter.rs | 206 +++++++++++++++++++---- crates/settings/src/chart.rs | 4 + crates/settings/src/config_source.rs | 36 ++-- crates/settings/src/plot_source.rs | 42 +++++ 6 files changed, 414 insertions(+), 59 deletions(-) create mode 100644 crates/cli/src/commands/order/cleanup.rs diff --git a/crates/cli/src/commands/order/cleanup.rs b/crates/cli/src/commands/order/cleanup.rs new file mode 100644 index 000000000..44826d19d --- /dev/null +++ b/crates/cli/src/commands/order/cleanup.rs @@ -0,0 +1,179 @@ +use crate::execute::Execute; +use anyhow::{anyhow, Result}; +use clap::{ArgAction, Parser}; +use rain_orderbook_common::dotrain_order::DotrainOrder; +use std::fs::read_to_string; +use std::path::PathBuf; + +/// Generate a new .rain with a cleaned up frontmatter that only includes the specified +/// deployments (and their related fields) from a given .rain and an optional setting.yml +#[derive(Parser, Clone)] +pub struct Cleanup { + /// Path to the .rain file + #[arg(short = 'f', long, value_name = "PATH")] + dotrain_file: PathBuf, + + /// Path to the settings yaml file + #[arg(short = 'c', long, value_name = "PATH")] + settings_file: Option, + + /// List of deployment keys to include in the output .rain frontmatter + #[arg(short = 'e', long, value_name = "DEPLOYMENT", num_args = 1..)] + deployments: Vec, + + /// Optional output file path to write the result into + #[arg(short = 'o', long, value_name = "PATH")] + pub output: Option, + + /// Print the result on console (send result to std out) + #[arg(long, action = ArgAction::SetTrue)] + pub stdout: bool, +} + +impl Execute for Cleanup { + async fn execute(&self) -> Result<()> { + // read inpput files + let dotrain = read_to_string(self.dotrain_file.clone()).map_err(|e| anyhow!(e))?; + let settings = match &self.settings_file { + Some(settings_file) => { + Some(read_to_string(settings_file.clone()).map_err(|e| anyhow!(e))?) + } + None => None, + }; + + // generate new dotrain order instance with cleaned up frontmatter + let order = DotrainOrder::new_with_deployments_frontmatter( + dotrain, + settings, + &self + .deployments + .iter() + .map(String::as_str) + .collect::>(), + ) + .await?; + + // handle output + if let Some(output) = &self.output { + std::fs::write(output, &order.dotrain)?; + } + if self.stdout { + println!("{}", order.dotrain); + } + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use clap::CommandFactory; + + #[test] + fn verify_cli() { + Cleanup::command().debug_assert(); + } + + #[tokio::test] + async fn test_execute_happy() { + let setting = r#" +networks: + some-network: + rpc: https://abcd.com + chain-id: 123 + network-id: 123 + currency: ETH + +subgraphs: + some-sg: https://www.some-sg.com + +deployers: + some-deployer: + network: some-network + address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba + +orderbooks: + some-orderbook: + address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 + network: some-network + subgraph: some-sg +"#; + let dotrain = r#" +tokens: + token1: + network: some-network + address: 0xc2132d05d31c914a87c6611c10748aeb04b58e8f + decimals: 6 + label: T1 + symbol: T1 + token2: + network: some-network + address: 0x8f3cf7ad23cd3cadbd9735aff958023239c6a063 + decimals: 18 + label: T2 + symbol: T2 + +scenarios: + some-scenario: + network: some-network + deployer: some-deployer + scenarios: + child-scenario: + bindings: + key1: value1 + +orders: + some-order: + inputs: + - token: token1 + vault-id: 1 + outputs: + - token: token1 + vault-id: 1 + deployer: some-deployer + orderbook: some-orderbook + +deployments: + some-deployment: + scenario: some-scenario.child-scenario + order: some-order +--- +#calculate-io +_ _: 0 0; +#handle-io +:; +#handle-add-order +:;"#; + + let dotrain_path = "./test_dotrain_cleanup.rain"; + let settings_path = "./test_settings_cleanup.yml"; + std::fs::write(dotrain_path, dotrain).unwrap(); + std::fs::write(settings_path, setting).unwrap(); + + let cleanup = Cleanup { + dotrain_file: dotrain_path.into(), + settings_file: Some(settings_path.into()), + deployments: vec!["some-deployment".to_string()], + output: None, + stdout: true, + }; + + assert!(cleanup.execute().await.is_ok()); + + std::fs::remove_file(dotrain_path).unwrap(); + std::fs::remove_file(settings_path).unwrap(); + } + + #[tokio::test] + async fn test_execute_unhappy() { + let cleanup = Cleanup { + dotrain_file: "./bad-path/test.rain".into(), + settings_file: None, + deployments: vec!["some-deployment".to_string()], + output: None, + stdout: true, + }; + + assert!(cleanup.execute().await.is_err()); + } +} diff --git a/crates/cli/src/commands/order/mod.rs b/crates/cli/src/commands/order/mod.rs index 3e3e5aa05..8c98292f4 100644 --- a/crates/cli/src/commands/order/mod.rs +++ b/crates/cli/src/commands/order/mod.rs @@ -1,5 +1,6 @@ mod add; mod calldata; +mod cleanup; mod compose; mod detail; mod list; @@ -12,6 +13,7 @@ use add::CliOrderAddArgs; use anyhow::Result; use calldata::AddOrderCalldata; use clap::Parser; +use cleanup::Cleanup; use compose::Compose; use detail::CliOrderDetailArgs; @@ -46,6 +48,9 @@ pub enum Order { alias = "ob-addr" )] OrderbookAddress(OrderbookAddress), + + #[command()] + Cleanup(Cleanup), } impl Execute for Order { @@ -58,6 +63,7 @@ impl Execute for Order { Order::Compose(compose) => compose.execute().await, Order::Calldata(calldata) => calldata.execute().await, Order::OrderbookAddress(orderbook_address) => orderbook_address.execute().await, + Order::Cleanup(cleanup) => cleanup.execute().await, } } } diff --git a/crates/common/src/frontmatter.rs b/crates/common/src/frontmatter.rs index 636bfaac4..0fa220aa3 100644 --- a/crates/common/src/frontmatter.rs +++ b/crates/common/src/frontmatter.rs @@ -10,18 +10,22 @@ pub async fn parse_frontmatter(dotrain: String) -> Result, deployments: &[&str], ) -> Result { Self::new(dotrain, config) .await? - .filter_deployments(deployments) + .clean_unused_frontmatter_by_deployments(deployments) .await } - pub async fn filter_deployments( + /// Generates a new instance with a frontmatter that only includes the + /// specified deployments and their related fields + pub async fn clean_unused_frontmatter_by_deployments( &self, deployments: &[&str], ) -> Result { @@ -52,16 +56,8 @@ impl DotrainOrder { )))? .clone(), ); - let (scenario_key, scenario) = self - .config - .scenarios - .iter() - .find(|(_, v)| *v == &deployment_ref.scenario) - .map(|(k, v)| (k.split('.').nth(0).unwrap(), v)) - .ok_or(DotrainOrderError::ShakeOutError(format!( - "undefined deployment scenario: {}", - deployment - )))?; + let scenario_main = &deployment_ref.scenario; + let scenario_key = scenario_main.name.split('.').nth(0).unwrap(); new_config.scenarios.insert( scenario_key.to_string(), config_org @@ -74,7 +70,7 @@ impl DotrainOrder { .clone(), ); for (chart_key, chart) in &self.config.charts { - if &chart.scenario == scenario { + if chart.scenario.name.split('.').nth(0).unwrap() == scenario_key { new_config.charts.insert( chart_key.clone(), config_org @@ -112,7 +108,7 @@ impl DotrainOrder { .config .deployers .iter() - .find(|(_, v)| *v == &scenario.deployer) + .find(|(_, v)| *v == &scenario_main.deployer) .ok_or(DotrainOrderError::ShakeOutError(format!( "undefined scenario deployer: {}", scenario_key @@ -371,8 +367,8 @@ mod tests { use super::*; #[tokio::test] - async fn test_dotrain_filter_deployments() { - let dotrain = " + async fn test_to_clean_frontmatter_with_deplyments_happy() { + let setting = r#" networks: some-network: rpc: https://abcd.com @@ -406,7 +402,8 @@ orderbooks: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: n2 subgraph: sg2 - +"#; + let dotrain = r#" tokens: token1: network: some-network @@ -431,9 +428,18 @@ scenarios: some-scenario: network: some-network deployer: some-deployer + scenarios: + child-scenario: + bindings: + key1: value1 s2: network: some-network - deployer: some-deployer + deployer: d2 + scenarios: + child-scenario: + bindings: + key1: value1 + key2: value2 orders: some-order: @@ -441,32 +447,68 @@ orders: - token: token1 vault-id: 1 outputs: - - token: token2 + - token: token1 vault-id: 1 deployer: some-deployer orderbook: some-orderbook deployments: some-deployment: - scenario: some-scenario + scenario: some-scenario.child-scenario order: some-order + +charts: + some-chart: + scenario: some-scenario + metrics: + - label: A metric + description: A description + unit-prefix: $ + unit-suffix: USD + value: 0.1 + plots: + plot1: + title: "My plot" + subtitle: "My subtitle" + marks: + - type: dot + options: + x: "0.1" + y: "0.2" + stroke: "black" + other-chart: + scenario: s2 + metrics: + - label: B metric + description: B description + unit-prefix: $ + unit-suffix: EUR + value: 0.1 + another-chart: + scenario: s2.child-scenario + metrics: + - label: A metric + description: A description + unit-prefix: $ + unit-suffix: USD + value: 0.1 --- #calculate-io _ _: 0 0; #handle-io :; #handle-add-order -:;"; +:;"#; - let result = DotrainOrder::new_with_filtered_deployments( + let result = DotrainOrder::new_with_deployments_frontmatter( dotrain.to_string(), - None, + Some(setting.to_string()), &["some-deployment"], ) .await .unwrap(); - let expected_dotrain = "networks: + let expected_dotrain = r#"networks: some-network: rpc: https://abcd.com/ chain-id: 123 @@ -486,12 +528,6 @@ tokens: decimals: 6 label: T1 symbol: T1 - token2: - network: some-network - address: 0x8f3cf7ad23cd3cadbd9735aff958023239c6a063 - decimals: 18 - label: T2 - symbol: T2 deployers: some-deployer: address: 0xf14e09601a47552de6abd3a0b165607fafd2b5ba @@ -502,16 +538,39 @@ orders: - token: token1 vault-id: '0x1' outputs: - - token: token2 + - token: token1 vault-id: '0x1' deployer: some-deployer orderbook: some-orderbook scenarios: some-scenario: deployer: some-deployer + scenarios: + child-scenario: + bindings: + key1: value1 +charts: + some-chart: + scenario: some-scenario + plots: + plot1: + title: My plot + subtitle: My subtitle + marks: + - type: dot + options: + x: '0.1' + y: '0.2' + stroke: black + metrics: + - label: A metric + description: A description + unit-prefix: $ + unit-suffix: USD + value: '0.1' deployments: some-deployment: - scenario: some-scenario + scenario: some-scenario.child-scenario order: some-order --- @@ -521,10 +580,87 @@ _ _: 0 0; #handle-io :; #handle-add-order -:;"; +:;"#; + let expected = DotrainOrder::new(expected_dotrain.to_string(), None) .await .unwrap(); - assert_eq!(result, expected); + + assert_eq!(result.config, expected.config); + assert_eq!(result.dotrain, expected.dotrain); + } + + #[tokio::test] + async fn test_to_clean_frontmatter_with_deplyments_unhappy() { + let setting = r#" +networks: + some-network: + rpc: https://abcd.com + chain-id: 123 + network-id: 123 + currency: ETH + +subgraphs: + some-sg: https://www.some-sg.com + +deployers: + some-deployer: + network: some-network + address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba + +orderbooks: + some-orderbook: + address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 + network: some-network + subgraph: some-sg +"#; + let dotrain = r#" +tokens: + token1: + network: some-network + address: 0xc2132d05d31c914a87c6611c10748aeb04b58e8f + decimals: 6 + label: T1 + symbol: T1 + +scenarios: + some-scenario: + network: some-network + deployer: some-deployer + scenarios: + child-scenario: + bindings: + key1: value1 + +orders: + some-order: + inputs: + - token: token1 + vault-id: 1 + outputs: + - token: token1 + vault-id: 1 + deployer: some-deployer + +deployments: + some-deployment: + scenario: some-scenario.child-scenario + order: some-order +--- +#calculate-io +_ _: 0 0; +#handle-io +:; +#handle-add-order +:;"#; + + let result = DotrainOrder::new_with_deployments_frontmatter( + dotrain.to_string(), + Some(setting.to_string()), + &["some-other-deployment"], + ) + .await; + + matches!(result, Err(DotrainOrderError::ShakeOutError(_))); } } diff --git a/crates/settings/src/chart.rs b/crates/settings/src/chart.rs index 722049012..8224cb2eb 100644 --- a/crates/settings/src/chart.rs +++ b/crates/settings/src/chart.rs @@ -19,10 +19,14 @@ pub struct Chart { #[serde(rename_all = "kebab-case")] pub struct Metric { pub label: String, + #[serde(skip_serializing_if = "Option::is_none")] pub description: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub unit_prefix: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub unit_suffix: Option, pub value: String, + #[serde(skip_serializing_if = "Option::is_none")] pub precision: Option, } diff --git a/crates/settings/src/config_source.rs b/crates/settings/src/config_source.rs index aefae4348..7f979ac2a 100644 --- a/crates/settings/src/config_source.rs +++ b/crates/settings/src/config_source.rs @@ -12,38 +12,27 @@ use url::Url; #[derive(Debug, Serialize, Deserialize, Clone, Default)] #[serde(rename_all = "kebab-case")] pub struct ConfigSource { - #[serde(default)] - #[serde(skip_serializing_if = "HashMap::is_empty")] + #[serde(default, skip_serializing_if = "HashMap::is_empty")] pub using_networks_from: HashMap, - #[serde(default)] - #[serde(skip_serializing_if = "HashMap::is_empty")] + #[serde(default, skip_serializing_if = "HashMap::is_empty")] pub networks: HashMap, - #[serde(default)] - #[serde(skip_serializing_if = "HashMap::is_empty")] + #[serde(default, skip_serializing_if = "HashMap::is_empty")] pub subgraphs: HashMap, - #[serde(default)] - #[serde(skip_serializing_if = "HashMap::is_empty")] + #[serde(default, skip_serializing_if = "HashMap::is_empty")] pub orderbooks: HashMap, - #[serde(default)] - #[serde(skip_serializing_if = "HashMap::is_empty")] + #[serde(default, skip_serializing_if = "HashMap::is_empty")] pub tokens: HashMap, - #[serde(default)] - #[serde(skip_serializing_if = "HashMap::is_empty")] + #[serde(default, skip_serializing_if = "HashMap::is_empty")] pub deployers: HashMap, - #[serde(default)] - #[serde(skip_serializing_if = "HashMap::is_empty")] + #[serde(default, skip_serializing_if = "HashMap::is_empty")] pub orders: HashMap, - #[serde(default)] - #[serde(skip_serializing_if = "HashMap::is_empty")] + #[serde(default, skip_serializing_if = "HashMap::is_empty")] pub scenarios: HashMap, - #[serde(default)] - #[serde(skip_serializing_if = "HashMap::is_empty")] + #[serde(default, skip_serializing_if = "HashMap::is_empty")] pub charts: HashMap, - #[serde(default)] - #[serde(skip_serializing_if = "HashMap::is_empty")] + #[serde(default, skip_serializing_if = "HashMap::is_empty")] pub deployments: HashMap, - #[serde(default)] - #[serde(skip_serializing_if = "HashMap::is_empty")] + #[serde(default, skip_serializing_if = "HashMap::is_empty")] pub metaboards: HashMap, #[serde(skip_serializing_if = "Option::is_none")] pub sentry: Option, @@ -169,8 +158,7 @@ pub struct OrderConfigSource { #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(rename_all = "kebab-case")] pub struct ScenarioConfigSource { - #[serde(default)] - #[serde(skip_serializing_if = "HashMap::is_empty")] + #[serde(default, skip_serializing_if = "HashMap::is_empty")] pub bindings: HashMap, #[typeshare(typescript(type = "number"))] #[serde(skip_serializing_if = "Option::is_none")] diff --git a/crates/settings/src/plot_source.rs b/crates/settings/src/plot_source.rs index 1a01dfe82..18a0c7d5f 100644 --- a/crates/settings/src/plot_source.rs +++ b/crates/settings/src/plot_source.rs @@ -5,16 +5,26 @@ use typeshare::typeshare; #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "kebab-case")] pub struct Plot { + #[serde(skip_serializing_if = "Option::is_none")] pub title: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub subtitle: Option, pub marks: Vec, + #[serde(skip_serializing_if = "Option::is_none")] pub x: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub y: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub margin: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub margin_left: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub margin_right: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub margin_top: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub margin_bottom: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub inset: Option, } @@ -30,22 +40,34 @@ pub enum Mark { #[typeshare] #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] pub struct DotOptions { + #[serde(skip_serializing_if = "Option::is_none")] pub x: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub y: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub r: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub fill: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub stroke: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub transform: Option, } #[typeshare] #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] pub struct LineOptions { + #[serde(skip_serializing_if = "Option::is_none")] pub x: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub y: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub r: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub fill: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub stroke: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub transform: Option, } @@ -53,10 +75,15 @@ pub struct LineOptions { #[typeshare] #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] pub struct RectYOptions { + #[serde(skip_serializing_if = "Option::is_none")] pub x0: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub x1: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub y0: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub y1: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub transform: Option, } @@ -65,9 +92,13 @@ pub struct RectYOptions { #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "kebab-case")] pub struct AxisOptions { + #[serde(skip_serializing_if = "Option::is_none")] pub label: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub anchor: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub label_anchor: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub label_arrow: Option, } @@ -84,11 +115,17 @@ pub enum Transform { #[typeshare] #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] pub struct TransformOutputs { + #[serde(skip_serializing_if = "Option::is_none")] x: Option, + #[serde(skip_serializing_if = "Option::is_none")] y: Option, + #[serde(skip_serializing_if = "Option::is_none")] r: Option, + #[serde(skip_serializing_if = "Option::is_none")] z: Option, + #[serde(skip_serializing_if = "Option::is_none")] stroke: Option, + #[serde(skip_serializing_if = "Option::is_none")] fill: Option, } @@ -103,8 +140,11 @@ pub struct HexBinTransform { #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "kebab-case")] pub struct HexBinOptions { + #[serde(skip_serializing_if = "Option::is_none")] x: Option, + #[serde(skip_serializing_if = "Option::is_none")] y: Option, + #[serde(skip_serializing_if = "Option::is_none")] bin_width: Option, } @@ -118,7 +158,9 @@ pub struct BinXTransform { #[typeshare] #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] pub struct BinXOptions { + #[serde(skip_serializing_if = "Option::is_none")] x: Option, + #[serde(skip_serializing_if = "Option::is_none")] thresholds: Option, } From cd5abbc6bd0321de147e800c56365c992b0b91a4 Mon Sep 17 00:00:00 2001 From: rouzwelt Date: Fri, 30 Aug 2024 03:47:28 +0000 Subject: [PATCH 3/6] update --- crates/cli/src/commands/order/cleanup.rs | 4 +- crates/common/src/dotrain_order.rs | 2 +- crates/common/src/frontmatter.rs | 117 +++++++++++++++-------- 3 files changed, 82 insertions(+), 41 deletions(-) diff --git a/crates/cli/src/commands/order/cleanup.rs b/crates/cli/src/commands/order/cleanup.rs index 44826d19d..fc2d65da1 100644 --- a/crates/cli/src/commands/order/cleanup.rs +++ b/crates/cli/src/commands/order/cleanup.rs @@ -5,8 +5,8 @@ use rain_orderbook_common::dotrain_order::DotrainOrder; use std::fs::read_to_string; use std::path::PathBuf; -/// Generate a new .rain with a cleaned up frontmatter that only includes the specified -/// deployments (and their related fields) from a given .rain and an optional setting.yml +/// Generate a new .rain with unused frontmatter cleaned, ie frontmatter will only include the +/// specified deployments (and their related fields) from a given .rain and an optional setting.yml #[derive(Parser, Clone)] pub struct Cleanup { /// Path to the .rain file diff --git a/crates/common/src/dotrain_order.rs b/crates/common/src/dotrain_order.rs index e5c59a15a..44d0838e1 100644 --- a/crates/common/src/dotrain_order.rs +++ b/crates/common/src/dotrain_order.rs @@ -55,7 +55,7 @@ pub enum DotrainOrderError { ParserError(#[from] ParserError), #[error("{0}")] - ShakeOutError(String), + CleanUnusedFrontmatterError(String), } impl DotrainOrder { diff --git a/crates/common/src/frontmatter.rs b/crates/common/src/frontmatter.rs index 0fa220aa3..ce9de04a6 100644 --- a/crates/common/src/frontmatter.rs +++ b/crates/common/src/frontmatter.rs @@ -29,6 +29,7 @@ impl DotrainOrder { &self, deployments: &[&str], ) -> Result { + // get the original ConfigSource to copy the used fields from let frontmatter = RainDocument::get_front_matter(&self.dotrain).unwrap(); let config_org = match &self.config_content { Some(config) => { @@ -40,22 +41,31 @@ impl DotrainOrder { } None => ConfigSource::try_from_string(frontmatter.to_string()).await?, }; + + // new empty config to copy used field into let mut new_config = ConfigSource::default(); for deployment in deployments { + // find and insert the specified deployment let deployment_ref = self.config.deployments.get(*deployment).ok_or( - DotrainOrderError::ShakeOutError(format!("undefined deployment: {}", deployment)), + DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined deployment: {}", + deployment + )), )?; new_config.deployments.insert( deployment.to_string(), config_org .deployments .get(*deployment) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined deployment: {}", deployment )))? .clone(), ); + + // find and insert the deployment scenario + // make sure to get the root scenario key let scenario_main = &deployment_ref.scenario; let scenario_key = scenario_main.name.split('.').nth(0).unwrap(); new_config.scenarios.insert( @@ -63,12 +73,14 @@ impl DotrainOrder { config_org .scenarios .get(scenario_key) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined scenario: {}", scenario_key )))? .clone(), ); + + // find and insert charts that reference the scenario for (chart_key, chart) in &self.config.charts { if chart.scenario.name.split('.').nth(0).unwrap() == scenario_key { new_config.charts.insert( @@ -76,7 +88,7 @@ impl DotrainOrder { config_org .charts .get(chart_key) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined chart: {}", chart_key )))? @@ -84,12 +96,14 @@ impl DotrainOrder { ); } } + + // find and insert the deployment order let (order_key, order) = self .config .orders .iter() .find(|(_, v)| *v == &deployment_ref.order) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined deployment order: {}", deployment )))?; @@ -98,18 +112,20 @@ impl DotrainOrder { config_org .orders .get(order_key) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined order: {}", order_key )))? .clone(), ); + + // find and insert the deployment scenario deployer let (deployer_key, deployer) = self .config .deployers .iter() .find(|(_, v)| *v == &scenario_main.deployer) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined scenario deployer: {}", scenario_key )))?; @@ -118,18 +134,20 @@ impl DotrainOrder { config_org .deployers .get(deployer_key) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined deployer: {}", deployer_key )))? .clone(), ); + + // find and insert the deployment scenario deployer network let (network_key, _) = self .config .networks .iter() .find(|(_, v)| *v == &deployer.network) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined scenario deployer network: {}", scenario_key )))?; @@ -138,18 +156,20 @@ impl DotrainOrder { config_org .networks .get(network_key) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined network: {}", network_key )))? .clone(), ); + + // find and insert the deployment order network let (network_key, _) = self .config .networks .iter() .find(|(_, v)| *v == &order.network) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined order network: {}", order_key )))?; @@ -158,19 +178,21 @@ impl DotrainOrder { config_org .networks .get(network_key) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined network: {}", network_key )))? .clone(), ); + + // find and insert the deployment order deployer if it is present if let Some(deployer_ref) = &order.deployer { let (deployer_key, deployer) = self .config .deployers .iter() .find(|(_, v)| *v == deployer_ref) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined order deployer: {}", order_key )))?; @@ -179,18 +201,20 @@ impl DotrainOrder { config_org .deployers .get(deployer_key) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined order deployer: {}", order_key )))? .clone(), ); + + // find and insert the deployment order deployer network let (network_key, _) = self .config .networks .iter() .find(|(_, v)| *v == &deployer.network) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined order deployer network: {}", order_key )))?; @@ -199,20 +223,22 @@ impl DotrainOrder { config_org .networks .get(network_key) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined network: {}", network_key )))? .clone(), ); } + + // find and insert the deployment order orderbook if it is present if let Some(orderbook_ref) = &order.orderbook { let (orderbook_key, orderbook) = self .config .orderbooks .iter() .find(|(_, v)| *v == orderbook_ref) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined order orderbook: {}", order_key )))?; @@ -221,18 +247,20 @@ impl DotrainOrder { config_org .orderbooks .get(orderbook_key) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined orderbook: {}", orderbook_key )))? .clone(), ); + + // find and insert the deployment order orderbook subgraph let (sg_key, _) = self .config .subgraphs .iter() .find(|(_, v)| *v == &orderbook_ref.subgraph) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined order orderbook subgraph: {}", order_key )))?; @@ -241,18 +269,20 @@ impl DotrainOrder { config_org .subgraphs .get(sg_key) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined subgraph: {}", sg_key )))? .clone(), ); + + // find and insert the deployment order orderbook network let (network_key, _) = self .config .networks .iter() .find(|(_, v)| *v == &orderbook.network) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined order orderbook network: {}", order_key )))?; @@ -261,40 +291,43 @@ impl DotrainOrder { config_org .networks .get(network_key) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined network: {}", network_key )))? .clone(), ); } + + // find and insert the deployment order inputs for io in &order.inputs { let (token_key, token) = self .config .tokens .iter() .find(|(_, v)| *v == &io.token) - .ok_or(DotrainOrderError::ShakeOutError(format!( - "undefined order input token: {}", - order_key - )))?; + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError( + format!("undefined order input token: {}", order_key), + ))?; new_config.tokens.insert( token_key.clone(), config_org .tokens .get(token_key) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined token: {}", token_key )))? .clone(), ); + + // find and insert the deployment order input network let (network_key, _) = self .config .networks .iter() .find(|(_, v)| *v == &token.network) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined order input token network: {}", token_key )))?; @@ -303,40 +336,43 @@ impl DotrainOrder { config_org .networks .get(network_key) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined network: {}", network_key )))? .clone(), ); } + + // // find and insert the deployment order outputs for io in &order.outputs { let (token_key, token) = self .config .tokens .iter() .find(|(_, v)| *v == &io.token) - .ok_or(DotrainOrderError::ShakeOutError(format!( - "undefined order output token: {}", - order_key - )))?; + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError( + format!("undefined order output token: {}", order_key), + ))?; new_config.tokens.insert( token_key.clone(), config_org .tokens .get(token_key) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined token: {}", token_key )))? .clone(), ); + + // find and insert the deployment order output network let (network_key, _) = self .config .networks .iter() .find(|(_, v)| *v == &token.network) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined order output token network: {}", token_key )))?; @@ -345,7 +381,7 @@ impl DotrainOrder { config_org .networks .get(network_key) - .ok_or(DotrainOrderError::ShakeOutError(format!( + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( "undefined network: {}", network_key )))? @@ -353,8 +389,10 @@ impl DotrainOrder { ); } } + + // reserialize the new config and construct a new dotrain order with existing dotrain body let mut new_dotrain = serde_yaml::to_string(&new_config) - .map_err(|e| DotrainOrderError::ShakeOutError(e.to_string()))?; + .map_err(|e| DotrainOrderError::CleanUnusedFrontmatterError(e.to_string()))?; new_dotrain.push_str("\n---\n"); new_dotrain.push_str(self.dotrain.split("---").nth(1).unwrap()); @@ -661,6 +699,9 @@ _ _: 0 0; ) .await; - matches!(result, Err(DotrainOrderError::ShakeOutError(_))); + matches!( + result, + Err(DotrainOrderError::CleanUnusedFrontmatterError(_)) + ); } } From 7d8d4db0e4ebc22b56a0a4ee8deed290bfaf3e12 Mon Sep 17 00:00:00 2001 From: rouzwelt Date: Fri, 30 Aug 2024 17:57:29 +0000 Subject: [PATCH 4/6] update --- crates/common/src/dotrain_order.rs | 11 +++--- crates/common/src/frontmatter.rs | 13 +------ crates/settings/src/config_source.rs | 22 +++++------ tauri-app/src-tauri/Cargo.lock | 56 ++++++++++++++++++++++++---- 4 files changed, 66 insertions(+), 36 deletions(-) diff --git a/crates/common/src/dotrain_order.rs b/crates/common/src/dotrain_order.rs index 44d0838e1..637635cff 100644 --- a/crates/common/src/dotrain_order.rs +++ b/crates/common/src/dotrain_order.rs @@ -19,7 +19,7 @@ use crate::{ pub struct DotrainOrder { pub config: Config, pub dotrain: String, - pub config_content: Option, + pub config_source: ConfigSource, } #[derive(Error, Debug)] @@ -69,18 +69,17 @@ impl DotrainOrder { frontmatter_config.merge(config_string)?; Ok(Self { dotrain, - config_content: Some(config), + config_source: frontmatter_config.clone(), config: frontmatter_config.try_into()?, }) } None => { let frontmatter = RainDocument::get_front_matter(&dotrain).unwrap(); - let config_string = ConfigSource::try_from_string(frontmatter.to_string()).await?; - let config: Config = config_string.try_into()?; + let config_source = ConfigSource::try_from_string(frontmatter.to_string()).await?; Ok(Self { dotrain, - config, - config_content: None, + config_source: config_source.clone(), + config: config_source.try_into()?, }) } } diff --git a/crates/common/src/frontmatter.rs b/crates/common/src/frontmatter.rs index ce9de04a6..d04e17483 100644 --- a/crates/common/src/frontmatter.rs +++ b/crates/common/src/frontmatter.rs @@ -29,18 +29,7 @@ impl DotrainOrder { &self, deployments: &[&str], ) -> Result { - // get the original ConfigSource to copy the used fields from - let frontmatter = RainDocument::get_front_matter(&self.dotrain).unwrap(); - let config_org = match &self.config_content { - Some(config) => { - let config_string = ConfigSource::try_from_string(config.clone()).await?; - let mut frontmatter_config = - ConfigSource::try_from_string(frontmatter.to_string()).await?; - frontmatter_config.merge(config_string)?; - frontmatter_config - } - None => ConfigSource::try_from_string(frontmatter.to_string()).await?, - }; + let config_org = &self.config_source; // new empty config to copy used field into let mut new_config = ConfigSource::default(); diff --git a/crates/settings/src/config_source.rs b/crates/settings/src/config_source.rs index 7f979ac2a..657b117a5 100644 --- a/crates/settings/src/config_source.rs +++ b/crates/settings/src/config_source.rs @@ -9,7 +9,7 @@ use typeshare::typeshare; use url::Url; #[typeshare] -#[derive(Debug, Serialize, Deserialize, Clone, Default)] +#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq)] #[serde(rename_all = "kebab-case")] pub struct ConfigSource { #[serde(default, skip_serializing_if = "HashMap::is_empty")] @@ -63,7 +63,7 @@ pub type TokenRef = String; pub type MetaboardRef = String; #[typeshare] -#[derive(Debug, Serialize, Deserialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "kebab-case")] pub struct NetworkConfigSource { pub rpc: Url, @@ -79,7 +79,7 @@ pub struct NetworkConfigSource { } #[typeshare] -#[derive(Debug, Serialize, Deserialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "kebab-case")] pub struct RemoteNetworksConfigSource { pub url: String, @@ -87,7 +87,7 @@ pub struct RemoteNetworksConfigSource { } #[typeshare] -#[derive(Debug, Serialize, Deserialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "kebab-case")] pub struct OrderbookConfigSource { pub address: Address, @@ -100,7 +100,7 @@ pub struct OrderbookConfigSource { } #[typeshare] -#[derive(Debug, Serialize, Deserialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "kebab-case")] pub struct TokenConfigSource { pub network: NetworkRef, @@ -114,7 +114,7 @@ pub struct TokenConfigSource { } #[typeshare] -#[derive(Debug, Serialize, Deserialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "kebab-case")] pub struct DeployerConfigSource { pub address: Address, @@ -125,7 +125,7 @@ pub struct DeployerConfigSource { } #[typeshare] -#[derive(Debug, Serialize, Deserialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "kebab-case")] pub struct DeploymentConfigSource { pub scenario: ScenarioRef, @@ -133,7 +133,7 @@ pub struct DeploymentConfigSource { } #[typeshare] -#[derive(Debug, Serialize, Deserialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "kebab-case")] pub struct IOString { pub token: TokenRef, @@ -143,7 +143,7 @@ pub struct IOString { } #[typeshare] -#[derive(Debug, Serialize, Deserialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "kebab-case")] pub struct OrderConfigSource { pub inputs: Vec, @@ -155,7 +155,7 @@ pub struct OrderConfigSource { } #[typeshare] -#[derive(Debug, Serialize, Deserialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "kebab-case")] pub struct ScenarioConfigSource { #[serde(default, skip_serializing_if = "HashMap::is_empty")] @@ -173,7 +173,7 @@ pub struct ScenarioConfigSource { } #[typeshare] -#[derive(Debug, Serialize, Deserialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "kebab-case")] pub struct ChartConfigSource { #[serde(skip_serializing_if = "Option::is_none")] diff --git a/tauri-app/src-tauri/Cargo.lock b/tauri-app/src-tauri/Cargo.lock index 9c0f07f5f..495ac2b88 100644 --- a/tauri-app/src-tauri/Cargo.lock +++ b/tauri-app/src-tauri/Cargo.lock @@ -1254,6 +1254,12 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "aurora-engine-modexp" version = "1.1.0" @@ -1414,7 +1420,7 @@ dependencies = [ "aws-smithy-types", "bytes", "fastrand", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "http-body 1.0.1", @@ -2688,6 +2694,18 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cynic-introspection" +version = "3.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1952cb2f976ddd5cb0c7268e8827fb5676fcd0d3281afcc8fbf07d8c6bd84218" +dependencies = [ + "cynic", + "cynic-codegen", + "indenter", + "thiserror", +] + [[package]] name = "cynic-parser" version = "0.4.5" @@ -4912,6 +4930,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", + "indexmap 2.4.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "half" version = "1.8.3" @@ -5162,7 +5199,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "httparse", @@ -5185,6 +5222,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", + "h2 0.4.6", "http 1.1.0", "http-body 1.0.1", "httparse", @@ -7796,7 +7834,7 @@ version = "0.0.1" dependencies = [ "alloy", "derive_builder 0.20.0", - "reqwest 0.11.27", + "reqwest 0.12.5", "serde", "serde_json", "serde_yaml", @@ -7843,7 +7881,7 @@ dependencies = [ "rain_orderbook_app_settings", "rain_orderbook_bindings", "rain_orderbook_subgraph_client", - "reqwest 0.11.27", + "reqwest 0.12.5", "serde", "serde-wasm-bindgen 0.6.5", "serde_bytes", @@ -7873,7 +7911,7 @@ dependencies = [ "rain-error-decoding", "rain_orderbook_bindings", "rain_orderbook_subgraph_client", - "reqwest 0.11.27", + "reqwest 0.12.5", "serde", "serde-wasm-bindgen 0.6.5", "serde_json", @@ -7896,8 +7934,9 @@ dependencies = [ "chrono", "cynic", "cynic-codegen", + "cynic-introspection", "rain_orderbook_bindings", - "reqwest 0.11.27", + "reqwest 0.12.5", "serde", "serde_json", "thiserror", @@ -8136,7 +8175,7 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.30", @@ -8177,9 +8216,11 @@ checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ "base64 0.22.1", "bytes", + "encoding_rs", "futures-channel", "futures-core", "futures-util", + "h2 0.4.6", "http 1.1.0", "http-body 1.0.1", "http-body-util", @@ -8204,6 +8245,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper 1.0.1", + "system-configuration", "tokio", "tokio-native-tls", "tokio-rustls 0.26.0", From 763c6018a4604cf9d2eb2a08c7f5b5a76dda1818 Mon Sep 17 00:00:00 2001 From: rouzwelt Date: Fri, 30 Aug 2024 21:53:14 +0000 Subject: [PATCH 5/6] update --- crates/cli/src/commands/order/calldata.rs | 4 +- crates/cli/src/commands/order/cleanup.rs | 4 +- .../src/commands/order/orderbook_address.rs | 3 +- crates/common/src/dotrain_order/filter.rs | 711 ++++++++++++++++++ .../mod.rs} | 23 +- crates/common/src/frontmatter.rs | 687 ----------------- crates/integration_tests/src/lib.rs | 4 +- crates/settings/src/config_source.rs | 1 + .../src-tauri/src/commands/trade_debug.rs | 2 +- tauri-app/src-tauri/src/error.rs | 2 +- 10 files changed, 741 insertions(+), 700 deletions(-) create mode 100644 crates/common/src/dotrain_order/filter.rs rename crates/common/src/{dotrain_order.rs => dotrain_order/mod.rs} (96%) diff --git a/crates/cli/src/commands/order/calldata.rs b/crates/cli/src/commands/order/calldata.rs index 7a0b57825..7cf3ff5ab 100644 --- a/crates/cli/src/commands/order/calldata.rs +++ b/crates/cli/src/commands/order/calldata.rs @@ -38,10 +38,10 @@ impl Execute for AddOrderCalldata { None => None, }; let order = DotrainOrder::new(dotrain, settings).await?; - let dotrain_string = order.dotrain.clone(); + let dotrain_string = order.dotrain().to_string(); let config_deployment = order - .config + .config() .deployments .get(&self.deployment) .ok_or(anyhow!("specified deployment is undefined!"))?; diff --git a/crates/cli/src/commands/order/cleanup.rs b/crates/cli/src/commands/order/cleanup.rs index fc2d65da1..4f2c22cbc 100644 --- a/crates/cli/src/commands/order/cleanup.rs +++ b/crates/cli/src/commands/order/cleanup.rs @@ -55,10 +55,10 @@ impl Execute for Cleanup { // handle output if let Some(output) = &self.output { - std::fs::write(output, &order.dotrain)?; + std::fs::write(output, order.dotrain())?; } if self.stdout { - println!("{}", order.dotrain); + println!("{}", order.dotrain()); } Ok(()) } diff --git a/crates/cli/src/commands/order/orderbook_address.rs b/crates/cli/src/commands/order/orderbook_address.rs index c19efa73c..5ef93352c 100644 --- a/crates/cli/src/commands/order/orderbook_address.rs +++ b/crates/cli/src/commands/order/orderbook_address.rs @@ -2,7 +2,6 @@ use crate::execute::Execute; use crate::output::{output, SupportedOutputEncoding}; use anyhow::{anyhow, Result}; use clap::Parser; -use rain_orderbook_app_settings::Config; use rain_orderbook_common::dotrain_order::DotrainOrder; use std::fs::read_to_string; use std::path::PathBuf; @@ -36,7 +35,7 @@ impl Execute for OrderbookAddress { None => None, }; let order = DotrainOrder::new(dotrain, settings).await?; - let order_config: Config = order.clone().config; + let order_config = order.config().clone(); let deployment_ref = order_config .deployments .get(&self.deployment) diff --git a/crates/common/src/dotrain_order/filter.rs b/crates/common/src/dotrain_order/filter.rs new file mode 100644 index 000000000..836d2feb7 --- /dev/null +++ b/crates/common/src/dotrain_order/filter.rs @@ -0,0 +1,711 @@ +use crate::dotrain_order::{DotrainOrder, DotrainOrderError}; +pub use rain_metadata::types::authoring::v2::*; +use rain_orderbook_app_settings::config_source::ConfigSource; + +impl DotrainOrder { + /// Creates a new instance with a clean frontmatter that only includes the + /// specified deployments and their related fields + pub async fn new_with_deployments_frontmatter( + dotrain: String, + config: Option, + deployments: &[&str], + ) -> Result { + Self::new(dotrain, config) + .await? + .clean_unused_frontmatter_by_deployments(deployments) + .await + } + + /// Generates a new instance with a frontmatter that only includes the + /// specified deployments and their related fields + pub async fn clean_unused_frontmatter_by_deployments( + &self, + deployments: &[&str], + ) -> Result { + // new empty config to copy used fields into + let mut new_config_source = ConfigSource::default(); + let config_source = &self.config_source; + + for deployment in deployments { + // find and insert the specified deployment + let deployment_ref = self.config.deployments.get(*deployment).ok_or( + DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined deployment: {}", + deployment + )), + )?; + new_config_source.deployments.insert( + deployment.to_string(), + config_source + .deployments + .get(*deployment) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined deployment: {}", + deployment + )))? + .clone(), + ); + + // find and insert the deployment scenario + // make sure to get the root scenario key + let scenario_ref = &deployment_ref.scenario; + let scenario_key = scenario_ref.name.split('.').nth(0).unwrap(); + new_config_source.scenarios.insert( + scenario_key.to_string(), + config_source + .scenarios + .get(scenario_key) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined scenario: {}", + scenario_key + )))? + .clone(), + ); + + // find and insert the deployment order + let (order_key, order) = self + .config + .orders + .iter() + .find(|(_, v)| *v == &deployment_ref.order) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined deployment order: {}", + deployment + )))?; + new_config_source.orders.insert( + order_key.clone(), + config_source + .orders + .get(order_key) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined order: {}", + order_key + )))? + .clone(), + ); + + // find and insert the deployment scenario deployer + let (deployer_key, deployer) = self + .config + .deployers + .iter() + .find(|(_, v)| *v == &scenario_ref.deployer) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined scenario deployer: {}", + scenario_key + )))?; + new_config_source.deployers.insert( + deployer_key.clone(), + config_source + .deployers + .get(deployer_key) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined deployer: {}", + deployer_key + )))? + .clone(), + ); + + // find and insert the deployment scenario deployer network + let (network_key, _) = self + .config + .networks + .iter() + .find(|(_, v)| *v == &deployer.network) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined scenario deployer network: {}", + scenario_key + )))?; + new_config_source.networks.insert( + network_key.clone(), + config_source + .networks + .get(network_key) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined network: {}", + network_key + )))? + .clone(), + ); + + // keep all network names to later on include charts if they happen to + // have the same network name as any of the names on this list + let mut all_network_keys = vec![]; + all_network_keys.push(network_key.as_str()); + + // find and insert the deployment order network + let (network_key, _) = self + .config + .networks + .iter() + .find(|(_, v)| *v == &order.network) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined order network: {}", + order_key + )))?; + new_config_source.networks.insert( + network_key.clone(), + config_source + .networks + .get(network_key) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined network: {}", + network_key + )))? + .clone(), + ); + if !all_network_keys.contains(&network_key.as_str()) { + all_network_keys.push(network_key.as_str()); + } + + // find and insert the deployment order deployer if it is present + if let Some(deployer_ref) = &order.deployer { + let (deployer_key, deployer) = self + .config + .deployers + .iter() + .find(|(_, v)| *v == deployer_ref) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined order deployer: {}", + order_key + )))?; + new_config_source.deployers.insert( + deployer_key.clone(), + config_source + .deployers + .get(deployer_key) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined order deployer: {}", + order_key + )))? + .clone(), + ); + + // find and insert the deployment order deployer network + let (network_key, _) = self + .config + .networks + .iter() + .find(|(_, v)| *v == &deployer.network) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined order deployer network: {}", + order_key + )))?; + new_config_source.networks.insert( + network_key.clone(), + config_source + .networks + .get(network_key) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined network: {}", + network_key + )))? + .clone(), + ); + if !all_network_keys.contains(&network_key.as_str()) { + all_network_keys.push(network_key.as_str()); + } + } + + // find and insert the deployment order orderbook if it is present + if let Some(orderbook_ref) = &order.orderbook { + let (orderbook_key, orderbook) = self + .config + .orderbooks + .iter() + .find(|(_, v)| *v == orderbook_ref) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined order orderbook: {}", + order_key + )))?; + new_config_source.orderbooks.insert( + orderbook_key.clone(), + config_source + .orderbooks + .get(orderbook_key) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined orderbook: {}", + orderbook_key + )))? + .clone(), + ); + + // find and insert the deployment order orderbook subgraph + let (sg_key, _) = self + .config + .subgraphs + .iter() + .find(|(_, v)| *v == &orderbook_ref.subgraph) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined order orderbook subgraph: {}", + order_key + )))?; + new_config_source.subgraphs.insert( + sg_key.clone(), + config_source + .subgraphs + .get(sg_key) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined subgraph: {}", + sg_key + )))? + .clone(), + ); + + // find and insert the deployment order orderbook network + let (network_key, _) = self + .config + .networks + .iter() + .find(|(_, v)| *v == &orderbook.network) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined order orderbook network: {}", + order_key + )))?; + new_config_source.networks.insert( + network_key.clone(), + config_source + .networks + .get(network_key) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined network: {}", + network_key + )))? + .clone(), + ); + if !all_network_keys.contains(&network_key.as_str()) { + all_network_keys.push(network_key.as_str()); + } + } + + // find and insert the deployment order inputs + for io in &order.inputs { + let (token_key, token) = self + .config + .tokens + .iter() + .find(|(_, v)| *v == &io.token) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError( + format!("undefined order input token: {}", order_key), + ))?; + new_config_source.tokens.insert( + token_key.clone(), + config_source + .tokens + .get(token_key) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined token: {}", + token_key + )))? + .clone(), + ); + + // find and insert the deployment order input network + let (network_key, _) = self + .config + .networks + .iter() + .find(|(_, v)| *v == &token.network) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined order input token network: {}", + token_key + )))?; + new_config_source.networks.insert( + network_key.clone(), + config_source + .networks + .get(network_key) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined network: {}", + network_key + )))? + .clone(), + ); + if !all_network_keys.contains(&network_key.as_str()) { + all_network_keys.push(network_key.as_str()); + } + } + + // // find and insert the deployment order outputs + for io in &order.outputs { + let (token_key, token) = self + .config + .tokens + .iter() + .find(|(_, v)| *v == &io.token) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError( + format!("undefined order output token: {}", order_key), + ))?; + new_config_source.tokens.insert( + token_key.clone(), + config_source + .tokens + .get(token_key) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined token: {}", + token_key + )))? + .clone(), + ); + + // find and insert the deployment order output network + let (network_key, _) = self + .config + .networks + .iter() + .find(|(_, v)| *v == &token.network) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined order output token network: {}", + token_key + )))?; + new_config_source.networks.insert( + network_key.clone(), + config_source + .networks + .get(network_key) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined network: {}", + network_key + )))? + .clone(), + ); + if !all_network_keys.contains(&network_key.as_str()) { + all_network_keys.push(network_key.as_str()); + } + } + + // find and insert charts that reference the scenario or if they have + // 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()) + { + new_config_source.charts.insert( + chart_key.clone(), + config_source + .charts + .get(chart_key) + .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( + "undefined chart: {}", + chart_key + )))? + .clone(), + ); + } + } + } + + // reserialize the new config and construct a new dotrain order with existing dotrain body + let mut new_dotrain = serde_yaml::to_string(&new_config_source) + .map_err(|e| DotrainOrderError::CleanUnusedFrontmatterError(e.to_string()))?; + new_dotrain.push_str("\n---\n"); + new_dotrain.push_str(self.dotrain.split("---").nth(1).unwrap()); + + Self::new(new_dotrain, None).await + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn test_clean_unused_frontmatter_by_deployments_happy() { + let setting = r#" +networks: + some-network: + rpc: https://abcd.com + chain-id: 123 + network-id: 123 + currency: ETH + n2: + rpc: https://efgh.com + chain-id: 44 + network-id: 44 + currency: RRR + +subgraphs: + some-sg: https://www.some-sg.com + sg2: https://www.sg2.com + +deployers: + some-deployer: + network: some-network + address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba + d2: + network: n2 + address: 0xF14E09601A47552De6aBd3A0B165607FaFd22134 + +orderbooks: + some-orderbook: + address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 + network: some-network + subgraph: some-sg + ob2: + address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 + network: n2 + subgraph: sg2 +"#; + let dotrain = r#" +tokens: + token1: + network: some-network + address: 0xc2132d05d31c914a87c6611c10748aeb04b58e8f + decimals: 6 + label: T1 + symbol: T1 + token2: + network: some-network + address: 0x8f3cf7ad23cd3cadbd9735aff958023239c6a063 + decimals: 18 + label: T2 + symbol: T2 + token3: + network: some-network + address: 0x8f3cf7ad23cd3cadbd9735aff958023239c6a063 + decimals: 77 + label: T3 + symbol: T3 + +scenarios: + some-scenario: + network: some-network + deployer: some-deployer + scenarios: + child-scenario: + bindings: + key1: value1 + s2: + network: n2 + deployer: d2 + scenarios: + child-scenario: + bindings: + key1: value1 + key2: value2 + +orders: + some-order: + inputs: + - token: token1 + vault-id: 1 + outputs: + - token: token1 + vault-id: 1 + deployer: some-deployer + orderbook: some-orderbook + +deployments: + some-deployment: + scenario: some-scenario.child-scenario + order: some-order + +charts: + some-chart: + scenario: some-scenario + metrics: + - label: A metric + description: A description + unit-prefix: $ + unit-suffix: USD + value: 0.1 + plots: + plot1: + title: "My plot" + subtitle: "My subtitle" + marks: + - type: dot + options: + x: "0.1" + y: "0.2" + stroke: "black" + other-chart: + scenario: s2 + metrics: + - label: B metric + description: B description + unit-prefix: $ + unit-suffix: EUR + value: 0.1 + another-chart: + scenario: s2.child-scenario + metrics: + - label: A metric + description: A description + unit-prefix: $ + unit-suffix: USD + value: 0.1 +--- +#calculate-io +_ _: 0 0; +#handle-io +:; +#handle-add-order +:;"#; + + let result = DotrainOrder::new_with_deployments_frontmatter( + dotrain.to_string(), + Some(setting.to_string()), + &["some-deployment"], + ) + .await + .unwrap(); + + let expected_dotrain = r#"networks: + some-network: + rpc: https://abcd.com/ + chain-id: 123 + network-id: 123 + currency: ETH +subgraphs: + some-sg: https://www.some-sg.com/ +orderbooks: + some-orderbook: + address: 0xc95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a6 + network: some-network + subgraph: some-sg +tokens: + token1: + network: some-network + address: 0xc2132d05d31c914a87c6611c10748aeb04b58e8f + decimals: 6 + label: T1 + symbol: T1 +deployers: + some-deployer: + address: 0xf14e09601a47552de6abd3a0b165607fafd2b5ba + network: some-network +orders: + some-order: + inputs: + - token: token1 + vault-id: '0x1' + outputs: + - token: token1 + vault-id: '0x1' + deployer: some-deployer + orderbook: some-orderbook +scenarios: + some-scenario: + deployer: some-deployer + scenarios: + child-scenario: + bindings: + key1: value1 +charts: + some-chart: + scenario: some-scenario + plots: + plot1: + title: My plot + subtitle: My subtitle + marks: + - type: dot + options: + x: '0.1' + y: '0.2' + stroke: black + metrics: + - label: A metric + description: A description + unit-prefix: $ + unit-suffix: USD + value: '0.1' +deployments: + some-deployment: + scenario: some-scenario.child-scenario + order: some-order + +--- + +#calculate-io +_ _: 0 0; +#handle-io +:; +#handle-add-order +:;"#; + + let expected = DotrainOrder::new(expected_dotrain.to_string(), None) + .await + .unwrap(); + + assert_eq!(result, expected); + } + + #[tokio::test] + async fn test_clean_unused_frontmatter_by_deployments_unhappy() { + let setting = r#" +networks: + some-network: + rpc: https://abcd.com + chain-id: 123 + network-id: 123 + currency: ETH + +subgraphs: + some-sg: https://www.some-sg.com + +deployers: + some-deployer: + network: some-network + address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba + +orderbooks: + some-orderbook: + address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 + network: some-network + subgraph: some-sg +"#; + let dotrain = r#" +tokens: + token1: + network: some-network + address: 0xc2132d05d31c914a87c6611c10748aeb04b58e8f + decimals: 6 + label: T1 + symbol: T1 + +scenarios: + some-scenario: + network: some-network + deployer: some-deployer + scenarios: + child-scenario: + bindings: + key1: value1 + +orders: + some-order: + inputs: + - token: token1 + vault-id: 1 + outputs: + - token: token1 + vault-id: 1 + deployer: some-deployer + +deployments: + some-deployment: + scenario: some-scenario.child-scenario + order: some-order +--- +#calculate-io +_ _: 0 0; +#handle-io +:; +#handle-add-order +:;"#; + + let result = DotrainOrder::new_with_deployments_frontmatter( + dotrain.to_string(), + Some(setting.to_string()), + &["some-other-deployment"], + ) + .await; + + matches!( + result, + Err(DotrainOrderError::CleanUnusedFrontmatterError(_)) + ); + } +} diff --git a/crates/common/src/dotrain_order.rs b/crates/common/src/dotrain_order/mod.rs similarity index 96% rename from crates/common/src/dotrain_order.rs rename to crates/common/src/dotrain_order/mod.rs index 8744ba9b6..194c970fd 100644 --- a/crates/common/src/dotrain_order.rs +++ b/crates/common/src/dotrain_order/mod.rs @@ -15,11 +15,13 @@ use rain_orderbook_app_settings::{ use rain_orderbook_env::GH_COMMIT_SHA; use thiserror::Error; +pub mod filter; + #[derive(Debug, Clone, PartialEq)] pub struct DotrainOrder { - pub config: Config, - pub dotrain: String, - pub config_source: ConfigSource, + config: Config, + dotrain: String, + config_source: ConfigSource, } #[derive(Error, Debug)] @@ -91,6 +93,21 @@ impl DotrainOrder { } } + // get this instance's config + pub fn config(&self) -> &Config { + &self.config + } + + // get this instance's config source + pub fn config_source(&self) -> &ConfigSource { + &self.config_source + } + + // get this instance's dotrain string + pub fn dotrain(&self) -> &str { + &self.dotrain + } + pub async fn compose_scenario_to_rainlang( &self, scenario: String, diff --git a/crates/common/src/frontmatter.rs b/crates/common/src/frontmatter.rs index d04e17483..d2a71807d 100644 --- a/crates/common/src/frontmatter.rs +++ b/crates/common/src/frontmatter.rs @@ -1,4 +1,3 @@ -use crate::dotrain_order::{DotrainOrder, DotrainOrderError}; use dotrain::RainDocument; pub use rain_metadata::types::authoring::v2::*; use rain_orderbook_app_settings::{config::ParseConfigSourceError, config_source::ConfigSource}; @@ -8,689 +7,3 @@ pub async fn parse_frontmatter(dotrain: String) -> Result, - deployments: &[&str], - ) -> Result { - Self::new(dotrain, config) - .await? - .clean_unused_frontmatter_by_deployments(deployments) - .await - } - - /// Generates a new instance with a frontmatter that only includes the - /// specified deployments and their related fields - pub async fn clean_unused_frontmatter_by_deployments( - &self, - deployments: &[&str], - ) -> Result { - let config_org = &self.config_source; - - // new empty config to copy used field into - let mut new_config = ConfigSource::default(); - for deployment in deployments { - // find and insert the specified deployment - let deployment_ref = self.config.deployments.get(*deployment).ok_or( - DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined deployment: {}", - deployment - )), - )?; - new_config.deployments.insert( - deployment.to_string(), - config_org - .deployments - .get(*deployment) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined deployment: {}", - deployment - )))? - .clone(), - ); - - // find and insert the deployment scenario - // make sure to get the root scenario key - let scenario_main = &deployment_ref.scenario; - let scenario_key = scenario_main.name.split('.').nth(0).unwrap(); - new_config.scenarios.insert( - scenario_key.to_string(), - config_org - .scenarios - .get(scenario_key) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined scenario: {}", - scenario_key - )))? - .clone(), - ); - - // find and insert charts that reference the scenario - for (chart_key, chart) in &self.config.charts { - if chart.scenario.name.split('.').nth(0).unwrap() == scenario_key { - new_config.charts.insert( - chart_key.clone(), - config_org - .charts - .get(chart_key) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined chart: {}", - chart_key - )))? - .clone(), - ); - } - } - - // find and insert the deployment order - let (order_key, order) = self - .config - .orders - .iter() - .find(|(_, v)| *v == &deployment_ref.order) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined deployment order: {}", - deployment - )))?; - new_config.orders.insert( - order_key.clone(), - config_org - .orders - .get(order_key) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined order: {}", - order_key - )))? - .clone(), - ); - - // find and insert the deployment scenario deployer - let (deployer_key, deployer) = self - .config - .deployers - .iter() - .find(|(_, v)| *v == &scenario_main.deployer) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined scenario deployer: {}", - scenario_key - )))?; - new_config.deployers.insert( - deployer_key.clone(), - config_org - .deployers - .get(deployer_key) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined deployer: {}", - deployer_key - )))? - .clone(), - ); - - // find and insert the deployment scenario deployer network - let (network_key, _) = self - .config - .networks - .iter() - .find(|(_, v)| *v == &deployer.network) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined scenario deployer network: {}", - scenario_key - )))?; - new_config.networks.insert( - network_key.clone(), - config_org - .networks - .get(network_key) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined network: {}", - network_key - )))? - .clone(), - ); - - // find and insert the deployment order network - let (network_key, _) = self - .config - .networks - .iter() - .find(|(_, v)| *v == &order.network) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined order network: {}", - order_key - )))?; - new_config.networks.insert( - network_key.clone(), - config_org - .networks - .get(network_key) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined network: {}", - network_key - )))? - .clone(), - ); - - // find and insert the deployment order deployer if it is present - if let Some(deployer_ref) = &order.deployer { - let (deployer_key, deployer) = self - .config - .deployers - .iter() - .find(|(_, v)| *v == deployer_ref) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined order deployer: {}", - order_key - )))?; - new_config.deployers.insert( - deployer_key.clone(), - config_org - .deployers - .get(deployer_key) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined order deployer: {}", - order_key - )))? - .clone(), - ); - - // find and insert the deployment order deployer network - let (network_key, _) = self - .config - .networks - .iter() - .find(|(_, v)| *v == &deployer.network) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined order deployer network: {}", - order_key - )))?; - new_config.networks.insert( - network_key.clone(), - config_org - .networks - .get(network_key) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined network: {}", - network_key - )))? - .clone(), - ); - } - - // find and insert the deployment order orderbook if it is present - if let Some(orderbook_ref) = &order.orderbook { - let (orderbook_key, orderbook) = self - .config - .orderbooks - .iter() - .find(|(_, v)| *v == orderbook_ref) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined order orderbook: {}", - order_key - )))?; - new_config.orderbooks.insert( - orderbook_key.clone(), - config_org - .orderbooks - .get(orderbook_key) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined orderbook: {}", - orderbook_key - )))? - .clone(), - ); - - // find and insert the deployment order orderbook subgraph - let (sg_key, _) = self - .config - .subgraphs - .iter() - .find(|(_, v)| *v == &orderbook_ref.subgraph) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined order orderbook subgraph: {}", - order_key - )))?; - new_config.subgraphs.insert( - sg_key.clone(), - config_org - .subgraphs - .get(sg_key) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined subgraph: {}", - sg_key - )))? - .clone(), - ); - - // find and insert the deployment order orderbook network - let (network_key, _) = self - .config - .networks - .iter() - .find(|(_, v)| *v == &orderbook.network) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined order orderbook network: {}", - order_key - )))?; - new_config.networks.insert( - network_key.clone(), - config_org - .networks - .get(network_key) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined network: {}", - network_key - )))? - .clone(), - ); - } - - // find and insert the deployment order inputs - for io in &order.inputs { - let (token_key, token) = self - .config - .tokens - .iter() - .find(|(_, v)| *v == &io.token) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError( - format!("undefined order input token: {}", order_key), - ))?; - new_config.tokens.insert( - token_key.clone(), - config_org - .tokens - .get(token_key) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined token: {}", - token_key - )))? - .clone(), - ); - - // find and insert the deployment order input network - let (network_key, _) = self - .config - .networks - .iter() - .find(|(_, v)| *v == &token.network) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined order input token network: {}", - token_key - )))?; - new_config.networks.insert( - network_key.clone(), - config_org - .networks - .get(network_key) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined network: {}", - network_key - )))? - .clone(), - ); - } - - // // find and insert the deployment order outputs - for io in &order.outputs { - let (token_key, token) = self - .config - .tokens - .iter() - .find(|(_, v)| *v == &io.token) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError( - format!("undefined order output token: {}", order_key), - ))?; - new_config.tokens.insert( - token_key.clone(), - config_org - .tokens - .get(token_key) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined token: {}", - token_key - )))? - .clone(), - ); - - // find and insert the deployment order output network - let (network_key, _) = self - .config - .networks - .iter() - .find(|(_, v)| *v == &token.network) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined order output token network: {}", - token_key - )))?; - new_config.networks.insert( - network_key.clone(), - config_org - .networks - .get(network_key) - .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined network: {}", - network_key - )))? - .clone(), - ); - } - } - - // reserialize the new config and construct a new dotrain order with existing dotrain body - let mut new_dotrain = serde_yaml::to_string(&new_config) - .map_err(|e| DotrainOrderError::CleanUnusedFrontmatterError(e.to_string()))?; - new_dotrain.push_str("\n---\n"); - new_dotrain.push_str(self.dotrain.split("---").nth(1).unwrap()); - - Self::new(new_dotrain, None).await - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[tokio::test] - async fn test_to_clean_frontmatter_with_deplyments_happy() { - let setting = r#" -networks: - some-network: - rpc: https://abcd.com - chain-id: 123 - network-id: 123 - currency: ETH - n2: - rpc: https://efgh.com - chain-id: 44 - network-id: 44 - currency: RRR - -subgraphs: - some-sg: https://www.some-sg.com - sg2: https://www.sg2.com - -deployers: - some-deployer: - network: some-network - address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba - d2: - network: some-network - address: 0xF14E09601A47552De6aBd3A0B165607FaFd22134 - -orderbooks: - some-orderbook: - address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 - network: some-network - subgraph: some-sg - ob2: - address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 - network: n2 - subgraph: sg2 -"#; - let dotrain = r#" -tokens: - token1: - network: some-network - address: 0xc2132d05d31c914a87c6611c10748aeb04b58e8f - decimals: 6 - label: T1 - symbol: T1 - token2: - network: some-network - address: 0x8f3cf7ad23cd3cadbd9735aff958023239c6a063 - decimals: 18 - label: T2 - symbol: T2 - token3: - network: some-network - address: 0x8f3cf7ad23cd3cadbd9735aff958023239c6a063 - decimals: 77 - label: T3 - symbol: T3 - -scenarios: - some-scenario: - network: some-network - deployer: some-deployer - scenarios: - child-scenario: - bindings: - key1: value1 - s2: - network: some-network - deployer: d2 - scenarios: - child-scenario: - bindings: - key1: value1 - key2: value2 - -orders: - some-order: - inputs: - - token: token1 - vault-id: 1 - outputs: - - token: token1 - vault-id: 1 - deployer: some-deployer - orderbook: some-orderbook - -deployments: - some-deployment: - scenario: some-scenario.child-scenario - order: some-order - -charts: - some-chart: - scenario: some-scenario - metrics: - - label: A metric - description: A description - unit-prefix: $ - unit-suffix: USD - value: 0.1 - plots: - plot1: - title: "My plot" - subtitle: "My subtitle" - marks: - - type: dot - options: - x: "0.1" - y: "0.2" - stroke: "black" - other-chart: - scenario: s2 - metrics: - - label: B metric - description: B description - unit-prefix: $ - unit-suffix: EUR - value: 0.1 - another-chart: - scenario: s2.child-scenario - metrics: - - label: A metric - description: A description - unit-prefix: $ - unit-suffix: USD - value: 0.1 ---- -#calculate-io -_ _: 0 0; -#handle-io -:; -#handle-add-order -:;"#; - - let result = DotrainOrder::new_with_deployments_frontmatter( - dotrain.to_string(), - Some(setting.to_string()), - &["some-deployment"], - ) - .await - .unwrap(); - - let expected_dotrain = r#"networks: - some-network: - rpc: https://abcd.com/ - chain-id: 123 - network-id: 123 - currency: ETH -subgraphs: - some-sg: https://www.some-sg.com/ -orderbooks: - some-orderbook: - address: 0xc95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a6 - network: some-network - subgraph: some-sg -tokens: - token1: - network: some-network - address: 0xc2132d05d31c914a87c6611c10748aeb04b58e8f - decimals: 6 - label: T1 - symbol: T1 -deployers: - some-deployer: - address: 0xf14e09601a47552de6abd3a0b165607fafd2b5ba - network: some-network -orders: - some-order: - inputs: - - token: token1 - vault-id: '0x1' - outputs: - - token: token1 - vault-id: '0x1' - deployer: some-deployer - orderbook: some-orderbook -scenarios: - some-scenario: - deployer: some-deployer - scenarios: - child-scenario: - bindings: - key1: value1 -charts: - some-chart: - scenario: some-scenario - plots: - plot1: - title: My plot - subtitle: My subtitle - marks: - - type: dot - options: - x: '0.1' - y: '0.2' - stroke: black - metrics: - - label: A metric - description: A description - unit-prefix: $ - unit-suffix: USD - value: '0.1' -deployments: - some-deployment: - scenario: some-scenario.child-scenario - order: some-order - ---- - -#calculate-io -_ _: 0 0; -#handle-io -:; -#handle-add-order -:;"#; - - let expected = DotrainOrder::new(expected_dotrain.to_string(), None) - .await - .unwrap(); - - assert_eq!(result.config, expected.config); - assert_eq!(result.dotrain, expected.dotrain); - } - - #[tokio::test] - async fn test_to_clean_frontmatter_with_deplyments_unhappy() { - let setting = r#" -networks: - some-network: - rpc: https://abcd.com - chain-id: 123 - network-id: 123 - currency: ETH - -subgraphs: - some-sg: https://www.some-sg.com - -deployers: - some-deployer: - network: some-network - address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba - -orderbooks: - some-orderbook: - address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 - network: some-network - subgraph: some-sg -"#; - let dotrain = r#" -tokens: - token1: - network: some-network - address: 0xc2132d05d31c914a87c6611c10748aeb04b58e8f - decimals: 6 - label: T1 - symbol: T1 - -scenarios: - some-scenario: - network: some-network - deployer: some-deployer - scenarios: - child-scenario: - bindings: - key1: value1 - -orders: - some-order: - inputs: - - token: token1 - vault-id: 1 - outputs: - - token: token1 - vault-id: 1 - deployer: some-deployer - -deployments: - some-deployment: - scenario: some-scenario.child-scenario - order: some-order ---- -#calculate-io -_ _: 0 0; -#handle-io -:; -#handle-add-order -:;"#; - - let result = DotrainOrder::new_with_deployments_frontmatter( - dotrain.to_string(), - Some(setting.to_string()), - &["some-other-deployment"], - ) - .await; - - matches!( - result, - Err(DotrainOrderError::CleanUnusedFrontmatterError(_)) - ); - } -} diff --git a/crates/integration_tests/src/lib.rs b/crates/integration_tests/src/lib.rs index 726b156c2..fec3363a2 100644 --- a/crates/integration_tests/src/lib.rs +++ b/crates/integration_tests/src/lib.rs @@ -99,7 +99,7 @@ amount price: get("amount") 52; let order = DotrainOrder::new(dotrain.clone(), None).await.unwrap(); - let deployment = order.config.deployments["polygon"].as_ref().clone(); + let deployment = order.config().deployments["polygon"].as_ref().clone(); let args = AddOrderArgs::new_from_deployment(dotrain, deployment) .await @@ -250,7 +250,7 @@ amount price: get("amount") 52; let order = DotrainOrder::new(dotrain.clone(), None).await.unwrap(); - let deployment = order.config.deployments["polygon"].as_ref().clone(); + let deployment = order.config().deployments["polygon"].as_ref().clone(); let args = AddOrderArgs::new_from_deployment(dotrain, deployment) .await diff --git a/crates/settings/src/config_source.rs b/crates/settings/src/config_source.rs index 8dfca797c..9c22fb4d3 100644 --- a/crates/settings/src/config_source.rs +++ b/crates/settings/src/config_source.rs @@ -36,6 +36,7 @@ pub struct ConfigSource { pub metaboards: HashMap, #[serde(skip_serializing_if = "Option::is_none")] pub sentry: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub raindex_version: Option, } diff --git a/tauri-app/src-tauri/src/commands/trade_debug.rs b/tauri-app/src-tauri/src/commands/trade_debug.rs index 0b476e66f..373327831 100644 --- a/tauri-app/src-tauri/src/commands/trade_debug.rs +++ b/tauri-app/src-tauri/src/commands/trade_debug.rs @@ -11,7 +11,7 @@ pub async fn debug_trade(tx_hash: String, rpc_url: String) -> CommandResult()?; let res = replayer.replay_tx(tx_hash).await?; - let stack = res.traces[1].stack.iter().map(|x| x.clone()).collect(); + let stack = res.traces[1].stack.to_vec(); Ok(stack) } diff --git a/tauri-app/src-tauri/src/error.rs b/tauri-app/src-tauri/src/error.rs index 1160eae56..a6f9df3d6 100644 --- a/tauri-app/src-tauri/src/error.rs +++ b/tauri-app/src-tauri/src/error.rs @@ -1,7 +1,7 @@ use alloy::hex::FromHexError; use alloy::primitives::ruint::{FromUintError, ParseError as FromUintParseError}; use alloy_ethers_typecast::{client::LedgerClientError, transaction::ReadableClientError}; -use dotrain::error::{self, ComposeError}; +use dotrain::error::ComposeError; use rain_orderbook_app_settings::config::ParseConfigSourceError; use rain_orderbook_app_settings::config_source::ConfigSourceError; use rain_orderbook_app_settings::merge::MergeError; From 2eb8266abab3f3e2d1d4beffbf7360d928df2186 Mon Sep 17 00:00:00 2001 From: rouzwelt Date: Mon, 2 Sep 2024 03:03:22 +0000 Subject: [PATCH 6/6] apply review changes --- .../commands/order/{cleanup.rs => filter.rs} | 20 ++--- crates/cli/src/commands/order/mod.rs | 8 +- crates/common/src/dotrain_order/filter.rs | 74 +++++++++---------- 3 files changed, 51 insertions(+), 51 deletions(-) rename crates/cli/src/commands/order/{cleanup.rs => filter.rs} (90%) diff --git a/crates/cli/src/commands/order/cleanup.rs b/crates/cli/src/commands/order/filter.rs similarity index 90% rename from crates/cli/src/commands/order/cleanup.rs rename to crates/cli/src/commands/order/filter.rs index 4f2c22cbc..978f95a4b 100644 --- a/crates/cli/src/commands/order/cleanup.rs +++ b/crates/cli/src/commands/order/filter.rs @@ -8,7 +8,7 @@ use std::path::PathBuf; /// Generate a new .rain with unused frontmatter cleaned, ie frontmatter will only include the /// specified deployments (and their related fields) from a given .rain and an optional setting.yml #[derive(Parser, Clone)] -pub struct Cleanup { +pub struct Filter { /// Path to the .rain file #[arg(short = 'f', long, value_name = "PATH")] dotrain_file: PathBuf, @@ -30,7 +30,7 @@ pub struct Cleanup { pub stdout: bool, } -impl Execute for Cleanup { +impl Execute for Filter { async fn execute(&self) -> Result<()> { // read inpput files let dotrain = read_to_string(self.dotrain_file.clone()).map_err(|e| anyhow!(e))?; @@ -42,7 +42,7 @@ impl Execute for Cleanup { }; // generate new dotrain order instance with cleaned up frontmatter - let order = DotrainOrder::new_with_deployments_frontmatter( + let order = DotrainOrder::new_with_frontmatter_filtered_by_deployment( dotrain, settings, &self @@ -71,7 +71,7 @@ mod tests { #[test] fn verify_cli() { - Cleanup::command().debug_assert(); + Filter::command().debug_assert(); } #[tokio::test] @@ -145,12 +145,12 @@ _ _: 0 0; #handle-add-order :;"#; - let dotrain_path = "./test_dotrain_cleanup.rain"; - let settings_path = "./test_settings_cleanup.yml"; + let dotrain_path = "./test_dotrain_filter.rain"; + let settings_path = "./test_settings_filter.yml"; std::fs::write(dotrain_path, dotrain).unwrap(); std::fs::write(settings_path, setting).unwrap(); - let cleanup = Cleanup { + let filter = Filter { dotrain_file: dotrain_path.into(), settings_file: Some(settings_path.into()), deployments: vec!["some-deployment".to_string()], @@ -158,7 +158,7 @@ _ _: 0 0; stdout: true, }; - assert!(cleanup.execute().await.is_ok()); + assert!(filter.execute().await.is_ok()); std::fs::remove_file(dotrain_path).unwrap(); std::fs::remove_file(settings_path).unwrap(); @@ -166,7 +166,7 @@ _ _: 0 0; #[tokio::test] async fn test_execute_unhappy() { - let cleanup = Cleanup { + let filter = Filter { dotrain_file: "./bad-path/test.rain".into(), settings_file: None, deployments: vec!["some-deployment".to_string()], @@ -174,6 +174,6 @@ _ _: 0 0; stdout: true, }; - assert!(cleanup.execute().await.is_err()); + assert!(filter.execute().await.is_err()); } } diff --git a/crates/cli/src/commands/order/mod.rs b/crates/cli/src/commands/order/mod.rs index 8c98292f4..52bce6652 100644 --- a/crates/cli/src/commands/order/mod.rs +++ b/crates/cli/src/commands/order/mod.rs @@ -1,8 +1,8 @@ mod add; mod calldata; -mod cleanup; mod compose; mod detail; +mod filter; mod list; mod orderbook_address; mod remove; @@ -13,8 +13,8 @@ use add::CliOrderAddArgs; use anyhow::Result; use calldata::AddOrderCalldata; use clap::Parser; -use cleanup::Cleanup; use compose::Compose; +use filter::Filter; use detail::CliOrderDetailArgs; use list::CliOrderListArgs; @@ -50,7 +50,7 @@ pub enum Order { OrderbookAddress(OrderbookAddress), #[command()] - Cleanup(Cleanup), + Filter(Filter), } impl Execute for Order { @@ -63,7 +63,7 @@ impl Execute for Order { Order::Compose(compose) => compose.execute().await, Order::Calldata(calldata) => calldata.execute().await, Order::OrderbookAddress(orderbook_address) => orderbook_address.execute().await, - Order::Cleanup(cleanup) => cleanup.execute().await, + Order::Filter(filter) => filter.execute().await, } } } diff --git a/crates/common/src/dotrain_order/filter.rs b/crates/common/src/dotrain_order/filter.rs index 836d2feb7..d884daba3 100644 --- a/crates/common/src/dotrain_order/filter.rs +++ b/crates/common/src/dotrain_order/filter.rs @@ -5,20 +5,20 @@ use rain_orderbook_app_settings::config_source::ConfigSource; impl DotrainOrder { /// Creates a new instance with a clean frontmatter that only includes the /// specified deployments and their related fields - pub async fn new_with_deployments_frontmatter( + pub async fn new_with_frontmatter_filtered_by_deployment( dotrain: String, config: Option, deployments: &[&str], ) -> Result { Self::new(dotrain, config) .await? - .clean_unused_frontmatter_by_deployments(deployments) + .filter_by_deployment(deployments) .await } /// Generates a new instance with a frontmatter that only includes the /// specified deployments and their related fields - pub async fn clean_unused_frontmatter_by_deployments( + pub async fn filter_by_deployment( &self, deployments: &[&str], ) -> Result { @@ -30,7 +30,7 @@ impl DotrainOrder { // find and insert the specified deployment let deployment_ref = self.config.deployments.get(*deployment).ok_or( DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined deployment: {}", + "Deployment \"{}\" not found", deployment )), )?; @@ -40,7 +40,7 @@ impl DotrainOrder { .deployments .get(*deployment) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined deployment: {}", + "Deployment \"{}\" not found", deployment )))? .clone(), @@ -56,7 +56,7 @@ impl DotrainOrder { .scenarios .get(scenario_key) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined scenario: {}", + "Scenario \"{}\" not found", scenario_key )))? .clone(), @@ -69,7 +69,7 @@ impl DotrainOrder { .iter() .find(|(_, v)| *v == &deployment_ref.order) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined deployment order: {}", + "Deployment \"{}\" order not found", deployment )))?; new_config_source.orders.insert( @@ -78,7 +78,7 @@ impl DotrainOrder { .orders .get(order_key) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined order: {}", + "Order \"{}\" not found", order_key )))? .clone(), @@ -91,7 +91,7 @@ impl DotrainOrder { .iter() .find(|(_, v)| *v == &scenario_ref.deployer) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined scenario deployer: {}", + "Scenario \"{}\" deployer not found", scenario_key )))?; new_config_source.deployers.insert( @@ -100,7 +100,7 @@ impl DotrainOrder { .deployers .get(deployer_key) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined deployer: {}", + "Deployer \"{}\" not found", deployer_key )))? .clone(), @@ -113,7 +113,7 @@ impl DotrainOrder { .iter() .find(|(_, v)| *v == &deployer.network) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined scenario deployer network: {}", + "Scenario \"{}\" deployer network not found", scenario_key )))?; new_config_source.networks.insert( @@ -122,7 +122,7 @@ impl DotrainOrder { .networks .get(network_key) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined network: {}", + "Network \"{}\" not found", network_key )))? .clone(), @@ -140,7 +140,7 @@ impl DotrainOrder { .iter() .find(|(_, v)| *v == &order.network) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined order network: {}", + "Order \"{}\" network not found", order_key )))?; new_config_source.networks.insert( @@ -149,7 +149,7 @@ impl DotrainOrder { .networks .get(network_key) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined network: {}", + "Network \"{}\" not found", network_key )))? .clone(), @@ -166,7 +166,7 @@ impl DotrainOrder { .iter() .find(|(_, v)| *v == deployer_ref) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined order deployer: {}", + "Order \"{}\" deployer not found", order_key )))?; new_config_source.deployers.insert( @@ -175,7 +175,7 @@ impl DotrainOrder { .deployers .get(deployer_key) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined order deployer: {}", + "Deployer \"{}\" not found", order_key )))? .clone(), @@ -188,7 +188,7 @@ impl DotrainOrder { .iter() .find(|(_, v)| *v == &deployer.network) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined order deployer network: {}", + "Order \"{}\" deployer network not found", order_key )))?; new_config_source.networks.insert( @@ -197,7 +197,7 @@ impl DotrainOrder { .networks .get(network_key) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined network: {}", + "Network \"{}\" not found", network_key )))? .clone(), @@ -215,7 +215,7 @@ impl DotrainOrder { .iter() .find(|(_, v)| *v == orderbook_ref) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined order orderbook: {}", + "Order \"{}\" orderbook not found", order_key )))?; new_config_source.orderbooks.insert( @@ -224,7 +224,7 @@ impl DotrainOrder { .orderbooks .get(orderbook_key) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined orderbook: {}", + "Orderbook \"{}\" not found", orderbook_key )))? .clone(), @@ -237,7 +237,7 @@ impl DotrainOrder { .iter() .find(|(_, v)| *v == &orderbook_ref.subgraph) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined order orderbook subgraph: {}", + "Order \"{}\" orderbook subgraph not found", order_key )))?; new_config_source.subgraphs.insert( @@ -246,7 +246,7 @@ impl DotrainOrder { .subgraphs .get(sg_key) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined subgraph: {}", + "Subgraph \"{}\" not found", sg_key )))? .clone(), @@ -259,7 +259,7 @@ impl DotrainOrder { .iter() .find(|(_, v)| *v == &orderbook.network) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined order orderbook network: {}", + "Order \"{}\" orderbook network not found", order_key )))?; new_config_source.networks.insert( @@ -268,7 +268,7 @@ impl DotrainOrder { .networks .get(network_key) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined network: {}", + "Network \"{}\" not found", network_key )))? .clone(), @@ -286,7 +286,7 @@ impl DotrainOrder { .iter() .find(|(_, v)| *v == &io.token) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError( - format!("undefined order input token: {}", order_key), + format!("Order \"{}\" input token not found", order_key), ))?; new_config_source.tokens.insert( token_key.clone(), @@ -294,7 +294,7 @@ impl DotrainOrder { .tokens .get(token_key) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined token: {}", + "Token \"{}\" not found", token_key )))? .clone(), @@ -307,7 +307,7 @@ impl DotrainOrder { .iter() .find(|(_, v)| *v == &token.network) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined order input token network: {}", + "Input token \"{}\" network not found", token_key )))?; new_config_source.networks.insert( @@ -316,7 +316,7 @@ impl DotrainOrder { .networks .get(network_key) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined network: {}", + "Network \"{}\" not found", network_key )))? .clone(), @@ -334,7 +334,7 @@ impl DotrainOrder { .iter() .find(|(_, v)| *v == &io.token) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError( - format!("undefined order output token: {}", order_key), + format!("Order \"{}\" output token not found", order_key), ))?; new_config_source.tokens.insert( token_key.clone(), @@ -342,7 +342,7 @@ impl DotrainOrder { .tokens .get(token_key) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined token: {}", + "Token \"{}\" not found", token_key )))? .clone(), @@ -355,7 +355,7 @@ impl DotrainOrder { .iter() .find(|(_, v)| *v == &token.network) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined order output token network: {}", + "Output token \"{}\" network not found", token_key )))?; new_config_source.networks.insert( @@ -364,7 +364,7 @@ impl DotrainOrder { .networks .get(network_key) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined network: {}", + "Network \"{}\" not found", network_key )))? .clone(), @@ -386,7 +386,7 @@ impl DotrainOrder { .charts .get(chart_key) .ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!( - "undefined chart: {}", + "Chart \"{}\" not found", chart_key )))? .clone(), @@ -410,7 +410,7 @@ mod tests { use super::*; #[tokio::test] - async fn test_clean_unused_frontmatter_by_deployments_happy() { + async fn test_filter_by_deployment_happy() { let setting = r#" networks: some-network: @@ -543,7 +543,7 @@ _ _: 0 0; #handle-add-order :;"#; - let result = DotrainOrder::new_with_deployments_frontmatter( + let result = DotrainOrder::new_with_frontmatter_filtered_by_deployment( dotrain.to_string(), Some(setting.to_string()), &["some-deployment"], @@ -633,7 +633,7 @@ _ _: 0 0; } #[tokio::test] - async fn test_clean_unused_frontmatter_by_deployments_unhappy() { + async fn test_filter_by_deployment_unhappy() { let setting = r#" networks: some-network: @@ -696,7 +696,7 @@ _ _: 0 0; #handle-add-order :;"#; - let result = DotrainOrder::new_with_deployments_frontmatter( + let result = DotrainOrder::new_with_frontmatter_filtered_by_deployment( dotrain.to_string(), Some(setting.to_string()), &["some-other-deployment"],