From 3ecad3f70b61b3041a370beac7bb524345b2f107 Mon Sep 17 00:00:00 2001 From: "Sam H. Smith" Date: Mon, 5 Feb 2024 22:31:17 +0100 Subject: [PATCH] [fix] #161: Register and Mint Asset Signed-off-by: Sam H. Smith --- docs-recipes/2.3.client.py | 12 +++---- docs-recipes/5.register-and-mint.py | 53 +++++++++++++++++++++++++++ src/client.rs | 22 ++++++++++++ src/isi.rs | 56 ++++++++++++++++++++++------- 4 files changed, 122 insertions(+), 21 deletions(-) create mode 100644 docs-recipes/5.register-and-mint.py diff --git a/docs-recipes/2.3.client.py b/docs-recipes/2.3.client.py index 4e1754d9..eb1c324b 100644 --- a/docs-recipes/2.3.client.py +++ b/docs-recipes/2.3.client.py @@ -23,13 +23,9 @@ password, api_url) -pyasset_id = iroha.AssetDefinitionId("pyasset", "wonderland") -alice = iroha.AccountId("alice", "wonderland") -bob = iroha.AccountId("bob", "wonderland") +domains = client.query_all_domains() +print("Listing all domains...") +for d in domains: + print(" - ", d,) -register = iroha.Instruction.register(iroha.NewAssetDefinition(pyasset_id, iroha.AssetValueType.QUANTITY)) -mint = iroha.Instruction.mint(1024, iroha.AssetId(pyasset_id, alice)) -transfer = iroha.Instruction.transfer(512, iroha.AssetId(pyasset_id, alice), bob) - -client.submit_executable([register, mint, transfer]) diff --git a/docs-recipes/5.register-and-mint.py b/docs-recipes/5.register-and-mint.py new file mode 100644 index 00000000..420574e7 --- /dev/null +++ b/docs-recipes/5.register-and-mint.py @@ -0,0 +1,53 @@ +import iroha + +key_pair = iroha.KeyPair.from_json(""" +{ + "public_key": "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0", + "private_key": { + "digest_function": "ed25519", + "payload": "9ac47abf59b356e0bd7dcbbbb4dec080e302156a48ca907e47cb6aea1d32719e7233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0" + } +} +""") + +account_id = "alice@wonderland" +web_login = "mad_hatter" +password = "ilovetea" +api_url = "http://127.0.0.1:8080/" +telemetry_url = "http://127.0.0.1:8180/" + +client = iroha.Client.create( + key_pair, + account_id, + web_login, + password, + api_url) + +assets = client.query_all_assets_owned_by_account("alice@wonderland") + +print("Listing all assets owned by alice@wonderland...") +for a in assets: + print(" - ", a,) + + +asset_definition_id = "time#wonderland" +asset_id = "time##alice@wonderland" + +if "time##alice@wonderland" in assets: + print("'alice@wonderland' already has asset 'time'.") + +register_definition = iroha.Instruction.register_asset_definition(asset_definition_id, "Quantity") + +mint = iroha.Instruction.mint_asset(5, asset_id, "Quantity") + +client.submit_executable([register_definition, mint]) + +while True: + assets = client.query_all_assets_owned_by_account("alice@wonderland") + + if asset_id in assets: + break + +print("Listing all assets owned by alice@wonderland...") +for a in assets: + print(" - ", a,) \ No newline at end of file diff --git a/src/client.rs b/src/client.rs index 274a936c..7a9227a5 100644 --- a/src/client.rs +++ b/src/client.rs @@ -113,6 +113,28 @@ impl Client { } Ok(items) } + + fn query_all_assets_owned_by_account(&self, account_id: &str) -> PyResult> { + let query = iroha_data_model::query::prelude::FindAssetsByAccountId { + account_id: AccountId::from_str(account_id) + .map_err(|e| PyValueError::new_err(e.to_string()))? + .into(), + }; + + let val = self + .client + .request(query) + .map_err(|e| PyRuntimeError::new_err(format!("{e:?}")))?; + + let mut items = Vec::new(); + for item in val { + items.push( + item.map(|d| d.id.to_string()) + .map_err(|e| PyRuntimeError::new_err(format!("{e:?}")))?, + ); + } + Ok(items) + } } macro_rules! register_query { diff --git a/src/isi.rs b/src/isi.rs index 01313a3b..ed0b3dbc 100644 --- a/src/isi.rs +++ b/src/isi.rs @@ -5,6 +5,7 @@ use iroha_data_model::isi::{ }; use iroha_data_model::prelude::*; use iroha_data_model::NumericValue; +use iroha_primitives::fixed::FixedPointOperationError; use pyo3::{exceptions::PyValueError, prelude::*}; use std::str::FromStr; @@ -61,7 +62,7 @@ impl PyInstruction { } #[staticmethod] - /// Create an instruction for registering a new domain. + /// Create an instruction for registering a new account. fn register_account( account_id: &str, public_keys: Vec, @@ -77,6 +78,26 @@ impl PyInstruction { )))); } + #[staticmethod] + /// Create an instruction for registering a new account. + fn register_asset_definition( + asset_definition_id: &str, + value_type: &str, + ) -> PyResult { + let new_definition_object = NewAssetDefinition { + id: AssetDefinitionId::from_str(asset_definition_id) + .map_err(|e| PyValueError::new_err(e.to_string()))?, + value_type: AssetValueType::from_str(value_type) + .map_err(|e| PyValueError::new_err(e.to_string()))?, + mintable: Mintable::Infinitely, + logo: None, + metadata: Metadata::default(), + }; + return Ok(PyInstruction(InstructionExpr::Register(RegisterExpr::new( + new_definition_object, + )))); + } + #[staticmethod] /// Create an instruction for un-registering an object. /// Currently supported are: Account, AssetDefinition and Domain @@ -174,22 +195,31 @@ impl PyInstruction { #[staticmethod] // Mint value to an Asset - fn mint(py: Python<'_>, value: PyObject, to: PyAssetId) -> PyResult { - let val = if let Ok(val) = value.extract::(py) { - NumericValue::U32(val) - } else if let Ok(val) = value.extract::(py) { - NumericValue::U128(val) - } else if let Ok(val) = value.extract::(py) { - let fixed = val.try_into().map_err(|e| { - PyValueError::new_err(format!("Couldn't convert {} to fixed: {}", val, e)) - })?; - NumericValue::Fixed(fixed) + fn mint_asset( + py: Python<'_>, + value: PyObject, + asset_id: &str, + value_type: &str, + ) -> PyResult { + let val = if value_type == "Quantity" { + NumericValue::U32(value.extract::(py)?) + } else if value_type == "BigQuantity" { + NumericValue::U128(value.extract::(py)?) + } else if value_type == "Fixed" { + NumericValue::Fixed( + value + .extract::(py)? + .try_into() + .map_err(|e: FixedPointOperationError| PyValueError::new_err(e.to_string()))?, + ) } else { - return Err(PyValueError::new_err("Invalid value to transfer")); + // TODO(Sam): Add Store variant because it's needed for metadata. + return Err(PyValueError::new_err("Value type is wrong. It needs to be one of these 4: Quantity, BigQuantity, Fixed or Store.")); }; Ok(PyInstruction(InstructionExpr::Mint(MintExpr::new( - val, to.0, + val, + AssetId::from_str(asset_id).map_err(|e| PyValueError::new_err(e.to_string()))?, )))) } }