difftreelog
Offchain schema added
in: master
6 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3086,6 +3086,7 @@
"frame-support",
"frame-system",
"parity-scale-codec",
+ "serde",
"sp-core",
"sp-io",
"sp-runtime",
pallets/nft/Cargo.tomldiffbeforeafterboth--- a/pallets/nft/Cargo.toml
+++ b/pallets/nft/Cargo.toml
@@ -32,6 +32,10 @@
git = 'https://github.com/usetech-llc/substrate.git'
branch = 'rc4_ext_dispatch_reenabled'
version = '2.0.0-rc4'
+
+[dependencies]
+# third-party dependencies
+serde = { version = "1.0.102", features = ["derive"] }
[package]
authors = ['Substrate DevHub <https://github.com/substrate-developer-hub>']
@@ -49,6 +53,7 @@
default = ['std']
std = [
'codec/std',
+ "serde/std",
'frame-support/std',
'frame-system/std',
'sp-runtime/std',
pallets/nft/src/lib.rsdiffbeforeafterboth--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -14,6 +14,27 @@
#[cfg(test)]
mod tests;
+#[derive(Encode, Decode, Debug, Eq, Clone, PartialEq)]
+pub enum CollectionMode {
+ Invalid,
+ // custom data size
+ NFT(u32),
+ // amount
+ Fungible(u32),
+ ReFungible,
+}
+
+impl Into<u8> for CollectionMode {
+ fn into(self) -> u8{
+ match self {
+ CollectionMode::Invalid => 0,
+ CollectionMode::NFT(_) => 1,
+ CollectionMode::Fungible(_) => 2,
+ CollectionMode::ReFungible => 3,
+ }
+ }
+}
+
#[derive(Encode, Decode, Debug, Clone, PartialEq)]
pub enum AccessMode {
Normal,
@@ -21,13 +42,6 @@
}
impl Default for AccessMode { fn default() -> Self { Self::Normal } }
-#[derive(Encode, Decode, Debug, Eq, Clone, PartialEq)]
-pub enum CollectionMode {
- Invalid,
- NFT,
- Fungible,
- ReFungible,
-}
impl Default for CollectionMode { fn default() -> Self { Self::Invalid } }
#[derive(Encode, Decode, Default, Clone, PartialEq)]
@@ -49,6 +63,9 @@
pub description: Vec<u16>, // 256 include null escape char
pub token_prefix: Vec<u8>, // 16 include null escape char
pub custom_data_size: u32,
+ pub offchain_schema: Vec<u8>,
+ pub sponsor: AccountId, // Who pays fees. If set to default address, the fees are applied to the transaction sender
+ pub unconfirmed_sponsor: AccountId, // Sponsor address that has not yet confirmed sponsorship
}
#[derive(Encode, Decode, Default, Clone, PartialEq)]
@@ -88,8 +105,10 @@
decl_storage! {
trait Store for Module<T: Trait> as Nft {
- // Next available collection ID
- NextCollectionID get(fn next_collection_id): u64;
+ // Private members
+ NextCollectionID: u64;
+ ItemListIndex: map hasher(blake2_128_concat) u64 => u64;
+
pub Collection get(fn collection): map hasher(identity) u64 => CollectionType<T::AccountId>;
pub AdminList get(fn admin_list_collection): map hasher(identity) u64 => Vec<T::AccountId>;
@@ -101,7 +120,6 @@
pub NftItemList get(fn nft_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => NftItemType<T::AccountId>;
pub FungibleItemList get(fn fungible_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => FungibleItemType<T::AccountId>;
pub ReFungibleItemList get(fn refungible_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => ReFungibleItemType<T::AccountId>;
- ItemListIndex get(fn item_index): map hasher(blake2_128_concat) u64 => u64;
pub AddressTokens get(fn address_tokens): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) T::AccountId => Vec<u64>;
}
@@ -132,36 +150,19 @@
collection_name: Vec<u16>,
collection_description: Vec<u16>,
token_prefix: Vec<u8>,
- mode: u8,
- decimal_points: u32,
- custom_data_size: u32) -> DispatchResult {
+ mode: CollectionMode) -> DispatchResult {
// Anyone can create a collection
let who = ensure_signed(origin)?;
- let collection_mode: CollectionMode;
- match mode {
- 1 => collection_mode = CollectionMode::NFT,
- 2 => collection_mode = CollectionMode::Fungible,
- 3 => collection_mode = CollectionMode::ReFungible,
- _ => collection_mode = CollectionMode::Invalid
- }
-
- // check type
- ensure!((collection_mode == CollectionMode::Fungible || collection_mode == CollectionMode::NFT || collection_mode == CollectionMode::ReFungible),
- "Collection mode must be Fungible, NFT or ReFungible");
-
- // NFT checks
- if collection_mode == CollectionMode::NFT
- {
- ensure!(decimal_points == 0, "Collection in NFT mode must have zero in decimal_points parameter");
- }
+ let custom_data_size = match mode {
+ CollectionMode::NFT(size) => size,
+ _ => 0
+ };
- // Fungible checks
- if collection_mode == CollectionMode::Fungible
- {
- ensure!(custom_data_size == 0, "Collection in Fungible mode must have zero in custom_data_size parameter");
- ensure!(decimal_points != 0, "Collection in Fungible mode must have not zero in decimal_points parameter");
- }
+ let decimal_points = match mode {
+ CollectionMode::Fungible(points) => points,
+ _ => 0
+ };
// check params
ensure!(decimal_points < 100, "decimal_points parameter must be lower than 100");
@@ -189,20 +190,23 @@
let new_collection = CollectionType {
owner: who.clone(),
name: name,
- mode: collection_mode.clone(),
+ mode: mode.clone(),
access: AccessMode::Normal,
description: description,
decimal_points: decimal_points,
token_prefix: prefix,
next_item_id: next_id,
+ offchain_schema: Vec::new(),
custom_data_size: custom_data_size,
+ sponsor: T::AccountId::default(),
+ unconfirmed_sponsor: T::AccountId::default(),
};
// Add new collection to map
<Collection<T>>::insert(next_id, new_collection);
// call event
- Self::deposit_event(RawEvent::Created(next_id, mode, who.clone()));
+ Self::deposit_event(RawEvent::Created(next_id, mode.into(), who.clone()));
Ok(())
}
@@ -285,19 +289,21 @@
<Balance<T>>::insert(collection_id, owner.clone(), new_balance);
// TODO: implement other modes
- ensure!(target_collection.mode == CollectionMode::NFT, "Collection type not implemented");
-
- if target_collection.mode == CollectionMode::NFT
+ match target_collection.mode
{
+ CollectionMode::NFT(_) => {
// Create nft item
- let item = NftItemType {
- collection: collection_id,
- owner: owner,
- data: properties,
- };
-
- Self::add_nft_item(item)?;
- }
+ let item = NftItemType {
+ collection: collection_id,
+ owner: owner,
+ data: properties,
+ };
+
+ Self::add_nft_item(item)?;
+
+ },
+ _ => ()
+ };
// call event
Self::deposit_event(RawEvent::ItemCreated(collection_id, <ItemListIndex>::get(collection_id)));
@@ -336,12 +342,11 @@
let target_collection = <Collection<T>>::get(collection_id);
// TODO: implement other modes
- ensure!(target_collection.mode == CollectionMode::NFT, "Collection type not implemented");
-
- if target_collection.mode == CollectionMode::NFT
+ match target_collection.mode
{
- Self::transfer_nft(collection_id, item_id, recipient)?;
- }
+ CollectionMode::NFT(_) => Self::transfer_nft(collection_id, item_id, recipient)?,
+ _ => ()
+ };
Ok(())
}
@@ -395,13 +400,12 @@
let target_collection = <Collection<T>>::get(collection_id);
- // TODO: implement other modes
- ensure!(target_collection.mode == CollectionMode::NFT, "Collection type not implemented");
-
- if target_collection.mode == CollectionMode::NFT
+ match target_collection.mode
{
- Self::transfer_nft(collection_id, item_id, recipient)?;
- }
+ CollectionMode::NFT(_) => Self::transfer_nft(collection_id, item_id, recipient)?,
+ // TODO: implement other modes
+ _ => ()
+ };
Ok(())
}
@@ -420,6 +424,22 @@
Ok(())
}
+
+ #[weight = 0]
+ pub fn set_offchain_schema(
+ origin,
+ collection_id: u64,
+ schema: Vec<u8>
+ ) -> DispatchResult {
+ let sender = ensure_signed(origin)?;
+ Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;
+
+ let mut target_collection = <Collection<T>>::get(collection_id);
+ target_collection.offchain_schema = schema;
+ <Collection<T>>::insert(collection_id, target_collection);
+
+ Ok(())
+ }
}
}
@@ -460,28 +480,14 @@
fn is_item_owner(subject: T::AccountId, collection_id: u64, item_id: u64) -> bool{
- let mut result = false;
let target_collection = <Collection<T>>::get(collection_id);
- if target_collection.mode == CollectionMode::NFT
- {
- let item = <NftItemList<T>>::get(collection_id, item_id);
- result = item.owner == subject;
- }
-
- if target_collection.mode == CollectionMode::Fungible
- {
- let item = <FungibleItemList<T>>::get(collection_id, item_id);
- result = item.owner.contains(&subject);
- }
-
- if target_collection.mode == CollectionMode::ReFungible
- {
- let item = <ReFungibleItemList<T>>::get(collection_id, item_id);
- result = item.owner.iter().any(|i| i.owner == subject);
+ match target_collection.mode {
+ CollectionMode::NFT(_) => <NftItemList<T>>::get(collection_id, item_id).owner == subject,
+ CollectionMode::Fungible(_) => <FungibleItemList<T>>::get(collection_id, item_id).owner.contains(&subject),
+ CollectionMode::ReFungible => <ReFungibleItemList<T>>::get(collection_id, item_id).owner.iter().any(|i| i.owner == subject),
+ CollectionMode::Invalid => false
}
-
- result
}
fn add_nft_item(item: NftItemType<T::AccountId>) -> DispatchResult {
smart_contract/ink-types-node-runtime/README.mddiffbeforeafterboth--- a/smart_contract/ink-types-node-runtime/README.md
+++ b/smart_contract/ink-types-node-runtime/README.md
@@ -30,4 +30,67 @@
## Test
```
cargo +nightly test
+```
+
+## UI custom types
+```
+{
+ "Schedule": {
+ "version": "u32",
+ "put_code_per_byte_cost": "Gas",
+ "grow_mem_cost": "Gas",
+ "regular_op_cost": "Gas",
+ "return_data_per_byte_cost": "Gas",
+ "event_data_per_byte_cost": "Gas",
+ "event_per_topic_cost": "Gas",
+ "event_base_cost": "Gas",
+ "call_base_cost": "Gas",
+ "instantiate_base_cost": "Gas",
+ "dispatch_base_cost": "Gas",
+ "sandbox_data_read_cost": "Gas",
+ "sandbox_data_write_cost": "Gas",
+ "transfer_cost": "Gas",
+ "instantiate_cost": "Gas",
+ "max_event_topics": "u32",
+ "max_stack_height": "u32",
+ "max_memory_pages": "u32",
+ "max_table_size": "u32",
+ "enable_println": "bool",
+ "max_subject_len": "u32"
+ },
+ "CollectionMode": {
+ "_enum": {
+ "Invalid": null,
+ "NFT": "u32",
+ "Fungible": "u32",
+ "ReFungible": null
+ }
+ },
+ "NftItemType": {
+ "Collection": "u64",
+ "Owner": "AccountId",
+ "Data": "Vec<u8>"
+ },
+
+
+"CollectionType": {
+ "Owner": "AccountId",
+ "Mode": "u8",
+ "ModeParam": "u32",
+ "Access": "u8",
+ "NextItemId": "u64",
+ "DecimalPoints": "u32",
+ "Name": "Vec<u16>",
+ "Description": "Vec<u16>",
+ "TokenPrefix": "Vec<u8>",
+ "CustomDataSize": "u32",
+ "OffchainSchema": "Vec<u8>",
+ "Sponsor": "AccountId",
+ "UnconfirmedSponsor": "AccountId"
+ },
+ "RawData": "Vec<u8>",
+ "Address": "AccountId",
+ "LookupSource": "AccountId",
+ "Weight": "u64"
+}
```
\ No newline at end of file
smart_contract/ink-types-node-runtime/calls/lib.rsdiffbeforeafterboth--- a/smart_contract/ink-types-node-runtime/calls/lib.rs
+++ b/smart_contract/ink-types-node-runtime/calls/lib.rs
@@ -123,15 +123,14 @@
}
// SafeTransferFrom
-
#[ink(message)]
- fn create_item(&self, collection_id: u64, properties: Vec<u8>) {
+ fn create_item(&self, collection_id: u64, properties: Vec<u8>, owner: AccountId) {
env::println(&format!(
"create_item invoke_runtime params {:?}, {:?} ",
collection_id, properties
));
- let create_item_call = runtime_calls::create_item(collection_id, properties);
+ let create_item_call = runtime_calls::create_item(collection_id, properties, owner);
// dispatch the call to the runtime
let result = self.env().invoke_runtime(&create_item_call);
smart_contract/ink-types-node-runtime/src/calls.rsdiffbeforeafterboth25 T::AccountId: Member + Codec,25 T::AccountId: Member + Codec,26{26{27 #[allow(non_camel_case_types)]27 #[allow(non_camel_case_types)]28 create_collection(Vec<u16>, Vec<u16>, Vec<u8>, u32),28 create_collection(Vec<u16>, Vec<u16>, Vec<u8>, u8, u32, u32),292930 #[allow(non_camel_case_types)]30 #[allow(non_camel_case_types)]31 destroy_collection(u64),31 destroy_collection(u64),40 remove_collection_admin(u64, T::AccountId),40 remove_collection_admin(u64, T::AccountId),414142 #[allow(non_camel_case_types)]42 #[allow(non_camel_case_types)]43 create_item(u64, Vec<u8>),43 create_item(u64, Vec<u8>, T::AccountId),444445 #[allow(non_camel_case_types)]45 #[allow(non_camel_case_types)]46 burn_item(u64, u64),46 burn_item(u64, u64),474748 #[allow(non_camel_case_types)]48 #[allow(non_camel_case_types)]49 transfer(u64, u64, T::AccountId),49 transfer(T::AccountId, u64, u64),505051 #[allow(non_camel_case_types)]51 #[allow(non_camel_case_types)]52 nft_approve(T::AccountId, u64, u64),52 nft_approve(T::AccountId, u64, u64),535354 #[allow(non_camel_case_types)]54 #[allow(non_camel_case_types)]55 nft_transfer_from(u64, u64, T::AccountId),55 nft_transfer_from(T::AccountId, u64, u64),565657 #[allow(non_camel_case_types)]57 #[allow(non_camel_case_types)]58 nft_safe_transfer(u64, u64, T::AccountId),58 nft_safe_transfer(u64, u64, T::AccountId),66 collection_name: Vec<u16>,66 collection_name: Vec<u16>,67 collection_description: Vec<u16>,67 collection_description: Vec<u16>,68 token_prefix: Vec<u8>,68 token_prefix: Vec<u8>,69 mode: u8,69 custom_data_sz: u32,70 decimal_points: u32,71 custom_data_size: u32,70) -> Call {72) -> Call {71 Nft::<NodeRuntimeTypes>::create_collection(73 Nft::<NodeRuntimeTypes>::create_collection(72 collection_name,74 collection_name,73 collection_description,75 collection_description,74 token_prefix,76 token_prefix,75 custom_data_sz,77 mode,78 decimal_points,79 custom_data_size,76 )80 )77 .into()81 .into()78}82}89 Nft::<NodeRuntimeTypes>::nft_transfer_from(collection_id, item_id, new_owner.into()).into()93 Nft::<NodeRuntimeTypes>::nft_transfer_from(collection_id, item_id, new_owner.into()).into()90}94}919592pub fn create_item(collection_id: u64, properties: Vec<u8>) -> Call {96pub fn create_item(collection_id: u64, properties: Vec<u8>, owner: AccountId) -> Call {93 Nft::<NodeRuntimeTypes>::create_item(collection_id, properties).into()97 Nft::<NodeRuntimeTypes>::create_item(collection_id, properties, owner).into()94}98}959996pub fn burn_item(collection_id: u64, item_id: u64) -> Call {100pub fn burn_item(collection_id: u64, item_id: u64) -> Call {