Skip to content

Commit

Permalink
Merge pull request #1165 from rainlanguage/2025-01-15-gui-constructor
Browse files Browse the repository at this point in the history
Refactor gui constructor and select tokens method
  • Loading branch information
findolor authored Jan 16, 2025
2 parents a7f3f38 + 546772c commit 64a27de
Show file tree
Hide file tree
Showing 12 changed files with 444 additions and 89 deletions.
96 changes: 44 additions & 52 deletions crates/js_api/src/gui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use alloy_ethers_typecast::transaction::ReadableClientError;
use base64::{engine::general_purpose::URL_SAFE, Engine};
use flate2::{read::GzDecoder, write::GzEncoder, Compression};
use rain_orderbook_app_settings::{
deployment::Deployment,
gui::{Gui, GuiDeployment, GuiFieldDefinition, GuiPreset, ParseGuiConfigSourceError},
network::Network,
order::Order,
yaml::YamlError,
};
use rain_orderbook_bindings::{impl_all_wasm_traits, wasm_traits::prelude::*};
Expand All @@ -23,8 +26,8 @@ mod select_tokens;
mod state_management;

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Tsify)]
pub struct AvailableDeployments(Vec<GuiDeployment>);
impl_all_wasm_traits!(AvailableDeployments);
pub struct DeploymentKeys(Vec<String>);
impl_all_wasm_traits!(DeploymentKeys);

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Tsify)]
pub struct TokenInfo {
Expand Down Expand Up @@ -52,18 +55,11 @@ pub struct DotrainOrderGui {
}
#[wasm_bindgen]
impl DotrainOrderGui {
#[wasm_bindgen(js_name = "getAvailableDeployments")]
pub async fn get_available_deployments(
dotrain: String,
) -> Result<AvailableDeployments, GuiError> {
#[wasm_bindgen(js_name = "getDeploymentKeys")]
pub async fn get_deployment_keys(dotrain: String) -> Result<DeploymentKeys, GuiError> {
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")]
Expand All @@ -73,11 +69,8 @@ impl DotrainOrderGui {
) -> Result<DotrainOrderGui, GuiError> {
let dotrain_order = DotrainOrder::new(dotrain, None).await?;

let gui = dotrain_order
.dotrain_yaml()
.get_gui()?
.ok_or(GuiError::GuiConfigNotFound)?;
if !gui.deployments.contains_key(&deployment_name) {
let keys = Gui::parse_deployment_keys(dotrain_order.dotrain_yaml().documents.clone())?;
if !keys.contains(&deployment_name) {
return Err(GuiError::DeploymentNotFound(deployment_name.clone()));
}

Expand Down Expand Up @@ -117,48 +110,47 @@ impl DotrainOrderGui {
/// Returns a [`TokenInfo`]
#[wasm_bindgen(js_name = "getTokenInfo")]
pub async fn get_token_info(&self, key: String) -> Result<TokenInfo, GuiError> {
let deployment = self.get_current_deployment()?;
let token = self.dotrain_order.orderbook_yaml().get_token(&key)?;

let token_info =
if token.decimals.is_some() && token.label.is_some() && token.symbol.is_some() {
TokenInfo {
address: token.address,
decimals: token.decimals.unwrap(),
name: token.label.unwrap(),
symbol: token.symbol.unwrap(),
}
} else {
let rpc_url = deployment
.deployment
.order
.orderbook
.clone()
.ok_or(GuiError::OrderbookNotFound)?
.network
.rpc
.clone();
let erc20 = ERC20::new(rpc_url, token.address);
let onchain_info = erc20.token_info(None).await?;

TokenInfo {
address: token.address,
decimals: token.decimals.unwrap_or(onchain_info.decimals),
name: token.label.unwrap_or(onchain_info.name),
symbol: token.symbol.unwrap_or(onchain_info.symbol),
}
};
let token_info = if token.decimals.is_some()
&& token.label.is_some()
&& token.symbol.is_some()
{
TokenInfo {
address: token.address,
decimals: token.decimals.unwrap(),
name: token.label.unwrap(),
symbol: token.symbol.unwrap(),
}
} else {
let order_key = Deployment::parse_order_key(
self.dotrain_order.dotrain_yaml().documents,
&self.selected_deployment,
)?;
let network_key =
Order::parse_network_key(self.dotrain_order.dotrain_yaml().documents, &order_key)?;
let rpc_url =
Network::parse_rpc(self.dotrain_order.dotrain_yaml().documents, &network_key)?;

let erc20 = ERC20::new(rpc_url, token.address);
let onchain_info = erc20.token_info(None).await?;

TokenInfo {
address: token.address,
decimals: token.decimals.unwrap_or(onchain_info.decimals),
name: token.label.unwrap_or(onchain_info.name),
symbol: token.symbol.unwrap_or(onchain_info.symbol),
}
};

Ok(token_info)
}

#[wasm_bindgen(js_name = "getGuiDetails")]
pub fn get_gui_details(&self) -> Result<GuiDetails, GuiError> {
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 })
}
}

Expand Down
69 changes: 44 additions & 25 deletions crates/js_api/src/gui/select_tokens.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
use super::*;
use rain_orderbook_app_settings::token::Token;
use rain_orderbook_app_settings::{
deployment::Deployment, network::Network, order::Order, token::Token,
};
use std::str::FromStr;

#[wasm_bindgen]
impl DotrainOrderGui {
#[wasm_bindgen(js_name = "getSelectTokens")]
pub fn get_select_tokens(&self) -> Result<Vec<String>, GuiError> {
let deployment = self.get_current_deployment()?;
Ok(deployment.select_tokens.unwrap_or(vec![]))
let select_tokens = Gui::parse_select_tokens(
self.dotrain_order.dotrain_yaml().documents,
&self.selected_deployment,
)?;
Ok(select_tokens.unwrap_or(vec![]))
}

#[wasm_bindgen(js_name = "isSelectTokenSet")]
Expand All @@ -17,9 +22,12 @@ impl DotrainOrderGui {

#[wasm_bindgen(js_name = "checkSelectTokens")]
pub fn check_select_tokens(&self) -> Result<(), GuiError> {
let deployment = self.get_current_deployment()?;
let select_tokens = Gui::parse_select_tokens(
self.dotrain_order.dotrain_yaml().documents,
&self.selected_deployment,
)?;

if let Some(select_tokens) = deployment.select_tokens {
if let Some(select_tokens) = select_tokens {
for key in select_tokens {
if self.dotrain_order.orderbook_yaml().get_token(&key).is_err() {
return Err(GuiError::TokenMustBeSelected(key.clone()));
Expand All @@ -36,33 +44,33 @@ impl DotrainOrderGui {
key: String,
address: String,
) -> Result<(), GuiError> {
let deployment = self.get_current_deployment()?;
if deployment.select_tokens.is_none() {
return Err(GuiError::SelectTokensNotSet);
}
let select_tokens = deployment.select_tokens.unwrap();
let select_tokens = Gui::parse_select_tokens(
self.dotrain_order.dotrain_yaml().documents,
&self.selected_deployment,
)?
.ok_or(GuiError::SelectTokensNotSet)?;
if !select_tokens.contains(&key) {
return Err(GuiError::TokenNotFound(key.clone()));
}

let address = Address::from_str(&address)?;

let rpc_url = deployment
.deployment
.order
.orderbook
.clone()
.ok_or(GuiError::OrderbookNotFound)?
.network
.rpc
.clone();
let order_key = Deployment::parse_order_key(
self.dotrain_order.dotrain_yaml().documents,
&self.selected_deployment,
)?;
let network_key =
Order::parse_network_key(self.dotrain_order.dotrain_yaml().documents, &order_key)?;
let rpc_url =
Network::parse_rpc(self.dotrain_order.dotrain_yaml().documents, &network_key)?;

let erc20 = ERC20::new(rpc_url.clone(), address);
let token_info = erc20.token_info(None).await?;

Token::add_record_to_yaml(
self.dotrain_order.orderbook_yaml().documents,
&key,
&deployment.deployment.scenario.deployer.network.key,
&network_key,
&address.to_string(),
Some(&token_info.decimals.to_string()),
Some(&token_info.name),
Expand All @@ -71,13 +79,24 @@ impl DotrainOrderGui {
Ok(())
}

#[wasm_bindgen(js_name = "replaceSelectToken")]
pub async fn replace_select_token(
&mut self,
key: String,
address: String,
) -> Result<(), GuiError> {
self.remove_select_token(key.clone())?;
self.save_select_token(key, address).await?;
Ok(())
}

#[wasm_bindgen(js_name = "removeSelectToken")]
pub fn remove_select_token(&mut self, key: String) -> Result<(), GuiError> {
let deployment = self.get_current_deployment()?;
if deployment.select_tokens.is_none() {
return Err(GuiError::SelectTokensNotSet);
}
let select_tokens = deployment.select_tokens.unwrap();
let select_tokens = Gui::parse_select_tokens(
self.dotrain_order.dotrain_yaml().documents,
&self.selected_deployment,
)?
.ok_or(GuiError::SelectTokensNotSet)?;
if !select_tokens.contains(&key) {
return Err(GuiError::TokenNotFound(key.clone()));
}
Expand Down
20 changes: 20 additions & 0 deletions crates/settings/src/deployer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,26 @@ impl Deployer {
pub fn validate_address(value: &str) -> Result<Address, ParseDeployerConfigSourceError> {
Address::from_str(value).map_err(ParseDeployerConfigSourceError::AddressParseError)
}

pub fn parse_network_key(
documents: Vec<Arc<RwLock<StrictYaml>>>,
deployer_key: &str,
) -> Result<String, YamlError> {
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")]
Expand Down
22 changes: 22 additions & 0 deletions crates/settings/src/deployment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,28 @@ pub struct Deployment {
#[cfg(target_family = "wasm")]
impl_all_wasm_traits!(Deployment);

impl Deployment {
pub fn parse_order_key(
documents: Vec<Arc<RwLock<StrictYaml>>>,
deployment_key: &str,
) -> Result<String, YamlError> {
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<Arc<RwLock<StrictYaml>>>,
Expand Down
Loading

0 comments on commit 64a27de

Please sign in to comment.