123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566#![recursion_limit = "1024"]67#![cfg_attr(not(feature = "std"), no_std)]68#![allow(69 clippy::too_many_arguments,70 clippy::unnecessary_mut_passed,71 clippy::unused_unit72)]7374extern crate alloc;7576pub use pallet::*;77use frame_support::pallet_prelude::*;78use frame_system::pallet_prelude::*;79pub mod eth;8081#[cfg(feature = "runtime-benchmarks")]82pub mod benchmarking;83pub mod weights;8485#[frame_support::pallet]86pub mod pallet {87 use super::*;8889 use frame_support::{dispatch::DispatchResult, ensure, fail, BoundedVec, storage::Key};90 use scale_info::TypeInfo;91 use frame_system::{ensure_signed, ensure_root};92 use sp_std::{vec, vec::Vec};93 use up_data_structs::{94 MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH,95 MAX_PROPERTIES_PER_ITEM, MAX_PROPERTY_KEY_LENGTH, MAX_PROPERTY_VALUE_LENGTH,96 MAX_COLLECTION_PROPERTIES_SIZE, COLLECTION_ADMINS_LIMIT, MAX_TOKEN_PROPERTIES_SIZE,97 CreateItemData, CollectionLimits, CollectionPermissions, CollectionId, CollectionMode,98 TokenId, CreateCollectionData, CreateItemExData, budget, Property, PropertyKey,99 PropertyKeyPermission,100 };101 use pallet_evm::account::CrossAccountId;102 use pallet_common::{103 CollectionHandle, Pallet as PalletCommon, CommonWeightInfo, dispatch::dispatch_tx,104 dispatch::CollectionDispatch, RefungibleExtensionsWeightInfo,105 };106 use weights::WeightInfo;107108 109 pub const NESTING_BUDGET: u32 = 5;110111 112 #[pallet::error]113 pub enum Error<T> {114 115 CollectionDecimalPointLimitExceeded,116 117 EmptyArgument,118 119 RepartitionCalledOnNonRefungibleCollection,120 }121122 123 #[pallet::config]124 pub trait Config: frame_system::Config + pallet_common::Config + Sized + TypeInfo {125 126 type WeightInfo: WeightInfo;127128 129 type CommonWeightInfo: CommonWeightInfo<Self::CrossAccountId>;130131 132 type RefungibleExtensionsWeightInfo: RefungibleExtensionsWeightInfo;133 }134135 #[pallet::pallet]136 pub struct Pallet<T>(_);137138 pub type SelfWeightOf<T> = <T as Config>::WeightInfo;139140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162163 164 165 #[pallet::storage]166 pub type ChainVersion<T> = StorageValue<_, u64, ValueQuery>;167 168169 170 171 172 #[pallet::storage]173 #[pallet::getter(fn create_item_busket)]174 pub type CreateItemBasket<T: Config> = StorageMap<175 Hasher = Blake2_128Concat,176 Key = (CollectionId, T::AccountId),177 Value = T::BlockNumber,178 QueryKind = OptionQuery,179 >;180 181 #[pallet::storage]182 #[pallet::getter(fn nft_transfer_basket)]183 pub type NftTransferBasket<T: Config> = StorageDoubleMap<184 Hasher1 = Blake2_128Concat,185 Key1 = CollectionId,186 Hasher2 = Blake2_128Concat,187 Key2 = TokenId,188 Value = T::BlockNumber,189 QueryKind = OptionQuery,190 >;191 192 #[pallet::storage]193 #[pallet::getter(fn fungible_transfer_basket)]194 pub type FungibleTransferBasket<T: Config> = StorageDoubleMap<195 Hasher1 = Blake2_128Concat,196 Key1 = CollectionId,197 Hasher2 = Twox64Concat,198 Key2 = T::AccountId,199 Value = T::BlockNumber,200 QueryKind = OptionQuery,201 >;202 203 #[pallet::storage]204 #[pallet::getter(fn refungible_transfer_basket)]205 pub type ReFungibleTransferBasket<T: Config> = StorageNMap<206 Key = (207 Key<Blake2_128Concat, CollectionId>,208 Key<Blake2_128Concat, TokenId>,209 Key<Twox64Concat, T::AccountId>,210 ),211 Value = T::BlockNumber,212 QueryKind = OptionQuery,213 >;214 215216 217 #[pallet::storage]218 #[pallet::getter(fn token_property_basket)]219 pub type TokenPropertyBasket<T: Config> = StorageDoubleMap<220 Hasher1 = Blake2_128Concat,221 Key1 = CollectionId,222 Hasher2 = Blake2_128Concat,223 Key2 = TokenId,224 Value = T::BlockNumber,225 QueryKind = OptionQuery,226 >;227228 229 #[pallet::storage]230 #[pallet::getter(fn nft_approve_basket)]231 pub type NftApproveBasket<T: Config> = StorageDoubleMap<232 Hasher1 = Blake2_128Concat,233 Key1 = CollectionId,234 Hasher2 = Blake2_128Concat,235 Key2 = TokenId,236 Value = T::BlockNumber,237 QueryKind = OptionQuery,238 >;239 240 #[pallet::storage]241 #[pallet::getter(fn fungible_approve_basket)]242 pub type FungibleApproveBasket<T: Config> = StorageDoubleMap<243 Hasher1 = Blake2_128Concat,244 Key1 = CollectionId,245 Hasher2 = Twox64Concat,246 Key2 = T::AccountId,247 Value = T::BlockNumber,248 QueryKind = OptionQuery,249 >;250 251 #[pallet::storage]252 #[pallet::getter(fn refungible_approve_basket)]253 pub type RefungibleApproveBasket<T: Config> = StorageNMap<254 Key = (255 Key<Blake2_128Concat, CollectionId>,256 Key<Blake2_128Concat, TokenId>,257 Key<Twox64Concat, T::AccountId>,258 ),259 Value = T::BlockNumber,260 QueryKind = OptionQuery,261 >;262263 #[pallet::extra_constants]264 impl<T: Config> Pallet<T> {265 266 fn nesting_budget() -> u32 {267 NESTING_BUDGET268 }269270 271 fn max_collection_name_length() -> u32 {272 MAX_COLLECTION_NAME_LENGTH273 }274275 276 fn max_collection_description_length() -> u32 {277 MAX_COLLECTION_DESCRIPTION_LENGTH278 }279280 281 fn max_token_prefix_length() -> u32 {282 MAX_TOKEN_PREFIX_LENGTH283 }284285 286 fn collection_admins_limit() -> u32 {287 COLLECTION_ADMINS_LIMIT288 }289290 291 fn max_property_key_length() -> u32 {292 MAX_PROPERTY_KEY_LENGTH293 }294295 296 fn max_property_value_length() -> u32 {297 MAX_PROPERTY_VALUE_LENGTH298 }299300 301 fn max_properties_per_item() -> u32 {302 MAX_PROPERTIES_PER_ITEM303 }304305 306 fn max_collection_properties_size() -> u32 {307 MAX_COLLECTION_PROPERTIES_SIZE308 }309310 311 fn max_token_properties_size() -> u32 {312 MAX_TOKEN_PROPERTIES_SIZE313 }314315 316 fn nft_default_collection_limits() -> CollectionLimits {317 CollectionLimits::with_default_limits(CollectionMode::NFT)318 }319320 321 fn rft_default_collection_limits() -> CollectionLimits {322 CollectionLimits::with_default_limits(CollectionMode::ReFungible)323 }324325 326 fn ft_default_collection_limits() -> CollectionLimits {327 CollectionLimits::with_default_limits(CollectionMode::Fungible(0))328 }329 }330331 332 #[pallet::call]333 impl<T: Config> Pallet<T> {334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 #[pallet::call_index(0)]360 #[pallet::weight(<SelfWeightOf<T>>::create_collection())]361 pub fn create_collection(362 origin: OriginFor<T>,363 collection_name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,364 collection_description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,365 token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,366 mode: CollectionMode,367 ) -> DispatchResult {368 let data: CreateCollectionData<T::AccountId> = CreateCollectionData {369 name: collection_name,370 description: collection_description,371 token_prefix,372 mode,373 ..Default::default()374 };375 Self::create_collection_ex(origin, data)376 }377378 379 380 381 382 383 384 385 386 387 388 389 #[pallet::call_index(1)]390 #[pallet::weight(<SelfWeightOf<T>>::create_collection())]391 pub fn create_collection_ex(392 origin: OriginFor<T>,393 data: CreateCollectionData<T::AccountId>,394 ) -> DispatchResult {395 let sender = ensure_signed(origin)?;396397 398 let sender = T::CrossAccountId::from_sub(sender);399 let _id =400 T::CollectionDispatch::create(sender.clone(), sender, data, Default::default())?;401402 Ok(())403 }404405 406 407 408 409 410 411 412 413 414 #[pallet::call_index(2)]415 #[pallet::weight(<SelfWeightOf<T>>::destroy_collection())]416 pub fn destroy_collection(417 origin: OriginFor<T>,418 collection_id: CollectionId,419 ) -> DispatchResult {420 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);421422 Self::destroy_collection_internal(sender, collection_id)423 }424425 426 427 428 429 430 431 432 433 434 435 436 #[pallet::call_index(3)]437 #[pallet::weight(<SelfWeightOf<T>>::add_to_allow_list())]438 pub fn add_to_allow_list(439 origin: OriginFor<T>,440 collection_id: CollectionId,441 address: T::CrossAccountId,442 ) -> DispatchResult {443 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);444 let collection = <CollectionHandle<T>>::try_get(collection_id)?;445 collection.check_is_internal()?;446447 <PalletCommon<T>>::toggle_allowlist(&collection, &sender, &address, true)?;448449 Ok(())450 }451452 453 454 455 456 457 458 459 460 461 462 463 #[pallet::call_index(4)]464 #[pallet::weight(<SelfWeightOf<T>>::remove_from_allow_list())]465 pub fn remove_from_allow_list(466 origin: OriginFor<T>,467 collection_id: CollectionId,468 address: T::CrossAccountId,469 ) -> DispatchResult {470 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);471 let collection = <CollectionHandle<T>>::try_get(collection_id)?;472 collection.check_is_internal()?;473474 <PalletCommon<T>>::toggle_allowlist(&collection, &sender, &address, false)?;475476 Ok(())477 }478479 480 481 482 483 484 485 486 487 488 489 #[pallet::call_index(5)]490 #[pallet::weight(<SelfWeightOf<T>>::change_collection_owner())]491 pub fn change_collection_owner(492 origin: OriginFor<T>,493 collection_id: CollectionId,494 new_owner: T::AccountId,495 ) -> DispatchResult {496 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);497 let new_owner = T::CrossAccountId::from_sub(new_owner);498 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;499 target_collection.change_owner(sender, new_owner.clone())500 }501502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 #[pallet::call_index(6)]519 #[pallet::weight(<SelfWeightOf<T>>::add_collection_admin())]520 pub fn add_collection_admin(521 origin: OriginFor<T>,522 collection_id: CollectionId,523 new_admin_id: T::CrossAccountId,524 ) -> DispatchResult {525 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);526 let collection = <CollectionHandle<T>>::try_get(collection_id)?;527 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)528 }529530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 #[pallet::call_index(7)]545 #[pallet::weight(<SelfWeightOf<T>>::remove_collection_admin())]546 pub fn remove_collection_admin(547 origin: OriginFor<T>,548 collection_id: CollectionId,549 account_id: T::CrossAccountId,550 ) -> DispatchResult {551 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);552 let collection = <CollectionHandle<T>>::try_get(collection_id)?;553 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)554 }555556 557 558 559 560 561 562 563 564 565 566 567 568 569 #[pallet::call_index(8)]570 #[pallet::weight(<SelfWeightOf<T>>::set_collection_sponsor())]571 pub fn set_collection_sponsor(572 origin: OriginFor<T>,573 collection_id: CollectionId,574 new_sponsor: T::AccountId,575 ) -> DispatchResult {576 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);577 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;578 target_collection.set_sponsor(&sender, new_sponsor.clone())579 }580581 582 583 584 585 586 587 588 589 590 591 592 593 594 #[pallet::call_index(9)]595 #[pallet::weight(<SelfWeightOf<T>>::confirm_sponsorship())]596 pub fn confirm_sponsorship(597 origin: OriginFor<T>,598 collection_id: CollectionId,599 ) -> DispatchResult {600 let sender = ensure_signed(origin)?;601 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;602 target_collection.confirm_sponsorship(&sender)603 }604605 606 607 608 609 610 611 612 613 614 #[pallet::call_index(10)]615 #[pallet::weight(<SelfWeightOf<T>>::remove_collection_sponsor())]616 pub fn remove_collection_sponsor(617 origin: OriginFor<T>,618 collection_id: CollectionId,619 ) -> DispatchResult {620 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);621 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;622 target_collection.remove_sponsor(&sender)623 }624625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 #[pallet::call_index(11)]644 #[pallet::weight(T::CommonWeightInfo::create_item(&data))]645 pub fn create_item(646 origin: OriginFor<T>,647 collection_id: CollectionId,648 owner: T::CrossAccountId,649 data: CreateItemData,650 ) -> DispatchResultWithPostInfo {651 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);652 let budget = budget::Value::new(NESTING_BUDGET);653654 dispatch_tx::<T, _>(collection_id, |d| {655 d.create_item(sender, owner, data, &budget)656 })657 }658659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 #[pallet::call_index(12)]678 #[pallet::weight(T::CommonWeightInfo::create_multiple_items(&items_data))]679 pub fn create_multiple_items(680 origin: OriginFor<T>,681 collection_id: CollectionId,682 owner: T::CrossAccountId,683 items_data: Vec<CreateItemData>,684 ) -> DispatchResultWithPostInfo {685 ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);686 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);687 let budget = budget::Value::new(NESTING_BUDGET);688689 dispatch_tx::<T, _>(collection_id, |d| {690 d.create_multiple_items(sender, owner, items_data, &budget)691 })692 }693694 695 696 697 698 699 700 701 702 703 704 705 706 #[pallet::call_index(13)]707 #[pallet::weight(T::CommonWeightInfo::set_collection_properties(properties.len() as u32))]708 pub fn set_collection_properties(709 origin: OriginFor<T>,710 collection_id: CollectionId,711 properties: Vec<Property>,712 ) -> DispatchResultWithPostInfo {713 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);714715 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);716717 dispatch_tx::<T, _>(collection_id, |d| {718 d.set_collection_properties(sender, properties)719 })720 }721722 723 724 725 726 727 728 729 730 731 732 733 734 #[pallet::call_index(14)]735 #[pallet::weight(T::CommonWeightInfo::delete_collection_properties(property_keys.len() as u32))]736 pub fn delete_collection_properties(737 origin: OriginFor<T>,738 collection_id: CollectionId,739 property_keys: Vec<PropertyKey>,740 ) -> DispatchResultWithPostInfo {741 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);742743 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);744745 dispatch_tx::<T, _>(collection_id, |d| {746 d.delete_collection_properties(&sender, property_keys)747 })748 }749750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 #[pallet::call_index(15)]769 #[pallet::weight(T::CommonWeightInfo::set_token_properties(properties.len() as u32))]770 pub fn set_token_properties(771 origin: OriginFor<T>,772 collection_id: CollectionId,773 token_id: TokenId,774 properties: Vec<Property>,775 ) -> DispatchResultWithPostInfo {776 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);777778 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);779 let budget = budget::Value::new(NESTING_BUDGET);780781 dispatch_tx::<T, _>(collection_id, |d| {782 d.set_token_properties(sender, token_id, properties, &budget)783 })784 }785786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 #[pallet::call_index(16)]802 #[pallet::weight(T::CommonWeightInfo::delete_token_properties(property_keys.len() as u32))]803 pub fn delete_token_properties(804 origin: OriginFor<T>,805 collection_id: CollectionId,806 token_id: TokenId,807 property_keys: Vec<PropertyKey>,808 ) -> DispatchResultWithPostInfo {809 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);810811 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);812 let budget = budget::Value::new(NESTING_BUDGET);813814 dispatch_tx::<T, _>(collection_id, |d| {815 d.delete_token_properties(sender, token_id, property_keys, &budget)816 })817 }818819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 #[pallet::call_index(17)]835 #[pallet::weight(T::CommonWeightInfo::set_token_property_permissions(property_permissions.len() as u32))]836 pub fn set_token_property_permissions(837 origin: OriginFor<T>,838 collection_id: CollectionId,839 property_permissions: Vec<PropertyKeyPermission>,840 ) -> DispatchResultWithPostInfo {841 ensure!(!property_permissions.is_empty(), Error::<T>::EmptyArgument);842843 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);844845 dispatch_tx::<T, _>(collection_id, |d| {846 d.set_token_property_permissions(&sender, property_permissions)847 })848 }849850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 #[pallet::call_index(18)]866 #[pallet::weight(T::CommonWeightInfo::create_multiple_items_ex(&data))]867 pub fn create_multiple_items_ex(868 origin: OriginFor<T>,869 collection_id: CollectionId,870 data: CreateItemExData<T::CrossAccountId>,871 ) -> DispatchResultWithPostInfo {872 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);873 let budget = budget::Value::new(NESTING_BUDGET);874875 dispatch_tx::<T, _>(collection_id, |d| {876 d.create_multiple_items_ex(sender, data, &budget)877 })878 }879880 881 882 883 884 885 886 887 888 889 890 #[pallet::call_index(19)]891 #[pallet::weight(<SelfWeightOf<T>>::set_transfers_enabled_flag())]892 pub fn set_transfers_enabled_flag(893 origin: OriginFor<T>,894 collection_id: CollectionId,895 value: bool,896 ) -> DispatchResult {897 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);898 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;899 target_collection.check_is_internal()?;900 target_collection.check_is_owner(&sender)?;901902 903904 target_collection.limits.transfers_enabled = Some(value);905 target_collection.save()906 }907908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 #[pallet::call_index(20)]925 #[pallet::weight(T::CommonWeightInfo::burn_item())]926 pub fn burn_item(927 origin: OriginFor<T>,928 collection_id: CollectionId,929 item_id: TokenId,930 value: u128,931 ) -> DispatchResultWithPostInfo {932 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);933934 let post_info =935 dispatch_tx::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;936 if value == 1 {937 <NftTransferBasket<T>>::remove(collection_id, item_id);938 <NftApproveBasket<T>>::remove(collection_id, item_id);939 }940 941 942 943 Ok(post_info)944 }945946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 #[pallet::call_index(21)]970 #[pallet::weight(T::CommonWeightInfo::burn_from())]971 pub fn burn_from(972 origin: OriginFor<T>,973 collection_id: CollectionId,974 from: T::CrossAccountId,975 item_id: TokenId,976 value: u128,977 ) -> DispatchResultWithPostInfo {978 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);979 let budget = budget::Value::new(NESTING_BUDGET);980981 dispatch_tx::<T, _>(collection_id, |d| {982 d.burn_from(sender, from, item_id, value, &budget)983 })984 }985986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 #[pallet::call_index(22)]1008 #[pallet::weight(T::CommonWeightInfo::transfer())]1009 pub fn transfer(1010 origin: OriginFor<T>,1011 recipient: T::CrossAccountId,1012 collection_id: CollectionId,1013 item_id: TokenId,1014 value: u128,1015 ) -> DispatchResultWithPostInfo {1016 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1017 let budget = budget::Value::new(NESTING_BUDGET);10181019 dispatch_tx::<T, _>(collection_id, |d| {1020 d.transfer(sender, recipient, item_id, value, &budget)1021 })1022 }10231024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 #[pallet::call_index(23)]1040 #[pallet::weight(T::CommonWeightInfo::approve())]1041 pub fn approve(1042 origin: OriginFor<T>,1043 spender: T::CrossAccountId,1044 collection_id: CollectionId,1045 item_id: TokenId,1046 amount: u128,1047 ) -> DispatchResultWithPostInfo {1048 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);10491050 dispatch_tx::<T, _>(collection_id, |d| {1051 d.approve(sender, spender, item_id, amount)1052 })1053 }10541055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 #[pallet::call_index(24)]1072 #[pallet::weight(T::CommonWeightInfo::approve_from())]1073 pub fn approve_from(1074 origin: OriginFor<T>,1075 from: T::CrossAccountId,1076 to: T::CrossAccountId,1077 collection_id: CollectionId,1078 item_id: TokenId,1079 amount: u128,1080 ) -> DispatchResultWithPostInfo {1081 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);10821083 dispatch_tx::<T, _>(collection_id, |d| {1084 d.approve_from(sender, from, to, item_id, amount)1085 })1086 }10871088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 #[pallet::call_index(25)]1113 #[pallet::weight(T::CommonWeightInfo::transfer_from())]1114 pub fn transfer_from(1115 origin: OriginFor<T>,1116 from: T::CrossAccountId,1117 recipient: T::CrossAccountId,1118 collection_id: CollectionId,1119 item_id: TokenId,1120 value: u128,1121 ) -> DispatchResultWithPostInfo {1122 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1123 let budget = budget::Value::new(NESTING_BUDGET);11241125 dispatch_tx::<T, _>(collection_id, |d| {1126 d.transfer_from(sender, from, recipient, item_id, value, &budget)1127 })1128 }11291130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 #[pallet::call_index(26)]1143 #[pallet::weight(<SelfWeightOf<T>>::set_collection_limits())]1144 pub fn set_collection_limits(1145 origin: OriginFor<T>,1146 collection_id: CollectionId,1147 new_limit: CollectionLimits,1148 ) -> DispatchResult {1149 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1150 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1151 <PalletCommon<T>>::update_limits(&sender, &mut target_collection, new_limit)1152 }11531154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 #[pallet::call_index(27)]1167 #[pallet::weight(<SelfWeightOf<T>>::set_collection_limits())]1168 pub fn set_collection_permissions(1169 origin: OriginFor<T>,1170 collection_id: CollectionId,1171 new_permission: CollectionPermissions,1172 ) -> DispatchResult {1173 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1174 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1175 <PalletCommon<T>>::update_permissions(&sender, &mut target_collection, new_permission)1176 }11771178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 #[pallet::call_index(28)]1190 #[pallet::weight(T::RefungibleExtensionsWeightInfo::repartition())]1191 pub fn repartition(1192 origin: OriginFor<T>,1193 collection_id: CollectionId,1194 token_id: TokenId,1195 amount: u128,1196 ) -> DispatchResultWithPostInfo {1197 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1198 dispatch_tx::<T, _>(collection_id, |d| {1199 if let Some(refungible_extensions) = d.refungible_extensions() {1200 refungible_extensions.repartition(&sender, token_id, amount)1201 } else {1202 fail!(<Error<T>>::RepartitionCalledOnNonRefungibleCollection)1203 }1204 })1205 }12061207 1208 1209 1210 1211 1212 1213 1214 1215 1216 #[pallet::call_index(29)]1217 #[pallet::weight(T::CommonWeightInfo::set_allowance_for_all())]1218 pub fn set_allowance_for_all(1219 origin: OriginFor<T>,1220 collection_id: CollectionId,1221 operator: T::CrossAccountId,1222 approve: bool,1223 ) -> DispatchResultWithPostInfo {1224 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1225 dispatch_tx::<T, _>(collection_id, |d| {1226 d.set_allowance_for_all(sender, operator, approve)1227 })1228 }12291230 1231 1232 1233 1234 1235 #[pallet::call_index(30)]1236 #[pallet::weight(<SelfWeightOf<T>>::force_repair_collection())]1237 pub fn force_repair_collection(1238 origin: OriginFor<T>,1239 collection_id: CollectionId,1240 ) -> DispatchResult {1241 ensure_root(origin)?;1242 <PalletCommon<T>>::repair_collection(collection_id)1243 }12441245 1246 1247 1248 1249 1250 1251 #[pallet::call_index(31)]1252 #[pallet::weight(T::CommonWeightInfo::force_repair_item())]1253 pub fn force_repair_item(1254 origin: OriginFor<T>,1255 collection_id: CollectionId,1256 item_id: TokenId,1257 ) -> DispatchResultWithPostInfo {1258 ensure_root(origin)?;1259 dispatch_tx::<T, _>(collection_id, |d| d.repair_item(item_id))1260 }1261 }12621263 impl<T: Config> Pallet<T> {1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 pub fn force_set_sponsor(1274 sponsor: T::AccountId,1275 collection_id: CollectionId,1276 ) -> DispatchResult {1277 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1278 target_collection.force_set_sponsor(sponsor.clone())1279 }12801281 1282 1283 1284 1285 1286 1287 1288 1289 pub fn force_remove_collection_sponsor(collection_id: CollectionId) -> DispatchResult {1290 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1291 target_collection.force_remove_sponsor()1292 }12931294 #[inline(always)]1295 pub(crate) fn destroy_collection_internal(1296 sender: T::CrossAccountId,1297 collection_id: CollectionId,1298 ) -> DispatchResult {1299 let collection = <CollectionHandle<T>>::try_get(collection_id)?;1300 collection.check_is_internal()?;13011302 T::CollectionDispatch::destroy(sender, collection)?;13031304 1305 13061307 let _ = <NftTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1308 let _ = <FungibleTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1309 let _ = <ReFungibleTransferBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);13101311 let _ = <NftApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1312 let _ = <FungibleApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1313 let _ = <RefungibleApproveBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);13141315 Ok(())1316 }1317 }1318}