git.delta.rocks / unique-network / refs/commits / d16b1c1c96a6

difftreelog

Substrate 2

str-mv2020-05-06parent: #6aa91b6.patch.diff
in: master

4 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2859,6 +2859,7 @@
  "sp-core",
  "sp-io",
  "sp-runtime",
+ "sp-std",
 ]
 
 [[package]]
modifiedpallets/template/Cargo.tomldiffbeforeafterboth
--- a/pallets/template/Cargo.toml
+++ b/pallets/template/Cargo.toml
@@ -17,6 +17,14 @@
 package = 'parity-scale-codec'
 version = '1.3.0'
 
+[dependencies.sp-std]
+default-features = false
+version = '2.0.0-alpha.6'
+
+[dependencies.sp-runtime]
+default-features = false
+version = '2.0.0-alpha.6'
+
 [dependencies.frame-support]
 default-features = false
 version = '2.0.0-alpha.6'
@@ -32,14 +40,15 @@
 default-features = false
 version = '2.0.0-alpha.6'
 
-[dev-dependencies.sp-runtime]
-default-features = false
-version = '2.0.0-alpha.6'
 
+
 [features]
 default = ['std']
 std = [
     'codec/std',
     'frame-support/std',
     'frame-system/std',
+    "sp-io/std",
+    "sp-runtime/std",
+    'sp-std/std',
 ]
