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 if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {444 fail!(<pallet_common::Error<T>>::UnsupportedOperation);445 }446447 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);448 let collection = <CollectionHandle<T>>::try_get(collection_id)?;449 collection.check_is_internal()?;450451 <PalletCommon<T>>::toggle_allowlist(&collection, &sender, &address, true)?;452453 Ok(())454 }455456 457 458 459 460 461 462 463 464 465 466 467 #[pallet::call_index(4)]468 #[pallet::weight(<SelfWeightOf<T>>::remove_from_allow_list())]469 pub fn remove_from_allow_list(470 origin: OriginFor<T>,471 collection_id: CollectionId,472 address: T::CrossAccountId,473 ) -> DispatchResult {474 if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {475 fail!(<pallet_common::Error<T>>::UnsupportedOperation);476 }477478 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);479 let collection = <CollectionHandle<T>>::try_get(collection_id)?;480 collection.check_is_internal()?;481482 <PalletCommon<T>>::toggle_allowlist(&collection, &sender, &address, false)?;483484 Ok(())485 }486487 488 489 490 491 492 493 494 495 496 497 #[pallet::call_index(5)]498 #[pallet::weight(<SelfWeightOf<T>>::change_collection_owner())]499 pub fn change_collection_owner(500 origin: OriginFor<T>,501 collection_id: CollectionId,502 new_owner: T::AccountId,503 ) -> DispatchResult {504 if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {505 fail!(<pallet_common::Error<T>>::UnsupportedOperation);506 }507 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);508 let new_owner = T::CrossAccountId::from_sub(new_owner);509 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;510 target_collection.change_owner(sender, new_owner.clone())511 }512513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 #[pallet::call_index(6)]530 #[pallet::weight(<SelfWeightOf<T>>::add_collection_admin())]531 pub fn add_collection_admin(532 origin: OriginFor<T>,533 collection_id: CollectionId,534 new_admin_id: T::CrossAccountId,535 ) -> DispatchResult {536 if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {537 fail!(<pallet_common::Error<T>>::UnsupportedOperation);538 }539 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);540 let collection = <CollectionHandle<T>>::try_get(collection_id)?;541 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)542 }543544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 #[pallet::call_index(7)]559 #[pallet::weight(<SelfWeightOf<T>>::remove_collection_admin())]560 pub fn remove_collection_admin(561 origin: OriginFor<T>,562 collection_id: CollectionId,563 account_id: T::CrossAccountId,564 ) -> DispatchResult {565 if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {566 fail!(<pallet_common::Error<T>>::UnsupportedOperation);567 }568 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);569 let collection = <CollectionHandle<T>>::try_get(collection_id)?;570 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)571 }572573 574 575 576 577 578 579 580 581 582 583 584 585 586 #[pallet::call_index(8)]587 #[pallet::weight(<SelfWeightOf<T>>::set_collection_sponsor())]588 pub fn set_collection_sponsor(589 origin: OriginFor<T>,590 collection_id: CollectionId,591 new_sponsor: T::AccountId,592 ) -> DispatchResult {593 if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {594 fail!(<pallet_common::Error<T>>::UnsupportedOperation);595 }596 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);597 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;598 target_collection.set_sponsor(&sender, new_sponsor.clone())599 }600601 602 603 604 605 606 607 608 609 610 611 612 613 614 #[pallet::call_index(9)]615 #[pallet::weight(<SelfWeightOf<T>>::confirm_sponsorship())]616 pub fn confirm_sponsorship(617 origin: OriginFor<T>,618 collection_id: CollectionId,619 ) -> DispatchResult {620 if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {621 fail!(<pallet_common::Error<T>>::UnsupportedOperation);622 }623 let sender = ensure_signed(origin)?;624 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;625 target_collection.confirm_sponsorship(&sender)626 }627628 629 630 631 632 633 634 635 636 637 #[pallet::call_index(10)]638 #[pallet::weight(<SelfWeightOf<T>>::remove_collection_sponsor())]639 pub fn remove_collection_sponsor(640 origin: OriginFor<T>,641 collection_id: CollectionId,642 ) -> DispatchResult {643 if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {644 fail!(<pallet_common::Error<T>>::UnsupportedOperation);645 }646 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);647 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;648 target_collection.remove_sponsor(&sender)649 }650651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 #[pallet::call_index(11)]670 #[pallet::weight(T::CommonWeightInfo::create_item(&data))]671 pub fn create_item(672 origin: OriginFor<T>,673 collection_id: CollectionId,674 owner: T::CrossAccountId,675 data: CreateItemData,676 ) -> DispatchResultWithPostInfo {677 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);678 let budget = budget::Value::new(NESTING_BUDGET);679680 dispatch_tx::<T, _>(collection_id, |d| {681 d.create_item(sender, owner, data, &budget)682 })683 }684685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 #[pallet::call_index(12)]704 #[pallet::weight(T::CommonWeightInfo::create_multiple_items(&items_data))]705 pub fn create_multiple_items(706 origin: OriginFor<T>,707 collection_id: CollectionId,708 owner: T::CrossAccountId,709 items_data: Vec<CreateItemData>,710 ) -> DispatchResultWithPostInfo {711 ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);712 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);713 let budget = budget::Value::new(NESTING_BUDGET);714715 dispatch_tx::<T, _>(collection_id, |d| {716 d.create_multiple_items(sender, owner, items_data, &budget)717 })718 }719720 721 722 723 724 725 726 727 728 729 730 731 732 #[pallet::call_index(13)]733 #[pallet::weight(T::CommonWeightInfo::set_collection_properties(properties.len() as u32))]734 pub fn set_collection_properties(735 origin: OriginFor<T>,736 collection_id: CollectionId,737 properties: Vec<Property>,738 ) -> DispatchResultWithPostInfo {739 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);740741 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);742743 dispatch_tx::<T, _>(collection_id, |d| {744 d.set_collection_properties(sender, properties)745 })746 }747748 749 750 751 752 753 754 755 756 757 758 759 760 #[pallet::call_index(14)]761 #[pallet::weight(T::CommonWeightInfo::delete_collection_properties(property_keys.len() as u32))]762 pub fn delete_collection_properties(763 origin: OriginFor<T>,764 collection_id: CollectionId,765 property_keys: Vec<PropertyKey>,766 ) -> DispatchResultWithPostInfo {767 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);768769 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);770771 dispatch_tx::<T, _>(collection_id, |d| {772 d.delete_collection_properties(&sender, property_keys)773 })774 }775776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 #[pallet::call_index(15)]795 #[pallet::weight(T::CommonWeightInfo::set_token_properties(properties.len() as u32))]796 pub fn set_token_properties(797 origin: OriginFor<T>,798 collection_id: CollectionId,799 token_id: TokenId,800 properties: Vec<Property>,801 ) -> DispatchResultWithPostInfo {802 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);803804 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);805 let budget = budget::Value::new(NESTING_BUDGET);806807 dispatch_tx::<T, _>(collection_id, |d| {808 d.set_token_properties(sender, token_id, properties, &budget)809 })810 }811812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 #[pallet::call_index(16)]828 #[pallet::weight(T::CommonWeightInfo::delete_token_properties(property_keys.len() as u32))]829 pub fn delete_token_properties(830 origin: OriginFor<T>,831 collection_id: CollectionId,832 token_id: TokenId,833 property_keys: Vec<PropertyKey>,834 ) -> DispatchResultWithPostInfo {835 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);836837 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);838 let budget = budget::Value::new(NESTING_BUDGET);839840 dispatch_tx::<T, _>(collection_id, |d| {841 d.delete_token_properties(sender, token_id, property_keys, &budget)842 })843 }844845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 #[pallet::call_index(17)]861 #[pallet::weight(T::CommonWeightInfo::set_token_property_permissions(property_permissions.len() as u32))]862 pub fn set_token_property_permissions(863 origin: OriginFor<T>,864 collection_id: CollectionId,865 property_permissions: Vec<PropertyKeyPermission>,866 ) -> DispatchResultWithPostInfo {867 ensure!(!property_permissions.is_empty(), Error::<T>::EmptyArgument);868869 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);870871 dispatch_tx::<T, _>(collection_id, |d| {872 d.set_token_property_permissions(&sender, property_permissions)873 })874 }875876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 #[pallet::call_index(18)]892 #[pallet::weight(T::CommonWeightInfo::create_multiple_items_ex(&data))]893 pub fn create_multiple_items_ex(894 origin: OriginFor<T>,895 collection_id: CollectionId,896 data: CreateItemExData<T::CrossAccountId>,897 ) -> DispatchResultWithPostInfo {898 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);899 let budget = budget::Value::new(NESTING_BUDGET);900901 dispatch_tx::<T, _>(collection_id, |d| {902 d.create_multiple_items_ex(sender, data, &budget)903 })904 }905906 907 908 909 910 911 912 913 914 915 916 #[pallet::call_index(19)]917 #[pallet::weight(<SelfWeightOf<T>>::set_transfers_enabled_flag())]918 pub fn set_transfers_enabled_flag(919 origin: OriginFor<T>,920 collection_id: CollectionId,921 value: bool,922 ) -> DispatchResult {923 if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {924 fail!(<pallet_common::Error<T>>::UnsupportedOperation);925 }926 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);927 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;928 target_collection.check_is_internal()?;929 target_collection.check_is_owner(&sender)?;930931 932933 target_collection.limits.transfers_enabled = Some(value);934 target_collection.save()935 }936937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 #[pallet::call_index(20)]954 #[pallet::weight(T::CommonWeightInfo::burn_item())]955 pub fn burn_item(956 origin: OriginFor<T>,957 collection_id: CollectionId,958 item_id: TokenId,959 value: u128,960 ) -> DispatchResultWithPostInfo {961 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);962963 let post_info =964 dispatch_tx::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;965 if value == 1 {966 <NftTransferBasket<T>>::remove(collection_id, item_id);967 <NftApproveBasket<T>>::remove(collection_id, item_id);968 }969 970 971 972 Ok(post_info)973 }974975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 #[pallet::call_index(21)]999 #[pallet::weight(T::CommonWeightInfo::burn_from())]1000 pub fn burn_from(1001 origin: OriginFor<T>,1002 collection_id: CollectionId,1003 from: T::CrossAccountId,1004 item_id: TokenId,1005 value: u128,1006 ) -> DispatchResultWithPostInfo {1007 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1008 let budget = budget::Value::new(NESTING_BUDGET);10091010 dispatch_tx::<T, _>(collection_id, |d| {1011 d.burn_from(sender, from, item_id, value, &budget)1012 })1013 }10141015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 #[pallet::call_index(22)]1037 #[pallet::weight(T::CommonWeightInfo::transfer())]1038 pub fn transfer(1039 origin: OriginFor<T>,1040 recipient: T::CrossAccountId,1041 collection_id: CollectionId,1042 item_id: TokenId,1043 value: u128,1044 ) -> DispatchResultWithPostInfo {1045 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1046 let budget = budget::Value::new(NESTING_BUDGET);10471048 dispatch_tx::<T, _>(collection_id, |d| {1049 d.transfer(sender, recipient, item_id, value, &budget)1050 })1051 }10521053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 #[pallet::call_index(23)]1069 #[pallet::weight(T::CommonWeightInfo::approve())]1070 pub fn approve(1071 origin: OriginFor<T>,1072 spender: T::CrossAccountId,1073 collection_id: CollectionId,1074 item_id: TokenId,1075 amount: u128,1076 ) -> DispatchResultWithPostInfo {1077 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);10781079 dispatch_tx::<T, _>(collection_id, |d| {1080 d.approve(sender, spender, item_id, amount)1081 })1082 }10831084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 #[pallet::call_index(24)]1101 #[pallet::weight(T::CommonWeightInfo::approve_from())]1102 pub fn approve_from(1103 origin: OriginFor<T>,1104 from: T::CrossAccountId,1105 to: T::CrossAccountId,1106 collection_id: CollectionId,1107 item_id: TokenId,1108 amount: u128,1109 ) -> DispatchResultWithPostInfo {1110 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);11111112 dispatch_tx::<T, _>(collection_id, |d| {1113 d.approve_from(sender, from, to, item_id, amount)1114 })1115 }11161117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 #[pallet::call_index(25)]1142 #[pallet::weight(T::CommonWeightInfo::transfer_from())]1143 pub fn transfer_from(1144 origin: OriginFor<T>,1145 from: T::CrossAccountId,1146 recipient: T::CrossAccountId,1147 collection_id: CollectionId,1148 item_id: TokenId,1149 value: u128,1150 ) -> DispatchResultWithPostInfo {1151 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1152 let budget = budget::Value::new(NESTING_BUDGET);11531154 dispatch_tx::<T, _>(collection_id, |d| {1155 d.transfer_from(sender, from, recipient, item_id, value, &budget)1156 })1157 }11581159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 #[pallet::call_index(26)]1172 #[pallet::weight(<SelfWeightOf<T>>::set_collection_limits())]1173 pub fn set_collection_limits(1174 origin: OriginFor<T>,1175 collection_id: CollectionId,1176 new_limit: CollectionLimits,1177 ) -> DispatchResult {1178 if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {1179 fail!(<pallet_common::Error<T>>::UnsupportedOperation);1180 }1181 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1182 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1183 <PalletCommon<T>>::update_limits(&sender, &mut target_collection, new_limit)1184 }11851186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 #[pallet::call_index(27)]1199 #[pallet::weight(<SelfWeightOf<T>>::set_collection_limits())]1200 pub fn set_collection_permissions(1201 origin: OriginFor<T>,1202 collection_id: CollectionId,1203 new_permission: CollectionPermissions,1204 ) -> DispatchResult {1205 if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {1206 fail!(<pallet_common::Error<T>>::UnsupportedOperation);1207 }1208 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1209 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1210 <PalletCommon<T>>::update_permissions(&sender, &mut target_collection, new_permission)1211 }12121213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 #[pallet::call_index(28)]1225 #[pallet::weight(T::RefungibleExtensionsWeightInfo::repartition())]1226 pub fn repartition(1227 origin: OriginFor<T>,1228 collection_id: CollectionId,1229 token_id: TokenId,1230 amount: u128,1231 ) -> DispatchResultWithPostInfo {1232 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1233 dispatch_tx::<T, _>(collection_id, |d| {1234 if let Some(refungible_extensions) = d.refungible_extensions() {1235 refungible_extensions.repartition(&sender, token_id, amount)1236 } else {1237 fail!(<Error<T>>::RepartitionCalledOnNonRefungibleCollection)1238 }1239 })1240 }12411242 1243 1244 1245 1246 1247 1248 1249 1250 1251 #[pallet::call_index(29)]1252 #[pallet::weight(T::CommonWeightInfo::set_allowance_for_all())]1253 pub fn set_allowance_for_all(1254 origin: OriginFor<T>,1255 collection_id: CollectionId,1256 operator: T::CrossAccountId,1257 approve: bool,1258 ) -> DispatchResultWithPostInfo {1259 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1260 dispatch_tx::<T, _>(collection_id, |d| {1261 d.set_allowance_for_all(sender, operator, approve)1262 })1263 }12641265 1266 1267 1268 1269 1270 #[pallet::call_index(30)]1271 #[pallet::weight(<SelfWeightOf<T>>::force_repair_collection())]1272 pub fn force_repair_collection(1273 origin: OriginFor<T>,1274 collection_id: CollectionId,1275 ) -> DispatchResult {1276 if collection_id == pallet_common::NATIVE_FINGIBLE_COLLECTION_ID {1277 fail!(<pallet_common::Error<T>>::UnsupportedOperation);1278 }1279 ensure_root(origin)?;1280 <PalletCommon<T>>::repair_collection(collection_id)1281 }12821283 1284 1285 1286 1287 1288 1289 #[pallet::call_index(31)]1290 #[pallet::weight(T::CommonWeightInfo::force_repair_item())]1291 pub fn force_repair_item(1292 origin: OriginFor<T>,1293 collection_id: CollectionId,1294 item_id: TokenId,1295 ) -> DispatchResultWithPostInfo {1296 ensure_root(origin)?;1297 dispatch_tx::<T, _>(collection_id, |d| d.repair_item(item_id))1298 }1299 }13001301 impl<T: Config> Pallet<T> {1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 pub fn force_set_sponsor(1312 sponsor: T::AccountId,1313 collection_id: CollectionId,1314 ) -> DispatchResult {1315 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1316 target_collection.force_set_sponsor(sponsor.clone())1317 }13181319 1320 1321 1322 1323 1324 1325 1326 1327 pub fn force_remove_collection_sponsor(collection_id: CollectionId) -> DispatchResult {1328 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1329 target_collection.force_remove_sponsor()1330 }13311332 #[inline(always)]1333 pub(crate) fn destroy_collection_internal(1334 sender: T::CrossAccountId,1335 collection_id: CollectionId,1336 ) -> DispatchResult {1337 T::CollectionDispatch::destroy(sender, collection_id)?;13381339 1340 13411342 let _ = <NftTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1343 let _ = <FungibleTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1344 let _ = <ReFungibleTransferBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);13451346 let _ = <NftApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1347 let _ = <FungibleApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1348 let _ = <RefungibleApproveBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);13491350 Ok(())1351 }1352 }1353}