Skip to content
Snippets Groups Projects
lib.rs 2.34 KiB
Newer Older
  • Learn to ignore specific revisions
  • use std::sync::Arc;
    
    
    Shaopeng Wang's avatar
    Shaopeng Wang committed
    use codec::Codec;
    use jsonrpc_core::{Error as RpcError, ErrorCode, Result};
    use jsonrpc_derive::rpc;
    use sp_api::ProvideRuntimeApi;
    use sp_blockchain::HeaderBackend;
    use sp_runtime::{generic::BlockId, traits::Block as BlockT};
    
    
    pub use self::gen_client::Client as OracleClient;
    
    Bryan Chen's avatar
    Bryan Chen committed
    pub use orml_oracle_rpc_runtime_api::OracleApi as OracleRuntimeApi;
    
    Shaopeng Wang's avatar
    Shaopeng Wang committed
    
    #[rpc]
    pub trait OracleApi<BlockHash, Key, Value> {
    	#[rpc(name = "oracle_getValue")]
    	fn get_value(&self, key: Key, at: Option<BlockHash>) -> Result<Option<Value>>;
    
    	#[rpc(name = "oracle_getAllValues")]
    	fn get_all_values(&self, at: Option<BlockHash>) -> Result<Vec<(Key, Option<Value>)>>;
    
    Shaopeng Wang's avatar
    Shaopeng Wang committed
    }
    
    /// A struct that implements the [`OracleApi`].
    pub struct Oracle<C, B> {
    	client: Arc<C>,
    	_marker: std::marker::PhantomData<B>,
    }
    
    impl<C, B> Oracle<C, B> {
    	/// Create new `Oracle` with the given reference to the client.
    	pub fn new(client: Arc<C>) -> Self {
    		Oracle {
    			client,
    			_marker: Default::default(),
    		}
    	}
    }
    
    pub enum Error {
    	RuntimeError,
    }
    
    impl From<Error> for i64 {
    	fn from(e: Error) -> i64 {
    		match e {
    			Error::RuntimeError => 1,
    		}
    	}
    }
    
    impl<C, Block, Key, Value> OracleApi<<Block as BlockT>::Hash, Key, Value> for Oracle<C, Block>
    where
    	Block: BlockT,
    	C: Send + Sync + 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,
    	C::Api: OracleRuntimeApi<Block, Key, Value>,
    	Key: Codec,
    	Value: Codec,
    {
    	fn get_value(&self, key: Key, at: Option<<Block as BlockT>::Hash>) -> Result<Option<Value>> {
    		let api = self.client.runtime_api();
    		let at = BlockId::hash(at.unwrap_or_else(||
    			// If the block hash is not supplied assume the best block.
    			self.client.info().best_hash));
    
    		api.get_value(&at, key)
    
    Shaopeng Wang's avatar
    Shaopeng Wang committed
    			.map_err(|e| RpcError {
    				code: ErrorCode::ServerError(Error::RuntimeError.into()),
    				message: "Unable to get value.".into(),
    				data: Some(format!("{:?}", e).into()),
    			})
    	}
    
    
    	fn get_all_values(&self, at: Option<<Block as BlockT>::Hash>) -> Result<Vec<(Key, Option<Value>)>> {
    		let api = self.client.runtime_api();
    		let at = BlockId::hash(at.unwrap_or_else(||
    			// If the block hash is not supplied assume the best block.
    			self.client.info().best_hash));
    		api.get_all_values(&at)
    			.map_err(|e| RpcError {
    				code: ErrorCode::ServerError(Error::RuntimeError.into()),
    				message: "Unable to get all values.".into(),
    				data: Some(format!("{:?}", e).into()),
    			})
    	}
    
    Shaopeng Wang's avatar
    Shaopeng Wang committed
    }