From 0eaf103f8d6ec1c65d00e1e59187137ac0527654 Mon Sep 17 00:00:00 2001 From: nino Date: Mon, 16 Dec 2024 17:36:50 +0400 Subject: [PATCH 01/11] Move InputToken.svelte to ui-components --- .../lib/components/input/InputToken.svelte | 60 +++++++++++++++++++ packages/ui-components/src/lib/index.ts | 1 + .../src/lib/components/InputToken.svelte | 60 ------------------- .../ModalVaultDepositGeneric.svelte | 2 +- 4 files changed, 62 insertions(+), 61 deletions(-) create mode 100644 packages/ui-components/src/lib/components/input/InputToken.svelte delete mode 100644 tauri-app/src/lib/components/InputToken.svelte diff --git a/packages/ui-components/src/lib/components/input/InputToken.svelte b/packages/ui-components/src/lib/components/input/InputToken.svelte new file mode 100644 index 000000000..fe16865e4 --- /dev/null +++ b/packages/ui-components/src/lib/components/input/InputToken.svelte @@ -0,0 +1,60 @@ + + +
+
+
+ +
+ + {#if !isAddressValid && address.length > 0} + Invalid Address + {/if} + + Token Address +
+
+ + Decimals +
+
diff --git a/packages/ui-components/src/lib/index.ts b/packages/ui-components/src/lib/index.ts index 170227373..9a30ff6c7 100644 --- a/packages/ui-components/src/lib/index.ts +++ b/packages/ui-components/src/lib/index.ts @@ -42,6 +42,7 @@ export { default as IconSuccess } from './components/IconSuccess.svelte'; export { default as IconTelegram } from './components/IconTelegram.svelte'; export { default as IconWalletConnect } from './components/IconWalletConnect.svelte'; export { default as IconWarning } from './components/IconWarning.svelte'; +export { default as InputToken } from './components/input/InputToken.svelte'; //Types export type { AppStoresInterface } from './types/appStores.ts'; diff --git a/tauri-app/src/lib/components/InputToken.svelte b/tauri-app/src/lib/components/InputToken.svelte deleted file mode 100644 index b5d4f2934..000000000 --- a/tauri-app/src/lib/components/InputToken.svelte +++ /dev/null @@ -1,60 +0,0 @@ - - -
-
-
- -
- - {#if !isAddressValid && address.length > 0} - Invalid Address - {/if} - - Token Address -
-
- - Decimals -
-
diff --git a/tauri-app/src/lib/components/ModalVaultDepositGeneric.svelte b/tauri-app/src/lib/components/ModalVaultDepositGeneric.svelte index 277fa44ae..5c83e956f 100644 --- a/tauri-app/src/lib/components/ModalVaultDepositGeneric.svelte +++ b/tauri-app/src/lib/components/ModalVaultDepositGeneric.svelte @@ -6,7 +6,7 @@ vaultDepositApproveCalldata, vaultDepositCalldata, } from '$lib/services/vault'; - import InputToken from '$lib/components/InputToken.svelte'; + import { InputToken } from '@rainlanguage/ui-components'; import InputVaultId from '$lib/components/InputVaultId.svelte'; import { orderbookAddress } from '$lib/stores/settings'; import { checkAllowance, ethersExecute } from '$lib/services/ethersTx'; From 986adbe6f14f311959bd9d2fb62172c5990643cc Mon Sep 17 00:00:00 2001 From: nino Date: Mon, 16 Dec 2024 18:30:19 +0400 Subject: [PATCH 02/11] Add additional typings in ui-components --- packages/ui-components/src/additional-svelte-typings.d.ts | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 packages/ui-components/src/additional-svelte-typings.d.ts diff --git a/packages/ui-components/src/additional-svelte-typings.d.ts b/packages/ui-components/src/additional-svelte-typings.d.ts new file mode 100644 index 000000000..d742690da --- /dev/null +++ b/packages/ui-components/src/additional-svelte-typings.d.ts @@ -0,0 +1,7 @@ +declare namespace svelteHTML { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + interface HTMLAttributes { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + 'on:complete'?: (event: any) => any; + } +} From 193b3dbe120295917f6bf14421c9fd4a7f698ea7 Mon Sep 17 00:00:00 2001 From: nino Date: Mon, 16 Dec 2024 18:55:25 +0400 Subject: [PATCH 03/11] Format --- .../ui-components/src/additional-svelte-typings.d.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/ui-components/src/additional-svelte-typings.d.ts b/packages/ui-components/src/additional-svelte-typings.d.ts index d742690da..cc18f8751 100644 --- a/packages/ui-components/src/additional-svelte-typings.d.ts +++ b/packages/ui-components/src/additional-svelte-typings.d.ts @@ -1,7 +1,7 @@ declare namespace svelteHTML { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - interface HTMLAttributes { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - 'on:complete'?: (event: any) => any; - } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + interface HTMLAttributes { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + 'on:complete'?: (event: any) => any; + } } From de40ff204fbbca02b0f6c590dedd9fa04ee2ee3f Mon Sep 17 00:00:00 2001 From: findolor Date: Wed, 18 Dec 2024 19:53:38 +0300 Subject: [PATCH 04/11] add order field to dotrain yaml --- crates/settings/src/order.rs | 295 +++++++++++++++++++++++++++- crates/settings/src/yaml/dotrain.rs | 74 ++++++- crates/settings/src/yaml/mod.rs | 9 +- 3 files changed, 372 insertions(+), 6 deletions(-) diff --git a/crates/settings/src/order.rs b/crates/settings/src/order.rs index a7db0f5f8..7a72a07c4 100644 --- a/crates/settings/src/order.rs +++ b/crates/settings/src/order.rs @@ -1,9 +1,17 @@ use crate::*; use alloy::primitives::U256; use serde::{Deserialize, Serialize}; -use std::{collections::HashMap, sync::Arc}; +use std::{ + collections::HashMap, + str::FromStr, + sync::{Arc, RwLock}, +}; +use strict_yaml_rust::StrictYaml; use thiserror::Error; use typeshare::typeshare; +use yaml::{ + optional_string, require_hash, require_string, require_vec, YamlError, YamlParsableHash, +}; #[cfg(target_family = "wasm")] use rain_orderbook_bindings::{impl_all_wasm_traits, wasm_traits::prelude::*}; @@ -27,10 +35,14 @@ pub struct OrderIO { impl_all_wasm_traits!(OrderIO); #[typeshare] -#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone)] #[cfg_attr(target_family = "wasm", derive(Tsify))] #[serde(rename_all = "kebab-case")] +#[serde(default)] pub struct Order { + #[serde(skip)] + pub document: Arc>, + pub key: String, #[typeshare(typescript(type = "OrderIO[]"))] #[cfg_attr(target_family = "wasm", tsify(type = "Vault[]"))] pub inputs: Vec, @@ -47,6 +59,189 @@ pub struct Order { #[cfg(target_family = "wasm")] impl_all_wasm_traits!(Order); +impl Order { + pub fn validate_vault_id(value: &str) -> Result { + U256::from_str(value).map_err(ParseOrderConfigSourceError::VaultParseError) + } +} + +impl YamlParsableHash for Order { + fn parse_all_from_yaml( + document: Arc>, + ) -> Result, YamlError> { + let document_read = document.read().map_err(|_| YamlError::ReadLockError)?; + let orders_hash = require_hash( + &document_read, + Some("orders"), + Some("missing field: orders".to_string()), + )?; + + orders_hash + .into_iter() + .map(|(key_yaml, order_yaml)| { + let order_key = key_yaml.as_str().unwrap_or_default().to_string(); + + let mut network: Option> = None; + + let deployer = match optional_string(order_yaml, "deployer") { + Some(deployer_name) => { + let deployer = + Arc::new(Deployer::parse_from_yaml(document.clone(), &deployer_name)?); + if let Some(n) = &network { + if deployer.network != *n { + return Err(YamlError::ParseOrderConfigSourceError( + ParseOrderConfigSourceError::NetworkNotMatch, + )); + } + } else { + network = Some(deployer.network.clone()); + } + Some(deployer) + } + None => None, + }; + + let orderbook = match optional_string(order_yaml, "orderbook") { + Some(orderbook_name) => { + let orderbook = Arc::new(Orderbook::parse_from_yaml( + document.clone(), + &orderbook_name, + )?); + if let Some(n) = &network { + if orderbook.network != *n { + return Err(YamlError::ParseOrderConfigSourceError( + ParseOrderConfigSourceError::NetworkNotMatch, + )); + } + } else { + network = Some(orderbook.network.clone()); + } + Some(orderbook) + } + None => None, + }; + + let inputs = require_vec( + order_yaml, + "inputs", + Some(format!("inputs list missing in order: {order_key}")), + )? + .iter() + .enumerate() + .map(|(i, input)| { + let token_name = require_string( + input, + Some("token"), + Some(format!( + "token string missing in input index: {i} in order: {order_key}" + )), + )?; + let token = Token::parse_from_yaml(document.clone(), &token_name)?; + + if let Some(n) = &network { + if token.network != *n { + return Err(YamlError::ParseOrderConfigSourceError( + ParseOrderConfigSourceError::NetworkNotMatch, + )); + } + } else { + network = Some(token.network.clone()); + } + + let vault_id = match optional_string(input, "vault-id") { + Some(id) => Some(Order::validate_vault_id(&id)?), + None => None, + }; + + Ok(OrderIO { + token: Arc::new(token), + vault_id, + }) + }) + .collect::, YamlError>>()?; + + let outputs = require_vec( + order_yaml, + "outputs", + Some(format!("outputs list missing in order: {order_key}")), + )? + .iter() + .enumerate() + .map(|(i, output)| { + let token_name = require_string( + output, + Some("token"), + Some(format!( + "token string missing in output index: {i} in order: {order_key}" + )), + )?; + let token = Token::parse_from_yaml(document.clone(), &token_name)?; + + if let Some(n) = &network { + if token.network != *n { + return Err(YamlError::ParseOrderConfigSourceError( + ParseOrderConfigSourceError::NetworkNotMatch, + )); + } + } else { + network = Some(token.network.clone()); + } + + let vault_id = match optional_string(output, "vault-id") { + Some(id) => Some(Order::validate_vault_id(&id)?), + None => None, + }; + + Ok(OrderIO { + token: Arc::new(token), + vault_id, + }) + }) + .collect::, YamlError>>()?; + + let order = Order { + document: document.clone(), + key: order_key.clone(), + inputs, + outputs, + network: network.ok_or(ParseOrderConfigSourceError::NetworkNotFoundError( + String::new(), + ))?, + deployer, + orderbook, + }; + + Ok((order_key, order)) + }) + .collect() + } +} + +impl Default for Order { + fn default() -> Self { + Self { + document: Arc::new(RwLock::new(StrictYaml::String("".to_string()))), + key: String::new(), + inputs: vec![], + outputs: vec![], + network: Arc::new(Network::default()), + deployer: None, + orderbook: None, + } + } +} + +impl PartialEq for Order { + fn eq(&self, other: &Self) -> bool { + self.key == other.key + && self.inputs == other.inputs + && self.outputs == other.outputs + && self.network == other.network + && self.deployer == other.deployer + && self.orderbook == other.orderbook + } +} + #[derive(Error, Debug, PartialEq)] pub enum ParseOrderConfigSourceError { #[error("Failed to parse deployer")] @@ -181,6 +376,8 @@ impl OrderConfigSource { .collect::, _>>()?; Ok(Order { + document: Arc::new(RwLock::new(StrictYaml::String("".to_string()))), + key: String::new(), inputs, outputs, network: network.ok_or(ParseOrderConfigSourceError::NetworkNotFoundError( @@ -194,6 +391,8 @@ impl OrderConfigSource { #[cfg(test)] mod tests { + use yaml::tests::get_document; + use super::*; use crate::test::*; @@ -327,4 +526,96 @@ mod tests { Err(ParseOrderConfigSourceError::TokenParseError(_)) )); } + + #[test] + fn test_parse_orders_from_yaml() { + let yaml = r#" +test: test +"#; + let error = Order::parse_all_from_yaml(get_document(yaml)).unwrap_err(); + assert_eq!( + error, + YamlError::ParseError("missing field: orders".to_string()) + ); + + let yaml = r#" +orders: + order1: +"#; + let error = Order::parse_all_from_yaml(get_document(yaml)).unwrap_err(); + assert_eq!( + error, + YamlError::ParseError("inputs list missing in order: order1".to_string()) + ); + + let yaml = r#" +orders: + order1: + inputs: + - test: test +"#; + let error = Order::parse_all_from_yaml(get_document(yaml)).unwrap_err(); + assert_eq!( + error, + YamlError::ParseError( + "token string missing in input index: 0 in order: order1".to_string() + ) + ); + + let yaml = r#" +orders: + order1: + inputs: + - token: eth +"#; + let error = Order::parse_all_from_yaml(get_document(yaml)).unwrap_err(); + assert_eq!( + error, + YamlError::ParseError("missing field: tokens".to_string()) + ); + + let yaml = r#" +networks: + mainnet: + rpc: "https://mainnet.infura.io" + chain-id: "1" +tokens: + eth: + network: mainnet + address: 0x1234567890123456789012345678901234567890 +orders: + order1: + inputs: + - token: eth +"#; + let error = Order::parse_all_from_yaml(get_document(yaml)).unwrap_err(); + assert_eq!( + error, + YamlError::ParseError("outputs list missing in order: order1".to_string()) + ); + + let yaml = r#" +networks: + mainnet: + rpc: "https://mainnet.infura.io" + chain-id: "1" +tokens: + eth: + network: mainnet + address: 0x1234567890123456789012345678901234567890 +orders: + order1: + inputs: + - token: eth + outputs: + - test: test +"#; + let error = Order::parse_all_from_yaml(get_document(yaml)).unwrap_err(); + assert_eq!( + error, + YamlError::ParseError( + "token string missing in output index: 0 in order: order1".to_string() + ) + ); + } } diff --git a/crates/settings/src/yaml/dotrain.rs b/crates/settings/src/yaml/dotrain.rs index 8e14e37f2..8129b057f 100644 --- a/crates/settings/src/yaml/dotrain.rs +++ b/crates/settings/src/yaml/dotrain.rs @@ -1,4 +1,5 @@ use super::*; +use crate::Order; use std::sync::{Arc, RwLock}; #[derive(Debug, Clone)] @@ -15,10 +16,79 @@ impl YamlParsable for DotrainYaml { let doc = docs[0].clone(); let document = Arc::new(RwLock::new(doc)); - if validate {} + if validate { + Order::parse_all_from_yaml(document.clone())?; + } Ok(DotrainYaml { document }) } } -impl DotrainYaml {} +impl DotrainYaml { + pub fn get_order_keys(&self) -> Result, YamlError> { + let orders = Order::parse_all_from_yaml(self.document.clone())?; + Ok(orders.keys().cloned().collect()) + } + pub fn get_order(&self, key: &str) -> Result { + Order::parse_from_yaml(self.document.clone(), key) + } +} + +#[cfg(test)] +mod tests { + use alloy::primitives::U256; + use orderbook::OrderbookYaml; + + use super::*; + + const FULL_YAML: &str = r#" + networks: + mainnet: + rpc: https://mainnet.infura.io + chain-id: 1 + tokens: + token1: + network: mainnet + address: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 + decimals: 18 + label: Wrapped Ether + symbol: WETH + token2: + network: mainnet + address: 0x0000000000000000000000000000000000000002 + decimals: 6 + label: USD Coin + symbol: USDC + orders: + order1: + inputs: + - token: token1 + vault-id: 1 + outputs: + - token: token2 + vault-id: 2 + "#; + + #[test] + fn test_full_yaml() { + let ob_yaml = OrderbookYaml::new(FULL_YAML.to_string(), false).unwrap(); + let dotrain_yaml = DotrainYaml::new(FULL_YAML.to_string(), false).unwrap(); + + assert_eq!(dotrain_yaml.get_order_keys().unwrap().len(), 1); + let order = dotrain_yaml.get_order("order1").unwrap(); + assert_eq!(order.inputs.len(), 1); + let input = order.inputs.first().unwrap(); + assert_eq!( + *input.token.clone().as_ref(), + ob_yaml.get_token("token1").unwrap() + ); + assert_eq!(input.vault_id, Some(U256::from(1))); + let output = order.outputs.first().unwrap(); + assert_eq!(*output.token.as_ref(), ob_yaml.get_token("token2").unwrap()); + assert_eq!(output.vault_id, Some(U256::from(2))); + assert_eq!( + *order.network.as_ref(), + ob_yaml.get_network("mainnet").unwrap() + ); + } +} diff --git a/crates/settings/src/yaml/mod.rs b/crates/settings/src/yaml/mod.rs index 144a06a70..cd6cca81b 100644 --- a/crates/settings/src/yaml/mod.rs +++ b/crates/settings/src/yaml/mod.rs @@ -2,9 +2,10 @@ pub mod dotrain; pub mod orderbook; use crate::{ - ParseDeployerConfigSourceError, ParseNetworkConfigSourceError, ParseOrderbookConfigSourceError, - ParseTokenConfigSourceError, + ParseDeployerConfigSourceError, ParseNetworkConfigSourceError, ParseOrderConfigSourceError, + ParseOrderbookConfigSourceError, ParseTokenConfigSourceError, }; +use alloy::primitives::ruint::ParseError as RuintParseError; use std::collections::HashMap; use std::sync::{Arc, RwLock}; use std::sync::{PoisonError, RwLockReadGuard, RwLockWriteGuard}; @@ -65,6 +66,8 @@ pub enum YamlError { RwLockWriteGuardError(#[from] PoisonError>), #[error(transparent)] UrlParseError(#[from] UrlParseError), + #[error(transparent)] + RuintParseError(#[from] RuintParseError), #[error("Yaml file is empty")] EmptyFile, #[error("Yaml parse error: {0}")] @@ -89,6 +92,8 @@ pub enum YamlError { ParseOrderbookConfigSourceError(#[from] ParseOrderbookConfigSourceError), #[error(transparent)] ParseDeployerConfigSourceError(#[from] ParseDeployerConfigSourceError), + #[error(transparent)] + ParseOrderConfigSourceError(#[from] ParseOrderConfigSourceError), } impl PartialEq for YamlError { fn eq(&self, other: &Self) -> bool { From 00bc84a1d15311a4e4a59747c0b2be48291eb6a4 Mon Sep 17 00:00:00 2001 From: findolor Date: Wed, 18 Dec 2024 19:53:42 +0300 Subject: [PATCH 05/11] udpate tests --- crates/common/src/add_order.rs | 6 ++++++ crates/settings/src/deployment.rs | 6 ++++++ crates/settings/src/gui.rs | 5 +++++ 3 files changed, 17 insertions(+) diff --git a/crates/common/src/add_order.rs b/crates/common/src/add_order.rs index 633542213..318104e33 100644 --- a/crates/common/src/add_order.rs +++ b/crates/common/src/add_order.rs @@ -485,6 +485,8 @@ price: 2e18; let token3_arc = Arc::new(token3); let known_vault_id = U256::from(1); let order = Order { + document: Arc::new(RwLock::new(StrictYaml::String("".to_string()))), + key: "".to_string(), inputs: vec![ OrderIO { token: token1_arc.clone(), @@ -591,6 +593,8 @@ _ _: 0 0; let token2_arc = Arc::new(token2); let token3_arc = Arc::new(token3); let order = Order { + document: Arc::new(RwLock::new(StrictYaml::String("".to_string()))), + key: "".to_string(), inputs: vec![ OrderIO { token: token1_arc.clone(), @@ -733,6 +737,8 @@ _ _: 0 0; let token3_arc = Arc::new(token3); let known_vault_id = U256::from(1); let order = Order { + document: Arc::new(RwLock::new(StrictYaml::String("".to_string()))), + key: "".to_string(), inputs: vec![ OrderIO { token: token1_arc.clone(), diff --git a/crates/settings/src/deployment.rs b/crates/settings/src/deployment.rs index 794b79fc9..ce3f6af01 100644 --- a/crates/settings/src/deployment.rs +++ b/crates/settings/src/deployment.rs @@ -65,6 +65,8 @@ impl DeploymentConfigSource { mod tests { use super::*; use crate::test::*; + use std::sync::RwLock; + use strict_yaml_rust::StrictYaml; #[test] fn test_try_into_deployment_success() { @@ -78,6 +80,8 @@ mod tests { blocks: None, }; let order = Order { + document: Arc::new(RwLock::new(StrictYaml::String("".to_string()))), + key: String::new(), inputs: vec![], outputs: vec![], network: mock_network(), @@ -107,6 +111,8 @@ mod tests { blocks: None, }; let order = Order { + document: Arc::new(RwLock::new(StrictYaml::String("".to_string()))), + key: String::new(), inputs: vec![], outputs: vec![], network: mock_network(), diff --git a/crates/settings/src/gui.rs b/crates/settings/src/gui.rs index 1b1a0a1dd..219d7ff66 100644 --- a/crates/settings/src/gui.rs +++ b/crates/settings/src/gui.rs @@ -226,12 +226,15 @@ impl_all_wasm_traits!(Gui); #[cfg(test)] mod tests { + use std::sync::RwLock; + use super::*; use crate::{ test::{mock_deployer, mock_network, mock_token}, Order, Scenario, }; use alloy::primitives::Address; + use strict_yaml_rust::StrictYaml; #[test] fn test_gui_creation_success() { @@ -308,6 +311,8 @@ mod tests { blocks: None, }; let order = Order { + document: Arc::new(RwLock::new(StrictYaml::String("".to_string()))), + key: String::new(), inputs: vec![], outputs: vec![], network: mock_network(), From c3af6ea3da1335a53379ec128f91647164328ce1 Mon Sep 17 00:00:00 2001 From: findolor Date: Wed, 18 Dec 2024 20:01:17 +0300 Subject: [PATCH 06/11] update tests --- packages/orderbook/test/js_api/gui.test.ts | 2 +- packages/webapp/src/routes/deployment/+page.svelte | 3 ++- tauri-app/src/tests/pickConfig.test.ts | 4 ++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/orderbook/test/js_api/gui.test.ts b/packages/orderbook/test/js_api/gui.test.ts index b4e4ea876..967bca540 100644 --- a/packages/orderbook/test/js_api/gui.test.ts +++ b/packages/orderbook/test/js_api/gui.test.ts @@ -592,7 +592,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Gui', async function () describe('state management tests', async () => { let serializedState = - 'H4sIAAAAAAAA_3WNTQoCMQyFZ1REb-FaUNLUdNqdR_AKSZvKIIygs_D4LkxdCL7Nl5_He-fuo4FDyJ6ZXNIEKLlWDigpRR-rehWUisKQyZNXikhZQ4m1FOAMLi0sZ2uUcSrjdD243g7Qb2y6PPSp887t2-fl0J8oDDEBSy5a_-2_4dg1LY0OoBWujfP9ppP7OldGgmN4A9ok8gT9AAAA'; + 'H4sIAAAAAAAA_3WNTQoCMQxGZ1REb-FaUJpMk7Y7j-AV0jaVQRhBZ-HxXdi6EObbvPzxcum-iUxoKQSJUbyFlEjFSPFZQrQumewZUYvmJMihOKABnLNUUJnVyap69s03Tnmcbifo68D0u1pdn_rS-QDHtnkDDpbY-WAkpqxlqf-XY9eyrgRj2sNt5fy46wS_y00lmTN_AHYyHjD9AAAA'; let gui: DotrainOrderGui; beforeAll(async () => { mockServer diff --git a/packages/webapp/src/routes/deployment/+page.svelte b/packages/webapp/src/routes/deployment/+page.svelte index c7457a600..ac0a3e33b 100644 --- a/packages/webapp/src/routes/deployment/+page.svelte +++ b/packages/webapp/src/routes/deployment/+page.svelte @@ -7,6 +7,7 @@ type DepositAndAddOrderCalldataResult, type GuiDeposit, type GuiFieldDefinition, + type Network, type SelectTokens, type TokenInfos } from '@rainlanguage/orderbook/js_api'; @@ -132,7 +133,7 @@ await window.ethereum?.request({ method: 'eth_requestAccounts' }); const walletClient = createWalletClient({ chain: getChainById( - gui.getCurrentDeployment().deployment.order.network['chain-id'] as number + (gui.getCurrentDeployment().deployment.order.network as Network)['chain-id'] as number ), // @ts-expect-error window.ethereum is not typed transport: custom(window.ethereum!) diff --git a/tauri-app/src/tests/pickConfig.test.ts b/tauri-app/src/tests/pickConfig.test.ts index 2e4b36044..96532bf24 100644 --- a/tauri-app/src/tests/pickConfig.test.ts +++ b/tauri-app/src/tests/pickConfig.test.ts @@ -48,6 +48,7 @@ export const config: Config = { tokens: {}, orders: { buy: { + key: 'buy', inputs: [], outputs: [], network: { @@ -57,6 +58,7 @@ export const config: Config = { }, }, sell: { + key: 'sell', inputs: [], outputs: [], network: { @@ -124,6 +126,7 @@ export const config: Config = { }, }, order: { + key: 'sell', inputs: [], outputs: [], network: { @@ -148,6 +151,7 @@ export const config: Config = { }, }, order: { + key: 'buy', inputs: [], outputs: [], network: { From ff282e595c6ff6ac65aa495ce87c7ed50fcb7313 Mon Sep 17 00:00:00 2001 From: findolor Date: Thu, 19 Dec 2024 09:13:36 +0300 Subject: [PATCH 07/11] fix order typescript interface --- crates/settings/src/order.rs | 6 +++--- crates/settings/src/yaml/mod.rs | 4 ++++ packages/orderbook/test/js_api/gui.test.ts | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/crates/settings/src/order.rs b/crates/settings/src/order.rs index 7a72a07c4..c72a32d9f 100644 --- a/crates/settings/src/order.rs +++ b/crates/settings/src/order.rs @@ -10,7 +10,8 @@ use strict_yaml_rust::StrictYaml; use thiserror::Error; use typeshare::typeshare; use yaml::{ - optional_string, require_hash, require_string, require_vec, YamlError, YamlParsableHash, + default_document, optional_string, require_hash, require_string, require_vec, YamlError, + YamlParsableHash, }; #[cfg(target_family = "wasm")] @@ -38,9 +39,8 @@ impl_all_wasm_traits!(OrderIO); #[derive(Debug, Serialize, Deserialize, Clone)] #[cfg_attr(target_family = "wasm", derive(Tsify))] #[serde(rename_all = "kebab-case")] -#[serde(default)] pub struct Order { - #[serde(skip)] + #[serde(skip, default = "default_document")] pub document: Arc>, pub key: String, #[typeshare(typescript(type = "OrderIO[]"))] diff --git a/crates/settings/src/yaml/mod.rs b/crates/settings/src/yaml/mod.rs index cd6cca81b..c7d788618 100644 --- a/crates/settings/src/yaml/mod.rs +++ b/crates/settings/src/yaml/mod.rs @@ -190,6 +190,10 @@ pub fn optional_vec<'a>(value: &'a StrictYaml, field: &str) -> Option<&'a Array> value[field].as_vec() } +pub fn default_document() -> Arc> { + Arc::new(RwLock::new(StrictYaml::String("".to_string()))) +} + #[cfg(test)] pub mod tests { use super::*; diff --git a/packages/orderbook/test/js_api/gui.test.ts b/packages/orderbook/test/js_api/gui.test.ts index 967bca540..b93f496f9 100644 --- a/packages/orderbook/test/js_api/gui.test.ts +++ b/packages/orderbook/test/js_api/gui.test.ts @@ -592,7 +592,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Gui', async function () describe('state management tests', async () => { let serializedState = - 'H4sIAAAAAAAA_3WNTQoCMQxGZ1REb-FaUJpMk7Y7j-AV0jaVQRhBZ-HxXdi6EObbvPzxcum-iUxoKQSJUbyFlEjFSPFZQrQumewZUYvmJMihOKABnLNUUJnVyap69s03Tnmcbifo68D0u1pdn_rS-QDHtnkDDpbY-WAkpqxlqf-XY9eyrgRj2sNt5fy46wS_y00lmTN_AHYyHjD9AAAA'; + 'H4sIAAAAAAAA_3WPTQoCMQyFZ1REb-FaUJq26TQ7j-AV0k4qg1BBZ-HxFUxdCL7Nlz_eI6fuI7DekQOkDHnIgdlxZBY_SikpcLFiLQsigCOIPpkEBYjIx1FCxLxQn60yTXWc6uUAvQ5Mv9HqfJeHzDvYt80TrPMYhkiGU34n_ut_zW3XtGxvGNMC18r5dpUK38uVEs0xvAARbQwj_QAAAA=='; let gui: DotrainOrderGui; beforeAll(async () => { mockServer From bbd057f5eb0356f6c8a4de738971eefb26c74743 Mon Sep 17 00:00:00 2001 From: nino Date: Fri, 27 Dec 2024 11:18:14 +0400 Subject: [PATCH 08/11] Add test for imputToken to check it renders with correct initial value --- .../src/__tests__/InputToken.test.ts | 16 ++++++++++++++++ .../src/lib/components/input/InputToken.svelte | 4 ++-- 2 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 packages/ui-components/src/__tests__/InputToken.test.ts diff --git a/packages/ui-components/src/__tests__/InputToken.test.ts b/packages/ui-components/src/__tests__/InputToken.test.ts new file mode 100644 index 000000000..2840a4064 --- /dev/null +++ b/packages/ui-components/src/__tests__/InputToken.test.ts @@ -0,0 +1,16 @@ +import { render } from '@testing-library/svelte'; +import InputToken from '../lib/components/input/InputToken.svelte'; + + +describe('InputToken', () => { + it('renders with initial values', () => { + const address = '0xc0D477556c25C9d67E1f57245C7453DA776B51cf'; + const decimals = 10; + const { getByTestId } = render(InputToken, { props: { address, decimals } }); + + const input = getByTestId('token-address-input').querySelector('input'); + expect(input?.value).toBe('0xc0D477556c25C9d67E1f57245C7453DA776B51cf'); + const decimalsInput = getByTestId('token-decimals-input').querySelector('input'); + expect(decimalsInput?.value).toBe('10'); + }); +}); diff --git a/packages/ui-components/src/lib/components/input/InputToken.svelte b/packages/ui-components/src/lib/components/input/InputToken.svelte index fe16865e4..c661b3db8 100644 --- a/packages/ui-components/src/lib/components/input/InputToken.svelte +++ b/packages/ui-components/src/lib/components/input/InputToken.svelte @@ -37,7 +37,7 @@
-
+
@@ -47,7 +47,7 @@ Token Address
-
+
Date: Fri, 27 Dec 2024 11:46:33 +0400 Subject: [PATCH 09/11] Add test for imputToken to check invalid address --- .../src/__tests__/InputToken.test.ts | 15 +++++++++++++-- .../src/lib/components/input/InputToken.svelte | 4 ++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/packages/ui-components/src/__tests__/InputToken.test.ts b/packages/ui-components/src/__tests__/InputToken.test.ts index 2840a4064..5c1eaf500 100644 --- a/packages/ui-components/src/__tests__/InputToken.test.ts +++ b/packages/ui-components/src/__tests__/InputToken.test.ts @@ -1,4 +1,4 @@ -import { render } from '@testing-library/svelte'; +import { render, fireEvent } from '@testing-library/svelte'; import InputToken from '../lib/components/input/InputToken.svelte'; @@ -8,9 +8,20 @@ describe('InputToken', () => { const decimals = 10; const { getByTestId } = render(InputToken, { props: { address, decimals } }); - const input = getByTestId('token-address-input').querySelector('input'); + const input = getByTestId('token-address').querySelector('input'); expect(input?.value).toBe('0xc0D477556c25C9d67E1f57245C7453DA776B51cf'); const decimalsInput = getByTestId('token-decimals-input').querySelector('input'); expect(decimalsInput?.value).toBe('10'); }); + + it('shows error for invalid address', async () => { + const address = 'abc'; + const decimals = 0; + const { getByTestId, getByText } = render(InputToken, { props: { address, decimals } }); + + const addressInput = getByTestId('token-address').querySelector('input') as HTMLInputElement; + await fireEvent.input(addressInput, { target: { value: 'invalidAddress' } }); + + expect(getByText('Invalid Address')).toBeInTheDocument(); + }); }); diff --git a/packages/ui-components/src/lib/components/input/InputToken.svelte b/packages/ui-components/src/lib/components/input/InputToken.svelte index c661b3db8..935674c55 100644 --- a/packages/ui-components/src/lib/components/input/InputToken.svelte +++ b/packages/ui-components/src/lib/components/input/InputToken.svelte @@ -36,8 +36,8 @@
-
-
+
+
From 56b032071ba748af573ba5d1526d1799269636e8 Mon Sep 17 00:00:00 2001 From: nino Date: Fri, 27 Dec 2024 11:48:38 +0400 Subject: [PATCH 10/11] Add test for imputToken to check does not show error for valid address --- .../ui-components/src/__tests__/InputToken.test.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/ui-components/src/__tests__/InputToken.test.ts b/packages/ui-components/src/__tests__/InputToken.test.ts index 5c1eaf500..1371eaa87 100644 --- a/packages/ui-components/src/__tests__/InputToken.test.ts +++ b/packages/ui-components/src/__tests__/InputToken.test.ts @@ -24,4 +24,15 @@ describe('InputToken', () => { expect(getByText('Invalid Address')).toBeInTheDocument(); }); + + it('does not show error for valid address', async () => { + const address = ''; + const decimals = 0; + const { getByTestId, queryByText } = render(InputToken, { props: { address, decimals } }); + + const addressInput = getByTestId('token-address').querySelector('input') as HTMLInputElement; + await fireEvent.input(addressInput, { target: { value: '0xc0D477556c25C9d67E1f57245C7453DA776B51cf' } }); + + expect(queryByText('Invalid Address')).toBeNull(); + }); }); From 24d7a5a8f2844a0bd12964103a40fb828daad7b6 Mon Sep 17 00:00:00 2001 From: nino Date: Fri, 27 Dec 2024 12:45:35 +0400 Subject: [PATCH 11/11] Format --- packages/ui-components/src/__tests__/InputToken.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/ui-components/src/__tests__/InputToken.test.ts b/packages/ui-components/src/__tests__/InputToken.test.ts index 1371eaa87..c1e808027 100644 --- a/packages/ui-components/src/__tests__/InputToken.test.ts +++ b/packages/ui-components/src/__tests__/InputToken.test.ts @@ -1,7 +1,6 @@ import { render, fireEvent } from '@testing-library/svelte'; import InputToken from '../lib/components/input/InputToken.svelte'; - describe('InputToken', () => { it('renders with initial values', () => { const address = '0xc0D477556c25C9d67E1f57245C7453DA776B51cf'; @@ -31,7 +30,9 @@ describe('InputToken', () => { const { getByTestId, queryByText } = render(InputToken, { props: { address, decimals } }); const addressInput = getByTestId('token-address').querySelector('input') as HTMLInputElement; - await fireEvent.input(addressInput, { target: { value: '0xc0D477556c25C9d67E1f57245C7453DA776B51cf' } }); + await fireEvent.input(addressInput, { + target: { value: '0xc0D477556c25C9d67E1f57245C7453DA776B51cf' } + }); expect(queryByText('Invalid Address')).toBeNull(); });