git.delta.rocks / unique-network / refs/commits / 055cc66f716b

difftreelog

source

client/rpc/src/lib.rs15.9 KiBsourcehistory
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617// Original License18use std::sync::Arc;1920use codec::{Decode, Encode};21use jsonrpsee::{22	core::{RpcResult as Result},23	proc_macros::rpc,24};25use anyhow::anyhow;26use up_data_structs::{27	RpcCollection, CollectionId, CollectionStats, CollectionLimits, TokenId, Property,28	PropertyKeyPermission, TokenData, TokenChild,29};30use sp_api::{BlockId, BlockT, ProvideRuntimeApi, ApiExt};31use sp_blockchain::HeaderBackend;32use up_rpc::UniqueApi as UniqueRuntimeApi;3334// RMRK35use rmrk_rpc::RmrkApi as RmrkRuntimeApi;36use up_data_structs::{37	RmrkCollectionId, RmrkNftId, RmrkBaseId, RmrkNftChild, RmrkThemeName, RmrkResourceId,38};3940pub use rmrk_unique_rpc::RmrkApiServer;4142#[rpc(server)]43#[async_trait]44pub trait UniqueApi<BlockHash, CrossAccountId, AccountId> {45	#[method(name = "unique_accountTokens")]46	fn account_tokens(47		&self,48		collection: CollectionId,49		account: CrossAccountId,50		at: Option<BlockHash>,51	) -> Result<Vec<TokenId>>;52	#[method(name = "unique_collectionTokens")]53	fn collection_tokens(54		&self,55		collection: CollectionId,56		at: Option<BlockHash>,57	) -> Result<Vec<TokenId>>;58	#[method(name = "unique_tokenExists")]59	fn token_exists(60		&self,61		collection: CollectionId,62		token: TokenId,63		at: Option<BlockHash>,64	) -> Result<bool>;6566	#[method(name = "unique_tokenOwner")]67	fn token_owner(68		&self,69		collection: CollectionId,70		token: TokenId,71		at: Option<BlockHash>,72	) -> Result<Option<CrossAccountId>>;7374	/// Returns 10 tokens owners in no particular order.75	#[method(name = "unique_tokenOwners")]76	fn token_owners(77		&self,78		collection: CollectionId,79		token: TokenId,80		at: Option<BlockHash>,81	) -> Result<Vec<CrossAccountId>>;8283	#[method(name = "unique_topmostTokenOwner")]84	fn topmost_token_owner(85		&self,86		collection: CollectionId,87		token: TokenId,88		at: Option<BlockHash>,89	) -> Result<Option<CrossAccountId>>;90	#[method(name = "unique_tokenChildren")]91	fn token_children(92		&self,93		collection: CollectionId,94		token: TokenId,95		at: Option<BlockHash>,96	) -> Result<Vec<TokenChild>>;9798	#[method(name = "unique_collectionProperties")]99	fn collection_properties(100		&self,101		collection: CollectionId,102		keys: Option<Vec<String>>,103		at: Option<BlockHash>,104	) -> Result<Vec<Property>>;105106	#[method(name = "unique_tokenProperties")]107	fn token_properties(108		&self,109		collection: CollectionId,110		token_id: TokenId,111		keys: Option<Vec<String>>,112		at: Option<BlockHash>,113	) -> Result<Vec<Property>>;114115	#[method(name = "unique_propertyPermissions")]116	fn property_permissions(117		&self,118		collection: CollectionId,119		keys: Option<Vec<String>>,120		at: Option<BlockHash>,121	) -> Result<Vec<PropertyKeyPermission>>;122123	#[method(name = "unique_tokenData")]124	fn token_data(125		&self,126		collection: CollectionId,127		token_id: TokenId,128		keys: Option<Vec<String>>,129		at: Option<BlockHash>,130	) -> Result<TokenData<CrossAccountId>>;131132	#[method(name = "unique_totalSupply")]133	fn total_supply(&self, collection: CollectionId, at: Option<BlockHash>) -> Result<u32>;134	#[method(name = "unique_accountBalance")]135	fn account_balance(136		&self,137		collection: CollectionId,138		account: CrossAccountId,139		at: Option<BlockHash>,140	) -> Result<u32>;141	#[method(name = "unique_balance")]142	fn balance(143		&self,144		collection: CollectionId,145		account: CrossAccountId,146		token: TokenId,147		at: Option<BlockHash>,148	) -> Result<String>;149	#[method(name = "unique_allowance")]150	fn allowance(151		&self,152		collection: CollectionId,153		sender: CrossAccountId,154		spender: CrossAccountId,155		token: TokenId,156		at: Option<BlockHash>,157	) -> Result<String>;158159	#[method(name = "unique_adminlist")]160	fn adminlist(161		&self,162		collection: CollectionId,163		at: Option<BlockHash>,164	) -> Result<Vec<CrossAccountId>>;165	#[method(name = "unique_allowlist")]166	fn allowlist(167		&self,168		collection: CollectionId,169		at: Option<BlockHash>,170	) -> Result<Vec<CrossAccountId>>;171	#[method(name = "unique_allowed")]172	fn allowed(173		&self,174		collection: CollectionId,175		user: CrossAccountId,176		at: Option<BlockHash>,177	) -> Result<bool>;178	#[method(name = "unique_lastTokenId")]179	fn last_token_id(&self, collection: CollectionId, at: Option<BlockHash>) -> Result<TokenId>;180	#[method(name = "unique_collectionById")]181	fn collection_by_id(182		&self,183		collection: CollectionId,184		at: Option<BlockHash>,185	) -> Result<Option<RpcCollection<AccountId>>>;186	#[method(name = "unique_collectionStats")]187	fn collection_stats(&self, at: Option<BlockHash>) -> Result<CollectionStats>;188189	#[method(name = "unique_nextSponsored")]190	fn next_sponsored(191		&self,192		collection: CollectionId,193		account: CrossAccountId,194		token: TokenId,195		at: Option<BlockHash>,196	) -> Result<Option<u64>>;197198	#[method(name = "unique_effectiveCollectionLimits")]199	fn effective_collection_limits(200		&self,201		collection_id: CollectionId,202		at: Option<BlockHash>,203	) -> Result<Option<CollectionLimits>>;204205	#[method(name = "unique_totalPieces")]206	fn total_pieces(207		&self,208		collection_id: CollectionId,209		token_id: TokenId,210		at: Option<BlockHash>,211	) -> Result<Option<u128>>;212}213214mod rmrk_unique_rpc {215	use super::*;216217	#[rpc(server)]218	#[async_trait]219	pub trait RmrkApi<220		BlockHash,221		AccountId,222		CollectionInfo,223		NftInfo,224		ResourceInfo,225		PropertyInfo,226		BaseInfo,227		PartType,228		Theme,229	>230	{231		#[method(name = "rmrk_lastCollectionIdx")]232		/// Get the latest created collection id233		fn last_collection_idx(&self, at: Option<BlockHash>) -> Result<RmrkCollectionId>;234235		#[method(name = "rmrk_collectionById")]236		/// Get collection by id237		fn collection_by_id(238			&self,239			id: RmrkCollectionId,240			at: Option<BlockHash>,241		) -> Result<Option<CollectionInfo>>;242243		#[method(name = "rmrk_nftById")]244		/// Get NFT by collection id and NFT id245		fn nft_by_id(246			&self,247			collection_id: RmrkCollectionId,248			nft_id: RmrkNftId,249			at: Option<BlockHash>,250		) -> Result<Option<NftInfo>>;251252		#[method(name = "rmrk_accountTokens")]253		/// Get tokens owned by an account in a collection254		fn account_tokens(255			&self,256			account_id: AccountId,257			collection_id: RmrkCollectionId,258			at: Option<BlockHash>,259		) -> Result<Vec<RmrkNftId>>;260261		#[method(name = "rmrk_nftChildren")]262		/// Get NFT children263		fn nft_children(264			&self,265			collection_id: RmrkCollectionId,266			nft_id: RmrkNftId,267			at: Option<BlockHash>,268		) -> Result<Vec<RmrkNftChild>>;269270		#[method(name = "rmrk_collectionProperties")]271		/// Get collection properties272		fn collection_properties(273			&self,274			collection_id: RmrkCollectionId,275			filter_keys: Option<Vec<String>>,276			at: Option<BlockHash>,277		) -> Result<Vec<PropertyInfo>>;278279		#[method(name = "rmrk_nftProperties")]280		/// Get NFT properties281		fn nft_properties(282			&self,283			collection_id: RmrkCollectionId,284			nft_id: RmrkNftId,285			filter_keys: Option<Vec<String>>,286			at: Option<BlockHash>,287		) -> Result<Vec<PropertyInfo>>;288289		#[method(name = "rmrk_nftResources")]290		/// Get NFT resources291		fn nft_resources(292			&self,293			collection_id: RmrkCollectionId,294			nft_id: RmrkNftId,295			at: Option<BlockHash>,296		) -> Result<Vec<ResourceInfo>>;297298		#[method(name = "rmrk_nftResourcePriority")]299		/// Get NFT resource priority300		fn nft_resource_priority(301			&self,302			collection_id: RmrkCollectionId,303			nft_id: RmrkNftId,304			resource_id: RmrkResourceId,305			at: Option<BlockHash>,306		) -> Result<Option<u32>>;307308		#[method(name = "rmrk_base")]309		/// Get base info310		fn base(&self, base_id: RmrkBaseId, at: Option<BlockHash>) -> Result<Option<BaseInfo>>;311312		#[method(name = "rmrk_baseParts")]313		/// Get all Base's parts314		fn base_parts(&self, base_id: RmrkBaseId, at: Option<BlockHash>) -> Result<Vec<PartType>>;315316		#[method(name = "rmrk_themeNames")]317		fn theme_names(318			&self,319			base_id: RmrkBaseId,320			at: Option<BlockHash>,321		) -> Result<Vec<RmrkThemeName>>;322323		#[method(name = "rmrk_themes")]324		fn theme(325			&self,326			base_id: RmrkBaseId,327			theme_name: String,328			filter_keys: Option<Vec<String>>,329			at: Option<BlockHash>,330		) -> Result<Option<Theme>>;331	}332}333334pub struct Unique<C, P> {335	client: Arc<C>,336	_marker: std::marker::PhantomData<P>,337}338339impl<C, P> Unique<C, P> {340	pub fn new(client: Arc<C>) -> Self {341		Self {342			client,343			_marker: Default::default(),344		}345	}346}347348pub struct Rmrk<C, P> {349	client: Arc<C>,350	_marker: std::marker::PhantomData<P>,351}352353impl<C, P> Rmrk<C, P> {354	pub fn new(client: Arc<C>) -> Self {355		Self {356			client,357			_marker: Default::default(),358		}359	}360}361362macro_rules! pass_method {363	(364		$method_name:ident(365			$($(#[map(|$map_arg:ident| $map:expr)])? $name:ident: $ty:ty),* $(,)?366		) -> $result:ty $(=> $mapper:expr)?,367		//$runtime_name:ident $(<$($lt: tt),+>)*368		$runtime_api_macro:ident369		$(; changed_in $ver:expr, $changed_method_name:ident ($($changed_name:expr), * $(,)?) => $fixer:expr)*370	) => {371		fn $method_name(372			&self,373			$(374				$name: $ty,375			)*376			at: Option<<Block as BlockT>::Hash>,377		) -> Result<$result> {378			let api = self.client.runtime_api();379			let at = BlockId::hash(at.unwrap_or_else(|| self.client.info().best_hash));380			let _api_version = if let Ok(Some(api_version)) =381				api.api_version::<$runtime_api_macro!()>(&at)382			{383				api_version384			} else {385				// unreachable for our runtime386				return Err(anyhow!("api is not available").into())387			};388389			let result = $(if _api_version < $ver {390				api.$changed_method_name(&at, $($changed_name),*).map(|r| r.map($fixer))391			} else)*392			{ api.$method_name(&at, $($((|$map_arg: $ty| $map))? ($name)),*) };393394			Ok(result395				.map_err(|e| anyhow!("unable to query: {e}"))?396				.map_err(|e| anyhow!("runtime error: {e:?}"))$(.map($mapper))??)397		}398	};399}400401macro_rules! unique_api {402	() => {403		dyn UniqueRuntimeApi<Block, CrossAccountId, AccountId>404	};405}406407macro_rules! rmrk_api {408	() => {409		dyn RmrkRuntimeApi<Block, AccountId, CollectionInfo, NftInfo, ResourceInfo, PropertyInfo, BaseInfo, PartType, Theme>410	};411}412413#[allow(deprecated)]414impl<C, Block, CrossAccountId, AccountId>415	UniqueApiServer<<Block as BlockT>::Hash, CrossAccountId, AccountId> for Unique<C, Block>416where417	Block: BlockT,418	AccountId: Decode,419	C: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,420	C::Api: UniqueRuntimeApi<Block, CrossAccountId, AccountId>,421	CrossAccountId: pallet_evm::account::CrossAccountId<AccountId>,422{423	pass_method!(424		account_tokens(collection: CollectionId, account: CrossAccountId) -> Vec<TokenId>, unique_api425	);426	pass_method!(427		collection_tokens(collection: CollectionId) -> Vec<TokenId>, unique_api428	);429	pass_method!(430		token_exists(collection: CollectionId, token: TokenId) -> bool, unique_api431	);432	pass_method!(433		token_owner(collection: CollectionId, token: TokenId) -> Option<CrossAccountId>, unique_api434	);435	pass_method!(436		topmost_token_owner(collection: CollectionId, token: TokenId) -> Option<CrossAccountId>, unique_api437	);438	pass_method!(token_children(collection: CollectionId, token: TokenId) -> Vec<TokenChild>, unique_api);439	pass_method!(total_supply(collection: CollectionId) -> u32, unique_api);440	pass_method!(account_balance(collection: CollectionId, account: CrossAccountId) -> u32, unique_api);441	pass_method!(balance(collection: CollectionId, account: CrossAccountId, token: TokenId) -> String => |v| v.to_string(), unique_api);442	pass_method!(443		allowance(collection: CollectionId, sender: CrossAccountId, spender: CrossAccountId, token: TokenId) -> String => |v| v.to_string(),444		unique_api445	);446447	pass_method!(collection_properties(448		collection: CollectionId,449450		#[map(|keys| string_keys_to_bytes_keys(keys))]451		keys: Option<Vec<String>>452	) -> Vec<Property>, unique_api);453454	pass_method!(token_properties(455		collection: CollectionId,456		token_id: TokenId,457458		#[map(|keys| string_keys_to_bytes_keys(keys))]459		keys: Option<Vec<String>>460	) -> Vec<Property>, unique_api);461462	pass_method!(property_permissions(463		collection: CollectionId,464465		#[map(|keys| string_keys_to_bytes_keys(keys))]466		keys: Option<Vec<String>>467	) -> Vec<PropertyKeyPermission>, unique_api);468469	pass_method!(token_data(470		collection: CollectionId,471		token_id: TokenId,472473		#[map(|keys| string_keys_to_bytes_keys(keys))]474		keys: Option<Vec<String>>,475	) -> TokenData<CrossAccountId>, unique_api);476477	pass_method!(adminlist(collection: CollectionId) -> Vec<CrossAccountId>, unique_api);478	pass_method!(allowlist(collection: CollectionId) -> Vec<CrossAccountId>, unique_api);479	pass_method!(allowed(collection: CollectionId, user: CrossAccountId) -> bool, unique_api);480	pass_method!(last_token_id(collection: CollectionId) -> TokenId, unique_api);481	pass_method!(collection_by_id(collection: CollectionId) -> Option<RpcCollection<AccountId>>, unique_api);482	pass_method!(collection_stats() -> CollectionStats, unique_api);483	pass_method!(next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Option<u64>, unique_api);484	pass_method!(effective_collection_limits(collection_id: CollectionId) -> Option<CollectionLimits>, unique_api);485	pass_method!(total_pieces(collection_id: CollectionId, token_id: TokenId) -> Option<u128>, unique_api);486	pass_method!(token_owners(collection: CollectionId, token: TokenId) -> Vec<CrossAccountId>, unique_api);487}488489#[allow(deprecated)]490impl<491		C,492		Block,493		AccountId,494		CollectionInfo,495		NftInfo,496		ResourceInfo,497		PropertyInfo,498		BaseInfo,499		PartType,500		Theme,501	>502	rmrk_unique_rpc::RmrkApiServer<503		<Block as BlockT>::Hash,504		AccountId,505		CollectionInfo,506		NftInfo,507		ResourceInfo,508		PropertyInfo,509		BaseInfo,510		PartType,511		Theme,512	> for Rmrk<C, Block>513where514	C: Send + Sync + 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,515	C::Api: RmrkRuntimeApi<516		Block,517		AccountId,518		CollectionInfo,519		NftInfo,520		ResourceInfo,521		PropertyInfo,522		BaseInfo,523		PartType,524		Theme,525	>,526	AccountId: Decode + Encode,527	CollectionInfo: Decode,528	NftInfo: Decode,529	ResourceInfo: Decode,530	PropertyInfo: Decode,531	BaseInfo: Decode,532	PartType: Decode,533	Theme: Decode,534	Block: BlockT,535{536	pass_method!(last_collection_idx() -> RmrkCollectionId, rmrk_api);537	pass_method!(collection_by_id(id: RmrkCollectionId) -> Option<CollectionInfo>, rmrk_api);538	pass_method!(nft_by_id(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Option<NftInfo>, rmrk_api);539	pass_method!(account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Vec<RmrkNftId>, rmrk_api);540	pass_method!(nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Vec<RmrkNftChild>, rmrk_api);541	pass_method!(542		collection_properties(543			collection_id: RmrkCollectionId,544545			#[map(|keys| string_keys_to_bytes_keys(keys))]546			filter_keys: Option<Vec<String>>547		) -> Vec<PropertyInfo>,548		rmrk_api549	);550	pass_method!(551		nft_properties(552			collection_id: RmrkCollectionId,553			nft_id: RmrkNftId,554555			#[map(|keys| string_keys_to_bytes_keys(keys))]556			filter_keys: Option<Vec<String>>557		) -> Vec<PropertyInfo>,558		rmrk_api559	);560	pass_method!(nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Vec<ResourceInfo>, rmrk_api);561	pass_method!(nft_resource_priority(collection_id: RmrkCollectionId, nft_id: RmrkNftId, resource_id: RmrkResourceId) -> Option<u32>, rmrk_api);562	pass_method!(base(base_id: RmrkBaseId) -> Option<BaseInfo>, rmrk_api);563	pass_method!(base_parts(base_id: RmrkBaseId) -> Vec<PartType>, rmrk_api);564	pass_method!(theme_names(base_id: RmrkBaseId) -> Vec<RmrkThemeName>, rmrk_api);565	pass_method!(566		theme(567			base_id: RmrkBaseId,568569			#[map(|n| n.into_bytes())]570			theme_name: String,571572			#[map(|keys| string_keys_to_bytes_keys(keys))]573			filter_keys: Option<Vec<String>>574		) -> Option<Theme>, rmrk_api);575}576577fn string_keys_to_bytes_keys(keys: Option<Vec<String>>) -> Option<Vec<Vec<u8>>> {578	keys.map(|keys| keys.into_iter().map(|key| key.into_bytes()).collect())579}