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

difftreelog

source

pallets/nft/src/sponsorship.rs6.2 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						if collection_limits.sponsor_transfer_timeout > NFT_SPONSOR_TRANSFER_TIMEOUT66						{67							collection_limits.sponsor_transfer_timeout68						} else {69							NFT_SPONSOR_TRANSFER_TIMEOUT70						}71					} else {72						073					};7475					let mut sponsored = true;76					if NftTransferBasket::<T>::contains_key(collection_id, item_id) {77						let last_tx_block = NftTransferBasket::<T>::get(collection_id, item_id);78						let limit_time = last_tx_block + limit.into();79						if block_number <= limit_time {80							sponsored = false;81						}82					}83					if sponsored {84						NftTransferBasket::<T>::insert(collection_id, item_id, block_number);85					}8687					sponsored88				}89				CollectionMode::Fungible(_) => {90					// get correct limit91					let limit: u32 = if collection_limits.sponsor_transfer_timeout != 0 {92						if collection_limits.sponsor_transfer_timeout93							> FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT94						{95							collection_limits.sponsor_transfer_timeout96						} else {97							FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT98						}99					} else {100						0101					};102103					let mut sponsored = true;104					if FungibleTransferBasket::<T>::contains_key(collection_id, who) {105						let last_tx_block = FungibleTransferBasket::<T>::get(collection_id, who);106						let limit_time = last_tx_block + limit.into();107						if block_number <= limit_time {108							sponsored = false;109						}110					}111					if sponsored {112						FungibleTransferBasket::<T>::insert(collection_id, who, block_number);113					}114115					sponsored116				}117				CollectionMode::ReFungible => {118					// get correct limit119					let limit: u32 = if collection_limits.sponsor_transfer_timeout != 0 {120						if collection_limits.sponsor_transfer_timeout121							> REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT122						{123							collection_limits.sponsor_transfer_timeout124						} else {125							REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT126						}127					} else {128						0129					};130131					let mut sponsored = true;132					if ReFungibleTransferBasket::<T>::contains_key(collection_id, item_id) {133						let last_tx_block =134							ReFungibleTransferBasket::<T>::get(collection_id, item_id);135						let limit_time = last_tx_block + limit.into();136						if block_number <= limit_time {137							sponsored = false;138						}139					}140					if sponsored {141						ReFungibleTransferBasket::<T>::insert(collection_id, item_id, block_number);142					}143144					sponsored145				}146			};147		}148149		if !sponsor_transfer {150			None151		} else {152			collection.sponsorship.sponsor().cloned()153		}154	}155156	pub fn withdraw_set_variable_meta_data(157		collection_id: &CollectionId,158		item_id: &TokenId,159		data: &[u8],160	) -> Option<T::AccountId> {161		let mut sponsor_metadata_changes = false;162163		let collection = CollectionById::<T>::get(collection_id)?;164165		if collection.sponsorship.confirmed() &&166			// Can't sponsor fungible collection, this tx will be rejected167			// as invalid168			!matches!(collection.mode, CollectionMode::Fungible(_)) &&169			data.len() <= collection.limits.sponsored_data_size as usize170		{171			if let Some(rate_limit) = collection.limits.sponsored_data_rate_limit {172				let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;173174				if VariableMetaDataBasket::<T>::get(collection_id, item_id)175					.map(|last_block| block_number - last_block > rate_limit)176					.unwrap_or(true)177				{178					sponsor_metadata_changes = true;179					VariableMetaDataBasket::<T>::insert(collection_id, item_id, block_number);180				}181			}182		}183184		if !sponsor_metadata_changes {185			None186		} else {187			collection.sponsorship.sponsor().cloned()188		}189	}190}191192impl<T, C> SponsorshipHandler<T::AccountId, C> for NftSponsorshipHandler<T>193where194	T: Config,195	C: IsSubType<Call<T>>,196{197	fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {198		match IsSubType::<Call<T>>::is_sub_type(call)? {199			Call::create_item(collection_id, _owner, properties) => {200				Self::withdraw_create_item(who, collection_id, properties)201			}202			Call::transfer(_new_owner, collection_id, item_id, _value) => {203				Self::withdraw_transfer(who, collection_id, item_id)204			}205			Call::set_variable_meta_data(collection_id, item_id, data) => {206				Self::withdraw_set_variable_meta_data(collection_id, item_id, data)207			}208			_ => None,209		}210	}211}