git.delta.rocks / unique-network / refs/commits / 50b15345cfd5

difftreelog

source

pallets/nft/src/sponsorship.rs5.9 KiBsourcehistory
1use crate::{2	Config, Call, CollectionById, CreateItemBasket, VariableMetaDataBasket,3	ReFungibleTransferBasket, FungibleTransferBasket, NftTransferBasket, CreateItemData,4	CollectionMode,5};6use core::marker::PhantomData;7use up_sponsorship::SponsorshipHandler;8use frame_support::{9	traits::{IsSubType},10	storage::{StorageMap, StorageDoubleMap},11};12use nft_data_structs::{13	TokenId, CollectionId, NFT_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,14	FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,15};1617pub struct NftSponsorshipHandler<T>(PhantomData<T>);18impl<T: Config> NftSponsorshipHandler<T> {19	pub fn withdraw_create_item(20		who: &T::AccountId,21		collection_id: &CollectionId,22		_properties: &CreateItemData,23	) -> Option<T::AccountId> {24		let collection = CollectionById::<T>::get(collection_id)?;2526		// sponsor timeout27		let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;2829		let limit = collection.limits.sponsor_transfer_timeout;30		if CreateItemBasket::<T>::contains_key((collection_id, &who)) {31			let last_tx_block = CreateItemBasket::<T>::get((collection_id, &who));32			let limit_time = last_tx_block + limit.into();33			if block_number <= limit_time {34				return None;35			}36		}37		CreateItemBasket::<T>::insert((collection_id, who.clone()), block_number);3839		// check free create limit40		if collection.limits.sponsored_data_size >= (_properties.data_size() as u32) {41			collection.sponsorship.sponsor().cloned()42		} else {43			None44		}45	}4647	pub fn withdraw_transfer(48		who: &T::AccountId,49		collection_id: &CollectionId,50		item_id: &TokenId,51	) -> Option<T::AccountId> {52		let collection = CollectionById::<T>::get(collection_id)?;5354		let mut sponsor_transfer = false;55		if collection.sponsorship.confirmed() {56			let collection_limits = collection.limits.clone();57			let collection_mode = collection.mode.clone();5859			// sponsor timeout60			let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;61			sponsor_transfer = match collection_mode {62				CollectionMode::NFT => {63					// get correct limit64					let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {65						collection_limits.sponsor_transfer_timeout66					} else {67						NFT_SPONSOR_TRANSFER_TIMEOUT68					};6970					let mut sponsored = true;71					if NftTransferBasket::<T>::contains_key(collection_id, item_id) {72						let last_tx_block = NftTransferBasket::<T>::get(collection_id, item_id);73						let limit_time = last_tx_block + limit.into();74						if block_number <= limit_time {75							sponsored = false;76						}77					}78					if sponsored {79						NftTransferBasket::<T>::insert(collection_id, item_id, block_number);80					}8182					sponsored83				}84				CollectionMode::Fungible(_) => {85					// get correct limit86					let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {87						collection_limits.sponsor_transfer_timeout88					} else {89						FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT90					};9192					let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;93					let mut sponsored = true;94					if FungibleTransferBasket::<T>::contains_key(collection_id, who) {95						let last_tx_block = FungibleTransferBasket::<T>::get(collection_id, who);96						let limit_time = last_tx_block + limit.into();97						if block_number <= limit_time {98							sponsored = false;99						}100					}101					if sponsored {102						FungibleTransferBasket::<T>::insert(collection_id, who, block_number);103					}104105					sponsored106				}107				CollectionMode::ReFungible => {108					// get correct limit109					let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {110						collection_limits.sponsor_transfer_timeout111					} else {112						REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT113					};114115					let mut sponsored = true;116					if ReFungibleTransferBasket::<T>::contains_key(collection_id, item_id) {117						let last_tx_block =118							ReFungibleTransferBasket::<T>::get(collection_id, item_id);119						let limit_time = last_tx_block + limit.into();120						if block_number <= limit_time {121							sponsored = false;122						}123					}124					if sponsored {125						ReFungibleTransferBasket::<T>::insert(collection_id, item_id, block_number);126					}127128					sponsored129				}130			};131		}132133		if !sponsor_transfer {134			None135		} else {136			collection.sponsorship.sponsor().cloned()137		}138	}139140	pub fn withdraw_set_variable_meta_data(141		collection_id: &CollectionId,142		item_id: &TokenId,143		data: &[u8],144	) -> Option<T::AccountId> {145		let mut sponsor_metadata_changes = false;146147		let collection = CollectionById::<T>::get(collection_id)?;148149		if collection.sponsorship.confirmed() &&150			// Can't sponsor fungible collection, this tx will be rejected151			// as invalid152			!matches!(collection.mode, CollectionMode::Fungible(_)) &&153			data.len() <= collection.limits.sponsored_data_size as usize154		{155			if let Some(rate_limit) = collection.limits.sponsored_data_rate_limit {156				let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;157158				if VariableMetaDataBasket::<T>::get(collection_id, item_id)159					.map(|last_block| block_number - last_block > rate_limit)160					.unwrap_or(true)161				{162					sponsor_metadata_changes = true;163					VariableMetaDataBasket::<T>::insert(collection_id, item_id, block_number);164				}165			}166		}167168		if !sponsor_metadata_changes {169			None170		} else {171			collection.sponsorship.sponsor().cloned()172		}173	}174}175176impl<T, C> SponsorshipHandler<T::AccountId, C> for NftSponsorshipHandler<T>177where178	T: Config,179	C: IsSubType<Call<T>>,180{181	fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {182		match IsSubType::<Call<T>>::is_sub_type(call)? {183			Call::create_item(collection_id, _owner, properties) => {184				Self::withdraw_create_item(who, collection_id, properties)185			}186			Call::transfer(_new_owner, collection_id, item_id, _value) => {187				Self::withdraw_transfer(who, collection_id, item_id)188			}189			Call::set_variable_meta_data(collection_id, item_id, data) => {190				Self::withdraw_set_variable_meta_data(collection_id, item_id, data)191			}192			_ => None,193		}194	}195}