difftreelog
refactor Generalization some operations.
in: master
13 files changed
pallets/common/src/erc.rsdiffbeforeafterboth222 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)?;224224225 check_is_owner_or_admin(caller, self)?;225 let caller = T::CrossAccountId::from_eth(caller);226226227 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 }232231233 /// 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)?;244243245 check_is_owner_or_admin(caller, self)?;244 let caller = T::CrossAccountId::from_eth(caller);246245247 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 }252250253 /// 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)?;266264267 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 }276269277 /// 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 }284276285 /// Get current sponsor.277 /// Get current sponsor.333 }325 }334 };326 };335327336 check_is_owner_or_admin(caller, self)?;337 let mut limits = self.limits.clone();328 let mut limits = self.limits.clone();338329339 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 }360361 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 }373364374 /// 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)?;387378388 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)?;402393403 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)?;414405415 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)?;427418428 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)?;440431441 check_is_owner_or_admin(caller, self)?;432 let caller = T::CrossAccountId::from_eth(caller);442433443 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);448439449 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>)?;455456 save(self)457 }441 }458442459 /// 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);476460477 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 };499483500 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>)?;506507 save(self)508 }485 }509486510 /// 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)?;516493517 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>)?;532533 save(self)534 }504 }535505536 /// 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)?;607577608 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>)?;619620 save(self)621 }584 }622585623 /// Check that account is the owner or admin of the collection586 /// Check that account is the owner or admin of the collection671634672 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 }677640699662700 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}pallets/common/src/lib.rsdiffbeforeafterboth231 /// 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)?;239233 self.collection.sponsorship = SponsorshipState::Unconfirmed(sponsor);240 self.collection.sponsorship = SponsorshipState::Unconfirmed(sponsor.clone());241242 <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 );249250 self.save()235 }251 }252253 /// Force set `sponsor`.254 ///255 /// Differs from [`set_sponsor`][`Self::set_sponsor`] in that confirmation256 /// from the `sponsor` is not required.257 ///258 /// # Arguments259 ///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()?;264265 self.collection.sponsorship = SponsorshipState::Confirmed(sponsor.clone());266267 <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 );275276 self.save()277 }236278237 /// Confirm sponsorship279 /// Confirm sponsorship238 ///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>::ConfirmUnsetSponsorFail243 return Ok(false);288 );244 }245289246 self.collection.sponsorship = SponsorshipState::Confirmed(sender.clone());290 self.collection.sponsorship = SponsorshipState::Confirmed(sender.clone());291292 <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 );299247 Ok(true)300 self.save()248 }301 }249302250 /// 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)?;307252 self.collection.sponsorship = SponsorshipState::Disabled;308 self.collection.sponsorship = SponsorshipState::Disabled;309310 <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 }319320 /// Force remove `sponsor`.321 ///322 /// Differs from `remove_sponsor` in that323 /// 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()?;326327 self.collection.sponsorship = SponsorshipState::Disabled;328329 <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 }255338256 /// 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 account329 /// #### Store read/writes412 /// #### Store read/writes330 /// 1 writes413 /// 1 writes331 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();422423 <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 );433338 self.save()434 self.save()339 }435 }528 PropertyKey,624 PropertyKey,529 ),625 ),626627 /// 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 ),634635 /// 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 ),642643 /// Collection admin was added.644 CollectionAdminAdded(645 /// ID of the affected collection.646 CollectionId,647 /// Admin address.648 T::CrossAccountId,649 ),650651 /// Collection admin was removed.652 CollectionAdminRemoved(653 /// ID of the affected collection.654 CollectionId,655 /// Removed admin address.656 T::CrossAccountId,657 ),658659 /// Collection limits were set.660 CollectionLimitSet(661 /// ID of the affected collection.662 CollectionId,663 ),664665 /// Collection owned was changed.666 CollectionOwnedChanged(667 /// ID of the affected collection.668 CollectionId,669 /// New owner address.670 T::AccountId,671 ),672673 /// Collection permissions were set.674 CollectionPermissionSet(675 /// ID of the affected collection.676 CollectionId,677 ),678679 /// Collection sponsor was set.680 CollectionSponsorSet(681 /// ID of the affected collection.682 CollectionId,683 /// New sponsor address.684 T::AccountId,685 ),686687 /// New sponsor was confirm.688 SponsorshipConfirmed(689 /// ID of the affected collection.690 CollectionId,691 /// New sponsor address.692 T::AccountId,693 ),694695 /// Collection sponsor was removed.696 CollectionSponsorRemoved(697 /// ID of the affected collection.698 CollectionId,699 ),530 }700 }531701532 #[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 API615 CollectionIsInternal,785 CollectionIsInternal,786787 /// This address is not set as sponsor, use setCollectionSponsor first.788 ConfirmUnsetSponsorFail,789790 /// The user is not an administrator.791 UserIsNotAdmin,616 }792 }617793618 /// 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.136315391364 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 }15531554 <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 );136915601370 Ok(())1561 Ok(())1371 }1562 }137215631373 /// 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/writes1375 /// 2 writes1566 /// 2 reads, 2 writes1376 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)?;138315751384 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);138915851401 <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);15991600 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));16071608 Self::deposit_event(Event::<T>::CollectionAdminRemoved(1609 collection.id,1610 user.clone(),1611 ));1406 }1612 }16131614 <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 );140716201408 Ok(())1621 Ok(())1409 }1622 }16231624 /// 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)?;16321633 collection.limits =1634 Self::clamp_limits(collection.mode.clone(), &collection.limits, new_limit)?;16351636 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 );16431644 collection.save()1645 }141016461411 /// 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 }16921693 /// 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 )?;17061707 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 );17141715 collection.save()1716 }145617171457 /// 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,pallets/unique/src/lib.rsdiffbeforeafterboth89 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 where142 <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 removed146 ///142 ///147 /// # Arguments143 /// # Arguments148 /// * collection_id: ID of the affected collection.144 /// * collection_id: ID of the affected collection.149 CollectionSponsorRemoved(CollectionId),145 CollectionSponsorRemoved(CollectionId),150151 /// Collection admin was added152 ///153 /// # Arguments154 /// * collection_id: ID of the affected collection.155 /// * admin: Admin address.156 CollectionAdminAdded(CollectionId, CrossAccountId),157158 /// Collection owned was changed159 ///160 /// # Arguments161 /// * collection_id: ID of the affected collection.162 /// * owner: New owner address.163 CollectionOwnedChanged(CollectionId, AccountId),164146165 /// Collection sponsor was set147 /// Collection sponsor was set166 ///148 ///169 /// * owner: New sponsor address.151 /// * owner: New sponsor address.170 CollectionSponsorSet(CollectionId, AccountId),152 CollectionSponsorSet(CollectionId, AccountId),171153172 /// New sponsor was confirm173 ///174 /// # Arguments175 /// * collection_id: ID of the affected collection.176 /// * sponsor: New sponsor address.177 SponsorshipConfirmed(CollectionId, AccountId),178179 /// Collection admin was removed180 ///181 /// # Arguments182 /// * collection_id: ID of the affected collection.183 /// * admin: Removed admin address.184 CollectionAdminRemoved(CollectionId, CrossAccountId),185186 /// Address was removed from the allow list187 ///188 /// # Arguments189 /// * collection_id: ID of the affected collection.190 /// * user: Address of the removed account.191 AllowListAddressRemoved(CollectionId, CrossAccountId),192193 /// Address was added to the allow list194 ///195 /// # Arguments196 /// * collection_id: ID of the affected collection.197 /// * user: Address of the added account.198 AllowListAddressAdded(CollectionId, CrossAccountId),199200 /// Collection limits were set201 ///202 /// # Arguments203 /// * collection_id: ID of the affected collection.204 CollectionLimitSet(CollectionId),205206 /// Collection permissions were set207 ///208 /// # Arguments209 /// * collection_id: ID of the affected collection.210 CollectionPermissionSet(CollectionId),211 }154 }212}155}213156433 true,376 true,434 )?;377 )?;435436 Self::deposit_event(Event::<T>::AllowListAddressAdded(437 collection_id,438 address439 ));440378441 Ok(())379 Ok(())442 }380 }466 false,404 false,467 )?;405 )?;468469 <Pallet<T>>::deposit_event(Event::<T>::AllowListAddressRemoved(470 collection_id,471 address472 ));473406474 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 {489490 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)?;495496 target_collection.owner = new_owner.clone();497 <Pallet<T>>::deposit_event(Event::<T>::CollectionOwnedChanged(498 collection_id,499 new_owner500 ));501502 target_collection.save()503 }426 }504427505 /// 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()?;526527 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminAdded(528 collection_id,529 new_admin_id.clone()530 ));531532 <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()?;554555 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminRemoved(556 collection_id,557 account_id.clone()558 ));559560 <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)?);579580 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()?;583584 target_collection.set_sponsor(new_sponsor.clone())?;585586 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(587 collection_id,588 new_sponsor589 ));590591 target_collection.save()592 }490 }593491594 /// 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)?;610611 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>::ConfirmUnsetSponsorFail616 );617618 <Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(619 collection_id,620 sender621 ));622623 target_collection.save()624 }510 }625511626 /// 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)?);638639 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)?;642643 target_collection.sponsorship = SponsorshipState::Disabled;644645 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(646 collection_id647 ));648 target_collection.save()649 }526 }650527651 /// 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;10591060 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)10611062 <Pallet<T>>::deposit_event(Event::<T>::CollectionLimitSet(1063 collection_id1064 ));10651066 target_collection.save()1067 }934 }10689351069 /// 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;10921093 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_permission1097 ));960 )10981099 target_collection.save()1100 }961 }11019621102 /// 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())11681169 Self::deposit_event(Event::<T>::CollectionSponsorSet(1170 collection_id,1171 sponsor.clone(),1172 ));11731174 ensure!(1175 target_collection.confirm_sponsorship(&sponsor)?,1176 Error::<T>::ConfirmUnsetSponsorFail1177 );11781179 Self::deposit_event(Event::<T>::SponsorshipConfirmed(collection_id, sponsor));11801181 target_collection.save()1182 }1028 }118310291184 /// 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;11961197 Self::deposit_event(Event::<T>::CollectionSponsorRemoved(collection_id));11981199 target_collection.save()1040 target_collection.force_remove_sponsor()1200 }1041 }120110421202 #[inline(always)]1043 #[inline(always)]tests/src/change-collection-owner.test.tsdiffbeforeafterboth146 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/);151151152 const limits = {152 const limits = {tests/src/confirmSponsorship.test.tsdiffbeforeafterboth207 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 });212212213 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 });219219220 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 });227227228 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 });233233234 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}) => {tests/src/eth/collectionSponsoring.test.tsdiffbeforeafterboth258 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())!;tests/src/eth/createFTCollection.test.tsdiffbeforeafterboth46 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)));484849 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');505051 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)));717172 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');737374 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.methods194 .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.methods199 .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.methods219 .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.methods224 .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 }); tests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth86 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)));888889 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');909091 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)));111111112 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');113113114 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.methods205 .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.methods210 .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.methods230 .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.methods235 .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 });tests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth121 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)));123123124 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');125125126 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)));145145146 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');147147148 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.methods237 .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.methods242 .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.methods262 .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.methods267 .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 });tests/src/eth/events.test.tsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// 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/>.161617import { 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';202021describe.only('NFT events', () => {21describe('NFT events', () => {22 let donor: IKeyringPair;22 let donor: IKeyringPair;23 23 24 before(async function () {24 before(async function () {292930 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 });434644 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: collectionAddress53 }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: collectionAddress75 }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: collectionAddress90 }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: collectionAddress112 }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 });140141 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: collectionAddress149 }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: collectionAddress164 }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: collectionAddress190 }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: collectionAddress204 }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: collectionAddress229 }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: collectionAddress255 }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: collectionAddress280 }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: collectionAddress294 }295 }296 ]);297 expect(subEvents).to.be.like([{method: 'CollectionPermissionSet'}]);298 }299 unsubscribe();300 });301302 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: collectionAddress322 }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: collectionAddress336 }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: collectionAddress350 }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 advance123 // 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: collectionAddress135 // }136 // }137 // ]);138 // });139});358});tests/src/removeCollectionAdmin.test.tsdiffbeforeafterboth51 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);535354 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});5757tests/src/removeCollectionSponsor.test.tsdiffbeforeafterboth112 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 });117117118 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});126126tests/src/util/playgrounds/unique.tsdiffbeforeafterboth43 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';464847export 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 }408409 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}406423407 clearChainLog(): void {424 clearChainLog(): void {408 this.chainLog = [];425 this.chainLog = [];834 true,851 true,835 );852 );836853837 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 }839856840 /**857 /**852 true,869 true,853 );870 );854871855 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 }857874858 /**875 /**870 true,887 true,871 );888 );872889873 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 }875892876 /**893 /**897 true,914 true,898 );915 );899916900 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 }902919903 /**920 /**916 true,933 true,917 );934 );918935919 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 }921938922 /**939 /**935 true,952 true,936 );953 );937954938 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 }940957941 /**958 /**954 true,971 true,955 );972 );956973957 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 }959976960 /**977 /**983 true,1000 true,984 );1001 );9851002986 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 }9881005989 /**1006 /**1001 true,1018 true,1002 );1019 );100310201004 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 }100610231007 /**1024 /**1020 true,1037 true,1021 );1038 );102210391023 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 }102510421026 /**1043 /**