Skip to content

Commit

Permalink
moving composing to common crate
Browse files Browse the repository at this point in the history
  • Loading branch information
hardyjosh committed Apr 5, 2024
1 parent 9428287 commit 7f07f60
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 18 deletions.
38 changes: 21 additions & 17 deletions crates/cli/src/commands/order/compose.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ use crate::execute::Execute;
use crate::output::{output, SupportedOutputEncoding};
use anyhow::{anyhow, Result};
use clap::Args;
use rain_orderbook_app_settings::{config_source::ConfigSource, Config};
use rain_orderbook_common::dotrain::RainDocument;
use rain_orderbook_common::rainlang::compose_to_rainlang;
use rain_orderbook_common::dotrain_order::DotrainOrder;
use std::fs::read_to_string;
use std::path::PathBuf;

Expand All @@ -17,31 +15,37 @@ pub struct Compose {
)]
dotrain_file: PathBuf,

// path to the settings yaml
#[arg(
short = 'c',
long,
help = "Path to the settings yaml file",
default_value = "settings.yml"
)]
settings_file: Option<PathBuf>,

// the name of the scenrio to use
#[arg(short = 's', long, help = "The name of the scenario to use")]
scenario: String,

// supported encoding
#[arg(short = 'o', long, help = "Output encoding", default_value = "Binary")]
#[arg(short = 'o', long, help = "Output encoding", default_value = "binary")]
encoding: SupportedOutputEncoding,
}

impl Execute for Compose {
async fn execute(&self) -> Result<()> {
let dotrain = read_to_string(self.dotrain_file.clone()).map_err(|e| anyhow!(e))?;
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 scenario = config.scenarios.get(&self.scenario).ok_or_else(|| {
anyhow!(
"Scenario {} not found in file {}",
self.scenario,
self.dotrain_file.display()
)
})?;

let rainlang = compose_to_rainlang(dotrain, scenario.bindings.clone())?;
let settings = match &self.settings_file {
Some(settings_file) => {
Some(read_to_string(settings_file.clone()).map_err(|e| anyhow!(e))?)
}
None => None,
};
let rainlang = DotrainOrder::new(dotrain, settings)
.await?
.compose_scenario_to_rainlang(self.scenario.clone())
.await?;

output(&None, self.encoding.clone(), rainlang.as_bytes())?;

Expand Down
2 changes: 1 addition & 1 deletion crates/cli/src/commands/order/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub enum Order {
#[command(about = "Remove an Order", alias = "rm")]
Remove(CliOrderRemoveArgs),

#[command(about = "Compose a .rain order file to Rainlang", alias = "compose")]
#[command(about = "Compose a .rain order file to Rainlang", alias = "comp")]
Compose(Compose),
}

Expand Down
182 changes: 182 additions & 0 deletions crates/common/src/dotrain_order.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
use dotrain::{error::ComposeError, RainDocument};
use rain_orderbook_app_settings::{
config_source::{ConfigSource, ConfigSourceError},
merge::MergeError,
Config, ParseConfigSourceError,
};
use thiserror::Error;

use crate::rainlang::compose_to_rainlang;

pub struct DotrainOrder {
pub config: Config,
pub dotrain: String,
}

#[derive(Error, Debug)]
pub enum DotrainOrderError {
#[error(transparent)]
ConfigSourceError(#[from] ConfigSourceError),

#[error(transparent)]
ParseConfigSourceError(#[from] ParseConfigSourceError),

#[error("Scenario {0} not found")]
ScenarioNotFound(String),

#[error(transparent)]
ComposeError(#[from] ComposeError),

#[error(transparent)]
MergeConfigError(#[from] MergeError),
}

impl DotrainOrder {
pub async fn new(dotrain: String, config: Option<String>) -> Result<Self, DotrainOrderError> {
match config {
Some(config) => {
let config_string = ConfigSource::try_from_string(config).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: 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()?;
Ok(Self { dotrain, config })
}
}
}

pub async fn compose_scenario_to_rainlang(
&self,
scenario: String,
) -> Result<String, DotrainOrderError> {
let scenario = self
.config
.scenarios
.get(&scenario)
.ok_or_else(|| DotrainOrderError::ScenarioNotFound(scenario))?;

Ok(compose_to_rainlang(
self.dotrain.clone(),
scenario.bindings.clone(),
)?)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[tokio::test]
async fn test_config_parse() {
let dotrain = r#"
networks:
polygon:
rpc: https://rpc.ankr.com/polygon
chain-id: 137
network-id: 137
currency: MATIC
deployers:
polygon:
address: 0x1234567890123456789012345678901234567890
scenarios:
polygon:
---
#calculate-io
_ _: 0 0;
#handle-io
:;"#;

let dotrain_order = DotrainOrder::new(dotrain.to_string(), None).await.unwrap();

assert_eq!(
dotrain_order.config.networks.get("polygon").unwrap().rpc,
"https://rpc.ankr.com/polygon".parse().unwrap()
);
}

#[tokio::test]
async fn test_rainlang_from_scenario() {
let dotrain = r#"
networks:
polygon:
rpc: https://rpc.ankr.com/polygon
chain-id: 137
network-id: 137
currency: MATIC
deployers:
polygon:
address: 0x1234567890123456789012345678901234567890
scenarios:
polygon:
---
#calculate-io
_ _: 0 0;
#handle-io
:;"#;

let dotrain_order = DotrainOrder::new(dotrain.to_string(), None).await.unwrap();

let rainlang = dotrain_order
.compose_scenario_to_rainlang("polygon".to_string())
.await
.unwrap();

assert_eq!(
rainlang,
r#"/* 0. calculate-io */
_ _: 0 0;
/* 1. handle-io */
:;"#
);
}

#[tokio::test]
async fn test_config_merge() {
let dotrain = r#"
networks:
polygon:
rpc: https://rpc.ankr.com/polygon
chain-id: 137
network-id: 137
currency: MATIC
---
#calculate-io
_ _: 00;
#handle-io
:;"#;

let settings = r#"
networks:
mainnet:
rpc: https://1rpc.io/eth
chain-id: 1
network-id: 1
currency: ETH"#;

let merged_dotrain_order =
DotrainOrder::new(dotrain.to_string(), Some(settings.to_string()))
.await
.unwrap();

assert_eq!(
merged_dotrain_order
.config
.networks
.get("mainnet")
.unwrap()
.rpc,
"https://1rpc.io/eth".parse().unwrap()
);
}
}
1 change: 1 addition & 0 deletions crates/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod add_order;
pub mod csv;
pub mod deposit;
pub mod dotrain_add_order_lsp;
pub mod dotrain_order;
pub mod frontmatter;
pub mod fuzz;
pub mod meta;
Expand Down

0 comments on commit 7f07f60

Please sign in to comment.