balius_runtime/ledgers/
u5c.rs

1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4use utxorpc::CardanoQueryClient;
5
6use crate::wit::balius::app::ledger as wit;
7
8impl From<utxorpc::Error> for crate::Error {
9    fn from(error: utxorpc::Error) -> Self {
10        crate::Error::Ledger(error.to_string())
11    }
12}
13
14impl From<utxorpc::Error> for wit::LedgerError {
15    fn from(error: utxorpc::Error) -> Self {
16        wit::LedgerError::Upstream(error.to_string())
17    }
18}
19
20impl From<wit::TxoRef> for utxorpc::spec::query::TxoRef {
21    fn from(value: wit::TxoRef) -> Self {
22        utxorpc::spec::query::TxoRef {
23            hash: value.tx_hash.into(),
24            index: value.tx_index,
25        }
26    }
27}
28
29impl From<utxorpc::spec::query::TxoRef> for wit::TxoRef {
30    fn from(value: utxorpc::spec::query::TxoRef) -> Self {
31        wit::TxoRef {
32            tx_hash: value.hash.into(),
33            tx_index: value.index,
34        }
35    }
36}
37
38impl From<utxorpc::ChainUtxo<utxorpc::spec::cardano::TxOutput>> for wit::Utxo {
39    fn from(value: utxorpc::ChainUtxo<utxorpc::spec::cardano::TxOutput>) -> Self {
40        wit::Utxo {
41            body: value.native.into(),
42            ref_: value.txo_ref.unwrap_or_default().into(),
43        }
44    }
45}
46
47impl From<wit::AddressPattern> for utxorpc::spec::cardano::AddressPattern {
48    fn from(value: wit::AddressPattern) -> Self {
49        utxorpc::spec::cardano::AddressPattern {
50            exact_address: value.exact_address.into(),
51            ..Default::default()
52        }
53    }
54}
55
56impl From<wit::AssetPattern> for utxorpc::spec::cardano::AssetPattern {
57    fn from(value: wit::AssetPattern) -> Self {
58        utxorpc::spec::cardano::AssetPattern {
59            policy_id: value.policy.into(),
60            asset_name: value.name.map(|n| n.into()).unwrap_or_default(),
61        }
62    }
63}
64
65impl From<wit::UtxoPattern> for utxorpc::spec::cardano::TxOutputPattern {
66    fn from(value: wit::UtxoPattern) -> Self {
67        utxorpc::spec::cardano::TxOutputPattern {
68            address: value.address.map(|a| a.into()),
69            asset: value.asset.map(|a| a.into()),
70        }
71    }
72}
73
74impl From<utxorpc::UtxoPage<utxorpc::Cardano>> for wit::UtxoPage {
75    fn from(value: utxorpc::UtxoPage<utxorpc::Cardano>) -> Self {
76        wit::UtxoPage {
77            utxos: value.items.into_iter().map(|u| u.into()).collect(),
78            next_token: value.next,
79        }
80    }
81}
82
83#[derive(Clone, Serialize, Deserialize, Debug)]
84pub struct Config {
85    pub endpoint_url: String,
86    pub headers: Option<HashMap<String, String>>,
87}
88
89#[derive(Clone)]
90pub struct Ledger {
91    queries: utxorpc::CardanoQueryClient,
92}
93
94impl Ledger {
95    pub async fn new(config: &Config) -> Result<Self, crate::Error> {
96        let mut builder = utxorpc::ClientBuilder::new().uri(&config.endpoint_url)?;
97        if let Some(headers) = &config.headers {
98            for (k, v) in headers.iter() {
99                builder = builder.metadata(k, v)?;
100            }
101        }
102
103        let queries = builder.build::<CardanoQueryClient>().await;
104
105        Ok(Self { queries })
106    }
107
108    pub async fn read_utxos(
109        &mut self,
110        refs: Vec<wit::TxoRef>,
111    ) -> Result<Vec<wit::Utxo>, wit::LedgerError> {
112        let refs = refs.into_iter().map(|r| r.into()).collect();
113        let utxos = self.queries.read_utxos(refs).await?;
114        Ok(utxos.into_iter().map(|u| u.into()).collect())
115    }
116
117    pub async fn search_utxos(
118        &mut self,
119        pattern: wit::UtxoPattern,
120        start: Option<String>,
121        max_items: u32,
122    ) -> Result<wit::UtxoPage, wit::LedgerError> {
123        let pattern = pattern.into();
124        let utxos = self.queries.match_utxos(pattern, start, max_items).await?;
125        Ok(utxos.into())
126    }
127
128    pub async fn read_params(&mut self) -> Result<wit::Json, wit::LedgerError> {
129        let req = utxorpc::spec::query::ReadParamsRequest::default();
130        let res = self
131            .queries
132            .read_params(req)
133            .await
134            .map_err(|err| wit::LedgerError::Upstream(format!("{err:?}")))?
135            .into_inner();
136
137        let params = res
138            .values
139            .and_then(|v| v.params)
140            .ok_or(wit::LedgerError::Upstream(
141                "unexpected response from read_params".to_string(),
142            ))?;
143        match params {
144            utxorpc::spec::query::any_chain_params::Params::Cardano(params) => {
145                Ok(serde_json::to_vec(&params).unwrap())
146            }
147            #[allow(unreachable_patterns)]
148            _ => Err(wit::LedgerError::Upstream(
149                "unexpected response from read_params".to_string(),
150            )),
151        }
152    }
153}