ton_liteapi 0.2.0

Implementation of TON lite_api.tl interface
Documentation
use adnl::AdnlPeer;
use tokio::net::ToSocketAddrs;
use tokio_tower::multiplex;
use tower::{Service as _, ServiceBuilder, ServiceExt as _};

use crate::{layers::{UnwrapErrorLayer, WrapMessagesLayer}, peer::LitePeer, tl::{common::*, request::*, response::*, utils::FromResponse}, types::LiteError};

type Result<T> = std::result::Result<T, LiteError>;

pub struct LiteClient {
    inner: tower::util::BoxService<
        WrappedRequest,
        Response,
        LiteError,
    >,
    wait_seqno: Option<u32>,
}

impl LiteClient {
    pub async fn connect<A: ToSocketAddrs>(address: A, public_key: impl AsRef<[u8]>) -> Result<Self> {
        let adnl = AdnlPeer::connect(public_key, address).await?;
        let lite = LitePeer::new(adnl);
        let service = ServiceBuilder::new()
            .layer(UnwrapErrorLayer)
            .layer(WrapMessagesLayer)
            .service(multiplex::Client::<_, Box<dyn std::error::Error + Send + Sync + 'static>, _>::new(lite));
        Ok(Self { inner: service.boxed(), wait_seqno: None })
    }

    pub fn wait_masterchain_seqno(mut self, seqno: u32) -> Self {
        self.wait_seqno = Some(seqno);
        self
    }

    async fn send_request<T: FromResponse>(&mut self, request: Request) -> Result<T>
    {
        let wrapped_request = WrappedRequest {
            wait_masterchain_seqno: self.wait_seqno.take().map(|seqno| WaitMasterchainSeqno { seqno, timeout_ms: 10000 }),
            request: request.into(),
        };
        T::from_response(self.inner.ready().await?.call(wrapped_request).await?)
    }

    pub async fn get_masterchain_info(&mut self) -> Result<MasterchainInfo> {
        let response: MasterchainInfo = self.send_request(Request::GetMasterchainInfo).await?;
        Ok(response)
    }

    pub async fn get_masterchain_info_ext(&mut self, mode: u32) -> Result<MasterchainInfoExt> {
        let request = Request::GetMasterchainInfoExt(GetMasterchainInfoExt { mode });
        let response: MasterchainInfoExt = self.send_request(request).await?;
        Ok(response)
    }

    pub async fn get_time(&mut self) -> Result<u32> {
        let response: CurrentTime = self.send_request(Request::GetTime).await?;
        Ok(response.now)
    }

    pub async fn get_version(&mut self) -> Result<Version> {
        let response: Version = self.send_request(Request::GetVersion).await?;
        Ok(response)
    }

    pub async fn get_block(&mut self, id: BlockIdExt) -> Result<Vec<u8>> {
        let request = Request::GetBlock(GetBlock { id });
        let response: BlockData = self.send_request(request).await?;
        Ok(response.data)
    }

    pub async fn get_state(&mut self, id: BlockIdExt) -> Result<BlockState> {
        let request = Request::GetState(GetState { id });
        let response: BlockState = self.send_request(request).await?;
        Ok(response)
    }

pub async fn get_block_header(
    &mut self,
    id: BlockIdExt,
    with_state_update: bool,
    with_value_flow: bool,
    with_extra: bool,
    with_shard_hashes: bool,
    with_prev_blk_signatures: bool,
) -> Result<Vec<u8>> {
        let request = Request::GetBlockHeader(GetBlockHeader {
            id,
            mode: (),
            with_state_update: if with_state_update { Some(()) } else { None },
            with_value_flow: if with_value_flow { Some(()) } else { None },
            with_extra: if with_extra { Some(()) } else { None },
            with_shard_hashes: if with_shard_hashes { Some(()) } else { None },
            with_prev_blk_signatures: if with_prev_blk_signatures { Some(()) } else { None },
        });
        let response: BlockHeader = self.send_request(request).await?;
        Ok(response.header_proof)
    }

    pub async fn send_message(&mut self, body: Vec<u8>) -> Result<u32> {
        let request = Request::SendMessage(SendMessage { body });
        let response: SendMsgStatus = self.send_request(request).await?;
        Ok(response.status)
    }

    pub async fn get_account_state(&mut self, id: BlockIdExt, account: AccountId) -> Result<AccountState> {
        let request = Request::GetAccountState(GetAccountState { id, account });
        let response: AccountState = self.send_request(request).await?;
        Ok(response)
    }

    pub async fn run_smc_method(&mut self, mode: u32, id: BlockIdExt, account: AccountId, method_id: u64, params: Vec<u8>) -> Result<RunMethodResult> {
        let request = Request::RunSmcMethod(RunSmcMethod { mode, id, account, method_id, params });
        let response: RunMethodResult = self.send_request(request).await?;
        Ok(response)
    }

    pub async fn get_shard_info(&mut self, id: BlockIdExt, workchain: i32, shard: u64, exact: bool) -> Result<ShardInfo> {
        let request = Request::GetShardInfo(GetShardInfo { id, workchain, shard, exact });
        let response: ShardInfo = self.send_request(request).await?;
        Ok(response)
    }

    pub async fn get_all_shards_info(&mut self, id: BlockIdExt) -> Result<AllShardsInfo> {
        let request = Request::GetAllShardsInfo(GetAllShardsInfo { id });
        let response: AllShardsInfo = self.send_request(request).await?;
        Ok(response)
    }

    pub async fn get_one_transaction(&mut self, id: BlockIdExt, account: AccountId, lt: u64) -> Result<TransactionInfo> {
        let request = Request::GetOneTransaction(GetOneTransaction { id, account, lt });
        let response: TransactionInfo = self.send_request(request).await?;
        Ok(response)
    }

    pub async fn get_transactions(&mut self, count: u32, account: AccountId, lt: u64, hash: Int256) -> Result<TransactionList> {
        let request = Request::GetTransactions(GetTransactions { count, account, lt, hash });
        let response: TransactionList = self.send_request(request).await?;
        Ok(response)
    }

pub async fn lookup_block(
    &mut self,
    mode: (),
    id: BlockId,
    seqno: Option<()>,
    lt: Option<u64>,
    utime: Option<u32>,
    with_state_update: bool,
    with_value_flow: bool,
    with_extra: bool,
    with_shard_hashes: bool,
    with_prev_blk_signatures: bool,
) -> Result<BlockHeader> {
        let request = Request::LookupBlock(LookupBlock {
            mode,
            id,
            seqno,
            lt,
            utime,
        with_state_update: if with_state_update { Some(()) } else { None },
        with_value_flow: if with_value_flow { Some(()) } else { None },
        with_extra: if with_extra { Some(()) } else { None },
        with_shard_hashes: if with_shard_hashes { Some(()) } else { None },
        with_prev_blk_signatures: if with_prev_blk_signatures { Some(()) } else { None },
    });
        let response: BlockHeader = self.send_request(request).await?;
        Ok(response)
    }

pub async fn list_block_transactions(
    &mut self,
    id: BlockIdExt,
    count: u32,
    after: Option<TransactionId3>,
    reverse_order: bool,
    want_proof: bool
) -> Result<BlockTransactions> {
    let request = Request::ListBlockTransactions(ListBlockTransactions {
        id,
        mode: (),
        count,
        after,
        reverse_order: if reverse_order { Some(()) } else { None },
        want_proof: if want_proof { Some(()) } else { None },
    });
        let response: BlockTransactions = self.send_request(request).await?;
        Ok(response)
    }

pub async fn get_block_proof(
    &mut self,
    known_block: BlockIdExt,
    target_block: Option<BlockIdExt>,
    allow_weak_target: bool,
    base_block_from_request: bool
) -> Result<PartialBlockProof> {
        let request = Request::GetBlockProof(GetBlockProof {
            mode: (),
            known_block,
            target_block,
        allow_weak_target: if allow_weak_target { Some(()) } else { None },
        base_block_from_request: if base_block_from_request { Some(()) } else { None },
        });
        let response: PartialBlockProof = self.send_request(request).await?;
        Ok(response)
    }

pub async fn get_config_all(
    &mut self,
    id: BlockIdExt,
    with_state_root: bool,
    with_libraries: bool,
    with_state_extra_root: bool,
    with_shard_hashes: bool,
    with_validator_set: bool,
    with_special_smc: bool,
    with_accounts_root: bool,
    with_prev_blocks: bool,
    with_workchain_info: bool,
    with_capabilities: bool,
    extract_from_key_block: bool,
) -> Result<ConfigInfo> {
        let request = Request::GetConfigAll(GetConfigAll {
            mode: (),
            id,
            with_state_root: if with_state_root { Some(()) } else { None },
            with_libraries: if with_libraries { Some(()) } else { None },
            with_state_extra_root: if with_state_extra_root { Some(()) } else { None },
            with_shard_hashes: if with_shard_hashes { Some(()) } else { None },
            with_validator_set: if with_validator_set { Some(()) } else { None },
            with_special_smc: if with_special_smc { Some(()) } else { None },
            with_accounts_root: if with_accounts_root { Some(()) } else { None },
            with_prev_blocks: if with_prev_blocks { Some(()) } else { None },
            with_workchain_info: if with_workchain_info { Some(()) } else { None },
            with_capabilities: if with_capabilities { Some(()) } else { None },
            extract_from_key_block: if extract_from_key_block { Some(()) } else { None },
        });
        let response: ConfigInfo = self.send_request(request).await?;
        Ok(response)
    }

pub async fn get_config_params(
    &mut self,
    id: BlockIdExt,
    param_list: Vec<i32>,
    with_state_root: bool,
    with_libraries: bool,
    with_state_extra_root: bool,
    with_shard_hashes: bool,
    with_validator_set: bool,
    with_special_smc: bool,
    with_accounts_root: bool,
    with_prev_blocks: bool,
    with_workchain_info: bool,
    with_capabilities: bool,
    extract_from_key_block: bool,
) -> Result<ConfigInfo> {
        let request = Request::GetConfigParams(GetConfigParams {
            mode: (),
            id,
            param_list,
            with_state_root: if with_state_root { Some(()) } else { None },
            with_libraries: if with_libraries { Some(()) } else { None },
            with_state_extra_root: if with_state_extra_root { Some(()) } else { None },
            with_shard_hashes: if with_shard_hashes { Some(()) } else { None },
            with_validator_set: if with_validator_set { Some(()) } else { None },
            with_special_smc: if with_special_smc { Some(()) } else { None },
            with_accounts_root: if with_accounts_root { Some(()) } else { None },
            with_prev_blocks: if with_prev_blocks { Some(()) } else { None },
            with_workchain_info: if with_workchain_info { Some(()) } else { None },
            with_capabilities: if with_capabilities { Some(()) } else { None },
            extract_from_key_block: if extract_from_key_block { Some(()) } else { None },
        });
        let response: ConfigInfo = self.send_request(request).await?;
        Ok(response)
    }

    pub async fn get_validator_stats(&mut self, id: BlockIdExt, limit: u32, start_after: Option<Int256>, modified_after: Option<u32>) -> Result<ValidatorStats> {
        let request = Request::GetValidatorStats(GetValidatorStats { mode: (), id, limit, start_after, modified_after });
        let response: ValidatorStats = self.send_request(request).await?;
        Ok(response)
    }

    pub async fn get_libraries(&mut self, library_list: Vec<Int256>) -> Result<Vec<LibraryEntry>> {
        let request = Request::GetLibraries(GetLibraries { library_list });
        let response: LibraryResult = self.send_request(request).await?;
        Ok(response.result)
    }
}