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::CrossAccountId> = 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::CrossAccountId>,394 ) -> DispatchResult {395 let sender = ensure_signed(origin)?;396397 398 let sender = T::CrossAccountId::from_sub(sender);399 let _id = T::CollectionDispatch::create(sender.clone(), sender, data)?;400401 Ok(())402 }403404 405 406 407 408 409 410 411 412 413 #[pallet::call_index(2)]414 #[pallet::weight(<SelfWeightOf<T>>::destroy_collection())]415 pub fn destroy_collection(416 origin: OriginFor<T>,417 collection_id: CollectionId,418 ) -> DispatchResult {419 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);420421 Self::destroy_collection_internal(sender, collection_id)422 }423424 425 426 427 428 429 430 431 432 433 434 435 #[pallet::call_index(3)]436 #[pallet::weight(<SelfWeightOf<T>>::add_to_allow_list())]437 pub fn add_to_allow_list(438 origin: OriginFor<T>,439 collection_id: CollectionId,440 address: T::CrossAccountId,441 ) -> DispatchResult {442 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {443 fail!(<pallet_common::Error<T>>::UnsupportedOperation);444 }445446 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);447 let collection = <CollectionHandle<T>>::try_get(collection_id)?;448 collection.check_is_internal()?;449450 <PalletCommon<T>>::toggle_allowlist(&collection, &sender, &address, true)?;451452 Ok(())453 }454455 456 457 458 459 460 461 462 463 464 465 466 #[pallet::call_index(4)]467 #[pallet::weight(<SelfWeightOf<T>>::remove_from_allow_list())]468 pub fn remove_from_allow_list(469 origin: OriginFor<T>,470 collection_id: CollectionId,471 address: T::CrossAccountId,472 ) -> DispatchResult {473 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {474 fail!(<pallet_common::Error<T>>::UnsupportedOperation);475 }476477 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);478 let collection = <CollectionHandle<T>>::try_get(collection_id)?;479 collection.check_is_internal()?;480481 <PalletCommon<T>>::toggle_allowlist(&collection, &sender, &address, false)?;482483 Ok(())484 }485486 487 488 489 490 491 492 493 494 495 496 #[pallet::call_index(5)]497 #[pallet::weight(<SelfWeightOf<T>>::change_collection_owner())]498 pub fn change_collection_owner(499 origin: OriginFor<T>,500 collection_id: CollectionId,501 new_owner: T::AccountId,502 ) -> DispatchResult {503 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {504 fail!(<pallet_common::Error<T>>::UnsupportedOperation);505 }506 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);507 let new_owner = T::CrossAccountId::from_sub(new_owner);508 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;509 target_collection.change_owner(sender, new_owner)510 }511512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 #[pallet::call_index(6)]529 #[pallet::weight(<SelfWeightOf<T>>::add_collection_admin())]530 pub fn add_collection_admin(531 origin: OriginFor<T>,532 collection_id: CollectionId,533 new_admin_id: T::CrossAccountId,534 ) -> DispatchResult {535 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {536 fail!(<pallet_common::Error<T>>::UnsupportedOperation);537 }538 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);539 let collection = <CollectionHandle<T>>::try_get(collection_id)?;540 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)541 }542543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 #[pallet::call_index(7)]558 #[pallet::weight(<SelfWeightOf<T>>::remove_collection_admin())]559 pub fn remove_collection_admin(560 origin: OriginFor<T>,561 collection_id: CollectionId,562 account_id: T::CrossAccountId,563 ) -> DispatchResult {564 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {565 fail!(<pallet_common::Error<T>>::UnsupportedOperation);566 }567 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);568 let collection = <CollectionHandle<T>>::try_get(collection_id)?;569 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)570 }571572 573 574 575 576 577 578 579 580 581 582 583 584 585 #[pallet::call_index(8)]586 #[pallet::weight(<SelfWeightOf<T>>::set_collection_sponsor())]587 pub fn set_collection_sponsor(588 origin: OriginFor<T>,589 collection_id: CollectionId,590 new_sponsor: T::AccountId,591 ) -> DispatchResult {592 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {593 fail!(<pallet_common::Error<T>>::UnsupportedOperation);594 }595 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);596 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;597 target_collection.set_sponsor(&sender, new_sponsor.clone())598 }599600 601 602 603 604 605 606 607 608 609 610 611 612 613 #[pallet::call_index(9)]614 #[pallet::weight(<SelfWeightOf<T>>::confirm_sponsorship())]615 pub fn confirm_sponsorship(616 origin: OriginFor<T>,617 collection_id: CollectionId,618 ) -> DispatchResult {619 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {620 fail!(<pallet_common::Error<T>>::UnsupportedOperation);621 }622 let sender = ensure_signed(origin)?;623 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;624 target_collection.confirm_sponsorship(&sender)625 }626627 628 629 630 631 632 633 634 635 636 #[pallet::call_index(10)]637 #[pallet::weight(<SelfWeightOf<T>>::remove_collection_sponsor())]638 pub fn remove_collection_sponsor(639 origin: OriginFor<T>,640 collection_id: CollectionId,641 ) -> DispatchResult {642 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {643 fail!(<pallet_common::Error<T>>::UnsupportedOperation);644 }645 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);646 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;647 target_collection.remove_sponsor(&sender)648 }649650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 #[pallet::call_index(11)]669 #[pallet::weight(T::CommonWeightInfo::create_item(data))]670 pub fn create_item(671 origin: OriginFor<T>,672 collection_id: CollectionId,673 owner: T::CrossAccountId,674 data: CreateItemData,675 ) -> DispatchResultWithPostInfo {676 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);677 let budget = budget::Value::new(NESTING_BUDGET);678679 dispatch_tx::<T, _>(collection_id, |d| {680 d.create_item(sender, owner, data, &budget)681 })682 }683684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 #[pallet::call_index(12)]703 #[pallet::weight(T::CommonWeightInfo::create_multiple_items(items_data))]704 pub fn create_multiple_items(705 origin: OriginFor<T>,706 collection_id: CollectionId,707 owner: T::CrossAccountId,708 items_data: Vec<CreateItemData>,709 ) -> DispatchResultWithPostInfo {710 ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);711 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);712 let budget = budget::Value::new(NESTING_BUDGET);713714 dispatch_tx::<T, _>(collection_id, |d| {715 d.create_multiple_items(sender, owner, items_data, &budget)716 })717 }718719 720 721 722 723 724 725 726 727 728 729 730 731 #[pallet::call_index(13)]732 #[pallet::weight(T::CommonWeightInfo::set_collection_properties(properties.len() as u32))]733 pub fn set_collection_properties(734 origin: OriginFor<T>,735 collection_id: CollectionId,736 properties: Vec<Property>,737 ) -> DispatchResultWithPostInfo {738 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);739740 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);741742 dispatch_tx::<T, _>(collection_id, |d| {743 d.set_collection_properties(sender, properties)744 })745 }746747 748 749 750 751 752 753 754 755 756 757 758 759 #[pallet::call_index(14)]760 #[pallet::weight(T::CommonWeightInfo::delete_collection_properties(property_keys.len() as u32))]761 pub fn delete_collection_properties(762 origin: OriginFor<T>,763 collection_id: CollectionId,764 property_keys: Vec<PropertyKey>,765 ) -> DispatchResultWithPostInfo {766 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);767768 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);769770 dispatch_tx::<T, _>(collection_id, |d| {771 d.delete_collection_properties(&sender, property_keys)772 })773 }774775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 #[pallet::call_index(15)]794 #[pallet::weight(T::CommonWeightInfo::set_token_properties(properties.len() as u32))]795 pub fn set_token_properties(796 origin: OriginFor<T>,797 collection_id: CollectionId,798 token_id: TokenId,799 properties: Vec<Property>,800 ) -> DispatchResultWithPostInfo {801 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);802803 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);804 let budget = budget::Value::new(NESTING_BUDGET);805806 dispatch_tx::<T, _>(collection_id, |d| {807 d.set_token_properties(sender, token_id, properties, &budget)808 })809 }810811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 #[pallet::call_index(16)]827 #[pallet::weight(T::CommonWeightInfo::delete_token_properties(property_keys.len() as u32))]828 pub fn delete_token_properties(829 origin: OriginFor<T>,830 collection_id: CollectionId,831 token_id: TokenId,832 property_keys: Vec<PropertyKey>,833 ) -> DispatchResultWithPostInfo {834 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);835836 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);837 let budget = budget::Value::new(NESTING_BUDGET);838839 dispatch_tx::<T, _>(collection_id, |d| {840 d.delete_token_properties(sender, token_id, property_keys, &budget)841 })842 }843844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 #[pallet::call_index(17)]860 #[pallet::weight(T::CommonWeightInfo::set_token_property_permissions(property_permissions.len() as u32))]861 pub fn set_token_property_permissions(862 origin: OriginFor<T>,863 collection_id: CollectionId,864 property_permissions: Vec<PropertyKeyPermission>,865 ) -> DispatchResultWithPostInfo {866 ensure!(!property_permissions.is_empty(), Error::<T>::EmptyArgument);867868 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);869870 dispatch_tx::<T, _>(collection_id, |d| {871 d.set_token_property_permissions(&sender, property_permissions)872 })873 }874875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 #[pallet::call_index(18)]891 #[pallet::weight(T::CommonWeightInfo::create_multiple_items_ex(data))]892 pub fn create_multiple_items_ex(893 origin: OriginFor<T>,894 collection_id: CollectionId,895 data: CreateItemExData<T::CrossAccountId>,896 ) -> DispatchResultWithPostInfo {897 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);898 let budget = budget::Value::new(NESTING_BUDGET);899900 dispatch_tx::<T, _>(collection_id, |d| {901 d.create_multiple_items_ex(sender, data, &budget)902 })903 }904905 906 907 908 909 910 911 912 913 914 915 #[pallet::call_index(19)]916 #[pallet::weight(<SelfWeightOf<T>>::set_transfers_enabled_flag())]917 pub fn set_transfers_enabled_flag(918 origin: OriginFor<T>,919 collection_id: CollectionId,920 value: bool,921 ) -> DispatchResult {922 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {923 fail!(<pallet_common::Error<T>>::UnsupportedOperation);924 }925 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);926 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;927 target_collection.check_is_internal()?;928 target_collection.check_is_owner(&sender)?;929930 931932 target_collection.limits.transfers_enabled = Some(value);933 target_collection.save()934 }935936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 #[pallet::call_index(20)]953 #[pallet::weight(T::CommonWeightInfo::burn_item())]954 pub fn burn_item(955 origin: OriginFor<T>,956 collection_id: CollectionId,957 item_id: TokenId,958 value: u128,959 ) -> DispatchResultWithPostInfo {960 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);961962 let post_info =963 dispatch_tx::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;964 if value == 1 {965 <NftTransferBasket<T>>::remove(collection_id, item_id);966 <NftApproveBasket<T>>::remove(collection_id, item_id);967 }968 969 970 971 Ok(post_info)972 }973974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 #[pallet::call_index(21)]998 #[pallet::weight(T::CommonWeightInfo::burn_from())]999 pub fn burn_from(1000 origin: OriginFor<T>,1001 collection_id: CollectionId,1002 from: T::CrossAccountId,1003 item_id: TokenId,1004 value: u128,1005 ) -> DispatchResultWithPostInfo {1006 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1007 let budget = budget::Value::new(NESTING_BUDGET);10081009 dispatch_tx::<T, _>(collection_id, |d| {1010 d.burn_from(sender, from, item_id, value, &budget)1011 })1012 }10131014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 #[pallet::call_index(22)]1036 #[pallet::weight(T::CommonWeightInfo::transfer())]1037 pub fn transfer(1038 origin: OriginFor<T>,1039 recipient: T::CrossAccountId,1040 collection_id: CollectionId,1041 item_id: TokenId,1042 value: u128,1043 ) -> DispatchResultWithPostInfo {1044 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1045 let budget = budget::Value::new(NESTING_BUDGET);10461047 dispatch_tx::<T, _>(collection_id, |d| {1048 d.transfer(sender, recipient, item_id, value, &budget)1049 })1050 }10511052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 #[pallet::call_index(23)]1068 #[pallet::weight(T::CommonWeightInfo::approve())]1069 pub fn approve(1070 origin: OriginFor<T>,1071 spender: T::CrossAccountId,1072 collection_id: CollectionId,1073 item_id: TokenId,1074 amount: u128,1075 ) -> DispatchResultWithPostInfo {1076 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);10771078 dispatch_tx::<T, _>(collection_id, |d| {1079 d.approve(sender, spender, item_id, amount)1080 })1081 }10821083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 #[pallet::call_index(24)]1100 #[pallet::weight(T::CommonWeightInfo::approve_from())]1101 pub fn approve_from(1102 origin: OriginFor<T>,1103 from: T::CrossAccountId,1104 to: T::CrossAccountId,1105 collection_id: CollectionId,1106 item_id: TokenId,1107 amount: u128,1108 ) -> DispatchResultWithPostInfo {1109 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);11101111 dispatch_tx::<T, _>(collection_id, |d| {1112 d.approve_from(sender, from, to, item_id, amount)1113 })1114 }11151116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 #[pallet::call_index(25)]1141 #[pallet::weight(T::CommonWeightInfo::transfer_from())]1142 pub fn transfer_from(1143 origin: OriginFor<T>,1144 from: T::CrossAccountId,1145 recipient: T::CrossAccountId,1146 collection_id: CollectionId,1147 item_id: TokenId,1148 value: u128,1149 ) -> DispatchResultWithPostInfo {1150 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1151 let budget = budget::Value::new(NESTING_BUDGET);11521153 dispatch_tx::<T, _>(collection_id, |d| {1154 d.transfer_from(sender, from, recipient, item_id, value, &budget)1155 })1156 }11571158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 #[pallet::call_index(26)]1171 #[pallet::weight(<SelfWeightOf<T>>::set_collection_limits())]1172 pub fn set_collection_limits(1173 origin: OriginFor<T>,1174 collection_id: CollectionId,1175 new_limit: CollectionLimits,1176 ) -> DispatchResult {1177 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {1178 fail!(<pallet_common::Error<T>>::UnsupportedOperation);1179 }1180 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1181 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1182 <PalletCommon<T>>::update_limits(&sender, &mut target_collection, new_limit)1183 }11841185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 #[pallet::call_index(27)]1198 #[pallet::weight(<SelfWeightOf<T>>::set_collection_limits())]1199 pub fn set_collection_permissions(1200 origin: OriginFor<T>,1201 collection_id: CollectionId,1202 new_permission: CollectionPermissions,1203 ) -> DispatchResult {1204 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {1205 fail!(<pallet_common::Error<T>>::UnsupportedOperation);1206 }1207 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1208 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1209 <PalletCommon<T>>::update_permissions(&sender, &mut target_collection, new_permission)1210 }12111212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 #[pallet::call_index(28)]1224 #[pallet::weight(T::RefungibleExtensionsWeightInfo::repartition())]1225 pub fn repartition(1226 origin: OriginFor<T>,1227 collection_id: CollectionId,1228 token_id: TokenId,1229 amount: u128,1230 ) -> DispatchResultWithPostInfo {1231 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1232 dispatch_tx::<T, _>(collection_id, |d| {1233 if let Some(refungible_extensions) = d.refungible_extensions() {1234 refungible_extensions.repartition(&sender, token_id, amount)1235 } else {1236 fail!(<Error<T>>::RepartitionCalledOnNonRefungibleCollection)1237 }1238 })1239 }12401241 1242 1243 1244 1245 1246 1247 1248 1249 1250 #[pallet::call_index(29)]1251 #[pallet::weight(T::CommonWeightInfo::set_allowance_for_all())]1252 pub fn set_allowance_for_all(1253 origin: OriginFor<T>,1254 collection_id: CollectionId,1255 operator: T::CrossAccountId,1256 approve: bool,1257 ) -> DispatchResultWithPostInfo {1258 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1259 dispatch_tx::<T, _>(collection_id, |d| {1260 d.set_allowance_for_all(sender, operator, approve)1261 })1262 }12631264 1265 1266 1267 1268 1269 #[pallet::call_index(30)]1270 #[pallet::weight(<SelfWeightOf<T>>::force_repair_collection())]1271 pub fn force_repair_collection(1272 origin: OriginFor<T>,1273 collection_id: CollectionId,1274 ) -> DispatchResult {1275 if collection_id == pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID {1276 fail!(<pallet_common::Error<T>>::UnsupportedOperation);1277 }1278 ensure_root(origin)?;1279 <PalletCommon<T>>::repair_collection(collection_id)1280 }12811282 1283 1284 1285 1286 1287 1288 #[pallet::call_index(31)]1289 #[pallet::weight(T::CommonWeightInfo::force_repair_item())]1290 pub fn force_repair_item(1291 origin: OriginFor<T>,1292 collection_id: CollectionId,1293 item_id: TokenId,1294 ) -> DispatchResultWithPostInfo {1295 ensure_root(origin)?;1296 dispatch_tx::<T, _>(collection_id, |d| d.repair_item(item_id))1297 }1298 }12991300 impl<T: Config> Pallet<T> {1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 pub fn force_set_sponsor(1311 sponsor: T::AccountId,1312 collection_id: CollectionId,1313 ) -> DispatchResult {1314 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1315 target_collection.force_set_sponsor(sponsor)1316 }13171318 1319 1320 1321 1322 1323 1324 1325 1326 pub fn force_remove_collection_sponsor(collection_id: CollectionId) -> DispatchResult {1327 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1328 target_collection.force_remove_sponsor()1329 }13301331 #[inline(always)]1332 pub(crate) fn destroy_collection_internal(1333 sender: T::CrossAccountId,1334 collection_id: CollectionId,1335 ) -> DispatchResult {1336 T::CollectionDispatch::destroy(sender, collection_id)?;13371338 1339 13401341 let _ = <NftTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1342 let _ = <FungibleTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1343 let _ = <ReFungibleTransferBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);13441345 let _ = <NftApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1346 let _ = <FungibleApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1347 let _ = <RefungibleApproveBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);13481349 Ok(())1350 }1351 }1352}