From 5021caf926e822fa3748163a01771cbf12e22332 Mon Sep 17 00:00:00 2001 From: rouzwelt Date: Mon, 23 Sep 2024 23:58:37 +0000 Subject: [PATCH 1/4] init --- crates/cli/src/commands/order/filter.rs | 6 +- crates/common/src/dotrain_order/filter.rs | 24 ++++--- crates/common/src/dotrain_order/mod.rs | 77 ++++++++++++++++------- test-js/common/test.test.ts | 15 ++++- 4 files changed, 85 insertions(+), 37 deletions(-) diff --git a/crates/cli/src/commands/order/filter.rs b/crates/cli/src/commands/order/filter.rs index 978f95a4b..95d8e9368 100644 --- a/crates/cli/src/commands/order/filter.rs +++ b/crates/cli/src/commands/order/filter.rs @@ -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::>(), ) .await?; diff --git a/crates/common/src/dotrain_order/filter.rs b/crates/common/src/dotrain_order/filter.rs index d884daba3..f0f8254b2 100644 --- a/crates/common/src/dotrain_order/filter.rs +++ b/crates/common/src/dotrain_order/filter.rs @@ -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, config: Option, - deployments: &[&str], - ) -> Result { + ) -> Result { Self::new(dotrain, config) .await? .filter_by_deployment(deployments) @@ -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 { + deployments: Vec, + ) -> 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( + let deployment_ref = self.config.deployments.get(&deployment).ok_or( DotrainOrderError::CleanUnusedFrontmatterError(format!( "Deployment \"{}\" not found", deployment @@ -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 @@ -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(); @@ -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; diff --git a/crates/common/src/dotrain_order/mod.rs b/crates/common/src/dotrain_order/mod.rs index 33b84a4b5..59b24f29d 100644 --- a/crates/common/src/dotrain_order/mod.rs +++ b/crates/common/src/dotrain_order/mod.rs @@ -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, @@ -69,6 +72,13 @@ pub enum DotrainOrderError { MissingRaindexVersion(String), } +#[cfg(target_family = "wasm")] +impl From for JsValue { + fn from(value: DotrainOrderError) -> Self { + JsError::new(&value.to_string()).into() + } +} + #[typeshare] #[derive(Serialize, Debug, Clone)] #[serde(tag = "type", content = "data")] @@ -101,8 +111,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) -> Result { + #[cfg_attr(target_family = "wasm", wasm_bindgen(js_name = "create"))] + pub async fn new( + dotrain: String, + config: Option, + ) -> Result { match config { Some(config) => { let config_string = ConfigSource::try_from_string(config.clone()).await?; @@ -128,31 +143,16 @@ 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_attr(target_family = "wasm", wasm_bindgen(getter, js_name = "dotrain"))] + pub fn dotrain_getter_js(&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, @@ -170,6 +170,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, @@ -186,6 +190,33 @@ impl DotrainOrder { &ORDERBOOK_ADDORDER_POST_TASK_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 + 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, diff --git a/test-js/common/test.test.ts b/test-js/common/test.test.ts index 548a76b99..69836f6a0 100644 --- a/test-js/common/test.test.ts +++ b/test-js/common/test.test.ts @@ -1,7 +1,7 @@ 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"; describe("Rain Orderbook Common Package Bindgen Tests", async function () { const mockServer = getLocal(); @@ -138,4 +138,17 @@ _ _: 0 0; ); } }); + + it("should compose scenario to rainlang", async () => { + const dotrainOrder = await DotrainOrder.create(dotrain); + const result = + await dotrainOrder.composeScenarioToRainlang("some-scenario"); + const expected = `/* 0. calculate-io */ +_ _: 0 0; + +/* 1. handle-io */ +:;`; + + assert.equal(result, expected); + }); }); From 6558d107a5ba5ffc05dd4a6abfadda677b38380e Mon Sep 17 00:00:00 2001 From: rouzwelt Date: Tue, 24 Sep 2024 01:36:12 +0000 Subject: [PATCH 2/4] fix ts compliaints on test files --- test-js/bindings/test.test.ts | 5 ++- test-js/common/test.test.ts | 27 +++++++++++--- test-js/quote/test.test.ts | 69 +++++++++++++++++++---------------- test-js/tsconfig.json | 4 +- 4 files changed, 65 insertions(+), 40 deletions(-) diff --git a/test-js/bindings/test.test.ts b/test-js/bindings/test.test.ts index 0cf5fee18..3005f918f 100644 --- a/test-js/bindings/test.test.ts +++ b/test-js/bindings/test.test.ts @@ -1,10 +1,11 @@ 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 () => { - const order: OrderV3 = { + const order = { owner: "0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba", evaluable: { interpreter: "0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba", diff --git a/test-js/common/test.test.ts b/test-js/common/test.test.ts index 69836f6a0..9e033aa30 100644 --- a/test-js/common/test.test.ts +++ b/test-js/common/test.test.ts @@ -1,7 +1,7 @@ import assert from "assert"; import { getLocal } from "mockttp"; import { describe, it, beforeEach, afterEach } from "vitest"; -import { getAddOrderCalldata, DotrainOrder } from "../../dist/cjs/common"; +import { getAddOrderCalldata, DotrainOrder } from "../../dist/cjs/common.js"; describe("Rain Orderbook Common Package Bindgen Tests", async function () { const mockServer = getLocal(); @@ -9,7 +9,6 @@ describe("Rain Orderbook Common Package Bindgen Tests", async function () { afterEach(() => mockServer.stop()); const dotrain = ` -raindex-version: ${process.env.COMMIT_SHA} networks: some-network: rpc: http://localhost:8080/rpc-url @@ -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: --- @@ -134,18 +132,37 @@ _ _: 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 scenario to rainlang", async () => { + it("should compose scenario to rainlang without config", async () => { const dotrainOrder = await DotrainOrder.create(dotrain); const result = await dotrainOrder.composeScenarioToRainlang("some-scenario"); 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 */ :;`; diff --git a/test-js/quote/test.test.ts b/test-js/quote/test.test.ts index 3ab03fd84..a1bcbc087 100644 --- a/test-js/quote/test.test.ts +++ b/test-js/quote/test.test.ts @@ -1,29 +1,31 @@ -import assert from "assert" -import { getLocal } from "mockttp" -import { describe, it, beforeEach, afterEach } from "vitest" +import assert from "assert"; +import { getLocal } from "mockttp"; +import { describe, it, beforeEach, afterEach } from "vitest"; import { - getId, QuoteSpec, QuoteTarget, - doQuoteTargets, OrderQuoteValue, +} from "../../dist/types/quote"; +import { + getId, + doQuoteTargets, getQuoteTargetFromSubgraph, -} from "../../dist/cjs/quote" +} from "../../dist/cjs/quote"; describe("Rain Orderbook Quote Package Bindgen Tests", async function () { - const mockServer = getLocal() - beforeEach(() => mockServer.start(8081)) - afterEach(() => mockServer.stop()) + const mockServer = getLocal(); + beforeEach(() => mockServer.start(8081)); + afterEach(() => mockServer.stop()); it("should get correct id", async () => { - const orderbook = "0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba" + const orderbook = "0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba"; const orderHash = - "0xf4058d50e798f18a048097265fe67fe2e8619f337b9377a7620bb87fc2f52721" - const result = getId(orderbook, orderHash) + "0xf4058d50e798f18a048097265fe67fe2e8619f337b9377a7620bb87fc2f52721"; + const result = getId(orderbook, orderHash); const expected = - "0xca228cb816102ef9f8e0f9a87bb34e06c49c4d4ddf5a2a0ec229ab671475c235" - assert.equal(result, expected) - }) + "0xca228cb816102ef9f8e0f9a87bb34e06c49c4d4ddf5a2a0ec229ab671475c235"; + assert.equal(result, expected); + }); it("should get correct quote targets from subgraph", async () => { await mockServer.forPost("/sg-url").thenReply( @@ -101,7 +103,7 @@ describe("Rain Orderbook Quote Package Bindgen Tests", async function () { ], }, }) - ) + ); const quoteSpec: QuoteSpec = { orderbook: "0x713180d188e1ff758f508d9f2e1d350d650fea5e", @@ -110,12 +112,12 @@ describe("Rain Orderbook Quote Package Bindgen Tests", async function () { outputIOIndex: 0, inputIOIndex: 0, signedContext: [], - } + }; try { const result = await getQuoteTargetFromSubgraph( [quoteSpec], mockServer.url + "/sg-url" - ) + ); const expected: QuoteTarget = { quoteConfig: { order: { @@ -149,20 +151,20 @@ describe("Rain Orderbook Quote Package Bindgen Tests", async function () { signedContext: [], }, orderbook: "0x713180d188e1ff758f508d9f2e1d350d650fea5e", - } - assert.deepEqual(result[0], expected) + }; + assert.deepEqual(result[0], expected); } catch (error) { - console.log(error) - assert.fail("expected to resolve, but failed") + console.log(error); + assert.fail("expected to resolve, but failed"); } - }) + }); it("should quote targets", async () => { await mockServer .forPost("/rpc-url") .thenSendJsonRpcResult( "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" - ) + ); const target: QuoteTarget = { orderbook: "0xc6768d9e1cdd2f2058c92185364a3a5d2e1e47de", quoteConfig: { @@ -196,19 +198,22 @@ describe("Rain Orderbook Quote Package Bindgen Tests", async function () { outputIOIndex: 0, signedContext: [], }, - } + }; try { - const result = await doQuoteTargets([target], mockServer.url + "/rpc-url") + const result = await doQuoteTargets( + [target], + mockServer.url + "/rpc-url" + ); const expected: OrderQuoteValue = { maxOutput: "0x0000000000000000000000000000000000000000000000000000000000000001", ratio: "0x0000000000000000000000000000000000000000000000000000000000000002", - } - assert.deepEqual(result[0], expected) + }; + assert.deepEqual(result[0], expected); } catch (error) { - console.log(error) - assert.fail("expected to resolve, but failed") + console.log(error); + assert.fail("expected to resolve, but failed"); } - }) -}) + }); +}); diff --git a/test-js/tsconfig.json b/test-js/tsconfig.json index 9c537c738..c52203ba2 100644 --- a/test-js/tsconfig.json +++ b/test-js/tsconfig.json @@ -9,6 +9,8 @@ "strict": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, - "skipLibCheck": true + "skipLibCheck": true, + "allowJs": true, + "outDir": "./dist", } } \ No newline at end of file From a0353c1b4892fb689a3df7f49fffe92064835a70 Mon Sep 17 00:00:00 2001 From: rouzwelt Date: Tue, 24 Sep 2024 16:30:26 +0000 Subject: [PATCH 3/4] update --- test-js/bindings/test.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-js/bindings/test.test.ts b/test-js/bindings/test.test.ts index 3005f918f..92134cc39 100644 --- a/test-js/bindings/test.test.ts +++ b/test-js/bindings/test.test.ts @@ -5,7 +5,7 @@ import { getOrderHash } from "../../dist/cjs/quote.js"; describe("Rain Orderbook Bindings Package Bindgen Tests", async function () { it("should get correct order hash", async () => { - const order = { + const order: OrderV3 = { owner: "0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba", evaluable: { interpreter: "0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba", From 476c9b42cd2de61c963febb085db777fd1c2f189 Mon Sep 17 00:00:00 2001 From: rouzwelt Date: Tue, 24 Sep 2024 20:12:34 +0000 Subject: [PATCH 4/4] add deployment to rainlang method --- crates/common/src/dotrain_order/mod.rs | 105 +++++++++++++++++++++++-- test-js/common/test.test.ts | 4 +- 2 files changed, 100 insertions(+), 9 deletions(-) diff --git a/crates/common/src/dotrain_order/mod.rs b/crates/common/src/dotrain_order/mod.rs index 59b24f29d..69617dd21 100644 --- a/crates/common/src/dotrain_order/mod.rs +++ b/crates/common/src/dotrain_order/mod.rs @@ -70,6 +70,9 @@ pub enum DotrainOrderError { #[error("Raindex version missing: should be {0}")] MissingRaindexVersion(String), + + #[error("Deployment {0} not found")] + DeploymentNotFound(String), } #[cfg(target_family = "wasm")] @@ -144,8 +147,9 @@ impl DotrainOrder { } // get this instance's dotrain string - #[cfg_attr(target_family = "wasm", wasm_bindgen(getter, js_name = "dotrain"))] - pub fn dotrain_getter_js(&self) -> String { + #[cfg(target_family = "wasm")] + #[wasm_bindgen(getter, js_name = "dotrain")] + pub fn dotrain(&self) -> String { self.dotrain.clone() } @@ -190,30 +194,53 @@ impl DotrainOrder { &ORDERBOOK_ADDORDER_POST_TASK_ENTRYPOINTS, )?) } + + #[cfg_attr( + target_family = "wasm", + wasm_bindgen(js_name = "composeDeploymentToRainlang") + )] + pub async fn compose_deployment_to_rainlang( + &self, + deployment: String, + ) -> Result { + 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 + /// get this instance's config pub fn config(&self) -> &Config { &self.config } - // get this instance's config source + /// get this instance's config source pub fn config_source(&self) -> &ConfigSource { &self.config_source } - // get this instance's dotrain string + /// get this instance's dotrain string + #[cfg(not(target_family = "wasm"))] pub fn dotrain(&self) -> &str { &self.dotrain } - // get this instance's config mut + /// get this instance's config mut pub fn config_mut(&mut self) -> &mut Config { &mut self.config } - // get this instance's config source mut + /// get this instance's config source mut pub fn config_source_mut(&mut self) -> &mut ConfigSource { &mut self.config_source } @@ -935,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 */ +:;"# + ); + } } diff --git a/test-js/common/test.test.ts b/test-js/common/test.test.ts index 9e033aa30..e6ad7e7e6 100644 --- a/test-js/common/test.test.ts +++ b/test-js/common/test.test.ts @@ -137,10 +137,10 @@ _ _: 0 0; } }); - it("should compose scenario to rainlang without config", async () => { + it("should compose deployment to rainlang", async () => { const dotrainOrder = await DotrainOrder.create(dotrain); const result = - await dotrainOrder.composeScenarioToRainlang("some-scenario"); + await dotrainOrder.composeDeploymentToRainlang("some-deployment"); const expected = `/* 0. calculate-io */ _ _: 0 0;