code/pallets/swap/rpc/src/lib.rs

lib.rs

144 lines · 4,184 bytes · 19a6485969RawGitHub
//! RPC interface for the Swap pallet

use codec::Encode;
use std::sync::Arc;

use jsonrpsee::{
    core::RpcResult,
    proc_macros::rpc,
    types::{ErrorObjectOwned, error::ErrorObject},
};
use sp_api::ProvideRuntimeApi;
use sp_blockchain::HeaderBackend;
use sp_runtime::traits::Block as BlockT;
use subtensor_runtime_common::{AlphaBalance, NetUid, TaoBalance};

pub use pallet_subtensor_swap_runtime_api::{SubnetPrice, SwapRuntimeApi};

#[rpc(client, server)]
pub trait SwapRpcApi<BlockHash> {
    #[method(name = "swap_currentAlphaPrice")]
    fn current_alpha_price(&self, netuid: NetUid, at: Option<BlockHash>) -> RpcResult<u64>;
    #[method(name = "swap_currentAlphaPriceAll")]
    fn current_alpha_price_all(&self, at: Option<BlockHash>) -> RpcResult<Vec<SubnetPrice>>;
    #[method(name = "swap_simSwapTaoForAlpha")]
    fn sim_swap_tao_for_alpha(
        &self,
        netuid: NetUid,
        tao: TaoBalance,
        at: Option<BlockHash>,
    ) -> RpcResult<Vec<u8>>;
    #[method(name = "swap_simSwapAlphaForTao")]
    fn sim_swap_alpha_for_tao(
        &self,
        netuid: NetUid,
        alpha: AlphaBalance,
        at: Option<BlockHash>,
    ) -> RpcResult<Vec<u8>>;
}

/// Error type of this RPC api.
pub enum Error {
    /// The call to runtime failed.
    RuntimeError(String),
}

impl From<Error> for ErrorObjectOwned {
    fn from(e: Error) -> Self {
        match e {
            Error::RuntimeError(e) => ErrorObject::owned(1, e, None::<()>),
        }
    }
}

impl From<Error> for i32 {
    fn from(e: Error) -> i32 {
        match e {
            Error::RuntimeError(_) => 1,
        }
    }
}

/// Swap RPC implementation.
pub struct Swap<C, Block> {
    client: Arc<C>,
    _marker: std::marker::PhantomData<Block>,
}

impl<C, Block> Swap<C, Block> {
    /// Create new `Swap` instance with the given reference to the client.
    pub fn new(client: Arc<C>) -> Self {
        Self {
            client,
            _marker: Default::default(),
        }
    }
}

impl<C, Block> SwapRpcApiServer<<Block as BlockT>::Hash> for Swap<C, Block>
where
    Block: BlockT,
    C: ProvideRuntimeApi<Block> + HeaderBackend<Block> + Send + Sync + 'static,
    C::Api: SwapRuntimeApi<Block>,
{
    fn current_alpha_price(
        &self,
        netuid: NetUid,
        at: Option<<Block as BlockT>::Hash>,
    ) -> RpcResult<u64> {
        let api = self.client.runtime_api();
        let at = at.unwrap_or_else(|| self.client.info().best_hash);

        api.current_alpha_price(at, netuid).map_err(|e| {
            Error::RuntimeError(format!("Unable to get current alpha price: {e:?}")).into()
        })
    }

    fn current_alpha_price_all(
        &self,
        at: Option<<Block as BlockT>::Hash>,
    ) -> RpcResult<Vec<SubnetPrice>> {
        let api = self.client.runtime_api();
        let at = at.unwrap_or_else(|| self.client.info().best_hash);

        api.current_alpha_price_all(at).map_err(|e| {
            Error::RuntimeError(format!("Unable to get all current alpha prices: {e:?}")).into()
        })
    }

    fn sim_swap_tao_for_alpha(
        &self,
        netuid: NetUid,
        tao: TaoBalance,
        at: Option<<Block as BlockT>::Hash>,
    ) -> RpcResult<Vec<u8>> {
        let api = self.client.runtime_api();
        let at = at.unwrap_or_else(|| self.client.info().best_hash);

        match api.sim_swap_tao_for_alpha(at, netuid, tao) {
            Ok(result) => Ok(result.encode()),
            Err(e) => Err(Error::RuntimeError(format!(
                "Unable to simulate tao -> alpha swap: {e:?}"
            ))
            .into()),
        }
    }

    fn sim_swap_alpha_for_tao(
        &self,
        netuid: NetUid,
        alpha: AlphaBalance,
        at: Option<<Block as BlockT>::Hash>,
    ) -> RpcResult<Vec<u8>> {
        let api = self.client.runtime_api();
        let at = at.unwrap_or_else(|| self.client.info().best_hash);

        match api.sim_swap_alpha_for_tao(at, netuid, alpha) {
            Ok(result) => Ok(result.encode()),
            Err(e) => Err(Error::RuntimeError(format!(
                "Unable to simulate alpha -> tao swap: {e:?}"
            ))
            .into()),
        }
    }
}