From b95f6a0fb41d1a0bd53bc96672c4afc6c6e9a271 Mon Sep 17 00:00:00 2001 From: David Craven Date: Mon, 3 Feb 2025 16:55:42 +0100 Subject: [PATCH] Add command to deploy chronicle. (#1475) --- .gitignore | 3 -- config/envs/development/config.yaml | 4 --- config/envs/development/prices.csv | 7 +++++ config/envs/integration/config.yaml | 4 --- config/envs/integration/prices.csv | 3 ++ config/envs/local/local-evm.yaml | 4 --- tc-cli/src/bin/slack_bot.rs | 42 ++++++++++++++++++------- tc-cli/src/config.rs | 49 ++++++++++++++++++++++------- tc-cli/src/gas_price_calculator.rs | 24 ++++++++------ tc-cli/src/main.rs | 6 ++++ 10 files changed, 98 insertions(+), 48 deletions(-) create mode 100644 config/envs/development/prices.csv create mode 100644 config/envs/integration/prices.csv diff --git a/.gitignore b/.gitignore index 341b3e499..a125bc365 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,3 @@ runtime/target/srtool # secrets .env gcp-key.json - -#Temp files -prices.csv diff --git a/config/envs/development/config.yaml b/config/envs/development/config.yaml index 971d6dfb5..d8badf9a3 100644 --- a/config/envs/development/config.yaml +++ b/config/envs/development/config.yaml @@ -89,8 +89,6 @@ networks: batch_gas_limit: 10000 gmp_margin: 0.0 shard_task_limit: 50 - symbol: "ETH" - token_decimals: 18 route_gas_limit: 10000000 route_base_fee: 1400000000 shard_size: 1 @@ -108,8 +106,6 @@ networks: batch_gas_limit: 10000 gmp_margin: 0.0 shard_task_limit: 50 - symbol: "SBY" - token_decimals: 18 route_gas_limit: 10000000 route_base_fee: 1400000000 shard_size: 1 diff --git a/config/envs/development/prices.csv b/config/envs/development/prices.csv new file mode 100644 index 000000000..b2b9fd30f --- /dev/null +++ b/config/envs/development/prices.csv @@ -0,0 +1,7 @@ +network_id,symbol,usd_price +0,TT,0.0032616625404162376 +1,TT,0.0032616625404162376 +2,TT,0.0032616625404162376 +3,TT,0.0032616625404162376 +4,ETH,0.0032616625404162376 +5,ASTR,0.0032616625404162376 diff --git a/config/envs/integration/config.yaml b/config/envs/integration/config.yaml index 52b9034e7..42daabb9d 100644 --- a/config/envs/integration/config.yaml +++ b/config/envs/integration/config.yaml @@ -21,8 +21,6 @@ networks: batch_gas_limit: 10000 gmp_margin: 0.0 shard_task_limit: 50 - symbol: "ETH" - token_decimals: 18 route_gas_limit: 10000000 route_base_fee: 1400000000 shard_size: 3 @@ -39,8 +37,6 @@ networks: batch_gas_limit: 10000 gmp_margin: 0.0 shard_task_limit: 50 - symbol: "SBY" - token_decimals: 18 route_gas_limit: 10000000 route_base_fee: 1400000000 shard_size: 3 diff --git a/config/envs/integration/prices.csv b/config/envs/integration/prices.csv new file mode 100644 index 000000000..9459f2b65 --- /dev/null +++ b/config/envs/integration/prices.csv @@ -0,0 +1,3 @@ +network_id,symbol,usd_price +10,ETH,0.003683198722878368 +11,ASTR,0.003683198722878368 diff --git a/config/envs/local/local-evm.yaml b/config/envs/local/local-evm.yaml index 4cbb3a02c..53428c76a 100644 --- a/config/envs/local/local-evm.yaml +++ b/config/envs/local/local-evm.yaml @@ -21,8 +21,6 @@ networks: batch_gas_limit: 10000000 gmp_margin: 0.0 shard_task_limit: 50 - symbol: "ETH" - token_decimals: 18 route_gas_limit: 10000000 route_base_fee: 1400000000 shard_size: 1 @@ -39,8 +37,6 @@ networks: batch_gas_limit: 10000000 gmp_margin: 0.0 shard_task_limit: 50 - symbol: "ETH" - token_decimals: 18 route_gas_limit: 10000000 route_base_fee: 1400000000 shard_size: 1 diff --git a/tc-cli/src/bin/slack_bot.rs b/tc-cli/src/bin/slack_bot.rs index 7cc6cc6e1..1b025541b 100644 --- a/tc-cli/src/bin/slack_bot.rs +++ b/tc-cli/src/bin/slack_bot.rs @@ -11,7 +11,7 @@ use tokio::net::TcpListener; #[derive(Clone, Debug, Eq, PartialEq)] enum Command { TcCli { tag: String, args: String }, - RuntimeUpgrade { branch: String }, + RuntimeUpgrade, DeployChronicles { tag: String }, } @@ -19,7 +19,7 @@ impl std::fmt::Display for Command { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { Self::TcCli { tag, args } => write!(f, "/tc-cli tag={tag} {args}"), - Self::RuntimeUpgrade { branch } => write!(f, "/runtime-upgrade branch={branch}"), + Self::RuntimeUpgrade => write!(f, "/runtime-upgrade"), Self::DeployChronicles { tag } => write!(f, "/deploy-chronicles tag={tag}"), } } @@ -44,21 +44,30 @@ impl Command { fn inputs(&self, env: Env) -> serde_json::Value { match self { Self::TcCli { tag, args } => { - json!({ "version": tag, "args": args, "environment": env.to_string() }) + json!({ + "environment": env.to_string(), + "version": tag, + "args": args, + }) }, - Self::RuntimeUpgrade { branch } => { - json!({ "branch": branch, "environment": env.to_string() }) + Self::RuntimeUpgrade => { + json!({ + "environment": env.to_string(), + }) }, Self::DeployChronicles { tag } => { - json!({ "version": tag, "environment": env.to_string() }) + json!({ + "environment": env.to_string(), + "version": tag, + }) }, } } - fn json(&self, env: Env) -> serde_json::Value { + fn json(&self, branch: &str, env: Env) -> serde_json::Value { let inputs = self.inputs(env); serde_json::json!({ - "ref": "development", + "ref": branch, "inputs": inputs, }) } @@ -67,12 +76,18 @@ impl Command { #[derive(Clone, Copy, Debug, Eq, PartialEq)] enum Env { Development, + Integration, + Testnet, + Mainnet, } impl std::fmt::Display for Env { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { Self::Development => write!(f, "development"), + Self::Integration => write!(f, "integration"), + Self::Testnet => write!(f, "testnet"), + Self::Mainnet => write!(f, "mainnet"), } } } @@ -92,12 +107,12 @@ impl GithubState { Ok(Self { client, token, user_agent }) } - async fn trigger_workflow(&self, command: &Command, env: Env) -> Result<()> { + async fn trigger_workflow(&self, command: &Command, branch: &str, env: Env) -> Result<()> { tracing::info!("triggering {command} in {env}"); let request = self .client .post(command.url()) - .json(&command.json(env)) + .json(&command.json(branch, env)) .bearer_auth(&self.token) .header("Accept", "application/vnd.github+json") .header("X-Github-Api-Version", "2022-11-28") @@ -136,7 +151,7 @@ async fn command_event( .join(" "); let command = match event.command.0.as_str() { "/tc-cli" => Command::TcCli { tag: tag.into(), args }, - "/runtime-upgrade" => Command::RuntimeUpgrade { branch: branch.into() }, + "/runtime-upgrade" => Command::RuntimeUpgrade, "/deploy-chronicles" => Command::DeployChronicles { tag: tag.into() }, _ => { return slack_error(format!("unknown command {}", &event.command.0)); @@ -144,11 +159,14 @@ async fn command_event( }; let env = match event.channel_id.0.as_str() { "C08A621SKRR" => Env::Development, + "C08BK21RPHA" => Env::Integration, + "C08B20E4NEB" => Env::Testnet, + "C08BV777PG9" => Env::Mainnet, _ => { return slack_error(format!("unknown channel {}", &event.channel_id.0)); }, }; - if let Err(err) = gh.trigger_workflow(&command, env).await { + if let Err(err) = gh.trigger_workflow(&command, branch, env).await { return slack_error(format!("triggering workflow failed: {err}")); } axum::Json( diff --git a/tc-cli/src/config.rs b/tc-cli/src/config.rs index f800b98cb..55f923db0 100644 --- a/tc-cli/src/config.rs +++ b/tc-cli/src/config.rs @@ -13,14 +13,11 @@ pub struct Config { impl Config { pub fn from_env(path: PathBuf, config: &str) -> Result { - let config = if let Ok(config) = std::env::var("CONFIG") { - config - } else { - let config = path.join(config); - std::fs::read_to_string(&config) - .with_context(|| format!("failed to read config file {}", config.display()))? - }; - let yaml = serde_yaml::from_str(&config).context("failed to parse config file")?; + let config_path = path.join(config); + let config = std::fs::read_to_string(&config_path) + .with_context(|| format!("failed to read config file {}", config_path.display()))?; + let yaml = serde_yaml::from_str(&config) + .with_context(|| format!("failed to parse config file {}", config_path.display()))?; Ok(Self { path, yaml }) } @@ -87,6 +84,7 @@ impl Config { } #[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] struct ConfigYaml { config: GlobalConfig, contracts: HashMap, @@ -95,6 +93,7 @@ struct ConfigYaml { } #[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] pub struct GlobalConfig { prices_path: PathBuf, pub chronicle_timechain_funds: String, @@ -102,6 +101,7 @@ pub struct GlobalConfig { } #[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] struct ContractsConfig { additional_params: PathBuf, proxy: PathBuf, @@ -118,6 +118,7 @@ pub struct Contracts { } #[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] pub struct NetworkConfig { pub backend: Backend, pub blockchain: String, @@ -139,11 +140,37 @@ pub struct NetworkConfig { #[cfg(test)] mod tests { use super::*; + use std::collections::HashSet; #[test] - fn make_sure_envs_parse() { + fn make_sure_envs_parse() -> Result<()> { let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../config/envs"); - Config::from_env(root.join("local"), "local-grpc.yaml").unwrap(); - Config::from_env(root.join("development"), "config.yaml").unwrap(); + let envs = std::fs::read_dir(&root)?; + for env in envs { + let env_dir = env?; + if !env_dir.file_type()?.is_dir() { + continue; + } + let mut networks = HashSet::new(); + let mut prices = HashSet::new(); + for config in std::fs::read_dir(env_dir.path())? { + let config = config?; + if !config.file_type()?.is_file() { + continue; + } + let config = config.file_name().into_string().unwrap(); + if !config.ends_with(".yaml") { + continue; + } + let config = Config::from_env(env_dir.path(), &config).unwrap(); + networks.extend(config.networks().keys().copied()); + let prices_path = config.prices(); + let prices_csv = + crate::gas_price_calculator::read_csv_token_prices(&prices_path).unwrap(); + prices.extend(prices_csv.keys().copied()); + } + assert_eq!(prices, networks, "{}", env_dir.path().display()); + } + Ok(()) } } diff --git a/tc-cli/src/gas_price_calculator.rs b/tc-cli/src/gas_price_calculator.rs index 5af47b4a6..69af579a9 100644 --- a/tc-cli/src/gas_price_calculator.rs +++ b/tc-cli/src/gas_price_calculator.rs @@ -11,6 +11,7 @@ use reqwest::header::{HeaderMap, HeaderValue}; use serde::Deserialize; use std::collections::HashMap; use std::fs::File; +use std::path::Path; use time_primitives::NetworkId; #[derive(Clone, Deserialize)] @@ -130,6 +131,18 @@ pub fn convert_bigint_to_u128(value: &BigUint) -> Result { .ok_or_else(|| anyhow::anyhow!("Could not convert bigint to u128")) } +pub fn read_csv_token_prices(price_path: &Path) -> Result> { + let mut rdr = Reader::from_path(price_path) + .with_context(|| format!("failed to open {}", price_path.display()))?; + + let mut network_map: HashMap = HashMap::new(); + for result in rdr.deserialize() { + let record: NetworkPrice = result?; + network_map.insert(record.network_id, (record.symbol, record.usd_price)); + } + Ok(network_map) +} + impl Tc { pub async fn fetch_token_prices(&self) -> Result<()> { let env = CoinMarketCap::from_env()?; @@ -170,16 +183,7 @@ impl Tc { } pub fn read_csv_token_prices(&self) -> Result> { - let price_path = self.config.prices(); - let mut rdr = Reader::from_path(&price_path) - .with_context(|| format!("failed to open {}", price_path.display()))?; - - let mut network_map: HashMap = HashMap::new(); - for result in rdr.deserialize() { - let record: NetworkPrice = result?; - network_map.insert(record.network_id, (record.symbol, record.usd_price)); - } - Ok(network_map) + read_csv_token_prices(&self.config.prices()) } pub fn calculate_relative_price( diff --git a/tc-cli/src/main.rs b/tc-cli/src/main.rs index c58dec226..00daccb48 100644 --- a/tc-cli/src/main.rs +++ b/tc-cli/src/main.rs @@ -116,6 +116,9 @@ enum Command { path: PathBuf, }, Deploy, + DeployChronicle { + url: String, + }, UnregisterMember { member: String, }, @@ -292,6 +295,9 @@ async fn real_main() -> Result<()> { Command::Deploy => { tc.deploy().await?; }, + Command::DeployChronicle { url } => { + tc.deploy_chronicle(&url).await?; + }, Command::UnregisterMember { member } => { let member = tc.parse_address(None, &member)?; tc.unregister_member(member.into()).await?;