git.delta.rocks / unique-network / refs/commits / 7680e6689f4d

difftreelog

refactor Generalization some operations.

Trubnikov Sergey2022-12-08parent: #1f2b5fa.patch.diff
in: master

13 files changed

modifiedpallets/common/src/erc.rsdiffbeforeafterboth
222 fn set_collection_sponsor(&mut self, caller: caller, sponsor: address) -> Result<void> {222 fn set_collection_sponsor(&mut self, caller: caller, sponsor: address) -> Result<void> {
223 self.consume_store_reads_and_writes(1, 1)?;223 self.consume_store_reads_and_writes(1, 1)?;
224224
225 check_is_owner_or_admin(caller, self)?;225 let caller = T::CrossAccountId::from_eth(caller);
226226
227 let sponsor = T::CrossAccountId::from_eth(sponsor);227 let sponsor = T::CrossAccountId::from_eth(sponsor);
228 self.set_sponsor(sponsor.as_sub().clone())228 self.set_sponsor(&caller, sponsor.as_sub().clone())
229 .map_err(dispatch_to_evm::<T>)?;229 .map_err(dispatch_to_evm::<T>)
230 save(self)
231 }230 }
232231
233 /// Set the sponsor of the collection.232 /// Set the sponsor of the collection.
242 ) -> Result<void> {241 ) -> Result<void> {
243 self.consume_store_reads_and_writes(1, 1)?;242 self.consume_store_reads_and_writes(1, 1)?;
244243
245 check_is_owner_or_admin(caller, self)?;244 let caller = T::CrossAccountId::from_eth(caller);
246245
247 let sponsor = sponsor.into_sub_cross_account::<T>()?;246 let sponsor = sponsor.into_sub_cross_account::<T>()?;
248 self.set_sponsor(sponsor.as_sub().clone())247 self.set_sponsor(&caller, sponsor.as_sub().clone())
249 .map_err(dispatch_to_evm::<T>)?;248 .map_err(dispatch_to_evm::<T>)
250 save(self)
251 }249 }
252250
253 /// Whether there is a pending sponsor.251 /// Whether there is a pending sponsor.
265 self.consume_store_writes(1)?;263 self.consume_store_writes(1)?;
266264
267 let caller = T::CrossAccountId::from_eth(caller);265 let caller = T::CrossAccountId::from_eth(caller);
268 if !self266 self.confirm_sponsorship(caller.as_sub())
269 .confirm_sponsorship(caller.as_sub())
270 .map_err(dispatch_to_evm::<T>)?267 .map_err(dispatch_to_evm::<T>)
271 {
272 return Err("caller is not set as sponsor".into());
273 }
274 save(self)
275 }268 }
276269
277 /// Remove collection sponsor.270 /// Remove collection sponsor.
278 fn remove_collection_sponsor(&mut self, caller: caller) -> Result<void> {271 fn remove_collection_sponsor(&mut self, caller: caller) -> Result<void> {
279 self.consume_store_reads_and_writes(1, 1)?;272 self.consume_store_reads_and_writes(1, 1)?;
280 check_is_owner_or_admin(caller, self)?;273 let caller = T::CrossAccountId::from_eth(caller);
281 self.remove_sponsor().map_err(dispatch_to_evm::<T>)?;274 self.remove_sponsor(&caller).map_err(dispatch_to_evm::<T>)
282 save(self)
283 }275 }
284276
285 /// Get current sponsor.277 /// Get current sponsor.
333 }325 }
334 };326 };
335327
336 check_is_owner_or_admin(caller, self)?;
337 let mut limits = self.limits.clone();328 let mut limits = self.limits.clone();
338329
339 match limit.as_str() {330 match limit.as_str() {
367 _ => return Err(Error::Revert(format!("unknown limit \"{}\"", limit))),358 _ => return Err(Error::Revert(format!("unknown limit \"{}\"", limit))),
368 }359 }
360
361 let caller = T::CrossAccountId::from_eth(caller);
369 self.limits = <Pallet<T>>::clamp_limits(self.mode.clone(), &self.limits, limits)362 <Pallet<T>>::update_limits(&caller, self, limits).map_err(dispatch_to_evm::<T>)
370 .map_err(dispatch_to_evm::<T>)?;
371 save(self)
372 }363 }
373364
374 /// Get contract address.365 /// Get contract address.
383 caller: caller,374 caller: caller,
384 new_admin: EthCrossAccount,375 new_admin: EthCrossAccount,
385 ) -> Result<void> {376 ) -> Result<void> {
386 self.consume_store_writes(2)?;377 self.consume_store_reads_and_writes(2, 2)?;
387378
388 let caller = T::CrossAccountId::from_eth(caller);379 let caller = T::CrossAccountId::from_eth(caller);
389 let new_admin = new_admin.into_sub_cross_account::<T>()?;380 let new_admin = new_admin.into_sub_cross_account::<T>()?;
398 caller: caller,389 caller: caller,
399 admin: EthCrossAccount,390 admin: EthCrossAccount,
400 ) -> Result<void> {391 ) -> Result<void> {
401 self.consume_store_writes(2)?;392 self.consume_store_reads_and_writes(2, 2)?;
402393
403 let caller = T::CrossAccountId::from_eth(caller);394 let caller = T::CrossAccountId::from_eth(caller);
404 let admin = admin.into_sub_cross_account::<T>()?;395 let admin = admin.into_sub_cross_account::<T>()?;
410 /// @param newAdmin Address of the added administrator.401 /// @param newAdmin Address of the added administrator.
411 #[solidity(hide)]402 #[solidity(hide)]
412 fn add_collection_admin(&mut self, caller: caller, new_admin: address) -> Result<void> {403 fn add_collection_admin(&mut self, caller: caller, new_admin: address) -> Result<void> {
413 self.consume_store_writes(2)?;404 self.consume_store_reads_and_writes(2, 2)?;
414405
415 let caller = T::CrossAccountId::from_eth(caller);406 let caller = T::CrossAccountId::from_eth(caller);
416 let new_admin = T::CrossAccountId::from_eth(new_admin);407 let new_admin = T::CrossAccountId::from_eth(new_admin);
423 /// @param admin Address of the removed administrator.414 /// @param admin Address of the removed administrator.
424 #[solidity(hide)]415 #[solidity(hide)]
425 fn remove_collection_admin(&mut self, caller: caller, admin: address) -> Result<void> {416 fn remove_collection_admin(&mut self, caller: caller, admin: address) -> Result<void> {
426 self.consume_store_writes(2)?;417 self.consume_store_reads_and_writes(2, 2)?;
427418
428 let caller = T::CrossAccountId::from_eth(caller);419 let caller = T::CrossAccountId::from_eth(caller);
429 let admin = T::CrossAccountId::from_eth(admin);420 let admin = T::CrossAccountId::from_eth(admin);
438 fn set_nesting_bool(&mut self, caller: caller, enable: bool) -> Result<void> {429 fn set_nesting_bool(&mut self, caller: caller, enable: bool) -> Result<void> {
439 self.consume_store_reads_and_writes(1, 1)?;430 self.consume_store_reads_and_writes(1, 1)?;
440431
441 check_is_owner_or_admin(caller, self)?;432 let caller = T::CrossAccountId::from_eth(caller);
442433
443 let mut permissions = self.collection.permissions.clone();434 let mut permissions = self.collection.permissions.clone();
444 let mut nesting = permissions.nesting().clone();435 let mut nesting = permissions.nesting().clone();
445 nesting.token_owner = enable;436 nesting.token_owner = enable;
446 nesting.restricted = None;437 nesting.restricted = None;
447 permissions.nesting = Some(nesting);438 permissions.nesting = Some(nesting);
448439
449 self.collection.permissions = <Pallet<T>>::clamp_permissions(440 <Pallet<T>>::update_permissions(&caller, self, permissions).map_err(dispatch_to_evm::<T>)
450 self.collection.mode.clone(),
451 &self.collection.permissions,
452 permissions,
453 )
454 .map_err(dispatch_to_evm::<T>)?;
455
456 save(self)
457 }441 }
458442
459 /// Toggle accessibility of collection nesting.443 /// Toggle accessibility of collection nesting.
472 if collections.is_empty() {456 if collections.is_empty() {
473 return Err("no addresses provided".into());457 return Err("no addresses provided".into());
474 }458 }
475 check_is_owner_or_admin(caller, self)?;459 let caller = T::CrossAccountId::from_eth(caller);
476460
477 let mut permissions = self.collection.permissions.clone();461 let mut permissions = self.collection.permissions.clone();
478 match enable {462 match enable {
497 }481 }
498 };482 };
499483
500 self.collection.permissions = <Pallet<T>>::clamp_permissions(484 <Pallet<T>>::update_permissions(&caller, self, permissions).map_err(dispatch_to_evm::<T>)
501 self.collection.mode.clone(),
502 &self.collection.permissions,
503 permissions,
504 )
505 .map_err(dispatch_to_evm::<T>)?;
506
507 save(self)
508 }485 }
509486
510 /// Set the collection access method.487 /// Set the collection access method.
514 fn set_collection_access(&mut self, caller: caller, mode: uint8) -> Result<void> {491 fn set_collection_access(&mut self, caller: caller, mode: uint8) -> Result<void> {
515 self.consume_store_reads_and_writes(1, 1)?;492 self.consume_store_reads_and_writes(1, 1)?;
516493
517 check_is_owner_or_admin(caller, self)?;494 let caller = T::CrossAccountId::from_eth(caller);
518 let permissions = CollectionPermissions {495 let permissions = CollectionPermissions {
519 access: Some(match mode {496 access: Some(match mode {
520 0 => AccessMode::Normal,497 0 => AccessMode::Normal,
523 }),500 }),
524 ..Default::default()501 ..Default::default()
525 };502 };
526 self.collection.permissions = <Pallet<T>>::clamp_permissions(503 <Pallet<T>>::update_permissions(&caller, self, permissions).map_err(dispatch_to_evm::<T>)
527 self.collection.mode.clone(),
528 &self.collection.permissions,
529 permissions,
530 )
531 .map_err(dispatch_to_evm::<T>)?;
532
533 save(self)
534 }504 }
535505
536 /// Checks that user allowed to operate with collection.506 /// Checks that user allowed to operate with collection.
605 fn set_collection_mint_mode(&mut self, caller: caller, mode: bool) -> Result<void> {575 fn set_collection_mint_mode(&mut self, caller: caller, mode: bool) -> Result<void> {
606 self.consume_store_reads_and_writes(1, 1)?;576 self.consume_store_reads_and_writes(1, 1)?;
607577
608 check_is_owner_or_admin(caller, self)?;578 let caller = T::CrossAccountId::from_eth(caller);
609 let permissions = CollectionPermissions {579 let permissions = CollectionPermissions {
610 mint_mode: Some(mode),580 mint_mode: Some(mode),
611 ..Default::default()581 ..Default::default()
612 };582 };
613 self.collection.permissions = <Pallet<T>>::clamp_permissions(583 <Pallet<T>>::update_permissions(&caller, self, permissions).map_err(dispatch_to_evm::<T>)
614 self.collection.mode.clone(),
615 &self.collection.permissions,
616 permissions,
617 )
618 .map_err(dispatch_to_evm::<T>)?;
619
620 save(self)
621 }584 }
622585
623 /// Check that account is the owner or admin of the collection586 /// Check that account is the owner or admin of the collection
671634
672 let caller = T::CrossAccountId::from_eth(caller);635 let caller = T::CrossAccountId::from_eth(caller);
673 let new_owner = T::CrossAccountId::from_eth(new_owner);636 let new_owner = T::CrossAccountId::from_eth(new_owner);
674 self.set_owner_internal(caller, new_owner)637 self.change_owner(caller, new_owner)
675 .map_err(dispatch_to_evm::<T>)638 .map_err(dispatch_to_evm::<T>)
676 }639 }
677640
699662
700 let caller = T::CrossAccountId::from_eth(caller);663 let caller = T::CrossAccountId::from_eth(caller);
701 let new_owner = new_owner.into_sub_cross_account::<T>()?;664 let new_owner = new_owner.into_sub_cross_account::<T>()?;
702 self.set_owner_internal(caller, new_owner)665 self.change_owner(caller, new_owner)
703 .map_err(dispatch_to_evm::<T>)666 .map_err(dispatch_to_evm::<T>)
704 }667 }
705}668}
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
231 /// In order for sponsorship to become active, it must be confirmed through [`Self::confirm_sponsorship`].231 /// In order for sponsorship to become active, it must be confirmed through [`Self::confirm_sponsorship`].
232 pub fn set_sponsor(&mut self, sponsor: T::AccountId) -> DispatchResult {232 pub fn set_sponsor(
233 &mut self,
234 sender: &T::CrossAccountId,
235 sponsor: T::AccountId,
236 ) -> DispatchResult {
237 self.check_is_internal()?;
238 self.check_is_owner_or_admin(sender)?;
239
233 self.collection.sponsorship = SponsorshipState::Unconfirmed(sponsor);240 self.collection.sponsorship = SponsorshipState::Unconfirmed(sponsor.clone());
241
242 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(self.id, sponsor));
234 Ok(())243 <PalletEvm<T>>::deposit_log(
244 erc::CollectionHelpersEvents::CollectionChanged {
245 collection_id: eth::collection_id_to_address(self.id),
246 }
247 .to_log(T::ContractAddress::get()),
248 );
249
250 self.save()
235 }251 }
252
253 /// Force set `sponsor`.
254 ///
255 /// Differs from [`set_sponsor`][`Self::set_sponsor`] in that confirmation
256 /// from the `sponsor` is not required.
257 ///
258 /// # Arguments
259 ///
260 /// * `sender`: Caller's account.
261 /// * `sponsor`: ID of the account of the sponsor-to-be.
262 pub fn force_set_sponsor(&mut self, sponsor: T::AccountId) -> DispatchResult {
263 self.check_is_internal()?;
264
265 self.collection.sponsorship = SponsorshipState::Confirmed(sponsor.clone());
266
267 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(self.id, sponsor.clone()));
268 <Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(self.id, sponsor));
269 <PalletEvm<T>>::deposit_log(
270 erc::CollectionHelpersEvents::CollectionChanged {
271 collection_id: eth::collection_id_to_address(self.id),
272 }
273 .to_log(T::ContractAddress::get()),
274 );
275
276 self.save()
277 }
236278
237 /// Confirm sponsorship279 /// Confirm sponsorship
238 ///280 ///
239 /// In order for the sponsorship to become active, the user set as the sponsor must confirm their participation.281 /// In order for the sponsorship to become active, the user set as the sponsor must confirm their participation.
240 /// Before confirming sponsorship, the user must be specified as the sponsor of the collection via [`Self::set_sponsor`].282 /// Before confirming sponsorship, the user must be specified as the sponsor of the collection via [`Self::set_sponsor`].
241 pub fn confirm_sponsorship(&mut self, sender: &T::AccountId) -> Result<bool, DispatchError> {283 pub fn confirm_sponsorship(&mut self, sender: &T::AccountId) -> DispatchResult {
284 self.check_is_internal()?;
285 ensure!(
242 if self.collection.sponsorship.pending_sponsor() != Some(sender) {286 self.collection.sponsorship.pending_sponsor() == Some(sender),
287 Error::<T>::ConfirmUnsetSponsorFail
243 return Ok(false);288 );
244 }
245289
246 self.collection.sponsorship = SponsorshipState::Confirmed(sender.clone());290 self.collection.sponsorship = SponsorshipState::Confirmed(sender.clone());
291
292 <Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(self.id, sender.clone()));
293 <PalletEvm<T>>::deposit_log(
294 erc::CollectionHelpersEvents::CollectionChanged {
295 collection_id: eth::collection_id_to_address(self.id),
296 }
297 .to_log(T::ContractAddress::get()),
298 );
299
247 Ok(true)300 self.save()
248 }301 }
249302
250 /// Remove collection sponsor.303 /// Remove collection sponsor.
251 pub fn remove_sponsor(&mut self) -> DispatchResult {304 pub fn remove_sponsor(&mut self, sender: &T::CrossAccountId) -> DispatchResult {
305 self.check_is_internal()?;
306 self.check_is_owner(sender)?;
307
252 self.collection.sponsorship = SponsorshipState::Disabled;308 self.collection.sponsorship = SponsorshipState::Disabled;
309
310 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(self.id));
253 Ok(())311 <PalletEvm<T>>::deposit_log(
312 erc::CollectionHelpersEvents::CollectionChanged {
313 collection_id: eth::collection_id_to_address(self.id),
314 }
315 .to_log(T::ContractAddress::get()),
316 );
317 self.save()
254 }318 }
319
320 /// Force remove `sponsor`.
321 ///
322 /// Differs from `remove_sponsor` in that
323 /// it doesn't require consent from the `owner` of the collection.
324 pub fn force_remove_sponsor(&mut self) -> DispatchResult {
325 self.check_is_internal()?;
326
327 self.collection.sponsorship = SponsorshipState::Disabled;
328
329 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(self.id));
330 <PalletEvm<T>>::deposit_log(
331 erc::CollectionHelpersEvents::CollectionChanged {
332 collection_id: eth::collection_id_to_address(self.id),
333 }
334 .to_log(T::ContractAddress::get()),
335 );
336 self.save()
337 }
255338
256 /// Checks that the collection was created with, and must be operated upon through **Unique API**.339 /// Checks that the collection was created with, and must be operated upon through **Unique API**.
257 /// Now check only the `external` flag and if it's **true**, then return [`Error::CollectionIsExternal`] error.340 /// Now check only the `external` flag and if it's **true**, then return [`Error::CollectionIsExternal`] error.
328 /// Changes collection owner to another account411 /// Changes collection owner to another account
329 /// #### Store read/writes412 /// #### Store read/writes
330 /// 1 writes413 /// 1 writes
331 fn set_owner_internal(414 pub fn change_owner(
332 &mut self,415 &mut self,
333 caller: T::CrossAccountId,416 caller: T::CrossAccountId,
334 new_owner: T::CrossAccountId,417 new_owner: T::CrossAccountId,
335 ) -> DispatchResult {418 ) -> DispatchResult {
419 self.check_is_internal()?;
336 self.check_is_owner(&caller)?;420 self.check_is_owner(&caller)?;
337 self.collection.owner = new_owner.as_sub().clone();421 self.collection.owner = new_owner.as_sub().clone();
422
423 <Pallet<T>>::deposit_event(Event::<T>::CollectionOwnedChanged(
424 self.id,
425 new_owner.as_sub().clone(),
426 ));
427 <PalletEvm<T>>::deposit_log(
428 erc::CollectionHelpersEvents::CollectionChanged {
429 collection_id: eth::collection_id_to_address(self.id),
430 }
431 .to_log(T::ContractAddress::get()),
432 );
433
338 self.save()434 self.save()
339 }435 }
528 PropertyKey,624 PropertyKey,
529 ),625 ),
626
627 /// Address was added to the allow list.
628 AllowListAddressAdded(
629 /// ID of the affected collection.
630 CollectionId,
631 /// Address of the added account.
632 T::CrossAccountId,
633 ),
634
635 /// Address was removed from the allow list.
636 AllowListAddressRemoved(
637 /// ID of the affected collection.
638 CollectionId,
639 /// Address of the removed account.
640 T::CrossAccountId,
641 ),
642
643 /// Collection admin was added.
644 CollectionAdminAdded(
645 /// ID of the affected collection.
646 CollectionId,
647 /// Admin address.
648 T::CrossAccountId,
649 ),
650
651 /// Collection admin was removed.
652 CollectionAdminRemoved(
653 /// ID of the affected collection.
654 CollectionId,
655 /// Removed admin address.
656 T::CrossAccountId,
657 ),
658
659 /// Collection limits were set.
660 CollectionLimitSet(
661 /// ID of the affected collection.
662 CollectionId,
663 ),
664
665 /// Collection owned was changed.
666 CollectionOwnedChanged(
667 /// ID of the affected collection.
668 CollectionId,
669 /// New owner address.
670 T::AccountId,
671 ),
672
673 /// Collection permissions were set.
674 CollectionPermissionSet(
675 /// ID of the affected collection.
676 CollectionId,
677 ),
678
679 /// Collection sponsor was set.
680 CollectionSponsorSet(
681 /// ID of the affected collection.
682 CollectionId,
683 /// New sponsor address.
684 T::AccountId,
685 ),
686
687 /// New sponsor was confirm.
688 SponsorshipConfirmed(
689 /// ID of the affected collection.
690 CollectionId,
691 /// New sponsor address.
692 T::AccountId,
693 ),
694
695 /// Collection sponsor was removed.
696 CollectionSponsorRemoved(
697 /// ID of the affected collection.
698 CollectionId,
699 ),
530 }700 }
531701
532 #[pallet::error]702 #[pallet::error]
614 /// Tried to access an internal collection with an external API784 /// Tried to access an internal collection with an external API
615 CollectionIsInternal,785 CollectionIsInternal,
786
787 /// This address is not set as sponsor, use setCollectionSponsor first.
788 ConfirmUnsetSponsorFail,
789
790 /// The user is not an administrator.
791 UserIsNotAdmin,
616 }792 }
617793
618 /// Storage of the count of created collections. Essentially contains the last collection ID.794 /// Storage of the count of created collections. Essentially contains the last collection ID.
13631539
1364 if allowed {1540 if allowed {
1365 <Allowlist<T>>::insert((collection.id, user), true);1541 <Allowlist<T>>::insert((collection.id, user), true);
1542 Self::deposit_event(Event::<T>::AllowListAddressAdded(
1543 collection.id,
1544 user.clone(),
1545 ));
1366 } else {1546 } else {
1367 <Allowlist<T>>::remove((collection.id, user));1547 <Allowlist<T>>::remove((collection.id, user));
1548 Self::deposit_event(Event::<T>::AllowListAddressRemoved(
1549 collection.id,
1550 user.clone(),
1551 ));
1368 }1552 }
1553
1554 <PalletEvm<T>>::deposit_log(
1555 erc::CollectionHelpersEvents::CollectionChanged {
1556 collection_id: eth::collection_id_to_address(collection.id),
1557 }
1558 .to_log(T::ContractAddress::get()),
1559 );
13691560
1370 Ok(())1561 Ok(())
1371 }1562 }
13721563
1373 /// Toggle `user` participation in the `collection`'s admin list.1564 /// Toggle `user` participation in the `collection`'s admin list.
1374 /// #### Store read/writes1565 /// #### Store read/writes
1375 /// 2 writes1566 /// 2 reads, 2 writes
1376 pub fn toggle_admin(1567 pub fn toggle_admin(
1377 collection: &CollectionHandle<T>,1568 collection: &CollectionHandle<T>,
1378 sender: &T::CrossAccountId,1569 sender: &T::CrossAccountId,
1379 user: &T::CrossAccountId,1570 user: &T::CrossAccountId,
1380 admin: bool,1571 admin: bool,
1381 ) -> DispatchResult {1572 ) -> DispatchResult {
1573 collection.check_is_internal()?;
1382 collection.check_is_owner(sender)?;1574 collection.check_is_owner(sender)?;
13831575
1384 let was_admin = <IsAdmin<T>>::get((collection.id, user));1576 let is_admin = <IsAdmin<T>>::get((collection.id, user));
1385 if was_admin == admin {1577 if is_admin == admin {
1578 if admin {
1386 return Ok(());1579 return Ok(());
1387 }1580 } else {
1581 ensure!(false, Error::<T>::UserIsNotAdmin);
1582 }
1583 }
1388 let amount = <AdminAmount<T>>::get(collection.id);1584 let amount = <AdminAmount<T>>::get(collection.id);
13891585
1401 <AdminAmount<T>>::insert(collection.id, amount);1597 <AdminAmount<T>>::insert(collection.id, amount);
1402 <IsAdmin<T>>::insert((collection.id, user), true);1598 <IsAdmin<T>>::insert((collection.id, user), true);
1599
1600 Self::deposit_event(Event::<T>::CollectionAdminAdded(
1601 collection.id,
1602 user.clone(),
1603 ));
1403 } else {1604 } else {
1404 <AdminAmount<T>>::insert(collection.id, amount.saturating_sub(1));1605 <AdminAmount<T>>::insert(collection.id, amount.saturating_sub(1));
1405 <IsAdmin<T>>::remove((collection.id, user));1606 <IsAdmin<T>>::remove((collection.id, user));
1607
1608 Self::deposit_event(Event::<T>::CollectionAdminRemoved(
1609 collection.id,
1610 user.clone(),
1611 ));
1406 }1612 }
1613
1614 <PalletEvm<T>>::deposit_log(
1615 erc::CollectionHelpersEvents::CollectionChanged {
1616 collection_id: eth::collection_id_to_address(collection.id),
1617 }
1618 .to_log(T::ContractAddress::get()),
1619 );
14071620
1408 Ok(())1621 Ok(())
1409 }1622 }
1623
1624 /// Update collection limits.
1625 pub fn update_limits(
1626 user: &T::CrossAccountId,
1627 collection: &mut CollectionHandle<T>,
1628 new_limit: CollectionLimits,
1629 ) -> DispatchResult {
1630 collection.check_is_internal()?;
1631 collection.check_is_owner_or_admin(user)?;
1632
1633 collection.limits =
1634 Self::clamp_limits(collection.mode.clone(), &collection.limits, new_limit)?;
1635
1636 Self::deposit_event(Event::<T>::CollectionLimitSet(collection.id));
1637 <PalletEvm<T>>::deposit_log(
1638 erc::CollectionHelpersEvents::CollectionChanged {
1639 collection_id: eth::collection_id_to_address(collection.id),
1640 }
1641 .to_log(T::ContractAddress::get()),
1642 );
1643
1644 collection.save()
1645 }
14101646
1411 /// Merge set fields from `new_limit` to `old_limit`.1647 /// Merge set fields from `new_limit` to `old_limit`.
1412 pub fn clamp_limits(1648 fn clamp_limits(
1413 mode: CollectionMode,1649 mode: CollectionMode,
1414 old_limit: &CollectionLimits,1650 old_limit: &CollectionLimits,
1415 mut new_limit: CollectionLimits,1651 mut new_limit: CollectionLimits,
1454 Ok(new_limit)1690 Ok(new_limit)
1455 }1691 }
1692
1693 /// Update collection permissions.
1694 pub fn update_permissions(
1695 user: &T::CrossAccountId,
1696 collection: &mut CollectionHandle<T>,
1697 new_permission: CollectionPermissions,
1698 ) -> DispatchResult {
1699 collection.check_is_internal()?;
1700 collection.check_is_owner_or_admin(user)?;
1701 collection.permissions = Self::clamp_permissions(
1702 collection.mode.clone(),
1703 &collection.permissions,
1704 new_permission,
1705 )?;
1706
1707 Self::deposit_event(Event::<T>::CollectionPermissionSet(collection.id));
1708 <PalletEvm<T>>::deposit_log(
1709 erc::CollectionHelpersEvents::CollectionChanged {
1710 collection_id: eth::collection_id_to_address(collection.id),
1711 }
1712 .to_log(T::ContractAddress::get()),
1713 );
1714
1715 collection.save()
1716 }
14561717
1457 /// Merge set fields from `new_permission` to `old_permission`.1718 /// Merge set fields from `new_permission` to `old_permission`.
1458 pub fn clamp_permissions(1719 fn clamp_permissions(
1459 _mode: CollectionMode,1720 _mode: CollectionMode,
1460 old_permission: &CollectionPermissions,1721 old_permission: &CollectionPermissions,
1461 mut new_permission: CollectionPermissions,1722 mut new_permission: CollectionPermissions,
modifiedpallets/unique/src/lib.rsdiffbeforeafterboth
89 MAX_PROPERTIES_PER_ITEM, MAX_PROPERTY_KEY_LENGTH, MAX_PROPERTY_VALUE_LENGTH,89 MAX_PROPERTIES_PER_ITEM, MAX_PROPERTY_KEY_LENGTH, MAX_PROPERTY_VALUE_LENGTH,
90 MAX_COLLECTION_PROPERTIES_SIZE, COLLECTION_ADMINS_LIMIT, MAX_TOKEN_PROPERTIES_SIZE,90 MAX_COLLECTION_PROPERTIES_SIZE, COLLECTION_ADMINS_LIMIT, MAX_TOKEN_PROPERTIES_SIZE,
91 CreateItemData, CollectionLimits, CollectionPermissions, CollectionId, CollectionMode, TokenId,91 CreateItemData, CollectionLimits, CollectionPermissions, CollectionId, CollectionMode, TokenId,
92 SponsorshipState, CreateCollectionData, CreateItemExData, budget, Property, PropertyKey,92 CreateCollectionData, CreateItemExData, budget, Property, PropertyKey, PropertyKeyPermission,
93 PropertyKeyPermission,
94};93};
95use pallet_evm::account::CrossAccountId;94use pallet_evm::{account::CrossAccountId};
96use pallet_common::{95use pallet_common::{
97 CollectionHandle, Pallet as PalletCommon, CommonWeightInfo, dispatch::dispatch_tx,96 CollectionHandle, Pallet as PalletCommon, CommonWeightInfo, dispatch::dispatch_tx,
98 dispatch::CollectionDispatch, RefungibleExtensionsWeightInfo,97 dispatch::CollectionDispatch, RefungibleExtensionsWeightInfo,
112 pub enum Error for Module<T: Config> {111 pub enum Error for Module<T: Config> {
113 /// Decimal_points parameter must be lower than [`up_data_structs::MAX_DECIMAL_POINTS`].112 /// Decimal_points parameter must be lower than [`up_data_structs::MAX_DECIMAL_POINTS`].
114 CollectionDecimalPointLimitExceeded,113 CollectionDecimalPointLimitExceeded,
115 /// This address is not set as sponsor, use setCollectionSponsor first.
116 ConfirmUnsetSponsorFail,
117 /// Length of items properties must be greater than 0.114 /// Length of items properties must be greater than 0.
118 EmptyArgument,115 EmptyArgument,
119 /// Repertition is only supported by refungible collection.116 /// Repertition is only supported by refungible collection.
140 pub enum Event<T>137 pub enum Event<T>
141 where138 where
142 <T as frame_system::Config>::AccountId,139 <T as frame_system::Config>::AccountId,
143 <T as pallet_evm::Config>::CrossAccountId,
144 {140 {
145 /// Collection sponsor was removed141 /// Collection sponsor was removed
146 ///142 ///
147 /// # Arguments143 /// # Arguments
148 /// * collection_id: ID of the affected collection.144 /// * collection_id: ID of the affected collection.
149 CollectionSponsorRemoved(CollectionId),145 CollectionSponsorRemoved(CollectionId),
150
151 /// Collection admin was added
152 ///
153 /// # Arguments
154 /// * collection_id: ID of the affected collection.
155 /// * admin: Admin address.
156 CollectionAdminAdded(CollectionId, CrossAccountId),
157
158 /// Collection owned was changed
159 ///
160 /// # Arguments
161 /// * collection_id: ID of the affected collection.
162 /// * owner: New owner address.
163 CollectionOwnedChanged(CollectionId, AccountId),
164146
165 /// Collection sponsor was set147 /// Collection sponsor was set
166 ///148 ///
169 /// * owner: New sponsor address.151 /// * owner: New sponsor address.
170 CollectionSponsorSet(CollectionId, AccountId),152 CollectionSponsorSet(CollectionId, AccountId),
171153
172 /// New sponsor was confirm
173 ///
174 /// # Arguments
175 /// * collection_id: ID of the affected collection.
176 /// * sponsor: New sponsor address.
177 SponsorshipConfirmed(CollectionId, AccountId),
178
179 /// Collection admin was removed
180 ///
181 /// # Arguments
182 /// * collection_id: ID of the affected collection.
183 /// * admin: Removed admin address.
184 CollectionAdminRemoved(CollectionId, CrossAccountId),
185
186 /// Address was removed from the allow list
187 ///
188 /// # Arguments
189 /// * collection_id: ID of the affected collection.
190 /// * user: Address of the removed account.
191 AllowListAddressRemoved(CollectionId, CrossAccountId),
192
193 /// Address was added to the allow list
194 ///
195 /// # Arguments
196 /// * collection_id: ID of the affected collection.
197 /// * user: Address of the added account.
198 AllowListAddressAdded(CollectionId, CrossAccountId),
199
200 /// Collection limits were set
201 ///
202 /// # Arguments
203 /// * collection_id: ID of the affected collection.
204 CollectionLimitSet(CollectionId),
205
206 /// Collection permissions were set
207 ///
208 /// # Arguments
209 /// * collection_id: ID of the affected collection.
210 CollectionPermissionSet(CollectionId),
211 }154 }
212}155}
213156
433 true,376 true,
434 )?;377 )?;
435
436 Self::deposit_event(Event::<T>::AllowListAddressAdded(
437 collection_id,
438 address
439 ));
440378
441 Ok(())379 Ok(())
442 }380 }
466 false,404 false,
467 )?;405 )?;
468
469 <Pallet<T>>::deposit_event(Event::<T>::AllowListAddressRemoved(
470 collection_id,
471 address
472 ));
473406
474 Ok(())407 Ok(())
475 }408 }
488 pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {421 pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {
489
490 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);422 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
491423 let new_owner = T::CrossAccountId::from_sub(new_owner);
492 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;424 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
493 target_collection.check_is_internal()?;425 target_collection.change_owner(sender, new_owner.clone())
494 target_collection.check_is_owner(&sender)?;
495
496 target_collection.owner = new_owner.clone();
497 <Pallet<T>>::deposit_event(Event::<T>::CollectionOwnedChanged(
498 collection_id,
499 new_owner
500 ));
501
502 target_collection.save()
503 }426 }
504427
505 /// Add an admin to a collection.428 /// Add an admin to a collection.
522 pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::CrossAccountId) -> DispatchResult {445 pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::CrossAccountId) -> DispatchResult {
523 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);446 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
524 let collection = <CollectionHandle<T>>::try_get(collection_id)?;447 let collection = <CollectionHandle<T>>::try_get(collection_id)?;
525 collection.check_is_internal()?;
526
527 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminAdded(
528 collection_id,
529 new_admin_id.clone()
530 ));
531
532 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)448 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)
533 }449 }
550 pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {466 pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {
551 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);467 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
552 let collection = <CollectionHandle<T>>::try_get(collection_id)?;468 let collection = <CollectionHandle<T>>::try_get(collection_id)?;
553 collection.check_is_internal()?;
554
555 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminRemoved(
556 collection_id,
557 account_id.clone()
558 ));
559
560 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)469 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)
561 }470 }
578 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);487 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
579
580 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;488 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
581 target_collection.check_is_owner_or_admin(&sender)?;489 target_collection.set_sponsor(&sender, new_sponsor.clone())
582 target_collection.check_is_internal()?;
583
584 target_collection.set_sponsor(new_sponsor.clone())?;
585
586 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(
587 collection_id,
588 new_sponsor
589 ));
590
591 target_collection.save()
592 }490 }
593491
594 /// Confirm own sponsorship of a collection, becoming the sponsor.492 /// Confirm own sponsorship of a collection, becoming the sponsor.
609 let sender = ensure_signed(origin)?;507 let sender = ensure_signed(origin)?;
610
611 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;508 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
612 target_collection.check_is_internal()?;509 target_collection.confirm_sponsorship(&sender)
613 ensure!(
614 target_collection.confirm_sponsorship(&sender)?,
615 Error::<T>::ConfirmUnsetSponsorFail
616 );
617
618 <Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(
619 collection_id,
620 sender
621 ));
622
623 target_collection.save()
624 }510 }
625511
626 /// Remove a collection's a sponsor, making everyone pay for their own transactions.512 /// Remove a collection's a sponsor, making everyone pay for their own transactions.
637 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);523 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
638
639 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;524 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
640 target_collection.check_is_internal()?;525 target_collection.remove_sponsor(&sender)
641 target_collection.check_is_owner(&sender)?;
642
643 target_collection.sponsorship = SponsorshipState::Disabled;
644
645 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(
646 collection_id
647 ));
648 target_collection.save()
649 }526 }
650527
651 /// Mint an item within a collection.528 /// Mint an item within a collection.
1053 ) -> DispatchResult {930 ) -> DispatchResult {
1054 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);931 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
1055 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;932 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
1056 target_collection.check_is_internal()?;
1057 target_collection.check_is_owner_or_admin(&sender)?;
1058 let old_limit = &target_collection.limits;
1059
1060 target_collection.limits = <PalletCommon<T>>::clamp_limits(target_collection.mode.clone(), &old_limit, new_limit)?;933 <PalletCommon<T>>::update_limits(&sender, &mut target_collection, new_limit)
1061
1062 <Pallet<T>>::deposit_event(Event::<T>::CollectionLimitSet(
1063 collection_id
1064 ));
1065
1066 target_collection.save()
1067 }934 }
1068935
1069 /// Set specific permissions of a collection. Empty, or None fields mean chain default.936 /// Set specific permissions of a collection. Empty, or None fields mean chain default.
1086 ) -> DispatchResult {953 ) -> DispatchResult {
1087 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);954 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
1088 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;955 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
1089 target_collection.check_is_internal()?;
1090 target_collection.check_is_owner_or_admin(&sender)?;
1091 let old_limit = &target_collection.permissions;
1092
1093 target_collection.permissions = <PalletCommon<T>>::clamp_permissions(target_collection.mode.clone(), &old_limit, new_permission)?;956 <PalletCommon<T>>::update_permissions(
1094957 &sender,
1095 <Pallet<T>>::deposit_event(Event::<T>::CollectionPermissionSet(958 &mut target_collection,
1096 collection_id959 new_permission
1097 ));960 )
1098
1099 target_collection.save()
1100 }961 }
1101962
1102 /// Re-partition a refungible token, while owning all of its parts/pieces.963 /// Re-partition a refungible token, while owning all of its parts/pieces.
1163 /// * `collection_id`: ID of the modified collection.1024 /// * `collection_id`: ID of the modified collection.
1164 pub fn force_set_sponsor(sponsor: T::AccountId, collection_id: CollectionId) -> DispatchResult {1025 pub fn force_set_sponsor(sponsor: T::AccountId, collection_id: CollectionId) -> DispatchResult {
1165 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1026 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
1166 target_collection.check_is_internal()?;
1167 target_collection.set_sponsor(sponsor.clone())?;1027 target_collection.force_set_sponsor(sponsor.clone())
1168
1169 Self::deposit_event(Event::<T>::CollectionSponsorSet(
1170 collection_id,
1171 sponsor.clone(),
1172 ));
1173
1174 ensure!(
1175 target_collection.confirm_sponsorship(&sponsor)?,
1176 Error::<T>::ConfirmUnsetSponsorFail
1177 );
1178
1179 Self::deposit_event(Event::<T>::SponsorshipConfirmed(collection_id, sponsor));
1180
1181 target_collection.save()
1182 }1028 }
11831029
1184 /// Force remove `sponsor` for `collection`.1030 /// Force remove `sponsor` for `collection`.
1191 /// * `collection_id`: ID of the modified collection.1037 /// * `collection_id`: ID of the modified collection.
1192 pub fn force_remove_collection_sponsor(collection_id: CollectionId) -> DispatchResult {1038 pub fn force_remove_collection_sponsor(collection_id: CollectionId) -> DispatchResult {
1193 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1039 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
1194 target_collection.check_is_internal()?;
1195 target_collection.sponsorship = SponsorshipState::Disabled;
1196
1197 Self::deposit_event(Event::<T>::CollectionSponsorRemoved(collection_id));
1198
1199 target_collection.save()1040 target_collection.force_remove_sponsor()
1200 }1041 }
12011042
1202 #[inline(always)]1043 #[inline(always)]
modifiedtests/src/change-collection-owner.test.tsdiffbeforeafterboth
146 const confirmSponsorshipTx = () => collection.confirmSponsorship(alice);146 const confirmSponsorshipTx = () => collection.confirmSponsorship(alice);
147 const removeSponsorTx = () => collection.removeSponsor(alice);147 const removeSponsorTx = () => collection.removeSponsor(alice);
148 await expect(setSponsorTx()).to.be.rejectedWith(/common\.NoPermission/);148 await expect(setSponsorTx()).to.be.rejectedWith(/common\.NoPermission/);
149 await expect(confirmSponsorshipTx()).to.be.rejectedWith(/unique\.ConfirmUnsetSponsorFail/);149 await expect(confirmSponsorshipTx()).to.be.rejectedWith(/common\.ConfirmUnsetSponsorFail/);
150 await expect(removeSponsorTx()).to.be.rejectedWith(/common\.NoPermission/);150 await expect(removeSponsorTx()).to.be.rejectedWith(/common\.NoPermission/);
151151
152 const limits = {152 const limits = {
modifiedtests/src/confirmSponsorship.test.tsdiffbeforeafterboth
207 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});207 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
208 await collection.setSponsor(alice, bob.address);208 await collection.setSponsor(alice, bob.address);
209 const confirmSponsorshipTx = () => collection.confirmSponsorship(charlie);209 const confirmSponsorshipTx = () => collection.confirmSponsorship(charlie);
210 await expect(confirmSponsorshipTx()).to.be.rejectedWith(/unique\.ConfirmUnsetSponsorFail/);210 await expect(confirmSponsorshipTx()).to.be.rejectedWith(/common\.ConfirmUnsetSponsorFail/);
211 });211 });
212212
213 itSub('(!negative test!) Confirm sponsorship using owner address', async ({helper}) => {213 itSub('(!negative test!) Confirm sponsorship using owner address', async ({helper}) => {
214 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});214 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
215 await collection.setSponsor(alice, bob.address);215 await collection.setSponsor(alice, bob.address);
216 const confirmSponsorshipTx = () => collection.confirmSponsorship(alice);216 const confirmSponsorshipTx = () => collection.confirmSponsorship(alice);
217 await expect(confirmSponsorshipTx()).to.be.rejectedWith(/unique\.ConfirmUnsetSponsorFail/);217 await expect(confirmSponsorshipTx()).to.be.rejectedWith(/common\.ConfirmUnsetSponsorFail/);
218 });218 });
219219
220 itSub('(!negative test!) Confirm sponsorship by collection admin', async ({helper}) => {220 itSub('(!negative test!) Confirm sponsorship by collection admin', async ({helper}) => {
221 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});221 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
222 await collection.setSponsor(alice, bob.address);222 await collection.setSponsor(alice, bob.address);
223 await collection.addAdmin(alice, {Substrate: charlie.address});223 await collection.addAdmin(alice, {Substrate: charlie.address});
224 const confirmSponsorshipTx = () => collection.confirmSponsorship(charlie);224 const confirmSponsorshipTx = () => collection.confirmSponsorship(charlie);
225 await expect(confirmSponsorshipTx()).to.be.rejectedWith(/unique\.ConfirmUnsetSponsorFail/);225 await expect(confirmSponsorshipTx()).to.be.rejectedWith(/common\.ConfirmUnsetSponsorFail/);
226 });226 });
227227
228 itSub('(!negative test!) Confirm sponsorship without sponsor being set with setCollectionSponsor', async ({helper}) => {228 itSub('(!negative test!) Confirm sponsorship without sponsor being set with setCollectionSponsor', async ({helper}) => {
229 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});229 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
230 const confirmSponsorshipTx = () => collection.confirmSponsorship(charlie);230 const confirmSponsorshipTx = () => collection.confirmSponsorship(charlie);
231 await expect(confirmSponsorshipTx()).to.be.rejectedWith(/unique\.ConfirmUnsetSponsorFail/);231 await expect(confirmSponsorshipTx()).to.be.rejectedWith(/common\.ConfirmUnsetSponsorFail/);
232 });232 });
233233
234 itSub('(!negative test!) Confirm sponsorship in a collection that was destroyed', async ({helper}) => {234 itSub('(!negative test!) Confirm sponsorship in a collection that was destroyed', async ({helper}) => {
modifiedtests/src/eth/collectionSponsoring.test.tsdiffbeforeafterboth
258 await collectionEvm.methods[testCase](testCase === 'setCollectionSponsor' ? sponsor : sponsorCross).send();258 await collectionEvm.methods[testCase](testCase === 'setCollectionSponsor' ? sponsor : sponsorCross).send();
259 let collectionData = (await collectionSub.getData())!;259 let collectionData = (await collectionSub.getData())!;
260 expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));260 expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));
261 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');261 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
262 262
263 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});263 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});
264 collectionData = (await collectionSub.getData())!;264 collectionData = (await collectionSub.getData())!;
modifiedtests/src/eth/createFTCollection.test.tsdiffbeforeafterboth
46 let data = (await helper.rft.getData(collectionId))!;46 let data = (await helper.rft.getData(collectionId))!;
47 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));47 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));
4848
49 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');49 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
5050
51 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);51 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);
52 await sponsorCollection.methods.confirmCollectionSponsorship().send();52 await sponsorCollection.methods.confirmCollectionSponsorship().send();
69 let data = (await helper.rft.getData(collectionId))!;69 let data = (await helper.rft.getData(collectionId))!;
70 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));70 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));
7171
72 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');72 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
7373
74 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);74 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);
75 await sponsorCollection.methods.confirmCollectionSponsorship().send();75 await sponsorCollection.methods.confirmCollectionSponsorship().send();
192 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'ft', sponsor, true);192 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'ft', sponsor, true);
193 await expect(sponsorCollection.methods193 await expect(sponsorCollection.methods
194 .confirmCollectionSponsorship()194 .confirmCollectionSponsorship()
195 .call()).to.be.rejectedWith('caller is not set as sponsor');195 .call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
196 }196 }
197 {197 {
198 await expect(peasantCollection.methods198 await expect(peasantCollection.methods
199 .setCollectionLimit('account_token_ownership_limit', '1000')199 .setCollectionLimit('accountTokenOwnershipLimit', '1000')
200 .call()).to.be.rejectedWith(EXPECTED_ERROR);200 .call()).to.be.rejectedWith(EXPECTED_ERROR);
201 }201 }
202 });202 });
217 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'ft', sponsor);217 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'ft', sponsor);
218 await expect(sponsorCollection.methods218 await expect(sponsorCollection.methods
219 .confirmCollectionSponsorship()219 .confirmCollectionSponsorship()
220 .call()).to.be.rejectedWith('caller is not set as sponsor');220 .call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
221 }221 }
222 {222 {
223 await expect(peasantCollection.methods223 await expect(peasantCollection.methods
224 .setCollectionLimit('account_token_ownership_limit', '1000')224 .setCollectionLimit('accountTokenOwnershipLimit', '1000')
225 .call()).to.be.rejectedWith(EXPECTED_ERROR);225 .call()).to.be.rejectedWith(EXPECTED_ERROR);
226 }226 }
227 }); 227 });
modifiedtests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth
86 let data = (await helper.nft.getData(collectionId))!;86 let data = (await helper.nft.getData(collectionId))!;
87 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));87 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));
8888
89 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');89 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
9090
91 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor, true);91 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor, true);
92 await sponsorCollection.methods.confirmCollectionSponsorship().send();92 await sponsorCollection.methods.confirmCollectionSponsorship().send();
109 let data = (await helper.nft.getData(collectionId))!;109 let data = (await helper.nft.getData(collectionId))!;
110 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));110 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));
111111
112 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');112 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
113113
114 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor);114 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor);
115 await sponsorCollection.methods.confirmCollectionSponsorship().send();115 await sponsorCollection.methods.confirmCollectionSponsorship().send();
203 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor, true);203 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor, true);
204 await expect(sponsorCollection.methods204 await expect(sponsorCollection.methods
205 .confirmCollectionSponsorship()205 .confirmCollectionSponsorship()
206 .call()).to.be.rejectedWith('caller is not set as sponsor');206 .call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
207 }207 }
208 {208 {
209 await expect(malfeasantCollection.methods209 await expect(malfeasantCollection.methods
210 .setCollectionLimit('account_token_ownership_limit', '1000')210 .setCollectionLimit('accountTokenOwnershipLimit', '1000')
211 .call()).to.be.rejectedWith(EXPECTED_ERROR);211 .call()).to.be.rejectedWith(EXPECTED_ERROR);
212 }212 }
213 });213 });
228 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor);228 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor);
229 await expect(sponsorCollection.methods229 await expect(sponsorCollection.methods
230 .confirmCollectionSponsorship()230 .confirmCollectionSponsorship()
231 .call()).to.be.rejectedWith('caller is not set as sponsor');231 .call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
232 }232 }
233 {233 {
234 await expect(malfeasantCollection.methods234 await expect(malfeasantCollection.methods
235 .setCollectionLimit('account_token_ownership_limit', '1000')235 .setCollectionLimit('accountTokenOwnershipLimit', '1000')
236 .call()).to.be.rejectedWith(EXPECTED_ERROR);236 .call()).to.be.rejectedWith(EXPECTED_ERROR);
237 }237 }
238 });238 });
modifiedtests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth
121 let data = (await helper.rft.getData(collectionId))!;121 let data = (await helper.rft.getData(collectionId))!;
122 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));122 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));
123123
124 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');124 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
125125
126 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);126 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);
127 await sponsorCollection.methods.confirmCollectionSponsorship().send();127 await sponsorCollection.methods.confirmCollectionSponsorship().send();
143 let data = (await helper.rft.getData(collectionId))!;143 let data = (await helper.rft.getData(collectionId))!;
144 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));144 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));
145145
146 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');146 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
147147
148 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);148 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);
149 await sponsorCollection.methods.confirmCollectionSponsorship().send();149 await sponsorCollection.methods.confirmCollectionSponsorship().send();
235 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);235 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);
236 await expect(sponsorCollection.methods236 await expect(sponsorCollection.methods
237 .confirmCollectionSponsorship()237 .confirmCollectionSponsorship()
238 .call()).to.be.rejectedWith('caller is not set as sponsor');238 .call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
239 }239 }
240 {240 {
241 await expect(peasantCollection.methods241 await expect(peasantCollection.methods
242 .setCollectionLimit('account_token_ownership_limit', '1000')242 .setCollectionLimit('accountTokenOwnershipLimit', '1000')
243 .call()).to.be.rejectedWith(EXPECTED_ERROR);243 .call()).to.be.rejectedWith(EXPECTED_ERROR);
244 }244 }
245 });245 });
260 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);260 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);
261 await expect(sponsorCollection.methods261 await expect(sponsorCollection.methods
262 .confirmCollectionSponsorship()262 .confirmCollectionSponsorship()
263 .call()).to.be.rejectedWith('caller is not set as sponsor');263 .call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
264 }264 }
265 {265 {
266 await expect(peasantCollection.methods266 await expect(peasantCollection.methods
267 .setCollectionLimit('account_token_ownership_limit', '1000')267 .setCollectionLimit('accountTokenOwnershipLimit', '1000')
268 .call()).to.be.rejectedWith(EXPECTED_ERROR);268 .call()).to.be.rejectedWith(EXPECTED_ERROR);
269 }269 }
270 });270 });
modifiedtests/src/eth/events.test.tsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1616
17import { expect } from 'chai';
17import {IKeyringPair} from '@polkadot/types/types';18import {IKeyringPair} from '@polkadot/types/types';
18import { expect } from 'chai';
19import { itEth, usingEthPlaygrounds } from './util';19import { itEth, usingEthPlaygrounds } from './util';
2020
21describe.only('NFT events', () => {21describe('NFT events', () => {
22 let donor: IKeyringPair;22 let donor: IKeyringPair;
23 23
24 before(async function () {24 before(async function () {
2929
30 itEth('Create event', async ({helper}) => {30 itEth('Create event', async ({helper}) => {
31 const owner = await helper.eth.createAccountWithBalance(donor);31 const owner = await helper.eth.createAccountWithBalance(donor);
32 const {collectionAddress, events} = await helper.eth.createCollecion('createNFTCollection', owner, 'A', 'B', 'C');32 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionCreated']}]);
33 const {collectionAddress, events: ethEvents} = await helper.eth.createCollecion('createNFTCollection', owner, 'A', 'B', 'C');
33 expect(events).to.be.like([34 expect(ethEvents).to.be.like([
34 {35 {
35 event: 'CollectionCreated',36 event: 'CollectionCreated',
36 args: {37 args: {
39 }40 }
40 }41 }
41 ]);42 ]);
43 expect(subEvents).to.be.like([{method: 'CollectionCreated'}]);
44 unsubscribe();
42 });45 });
4346
44 itEth('Destroy event', async ({helper}) => {47 itEth('Destroy event', async ({helper}) => {
45 const owner = await helper.eth.createAccountWithBalance(donor);48 const owner = await helper.eth.createAccountWithBalance(donor);
46 const {collectionAddress} = await helper.eth.createCollecion('createNFTCollection', owner, 'A', 'B', 'C');49 const {collectionAddress} = await helper.eth.createCollecion('createNFTCollection', owner, 'A', 'B', 'C');
47 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);50 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
48 let resutl = await collectionHelper.methods.destroyCollection(collectionAddress).send({from:owner});51 const {unsubscribe, collectedEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionDestroyed']}]);
52 let result = await collectionHelper.methods.destroyCollection(collectionAddress).send({from:owner});
49 expect(resutl.events).to.be.like({53 expect(result.events).to.be.like({
50 CollectionDestroyed: {54 CollectionDestroyed: {
51 returnValues: {55 returnValues: {
52 collectionId: collectionAddress56 collectionId: collectionAddress
53 }57 }
54 }58 }
55 });59 });
60 expect(collectedEvents).to.be.like([{method: 'CollectionDestroyed'}]);
61 unsubscribe();
56 });62 });
57 63
58 itEth('CollectionChanged event for CollectionPropertySet and CollectionPropertyDeleted', async ({helper}) => {64 itEth('CollectionChanged event for CollectionPropertySet and CollectionPropertyDeleted', async ({helper}) => {
61 const collection = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);67 const collection = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
62 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);68 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
63 69
70 let {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionPropertySet', 'CollectionPropertyDeleted']}]);
64 {71 {
65 const events: any = [];72 const ethEvents: any = [];
66 collectionHelper.events.allEvents((_: any, event: any) => {73 collectionHelper.events.allEvents((_: any, event: any) => {
67 events.push(event);74 ethEvents.push(event);
68 });75 });
69 await collection.methods.setCollectionProperties([{key: 'A', value: [0,1,2,3]}]).send({from:owner});76 await collection.methods.setCollectionProperties([{key: 'A', value: [0,1,2,3]}]).send({from:owner});
70 expect(events).to.be.like([77 expect(ethEvents).to.be.like([
71 {78 {
72 event: 'CollectionChanged',79 event: 'CollectionChanged',
73 returnValues: {80 returnValues: {
74 collectionId: collectionAddress81 collectionId: collectionAddress
75 }82 }
76 }83 }
77 ]);84 ]);
85 expect(subEvents).to.be.like([{method: 'CollectionPropertySet'}]);
86 subEvents.pop();
78 }87 }
79 {88 {
80 const events: any = [];89 const ethEvents: any = [];
81 collectionHelper.events.allEvents((_: any, event: any) => {90 collectionHelper.events.allEvents((_: any, event: any) => {
82 events.push(event);91 ethEvents.push(event);
83 });92 });
84 await collection.methods.deleteCollectionProperties(['A']).send({from:owner});93 await collection.methods.deleteCollectionProperties(['A']).send({from:owner});
85 expect(events).to.be.like([94 expect(ethEvents).to.be.like([
86 {95 {
87 event: 'CollectionChanged',96 event: 'CollectionChanged',
88 returnValues: {97 returnValues: {
89 collectionId: collectionAddress98 collectionId: collectionAddress
90 }99 }
91 }100 }
92 ]);101 ]);
102 expect(subEvents).to.be.like([{method: 'CollectionPropertyDeleted'}]);
93 }103 }
94104 unsubscribe();
95 });105 });
96 106
97 itEth('CollectionChanged event for PropertyPermissionSet', async ({helper}) => {107 itEth('CollectionChanged event for PropertyPermissionSet', async ({helper}) => {
98 const owner = await helper.eth.createAccountWithBalance(donor);108 const owner = await helper.eth.createAccountWithBalance(donor);
99 const {collectionAddress} = await helper.eth.createCollecion('createNFTCollection', owner, 'A', 'B', 'C');109 const {collectionAddress} = await helper.eth.createCollecion('createNFTCollection', owner, 'A', 'B', 'C');
100 const collection = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);110 const collection = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
101 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);111 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
102 const events: any = [];112 const eethEvents: any = [];
103 collectionHelper.events.allEvents((_: any, event: any) => {113 collectionHelper.events.allEvents((_: any, event: any) => {
104 events.push(event);114 eethEvents.push(event);
105 });115 });
116 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['PropertyPermissionSet']}]);
106 await collection.methods.setTokenPropertyPermission('testKey', true, true, true).send({from: owner});117 await collection.methods.setTokenPropertyPermission('testKey', true, true, true).send({from: owner});
107 expect(events).to.be.like([118 expect(eethEvents).to.be.like([
108 {119 {
109 event: 'CollectionChanged',120 event: 'CollectionChanged',
110 returnValues: {121 returnValues: {
111 collectionId: collectionAddress122 collectionId: collectionAddress
112 }123 }
113 }124 }
114 ]);125 ]);
126 expect(subEvents).to.be.like([{method: 'PropertyPermissionSet'}]);
127 unsubscribe();
128 });
129
130 itEth('CollectionChanged event for AllowListAddressAdded, AllowListAddressRemoved', async ({helper}) => {
131 const owner = await helper.eth.createAccountWithBalance(donor);
132 const user = helper.ethCrossAccount.createAccount();
133 const {collectionAddress} = await helper.eth.createCollecion('createNFTCollection', owner, 'A', 'B', 'C');
134 const collection = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
135 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
136 const ethEvents: any[] = [];
137 collectionHelper.events.allEvents((_: any, event: any) => {
138 ethEvents.push(event);
139 });
140
141 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['AllowListAddressAdded', 'AllowListAddressRemoved']}]);
142 {
143 await collection.methods.addToCollectionAllowListCross(user).send({from: owner});
144 expect(ethEvents).to.be.like([
145 {
146 event: 'CollectionChanged',
147 returnValues: {
148 collectionId: collectionAddress
149 }
150 }
151 ]);
152 expect(subEvents).to.be.like([{method: 'AllowListAddressAdded'}]);
153 ethEvents.pop();
154 subEvents.pop();
155 }
156 {
157 await collection.methods.removeFromCollectionAllowListCross(user).send({from: owner});
158 expect(ethEvents.length).to.be.eq(1);
159 expect(ethEvents).to.be.like([
160 {
161 event: 'CollectionChanged',
162 returnValues: {
163 collectionId: collectionAddress
164 }
165 }
166 ]);
167 expect(subEvents).to.be.like([{method: 'AllowListAddressRemoved'}]);
168 }
169 unsubscribe();
170 });
171
172 itEth('CollectionChanged event for CollectionAdminAdded, CollectionAdminRemoved', async ({helper}) => {
173 const owner = await helper.eth.createAccountWithBalance(donor);
174 const user = helper.ethCrossAccount.createAccount();
175 const {collectionAddress} = await helper.eth.createCollecion('createNFTCollection', owner, 'A', 'B', 'C');
176 const collection = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
177 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
178 const ethEvents: any = [];
179 collectionHelper.events.allEvents((_: any, event: any) => {
180 ethEvents.push(event);
181 });
182 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionAdminAdded', 'CollectionAdminRemoved']}]);
183 {
184 await collection.methods.addCollectionAdminCross(user).send({from: owner});
185 expect(ethEvents).to.be.like([
186 {
187 event: 'CollectionChanged',
188 returnValues: {
189 collectionId: collectionAddress
190 }
191 }
192 ]);
193 expect(subEvents).to.be.like([{method: 'CollectionAdminAdded'}]);
194 ethEvents.pop();
195 subEvents.pop();
196 }
197 {
198 await collection.methods.removeCollectionAdminCross(user).send({from: owner});
199 expect(ethEvents).to.be.like([
200 {
201 event: 'CollectionChanged',
202 returnValues: {
203 collectionId: collectionAddress
204 }
205 }
206 ]);
207 expect(subEvents).to.be.like([{method: 'CollectionAdminRemoved'}]);
208 }
209 unsubscribe();
210 });
211
212 itEth('CollectionChanged event for CollectionLimitSet', async ({helper}) => {
213 const owner = await helper.eth.createAccountWithBalance(donor);
214 const {collectionAddress} = await helper.eth.createCollecion('createNFTCollection', owner, 'A', 'B', 'C');
215 const collection = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
216 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
217 const ethEvents: any = [];
218 collectionHelper.events.allEvents((_: any, event: any) => {
219 ethEvents.push(event);
220 });
221 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionLimitSet']}]);
222 {
223 await collection.methods.setCollectionLimit('ownerCanTransfer', 0n).send({from: owner});
224 expect(ethEvents).to.be.like([
225 {
226 event: 'CollectionChanged',
227 returnValues: {
228 collectionId: collectionAddress
229 }
230 }
231 ]);
232 expect(subEvents).to.be.like([{method: 'CollectionLimitSet'}]);
233 }
234 unsubscribe();
235 });
236
237 itEth('CollectionChanged event for CollectionOwnedChanged', async ({helper}) => {
238 const owner = await helper.eth.createAccountWithBalance(donor);
239 const new_owner = helper.ethCrossAccount.createAccount();
240 const {collectionAddress} = await helper.eth.createCollecion('createNFTCollection', owner, 'A', 'B', 'C');
241 const collection = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
242 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
243 const ethEvents: any = [];
244 collectionHelper.events.allEvents((_: any, event: any) => {
245 ethEvents.push(event);
246 });
247 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionOwnedChanged']}]);
248 {
249 await collection.methods.changeCollectionOwnerCross(new_owner).send({from: owner});
250 expect(ethEvents).to.be.like([
251 {
252 event: 'CollectionChanged',
253 returnValues: {
254 collectionId: collectionAddress
255 }
256 }
257 ]);
258 expect(subEvents).to.be.like([{method: 'CollectionOwnedChanged'}]);
259 }
260 unsubscribe();
261 });
262
263 itEth('CollectionChanged event for CollectionPermissionSet', async ({helper}) => {
264 const owner = await helper.eth.createAccountWithBalance(donor);
265 const {collectionAddress} = await helper.eth.createCollecion('createNFTCollection', owner, 'A', 'B', 'C');
266 const collection = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
267 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
268 const ethEvents: any = [];
269 collectionHelper.events.allEvents((_: any, event: any) => {
270 ethEvents.push(event);
271 });
272 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionPermissionSet']}]);
273 {
274 await collection.methods.setCollectionMintMode(true).send({from: owner});
275 expect(ethEvents).to.be.like([
276 {
277 event: 'CollectionChanged',
278 returnValues: {
279 collectionId: collectionAddress
280 }
281 }
282 ]);
283 expect(subEvents).to.be.like([{method: 'CollectionPermissionSet'}]);
284 ethEvents.pop();
285 subEvents.pop();
286 }
287 {
288 await collection.methods.setCollectionAccess(1).send({from: owner});
289 expect(ethEvents).to.be.like([
290 {
291 event: 'CollectionChanged',
292 returnValues: {
293 collectionId: collectionAddress
294 }
295 }
296 ]);
297 expect(subEvents).to.be.like([{method: 'CollectionPermissionSet'}]);
298 }
299 unsubscribe();
300 });
301
302 itEth('CollectionChanged event for CollectionSponsorSet, SponsorshipConfirmed, CollectionSponsorRemoved', async ({helper}) => {
303 const owner = await helper.eth.createAccountWithBalance(donor);
304 const sponsor = await helper.ethCrossAccount.createAccountWithBalance(donor);
305 const {collectionAddress} = await helper.eth.createCollecion('createNFTCollection', owner, 'A', 'B', 'C');
306 const collection = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
307 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
308 const ethEvents: any = [];
309 collectionHelper.events.allEvents((_: any, event: any) => {
310 ethEvents.push(event);
311 });
312 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{
313 section: 'common', names: ['CollectionSponsorSet', 'SponsorshipConfirmed', 'CollectionSponsorRemoved'
314 ]}]);
315 {
316 await collection.methods.setCollectionSponsorCross(sponsor).send({from: owner});
317 expect(ethEvents).to.be.like([
318 {
319 event: 'CollectionChanged',
320 returnValues: {
321 collectionId: collectionAddress
322 }
323 }
324 ]);
325 expect(subEvents).to.be.like([{method: 'CollectionSponsorSet'}]);
326 ethEvents.pop();
327 subEvents.pop();
328 }
329 {
330 await collection.methods.confirmCollectionSponsorship().send({from: sponsor.eth});
331 expect(ethEvents).to.be.like([
332 {
333 event: 'CollectionChanged',
334 returnValues: {
335 collectionId: collectionAddress
336 }
337 }
338 ]);
339 expect(subEvents).to.be.like([{method: 'SponsorshipConfirmed'}]);
340 ethEvents.pop();
341 subEvents.pop();
342 }
343 {
344 await collection.methods.removeCollectionSponsor().send({from: owner});
345 expect(ethEvents).to.be.like([
346 {
347 event: 'CollectionChanged',
348 returnValues: {
349 collectionId: collectionAddress
350 }
351 }
352 ]);
353 expect(subEvents).to.be.like([{method: 'CollectionSponsorRemoved'}]);
354 }
355 unsubscribe();
115 });356 });
116 357
117 // itEth('CollectionChanged event for AllowListAddressAdded', async ({helper}) => {
118 // const owner = await helper.eth.createAccountWithBalance(donor);
119 // const user = await helper.eth.createAccount();
120 // const userCross = helper.ethCrossAccount.fromAddress(user);
121 // const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
122 // // allow list does not need to be enabled to add someone in advance
123 // const collection = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
124 // const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
125 // const events: any = [];
126 // collectionHelper.events.allEvents((_: any, event: any) => {
127 // events.push(event);
128 // });
129 // await helper.nft.addToAllowList(alice, collectionId, {Substrate: bob.address});
130 // expect(events).to.be.like([
131 // {
132 // event: 'CollectionChanged',
133 // returnValues: {
134 // collectionId: collectionAddress
135 // }
136 // }
137 // ]);
138 // });
139});358});
modifiedtests/src/removeCollectionAdmin.test.tsdiffbeforeafterboth
51 const adminListBeforeAddAdmin = await collection.getAdmins();51 const adminListBeforeAddAdmin = await collection.getAdmins();
52 expect(adminListBeforeAddAdmin).to.have.lengthOf(0);52 expect(adminListBeforeAddAdmin).to.have.lengthOf(0);
5353
54 await collection.removeAdmin(alice, {Substrate: alice.address});54 await expect(collection.removeAdmin(alice, {Substrate: alice.address})).to.be.rejectedWith('common.UserIsNotAdmin');
55 });55 });
56});56});
5757
modifiedtests/src/removeCollectionSponsor.test.tsdiffbeforeafterboth
112 const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-Neg-4', tokenPrefix: 'RCS'});112 const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-Neg-4', tokenPrefix: 'RCS'});
113 await collection.setSponsor(alice, bob.address);113 await collection.setSponsor(alice, bob.address);
114 await collection.removeSponsor(alice);114 await collection.removeSponsor(alice);
115 await expect(collection.confirmSponsorship(bob)).to.be.rejectedWith(/unique\.ConfirmUnsetSponsorFail/);115 await expect(collection.confirmSponsorship(bob)).to.be.rejectedWith(/common\.ConfirmUnsetSponsorFail/);
116 });116 });
117117
118 itSub('Set - confirm - remove - confirm: Sponsor cannot come back', async ({helper}) => {118 itSub('Set - confirm - remove - confirm: Sponsor cannot come back', async ({helper}) => {
119 const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-Neg-5', tokenPrefix: 'RCS'});119 const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-Neg-5', tokenPrefix: 'RCS'});
120 await collection.setSponsor(alice, bob.address);120 await collection.setSponsor(alice, bob.address);
121 await collection.confirmSponsorship(bob);121 await collection.confirmSponsorship(bob);
122 await collection.removeSponsor(alice);122 await collection.removeSponsor(alice);
123 await expect(collection.confirmSponsorship(bob)).to.be.rejectedWith(/unique\.ConfirmUnsetSponsorFail/);123 await expect(collection.confirmSponsorship(bob)).to.be.rejectedWith(/common\.ConfirmUnsetSponsorFail/);
124 });124 });
125});125});
126126
modifiedtests/src/util/playgrounds/unique.tsdiffbeforeafterboth
43 IEthCrossAccountId,43 IEthCrossAccountId,
44} from './types';44} from './types';
45import {RuntimeDispatchInfo} from '@polkadot/types/interfaces';45import {RuntimeDispatchInfo} from '@polkadot/types/interfaces';
46import type {Vec} from '@polkadot/types-codec';
47import { FrameSystemEventRecord } from '@polkadot/types/lookup';
4648
47export class CrossAccountId implements ICrossAccountId {49export class CrossAccountId implements ICrossAccountId {
48 Substrate?: TSubstrateAccount;50 Substrate?: TSubstrateAccount;
404 return this.api;406 return this.api;
405 }407 }
408
409 async subscribeEvents(expectedEvents: {section: string, names: string[]}[]) {
410 const collectedEvents: IEvent[] = [];
411 const unsubscribe = await this.getApi().query.system.events((events: Vec<FrameSystemEventRecord>) => {
412 const ievents = this.eventHelper.extractEvents(events);
413 ievents.forEach((event) => {
414 expectedEvents.forEach((e => {
415 if (event.section === e.section && e.names.includes(event.method)) {
416 collectedEvents.push(event);
417 }
418 }))
419 });
420 });
421 return {unsubscribe: unsubscribe as any, collectedEvents};
422}
406423
407 clearChainLog(): void {424 clearChainLog(): void {
408 this.chainLog = [];425 this.chainLog = [];
834 true,851 true,
835 );852 );
836853
837 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionSponsorSet');854 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionSponsorSet');
838 }855 }
839856
840 /**857 /**
852 true,869 true,
853 );870 );
854871
855 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'SponsorshipConfirmed');872 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'SponsorshipConfirmed');
856 }873 }
857874
858 /**875 /**
870 true,887 true,
871 );888 );
872889
873 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionSponsorRemoved');890 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionSponsorRemoved');
874 }891 }
875892
876 /**893 /**
897 true,914 true,
898 );915 );
899916
900 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionLimitSet');917 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionLimitSet');
901 }918 }
902919
903 /**920 /**
916 true,933 true,
917 );934 );
918935
919 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionOwnedChanged');936 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionOwnedChanged');
920 }937 }
921938
922 /**939 /**
935 true,952 true,
936 );953 );
937954
938 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionAdminAdded');955 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionAdminAdded');
939 }956 }
940957
941 /**958 /**
954 true,971 true,
955 );972 );
956973
957 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionAdminRemoved');974 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionAdminRemoved');
958 }975 }
959976
960 /**977 /**
983 true,1000 true,
984 );1001 );
9851002
986 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'AllowListAddressAdded');1003 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'AllowListAddressAdded');
987 }1004 }
9881005
989 /**1006 /**
1001 true,1018 true,
1002 );1019 );
10031020
1004 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'AllowListAddressRemoved');1021 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'AllowListAddressRemoved');
1005 }1022 }
10061023
1007 /**1024 /**
1020 true,1037 true,
1021 );1038 );
10221039
1023 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionPermissionSet');1040 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionPermissionSet');
1024 }1041 }
10251042
1026 /**1043 /**