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::{90 dispatch::DispatchResult,91 ensure, fail,92 BoundedVec,93 storage::Key,94 };95 use scale_info::TypeInfo;96 use frame_system::{ensure_signed, ensure_root};97 use sp_std::{vec, vec::Vec};98 use up_data_structs::{99 MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH,100 MAX_PROPERTIES_PER_ITEM, MAX_PROPERTY_KEY_LENGTH, MAX_PROPERTY_VALUE_LENGTH,101 MAX_COLLECTION_PROPERTIES_SIZE, COLLECTION_ADMINS_LIMIT, MAX_TOKEN_PROPERTIES_SIZE,102 CreateItemData, CollectionLimits, CollectionPermissions, CollectionId, CollectionMode,103 TokenId, CreateCollectionData, CreateItemExData, budget, Property, PropertyKey,104 PropertyKeyPermission,105 };106 use pallet_evm::account::CrossAccountId;107 use pallet_common::{108 CollectionHandle, Pallet as PalletCommon, CommonWeightInfo, dispatch::dispatch_tx,109 dispatch::CollectionDispatch, RefungibleExtensionsWeightInfo,110 };111 use weights::WeightInfo;112113 114 pub const NESTING_BUDGET: u32 = 5;115116 117 #[pallet::error]118 pub enum Error<T> {119 120 CollectionDecimalPointLimitExceeded,121 122 EmptyArgument,123 124 RepartitionCalledOnNonRefungibleCollection,125 }126127 128 #[pallet::config]129 pub trait Config: frame_system::Config + pallet_common::Config + Sized + TypeInfo {130 131 type WeightInfo: WeightInfo;132133 134 type CommonWeightInfo: CommonWeightInfo<Self::CrossAccountId>;135136 137 type RefungibleExtensionsWeightInfo: RefungibleExtensionsWeightInfo;138 }139140 #[pallet::pallet]141 pub struct Pallet<T>(_);142143 pub type SelfWeightOf<T> = <T as Config>::WeightInfo;144145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167168 169 170 #[pallet::storage]171 pub type ChainVersion<T> = StorageValue<_, u64, ValueQuery>;172 173174 175 176 177 #[pallet::storage]178 #[pallet::getter(fn create_item_busket)]179 pub type CreateItemBasket<T: Config> = StorageMap<180 Hasher = Blake2_128Concat,181 Key = (CollectionId, T::AccountId),182 Value = T::BlockNumber,183 QueryKind = OptionQuery,184 >;185 186 #[pallet::storage]187 #[pallet::getter(fn nft_transfer_basket)]188 pub type NftTransferBasket<T: Config> = StorageDoubleMap<189 Hasher1 = Blake2_128Concat,190 Key1 = CollectionId,191 Hasher2 = Blake2_128Concat,192 Key2 = TokenId,193 Value = T::BlockNumber,194 QueryKind = OptionQuery,195 >;196 197 #[pallet::storage]198 #[pallet::getter(fn fungible_transfer_basket)]199 pub type FungibleTransferBasket<T: Config> = StorageDoubleMap<200 Hasher1 = Blake2_128Concat,201 Key1 = CollectionId,202 Hasher2 = Twox64Concat,203 Key2 = T::AccountId,204 Value = T::BlockNumber,205 QueryKind = OptionQuery,206 >;207 208 #[pallet::storage]209 #[pallet::getter(fn refungible_transfer_basket)]210 pub type ReFungibleTransferBasket<T: Config> = StorageNMap<211 Key = (212 Key<Blake2_128Concat, CollectionId>,213 Key<Blake2_128Concat, TokenId>,214 Key<Twox64Concat, T::AccountId>,215 ),216 Value = T::BlockNumber,217 QueryKind = OptionQuery,218 >;219 220221 222 #[pallet::storage]223 #[pallet::getter(fn token_property_basket)]224 pub type TokenPropertyBasket<T: Config> = StorageDoubleMap<225 Hasher1 = Blake2_128Concat,226 Key1 = CollectionId,227 Hasher2 = Blake2_128Concat,228 Key2 = TokenId,229 Value = T::BlockNumber,230 QueryKind = OptionQuery,231 >;232233 234 #[pallet::storage]235 #[pallet::getter(fn nft_approve_basket)]236 pub type NftApproveBasket<T: Config> = StorageDoubleMap<237 Hasher1 = Blake2_128Concat,238 Key1 = CollectionId,239 Hasher2 = Blake2_128Concat,240 Key2 = TokenId,241 Value = T::BlockNumber,242 QueryKind = OptionQuery,243 >;244 245 #[pallet::storage]246 #[pallet::getter(fn fungible_approve_basket)]247 pub type FungibleApproveBasket<T: Config> = StorageDoubleMap<248 Hasher1 = Blake2_128Concat,249 Key1 = CollectionId,250 Hasher2 = Twox64Concat,251 Key2 = T::AccountId,252 Value = T::BlockNumber,253 QueryKind = OptionQuery,254 >;255 256 #[pallet::storage]257 #[pallet::getter(fn refungible_approve_basket)]258 pub type RefungibleApproveBasket<T: Config> = StorageNMap<259 Key = (260 Key<Blake2_128Concat, CollectionId>,261 Key<Blake2_128Concat, TokenId>,262 Key<Twox64Concat, T::AccountId>,263 ),264 Value = T::BlockNumber,265 QueryKind = OptionQuery,266 >;267268 #[pallet::extra_constants]269 impl<T: Config> Pallet<T> {270 271 fn nesting_budget() -> u32 {272 NESTING_BUDGET273 }274275 276 fn max_collection_name_length() -> u32 {277 MAX_COLLECTION_NAME_LENGTH278 }279280 281 fn max_collection_description_length() -> u32 {282 MAX_COLLECTION_DESCRIPTION_LENGTH283 }284285 286 fn max_token_prefix_length() -> u32 {287 MAX_TOKEN_PREFIX_LENGTH288 }289290 291 fn collection_admins_limit() -> u32 {292 COLLECTION_ADMINS_LIMIT293 }294295 296 fn max_property_key_length() -> u32 {297 MAX_PROPERTY_KEY_LENGTH298 }299300 301 fn max_property_value_length() -> u32 {302 MAX_PROPERTY_VALUE_LENGTH303 }304305 306 fn max_properties_per_item() -> u32 {307 MAX_PROPERTIES_PER_ITEM308 }309310 311 fn max_collection_properties_size() -> u32 {312 MAX_COLLECTION_PROPERTIES_SIZE313 }314315 316 fn max_token_properties_size() -> u32 {317 MAX_TOKEN_PROPERTIES_SIZE318 }319320 321 fn nft_default_collection_limits() -> CollectionLimits {322 CollectionLimits::with_default_limits(CollectionMode::NFT)323 }324325 326 fn rft_default_collection_limits() -> CollectionLimits {327 CollectionLimits::with_default_limits(CollectionMode::ReFungible)328 }329330 331 fn ft_default_collection_limits() -> CollectionLimits {332 CollectionLimits::with_default_limits(CollectionMode::Fungible(0))333 }334 }335336 337 #[pallet::call]338 impl<T: Config> Pallet<T> {339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 #[pallet::call_index(0)]365 #[pallet::weight(<SelfWeightOf<T>>::create_collection())]366 pub fn create_collection(367 origin: OriginFor<T>,368 collection_name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,369 collection_description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,370 token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,371 mode: CollectionMode,372 ) -> DispatchResult {373 let data: CreateCollectionData<T::AccountId> = CreateCollectionData {374 name: collection_name,375 description: collection_description,376 token_prefix,377 mode,378 ..Default::default()379 };380 Self::create_collection_ex(origin, data)381 }382383 384 385 386 387 388 389 390 391 392 393 394 #[pallet::call_index(1)]395 #[pallet::weight(<SelfWeightOf<T>>::create_collection())]396 pub fn create_collection_ex(397 origin: OriginFor<T>,398 data: CreateCollectionData<T::AccountId>,399 ) -> DispatchResult {400 let sender = ensure_signed(origin)?;401402 403 let sender = T::CrossAccountId::from_sub(sender);404 let _id =405 T::CollectionDispatch::create(sender.clone(), sender, data, Default::default())?;406407 Ok(())408 }409410 411 412 413 414 415 416 417 418 419 #[pallet::call_index(2)]420 #[pallet::weight(<SelfWeightOf<T>>::destroy_collection())]421 pub fn destroy_collection(422 origin: OriginFor<T>,423 collection_id: CollectionId,424 ) -> DispatchResult {425 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);426427 Self::destroy_collection_internal(sender, collection_id)428 }429430 431 432 433 434 435 436 437 438 439 440 441 #[pallet::call_index(3)]442 #[pallet::weight(<SelfWeightOf<T>>::add_to_allow_list())]443 pub fn add_to_allow_list(444 origin: OriginFor<T>,445 collection_id: CollectionId,446 address: T::CrossAccountId,447 ) -> DispatchResult {448 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);449 let collection = <CollectionHandle<T>>::try_get(collection_id)?;450 collection.check_is_internal()?;451452 <PalletCommon<T>>::toggle_allowlist(&collection, &sender, &address, true)?;453454 Ok(())455 }456457 458 459 460 461 462 463 464 465 466 467 468 #[pallet::call_index(4)]469 #[pallet::weight(<SelfWeightOf<T>>::remove_from_allow_list())]470 pub fn remove_from_allow_list(471 origin: OriginFor<T>,472 collection_id: CollectionId,473 address: T::CrossAccountId,474 ) -> DispatchResult {475 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);476 let collection = <CollectionHandle<T>>::try_get(collection_id)?;477 collection.check_is_internal()?;478479 <PalletCommon<T>>::toggle_allowlist(&collection, &sender, &address, false)?;480481 Ok(())482 }483484 485 486 487 488 489 490 491 492 493 494 #[pallet::call_index(5)]495 #[pallet::weight(<SelfWeightOf<T>>::change_collection_owner())]496 pub fn change_collection_owner(497 origin: OriginFor<T>,498 collection_id: CollectionId,499 new_owner: T::AccountId,500 ) -> DispatchResult {501 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);502 let new_owner = T::CrossAccountId::from_sub(new_owner);503 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;504 target_collection.change_owner(sender, new_owner.clone())505 }506507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 #[pallet::call_index(6)]524 #[pallet::weight(<SelfWeightOf<T>>::add_collection_admin())]525 pub fn add_collection_admin(526 origin: OriginFor<T>,527 collection_id: CollectionId,528 new_admin_id: T::CrossAccountId,529 ) -> DispatchResult {530 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);531 let collection = <CollectionHandle<T>>::try_get(collection_id)?;532 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)533 }534535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 #[pallet::call_index(7)]550 #[pallet::weight(<SelfWeightOf<T>>::remove_collection_admin())]551 pub fn remove_collection_admin(552 origin: OriginFor<T>,553 collection_id: CollectionId,554 account_id: T::CrossAccountId,555 ) -> DispatchResult {556 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);557 let collection = <CollectionHandle<T>>::try_get(collection_id)?;558 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)559 }560561 562 563 564 565 566 567 568 569 570 571 572 573 574 #[pallet::call_index(8)]575 #[pallet::weight(<SelfWeightOf<T>>::set_collection_sponsor())]576 pub fn set_collection_sponsor(577 origin: OriginFor<T>,578 collection_id: CollectionId,579 new_sponsor: T::AccountId,580 ) -> DispatchResult {581 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);582 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;583 target_collection.set_sponsor(&sender, new_sponsor.clone())584 }585586 587 588 589 590 591 592 593 594 595 596 597 598 599 #[pallet::call_index(9)]600 #[pallet::weight(<SelfWeightOf<T>>::confirm_sponsorship())]601 pub fn confirm_sponsorship(602 origin: OriginFor<T>,603 collection_id: CollectionId,604 ) -> DispatchResult {605 let sender = ensure_signed(origin)?;606 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;607 target_collection.confirm_sponsorship(&sender)608 }609610 611 612 613 614 615 616 617 618 619 #[pallet::call_index(10)]620 #[pallet::weight(<SelfWeightOf<T>>::remove_collection_sponsor())]621 pub fn remove_collection_sponsor(622 origin: OriginFor<T>,623 collection_id: CollectionId,624 ) -> DispatchResult {625 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);626 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;627 target_collection.remove_sponsor(&sender)628 }629630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 #[pallet::call_index(11)]649 #[pallet::weight(T::CommonWeightInfo::create_item(&data))]650 pub fn create_item(651 origin: OriginFor<T>,652 collection_id: CollectionId,653 owner: T::CrossAccountId,654 data: CreateItemData,655 ) -> DispatchResultWithPostInfo {656 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);657 let budget = budget::Value::new(NESTING_BUDGET);658659 dispatch_tx::<T, _>(collection_id, |d| {660 d.create_item(sender, owner, data, &budget)661 })662 }663664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 #[pallet::call_index(12)]683 #[pallet::weight(T::CommonWeightInfo::create_multiple_items(&items_data))]684 pub fn create_multiple_items(685 origin: OriginFor<T>,686 collection_id: CollectionId,687 owner: T::CrossAccountId,688 items_data: Vec<CreateItemData>,689 ) -> DispatchResultWithPostInfo {690 ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);691 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);692 let budget = budget::Value::new(NESTING_BUDGET);693694 dispatch_tx::<T, _>(collection_id, |d| {695 d.create_multiple_items(sender, owner, items_data, &budget)696 })697 }698699 700 701 702 703 704 705 706 707 708 709 710 711 #[pallet::call_index(13)]712 #[pallet::weight(T::CommonWeightInfo::set_collection_properties(properties.len() as u32))]713 pub fn set_collection_properties(714 origin: OriginFor<T>,715 collection_id: CollectionId,716 properties: Vec<Property>,717 ) -> DispatchResultWithPostInfo {718 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);719720 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);721722 dispatch_tx::<T, _>(collection_id, |d| {723 d.set_collection_properties(sender, properties)724 })725 }726727 728 729 730 731 732 733 734 735 736 737 738 739 #[pallet::call_index(14)]740 #[pallet::weight(T::CommonWeightInfo::delete_collection_properties(property_keys.len() as u32))]741 pub fn delete_collection_properties(742 origin: OriginFor<T>,743 collection_id: CollectionId,744 property_keys: Vec<PropertyKey>,745 ) -> DispatchResultWithPostInfo {746 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);747748 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);749750 dispatch_tx::<T, _>(collection_id, |d| {751 d.delete_collection_properties(&sender, property_keys)752 })753 }754755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 #[pallet::call_index(15)]774 #[pallet::weight(T::CommonWeightInfo::set_token_properties(properties.len() as u32))]775 pub fn set_token_properties(776 origin: OriginFor<T>,777 collection_id: CollectionId,778 token_id: TokenId,779 properties: Vec<Property>,780 ) -> DispatchResultWithPostInfo {781 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);782783 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);784 let budget = budget::Value::new(NESTING_BUDGET);785786 dispatch_tx::<T, _>(collection_id, |d| {787 d.set_token_properties(sender, token_id, properties, &budget)788 })789 }790791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 #[pallet::call_index(16)]807 #[pallet::weight(T::CommonWeightInfo::delete_token_properties(property_keys.len() as u32))]808 pub fn delete_token_properties(809 origin: OriginFor<T>,810 collection_id: CollectionId,811 token_id: TokenId,812 property_keys: Vec<PropertyKey>,813 ) -> DispatchResultWithPostInfo {814 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);815816 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);817 let budget = budget::Value::new(NESTING_BUDGET);818819 dispatch_tx::<T, _>(collection_id, |d| {820 d.delete_token_properties(sender, token_id, property_keys, &budget)821 })822 }823824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 #[pallet::call_index(17)]840 #[pallet::weight(T::CommonWeightInfo::set_token_property_permissions(property_permissions.len() as u32))]841 pub fn set_token_property_permissions(842 origin: OriginFor<T>,843 collection_id: CollectionId,844 property_permissions: Vec<PropertyKeyPermission>,845 ) -> DispatchResultWithPostInfo {846 ensure!(!property_permissions.is_empty(), Error::<T>::EmptyArgument);847848 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);849850 dispatch_tx::<T, _>(collection_id, |d| {851 d.set_token_property_permissions(&sender, property_permissions)852 })853 }854855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 #[pallet::call_index(18)]871 #[pallet::weight(T::CommonWeightInfo::create_multiple_items_ex(&data))]872 pub fn create_multiple_items_ex(873 origin: OriginFor<T>,874 collection_id: CollectionId,875 data: CreateItemExData<T::CrossAccountId>,876 ) -> DispatchResultWithPostInfo {877 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);878 let budget = budget::Value::new(NESTING_BUDGET);879880 dispatch_tx::<T, _>(collection_id, |d| {881 d.create_multiple_items_ex(sender, data, &budget)882 })883 }884885 886 887 888 889 890 891 892 893 894 895 #[pallet::call_index(19)]896 #[pallet::weight(<SelfWeightOf<T>>::set_transfers_enabled_flag())]897 pub fn set_transfers_enabled_flag(898 origin: OriginFor<T>,899 collection_id: CollectionId,900 value: bool,901 ) -> DispatchResult {902 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);903 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;904 target_collection.check_is_internal()?;905 target_collection.check_is_owner(&sender)?;906907 908909 target_collection.limits.transfers_enabled = Some(value);910 target_collection.save()911 }912913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 #[pallet::call_index(20)]930 #[pallet::weight(T::CommonWeightInfo::burn_item())]931 pub fn burn_item(932 origin: OriginFor<T>,933 collection_id: CollectionId,934 item_id: TokenId,935 value: u128,936 ) -> DispatchResultWithPostInfo {937 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);938939 let post_info =940 dispatch_tx::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;941 if value == 1 {942 <NftTransferBasket<T>>::remove(collection_id, item_id);943 <NftApproveBasket<T>>::remove(collection_id, item_id);944 }945 946 947 948 Ok(post_info)949 }950951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 #[pallet::call_index(21)]975 #[pallet::weight(T::CommonWeightInfo::burn_from())]976 pub fn burn_from(977 origin: OriginFor<T>,978 collection_id: CollectionId,979 from: T::CrossAccountId,980 item_id: TokenId,981 value: u128,982 ) -> DispatchResultWithPostInfo {983 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);984 let budget = budget::Value::new(NESTING_BUDGET);985986 dispatch_tx::<T, _>(collection_id, |d| {987 d.burn_from(sender, from, item_id, value, &budget)988 })989 }990991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 #[pallet::call_index(22)]1013 #[pallet::weight(T::CommonWeightInfo::transfer())]1014 pub fn transfer(1015 origin: OriginFor<T>,1016 recipient: T::CrossAccountId,1017 collection_id: CollectionId,1018 item_id: TokenId,1019 value: u128,1020 ) -> DispatchResultWithPostInfo {1021 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1022 let budget = budget::Value::new(NESTING_BUDGET);10231024 dispatch_tx::<T, _>(collection_id, |d| {1025 d.transfer(sender, recipient, item_id, value, &budget)1026 })1027 }10281029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 #[pallet::call_index(23)]1045 #[pallet::weight(T::CommonWeightInfo::approve())]1046 pub fn approve(1047 origin: OriginFor<T>,1048 spender: T::CrossAccountId,1049 collection_id: CollectionId,1050 item_id: TokenId,1051 amount: u128,1052 ) -> DispatchResultWithPostInfo {1053 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);10541055 dispatch_tx::<T, _>(collection_id, |d| {1056 d.approve(sender, spender, item_id, amount)1057 })1058 }10591060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 #[pallet::call_index(24)]1077 #[pallet::weight(T::CommonWeightInfo::approve_from())]1078 pub fn approve_from(1079 origin: OriginFor<T>,1080 from: T::CrossAccountId,1081 to: T::CrossAccountId,1082 collection_id: CollectionId,1083 item_id: TokenId,1084 amount: u128,1085 ) -> DispatchResultWithPostInfo {1086 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);10871088 dispatch_tx::<T, _>(collection_id, |d| {1089 d.approve_from(sender, from, to, item_id, amount)1090 })1091 }10921093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 #[pallet::call_index(25)]1118 #[pallet::weight(T::CommonWeightInfo::transfer_from())]1119 pub fn transfer_from(1120 origin: OriginFor<T>,1121 from: T::CrossAccountId,1122 recipient: T::CrossAccountId,1123 collection_id: CollectionId,1124 item_id: TokenId,1125 value: u128,1126 ) -> DispatchResultWithPostInfo {1127 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1128 let budget = budget::Value::new(NESTING_BUDGET);11291130 dispatch_tx::<T, _>(collection_id, |d| {1131 d.transfer_from(sender, from, recipient, item_id, value, &budget)1132 })1133 }11341135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 #[pallet::call_index(26)]1148 #[pallet::weight(<SelfWeightOf<T>>::set_collection_limits())]1149 pub fn set_collection_limits(1150 origin: OriginFor<T>,1151 collection_id: CollectionId,1152 new_limit: CollectionLimits,1153 ) -> DispatchResult {1154 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1155 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1156 <PalletCommon<T>>::update_limits(&sender, &mut target_collection, new_limit)1157 }11581159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 #[pallet::call_index(27)]1172 #[pallet::weight(<SelfWeightOf<T>>::set_collection_limits())]1173 pub fn set_collection_permissions(1174 origin: OriginFor<T>,1175 collection_id: CollectionId,1176 new_permission: CollectionPermissions,1177 ) -> DispatchResult {1178 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1179 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1180 <PalletCommon<T>>::update_permissions(&sender, &mut target_collection, new_permission)1181 }11821183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 #[pallet::call_index(28)]1195 #[pallet::weight(T::RefungibleExtensionsWeightInfo::repartition())]1196 pub fn repartition(1197 origin: OriginFor<T>,1198 collection_id: CollectionId,1199 token_id: TokenId,1200 amount: u128,1201 ) -> DispatchResultWithPostInfo {1202 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1203 dispatch_tx::<T, _>(collection_id, |d| {1204 if let Some(refungible_extensions) = d.refungible_extensions() {1205 refungible_extensions.repartition(&sender, token_id, amount)1206 } else {1207 fail!(<Error<T>>::RepartitionCalledOnNonRefungibleCollection)1208 }1209 })1210 }12111212 1213 1214 1215 1216 1217 1218 1219 1220 1221 #[pallet::call_index(29)]1222 #[pallet::weight(T::CommonWeightInfo::set_allowance_for_all())]1223 pub fn set_allowance_for_all(1224 origin: OriginFor<T>,1225 collection_id: CollectionId,1226 operator: T::CrossAccountId,1227 approve: bool,1228 ) -> DispatchResultWithPostInfo {1229 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1230 dispatch_tx::<T, _>(collection_id, |d| {1231 d.set_allowance_for_all(sender, operator, approve)1232 })1233 }12341235 1236 1237 1238 1239 1240 #[pallet::call_index(30)]1241 #[pallet::weight(<SelfWeightOf<T>>::force_repair_collection())]1242 pub fn force_repair_collection(1243 origin: OriginFor<T>,1244 collection_id: CollectionId,1245 ) -> DispatchResult {1246 ensure_root(origin)?;1247 <PalletCommon<T>>::repair_collection(collection_id)1248 }12491250 1251 1252 1253 1254 1255 1256 #[pallet::call_index(31)]1257 #[pallet::weight(T::CommonWeightInfo::force_repair_item())]1258 pub fn force_repair_item(1259 origin: OriginFor<T>,1260 collection_id: CollectionId,1261 item_id: TokenId,1262 ) -> DispatchResultWithPostInfo {1263 ensure_root(origin)?;1264 dispatch_tx::<T, _>(collection_id, |d| d.repair_item(item_id))1265 }1266 }12671268 impl<T: Config> Pallet<T> {1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 pub fn force_set_sponsor(1279 sponsor: T::AccountId,1280 collection_id: CollectionId,1281 ) -> DispatchResult {1282 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1283 target_collection.force_set_sponsor(sponsor.clone())1284 }12851286 1287 1288 1289 1290 1291 1292 1293 1294 pub fn force_remove_collection_sponsor(collection_id: CollectionId) -> DispatchResult {1295 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1296 target_collection.force_remove_sponsor()1297 }12981299 #[inline(always)]1300 pub(crate) fn destroy_collection_internal(1301 sender: T::CrossAccountId,1302 collection_id: CollectionId,1303 ) -> DispatchResult {1304 let collection = <CollectionHandle<T>>::try_get(collection_id)?;1305 collection.check_is_internal()?;13061307 T::CollectionDispatch::destroy(sender, collection)?;13081309 1310 13111312 let _ = <NftTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1313 let _ = <FungibleTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1314 let _ = <ReFungibleTransferBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);13151316 let _ = <NftApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1317 let _ = <FungibleApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);1318 let _ = <RefungibleApproveBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);13191320 Ok(())1321 }1322 }1323}