From a826767785a632823b6037d2207ca2b7e0ae5735 Mon Sep 17 00:00:00 2001 From: SkymanOne Date: Mon, 19 Sep 2022 16:16:35 +0100 Subject: [PATCH 01/20] denominated units for balances in events --- CHANGELOG.md | 1 + .../cargo-contract/src/cmd/extrinsics/call.rs | 2 +- .../src/cmd/extrinsics/events.rs | 79 +++++++++++++++---- .../src/cmd/extrinsics/instantiate.rs | 8 +- .../cargo-contract/src/cmd/extrinsics/mod.rs | 52 ++++++++++++ .../src/cmd/extrinsics/upload.rs | 2 +- 6 files changed, 123 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06ce54ba7..d7d0da895 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - `--output-json` support for `call`, `instantiate` and `upload` commands - [#722](https://github.com/paritytech/cargo-contract/pull/722) +- Denominated units for Balances ## [2.0.0-alpha.2] - 2022-09-02 diff --git a/crates/cargo-contract/src/cmd/extrinsics/call.rs b/crates/cargo-contract/src/cmd/extrinsics/call.rs index b64372dcd..6da7eabde 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/call.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/call.rs @@ -211,7 +211,7 @@ impl CallCommand { let output = if self.output_json { display_events.to_json()? } else { - display_events.display_events(self.extrinsic_opts.verbosity()?) + display_events.display_events(self.extrinsic_opts.verbosity()?, client).await? }; println!("{}", output); diff --git a/crates/cargo-contract/src/cmd/extrinsics/events.rs b/crates/cargo-contract/src/cmd/extrinsics/events.rs index 778ade469..8baa53c2e 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/events.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/events.rs @@ -15,7 +15,9 @@ // along with cargo-contract. If not, see . use super::{ + denominate_units, runtime_api::api::contracts::events::ContractEmitted, + Client, DefaultConfig, }; use crate::{ @@ -23,6 +25,7 @@ use crate::{ DEFAULT_KEY_COL_WIDTH, }; use colored::Colorize as _; +use serde_json::json; use transcode::{ ContractMessageTranscoder, TranscoderBuilder, @@ -30,6 +33,7 @@ use transcode::{ }; use anyhow::{ + Context, Ok, Result, }; @@ -47,11 +51,18 @@ pub struct Field { pub name: String, /// value of a field pub value: Value, + /// The name of a type as defined in the pallet Source Code + #[serde(skip_serializing)] + pub type_name: Option, } impl Field { - pub fn new(name: String, value: Value) -> Self { - Field { name, value } + pub fn new(name: String, value: Value, type_name: Option) -> Self { + Field { + name, + value, + type_name, + } } } @@ -100,29 +111,40 @@ impl DisplayEvents { let event_data = &mut event.field_bytes(); let mut unnamed_field_name = 0; - for (field, field_ty) in event_fields { + for field_metadata in event_fields { if ::is_event( event.pallet_name(), event.variant_name(), - ) && field.as_ref() == Some(&"data".to_string()) + ) && field_metadata.name() == Some("data") { tracing::debug!("event data: {:?}", hex::encode(&event_data)); let contract_event = transcoder.decode_contract_event(event_data)?; - let field = Field::new(String::from("data"), contract_event); + let field = Field::new( + String::from("data"), + contract_event, + field_metadata.type_name().map(|s| s.to_string()), + ); event_entry.fields.push(field); } else { - let field_name = field.clone().unwrap_or_else(|| { - let name = unnamed_field_name.to_string(); - unnamed_field_name += 1; - name - }); + let field_name = field_metadata + .name() + .map(|s| s.to_string()) + .unwrap_or_else(|| { + let name = unnamed_field_name.to_string(); + unnamed_field_name += 1; + name + }); let decoded_field = events_transcoder.decode( &runtime_metadata.types, - *field_ty, + field_metadata.type_id(), event_data, )?; - let field = Field::new(field_name, decoded_field); + let field = Field::new( + field_name, + decoded_field, + field_metadata.type_name().map(|s| s.to_string()), + ); event_entry.fields.push(field); } } @@ -133,7 +155,26 @@ impl DisplayEvents { } /// Displays events in a human readable format - pub fn display_events(&self, verbosity: Verbosity) -> String { + pub async fn display_events( + &self, + verbosity: Verbosity, + client: &Client, + ) -> Result { + let sys_props = client.rpc().system_properties().await?; + + let default_decimals = json!(12); + let default_units = json!("UNIT"); + let decimals = sys_props + .get("tokenDecimals") + .unwrap_or(&default_decimals) + .as_u64() + .context("error converting decimal to u64")?; + let symbol = sys_props + .get("tokenSymbol") + .unwrap_or(&default_units) + .as_str() + .context("error converting symbol to string")?; + let event_field_indent: usize = DEFAULT_KEY_COL_WIDTH - 3; let mut out = format!( "{:>width$}\n", @@ -152,18 +193,26 @@ impl DisplayEvents { for field in &event.fields { if verbosity.is_verbose() { + let mut value: String = field.value.to_string(); + if field.type_name == Some("T::Balance".to_string()) + || field.type_name == Some("BalanceOf".to_string()) + { + if let Value::UInt(balance) = field.value { + value = denominate_units(balance, decimals as u128, symbol); + } + } let _ = writeln!( out, "{:width$}{}: {}", "", field.name.bright_white(), - field.value, + value, width = event_field_indent, ); } } } - out + Ok(out) } /// Returns an event result in json format diff --git a/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs b/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs index 26c97878c..aa9c68fb1 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs @@ -300,7 +300,7 @@ impl Exec { .find_first::()? .ok_or_else(|| anyhow!("Failed to find Instantiated event"))?; - self.display_result(&result, code_hash, instantiated.contract) + self.display_result(&result, code_hash, instantiated.contract).await } async fn instantiate(&self, code_hash: CodeHash) -> Result<(), ErrorVariant> { @@ -334,10 +334,10 @@ impl Exec { .find_first::()? .ok_or_else(|| anyhow!("Failed to find Instantiated event"))?; - self.display_result(&result, None, instantiated.contract) + self.display_result(&result, None, instantiated.contract).await } - fn display_result( + async fn display_result( &self, result: &TxEvents, code_hash: Option, @@ -362,7 +362,7 @@ impl Exec { name_value_println!("Code hash", format!("{:?}", code_hash)); } name_value_println!("Contract", contract_address); - println!("{}", events.display_events(self.verbosity)) + println!("{}", events.display_events(self.verbosity, &self.client).await?) }; Ok(()) } diff --git a/crates/cargo-contract/src/cmd/extrinsics/mod.rs b/crates/cargo-contract/src/cmd/extrinsics/mod.rs index 7b4fb264b..2401d04ca 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/mod.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/mod.rs @@ -278,3 +278,55 @@ fn print_gas_required_success(gas: u64) { width = DEFAULT_KEY_COL_WIDTH ); } + +fn denominate_units>(value: T, decimals: u128, symbol: &str) -> String { + let n: u128 = value.into(); + + if n == 0 { + return format!("0 {}", symbol) + } + + let units = n / decimals; + if (1..1_000).contains(&units) { + let remainder = n % decimals; + if remainder > 0 { + let remainder = remainder.to_string().trim_end_matches('0').to_owned(); + format!("{}.{} {}", units, remainder, symbol) + } else { + format!("0 {}", symbol) + } + } else if (1_000..1_000_000).contains(&units) { + let remainder = units % 1_000; + let units = units / 1_000; + if remainder > 0 { + let remainder = remainder.to_string().trim_end_matches('0').to_owned(); + format!("{}.{} k{}", units, remainder, symbol) + } else { + format!("{} k{}", units, symbol) + } + } else if (1_000_000..1_000_000_000).contains(&units) { + let remainder = units % 1_000_000; + let units = units / 1_000_000; + if remainder > 0 { + let remainder = remainder.to_string().trim_end_matches('0').to_owned(); + format!("{}.{} M{}", units, remainder, symbol) + } else { + format!("{} M{}", units, symbol) + } + } else if n / 1_000_000_000 > 0 { + let remainder = n % 1_000_000_000; + let remainder = remainder.to_string().trim_end_matches('0').to_owned(); + let units = n / 1_000_000_000; + format!("{}.{} n{}", units, remainder, symbol) + } else if n / 1_000_000 > 0 { + let remainder = n % 1_000_000; + let remainder = remainder.to_string().trim_end_matches('0').to_owned(); + let units = n / 1_000_000; + format!("{}.{} μ{}", units, remainder, symbol) + } else { + let remainder = n % 1_000; + let remainder = remainder.to_string().trim_end_matches('0').to_owned(); + let units = n / 1_000; + format!("{}.{} m{}", units, remainder, symbol) + } +} diff --git a/crates/cargo-contract/src/cmd/extrinsics/upload.rs b/crates/cargo-contract/src/cmd/extrinsics/upload.rs index ee746198d..ab734f51c 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/upload.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/upload.rs @@ -164,7 +164,7 @@ impl UploadCommand { let output = if self.output_json { display_events.to_json()? } else { - display_events.display_events(self.extrinsic_opts.verbosity()?) + display_events.display_events(self.extrinsic_opts.verbosity()?, client).await? }; println!("{}", output); let code_stored = result.find_first::()?; From ae983f257095bb6ce8bf4f88241feeb9c61a10de Mon Sep 17 00:00:00 2001 From: SkymanOne Date: Mon, 19 Sep 2022 16:18:08 +0100 Subject: [PATCH 02/20] fmt and changelog --- crates/cargo-contract/src/cmd/extrinsics/call.rs | 4 +++- .../cargo-contract/src/cmd/extrinsics/instantiate.rs | 11 ++++++++--- crates/cargo-contract/src/cmd/extrinsics/upload.rs | 4 +++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/crates/cargo-contract/src/cmd/extrinsics/call.rs b/crates/cargo-contract/src/cmd/extrinsics/call.rs index 6da7eabde..c77fe6b8e 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/call.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/call.rs @@ -211,7 +211,9 @@ impl CallCommand { let output = if self.output_json { display_events.to_json()? } else { - display_events.display_events(self.extrinsic_opts.verbosity()?, client).await? + display_events + .display_events(self.extrinsic_opts.verbosity()?, client) + .await? }; println!("{}", output); diff --git a/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs b/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs index aa9c68fb1..c7cb2dace 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs @@ -300,7 +300,8 @@ impl Exec { .find_first::()? .ok_or_else(|| anyhow!("Failed to find Instantiated event"))?; - self.display_result(&result, code_hash, instantiated.contract).await + self.display_result(&result, code_hash, instantiated.contract) + .await } async fn instantiate(&self, code_hash: CodeHash) -> Result<(), ErrorVariant> { @@ -334,7 +335,8 @@ impl Exec { .find_first::()? .ok_or_else(|| anyhow!("Failed to find Instantiated event"))?; - self.display_result(&result, None, instantiated.contract).await + self.display_result(&result, None, instantiated.contract) + .await } async fn display_result( @@ -362,7 +364,10 @@ impl Exec { name_value_println!("Code hash", format!("{:?}", code_hash)); } name_value_println!("Contract", contract_address); - println!("{}", events.display_events(self.verbosity, &self.client).await?) + println!( + "{}", + events.display_events(self.verbosity, &self.client).await? + ) }; Ok(()) } diff --git a/crates/cargo-contract/src/cmd/extrinsics/upload.rs b/crates/cargo-contract/src/cmd/extrinsics/upload.rs index ab734f51c..0ff7cbf24 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/upload.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/upload.rs @@ -164,7 +164,9 @@ impl UploadCommand { let output = if self.output_json { display_events.to_json()? } else { - display_events.display_events(self.extrinsic_opts.verbosity()?, client).await? + display_events + .display_events(self.extrinsic_opts.verbosity()?, client) + .await? }; println!("{}", output); let code_stored = result.find_first::()?; From 1da093fdab9bb0685677d76fd9b29c6715234cac Mon Sep 17 00:00:00 2001 From: SkymanOne Date: Tue, 20 Sep 2022 19:54:07 +0100 Subject: [PATCH 03/20] denominated input for balances --- CHANGELOG.md | 2 +- .../src/cmd/extrinsics/balance.rs | 261 ++++++++++++++++++ .../cargo-contract/src/cmd/extrinsics/call.rs | 29 +- .../src/cmd/extrinsics/events.rs | 23 +- .../src/cmd/extrinsics/instantiate.rs | 31 ++- .../cargo-contract/src/cmd/extrinsics/mod.rs | 76 ++--- .../src/cmd/extrinsics/upload.rs | 21 +- 7 files changed, 344 insertions(+), 99 deletions(-) create mode 100644 crates/cargo-contract/src/cmd/extrinsics/balance.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index d7d0da895..55d4aec33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - `--output-json` support for `call`, `instantiate` and `upload` commands - [#722](https://github.com/paritytech/cargo-contract/pull/722) -- Denominated units for Balances +- Denominated units for Balances - [#750](https://github.com/paritytech/cargo-contract/pull/750) ## [2.0.0-alpha.2] - 2022-09-02 diff --git a/crates/cargo-contract/src/cmd/extrinsics/balance.rs b/crates/cargo-contract/src/cmd/extrinsics/balance.rs new file mode 100644 index 000000000..b580c7bb1 --- /dev/null +++ b/crates/cargo-contract/src/cmd/extrinsics/balance.rs @@ -0,0 +1,261 @@ +// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// This file is part of cargo-contract. +// +// cargo-contract is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// cargo-contract is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with cargo-contract. If not, see . + +use std::fmt::Display; + +use serde_json::json; + +use super::{ + Balance, + Client, +}; + +use anyhow::{ + Context, + Ok, + Result, +}; + +/// Represents different formats of a balance +#[derive(Debug, Clone)] +pub enum BalanceVariant { + /// Default format: no symbol, no denomination + Default(Balance), + /// Denominated format: symbol and denomination are present + Denominated(String), +} + +#[derive(Debug, Clone)] +pub struct TokeMetadata { + /// Number of denomination used for denomination + pub denomination: u128, + /// Token symbol + pub symbol: String, +} + +impl TokeMetadata { + /// Query [TokeMetadata] through the node's RPC + pub async fn query(client: &Client) -> Result { + let sys_props = client.rpc().system_properties().await?; + + let default_decimals = json!(12); + let default_units = json!("UNIT"); + let decimals = sys_props + .get("tokenDecimal") + .unwrap_or(&default_decimals) + .as_u64() + .context("error converting decimal to u64")?; + let symbol = sys_props + .get("tokenSymbol") + .unwrap_or(&default_units) + .as_str() + .context("error converting symbol to string")?; + let denomination: u128 = format!("1{}", "0".repeat(decimals as usize)).parse()?; + Ok(Self { + denomination, + symbol: symbol.to_string(), + }) + } +} + +impl BalanceVariant { + /// Converts BalanceVariant into Balance. + /// + /// Throws Error if [BalanceVariant::Denominated(String)] is in an incorrect format. + pub fn denominate_balance(&self, token_metadata: &TokeMetadata) -> Result { + match self { + BalanceVariant::Default(balance) => Ok(*balance), + BalanceVariant::Denominated(input) => { + if let Some(balance_str) = + input.strip_suffix(&format!("k{}", token_metadata.symbol)) + { + let balance: f64 = balance_str.parse()?; + Ok((balance * 1_000.0) as Balance * token_metadata.denomination) + } else if let Some(balance_str) = + input.strip_suffix(&format!("M{}", token_metadata.symbol)) + { + let balance: f64 = balance_str.parse()?; + Ok((balance * 1_000_000.0) as Balance * token_metadata.denomination) + } else if let Some(balance_str) = + input.strip_suffix(&format!("n{}", token_metadata.symbol)) + { + let balance: f64 = balance_str.parse()?; + Ok((balance * 1_000_000_000.0) as Balance) + } else if let Some(balance_str) = + input.strip_suffix(&format!("μ{}", token_metadata.symbol)) + { + let balance: f64 = balance_str.parse()?; + Ok((balance * 1_000_000.0) as Balance) + } else if let Some(balance_str) = + input.strip_suffix(&format!("m{}", token_metadata.symbol)) + { + let balance: f64 = balance_str.parse()?; + Ok((balance * 1_000.0) as Balance) + } else if let Some(balance_str) = + input.strip_suffix(&token_metadata.symbol) + { + let balance: f64 = balance_str.parse()?; + Ok((balance * token_metadata.denomination as f64) as Balance) + } else { + let balance: f64 = input.parse()?; + Ok((balance * token_metadata.denomination as f64) as Balance) + } + } + } + } + + /// Display token units in a denominated format. + pub fn from>(value: T, token_metadata: Option<&TokeMetadata>) -> Self { + let n: u128 = value.into(); + + if let Some(token_metadata) = token_metadata { + if n == 0 { + return BalanceVariant::Denominated(format!("0{}", token_metadata.symbol)) + } + + let units_result = n / token_metadata.denomination; + let mut symbol = ""; + let remainder: u128; + let units: u128; + if (1..1_000).contains(&units_result) { + remainder = n % token_metadata.denomination; + units = units_result; + } else if (1_000..1_000_000).contains(&units_result) { + remainder = units_result % 1_000; + units = units_result / 1_000; + symbol = "k"; + } else if (1_000_000..1_000_000_000).contains(&units_result) { + remainder = units_result % 1_000_000; + units = units_result / 1_000_000; + symbol = "M"; + } else if n / 1_000_000_000 > 0 { + remainder = n % 1_000_000_000; + units = n / 1_000_000_000; + symbol = "n"; + } else if n / 1_000_000 > 0 { + remainder = n % 1_000_000; + units = n / 1_000_000; + symbol = "μ"; + } else { + remainder = n % 1_000; + units = n / 1_000; + symbol = "m"; + } + if remainder > 0 { + let remainder = remainder.to_string().trim_end_matches('0').to_owned(); + BalanceVariant::Denominated(format!( + "{}.{}{}{}", + units, remainder, symbol, token_metadata.symbol + )) + } else { + BalanceVariant::Denominated(format!( + "{}{}{}", + units, symbol, token_metadata.symbol + )) + } + } else { + BalanceVariant::Default(n) + } + } +} + +impl Display for BalanceVariant { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + BalanceVariant::Default(balance) => f.write_str(&balance.to_string()), + BalanceVariant::Denominated(input) => f.write_str(input), + } + } +} + +#[cfg(test)] +mod tests { + use crate::cmd::extrinsics::parse_balance; + + use super::*; + + #[test] + fn correct_balances_parses_success() { + assert!( + parse_balance("500DOT").is_ok(), + "<500DOT> was not parsed correctly" + ); + assert!( + parse_balance("500").is_ok(), + "<500> was not parsed correctly" + ); + } + + #[test] + fn incorrect_balances() { + assert!( + parse_balance("500%").is_err(), + "expected to fail parsing incorrect balance" + ); + } + + #[test] + fn balance_variant_denominated_success() { + let tm = TokeMetadata { + denomination: 12, + symbol: String::from("DOT"), + }; + let bv = parse_balance("500MDOT").expect("successful parsing. qed"); + assert!( + bv.denominate_balance(&tm).is_ok(), + "balances could not be denominated correctly" + ); + } + + #[test] + fn balance_variant_denominated_equal() { + let denomination: u128 = format!("1{}", "0".repeat(12)).parse().unwrap(); + let tm = TokeMetadata { + denomination, + symbol: String::from("DOT"), + }; + let balance: Balance = 500 * 1_000_000 * denomination; + let bv = parse_balance("500MDOT").expect("successful parsing. qed"); + let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); + assert_eq!(balance, balance_parsed); + } + + #[test] + fn balance_variant_denominated_equal_fraction() { + let denomination: u128 = format!("1{}", "0".repeat(12)).parse().unwrap(); + let tm = TokeMetadata { + denomination, + symbol: String::from("DOT"), + }; + let balance: Balance = (500 * 1_000_000 + 500_000) * denomination; + let bv = parse_balance("500.5MDOT").expect("successful parsing. qed"); + let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); + assert_eq!(balance, balance_parsed); + } + + #[test] + fn balance_variant_denominated_equal_small_units() { + let denomination: u128 = format!("1{}", "0".repeat(12)).parse().unwrap(); + let tm = TokeMetadata { + denomination, + symbol: String::from("DOT"), + }; + let balance: Balance = 500 * 1_000_000 + 500_000; + let bv = parse_balance("500.5μDOT").expect("successful parsing. qed"); + let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); + assert_eq!(balance, balance_parsed); + } +} diff --git a/crates/cargo-contract/src/cmd/extrinsics/call.rs b/crates/cargo-contract/src/cmd/extrinsics/call.rs index c77fe6b8e..97630ef07 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/call.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/call.rs @@ -25,12 +25,14 @@ use super::{ state_call, submit_extrinsic, Balance, + BalanceVariant, Client, ContractMessageTranscoder, CrateMetadata, DefaultConfig, ExtrinsicOpts, PairSigner, + TokeMetadata, MAX_KEY_COL_WIDTH, }; @@ -81,7 +83,7 @@ pub struct CallCommand { gas_limit: Option, /// The value to be transferred as part of the call. #[clap(name = "value", long, parse(try_from_str = parse_balance), default_value = "0")] - value: Balance, + value: BalanceVariant, /// Export the call output in JSON format. #[clap(long, conflicts_with = "verbose")] output_json: bool, @@ -107,7 +109,7 @@ impl CallCommand { let client = OnlineClient::from_url(url.clone()).await?; if self.extrinsic_opts.dry_run { - let result = self.call_dry_run(call_data, &signer).await?; + let result = self.call_dry_run(call_data, &client, &signer).await?; match result.result { Ok(ref ret_val) => { @@ -154,15 +156,22 @@ impl CallCommand { async fn call_dry_run( &self, input_data: Vec, + client: &Client, signer: &PairSigner, ) -> Result> { let url = self.extrinsic_opts.url_to_string(); let gas_limit = *self.gas_limit.as_ref().unwrap_or(&5_000_000_000_000); - let storage_deposit_limit = self.extrinsic_opts.storage_deposit_limit; + let token_metadata = TokeMetadata::query(client).await?; + let storage_deposit_limit = self + .extrinsic_opts + .storage_deposit_limit + .as_ref() + .map(|bv| bv.denominate_balance(&token_metadata)) + .transpose()?; let call_request = CallRequest { origin: signer.account_id().clone(), dest: self.contract.clone(), - value: self.value, + value: self.value.denominate_balance(&token_metadata)?, gas_limit: Weight::from_ref_time(gas_limit), storage_deposit_limit, input_data, @@ -195,11 +204,17 @@ impl CallCommand { })?; } + let token_metadata = TokeMetadata::query(client).await?; + let call = api::tx().contracts().call( self.contract.clone().into(), - self.value, + self.value.denominate_balance(&token_metadata)?, gas_limit, - self.extrinsic_opts.storage_deposit_limit, + self.extrinsic_opts + .storage_deposit_limit + .as_ref() + .map(|bv| bv.denominate_balance(&token_metadata)) + .transpose()?, data, ); @@ -240,7 +255,7 @@ impl CallCommand { if !self.output_json { super::print_dry_running_status(&self.message); } - let call_result = self.call_dry_run(data, signer).await?; + let call_result = self.call_dry_run(data, client, signer).await?; match call_result.result { Ok(_) => { if !self.output_json { diff --git a/crates/cargo-contract/src/cmd/extrinsics/events.rs b/crates/cargo-contract/src/cmd/extrinsics/events.rs index 8baa53c2e..8817e7d1a 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/events.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/events.rs @@ -15,17 +15,17 @@ // along with cargo-contract. If not, see . use super::{ - denominate_units, runtime_api::api::contracts::events::ContractEmitted, + BalanceVariant, Client, DefaultConfig, + TokeMetadata, }; use crate::{ Verbosity, DEFAULT_KEY_COL_WIDTH, }; use colored::Colorize as _; -use serde_json::json; use transcode::{ ContractMessageTranscoder, TranscoderBuilder, @@ -33,7 +33,6 @@ use transcode::{ }; use anyhow::{ - Context, Ok, Result, }; @@ -160,20 +159,7 @@ impl DisplayEvents { verbosity: Verbosity, client: &Client, ) -> Result { - let sys_props = client.rpc().system_properties().await?; - - let default_decimals = json!(12); - let default_units = json!("UNIT"); - let decimals = sys_props - .get("tokenDecimals") - .unwrap_or(&default_decimals) - .as_u64() - .context("error converting decimal to u64")?; - let symbol = sys_props - .get("tokenSymbol") - .unwrap_or(&default_units) - .as_str() - .context("error converting symbol to string")?; + let token_metadata = TokeMetadata::query(client).await?; let event_field_indent: usize = DEFAULT_KEY_COL_WIDTH - 3; let mut out = format!( @@ -198,7 +184,8 @@ impl DisplayEvents { || field.type_name == Some("BalanceOf".to_string()) { if let Value::UInt(balance) = field.value { - value = denominate_units(balance, decimals as u128, symbol); + value = BalanceVariant::from(balance, Some(&token_metadata)) + .to_string(); } } let _ = writeln!( diff --git a/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs b/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs index c7cb2dace..732eeda07 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs @@ -25,6 +25,7 @@ use super::{ state_call, submit_extrinsic, Balance, + BalanceVariant, Client, CodeHash, ContractMessageTranscoder, @@ -39,6 +40,7 @@ use crate::{ display_contract_exec_result_debug, events::DisplayEvents, ErrorVariant, + TokeMetadata, }, name_value_println, util::decode_hex, @@ -96,7 +98,7 @@ pub struct InstantiateCommand { extrinsic_opts: ExtrinsicOpts, /// Transfers an initial balance to the instantiated contract #[clap(name = "value", long, default_value = "0", parse(try_from_str = parse_balance))] - value: Balance, + value: BalanceVariant, /// Maximum amount of gas to be used for this command. /// If not specified will perform a dry-run to estimate the gas consumed for the instantiation. #[clap(name = "gas", long)] @@ -169,19 +171,26 @@ impl InstantiateCommand { }?; let salt = self.salt.clone().map(|s| s.0).unwrap_or_default(); - let args = InstantiateArgs { - constructor: self.constructor.clone(), - raw_args: self.args.clone(), - value: self.value, - gas_limit: self.gas_limit.map(Weight::from_ref_time), - storage_deposit_limit: self.extrinsic_opts.storage_deposit_limit, - data, - salt, - }; - async_std::task::block_on(async move { let client = OnlineClient::from_url(url.clone()).await?; + let token_metadata = TokeMetadata::query(&client).await?; + + let args = InstantiateArgs { + constructor: self.constructor.clone(), + raw_args: self.args.clone(), + value: self.value.denominate_balance(&token_metadata)?, + gas_limit: self.gas_limit.map(Weight::from_ref_time), + storage_deposit_limit: self + .extrinsic_opts + .storage_deposit_limit + .as_ref() + .map(|bv| bv.denominate_balance(&token_metadata)) + .transpose()?, + data, + salt, + }; + let exec = Exec { args, opts: self.extrinsic_opts.clone(), diff --git a/crates/cargo-contract/src/cmd/extrinsics/mod.rs b/crates/cargo-contract/src/cmd/extrinsics/mod.rs index 2401d04ca..e8250b89d 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/mod.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/mod.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with cargo-contract. If not, see . +mod balance; mod call; mod error; mod events; @@ -28,6 +29,7 @@ mod integration_tests; use anyhow::{ anyhow, Context, + Ok, Result, }; use colored::Colorize; @@ -67,6 +69,12 @@ use subxt::{ OnlineClient, }; +use std::option::Option; + +pub use balance::{ + BalanceVariant, + TokeMetadata, +}; pub use call::CallCommand; pub use error::ErrorVariant; pub use instantiate::InstantiateCommand; @@ -107,7 +115,7 @@ pub struct ExtrinsicOpts { /// The maximum amount of balance that can be charged from the caller to pay for the storage /// consumed. #[clap(long, parse(try_from_str = parse_balance))] - storage_deposit_limit: Option, + storage_deposit_limit: Option, /// Before submitting a transaction, do not dry-run it via RPC first. #[clap(long)] skip_dry_run: bool, @@ -141,11 +149,13 @@ impl ExtrinsicOpts { } /// Parse Rust style integer balance literals which can contain underscores. -fn parse_balance(input: &str) -> Result { - input - .replace('_', "") - .parse::() - .map_err(Into::into) +fn parse_balance(input: &str) -> Result { + let input = input.replace('_', ""); + if input.contains('.') || input.ends_with(|ch: char| ch.is_alphabetic()) { + Ok(BalanceVariant::Denominated(input)) + } else { + Ok(BalanceVariant::Default(input.parse::()?)) + } } /// Create a new [`PairSigner`] from the given [`sr25519::Pair`]. @@ -237,7 +247,7 @@ async fn state_call(url: &str, func: &str, args: A) -> Res Ok(R::decode(&mut bytes.as_ref())?) } -/// Prompt the user to confirm transaction submission +/// Prompt the user to confirm transaction submission. fn prompt_confirm_tx(show_details: F) -> Result<()> { println!( "{} (skip with --skip-confirm)", @@ -278,55 +288,3 @@ fn print_gas_required_success(gas: u64) { width = DEFAULT_KEY_COL_WIDTH ); } - -fn denominate_units>(value: T, decimals: u128, symbol: &str) -> String { - let n: u128 = value.into(); - - if n == 0 { - return format!("0 {}", symbol) - } - - let units = n / decimals; - if (1..1_000).contains(&units) { - let remainder = n % decimals; - if remainder > 0 { - let remainder = remainder.to_string().trim_end_matches('0').to_owned(); - format!("{}.{} {}", units, remainder, symbol) - } else { - format!("0 {}", symbol) - } - } else if (1_000..1_000_000).contains(&units) { - let remainder = units % 1_000; - let units = units / 1_000; - if remainder > 0 { - let remainder = remainder.to_string().trim_end_matches('0').to_owned(); - format!("{}.{} k{}", units, remainder, symbol) - } else { - format!("{} k{}", units, symbol) - } - } else if (1_000_000..1_000_000_000).contains(&units) { - let remainder = units % 1_000_000; - let units = units / 1_000_000; - if remainder > 0 { - let remainder = remainder.to_string().trim_end_matches('0').to_owned(); - format!("{}.{} M{}", units, remainder, symbol) - } else { - format!("{} M{}", units, symbol) - } - } else if n / 1_000_000_000 > 0 { - let remainder = n % 1_000_000_000; - let remainder = remainder.to_string().trim_end_matches('0').to_owned(); - let units = n / 1_000_000_000; - format!("{}.{} n{}", units, remainder, symbol) - } else if n / 1_000_000 > 0 { - let remainder = n % 1_000_000; - let remainder = remainder.to_string().trim_end_matches('0').to_owned(); - let units = n / 1_000_000; - format!("{}.{} μ{}", units, remainder, symbol) - } else { - let remainder = n % 1_000; - let remainder = remainder.to_string().trim_end_matches('0').to_owned(); - let units = n / 1_000; - format!("{}.{} m{}", units, remainder, symbol) - } -} diff --git a/crates/cargo-contract/src/cmd/extrinsics/upload.rs b/crates/cargo-contract/src/cmd/extrinsics/upload.rs index 0ff7cbf24..ddfe003f4 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/upload.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/upload.rs @@ -26,6 +26,7 @@ use super::{ DefaultConfig, ExtrinsicOpts, PairSigner, + TokeMetadata, }; use crate::{ cmd::extrinsics::{ @@ -88,7 +89,7 @@ impl UploadCommand { let client = OnlineClient::from_url(url.clone()).await?; if self.extrinsic_opts.dry_run { - match self.upload_code_rpc(code, &signer).await? { + match self.upload_code_rpc(code, &client, &signer).await? { Ok(result) => { let upload_result = UploadDryRunResult { result: String::from("Success!"), @@ -134,10 +135,17 @@ impl UploadCommand { async fn upload_code_rpc( &self, code: Vec, + client: &Client, signer: &PairSigner, ) -> Result> { let url = self.extrinsic_opts.url_to_string(); - let storage_deposit_limit = self.extrinsic_opts.storage_deposit_limit; + let token_metadata = TokeMetadata::query(client).await?; + let storage_deposit_limit = self + .extrinsic_opts + .storage_deposit_limit + .as_ref() + .map(|bv| bv.denominate_balance(&token_metadata)) + .transpose()?; let call_request = CodeUploadRequest { origin: signer.account_id().clone(), code, @@ -153,9 +161,16 @@ impl UploadCommand { signer: &PairSigner, transcoder: &ContractMessageTranscoder, ) -> Result, ErrorVariant> { + let token_metadata = TokeMetadata::query(client).await?; + let storage_deposit_limit = self + .extrinsic_opts + .storage_deposit_limit + .as_ref() + .map(|bv| bv.denominate_balance(&token_metadata)) + .transpose()?; let call = super::runtime_api::api::tx() .contracts() - .upload_code(code, self.extrinsic_opts.storage_deposit_limit); + .upload_code(code, storage_deposit_limit); let result = submit_extrinsic(client, &call, signer).await?; let display_events = From 7e76f62e373965a9199e5933dd91dcbe49dcfd2d Mon Sep 17 00:00:00 2001 From: SkymanOne Date: Tue, 20 Sep 2022 20:56:32 +0100 Subject: [PATCH 04/20] fix spelling --- .../src/cmd/extrinsics/balance.rs | 20 +++++++++---------- .../cargo-contract/src/cmd/extrinsics/call.rs | 6 +++--- .../src/cmd/extrinsics/events.rs | 4 ++-- .../src/cmd/extrinsics/instantiate.rs | 4 ++-- .../cargo-contract/src/cmd/extrinsics/mod.rs | 2 +- .../src/cmd/extrinsics/upload.rs | 6 +++--- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/crates/cargo-contract/src/cmd/extrinsics/balance.rs b/crates/cargo-contract/src/cmd/extrinsics/balance.rs index b580c7bb1..61b4853f4 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/balance.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/balance.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2020 Parity Technologies (UK) Ltd. +// Copyright 2018-2022 Parity Technologies (UK) Ltd. // This file is part of cargo-contract. // // cargo-contract is free software: you can redistribute it and/or modify @@ -39,15 +39,15 @@ pub enum BalanceVariant { } #[derive(Debug, Clone)] -pub struct TokeMetadata { +pub struct TokenMetadata { /// Number of denomination used for denomination pub denomination: u128, /// Token symbol pub symbol: String, } -impl TokeMetadata { - /// Query [TokeMetadata] through the node's RPC +impl TokenMetadata { + /// Query [TokenMetadata] through the node's RPC pub async fn query(client: &Client) -> Result { let sys_props = client.rpc().system_properties().await?; @@ -75,7 +75,7 @@ impl BalanceVariant { /// Converts BalanceVariant into Balance. /// /// Throws Error if [BalanceVariant::Denominated(String)] is in an incorrect format. - pub fn denominate_balance(&self, token_metadata: &TokeMetadata) -> Result { + pub fn denominate_balance(&self, token_metadata: &TokenMetadata) -> Result { match self { BalanceVariant::Default(balance) => Ok(*balance), BalanceVariant::Denominated(input) => { @@ -118,7 +118,7 @@ impl BalanceVariant { } /// Display token units in a denominated format. - pub fn from>(value: T, token_metadata: Option<&TokeMetadata>) -> Self { + pub fn from>(value: T, token_metadata: Option<&TokenMetadata>) -> Self { let n: u128 = value.into(); if let Some(token_metadata) = token_metadata { @@ -209,7 +209,7 @@ mod tests { #[test] fn balance_variant_denominated_success() { - let tm = TokeMetadata { + let tm = TokenMetadata { denomination: 12, symbol: String::from("DOT"), }; @@ -223,7 +223,7 @@ mod tests { #[test] fn balance_variant_denominated_equal() { let denomination: u128 = format!("1{}", "0".repeat(12)).parse().unwrap(); - let tm = TokeMetadata { + let tm = TokenMetadata { denomination, symbol: String::from("DOT"), }; @@ -236,7 +236,7 @@ mod tests { #[test] fn balance_variant_denominated_equal_fraction() { let denomination: u128 = format!("1{}", "0".repeat(12)).parse().unwrap(); - let tm = TokeMetadata { + let tm = TokenMetadata { denomination, symbol: String::from("DOT"), }; @@ -249,7 +249,7 @@ mod tests { #[test] fn balance_variant_denominated_equal_small_units() { let denomination: u128 = format!("1{}", "0".repeat(12)).parse().unwrap(); - let tm = TokeMetadata { + let tm = TokenMetadata { denomination, symbol: String::from("DOT"), }; diff --git a/crates/cargo-contract/src/cmd/extrinsics/call.rs b/crates/cargo-contract/src/cmd/extrinsics/call.rs index 97630ef07..31c060b61 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/call.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/call.rs @@ -32,7 +32,7 @@ use super::{ DefaultConfig, ExtrinsicOpts, PairSigner, - TokeMetadata, + TokenMetadata, MAX_KEY_COL_WIDTH, }; @@ -161,7 +161,7 @@ impl CallCommand { ) -> Result> { let url = self.extrinsic_opts.url_to_string(); let gas_limit = *self.gas_limit.as_ref().unwrap_or(&5_000_000_000_000); - let token_metadata = TokeMetadata::query(client).await?; + let token_metadata = TokenMetadata::query(client).await?; let storage_deposit_limit = self .extrinsic_opts .storage_deposit_limit @@ -204,7 +204,7 @@ impl CallCommand { })?; } - let token_metadata = TokeMetadata::query(client).await?; + let token_metadata = TokenMetadata::query(client).await?; let call = api::tx().contracts().call( self.contract.clone().into(), diff --git a/crates/cargo-contract/src/cmd/extrinsics/events.rs b/crates/cargo-contract/src/cmd/extrinsics/events.rs index 8817e7d1a..b923ea048 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/events.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/events.rs @@ -19,7 +19,7 @@ use super::{ BalanceVariant, Client, DefaultConfig, - TokeMetadata, + TokenMetadata, }; use crate::{ Verbosity, @@ -159,7 +159,7 @@ impl DisplayEvents { verbosity: Verbosity, client: &Client, ) -> Result { - let token_metadata = TokeMetadata::query(client).await?; + let token_metadata = TokenMetadata::query(client).await?; let event_field_indent: usize = DEFAULT_KEY_COL_WIDTH - 3; let mut out = format!( diff --git a/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs b/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs index 732eeda07..ed80816d1 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs @@ -40,7 +40,7 @@ use crate::{ display_contract_exec_result_debug, events::DisplayEvents, ErrorVariant, - TokeMetadata, + TokenMetadata, }, name_value_println, util::decode_hex, @@ -174,7 +174,7 @@ impl InstantiateCommand { async_std::task::block_on(async move { let client = OnlineClient::from_url(url.clone()).await?; - let token_metadata = TokeMetadata::query(&client).await?; + let token_metadata = TokenMetadata::query(&client).await?; let args = InstantiateArgs { constructor: self.constructor.clone(), diff --git a/crates/cargo-contract/src/cmd/extrinsics/mod.rs b/crates/cargo-contract/src/cmd/extrinsics/mod.rs index e8250b89d..061bd711a 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/mod.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/mod.rs @@ -73,7 +73,7 @@ use std::option::Option; pub use balance::{ BalanceVariant, - TokeMetadata, + TokenMetadata, }; pub use call::CallCommand; pub use error::ErrorVariant; diff --git a/crates/cargo-contract/src/cmd/extrinsics/upload.rs b/crates/cargo-contract/src/cmd/extrinsics/upload.rs index ddfe003f4..ca0af113d 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/upload.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/upload.rs @@ -26,7 +26,7 @@ use super::{ DefaultConfig, ExtrinsicOpts, PairSigner, - TokeMetadata, + TokenMetadata, }; use crate::{ cmd::extrinsics::{ @@ -139,7 +139,7 @@ impl UploadCommand { signer: &PairSigner, ) -> Result> { let url = self.extrinsic_opts.url_to_string(); - let token_metadata = TokeMetadata::query(client).await?; + let token_metadata = TokenMetadata::query(client).await?; let storage_deposit_limit = self .extrinsic_opts .storage_deposit_limit @@ -161,7 +161,7 @@ impl UploadCommand { signer: &PairSigner, transcoder: &ContractMessageTranscoder, ) -> Result, ErrorVariant> { - let token_metadata = TokeMetadata::query(client).await?; + let token_metadata = TokenMetadata::query(client).await?; let storage_deposit_limit = self .extrinsic_opts .storage_deposit_limit From 3317435b686e4b79ba22834325adf6272581235b Mon Sep 17 00:00:00 2001 From: SkymanOne Date: Wed, 21 Sep 2022 19:09:34 +0100 Subject: [PATCH 05/20] add test for incorrect token symbol --- crates/cargo-contract/src/cmd/extrinsics/balance.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/crates/cargo-contract/src/cmd/extrinsics/balance.rs b/crates/cargo-contract/src/cmd/extrinsics/balance.rs index 61b4853f4..d9e19927a 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/balance.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/balance.rs @@ -220,6 +220,19 @@ mod tests { ); } + #[test] + fn balance_variant_denominated_incorrect_token() { + let tm = TokenMetadata { + denomination: 12, + symbol: String::from("DOT"), + }; + let bv = parse_balance("500MKSM").expect("successful parsing. qed"); + assert!( + bv.denominate_balance(&tm).is_err(), + "balances denominated should fail because of an incorrect token" + ); + } + #[test] fn balance_variant_denominated_equal() { let denomination: u128 = format!("1{}", "0".repeat(12)).parse().unwrap(); From 9d801b35edf15ebc519ca3a1b709fd22d492df70 Mon Sep 17 00:00:00 2001 From: SkymanOne Date: Wed, 21 Sep 2022 19:52:04 +0100 Subject: [PATCH 06/20] optimise rpc calls for token metadata --- crates/cargo-contract/src/cmd/extrinsics/call.rs | 3 +-- crates/cargo-contract/src/cmd/extrinsics/events.rs | 8 +++----- crates/cargo-contract/src/cmd/extrinsics/instantiate.rs | 9 ++++++--- crates/cargo-contract/src/cmd/extrinsics/upload.rs | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/crates/cargo-contract/src/cmd/extrinsics/call.rs b/crates/cargo-contract/src/cmd/extrinsics/call.rs index 31c060b61..1e49a1925 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/call.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/call.rs @@ -227,8 +227,7 @@ impl CallCommand { display_events.to_json()? } else { display_events - .display_events(self.extrinsic_opts.verbosity()?, client) - .await? + .display_events(self.extrinsic_opts.verbosity()?, &token_metadata)? }; println!("{}", output); diff --git a/crates/cargo-contract/src/cmd/extrinsics/events.rs b/crates/cargo-contract/src/cmd/extrinsics/events.rs index b923ea048..04e63b5b0 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/events.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/events.rs @@ -17,7 +17,6 @@ use super::{ runtime_api::api::contracts::events::ContractEmitted, BalanceVariant, - Client, DefaultConfig, TokenMetadata, }; @@ -154,12 +153,11 @@ impl DisplayEvents { } /// Displays events in a human readable format - pub async fn display_events( + pub fn display_events( &self, verbosity: Verbosity, - client: &Client, + token_metadata: &TokenMetadata ) -> Result { - let token_metadata = TokenMetadata::query(client).await?; let event_field_indent: usize = DEFAULT_KEY_COL_WIDTH - 3; let mut out = format!( @@ -184,7 +182,7 @@ impl DisplayEvents { || field.type_name == Some("BalanceOf".to_string()) { if let Value::UInt(balance) = field.value { - value = BalanceVariant::from(balance, Some(&token_metadata)) + value = BalanceVariant::from(balance, Some(token_metadata)) .to_string(); } } diff --git a/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs b/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs index ed80816d1..309cd4b05 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs @@ -309,7 +309,8 @@ impl Exec { .find_first::()? .ok_or_else(|| anyhow!("Failed to find Instantiated event"))?; - self.display_result(&result, code_hash, instantiated.contract) + let token_metadata = TokenMetadata::query(&self.client).await?; + self.display_result(&result, code_hash, instantiated.contract, &token_metadata) .await } @@ -344,7 +345,8 @@ impl Exec { .find_first::()? .ok_or_else(|| anyhow!("Failed to find Instantiated event"))?; - self.display_result(&result, None, instantiated.contract) + let token_metadata = TokenMetadata::query(&self.client).await?; + self.display_result(&result, None, instantiated.contract, &token_metadata) .await } @@ -353,6 +355,7 @@ impl Exec { result: &TxEvents, code_hash: Option, contract_address: sp_core::crypto::AccountId32, + token_metadata: &TokenMetadata ) -> Result<(), ErrorVariant> { let events = DisplayEvents::from_events( result, @@ -375,7 +378,7 @@ impl Exec { name_value_println!("Contract", contract_address); println!( "{}", - events.display_events(self.verbosity, &self.client).await? + events.display_events(self.verbosity, token_metadata)? ) }; Ok(()) diff --git a/crates/cargo-contract/src/cmd/extrinsics/upload.rs b/crates/cargo-contract/src/cmd/extrinsics/upload.rs index ca0af113d..2bf23f708 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/upload.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/upload.rs @@ -179,9 +179,9 @@ impl UploadCommand { let output = if self.output_json { display_events.to_json()? } else { + let token_metadata = TokenMetadata::query(client).await?; display_events - .display_events(self.extrinsic_opts.verbosity()?, client) - .await? + .display_events(self.extrinsic_opts.verbosity()?, &token_metadata)? }; println!("{}", output); let code_stored = result.find_first::()?; From 3252aee0b81081eca8822ac8985cd4270dbfc5db Mon Sep 17 00:00:00 2001 From: SkymanOne Date: Fri, 23 Sep 2022 00:19:12 +0100 Subject: [PATCH 07/20] bump subxt, add Compact compatibility --- Cargo.lock | 519 +++++++++--------- crates/cargo-contract/Cargo.toml | 2 +- .../cargo-contract/src/cmd/extrinsics/call.rs | 6 +- .../src/cmd/extrinsics/events.rs | 3 +- .../src/cmd/extrinsics/instantiate.rs | 19 +- .../cargo-contract/src/cmd/extrinsics/mod.rs | 13 + .../src/cmd/extrinsics/upload.rs | 8 +- 7 files changed, 301 insertions(+), 269 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 78466a507..76cd5066f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,20 +33,29 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.6", + "getrandom 0.2.7", "once_cell", "version_check", ] [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" dependencies = [ "memchr", ] +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "ansi_term" version = "0.12.1" @@ -64,9 +73,9 @@ checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602" [[package]] name = "array-init" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6945cc5422176fc5e602e590c2878d2c2acd9a4fe20a4baa7c28022521698ec6" +checksum = "bfb6d71005dc22a708c7496eee5c8dc0300ee47355de6256c3b35b12b5fef596" [[package]] name = "arrayref" @@ -127,9 +136,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "1.6.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" +checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28" dependencies = [ "concurrent-queue", "event-listener", @@ -152,27 +161,27 @@ dependencies = [ [[package]] name = "async-global-executor" -version = "2.0.4" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c290043c9a95b05d45e952fb6383c67bcb61471f60cfa21e890dba6654234f43" +checksum = "0da5b41ee986eed3f524c380e6d64965aea573882a8907682ad100f7859305ca" dependencies = [ "async-channel", "async-executor", "async-io", - "async-mutex", + "async-lock", "blocking", "futures-lite", - "num_cpus", "once_cell", "tokio", ] [[package]] name = "async-io" -version = "1.6.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b" +checksum = "83e21f3a490c72b3b0cf44962180e60045de2925d8dff97918f7ee43c8f637c7" dependencies = [ + "autocfg", "concurrent-queue", "futures-lite", "libc", @@ -195,15 +204,6 @@ dependencies = [ "event-listener", ] -[[package]] -name = "async-mutex" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" -dependencies = [ - "event-listener", -] - [[package]] name = "async-std" version = "1.12.0" @@ -233,15 +233,15 @@ dependencies = [ [[package]] name = "async-task" -version = "4.2.0" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9" +checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" [[package]] name = "async-trait" -version = "0.1.53" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600" +checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f" dependencies = [ "proc-macro2", "quote", @@ -273,9 +273,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.65" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11a17d453482a265fd5f8479f2a3f405566e6ca627837aaddb85af8b1ab8ef61" +checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" dependencies = [ "addr2line", "cc", @@ -300,9 +300,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "beef" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bed554bd50246729a1ec158d08aa3235d1b69d94ad120ebe187e28894787e736" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" dependencies = [ "serde", ] @@ -315,9 +315,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitvec" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1489fcb93a5bb47da0462ca93ad252ad6af2145cce58d10d46a83931ba9f016b" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ "funty", "radium", @@ -331,7 +331,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9cf849ee05b2ee5fba5e36f97ff8ec2533916700fc0758d40d92136a42f3388" dependencies = [ - "digest 0.10.3", + "digest 0.10.5", ] [[package]] @@ -362,16 +362,16 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.6", ] [[package]] name = "block-buffer" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.6", ] [[package]] @@ -419,9 +419,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.9.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" [[package]] name = "byte-slice-cast" @@ -443,9 +443,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" [[package]] name = "cache-padded" @@ -455,9 +455,9 @@ checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" [[package]] name = "camino" -version = "1.0.8" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07fd178c5af4d59e83498ef15cf3f154e1a6f9d091270cb86283c65ef44e9ef0" +checksum = "88ad0e1e3e88dd237a156ab9f571021b8a158caa0ae44b1968a241efb5144c1e" dependencies = [ "serde", ] @@ -541,11 +541,11 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.19" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" dependencies = [ - "libc", + "iana-time-zone", "num-integer", "num-traits", "winapi", @@ -583,9 +583,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5538cd660450ebeb4234cfecf8f2284b844ffc4c50531e66d584ad5b91293613" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" dependencies = [ "os_str_bytes", ] @@ -612,9 +612,9 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "1.2.2" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" +checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c" dependencies = [ "cache-padded", ] @@ -681,9 +681,9 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "cpufeatures" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" dependencies = [ "libc", ] @@ -699,12 +699,12 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" dependencies = [ "cfg-if", - "lazy_static", + "once_cell", ] [[package]] @@ -715,11 +715,11 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-common" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.6", "typenum", ] @@ -729,7 +729,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.6", "subtle", ] @@ -739,15 +739,15 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.6", "subtle", ] [[package]] name = "ctor" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" +checksum = "cdffe87e1d521a10f9696f833fe502293ea446d7f256c06128293a4119bdf4cb" dependencies = [ "quote", "syn", @@ -844,9 +844,9 @@ dependencies = [ [[package]] name = "diff" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "difflib" @@ -869,16 +869,16 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.6", ] [[package]] name = "digest" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" dependencies = [ - "block-buffer 0.10.2", + "block-buffer 0.10.3", "crypto-common", "subtle", ] @@ -938,9 +938,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e50f3adc76d6a43f5ed73b698a87d0760ca74617f60f7c3b879003536fdd28" +checksum = "4f94fa09c2aeea5b8839e414b7b841bf429fd25b9c522116ac97ee87856d88b2" [[package]] name = "ed25519" @@ -967,9 +967,9 @@ dependencies = [ [[package]] name = "either" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "env_logger" @@ -1001,9 +1001,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "2.5.2" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "fake-simd" @@ -1013,9 +1013,9 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "fastrand" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ "instant", ] @@ -1076,9 +1076,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c" dependencies = [ "futures-channel", "futures-core", @@ -1091,9 +1091,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" dependencies = [ "futures-core", "futures-sink", @@ -1101,15 +1101,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" [[package]] name = "futures-executor" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab" dependencies = [ "futures-core", "futures-task", @@ -1119,9 +1119,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" +checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68" [[package]] name = "futures-lite" @@ -1140,9 +1140,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17" dependencies = [ "proc-macro2", "quote", @@ -1151,15 +1151,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" [[package]] name = "futures-task" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" [[package]] name = "futures-timer" @@ -1169,9 +1169,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" dependencies = [ "futures-channel", "futures-core", @@ -1196,9 +1196,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", "version_check", @@ -1219,20 +1219,20 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", - "wasi 0.10.2+wasi-snapshot-preview1", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] name = "gimli" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" [[package]] name = "glob" @@ -1269,9 +1269,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ "ahash", ] @@ -1324,26 +1324,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" dependencies = [ "digest 0.9.0", - "generic-array 0.14.5", + "generic-array 0.14.6", "hmac 0.8.1", ] [[package]] name = "http" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff8670570af52249509a86f5e3e18a08c60b177071826898fde8997cf5f6bfbb" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes", "fnv", - "itoa 1.0.2", + "itoa 1.0.3", ] [[package]] name = "httparse" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "humantime" @@ -1351,6 +1351,20 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "iana-time-zone" +version = "0.1.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "237a0714f28b1ee39ccec0770ccb544eb02c9ef2c82bb096230eefcffa6468b0" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "js-sys", + "once_cell", + "wasm-bindgen", + "winapi", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1478,7 +1492,7 @@ dependencies = [ "parity-scale-codec", "rand 0.8.5", "secp256k1 0.24.0", - "sha2 0.10.2", + "sha2 0.10.6", "sha3", ] @@ -1505,7 +1519,7 @@ dependencies = [ "rlibc", "scale-info", "secp256k1 0.24.0", - "sha2 0.10.2", + "sha2 0.10.6", "sha3", "static_assertions", ] @@ -1643,9 +1657,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" [[package]] name = "joinery" @@ -1655,9 +1669,9 @@ checksum = "72167d68f5fce3b8655487b8038691a3c9984ee769590f93f2a631f4ad64e4f5" [[package]] name = "js-sys" -version = "0.3.57" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] @@ -1746,9 +1760,9 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" +checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838" [[package]] name = "kv-log-macro" @@ -1767,15 +1781,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.126" +version = "0.2.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" [[package]] name = "libsecp256k1" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0452aac8bab02242429380e9b2f94ea20cea2b37e2c1777a1358799bbe97f37" +checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" dependencies = [ "arrayref", "base64", @@ -1821,9 +1835,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390" dependencies = [ "autocfg", "scopeguard", @@ -1900,18 +1914,18 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.5.1" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" +checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" dependencies = [ "libc", "log", @@ -2018,18 +2032,18 @@ dependencies = [ [[package]] name = "object" -version = "0.28.4" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" +checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" [[package]] name = "opaque-debug" @@ -2051,9 +2065,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "os_str_bytes" -version = "6.0.1" +version = "6.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029d8d0b2f198229de29dca79676f2738ff952edf3fde542eb8bf94d8c21b435" +checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" [[package]] name = "output_vt100" @@ -2082,9 +2096,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.1.2" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8b44461635bbb1a0300f100a841e571e7d919c81c73075ef5d152ffdb521066" +checksum = "366e44391a8af4cfd6002ef6ba072bae071a96aafca98d7d448a34c5dca38b6a" dependencies = [ "arrayvec 0.7.2", "bitvec", @@ -2096,9 +2110,9 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.1.2" +version = "3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c45ed1f39709f5a89338fab50e59816b2e8815f5bb58276e7ddf9afd495f73f8" +checksum = "9299338969a3d2f491d65f140b00ddec470858402f888af98e8642fb5e8965cd" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -2152,9 +2166,9 @@ checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" [[package]] name = "parking_lot" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", "parking_lot_core", @@ -2175,9 +2189,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.7" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" +checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" [[package]] name = "pbkdf2" @@ -2205,18 +2219,18 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pin-project" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", @@ -2243,10 +2257,11 @@ checksum = "989d43012e2ca1c4a02507c67282691a0a3207f9dc67cec596b43fe925b3d325" [[package]] name = "polling" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" +checksum = "899b00b9c8ab553c743b3e11e87c5c7d423b2a2de229ba95b24a756344748011" dependencies = [ + "autocfg", "cfg-if", "libc", "log", @@ -2317,10 +2332,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" +checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" dependencies = [ + "once_cell", "thiserror", "toml", ] @@ -2351,18 +2367,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.39" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.18" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] @@ -2395,7 +2411,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.1", - "rand_core 0.6.3", + "rand_core 0.6.4", ] [[package]] @@ -2415,7 +2431,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.3", + "rand_core 0.6.4", ] [[package]] @@ -2429,11 +2445,11 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.6", + "getrandom 0.2.7", ] [[package]] @@ -2456,9 +2472,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.13" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] @@ -2469,25 +2485,25 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.6", + "getrandom 0.2.7", "redox_syscall", "thiserror", ] [[package]] name = "ref-cast" -version = "1.0.7" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685d58625b6c2b83e4cc88a27c4bf65adb7b6b16dbdc413e515c9405b47432ab" +checksum = "ed13bcd201494ab44900a96490291651d200730904221832b9547d24a87d332b" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.7" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a043824e29c94169374ac5183ac0ed43f5724dc4556b19568007486bd840fa1f" +checksum = "5234cd6063258a5e32903b53b1b6ac043a0541c8adc1f610f67b0326c7a578fa" dependencies = [ "proc-macro2", "quote", @@ -2603,24 +2619,24 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9" +checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55" dependencies = [ "base64", ] [[package]] name = "rustversion" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" +checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" [[package]] name = "ryu" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "same-file" @@ -2632,13 +2648,24 @@ dependencies = [ ] [[package]] -name = "scale-decode" +name = "scale-bits" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c70dece385bc3e5918109830d9509806b5d4525fdf594e3463078c529122979e" +checksum = "8dd7aca73785181cc41f0bbe017263e682b585ca660540ba569133901d013ecf" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "scale-decode" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d823d4be477fc33321f93d08fb6c2698273d044f01362dc27573a750deb7c233" dependencies = [ - "bitvec", "parity-scale-codec", + "scale-bits", "scale-info", "thiserror", ] @@ -2671,14 +2698,14 @@ dependencies = [ [[package]] name = "scale-value" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae8b296b3ebcb3425661e9b612ccc34cb1064483a61dc379c65e6b1463498f1" +checksum = "16a5e7810815bd295da73e4216d1dfbced3c7c7c7054d70fa5f6e4c58123fff4" dependencies = [ - "bitvec", "either", "frame-metadata", "parity-scale-codec", + "scale-bits", "scale-decode", "scale-info", "serde", @@ -2777,9 +2804,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.6.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" dependencies = [ "bitflags", "core-foundation", @@ -2833,7 +2860,7 @@ version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ - "itoa 1.0.2", + "itoa 1.0.3", "ryu", "serde", ] @@ -2878,22 +2905,22 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.2" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.3", + "digest 0.10.5", ] [[package]] name = "sha3" -version = "0.10.1" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881bf8156c87b6301fc5ca6b27f11eeb2761224c7081e69b409d5a1951a70c86" +checksum = "e2904bea16a1ae962b483322a1c7b81d976029203aea1f461e51cd7705db7ba9" dependencies = [ - "digest 0.10.3", + "digest 0.10.5", "keccak", ] @@ -2908,27 +2935,30 @@ dependencies = [ [[package]] name = "signature" -version = "1.5.0" +version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" +checksum = "deb766570a2825fa972bceff0d195727876a9cdf2460ab2e52d455dc2de47fd9" [[package]] name = "slab" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] [[package]] name = "smallvec" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "socket2" -version = "0.4.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ "libc", "winapi", @@ -3276,9 +3306,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "ss58-registry" -version = "1.18.0" +version = "1.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceb8b72a924ccfe7882d0e26144c114503760a4d1248bb5cd06c8ab2d55404cc" +checksum = "b0837b5d62f42082c9d56cd946495ae273a3c68083b637b9153341d5e465146d" dependencies = [ "Inflector", "num-format", @@ -3331,9 +3361,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "subxt" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d5d7eafcc9b412a74269e0eaa413e9228d8b9da812e0d29c43c883da9b98b57" +checksum = "0a8757ee0e19f87e722577282ab1386c86592a4b13ff963b9c6ec4176348104c" dependencies = [ "bitvec", "derivative", @@ -3358,9 +3388,9 @@ dependencies = [ [[package]] name = "subxt-codegen" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d024e9b6fec95eba52fbe4512bf95b0ad079be3792ab190eec478d1731a17358" +checksum = "bb77f93e11e6ff3ff95fe33e3d24c27c342e16feca8ef47759993614ebe90d2c" dependencies = [ "darling", "frame-metadata", @@ -3376,9 +3406,9 @@ dependencies = [ [[package]] name = "subxt-macro" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18dbe609475b86207792e1021a4f958e0381ebc2c17cf4eddd4d885883b96f8a" +checksum = "051cc21d77a54ae944b872eafdf9edfe1d9134fdfcfc3477dc10f763c76564a9" dependencies = [ "darling", "proc-macro-error", @@ -3388,9 +3418,9 @@ dependencies = [ [[package]] name = "subxt-metadata" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b7b9f8c2b42d3626dc18856727fc23cf6a04c4c044507735f55110e44a3986c" +checksum = "5ed78d80db3a97d55e8b1cfecc1f6f9e21793a589d4e2e5f4fe2d6d5850c2e54" dependencies = [ "frame-metadata", "parity-scale-codec", @@ -3400,9 +3430,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.95" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" +checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e" dependencies = [ "proc-macro2", "quote", @@ -3464,18 +3494,18 @@ checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" [[package]] name = "thiserror" -version = "1.0.31" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +checksum = "c53f98874615aea268107765aa1ed8f6116782501d18e53d08b471733bea6c85" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.31" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +checksum = "f8b463991b4eab2d801e724172285ec4195c650e8ec79b149e6c2a8e6dd3f783" dependencies = [ "proc-macro2", "quote", @@ -3536,10 +3566,11 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.18.2" +version = "1.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4903bf0427cf68dddd5aa6a93220756f8be0c34fcfa9f5e6191e103e15a31395" +checksum = "0020c875007ad96677dcc890298f4b942882c5d4eb7cc8f439fc3bf813dc9c95" dependencies = [ + "autocfg", "libc", "mio", "num_cpus", @@ -3552,9 +3583,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" dependencies = [ "proc-macro2", "quote", @@ -3574,9 +3605,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f988a1a1adc2fb21f9c12aa96441da33a1728193ae0b95d2be22dbd17fcb4e5c" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" dependencies = [ "bytes", "futures-core", @@ -3758,24 +3789,24 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" [[package]] name = "unicode-normalization" -version = "0.1.19" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-xid" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "untrusted" @@ -3872,12 +3903,6 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -3886,9 +3911,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.80" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -3896,13 +3921,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.80" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", - "lazy_static", "log", + "once_cell", "proc-macro2", "quote", "syn", @@ -3911,9 +3936,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.30" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2" +checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" dependencies = [ "cfg-if", "js-sys", @@ -3923,9 +3948,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.80" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3933,9 +3958,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.80" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", @@ -3946,9 +3971,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.80" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "wasmi" @@ -3976,9 +4001,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.57" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" dependencies = [ "js-sys", "wasm-bindgen", @@ -3996,9 +4021,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.22.3" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d8de8415c823c8abd270ad483c6feeac771fad964890779f9a8cb24fbbc1bf" +checksum = "f1c760f0d366a6c24a02ed7816e23e691f5d92291f94d15e836006fd11b04daf" dependencies = [ "webpki", ] @@ -4126,9 +4151,9 @@ checksum = "5fc77f52dc9e9b10d55d3f4462c3b7fc393c4f17975d641542833ab2d3bc26ef" [[package]] name = "zeroize" -version = "1.5.5" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07" +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" dependencies = [ "zeroize_derive", ] diff --git a/crates/cargo-contract/Cargo.toml b/crates/cargo-contract/Cargo.toml index 39399ed3c..64ddb77dd 100644 --- a/crates/cargo-contract/Cargo.toml +++ b/crates/cargo-contract/Cargo.toml @@ -46,7 +46,7 @@ regex = "1.6.0" async-std = { version = "1.12.0", features = ["attributes", "tokio1"] } sp-core = "6.0.0" pallet-contracts-primitives = "6.0.0" -subxt = "0.23.0" +subxt = "0.24.0" hex = "0.4.3" jsonrpsee = { version = "0.15.1", features = ["ws-client"] } diff --git a/crates/cargo-contract/src/cmd/extrinsics/call.rs b/crates/cargo-contract/src/cmd/extrinsics/call.rs index 1e49a1925..e286da26c 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/call.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/call.rs @@ -210,11 +210,7 @@ impl CallCommand { self.contract.clone().into(), self.value.denominate_balance(&token_metadata)?, gas_limit, - self.extrinsic_opts - .storage_deposit_limit - .as_ref() - .map(|bv| bv.denominate_balance(&token_metadata)) - .transpose()?, + self.extrinsic_opts.storage_deposit_limit(&token_metadata)?, data, ); diff --git a/crates/cargo-contract/src/cmd/extrinsics/events.rs b/crates/cargo-contract/src/cmd/extrinsics/events.rs index 04e63b5b0..381d8e66c 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/events.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/events.rs @@ -156,9 +156,8 @@ impl DisplayEvents { pub fn display_events( &self, verbosity: Verbosity, - token_metadata: &TokenMetadata + token_metadata: &TokenMetadata, ) -> Result { - let event_field_indent: usize = DEFAULT_KEY_COL_WIDTH - 3; let mut out = format!( "{:>width$}\n", diff --git a/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs b/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs index 309cd4b05..091f64fe5 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/instantiate.rs @@ -217,6 +217,12 @@ struct InstantiateArgs { salt: Vec, } +impl InstantiateArgs { + fn storage_deposit_limit_compact(&self) -> Option> { + self.storage_deposit_limit.map(Into::into) + } +} + pub struct Exec { opts: ExtrinsicOpts, args: InstantiateArgs, @@ -292,7 +298,7 @@ impl Exec { let call = api::tx().contracts().instantiate_with_code( self.args.value, gas_limit, - self.args.storage_deposit_limit, + self.args.storage_deposit_limit_compact(), code.to_vec(), self.args.data.clone(), self.args.salt.clone(), @@ -309,7 +315,7 @@ impl Exec { .find_first::()? .ok_or_else(|| anyhow!("Failed to find Instantiated event"))?; - let token_metadata = TokenMetadata::query(&self.client).await?; + let token_metadata = TokenMetadata::query(&self.client).await?; self.display_result(&result, code_hash, instantiated.contract, &token_metadata) .await } @@ -333,7 +339,7 @@ impl Exec { let call = api::tx().contracts().instantiate( self.args.value, gas_limit, - self.args.storage_deposit_limit, + self.args.storage_deposit_limit_compact(), code_hash, self.args.data.clone(), self.args.salt.clone(), @@ -355,7 +361,7 @@ impl Exec { result: &TxEvents, code_hash: Option, contract_address: sp_core::crypto::AccountId32, - token_metadata: &TokenMetadata + token_metadata: &TokenMetadata, ) -> Result<(), ErrorVariant> { let events = DisplayEvents::from_events( result, @@ -376,10 +382,7 @@ impl Exec { name_value_println!("Code hash", format!("{:?}", code_hash)); } name_value_println!("Contract", contract_address); - println!( - "{}", - events.display_events(self.verbosity, token_metadata)? - ) + println!("{}", events.display_events(self.verbosity, token_metadata)?) }; Ok(()) } diff --git a/crates/cargo-contract/src/cmd/extrinsics/mod.rs b/crates/cargo-contract/src/cmd/extrinsics/mod.rs index 061bd711a..b93a464a7 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/mod.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/mod.rs @@ -146,6 +146,19 @@ impl ExtrinsicOpts { _ => res, } } + + /// Get the storage deposit limit converted to compact for passing to extrinsics. + pub fn storage_deposit_limit( + &self, + token_metadata: &TokenMetadata, + ) -> Result>> { + Ok(self + .storage_deposit_limit + .as_ref() + .map(|bv| bv.denominate_balance(token_metadata)) + .transpose()? + .map(Into::into)) + } } /// Parse Rust style integer balance literals which can contain underscores. diff --git a/crates/cargo-contract/src/cmd/extrinsics/upload.rs b/crates/cargo-contract/src/cmd/extrinsics/upload.rs index 2bf23f708..b1e4c2918 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/upload.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/upload.rs @@ -162,12 +162,8 @@ impl UploadCommand { transcoder: &ContractMessageTranscoder, ) -> Result, ErrorVariant> { let token_metadata = TokenMetadata::query(client).await?; - let storage_deposit_limit = self - .extrinsic_opts - .storage_deposit_limit - .as_ref() - .map(|bv| bv.denominate_balance(&token_metadata)) - .transpose()?; + let storage_deposit_limit = + self.extrinsic_opts.storage_deposit_limit(&token_metadata)?; let call = super::runtime_api::api::tx() .contracts() .upload_code(code, storage_deposit_limit); From 130cdfce55b81cfc7fb23866b94a318f18600d2b Mon Sep 17 00:00:00 2001 From: SkymanOne Date: Sun, 25 Sep 2022 23:43:41 +0100 Subject: [PATCH 08/20] replace f64 with rust_decimal --- Cargo.lock | 23 ++++++++++ crates/cargo-contract/Cargo.toml | 2 + .../src/cmd/extrinsics/balance.rs | 45 ++++++++++++------- 3 files changed, 55 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 76cd5066f..2c71428b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -487,6 +487,8 @@ dependencies = [ "predicates", "pretty_assertions", "regex", + "rust_decimal", + "rust_decimal_macros", "rustc_version", "semver", "serde", @@ -2566,6 +2568,27 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc874b127765f014d792f16763a81245ab80500e2ad921ed4ee9e82481ee08fe" +[[package]] +name = "rust_decimal" +version = "1.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee9164faf726e4f3ece4978b25ca877ddc6802fa77f38cdccb32c7f805ecd70c" +dependencies = [ + "arrayvec 0.7.2", + "num-traits", + "serde", +] + +[[package]] +name = "rust_decimal_macros" +version = "1.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4903d8db81d2321699ca8318035d6ff805c548868df435813968795a802171b2" +dependencies = [ + "quote", + "rust_decimal", +] + [[package]] name = "rustc-demangle" version = "0.1.21" diff --git a/crates/cargo-contract/Cargo.toml b/crates/cargo-contract/Cargo.toml index 64ddb77dd..3302b94c6 100644 --- a/crates/cargo-contract/Cargo.toml +++ b/crates/cargo-contract/Cargo.toml @@ -41,6 +41,8 @@ tempfile = "3.3.0" url = { version = "2.3.1", features = ["serde"] } impl-serde = "0.4.0" regex = "1.6.0" +rust_decimal = "1.26" +rust_decimal_macros = "1.26" # dependencies for extrinsics (deploying and calling a contract) async-std = { version = "1.12.0", features = ["attributes", "tokio1"] } diff --git a/crates/cargo-contract/src/cmd/extrinsics/balance.rs b/crates/cargo-contract/src/cmd/extrinsics/balance.rs index d9e19927a..9ee727468 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/balance.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/balance.rs @@ -14,8 +14,16 @@ // You should have received a copy of the GNU General Public License // along with cargo-contract. If not, see . -use std::fmt::Display; +use std::{ + fmt::Display, + str::FromStr, +}; +use rust_decimal::{ + self, + Decimal, +}; +use rust_decimal_macros::dec; use serde_json::json; use super::{ @@ -82,36 +90,43 @@ impl BalanceVariant { if let Some(balance_str) = input.strip_suffix(&format!("k{}", token_metadata.symbol)) { - let balance: f64 = balance_str.parse()?; - Ok((balance * 1_000.0) as Balance * token_metadata.denomination) + let balance = Decimal::from_str(balance_str)?; + Ok(::try_from(balance * dec!(1_000))? + * token_metadata.denomination) } else if let Some(balance_str) = input.strip_suffix(&format!("M{}", token_metadata.symbol)) { - let balance: f64 = balance_str.parse()?; - Ok((balance * 1_000_000.0) as Balance * token_metadata.denomination) + let balance = Decimal::from_str(balance_str)?; + Ok(::try_from(balance * dec!(1_000_000))? + * token_metadata.denomination) } else if let Some(balance_str) = input.strip_suffix(&format!("n{}", token_metadata.symbol)) { - let balance: f64 = balance_str.parse()?; - Ok((balance * 1_000_000_000.0) as Balance) + let balance = Decimal::from_str(balance_str)?; + Ok(::try_from(balance * dec!(1_000_000_000))? + * token_metadata.denomination) } else if let Some(balance_str) = input.strip_suffix(&format!("μ{}", token_metadata.symbol)) { - let balance: f64 = balance_str.parse()?; - Ok((balance * 1_000_000.0) as Balance) + let balance = Decimal::from_str(balance_str)?; + Ok(::try_from(balance * dec!(1_000_000))?) } else if let Some(balance_str) = input.strip_suffix(&format!("m{}", token_metadata.symbol)) { - let balance: f64 = balance_str.parse()?; - Ok((balance * 1_000.0) as Balance) + let balance = Decimal::from_str(balance_str)?; + Ok(::try_from(balance * dec!(1_000))?) } else if let Some(balance_str) = input.strip_suffix(&token_metadata.symbol) { - let balance: f64 = balance_str.parse()?; - Ok((balance * token_metadata.denomination as f64) as Balance) + let balance = Decimal::from_str(balance_str)?; + Ok(::try_from( + balance * Decimal::from(token_metadata.denomination), + )?) } else { - let balance: f64 = input.parse()?; - Ok((balance * token_metadata.denomination as f64) as Balance) + let balance = Decimal::from_str(input)?; + Ok(::try_from( + balance * Decimal::from(token_metadata.denomination), + )?) } } } From af9c9bc3d08dcf421f6bc650c3024b8de16f3036 Mon Sep 17 00:00:00 2001 From: SkymanOne Date: Tue, 27 Sep 2022 23:42:29 +0100 Subject: [PATCH 09/20] more comprehensive denomination --- Cargo.lock | 11 - crates/cargo-contract/Cargo.toml | 1 - .../src/cmd/extrinsics/balance.rs | 431 +++++++++++++----- .../src/cmd/extrinsics/events.rs | 2 +- .../cargo-contract/src/cmd/extrinsics/mod.rs | 6 +- 5 files changed, 321 insertions(+), 130 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 67a5a7b04..bc630f1d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -488,7 +488,6 @@ dependencies = [ "pretty_assertions", "regex", "rust_decimal", - "rust_decimal_macros", "rustc_version", "semver", "serde", @@ -2579,16 +2578,6 @@ dependencies = [ "serde", ] -[[package]] -name = "rust_decimal_macros" -version = "1.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4903d8db81d2321699ca8318035d6ff805c548868df435813968795a802171b2" -dependencies = [ - "quote", - "rust_decimal", -] - [[package]] name = "rustc-demangle" version = "0.1.21" diff --git a/crates/cargo-contract/Cargo.toml b/crates/cargo-contract/Cargo.toml index 9a724a23b..2f4d510ba 100644 --- a/crates/cargo-contract/Cargo.toml +++ b/crates/cargo-contract/Cargo.toml @@ -42,7 +42,6 @@ url = { version = "2.3.1", features = ["serde"] } impl-serde = "0.4.0" regex = "1.6.0" rust_decimal = "1.26" -rust_decimal_macros = "1.26" # dependencies for extrinsics (deploying and calling a contract) async-std = { version = "1.12.0", features = ["attributes", "tokio1"] } diff --git a/crates/cargo-contract/src/cmd/extrinsics/balance.rs b/crates/cargo-contract/src/cmd/extrinsics/balance.rs index 9ee727468..d952211c5 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/balance.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/balance.rs @@ -14,16 +14,13 @@ // You should have received a copy of the GNU General Public License // along with cargo-contract. If not, see . -use std::{ - fmt::Display, - str::FromStr, -}; +use std::fmt::Display; use rust_decimal::{ self, + prelude::FromPrimitive, Decimal, }; -use rust_decimal_macros::dec; use serde_json::json; use super::{ @@ -43,17 +40,35 @@ pub enum BalanceVariant { /// Default format: no symbol, no denomination Default(Balance), /// Denominated format: symbol and denomination are present - Denominated(String), + Denominated(DenominatedBalance), } #[derive(Debug, Clone)] pub struct TokenMetadata { /// Number of denomination used for denomination - pub denomination: u128, + pub denomination: usize, /// Token symbol pub symbol: String, } +#[derive(Debug, Clone)] +pub struct DenominatedBalance { + value: Decimal, + unit: UnitPrefix, + symbol: String, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum UnitPrefix { + Giga, + Mega, + Kilo, + One, + Milli, + Micro, + Nano, +} + impl TokenMetadata { /// Query [TokenMetadata] through the node's RPC pub async fn query(client: &Client) -> Result { @@ -61,17 +76,17 @@ impl TokenMetadata { let default_decimals = json!(12); let default_units = json!("UNIT"); - let decimals = sys_props + let denomination = sys_props .get("tokenDecimal") .unwrap_or(&default_decimals) .as_u64() - .context("error converting decimal to u64")?; + .context("error converting decimal to u64")? + as usize; let symbol = sys_props .get("tokenSymbol") .unwrap_or(&default_units) .as_str() .context("error converting symbol to string")?; - let denomination: u128 = format!("1{}", "0".repeat(decimals as usize)).parse()?; Ok(Self { denomination, symbol: symbol.to_string(), @@ -79,6 +94,44 @@ impl TokenMetadata { } } +impl TryFrom for DenominatedBalance { + type Error = anyhow::Error; + + fn try_from(value: String) -> Result { + let symbols = value + .trim_start_matches(|ch: char| ch.is_numeric() || ch == '.' || ch == ','); + let unit_char = symbols + .chars() + .next() + .context("no units or symbols present")?; + let unit: UnitPrefix = match unit_char { + 'G' => UnitPrefix::Giga, + 'M' => UnitPrefix::Mega, + 'K' => UnitPrefix::Kilo, + 'm' => UnitPrefix::Milli, + '\u{3bc}' => UnitPrefix::Micro, + 'n' => UnitPrefix::Nano, + _ => UnitPrefix::One, + }; + let symbol = if unit != UnitPrefix::One { + let (start, _) = symbols + .char_indices() + .nth(1) + .context("cannot find the first char's index")?; + symbols[start..].to_string() + } else { + String::new() + }; + let value = value.trim_end_matches(|ch: char| ch.is_alphabetic()); + let value = Decimal::from_str_exact(value)?; + Ok(Self { + value, + unit, + symbol, + }) + } +} + impl BalanceVariant { /// Converts BalanceVariant into Balance. /// @@ -86,103 +139,118 @@ impl BalanceVariant { pub fn denominate_balance(&self, token_metadata: &TokenMetadata) -> Result { match self { BalanceVariant::Default(balance) => Ok(*balance), - BalanceVariant::Denominated(input) => { - if let Some(balance_str) = - input.strip_suffix(&format!("k{}", token_metadata.symbol)) - { - let balance = Decimal::from_str(balance_str)?; - Ok(::try_from(balance * dec!(1_000))? - * token_metadata.denomination) - } else if let Some(balance_str) = - input.strip_suffix(&format!("M{}", token_metadata.symbol)) - { - let balance = Decimal::from_str(balance_str)?; - Ok(::try_from(balance * dec!(1_000_000))? - * token_metadata.denomination) - } else if let Some(balance_str) = - input.strip_suffix(&format!("n{}", token_metadata.symbol)) - { - let balance = Decimal::from_str(balance_str)?; - Ok(::try_from(balance * dec!(1_000_000_000))? - * token_metadata.denomination) - } else if let Some(balance_str) = - input.strip_suffix(&format!("μ{}", token_metadata.symbol)) - { - let balance = Decimal::from_str(balance_str)?; - Ok(::try_from(balance * dec!(1_000_000))?) - } else if let Some(balance_str) = - input.strip_suffix(&format!("m{}", token_metadata.symbol)) - { - let balance = Decimal::from_str(balance_str)?; - Ok(::try_from(balance * dec!(1_000))?) - } else if let Some(balance_str) = - input.strip_suffix(&token_metadata.symbol) - { - let balance = Decimal::from_str(balance_str)?; - Ok(::try_from( - balance * Decimal::from(token_metadata.denomination), - )?) - } else { - let balance = Decimal::from_str(input)?; - Ok(::try_from( - balance * Decimal::from(token_metadata.denomination), - )?) - } + BalanceVariant::Denominated(den_balance) => { + let zeros: usize = (token_metadata.denomination as isize + + match den_balance.unit { + UnitPrefix::Giga => 9, + UnitPrefix::Mega => 6, + UnitPrefix::Kilo => 3, + UnitPrefix::One => 0, + UnitPrefix::Milli => -3, + UnitPrefix::Micro => -6, + UnitPrefix::Nano => -9, + }) + .try_into()?; + let multiple = + Decimal::from_str_exact(&format!("1{}", "0".repeat(zeros)))?; + let balance: Balance = (den_balance.value * multiple).try_into()?; + Ok(balance) } } } /// Display token units in a denominated format. - pub fn from>(value: T, token_metadata: Option<&TokenMetadata>) -> Self { + pub fn from>( + value: T, + token_metadata: Option<&TokenMetadata>, + ) -> Result { let n: u128 = value.into(); if let Some(token_metadata) = token_metadata { if n == 0 { - return BalanceVariant::Denominated(format!("0{}", token_metadata.symbol)) + return Ok(BalanceVariant::Denominated(DenominatedBalance { + value: Decimal::ZERO, + unit: UnitPrefix::One, + symbol: token_metadata.symbol.clone(), + })) } - let units_result = n / token_metadata.denomination; - let mut symbol = ""; - let remainder: u128; - let units: u128; - if (1..1_000).contains(&units_result) { - remainder = n % token_metadata.denomination; - units = units_result; - } else if (1_000..1_000_000).contains(&units_result) { - remainder = units_result % 1_000; - units = units_result / 1_000; - symbol = "k"; - } else if (1_000_000..1_000_000_000).contains(&units_result) { - remainder = units_result % 1_000_000; - units = units_result / 1_000_000; - symbol = "M"; - } else if n / 1_000_000_000 > 0 { - remainder = n % 1_000_000_000; - units = n / 1_000_000_000; - symbol = "n"; - } else if n / 1_000_000 > 0 { - remainder = n % 1_000_000; - units = n / 1_000_000; - symbol = "μ"; - } else { - remainder = n % 1_000; - units = n / 1_000; - symbol = "m"; - } - if remainder > 0 { - let remainder = remainder.to_string().trim_end_matches('0').to_owned(); - BalanceVariant::Denominated(format!( - "{}.{}{}{}", - units, remainder, symbol, token_metadata.symbol - )) + let number_of_digits = n.to_string().len(); + + let giga_units_zeros = token_metadata.denomination + 9; + let mega_units_zeros = token_metadata.denomination + 6; + let kilo_units_zeros = token_metadata.denomination + 3; + let one_unit_zeros = token_metadata.denomination; + let milli_units_zeros = token_metadata.denomination - 3; + let micro_units_zeros = token_metadata.denomination - 6; + let nano_units_zeros = token_metadata.denomination - 9; + + let multiple: Decimal; + let unit: UnitPrefix; + if number_of_digits > giga_units_zeros { + multiple = Decimal::from_str_exact(&format!( + "1{}", + "0".repeat(giga_units_zeros) + ))?; + unit = UnitPrefix::Giga; + } else if number_of_digits <= giga_units_zeros + && number_of_digits > mega_units_zeros + { + multiple = Decimal::from_str_exact(&format!( + "1{}", + "0".repeat(mega_units_zeros) + ))?; + unit = UnitPrefix::Mega; + } else if number_of_digits <= mega_units_zeros + && number_of_digits > kilo_units_zeros + { + multiple = Decimal::from_str_exact(&format!( + "1{}", + "0".repeat(kilo_units_zeros) + ))?; + unit = UnitPrefix::Mega; + } else if number_of_digits <= kilo_units_zeros + && number_of_digits > one_unit_zeros + { + multiple = + Decimal::from_str_exact(&format!("1{}", "0".repeat(one_unit_zeros)))?; + unit = UnitPrefix::Mega; + } else if number_of_digits <= one_unit_zeros + && number_of_digits > milli_units_zeros + { + multiple = Decimal::from_str_exact(&format!( + "1{}", + "0".repeat(milli_units_zeros) + ))?; + unit = UnitPrefix::Mega; + } else if number_of_digits <= milli_units_zeros + && number_of_digits > micro_units_zeros + { + multiple = Decimal::from_str_exact(&format!( + "1{}", + "0".repeat(micro_units_zeros) + ))?; + unit = UnitPrefix::Mega; } else { - BalanceVariant::Denominated(format!( - "{}{}{}", - units, symbol, token_metadata.symbol - )) + multiple = Decimal::from_str_exact(&format!( + "1{}", + "0".repeat(nano_units_zeros) + ))?; + unit = UnitPrefix::Mega; } + let value = Decimal::from_u128(n) + .context("value can not be converted into decimal")? + / multiple; + + let den_balance = DenominatedBalance { + value, + unit, + symbol: token_metadata.symbol.clone(), + }; + + Ok(BalanceVariant::Denominated(den_balance)) } else { - BalanceVariant::Default(n) + Ok(BalanceVariant::Default(n)) } } } @@ -191,11 +259,26 @@ impl Display for BalanceVariant { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { BalanceVariant::Default(balance) => f.write_str(&balance.to_string()), - BalanceVariant::Denominated(input) => f.write_str(input), + BalanceVariant::Denominated(input) => f.write_str(&input.to_string()), } } } +impl Display for DenominatedBalance { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let prefix = match self.unit { + UnitPrefix::Giga => "G", + UnitPrefix::Mega => "M", + UnitPrefix::Kilo => "K", + UnitPrefix::One => "", + UnitPrefix::Milli => "m", + UnitPrefix::Micro => "μ", + UnitPrefix::Nano => "n", + }; + f.write_fmt(format_args!("{}{}{}", self.value, prefix, self.symbol)) + } +} + #[cfg(test)] mod tests { use crate::cmd::extrinsics::parse_balance; @@ -225,7 +308,7 @@ mod tests { #[test] fn balance_variant_denominated_success() { let tm = TokenMetadata { - denomination: 12, + denomination: 10, symbol: String::from("DOT"), }; let bv = parse_balance("500MDOT").expect("successful parsing. qed"); @@ -236,54 +319,170 @@ mod tests { } #[test] - fn balance_variant_denominated_incorrect_token() { + fn balance_variant_denominated_equal() { + let decimals = 10; let tm = TokenMetadata { - denomination: 12, + denomination: decimals, symbol: String::from("DOT"), }; - let bv = parse_balance("500MKSM").expect("successful parsing. qed"); - assert!( - bv.denominate_balance(&tm).is_err(), - "balances denominated should fail because of an incorrect token" - ); + let balance: Balance = 500 * 1_000_000 * 10_000_000_000; + let bv = parse_balance("500MDOT").expect("successful parsing. qed"); + let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); + assert_eq!(balance, balance_parsed); } #[test] - fn balance_variant_denominated_equal() { - let denomination: u128 = format!("1{}", "0".repeat(12)).parse().unwrap(); + fn balance_variant_denominated_equal_fraction() { + let decimals = 10; let tm = TokenMetadata { - denomination, + denomination: decimals, symbol: String::from("DOT"), }; - let balance: Balance = 500 * 1_000_000 * denomination; - let bv = parse_balance("500MDOT").expect("successful parsing. qed"); + let balance: Balance = 5_005_000_000_000_000_000; + let bv = parse_balance("500.5MDOT").expect("successful parsing. qed"); let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); assert_eq!(balance, balance_parsed); } #[test] - fn balance_variant_denominated_equal_fraction() { - let denomination: u128 = format!("1{}", "0".repeat(12)).parse().unwrap(); + fn balance_variant_denominated_equal_small_units() { + let decimals = 10; let tm = TokenMetadata { - denomination, + denomination: decimals, symbol: String::from("DOT"), }; - let balance: Balance = (500 * 1_000_000 + 500_000) * denomination; - let bv = parse_balance("500.5MDOT").expect("successful parsing. qed"); + let balance: Balance = 5_005_000; + let bv = parse_balance("500.5μDOT").expect("successful parsing. qed"); + let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); + assert_eq!(balance, balance_parsed); + } + #[test] + fn smallest_value() { + let decimals = 10; + let tm = TokenMetadata { + denomination: decimals, + symbol: String::from("DOT"), + }; + let balance: Balance = 1; + let bv = parse_balance("0.1nDOT").expect("successful parsing. qed"); let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); assert_eq!(balance, balance_parsed); } #[test] - fn balance_variant_denominated_equal_small_units() { - let denomination: u128 = format!("1{}", "0".repeat(12)).parse().unwrap(); + fn value_less_than_precision() { + // here we test if the user tries to input the denominated balance + // which results in value less than zero + let decimals = 10; let tm = TokenMetadata { - denomination, + denomination: decimals, symbol: String::from("DOT"), }; - let balance: Balance = 500 * 1_000_000 + 500_000; + let balance: Balance = 0; + let bv = parse_balance("0.0001nDOT").expect("successful parsing. qed"); + let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); + assert_eq!(balance, balance_parsed); + } + + #[test] + fn giga() { + let decimals = 10; + let tm = TokenMetadata { + denomination: decimals, + symbol: String::from("DOT"), + }; + let balance: Balance = 5_005_000_000_000_000_000_000; + let bv = parse_balance("500.5GDOT").expect("successful parsing. qed"); + let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); + assert_eq!(balance, balance_parsed); + } + + #[test] + fn kilo() { + let decimals = 10; + let tm = TokenMetadata { + denomination: decimals, + symbol: String::from("DOT"), + }; + let balance: Balance = 5_005_000_000_000_000; + let bv = parse_balance("500.5KDOT").expect("successful parsing. qed"); + let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); + assert_eq!(balance, balance_parsed); + } + + #[test] + fn unit() { + let decimals = 10; + let tm = TokenMetadata { + denomination: decimals, + symbol: String::from("DOT"), + }; + let balance: Balance = 5_005_000_000_000; + let bv = parse_balance("500.5DOT").expect("successful parsing. qed"); + let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); + assert_eq!(balance, balance_parsed); + } + + #[test] + fn milli() { + let decimals = 10; + let tm = TokenMetadata { + denomination: decimals, + symbol: String::from("DOT"), + }; + let balance: Balance = 5_005_000_000; + let bv = parse_balance("500.5mDOT").expect("successful parsing. qed"); + let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); + assert_eq!(balance, balance_parsed); + } + #[test] + fn micro() { + let decimals = 10; + let tm = TokenMetadata { + denomination: decimals, + symbol: String::from("DOT"), + }; + let balance: Balance = 5_005_000; let bv = parse_balance("500.5μDOT").expect("successful parsing. qed"); let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); assert_eq!(balance, balance_parsed); } + #[test] + fn nano() { + let decimals = 10; + let tm = TokenMetadata { + denomination: decimals, + symbol: String::from("DOT"), + }; + let balance: Balance = 5_005; + let bv = parse_balance("500.5nDOT").expect("successful parsing. qed"); + let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); + assert_eq!(balance, balance_parsed); + } + + #[test] + fn different_digits() { + let decimals = 10; + let tm = TokenMetadata { + denomination: decimals, + symbol: String::from("DOT"), + }; + let balance: Balance = 5_235_456_210_000_000; + let bv = parse_balance("523.545621KDOT").expect("successful parsing. qed"); + let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); + assert_eq!(balance, balance_parsed); + } + + #[test] + fn non_standard_denomination() { + let decimals = 10; + let tm = TokenMetadata { + denomination: decimals, + symbol: String::from("DOT"), + }; + let balance: Balance = 50_015_000_000_000; + let bv = parse_balance("5001.5DOT").expect("successful parsing. qed"); + let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); + assert_eq!(balance, balance_parsed); + } } diff --git a/crates/cargo-contract/src/cmd/extrinsics/events.rs b/crates/cargo-contract/src/cmd/extrinsics/events.rs index 381d8e66c..f422d652d 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/events.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/events.rs @@ -181,7 +181,7 @@ impl DisplayEvents { || field.type_name == Some("BalanceOf".to_string()) { if let Value::UInt(balance) = field.value { - value = BalanceVariant::from(balance, Some(token_metadata)) + value = BalanceVariant::from(balance, Some(token_metadata))? .to_string(); } } diff --git a/crates/cargo-contract/src/cmd/extrinsics/mod.rs b/crates/cargo-contract/src/cmd/extrinsics/mod.rs index b93a464a7..2209087b9 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/mod.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/mod.rs @@ -82,6 +82,8 @@ pub use subxt::PolkadotConfig as DefaultConfig; pub use transcode::ContractMessageTranscoder; pub use upload::UploadCommand; +use self::balance::DenominatedBalance; + type Balance = u128; type CodeHash = ::Hash; type PairSigner = tx::PairSigner; @@ -165,7 +167,9 @@ impl ExtrinsicOpts { fn parse_balance(input: &str) -> Result { let input = input.replace('_', ""); if input.contains('.') || input.ends_with(|ch: char| ch.is_alphabetic()) { - Ok(BalanceVariant::Denominated(input)) + Ok(BalanceVariant::Denominated(DenominatedBalance::try_from( + input, + )?)) } else { Ok(BalanceVariant::Default(input.parse::()?)) } From e53326ad751fe6a52f6257422d7cbe78759e7d8c Mon Sep 17 00:00:00 2001 From: SkymanOne Date: Tue, 27 Sep 2022 23:50:06 +0100 Subject: [PATCH 10/20] covering edge case with small values --- .../src/cmd/extrinsics/balance.rs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/crates/cargo-contract/src/cmd/extrinsics/balance.rs b/crates/cargo-contract/src/cmd/extrinsics/balance.rs index d952211c5..216231c80 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/balance.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/balance.rs @@ -485,4 +485,30 @@ mod tests { let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); assert_eq!(balance, balance_parsed); } + + #[test] + fn small_number_of_decimals_zero() { + let decimals = 6; + let tm = TokenMetadata { + denomination: decimals, + symbol: String::from("DOT"), + }; + let balance: Balance = 0; + let bv = parse_balance("0.4μDOT").expect("successful parsing. qed"); + let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); + assert_eq!(balance, balance_parsed); + } + + #[test] + fn small_number_of_decimals_more_than_zero() { + let decimals = 6; + let tm = TokenMetadata { + denomination: decimals, + symbol: String::from("DOT"), + }; + let balance: Balance = 5; + let bv = parse_balance("5.4μDOT").expect("successful parsing. qed"); + let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); + assert_eq!(balance, balance_parsed); + } } From 3a573b72e78332fc36d48c8723b1afa39dc92363 Mon Sep 17 00:00:00 2001 From: SkymanOne Date: Wed, 28 Sep 2022 14:36:42 +0100 Subject: [PATCH 11/20] more tests and docs --- .../src/cmd/extrinsics/balance.rs | 103 ++++++++++++++---- 1 file changed, 81 insertions(+), 22 deletions(-) diff --git a/crates/cargo-contract/src/cmd/extrinsics/balance.rs b/crates/cargo-contract/src/cmd/extrinsics/balance.rs index 216231c80..079b68867 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/balance.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/balance.rs @@ -29,6 +29,7 @@ use super::{ }; use anyhow::{ + anyhow, Context, Ok, Result, @@ -123,7 +124,7 @@ impl TryFrom for DenominatedBalance { String::new() }; let value = value.trim_end_matches(|ch: char| ch.is_alphabetic()); - let value = Decimal::from_str_exact(value)?; + let value = Decimal::from_str_exact(value)?.normalize(); Ok(Self { value, unit, @@ -135,7 +136,43 @@ impl TryFrom for DenominatedBalance { impl BalanceVariant { /// Converts BalanceVariant into Balance. /// - /// Throws Error if [BalanceVariant::Denominated(String)] is in an incorrect format. + /// It is a reverse process of `from>()` + /// + /// Throws Error if `value` is of nigher precision that allowed. + /// + /// ```rust + /// use anyhow::{Result, Ok}; + /// let decimals = 6; + /// let tm = TokenMetadata { + /// denomination: decimals, + /// symbol: String::from("DOT"), + /// }; + /// let sample_den_balance = Balance::Denominated(DenominatedBalance { + /// value: Decimal::new(4, 1), + /// unit: UnitPrefix::Micro, + /// symbol: String::new("DOT") + /// }); + /// let result = sample_den_balance.denominate_balance(tm); + /// assert!(result.is_err()); + /// ``` + /// + /// Otherwise, [Balance] is returned: + /// ```rust + /// use anyhow::{Result, Ok}; + /// let decimals = 6; + /// let tm = TokenMetadata { + /// denomination: decimals, + /// symbol: String::from("DOT"), + /// }; + /// let sample_den_balance = Balance::Denominated(DenominatedBalance { + /// value: Decimal::new(4123, 0), + /// unit: UnitPrefix::Micro, + /// symbol: String::new("DOT") + /// }); + /// let balance = 4123; + /// let result = sample_den_balance.denominate_balance(tm).unwrap() + /// assert_eq!(balance, result); + /// ``` pub fn denominate_balance(&self, token_metadata: &TokenMetadata) -> Result { match self { BalanceVariant::Default(balance) => Ok(*balance), @@ -153,13 +190,50 @@ impl BalanceVariant { .try_into()?; let multiple = Decimal::from_str_exact(&format!("1{}", "0".repeat(zeros)))?; + let fract_scale = den_balance.value.fract().scale(); + let mantissa_difference = zeros as isize - fract_scale as isize; + if mantissa_difference < 0 { + return Err(anyhow!( + "Given precision of a Balance value is higher than allowed" + )) + } let balance: Balance = (den_balance.value * multiple).try_into()?; Ok(balance) } } } + /// # Summary /// Display token units in a denominated format. + /// + /// I takes `value` of `Into` and [TokenMetadata] + /// and calculates the value in an denominated format + /// by manipulating the denomination. + /// + /// If the number is divisible by 10^(`denomination` + `unit_zeros`), + /// It sets the [UnitPrefix] and divides the `value` into `Decimal` + /// + /// If no [TokenMetadata] was present, than that means + /// that [Balance] is to be displayed in *normal* format + /// and `BalanceVariant::Default` is returned + /// + /// # Examples + /// ```rust + /// use anyhow::{Result, Ok}; + /// let decimals = 10; + /// let tm = TokenMetadata { + /// denomination: decimals, + /// symbol: String::from("DOT"), + /// }; + /// let sample_den_balance = Balance::Denominated(DenominatedBalance { + /// value: Decimal::new(5005, 1), + /// unit: UnitPrefix::Mega, + /// symbol: String::new("DOT") + /// }); + /// let balance: Balance = 5_005_000_000_000_000_000; + /// let den_balance = BalanceVariant::from(balance, Some(tm)); + /// assert_eq!(Ok(sample_den_balance), Ok(den_balance)); + /// ``` pub fn from>( value: T, token_metadata: Option<&TokenMetadata>, @@ -378,10 +452,9 @@ mod tests { denomination: decimals, symbol: String::from("DOT"), }; - let balance: Balance = 0; - let bv = parse_balance("0.0001nDOT").expect("successful parsing. qed"); - let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); - assert_eq!(balance, balance_parsed); + let bv = parse_balance("0.01546nDOT").expect("successful parsing. qed"); + let balance_parsed = bv.denominate_balance(&tm); + assert!(balance_parsed.is_err()) } #[test] @@ -493,22 +566,8 @@ mod tests { denomination: decimals, symbol: String::from("DOT"), }; - let balance: Balance = 0; let bv = parse_balance("0.4μDOT").expect("successful parsing. qed"); - let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); - assert_eq!(balance, balance_parsed); - } - - #[test] - fn small_number_of_decimals_more_than_zero() { - let decimals = 6; - let tm = TokenMetadata { - denomination: decimals, - symbol: String::from("DOT"), - }; - let balance: Balance = 5; - let bv = parse_balance("5.4μDOT").expect("successful parsing. qed"); - let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); - assert_eq!(balance, balance_parsed); + let balance_parsed = bv.denominate_balance(&tm); + assert!(balance_parsed.is_err()) } } From 54a340a6566a52cd165e43ce4917b2dfce09a2f0 Mon Sep 17 00:00:00 2001 From: SkymanOne Date: Wed, 28 Sep 2022 22:23:35 +0100 Subject: [PATCH 12/20] context for balance overflows --- .../src/cmd/extrinsics/balance.rs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/crates/cargo-contract/src/cmd/extrinsics/balance.rs b/crates/cargo-contract/src/cmd/extrinsics/balance.rs index 079b68867..4e92dc1f0 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/balance.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/balance.rs @@ -124,7 +124,9 @@ impl TryFrom for DenominatedBalance { String::new() }; let value = value.trim_end_matches(|ch: char| ch.is_alphabetic()); - let value = Decimal::from_str_exact(value)?.normalize(); + let value = Decimal::from_str_exact(value) + .context("Error while parsing the value. Please denominate and normalize the balance first.")? + .normalize(); Ok(Self { value, unit, @@ -570,4 +572,20 @@ mod tests { let balance_parsed = bv.denominate_balance(&tm); assert!(balance_parsed.is_err()) } + + #[test] + fn big_input_to_denominate() { + // max value of Decimal:MAX is 79_228_162_514_264_337_593_543_950_335 + let s = "79_228_162_514_264_337_593_543_950_336DOT"; + let bv = parse_balance(s); + assert!(bv.is_err()) + } + + #[test] + fn big_input_to_raw() { + // max value of Decimal:MAX is 79_228_162_514_264_337_593_543_950_335 + let s = "79_228_162_514_264_337_593_543_950_336"; + let bv = parse_balance(s); + assert!(bv.is_ok()) + } } From 8bd6e3aab63fa5dfb32c5dcdd072c1039c56edeb Mon Sep 17 00:00:00 2001 From: SkymanOne Date: Thu, 6 Oct 2022 09:31:50 +0100 Subject: [PATCH 13/20] tested conversion from u128 --- .../src/cmd/extrinsics/balance.rs | 71 +++++++++++++------ 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/crates/cargo-contract/src/cmd/extrinsics/balance.rs b/crates/cargo-contract/src/cmd/extrinsics/balance.rs index e69da4ebb..87469d919 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/balance.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/balance.rs @@ -39,7 +39,7 @@ use anyhow::{ }; /// Represents different formats of a balance -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum BalanceVariant { /// Default format: no symbol, no denomination Default(Balance), @@ -55,7 +55,7 @@ pub struct TokenMetadata { pub symbol: String, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct DenominatedBalance { value: Decimal, unit: UnitPrefix, @@ -104,7 +104,9 @@ impl FromStr for BalanceVariant { fn from_str(input: &str) -> Result { let input = input.replace('_', ""); if input.contains('.') || input.ends_with(|ch: char| ch.is_alphabetic()) { - Ok(BalanceVariant::Denominated(DenominatedBalance::from_str(&input)?)) + Ok(BalanceVariant::Denominated(DenominatedBalance::from_str( + &input, + )?)) } else { Ok(BalanceVariant::Default(input.parse::()?)) } @@ -243,10 +245,10 @@ impl BalanceVariant { /// denomination: decimals, /// symbol: String::from("DOT"), /// }; - /// let sample_den_balance = Balance::Denominated(DenominatedBalance { + /// let sample_den_balance = BalanceVariant::Denominated(DenominatedBalance { /// value: Decimal::new(5005, 1), /// unit: UnitPrefix::Mega, - /// symbol: String::new("DOT") + /// symbol: String::from("DOT") /// }); /// let balance: Balance = 5_005_000_000_000_000_000; /// let den_balance = BalanceVariant::from(balance, Some(tm)); @@ -273,9 +275,9 @@ impl BalanceVariant { let mega_units_zeros = token_metadata.denomination + 6; let kilo_units_zeros = token_metadata.denomination + 3; let one_unit_zeros = token_metadata.denomination; - let milli_units_zeros = token_metadata.denomination - 3; - let micro_units_zeros = token_metadata.denomination - 6; - let nano_units_zeros = token_metadata.denomination - 9; + let milli_units_zeros = token_metadata.denomination.checked_sub(3); + let micro_units_zeros = token_metadata.denomination.checked_sub(6); + let nano_units_zeros = token_metadata.denomination.checked_sub(9); let multiple: Decimal; let unit: UnitPrefix; @@ -300,35 +302,40 @@ impl BalanceVariant { "1{}", "0".repeat(kilo_units_zeros) ))?; - unit = UnitPrefix::Mega; + unit = UnitPrefix::Kilo; } else if number_of_digits <= kilo_units_zeros && number_of_digits > one_unit_zeros { multiple = Decimal::from_str_exact(&format!("1{}", "0".repeat(one_unit_zeros)))?; - unit = UnitPrefix::Mega; + unit = UnitPrefix::One; } else if number_of_digits <= one_unit_zeros - && number_of_digits > milli_units_zeros + && milli_units_zeros.is_some() + && number_of_digits > milli_units_zeros.unwrap() { multiple = Decimal::from_str_exact(&format!( "1{}", - "0".repeat(milli_units_zeros) + "0".repeat(milli_units_zeros.unwrap()) ))?; - unit = UnitPrefix::Mega; - } else if number_of_digits <= milli_units_zeros - && number_of_digits > micro_units_zeros + unit = UnitPrefix::Milli; + } else if milli_units_zeros.is_some() + && micro_units_zeros.is_some() + && number_of_digits <= milli_units_zeros.unwrap() + && number_of_digits > micro_units_zeros.unwrap() { multiple = Decimal::from_str_exact(&format!( "1{}", - "0".repeat(micro_units_zeros) + "0".repeat(micro_units_zeros.unwrap()) ))?; - unit = UnitPrefix::Mega; - } else { + unit = UnitPrefix::Micro; + } else if nano_units_zeros.is_some() { multiple = Decimal::from_str_exact(&format!( "1{}", - "0".repeat(nano_units_zeros) + "0".repeat(nano_units_zeros.unwrap()) ))?; - unit = UnitPrefix::Mega; + unit = UnitPrefix::Nano; + } else { + return Err(anyhow!("Invalid denomination")) } let value = Decimal::from_u128(n) .context("value can not be converted into decimal")? @@ -468,7 +475,8 @@ mod tests { denomination: decimals, symbol: String::from("DOT"), }; - let bv = BalanceVariant::from_str("0.01546nDOT").expect("successful parsing. qed"); + let bv = + BalanceVariant::from_str("0.01546nDOT").expect("successful parsing. qed"); let balance_parsed = bv.denominate_balance(&tm); assert!(balance_parsed.is_err()) } @@ -557,7 +565,8 @@ mod tests { symbol: String::from("DOT"), }; let balance: Balance = 5_235_456_210_000_000; - let bv = BalanceVariant::from_str("523.545621KDOT").expect("successful parsing. qed"); + let bv = + BalanceVariant::from_str("523.545621KDOT").expect("successful parsing. qed"); let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); assert_eq!(balance, balance_parsed); } @@ -602,4 +611,22 @@ mod tests { let bv = BalanceVariant::from_str(s); assert!(bv.is_ok()) } + + #[test] + fn convert_from_u128() { + let decimals = 6; + let tm = TokenMetadata { + denomination: decimals, + symbol: String::from("DOT"), + }; + let balance = 532_500_000_000_u128; + let denominated_balance = + BalanceVariant::from(balance, Some(&tm)).expect("successful conversion"); + let sample = BalanceVariant::Denominated(DenominatedBalance { + value: Decimal::new(5325, 1), + unit: UnitPrefix::Kilo, + symbol: String::from("DOT"), + }); + assert_eq!(sample, denominated_balance); + } } From cd6a6a676c61bb48f69b259b3e2ddf50256156ad Mon Sep 17 00:00:00 2001 From: SkymanOne Date: Thu, 6 Oct 2022 09:46:58 +0100 Subject: [PATCH 14/20] more tests and better conditionals --- .../src/cmd/extrinsics/balance.rs | 63 +++++++++++++++---- 1 file changed, 51 insertions(+), 12 deletions(-) diff --git a/crates/cargo-contract/src/cmd/extrinsics/balance.rs b/crates/cargo-contract/src/cmd/extrinsics/balance.rs index 87469d919..5864b2b7e 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/balance.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/balance.rs @@ -281,37 +281,36 @@ impl BalanceVariant { let multiple: Decimal; let unit: UnitPrefix; - if number_of_digits > giga_units_zeros { + if (giga_units_zeros + 1..).contains(&number_of_digits) { multiple = Decimal::from_str_exact(&format!( "1{}", "0".repeat(giga_units_zeros) ))?; unit = UnitPrefix::Giga; - } else if number_of_digits <= giga_units_zeros - && number_of_digits > mega_units_zeros + } else if (mega_units_zeros + 1..=giga_units_zeros) + .contains(&number_of_digits) { multiple = Decimal::from_str_exact(&format!( "1{}", "0".repeat(mega_units_zeros) ))?; unit = UnitPrefix::Mega; - } else if number_of_digits <= mega_units_zeros - && number_of_digits > kilo_units_zeros + } else if (kilo_units_zeros + 1..=mega_units_zeros) + .contains(&number_of_digits) { multiple = Decimal::from_str_exact(&format!( "1{}", "0".repeat(kilo_units_zeros) ))?; unit = UnitPrefix::Kilo; - } else if number_of_digits <= kilo_units_zeros - && number_of_digits > one_unit_zeros + } else if (one_unit_zeros + 1..=kilo_units_zeros).contains(&number_of_digits) { multiple = Decimal::from_str_exact(&format!("1{}", "0".repeat(one_unit_zeros)))?; unit = UnitPrefix::One; - } else if number_of_digits <= one_unit_zeros - && milli_units_zeros.is_some() - && number_of_digits > milli_units_zeros.unwrap() + } else if milli_units_zeros.is_some() + && (milli_units_zeros.unwrap() + 1..=one_unit_zeros) + .contains(&number_of_digits) { multiple = Decimal::from_str_exact(&format!( "1{}", @@ -320,8 +319,8 @@ impl BalanceVariant { unit = UnitPrefix::Milli; } else if milli_units_zeros.is_some() && micro_units_zeros.is_some() - && number_of_digits <= milli_units_zeros.unwrap() - && number_of_digits > micro_units_zeros.unwrap() + && (micro_units_zeros.unwrap() + 1..=milli_units_zeros.unwrap()) + .contains(&number_of_digits) { multiple = Decimal::from_str_exact(&format!( "1{}", @@ -629,4 +628,44 @@ mod tests { }); assert_eq!(sample, denominated_balance); } + + #[test] + fn convert_one_from_u128() { + let decimals = 10; + let tm = TokenMetadata { + denomination: decimals, + symbol: String::from("DOT"), + }; + let balance = 532_500_000_000_u128; + let denominated_balance = + BalanceVariant::from(balance, Some(&tm)).expect("successful conversion"); + let sample = BalanceVariant::Denominated(DenominatedBalance { + value: Decimal::new(5325, 2), + unit: UnitPrefix::One, + symbol: String::from("DOT"), + }); + assert_eq!(sample, denominated_balance); + } + + #[test] + fn convert_small_from_u128() { + let decimals = 10; + let tm = TokenMetadata { + denomination: decimals, + symbol: String::from("DOT"), + }; + // 10_000_000_000 - One + // 10_000_000 - Milli + // 10_000 - Micro + // 532_500 - 52.25 Micro + let balance = 532_500_u128; + let denominated_balance = + BalanceVariant::from(balance, Some(&tm)).expect("successful conversion"); + let sample = BalanceVariant::Denominated(DenominatedBalance { + value: Decimal::new(5325, 2), + unit: UnitPrefix::Micro, + symbol: String::from("DOT"), + }); + assert_eq!(sample, denominated_balance); + } } From 7e1336d5e573c9d503d27806b8868f4c86cafe19 Mon Sep 17 00:00:00 2001 From: SkymanOne Date: Thu, 6 Oct 2022 09:51:10 +0100 Subject: [PATCH 15/20] include suggestions from review --- .../src/cmd/extrinsics/balance.rs | 78 +++++++++---------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/crates/cargo-contract/src/cmd/extrinsics/balance.rs b/crates/cargo-contract/src/cmd/extrinsics/balance.rs index 5864b2b7e..09909ba87 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/balance.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/balance.rs @@ -41,16 +41,16 @@ use anyhow::{ /// Represents different formats of a balance #[derive(Debug, Clone, PartialEq, Eq)] pub enum BalanceVariant { - /// Default format: no symbol, no denomination + /// Default format: no symbol, no token_decimals Default(Balance), - /// Denominated format: symbol and denomination are present + /// Denominated format: symbol and token_decimals are present Denominated(DenominatedBalance), } #[derive(Debug, Clone)] pub struct TokenMetadata { - /// Number of denomination used for denomination - pub denomination: usize, + /// Number of token_decimals used for denomination + pub token_decimals: usize, /// Token symbol pub symbol: String, } @@ -80,8 +80,8 @@ impl TokenMetadata { let default_decimals = json!(12); let default_units = json!("UNIT"); - let denomination = sys_props - .get("tokenDecimal") + let token_decimals = sys_props + .get("tokenDecimals") .unwrap_or(&default_decimals) .as_u64() .context("error converting decimal to u64")? @@ -92,7 +92,7 @@ impl TokenMetadata { .as_str() .context("error converting symbol to string")?; Ok(Self { - denomination, + token_decimals, symbol: symbol.to_string(), }) } @@ -164,7 +164,7 @@ impl BalanceVariant { /// use anyhow::{Result, Ok}; /// let decimals = 6; /// let tm = TokenMetadata { - /// denomination: decimals, + /// token_decimals: decimals, /// symbol: String::from("DOT"), /// }; /// let sample_den_balance = Balance::Denominated(DenominatedBalance { @@ -181,7 +181,7 @@ impl BalanceVariant { /// use anyhow::{Result, Ok}; /// let decimals = 6; /// let tm = TokenMetadata { - /// denomination: decimals, + /// token_decimals: decimals, /// symbol: String::from("DOT"), /// }; /// let sample_den_balance = Balance::Denominated(DenominatedBalance { @@ -197,7 +197,7 @@ impl BalanceVariant { match self { BalanceVariant::Default(balance) => Ok(*balance), BalanceVariant::Denominated(den_balance) => { - let zeros: usize = (token_metadata.denomination as isize + let zeros: usize = (token_metadata.token_decimals as isize + match den_balance.unit { UnitPrefix::Giga => 9, UnitPrefix::Mega => 6, @@ -228,9 +228,9 @@ impl BalanceVariant { /// /// I takes `value` of `Into` and [TokenMetadata] /// and calculates the value in an denominated format - /// by manipulating the denomination. + /// by manipulating the token_decimals. /// - /// If the number is divisible by 10^(`denomination` + `unit_zeros`), + /// If the number is divisible by 10^(`token_decimals` + `unit_zeros`), /// It sets the [UnitPrefix] and divides the `value` into `Decimal` /// /// If no [TokenMetadata] was present, than that means @@ -242,7 +242,7 @@ impl BalanceVariant { /// use anyhow::{Result, Ok}; /// let decimals = 10; /// let tm = TokenMetadata { - /// denomination: decimals, + /// token_decimals: decimals, /// symbol: String::from("DOT"), /// }; /// let sample_den_balance = BalanceVariant::Denominated(DenominatedBalance { @@ -271,13 +271,13 @@ impl BalanceVariant { let number_of_digits = n.to_string().len(); - let giga_units_zeros = token_metadata.denomination + 9; - let mega_units_zeros = token_metadata.denomination + 6; - let kilo_units_zeros = token_metadata.denomination + 3; - let one_unit_zeros = token_metadata.denomination; - let milli_units_zeros = token_metadata.denomination.checked_sub(3); - let micro_units_zeros = token_metadata.denomination.checked_sub(6); - let nano_units_zeros = token_metadata.denomination.checked_sub(9); + let giga_units_zeros = token_metadata.token_decimals + 9; + let mega_units_zeros = token_metadata.token_decimals + 6; + let kilo_units_zeros = token_metadata.token_decimals + 3; + let one_unit_zeros = token_metadata.token_decimals; + let milli_units_zeros = token_metadata.token_decimals.checked_sub(3); + let micro_units_zeros = token_metadata.token_decimals.checked_sub(6); + let nano_units_zeros = token_metadata.token_decimals.checked_sub(9); let multiple: Decimal; let unit: UnitPrefix; @@ -404,7 +404,7 @@ mod tests { #[test] fn balance_variant_denominated_success() { let tm = TokenMetadata { - denomination: 10, + token_decimals: 10, symbol: String::from("DOT"), }; let bv = BalanceVariant::from_str("500MDOT").expect("successful parsing. qed"); @@ -418,7 +418,7 @@ mod tests { fn balance_variant_denominated_equal() { let decimals = 10; let tm = TokenMetadata { - denomination: decimals, + token_decimals: decimals, symbol: String::from("DOT"), }; let balance: Balance = 500 * 1_000_000 * 10_000_000_000; @@ -431,7 +431,7 @@ mod tests { fn balance_variant_denominated_equal_fraction() { let decimals = 10; let tm = TokenMetadata { - denomination: decimals, + token_decimals: decimals, symbol: String::from("DOT"), }; let balance: Balance = 5_005_000_000_000_000_000; @@ -444,7 +444,7 @@ mod tests { fn balance_variant_denominated_equal_small_units() { let decimals = 10; let tm = TokenMetadata { - denomination: decimals, + token_decimals: decimals, symbol: String::from("DOT"), }; let balance: Balance = 5_005_000; @@ -456,7 +456,7 @@ mod tests { fn smallest_value() { let decimals = 10; let tm = TokenMetadata { - denomination: decimals, + token_decimals: decimals, symbol: String::from("DOT"), }; let balance: Balance = 1; @@ -471,7 +471,7 @@ mod tests { // which results in value less than zero let decimals = 10; let tm = TokenMetadata { - denomination: decimals, + token_decimals: decimals, symbol: String::from("DOT"), }; let bv = @@ -484,7 +484,7 @@ mod tests { fn giga() { let decimals = 10; let tm = TokenMetadata { - denomination: decimals, + token_decimals: decimals, symbol: String::from("DOT"), }; let balance: Balance = 5_005_000_000_000_000_000_000; @@ -497,7 +497,7 @@ mod tests { fn kilo() { let decimals = 10; let tm = TokenMetadata { - denomination: decimals, + token_decimals: decimals, symbol: String::from("DOT"), }; let balance: Balance = 5_005_000_000_000_000; @@ -510,7 +510,7 @@ mod tests { fn unit() { let decimals = 10; let tm = TokenMetadata { - denomination: decimals, + token_decimals: decimals, symbol: String::from("DOT"), }; let balance: Balance = 5_005_000_000_000; @@ -523,7 +523,7 @@ mod tests { fn milli() { let decimals = 10; let tm = TokenMetadata { - denomination: decimals, + token_decimals: decimals, symbol: String::from("DOT"), }; let balance: Balance = 5_005_000_000; @@ -535,7 +535,7 @@ mod tests { fn micro() { let decimals = 10; let tm = TokenMetadata { - denomination: decimals, + token_decimals: decimals, symbol: String::from("DOT"), }; let balance: Balance = 5_005_000; @@ -547,7 +547,7 @@ mod tests { fn nano() { let decimals = 10; let tm = TokenMetadata { - denomination: decimals, + token_decimals: decimals, symbol: String::from("DOT"), }; let balance: Balance = 5_005; @@ -560,7 +560,7 @@ mod tests { fn different_digits() { let decimals = 10; let tm = TokenMetadata { - denomination: decimals, + token_decimals: decimals, symbol: String::from("DOT"), }; let balance: Balance = 5_235_456_210_000_000; @@ -571,10 +571,10 @@ mod tests { } #[test] - fn non_standard_denomination() { + fn non_standard_token_decimals() { let decimals = 10; let tm = TokenMetadata { - denomination: decimals, + token_decimals: decimals, symbol: String::from("DOT"), }; let balance: Balance = 50_015_000_000_000; @@ -587,7 +587,7 @@ mod tests { fn small_number_of_decimals_zero() { let decimals = 6; let tm = TokenMetadata { - denomination: decimals, + token_decimals: decimals, symbol: String::from("DOT"), }; let bv = BalanceVariant::from_str("0.4μDOT").expect("successful parsing. qed"); @@ -615,7 +615,7 @@ mod tests { fn convert_from_u128() { let decimals = 6; let tm = TokenMetadata { - denomination: decimals, + token_decimals: decimals, symbol: String::from("DOT"), }; let balance = 532_500_000_000_u128; @@ -633,7 +633,7 @@ mod tests { fn convert_one_from_u128() { let decimals = 10; let tm = TokenMetadata { - denomination: decimals, + token_decimals: decimals, symbol: String::from("DOT"), }; let balance = 532_500_000_000_u128; @@ -651,7 +651,7 @@ mod tests { fn convert_small_from_u128() { let decimals = 10; let tm = TokenMetadata { - denomination: decimals, + token_decimals: decimals, symbol: String::from("DOT"), }; // 10_000_000_000 - One From 569e8ae0d787e0ad8170e4839efa6686d902f510 Mon Sep 17 00:00:00 2001 From: SkymanOne Date: Thu, 13 Oct 2022 00:53:36 +0100 Subject: [PATCH 16/20] apply changes from review --- .../src/cmd/extrinsics/balance.rs | 69 ++++++------------- 1 file changed, 20 insertions(+), 49 deletions(-) diff --git a/crates/cargo-contract/src/cmd/extrinsics/balance.rs b/crates/cargo-contract/src/cmd/extrinsics/balance.rs index ae236c6d8..aa03347f9 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/balance.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/balance.rs @@ -14,28 +14,14 @@ // You should have received a copy of the GNU General Public License // along with cargo-contract. If not, see . -use std::{ - fmt::Display, - str::FromStr, -}; - -use rust_decimal::{ - prelude::FromPrimitive, - Decimal, -}; +use std::{fmt::Display, str::FromStr}; + +use rust_decimal::{prelude::FromPrimitive, Decimal}; use serde_json::json; -use super::{ - Balance, - Client, -}; +use super::{Balance, Client}; -use anyhow::{ - anyhow, - Context, - Ok, - Result, -}; +use anyhow::{anyhow, Context, Ok, Result}; /// Represents different formats of a balance #[derive(Debug, Clone, PartialEq, Eq)] @@ -214,7 +200,7 @@ impl BalanceVariant { if mantissa_difference < 0 { return Err(anyhow!( "Given precision of a Balance value is higher than allowed" - )) + )); } let balance: Balance = (den_balance.value * multiple).try_into()?; Ok(balance) @@ -265,7 +251,7 @@ impl BalanceVariant { value: Decimal::ZERO, unit: UnitPrefix::One, symbol: token_metadata.symbol.clone(), - })) + })); } let number_of_digits = n.to_string().len(); @@ -278,63 +264,48 @@ impl BalanceVariant { let micro_units_zeros = token_metadata.token_decimals.checked_sub(6); let nano_units_zeros = token_metadata.token_decimals.checked_sub(9); - let multiple: Decimal; let unit: UnitPrefix; + let zeros: usize; if (giga_units_zeros + 1..).contains(&number_of_digits) { - multiple = Decimal::from_str_exact(&format!( - "1{}", - "0".repeat(giga_units_zeros) - ))?; + zeros = giga_units_zeros; unit = UnitPrefix::Giga; } else if (mega_units_zeros + 1..=giga_units_zeros) .contains(&number_of_digits) { - multiple = Decimal::from_str_exact(&format!( - "1{}", - "0".repeat(mega_units_zeros) - ))?; + zeros = mega_units_zeros; unit = UnitPrefix::Mega; } else if (kilo_units_zeros + 1..=mega_units_zeros) .contains(&number_of_digits) { - multiple = Decimal::from_str_exact(&format!( - "1{}", - "0".repeat(kilo_units_zeros) - ))?; + zeros = kilo_units_zeros; unit = UnitPrefix::Kilo; } else if (one_unit_zeros + 1..=kilo_units_zeros).contains(&number_of_digits) { - multiple = - Decimal::from_str_exact(&format!("1{}", "0".repeat(one_unit_zeros)))?; + zeros = one_unit_zeros; unit = UnitPrefix::One; } else if milli_units_zeros.is_some() && (milli_units_zeros.unwrap() + 1..=one_unit_zeros) .contains(&number_of_digits) { - multiple = Decimal::from_str_exact(&format!( - "1{}", - "0".repeat(milli_units_zeros.unwrap()) - ))?; + zeros = milli_units_zeros.expect("the number is checked to be >= 0. qed"); unit = UnitPrefix::Milli; } else if milli_units_zeros.is_some() && micro_units_zeros.is_some() && (micro_units_zeros.unwrap() + 1..=milli_units_zeros.unwrap()) .contains(&number_of_digits) { - multiple = Decimal::from_str_exact(&format!( - "1{}", - "0".repeat(micro_units_zeros.unwrap()) - ))?; + zeros = micro_units_zeros.expect("the number is checked to be >= 0. qed"); unit = UnitPrefix::Micro; } else if nano_units_zeros.is_some() { - multiple = Decimal::from_str_exact(&format!( - "1{}", - "0".repeat(nano_units_zeros.unwrap()) - ))?; + zeros = nano_units_zeros.expect("the number is checked to be >= 0. qed"); unit = UnitPrefix::Nano; } else { - return Err(anyhow!("Invalid denomination")) + return Err(anyhow!("Invalid denomination")); } + let multiple = Decimal::from_str_exact(&format!( + "1{}", + "0".repeat(zeros) + ))?; let value = Decimal::from_u128(n) .context("value can not be converted into decimal")? / multiple; From 522d807ed6ce2009b8668fce4117667c46203149 Mon Sep 17 00:00:00 2001 From: SkymanOne Date: Thu, 13 Oct 2022 01:02:14 +0100 Subject: [PATCH 17/20] inline unwrap and formatting --- .../src/cmd/extrinsics/balance.rs | 50 +++++++++++++------ 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/crates/cargo-contract/src/cmd/extrinsics/balance.rs b/crates/cargo-contract/src/cmd/extrinsics/balance.rs index aa03347f9..2c2680bd5 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/balance.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/balance.rs @@ -14,14 +14,28 @@ // You should have received a copy of the GNU General Public License // along with cargo-contract. If not, see . -use std::{fmt::Display, str::FromStr}; - -use rust_decimal::{prelude::FromPrimitive, Decimal}; +use std::{ + fmt::Display, + str::FromStr, +}; + +use rust_decimal::{ + prelude::FromPrimitive, + Decimal, +}; use serde_json::json; -use super::{Balance, Client}; +use super::{ + Balance, + Client, +}; -use anyhow::{anyhow, Context, Ok, Result}; +use anyhow::{ + anyhow, + Context, + Ok, + Result, +}; /// Represents different formats of a balance #[derive(Debug, Clone, PartialEq, Eq)] @@ -200,7 +214,7 @@ impl BalanceVariant { if mantissa_difference < 0 { return Err(anyhow!( "Given precision of a Balance value is higher than allowed" - )); + )) } let balance: Balance = (den_balance.value * multiple).try_into()?; Ok(balance) @@ -251,7 +265,7 @@ impl BalanceVariant { value: Decimal::ZERO, unit: UnitPrefix::One, symbol: token_metadata.symbol.clone(), - })); + })) } let number_of_digits = n.to_string().len(); @@ -287,25 +301,31 @@ impl BalanceVariant { && (milli_units_zeros.unwrap() + 1..=one_unit_zeros) .contains(&number_of_digits) { - zeros = milli_units_zeros.expect("the number is checked to be >= 0. qed"); + zeros = match milli_units_zeros { + Some(val) => val, + None => return Err(anyhow!("the number is checked to be >= 0. qed")), + }; unit = UnitPrefix::Milli; } else if milli_units_zeros.is_some() && micro_units_zeros.is_some() && (micro_units_zeros.unwrap() + 1..=milli_units_zeros.unwrap()) .contains(&number_of_digits) { - zeros = micro_units_zeros.expect("the number is checked to be >= 0. qed"); + zeros = match micro_units_zeros { + Some(val) => val, + None => return Err(anyhow!("the number is checked to be >= 0. qed")), + }; unit = UnitPrefix::Micro; } else if nano_units_zeros.is_some() { - zeros = nano_units_zeros.expect("the number is checked to be >= 0. qed"); + zeros = match nano_units_zeros { + Some(val) => val, + None => return Err(anyhow!("the number is checked to be >= 0. qed")), + }; unit = UnitPrefix::Nano; } else { - return Err(anyhow!("Invalid denomination")); + return Err(anyhow!("Invalid denomination")) } - let multiple = Decimal::from_str_exact(&format!( - "1{}", - "0".repeat(zeros) - ))?; + let multiple = Decimal::from_str_exact(&format!("1{}", "0".repeat(zeros)))?; let value = Decimal::from_u128(n) .context("value can not be converted into decimal")? / multiple; From c5549450e15445a0ac13ee37a869e52b43e52620 Mon Sep 17 00:00:00 2001 From: SkymanOne Date: Fri, 21 Oct 2022 21:57:09 +0100 Subject: [PATCH 18/20] more clarity in string parsing for balances --- .../src/cmd/extrinsics/balance.rs | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/crates/cargo-contract/src/cmd/extrinsics/balance.rs b/crates/cargo-contract/src/cmd/extrinsics/balance.rs index 2c2680bd5..42aef669e 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/balance.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/balance.rs @@ -16,6 +16,7 @@ use std::{ fmt::Display, + result::Result::Ok, str::FromStr, }; @@ -33,7 +34,6 @@ use super::{ use anyhow::{ anyhow, Context, - Ok, Result, }; @@ -100,15 +100,19 @@ impl TokenMetadata { impl FromStr for BalanceVariant { type Err = anyhow::Error; + /// Attempts to parse the balance either in plain or denominated formats + /// If the balance is provide without the token symbol, + /// then it is treated as raw. + /// Otherwise, the balance is attempted to be parsed in a denominated format fn from_str(input: &str) -> Result { let input = input.replace('_', ""); - if input.contains('.') || input.ends_with(|ch: char| ch.is_alphabetic()) { - Ok(BalanceVariant::Denominated(DenominatedBalance::from_str( - &input, - )?)) - } else { - Ok(BalanceVariant::Default(input.parse::()?)) - } + // if we cannot parse the balance in raw format + // it means it is in a denominated format + let result = match input.parse::() { + Ok(balance) => BalanceVariant::Default(balance), + Err(_) => BalanceVariant::Denominated(DenominatedBalance::from_str(&input)?), + }; + Ok(result) } } @@ -381,6 +385,14 @@ mod tests { BalanceVariant::from_str("500").is_ok(), "<500> was not parsed correctly" ); + assert!( + BalanceVariant::from_str("1.0").is_err(), + "<1.0> was not parsed correctly. Units must be provided" + ); + assert!( + BalanceVariant::from_str("1.0DOT").is_ok(), + "<1.0DOt> was not parsed correctly" + ); } #[test] From 5329638c90fdd234f8f9775c584ae3e3434c009c Mon Sep 17 00:00:00 2001 From: SkymanOne Date: Fri, 28 Oct 2022 14:47:59 +0200 Subject: [PATCH 19/20] checked mul and renamed Kilo symbol --- .../cargo-contract/src/cmd/extrinsics/balance.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/crates/cargo-contract/src/cmd/extrinsics/balance.rs b/crates/cargo-contract/src/cmd/extrinsics/balance.rs index 42aef669e..aa9e73995 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/balance.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/balance.rs @@ -129,7 +129,7 @@ impl FromStr for DenominatedBalance { let unit: UnitPrefix = match unit_char { 'G' => UnitPrefix::Giga, 'M' => UnitPrefix::Mega, - 'K' => UnitPrefix::Kilo, + 'k' => UnitPrefix::Kilo, 'm' => UnitPrefix::Milli, '\u{3bc}' => UnitPrefix::Micro, 'n' => UnitPrefix::Nano, @@ -220,7 +220,11 @@ impl BalanceVariant { "Given precision of a Balance value is higher than allowed" )) } - let balance: Balance = (den_balance.value * multiple).try_into()?; + let balance: Balance = den_balance + .value + .checked_mul(multiple) + .context("error while converting balance to raw format.")? + .try_into()?; Ok(balance) } } @@ -361,7 +365,7 @@ impl Display for DenominatedBalance { let prefix = match self.unit { UnitPrefix::Giga => "G", UnitPrefix::Mega => "M", - UnitPrefix::Kilo => "K", + UnitPrefix::Kilo => "k", UnitPrefix::One => "", UnitPrefix::Milli => "m", UnitPrefix::Micro => "μ", @@ -503,7 +507,7 @@ mod tests { symbol: String::from("DOT"), }; let balance: Balance = 5_005_000_000_000_000; - let bv = BalanceVariant::from_str("500.5KDOT").expect("successful parsing. qed"); + let bv = BalanceVariant::from_str("500.5kDOT").expect("successful parsing. qed"); let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); assert_eq!(balance, balance_parsed); } @@ -567,7 +571,7 @@ mod tests { }; let balance: Balance = 5_235_456_210_000_000; let bv = - BalanceVariant::from_str("523.545621KDOT").expect("successful parsing. qed"); + BalanceVariant::from_str("523.545621kDOT").expect("successful parsing. qed"); let balance_parsed = bv.denominate_balance(&tm).expect("successful parsing. qed"); assert_eq!(balance, balance_parsed); } From 6814589f05b587ae2c478bd41914d3feab985447 Mon Sep 17 00:00:00 2001 From: SkymanOne Date: Fri, 28 Oct 2022 17:26:51 +0200 Subject: [PATCH 20/20] better comments for error and bumped wasm-opt --- Cargo.lock | 28 +++++++++---------- crates/cargo-contract/Cargo.toml | 2 +- .../src/cmd/extrinsics/balance.rs | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d7aa4cd4d..14076b9c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -799,9 +799,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.75" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7df2292959b7e22a5cb39d37b7e72b2c748b12f956cc409b529fddcdc8857b" +checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a" dependencies = [ "cc", "cxxbridge-flags", @@ -811,9 +811,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.75" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0806e5c64f74bd64b94d857b1c28cc3d493579a65f5f31e7d3451706d4025405" +checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827" dependencies = [ "cc", "codespan-reporting", @@ -826,15 +826,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.75" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2069b1573efd6e5901004e8fdca2e28bc6f47f86dc24da81182851e71cf3208" +checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a" [[package]] name = "cxxbridge-macro" -version = "1.0.75" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d980827d1ec28ea6e0db545fceaa611eb8e43f70eff8c1c33cc2c96ffa0f0476" +checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7" dependencies = [ "proc-macro2", "quote", @@ -4101,9 +4101,9 @@ checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "wasm-opt" -version = "0.110.1" +version = "0.110.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92186976135b1af91a88c255c15d273b393d73f8032c8ca373a1e69ea1b56ec5" +checksum = "b68e8037b4daf711393f4be2056246d12d975651b14d581520ad5d1f19219cec" dependencies = [ "anyhow", "libc", @@ -4117,9 +4117,9 @@ dependencies = [ [[package]] name = "wasm-opt-cxx-sys" -version = "0.110.1" +version = "0.110.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dc16d755d1a6bc0555e43adc5cfd7ae66f3ad590b3394a949ba616248dd84ff" +checksum = "91adbad477e97bba3fbd21dd7bfb594e7ad5ceb9169ab1c93ab9cb0ada636b6f" dependencies = [ "anyhow", "cxx", @@ -4129,9 +4129,9 @@ dependencies = [ [[package]] name = "wasm-opt-sys" -version = "0.110.1" +version = "0.110.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d7d039c9786215a640602f861c6e9e7eb6ba855fb105b36e62a79a45ef173b2" +checksum = "ec4fa5a322a4e6ac22fd141f498d56afbdbf9df5debeac32380d2dcaa3e06941" dependencies = [ "anyhow", "cc", diff --git a/crates/cargo-contract/Cargo.toml b/crates/cargo-contract/Cargo.toml index 372d98015..6fe2582ed 100644 --- a/crates/cargo-contract/Cargo.toml +++ b/crates/cargo-contract/Cargo.toml @@ -41,7 +41,7 @@ tempfile = "3.3.0" url = { version = "2.3.1", features = ["serde"] } impl-serde = "0.4.0" rust_decimal = "1.26" -wasm-opt = "0.110.1" +wasm-opt = "0.110.2" # dependencies for extrinsics (deploying and calling a contract) async-std = { version = "1.12.0", features = ["attributes", "tokio1"] } diff --git a/crates/cargo-contract/src/cmd/extrinsics/balance.rs b/crates/cargo-contract/src/cmd/extrinsics/balance.rs index aa9e73995..10d2669e4 100644 --- a/crates/cargo-contract/src/cmd/extrinsics/balance.rs +++ b/crates/cargo-contract/src/cmd/extrinsics/balance.rs @@ -223,7 +223,7 @@ impl BalanceVariant { let balance: Balance = den_balance .value .checked_mul(multiple) - .context("error while converting balance to raw format.")? + .context("error while converting balance to raw format. Overflow during multiplication!")? .try_into()?; Ok(balance) }