git.delta.rocks / unique-network / refs/commits / 675d1d0e13af

difftreelog

Offchain schema added

str-mv2020-08-03parent: #a3fcd2f.patch.diff
in: master

6 files changed

modifiedCargo.lockdiffbeforeafterboth
3086 "frame-support",3086 "frame-support",
3087 "frame-system",3087 "frame-system",
3088 "parity-scale-codec",3088 "parity-scale-codec",
3089 "serde",
3089 "sp-core",3090 "sp-core",
3090 "sp-io",3091 "sp-io",
3091 "sp-runtime",3092 "sp-runtime",
modifiedpallets/nft/Cargo.tomldiffbeforeafterboth
33branch = 'rc4_ext_dispatch_reenabled'33branch = 'rc4_ext_dispatch_reenabled'
34version = '2.0.0-rc4'34version = '2.0.0-rc4'
35
36[dependencies]
37# third-party dependencies
38serde = { version = "1.0.102", features = ["derive"] }
3539
36[package]40[package]
37authors = ['Substrate DevHub <https://github.com/substrate-developer-hub>']41authors = ['Substrate DevHub <https://github.com/substrate-developer-hub>']
49default = ['std']53default = ['std']
50std = [54std = [
51 'codec/std',55 'codec/std',
56 "serde/std",
52 'frame-support/std',57 'frame-support/std',
53 'frame-system/std',58 'frame-system/std',
54 'sp-runtime/std',59 'sp-runtime/std',
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
14#[cfg(test)]14#[cfg(test)]
15mod tests;15mod tests;
16
17#[derive(Encode, Decode, Debug, Eq, Clone, PartialEq)]
18pub enum CollectionMode {
19 Invalid,
20 // custom data size
21 NFT(u32),
22 // amount
23 Fungible(u32),
24 ReFungible,
25}
26
27impl Into<u8> for CollectionMode {
28 fn into(self) -> u8{
29 match self {
30 CollectionMode::Invalid => 0,
31 CollectionMode::NFT(_) => 1,
32 CollectionMode::Fungible(_) => 2,
33 CollectionMode::ReFungible => 3,
34 }
35 }
36}
1637
17#[derive(Encode, Decode, Debug, Clone, PartialEq)]38#[derive(Encode, Decode, Debug, Clone, PartialEq)]
18pub enum AccessMode {39pub enum AccessMode {
21}42}
22impl Default for AccessMode { fn default() -> Self { Self::Normal } }43impl Default for AccessMode { fn default() -> Self { Self::Normal } }
2344
24#[derive(Encode, Decode, Debug, Eq, Clone, PartialEq)]
25pub enum CollectionMode {
26 Invalid,
27 NFT,
28 Fungible,
29 ReFungible,
30}
31impl Default for CollectionMode { fn default() -> Self { Self::Invalid } }45impl Default for CollectionMode { fn default() -> Self { Self::Invalid } }
3246
33#[derive(Encode, Decode, Default, Clone, PartialEq)]47#[derive(Encode, Decode, Default, Clone, PartialEq)]
49 pub description: Vec<u16>, // 256 include null escape char63 pub description: Vec<u16>, // 256 include null escape char
50 pub token_prefix: Vec<u8>, // 16 include null escape char64 pub token_prefix: Vec<u8>, // 16 include null escape char
51 pub custom_data_size: u32,65 pub custom_data_size: u32,
66 pub offchain_schema: Vec<u8>,
67 pub sponsor: AccountId, // Who pays fees. If set to default address, the fees are applied to the transaction sender
68 pub unconfirmed_sponsor: AccountId, // Sponsor address that has not yet confirmed sponsorship
52}69}
5370
54#[derive(Encode, Decode, Default, Clone, PartialEq)]71#[derive(Encode, Decode, Default, Clone, PartialEq)]
88decl_storage! {105decl_storage! {
89 trait Store for Module<T: Trait> as Nft {106 trait Store for Module<T: Trait> as Nft {
90107
91 // Next available collection ID108 // Private members
92 NextCollectionID get(fn next_collection_id): u64;109 NextCollectionID: u64;
110 ItemListIndex: map hasher(blake2_128_concat) u64 => u64;
111
93 pub Collection get(fn collection): map hasher(identity) u64 => CollectionType<T::AccountId>;112 pub Collection get(fn collection): map hasher(identity) u64 => CollectionType<T::AccountId>;
94 pub AdminList get(fn admin_list_collection): map hasher(identity) u64 => Vec<T::AccountId>;113 pub AdminList get(fn admin_list_collection): map hasher(identity) u64 => Vec<T::AccountId>;
101 pub NftItemList get(fn nft_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => NftItemType<T::AccountId>;120 pub NftItemList get(fn nft_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => NftItemType<T::AccountId>;
102 pub FungibleItemList get(fn fungible_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => FungibleItemType<T::AccountId>;121 pub FungibleItemList get(fn fungible_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => FungibleItemType<T::AccountId>;
103 pub ReFungibleItemList get(fn refungible_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => ReFungibleItemType<T::AccountId>;122 pub ReFungibleItemList get(fn refungible_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => ReFungibleItemType<T::AccountId>;
104 ItemListIndex get(fn item_index): map hasher(blake2_128_concat) u64 => u64;
105123
106 pub AddressTokens get(fn address_tokens): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) T::AccountId => Vec<u64>;124 pub AddressTokens get(fn address_tokens): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) T::AccountId => Vec<u64>;
107 }125 }
132 collection_name: Vec<u16>,150 collection_name: Vec<u16>,
133 collection_description: Vec<u16>,151 collection_description: Vec<u16>,
134 token_prefix: Vec<u8>,152 token_prefix: Vec<u8>,
135 mode: u8,153 mode: CollectionMode) -> DispatchResult {
136 decimal_points: u32,
137 custom_data_size: u32) -> DispatchResult {
138154
139 // Anyone can create a collection155 // Anyone can create a collection
140 let who = ensure_signed(origin)?;156 let who = ensure_signed(origin)?;
141 let collection_mode: CollectionMode;157 let custom_data_size = match mode {
142 match mode {
143 1 => collection_mode = CollectionMode::NFT,158 CollectionMode::NFT(size) => size,
144 2 => collection_mode = CollectionMode::Fungible,
145 3 => collection_mode = CollectionMode::ReFungible,
146 _ => collection_mode = CollectionMode::Invalid159 _ => 0
147 }160 };
148161
149 // check type
150 ensure!((collection_mode == CollectionMode::Fungible || collection_mode == CollectionMode::NFT || collection_mode == CollectionMode::ReFungible),
151 "Collection mode must be Fungible, NFT or ReFungible");
152
153 // NFT checks
154 if collection_mode == CollectionMode::NFT
155 {
156 ensure!(decimal_points == 0, "Collection in NFT mode must have zero in decimal_points parameter"); 162 let decimal_points = match mode {
157 }
158
159 // Fungible checks
160 if collection_mode == CollectionMode::Fungible163 CollectionMode::Fungible(points) => points,
161 {
162 ensure!(custom_data_size == 0, "Collection in Fungible mode must have zero in custom_data_size parameter");
163 ensure!(decimal_points != 0, "Collection in Fungible mode must have not zero in decimal_points parameter"); 164 _ => 0
164 }165 };
165166
166 // check params167 // check params
167 ensure!(decimal_points < 100, "decimal_points parameter must be lower than 100"); 168 ensure!(decimal_points < 100, "decimal_points parameter must be lower than 100");
189 let new_collection = CollectionType {190 let new_collection = CollectionType {
190 owner: who.clone(),191 owner: who.clone(),
191 name: name,192 name: name,
192 mode: collection_mode.clone(),193 mode: mode.clone(),
193 access: AccessMode::Normal,194 access: AccessMode::Normal,
194 description: description,195 description: description,
195 decimal_points: decimal_points,196 decimal_points: decimal_points,
196 token_prefix: prefix,197 token_prefix: prefix,
197 next_item_id: next_id,198 next_item_id: next_id,
199 offchain_schema: Vec::new(),
198 custom_data_size: custom_data_size,200 custom_data_size: custom_data_size,
201 sponsor: T::AccountId::default(),
202 unconfirmed_sponsor: T::AccountId::default(),
199 };203 };
200204
201 // Add new collection to map205 // Add new collection to map
202 <Collection<T>>::insert(next_id, new_collection);206 <Collection<T>>::insert(next_id, new_collection);
203207
204 // call event208 // call event
205 Self::deposit_event(RawEvent::Created(next_id, mode, who.clone()));209 Self::deposit_event(RawEvent::Created(next_id, mode.into(), who.clone()));
206210
207 Ok(())211 Ok(())
208 }212 }
285 <Balance<T>>::insert(collection_id, owner.clone(), new_balance);289 <Balance<T>>::insert(collection_id, owner.clone(), new_balance);
286290
287 // TODO: implement other modes291 // TODO: implement other modes
288 ensure!(target_collection.mode == CollectionMode::NFT, "Collection type not implemented");292 match target_collection.mode
289293 {
290 if target_collection.mode == CollectionMode::NFT
291 {294 CollectionMode::NFT(_) => {
292 // Create nft item295 // Create nft item
293 let item = NftItemType {296 let item = NftItemType {
294 collection: collection_id,297 collection: collection_id,
298301
299 Self::add_nft_item(item)?;302 Self::add_nft_item(item)?;
303
300 }304 },
305 _ => ()
306 };
301307
302 // call event308 // call event
303 Self::deposit_event(RawEvent::ItemCreated(collection_id, <ItemListIndex>::get(collection_id)));309 Self::deposit_event(RawEvent::ItemCreated(collection_id, <ItemListIndex>::get(collection_id)));
336 let target_collection = <Collection<T>>::get(collection_id);342 let target_collection = <Collection<T>>::get(collection_id);
337343
338 // TODO: implement other modes344 // TODO: implement other modes
339 ensure!(target_collection.mode == CollectionMode::NFT, "Collection type not implemented");345 match target_collection.mode
340346 {
341 if target_collection.mode == CollectionMode::NFT
342 {
343 Self::transfer_nft(collection_id, item_id, recipient)?;347 CollectionMode::NFT(_) => Self::transfer_nft(collection_id, item_id, recipient)?,
344 }348 _ => ()
349 };
345350
346 Ok(())351 Ok(())
347 }352 }
395 400
396 let target_collection = <Collection<T>>::get(collection_id);401 let target_collection = <Collection<T>>::get(collection_id);
397402
398 // TODO: implement other modes
399 ensure!(target_collection.mode == CollectionMode::NFT, "Collection type not implemented");403 match target_collection.mode
400404 {
401 if target_collection.mode == CollectionMode::NFT
402 {
403 Self::transfer_nft(collection_id, item_id, recipient)?;405 CollectionMode::NFT(_) => Self::transfer_nft(collection_id, item_id, recipient)?,
404 }406 // TODO: implement other modes
407 _ => ()
408 };
405409
406 Ok(())410 Ok(())
407 }411 }
421 Ok(())425 Ok(())
422 }426 }
427
428 #[weight = 0]
429 pub fn set_offchain_schema(
430 origin,
431 collection_id: u64,
432 schema: Vec<u8>
433 ) -> DispatchResult {
434 let sender = ensure_signed(origin)?;
435 Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;
436
437 let mut target_collection = <Collection<T>>::get(collection_id);
438 target_collection.offchain_schema = schema;
439 <Collection<T>>::insert(collection_id, target_collection);
440
441 Ok(())
442 }
423 }443 }
424}444}
425445
460480
461 fn is_item_owner(subject: T::AccountId, collection_id: u64, item_id: u64) -> bool{481 fn is_item_owner(subject: T::AccountId, collection_id: u64, item_id: u64) -> bool{
462482
463 let mut result = false;
464 let target_collection = <Collection<T>>::get(collection_id);483 let target_collection = <Collection<T>>::get(collection_id);
465484
466 if target_collection.mode == CollectionMode::NFT485 match target_collection.mode {
467 {486 CollectionMode::NFT(_) => <NftItemList<T>>::get(collection_id, item_id).owner == subject,
468 let item = <NftItemList<T>>::get(collection_id, item_id);
469 result = item.owner == subject;
470 }
471
472 if target_collection.mode == CollectionMode::Fungible487 CollectionMode::Fungible(_) => <FungibleItemList<T>>::get(collection_id, item_id).owner.contains(&subject),
473 {
474 let item = <FungibleItemList<T>>::get(collection_id, item_id);
475 result = item.owner.contains(&subject);
476 }
477
478 if target_collection.mode == CollectionMode::ReFungible488 CollectionMode::ReFungible => <ReFungibleItemList<T>>::get(collection_id, item_id).owner.iter().any(|i| i.owner == subject),
479 {489 CollectionMode::Invalid => false
480 let item = <ReFungibleItemList<T>>::get(collection_id, item_id);490 }
481 result = item.owner.iter().any(|i| i.owner == subject);
482 }
483
484 result
485 }491 }
486492
487 fn add_nft_item(item: NftItemType<T::AccountId>) -> DispatchResult {493 fn add_nft_item(item: NftItemType<T::AccountId>) -> DispatchResult {
modifiedsmart_contract/ink-types-node-runtime/README.mddiffbeforeafterboth
30## Test30## Test
31```31```
32cargo +nightly test32cargo +nightly test
33```
34
35## UI custom types
36```
37{
38 "Schedule": {
39 "version": "u32",
40 "put_code_per_byte_cost": "Gas",
41 "grow_mem_cost": "Gas",
42 "regular_op_cost": "Gas",
43 "return_data_per_byte_cost": "Gas",
44 "event_data_per_byte_cost": "Gas",
45 "event_per_topic_cost": "Gas",
46 "event_base_cost": "Gas",
47 "call_base_cost": "Gas",
48 "instantiate_base_cost": "Gas",
49 "dispatch_base_cost": "Gas",
50 "sandbox_data_read_cost": "Gas",
51 "sandbox_data_write_cost": "Gas",
52 "transfer_cost": "Gas",
53 "instantiate_cost": "Gas",
54 "max_event_topics": "u32",
55 "max_stack_height": "u32",
56 "max_memory_pages": "u32",
57 "max_table_size": "u32",
58 "enable_println": "bool",
59 "max_subject_len": "u32"
60 },
61 "CollectionMode": {
62 "_enum": {
63 "Invalid": null,
64 "NFT": "u32",
65 "Fungible": "u32",
66 "ReFungible": null
67 }
68 },
69 "NftItemType": {
70 "Collection": "u64",
71 "Owner": "AccountId",
72 "Data": "Vec<u8>"
73 },
74
75
76"CollectionType": {
77 "Owner": "AccountId",
78 "Mode": "u8",
79 "ModeParam": "u32",
80 "Access": "u8",
81 "NextItemId": "u64",
82 "DecimalPoints": "u32",
83 "Name": "Vec<u16>",
84 "Description": "Vec<u16>",
85 "TokenPrefix": "Vec<u8>",
86 "CustomDataSize": "u32",
87 "OffchainSchema": "Vec<u8>",
88 "Sponsor": "AccountId",
89 "UnconfirmedSponsor": "AccountId"
90 },
91 "RawData": "Vec<u8>",
92 "Address": "AccountId",
93 "LookupSource": "AccountId",
94 "Weight": "u64"
95}
33```96```
modifiedsmart_contract/ink-types-node-runtime/calls/lib.rsdiffbeforeafterboth
125 // SafeTransferFrom125 // SafeTransferFrom
126
127 #[ink(message)]126 #[ink(message)]
128 fn create_item(&self, collection_id: u64, properties: Vec<u8>) {127 fn create_item(&self, collection_id: u64, properties: Vec<u8>, owner: AccountId) {
129 env::println(&format!(128 env::println(&format!(
130 "create_item invoke_runtime params {:?}, {:?} ",129 "create_item invoke_runtime params {:?}, {:?} ",
131 collection_id, properties130 collection_id, properties
132 ));131 ));
133132
134 let create_item_call = runtime_calls::create_item(collection_id, properties);133 let create_item_call = runtime_calls::create_item(collection_id, properties, owner);
135 // dispatch the call to the runtime134 // dispatch the call to the runtime
136 let result = self.env().invoke_runtime(&create_item_call);135 let result = self.env().invoke_runtime(&create_item_call);
137136
modifiedsmart_contract/ink-types-node-runtime/src/calls.rsdiffbeforeafterboth
25 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),
2929
30 #[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),
4141
42 #[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),
4444
45 #[allow(non_camel_case_types)]45 #[allow(non_camel_case_types)]
46 burn_item(u64, u64),46 burn_item(u64, u64),
4747
48 #[allow(non_camel_case_types)]48 #[allow(non_camel_case_types)]
49 transfer(u64, u64, T::AccountId),49 transfer(T::AccountId, u64, u64),
5050
51 #[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),
5353
54 #[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),
5656
57 #[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}
9195
92pub 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}
9599
96pub fn burn_item(collection_id: u64, item_id: u64) -> Call {100pub fn burn_item(collection_id: u64, item_id: u64) -> Call {