, Error> {
+ let cargo_toml_path = match path.ends_with("Cargo.toml") {
+ true => path.to_path_buf(),
+ false => path.join("Cargo.toml"),
+ };
+ let contract_artifacts =
+ ContractArtifacts::from_manifest_or_file(Some(&cargo_toml_path), None)?;
+ let transcoder = contract_artifacts.contract_transcoder()?;
+ let metadata = transcoder.metadata();
+ Ok(metadata
+ .spec()
+ .messages()
+ .iter()
+ .map(|message| ContractFunction {
+ label: message.label().to_string(),
+ mutates: message.mutates(),
+ payable: message.payable(),
+ args: process_args(message.args(), metadata.registry()),
+ docs: message.docs().join(" "),
+ default: *message.default(),
+ })
+ .collect())
+}
+
+/// Extracts the information of a smart contract message parsing the metadata file.
+///
+/// # Arguments
+/// * `path` - Location path of the project.
+/// * `message` - The label of the contract message.
+fn get_message(path: P, message: &str) -> Result
+where
+ P: AsRef,
+{
+ get_messages(path.as_ref())?
+ .into_iter()
+ .find(|msg| msg.label == message)
+ .ok_or_else(|| Error::InvalidMessageName(message.to_string()))
+}
+
+/// Extracts a list of smart contract contructors parsing the metadata file.
+///
+/// # Arguments
+/// * `path` - Location path of the project.
+pub fn get_constructors(path: &Path) -> Result, Error> {
+ let cargo_toml_path = match path.ends_with("Cargo.toml") {
+ true => path.to_path_buf(),
+ false => path.join("Cargo.toml"),
+ };
+ let contract_artifacts =
+ ContractArtifacts::from_manifest_or_file(Some(&cargo_toml_path), None)?;
+ let transcoder = contract_artifacts.contract_transcoder()?;
+ let metadata = transcoder.metadata();
+ Ok(metadata
+ .spec()
+ .constructors()
+ .iter()
+ .map(|constructor| ContractFunction {
+ label: constructor.label().to_string(),
+ payable: *constructor.payable(),
+ args: process_args(constructor.args(), metadata.registry()),
+ docs: constructor.docs().join(" "),
+ default: *constructor.default(),
+ mutates: true,
+ })
+ .collect())
+}
+
+/// Extracts the information of a smart contract constructor parsing the metadata file.
+///
+/// # Arguments
+/// * `path` - Location path of the project.
+/// * `constructor` - The label of the constructor.
+fn get_constructor(path: P, constructor: &str) -> Result
+where
+ P: AsRef,
+{
+ get_constructors(path.as_ref())?
+ .into_iter()
+ .find(|c| c.label == constructor)
+ .ok_or_else(|| Error::InvalidConstructorName(constructor.to_string()))
+}
+
+// Parse the parameters into a vector of argument labels.
+fn process_args(
+ params: &[MessageParamSpec],
+ registry: &PortableRegistry,
+) -> Vec {
+ let mut args: Vec = Vec::new();
+ for arg in params {
+ // Resolve type from registry to provide full type representation.
+ let type_name =
+ format_type(registry.resolve(arg.ty().ty().id).expect("type not found"), registry);
+ args.push(Param { label: arg.label().to_string(), type_name });
+ }
+ args
+}
+
+// Formats a specified type, using the registry to output its full type representation.
+fn format_type(ty: &Type, registry: &PortableRegistry) -> String {
+ let mut name = ty
+ .path
+ .segments
+ .last()
+ .map(|s| s.to_owned())
+ .unwrap_or_else(|| ty.path.to_string());
+
+ if !ty.type_params.is_empty() {
+ let params: Vec<_> = ty
+ .type_params
+ .iter()
+ .filter_map(|p| registry.resolve(p.ty.unwrap().id))
+ .map(|t| format_type(t, registry))
+ .collect();
+ name = format!("{name}<{}>", params.join(","));
+ }
+
+ name = format!(
+ "{name}{}",
+ match &ty.type_def {
+ TypeDef::Composite(composite) => {
+ if composite.fields.is_empty() {
+ return "".to_string();
+ }
+
+ let mut named = false;
+ let fields: Vec<_> = composite
+ .fields
+ .iter()
+ .filter_map(|f| match f.name.as_ref() {
+ None => registry.resolve(f.ty.id).map(|t| format_type(t, registry)),
+ Some(field) => {
+ named = true;
+ f.type_name.as_ref().map(|t| format!("{field}: {t}"))
+ },
+ })
+ .collect();
+ match named {
+ true => format!(" {{ {} }}", fields.join(", ")),
+ false => format!(" ({})", fields.join(", ")),
+ }
+ },
+ TypeDef::Variant(variant) => {
+ let variants: Vec<_> = variant
+ .variants
+ .iter()
+ .map(|v| {
+ if v.fields.is_empty() {
+ return v.name.clone();
+ }
+
+ let name = v.name.as_str();
+ let mut named = false;
+ let fields: Vec<_> = v
+ .fields
+ .iter()
+ .filter_map(|f| match f.name.as_ref() {
+ None => registry.resolve(f.ty.id).map(|t| format_type(t, registry)),
+ Some(field) => {
+ named = true;
+ f.type_name.as_ref().map(|t| format!("{field}: {t}"))
+ },
+ })
+ .collect();
+ format!(
+ "{name}{}",
+ match named {
+ true => format!("{{ {} }}", fields.join(", ")),
+ false => format!("({})", fields.join(", ")),
+ }
+ )
+ })
+ .collect();
+ format!(": {}", variants.join(", "))
+ },
+ TypeDef::Sequence(sequence) => {
+ format!(
+ "[{}]",
+ format_type(
+ registry.resolve(sequence.type_param.id).expect("sequence type not found"),
+ registry
+ )
+ )
+ },
+ TypeDef::Array(array) => {
+ format!(
+ "[{};{}]",
+ format_type(
+ registry.resolve(array.type_param.id).expect("array type not found"),
+ registry
+ ),
+ array.len
+ )
+ },
+ TypeDef::Tuple(tuple) => {
+ let fields: Vec<_> = tuple
+ .fields
+ .iter()
+ .filter_map(|p| registry.resolve(p.id))
+ .map(|t| format_type(t, registry))
+ .collect();
+ format!("({})", fields.join(","))
+ },
+ TypeDef::Primitive(primitive) => {
+ use TypeDefPrimitive::*;
+ match primitive {
+ Bool => "bool",
+ Char => "char",
+ Str => "str",
+ U8 => "u8",
+ U16 => "u16",
+ U32 => "u32",
+ U64 => "u64",
+ U128 => "u128",
+ U256 => "u256",
+ I8 => "i8",
+ I16 => "i16",
+ I32 => "i32",
+ I64 => "i64",
+ I128 => "i128",
+ I256 => "i256",
+ }
+ .to_string()
+ },
+ TypeDef::Compact(compact) => {
+ format!(
+ "Compact<{}>",
+ format_type(
+ registry.resolve(compact.type_param.id).expect("compact type not found"),
+ registry
+ )
+ )
+ },
+ TypeDef::BitSequence(_) => {
+ unimplemented!("bit sequence not currently supported")
+ },
+ }
+ );
+
+ name
+}
+
+/// Processes a list of argument values for a specified contract function,
+/// wrapping each value in `Some(...)` or replacing it with `None` if the argument is optional
+///
+/// # Arguments
+/// * `path` - Location path of the project.
+/// * `label` - Label of the contract message to retrieve.
+/// * `args` - Argument values provided by the user.
+pub fn process_function_args(
+ path: P,
+ label: &str,
+ args: Vec,
+ function_type: FunctionType,
+) -> Result, Error>
+where
+ P: AsRef,
+{
+ let function = match function_type {
+ FunctionType::Message => get_message(path, label)?,
+ FunctionType::Constructor => get_constructor(path, label)?,
+ };
+ if args.len() != function.args.len() {
+ return Err(Error::IncorrectArguments {
+ expected: function.args.len(),
+ provided: args.len(),
+ });
+ }
+ Ok(args
+ .into_iter()
+ .zip(&function.args)
+ .map(|(arg, param)| match (param.type_name.starts_with("Option<"), arg.is_empty()) {
+ // If the argument is Option and empty, replace it with `None`
+ (true, true) => "None".to_string(),
+ // If the argument is Option and not empty, wrap it in `Some(...)`
+ (true, false) => format!("Some({})", arg),
+ // If the argument is not Option, return it as is
+ _ => arg,
+ })
+ .collect::>())
+}
+
+#[cfg(test)]
+mod tests {
+ use std::env;
+
+ use super::*;
+ use crate::{mock_build_process, new_environment};
+ use anyhow::Result;
+
+ #[test]
+ fn get_messages_work() -> Result<()> {
+ let temp_dir = new_environment("testing")?;
+ let current_dir = env::current_dir().expect("Failed to get current directory");
+ mock_build_process(
+ temp_dir.path().join("testing"),
+ current_dir.join("./tests/files/testing.contract"),
+ current_dir.join("./tests/files/testing.json"),
+ )?;
+ let message = get_messages(&temp_dir.path().join("testing"))?;
+ assert_eq!(message.len(), 3);
+ assert_eq!(message[0].label, "flip");
+ assert_eq!(message[0].docs, " A message that can be called on instantiated contracts. This one flips the value of the stored `bool` from `true` to `false` and vice versa.");
+ assert_eq!(message[1].label, "get");
+ assert_eq!(message[1].docs, " Simply returns the current value of our `bool`.");
+ assert_eq!(message[2].label, "specific_flip");
+ assert_eq!(message[2].docs, " A message for testing, flips the value of the stored `bool` with `new_value` and is payable");
+ // assert parsed arguments
+ assert_eq!(message[2].args.len(), 2);
+ assert_eq!(message[2].args[0].label, "new_value".to_string());
+ assert_eq!(message[2].args[0].type_name, "bool".to_string());
+ assert_eq!(message[2].args[1].label, "number".to_string());
+ assert_eq!(message[2].args[1].type_name, "Option: None, Some(u32)".to_string());
+ Ok(())
+ }
+
+ #[test]
+ fn get_message_work() -> Result<()> {
+ let temp_dir = new_environment("testing")?;
+ let current_dir = env::current_dir().expect("Failed to get current directory");
+ mock_build_process(
+ temp_dir.path().join("testing"),
+ current_dir.join("./tests/files/testing.contract"),
+ current_dir.join("./tests/files/testing.json"),
+ )?;
+ assert!(matches!(
+ get_message(&temp_dir.path().join("testing"), "wrong_flip"),
+ Err(Error::InvalidMessageName(name)) if name == "wrong_flip".to_string()));
+ let message = get_message(&temp_dir.path().join("testing"), "specific_flip")?;
+ assert_eq!(message.label, "specific_flip");
+ assert_eq!(message.docs, " A message for testing, flips the value of the stored `bool` with `new_value` and is payable");
+ // assert parsed arguments
+ assert_eq!(message.args.len(), 2);
+ assert_eq!(message.args[0].label, "new_value".to_string());
+ assert_eq!(message.args[0].type_name, "bool".to_string());
+ assert_eq!(message.args[1].label, "number".to_string());
+ assert_eq!(message.args[1].type_name, "Option: None, Some(u32)".to_string());
+ Ok(())
+ }
+
+ #[test]
+ fn get_constructors_work() -> Result<()> {
+ let temp_dir = new_environment("testing")?;
+ let current_dir = env::current_dir().expect("Failed to get current directory");
+ mock_build_process(
+ temp_dir.path().join("testing"),
+ current_dir.join("./tests/files/testing.contract"),
+ current_dir.join("./tests/files/testing.json"),
+ )?;
+ let constructor = get_constructors(&temp_dir.path().join("testing"))?;
+ assert_eq!(constructor.len(), 2);
+ assert_eq!(constructor[0].label, "new");
+ assert_eq!(
+ constructor[0].docs,
+ "Constructor that initializes the `bool` value to the given `init_value`."
+ );
+ assert_eq!(constructor[1].label, "default");
+ assert_eq!(
+ constructor[1].docs,
+ "Constructor that initializes the `bool` value to `false`. Constructors can delegate to other constructors."
+ );
+ // assert parsed arguments
+ assert_eq!(constructor[0].args.len(), 1);
+ assert_eq!(constructor[0].args[0].label, "init_value".to_string());
+ assert_eq!(constructor[0].args[0].type_name, "bool".to_string());
+ assert_eq!(constructor[1].args.len(), 2);
+ assert_eq!(constructor[1].args[0].label, "init_value".to_string());
+ assert_eq!(constructor[1].args[0].type_name, "bool".to_string());
+ assert_eq!(constructor[1].args[1].label, "number".to_string());
+ assert_eq!(constructor[1].args[1].type_name, "Option: None, Some(u32)".to_string());
+ Ok(())
+ }
+
+ #[test]
+ fn get_constructor_work() -> Result<()> {
+ let temp_dir = new_environment("testing")?;
+ let current_dir = env::current_dir().expect("Failed to get current directory");
+ mock_build_process(
+ temp_dir.path().join("testing"),
+ current_dir.join("./tests/files/testing.contract"),
+ current_dir.join("./tests/files/testing.json"),
+ )?;
+ assert!(matches!(
+ get_constructor(&temp_dir.path().join("testing"), "wrong_constructor"),
+ Err(Error::InvalidConstructorName(name)) if name == "wrong_constructor".to_string()));
+ let constructor = get_constructor(&temp_dir.path().join("testing"), "default")?;
+ assert_eq!(constructor.label, "default");
+ assert_eq!(
+ constructor.docs,
+ "Constructor that initializes the `bool` value to `false`. Constructors can delegate to other constructors."
+ );
+ // assert parsed arguments
+ assert_eq!(constructor.args.len(), 2);
+ assert_eq!(constructor.args[0].label, "init_value".to_string());
+ assert_eq!(constructor.args[0].type_name, "bool".to_string());
+ assert_eq!(constructor.args[1].label, "number".to_string());
+ assert_eq!(constructor.args[1].type_name, "Option: None, Some(u32)".to_string());
+ Ok(())
+ }
+
+ #[test]
+ fn process_function_args_work() -> Result<()> {
+ let temp_dir = new_environment("testing")?;
+ let current_dir = env::current_dir().expect("Failed to get current directory");
+ mock_build_process(
+ temp_dir.path().join("testing"),
+ current_dir.join("./tests/files/testing.contract"),
+ current_dir.join("./tests/files/testing.json"),
+ )?;
+ assert!(matches!(
+ process_function_args(temp_dir.path().join("testing"),"wrong_flip", Vec::new(), FunctionType::Message),
+ Err(Error::InvalidMessageName(error)) if error == "wrong_flip".to_string()));
+ assert!(matches!(
+ process_function_args(
+ temp_dir.path().join("testing"),
+ "specific_flip",
+ Vec::new(),
+ FunctionType::Message
+ ),
+ Err(Error::IncorrectArguments {expected, provided }) if expected == 2 && provided == 0
+ ));
+ assert_eq!(
+ process_function_args(
+ temp_dir.path().join("testing"),
+ "specific_flip",
+ ["true".to_string(), "2".to_string()].to_vec(),
+ FunctionType::Message
+ )?,
+ ["true".to_string(), "Some(2)".to_string()]
+ );
+ assert_eq!(
+ process_function_args(
+ temp_dir.path().join("testing"),
+ "specific_flip",
+ ["true".to_string(), "".to_string()].to_vec(),
+ FunctionType::Message
+ )?,
+ ["true".to_string(), "None".to_string()]
+ );
+
+ // Test constructors
+ assert!(matches!(
+ process_function_args(temp_dir.path().join("testing"),"wrong_constructor", Vec::new(), FunctionType::Constructor),
+ Err(Error::InvalidConstructorName(error)) if error == "wrong_constructor".to_string()));
+ assert!(matches!(
+ process_function_args(
+ temp_dir.path().join("testing"),
+ "default",
+ Vec::new(),
+ FunctionType::Constructor
+ ),
+ Err(Error::IncorrectArguments {expected, provided }) if expected == 2 && provided == 0
+ ));
+ assert_eq!(
+ process_function_args(
+ temp_dir.path().join("testing"),
+ "default",
+ ["true".to_string(), "2".to_string()].to_vec(),
+ FunctionType::Constructor
+ )?,
+ ["true".to_string(), "Some(2)".to_string()]
+ );
+ assert_eq!(
+ process_function_args(
+ temp_dir.path().join("testing"),
+ "default",
+ ["true".to_string(), "".to_string()].to_vec(),
+ FunctionType::Constructor
+ )?,
+ ["true".to_string(), "None".to_string()]
+ );
+ Ok(())
+ }
+}
diff --git a/crates/pop-contracts/src/utils/mod.rs b/crates/pop-contracts/src/utils/mod.rs
index 357c6608..ad49e2dc 100644
--- a/crates/pop-contracts/src/utils/mod.rs
+++ b/crates/pop-contracts/src/utils/mod.rs
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-3.0
pub mod helpers;
+pub mod metadata;
pub mod signer;
diff --git a/crates/pop-contracts/tests/files/testing.contract b/crates/pop-contracts/tests/files/testing.contract
index 5fb54f3c..fbd8e6fb 100644
--- a/crates/pop-contracts/tests/files/testing.contract
+++ b/crates/pop-contracts/tests/files/testing.contract
@@ -1 +1 @@
-{"source":{"hash":"0x80776e58b218850d7d86447b2edea78d827ed0ed2499ff3a92b7ea10e4f95eb5","language":"ink! 5.0.0","compiler":"rustc 1.78.0","wasm":"0x0061736d01000000012b0860027f7f0060037f7f7f017f60000060047f7f7f7f017f60037f7f7f0060017f006000017f60017f017f027406057365616c310b6765745f73746f726167650003057365616c3005696e7075740000057365616c320b7365745f73746f726167650003057365616c300b7365616c5f72657475726e0004057365616c301176616c75655f7472616e73666572726564000003656e76066d656d6f72790201021003100f0101010105040006070002050002020616037f01418080040b7f00418080050b7f00418080050b0711020463616c6c0012066465706c6f7900130aa80c0f2b01017f037f2002200346047f200005200020036a200120036a2d00003a0000200341016a21030c010b0b0b6f01017f0240200020014d04402000210303402002450d02200320012d00003a0000200341016a2103200141016a2101200241016b21020c000b000b200041016b2103200141016b210103402002450d01200220036a200120026a2d00003a0000200241016b21020c000b000b20000b2501017f037f2002200346047f200005200020036a20013a0000200341016a21030c010b0b0b3f01027f0340200245044041000f0b200241016b210220012d0000210320002d00002104200141016a2101200041016a210020032004460d000b200420036b0b2601017f230041106b220124002001410036020c20002001410c6a4104100a200141106a24000b4801027f024002402000280208220320026a22042003490d00200420002802044b0d00200420036b2002470d01200028020020036a2001200210051a200020043602080f0b000b000b2601017f230041106b22022400200220003a000f20012002410f6a4101100a200241106a24000b6102027f027e230041206b22002400200041106a22014200370300200042003703082000411036021c200041086a2000411c6a1004200028021c41114f0440000b2001290300210220002903082103200041206a2400410541042002200384501b0b3f01017f2000280204220145044041020f0b2000200141016b36020420002000280200220041016a3602004101410220002d000022004101461b410020001b0b3c01027f027f200145044041808004210141010c010b410121024180800441013a000041818004210141020b2103200120023a0000200020031011000b12004180800441003b0100410041021011000b8a0101057f230041106b22012400200142808001370208200141808004360204200141046a22041009024020012802082205200128020c2202490d00200128020421032001410036020c2001200520026b3602082001200220036a36020420002004100b200128020c220020012802084b0d00200320022001280204200010021a200141106a24000f0b000b0d0020004180800420011003000b990401067f230041106b2200240020004180800136020441808004200041046a10010240024020002802042202418180014f0d000240024020024104490d002000418480043602042000200241046b360208418380042d00002101418280042d00002104418180042d00002103418080042d00002202412f470440200241ec00470440200241e300470d02410221022003413a46200441a5014671200141d10046710d030c020b2003410f472004411d4772200141f70147720d01200041046a100d220241ff01714102460d010c020b41032102200341860146200441db004671200141d90146710d010b41014101100e000b200042808001370208200041808004360204200041046a2204100920002802082205200028020c2201490d00200028020421032000200520016b220536020420032001200120036a2201200410002000280204220320054b720d0020002003360208200020013602042004100d220141ff01714102460d0020002802080d000240024002404102200241026b41ff01712200200041024f1b41016b0e020100020b2002410171101041004100100e000b100c41ff01714105470d01230041106b220024002000418080043602044180800441003a00002000428080818010370208200141ff0171410047200041046a100b200028020c2200418180014f0440000b410020001011000b100c41ff01714105460d010b000b200141ff017145101041004100100e000be50101057f230041106b2200240002400240100c41ff01714105470d0020004180800136020c418080042000410c6a1001200028020c2201418180014f0d0020014104490d012000418480043602042000200141046b360208418380042d00002101418280042d00002102418180042d000021030240418080042d0000220441ed014704402004419b0147200341ae0147722002419d0147200141de004772720d03200041046a100d220041ff01714102470d010c030b200341cb00462002419d0146712001411b4671450d0241001010100f000b20001010100f000b000b41014101100e000b","build_info":{"rust_toolchain":"stable-aarch64-apple-darwin","cargo_contract_version":"5.0.0-alpha","build_mode":"Release","wasm_opt_settings":{"optimization_passes":"Z","keep_debug_symbols":false}}},"contract":{"name":"testing","version":"0.1.0","authors":["[your_name] <[your_email]>"]},"image":null,"version":5,"types":[{"id":0,"type":{"def":{"primitive":"bool"}}},{"id":1,"type":{"path":["testing","testing","Testing"],"def":{"composite":{"fields":[{"name":"value","type":0,"typeName":",>>::Type"}]}}}},{"id":2,"type":{"path":["Result"],"params":[{"name":"T","type":3},{"name":"E","type":4}],"def":{"variant":{"variants":[{"name":"Ok","fields":[{"type":3}],"index":0},{"name":"Err","fields":[{"type":4}],"index":1}]}}}},{"id":3,"type":{"def":{"tuple":[]}}},{"id":4,"type":{"path":["ink_primitives","LangError"],"def":{"variant":{"variants":[{"name":"CouldNotReadInput","index":1}]}}}},{"id":5,"type":{"path":["Result"],"params":[{"name":"T","type":0},{"name":"E","type":4}],"def":{"variant":{"variants":[{"name":"Ok","fields":[{"type":0}],"index":0},{"name":"Err","fields":[{"type":4}],"index":1}]}}}},{"id":6,"type":{"path":["ink_primitives","types","AccountId"],"def":{"composite":{"fields":[{"type":7,"typeName":"[u8; 32]"}]}}}},{"id":7,"type":{"def":{"array":{"len":32,"type":8}}}},{"id":8,"type":{"def":{"primitive":"u8"}}},{"id":9,"type":{"def":{"primitive":"u128"}}},{"id":10,"type":{"path":["ink_primitives","types","Hash"],"def":{"composite":{"fields":[{"type":7,"typeName":"[u8; 32]"}]}}}},{"id":11,"type":{"def":{"primitive":"u64"}}},{"id":12,"type":{"def":{"primitive":"u32"}}},{"id":13,"type":{"path":["ink_env","types","NoChainExtension"],"def":{"variant":{}}}}],"storage":{"root":{"root_key":"0x00000000","layout":{"struct":{"name":"Testing","fields":[{"name":"value","layout":{"leaf":{"key":"0x00000000","ty":0}}}]}},"ty":1}},"spec":{"constructors":[{"label":"new","selector":"0x9bae9d5e","payable":false,"args":[{"label":"init_value","type":{"type":0,"displayName":["bool"]}}],"returnType":{"type":2,"displayName":["ink_primitives","ConstructorResult"]},"docs":["Constructor that initializes the `bool` value to the given `init_value`."],"default":false},{"label":"default","selector":"0xed4b9d1b","payable":false,"args":[],"returnType":{"type":2,"displayName":["ink_primitives","ConstructorResult"]},"docs":["Constructor that initializes the `bool` value to `false`.","","Constructors can delegate to other constructors."],"default":false}],"messages":[{"label":"flip","selector":"0x633aa551","mutates":true,"payable":false,"args":[],"returnType":{"type":2,"displayName":["ink","MessageResult"]},"docs":[" A message that can be called on instantiated contracts."," This one flips the value of the stored `bool` from `true`"," to `false` and vice versa."],"default":false},{"label":"get","selector":"0x2f865bd9","mutates":false,"payable":false,"args":[],"returnType":{"type":5,"displayName":["ink","MessageResult"]},"docs":[" Simply returns the current value of our `bool`."],"default":false},{"label":"specific_flip","selector":"0x6c0f1df7","mutates":true,"payable":true,"args":[{"label":"new_value","type":{"type":0,"displayName":["bool"]}}],"returnType":{"type":2,"displayName":["ink","MessageResult"]},"docs":[" A message for testing, flips the value of the stored `bool` with `new_value`"," and is payable"],"default":false}],"events":[],"docs":[],"lang_error":{"type":4,"displayName":["ink","LangError"]},"environment":{"accountId":{"type":6,"displayName":["AccountId"]},"balance":{"type":9,"displayName":["Balance"]},"hash":{"type":10,"displayName":["Hash"]},"timestamp":{"type":11,"displayName":["Timestamp"]},"blockNumber":{"type":12,"displayName":["BlockNumber"]},"chainExtension":{"type":13,"displayName":["ChainExtension"]},"maxEventTopics":4,"staticBufferSize":16384}}}
\ No newline at end of file
+{"source":{"hash":"0xf4f0cafd08d8e362141b3c64e3c651ad6a38225dbf0b66f691c15bb0ea00eac3","language":"ink! 5.0.0","compiler":"rustc 1.78.0","wasm":"0x0061736d0100000001270760027f7f0060037f7f7f017f60000060047f7f7f7f017f60037f7f7f0060017f017f6000017f027406057365616c310b6765745f73746f726167650003057365616c3005696e7075740000057365616c320b7365745f73746f726167650003057365616c300b7365616c5f72657475726e0004057365616c301176616c75655f7472616e73666572726564000003656e76066d656d6f7279020102100313120101010100050000040006000200000002020616037f01418080040b7f00418080050b7f00418080050b0711020463616c6c0015066465706c6f7900160ad910122b01017f037f2002200346047f200005200020036a200120036a2d00003a0000200341016a21030c010b0b0b6f01017f0240200020014d04402000210303402002450d02200320012d00003a0000200341016a2103200141016a2101200241016b21020c000b000b200041016b2103200141016b210103402002450d01200220036a200120026a2d00003a0000200241016b21020c000b000b20000b2501017f037f2002200346047f200005200020036a20013a0000200341016a21030c010b0b0b3f01027f0340200245044041000f0b200241016b210220012d0000210320002d00002104200141016a2101200041016a210020032004460d000b200420036b0bc00101057f230041106b22022400410221044104210502402001100a220641ff01714102460d00200241086a2001100b20022d00080d000240024020022d000922030e020100020b20012802042203410449047f4101052001200341046b36020420012001280200220141046a3602002001280000210341000b2101200220033602042002200136020020022802000d0141012103200228020421040b20002003360204200020063a0000410821050b200020056a2004360200200241106a24000b3f01027f230041106b22012400200141086a2000100b20012d0009210020012d00082102200141106a240041024101410220004101461b410020001b20021b0b3c01017f200020012802042202047f2001200241016b36020420012001280200220141016a36020020012d00000520010b3a000120002002453a00000b2601017f230041106b220224002002200036020c20012002410c6a4104100d200241106a24000b4801027f024002402000280208220320026a22042003490d00200420002802044b0d00200420036b2002470d01200028020020036a2001200210051a200020043602080f0b000b000b2601017f230041106b22022400200220003a000f20012002410f6a4101100d200241106a24000b6102027f027e230041206b22002400200041106a22014200370300200042003703082000411036021c200041086a2000411c6a1004200028021c41114f0440000b2001290300210220002903082103200041206a2400410541042002200384501b0b3c01027f027f200145044041808004210141010c010b410121024180800441013a000041818004210141020b2103200120023a0000200020031013000b12004180800441003b0100410041021013000b920101057f230041106b220224002002428080013702082002418080043602044100200241046a2204100c024020022802082206200228020c2203490d00200228020421052002410036020c2002200620036b3602082002200320056a36020420012004100e20002004100c200228020c220020022802084b0d00200520032002280204200010021a200241106a24000f0b000b0d0020004180800420011003000b08002000200110120bb60501087f230041206b2200240020004180800136021441808004200041146a100102400240024020002802142201418180014f0d0041042104027f410420014104490d001a20004184800436020c2000200141046b360210418380042d00002101418280042d00002102418180042d00002103024002400240418080042d00002205412f470440200541ec00460d014104200541e300470d041a41042003413a470d041a4104200241a501470d041a41042202200141d100470d041a410221010c020b41042003418601470d031a4104200241db00470d031a41042202200141d901470d031a410321010c010b41042003410f470d021a41042002411d470d021a4104200141f701470d021a200041146a2000410c6a1009200028021822014102460d01200028021c210420002d001421020b20002001360204200020023a000041080c010b41040b20006a2004360200200028020422024104460d012000280208210520002d000021072000428080013702182000418080043602144100200041146a2203100c20002802182206200028021c2201490d00200028021421042000200620016b220636021420042001200120046a2201200310002000280214220420064b720d0020002004360218200020013602142003100a220141ff01714102460d002000280218220341034d2003410447720d00200028021428000021000240024002404102200241026b2203200341024f1b41016b0e020100020b2005200020021b20074100471014410041001010000b100f41ff01714105470d01230041106b220024002000418080043602044180800441003a00002000428080818010370208200141ff0171410047200041046a100e200028020c2200418180014f0440000b410020001013000b100f41ff01714105460d020b000b410141011010000b2000200141ff0171451014410041001010000be90201067f230041206b22002400024002400240100f41ff01714105470d0020004180800136021441808004200041146a100120002802142201418180014f0d004104210220014104490d0120004184800436020c2000200141046b360210418380042d00002101418280042d00002103418180042d00002104027f418080042d0000220541ed014704402005419b0147200441ae0147722003419d0147200141de004772720d0341022103410322012000410c6a100a220441ff01714102470d011a0c040b200441cb00472003419d0147722001411b47720d02200041146a2000410c6a1009200028021822034102460d0220002d00142104200028021c0b210120002003360204200020043a0000410821020c020b000b410321010b200020026a2001360200024020002802042201410347044020002d0000210220014102460d012000280208410020011b200241004710121011000b410141011010000b4100200210121011000b","build_info":{"rust_toolchain":"stable-aarch64-apple-darwin","cargo_contract_version":"5.0.0-alpha","build_mode":"Release","wasm_opt_settings":{"optimization_passes":"Z","keep_debug_symbols":false}}},"contract":{"name":"testing","version":"0.1.0","authors":["[your_name] <[your_email]>"]},"image":null,"version":5,"types":[{"id":0,"type":{"def":{"primitive":"bool"}}},{"id":1,"type":{"def":{"primitive":"u32"}}},{"id":2,"type":{"path":["testing","testing","Testing"],"def":{"composite":{"fields":[{"name":"value","type":0,"typeName":",>>::Type"},{"name":"number","type":1,"typeName":",>>::Type"}]}}}},{"id":3,"type":{"path":["Result"],"params":[{"name":"T","type":4},{"name":"E","type":5}],"def":{"variant":{"variants":[{"name":"Ok","fields":[{"type":4}],"index":0},{"name":"Err","fields":[{"type":5}],"index":1}]}}}},{"id":4,"type":{"def":{"tuple":[]}}},{"id":5,"type":{"path":["ink_primitives","LangError"],"def":{"variant":{"variants":[{"name":"CouldNotReadInput","index":1}]}}}},{"id":6,"type":{"path":["Option"],"params":[{"name":"T","type":1}],"def":{"variant":{"variants":[{"name":"None","index":0},{"name":"Some","fields":[{"type":1}],"index":1}]}}}},{"id":7,"type":{"path":["Result"],"params":[{"name":"T","type":0},{"name":"E","type":5}],"def":{"variant":{"variants":[{"name":"Ok","fields":[{"type":0}],"index":0},{"name":"Err","fields":[{"type":5}],"index":1}]}}}},{"id":8,"type":{"path":["ink_primitives","types","AccountId"],"def":{"composite":{"fields":[{"type":9,"typeName":"[u8; 32]"}]}}}},{"id":9,"type":{"def":{"array":{"len":32,"type":10}}}},{"id":10,"type":{"def":{"primitive":"u8"}}},{"id":11,"type":{"def":{"primitive":"u128"}}},{"id":12,"type":{"path":["ink_primitives","types","Hash"],"def":{"composite":{"fields":[{"type":9,"typeName":"[u8; 32]"}]}}}},{"id":13,"type":{"def":{"primitive":"u64"}}},{"id":14,"type":{"path":["ink_env","types","NoChainExtension"],"def":{"variant":{}}}}],"storage":{"root":{"root_key":"0x00000000","layout":{"struct":{"name":"Testing","fields":[{"name":"value","layout":{"leaf":{"key":"0x00000000","ty":0}}},{"name":"number","layout":{"leaf":{"key":"0x00000000","ty":1}}}]}},"ty":2}},"spec":{"constructors":[{"label":"new","selector":"0x9bae9d5e","payable":false,"args":[{"label":"init_value","type":{"type":0,"displayName":["bool"]}}],"returnType":{"type":3,"displayName":["ink_primitives","ConstructorResult"]},"docs":["Constructor that initializes the `bool` value to the given `init_value`."],"default":false},{"label":"default","selector":"0xed4b9d1b","payable":false,"args":[{"label":"init_value","type":{"type":0,"displayName":["bool"]}},{"label":"number","type":{"type":6,"displayName":["Option"]}}],"returnType":{"type":3,"displayName":["ink_primitives","ConstructorResult"]},"docs":["Constructor that initializes the `bool` value to `false`.","","Constructors can delegate to other constructors."],"default":false}],"messages":[{"label":"flip","selector":"0x633aa551","mutates":true,"payable":false,"args":[],"returnType":{"type":3,"displayName":["ink","MessageResult"]},"docs":[" A message that can be called on instantiated contracts."," This one flips the value of the stored `bool` from `true`"," to `false` and vice versa."],"default":false},{"label":"get","selector":"0x2f865bd9","mutates":false,"payable":false,"args":[],"returnType":{"type":7,"displayName":["ink","MessageResult"]},"docs":[" Simply returns the current value of our `bool`."],"default":false},{"label":"specific_flip","selector":"0x6c0f1df7","mutates":true,"payable":true,"args":[{"label":"new_value","type":{"type":0,"displayName":["bool"]}},{"label":"number","type":{"type":6,"displayName":["Option"]}}],"returnType":{"type":3,"displayName":["ink","MessageResult"]},"docs":[" A message for testing, flips the value of the stored `bool` with `new_value`"," and is payable"],"default":false}],"events":[],"docs":[],"lang_error":{"type":5,"displayName":["ink","LangError"]},"environment":{"accountId":{"type":8,"displayName":["AccountId"]},"balance":{"type":11,"displayName":["Balance"]},"hash":{"type":12,"displayName":["Hash"]},"timestamp":{"type":13,"displayName":["Timestamp"]},"blockNumber":{"type":1,"displayName":["BlockNumber"]},"chainExtension":{"type":14,"displayName":["ChainExtension"]},"maxEventTopics":4,"staticBufferSize":16384}}}
\ No newline at end of file
diff --git a/crates/pop-contracts/tests/files/testing.json b/crates/pop-contracts/tests/files/testing.json
index ed230c98..61921986 100644
--- a/crates/pop-contracts/tests/files/testing.json
+++ b/crates/pop-contracts/tests/files/testing.json
@@ -1,6 +1,6 @@
{
"source": {
- "hash": "0x80776e58b218850d7d86447b2edea78d827ed0ed2499ff3a92b7ea10e4f95eb5",
+ "hash": "0xf4f0cafd08d8e362141b3c64e3c651ad6a38225dbf0b66f691c15bb0ea00eac3",
"language": "ink! 5.0.0",
"compiler": "rustc 1.78.0",
"build_info": {
@@ -33,6 +33,14 @@
},
{
"id": 1,
+ "type": {
+ "def": {
+ "primitive": "u32"
+ }
+ }
+ },
+ {
+ "id": 2,
"type": {
"path": [
"testing",
@@ -46,6 +54,11 @@
"name": "value",
"type": 0,
"typeName": ",>>::Type"
+ },
+ {
+ "name": "number",
+ "type": 1,
+ "typeName": ",>>::Type"
}
]
}
@@ -53,7 +66,7 @@
}
},
{
- "id": 2,
+ "id": 3,
"type": {
"path": [
"Result"
@@ -61,11 +74,11 @@
"params": [
{
"name": "T",
- "type": 3
+ "type": 4
},
{
"name": "E",
- "type": 4
+ "type": 5
}
],
"def": {
@@ -75,7 +88,7 @@
"name": "Ok",
"fields": [
{
- "type": 3
+ "type": 4
}
],
"index": 0
@@ -84,7 +97,7 @@
"name": "Err",
"fields": [
{
- "type": 4
+ "type": 5
}
],
"index": 1
@@ -95,7 +108,7 @@
}
},
{
- "id": 3,
+ "id": 4,
"type": {
"def": {
"tuple": []
@@ -103,7 +116,7 @@
}
},
{
- "id": 4,
+ "id": 5,
"type": {
"path": [
"ink_primitives",
@@ -122,7 +135,40 @@
}
},
{
- "id": 5,
+ "id": 6,
+ "type": {
+ "path": [
+ "Option"
+ ],
+ "params": [
+ {
+ "name": "T",
+ "type": 1
+ }
+ ],
+ "def": {
+ "variant": {
+ "variants": [
+ {
+ "name": "None",
+ "index": 0
+ },
+ {
+ "name": "Some",
+ "fields": [
+ {
+ "type": 1
+ }
+ ],
+ "index": 1
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "id": 7,
"type": {
"path": [
"Result"
@@ -134,7 +180,7 @@
},
{
"name": "E",
- "type": 4
+ "type": 5
}
],
"def": {
@@ -153,7 +199,7 @@
"name": "Err",
"fields": [
{
- "type": 4
+ "type": 5
}
],
"index": 1
@@ -164,7 +210,7 @@
}
},
{
- "id": 6,
+ "id": 8,
"type": {
"path": [
"ink_primitives",
@@ -175,7 +221,7 @@
"composite": {
"fields": [
{
- "type": 7,
+ "type": 9,
"typeName": "[u8; 32]"
}
]
@@ -184,18 +230,18 @@
}
},
{
- "id": 7,
+ "id": 9,
"type": {
"def": {
"array": {
"len": 32,
- "type": 8
+ "type": 10
}
}
}
},
{
- "id": 8,
+ "id": 10,
"type": {
"def": {
"primitive": "u8"
@@ -203,7 +249,7 @@
}
},
{
- "id": 9,
+ "id": 11,
"type": {
"def": {
"primitive": "u128"
@@ -211,7 +257,7 @@
}
},
{
- "id": 10,
+ "id": 12,
"type": {
"path": [
"ink_primitives",
@@ -222,7 +268,7 @@
"composite": {
"fields": [
{
- "type": 7,
+ "type": 9,
"typeName": "[u8; 32]"
}
]
@@ -231,7 +277,7 @@
}
},
{
- "id": 11,
+ "id": 13,
"type": {
"def": {
"primitive": "u64"
@@ -239,15 +285,7 @@
}
},
{
- "id": 12,
- "type": {
- "def": {
- "primitive": "u32"
- }
- }
- },
- {
- "id": 13,
+ "id": 14,
"type": {
"path": [
"ink_env",
@@ -275,11 +313,20 @@
"ty": 0
}
}
+ },
+ {
+ "name": "number",
+ "layout": {
+ "leaf": {
+ "key": "0x00000000",
+ "ty": 1
+ }
+ }
}
]
}
},
- "ty": 1
+ "ty": 2
}
},
"spec": {
@@ -300,7 +347,7 @@
}
],
"returnType": {
- "type": 2,
+ "type": 3,
"displayName": [
"ink_primitives",
"ConstructorResult"
@@ -315,9 +362,28 @@
"label": "default",
"selector": "0xed4b9d1b",
"payable": false,
- "args": [],
+ "args": [
+ {
+ "label": "init_value",
+ "type": {
+ "type": 0,
+ "displayName": [
+ "bool"
+ ]
+ }
+ },
+ {
+ "label": "number",
+ "type": {
+ "type": 6,
+ "displayName": [
+ "Option"
+ ]
+ }
+ }
+ ],
"returnType": {
- "type": 2,
+ "type": 3,
"displayName": [
"ink_primitives",
"ConstructorResult"
@@ -339,7 +405,7 @@
"payable": false,
"args": [],
"returnType": {
- "type": 2,
+ "type": 3,
"displayName": [
"ink",
"MessageResult"
@@ -359,7 +425,7 @@
"payable": false,
"args": [],
"returnType": {
- "type": 5,
+ "type": 7,
"displayName": [
"ink",
"MessageResult"
@@ -384,10 +450,19 @@
"bool"
]
}
+ },
+ {
+ "label": "number",
+ "type": {
+ "type": 6,
+ "displayName": [
+ "Option"
+ ]
+ }
}
],
"returnType": {
- "type": 2,
+ "type": 3,
"displayName": [
"ink",
"MessageResult"
@@ -403,7 +478,7 @@
"events": [],
"docs": [],
"lang_error": {
- "type": 4,
+ "type": 5,
"displayName": [
"ink",
"LangError"
@@ -411,37 +486,37 @@
},
"environment": {
"accountId": {
- "type": 6,
+ "type": 8,
"displayName": [
"AccountId"
]
},
"balance": {
- "type": 9,
+ "type": 11,
"displayName": [
"Balance"
]
},
"hash": {
- "type": 10,
+ "type": 12,
"displayName": [
"Hash"
]
},
"timestamp": {
- "type": 11,
+ "type": 13,
"displayName": [
"Timestamp"
]
},
"blockNumber": {
- "type": 12,
+ "type": 1,
"displayName": [
"BlockNumber"
]
},
"chainExtension": {
- "type": 13,
+ "type": 14,
"displayName": [
"ChainExtension"
]