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

difftreelog

source

pallets/nft/src/sponsorship.rs5.9 KiBsourcehistory
1use crate::{2	Config, Call, CreateItemBasket, VariableMetaDataBasket, ReFungibleTransferBasket,3	FungibleTransferBasket, NftTransferBasket, CreateItemData, CollectionMode,4};5use core::marker::PhantomData;6use up_sponsorship::SponsorshipHandler;7use frame_support::{8	traits::{IsSubType},9	storage::{StorageMap, StorageDoubleMap},10};11use nft_data_structs::{12	TokenId, CollectionId, NFT_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,13	FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,14};15use pallet_common::{CollectionById};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 = collection30			.limits31			.sponsor_transfer_timeout(match _properties {32				CreateItemData::NFT(_) => NFT_SPONSOR_TRANSFER_TIMEOUT,33				CreateItemData::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,34				CreateItemData::ReFungible(_) => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,35			});36		if CreateItemBasket::<T>::contains_key((collection_id, &who)) {37			let last_tx_block = CreateItemBasket::<T>::get((collection_id, &who));38			let limit_time = last_tx_block + limit.into();39			if block_number <= limit_time {40				return None;41			}42		}43		CreateItemBasket::<T>::insert((collection_id, who.clone()), block_number);4445		// check free create limit46		if collection.limits.sponsored_data_size() >= (_properties.data_size() as u32) {47			collection.sponsorship.sponsor().cloned()48		} else {49			None50		}51	}5253	pub fn withdraw_transfer(54		who: &T::AccountId,55		collection_id: &CollectionId,56		item_id: &TokenId,57	) -> Option<T::AccountId> {58		let collection = CollectionById::<T>::get(collection_id)?;5960		let mut sponsor_transfer = false;61		if collection.sponsorship.confirmed() {62			let collection_limits = collection.limits.clone();63			let collection_mode = collection.mode.clone();6465			// sponsor timeout66			let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;67			sponsor_transfer = match collection_mode {68				CollectionMode::NFT => {69					// get correct limit70					let limit =71						collection_limits.sponsor_transfer_timeout(NFT_SPONSOR_TRANSFER_TIMEOUT);7273					let mut sponsored = true;74					if NftTransferBasket::<T>::contains_key(collection_id, item_id) {75						let last_tx_block = NftTransferBasket::<T>::get(collection_id, item_id);76						let limit_time = last_tx_block + limit.into();77						if block_number <= limit_time {78							sponsored = false;79						}80					}81					if sponsored {82						NftTransferBasket::<T>::insert(collection_id, item_id, block_number);83					}8485					sponsored86				}87				CollectionMode::Fungible(_) => {88					// get correct limit89					let limit = collection_limits90						.sponsor_transfer_timeout(FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT);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 = collection_limits110						.sponsor_transfer_timeout(REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT);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			};128		}129130		if !sponsor_transfer {131			None132		} else {133			collection.sponsorship.sponsor().cloned()134		}135	}136137	pub fn withdraw_set_variable_meta_data(138		collection_id: &CollectionId,139		item_id: &TokenId,140		data: &[u8],141	) -> Option<T::AccountId> {142		let mut sponsor_metadata_changes = false;143144		let collection = CollectionById::<T>::get(collection_id)?;145146		if collection.sponsorship.confirmed() &&147			// Can't sponsor fungible collection, this tx will be rejected148			// as invalid149			!matches!(collection.mode, CollectionMode::Fungible(_)) &&150			data.len() <= collection.limits.sponsored_data_size() as usize151		{152			if let Some(rate_limit) = collection.limits.sponsored_data_rate_limit() {153				let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;154155				if VariableMetaDataBasket::<T>::get(collection_id, item_id)156					.map(|last_block| block_number - last_block > rate_limit.into())157					.unwrap_or(true)158				{159					sponsor_metadata_changes = true;160					VariableMetaDataBasket::<T>::insert(collection_id, item_id, block_number);161				}162			}163		}164165		if !sponsor_metadata_changes {166			None167		} else {168			collection.sponsorship.sponsor().cloned()169		}170	}171}172173impl<T, C> SponsorshipHandler<T::AccountId, C> for NftSponsorshipHandler<T>174where175	T: Config,176	C: IsSubType<Call<T>>,177{178	fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {179		match IsSubType::<Call<T>>::is_sub_type(call)? {180			Call::create_item {181				collection_id,182				data,183				..184			} => Self::withdraw_create_item(who, collection_id, data),185			Call::transfer {186				collection_id,187				item_id,188				..189			} => Self::withdraw_transfer(who, collection_id, item_id),190			Call::set_variable_meta_data {191				collection_id,192				item_id,193				data,194			} => Self::withdraw_set_variable_meta_data(collection_id, item_id, data),195			_ => None,196		}197	}198}