--- a/client/rpc/src/lib.rs +++ b/client/rpc/src/lib.rs @@ -432,16 +432,15 @@ keys: Option> ) -> Vec, unique_api); - pass_method!( - token_data( - collection: CollectionId, - token_id: TokenId, - - #[map = string_keys_to_bytes_keys] - keys: Option>, - ) -> TokenData, unique_api; - changed_in 3, token_data_before_version_3(collection, token_id, string_keys_to_bytes_keys(keys)) => |value| Ok(value.into()) - ); + fn token_data( + &self, + collection: CollectionId, + token_id: TokenId, + keys: Option>, + at: Option<::Hash>, + ) -> Result> { + token_data_internal(self.client.clone(), collection, token_id, keys, at) + } pass_method!(adminlist(collection: CollectionId) -> Vec, unique_api); pass_method!(allowlist(collection: CollectionId) -> Vec, unique_api); @@ -497,6 +496,55 @@ .collect::>(), app_promotion_api); } +fn token_data_internal( + client: Arc, + collection: CollectionId, + token_id: TokenId, + keys: Option>, + at: Option<::Hash>, +) -> Result> +where + AccountId: Decode, + Block: BlockT, + Client: ProvideRuntimeApi + HeaderBackend, + Client::Api: UniqueRuntimeApi, + CrossAccountId: pallet_evm::account::CrossAccountId, +{ + let api = client.runtime_api(); + let at = at.unwrap_or_else(|| client.info().best_hash); + let api_version = if let Ok(Some(api_version)) = + api.api_version::>(at) + { + api_version + } else { + return Err(anyhow!("api is not available").into()); + }; + let result = if api_version >= 3 { + api.token_data(at, collection, token_id, string_keys_to_bytes_keys(keys)) + } else { + #[allow(deprecated)] + api.token_data_before_version_3(at, collection, token_id, string_keys_to_bytes_keys(keys)) + .map( + |r: sc_service::Result< + up_data_structs::TokenDataVersion1, + sp_runtime::DispatchError, + >| r.and_then(|value| Ok(value.into())), + ) + .or_else(|_| { + Ok(api + .token_owner(at, collection, token_id)? + .map(|owner| TokenData { + properties: Vec::new(), + owner, + pieces: 0, + })) + }) + }; + Ok(result + .map_err(|e| anyhow!("unable to query: {e}"))? + .map_err(|e| anyhow!("runtime error: {e:?}"))?) +} + fn string_keys_to_bytes_keys(keys: Option>) -> Option>> { keys.map(|keys| keys.into_iter().map(|key| key.into_bytes()).collect()) }