use tonic::transport::Channel;
use uniffi::Object;
use celestia_types::blob::BlobParams;
use celestia_types::block::Block;
use celestia_types::hash::uniffi_types::UniffiHash;
use celestia_types::state::auth::{Account, AuthParams};
use celestia_types::state::{AbciQueryResponse, Coin, TxResponse};
use celestia_types::{ExtendedHeader, UniffiConversionError};
use crate::grpc::{
BroadcastMode, GasEstimate, GasInfo, GetTxResponse, TxPriority, TxStatusResponse,
};
pub type Result<T, E = GrpcClientError> = std::result::Result<T, E>;
#[derive(Debug, thiserror::Error, uniffi::Error)]
pub enum GrpcClientError {
#[error("grpc error: {msg}")]
GrpcError {
msg: String,
},
#[error("uniffi conversion error: {msg}")]
UniffiConversionError {
msg: String,
},
}
type InnerClient = crate::GrpcClient<Channel>;
#[derive(Object)]
pub struct GrpcClient {
client: InnerClient,
}
#[uniffi::export(async_runtime = "tokio")]
impl GrpcClient {
#[uniffi::constructor(name = "create")]
pub async fn new(url: String) -> Result<Self> {
Ok(GrpcClient {
client: InnerClient::with_url(url).map_err(crate::Error::TransportError)?,
})
}
pub async fn get_auth_params(&self) -> Result<AuthParams> {
Ok(self.client.get_auth_params().await?)
}
pub async fn get_account(&self, account: &str) -> Result<Account> {
Ok(self.client.get_account(&account.parse()?).await?)
}
pub async fn get_accounts(&self) -> Result<Vec<Account>> {
Ok(self.client.get_accounts().await?)
}
pub async fn get_verified_balance(&self, address: &str, header: &str) -> Result<Coin> {
let header: ExtendedHeader = serde_json::from_str(header)
.map_err(|e| GrpcClientError::UniffiConversionError { msg: e.to_string() })?;
Ok(self
.client
.get_verified_balance(&address.parse()?, &header)
.await?)
}
pub async fn get_balance(&self, address: &str, denom: String) -> Result<Coin> {
Ok(self.client.get_balance(&address.parse()?, denom).await?)
}
pub async fn get_all_balances(&self, address: &str) -> Result<Vec<Coin>> {
Ok(self.client.get_all_balances(&address.parse()?).await?)
}
pub async fn get_spendable_balances(&self, address: &str) -> Result<Vec<Coin>> {
Ok(self
.client
.get_spendable_balances(&address.parse()?)
.await?)
}
pub async fn get_total_supply(&self) -> Result<Vec<Coin>> {
Ok(self.client.get_total_supply().await?)
}
pub async fn get_min_gas_price(&self) -> Result<f64> {
Ok(self.client.get_min_gas_price().await?)
}
pub async fn get_latest_block(&self) -> Result<Block> {
Ok(self.client.get_latest_block().await?)
}
pub async fn get_block_by_height(&self, height: i64) -> Result<Block> {
Ok(self.client.get_block_by_height(height).await?)
}
async fn abci_query(
&self,
data: &[u8],
path: &str,
height: u64,
prove: bool,
) -> Result<AbciQueryResponse> {
Ok(self.client.abci_query(data, path, height, prove).await?)
}
async fn broadcast_tx(&self, tx_bytes: Vec<u8>, mode: BroadcastMode) -> Result<TxResponse> {
Ok(self.client.broadcast_tx(tx_bytes, mode).await?)
}
async fn get_tx(&self, hash: UniffiHash) -> Result<GetTxResponse> {
Ok(self.client.get_tx(hash.try_into()?).await?)
}
pub async fn simulate(&self, tx_bytes: Vec<u8>) -> Result<GasInfo> {
Ok(self.client.simulate(tx_bytes).await?)
}
pub async fn get_blob_params(&self) -> Result<BlobParams> {
Ok(self.client.get_blob_params().await?)
}
pub async fn tx_status(&self, hash: UniffiHash) -> Result<TxStatusResponse> {
Ok(self.client.tx_status(hash.try_into()?).await?)
}
async fn estimate_gas_price(&self, priority: TxPriority) -> Result<f64> {
Ok(self.client.estimate_gas_price(priority).await?)
}
async fn estimate_gas_price_and_usage(
&self,
priority: TxPriority,
tx_bytes: Vec<u8>,
) -> Result<GasEstimate> {
Ok(self
.client
.estimate_gas_price_and_usage(priority, tx_bytes)
.await?)
}
}
impl From<crate::Error> for GrpcClientError {
fn from(value: crate::Error) -> Self {
GrpcClientError::GrpcError {
msg: value.to_string(),
}
}
}
impl From<UniffiConversionError> for GrpcClientError {
fn from(value: UniffiConversionError) -> Self {
GrpcClientError::GrpcError {
msg: value.to_string(),
}
}
}
impl From<celestia_types::Error> for GrpcClientError {
fn from(value: celestia_types::Error) -> Self {
crate::Error::from(value).into()
}
}