Skip to content

Commit

Permalink
Merge pull request #884 from rainlanguage/2024-09-23-dotrain-order-wa…
Browse files Browse the repository at this point in the history
…sm-js

`DotrainOrder` wasm/js api
  • Loading branch information
hardyjosh authored Sep 25, 2024
2 parents 38389d4 + 87a245c commit 0767221
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 74 deletions.
6 changes: 1 addition & 5 deletions crates/cli/src/commands/order/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,8 @@ impl Execute for Filter {
// generate new dotrain order instance with cleaned up frontmatter
let order = DotrainOrder::new_with_frontmatter_filtered_by_deployment(
dotrain,
self.deployments.clone(),
settings,
&self
.deployments
.iter()
.map(String::as_str)
.collect::<Vec<&str>>(),
)
.await?;

Expand Down
24 changes: 16 additions & 8 deletions crates/common/src/dotrain_order/filter.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
use crate::dotrain_order::{DotrainOrder, DotrainOrderError};
pub use rain_metadata::types::authoring::v2::*;
use rain_orderbook_app_settings::config_source::ConfigSource;
#[cfg(target_family = "wasm")]
use wasm_bindgen::prelude::*;

#[cfg_attr(target_family = "wasm", wasm_bindgen)]
impl DotrainOrder {
/// Creates a new instance with a clean frontmatter that only includes the
/// specified deployments and their related fields
#[cfg_attr(
target_family = "wasm",
wasm_bindgen(js_name = "newWithFrontmatterFilteredByDeployment")
)]
pub async fn new_with_frontmatter_filtered_by_deployment(
dotrain: String,
deployments: Vec<String>,
config: Option<String>,
deployments: &[&str],
) -> Result<Self, DotrainOrderError> {
) -> Result<DotrainOrder, DotrainOrderError> {
Self::new(dotrain, config)
.await?
.filter_by_deployment(deployments)
Expand All @@ -18,17 +25,18 @@ impl DotrainOrder {

/// Generates a new instance with a frontmatter that only includes the
/// specified deployments and their related fields
#[cfg_attr(target_family = "wasm", wasm_bindgen(js_name = "filterByDeployment"))]
pub async fn filter_by_deployment(
&self,
deployments: &[&str],
) -> Result<Self, DotrainOrderError> {
deployments: Vec<String>,
) -> Result<DotrainOrder, DotrainOrderError> {
// 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(
let deployment_ref = self.config.deployments.get(&deployment).ok_or(
DotrainOrderError::CleanUnusedFrontmatterError(format!(
"Deployment \"{}\" not found",
deployment
Expand All @@ -38,7 +46,7 @@ impl DotrainOrder {
deployment.to_string(),
config_source
.deployments
.get(*deployment)
.get(&deployment)
.ok_or(DotrainOrderError::CleanUnusedFrontmatterError(format!(
"Deployment \"{}\" not found",
deployment
Expand Down Expand Up @@ -545,8 +553,8 @@ _ _: 0 0;

let result = DotrainOrder::new_with_frontmatter_filtered_by_deployment(
dotrain.to_string(),
vec!["some-deployment".to_string()],
Some(setting.to_string()),
&["some-deployment"],
)
.await
.unwrap();
Expand Down Expand Up @@ -698,8 +706,8 @@ _ _: 0 0;

let result = DotrainOrder::new_with_frontmatter_filtered_by_deployment(
dotrain.to_string(),
vec!["some-other-deployment".to_string()],
Some(setting.to_string()),
&["some-other-deployment"],
)
.await;

Expand Down
168 changes: 145 additions & 23 deletions crates/common/src/dotrain_order/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ use rain_orderbook_app_settings::{
use serde::Serialize;
use thiserror::Error;
use typeshare::typeshare;
#[cfg(target_family = "wasm")]
use wasm_bindgen::prelude::*;

pub mod filter;

#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(target_family = "wasm", wasm_bindgen)]
pub struct DotrainOrder {
config: Config,
dotrain: String,
Expand Down Expand Up @@ -67,6 +70,16 @@ pub enum DotrainOrderError {

#[error("Raindex version missing: should be {0}")]
MissingRaindexVersion(String),

#[error("Deployment {0} not found")]
DeploymentNotFound(String),
}

#[cfg(target_family = "wasm")]
impl From<DotrainOrderError> for JsValue {
fn from(value: DotrainOrderError) -> Self {
JsError::new(&value.to_string()).into()
}
}

#[typeshare]
Expand Down Expand Up @@ -101,8 +114,13 @@ pub struct ScenarioWords {
pub deployer_words: ContractWords,
}

#[cfg_attr(target_family = "wasm", wasm_bindgen)]
impl DotrainOrder {
pub async fn new(dotrain: String, config: Option<String>) -> Result<Self, DotrainOrderError> {
#[cfg_attr(target_family = "wasm", wasm_bindgen(js_name = "create"))]
pub async fn new(
dotrain: String,
config: Option<String>,
) -> Result<DotrainOrder, DotrainOrderError> {
match config {
Some(config) => {
let config_string = ConfigSource::try_from_string(config.clone()).await?;
Expand All @@ -128,31 +146,17 @@ 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
}

// get this instance's config mut
pub fn config_mut(&mut self) -> &mut Config {
&mut self.config
}

// get this instance's config source mut
pub fn config_source_mut(&mut self) -> &mut ConfigSource {
&mut self.config_source
#[cfg(target_family = "wasm")]
#[wasm_bindgen(getter, js_name = "dotrain")]
pub fn dotrain(&self) -> String {
self.dotrain.clone()
}

#[cfg_attr(
target_family = "wasm",
wasm_bindgen(js_name = "composeScenarioToRainlang")
)]
pub async fn compose_scenario_to_rainlang(
&self,
scenario: String,
Expand All @@ -170,6 +174,10 @@ impl DotrainOrder {
)?)
}

#[cfg_attr(
target_family = "wasm",
wasm_bindgen(js_name = "composeScenarioToPostTaskRainlang")
)]
pub async fn compose_scenario_to_post_task_rainlang(
&self,
scenario: String,
Expand All @@ -187,6 +195,56 @@ impl DotrainOrder {
)?)
}

#[cfg_attr(
target_family = "wasm",
wasm_bindgen(js_name = "composeDeploymentToRainlang")
)]
pub async fn compose_deployment_to_rainlang(
&self,
deployment: String,
) -> Result<String, DotrainOrderError> {
let scenario = &self
.config
.deployments
.get(&deployment)
.ok_or_else(|| DotrainOrderError::DeploymentNotFound(deployment))?
.scenario;

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

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
#[cfg(not(target_family = "wasm"))]
pub fn dotrain(&self) -> &str {
&self.dotrain
}

/// get this instance's config mut
pub fn config_mut(&mut self) -> &mut Config {
&mut self.config
}

/// get this instance's config source mut
pub fn config_source_mut(&mut self) -> &mut ConfigSource {
&mut self.config_source
}

pub async fn get_pragmas_for_scenario(
&self,
scenario: &str,
Expand Down Expand Up @@ -904,4 +962,68 @@ _ _: 0 0;

assert!(dotrain_order.validate_raindex_version().await.is_err());
}

#[tokio::test]
async fn test_rainlang_from_deployment() {
let server = mock_server(vec![]);
let dotrain = format!(
r#"
networks:
polygon:
rpc: {rpc_url}
chain-id: 137
network-id: 137
currency: MATIC
deployers:
polygon:
address: 0x1234567890123456789012345678901234567890
scenarios:
polygon:
tokens:
t1:
network: polygon
address: 0x1111111111111111111111111111111111111111
decimals: 18
label: Token1
symbol: Token1
t2:
network: polygon
address: 0x2222222222222222222222222222222222222222
decimals: 18
label: Token2
symbol: token2
orders:
polygon:
inputs:
- token: t1
outputs:
- token: t2
deployments:
polygon:
scenario: polygon
order: polygon
---
#calculate-io
_ _: 0 0;
#handle-io
:;"#,
rpc_url = server.url("/rpc"),
);

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

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

assert_eq!(
rainlang,
r#"/* 0. calculate-io */
_ _: 0 0;
/* 1. handle-io */
:;"#
);
}
}
3 changes: 2 additions & 1 deletion test-js/bindings/test.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import assert from "assert";
import { describe, it } from "vitest";
import { getOrderHash, OrderV3 } from "../../dist/cjs/quote";
import { OrderV3 } from "../../dist/types/quote";
import { getOrderHash } from "../../dist/cjs/quote.js";

describe("Rain Orderbook Bindings Package Bindgen Tests", async function () {
it("should get correct order hash", async () => {
Expand Down
38 changes: 34 additions & 4 deletions test-js/common/test.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import assert from "assert";
import { getLocal } from "mockttp";
import { getAddOrderCalldata } from "../../dist/cjs/common";
import { describe, it, beforeEach, afterEach } from "vitest";
import { getAddOrderCalldata, DotrainOrder } from "../../dist/cjs/common.js";

describe("Rain Orderbook Common Package Bindgen Tests", async function () {
const mockServer = getLocal();
beforeEach(() => mockServer.start(8080));
afterEach(() => mockServer.stop());

const dotrain = `
raindex-version: ${process.env.COMMIT_SHA}
networks:
some-network:
rpc: http://localhost:8080/rpc-url
Expand Down Expand Up @@ -117,7 +116,6 @@ _ _: 0 0;
it("should throw frontmatter missing field error", async () => {
try {
const dotrain = `
raindex-version: ${process.env.COMMIT_SHA}
deployers:
some-deployer:
---
Expand All @@ -134,8 +132,40 @@ _ _: 0 0;
assert.ok(error instanceof Error);
assert.equal(
error.message,
"deployers.some-deployer: missing field `address` at line 4 column 19"
"deployers.some-deployer: missing field `address` at line 3 column 19"
);
}
});

it("should compose deployment to rainlang", async () => {
const dotrainOrder = await DotrainOrder.create(dotrain);
const result =
await dotrainOrder.composeDeploymentToRainlang("some-deployment");
const expected = `/* 0. calculate-io */
_ _: 0 0;
/* 1. handle-io */
:;`;

assert.equal(result, expected);
});

it("should compose scenario to rainlang with config", async () => {
const config = `
scenarios:
config-scenario:
network: some-network
deployer: some-deployer
`;
const dotrainOrder = await DotrainOrder.create(dotrain, config);
const result =
await dotrainOrder.composeScenarioToRainlang("config-scenario");
const expected = `/* 0. calculate-io */
_ _: 0 0;
/* 1. handle-io */
:;`;

assert.equal(result, expected);
});
});
Loading

0 comments on commit 0767221

Please sign in to comment.