diff --git a/crates/js_api/src/gui/mod.rs b/crates/js_api/src/gui/mod.rs index 67b6e7889..49bad076b 100644 --- a/crates/js_api/src/gui/mod.rs +++ b/crates/js_api/src/gui/mod.rs @@ -3,7 +3,10 @@ use alloy_ethers_typecast::transaction::ReadableClientError; use base64::{engine::general_purpose::URL_SAFE, Engine}; use flate2::{read::GzDecoder, write::GzEncoder, Compression}; use rain_orderbook_app_settings::{ + deployment::Deployment, gui::{Gui, GuiDeployment, GuiFieldDefinition, GuiPreset, ParseGuiConfigSourceError}, + network::Network, + order::Order, yaml::YamlError, }; use rain_orderbook_bindings::{impl_all_wasm_traits, wasm_traits::prelude::*}; @@ -23,8 +26,8 @@ mod select_tokens; mod state_management; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Tsify)] -pub struct AvailableDeployments(Vec); -impl_all_wasm_traits!(AvailableDeployments); +pub struct DeploymentKeys(Vec); +impl_all_wasm_traits!(DeploymentKeys); #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Tsify)] pub struct TokenInfo { @@ -52,18 +55,11 @@ pub struct DotrainOrderGui { } #[wasm_bindgen] impl DotrainOrderGui { - #[wasm_bindgen(js_name = "getAvailableDeployments")] - pub async fn get_available_deployments( - dotrain: String, - ) -> Result { + #[wasm_bindgen(js_name = "getDeploymentKeys")] + pub async fn get_deployment_keys(dotrain: String) -> Result { let dotrain_order = DotrainOrder::new(dotrain, None).await?; - let gui = dotrain_order - .dotrain_yaml() - .get_gui()? - .ok_or(GuiError::GuiConfigNotFound)?; - Ok(AvailableDeployments( - gui.deployments.values().cloned().collect(), - )) + let keys = Gui::parse_deployment_keys(dotrain_order.dotrain_yaml().documents.clone())?; + Ok(DeploymentKeys(keys)) } #[wasm_bindgen(js_name = "chooseDeployment")] @@ -73,11 +69,8 @@ impl DotrainOrderGui { ) -> Result { let dotrain_order = DotrainOrder::new(dotrain, None).await?; - let gui = dotrain_order - .dotrain_yaml() - .get_gui()? - .ok_or(GuiError::GuiConfigNotFound)?; - if !gui.deployments.contains_key(&deployment_name) { + let keys = Gui::parse_deployment_keys(dotrain_order.dotrain_yaml().documents.clone())?; + if !keys.contains(&deployment_name) { return Err(GuiError::DeploymentNotFound(deployment_name.clone())); } @@ -117,48 +110,47 @@ impl DotrainOrderGui { /// Returns a [`TokenInfo`] #[wasm_bindgen(js_name = "getTokenInfo")] pub async fn get_token_info(&self, key: String) -> Result { - let deployment = self.get_current_deployment()?; let token = self.dotrain_order.orderbook_yaml().get_token(&key)?; - let token_info = - if token.decimals.is_some() && token.label.is_some() && token.symbol.is_some() { - TokenInfo { - address: token.address, - decimals: token.decimals.unwrap(), - name: token.label.unwrap(), - symbol: token.symbol.unwrap(), - } - } else { - let rpc_url = deployment - .deployment - .order - .orderbook - .clone() - .ok_or(GuiError::OrderbookNotFound)? - .network - .rpc - .clone(); - let erc20 = ERC20::new(rpc_url, token.address); - let onchain_info = erc20.token_info(None).await?; - - TokenInfo { - address: token.address, - decimals: token.decimals.unwrap_or(onchain_info.decimals), - name: token.label.unwrap_or(onchain_info.name), - symbol: token.symbol.unwrap_or(onchain_info.symbol), - } - }; + let token_info = if token.decimals.is_some() + && token.label.is_some() + && token.symbol.is_some() + { + TokenInfo { + address: token.address, + decimals: token.decimals.unwrap(), + name: token.label.unwrap(), + symbol: token.symbol.unwrap(), + } + } else { + let order_key = Deployment::parse_order_key( + self.dotrain_order.dotrain_yaml().documents, + &self.selected_deployment, + )?; + let network_key = + Order::parse_network_key(self.dotrain_order.dotrain_yaml().documents, &order_key)?; + let rpc_url = + Network::parse_rpc(self.dotrain_order.dotrain_yaml().documents, &network_key)?; + + let erc20 = ERC20::new(rpc_url, token.address); + let onchain_info = erc20.token_info(None).await?; + + TokenInfo { + address: token.address, + decimals: token.decimals.unwrap_or(onchain_info.decimals), + name: token.label.unwrap_or(onchain_info.name), + symbol: token.symbol.unwrap_or(onchain_info.symbol), + } + }; Ok(token_info) } #[wasm_bindgen(js_name = "getGuiDetails")] pub fn get_gui_details(&self) -> Result { - let gui = self.get_gui_config()?; - Ok(GuiDetails { - name: gui.name, - description: gui.description, - }) + let (name, description) = + Gui::parse_gui_details(self.dotrain_order.dotrain_yaml().documents.clone())?; + Ok(GuiDetails { name, description }) } } diff --git a/crates/js_api/src/gui/select_tokens.rs b/crates/js_api/src/gui/select_tokens.rs index 20ae160c4..966b0b056 100644 --- a/crates/js_api/src/gui/select_tokens.rs +++ b/crates/js_api/src/gui/select_tokens.rs @@ -1,13 +1,18 @@ use super::*; -use rain_orderbook_app_settings::token::Token; +use rain_orderbook_app_settings::{ + deployment::Deployment, network::Network, order::Order, token::Token, +}; use std::str::FromStr; #[wasm_bindgen] impl DotrainOrderGui { #[wasm_bindgen(js_name = "getSelectTokens")] pub fn get_select_tokens(&self) -> Result, GuiError> { - let deployment = self.get_current_deployment()?; - Ok(deployment.select_tokens.unwrap_or(vec![])) + let select_tokens = Gui::parse_select_tokens( + self.dotrain_order.dotrain_yaml().documents, + &self.selected_deployment, + )?; + Ok(select_tokens.unwrap_or(vec![])) } #[wasm_bindgen(js_name = "isSelectTokenSet")] @@ -17,9 +22,12 @@ impl DotrainOrderGui { #[wasm_bindgen(js_name = "checkSelectTokens")] pub fn check_select_tokens(&self) -> Result<(), GuiError> { - let deployment = self.get_current_deployment()?; + let select_tokens = Gui::parse_select_tokens( + self.dotrain_order.dotrain_yaml().documents, + &self.selected_deployment, + )?; - if let Some(select_tokens) = deployment.select_tokens { + if let Some(select_tokens) = select_tokens { for key in select_tokens { if self.dotrain_order.orderbook_yaml().get_token(&key).is_err() { return Err(GuiError::TokenMustBeSelected(key.clone())); @@ -36,33 +44,33 @@ impl DotrainOrderGui { key: String, address: String, ) -> Result<(), GuiError> { - let deployment = self.get_current_deployment()?; - if deployment.select_tokens.is_none() { - return Err(GuiError::SelectTokensNotSet); - } - let select_tokens = deployment.select_tokens.unwrap(); + let select_tokens = Gui::parse_select_tokens( + self.dotrain_order.dotrain_yaml().documents, + &self.selected_deployment, + )? + .ok_or(GuiError::SelectTokensNotSet)?; if !select_tokens.contains(&key) { return Err(GuiError::TokenNotFound(key.clone())); } let address = Address::from_str(&address)?; - let rpc_url = deployment - .deployment - .order - .orderbook - .clone() - .ok_or(GuiError::OrderbookNotFound)? - .network - .rpc - .clone(); + let order_key = Deployment::parse_order_key( + self.dotrain_order.dotrain_yaml().documents, + &self.selected_deployment, + )?; + let network_key = + Order::parse_network_key(self.dotrain_order.dotrain_yaml().documents, &order_key)?; + let rpc_url = + Network::parse_rpc(self.dotrain_order.dotrain_yaml().documents, &network_key)?; + let erc20 = ERC20::new(rpc_url.clone(), address); let token_info = erc20.token_info(None).await?; Token::add_record_to_yaml( self.dotrain_order.orderbook_yaml().documents, &key, - &deployment.deployment.scenario.deployer.network.key, + &network_key, &address.to_string(), Some(&token_info.decimals.to_string()), Some(&token_info.name), @@ -71,13 +79,24 @@ impl DotrainOrderGui { Ok(()) } + #[wasm_bindgen(js_name = "replaceSelectToken")] + pub async fn replace_select_token( + &mut self, + key: String, + address: String, + ) -> Result<(), GuiError> { + self.remove_select_token(key.clone())?; + self.save_select_token(key, address).await?; + Ok(()) + } + #[wasm_bindgen(js_name = "removeSelectToken")] pub fn remove_select_token(&mut self, key: String) -> Result<(), GuiError> { - let deployment = self.get_current_deployment()?; - if deployment.select_tokens.is_none() { - return Err(GuiError::SelectTokensNotSet); - } - let select_tokens = deployment.select_tokens.unwrap(); + let select_tokens = Gui::parse_select_tokens( + self.dotrain_order.dotrain_yaml().documents, + &self.selected_deployment, + )? + .ok_or(GuiError::SelectTokensNotSet)?; if !select_tokens.contains(&key) { return Err(GuiError::TokenNotFound(key.clone())); } diff --git a/crates/settings/src/deployer.rs b/crates/settings/src/deployer.rs index 0dfb9991d..d5b5b7d21 100644 --- a/crates/settings/src/deployer.rs +++ b/crates/settings/src/deployer.rs @@ -44,6 +44,26 @@ impl Deployer { pub fn validate_address(value: &str) -> Result { Address::from_str(value).map_err(ParseDeployerConfigSourceError::AddressParseError) } + + pub fn parse_network_key( + documents: Vec>>, + deployer_key: &str, + ) -> Result { + for document in &documents { + let document_read = document.read().map_err(|_| YamlError::ReadLockError)?; + + if let Ok(deployers_hash) = require_hash(&document_read, Some("deployers"), None) { + if let Some(deployer_yaml) = + deployers_hash.get(&StrictYaml::String(deployer_key.to_string())) + { + return require_string(deployer_yaml, Some("network"), None); + } + } + } + Err(YamlError::ParseError(format!( + "network key not found for deployer: {deployer_key}" + ))) + } } #[cfg(target_family = "wasm")] diff --git a/crates/settings/src/deployment.rs b/crates/settings/src/deployment.rs index e46c65cd8..37128a635 100644 --- a/crates/settings/src/deployment.rs +++ b/crates/settings/src/deployment.rs @@ -30,6 +30,28 @@ pub struct Deployment { #[cfg(target_family = "wasm")] impl_all_wasm_traits!(Deployment); +impl Deployment { + pub fn parse_order_key( + documents: Vec>>, + deployment_key: &str, + ) -> Result { + for document in &documents { + let document_read = document.read().map_err(|_| YamlError::ReadLockError)?; + + if let Ok(deployments_hash) = require_hash(&document_read, Some("deployments"), None) { + if let Some(deployment_yaml) = + deployments_hash.get(&StrictYaml::String(deployment_key.to_string())) + { + return require_string(deployment_yaml, Some("order"), None); + } + } + } + Err(YamlError::ParseError(format!( + "order key not found for deployment: {deployment_key}" + ))) + } +} + impl YamlParsableHash for Deployment { fn parse_all_from_yaml( documents: Vec>>, diff --git a/crates/settings/src/gui.rs b/crates/settings/src/gui.rs index 6f97d15e6..3c9a28b31 100644 --- a/crates/settings/src/gui.rs +++ b/crates/settings/src/gui.rs @@ -248,7 +248,96 @@ pub struct Gui { #[cfg(target_family = "wasm")] impl_all_wasm_traits!(Gui); -impl Gui {} +impl Gui { + pub fn parse_deployment_keys( + documents: Vec>>, + ) -> Result, YamlError> { + let mut deployment_keys = Vec::new(); + + for document in documents { + let document_read = document.read().map_err(|_| YamlError::ReadLockError)?; + + if let Some(gui) = optional_hash(&document_read, "gui") { + let deployments = gui + .get(&StrictYaml::String("deployments".to_string())) + .ok_or(YamlError::ParseError( + "deployments field missing in gui".to_string(), + ))?; + + if let StrictYaml::Hash(deployments_hash) = deployments { + for (key, _) in deployments_hash { + if let StrictYaml::String(key) = key { + deployment_keys.push(key.clone()); + } + } + } + } + } + + Ok(deployment_keys) + } + + pub fn parse_select_tokens( + documents: Vec>>, + deployment_key: &str, + ) -> Result>, YamlError> { + for document in documents { + let document_read = document.read().map_err(|_| YamlError::ReadLockError)?; + + if let Some(gui) = optional_hash(&document_read, "gui") { + if let Some(StrictYaml::Hash(deployments_hash)) = + gui.get(&StrictYaml::String("deployments".to_string())) + { + if let Some(StrictYaml::Hash(deployment_hash)) = + deployments_hash.get(&StrictYaml::String(deployment_key.to_string())) + { + if let Some(StrictYaml::Array(tokens)) = + deployment_hash.get(&StrictYaml::String("select-tokens".to_string())) + { + let mut result = Vec::new(); + for token in tokens { + if let StrictYaml::String(token_str) = token { + result.push(token_str.clone()); + } + } + return Ok(Some(result)); + } + } + } + } + } + Ok(None) + } + + pub fn parse_gui_details( + documents: Vec>>, + ) -> Result<(String, String), YamlError> { + for document in documents { + let document_read = document.read().map_err(|_| YamlError::ReadLockError)?; + + if let Some(gui) = optional_hash(&document_read, "gui") { + let name = require_string( + get_hash_value(gui, "name", Some("name field missing in gui".to_string()))?, + None, + Some("name field must be a string in gui".to_string()), + )?; + + let description = require_string( + get_hash_value( + gui, + "description", + Some("description field missing in gui".to_string()), + )?, + None, + Some("description field must be a string in gui".to_string()), + )?; + + return Ok((name, description)); + } + } + Err(YamlError::ParseError("gui details not found".to_string())) + } +} impl YamlParseableValue for Gui { fn parse_from_yaml( diff --git a/crates/settings/src/network.rs b/crates/settings/src/network.rs index b4bf9a3de..c415eab61 100644 --- a/crates/settings/src/network.rs +++ b/crates/settings/src/network.rs @@ -95,6 +95,30 @@ impl Network { Ok(self.clone()) } + + pub fn parse_rpc( + documents: Vec>>, + network_key: &str, + ) -> Result { + for document in &documents { + let document_read = document.read().map_err(|_| YamlError::ReadLockError)?; + + if let Ok(networks_hash) = require_hash(&document_read, Some("networks"), None) { + if let Some(network_yaml) = + networks_hash.get(&StrictYaml::String(network_key.to_string())) + { + return Ok(Network::validate_rpc(&require_string( + network_yaml, + Some("rpc"), + None, + )?)?); + } + } + } + Err(YamlError::ParseError(format!( + "rpc not found for network: {network_key}" + ))) + } } #[cfg(target_family = "wasm")] impl_all_wasm_traits!(Network); diff --git a/crates/settings/src/order.rs b/crates/settings/src/order.rs index f7f5ef6c2..aa51ccd53 100644 --- a/crates/settings/src/order.rs +++ b/crates/settings/src/order.rs @@ -223,6 +223,87 @@ impl Order { Ok(self.clone()) } + + pub fn parse_network_key( + documents: Vec>>, + order_key: &str, + ) -> Result { + let mut network_key = None; + + for document in &documents { + let document_read = document.read().map_err(|_| YamlError::ReadLockError)?; + + if let Ok(orders_hash) = require_hash(&document_read, Some("orders"), None) { + if let Some(order_yaml) = + orders_hash.get(&StrictYaml::String(order_key.to_string())) + { + if let Some(deployer_key) = optional_string(order_yaml, "deployer") { + let key = Deployer::parse_network_key(documents.clone(), &deployer_key)?; + + if let Some(ref existing_key) = network_key { + if *existing_key != key { + return Err(YamlError::ParseOrderConfigSourceError( + ParseOrderConfigSourceError::NetworkNotMatch, + )); + } + } else { + network_key = Some(key); + } + } + + if let Some(orderbook_key) = optional_string(order_yaml, "orderbook") { + let key = Orderbook::parse_network_key(documents.clone(), &orderbook_key)?; + + if let Some(ref existing_key) = network_key { + if *existing_key != key { + return Err(YamlError::ParseOrderConfigSourceError( + ParseOrderConfigSourceError::NetworkNotMatch, + )); + } + } else { + network_key = Some(key); + } + } + + for input in require_vec(order_yaml, "inputs", None)? { + let token_key = require_string(input, Some("token"), None)?; + let res = Token::parse_network_key(documents.clone(), &token_key); + if let Ok(key) = res { + if let Some(ref existing_key) = network_key { + if *existing_key != key { + return Err(YamlError::ParseOrderConfigSourceError( + ParseOrderConfigSourceError::NetworkNotMatch, + )); + } + } else { + network_key = Some(key); + } + } + } + + for output in require_vec(order_yaml, "outputs", None)? { + let token_key = require_string(output, Some("token"), None)?; + let res = Token::parse_network_key(documents.clone(), &token_key); + if let Ok(key) = res { + if let Some(ref existing_key) = network_key { + if *existing_key != key { + return Err(YamlError::ParseOrderConfigSourceError( + ParseOrderConfigSourceError::NetworkNotMatch, + )); + } + } + } + } + } + } + } + + Ok( + network_key.ok_or(ParseOrderConfigSourceError::NetworkNotFoundError( + String::new(), + ))?, + ) + } } impl YamlParsableHash for Order { diff --git a/crates/settings/src/orderbook.rs b/crates/settings/src/orderbook.rs index 1272de7dd..4e4fe18fd 100644 --- a/crates/settings/src/orderbook.rs +++ b/crates/settings/src/orderbook.rs @@ -34,6 +34,26 @@ impl Orderbook { pub fn validate_address(address: &str) -> Result { Address::from_str(address).map_err(ParseOrderbookConfigSourceError::AddressParseError) } + + pub fn parse_network_key( + documents: Vec>>, + orderbook_key: &str, + ) -> Result { + for document in &documents { + let document_read = document.read().map_err(|_| YamlError::ReadLockError)?; + + if let Ok(orderbooks_hash) = require_hash(&document_read, Some("orderbooks"), None) { + if let Some(orderbook_yaml) = + orderbooks_hash.get(&StrictYaml::String(orderbook_key.to_string())) + { + return require_string(orderbook_yaml, Some("network"), None); + } + } + } + Err(YamlError::ParseError(format!( + "network key not found for orderbook: {orderbook_key}" + ))) + } } impl YamlParsableHash for Orderbook { diff --git a/crates/settings/src/token.rs b/crates/settings/src/token.rs index ab29bfd86..073104e3f 100644 --- a/crates/settings/src/token.rs +++ b/crates/settings/src/token.rs @@ -180,6 +180,26 @@ impl Token { Err(YamlError::KeyNotFound(key.to_string())) } + + pub fn parse_network_key( + documents: Vec>>, + token_key: &str, + ) -> Result { + for document in &documents { + let document_read = document.read().map_err(|_| YamlError::ReadLockError)?; + + if let Ok(tokens_hash) = require_hash(&document_read, Some("tokens"), None) { + if let Some(token_yaml) = + tokens_hash.get(&StrictYaml::String(token_key.to_string())) + { + return require_string(token_yaml, Some("network"), None); + } + } + } + Err(YamlError::ParseError(format!( + "network key not found for token: {token_key}" + ))) + } } impl YamlParsableHash for Token { fn parse_all_from_yaml( diff --git a/crates/settings/src/yaml/dotrain.rs b/crates/settings/src/yaml/dotrain.rs index 4005fa9d4..4a9a53403 100644 --- a/crates/settings/src/yaml/dotrain.rs +++ b/crates/settings/src/yaml/dotrain.rs @@ -341,6 +341,14 @@ mod tests { deployment.scenario, dotrain_yaml.get_scenario("scenario1").unwrap().into() ); + assert_eq!( + Deployment::parse_order_key(dotrain_yaml.documents.clone(), "deployment1").unwrap(), + "order1" + ); + assert_eq!( + Deployment::parse_order_key(dotrain_yaml.documents.clone(), "deployment2").unwrap(), + "order1" + ); let gui = dotrain_yaml.get_gui().unwrap().unwrap(); assert_eq!(gui.name, "Test gui"); @@ -367,6 +375,23 @@ mod tests { let select_tokens = deployment.select_tokens.as_ref().unwrap(); assert_eq!(select_tokens.len(), 1); assert_eq!(select_tokens[0], "token2"); + + let (name, description) = Gui::parse_gui_details(dotrain_yaml.documents.clone()).unwrap(); + assert_eq!(name, "Test gui"); + assert_eq!(description, "Test description"); + + let deployment_keys = Gui::parse_deployment_keys(dotrain_yaml.documents.clone()).unwrap(); + assert_eq!(deployment_keys.len(), 1); + assert_eq!(deployment_keys[0], "deployment1"); + + let select_tokens = + Gui::parse_select_tokens(dotrain_yaml.documents.clone(), "deployment1").unwrap(); + assert!(select_tokens.is_some()); + assert_eq!(select_tokens.unwrap()[0], "token2"); + + let select_tokens = + Gui::parse_select_tokens(dotrain_yaml.documents.clone(), "deployment2").unwrap(); + assert!(select_tokens.is_none()); } #[test] diff --git a/crates/settings/src/yaml/orderbook.rs b/crates/settings/src/yaml/orderbook.rs index 2f96feb4f..d97c34d28 100644 --- a/crates/settings/src/yaml/orderbook.rs +++ b/crates/settings/src/yaml/orderbook.rs @@ -251,6 +251,10 @@ mod tests { assert_eq!(network.label, Some("Ethereum Mainnet".to_string())); assert_eq!(network.network_id, Some(1)); assert_eq!(network.currency, Some("ETH".to_string())); + assert_eq!( + Network::parse_rpc(ob_yaml.documents.clone(), "mainnet").unwrap(), + Url::parse("https://mainnet.infura.io").unwrap() + ); assert_eq!(ob_yaml.get_token_keys().unwrap().len(), 1); let token = ob_yaml.get_token("token1").unwrap(); @@ -261,6 +265,10 @@ mod tests { assert_eq!(token.decimals, Some(18)); assert_eq!(token.label, Some("Wrapped Ether".to_string())); assert_eq!(token.symbol, Some("WETH".to_string())); + assert_eq!( + Token::parse_network_key(ob_yaml.documents.clone(), "token1").unwrap(), + "mainnet" + ); assert_eq!(ob_yaml.get_subgraph_keys().unwrap().len(), 2); let subgraph = ob_yaml.get_subgraph("mainnet").unwrap(); @@ -278,6 +286,10 @@ mod tests { assert_eq!(orderbook.network, network.clone().into()); assert_eq!(orderbook.subgraph, subgraph.into()); assert_eq!(orderbook.label, Some("Primary Orderbook".to_string())); + assert_eq!( + Orderbook::parse_network_key(ob_yaml.documents.clone(), "orderbook1").unwrap(), + "mainnet" + ); assert_eq!(ob_yaml.get_metaboard_keys().unwrap().len(), 2); assert_eq!( @@ -296,6 +308,10 @@ mod tests { Address::from_str("0x0000000000000000000000000000000000000002").unwrap() ); assert_eq!(deployer.network, network.into()); + assert_eq!( + Deployer::parse_network_key(ob_yaml.documents.clone(), "deployer1").unwrap(), + "mainnet" + ); assert!(ob_yaml.get_sentry().unwrap()); diff --git a/packages/orderbook/test/js_api/gui.test.ts b/packages/orderbook/test/js_api/gui.test.ts index e47465038..1d3dcbc59 100644 --- a/packages/orderbook/test/js_api/gui.test.ts +++ b/packages/orderbook/test/js_api/gui.test.ts @@ -6,7 +6,7 @@ import { AllFieldValuesResult, AllowancesResult, ApprovalCalldataResult, - AvailableDeployments, + DeploymentKeys, DepositAndAddOrderCalldataResult, DepositCalldataResult, Gui, @@ -345,17 +345,10 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Gui', async function () }); it('should return available deployments', async () => { - const deployments: AvailableDeployments = - await DotrainOrderGui.getAvailableDeployments(dotrainWithGui); + const deployments: DeploymentKeys = await DotrainOrderGui.getDeploymentKeys(dotrainWithGui); assert.equal(deployments.length, 2); - assert.equal(deployments[0].key, 'other-deployment'); - assert.equal(deployments[1].key, 'some-deployment'); - }); - - it('should return error if gui config is not found', async () => { - await expect(DotrainOrderGui.chooseDeployment(dotrain, 'some-deployment')).rejects.toEqual( - new Error('Gui config not found') - ); + assert.equal(deployments[0], 'some-deployment'); + assert.equal(deployments[1], 'other-deployment'); }); it('should initialize gui object', async () => { @@ -1159,6 +1152,40 @@ ${dotrainWithoutVaultIds}`; assert.equal(tokenInfo.decimals, 18); }); + it('should replace select token', async () => { + gui.removeSelectToken('token1'); + gui.removeSelectToken('token2'); + + mockServer + .forPost('/rpc-url') + .once() + .withBodyIncluding('0x82ad56cb') + .thenSendJsonRpcResult( + '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000007546f6b656e203100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000025431000000000000000000000000000000000000000000000000000000000000' + ); + mockServer + .forPost('/rpc-url') + .once() + .withBodyIncluding('0x82ad56cb') + .thenSendJsonRpcResult( + '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000754656b656e203200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000025432000000000000000000000000000000000000000000000000000000000000' + ); + + await gui.saveSelectToken('token1', '0x6666666666666666666666666666666666666666'); + assert.equal(gui.isSelectTokenSet('token1'), true); + let tokenInfo = await gui.getTokenInfo('token1'); + assert.equal(tokenInfo.name, 'Token 1'); + assert.equal(tokenInfo.symbol, 'T1'); + assert.equal(tokenInfo.decimals, 6); + + await gui.replaceSelectToken('token1', '0x8888888888888888888888888888888888888888'); + assert.equal(gui.isSelectTokenSet('token1'), true); + tokenInfo = await gui.getTokenInfo('token1'); + assert.equal(tokenInfo.name, 'Teken 2'); + assert.equal(tokenInfo.symbol, 'T2'); + assert.equal(tokenInfo.decimals, 18); + }); + it('should remove select token', async () => { let dotrain3 = ` ${guiConfig3}