--- a/pallets/nft/src/lib.rs +++ b/pallets/nft/src/lib.rs @@ -96,15 +96,6 @@ // this is needed only if you are using events in your pallet fn deposit_event() = default; - // Initializing events - // this is needed only if you are using events in your module - // fn deposit_event() = default; - - // Create collection of NFT with given parameters - // - // @param customDataSz size of custom data in each collection item - // returns collection ID - // Create collection of NFT with given parameters // // @param customDataSz size of custom data in each collection item --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -8,6 +8,7 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +use contracts_rpc_runtime_api::ContractExecResult; use grandpa::fg_primitives; use grandpa::{AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use sp_api::impl_runtime_apis; @@ -21,7 +22,6 @@ transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, MultiSignature, }; -use contracts_rpc_runtime_api::ContractExecResult; use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; --- a/smart_contract/ink-types-node-runtime/Cargo.toml +++ b/smart_contract/ink-types-node-runtime/Cargo.toml @@ -19,6 +19,7 @@ [dependencies] ink_core = { version = "2", git = "https://github.com/paritytech/ink", tag = "latest-v2", package = "ink_core", default-features = false } +ink_prelude = { version = "2", git = "https://github.com/paritytech/ink", tag = "latest-v2", package = "ink_prelude", default-features = false } frame-system = { git = "https://github.com/paritytech/substrate/", tag = "v2.0.0-rc3", package = "frame-system", default-features = false } pallet-indices = { git = "https://github.com/paritytech/substrate/", tag = "v2.0.0-rc3", package = "pallet-indices", default-features = false } sp-core = { git = "https://github.com/paritytech/substrate/", tag = "v2.0.0-rc3", package = "sp-core", default-features = false } --- a/smart_contract/ink-types-node-runtime/examples/calls/Cargo.lock +++ b/smart_contract/ink-types-node-runtime/examples/calls/Cargo.lock @@ -803,6 +803,7 @@ dependencies = [ "frame-system", "ink_core", + "ink_prelude", "pallet-indices", "parity-scale-codec", "sp-core", --- a/smart_contract/ink-types-node-runtime/examples/calls/lib.rs +++ b/smart_contract/ink-types-node-runtime/examples/calls/lib.rs @@ -7,7 +7,7 @@ use ink_core::env; use ink_prelude::*; use ink_types_node_runtime::{calls as runtime_calls, NodeRuntimeTypes}; - use ink_core::{memory::vec::Vec, storage}; + use ink_prelude::vec::Vec; /// This simple dummy contract dispatches substrate runtime calls #[ink(storage)] @@ -17,43 +17,167 @@ #[ink(constructor)] fn new(&mut self) {} - /// Dispatches a `transfer` call to the Balances srml module #[ink(message)] - fn create_collection(&self, collection_name: Vec, collection_description: Vec, - token_prefix: Vec, - custom_data_sz: u32) { - // create the Balances::transfer Call + fn transfer(&self, collection_id: u64, item_id: u64, new_owner: AccountId) { - // collection_name: Vec, - // collection_description: Vec, - // token_prefix: Vec, - // custom_data_sz: u32 + env::println(&format!( + "transfer invoke_runtime params {:?}, {:?}, {:?} ", + collection_id, + item_id, + new_owner + )); - let transfer_call = runtime_calls::create_collection(collection_name, collection_description, token_prefix, custom_data_sz); + let transfer_call = runtime_calls::transfer(collection_id, item_id, new_owner); // dispatch the call to the runtime let result = self.env().invoke_runtime(&transfer_call); // report result to console // NOTE: println should only be used on a development chain) env::println(&format!( - "Balance transfer invoke_runtime result {:?}", + "transfer invoke_runtime result {:?}", + result + )); + } + + // SafeTransfer + + #[ink(message)] + fn approve(&self, approved: AccountId, collection_id: u64, item_id: u64) { + + env::println(&format!( + "approve invoke_runtime params {:?}, {:?}, {:?} ", + approved, + collection_id, + item_id + )); + + let approve_call = runtime_calls::approve(approved, collection_id, item_id); + // dispatch the call to the runtime + let result = self.env().invoke_runtime(&approve_call); + + // report result to console + // NOTE: println should only be used on a development chain) + env::println(&format!( + "approve invoke_runtime result {:?}", + result + )); + } + + ////////////////////////////////////////// GetApproved + /// + /// Returns an account's free balance, read directly from runtime storage + /// + /// # Key Scheme + /// + /// A key for the [substrate storage map] + /// (https://github.com/paritytech/substrate/blob/dd97b1478b31a4715df7e88a5ebc6664425fb6c6/frame/support/src/storage/generator/map.rs#L28) + /// is constructed with: + /// + /// ```nocompile + /// Twox128(module_prefix) ++ Twox128(storage_prefix) ++ Hasher(encode(key)) + /// ``` + /// + /// For the `System` module's `Account` map, the [hasher implementation] + /// (https://github.com/paritytech/substrate/blob/2c87fe171bc341755a43a3b32d67560469f8daac/frame/system/src/lib.rs#L349) + /// is `blake2_128_concat`. + // #[ink(message)] + // fn get_balance(&self, account: AccountId) -> Balance { + // let mut key = vec![ + // // Precomputed: Twox128("System") + // 38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, + // // Precomputed: Twox128("Account") + // 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, + // ]; + + // let encoded_account = account.encode(); + // let hashed_account = ::hash_bytes(&encoded_account); + + // // The hasher is `Blake2_128Concat` which appends the unhashed account to the hashed account + // key.extend_from_slice(&hashed_account); + // key.extend_from_slice(&encoded_account); + + // // fetch from runtime storage + // let result = self.env().get_runtime_storage::(&key[..]); + // match result { + // Some(Ok(account_info)) => account_info.data.free, + // Some(Err(err)) => { + // env::println(&format!("Error reading AccountInfo {:?}", err)); + // 0 + // } + // None => { + // env::println(&format!("No data at key {:?}", key)); + // 0 + // } + // } + // } + + #[ink(message)] + fn transfer_from(&self, collection_id: u64, item_id: u64, new_owner: AccountId) { + + env::println(&format!( + "transfer_from invoke_runtime params {:?}, {:?}, {:?} ", + collection_id, + item_id, + new_owner + )); + + let transfer_from_call = runtime_calls::transfer_from(collection_id, item_id, new_owner); + // dispatch the call to the runtime + let result = self.env().invoke_runtime(&transfer_from_call); + + // report result to console + // NOTE: println should only be used on a development chain) + env::println(&format!( + "transfer_from invoke_runtime result {:?}", + result + )); + } + + // SafeTransferFrom + + #[ink(message)] + fn create_item(&self, collection_id: u64, properties: Vec) { + + env::println(&format!( + "create_item invoke_runtime params {:?}, {:?} ", + collection_id, + properties + )); + + let create_item_call = runtime_calls::create_item(collection_id, properties); + // dispatch the call to the runtime + let result = self.env().invoke_runtime(&create_item_call); + + // report result to console + // NOTE: println should only be used on a development chain) + env::println(&format!( + "create_item invoke_runtime result {:?}", result )); } - } - #[cfg(test)] - mod tests { - use super::*; - use sp_keyring::AccountKeyring; + #[ink(message)] + fn burn_item(&self, collection_id: u64, item_id: u64) { - #[test] - fn dispatches_balances_call() { - let calls = Calls::new(); - let alice = AccountId::from(AccountKeyring::Alice.to_account_id()); - // assert_eq!(calls.env().dispatched_calls().into_iter().count(), 0); - calls.balance_transfer(alice, 10000); - // assert_eq!(calls.env().dispatched_calls().into_iter().count(), 1); + env::println(&format!( + "burn_item invoke_runtime params {:?}, {:?}", + collection_id, + item_id + )); + + let burn_item_call = runtime_calls::burn_item(collection_id, item_id); + // dispatch the call to the runtime + let result = self.env().invoke_runtime(&burn_item_call); + + // report result to console + // NOTE: println should only be used on a development chain) + env::println(&format!( + "burn_item invoke_runtime result {:?}", + result + )); } + + // GetOwner + // BalanceOf } } --- a/smart_contract/ink-types-node-runtime/src/calls.rs +++ b/smart_contract/ink-types-node-runtime/src/calls.rs @@ -50,46 +50,6 @@ // Balances::::transfer(account.into(), balance).into() // } -// #[cfg(test)] -// mod tests { -// use crate::{calls, NodeRuntimeTypes}; -// use super::Call; - -// use node_runtime::{self, Runtime}; -// use pallet_indices::address; -// use scale::{Decode, Encode}; - - -// #[test] -// fn call_balance_transfer() { -// let balance = 10_000; -// let account_index = 0; - -// let contract_address = calls::Address::Index(account_index); -// let contract_transfer = -// calls::Balances::::transfer(contract_address, balance); -// let contract_call = Call::Balances(contract_transfer); - -// let srml_address = address::Address::Index(account_index); -// let srml_transfer = node_runtime::BalancesCall::::transfer(srml_address, balance); -// let srml_call = node_runtime::Call::Balances(srml_transfer); - -// let contract_call_encoded = contract_call.encode(); -// let srml_call_encoded = srml_call.encode(); - -// assert_eq!(srml_call_encoded, contract_call_encoded); - -// let srml_call_decoded: node_runtime::Call = -// Decode::decode(&mut contract_call_encoded.as_slice()) -// .expect("Balances transfer call decodes to srml type"); -// let srml_call_encoded = srml_call_decoded.encode(); -// let contract_call_decoded: Call = Decode::decode(&mut srml_call_encoded.as_slice()) -// .expect("Balances transfer call decodes back to contract type"); -// assert!(contract_call == contract_call_decoded); -// } -// } - - @@ -114,18 +74,18 @@ use ink_core::env::EnvTypes; use scale::{Codec, Decode, Encode}; -use pallet_indices::address::Address; use sp_runtime::traits::Member; +use ink_prelude::vec::Vec; use crate::{AccountId, Balance, NodeRuntimeTypes}; -use sp_runtime::sp_std::prelude::Vec; + /// Default runtime Call type, a subset of the runtime Call module variants /// /// The codec indices of the modules *MUST* match those in the concrete runtime. #[derive(Encode, Decode)] #[cfg_attr(feature = "std", derive(Clone, PartialEq, Eq))] pub enum Call { - #[codec(index = "8")] + #[codec(index = "7")] Nft(Nft), } @@ -140,61 +100,74 @@ where T: EnvTypes, T::AccountId: Member + Codec, -{ - #[allow(non_camel_case_types)] - create_nft_collection(Vec, Vec, Vec, u32), + { + #[allow(non_camel_case_types)] + create_collection(Vec, Vec, Vec, u32), - #[allow(non_camel_case_types)] - add_collection_admin(u64, T::AccountId), + #[allow(non_camel_case_types)] + destroy_collection(u64), - // collection_name: Vec, - // collection_description: Vec, - // token_prefix: Vec, - // custom_data_sz: u32 + #[allow(non_camel_case_types)] + change_collection_owner(u64, T::AccountId), -} + #[allow(non_camel_case_types)] + add_collection_admin(u64, T::AccountId), -// Construct a `Balances::transfer` call -pub fn create_collection(collection_name: Vec, collection_description: Vec, - token_prefix: Vec, custom_data_sz: u32) -> Call { - Nft::::create_nft_collection(collection_name, collection_description, token_prefix, custom_data_sz).into() -} + #[allow(non_camel_case_types)] + remove_collection_admin(u64, T::AccountId), -#[cfg(test)] -mod tests { - use crate::{calls, NodeRuntimeTypes}; - use super::Call; + #[allow(non_camel_case_types)] + create_item(u64, Vec), - use node_runtime::{self, Runtime}; - use pallet_indices::address; - use scale::{Decode, Encode}; + #[allow(non_camel_case_types)] + burn_item(u64, u64), + #[allow(non_camel_case_types)] + transfer(u64, u64, T::AccountId), - #[test] - fn call_balance_transfer() { - let balance = 10_000; - let account_index = 0; + #[allow(non_camel_case_types)] + nft_approve(T::AccountId, u64, u64), - let contract_address = calls::Address::Index(account_index); - let contract_transfer = - calls::Balances::::transfer(contract_address, balance); - let contract_call = Call::Balances(contract_transfer); + #[allow(non_camel_case_types)] + nft_transfer_from(u64, u64, T::AccountId), - let srml_address = address::Address::Index(account_index); - let srml_transfer = node_runtime::BalancesCall::::transfer(srml_address, balance); - let srml_call = node_runtime::Call::Balances(srml_transfer); + #[allow(non_camel_case_types)] + nft_safe_transfer(u64, u64, T::AccountId), + } - let contract_call_encoded = contract_call.encode(); - let srml_call_encoded = srml_call.encode(); - assert_eq!(srml_call_encoded, contract_call_encoded); - let srml_call_decoded: node_runtime::Call = - Decode::decode(&mut contract_call_encoded.as_slice()) - .expect("Balances transfer call decodes to srml type"); - let srml_call_encoded = srml_call_decoded.encode(); - let contract_call_decoded: Call = Decode::decode(&mut srml_call_encoded.as_slice()) - .expect("Balances transfer call decodes back to contract type"); - assert!(contract_call == contract_call_decoded); - } + +pub fn transfer(collection_id: u64, item_id: u64, new_owner: AccountId) -> Call { + Nft::::transfer(collection_id, item_id, new_owner.into()).into() +} + +pub fn create_collection(collection_name: Vec, collection_description: Vec, + token_prefix: Vec, custom_data_sz: u32) -> Call { + Nft::::create_collection(collection_name, collection_description, token_prefix, custom_data_sz).into() +} + +// pub fn safe_transfer(collection_id: u64, item_id: u64, new_owner: AccountId) -> Call { +// Nft::::nft_safe_transfer(collection_id, item_id, new_owner.into()).into() +// } + +pub fn approve(approved: AccountId, collection_id: u64, item_id: u64) -> Call { + Nft::::nft_approve(approved.into(), collection_id, item_id).into() +} + +//GetApproved + +pub fn transfer_from(collection_id: u64, item_id: u64, new_owner: AccountId) -> Call { + Nft::::nft_transfer_from(collection_id, item_id, new_owner.into()).into() +} + +pub fn create_item(collection_id: u64, properties: Vec) -> Call { + Nft::::create_item(collection_id, properties).into() +} + +pub fn burn_item(collection_id: u64, item_id: u64) -> Call { + Nft::::burn_item(collection_id, item_id).into() } + +//GetOwner +//BalanceOf \ No newline at end of file --- a/smart_contract/ink-types-node-runtime/src/lib.rs +++ b/smart_contract/ink-types-node-runtime/src/lib.rs @@ -36,6 +36,7 @@ #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Encode, Decode)] pub struct AccountId (AccountId32); + impl From for AccountId { fn from(account: AccountId32) -> Self { AccountId(account)