git.delta.rocks / unique-network / refs/commits / 7f0dbc230b55

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				_ => false,131			};132		}133134		if !sponsor_transfer {135			None136		} else {137			collection.sponsorship.sponsor().cloned()138		}139	}140141	pub fn withdraw_set_variable_meta_data(142		collection_id: &CollectionId,143		item_id: &TokenId,144		data: &[u8],145	) -> Option<T::AccountId> {146		let mut sponsor_metadata_changes = false;147148		let collection = CollectionById::<T>::get(collection_id)?;149150		if collection.sponsorship.confirmed() &&151			// Can't sponsor fungible collection, this tx will be rejected152			// as invalid153			!matches!(collection.mode, CollectionMode::Fungible(_)) &&154			data.len() <= collection.limits.sponsored_data_size as usize155		{156			if let Some(rate_limit) = collection.limits.sponsored_data_rate_limit {157				let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;158159				if VariableMetaDataBasket::<T>::get(collection_id, item_id)160					.map(|last_block| block_number - last_block > rate_limit)161					.unwrap_or(true)162				{163					sponsor_metadata_changes = true;164					VariableMetaDataBasket::<T>::insert(collection_id, item_id, block_number);165				}166			}167		}168169		if !sponsor_metadata_changes {170			None171		} else {172			collection.sponsorship.sponsor().cloned()173		}174	}175}176177impl<T, C> SponsorshipHandler<T::AccountId, C> for NftSponsorshipHandler<T>178where179	T: Config,180	C: IsSubType<Call<T>>,181{182	fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {183		match IsSubType::<Call<T>>::is_sub_type(call)? {184			Call::create_item(collection_id, _owner, properties) => {185				Self::withdraw_create_item(who, collection_id, properties)186			}187			Call::transfer(_new_owner, collection_id, item_id, _value) => {188				Self::withdraw_transfer(who, collection_id, item_id)189			}190			Call::set_variable_meta_data(collection_id, item_id, data) => {191				Self::withdraw_set_variable_meta_data(collection_id, item_id, data)192			}193			_ => None,194		}195	}196}