modifiedpallets/template/src/lib.rsdiffbeforeafterboth
9/// For more guidance on Substrate FRAME, see the example pallet9/// For more guidance on Substrate FRAME, see the example pallet
10/// https://github.com/paritytech/substrate/blob/master/frame/example/src/lib.rs10/// https://github.com/paritytech/substrate/blob/master/frame/example/src/lib.rs
1111
12use frame_support::{decl_module, decl_storage, decl_event, decl_error, dispatch};12use frame_support::{
13 dispatch::DispatchResult, decl_module, decl_storage, decl_event,
14 weights::{DispatchClass, ClassifyDispatch, WeighData, Weight},
15 ensure,
16};
13use frame_system::{self as system, ensure_signed};17use frame_system::{self as system, ensure_signed };
18use codec::{Encode, Decode};
19use sp_runtime::sp_std::prelude::Vec;
1420
15#[cfg(test)]21#[cfg(test)]
16mod mock;22mod mock;
1723
18#[cfg(test)]24#[cfg(test)]
19mod tests;25mod tests;
26
27#[derive(Encode, Decode, Default, Clone, PartialEq)]
28#[cfg_attr(feature = "std", derive(Debug))]
29pub struct CollectionType<AccountId> {
30 pub owner: AccountId,
31 pub next_item_id: u64,
32 pub custom_data_size: u32,
33}
34
35#[derive(Encode, Decode, Default, Clone, PartialEq)]
36#[cfg_attr(feature = "std", derive(Debug))]
37pub struct CollectionAdminsType<AccountId> {
38 pub admin: AccountId,
39 pub collection_id: u64,
40}
41
42#[derive(Encode, Decode, Default, Clone, PartialEq)]
43#[cfg_attr(feature = "std", derive(Debug))]
44pub struct NftItemType<AccountId> {
45 pub collection: u64,
46 pub owner: AccountId,
47 pub data: Vec<u8>,
48}
2049
21/// The pallet's configuration trait.50/// The pallet's configuration trait.
22pub trait Trait: system::Trait {51pub trait Trait: system::Trait {
30decl_storage! {59decl_storage! {
31 // It is important to update your storage name so that your pallet's60 // It is important to update your storage name so that your pallet's
32 // storage items are isolated from other pallets.61 // storage items are isolated from other pallets.
33 // ---------------------------------vvvvvvvvvvvvvv
34 trait Store for Module<T: Trait> as TemplateModule {62 trait Store for Module<T: Trait> as TemplateModule {
35 // Just a dummy storage item.63
36 // Here we are declaring a StorageValue, `Something` as a Option<u32>64 /// Next available collection ID
37 // `get(fn something)` is the default getter which returns either the stored `u32` or `None` if nothing stored65 pub NextCollectionID get(next_collection_id): u64;
66
67 /// Collection map
68 pub Collection get(collection): map hasher(blake2_128_concat) u64 => CollectionType<T::AccountId>;
69
70 /// Admins map (collection)
71 pub AdminList get(admin_list_collection): map hasher(blake2_128_concat) u64 => Vec<T::AccountId>;
72
73 /// Balance owner per collection map
74 pub Balance get(balance_count): map hasher(blake2_128_concat) (u64, T::AccountId) => u64;
75
76 /// Item double map (collection)
38 Something get(fn something): Option<u32>;77 pub ItemList get(item_id): map hasher(blake2_128_concat) (u64, u64) => NftItemType<T::AccountId>;
78 pub ItemListIndex get(item_index): map hasher(blake2_128_concat) u64 => u64;
39 }79 }
40}80}
4181
42// The pallet's events82// The pallet's events
43decl_event!(83decl_event!(
44 pub enum Event<T> where AccountId = <T as system::Trait>::AccountId {84 pub enum Event<T> where AccountId = <T as system::Trait>::AccountId {
45 /// Just a dummy event.
46 /// Event `Something` is declared with a parameter of the type `u32` and `AccountId`
47 /// To emit this event, we call the deposit function, from our runtime functions
48 SomethingStored(u32, AccountId),85 Created(u32, AccountId),
49 }86 }
50);87);
51
52// The pallet's errors
53decl_error! {
54 pub enum Error for Module<T: Trait> {
55 /// Value was None
56 NoneValue,
57 /// Value reached maximum and cannot be incremented further
58 StorageOverflow,
59 }
60}
6188
62// The pallet's dispatchable functions.89// The pallet's dispatchable functions.
63decl_module! {90decl_module! {
64 /// The module declaration.91 /// The module declaration.
65 pub struct Module<T: Trait> for enum Call where origin: T::Origin {92 pub struct Module<T: Trait> for enum Call where origin: T::Origin {
66 // Initializing errors
67 // this includes information about your errors in the node's metadata.
68 // it is needed only if you are using errors in your pallet
69 type Error = Error<T>;
7093
71 // Initializing events94 // Initializing events
72 // this is needed only if you are using events in your pallet95 // this is needed only if you are using events in your pallet
73 fn deposit_event() = default;96 fn deposit_event() = default;
7497
75 /// Just a dummy entry point.98 // Initializing events
76 /// function that can be called by the external world as an extrinsics call99 // this is needed only if you are using events in your module
77 /// takes a parameter of the type `AccountId`, stores it, and emits an event100 // fn deposit_event<T>() = default;
101
102 // Create collection of NFT with given parameters
103 //
104 // @param customDataSz size of custom data in each collection item
105 // returns collection ID
106
107 // Create collection of NFT with given parameters
108 //
109 // @param customDataSz size of custom data in each collection item
110 // returns collection ID
78 #[weight = frame_support::weights::SimpleDispatchInfo::default()]111 #[weight = frame_support::weights::SimpleDispatchInfo::default()]
79 pub fn do_something(origin, something: u32) -> dispatch::DispatchResult {112 pub fn create_collection(origin, custom_data_sz: u32) -> DispatchResult {
80 // Check it was signed and get the signer. See also: ensure_root and ensure_none113 // Anyone can create a collection
81 let who = ensure_signed(origin)?;114 let who = ensure_signed(origin)?;
82115
83 // Code to execute when something calls this.116 // Generate next collection ID
84 // For example: the following line stores the passed in u32 in the storage117 let next_id = Self::next_collection_id();
85 Something::put(something);118 <NextCollectionID>::put(next_id+1);
86119
87 // Here we are raising the Something event120 // Create new collection
121 let new_collection = CollectionType {
122 owner: who,
123 next_item_id: next_id,
124 custom_data_size: custom_data_sz,
125 };
126
127 // Add new collection to map
88 Self::deposit_event(RawEvent::SomethingStored(something, who));128 <Collection<T>>::insert(next_id, new_collection);
129
89 Ok(())130 Ok(())
90 }131 }
91132
92 /// Another dummy entry point.
93 /// takes no parameters, attempts to increment storage value, and possibly throws an error
94 #[weight = frame_support::weights::SimpleDispatchInfo::default()]133 #[weight = frame_support::weights::SimpleDispatchInfo::default()]
95 pub fn cause_error(origin) -> dispatch::DispatchResult {134 pub fn destroy_collection(origin, collection_id: u64) -> DispatchResult {
96 // Check it was signed and get the signer. See also: ensure_root and ensure_none135
136 let sender = ensure_signed(origin)?;
137 ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
138
139 let owner = <Collection<T>>::get(collection_id).owner;
140 ensure!(sender == owner, "You do not own this collection");
141 <Collection<T>>::remove(collection_id);
142
143 Ok(())
144 }
145
146 #[weight = frame_support::weights::SimpleDispatchInfo::default()]
147 pub fn change_collection_owner(origin, collection_id: u64, new_owner: T::AccountId) -> DispatchResult {
148
149 let sender = ensure_signed(origin)?;
150 ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
151
152 let mut target_collection = <Collection<T>>::get(collection_id);
153 ensure!(sender == target_collection.owner, "You do not own this collection");
154
155 target_collection.owner = new_owner;
156 <Collection<T>>::insert(collection_id, target_collection);
157
158 Ok(())
159 }
160
161 #[weight = frame_support::weights::SimpleDispatchInfo::default()]
162 pub fn add_collection_admin(origin, collection_id: u64, new_admin_id: T::AccountId) -> DispatchResult {
163
97 let _who = ensure_signed(origin)?;164 let sender = ensure_signed(origin)?;
165 ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
98166
99 match Something::get() {167 let target_collection = <Collection<T>>::get(collection_id);
168 let is_owner = sender == target_collection.owner;
169
170 let no_perm_mes = "You do not have permissions to modify this collection";
100 None => Err(Error::<T>::NoneValue)?,171 let exists = <AdminList<T>>::contains_key(collection_id);
172
173 if !is_owner
174 {
175 ensure!(exists, no_perm_mes);
101 Some(old) => {176 ensure!(<AdminList<T>>::get(collection_id).contains(&sender), no_perm_mes);
177 }
178
102 let new = old.checked_add(1).ok_or(Error::<T>::StorageOverflow)?;179 let mut admin_arr: Vec<T::AccountId> = Vec::new();
180 if exists
181 {
182 admin_arr = <AdminList<T>>::get(collection_id);
183 ensure!(!admin_arr.contains(&new_admin_id), "Account already has admin role");
184 }
185
186 admin_arr.push(new_admin_id);
187 <AdminList<T>>::insert(collection_id, admin_arr);
188
189 Ok(())
190 }
191
192 #[weight = frame_support::weights::SimpleDispatchInfo::default()]
193 pub fn remove_collection_admin(origin, collection_id: u64, account_id: T::AccountId) -> DispatchResult {
194
195 let sender = ensure_signed(origin)?;
196 ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
197
198 let target_collection = <Collection<T>>::get(collection_id);
199 let is_owner = sender == target_collection.owner;
200
201 let no_perm_mes = "You do not have permissions to modify this collection";
202 let exists = <AdminList<T>>::contains_key(collection_id);
203
204 if !is_owner
205 {
206 ensure!(exists, no_perm_mes);
207 ensure!(<AdminList<T>>::get(collection_id).contains(&sender), no_perm_mes);
208 }
209
210 if exists
211 {
212 let mut admin_arr = <AdminList<T>>::get(collection_id);
213 admin_arr.retain(|i| *i != account_id);
214 <AdminList<T>>::insert(collection_id, admin_arr);
215 }
216
217 Ok(())
218 }
219
220 #[weight = frame_support::weights::SimpleDispatchInfo::default()]
221 pub fn create_item(origin, collection_id: u64, properties: Vec<u8>) -> DispatchResult {
222
223 let sender = ensure_signed(origin)?;
224 ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
225
226 let target_collection = <Collection<T>>::get(collection_id);
227 ensure!(target_collection.custom_data_size >= properties.len() as u32, "Size of item is too large");
228 let is_owner = sender == target_collection.owner;
229
230 let no_perm_mes = "You do not have permissions to modify this collection";
231 let exists = <AdminList<T>>::contains_key(collection_id);
232
233 if !is_owner
234 {
235 ensure!(exists, no_perm_mes);
236 ensure!(<AdminList<T>>::get(collection_id).contains(&sender), no_perm_mes);
237 }
238
239 let new_balance = <Balance<T>>::get((collection_id, sender.clone())) + 1;
240 <Balance<T>>::insert((collection_id, sender.clone()), new_balance);
241
242 // Create new item
243 let new_item = NftItemType {
244 collection: collection_id,
245 owner: sender,
246 data: properties,
247 };
248
249 let current_index = <ItemListIndex>::get(collection_id);
250 <ItemListIndex>::insert(collection_id, current_index+1);
251 <ItemList<T>>::insert((collection_id, current_index), new_item);
252
253 Ok(())
254 }
255
256 #[weight = frame_support::weights::SimpleDispatchInfo::default()]
257 pub fn burn_item(origin, collection_id: u64, item_id: u64) -> DispatchResult {
258
259 let sender = ensure_signed(origin)?;
260 ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
261
262 let target_collection = <Collection<T>>::get(collection_id);
263 let is_owner = sender == target_collection.owner;
264
265 ensure!(<ItemList<T>>::contains_key((collection_id, item_id)), "Item does not exists");
266 let item = <ItemList<T>>::get((collection_id, item_id));
267
268 if !is_owner
269 {
270 // check if item owner
271 if item.owner != sender
272 {
273 let no_perm_mes = "You do not have permissions to modify this collection";
274
103 Something::put(new);275 ensure!(<AdminList<T>>::contains_key(collection_id), no_perm_mes);
276 ensure!(<AdminList<T>>::get(collection_id).contains(&sender), no_perm_mes);
277 }
278 }
279 <ItemList<T>>::remove((collection_id, item_id));
280
104 Ok(())281 Ok(())
282 }
283
284 #[weight = frame_support::weights::SimpleDispatchInfo::default()]
285 pub fn transfer(origin, collection_id: u64, item_id: u64, new_owner: T::AccountId) -> DispatchResult {
286
287 let sender = ensure_signed(origin)?;
105 },288 ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
106 }289
107 }290 let target_collection = <Collection<T>>::get(collection_id);
291 let is_owner = sender == target_collection.owner;
292
293 ensure!(<ItemList<T>>::contains_key((collection_id, item_id)), "Item does not exists");
294 let mut item = <ItemList<T>>::get((collection_id, item_id));
295
296 if !is_owner
297 {
298 // check if item owner
299 if item.owner != sender
300 {
301 let no_perm_mes = "You do not have permissions to modify this collection";
302
303 ensure!(<AdminList<T>>::contains_key(collection_id), no_perm_mes);
304 ensure!(<AdminList<T>>::get(collection_id).contains(&sender), no_perm_mes);
305 }
306 }
307 <ItemList<T>>::remove((collection_id, item_id));
308
309 // change owner
310 item.owner = new_owner;
311 <ItemList<T>>::insert((collection_id, item_id), item);
312
313 Ok(())
314 }
108 }315 }
109}316}
110
modifiedpallets/template/src/tests.rsdiffbeforeafterboth
--- a/pallets/template/src/tests.rs
+++ b/pallets/template/src/tests.rs
@@ -1,26 +1,24 @@
 // Tests to be written here
-
-use crate::{Error, mock::*};
 use frame_support::{assert_ok, assert_noop};
 
-#[test]
-fn it_works_for_default_value() {
-	new_test_ext().execute_with(|| {
-		// Just a dummy test for the dummy function `do_something`
-		// calling the `do_something` function with a value 42
-		assert_ok!(TemplateModule::do_something(Origin::signed(1), 42));
-		// asserting that the stored value is equal to what we stored
-		assert_eq!(TemplateModule::something(), Some(42));
-	});
-}
+// #[test]
+// fn it_works_for_default_value() {
+// 	new_test_ext().execute_with(|| {
+// 		// Just a dummy test for the dummy function `do_something`
+// 		// calling the `do_something` function with a value 42
+// 		assert_ok!(TemplateModule::do_something(Origin::signed(1), 42));
+// 		// asserting that the stored value is equal to what we stored
+// 		assert_eq!(TemplateModule::something(), Some(42));
+// 	});
+// }
 
-#[test]
-fn correct_error_for_none_value() {
-	new_test_ext().execute_with(|| {
-		// Ensure the correct error is thrown on None value
-		assert_noop!(
-			TemplateModule::cause_error(Origin::signed(1)),
-			Error::<Test>::NoneValue
-		);
-	});
-}
+// #[test]
+// fn correct_error_for_none_value() {
+// 	new_test_ext().execute_with(|| {
+// 		// Ensure the correct error is thrown on None value
+// 		assert_noop!(
+// 			TemplateModule::cause_error(Origin::signed(1)),
+// 			Error::<Test>::NoneValue
+// 		);
+// 	});
+// }