Skip to main content

polyester/services/
balances.rs

1use super::ServiceContext;
2use super::scope;
3use super::unary;
4use crate::codecs::decode::{
5    balance_history_from_proto, balances_list_from_proto, equity_history_from_proto,
6    holds_list_from_proto, transfers_list_from_proto,
7};
8use crate::connect::ledger::read::v1::LedgerReadServiceClient;
9use crate::errors::Result;
10use crate::models::{
11    AssetBalance, BalanceHistory, BalancesList, EquityHistory, HoldsList, TransfersList,
12};
13use crate::proto::ledger::read::v1::{
14    GetBalanceHistoryRequest, GetBalancesRequest, GetEquityHistorySeriesRequest,
15};
16
17#[derive(Clone)]
18pub struct BalancesService {
19    ctx: ServiceContext,
20}
21
22impl BalancesService {
23    pub fn new(ctx: ServiceContext) -> Self {
24        Self { ctx }
25    }
26
27    fn client(&self) -> LedgerReadServiceClient<crate::transport::SharedTransport> {
28        LedgerReadServiceClient::new(
29            self.ctx.factory.transport(),
30            self.ctx.factory.connect_config(),
31        )
32    }
33
34    pub async fn list(&self, req: GetBalancesRequest) -> Result<BalancesList> {
35        let client = self.client();
36        let resp = unary::await_auth(
37            &self.ctx.factory,
38            "/ledger.read.v1.LedgerReadService/GetBalances",
39            req,
40            |req, opts| client.get_balances_with_options(req, opts),
41        )
42        .await?
43        .into_owned();
44        Ok(balances_list_from_proto(&resp))
45    }
46
47    pub async fn get_balance_history(
48        &self,
49        req: GetBalanceHistoryRequest,
50    ) -> Result<BalanceHistory> {
51        let client = self.client();
52        let resp = unary::await_auth(
53            &self.ctx.factory,
54            "/ledger.read.v1.LedgerReadService/GetBalanceHistory",
55            req,
56            |req, opts| client.get_balance_history_with_options(req, opts),
57        )
58        .await?
59        .into_owned();
60        Ok(balance_history_from_proto(&resp))
61    }
62
63    pub async fn get_equity_history(
64        &self,
65        req: GetEquityHistorySeriesRequest,
66    ) -> Result<EquityHistory> {
67        let client = self.client();
68        let resp = unary::await_auth(
69            &self.ctx.factory,
70            "/ledger.read.v1.LedgerReadService/GetEquityHistorySeries",
71            req,
72            |req, opts| client.get_equity_history_series_with_options(req, opts),
73        )
74        .await?
75        .into_owned();
76        Ok(equity_history_from_proto(&resp))
77    }
78
79    pub async fn list_transfers(
80        &self,
81        req: crate::proto::ledger::read::v1::ListTransfersRequest,
82    ) -> Result<TransfersList> {
83        let client = self.client();
84        let resp = unary::await_auth(
85            &self.ctx.factory,
86            "/ledger.read.v1.LedgerReadService/ListTransfers",
87            req,
88            |req, opts| client.list_transfers_with_options(req, opts),
89        )
90        .await?
91        .into_owned();
92        Ok(transfers_list_from_proto(&resp))
93    }
94
95    pub async fn list_holds(
96        &self,
97        req: crate::proto::ledger::read::v1::ListHoldsRequest,
98    ) -> Result<HoldsList> {
99        let client = self.client();
100        let resp = unary::await_auth(
101            &self.ctx.factory,
102            "/ledger.read.v1.LedgerReadService/ListHolds",
103            req,
104            |req, opts| client.list_holds_with_options(req, opts),
105        )
106        .await?
107        .into_owned();
108        Ok(holds_list_from_proto(&resp))
109    }
110
111    /// Subscribe to private balance updates (requires `realtime` feature).
112    pub async fn subscribe(
113        &self,
114        account_id: Option<&str>,
115    ) -> Result<crate::realtime::TypedSubscription<AssetBalance>> {
116        let account = scope::resolve_account_id(&self.ctx, account_id)?;
117        let channel = format!("private:ledger:balances:{account}:proto");
118        self.ctx
119            .realtime
120            .subscribe_proto(&channel, crate::codecs::decode::asset_balance_from_bytes)
121            .await
122    }
123}