git.delta.rocks / unique-network / refs/commits / 3fb62366cc89

difftreelog

source

pallets/nft/src/sponsorship.rs5.9 KiBsourcehistory
1use crate::{2	Config, Call, CollectionById, CreateItemBasket, VariableMetaDataBasket,3	ReFungibleTransferBasket, FungibleTransferBasket, NftTransferBasket, ChainLimit,4	CreateItemData, CollectionMode,5};6use core::marker::PhantomData;7use up_sponsorship::SponsorshipHandler;8use frame_support::{9	traits::IsSubType,10	storage::{StorageMap, StorageDoubleMap, StorageValue},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,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)?;50		let limits = ChainLimit::get();5152		let mut sponsor_transfer = false;53		if collection.sponsorship.confirmed() {54			let collection_limits = collection.limits.clone();55			let collection_mode = collection.mode.clone();5657			// sponsor timeout58			let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;59			sponsor_transfer = match collection_mode {60				CollectionMode::NFT => {61					// get correct limit62					let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {63						collection_limits.sponsor_transfer_timeout64					} else {65						limits.nft_sponsor_transfer_timeout66					};6768					let mut sponsored = true;69					if NftTransferBasket::<T>::contains_key(collection_id, item_id) {70						let last_tx_block = NftTransferBasket::<T>::get(collection_id, item_id);71						let limit_time = last_tx_block + limit.into();72						if block_number <= limit_time {73							sponsored = false;74						}75					}76					if sponsored {77						NftTransferBasket::<T>::insert(collection_id, item_id, block_number);78					}7980					sponsored81				}82				CollectionMode::Fungible(_) => {83					// get correct limit84					let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {85						collection_limits.sponsor_transfer_timeout86					} else {87						limits.fungible_sponsor_transfer_timeout88					};8990					let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;91					let mut sponsored = true;92					if FungibleTransferBasket::<T>::contains_key(collection_id, who) {93						let last_tx_block = FungibleTransferBasket::<T>::get(collection_id, who);94						let limit_time = last_tx_block + limit.into();95						if block_number <= limit_time {96							sponsored = false;97						}98					}99					if sponsored {100						FungibleTransferBasket::<T>::insert(collection_id, who, block_number);101					}102103					sponsored104				}105				CollectionMode::ReFungible => {106					// get correct limit107					let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {108						collection_limits.sponsor_transfer_timeout109					} else {110						limits.refungible_sponsor_transfer_timeout111					};112113					let mut sponsored = true;114					if ReFungibleTransferBasket::<T>::contains_key(collection_id, item_id) {115						let last_tx_block =116							ReFungibleTransferBasket::<T>::get(collection_id, item_id);117						let limit_time = last_tx_block + limit.into();118						if block_number <= limit_time {119							sponsored = false;120						}121					}122					if sponsored {123						ReFungibleTransferBasket::<T>::insert(collection_id, item_id, block_number);124					}125126					sponsored127				}128				_ => false,129			};130		}131132		if !sponsor_transfer {133			None134		} else {135			collection.sponsorship.sponsor().cloned()136		}137	}138139	pub fn withdraw_set_variable_meta_data(140		collection_id: &CollectionId,141		item_id: &TokenId,142		data: &[u8],143	) -> Option<T::AccountId> {144		let mut sponsor_metadata_changes = false;145146		let collection = CollectionById::<T>::get(collection_id)?;147148		if collection.sponsorship.confirmed() &&149			// Can't sponsor fungible collection, this tx will be rejected150			// as invalid151			!matches!(collection.mode, CollectionMode::Fungible(_)) &&152			data.len() <= collection.limits.sponsored_data_size as usize153		{154			if let Some(rate_limit) = collection.limits.sponsored_data_rate_limit {155				let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;156157				if VariableMetaDataBasket::<T>::get(collection_id, item_id)158					.map(|last_block| block_number - last_block > rate_limit)159					.unwrap_or(true)160				{161					sponsor_metadata_changes = true;162					VariableMetaDataBasket::<T>::insert(collection_id, item_id, block_number);163				}164			}165		}166167		if !sponsor_metadata_changes {168			None169		} else {170			collection.sponsorship.sponsor().cloned()171		}172	}173}174175impl<T, C> SponsorshipHandler<T::AccountId, C> for NftSponsorshipHandler<T>176where177	T: Config,178	C: IsSubType<Call<T>>,179{180	fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {181		match IsSubType::<Call<T>>::is_sub_type(call)? {182			Call::create_item(collection_id, _owner, properties) => {183				Self::withdraw_create_item(who, collection_id, properties)184			}185			Call::transfer(_new_owner, collection_id, item_id, _value) => {186				Self::withdraw_transfer(who, collection_id, item_id)187			}188			Call::set_variable_meta_data(collection_id, item_id, data) => {189				Self::withdraw_set_variable_meta_data(collection_id, item_id, data)190			}191			_ => None,192		}193	}194}