git.delta.rocks / unique-network / refs/commits / fb1ebd6bb0f6

difftreelog

source

pallets/nft/src/sponsorship.rs5.9 KiBsourcehistory
1use crate::{2	Config, Call, CollectionById, CreateItemBasket, VariableMetaDataBasket,3	ReFungibleTransferBasket, FungibleTransferBasket, NftTransferBasket,4	CreateItemData, CollectionMode, limit,5};6use core::marker::PhantomData;7use up_sponsorship::SponsorshipHandler;8use frame_support::{9	traits::{IsSubType, Get},10	storage::{StorageMap, StorageDoubleMap},11};12use nft_data_structs::{TokenId, CollectionId};1314pub struct NftSponsorshipHandler<T>(PhantomData<T>);15impl<T: Config> NftSponsorshipHandler<T> {16	pub fn withdraw_create_item(17		who: &T::AccountId,18		collection_id: &CollectionId,19		_properties: &CreateItemData<T::ChainLimits>,20	) -> Option<T::AccountId> {21		let collection = CollectionById::<T>::get(collection_id)?;2223		// sponsor timeout24		let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;2526		let limit = collection.limits.sponsor_transfer_timeout;27		if CreateItemBasket::<T>::contains_key((collection_id, &who)) {28			let last_tx_block = CreateItemBasket::<T>::get((collection_id, &who));29			let limit_time = last_tx_block + limit.into();30			if block_number <= limit_time {31				return None;32			}33		}34		CreateItemBasket::<T>::insert((collection_id, who.clone()), block_number);3536		// check free create limit37		if collection.limits.sponsored_data_size >= (_properties.data_size() as u32) {38			collection.sponsorship.sponsor().cloned()39		} else {40			None41		}42	}4344	pub fn withdraw_transfer(45		who: &T::AccountId,46		collection_id: &CollectionId,47		item_id: &TokenId,48	) -> Option<T::AccountId> {49		let collection = CollectionById::<T>::get(collection_id)?;5051		let mut sponsor_transfer = false;52		if collection.sponsorship.confirmed() {53			let collection_limits = collection.limits.clone();54			let collection_mode = collection.mode.clone();5556			// sponsor timeout57			let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;58			sponsor_transfer = match collection_mode {59				CollectionMode::NFT => {60					// get correct limit61					let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {62						collection_limits.sponsor_transfer_timeout63					} else {64						<limit!(T, NftSponsorTransferTimeout)>::get()65					};6667					let mut sponsored = true;68					if NftTransferBasket::<T>::contains_key(collection_id, item_id) {69						let last_tx_block = NftTransferBasket::<T>::get(collection_id, item_id);70						let limit_time = last_tx_block + limit.into();71						if block_number <= limit_time {72							sponsored = false;73						}74					}75					if sponsored {76						NftTransferBasket::<T>::insert(collection_id, item_id, block_number);77					}7879					sponsored80				}81				CollectionMode::Fungible(_) => {82					// get correct limit83					let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {84						collection_limits.sponsor_transfer_timeout85					} else {86						<limit!(T, FungibleSponsorTransferTimeout)>::get()87					};8889					let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;90					let mut sponsored = true;91					if FungibleTransferBasket::<T>::contains_key(collection_id, who) {92						let last_tx_block = FungibleTransferBasket::<T>::get(collection_id, who);93						let limit_time = last_tx_block + limit.into();94						if block_number <= limit_time {95							sponsored = false;96						}97					}98					if sponsored {99						FungibleTransferBasket::<T>::insert(collection_id, who, block_number);100					}101102					sponsored103				}104				CollectionMode::ReFungible => {105					// get correct limit106					let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {107						collection_limits.sponsor_transfer_timeout108					} else {109						<limit!(T, ReFungibleSponsorTransferTimeout)>::get()110					};111112					let mut sponsored = true;113					if ReFungibleTransferBasket::<T>::contains_key(collection_id, item_id) {114						let last_tx_block =115							ReFungibleTransferBasket::<T>::get(collection_id, item_id);116						let limit_time = last_tx_block + limit.into();117						if block_number <= limit_time {118							sponsored = false;119						}120					}121					if sponsored {122						ReFungibleTransferBasket::<T>::insert(collection_id, item_id, block_number);123					}124125					sponsored126				}127				_ => false,128			};129		}130131		if !sponsor_transfer {132			None133		} else {134			collection.sponsorship.sponsor().cloned()135		}136	}137138	pub fn withdraw_set_variable_meta_data(139		collection_id: &CollectionId,140		item_id: &TokenId,141		data: &[u8],142	) -> Option<T::AccountId> {143		let mut sponsor_metadata_changes = false;144145		let collection = CollectionById::<T>::get(collection_id)?;146147		if collection.sponsorship.confirmed() &&148			// Can't sponsor fungible collection, this tx will be rejected149			// as invalid150			!matches!(collection.mode, CollectionMode::Fungible(_)) &&151			data.len() <= collection.limits.sponsored_data_size as usize152		{153			if let Some(rate_limit) = collection.limits.sponsored_data_rate_limit {154				let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;155156				if VariableMetaDataBasket::<T>::get(collection_id, item_id)157					.map(|last_block| block_number - last_block > rate_limit)158					.unwrap_or(true)159				{160					sponsor_metadata_changes = true;161					VariableMetaDataBasket::<T>::insert(collection_id, item_id, block_number);162				}163			}164		}165166		if !sponsor_metadata_changes {167			None168		} else {169			collection.sponsorship.sponsor().cloned()170		}171	}172}173174impl<T, C> SponsorshipHandler<T::AccountId, C> for NftSponsorshipHandler<T>175where176	T: Config,177	C: IsSubType<Call<T>>,178{179	fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {180		match IsSubType::<Call<T>>::is_sub_type(call)? {181			Call::create_item(collection_id, _owner, properties) => {182				Self::withdraw_create_item(who, collection_id, properties)183			}184			Call::transfer(_new_owner, collection_id, item_id, _value) => {185				Self::withdraw_transfer(who, collection_id, item_id)186			}187			Call::set_variable_meta_data(collection_id, item_id, data) => {188				Self::withdraw_set_variable_meta_data(collection_id, item_id, data)189			}190			_ => None,191		}192	}193}