use bon::{bon, Builder}; use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, Serialize, Deserialize, Builder)] #[serde(rename_all = "camelCase")] pub struct Bip44Config { pub coin_type: u32, } // NOTE: Are `public` variants used? #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Bech32Config { #[serde(rename = "bech32PrefixAccAddress")] pub account_address_prefix: String, #[serde(rename = "bech32PrefixAccPub")] pub account_address_public_prefix: String, #[serde(rename = "bech32PrefixValOper")] pub validator_operator_prefix: String, #[serde(rename = "bech32PrefixValPub")] pub validator_operator_public_prefix: String, #[serde(rename = "bech32PrefixConsAddr")] pub consensus_node_prefix: String, #[serde(rename = "bech32PrefixConsPub")] pub consensus_node_public_prefix: String, } #[bon] impl Bech32Config { #[builder] fn new( account_address_prefix: &'static str, account_address_public_prefix: &'static str, validator_operator_prefix: &'static str, validator_operator_public_prefix: &'static str, consensus_node_prefix: &'static str, consensus_node_public_prefix: &'static str, ) -> Self { Self { account_address_prefix: account_address_prefix.to_string(), account_address_public_prefix: account_address_public_prefix.to_string(), validator_operator_prefix: validator_operator_prefix.to_string(), validator_operator_public_prefix: validator_operator_public_prefix.to_string(), consensus_node_prefix: consensus_node_prefix.to_string(), consensus_node_public_prefix: consensus_node_public_prefix.to_string(), } } fn with_similar_prefix(prefix: &'static str) -> Self { Self { account_address_prefix: format!("{prefix}"), account_address_public_prefix: format!("{prefix}pub"), validator_operator_prefix: format!("{prefix}valoper"), validator_operator_public_prefix: format!("{prefix}valoperpub"), consensus_node_prefix: format!("{prefix}valcons"), consensus_node_public_prefix: format!("{prefix}valconspub"), } } } #[derive(Clone, Debug, Serialize, Deserialize, Builder)] pub struct GasPriceStep { pub low: f64, pub average: f64, pub high: f64, } #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Currency { pub coin_denom: String, pub coin_minimal_denom: String, pub coin_decimals: u8, pub coin_gecko_id: String, } #[bon] impl Currency { #[builder] fn new( coin_denom: &'static str, coin_minimal_denom: &'static str, coin_decimals: u8, coin_gecko_id: &'static str, ) -> Self { Self { coin_denom: coin_denom.to_string(), coin_minimal_denom: coin_minimal_denom.to_string(), coin_decimals, coin_gecko_id: coin_gecko_id.to_string(), } } } #[derive(Clone, Debug, Serialize, Deserialize, Builder)] #[serde(rename_all = "camelCase")] pub struct CurrencyWithGas { #[serde(flatten)] pub currency: Currency, pub gas_price_step: GasPriceStep, } #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Blockchain { pub chain_name: String, pub chain_id: String, pub rpc_url: String, pub rest_url: String, pub explorer_url_format: String, #[serde(rename = "bip44")] pub bip44_config: Bip44Config, #[serde(rename = "bech32Config")] pub bech32_config: Bech32Config, pub currencies: Vec, pub fee_currencies: Vec, pub gas_price_step: GasPriceStep, pub stake_currency: Currency, } #[bon] impl Blockchain { #[builder] fn new( chain_id: &'static str, chain_name: &'static str, rpc_url: &'static str, rest_url: &'static str, explorer_url_format: &'static str, bip44_config: Bip44Config, bech32_config: Bech32Config, currencies: &[Currency], fee_currencies: &[CurrencyWithGas], gas_price_step: GasPriceStep, stake_currency: Currency, ) -> Self { Self { chain_id: chain_id.to_string(), chain_name: chain_name.to_string(), rpc_url: rpc_url.to_string(), rest_url: rest_url.to_string(), explorer_url_format: explorer_url_format.to_string(), bip44_config, bech32_config, currencies: currencies.to_vec(), fee_currencies: fee_currencies.to_vec(), gas_price_step, stake_currency, } } } fn seda_chains() -> Vec { let mut chains = vec![]; let aseda = Currency::builder() .coin_denom("seda") .coin_minimal_denom("aseda") .coin_decimals(18) .coin_gecko_id("ID") .build(); let aseda_gas = GasPriceStep::builder() .low(5000000000.) .average(10000000000.) .high(15000000000.) .build(); chains.push( Blockchain::builder() .chain_id("seda-1-devnet") // NOTE: Officially, this is just "devnet", but otherwise this would conflict. // We'll override it in our config. .chain_name("seda-devnet") .rpc_url("https://rpc.devnet.seda.xyz") .rest_url("https://lcd.devnet.seda.xyz") .explorer_url_format("https://devnet.explorer.seda.xyz/txs/%s") .bip44_config(Bip44Config::builder().coin_type(118).build()) .bech32_config(Bech32Config::with_similar_prefix("seda")) .currencies(&[aseda.clone()]) .fee_currencies(&[CurrencyWithGas::builder() .currency(aseda.clone()) .gas_price_step(aseda_gas.clone()).build()]) .gas_price_step(aseda_gas) .stake_currency(aseda) .build(), ); chains } fn kyve_chains() -> Vec { let mut chains = vec![]; let tkyve = Currency::builder() .coin_denom("KYVE") .coin_minimal_denom("tkyve") .coin_decimals(6) .coin_gecko_id("unknown") .build(); let tkyve_gas = GasPriceStep::builder() .low(0.01) .average(0.025) .high(0.03) .build(); chains.push( Blockchain::builder() .chain_id("korellia-2") .chain_name("korellia") .rpc_url("https://rpc.korellia.kyve.network") .rest_url("https://api.korellia.kyve.network") .explorer_url_format("https://explorer.kyve.network/korellia/tx/%s") .bip44_config(Bip44Config::builder().coin_type(118).build()) .bech32_config(Bech32Config::with_similar_prefix("kyve")) .currencies(&[tkyve.clone()]) .fee_currencies(&[CurrencyWithGas::builder() .currency(tkyve.clone()) .gas_price_step(tkyve_gas.clone()) .build()]) .gas_price_step(tkyve_gas.clone()) .stake_currency(tkyve.clone()) .build(), ); chains } pub fn default_chains() -> Vec { let mut chains = vec![]; chains.extend(kyve_chains()); chains.extend(seda_chains()); chains }