git.delta.rocks / unique-network / refs/commits / 76768073dbc4

difftreelog

source

client/rpc/src/lib.rs9.4 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/>.1617use std::sync::Arc;1819use codec::Decode;20use jsonrpc_core::{Error as RpcError, ErrorCode, Result};21use jsonrpc_derive::rpc;22use up_data_structs::{23	RpcCollection, CollectionId, CollectionStats, CollectionLimits, TokenId, Property,24	PropertyKeyPermission, TokenData,25};26use sp_api::{BlockId, BlockT, ProvideRuntimeApi, ApiExt};27use sp_blockchain::HeaderBackend;28use up_rpc::UniqueApi as UniqueRuntimeApi;2930#[rpc]31pub trait UniqueApi<BlockHash, CrossAccountId, AccountId> {32	#[rpc(name = "unique_accountTokens")]33	fn account_tokens(34		&self,35		collection: CollectionId,36		account: CrossAccountId,37		at: Option<BlockHash>,38	) -> Result<Vec<TokenId>>;39	#[rpc(name = "unique_collectionTokens")]40	fn collection_tokens(41		&self,42		collection: CollectionId,43		at: Option<BlockHash>,44	) -> Result<Vec<TokenId>>;45	#[rpc(name = "unique_tokenExists")]46	fn token_exists(47		&self,48		collection: CollectionId,49		token: TokenId,50		at: Option<BlockHash>,51	) -> Result<bool>;5253	#[rpc(name = "unique_tokenOwner")]54	fn token_owner(55		&self,56		collection: CollectionId,57		token: TokenId,58		at: Option<BlockHash>,59	) -> Result<Option<CrossAccountId>>;60	#[rpc(name = "unique_topmostTokenOwner")]61	fn topmost_token_owner(62		&self,63		collection: CollectionId,64		token: TokenId,65		at: Option<BlockHash>,66	) -> Result<Option<CrossAccountId>>;67	#[rpc(name = "unique_constMetadata")]68	fn const_metadata(69		&self,70		collection: CollectionId,71		token: TokenId,72		at: Option<BlockHash>,73	) -> Result<Vec<u8>>;7475	#[rpc(name = "unique_collectionProperties")]76	fn collection_properties(77		&self,78		collection: CollectionId,79		keys: Vec<String>,80		at: Option<BlockHash>,81	) -> Result<Vec<Property>>;8283	#[rpc(name = "unique_tokenProperties")]84	fn token_properties(85		&self,86		collection: CollectionId,87		token_id: TokenId,88		properties: Vec<String>,89		at: Option<BlockHash>,90	) -> Result<Vec<Property>>;9192	#[rpc(name = "unique_propertyPermissions")]93	fn property_permissions(94		&self,95		collection: CollectionId,96		keys: Vec<String>,97		at: Option<BlockHash>,98	) -> Result<Vec<PropertyKeyPermission>>;99100	#[rpc(name = "unique_tokenData")]101	fn token_data(102		&self,103		collection: CollectionId,104		token_id: TokenId,105		keys: Vec<String>,106		at: Option<BlockHash>,107	) -> Result<TokenData<CrossAccountId>>;108109	#[rpc(name = "unique_totalSupply")]110	fn total_supply(&self, collection: CollectionId, at: Option<BlockHash>) -> Result<u32>;111	#[rpc(name = "unique_accountBalance")]112	fn account_balance(113		&self,114		collection: CollectionId,115		account: CrossAccountId,116		at: Option<BlockHash>,117	) -> Result<u32>;118	#[rpc(name = "unique_balance")]119	fn balance(120		&self,121		collection: CollectionId,122		account: CrossAccountId,123		token: TokenId,124		at: Option<BlockHash>,125	) -> Result<String>;126	#[rpc(name = "unique_allowance")]127	fn allowance(128		&self,129		collection: CollectionId,130		sender: CrossAccountId,131		spender: CrossAccountId,132		token: TokenId,133		at: Option<BlockHash>,134	) -> Result<String>;135136	#[rpc(name = "unique_adminlist")]137	fn adminlist(138		&self,139		collection: CollectionId,140		at: Option<BlockHash>,141	) -> Result<Vec<CrossAccountId>>;142	#[rpc(name = "unique_allowlist")]143	fn allowlist(144		&self,145		collection: CollectionId,146		at: Option<BlockHash>,147	) -> Result<Vec<CrossAccountId>>;148	#[rpc(name = "unique_allowed")]149	fn allowed(150		&self,151		collection: CollectionId,152		user: CrossAccountId,153		at: Option<BlockHash>,154	) -> Result<bool>;155	#[rpc(name = "unique_lastTokenId")]156	fn last_token_id(&self, collection: CollectionId, at: Option<BlockHash>) -> Result<TokenId>;157	#[rpc(name = "unique_collectionById")]158	fn collection_by_id(159		&self,160		collection: CollectionId,161		at: Option<BlockHash>,162	) -> Result<Option<RpcCollection<AccountId>>>;163	#[rpc(name = "unique_collectionStats")]164	fn collection_stats(&self, at: Option<BlockHash>) -> Result<CollectionStats>;165166	#[rpc(name = "unique_nextSponsored")]167	fn next_sponsored(168		&self,169		collection: CollectionId,170		account: CrossAccountId,171		token: TokenId,172		at: Option<BlockHash>,173	) -> Result<Option<u64>>;174	#[rpc(name = "unique_effectiveCollectionLimits")]175	fn effective_collection_limits(176		&self,177		collection_id: CollectionId,178		at: Option<BlockHash>,179	) -> Result<Option<CollectionLimits>>;180}181182pub struct Unique<C, P> {183	client: Arc<C>,184	_marker: std::marker::PhantomData<P>,185}186187impl<C, P> Unique<C, P> {188	pub fn new(client: Arc<C>) -> Self {189		Self {190			client,191			_marker: Default::default(),192		}193	}194}195196pub enum Error {197	RuntimeError,198}199200impl From<Error> for i64 {201	fn from(e: Error) -> i64 {202		match e {203			Error::RuntimeError => 1,204		}205	}206}207208macro_rules! pass_method {209	(210		$method_name:ident(211			$($(#[map(|$map_arg:ident| $map:expr)])? $name:ident: $ty:ty),* $(,)?212		) -> $result:ty $(=> $mapper:expr)?213		$(; changed_in $ver:expr, $changed_method_name:ident ($($changed_name:expr), * $(,)?) => $fixer:expr)*214	) => {215		fn $method_name(216			&self,217			$(218				$name: $ty,219			)*220			at: Option<<Block as BlockT>::Hash>,221		) -> Result<$result> {222			let api = self.client.runtime_api();223			let at = BlockId::hash(at.unwrap_or_else(|| self.client.info().best_hash));224			let _api_version = if let Ok(Some(api_version)) =225				api.api_version::<dyn UniqueRuntimeApi<Block, CrossAccountId, AccountId>>(&at)226			{227				api_version228			} else {229				// unreachable for our runtime230				return Err(RpcError {231					code: ErrorCode::InvalidParams,232					message: "Api is not available".into(),233					data: None,234				})235			};236237			let result = $(if _api_version < $ver {238				api.$changed_method_name(&at, $($changed_name),*).map(|r| r.map($fixer))239			} else)*240			{ api.$method_name(&at, $($((|$map_arg: $ty| $map))? ($name)),*) };241242			let result = result.map_err(|e| RpcError {243				code: ErrorCode::ServerError(Error::RuntimeError.into()),244				message: "Unable to query".into(),245				data: Some(format!("{:?}", e).into()),246			})?;247			result.map_err(|e| RpcError {248				code: ErrorCode::InvalidParams,249				message: "Runtime returned error".into(),250				data: Some(format!("{:?}", e).into()),251			})$(.map($mapper))?252		}253	};254}255256#[allow(deprecated)]257impl<C, Block, CrossAccountId, AccountId>258	UniqueApi<<Block as BlockT>::Hash, CrossAccountId, AccountId> for Unique<C, Block>259where260	Block: BlockT,261	AccountId: Decode,262	C: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,263	C::Api: UniqueRuntimeApi<Block, CrossAccountId, AccountId>,264	CrossAccountId: pallet_evm::account::CrossAccountId<AccountId>,265{266	pass_method!(account_tokens(collection: CollectionId, account: CrossAccountId) -> Vec<TokenId>);267	pass_method!(collection_tokens(collection: CollectionId) -> Vec<TokenId>);268	pass_method!(token_exists(collection: CollectionId, token: TokenId) -> bool);269	pass_method!(270		token_owner(collection: CollectionId, token: TokenId) -> Option<CrossAccountId>;271		changed_in 2, token_owner_before_version_2(collection, token) => |u| Some(u)272	);273	pass_method!(topmost_token_owner(collection: CollectionId, token: TokenId) -> Option<CrossAccountId>);274	pass_method!(const_metadata(collection: CollectionId, token: TokenId) -> Vec<u8>);275276	pass_method!(collection_properties(277		collection: CollectionId,278279		#[map(|keys| string_keys_to_bytes_keys(keys))]280		keys: Vec<String>281	) -> Vec<Property>);282283	pass_method!(token_properties(284		collection: CollectionId,285		token_id: TokenId,286287		#[map(|keys| string_keys_to_bytes_keys(keys))]288		properties: Vec<String>289	) -> Vec<Property>);290291	pass_method!(property_permissions(292		collection: CollectionId,293294		#[map(|keys| string_keys_to_bytes_keys(keys))]295		keys: Vec<String>296	) -> Vec<PropertyKeyPermission>);297298	pass_method!(token_data(299		collection: CollectionId,300		token_id: TokenId,301302		#[map(|keys| string_keys_to_bytes_keys(keys))]303		keys: Vec<String>,304	) -> TokenData<CrossAccountId>);305306	pass_method!(total_supply(collection: CollectionId) -> u32);307	pass_method!(account_balance(collection: CollectionId, account: CrossAccountId) -> u32);308	pass_method!(balance(collection: CollectionId, account: CrossAccountId, token: TokenId) -> String => |v| v.to_string());309	pass_method!(allowance(collection: CollectionId, sender: CrossAccountId, spender: CrossAccountId, token: TokenId) -> String => |v| v.to_string());310311	pass_method!(adminlist(collection: CollectionId) -> Vec<CrossAccountId>);312	pass_method!(allowlist(collection: CollectionId) -> Vec<CrossAccountId>);313	pass_method!(allowed(collection: CollectionId, user: CrossAccountId) -> bool);314	pass_method!(last_token_id(collection: CollectionId) -> TokenId);315	pass_method!(collection_by_id(collection: CollectionId) -> Option<RpcCollection<AccountId>>);316	pass_method!(collection_stats() -> CollectionStats);317	pass_method!(next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Option<u64>);318	pass_method!(effective_collection_limits(collection_id: CollectionId) -> Option<CollectionLimits>);319}320321fn string_keys_to_bytes_keys(keys: Vec<String>) -> Vec<Vec<u8>> {322	keys.into_iter().map(|key| key.into_bytes()).collect()323}