--- a/client/rpc/src/lib.rs +++ b/client/rpc/src/lib.rs @@ -4,7 +4,7 @@ use jsonrpc_core::{Error as RpcError, ErrorCode, Result}; use jsonrpc_derive::rpc; use up_data_structs::{Collection, CollectionId, CollectionStats, TokenId}; -use sp_api::{BlockId, BlockT, ProvideRuntimeApi}; +use sp_api::{BlockId, BlockT, ProvideRuntimeApi, ApiExt}; use sp_blockchain::HeaderBackend; use up_rpc::UniqueApi as UniqueRuntimeApi; @@ -132,7 +132,10 @@ } macro_rules! pass_method { - ($method_name:ident($($name:ident: $ty:ty),* $(,)?) -> $result:ty $(=> $mapper:expr)?) => { + ( + $method_name:ident($($name:ident: $ty:ty),* $(,)?) -> $result:ty $(=> $mapper:expr)? + $(; changed_in $ver:expr, $changed_method_name:ident ($($changed_name:expr), * $(,)?) => $fixer:expr)* + ) => { fn $method_name( &self, $( @@ -142,8 +145,25 @@ ) -> Result<$result> { let api = self.client.runtime_api(); let at = BlockId::hash(at.unwrap_or_else(|| self.client.info().best_hash)); + let _api_version = if let Ok(Some(api_version)) = + api.api_version::>(&at) + { + api_version + } else { + // unreachable for our runtime + return Err(RpcError { + code: ErrorCode::InvalidParams, + message: "Api is not available".into(), + data: None, + }) + }; - let result = api.$method_name(&at, $($name),*).map_err(|e| RpcError { + let result = $(if _api_version < $ver { + api.$changed_method_name(&at, $($changed_name),*).map(|r| r.map($fixer)) + } else)* + { api.$method_name(&at, $($name),*) }; + + let result = result.map_err(|e| RpcError { code: ErrorCode::ServerError(Error::RuntimeError.into()), message: "Unable to query".into(), data: Some(format!("{:?}", e).into()), @@ -168,7 +188,10 @@ { pass_method!(account_tokens(collection: CollectionId, account: CrossAccountId) -> Vec); pass_method!(token_exists(collection: CollectionId, token: TokenId) -> bool); - pass_method!(token_owner(collection: CollectionId, token: TokenId) -> Option); + pass_method!( + token_owner(collection: CollectionId, token: TokenId) -> Option; + changed_in 2, token_owner_before_version_2(collection, token) => |u| Some(u) + ); pass_method!(const_metadata(collection: CollectionId, token: TokenId) -> Vec); pass_method!(variable_metadata(collection: CollectionId, token: TokenId) -> Vec); pass_method!(collection_tokens(collection: CollectionId) -> u32); --- a/primitives/rpc/src/lib.rs +++ b/primitives/rpc/src/lib.rs @@ -9,10 +9,14 @@ type Result = core::result::Result; sp_api::decl_runtime_apis! { + #[api_version(2)] pub trait UniqueApi where AccountId: Decode, CrossAccountId: pallet_common::account::CrossAccountId, { + #[changed_in(2)] + fn token_owner(collection: CollectionId, token: TokenId) -> Result; + fn account_tokens(collection: CollectionId, account: CrossAccountId) -> Result>; fn token_exists(collection: CollectionId, token: TokenId) -> Result;