diff --git a/.vscode/settings.json b/.vscode/settings.json index 237f93c57..b8dfff267 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,6 +3,7 @@ "svelte.enable-ts-plugin": true, "rust-analyzer.linkedProjects": ["./Cargo.toml", "tauri-app/src-tauri/Cargo.toml"], + "[rust]": { "editor.defaultFormatter": "rust-lang.rust-analyzer", "editor.formatOnSave": true, diff --git a/Cargo.toml b/Cargo.toml index a357ee824..12b00e29b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ resolver = "2" [workspace.package] edition = "2021" license = "LicenseRef-DCL-1.0" -author = "Rain Open Source LLC" +author = "Rain Open Source Software Ltd" version = "0.0.0-alpha.0" homepage = "https://github.com/rainprotocol/rain.orderbook" diff --git a/README.md b/README.md index 4798d4664..d83cfe2ef 100644 --- a/README.md +++ b/README.md @@ -26,3 +26,33 @@ cd packages/webapp && nix develop -c npm run dev ``` nix develop .#tauri-shell --command cargo tauri dev ``` + +## Legal stuff + +Everything is under DecentraLicense 1.0 (DCL-1.0) which can be found in `LICENSES/`. + +This is basically `CAL-1.0` which is an open source license +https://opensource.org/license/cal-1-0 + +The non-legal summary of DCL-1.0 is that the source is open, as expected, but +also user data in the systems that this code runs on must also be made available +to those users as relevant, and that private keys remain private. + +Roughly it's "not your keys, not your coins" aware, as close as we could get in +legalese. + +This is the default situation on permissionless blockchains, so shouldn't require +any additional effort by dev-users to adhere to the license terms. + +This repo is REUSE 3.2 compliant https://reuse.software/spec-3.2/ and compatible +with `reuse` tooling (also available in the nix shell here). + +``` +nix develop -c rainix-sol-legal +``` + +## Contributions + +Contributions are welcome **under the same license** as above. + +Contributors agree and warrant that their contributions are compliant. \ No newline at end of file diff --git a/REUSE.toml b/REUSE.toml index 89be37d82..9a2a87adb 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -23,16 +23,10 @@ path = [ ".env.example", "tauri-app/.env.example", "prep-all.sh", -] -SPDX-FileCopyrightText = "Copyright (c) 2020 thedavidmeister" -SPDX-License-Identifier = "LicenseRef-DCL-1.0" - -[[annotations]] -path = [ "packages/**/", "subgraph/**/", "crates/**/", "tauri-app/**/", ] -SPDX-FileCopyrightText = "Copyright (c) 2020 Rain Open Source LLC" +SPDX-FileCopyrightText = "Copyright (c) 2020 Rain Open Source Software Ltd" SPDX-License-Identifier = "LicenseRef-DCL-1.0" diff --git a/crates/common/src/add_order.rs b/crates/common/src/add_order.rs index 36eeaa3fa..32fd28b5e 100644 --- a/crates/common/src/add_order.rs +++ b/crates/common/src/add_order.rs @@ -60,6 +60,10 @@ pub enum AddOrderArgsError { #[cfg(not(target_family = "wasm"))] #[error(transparent)] ForkCallError(#[from] ForkCallError), + #[error("Input token not found for index: {0}")] + InputTokenNotFound(String), + #[error("Output token not found for index: {0}")] + OutputTokenNotFound(String), } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] @@ -80,24 +84,29 @@ impl AddOrderArgs { ) -> Result { let random_vault_id: U256 = rand::random(); let mut inputs = vec![]; - for input in &deployment.order.inputs { - if let Some(decimals) = input.token.decimals { + for (i, input) in deployment.order.inputs.iter().enumerate() { + let input_token = input + .token + .as_ref() + .ok_or_else(|| AddOrderArgsError::InputTokenNotFound(i.to_string()))?; + + if let Some(decimals) = input_token.decimals { inputs.push(IO { - token: input.token.address, + token: input_token.address, vaultId: input.vault_id.unwrap_or(random_vault_id), decimals, }); } else { - let client = ReadableClientHttp::new_from_url(input.token.network.rpc.to_string())?; + let client = ReadableClientHttp::new_from_url(input_token.network.rpc.to_string())?; let parameters = ReadContractParameters { - address: input.token.address, + address: input_token.address, call: decimalsCall {}, block_number: None, gas: None, }; let decimals = client.read(parameters).await?._0; inputs.push(IO { - token: input.token.address, + token: input_token.address, vaultId: input.vault_id.unwrap_or(random_vault_id), decimals, }); @@ -105,25 +114,30 @@ impl AddOrderArgs { } let mut outputs = vec![]; - for output in &deployment.order.outputs { - if let Some(decimals) = output.token.decimals { + for (i, output) in deployment.order.outputs.iter().enumerate() { + let output_token = output + .token + .as_ref() + .ok_or_else(|| AddOrderArgsError::OutputTokenNotFound(i.to_string()))?; + + if let Some(decimals) = output_token.decimals { outputs.push(IO { - token: output.token.address, + token: output_token.address, vaultId: output.vault_id.unwrap_or(random_vault_id), decimals, }); } else { let client = - ReadableClientHttp::new_from_url(output.token.network.rpc.to_string())?; + ReadableClientHttp::new_from_url(output_token.network.rpc.to_string())?; let parameters = ReadContractParameters { - address: output.token.address, + address: output_token.address, call: decimalsCall {}, block_number: None, gas: None, }; let decimals = client.read(parameters).await?._0; outputs.push(IO { - token: output.token.address, + token: output_token.address, vaultId: output.vault_id.unwrap_or(random_vault_id), decimals, }); @@ -489,16 +503,16 @@ price: 2e18; key: "".to_string(), inputs: vec![ OrderIO { - token: token1_arc.clone(), + token: Some(token1_arc.clone()), vault_id: None, }, OrderIO { - token: token2_arc.clone(), + token: Some(token2_arc.clone()), vault_id: Some(known_vault_id), }, ], outputs: vec![OrderIO { - token: token3_arc.clone(), + token: Some(token3_arc.clone()), vault_id: None, }], network: network_arc.clone(), @@ -599,16 +613,16 @@ _ _: 0 0; key: "".to_string(), inputs: vec![ OrderIO { - token: token1_arc.clone(), + token: Some(token1_arc.clone()), vault_id: Some(U256::from(2)), }, OrderIO { - token: token2_arc.clone(), + token: Some(token2_arc.clone()), vault_id: Some(U256::from(1)), }, ], outputs: vec![OrderIO { - token: token3_arc.clone(), + token: Some(token3_arc.clone()), vault_id: Some(U256::from(4)), }], network: network_arc.clone(), @@ -745,16 +759,16 @@ _ _: 0 0; key: "".to_string(), inputs: vec![ OrderIO { - token: token1_arc.clone(), + token: Some(token1_arc.clone()), vault_id: None, }, OrderIO { - token: token2_arc.clone(), + token: Some(token2_arc.clone()), vault_id: Some(known_vault_id), }, ], outputs: vec![OrderIO { - token: token3_arc.clone(), + token: Some(token3_arc.clone()), vault_id: None, }], network: network_arc.clone(), diff --git a/crates/common/src/dotrain_order/calldata.rs b/crates/common/src/dotrain_order/calldata.rs index 19d755178..88d4a3504 100644 --- a/crates/common/src/dotrain_order/calldata.rs +++ b/crates/common/src/dotrain_order/calldata.rs @@ -45,18 +45,23 @@ impl DotrainOrder { &self, deployment_name: &str, owner: &str, - token_deposits: &HashMap, + token_deposits: &HashMap, ) -> Result, DotrainOrderCalldataError> { let deployment = self.get_deployment(deployment_name)?; let orderbook = self.get_orderbook(deployment_name)?; let mut calldatas = Vec::new(); - for output in &deployment.order.outputs { - if let Some(deposit_amount) = token_deposits.get(&output.token.address) { + for (i, output) in deployment.order.outputs.iter().enumerate() { + let output_token = output + .token + .as_ref() + .ok_or_else(|| DotrainOrderCalldataError::OutputTokenNotFound(i.to_string()))?; + + if let Some(deposit_amount) = token_deposits.get(&output_token.key) { let deposit_amount = deposit_amount.to_owned(); let deposit_args = DepositArgs { - token: output.token.address, + token: output_token.address, amount: deposit_amount, vault_id: U256::default(), }; @@ -75,7 +80,7 @@ impl DotrainOrder { .get_approve_calldata(transaction_args, allowance) .await?; calldatas.push(ApprovalCalldata { - token: output.token.address, + token: output_token.address, calldata: Bytes::copy_from_slice(&approve_call), }); } @@ -94,14 +99,18 @@ impl DotrainOrder { let mut calldatas = Vec::new(); for (i, output) in deployment.order.outputs.iter().enumerate() { + let output_token = output + .token + .as_ref() + .ok_or_else(|| DotrainOrderCalldataError::OutputTokenNotFound(i.to_string()))?; let vault_id = output .vault_id .ok_or(DotrainOrderCalldataError::VaultIdNotFound(i.to_string()))?; let token_deposit = token_deposits - .get(&(vault_id, output.token.address)) + .get(&(vault_id, output_token.address)) .ok_or(DotrainOrderCalldataError::TokenNotFound( - output.token.address.to_string(), + output_token.address.to_string(), ))?; if *token_deposit == U256::ZERO { @@ -109,7 +118,7 @@ impl DotrainOrder { } let calldata = DepositArgs { - token: output.token.address, + token: output_token.address, amount: token_deposit.to_owned(), vault_id, } @@ -150,12 +159,15 @@ pub enum DotrainOrderCalldataError { #[error("Orderbook not found")] OrderbookNotFound, - #[error("Token not found {0}")] - TokenNotFound(String), + #[error("Token not found for output index: {0}")] + OutputTokenNotFound(String), #[error("Vault id not found for output index: {0}")] VaultIdNotFound(String), + #[error("Token not found {0}")] + TokenNotFound(String), + #[error(transparent)] DepositError(#[from] DepositError), diff --git a/crates/common/src/types/order_detail_extended.rs b/crates/common/src/types/order_detail_extended.rs index 0b2eebd79..7ddf5a617 100644 --- a/crates/common/src/types/order_detail_extended.rs +++ b/crates/common/src/types/order_detail_extended.rs @@ -10,6 +10,8 @@ use typeshare::typeshare; #[serde(rename_all = "camelCase")] #[typeshare] pub struct OrderDetailExtended { + #[typeshare(typescript(type = "OrderSubgraph"))] + #[cfg_attr(target_family = "wasm", tsify(type = "OrderSubgraph"))] pub order: Order, pub rainlang: Option, } diff --git a/crates/js_api/src/gui/deposits.rs b/crates/js_api/src/gui/deposits.rs index fad1e7b8b..d2874d9f1 100644 --- a/crates/js_api/src/gui/deposits.rs +++ b/crates/js_api/src/gui/deposits.rs @@ -16,12 +16,12 @@ impl DotrainOrderGui { let deployment = self.get_current_deployment()?; self.deposits .iter() - .map(|(token, value)| { + .map(|(key, value)| { let gui_deposit = deployment .deposits .iter() - .find(|dg| dg.token.key == *token) - .ok_or(GuiError::DepositTokenNotFound(token.clone()))?; + .find(|dg| dg.token.as_ref().map_or(false, |t| t.key == *key)) + .ok_or(GuiError::DepositTokenNotFound(key.clone()))?; let amount: String = if value.is_preset { let index = value .value @@ -35,10 +35,16 @@ impl DotrainOrderGui { } else { value.value.clone() }; + + if gui_deposit.token.is_none() { + return Err(GuiError::TokenMustBeSelected(key.clone())); + } + let token = gui_deposit.token.as_ref().unwrap(); + Ok(TokenDeposit { - token: gui_deposit.token.key.clone(), + token: token.key.clone(), amount, - address: gui_deposit.token.address, + address: token.address, }) }) .collect::, GuiError>>() @@ -50,7 +56,7 @@ impl DotrainOrderGui { let gui_deposit = deployment .deposits .iter() - .find(|dg| dg.token.key == token) + .find(|dg| dg.token.as_ref().map_or(false, |t| t.key == token)) .ok_or(GuiError::DepositTokenNotFound(token.clone()))?; let value = if let Some(index) = gui_deposit.presets.iter().position(|p| **p == amount) { @@ -75,13 +81,13 @@ impl DotrainOrderGui { } #[wasm_bindgen(js_name = "getDepositPresets")] - pub fn get_deposit_presets(&self, token: String) -> Result, GuiError> { + pub fn get_deposit_presets(&self, key: String) -> Result, GuiError> { let deployment = self.get_current_deployment()?; let gui_deposit = deployment .deposits .iter() - .find(|dg| dg.token.key == token) - .ok_or(GuiError::DepositTokenNotFound(token.clone()))?; + .find(|dg| dg.token.as_ref().map_or(false, |t| t.key == key)) + .ok_or(GuiError::DepositTokenNotFound(key.clone()))?; Ok(gui_deposit.presets.clone()) } } diff --git a/crates/js_api/src/gui/mod.rs b/crates/js_api/src/gui/mod.rs index 35701359a..2f87c83e8 100644 --- a/crates/js_api/src/gui/mod.rs +++ b/crates/js_api/src/gui/mod.rs @@ -3,13 +3,16 @@ 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::*}; use rain_orderbook_common::{ dotrain_order::{calldata::DotrainOrderCalldataError, DotrainOrder, DotrainOrderError}, - erc20::{TokenInfo, ERC20}, + erc20::ERC20, }; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -23,12 +26,17 @@ 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 TokenInfos(#[tsify(type = "Map")] BTreeMap); -impl_all_wasm_traits!(TokenInfos); +pub struct TokenInfo { + pub address: Address, + pub decimals: u8, + pub name: String, + pub symbol: String, +} +impl_all_wasm_traits!(TokenInfo); #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Tsify)] pub struct GuiDetails { @@ -44,75 +52,26 @@ pub struct DotrainOrderGui { selected_deployment: String, field_values: BTreeMap, deposits: BTreeMap, - select_tokens: Option>, - onchain_token_info: BTreeMap, } #[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")] pub async fn choose_deployment( dotrain: String, deployment_name: String, - multicall_address: Option, ) -> Result { let dotrain_order = DotrainOrder::new(dotrain, None).await?; - let gui = dotrain_order - .dotrain_yaml() - .get_gui()? - .ok_or(GuiError::GuiConfigNotFound)?; - - let (_, gui_deployment) = gui - .deployments - .into_iter() - .find(|(name, _)| name == &deployment_name) - .ok_or(GuiError::DeploymentNotFound(deployment_name.clone()))?; - - let select_tokens = gui_deployment.select_tokens.clone().map(|tokens| { - tokens - .iter() - .map(|token: &String| (token.clone(), Address::ZERO)) - .collect::>() - }); - - let rpc_url = gui_deployment - .deployment - .order - .orderbook - .clone() - .ok_or(GuiError::OrderbookNotFound)? - .network - .rpc - .clone(); - let mut onchain_token_info: BTreeMap = BTreeMap::new(); - for token in gui_deployment.deposits.iter() { - if onchain_token_info.contains_key(&token.token.address) { - continue; - } - - if let Some(select_tokens) = &select_tokens { - if select_tokens.contains_key(&token.token.key) { - continue; - } - } - - let erc20 = ERC20::new(rpc_url.clone(), token.token.address); - let token_info = erc20.token_info(multicall_address.clone()).await?; - onchain_token_info.insert(token.token.address, token_info); + let keys = Gui::parse_deployment_keys(dotrain_order.dotrain_yaml().documents.clone())?; + if !keys.contains(&deployment_name) { + return Err(GuiError::DeploymentNotFound(deployment_name.clone())); } Ok(Self { @@ -120,8 +79,6 @@ impl DotrainOrderGui { selected_deployment: deployment_name.clone(), field_values: BTreeMap::new(), deposits: BTreeMap::new(), - select_tokens, - onchain_token_info, }) } @@ -148,21 +105,52 @@ impl DotrainOrderGui { Ok(gui_deployment.clone()) } - /// Get all token infos in input and output vaults + /// Get token info for a given key /// - /// Returns a map of token address to [`TokenInfo`] - #[wasm_bindgen(js_name = "getTokenInfos")] - pub fn get_token_infos(&self) -> Result { - Ok(TokenInfos(self.onchain_token_info.clone())) + /// Returns a [`TokenInfo`] + #[wasm_bindgen(js_name = "getTokenInfo")] + pub async fn get_token_info(&self, key: String) -> Result { + 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 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 }) } } @@ -194,6 +182,8 @@ pub enum GuiError { TokenMustBeSelected(String), #[error("Binding has no presets: {0}")] BindingHasNoPresets(String), + #[error("Token not in select tokens: {0}")] + TokenNotInSelectTokens(String), #[error(transparent)] DotrainOrderError(#[from] DotrainOrderError), #[error(transparent)] diff --git a/crates/js_api/src/gui/order_operations.rs b/crates/js_api/src/gui/order_operations.rs index e917edc5c..6390962b3 100644 --- a/crates/js_api/src/gui/order_operations.rs +++ b/crates/js_api/src/gui/order_operations.rs @@ -54,39 +54,42 @@ impl DotrainOrderGui { .cloned() } - fn get_deposits_as_map(&self) -> Result, GuiError> { - let mut map: HashMap = HashMap::new(); + async fn get_deposits_as_map(&self) -> Result, GuiError> { + let mut map: HashMap = HashMap::new(); for d in self.get_deposits()? { - let token_decimals = self - .onchain_token_info - .get(&d.address) - .ok_or(GuiError::TokenNotFound(d.address.to_string()))? - .decimals; - let amount = parse_units(&d.amount, token_decimals)?.into(); - map.insert(d.address, amount); + let token_info = self.get_token_info(d.token.clone()).await?; + let amount = parse_units(&d.amount, token_info.decimals)?.into(); + map.insert(d.token, amount); } Ok(map) } - fn get_vaults_and_deposits( + async fn get_vaults_and_deposits( &self, deployment: &GuiDeployment, ) -> Result, GuiError> { - let deposits_map = self.get_deposits_as_map()?; + let deposits_map = self.get_deposits_as_map().await?; let results = deployment .deployment .order .outputs .clone() .into_iter() - .filter(|output| deposits_map.contains_key(&output.token.address)) + .filter(|output| { + output + .token + .as_ref() + .map_or(false, |token| deposits_map.contains_key(&token.key)) + }) .map(|output| { - ( - output.clone(), - *deposits_map.get(&output.token.address).unwrap(), - ) + if output.token.is_none() { + return Err(GuiError::SelectTokensNotSet); + } + let token = output.token.as_ref().unwrap(); + + Ok((output.clone(), *deposits_map.get(&token.key).unwrap())) }) - .collect(); + .collect::, GuiError>>()?; Ok(results) } @@ -118,15 +121,20 @@ impl DotrainOrderGui { #[wasm_bindgen(js_name = "checkAllowances")] pub async fn check_allowances(&self, owner: String) -> Result { let deployment = self.get_current_deployment()?; - self.check_token_addresses()?; + self.check_select_tokens()?; let orderbook = self.get_orderbook()?; - let vaults_and_deposits = self.get_vaults_and_deposits(&deployment)?; + let vaults_and_deposits = self.get_vaults_and_deposits(&deployment).await?; let mut results = Vec::new(); for (order_io, amount) in vaults_and_deposits.iter() { + if order_io.token.is_none() { + return Err(GuiError::SelectTokensNotSet); + } + let token = order_io.token.as_ref().unwrap(); + let deposit_args = DepositArgs { - token: order_io.token.address, + token: token.address, vault_id: rand::random(), amount: *amount, }; @@ -148,11 +156,15 @@ impl DotrainOrderGui { owner: String, ) -> Result { let deployment = self.get_current_deployment()?; - self.check_token_addresses()?; + self.check_select_tokens()?; let calldatas = self .dotrain_order - .generate_approval_calldatas(&deployment.key, &owner, &self.get_deposits_as_map()?) + .generate_approval_calldatas( + &deployment.key, + &owner, + &self.get_deposits_as_map().await?, + ) .await?; Ok(ApprovalCalldataResult(calldatas)) } @@ -187,19 +199,26 @@ impl DotrainOrderGui { #[wasm_bindgen(js_name = "generateDepositCalldatas")] pub async fn generate_deposit_calldatas(&mut self) -> Result { let deployment = self.get_current_deployment()?; - self.check_token_addresses()?; + self.check_select_tokens()?; self.populate_vault_ids(&deployment)?; let deployment = self.get_current_deployment()?; let token_deposits = self - .get_vaults_and_deposits(&deployment)? + .get_vaults_and_deposits(&deployment) + .await? .iter() .enumerate() .map(|(i, (order_io, amount))| { let vault_id = order_io .vault_id .ok_or(GuiError::VaultIdNotFound(i.to_string()))?; - Ok(((vault_id, order_io.token.address), *amount)) + + if order_io.token.is_none() { + return Err(GuiError::SelectTokensNotSet); + } + let token = order_io.token.as_ref().unwrap(); + + Ok(((vault_id, token.address), *amount)) }) .collect::, GuiError>>()?; let calldatas = self @@ -215,7 +234,7 @@ impl DotrainOrderGui { &mut self, ) -> Result { let deployment = self.get_current_deployment()?; - self.check_token_addresses()?; + self.check_select_tokens()?; self.populate_vault_ids(&deployment)?; self.update_config_source_bindings(&deployment)?; let deployment = self.get_current_deployment()?; @@ -232,20 +251,27 @@ impl DotrainOrderGui { &mut self, ) -> Result { let deployment = self.get_current_deployment()?; - self.check_token_addresses()?; + self.check_select_tokens()?; self.populate_vault_ids(&deployment)?; self.update_config_source_bindings(&deployment)?; let deployment = self.get_current_deployment()?; let token_deposits = self - .get_vaults_and_deposits(&deployment)? + .get_vaults_and_deposits(&deployment) + .await? .iter() .enumerate() .map(|(i, (order_io, amount))| { let vault_id = order_io .vault_id .ok_or(GuiError::VaultIdNotFound(i.to_string()))?; - Ok(((vault_id, order_io.token.address), *amount)) + + if order_io.token.is_none() { + return Err(GuiError::SelectTokensNotSet); + } + let token = order_io.token.as_ref().unwrap(); + + Ok(((vault_id, token.address), *amount)) }) .collect::, GuiError>>()?; diff --git a/crates/js_api/src/gui/select_tokens.rs b/crates/js_api/src/gui/select_tokens.rs index 005662b5d..966b0b056 100644 --- a/crates/js_api/src/gui/select_tokens.rs +++ b/crates/js_api/src/gui/select_tokens.rs @@ -1,72 +1,107 @@ -use std::str::FromStr; - use super::*; - -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Tsify)] -pub struct SelectTokens(#[tsify(type = "Map")] BTreeMap); -impl_all_wasm_traits!(SelectTokens); +use rain_orderbook_app_settings::{ + deployment::Deployment, network::Network, order::Order, token::Token, +}; +use std::str::FromStr; #[wasm_bindgen] impl DotrainOrderGui { - pub fn check_token_addresses(&self) -> Result<(), GuiError> { - if let Some(select_tokens) = &self.select_tokens { - for (token, address) in select_tokens.iter() { - if address == &Address::ZERO { - return Err(GuiError::TokenMustBeSelected(token.clone())); + #[wasm_bindgen(js_name = "getSelectTokens")] + pub fn get_select_tokens(&self) -> Result, GuiError> { + 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")] + pub fn is_select_token_set(&self, key: String) -> Result { + Ok(self.dotrain_order.orderbook_yaml().get_token(&key).is_ok()) + } + + #[wasm_bindgen(js_name = "checkSelectTokens")] + pub fn check_select_tokens(&self) -> Result<(), GuiError> { + let select_tokens = Gui::parse_select_tokens( + self.dotrain_order.dotrain_yaml().documents, + &self.selected_deployment, + )?; + + 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())); } } } - Ok(()) - } - /// Get all selected tokens and their addresses - /// - /// Returns a map of token name to address - #[wasm_bindgen(js_name = "getSelectTokens")] - pub fn get_select_tokens(&self) -> Result { - let select_tokens = self - .select_tokens - .clone() - .ok_or(GuiError::SelectTokensNotSet)?; - Ok(SelectTokens(select_tokens)) + Ok(()) } - #[wasm_bindgen(js_name = "saveSelectTokenAddress")] - pub async fn save_select_token_address( + #[wasm_bindgen(js_name = "saveSelectToken")] + pub async fn save_select_token( &mut self, - token_name: String, + key: String, address: String, ) -> Result<(), GuiError> { - let deployment = self.get_current_deployment()?; - let mut select_tokens = self - .select_tokens - .clone() - .ok_or(GuiError::SelectTokensNotSet)?; - if !select_tokens.contains_key(&token_name) { - return Err(GuiError::TokenNotFound(token_name.clone())); + 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)?; - select_tokens.insert(token_name.clone(), address); - self.select_tokens = Some(select_tokens); - 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?; - self.onchain_token_info.insert(address, token_info); - self.dotrain_order - .orderbook_yaml() - .get_token(&token_name)? - .update_address(&address.to_string())?; + Token::add_record_to_yaml( + self.dotrain_order.orderbook_yaml().documents, + &key, + &network_key, + &address.to_string(), + Some(&token_info.decimals.to_string()), + Some(&token_info.name), + Some(&token_info.symbol), + )?; + 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 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())); + } + + Token::remove_record_from_yaml(self.dotrain_order.orderbook_yaml().documents, &key)?; Ok(()) } } diff --git a/crates/js_api/src/gui/state_management.rs b/crates/js_api/src/gui/state_management.rs index a256a0d0d..18e7b5b26 100644 --- a/crates/js_api/src/gui/state_management.rs +++ b/crates/js_api/src/gui/state_management.rs @@ -1,15 +1,20 @@ use super::*; +use rain_orderbook_app_settings::token::Token; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] struct SerializedGuiState { field_values: BTreeMap, deposits: BTreeMap, + select_tokens: BTreeMap, + vault_ids: BTreeMap<(bool, u8), Option>, } #[wasm_bindgen] impl DotrainOrderGui { #[wasm_bindgen(js_name = "serializeState")] - pub fn serialize(&self) -> Result { + pub fn serialize_state(&self) -> Result { + let deployment = self.get_current_deployment()?; + let mut field_values = BTreeMap::new(); for (k, v) in self.field_values.iter() { let preset = if v.is_preset { @@ -50,9 +55,27 @@ impl DotrainOrderGui { deposits.insert(k.clone(), preset); } + let mut select_tokens: BTreeMap = BTreeMap::new(); + if let Some(st) = deployment.select_tokens { + for key in st { + let token = self.dotrain_order.orderbook_yaml().get_token(&key)?; + select_tokens.insert(key, token); + } + } + + let mut vault_ids = BTreeMap::new(); + for (i, input) in deployment.deployment.order.inputs.iter().enumerate() { + vault_ids.insert((true, i as u8), input.vault_id.map(|v| v.to_string())); + } + for (i, output) in deployment.deployment.order.outputs.iter().enumerate() { + vault_ids.insert((false, i as u8), output.vault_id.map(|v| v.to_string())); + } + let state = SerializedGuiState { field_values: field_values.clone(), deposits: deposits.clone(), + select_tokens: select_tokens.clone(), + vault_ids: vault_ids.clone(), }; let bytes = bincode::serialize(&state)?; @@ -65,6 +88,7 @@ impl DotrainOrderGui { #[wasm_bindgen(js_name = "deserializeState")] pub fn deserialize_state(&mut self, serialized: String) -> Result<(), GuiError> { + let deployment = self.get_current_deployment()?; let compressed = URL_SAFE.decode(serialized)?; let mut decoder = GzDecoder::new(&compressed[..]); @@ -91,6 +115,7 @@ impl DotrainOrderGui { (k, pair_value) }) .collect::>(); + let deposits = state .deposits .into_iter() @@ -113,6 +138,40 @@ impl DotrainOrderGui { self.field_values = field_values; self.deposits = deposits; + for (key, token) in state.select_tokens { + let select_tokens = deployment + .select_tokens + .as_ref() + .ok_or(GuiError::SelectTokensNotSet)?; + if !select_tokens.contains(&key) { + return Err(GuiError::TokenNotInSelectTokens(key)); + } + if self.is_select_token_set(key.clone())? { + Token::remove_record_from_yaml( + self.dotrain_order.orderbook_yaml().documents.clone(), + &key, + )?; + } + Token::add_record_to_yaml( + self.dotrain_order.orderbook_yaml().documents.clone(), + &key, + &token.network.key, + &token.address.to_string(), + token.decimals.map(|d| d.to_string()).as_deref(), + token.label.map(|l| l.to_string()).as_deref(), + token.symbol.map(|s| s.to_string()).as_deref(), + )?; + } + + for ((is_input, index), vault_id) in state.vault_ids { + self.dotrain_order + .dotrain_yaml() + .get_order(&deployment.deployment.order.key) + .and_then(|mut order| { + order.update_vault_id(is_input, index, vault_id.unwrap_or_default()) + })?; + } + Ok(()) } 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 8053382cf..37128a635 100644 --- a/crates/settings/src/deployment.rs +++ b/crates/settings/src/deployment.rs @@ -30,10 +30,32 @@ 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>>, - _: Option<&Context>, + context: Option<&Context>, ) -> Result, YamlError> { let mut deployments = HashMap::new(); @@ -53,10 +75,11 @@ impl YamlParsableHash for Deployment { "order string missing in deployment: {deployment_key}" )), )?, - None, + context, )?; - let context = Context::with_order(Arc::new(order.clone())); + let mut context = Context::new(); + context.add_order(Arc::new(order.clone())); let scenario = Scenario::parse_from_yaml( documents.clone(), diff --git a/crates/settings/src/gui.rs b/crates/settings/src/gui.rs index 5b50b849a..3c9a28b31 100644 --- a/crates/settings/src/gui.rs +++ b/crates/settings/src/gui.rs @@ -98,7 +98,7 @@ impl GuiConfigSource { .map(Arc::clone)?; Ok(GuiDeposit { - token: token.clone(), + token: Some(token.clone()), presets: deposit_source.presets.clone(), }) }) @@ -187,8 +187,8 @@ impl_all_wasm_traits!(GuiPreset); #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] #[cfg_attr(target_family = "wasm", derive(Tsify))] pub struct GuiDeposit { - #[typeshare(typescript(type = "Token"))] - pub token: Arc, + #[typeshare(typescript(type = "Token | undefined"))] + pub token: Option>, #[cfg_attr(target_family = "wasm", tsify(type = "string[]"))] pub presets: Vec, } @@ -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( @@ -306,10 +395,32 @@ impl YamlParseableValue for Gui { for (deployment_name, deployment_yaml) in deployments { let deployment_name = deployment_name.as_str().unwrap_or_default().to_string(); - let deployment = - Deployment::parse_from_yaml(documents.clone(), &deployment_name, None)?; + let mut context = Context::new(); + + let select_tokens = match optional_vec(deployment_yaml, "select-tokens") { + Some(tokens) => Some( + tokens + .iter() + .enumerate() + .map(|(select_token_index, select_token_value)| { + Ok(select_token_value.as_str().ok_or(YamlError::ParseError(format!( + "select-token value must be a string for select-token index: {select_token_index} in gui deployment: {deployment_name}", + )))?.to_string()) + }) + .collect::, YamlError>>()?, + ), + None => None, + }; + if let Some(ref select_tokens) = select_tokens { + context.add_select_tokens(select_tokens.clone()); + } - let context = Context::with_order(deployment.order.clone()); + let deployment = Deployment::parse_from_yaml( + documents.clone(), + &deployment_name, + Some(&context), + )?; + context.add_order(deployment.order.clone()); let name = require_string( deployment_yaml, @@ -340,7 +451,7 @@ impl YamlParseableValue for Gui { Some(format!( "token string missing for deposit index: {deposit_index} in gui deployment: {deployment_name}", )), - )?, None)?; + )?, None); let presets = require_vec( deposit_value, @@ -359,7 +470,7 @@ impl YamlParseableValue for Gui { .collect::, YamlError>>()?; let gui_deposit = GuiDeposit { - token: Arc::new(token), + token: token.ok().map(Arc::new), presets, }; Ok(gui_deposit) @@ -425,21 +536,6 @@ impl YamlParseableValue for Gui { }) .collect::, YamlError>>()?; - let select_tokens = match optional_vec(deployment_yaml, "select-tokens") { - Some(tokens) => Some( - tokens - .iter() - .enumerate() - .map(|(select_token_index, select_token_value)| { - Ok(select_token_value.as_str().ok_or(YamlError::ParseError(format!( - "select-token value must be a string for select-token index: {select_token_index} in gui deployment: {deployment_name}", - )))?.to_string()) - }) - .collect::, YamlError>>()?, - ), - None => None, - }; - let gui_deployment = GuiDeployment { document: document.clone(), key: deployment_name.clone(), @@ -585,7 +681,10 @@ mod tests { assert_eq!(deployment.description, "test-deployment-description"); assert_eq!(deployment.deposits.len(), 1); let deposit = &deployment.deposits[0]; - assert_eq!(deposit.token.label, Some("test-token".to_string())); + assert_eq!( + deposit.token.as_ref().unwrap().label, + Some("test-token".to_string()) + ); assert_eq!(deposit.presets.len(), 2); assert_eq!(deposit.presets[0], "1.3".to_string()); assert_eq!(deposit.presets[1], "2.7".to_string()); @@ -855,24 +954,6 @@ gui: let yaml = r#" gui: - name: test - description: test - deployments: - deployment1: - name: test - description: test - deposits: - - token: test -"#; - let error = Gui::parse_from_yaml_optional( - vec![get_document(&format!("{yaml_prefix}{yaml}"))], - None, - ) - .unwrap_err(); - assert_eq!(error, YamlError::KeyNotFound("test".to_string())); - - let yaml = r#" -gui: name: test description: test deployments: @@ -1149,12 +1230,12 @@ gui: let deployment = gui.deployments.get("deployment1").unwrap(); assert_eq!(deployment.name, "test"); assert_eq!(deployment.description, "test"); - assert_eq!(deployment.deposits[0].token.key, "token1"); + assert_eq!(deployment.deposits[0].token.as_ref().unwrap().key, "token1"); let deployment = gui.deployments.get("deployment2").unwrap(); assert_eq!(deployment.name, "test another"); assert_eq!(deployment.description, "test another"); - assert_eq!(deployment.deposits[0].token.key, "token2"); + assert_eq!(deployment.deposits[0].token.as_ref().unwrap().key, "token2"); } #[test] 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 d87918b19..aa51ccd53 100644 --- a/crates/settings/src/order.rs +++ b/crates/settings/src/order.rs @@ -10,8 +10,9 @@ use strict_yaml_rust::StrictYaml; use thiserror::Error; use typeshare::typeshare; use yaml::{ - context::Context, default_document, optional_string, require_hash, require_string, require_vec, - YamlError, YamlParsableHash, + context::{Context, SelectTokensContext}, + default_document, optional_string, require_hash, require_string, require_vec, YamlError, + YamlParsableHash, }; #[cfg(target_family = "wasm")] @@ -22,8 +23,8 @@ use rain_orderbook_bindings::{impl_all_wasm_traits, wasm_traits::prelude::*}; #[cfg_attr(target_family = "wasm", derive(Tsify))] #[serde(rename_all = "kebab-case")] pub struct OrderIO { - #[typeshare(typescript(type = "Token"))] - pub token: Arc, + #[typeshare(typescript(type = "Token | undefined"))] + pub token: Option>, #[typeshare(typescript(type = "string"))] #[cfg_attr( target_family = "wasm", @@ -44,10 +45,10 @@ pub struct Order { pub document: Arc>, pub key: String, #[typeshare(typescript(type = "OrderIO[]"))] - #[cfg_attr(target_family = "wasm", tsify(type = "Vault[]"))] + #[cfg_attr(target_family = "wasm", tsify(type = "OrderIO[]"))] pub inputs: Vec, #[typeshare(typescript(type = "OrderIO[]"))] - #[cfg_attr(target_family = "wasm", tsify(type = "Vault[]"))] + #[cfg_attr(target_family = "wasm", tsify(type = "OrderIO[]"))] pub outputs: Vec, #[typeshare(typescript(type = "Network"))] pub network: Arc, @@ -222,12 +223,93 @@ 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 { fn parse_all_from_yaml( documents: Vec>>, - _: Option<&Context>, + context: Option<&Context>, ) -> Result, YamlError> { let mut orders = HashMap::new(); @@ -297,16 +379,24 @@ impl YamlParsableHash for Order { "token string missing in input index: {i} in order: {order_key}" )), )?; - let token = Token::parse_from_yaml(documents.clone(), &token_name, None)?; + let token = Token::parse_from_yaml(documents.clone(), &token_name, None); - if let Some(n) = &network { - if token.network != *n { - return Err(YamlError::ParseOrderConfigSourceError( - ParseOrderConfigSourceError::NetworkNotMatch, - )); + if let Ok(ref token) = token { + if let Some(n) = &network { + if token.network != *n { + return Err(YamlError::ParseOrderConfigSourceError( + ParseOrderConfigSourceError::NetworkNotMatch, + )); + } + } else { + network = Some(token.network.clone()); + } + } else if let Some(context) = context { + if !context.is_select_token(&token_name) { + return Err(YamlError::ParseError(format!( + "yaml data for token: {token_name} not found in input index: {i} in order: {order_key}" + ))); } - } else { - network = Some(token.network.clone()); } let vault_id = match optional_string(input, "vault-id") { @@ -315,7 +405,7 @@ impl YamlParsableHash for Order { }; Ok(OrderIO { - token: Arc::new(token), + token: token.ok().map(Arc::new), vault_id, }) }) @@ -336,16 +426,24 @@ impl YamlParsableHash for Order { "token string missing in output index: {i} in order: {order_key}" )), )?; - let token = Token::parse_from_yaml(documents.clone(), &token_name, None)?; + let token = Token::parse_from_yaml(documents.clone(), &token_name, None); - if let Some(n) = &network { - if token.network != *n { - return Err(YamlError::ParseOrderConfigSourceError( - ParseOrderConfigSourceError::NetworkNotMatch, - )); + if let Ok(ref token) = token { + if let Some(n) = &network { + if token.network != *n { + return Err(YamlError::ParseOrderConfigSourceError( + ParseOrderConfigSourceError::NetworkNotMatch, + )); + } + } else { + network = Some(token.network.clone()); + } + } else if let Some(context) = context { + if !context.is_select_token(&token_name) { + return Err(YamlError::ParseError(format!( + "yaml data for token: {token_name} not found in output index: {i} in order: {order_key}" + ))); } - } else { - network = Some(token.network.clone()); } let vault_id = match optional_string(output, "vault-id") { @@ -354,7 +452,7 @@ impl YamlParsableHash for Order { }; Ok(OrderIO { - token: Arc::new(token), + token: token.ok().map(Arc::new), vault_id, }) }) @@ -499,7 +597,7 @@ impl OrderConfigSource { if let Some(n) = &network { if v.network == *n { Ok(OrderIO { - token: v.clone(), + token: Some(v.clone()), vault_id: input.vault_id, }) } else { @@ -508,7 +606,7 @@ impl OrderConfigSource { } else { network = Some(v.network.clone()); Ok(OrderIO { - token: v.clone(), + token: Some(v.clone()), vault_id: input.vault_id, }) } @@ -529,7 +627,7 @@ impl OrderConfigSource { if let Some(n) = &network { if v.network == *n { Ok(OrderIO { - token: v.clone(), + token: Some(v.clone()), vault_id: output.vault_id, }) } else { @@ -538,7 +636,7 @@ impl OrderConfigSource { } else { network = Some(v.network.clone()); Ok(OrderIO { - token: v.clone(), + token: Some(v.clone()), vault_id: output.vault_id, }) } @@ -611,7 +709,7 @@ mod tests { order .inputs .iter() - .map(|v| v.token.clone()) + .map(|v| v.token.clone().unwrap()) .collect::>(), vec![token_input] ); @@ -619,7 +717,7 @@ mod tests { order .outputs .iter() - .map(|v| v.token.clone()) + .map(|v| v.token.clone().unwrap()) .collect::>(), vec![token_output] ); @@ -733,18 +831,6 @@ orders: ) ); - let yaml = r#" -orders: - order1: - inputs: - - token: eth -"#; - let error = Order::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); - assert_eq!( - error, - YamlError::ParseError("missing field: tokens".to_string()) - ); - let yaml = r#" networks: mainnet: @@ -797,6 +883,10 @@ networks: mainnet: rpc: "https://mainnet.infura.io" chain-id: "1" +deployers: + mainnet: + address: 0x0000000000000000000000000000000000000001 + network: mainnet tokens: token-one: network: mainnet @@ -806,6 +896,7 @@ tokens: address: 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa orders: OrderOne: + deployer: mainnet inputs: - token: token-one outputs: @@ -814,6 +905,7 @@ orders: let yaml_two = r#" orders: OrderTwo: + deployer: mainnet inputs: - token: token-one outputs: @@ -838,6 +930,10 @@ networks: mainnet: rpc: "https://mainnet.infura.io" chain-id: "1" +deployers: + mainnet: + address: 0x0000000000000000000000000000000000000001 + network: mainnet tokens: token-one: network: mainnet @@ -847,6 +943,7 @@ tokens: address: 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa orders: DuplicateOrder: + deployer: mainnet inputs: - token: token-one outputs: @@ -855,6 +952,7 @@ orders: let yaml_two = r#" orders: DuplicateOrder: + deployer: mainnet inputs: - token: token-one outputs: 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/scenario.rs b/crates/settings/src/scenario.rs index ec9c3220e..a16c88216 100644 --- a/crates/settings/src/scenario.rs +++ b/crates/settings/src/scenario.rs @@ -64,15 +64,12 @@ impl Scenario { scenario_yaml: &StrictYaml, context: Option<&Context>, ) -> Result<(), YamlError> { - let current_bindings = require_hash( - scenario_yaml, - Some("bindings"), - Some(format!("bindings map missing in scenario: {scenario_key}")), - )? - .iter() - .map(|(binding_key, binding_value)| { - let binding_key = binding_key.as_str().unwrap_or_default(); - let binding_value = require_string( + let mut current_bindings = HashMap::new(); + + if let Some(bindings) = optional_hash(scenario_yaml, "bindings") { + for (binding_key, binding_value) in bindings { + let binding_key = binding_key.as_str().unwrap_or_default(); + let binding_value = require_string( binding_value, None, Some(format!( @@ -80,17 +77,14 @@ impl Scenario { )), )?; - let interpolated_value = match context { - Some(context) => context.interpolate(&binding_value)?, - None => binding_value.to_string(), - }; + let interpolated_value = match context { + Some(context) => context.interpolate(&binding_value)?, + None => binding_value.to_string(), + }; - Ok(( - binding_key.to_string(), - interpolated_value, - )) - }) - .collect::, YamlError>>()?; + current_bindings.insert(binding_key.to_string(), interpolated_value); + } + } let mut bindings = parent_scenario .bindings @@ -121,20 +115,28 @@ impl Scenario { .map(|blocks| Scenario::validate_blocks(&blocks)) .transpose()?; - if let Some(deployer_name) = optional_string(scenario_yaml, "deployer") { - let current_deployer = - Deployer::parse_from_yaml(documents.clone(), &deployer_name, None)?; + let mut current_deployer: Option = None; + if let Ok(dep) = Deployer::parse_from_yaml(documents.clone(), &scenario_key, None) { + current_deployer = Some(dep); + } else if let Some(deployer_name) = optional_string(scenario_yaml, "deployer") { + current_deployer = Some(Deployer::parse_from_yaml( + documents.clone(), + &deployer_name, + None, + )?); + } + + if let Some(current_deployer) = current_deployer { if let Some(parent_deployer) = parent_scenario.deployer.as_ref() { if current_deployer.key != parent_deployer.key { return Err(YamlError::ParseScenarioConfigSourceError( ParseScenarioConfigSourceError::ParentDeployerShadowedError( - deployer_name.clone(), + current_deployer.key.clone(), ), )); } } - *deployer = Some(Arc::new(current_deployer)); } @@ -657,17 +659,6 @@ test: test let yaml = r#" scenarios: - scenario1: - test: test -"#; - let error = Scenario::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); - assert_eq!( - error, - YamlError::ParseError("bindings map missing in scenario: scenario1".to_string()) - ); - - let yaml = r#" -scenarios: scenario1: bindings: key1: diff --git a/crates/settings/src/token.rs b/crates/settings/src/token.rs index 19f8314ab..073104e3f 100644 --- a/crates/settings/src/token.rs +++ b/crates/settings/src/token.rs @@ -7,6 +7,7 @@ use serde::{Deserialize, Serialize}; use std::str::FromStr; use std::sync::RwLock; use std::{collections::HashMap, sync::Arc}; +use strict_yaml_rust::strict_yaml::Hash; use strict_yaml_rust::StrictYaml; use thiserror::Error; use typeshare::typeshare; @@ -75,6 +76,130 @@ impl Token { Ok(self.clone()) } + + pub fn add_record_to_yaml( + documents: Vec>>, + key: &str, + network_key: &str, + address: &str, + decimals: Option<&str>, + label: Option<&str>, + symbol: Option<&str>, + ) -> Result<(), YamlError> { + if Token::parse_from_yaml(documents.clone(), key, None).is_ok() { + return Err(YamlError::KeyShadowing(key.to_string())); + } + + let address = Token::validate_address(address)?; + let decimals = decimals.map(Token::validate_decimals).transpose()?; + Network::parse_from_yaml(documents.clone(), network_key, None)?; + + let mut document = documents[0] + .write() + .map_err(|_| YamlError::WriteLockError)?; + + if let StrictYaml::Hash(ref mut document_hash) = *document { + if !document_hash.contains_key(&StrictYaml::String("tokens".to_string())) + || document_hash + .get_mut(&StrictYaml::String("tokens".to_string())) + .is_none() + { + document_hash.insert( + StrictYaml::String("tokens".to_string()), + StrictYaml::Hash(Hash::new()), + ); + } + + if let Some(StrictYaml::Hash(ref mut tokens)) = + document_hash.get_mut(&StrictYaml::String("tokens".to_string())) + { + if tokens.contains_key(&StrictYaml::String(key.to_string())) { + return Err(YamlError::KeyShadowing(key.to_string())); + } + + let mut token_hash = Hash::new(); + token_hash.insert( + StrictYaml::String("network".to_string()), + StrictYaml::String(network_key.to_string()), + ); + token_hash.insert( + StrictYaml::String("address".to_string()), + StrictYaml::String(address.to_string()), + ); + if let Some(decimals) = decimals { + token_hash.insert( + StrictYaml::String("decimals".to_string()), + StrictYaml::String(decimals.to_string()), + ); + } + if let Some(label) = label { + token_hash.insert( + StrictYaml::String("label".to_string()), + StrictYaml::String(label.to_string()), + ); + } + if let Some(symbol) = symbol { + token_hash.insert( + StrictYaml::String("symbol".to_string()), + StrictYaml::String(symbol.to_string()), + ); + } + + tokens.insert( + StrictYaml::String(key.to_string()), + StrictYaml::Hash(token_hash), + ); + } else { + return Err(YamlError::ParseError("missing field: token".to_string())); + } + } else { + return Err(YamlError::ParseError("document parse error".to_string())); + } + + Ok(()) + } + + pub fn remove_record_from_yaml( + documents: Vec>>, + key: &str, + ) -> Result<(), YamlError> { + for document in documents { + let mut document_write = document.write().map_err(|_| YamlError::WriteLockError)?; + + if let StrictYaml::Hash(ref mut document_hash) = *document_write { + if let Some(StrictYaml::Hash(ref mut tokens)) = + document_hash.get_mut(&StrictYaml::String("tokens".to_string())) + { + if tokens.contains_key(&StrictYaml::String(key.to_string())) { + tokens.remove(&StrictYaml::String(key.to_string())); + return Ok(()); + } + } + } + } + + 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/context.rs b/crates/settings/src/yaml/context.rs index fffa3d67a..bc2cd88eb 100644 --- a/crates/settings/src/yaml/context.rs +++ b/crates/settings/src/yaml/context.rs @@ -5,6 +5,7 @@ use thiserror::Error; #[derive(Debug, Clone, Default)] pub struct Context { pub order: Option>, + pub select_tokens: Option>, } #[derive(Error, Debug, PartialEq)] @@ -35,6 +36,22 @@ pub trait OrderContext { fn resolve_token_path(&self, token: &Token, parts: &[&str]) -> Result; } +pub trait SelectTokensContext { + fn select_tokens(&self) -> Option<&Vec>; + + fn is_select_token(&self, key: &str) -> bool { + self.select_tokens() + .map(|tokens| tokens.iter().any(|t| t == key)) + .unwrap_or(false) + } +} + +impl SelectTokensContext for Context { + fn select_tokens(&self) -> Option<&Vec> { + self.select_tokens.as_ref() + } +} + impl OrderContext for Context { fn order(&self) -> Option<&Arc> { self.order.as_ref() @@ -52,7 +69,10 @@ impl OrderContext for Context { .ok_or_else(|| ContextError::InvalidIndex(index.to_string()))?; match parts.get(1) { - Some(&"token") => self.resolve_token_path(&io.token, &parts[2..]), + Some(&"token") => match &io.token { + Some(token) => self.resolve_token_path(token, &parts[2..]), + None => Err(ContextError::PropertyNotFound("token".to_string())), + }, Some(&"vault-id") => match &io.vault_id { Some(vault_id) => Ok(vault_id.to_string()), None => Err(ContextError::PropertyNotFound("vault-id".to_string())), @@ -83,11 +103,20 @@ impl OrderContext for Context { impl Context { pub fn new() -> Self { - Self { order: None } + Self { + order: None, + select_tokens: None, + } + } + + pub fn add_order(&mut self, order: Arc) -> &mut Self { + self.order = Some(order); + self } - pub fn with_order(order: Arc) -> Self { - Self { order: Some(order) } + pub fn add_select_tokens(&mut self, select_tokens: Vec) -> &mut Self { + self.select_tokens = Some(select_tokens); + self } fn resolve_path(&self, path: &str) -> Result { @@ -144,11 +173,11 @@ mod tests { document: Arc::new(RwLock::new(StrictYaml::String("".to_string()))), key: "test_order".to_string(), inputs: vec![OrderIO { - token: Arc::new(token.clone()), + token: Some(Arc::new(token.clone())), vault_id: Some(U256::from(42)), }], outputs: vec![OrderIO { - token: Arc::new(token), + token: Some(Arc::new(token.clone())), vault_id: None, }], network: mock_network(), @@ -160,7 +189,8 @@ mod tests { #[test] fn test_context_interpolation() { let order = setup_test_order_with_vault_id(); - let context = Context::with_order(order.clone()); + let mut context = Context::new(); + context.add_order(order.clone()); // Test basic interpolation assert_eq!( diff --git a/crates/settings/src/yaml/dotrain.rs b/crates/settings/src/yaml/dotrain.rs index 8507a754a..607b91ba3 100644 --- a/crates/settings/src/yaml/dotrain.rs +++ b/crates/settings/src/yaml/dotrain.rs @@ -161,7 +161,7 @@ mod tests { label: USD Coin symbol: USDC deployers: - deployer1: + scenario1: address: 0x0000000000000000000000000000000000000002 network: mainnet deployer2: @@ -179,11 +179,12 @@ mod tests { scenario1: bindings: key1: value1 - deployer: deployer1 scenarios: scenario2: bindings: key2: value2 + scenarios: + runs: 10 deployments: deployment1: order: order1 @@ -285,12 +286,15 @@ mod tests { 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() + *input.token.clone().as_ref().unwrap(), + ob_yaml.get_token("token1").unwrap().into() ); 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.token.as_ref().unwrap(), + ob_yaml.get_token("token2").unwrap().into() + ); assert_eq!(output.vault_id, Some(U256::from(2))); assert_eq!( *order.network.as_ref(), @@ -298,13 +302,13 @@ mod tests { ); let scenario_keys = dotrain_yaml.get_scenario_keys().unwrap(); - assert_eq!(scenario_keys.len(), 2); + assert_eq!(scenario_keys.len(), 3); let scenario1 = dotrain_yaml.get_scenario("scenario1").unwrap(); assert_eq!(scenario1.bindings.len(), 1); assert_eq!(scenario1.bindings.get("key1").unwrap(), "value1"); assert_eq!( *scenario1.deployer.as_ref(), - ob_yaml.get_deployer("deployer1").unwrap() + ob_yaml.get_deployer("scenario1").unwrap() ); let scenario2 = dotrain_yaml.get_scenario("scenario1.scenario2").unwrap(); assert_eq!(scenario2.bindings.len(), 2); @@ -312,7 +316,7 @@ mod tests { assert_eq!(scenario2.bindings.get("key2").unwrap(), "value2"); assert_eq!( *scenario2.deployer.as_ref(), - ob_yaml.get_deployer("deployer1").unwrap() + ob_yaml.get_deployer("scenario1").unwrap() ); let deployment_keys = dotrain_yaml.get_deployment_keys().unwrap(); @@ -338,6 +342,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"); @@ -349,8 +361,8 @@ mod tests { assert_eq!(deployment.deposits.len(), 1); let deposit = &deployment.deposits[0]; assert_eq!( - *deposit.token.as_ref(), - ob_yaml.get_token("token1").unwrap() + *deposit.token.as_ref().unwrap(), + ob_yaml.get_token("token1").unwrap().into() ); assert_eq!(deposit.presets.len(), 2); assert_eq!(deposit.presets[0], "100".to_string()); @@ -364,6 +376,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] @@ -566,4 +595,94 @@ mod tests { Some("With token symbol WETH".to_string()) ); } + + #[test] + fn test_parse_orders_missing_token() { + let yaml_prefix = r#" +networks: + mainnet: + rpc: https://mainnet.infura.io + chain-id: 1 +deployers: + mainnet: + address: 0x0000000000000000000000000000000000000001 + network: mainnet +scenarios: + scenario1: + deployer: mainnet + bindings: + key1: value1 +deployments: + deployment1: + order: order1 + scenario: scenario1 +gui: + name: test + description: test + deployments: + deployment1: + name: test + description: test + deposits: + - token: token-one + presets: + - 1 + - token: token-two + presets: + - 1 + - token: token-three + presets: + - 1 + fields: + - binding: key1 + name: test + presets: + - value: 1 + select-tokens: + - token-one + - token-two +"#; + let missing_input_token_yaml = format!( + "{yaml_prefix} +orders: + order1: + inputs: + - token: token-three + outputs: + - token: token-two + - token: token-three + " + ); + let missing_output_token_yaml = format!( + "{yaml_prefix} +orders: + order1: + inputs: + - token: token-one + - token: token-two + outputs: + - token: token-three + " + ); + + let dotrain_yaml = DotrainYaml::new(vec![missing_input_token_yaml], false).unwrap(); + let error = dotrain_yaml.get_gui().unwrap_err(); + assert_eq!( + error, + YamlError::ParseError( + "yaml data for token: token-three not found in input index: 0 in order: order1" + .to_string() + ) + ); + + let dotrain_yaml = DotrainYaml::new(vec![missing_output_token_yaml], false).unwrap(); + let error = dotrain_yaml.get_gui().unwrap_err(); + assert_eq!( + error, + YamlError::ParseError( + "yaml data for token: token-three not found in output index: 0 in order: order1" + .to_string() + ) + ); + } } diff --git a/crates/settings/src/yaml/orderbook.rs b/crates/settings/src/yaml/orderbook.rs index 5987854cc..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()); @@ -355,6 +371,48 @@ mod tests { ); } + #[test] + fn test_add_token_to_yaml() { + let yaml = r#" +networks: + mainnet: + rpc: "https://mainnet.infura.io" + chain-id: "1" +"#; + let ob_yaml = OrderbookYaml::new(vec![yaml.to_string()], false).unwrap(); + + Token::add_record_to_yaml( + ob_yaml.documents.clone(), + "test-token", + "mainnet", + "0x0000000000000000000000000000000000000001", + Some("18"), + Some("Test Token"), + Some("TTK"), + ) + .unwrap(); + + let token = ob_yaml.get_token("test-token").unwrap(); + assert_eq!(token.key, "test-token"); + assert_eq!(token.network.key, "mainnet"); + assert_eq!( + token.address, + Address::from_str("0x0000000000000000000000000000000000000001").unwrap() + ); + assert_eq!(token.decimals, Some(18)); + assert_eq!(token.label, Some("Test Token".to_string())); + assert_eq!(token.symbol, Some("TTK".to_string())); + } + + #[test] + fn test_remove_token_from_yaml() { + let ob_yaml = OrderbookYaml::new(vec![FULL_YAML.to_string()], false).unwrap(); + + assert!(ob_yaml.get_token("token1").is_ok()); + Token::remove_record_from_yaml(ob_yaml.documents.clone(), "token1").unwrap(); + assert!(ob_yaml.get_token("token1").is_err()); + } + #[test] fn test_add_metaboard_to_yaml() { let yaml = r#" diff --git a/crates/subgraph/src/types/common.rs b/crates/subgraph/src/types/common.rs index 68c81abba..cc97ff93c 100644 --- a/crates/subgraph/src/types/common.rs +++ b/crates/subgraph/src/types/common.rs @@ -81,6 +81,7 @@ pub type RainMetaV1 = Bytes; #[cfg_attr(target_family = "wasm", derive(Tsify))] #[typeshare] #[serde(rename_all = "camelCase")] +#[serde(rename = "OrderSubgraph")] pub struct Order { pub id: Bytes, pub order_bytes: Bytes, @@ -103,6 +104,8 @@ pub struct Order { #[typeshare] #[serde(rename_all = "camelCase")] pub struct OrderWithSubgraphName { + #[typeshare(typescript(type = "OrderSubgraph"))] + #[cfg_attr(target_family = "wasm", tsify(type = "OrderSubgraph"))] pub order: Order, pub subgraph_name: String, } diff --git a/crates/subgraph/src/types/order.rs b/crates/subgraph/src/types/order.rs index 233c566a9..68540bf88 100644 --- a/crates/subgraph/src/types/order.rs +++ b/crates/subgraph/src/types/order.rs @@ -22,6 +22,7 @@ pub struct OrderIdList { #[cynic(graphql_type = "Query", variables = "BatchOrderDetailQueryVariables")] #[typeshare] pub struct BatchOrderDetailQuery { + #[typeshare(typescript(type = "OrderSubgraph[]"))] #[arguments(where: $id_list)] pub orders: Vec, } @@ -30,6 +31,7 @@ pub struct BatchOrderDetailQuery { #[cynic(graphql_type = "Query", variables = "OrdersListQueryVariables")] #[typeshare] pub struct OrdersListQuery { + #[typeshare(typescript(type = "OrderSubgraph[]"))] #[arguments(orderBy: "timestampAdded", orderDirection: "desc", skip: $skip, first: $first, where: $filters)] pub orders: Vec, } @@ -39,5 +41,6 @@ pub struct OrdersListQuery { #[typeshare] pub struct OrderDetailQuery { #[arguments(id: $id)] + #[typeshare(typescript(type = "OrderSubgraph"))] pub order: Option, } diff --git a/package-lock.json b/package-lock.json index 3b8cbbbe5..da5609d1d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,7 +5,7 @@ "packages": { "": { "name": "rainlanguage-packages", - "license": "CAL-1.0", + "license": "LicenseRef-DCL-1.0", "workspaces": [ "packages/*", "tauri-app" diff --git a/package.json b/package.json index e4954b281..f445231e8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "rainlanguage-packages", - "author": "Rain Language", - "license": "CAL-1.0", + "author": "Rain Open Source Software Ltd", + "license": "LicenseRef-DCL-1.0", "repository": { "type": "git", "url": "https://github.com/rainlanguage/rain.orderbook.git" @@ -24,12 +24,12 @@ "lint:all": "npm run lint --workspaces --if-present", "format:all": "npm run format --workspaces --if-present", "check:all": "npm run check --workspaces --if-present", - "lint-format-check:all": "npm run lint:all && npm run format:all && npm run check:all" + "lint-format-check:all": "npm run lint:all && npm run format:all && npm run check:all" }, "devDependencies": { "@tanstack/svelte-query": "^5.59.20", "@typescript-eslint/eslint-plugin": "^7.3.1", - "@typescript-eslint/parser": "^7.3.1", + "@typescript-eslint/parser": "^7.3.1", "@testing-library/jest-dom": "^6.4.2", "@testing-library/svelte": "^5.1.0", "@testing-library/user-event": "^14.5.2", @@ -43,7 +43,7 @@ "@vitest/expect": "^1.5.2", "@square/svelte-store": "^1.0.18", "dayjs": "^1.11.13", - "jsdom": "^24.0.0", + "jsdom": "^24.0.0", "autoprefixer": "^10.4.20", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", diff --git a/packages/orderbook/package.json b/packages/orderbook/package.json index e8330b5c8..489c91582 100644 --- a/packages/orderbook/package.json +++ b/packages/orderbook/package.json @@ -3,7 +3,7 @@ "description": "Provides RainLanguage Orderbook rust crates' functionalities in typescript through wasm bindgen", "version": "0.0.1-alpha.6", "license": "LicenseRef-DCL-1.0", - "author": "Rain Open Source LLC", + "author": "Rain Open Source Software Ltd", "repository": { "type": "git", "url": "https://github.com/rainlanguage/rain.orderbook.git" diff --git a/packages/orderbook/test/js_api/gui.test.ts b/packages/orderbook/test/js_api/gui.test.ts index 9115eb9e6..27c54aaa8 100644 --- a/packages/orderbook/test/js_api/gui.test.ts +++ b/packages/orderbook/test/js_api/gui.test.ts @@ -6,15 +6,14 @@ import { AllFieldValuesResult, AllowancesResult, ApprovalCalldataResult, - AvailableDeployments, + DeploymentKeys, DepositAndAddOrderCalldataResult, DepositCalldataResult, Gui, GuiDeployment, GuiDetails, - SelectTokens, TokenDeposit, - TokenInfos + TokenInfo } from '../../dist/types/js_api.js'; import { getLocal } from 'mockttp'; @@ -273,6 +272,60 @@ _ _: 0 0; #handle-add-order :; `; +const dotrainWithoutTokens = ` +networks: + some-network: + rpc: http://localhost:8085/rpc-url + chain-id: 123 + network-id: 123 + currency: ETH + +subgraphs: + some-sg: https://www.some-sg.com +metaboards: + test: https://metaboard.com + +deployers: + some-deployer: + network: some-network + address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba + +orderbooks: + some-orderbook: + address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 + network: some-network + subgraph: some-sg + +scenarios: + some-scenario: + deployer: some-deployer + bindings: + test-binding: 5 + +orders: + some-order: + inputs: + - token: token1 + outputs: + - token: token2 + deployer: some-deployer + orderbook: some-orderbook + +deployments: + some-deployment: + scenario: some-scenario + order: some-order + other-deployment: + scenario: some-scenario + order: some-order +--- +#calculate-io +_ _: 0 0; +#handle-io +:; +#handle-add-order +:; +`; const dotrainWithGui = ` ${guiConfig} @@ -292,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 () => { @@ -347,15 +393,16 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Gui', async function () `; const gui = await DotrainOrderGui.chooseDeployment(dotrainWithGui, 'other-deployment'); - const tokenInfos: TokenInfos = gui.getTokenInfos(); - const token1Address = '0xc2132d05d31c914a87c6611c10748aeb04b58e8f'; - const token2Address = '0x8f3cf7ad23cd3cadbd9735aff958023239c6a063'; - assert.equal(tokenInfos.get(token1Address)?.decimals, 6); - assert.equal(tokenInfos.get(token1Address)?.name, 'Token 1'); - assert.equal(tokenInfos.get(token1Address)?.symbol, 'T1'); - assert.equal(tokenInfos.get(token2Address)?.decimals, 18); - assert.equal(tokenInfos.get(token2Address)?.name, 'Token 2'); - assert.equal(tokenInfos.get(token2Address)?.symbol, 'T2'); + let token1TokenInfo = await gui.getTokenInfo('token1'); + let token2TokenInfo = await gui.getTokenInfo('token2'); + assert.equal(token1TokenInfo.address, '0xc2132d05d31c914a87c6611c10748aeb04b58e8f'); + assert.equal(token1TokenInfo.decimals, 6); + assert.equal(token1TokenInfo.name, 'Token 1'); + assert.equal(token1TokenInfo.symbol, 'T1'); + assert.equal(token2TokenInfo.address, '0x8f3cf7ad23cd3cadbd9735aff958023239c6a063'); + assert.equal(token2TokenInfo.decimals, 18); + assert.equal(token2TokenInfo.name, 'Token 2'); + assert.equal(token2TokenInfo.symbol, 'T2'); }); describe('deposit tests', async () => { @@ -607,23 +654,47 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Gui', async function () describe('state management tests', async () => { let serializedState = - 'H4sIAAAAAAAA_3WNTQ5AMBCF_UW4hbWEzJQWt3AF1ZJGUgldOL6FqYXE23zz8_JeFDzKidJYZexaYUgHCDOaxkOf2hVY-s-FrGm56PoBJjkrvfzt33AWeMVEBPCFKdHtm7b4OhMih1rc8yX-NrUAAAA='; + 'H4sIAAAAAAAA_7VOyw6CMBBk1WBiPHo18QeQgqEh3E38AH4AsQqhtgSKHvx5Q9xVmhBvzGV3ZvYx4HywxmpEa7xzqS6lugFqzFkN3UcmOzFDxSVHV0IFDmGBNWJ7bo2E35E51oCx8WM2o4CtvgtPCfPUTbVFrTCmTnxf6jyThW5NErM48ps697pGvughUAf0-pieNtheRwAuLNFO-wy7AChpaqcLbTZx1sMI_malbnCuX_kxzvkbrBXoaQkCAAA='; let gui: DotrainOrderGui; beforeAll(async () => { mockServer .forPost('/rpc-url') + .once() .withBodyIncluding('0x82ad56cb') .thenSendJsonRpcResult( '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000007546f6b656e203100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000025431000000000000000000000000000000000000000000000000000000000000' ); - gui = await DotrainOrderGui.chooseDeployment(dotrainWithGui, 'some-deployment'); + mockServer + .forPost('/rpc-url') + .once() + .withBodyIncluding('0x82ad56cb') + .thenSendJsonRpcResult( + '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000007546f6b656e203100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000025431000000000000000000000000000000000000000000000000000000000000' + ); + mockServer + .forPost('/rpc-url') + .once() + .withBodyIncluding('0x82ad56cb') + .thenSendJsonRpcResult( + '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000754656b656e203200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000025432000000000000000000000000000000000000000000000000000000000000' + ); + let dotrain3 = `${guiConfig3} - gui.saveFieldValue('binding-1', { +${dotrain}`; + gui = await DotrainOrderGui.chooseDeployment(dotrain3, 'other-deployment'); + + gui.saveFieldValue('test-binding', { isPreset: true, - value: gui.getFieldDefinition('binding-1').presets[0].id + value: gui.getFieldDefinition('test-binding').presets[0].id }); - gui.saveFieldValue('binding-2', { isPreset: false, value: '100' }); gui.saveDeposit('token1', '50.6'); + gui.saveDeposit('token2', '100'); + gui.removeSelectToken('token1'); + gui.removeSelectToken('token2'); + await gui.saveSelectToken('token1', '0x6666666666666666666666666666666666666666'); + await gui.saveSelectToken('token2', '0x3333333333333333333333333333333333333333'); + gui.setVaultId(true, 0, '666'); + gui.setVaultId(false, 0, '333'); }); it('should serialize gui state', async () => { @@ -632,31 +703,55 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Gui', async function () }); it('should deserialize gui state', async () => { - gui.clearState(); + mockServer + .forPost('/rpc-url') + .once() + .withBodyIncluding('0x82ad56cb') + .thenSendJsonRpcResult( + '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000007546f6b656e203100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000025431000000000000000000000000000000000000000000000000000000000000' + ); + let dotrain3 = `${guiConfig3} + +${dotrain}`; + gui = await DotrainOrderGui.chooseDeployment(dotrain3, 'other-deployment'); + gui.removeSelectToken('token1'); + gui.removeSelectToken('token2'); + + assert.equal(gui.getAllFieldValues().length, 0); + assert.equal(gui.getDeposits().length, 0); + assert.equal(gui.isSelectTokenSet('token1'), false); + assert.equal(gui.isSelectTokenSet('token2'), false); + let oldGuiDeployment: GuiDeployment = gui.getCurrentDeployment(); + assert.equal(oldGuiDeployment.deployment.order.inputs[0].vaultId, '0x1'); + assert.equal(oldGuiDeployment.deployment.order.outputs[0].vaultId, '0x1'); + gui.deserializeState(serializedState); + const fieldValues: AllFieldValuesResult[] = gui.getAllFieldValues(); - assert.equal(fieldValues.length, 2); + assert.equal(fieldValues.length, 1); assert.deepEqual(fieldValues[0], { - binding: 'binding-1', + binding: 'test-binding', value: { id: '0', - name: 'Preset 1', - value: '0x1234567890abcdef1234567890abcdef12345678' - } - }); - assert.deepEqual(fieldValues[1], { - binding: 'binding-2', - value: { - id: '', name: undefined, - value: '100' + value: 'test-value' } }); + + assert.equal(gui.isSelectTokenSet('token1'), true); + assert.equal(gui.isSelectTokenSet('token2'), true); const deposits: TokenDeposit[] = gui.getDeposits(); - assert.equal(deposits.length, 1); + assert.equal(deposits.length, 2); assert.equal(deposits[0].token, 'token1'); assert.equal(deposits[0].amount, '50.6'); - assert.equal(deposits[0].address, '0xc2132d05d31c914a87c6611c10748aeb04b58e8f'); + assert.equal(deposits[0].address, '0x6666666666666666666666666666666666666666'); + assert.equal(deposits[1].token, 'token2'); + assert.equal(deposits[1].amount, '100'); + assert.equal(deposits[1].address, '0x3333333333333333333333333333333333333333'); + + let guiDeployment: GuiDeployment = gui.getCurrentDeployment(); + assert.equal(guiDeployment.deployment.order.inputs[0].vaultId, '0x29a'); + assert.equal(guiDeployment.deployment.order.outputs[0].vaultId, '0x14d'); }); it('should clear state', async () => { @@ -668,22 +763,22 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Gui', async function () }); it('should check if field is preset', async () => { - gui.saveFieldValue('binding-1', { + gui.saveFieldValue('test-binding', { isPreset: true, - value: gui.getFieldDefinition('binding-1').presets[0].id + value: gui.getFieldDefinition('test-binding').presets[0].id }); - assert.equal(gui.isFieldPreset('binding-1'), true); - gui.saveFieldValue('binding-2', { + assert.equal(gui.isFieldPreset('test-binding'), true); + gui.saveFieldValue('test-binding', { isPreset: false, value: '100' }); - assert.equal(gui.isFieldPreset('binding-2'), false); + assert.equal(gui.isFieldPreset('test-binding'), false); }); it('should check if deposit is preset', async () => { gui.saveDeposit('token1', '55'); assert.equal(gui.isDepositPreset('token1'), false); - gui.saveDeposit('token1', '100'); + gui.saveDeposit('token1', '0'); assert.equal(gui.isDepositPreset('token1'), true); }); }); @@ -942,7 +1037,7 @@ ${dotrainWithoutVaultIds}`; let testDotrain = ` ${guiConfig3} - ${dotrain} + ${dotrainWithoutTokens} `; let testGui = await DotrainOrderGui.chooseDeployment(testDotrain, 'other-deployment'); @@ -1027,16 +1122,16 @@ ${dotrainWithoutVaultIds}`; let dotrain3 = ` ${guiConfig3} - ${dotrain} + ${dotrainWithoutTokens} `; gui = await DotrainOrderGui.chooseDeployment(dotrain3, 'other-deployment'); }); it('should get select tokens', async () => { - const selectTokens: SelectTokens = gui.getSelectTokens(); - assert.equal(selectTokens.size, 2); - assert.equal(selectTokens.get('token1'), '0x0000000000000000000000000000000000000000'); - assert.equal(selectTokens.get('token2'), '0x0000000000000000000000000000000000000000'); + const selectTokens: string[] = gui.getSelectTokens(); + assert.equal(selectTokens.length, 2); + assert.equal(selectTokens[0], 'token1'); + assert.equal(selectTokens[1], 'token2'); }); it('should throw error if select tokens not set', async () => { @@ -1049,14 +1144,14 @@ ${dotrainWithoutVaultIds}`; ); let testGui = await DotrainOrderGui.chooseDeployment(dotrainWithGui, 'some-deployment'); - expect(() => testGui.getSelectTokens()).toThrow('Select tokens not set'); - await expect( - async () => await testGui.saveSelectTokenAddress('token1', '0x1') - ).rejects.toThrow('Select tokens not set'); + assert.equal(testGui.getSelectTokens().length, 0); + await expect(async () => await testGui.saveSelectToken('token1', '0x1')).rejects.toThrow( + 'Select tokens not set' + ); }); it('should throw error if token not found', async () => { - await expect(async () => await gui.saveSelectTokenAddress('token3', '0x1')).rejects.toThrow( + await expect(async () => await gui.saveSelectToken('token3', '0x1')).rejects.toThrow( 'Token not found' ); }); @@ -1078,41 +1173,101 @@ ${dotrainWithoutVaultIds}`; '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000754656b656e203200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000025432000000000000000000000000000000000000000000000000000000000000' ); - let initialTokenInfo: TokenInfos = await gui.getTokenInfos(); - assert.equal(initialTokenInfo.size, 0); + assert.equal(gui.isSelectTokenSet('token1'), false); + assert.equal(gui.isSelectTokenSet('token2'), false); - let currentDeployment: GuiDeployment = gui.getCurrentDeployment(); - assert.equal( - currentDeployment.deployment.order.inputs[0].token.address, - '0xc2132d05d31c914a87c6611c10748aeb04b58e8f' + await expect(async () => await gui.getTokenInfo('token1')).rejects.toThrow( + 'Yaml parse error: missing field: token' ); - assert.equal( - currentDeployment.deployment.order.outputs[0].token.address, - '0x8f3cf7ad23cd3cadbd9735aff958023239c6a063' + await expect(async () => await gui.getTokenInfo('token2')).rejects.toThrow( + 'Yaml parse error: missing field: token' ); - await gui.saveSelectTokenAddress('token1', '0x6666666666666666666666666666666666666666'); - await gui.saveSelectTokenAddress('token2', '0x8888888888888888888888888888888888888888'); - assert.equal( - gui.getSelectTokens().get('token1'), - '0x6666666666666666666666666666666666666666' - ); - assert.equal( - gui.getSelectTokens().get('token2'), - '0x8888888888888888888888888888888888888888' - ); + await gui.saveSelectToken('token1', '0x6666666666666666666666666666666666666666'); + await gui.saveSelectToken('token2', '0x8888888888888888888888888888888888888888'); - let tokenInfo: TokenInfos = await gui.getTokenInfos(); - assert.equal(tokenInfo.size, 2); + assert.equal(gui.isSelectTokenSet('token1'), true); + assert.equal(gui.isSelectTokenSet('token2'), true); - let newCurrentDeployment: GuiDeployment = gui.getCurrentDeployment(); - assert.equal( - newCurrentDeployment.deployment.order.inputs[0].token.address, - '0x6666666666666666666666666666666666666666' - ); - assert.equal( - newCurrentDeployment.deployment.order.outputs[0].token.address, - '0x8888888888888888888888888888888888888888' + let tokenInfo: TokenInfo = await gui.getTokenInfo('token1'); + assert.equal(tokenInfo.name, 'Token 1'); + assert.equal(tokenInfo.symbol, 'T1'); + assert.equal(tokenInfo.decimals, 6); + + tokenInfo = await gui.getTokenInfo('token2'); + assert.equal(tokenInfo.name, 'Teken 2'); + assert.equal(tokenInfo.symbol, 'T2'); + 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} + + ${dotrainWithoutTokens} + `; + gui = await DotrainOrderGui.chooseDeployment(dotrain3, 'other-deployment'); + + 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); + + gui.removeSelectToken('token1'); + assert.equal(gui.isSelectTokenSet('token1'), false); + await expect(async () => await gui.getTokenInfo('token1')).rejects.toThrow( + 'Yaml parse error: missing field: token' ); }); }); diff --git a/packages/ui-components/.prettierignore b/packages/ui-components/.prettierignore index ab78a95dd..c2fb3dc7d 100644 --- a/packages/ui-components/.prettierignore +++ b/packages/ui-components/.prettierignore @@ -2,3 +2,4 @@ package-lock.json pnpm-lock.yaml yarn.lock +*.rain \ No newline at end of file diff --git a/packages/ui-components/package.json b/packages/ui-components/package.json index f64d1260e..b74ba94c1 100644 --- a/packages/ui-components/package.json +++ b/packages/ui-components/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "description": "A component library for building Svelte applications to be used with Raindex.", "license": "LicenseRef-DCL-1.0", - "author": "Rain Open Source LLC", + "author": "Rain Open Source Software Ltd", "main": "dist/index.js", "module": "dist/index.js", "exports": { diff --git a/packages/ui-components/src/__tests__/CodeMirrorRainlang.test.ts b/packages/ui-components/src/__tests__/CodeMirrorRainlang.test.ts index 1a4cef907..9a405fdbd 100644 --- a/packages/ui-components/src/__tests__/CodeMirrorRainlang.test.ts +++ b/packages/ui-components/src/__tests__/CodeMirrorRainlang.test.ts @@ -1,14 +1,14 @@ import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; import { render, waitFor } from '@testing-library/svelte'; import CodeMirrorRainlang from '../lib/components/CodeMirrorRainlang.svelte'; -import type { Order } from '@rainlanguage/orderbook/js_api'; +import type { OrderSubgraph } from '@rainlanguage/orderbook/js_api'; import { extendOrder } from '@rainlanguage/orderbook/js_api'; import { writable } from 'svelte/store'; // Mock the extendOrder function vi.mock('@rainlanguage/orderbook/js_api', () => ({ // eslint-disable-next-line @typescript-eslint/no-unused-vars - extendOrder: vi.fn((order: Order) => ({ + extendOrder: vi.fn((order: OrderSubgraph) => ({ rainlang: 'mocked rainlang text' })) })); @@ -28,7 +28,7 @@ describe('CodeMirrorRainlang', () => { }); it('should use extendOrder when order prop is provided', () => { - const mockOrder: Order = {} as Order; + const mockOrder: OrderSubgraph = {} as OrderSubgraph; render(CodeMirrorRainlang, { props: { @@ -59,7 +59,7 @@ describe('CodeMirrorRainlang', () => { }); it('should pass through disabled prop', async () => { - const mockOrder: Order = {} as Order; + const mockOrder: OrderSubgraph = {} as OrderSubgraph; const mockExtendedOrder = { order: {} }; (extendOrder as Mock).mockReturnValue(mockExtendedOrder); diff --git a/packages/ui-components/src/__tests__/DeploymentSteps.test.ts b/packages/ui-components/src/__tests__/DeploymentSteps.test.ts new file mode 100644 index 000000000..22ea3012e --- /dev/null +++ b/packages/ui-components/src/__tests__/DeploymentSteps.test.ts @@ -0,0 +1,680 @@ +import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; +import { render, screen, fireEvent, waitFor } from '@testing-library/svelte'; +import DeploymentSteps from '../lib/components/deployment/DeploymentSteps.svelte'; +import { DotrainOrderGui } from '@rainlanguage/orderbook/js_api'; +import userEvent from '@testing-library/user-event'; + +vi.mock('@rainlanguage/orderbook/js_api', () => ({ + DotrainOrderGui: { + getDeploymentKeys: vi.fn(), + chooseDeployment: vi.fn() + } +})); + +const dotrain = `raindex-version: 8898591f3bcaa21dc91dc3b8584330fc405eadfa + +gui: + name: Two-sided dynamic spread strategies + description: The dynamic spread strategy for market-making uses time-based adjustments to maintain liquidity by narrowing spreads as market conditions stabilize, while recalculating averages and trade sizes to mitigate risks during trends. + deployments: + flare-sflr-wflr: + name: SFLR<>WFLR on Flare. + description: Rotate sFLR (Sceptre staked FLR) and WFLR on Flare. + fields: + - binding: is-fast-exit + name: Fast exit? + description: If enabled, the strategy will attempt to exit any position it builds up in a single trade, as soon as it can do so profitably. + presets: + - name: Yes + value: 1 + - name: No + value: 0 + - binding: initial-io + name: Initial price (WFLR per sFLR) + description: The rough initial WFLR to sFLR ratio (e.g. 1.11). + min: 1 + - binding: next-trade-multiplier + name: Next trade multiplier + description: This is the most the strategy will move the price in a single trade. Larger numbers will capture larger price jumps but trade less often, smaller numbers will trade more often but be less defensive against large price jumps in the market. + min: 1 + presets: + - name: 1.001x + value: 1.001 + - name: 1.002x + value: 1.002 + - name: 1.005x + value: 1.005 + - binding: cost-basis-multiplier + name: Cost basis multiplier + description: The minimum spread applied to the breakeven in addition to the auction. This is applied in both directions so 1.01x would be a 2% total spread. + min: 1 + presets: + - name: 1 (auction spread only) + value: 1 + - name: 1.0005x (0.1% total) + value: 1.0005 + - name: 1.001x (0.2% total) + value: 1.001 + - name: 1.0025x (0.5% total) + value: 1.0025 + - name: 1.005x (1% total) + value: 1.005 + - binding: time-per-epoch + name: Time per halving (seconds) + description: The amount of time (in seconds) between halvings of the price and the amount offered during each auction, relative to their baselines. + min: 600 + presets: + - name: 1 hour (3600) + value: 3600 + - name: 2 hours (7200) + value: 7200 + - name: 4 hours (14400) + value: 14400 + - name: 8 hours (28800) + value: 28800 + - binding: max-amount + name: Max amount + description: The maximum amount of sFLR that will be offered in a single auction. + min: 0 + presets: + - name: 100 + value: 100 + - name: 1000 + value: 1000 + - name: 10000 + value: 10000 + - name: 100000 + value: 100000 + - binding: min-amount + name: Minimum amount + description: The minimum amount of sFLR that will be offered in a single auction. + min: 0 + presets: + - name: 10 + value: 10 + - name: 100 + value: 100 + - name: 1000 + value: 1000 + + deposits: + - token: flare-sflr + min: 0 + presets: + - 0 + - 100 + - 1000 + - 10000 + - token: flare-wflr + min: 0 + presets: + - 0 + - 100 + - 1000 + - 10000 + flare-cusdx-cysflr: + name: cUSDX<>cysFLR on Flare. + description: Rotate cUSDX and cysFLR on Flare. + + fields: + - binding: is-fast-exit + name: Fast exit? + description: If enabled, the strategy will attempt to exit any position it builds up in a single trade, as soon as it can do so profitably. + presets: + - name: Yes + value: 1 + - name: No + value: 0 + - binding: initial-io + name: Initial price (cUSDX per cysFLR) + description: The rough initial cUSDX per cysFLR ratio (e.g. 0.75). + min: 0 + - binding: next-trade-multiplier + name: Next trade multiplier + description: This is the most the strategy will move the price in a single trade. Larger numbers will capture larger price jumps but trade less often, smaller numbers will trade more often but be less defensive against large price jumps in the market. + min: 1 + presets: + - name: 1.001x + value: 1.001 + - name: 1.002x + value: 1.002 + - name: 1.005x + value: 1.005 + - binding: cost-basis-multiplier + name: Cost basis multiplier + description: The minimum spread applied to the breakeven in addition to the auction. This is applied in both directions so 1.01x would be a 2% total spread. + min: 1 + presets: + - name: 1 (auction spread only) + value: 1 + - name: 1.0005x (0.1% total) + value: 1.0005 + - name: 1.001x (0.2% total) + value: 1.001 + - name: 1.0025x (0.5% total) + value: 1.0025 + - name: 1.005x (1% total) + value: 1.005 + - binding: time-per-epoch + name: Time per halving (seconds) + description: The amount of time (in seconds) between halvings of the price and the amount offered during each auction, relative to their baselines. + min: 600 + presets: + - name: 1 hour (3600) + value: 3600 + - name: 2 hours (7200) + value: 7200 + - name: 4 hours (14400) + value: 14400 + - name: 8 hours (28800) + value: 28800 + - binding: max-amount + name: Max amount + description: The maximum amount of cUSDX that will be offered in a single auction. + min: 0 + presets: + - name: 10 + value: 10 + - name: 100 + value: 100 + - name: 1000 + value: 1000 + - binding: min-amount + name: Minimum amount + description: The minimum amount of cUSDX that will be offered in a single auction. + min: 0 + presets: + - name: 10 + value: 10 + - name: 100 + value: 100 + - name: 1000 + value: 1000 + + deposits: + - token: flare-cysflr + min: 0 + presets: + - 0 + - 100 + - 200 + - 500 + - token: flare-cusdx + min: 0 + presets: + - 0 + - 100 + - 200 + - 500 + +networks: + flare: + rpc: https://rpc.ankr.com/flare + chain-id: 14 + network-id: 14 + currency: FLR + +scenarios: + flare: + deployer: flare + orderbook: flare + runs: 1 + bindings: + raindex-subparser: 0xFe2411CDa193D9E4e83A5c234C7Fd320101883aC + history-cap: '1e50' + shy-epoch: 0.05 + scenarios: + sflr-wflr: + runs: 1 + bindings: + amount-token: 0x12e605bc104e93B45e1aD99F9e555f659051c2BB + initial-output-token: 0x12e605bc104e93B45e1aD99F9e555f659051c2BB + initial-input-token: 0x1D80c49BbBCd1C0911346656B529DF9E5c2F783d + cusdx-cysflr: + runs: 1 + bindings: + amount-token: 0xFE2907DFa8DB6e320cDbF45f0aa888F6135ec4f8 + initial-output-token: 0x19831cfB53A0dbeAD9866C43557C1D48DfF76567 + initial-input-token: 0xFE2907DFa8DB6e320cDbF45f0aa888F6135ec4f8 + sflr-joule: + runs: 1 + bindings: + amount-token: 0x12e605bc104e93B45e1aD99F9e555f659051c2BB + initial-output-token: 0xE6505f92583103AF7ed9974DEC451A7Af4e3A3bE + initial-input-token: 0x12e605bc104e93B45e1aD99F9e555f659051c2BB + wflr-eusdt: + runs: 1 + bindings: + amount-token: 0xfbda5f676cb37624f28265a144a48b0d6e87d3b6 + initial-output-token: 0x12e605bc104e93B45e1aD99F9e555f659051c2BB + initial-input-token: 0xfbda5f676cb37624f28265a144a48b0d6e87d3b6 + usdce-sflr: + runs: 1 + bindings: + amount-token: 0xfbda5f676cb37624f28265a144a48b0d6e87d3b6 + initial-output-token: 0x12e605bc104e93B45e1aD99F9e555f659051c2BB + initial-input-token: 0xfbda5f676cb37624f28265a144a48b0d6e87d3b6 + usdce-cusdx: + runs: 1 + bindings: + amount-token: 0xfbda5f676cb37624f28265a144a48b0d6e87d3b6 + initial-output-token: 0xFE2907DFa8DB6e320cDbF45f0aa888F6135ec4f8 + initial-input-token: 0xfbda5f676cb37624f28265a144a48b0d6e87d3b6 + usdce-wflr: + runs: 1 + bindings: + amount-token: 0xfbda5f676cb37624f28265a144a48b0d6e87d3b6 + initial-output-token: 0x1D80c49BbBCd1C0911346656B529DF9E5c2F783d + initial-input-token: 0xfbda5f676cb37624f28265a144a48b0d6e87d3b6 + usdce-weth: + runs: 1 + bindings: + amount-token: 0xfbda5f676cb37624f28265a144a48b0d6e87d3b6 + initial-output-token: 0x1502FA4be69d526124D453619276FacCab275d3D + initial-input-token: 0xfbda5f676cb37624f28265a144a48b0d6e87d3b6 + +metaboards: + flare: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-flare-0x893BBFB7/0.1/gn + +subgraphs: + flare: https://example.com/subgraph + +orderbooks: + flare: + address: 0xCEe8Cd002F151A536394E564b84076c41bBBcD4d + +deployers: + flare: + address: 0xE3989Ea7486c0F418C764e6c511e86f6E8830FAb + +tokens: + flare-usdce: + network: flare + address: 0xfbda5f676cb37624f28265a144a48b0d6e87d3b6 + decimals: 6 + flare-wflr: + network: flare + address: 0x1D80c49BbBCd1C0911346656B529DF9E5c2F783d + decimals: 18 + flare-sflr: + network: flare + address: 0x12e605bc104e93B45e1aD99F9e555f659051c2BB + decimals: 18 + flare-weth: + network: flare + address: 0x1502FA4be69d526124D453619276FacCab275d3D + decimals: 18 + flare-cysflr: + network: flare + address: 0x19831cfB53A0dbeAD9866C43557C1D48DfF76567 + flare-cusdx: + network: flare + address: 0xFE2907DFa8DB6e320cDbF45f0aa888F6135ec4f8 + flare-joule: + network: flare + address: 0xE6505f92583103AF7ed9974DEC451A7Af4e3A3bE + decimals: 18 + +orders: + flare-usdce-sflr: + network: flare + orderbook: flare + inputs: + - token: flare-sflr + - token: flare-usdce + outputs: + - token: flare-sflr + - token: flare-usdce + flare-sflr-wflr: + network: flare + orderbook: flare + inputs: + - token: flare-sflr + - token: flare-wflr + outputs: + - token: flare-sflr + - token: flare-wflr + flare-cusdx-cysflr: + network: flare + orderbook: flare + inputs: + - token: flare-cusdx + - token: flare-cysflr + outputs: + - token: flare-cusdx + - token: flare-cysflr + flare-sflr-joule: + network: flare + orderbook: flare + inputs: + - token: flare-sflr + - token: flare-joule + outputs: + - token: flare-sflr + - token: flare-joule + flare-usdce-weth: + network: flare + orderbook: flare + inputs: + - token: flare-usdce + - token: flare-weth + outputs: + - token: flare-usdce + - token: flare-weth + flare-usdce-wflr: + network: flare + orderbook: flare + inputs: + - token: flare-usdce + - token: flare-wflr + outputs: + - token: flare-usdce + - token: flare-wflr + flare-usdce-cusdx: + network: flare + orderbook: flare + inputs: + - token: flare-usdce + - token: flare-cusdx + outputs: + - token: flare-usdce + - token: flare-cusdx + +deployments: + flare-usdce-sflr: + order: flare-usdce-sflr + scenario: flare.usdce-sflr + flare-sflr-wflr: + order: flare-sflr-wflr + scenario: flare.sflr-wflr + flare-cusdx-cysflr: + order: flare-cusdx-cysflr + scenario: flare.cusdx-cysflr + flare-usdce-weth: + order: flare-usdce-weth + scenario: flare.usdce-weth + flare-usdce-wflr: + order: flare-usdce-wflr + scenario: flare.usdce-wflr + flare-usdce-cusdx: + order: flare-usdce-cusdx + scenario: flare.usdce-cusdx + flare-sflr-joule: + order: flare-sflr-joule + scenario: flare.sflr-joule + +--- + +#raindex-subparser !Subparser for the Raindex. + +#min-amount !Amount will decay down to this number each epoch. +#max-amount !Amount will decay down from this number each epoch. +#time-per-epoch !Duration of one unit of streaming amount and io ratio halflife. +#shy-epoch !Epoch below which only the minimum amount is offered. +#next-trade-multiplier !Start next auction at this x the last trade. +#history-cap !The max amount of trade history kept for cost basis tracking (denominated in same token as tranche size). +#amount-token !The token that is the amount token for the strategy. This denominates tranche sizes. +#initial-io !The IO ratio that the strategy starts at. The quote token is the output so that the IO ratio looks like a CEX price. +#initial-output-token !Initial output token for the initial IO ratio. +#initial-input-token !Initial input token for the initial IO ratio. +#cost-basis-multiplier !Multiplier for the cost basis IO ratio. Effectively a minimum spread. + +#is-fast-exit !Non-zero for fast exit behaviour. + +#last-trade-io-key "last-trade-io" +#last-trade-time-key "last-trade-time" +#last-trade-output-token-key "last-trade-output-token" +#vwaio-key "cost-basis-io-ratio" + +#amount-is-output + _: equal-to(amount-token output-token()); + +#get-cost-basis-io-ratio + this-total-out-key: hash(order-hash() input-token() output-token()), + this-vwaio-key: hash(this-total-out-key vwaio-key), + other-total-out-key: hash(order-hash() output-token() input-token()), + other-vwaio-key: hash(other-total-out-key vwaio-key), + + this-total-out: get(this-total-out-key), + other-total-out: get(other-total-out-key), + + this-vwaio: get(this-vwaio-key), + other-vwaio: get(other-vwaio-key); + +#set-cost-basis-io-ratio + /* first reduce outstanding inventory */ + this-total-out-key + this-vwaio-key + other-total-out-key + other-vwaio-key + this-total-out + other-total-out + this-vwaio + other-vwaio: call<'get-cost-basis-io-ratio>(), + + other-reduction-out: min(other-total-out input-vault-increase()), + reduced-other-total-out: sub(other-total-out other-reduction-out), + + :set(other-total-out-key reduced-other-total-out), + :set(other-vwaio-key every(reduced-other-total-out other-vwaio)), + + /* then increase our inventory */ + this-total-in: mul(this-total-out this-vwaio), + this-remaining-in: sub(input-vault-increase() other-reduction-out), + this-new-in: add(this-total-in this-remaining-in), + this-remaining-out: div(this-remaining-in calculated-io-ratio()), + this-new-out: add(this-total-out this-remaining-out), + this-new-vwaio: every(this-new-out div(this-new-in any(this-new-out max-value()))), + cap-out: if(call<'amount-is-output>() history-cap div(history-cap any(this-new-vwaio calculated-io-ratio()))), + capped-out: min(this-new-out cap-out), + + :set(this-total-out-key capped-out), + :set(this-vwaio-key this-new-vwaio); + +#halflife +epoch:, +multiplier: + power(0.5 div(epoch 10)), +val: + mul( + multiplier + multiplier + multiplier + multiplier + multiplier + multiplier + multiplier + multiplier + multiplier + multiplier + ); + +#set-last-trade +last-io:, +:set(hash(order-hash() last-trade-time-key) now()), +:set(hash(order-hash() last-trade-io-key) last-io), +:set(hash(order-hash() last-trade-output-token-key) output-token()); + +#handle-add-order +using-words-from raindex-subparser +:set(hash(order-hash() last-trade-time-key) now()), +:set(hash(order-hash() last-trade-io-key) initial-io), +:set(hash(order-hash() last-trade-output-token-key) initial-output-token), +this-total-out-key: hash(order-hash() initial-input-token initial-output-token), +:set(this-total-out-key 1e-18), +:set(hash(this-total-out-key vwaio-key) initial-io); + +#get-last-trade +stored-last-io:get(hash(order-hash() last-trade-io-key)), +stored-last-output-token:get(hash(order-hash() last-trade-output-token-key)), +last-time:get(hash(order-hash() last-trade-time-key)), +_: if(equal-to(stored-last-output-token output-token()) stored-last-io inv(stored-last-io)); + +#get-epoch +last-time _: call<'get-last-trade>(), +duration: sub(now() last-time), +epochs: div(duration time-per-epoch); + +#amount-for-epoch +epoch io:, +decay: call<'halflife>(epoch), +shy-decay: every(greater-than(epoch shy-epoch) decay), +variable-component: sub(max-amount min-amount), +base-amount: add(min-amount mul(variable-component shy-decay)), +_: if(call<'amount-is-output>() base-amount mul(base-amount inv(io))); + +#io-for-epoch +epoch:, +last-io: call<'get-last-trade>(), +this-vwaio +other-vwaio: call<'get-cost-basis-io-ratio>(), +cost-basis-io: mul(any(this-vwaio inv(any(other-vwaio max-value()))) cost-basis-multiplier), +max-next-trade: mul(max(cost-basis-io last-io) next-trade-multiplier), +baseline: any(cost-basis-io last-io), +variable-component: sub(max-next-trade baseline), +decay: call<'halflife>(epoch), +above-baseline: mul(variable-component decay), +_: add(baseline above-baseline); + +#calculate-io +using-words-from raindex-subparser +epoch:call<'get-epoch>(), +io: call<'io-for-epoch>(epoch), +epoch-max-output: call<'amount-for-epoch>(epoch io), +other-total-out +_ +other-vwaio: call<'get-cost-basis-io-ratio>(), +max-output: max( + epoch-max-output + every( + is-fast-exit + mul(other-total-out other-vwaio))), +_: io, +:call<'set-last-trade>(io); + +#handle-io +min-trade-amount: mul(min-amount 0.9), +:ensure( + greater-than-or-equal-to( + if(call<'amount-is-output>() output-vault-decrease() input-vault-increase()) + min-trade-amount) + "Min trade amount."), +:call<'set-cost-basis-io-ratio>();`; + +describe('DeploymentSteps', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it('renders strategy URL input and load button initially', () => { + render(DeploymentSteps); + expect(screen.getByPlaceholderText('Enter URL to .rain file')).toBeInTheDocument(); + const loadButton = screen.getByText('Load Strategy'); + expect(loadButton).toBeInTheDocument(); + expect(loadButton).toBeDisabled(); + }); + + it('enables load button when URL is entered', async () => { + render(DeploymentSteps); + const urlInput = screen.getByPlaceholderText('Enter URL to .rain file'); + const loadButton = screen.getByText('Load Strategy'); + + await userEvent.type(urlInput, 'https://example.com/strategy.rain'); + await waitFor(() => { + expect(loadButton).not.toBeDisabled(); + }); + }); + + it('loads strategy from URL when button is clicked', async () => { + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + text: () => Promise.resolve(JSON.stringify(dotrain)) + }); + + render(DeploymentSteps); + const urlInput = screen.getByPlaceholderText('Enter URL to .rain file'); + const loadButton = screen.getByText('Load Strategy'); + await userEvent.clear(urlInput); + await fireEvent.input(urlInput, { target: { value: 'https://example.com/strategy.rain' } }); + await userEvent.click(loadButton); + + await waitFor(() => { + expect(global.fetch).toHaveBeenCalledWith('https://example.com/strategy.rain'); + }); + }); + + it('shows deployments dropdown after strategy is loaded', async () => { + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + text: () => Promise.resolve(JSON.stringify(dotrain)) + }); + + const mockDeployments = [ + { key: 'deployment1', label: 'Deployment 1' }, + { key: 'deployment2', label: 'Deployment 2' } + ]; + + (DotrainOrderGui.getDeploymentKeys as Mock).mockResolvedValue(mockDeployments); + + render(DeploymentSteps); + const urlInput = screen.getByPlaceholderText('Enter URL to .rain file'); + const loadButton = screen.getByText('Load Strategy'); + + await userEvent.type(urlInput, 'https://example.com/strategy.rain'); + await userEvent.click(loadButton); + + await waitFor(() => { + expect(screen.getByText('Select Deployment')).toBeInTheDocument(); + expect(screen.getByText('Select a deployment')).toBeInTheDocument(); + }); + }); + + it('handles URL fetch errors', async () => { + global.fetch = vi.fn().mockRejectedValue(new Error('Failed to fetch')); + + render(DeploymentSteps); + const urlInput = screen.getByPlaceholderText('Enter URL to .rain file'); + const loadButton = screen.getByText('Load Strategy'); + + await userEvent.type(urlInput, 'https://example.com/strategy.rain'); + await userEvent.click(loadButton); + + await waitFor(() => { + expect(screen.getByText('No valid strategy exists at this URL')).toBeInTheDocument(); + }); + }); + + it('initializes GUI when deployment is selected', async () => { + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + text: () => Promise.resolve(JSON.stringify(dotrain)) + }); + + const mockDeployments: string[] = ['deployment1', 'deployment2']; + + (DotrainOrderGui.getDeploymentKeys as Mock).mockResolvedValue(mockDeployments); + + render(DeploymentSteps); + const urlInput = screen.getByPlaceholderText('Enter URL to .rain file'); + const loadButton = screen.getByText('Load Strategy'); + + await userEvent.type(urlInput, 'https://example.com/strategy.rain'); + await userEvent.click(loadButton); + + await waitFor(() => { + expect(screen.getByText('Select Deployment')).toBeInTheDocument(); + expect(screen.getByText('Select a deployment')).toBeInTheDocument(); + }); + + const dropdownButton = screen.getByTestId('dropdown-button'); + await userEvent.click(dropdownButton); + const dropdown = screen.getByTestId('dropdown'); + await userEvent.click(dropdown); + const deploymentOption = screen.getByText('deployment1'); + await userEvent.click(deploymentOption); + + await waitFor(() => { + expect(DotrainOrderGui.chooseDeployment).toHaveBeenCalled(); + }); + }); +}); diff --git a/packages/ui-components/src/__tests__/DepositInput.test.ts b/packages/ui-components/src/__tests__/DepositInput.test.ts new file mode 100644 index 000000000..a7c45b490 --- /dev/null +++ b/packages/ui-components/src/__tests__/DepositInput.test.ts @@ -0,0 +1,71 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { render, fireEvent, waitFor } from '@testing-library/svelte'; +import DepositInput from '../lib/components/deployment/DepositInput.svelte'; +import type { GuiDeposit } from '@rainlanguage/orderbook/js_api'; +import type { ComponentProps } from 'svelte'; + +type DepositInputProps = ComponentProps; + +describe('DepositInput', () => { + const mockGui = { + getTokenInfo: vi.fn(), + isDepositPreset: vi.fn(), + saveDeposit: vi.fn(), + getDeposits: vi.fn().mockReturnValue([{ token: 'output', amount: '10', address: '0x1234' }]) + }; + + const mockDeposit: GuiDeposit = { + token: { address: '0x123', key: 'TEST', symbol: 'TEST' }, + presets: ['100', '200', '300'] + } as unknown as GuiDeposit; + + beforeEach(() => { + vi.clearAllMocks(); + }); + + it('renders token name and presets', async () => { + const { getByText } = render(DepositInput, { + props: { + deposit: mockDeposit, + gui: { + ...mockGui, + getTokenInfo: vi.fn().mockReturnValue({ name: 'Test Token', symbol: 'TEST' }) + } + } as unknown as DepositInputProps + }); + await waitFor(() => { + expect(getByText(`Deposit amount (${mockDeposit.token?.symbol})`)).toBeTruthy(); + expect(getByText('100')).toBeTruthy(); + expect(getByText('200')).toBeTruthy(); + expect(getByText('300')).toBeTruthy(); + }); + }); + + it('handles preset button clicks', async () => { + const { getByText } = render(DepositInput, { + props: { + deposit: mockDeposit, + gui: mockGui + } as unknown as DepositInputProps + }); + + await fireEvent.click(getByText('100')); + expect(mockGui.saveDeposit).toHaveBeenCalledWith('TEST', '100'); + }); + + it('handles custom input changes', async () => { + mockGui.isDepositPreset.mockReturnValue(false); + + const { getByPlaceholderText } = render(DepositInput, { + props: { + deposit: mockDeposit, + gui: mockGui + } as unknown as DepositInputProps + }); + + const input = getByPlaceholderText('Enter deposit amount'); + await fireEvent.input(input, { target: { value: '150' } }); + + expect(mockGui.saveDeposit).toHaveBeenCalledWith('TEST', '150'); + }); +}); diff --git a/packages/ui-components/src/__tests__/FieldDefinitionInput.test.ts b/packages/ui-components/src/__tests__/FieldDefinitionInput.test.ts new file mode 100644 index 000000000..03b4bd4ae --- /dev/null +++ b/packages/ui-components/src/__tests__/FieldDefinitionInput.test.ts @@ -0,0 +1,102 @@ +import { render, fireEvent } from '@testing-library/svelte'; +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import FieldDefinitionInput from '../lib/components/deployment/FieldDefinitionInput.svelte'; +import { DotrainOrderGui } from '@rainlanguage/orderbook/js_api'; + +vi.mock('@rainlanguage/orderbook/js_api', () => ({ + DotrainOrderGui: vi.fn().mockImplementation(() => ({ + saveFieldValue: vi.fn(), + getFieldValue: vi.fn(), + isFieldPreset: vi.fn() + })) +})); + +describe('FieldDefinitionInput', () => { + let mockGui: DotrainOrderGui; + const mockFieldDefinition = { + binding: 'test-binding', + name: 'Test Field', + description: 'Test Description', + presets: [ + { id: 'preset1', name: 'Preset 1', value: 'value1' }, + { id: 'preset2', name: 'Preset 2', value: 'value2' } + ] + }; + + beforeEach(() => { + mockGui = new DotrainOrderGui(); + }); + + it('renders field name and description', () => { + const { getByText } = render(FieldDefinitionInput, { + props: { + fieldDefinition: mockFieldDefinition, + gui: mockGui + } + }); + + expect(getByText('Test Field')).toBeTruthy(); + expect(getByText('Test Description')).toBeTruthy(); + }); + + it('renders preset buttons', () => { + const { getByText } = render(FieldDefinitionInput, { + props: { + fieldDefinition: mockFieldDefinition, + gui: mockGui + } + }); + + expect(getByText('Preset 1')).toBeTruthy(); + expect(getByText('Preset 2')).toBeTruthy(); + }); + + it('handles preset button clicks', async () => { + const { getByText } = render(FieldDefinitionInput, { + props: { + fieldDefinition: mockFieldDefinition, + gui: mockGui + } + }); + + await fireEvent.click(getByText('Preset 1')); + + expect(mockGui.saveFieldValue).toHaveBeenCalledWith('test-binding', { + isPreset: true, + value: 'preset1' + }); + }); + + it('handles custom input changes', async () => { + const { getByPlaceholderText } = render(FieldDefinitionInput, { + props: { + fieldDefinition: mockFieldDefinition, + gui: mockGui + } + }); + + const input = getByPlaceholderText('Enter custom value'); + await fireEvent.input(input, { target: { value: 'custom value' } }); + + expect(mockGui.saveFieldValue).toHaveBeenCalledWith('test-binding', { + isPreset: false, + value: 'custom value' + }); + }); + + it('does not show Custom button for is-fast-exit binding', () => { + const fastExitFieldDef = { + ...mockFieldDefinition, + binding: 'is-fast-exit' + }; + + const { queryByText } = render(FieldDefinitionInput, { + props: { + fieldDefinition: fastExitFieldDef, + gui: mockGui + } + }); + + expect(queryByText('Custom')).toBeNull(); + }); +}); diff --git a/packages/ui-components/src/__tests__/OrderDetail.test.svelte b/packages/ui-components/src/__tests__/OrderDetail.test.svelte index cf01f1157..2cace9b7b 100644 --- a/packages/ui-components/src/__tests__/OrderDetail.test.svelte +++ b/packages/ui-components/src/__tests__/OrderDetail.test.svelte @@ -1,7 +1,7 @@ - diff --git a/packages/ui-components/src/lib/components/deployment/ButtonSelectOption.svelte b/packages/ui-components/src/lib/components/deployment/ButtonSelectOption.svelte new file mode 100644 index 000000000..fd3a12098 --- /dev/null +++ b/packages/ui-components/src/lib/components/deployment/ButtonSelectOption.svelte @@ -0,0 +1,15 @@ + + + diff --git a/packages/ui-components/src/lib/components/deployment/DeploymentSectionHeader.svelte b/packages/ui-components/src/lib/components/deployment/DeploymentSectionHeader.svelte new file mode 100644 index 000000000..b94a6e94d --- /dev/null +++ b/packages/ui-components/src/lib/components/deployment/DeploymentSectionHeader.svelte @@ -0,0 +1,11 @@ + + +
+

{title}

+

+ {description} +

+
diff --git a/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte new file mode 100644 index 000000000..4b48e06ed --- /dev/null +++ b/packages/ui-components/src/lib/components/deployment/DeploymentSteps.svelte @@ -0,0 +1,376 @@ + + +
+
+
+ +
+ +
+
+ +{#if error} +

{error}

+{/if} +{#if errorDetails} +

{errorDetails}

+{/if} +{#if dotrain} + + + + {#if selectedRef === undefined} + Select a deployment + {:else if selectedOption?.label} + {selectedOption.label} + {:else} + {selectedRef} + {/if} + + + +
+
{option.label ? option.label : ref}
+
+
+
+ + {#if isLoading} + + {/if} + {#if gui} +
+ {#if guiDetails} +
+

+ {guiDetails.name} +

+

+ {guiDetails.description} +

+
+ {/if} + + {#if selectTokens && selectTokens.length > 0} +
+ +
+ {#each selectTokens as tokenKey} + + {/each} +
+
+ {/if} + + {#if allTokensSelected || selectTokens?.length === 0} + {#if allFieldDefinitions.length > 0} +
+ {#each allFieldDefinitions as fieldDefinition} + + {/each} +
+ {/if} + + {#if allDepositFields.length > 0} +
+ {#each allDepositFields as deposit} + + {/each} +
+ {/if} + {#if allTokenInputs.length > 0 && allTokenOutputs.length > 0} +
+ + {#if allTokenInputs.length > 0} + {#each allTokenInputs as input, i} + + {/each} + {/if} + + {#if allTokenOutputs.length > 0} + {#each allTokenOutputs as output, i} + + {/each} + {/if} +
+ {/if} + + {/if} +
+ {/if} +{/if} diff --git a/packages/ui-components/src/lib/components/deployment/DepositInput.svelte b/packages/ui-components/src/lib/components/deployment/DepositInput.svelte new file mode 100644 index 000000000..e68b53546 --- /dev/null +++ b/packages/ui-components/src/lib/components/deployment/DepositInput.svelte @@ -0,0 +1,87 @@ + + +
+ + {#if deposit.presets} +
+ {#each deposit.presets as preset} + handlePresetClick(preset)} + /> + {/each} +
+ {/if} + + handleInput(e)} + /> + + {#if error} +
+ + {error} +
+ {/if} +
diff --git a/packages/ui-components/src/lib/components/deployment/FieldDefinitionInput.svelte b/packages/ui-components/src/lib/components/deployment/FieldDefinitionInput.svelte new file mode 100644 index 000000000..dfd1286db --- /dev/null +++ b/packages/ui-components/src/lib/components/deployment/FieldDefinitionInput.svelte @@ -0,0 +1,65 @@ + + +
+ + + {#if fieldDefinition.presets} +
+ {#each fieldDefinition.presets as preset} + handlePresetClick(preset)} + active={currentFieldDefinition?.value === preset.value} + /> + {/each} +
+ {/if} + {#if fieldDefinition.binding !== 'is-fast-exit'} + { + if (currentTarget instanceof HTMLInputElement) { + handleCustomInputChange(currentTarget.value); + } + }} + /> + {/if} +
diff --git a/packages/ui-components/src/lib/components/deployment/SelectToken.svelte b/packages/ui-components/src/lib/components/deployment/SelectToken.svelte new file mode 100644 index 000000000..387207e21 --- /dev/null +++ b/packages/ui-components/src/lib/components/deployment/SelectToken.svelte @@ -0,0 +1,84 @@ + + +
+
+
+ + {#if checking} +
+ + Checking... +
+ {:else if tokenInfo} +
+ + {tokenInfo.name} +
+ {:else if error} +
+ + {error} +
+ {/if} +
+ +
+
diff --git a/packages/ui-components/src/lib/components/deployment/TokenInputOrOutput.svelte b/packages/ui-components/src/lib/components/deployment/TokenInputOrOutput.svelte new file mode 100644 index 000000000..1b14acfb8 --- /dev/null +++ b/packages/ui-components/src/lib/components/deployment/TokenInputOrOutput.svelte @@ -0,0 +1,52 @@ + + +
+
+
+ +
+ gui?.setVaultId(true, i, vaultIds[i])} + /> +
+ {#if error} +
+ + {error} +
+ {/if} +
diff --git a/packages/ui-components/src/lib/components/detail/OrderDetail.svelte b/packages/ui-components/src/lib/components/detail/OrderDetail.svelte index 1cb312dca..208dd4b48 100644 --- a/packages/ui-components/src/lib/components/detail/OrderDetail.svelte +++ b/packages/ui-components/src/lib/components/detail/OrderDetail.svelte @@ -12,7 +12,7 @@ import { QKEY_ORDER } from '../../queries/keys'; import CodeMirrorRainlang from '../CodeMirrorRainlang.svelte'; import { queryClient } from '../../stores/queryClient'; - import { getOrder, type Order } from '@rainlanguage/orderbook/js_api'; + import { getOrder, type OrderSubgraph } from '@rainlanguage/orderbook/js_api'; import { createQuery } from '@tanstack/svelte-query'; import { Button, TabItem, Tabs } from 'flowbite-svelte'; import { onDestroy } from 'svelte'; @@ -22,12 +22,13 @@ export let walletAddressMatchesOrBlank: Readable<(address: string) => boolean> | undefined = undefined; - export let handleOrderRemoveModal: ((order: Order, refetch: () => void) => void) | undefined = - undefined; + export let handleOrderRemoveModal: + | ((order: OrderSubgraph, refetch: () => void) => void) + | undefined = undefined; export let handleQuoteDebugModal: | undefined | (( - order: Order, + order: OrderSubgraph, rpcUrl: string, orderbook: string, inputIOIndex: number, @@ -47,7 +48,7 @@ let codeMirrorDisabled = true; let codeMirrorStyles = {}; - $: orderDetailQuery = createQuery({ + $: orderDetailQuery = createQuery({ queryKey: [id, QKEY_ORDER + id], queryFn: () => getOrder(subgraphUrl, id), enabled: !!subgraphUrl diff --git a/packages/ui-components/src/lib/components/detail/TanstackOrderQuote.svelte b/packages/ui-components/src/lib/components/detail/TanstackOrderQuote.svelte index 787517711..157b9a9b1 100644 --- a/packages/ui-components/src/lib/components/detail/TanstackOrderQuote.svelte +++ b/packages/ui-components/src/lib/components/detail/TanstackOrderQuote.svelte @@ -5,7 +5,7 @@ import { QKEY_ORDER_QUOTE } from '../../queries/keys'; import { formatUnits, hexToNumber, isHex } from 'viem'; import { createQuery } from '@tanstack/svelte-query'; - import type { Order } from '@rainlanguage/orderbook/js_api'; + import type { OrderSubgraph } from '@rainlanguage/orderbook/js_api'; import { Table, TableBody, @@ -18,13 +18,13 @@ import { BugOutline, PauseSolid, PlaySolid } from 'flowbite-svelte-icons'; export let id: string; - export let order: Order; + export let order: OrderSubgraph; export let rpcUrl: string; export let orderbookAddress: string = ''; export let handleQuoteDebugModal: | undefined | (( - order: Order, + order: OrderSubgraph, rpcUrl: string, orderbookAddress: string, inputIndex: number, diff --git a/packages/ui-components/src/lib/components/detail/VaultDetail.svelte b/packages/ui-components/src/lib/components/detail/VaultDetail.svelte index 07e173c45..8b321af98 100644 --- a/packages/ui-components/src/lib/components/detail/VaultDetail.svelte +++ b/packages/ui-components/src/lib/components/detail/VaultDetail.svelte @@ -19,6 +19,7 @@ import { ArrowDownOutline, ArrowUpOutline } from 'flowbite-svelte-icons'; import type { Vault } from '@rainlanguage/orderbook/js_api'; + import type { AppStoresInterface } from '../../types/appStores'; export let id: string; export let network: string; @@ -29,6 +30,8 @@ export let handleWithdrawModal: ((vault: Vault, onWithdraw: () => void) => void) | undefined = undefined; export let lightweightChartsTheme: Readable | undefined = undefined; + export let activeNetworkRef: AppStoresInterface['activeNetworkRef']; + export let activeOrderbookRef: AppStoresInterface['activeOrderbookRef']; export let settings; const subgraphUrl = $settings?.subgraphs?.[network] || ''; @@ -40,6 +43,11 @@ enabled: !!subgraphUrl }); + const updateActiveNetworkAndOrderbook = (subgraphName: string) => { + activeNetworkRef.set(subgraphName); + activeOrderbookRef.set(subgraphName); + }; + const interval = setInterval(async () => { // This invalidate function invalidates // both vault detail and vault balance changes queries @@ -129,7 +137,10 @@ tauri-app/src/lib/components/detail/VaultDetail.svelte goto(`/orders/${order.id}`)} + on:click={() => { + updateActiveNetworkAndOrderbook(order.subgraphName); + goto(`/orders/${order.id}`); + }} > @@ -152,7 +163,10 @@ tauri-app/src/lib/components/detail/VaultDetail.svelte goto(`/orders/${order.id}`)} + on:click={() => { + updateActiveNetworkAndOrderbook(order.subgraphName); + goto(`/orders/${order.id}`); + }} > diff --git a/packages/ui-components/src/lib/components/dropdown/DropdownRadio.svelte b/packages/ui-components/src/lib/components/dropdown/DropdownRadio.svelte index 50da95644..0c15973fe 100644 --- a/packages/ui-components/src/lib/components/dropdown/DropdownRadio.svelte +++ b/packages/ui-components/src/lib/components/dropdown/DropdownRadio.svelte @@ -25,6 +25,7 @@ - + {#each optionsSorted as [ref, option]} Output Token(s) Trades - diff --git a/packages/ui-components/src/lib/components/tables/VaultsListTable.svelte b/packages/ui-components/src/lib/components/tables/VaultsListTable.svelte index 28c8d7a3a..57aa95cc3 100644 --- a/packages/ui-components/src/lib/components/tables/VaultsListTable.svelte +++ b/packages/ui-components/src/lib/components/tables/VaultsListTable.svelte @@ -138,7 +138,6 @@ Balance Input For Output For - diff --git a/packages/ui-components/src/lib/index.ts b/packages/ui-components/src/lib/index.ts index 0b2362543..92a2fe076 100644 --- a/packages/ui-components/src/lib/index.ts +++ b/packages/ui-components/src/lib/index.ts @@ -46,6 +46,13 @@ 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 FieldDefinitionInput } from './components/deployment/FieldDefinitionInput.svelte'; +export { default as DepositInput } from './components/deployment/DepositInput.svelte'; +export { default as DeploymentSteps } from './components/deployment/DeploymentSteps.svelte'; +export { default as TokenOutput } from './components/deployment/TokenInputOrOutput.svelte'; +export { default as SelectToken } from './components/deployment/SelectToken.svelte'; + +export { default as TokenInputOrOutput } from './components/deployment/TokenInputOrOutput.svelte'; export { default as VaultBalanceChangesTable } from './components/tables/VaultBalanceChangesTable.svelte'; export { default as VaultBalanceChart } from './components/charts/VaultBalanceChart.svelte'; export { default as VaultDetail } from './components/detail/VaultDetail.svelte'; diff --git a/packages/ui-components/vite.config.ts b/packages/ui-components/vite.config.ts index 006befcf3..ef13532ad 100644 --- a/packages/ui-components/vite.config.ts +++ b/packages/ui-components/vite.config.ts @@ -3,6 +3,7 @@ import { sveltekit } from '@sveltejs/kit/vite'; import { loadEnv } from 'vite'; export default defineConfig(({ mode }) => ({ + assetsInclude: ['**/*.rain'], plugins: [sveltekit()], resolve: { conditions: mode === 'test' ? ['browser'] : [] diff --git a/packages/webapp/.prettierignore b/packages/webapp/.prettierignore index ab78a95dd..6d06c2d43 100644 --- a/packages/webapp/.prettierignore +++ b/packages/webapp/.prettierignore @@ -2,3 +2,5 @@ package-lock.json pnpm-lock.yaml yarn.lock +*.md +*.rain \ No newline at end of file diff --git a/packages/webapp/package.json b/packages/webapp/package.json index c9c0439f3..3eee56bdf 100644 --- a/packages/webapp/package.json +++ b/packages/webapp/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "type": "module", "license": "LicenseRef-DCL-1.0", - "author": "Rain Open Source LLC", + "author": "Rain Open Source Software Ltd", "scripts": { "dev": "vite dev", "build": "vite build", diff --git a/packages/webapp/src/lib/settings-12-11-24.json b/packages/webapp/src/lib/settings-12-11-24.json deleted file mode 100644 index ac5d9041d..000000000 --- a/packages/webapp/src/lib/settings-12-11-24.json +++ /dev/null @@ -1,160 +0,0 @@ -{ - "accounts": { - "wallet1": "0xf08bCbce72f62c95Dcb7c07dCb5Ed26ACfCfBc11", - "wallet2": "0x6bc14a99ccf7f9037c98d75eec6c6d807f9d953f" - }, - "networks": { - "flare": { - "rpc": "https://rpc.ankr.com/flare", - "chain-id": 14, - "currency": "FLR" - }, - "base": { - "rpc": "https://mainnet.base.org", - "chain-id": 8453, - "network-id": 8453, - "currency": "ETH" - }, - "sepolia": { - "rpc": "https://1rpc.io/sepolia", - "chain-id": 11155111, - "network-id": 11155111, - "currency": "ETH" - }, - "polygon": { - "rpc": "https://rpc.ankr.com/polygon", - "chain-id": 137, - "network-id": 137, - "currency": "POL" - }, - "arbitrum": { - "rpc": "https://rpc.ankr.com/arbitrum", - "chain-id": 42161, - "network-id": 42161, - "currency": "ETH" - }, - "bsc": { - "rpc": "https://rpc.ankr.com/bsc", - "chain-id": 56, - "network-id": 56, - "currency": "BNB" - }, - "linea": { - "rpc": "https://rpc.linea.build", - "chain-id": 59144, - "network-id": 59144, - "currency": "ETH" - }, - "ethereum": { - "rpc": "https://rpc.ankr.com/eth", - "chain-id": 1, - "network-id": 1, - "currency": "ETH" - } - }, - "subgraphs": { - "flare": "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-flare/0.8/gn", - "base": "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-base/0.9/gn", - "sepolia": "http://replaceme.com", - "polygon": "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-polygon/0.6/gn", - "arbitrum": "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-arbitrum/0.2/gn", - "bsc": "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-bsc/2024-10-14-63f4/gn", - "linea": "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-linea/2024-10-14-12fc/gn", - "ethereum": "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-mainnet/2024-10-25-af6a/gn" - }, - "metaboards": { - "flare": "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-flare-0x893BBFB7/0.1/gn", - "base": "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-base-0x59401C93/0.1/gn", - "sepolia": "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-sepolia-0x77991674/0.1/gn", - "polygon": "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-polygon/0.1/gn", - "arbitrum": "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-arbitrum/0.1/gn", - "bsc": "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-bsc/0.1/gn", - "linea": "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-linea-0xed7d6156/1.0.0/gn", - "ethereum": "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/metadata-mainnet/2024-10-25-2857/gn" - }, - "orderbooks": { - "flare": { - "address": "0xCEe8Cd002F151A536394E564b84076c41bBBcD4d", - "network": "flare", - "subgraph": "flare" - }, - "base": { - "address": "0xd2938e7c9fe3597f78832ce780feb61945c377d7", - "network": "base", - "subgraph": "base" - }, - "sepolia": { - "address": "0x0bB72B4C7c0d47b2CaED07c804D9243C1B8a0728", - "network": "sepolia", - "subgraph": "sepolia" - }, - "polygon": { - "address": "0x7D2f700b1f6FD75734824EA4578960747bdF269A", - "network": "polygon", - "subgraph": "polygon" - }, - "arbitrum": { - "address": "0x550878091b2B1506069F61ae59e3A5484Bca9166", - "network": "arbitrum", - "subgraph": "arbitrum" - }, - "matchain": { - "address": "0x40312edab8fe65091354172ad79e9459f21094e2", - "network": "matchain", - "subgraph": "matchain" - }, - "bsc": { - "address": "0xd2938E7c9fe3597F78832CE780Feb61945c377d7", - "network": "bsc", - "subgraph": "bsc" - }, - "linea": { - "address": "0x22410e2a46261a1B1e3899a072f303022801C764", - "network": "linea", - "subgraph": "linea" - }, - "ethereum": { - "address": "0x0eA6d458488d1cf51695e1D6e4744e6FB715d37C", - "network": "ethereum", - "subgraph": "ethereum" - } - }, - "deployers": { - "flare": { - "address": "0xE3989Ea7486c0F418C764e6c511e86f6E8830FAb", - "network": "flare" - }, - "base": { - "address": "0xC1A14cE2fd58A3A2f99deCb8eDd866204eE07f8D", - "network": "base" - }, - "sepolia": { - "address": "0x7692BA8446Bb8B3140A2c02df073080BeD0a7F8E", - "network": "sepolia" - }, - "polygon": { - "address": "0xE7116BC05C8afe25e5B54b813A74F916B5D42aB1", - "network": "polygon" - }, - "arbitrum": { - "address": "0x9B0D254bd858208074De3d2DaF5af11b3D2F377F", - "network": "arbitrum" - }, - "matchain": { - "address": "0x582d9e838FE6cD9F8147C66A8f56A3FBE513a6A2", - "network": "polygon" - }, - "bsc": { - "address": "0xA2f56F8F74B7d04d61f281BE6576b6155581dcBA", - "network": "bsc" - }, - "linea": { - "address": "0xA2f56F8F74B7d04d61f281BE6576b6155581dcBA", - "network": "linea" - }, - "ethereum": { - "address": "0xd19581a021f4704ad4eBfF68258e7A0a9DB1CD77", - "network": "ethereum" - } - } -} diff --git a/packages/webapp/src/lib/settings-12-11-24.yml b/packages/webapp/src/lib/settings-12-11-24.yml deleted file mode 100644 index 2ad6dd7d2..000000000 --- a/packages/webapp/src/lib/settings-12-11-24.yml +++ /dev/null @@ -1,133 +0,0 @@ -networks: - flare: - rpc: https://rpc.ankr.com/flare - chain-id: 14 - currency: FLR - base: - rpc: https://mainnet.base.org - chain-id: 8453 - network-id: 8453 - currency: ETH - sepolia: - rpc: https://1rpc.io/sepolia - chain-id: 11155111 - network-id: 11155111 - currency: ETH - polygon: - rpc: https://rpc.ankr.com/polygon - chain-id: 137 - network-id: 137 - currency: POL - arbitrum: - rpc: https://rpc.ankr.com/arbitrum - chain-id: 42161 - network-id: 42161 - currency: ETH - matchain: - rpc: https://rpc.matchain.io - chain-id: 698 - network-id: 698 - currency: BNB - bsc: - rpc: https://rpc.ankr.com/bsc - chain-id: 56 - network-id: 56 - currency: BNB - linea: - rpc: https://rpc.linea.build - chain-id: 59144 - network-id: 59144 - currency: ETH - ethereum: - rpc: https://rpc.ankr.com/eth - chain-id: 1 - network-id: 1 - currency: ETH - -subgraphs: - flare: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-flare/0.8/gn - base: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-base/0.9/gn - sepolia: http://replaceme.com - polygon: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-polygon/0.6/gn - arbitrum: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-arbitrum/0.2/gn - matchain: http://subgraph.mobula.io:8000/subgraphs/name/matchain-ob - bsc: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-bsc/2024-10-14-63f4/gn - linea: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-linea/2024-10-14-12fc/gn - ethereum: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-mainnet/2024-10-25-af6a/gn - -metaboards: - flare: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-flare-0x893BBFB7/0.1/gn - base: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-base-0x59401C93/0.1/gn - sepolia: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-sepolia-0x77991674/0.1/gn - polygon: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-polygon/0.1/gn - arbitrum: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-arbitrum/0.1/gn - bsc: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-bsc/0.1/gn - linea: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-linea-0xed7d6156/1.0.0/gn - ethereum: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/metadata-mainnet/2024-10-25-2857/gn - -orderbooks: - flare: - address: 0xCEe8Cd002F151A536394E564b84076c41bBBcD4d - network: flare - subgraph: flare - base: - address: 0xd2938e7c9fe3597f78832ce780feb61945c377d7 - network: base - subgraph: base - sepolia: - address: 0x0bB72B4C7c0d47b2CaED07c804D9243C1B8a0728 - network: sepolia - subgraph: sepolia - polygon: - address: 0x7D2f700b1f6FD75734824EA4578960747bdF269A - network: polygon - subgraph: polygon - arbitrum: - address: 0x550878091b2B1506069F61ae59e3A5484Bca9166 - network: arbitrum - subgraph: arbitrum - matchain: - address: 0x40312edab8fe65091354172ad79e9459f21094e2 - network: matchain - subgraph: matchain - bsc: - address: 0xd2938E7c9fe3597F78832CE780Feb61945c377d7 - network: bsc - subgraph: bsc - linea: - address: 0x22410e2a46261a1B1e3899a072f303022801C764 - network: linea - subgraph: linea - ethereum: - address: 0x0eA6d458488d1cf51695e1D6e4744e6FB715d37C - network: ethereum - subgraph: ethereum - -deployers: - flare: - address: 0xE3989Ea7486c0F418C764e6c511e86f6E8830FAb - network: flare - base: - address: 0xC1A14cE2fd58A3A2f99deCb8eDd866204eE07f8D - network: base - sepolia: - address: 0x7692BA8446Bb8B3140A2c02df073080BeD0a7F8E - network: sepolia - polygon: - address: 0xE7116BC05C8afe25e5B54b813A74F916B5D42aB1 - network: polygon - arbitrum: - address: 0x9B0D254bd858208074De3d2DaF5af11b3D2F377F - network: arbitrum - matchain: - address: 0x582d9e838FE6cD9F8147C66A8f56A3FBE513a6A2 - network: polygon - bsc: - address: 0xA2f56F8F74B7d04d61f281BE6576b6155581dcBA - network: bsc - linea: - address: 0xA2f56F8F74B7d04d61f281BE6576b6155581dcBA - network: linea - ethereum: - address: 0xd19581a021f4704ad4eBfF68258e7A0a9DB1CD77 - network: ethereum diff --git a/packages/webapp/src/routes/+layout.ts b/packages/webapp/src/routes/+layout.ts index 8b97108a1..de666886a 100644 --- a/packages/webapp/src/routes/+layout.ts +++ b/packages/webapp/src/routes/+layout.ts @@ -5,14 +5,17 @@ import type { OrderbookRef } from '@rainlanguage/ui-components'; import { writable, derived } from 'svelte/store'; -import settingsJson from '$lib/settings-12-11-24.json'; import pkg from 'lodash'; const { pickBy } = pkg; export interface LayoutData { stores: AppStoresInterface; } -export const load = () => { +export const load = async () => { + const response = await fetch( + 'https://raw.githubusercontent.com/rainlanguage/rain.strategies/refs/heads/main/settings.json' + ); + const settingsJson = await response.json(); const activeNetworkRef = writable(''); const settings = writable(settingsJson); const activeOrderbookRef = writable(''); diff --git a/packages/webapp/src/routes/deployment/+page.svelte b/packages/webapp/src/routes/deployment/+page.svelte index c9a40f161..d6104a5d9 100644 --- a/packages/webapp/src/routes/deployment/+page.svelte +++ b/packages/webapp/src/routes/deployment/+page.svelte @@ -1,401 +1,7 @@ -
- { - gui = undefined; - }} - /> -
- -
- - - - {#if selectedRef === undefined} - Select a deployment - {:else if selectedOption?.label} - {selectedOption.label} - {:else} - {selectedRef} - {/if} - - - -
-
{option.label ? option.label : ref}
-
-
-
+
+
- -{#if gui} - {#if isLimitStrat && selectTokens.size > 0} - - - {#each selectTokens.entries() as [token]} -
- - - { - if (currentTarget instanceof HTMLInputElement) { - if (!gui) return; - await gui.saveSelectTokenAddress(token, currentTarget.value); - selectTokens = gui.getSelectTokens(); - gui = gui; - } - }} - /> -
- {/each} - {/if} - - {#if allFieldDefinitions.length > 0} - - - {#each allFieldDefinitions as fieldDefinition} -
- - - [ - preset.id, - { - label: preset.name, - id: preset.id - } - ]) - ), - ...{ custom: { label: 'Custom value', id: '' } } - }} - on:change={({ detail }) => { - gui?.saveFieldValue(fieldDefinition.binding, { - isPreset: detail.value !== 'custom', - value: detail.value === 'custom' ? '' : detail.value || '' - }); - gui = gui; - }} - > - - {#if selectedRef === undefined} - Select a preset - {:else if selectedOption?.label} - {selectedOption.label} - {:else} - {selectedRef} - {/if} - - - -
-
{option.label ? option.label : ref}
-
-
-
- - {#if gui?.isFieldPreset(fieldDefinition.binding) === false} - { - if (currentTarget instanceof HTMLInputElement) { - gui?.saveFieldValue(fieldDefinition.binding, { - isPreset: false, - value: currentTarget.value - }); - } - }} - /> - {/if} -
- {/each} - {/if} - - {#if allDeposits.length > 0} - - - {#each allDeposits as deposit} -
- - - [ - preset, - { - label: preset - } - ]) - ), - ...{ custom: { label: 'Custom value' } } - }} - on:change={({ detail }) => { - gui?.saveDeposit( - deposit.token.key, - detail.value === 'custom' ? '' : detail.value || '' - ); - gui = gui; - }} - > - - {#if selectedRef === undefined} - Choose deposit amount - {:else if selectedOption?.label} - {selectedOption.label} - {:else} - {selectedRef} - {/if} - - - -
-
{option.label ? option.label : ref}
-
-
-
- - {#if gui?.isDepositPreset(deposit.token.key) === false} - { - if (currentTarget instanceof HTMLInputElement) { - gui?.saveDeposit(deposit.token.key, currentTarget.value); - } - }} - /> - {/if} -
- {/each} - {/if} - - {#if selectedDeployment} -
-
- -
- - {#if useCustomVaultIds} - - - {#if gui?.getCurrentDeployment().deployment.order.inputs.length > 0} - - {#each gui?.getCurrentDeployment().deployment.order.inputs as input, i} -
- - gui?.setVaultId(true, i, inputVaultIds[i])} - /> -
- {/each} - {/if} - - {#if gui?.getCurrentDeployment().deployment.order.outputs.length > 0} - - {#each gui?.getCurrentDeployment().deployment.order.outputs as output, i} -
- - gui?.setVaultId(false, i, outputVaultIds[i])} - /> -
- {/each} - {/if} - {/if} -
- - - {/if} -{/if} diff --git a/packages/webapp/src/routes/test/+page.svelte b/packages/webapp/src/routes/test/+page.svelte index e56869beb..f42a0153d 100644 --- a/packages/webapp/src/routes/test/+page.svelte +++ b/packages/webapp/src/routes/test/+page.svelte @@ -30,7 +30,7 @@ - + - import { - VaultBalanceChangesTable, - VaultBalanceChart, - QKEY_VAULT, - TanstackPageContentDetail, - bigintStringToHex, - CardProperty, - Hash, - HashType - } from '@rainlanguage/ui-components'; + import { PageHeader } from '@rainlanguage/ui-components'; import { page } from '$app/stores'; - import { createQuery } from '@tanstack/svelte-query'; - import { getVault } from '@rainlanguage/orderbook/js_api'; - import { goto } from '$app/navigation'; - import { Button } from 'flowbite-svelte'; - import { formatUnits } from 'viem'; + import { VaultDetail } from '@rainlanguage/ui-components'; - const { settings } = $page.data.stores; - const { lightweightChartsTheme } = $page.data.stores; - const id = $page.params.id; - const network = $page.params.network; - const subgraphUrl = $settings?.subgraphs?.[network] || ''; - - $: vaultDetailQuery = createQuery({ - queryKey: [id, QKEY_VAULT + id], - queryFn: () => { - return getVault(subgraphUrl || '', id); - }, - enabled: !!subgraphUrl - }); + const { settings, activeOrderbookRef, activeNetworkRef, lightweightChartsTheme } = + $page.data.stores; - - -
- {data.token.name} -
-
- - - Vault ID - {bigintStringToHex(data.vaultId)} - - - - Orderbook - - - - - - - Owner Address - - - - - - - Token address - - - - - - - Balance - {formatUnits(BigInt(data.balance), Number(data.token.decimals ?? 0))} - {data.token.symbol} - - - - Orders as input - -

- {#if data.ordersAsInput && data.ordersAsInput.length > 0} - {#each data.ordersAsInput as order} - - {/each} - {:else} - None - {/if} -

-
-
- - - Orders as output - -

- {#if data.ordersAsOutput && data.ordersAsOutput.length > 0} - {#each data.ordersAsOutput as order} - - {/each} - {:else} - None - {/if} -

-
-
-
- - - - + - -
+ diff --git a/script/BuildAuthoringMeta.sol b/script/BuildAuthoringMeta.sol index 144a46f31..564be3412 100644 --- a/script/BuildAuthoringMeta.sol +++ b/script/BuildAuthoringMeta.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Script} from "forge-std/Script.sol"; diff --git a/script/BuildPointers.sol b/script/BuildPointers.sol index f038243ed..88912b140 100644 --- a/script/BuildPointers.sol +++ b/script/BuildPointers.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Script} from "forge-std/Script.sol"; diff --git a/script/Deploy.sol b/script/Deploy.sol index 1604f0035..26478e36e 100644 --- a/script/Deploy.sol +++ b/script/Deploy.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Script} from "forge-std/Script.sol"; diff --git a/src/abstract/OrderBookV4ArbCommon.sol b/src/abstract/OrderBookV4ArbCommon.sol index 3d9894866..e10766ef3 100644 --- a/src/abstract/OrderBookV4ArbCommon.sol +++ b/src/abstract/OrderBookV4ArbCommon.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.19; import {EvaluableV3, SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV3.sol"; diff --git a/src/abstract/OrderBookV4ArbOrderTaker.sol b/src/abstract/OrderBookV4ArbOrderTaker.sol index 6e0d0d801..be5378852 100644 --- a/src/abstract/OrderBookV4ArbOrderTaker.sol +++ b/src/abstract/OrderBookV4ArbOrderTaker.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.19; import {ERC165, IERC165} from "openzeppelin-contracts/contracts/utils/introspection/ERC165.sol"; diff --git a/src/abstract/OrderBookV4FlashBorrower.sol b/src/abstract/OrderBookV4FlashBorrower.sol index 9d8f78e9e..efe61f40f 100644 --- a/src/abstract/OrderBookV4FlashBorrower.sol +++ b/src/abstract/OrderBookV4FlashBorrower.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.19; import {ERC165, IERC165} from "openzeppelin-contracts/contracts/utils/introspection/ERC165.sol"; diff --git a/src/abstract/OrderBookV4FlashLender.sol b/src/abstract/OrderBookV4FlashLender.sol index 3934c0262..e8b962d00 100644 --- a/src/abstract/OrderBookV4FlashLender.sol +++ b/src/abstract/OrderBookV4FlashLender.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.19; import {ERC165, IERC165} from "openzeppelin-contracts/contracts/utils/introspection/ERC165.sol"; diff --git a/src/concrete/arb/GenericPoolOrderBookV4ArbOrderTaker.sol b/src/concrete/arb/GenericPoolOrderBookV4ArbOrderTaker.sol index c8d6227b7..9a8777f5d 100644 --- a/src/concrete/arb/GenericPoolOrderBookV4ArbOrderTaker.sol +++ b/src/concrete/arb/GenericPoolOrderBookV4ArbOrderTaker.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; diff --git a/src/concrete/arb/GenericPoolOrderBookV4FlashBorrower.sol b/src/concrete/arb/GenericPoolOrderBookV4FlashBorrower.sol index ff7d3076b..9e1c89de3 100644 --- a/src/concrete/arb/GenericPoolOrderBookV4FlashBorrower.sol +++ b/src/concrete/arb/GenericPoolOrderBookV4FlashBorrower.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {IERC3156FlashLender} from "rain.orderbook.interface/interface/ierc3156/IERC3156FlashLender.sol"; diff --git a/src/concrete/arb/RouteProcessorOrderBookV4ArbOrderTaker.sol b/src/concrete/arb/RouteProcessorOrderBookV4ArbOrderTaker.sol index 8b2fd036a..b71a0d2d8 100644 --- a/src/concrete/arb/RouteProcessorOrderBookV4ArbOrderTaker.sol +++ b/src/concrete/arb/RouteProcessorOrderBookV4ArbOrderTaker.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {IRouteProcessor} from "sushixswap-v2/src/interfaces/IRouteProcessor.sol"; diff --git a/src/concrete/ob/OrderBook.sol b/src/concrete/ob/OrderBook.sol index 44baa77a1..b5f3daf5a 100644 --- a/src/concrete/ob/OrderBook.sol +++ b/src/concrete/ob/OrderBook.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Math} from "openzeppelin-contracts/contracts/utils/math/Math.sol"; diff --git a/src/concrete/parser/OrderBookSubParser.sol b/src/concrete/parser/OrderBookSubParser.sol index 1f595f07d..30ba2b681 100644 --- a/src/concrete/parser/OrderBookSubParser.sol +++ b/src/concrete/parser/OrderBookSubParser.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import { diff --git a/src/lib/LibOrder.sol b/src/lib/LibOrder.sol index e8bb91eba..1725f475f 100644 --- a/src/lib/LibOrder.sol +++ b/src/lib/LibOrder.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.18; import {OrderV3} from "rain.orderbook.interface/interface/IOrderBookV4.sol"; diff --git a/src/lib/LibOrderBook.sol b/src/lib/LibOrderBook.sol index 36911e689..37e4fd9fd 100644 --- a/src/lib/LibOrderBook.sol +++ b/src/lib/LibOrderBook.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.19; import { diff --git a/src/lib/LibOrderBookArb.sol b/src/lib/LibOrderBookArb.sol index 66049b6ad..651c99dda 100644 --- a/src/lib/LibOrderBookArb.sol +++ b/src/lib/LibOrderBookArb.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.19; import {TaskV1} from "rain.orderbook.interface/interface/IOrderBookV4.sol"; diff --git a/src/lib/LibOrderBookSubParser.sol b/src/lib/LibOrderBookSubParser.sol index 8afc96b67..b07d826db 100644 --- a/src/lib/LibOrderBookSubParser.sol +++ b/src/lib/LibOrderBookSubParser.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.19; import {AuthoringMetaV2, Operand} from "rain.interpreter.interface/interface/ISubParserV3.sol"; diff --git a/subgraph/package.json b/subgraph/package.json index fe3e272d3..d34c5c90f 100644 --- a/subgraph/package.json +++ b/subgraph/package.json @@ -3,7 +3,7 @@ "description": "Subgraph setup", "version": "1.0.0", "license": "LicenseRef-DCL-1.0", - "author": "Rain Open Source LLC", + "author": "Rain Open Source Software Ltd", "scripts": { "test": "graph test -d" }, diff --git a/tauri-app/package.json b/tauri-app/package.json index dee736725..9220efbe0 100644 --- a/tauri-app/package.json +++ b/tauri-app/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "private": true, "license": "LicenseRef-DCL-1.0", - "author": "Rain Open Source LLC", + "author": "Rain Open Source Software Ltd", "scripts": { "dev": "vite dev", "build": "vite build", diff --git a/tauri-app/src-tauri/Cargo.toml b/tauri-app/src-tauri/Cargo.toml index 79cdfafde..61a5d594f 100644 --- a/tauri-app/src-tauri/Cargo.toml +++ b/tauri-app/src-tauri/Cargo.toml @@ -4,7 +4,7 @@ version = "0.0.0" description = "raindex" edition = "2021" license = "LicenseRef-DCL-1.0" -author = "Rain Open Source LLC" +author = "Rain Open Source Software Ltd" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tauri-app/src/lib/components/modal/ModalOrderRemove.svelte b/tauri-app/src/lib/components/modal/ModalOrderRemove.svelte index 5d7830726..dc8276e57 100644 --- a/tauri-app/src/lib/components/modal/ModalOrderRemove.svelte +++ b/tauri-app/src/lib/components/modal/ModalOrderRemove.svelte @@ -6,7 +6,7 @@ import { toasts } from '$lib/stores/toasts'; import { reportErrorToSentry } from '$lib/services/sentry'; import { formatEthersTransactionError } from '$lib/utils/transaction'; - import type { Order as OrderDetailOrder } from '@rainlanguage/orderbook/js_api'; + import type { OrderSubgraph as OrderDetailOrder } from '@rainlanguage/orderbook/js_api'; let openOrderRemoveModal = true; export let order: OrderDetailOrder; diff --git a/tauri-app/src/lib/components/modal/ModalQuoteDebug.svelte b/tauri-app/src/lib/components/modal/ModalQuoteDebug.svelte index 48fe86cb8..989a34d23 100644 --- a/tauri-app/src/lib/components/modal/ModalQuoteDebug.svelte +++ b/tauri-app/src/lib/components/modal/ModalQuoteDebug.svelte @@ -1,7 +1,7 @@ @@ -18,4 +18,6 @@ {lightweightChartsTheme} {settings} {walletAddressMatchesOrBlank} + {activeNetworkRef} + {activeOrderbookRef} /> diff --git a/test/abstract/OrderBookV4ArbOrderTaker.context.t.sol b/test/abstract/OrderBookV4ArbOrderTaker.context.t.sol index 8d5085ad4..776f7ed9f 100644 --- a/test/abstract/OrderBookV4ArbOrderTaker.context.t.sol +++ b/test/abstract/OrderBookV4ArbOrderTaker.context.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import { diff --git a/test/abstract/OrderBookV4ArbOrderTaker.ierc165.t.sol b/test/abstract/OrderBookV4ArbOrderTaker.ierc165.t.sol index c2810766c..0664d7e3a 100644 --- a/test/abstract/OrderBookV4ArbOrderTaker.ierc165.t.sol +++ b/test/abstract/OrderBookV4ArbOrderTaker.ierc165.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; diff --git a/test/abstract/OrderBookV4FlashBorrower.ierc165.t.sol b/test/abstract/OrderBookV4FlashBorrower.ierc165.t.sol index 3d93eca32..c2663513a 100644 --- a/test/abstract/OrderBookV4FlashBorrower.ierc165.t.sol +++ b/test/abstract/OrderBookV4FlashBorrower.ierc165.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; diff --git a/test/abstract/OrderBookV4FlashLender.fee.t.sol b/test/abstract/OrderBookV4FlashLender.fee.t.sol index ce2b33e0b..71f3874ed 100644 --- a/test/abstract/OrderBookV4FlashLender.fee.t.sol +++ b/test/abstract/OrderBookV4FlashLender.fee.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalMockTest} from "test/util/abstract/OrderBookExternalMockTest.sol"; diff --git a/test/abstract/OrderBookV4FlashLender.griefRecipient.t.sol b/test/abstract/OrderBookV4FlashLender.griefRecipient.t.sol index 38bccea4f..571037930 100644 --- a/test/abstract/OrderBookV4FlashLender.griefRecipient.t.sol +++ b/test/abstract/OrderBookV4FlashLender.griefRecipient.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalMockTest} from "test/util/abstract/OrderBookExternalMockTest.sol"; diff --git a/test/abstract/OrderBookV4FlashLender.ierc165.t.sol b/test/abstract/OrderBookV4FlashLender.ierc165.t.sol index 2b595fefa..02581b1e5 100644 --- a/test/abstract/OrderBookV4FlashLender.ierc165.t.sol +++ b/test/abstract/OrderBookV4FlashLender.ierc165.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; diff --git a/test/abstract/OrderBookV4FlashLender.maxFlashLoan.t.sol b/test/abstract/OrderBookV4FlashLender.maxFlashLoan.t.sol index 8fa3e32a3..c8262076d 100644 --- a/test/abstract/OrderBookV4FlashLender.maxFlashLoan.t.sol +++ b/test/abstract/OrderBookV4FlashLender.maxFlashLoan.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalMockTest} from "test/util/abstract/OrderBookExternalMockTest.sol"; diff --git a/test/abstract/OrderBookV4FlashLender.mockSuccess.t.sol b/test/abstract/OrderBookV4FlashLender.mockSuccess.t.sol index e6c095f3b..0861da130 100644 --- a/test/abstract/OrderBookV4FlashLender.mockSuccess.t.sol +++ b/test/abstract/OrderBookV4FlashLender.mockSuccess.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalMockTest} from "test/util/abstract/OrderBookExternalMockTest.sol"; diff --git a/test/abstract/OrderBookV4FlashLender.reentrant.t.sol b/test/abstract/OrderBookV4FlashLender.reentrant.t.sol index 0f12eeade..1011f1f83 100644 --- a/test/abstract/OrderBookV4FlashLender.reentrant.t.sol +++ b/test/abstract/OrderBookV4FlashLender.reentrant.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Vm} from "forge-std/Vm.sol"; diff --git a/test/abstract/OrderBookV4FlashLender.transfers.t.sol b/test/abstract/OrderBookV4FlashLender.transfers.t.sol index 4c6b3136d..c5e713edc 100644 --- a/test/abstract/OrderBookV4FlashLender.transfers.t.sol +++ b/test/abstract/OrderBookV4FlashLender.transfers.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {stdError} from "forge-std/Test.sol"; diff --git a/test/concrete/arb/GenericPoolOrderBookV4ArbOrderTaker.expression.t.sol b/test/concrete/arb/GenericPoolOrderBookV4ArbOrderTaker.expression.t.sol index 889cfedce..4a3348114 100644 --- a/test/concrete/arb/GenericPoolOrderBookV4ArbOrderTaker.expression.t.sol +++ b/test/concrete/arb/GenericPoolOrderBookV4ArbOrderTaker.expression.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {GenericPoolOrderBookV4ArbOrderTakerTest} from "test/util/abstract/GenericPoolOrderBookV4ArbOrderTakerTest.sol"; diff --git a/test/concrete/arb/GenericPoolOrderBookV4ArbOrderTaker.sender.t.sol b/test/concrete/arb/GenericPoolOrderBookV4ArbOrderTaker.sender.t.sol index 907b17077..9cf87f604 100644 --- a/test/concrete/arb/GenericPoolOrderBookV4ArbOrderTaker.sender.t.sol +++ b/test/concrete/arb/GenericPoolOrderBookV4ArbOrderTaker.sender.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {GenericPoolOrderBookV4ArbOrderTakerTest} from "test/util/abstract/GenericPoolOrderBookV4ArbOrderTakerTest.sol"; diff --git a/test/concrete/arb/GenericPoolOrderBookV4FlashBorrower.sender.t.sol b/test/concrete/arb/GenericPoolOrderBookV4FlashBorrower.sender.t.sol index 983c45073..0e7e62b01 100644 --- a/test/concrete/arb/GenericPoolOrderBookV4FlashBorrower.sender.t.sol +++ b/test/concrete/arb/GenericPoolOrderBookV4FlashBorrower.sender.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {ArbTest} from "test/util/abstract/ArbTest.sol"; diff --git a/test/concrete/arb/RouteProcessorOrderBookV4ArbOrderTaker.expression.t.sol b/test/concrete/arb/RouteProcessorOrderBookV4ArbOrderTaker.expression.t.sol index 836210da4..0a01d4bbe 100644 --- a/test/concrete/arb/RouteProcessorOrderBookV4ArbOrderTaker.expression.t.sol +++ b/test/concrete/arb/RouteProcessorOrderBookV4ArbOrderTaker.expression.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {RouteProcessorOrderBookV4ArbOrderTakerTest} from diff --git a/test/concrete/arb/RouteProcessorOrderBookV4ArbOrderTaker.sender.t.sol b/test/concrete/arb/RouteProcessorOrderBookV4ArbOrderTaker.sender.t.sol index 05847d056..4bb808cd8 100644 --- a/test/concrete/arb/RouteProcessorOrderBookV4ArbOrderTaker.sender.t.sol +++ b/test/concrete/arb/RouteProcessorOrderBookV4ArbOrderTaker.sender.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {RouteProcessorOrderBookV4ArbOrderTakerTest} from diff --git a/test/concrete/ob/OrderBook.addOrder.entask.t.sol b/test/concrete/ob/OrderBook.addOrder.entask.t.sol index 065c6e99f..932aba05e 100644 --- a/test/concrete/ob/OrderBook.addOrder.entask.t.sol +++ b/test/concrete/ob/OrderBook.addOrder.entask.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalRealTest} from "test/util/abstract/OrderBookExternalRealTest.sol"; diff --git a/test/concrete/ob/OrderBook.addOrder.mock.t.sol b/test/concrete/ob/OrderBook.addOrder.mock.t.sol index 5efcc210a..f238cc7ca 100644 --- a/test/concrete/ob/OrderBook.addOrder.mock.t.sol +++ b/test/concrete/ob/OrderBook.addOrder.mock.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalMockTest} from "test/util/abstract/OrderBookExternalMockTest.sol"; diff --git a/test/concrete/ob/OrderBook.addOrder.nonce.t.sol b/test/concrete/ob/OrderBook.addOrder.nonce.t.sol index fece4b03a..982ec9612 100644 --- a/test/concrete/ob/OrderBook.addOrder.nonce.t.sol +++ b/test/concrete/ob/OrderBook.addOrder.nonce.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalRealTest} from "test/util/abstract/OrderBookExternalRealTest.sol"; diff --git a/test/concrete/ob/OrderBook.addOrder.owner.t.sol b/test/concrete/ob/OrderBook.addOrder.owner.t.sol index 76593a5a5..672c03b28 100644 --- a/test/concrete/ob/OrderBook.addOrder.owner.t.sol +++ b/test/concrete/ob/OrderBook.addOrder.owner.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalRealTest} from "test/util/abstract/OrderBookExternalRealTest.sol"; diff --git a/test/concrete/ob/OrderBook.addOrder.t.sol b/test/concrete/ob/OrderBook.addOrder.t.sol index a1f2f6552..27ab6ccdf 100644 --- a/test/concrete/ob/OrderBook.addOrder.t.sol +++ b/test/concrete/ob/OrderBook.addOrder.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalRealTest} from "test/util/abstract/OrderBookExternalRealTest.sol"; diff --git a/test/concrete/ob/OrderBook.clear.badStack.t.sol b/test/concrete/ob/OrderBook.clear.badStack.t.sol index 4899e9ac0..78e1d7185 100644 --- a/test/concrete/ob/OrderBook.clear.badStack.t.sol +++ b/test/concrete/ob/OrderBook.clear.badStack.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalRealTest} from "test/util/abstract/OrderBookExternalRealTest.sol"; diff --git a/test/concrete/ob/OrderBook.clear.context.t.sol b/test/concrete/ob/OrderBook.clear.context.t.sol index 638a7c714..0a37d90c9 100644 --- a/test/concrete/ob/OrderBook.clear.context.t.sol +++ b/test/concrete/ob/OrderBook.clear.context.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalRealTest} from "test/util/abstract/OrderBookExternalRealTest.sol"; diff --git a/test/concrete/ob/OrderBook.clear.handleIO.revert.t.sol b/test/concrete/ob/OrderBook.clear.handleIO.revert.t.sol index 621ada147..998a30468 100644 --- a/test/concrete/ob/OrderBook.clear.handleIO.revert.t.sol +++ b/test/concrete/ob/OrderBook.clear.handleIO.revert.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Vm} from "forge-std/Vm.sol"; diff --git a/test/concrete/ob/OrderBook.clear.mock.t.sol b/test/concrete/ob/OrderBook.clear.mock.t.sol index be2e982b8..a89823531 100644 --- a/test/concrete/ob/OrderBook.clear.mock.t.sol +++ b/test/concrete/ob/OrderBook.clear.mock.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Test, stdError} from "forge-std/Test.sol"; diff --git a/test/concrete/ob/OrderBook.clear.sameToken.t.sol b/test/concrete/ob/OrderBook.clear.sameToken.t.sol index 98315784c..1dca040e8 100644 --- a/test/concrete/ob/OrderBook.clear.sameToken.t.sol +++ b/test/concrete/ob/OrderBook.clear.sameToken.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalRealTest} from "test/util/abstract/OrderBookExternalRealTest.sol"; diff --git a/test/concrete/ob/OrderBook.deposit.entask.t.sol b/test/concrete/ob/OrderBook.deposit.entask.t.sol index 10c9cc9fe..d4a336b9f 100644 --- a/test/concrete/ob/OrderBook.deposit.entask.t.sol +++ b/test/concrete/ob/OrderBook.deposit.entask.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalRealTest} from "test/util/abstract/OrderBookExternalRealTest.sol"; diff --git a/test/concrete/ob/OrderBook.deposit.t.sol b/test/concrete/ob/OrderBook.deposit.t.sol index 1261bf39c..ac1185c77 100644 --- a/test/concrete/ob/OrderBook.deposit.t.sol +++ b/test/concrete/ob/OrderBook.deposit.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {stdError} from "forge-std/Test.sol"; diff --git a/test/concrete/ob/OrderBook.entask.t.sol b/test/concrete/ob/OrderBook.entask.t.sol index 411cc0882..9cc13e939 100644 --- a/test/concrete/ob/OrderBook.entask.t.sol +++ b/test/concrete/ob/OrderBook.entask.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalRealTest} from "test/util/abstract/OrderBookExternalRealTest.sol"; diff --git a/test/concrete/ob/OrderBook.quote.sameToken.t.sol b/test/concrete/ob/OrderBook.quote.sameToken.t.sol index 34ef808b2..8a395ffe9 100644 --- a/test/concrete/ob/OrderBook.quote.sameToken.t.sol +++ b/test/concrete/ob/OrderBook.quote.sameToken.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalRealTest} from "test/util/abstract/OrderBookExternalRealTest.sol"; diff --git a/test/concrete/ob/OrderBook.quote.t.sol b/test/concrete/ob/OrderBook.quote.t.sol index 3501f3479..ae1602586 100644 --- a/test/concrete/ob/OrderBook.quote.t.sol +++ b/test/concrete/ob/OrderBook.quote.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalRealTest} from "test/util/abstract/OrderBookExternalRealTest.sol"; diff --git a/test/concrete/ob/OrderBook.removeOrder.entask.t.sol b/test/concrete/ob/OrderBook.removeOrder.entask.t.sol index b8c0de44e..98a31ba84 100644 --- a/test/concrete/ob/OrderBook.removeOrder.entask.t.sol +++ b/test/concrete/ob/OrderBook.removeOrder.entask.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalRealTest} from "test/util/abstract/OrderBookExternalRealTest.sol"; diff --git a/test/concrete/ob/OrderBook.removeOrder.mock.t.sol b/test/concrete/ob/OrderBook.removeOrder.mock.t.sol index a263e99ac..7f6d364fc 100644 --- a/test/concrete/ob/OrderBook.removeOrder.mock.t.sol +++ b/test/concrete/ob/OrderBook.removeOrder.mock.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalMockTest} from "test/util/abstract/OrderBookExternalMockTest.sol"; diff --git a/test/concrete/ob/OrderBook.removeOrder.owner.t.sol b/test/concrete/ob/OrderBook.removeOrder.owner.t.sol index a46ffcb74..cde6971f9 100644 --- a/test/concrete/ob/OrderBook.removeOrder.owner.t.sol +++ b/test/concrete/ob/OrderBook.removeOrder.owner.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalRealTest} from "test/util/abstract/OrderBookExternalRealTest.sol"; diff --git a/test/concrete/ob/OrderBook.takeOrder.badStack.t.sol b/test/concrete/ob/OrderBook.takeOrder.badStack.t.sol index 2d8f1058f..033f05fcf 100644 --- a/test/concrete/ob/OrderBook.takeOrder.badStack.t.sol +++ b/test/concrete/ob/OrderBook.takeOrder.badStack.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalRealTest} from "test/util/abstract/OrderBookExternalRealTest.sol"; diff --git a/test/concrete/ob/OrderBook.takeOrder.handleIO.revert.t.sol b/test/concrete/ob/OrderBook.takeOrder.handleIO.revert.t.sol index 25cac9abf..28e676a0a 100644 --- a/test/concrete/ob/OrderBook.takeOrder.handleIO.revert.t.sol +++ b/test/concrete/ob/OrderBook.takeOrder.handleIO.revert.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Vm} from "forge-std/Vm.sol"; diff --git a/test/concrete/ob/OrderBook.takeOrder.maximumInput.t.sol b/test/concrete/ob/OrderBook.takeOrder.maximumInput.t.sol index a4dbcfff9..54a31f164 100644 --- a/test/concrete/ob/OrderBook.takeOrder.maximumInput.t.sol +++ b/test/concrete/ob/OrderBook.takeOrder.maximumInput.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; diff --git a/test/concrete/ob/OrderBook.takeOrder.noop.t.sol b/test/concrete/ob/OrderBook.takeOrder.noop.t.sol index e482eec4d..2b3e5f443 100644 --- a/test/concrete/ob/OrderBook.takeOrder.noop.t.sol +++ b/test/concrete/ob/OrderBook.takeOrder.noop.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Vm} from "forge-std/Test.sol"; diff --git a/test/concrete/ob/OrderBook.takeOrder.precision.t.sol b/test/concrete/ob/OrderBook.takeOrder.precision.t.sol index eeaa3547f..b0b470afe 100644 --- a/test/concrete/ob/OrderBook.takeOrder.precision.t.sol +++ b/test/concrete/ob/OrderBook.takeOrder.precision.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Vm} from "forge-std/Test.sol"; diff --git a/test/concrete/ob/OrderBook.takeOrder.sameToken.t.sol b/test/concrete/ob/OrderBook.takeOrder.sameToken.t.sol index 7441a7dca..1143518cb 100644 --- a/test/concrete/ob/OrderBook.takeOrder.sameToken.t.sol +++ b/test/concrete/ob/OrderBook.takeOrder.sameToken.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalRealTest} from "test/util/abstract/OrderBookExternalRealTest.sol"; diff --git a/test/concrete/ob/OrderBook.takeOrder.tokenMismatch.t.sol b/test/concrete/ob/OrderBook.takeOrder.tokenMismatch.t.sol index 59c5a7a27..98d60f9e2 100644 --- a/test/concrete/ob/OrderBook.takeOrder.tokenMismatch.t.sol +++ b/test/concrete/ob/OrderBook.takeOrder.tokenMismatch.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalRealTest} from "test/util/abstract/OrderBookExternalRealTest.sol"; diff --git a/test/concrete/ob/OrderBook.takeOrder.tokenMismatchDecimals.t.sol b/test/concrete/ob/OrderBook.takeOrder.tokenMismatchDecimals.t.sol index 78e3429db..3003d993a 100644 --- a/test/concrete/ob/OrderBook.takeOrder.tokenMismatchDecimals.t.sol +++ b/test/concrete/ob/OrderBook.takeOrder.tokenMismatchDecimals.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalRealTest} from "test/util/abstract/OrderBookExternalRealTest.sol"; diff --git a/test/concrete/ob/OrderBook.vaultBalance.t.sol b/test/concrete/ob/OrderBook.vaultBalance.t.sol index b5f389983..ed6358d68 100644 --- a/test/concrete/ob/OrderBook.vaultBalance.t.sol +++ b/test/concrete/ob/OrderBook.vaultBalance.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalMockTest} from "test/util/abstract/OrderBookExternalMockTest.sol"; diff --git a/test/concrete/ob/OrderBook.withdraw.entask.t.sol b/test/concrete/ob/OrderBook.withdraw.entask.t.sol index 131af8512..214f7f7a7 100644 --- a/test/concrete/ob/OrderBook.withdraw.entask.t.sol +++ b/test/concrete/ob/OrderBook.withdraw.entask.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookExternalRealTest} from "test/util/abstract/OrderBookExternalRealTest.sol"; diff --git a/test/concrete/ob/OrderBook.withdraw.t.sol b/test/concrete/ob/OrderBook.withdraw.t.sol index 1d03aece7..52828d111 100644 --- a/test/concrete/ob/OrderBook.withdraw.t.sol +++ b/test/concrete/ob/OrderBook.withdraw.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.contextCalculatedIORatio.t.sol b/test/concrete/parser/OrderBookSubParser.contextCalculatedIORatio.t.sol index 293f0b20c..561998260 100644 --- a/test/concrete/parser/OrderBookSubParser.contextCalculatedIORatio.t.sol +++ b/test/concrete/parser/OrderBookSubParser.contextCalculatedIORatio.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookSubParserContextTest} from "test/util/abstract/OrderBookSubParserContextTest.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.contextCalculatedMaxOutput.t.sol b/test/concrete/parser/OrderBookSubParser.contextCalculatedMaxOutput.t.sol index dde1a5c82..387cafaf9 100644 --- a/test/concrete/parser/OrderBookSubParser.contextCalculatedMaxOutput.t.sol +++ b/test/concrete/parser/OrderBookSubParser.contextCalculatedMaxOutput.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookSubParserContextTest} from "test/util/abstract/OrderBookSubParserContextTest.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.contextInputToken.t.sol b/test/concrete/parser/OrderBookSubParser.contextInputToken.t.sol index d64b1115f..329775729 100644 --- a/test/concrete/parser/OrderBookSubParser.contextInputToken.t.sol +++ b/test/concrete/parser/OrderBookSubParser.contextInputToken.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookSubParserContextTest} from "test/util/abstract/OrderBookSubParserContextTest.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.contextInputTokenDecimals.t.sol b/test/concrete/parser/OrderBookSubParser.contextInputTokenDecimals.t.sol index 235217c5e..bfcd54b55 100644 --- a/test/concrete/parser/OrderBookSubParser.contextInputTokenDecimals.t.sol +++ b/test/concrete/parser/OrderBookSubParser.contextInputTokenDecimals.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookSubParserContextTest} from "test/util/abstract/OrderBookSubParserContextTest.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.contextInputVaultBalanceBefore.t.sol b/test/concrete/parser/OrderBookSubParser.contextInputVaultBalanceBefore.t.sol index 7cc42f720..6be948e08 100644 --- a/test/concrete/parser/OrderBookSubParser.contextInputVaultBalanceBefore.t.sol +++ b/test/concrete/parser/OrderBookSubParser.contextInputVaultBalanceBefore.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookSubParserContextTest} from "test/util/abstract/OrderBookSubParserContextTest.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.contextInputVaultBalanceIncrease.t.sol b/test/concrete/parser/OrderBookSubParser.contextInputVaultBalanceIncrease.t.sol index 7fbd0a06b..c8026913a 100644 --- a/test/concrete/parser/OrderBookSubParser.contextInputVaultBalanceIncrease.t.sol +++ b/test/concrete/parser/OrderBookSubParser.contextInputVaultBalanceIncrease.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookSubParserContextTest} from "test/util/abstract/OrderBookSubParserContextTest.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.contextInputVaultId.t.sol b/test/concrete/parser/OrderBookSubParser.contextInputVaultId.t.sol index d737dd91e..88a00f9df 100644 --- a/test/concrete/parser/OrderBookSubParser.contextInputVaultId.t.sol +++ b/test/concrete/parser/OrderBookSubParser.contextInputVaultId.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookSubParserContextTest} from "test/util/abstract/OrderBookSubParserContextTest.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.contextOrderBook.t.sol b/test/concrete/parser/OrderBookSubParser.contextOrderBook.t.sol index 62f76b043..73e0d9cdc 100644 --- a/test/concrete/parser/OrderBookSubParser.contextOrderBook.t.sol +++ b/test/concrete/parser/OrderBookSubParser.contextOrderBook.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookSubParserContextTest} from "test/util/abstract/OrderBookSubParserContextTest.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.contextOrderClearer.t.sol b/test/concrete/parser/OrderBookSubParser.contextOrderClearer.t.sol index 452f3fcb1..e488a967f 100644 --- a/test/concrete/parser/OrderBookSubParser.contextOrderClearer.t.sol +++ b/test/concrete/parser/OrderBookSubParser.contextOrderClearer.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookSubParserContextTest} from "test/util/abstract/OrderBookSubParserContextTest.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.contextOrderCounterparty.t.sol b/test/concrete/parser/OrderBookSubParser.contextOrderCounterparty.t.sol index fdc8bb663..3d596177c 100644 --- a/test/concrete/parser/OrderBookSubParser.contextOrderCounterparty.t.sol +++ b/test/concrete/parser/OrderBookSubParser.contextOrderCounterparty.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookSubParserContextTest} from "test/util/abstract/OrderBookSubParserContextTest.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.contextOrderHash.t.sol b/test/concrete/parser/OrderBookSubParser.contextOrderHash.t.sol index dd6b2d955..791ce726d 100644 --- a/test/concrete/parser/OrderBookSubParser.contextOrderHash.t.sol +++ b/test/concrete/parser/OrderBookSubParser.contextOrderHash.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookSubParserContextTest} from "test/util/abstract/OrderBookSubParserContextTest.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.contextOrderOwner.t.sol b/test/concrete/parser/OrderBookSubParser.contextOrderOwner.t.sol index f9c8dca54..ad66c601e 100644 --- a/test/concrete/parser/OrderBookSubParser.contextOrderOwner.t.sol +++ b/test/concrete/parser/OrderBookSubParser.contextOrderOwner.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookSubParserContextTest} from "test/util/abstract/OrderBookSubParserContextTest.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.contextOutputToken.t.sol b/test/concrete/parser/OrderBookSubParser.contextOutputToken.t.sol index a389a4dfd..c5970ef60 100644 --- a/test/concrete/parser/OrderBookSubParser.contextOutputToken.t.sol +++ b/test/concrete/parser/OrderBookSubParser.contextOutputToken.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookSubParserContextTest} from "test/util/abstract/OrderBookSubParserContextTest.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.contextOutputTokenDecimals.t.sol b/test/concrete/parser/OrderBookSubParser.contextOutputTokenDecimals.t.sol index 72fc12c8a..6874cf6d8 100644 --- a/test/concrete/parser/OrderBookSubParser.contextOutputTokenDecimals.t.sol +++ b/test/concrete/parser/OrderBookSubParser.contextOutputTokenDecimals.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookSubParserContextTest} from "test/util/abstract/OrderBookSubParserContextTest.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.contextOutputVaultBalanceBefore.t.sol b/test/concrete/parser/OrderBookSubParser.contextOutputVaultBalanceBefore.t.sol index 56eb36701..ec8fbeb2f 100644 --- a/test/concrete/parser/OrderBookSubParser.contextOutputVaultBalanceBefore.t.sol +++ b/test/concrete/parser/OrderBookSubParser.contextOutputVaultBalanceBefore.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookSubParserContextTest} from "test/util/abstract/OrderBookSubParserContextTest.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.contextOutputVaultBalanceDecrease.t.sol b/test/concrete/parser/OrderBookSubParser.contextOutputVaultBalanceDecrease.t.sol index 2726f82ec..538f996ae 100644 --- a/test/concrete/parser/OrderBookSubParser.contextOutputVaultBalanceDecrease.t.sol +++ b/test/concrete/parser/OrderBookSubParser.contextOutputVaultBalanceDecrease.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookSubParserContextTest} from "test/util/abstract/OrderBookSubParserContextTest.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.contextOutputVaultId.t.sol b/test/concrete/parser/OrderBookSubParser.contextOutputVaultId.t.sol index 66c7ad0be..8f26fe348 100644 --- a/test/concrete/parser/OrderBookSubParser.contextOutputVaultId.t.sol +++ b/test/concrete/parser/OrderBookSubParser.contextOutputVaultId.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {OrderBookSubParserContextTest} from "test/util/abstract/OrderBookSubParserContextTest.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.describedByMeta.t.sol b/test/concrete/parser/OrderBookSubParser.describedByMeta.t.sol index 3c4bec86a..8f2b7b52e 100644 --- a/test/concrete/parser/OrderBookSubParser.describedByMeta.t.sol +++ b/test/concrete/parser/OrderBookSubParser.describedByMeta.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.ierc165.t.sol b/test/concrete/parser/OrderBookSubParser.ierc165.t.sol index bf11ca3d9..33587667f 100644 --- a/test/concrete/parser/OrderBookSubParser.ierc165.t.sol +++ b/test/concrete/parser/OrderBookSubParser.ierc165.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.pointers.t.sol b/test/concrete/parser/OrderBookSubParser.pointers.t.sol index e2da1fe80..84d1ce8ed 100644 --- a/test/concrete/parser/OrderBookSubParser.pointers.t.sol +++ b/test/concrete/parser/OrderBookSubParser.pointers.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.signedContext.t.sol b/test/concrete/parser/OrderBookSubParser.signedContext.t.sol index 3e37ab35f..8acba9759 100644 --- a/test/concrete/parser/OrderBookSubParser.signedContext.t.sol +++ b/test/concrete/parser/OrderBookSubParser.signedContext.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {StackAllocationMismatch} from "rain.interpreter/error/ErrIntegrity.sol"; diff --git a/test/concrete/parser/OrderBookSubParser.signers.t.sol b/test/concrete/parser/OrderBookSubParser.signers.t.sol index 9630775a4..b81fb96a9 100644 --- a/test/concrete/parser/OrderBookSubParser.signers.t.sol +++ b/test/concrete/parser/OrderBookSubParser.signers.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {StackAllocationMismatch} from "rain.interpreter/error/ErrIntegrity.sol"; diff --git a/test/lib/LibOrder.t.sol b/test/lib/LibOrder.t.sol index f0a06394a..9c0c1a9dd 100644 --- a/test/lib/LibOrder.t.sol +++ b/test/lib/LibOrder.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; diff --git a/test/util/abstract/ArbTest.sol b/test/util/abstract/ArbTest.sol index 7201d9016..89502c0ae 100644 --- a/test/util/abstract/ArbTest.sol +++ b/test/util/abstract/ArbTest.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; diff --git a/test/util/abstract/GenericPoolOrderBookV4ArbOrderTakerTest.sol b/test/util/abstract/GenericPoolOrderBookV4ArbOrderTakerTest.sol index 636d18308..a708708cf 100644 --- a/test/util/abstract/GenericPoolOrderBookV4ArbOrderTakerTest.sol +++ b/test/util/abstract/GenericPoolOrderBookV4ArbOrderTakerTest.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {ArbTest} from "./ArbTest.sol"; diff --git a/test/util/abstract/IOrderBookV4Stub.sol b/test/util/abstract/IOrderBookV4Stub.sol index 5112f3829..abcaaeb8a 100644 --- a/test/util/abstract/IOrderBookV4Stub.sol +++ b/test/util/abstract/IOrderBookV4Stub.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import { diff --git a/test/util/abstract/OrderBookExternalMockTest.sol b/test/util/abstract/OrderBookExternalMockTest.sol index 0445a760a..ecb986110 100644 --- a/test/util/abstract/OrderBookExternalMockTest.sol +++ b/test/util/abstract/OrderBookExternalMockTest.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; diff --git a/test/util/abstract/OrderBookExternalRealTest.sol b/test/util/abstract/OrderBookExternalRealTest.sol index b834e821d..7bf4c8a17 100644 --- a/test/util/abstract/OrderBookExternalRealTest.sol +++ b/test/util/abstract/OrderBookExternalRealTest.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Test, Vm, console2} from "forge-std/Test.sol"; diff --git a/test/util/abstract/OrderBookSelfTest.sol b/test/util/abstract/OrderBookSelfTest.sol index 3c802718f..198da0da3 100644 --- a/test/util/abstract/OrderBookSelfTest.sol +++ b/test/util/abstract/OrderBookSelfTest.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; diff --git a/test/util/abstract/OrderBookSubParserContextTest.sol b/test/util/abstract/OrderBookSubParserContextTest.sol index 7e9b037da..e077a048f 100644 --- a/test/util/abstract/OrderBookSubParserContextTest.sol +++ b/test/util/abstract/OrderBookSubParserContextTest.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {StackAllocationMismatch} from "rain.interpreter/error/ErrIntegrity.sol"; diff --git a/test/util/abstract/RouteProcessorOrderBookV4ArbOrderTakerTest.sol b/test/util/abstract/RouteProcessorOrderBookV4ArbOrderTakerTest.sol index eaff00f01..b606aeafa 100644 --- a/test/util/abstract/RouteProcessorOrderBookV4ArbOrderTakerTest.sol +++ b/test/util/abstract/RouteProcessorOrderBookV4ArbOrderTakerTest.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {ArbTest} from "./ArbTest.sol"; diff --git a/test/util/concrete/ChildOrderBookV4ArbOrderTaker.sol b/test/util/concrete/ChildOrderBookV4ArbOrderTaker.sol index 7107cfb47..daf4c1882 100644 --- a/test/util/concrete/ChildOrderBookV4ArbOrderTaker.sol +++ b/test/util/concrete/ChildOrderBookV4ArbOrderTaker.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import { diff --git a/test/util/concrete/FlashLendingMockOrderBook.sol b/test/util/concrete/FlashLendingMockOrderBook.sol index 6671a0add..fb8ff2758 100644 --- a/test/util/concrete/FlashLendingMockOrderBook.sol +++ b/test/util/concrete/FlashLendingMockOrderBook.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import { diff --git a/test/util/concrete/Reenteroor.sol b/test/util/concrete/Reenteroor.sol index f4bd38536..c12d1f1d4 100644 --- a/test/util/concrete/Reenteroor.sol +++ b/test/util/concrete/Reenteroor.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import {Address} from "openzeppelin-contracts/contracts/utils/Address.sol"; diff --git a/test/util/concrete/Refundoor.sol b/test/util/concrete/Refundoor.sol index d9087357b..66a7a195e 100644 --- a/test/util/concrete/Refundoor.sol +++ b/test/util/concrete/Refundoor.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import "openzeppelin-contracts/contracts/utils/Address.sol"; diff --git a/test/util/fixture/LibOrderBookSubParserContextFixture.sol b/test/util/fixture/LibOrderBookSubParserContextFixture.sol index a19c1b7c1..abac622a5 100644 --- a/test/util/fixture/LibOrderBookSubParserContextFixture.sol +++ b/test/util/fixture/LibOrderBookSubParserContextFixture.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; import { diff --git a/test/util/lib/LibTestAddOrder.sol b/test/util/lib/LibTestAddOrder.sol index 5a4d20e46..696ff28c2 100644 --- a/test/util/lib/LibTestAddOrder.sol +++ b/test/util/lib/LibTestAddOrder.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.19; import {META_MAGIC_NUMBER_V1} from "rain.metadata/lib/LibMeta.sol"; diff --git a/test/util/lib/LibTestConstants.sol b/test/util/lib/LibTestConstants.sol index c08a8d4f9..391a49914 100644 --- a/test/util/lib/LibTestConstants.sol +++ b/test/util/lib/LibTestConstants.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.18; /// @dev Mocks need to be etched with some bytecode or they cannot even be