git.delta.rocks / unique-network / refs/commits / 18f1623e4e86

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				_ => false,147			};148		}149150		if !sponsor_transfer {151			None152		} else {153			collection.sponsorship.sponsor().cloned()154		}155	}156157	pub fn withdraw_set_variable_meta_data(158		collection_id: &CollectionId,159		item_id: &TokenId,160		data: &[u8],161	) -> Option<T::AccountId> {162		let mut sponsor_metadata_changes = false;163164		let collection = CollectionById::<T>::get(collection_id)?;165166		if collection.sponsorship.confirmed() &&167			// Can't sponsor fungible collection, this tx will be rejected168			// as invalid169			!matches!(collection.mode, CollectionMode::Fungible(_)) &&170			data.len() <= collection.limits.sponsored_data_size as usize171		{172			if let Some(rate_limit) = collection.limits.sponsored_data_rate_limit {173				let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;174175				if VariableMetaDataBasket::<T>::get(collection_id, item_id)176					.map(|last_block| block_number - last_block > rate_limit)177					.unwrap_or(true)178				{179					sponsor_metadata_changes = true;180					VariableMetaDataBasket::<T>::insert(collection_id, item_id, block_number);181				}182			}183		}184185		if !sponsor_metadata_changes {186			None187		} else {188			collection.sponsorship.sponsor().cloned()189		}190	}191}192193impl<T, C> SponsorshipHandler<T::AccountId, C> for NftSponsorshipHandler<T>194where195	T: Config,196	C: IsSubType<Call<T>>,197{198	fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {199		match IsSubType::<Call<T>>::is_sub_type(call)? {200			Call::create_item(collection_id, _owner, properties) => {201				Self::withdraw_create_item(who, collection_id, properties)202			}203			Call::transfer(_new_owner, collection_id, item_id, _value) => {204				Self::withdraw_transfer(who, collection_id, item_id)205			}206			Call::set_variable_meta_data(collection_id, item_id, data) => {207				Self::withdraw_set_variable_meta_data(collection_id, item_id, data)208			}209			_ => None,210		}211	}212}