diff --git a/kalatori-ah/src/lib.rs b/kalatori-ah/src/lib.rs index 6ad0b26..f50b9b0 100644 --- a/kalatori-ah/src/lib.rs +++ b/kalatori-ah/src/lib.rs @@ -2,7 +2,7 @@ use anyhow::{Context, Error, Result}; use database::Database; use env_logger::{Builder, Env}; use environment_variables::{ - DATABASE, DECIMALS, DESTINATION, HOST, IN_MEMORY_DB, LOG, LOG_STYLE, OVERRIDE_RPC, RPC, SEED, + DATABASE, DESTINATION, HOST, IN_MEMORY_DB, LOG, LOG_STYLE, OVERRIDE_RPC, RPC, SEED, }; use log::LevelFilter; use rpc::Processor; @@ -41,7 +41,6 @@ pub mod environment_variables { pub const RPC: &str = "KALATORI_RPC"; pub const OVERRIDE_RPC: &str = "KALATORI_OVERRIDE_RPC"; pub const IN_MEMORY_DB: &str = "KALATORI_IN_MEMORY_DB"; - pub const DECIMALS: &str = "KALATORI_DECIMALS"; pub const DESTINATION: &str = "KALATORI_DESTINATION"; } @@ -190,11 +189,6 @@ pub async fn main() -> Result<()> { None }; - let decimals = env::var(DECIMALS) - .with_context(|| format!("`{DECIMALS}` isn't set"))? - .parse() - .with_context(|| format!("failed to convert `{DECIMALS}` to decimals"))?; - let destination = match env::var(DESTINATION) { Ok(destination) => Ok(Some( AccountId32::try_from(hex::decode(&destination[2..])?.as_ref()) @@ -214,7 +208,7 @@ pub async fn main() -> Result<()> { let (error_tx, mut error_rx) = mpsc::unbounded_channel(); let (api_config, endpoint_properties, updater) = - rpc::prepare(endpoint, decimals, shutdown_notification.clone()) + rpc::prepare(endpoint, shutdown_notification.clone()) .await .context("failed to prepare the node module")?; diff --git a/kalatori-ah/src/rpc.rs b/kalatori-ah/src/rpc.rs index fe37ae1..84fafa3 100644 --- a/kalatori-ah/src/rpc.rs +++ b/kalatori-ah/src/rpc.rs @@ -117,6 +117,29 @@ async fn fetch_metadata(backend: &impl Backend, at: Hash) -> Resu .map_err(Into::into) } +async fn fetch_decimals(storage: Storage) -> Result { + const METADATA: &str = "Metadata"; + const DECIMALS: &str = "decimals"; + + let asset_metadata = storage + .fetch(&dynamic::storage(ASSETS, METADATA, vec![USDT_ID])) + .await + .context("failed to fetch asset info from the chain")? + .context("received nothing after fetching asset info from the chain")? + .to_value() + .context("failed to decode account info")?; + let encoded_decimals = asset_metadata + .at(DECIMALS) + .with_context(|| format!("{DECIMALS} field wasn't found in asset info"))?; + + encoded_decimals + .as_u128() + .map(|num| num.try_into().expect("must be less than u64")) + .with_context(|| { + format!("expected `u128` as the type of the min balance, got {encoded_decimals}") + }) +} + fn fetch_constant( constants: &ConstantsClient, constant: (&str, &str), @@ -174,7 +197,6 @@ impl CheckedUrl { pub async fn prepare( url: String, - decimals: Decimals, shutdown_notification: CancellationToken, ) -> Result<(ApiConfig, EndpointProperties, Updater)> { // TODO: @@ -214,6 +236,7 @@ pub async fn prepare( .await?, ) .await?; + let decimals = fetch_decimals(api.storage().at_latest().await?).await?; let properties = ChainProperties::fetch_only_constants(min_balance, decimals, &constants)?; log::info!( @@ -584,6 +607,8 @@ impl ProcessorFinalized { const UPDATE: &str = "CodeUpdated"; const TRANSFERRED: &str = "Transferred"; const ASSET_MIN_BALANCE_CHANGED: &str = "AssetMinBalanceChanged"; + const METADATA_SET: &str = "MetadataSet"; + let event = event_result.context("failed to decode an event")?; let metadata = event.event_metadata(); @@ -603,6 +628,15 @@ impl ProcessorFinalized { props.existential_deposit = new_min_balance; } + (ASSETS, METADATA_SET) => { + let new_decimals = + fetch_decimals(self.client.storage().at_latest().await?).await?; + let props = self.database.properties_write().await; + + if props.decimals != new_decimals { + anyhow::bail!("decimals have been changed: {new_decimals}"); + } + } _ => {} } }