whisky_provider/maestro/
evaluator.rs

1use async_trait::async_trait;
2use whisky_csl::{calculate_tx_hash, TxParser};
3
4use uplc::tx::SlotConfig;
5use whisky_common::models::{Network, UTxO};
6
7use whisky_common::*;
8
9use super::*;
10
11#[derive(Serialize)]
12pub struct AdditionalUtxo {
13    pub tx_hash: String,
14    pub index: u32,
15    pub txout_cbor: String,
16}
17
18#[derive(Serialize)]
19pub struct EvaluateTx {
20    cbor: String,
21    additional_utxos: Vec<AdditionalUtxo>,
22}
23
24#[async_trait]
25impl Evaluator for MaestroProvider {
26    async fn evaluate_tx(
27        &self,
28        tx: &str,
29        _inputs: &[UTxO], // TODO: parse this also into additional_txs
30        additional_txs: &[String],
31        _network: &Network,
32        _slot_config: &SlotConfig,
33    ) -> Result<Vec<Action>, WError> {
34        let tx_out_cbors: Vec<AdditionalUtxo> = additional_txs
35            .iter()
36            .flat_map(|tx| {
37                let parsed_tx = TxParser::new(tx);
38                parsed_tx
39                    .unwrap() //TODO: add error handling
40                    .get_tx_outs_cbor()
41                    .iter()
42                    .enumerate() // Add this line to get the index
43                    .map(|(index, txout_cbor)| AdditionalUtxo {
44                        tx_hash: calculate_tx_hash(tx).unwrap(), // TODO: add error handling
45                        index: index as u32,                     // Use the index here
46                        txout_cbor: txout_cbor.to_string(),
47                    })
48                    .collect::<Vec<AdditionalUtxo>>()
49            })
50            .collect();
51
52        let url = "/transactions/evaluate";
53        let body = EvaluateTx {
54            cbor: tx.to_string(),
55            additional_utxos: tx_out_cbors,
56        };
57
58        let resp = self
59            .maestro_client
60            .post(url, &body)
61            .await
62            .map_err(WError::from_err("Maestro - evaluate_tx"))?;
63
64        let result: Vec<Action> = serde_json::from_str::<Vec<RedeemerEvaluation>>(&resp)
65            .map_err(WError::from_err("Maestro - evaluate_tx"))?
66            .iter()
67            .map(|r: &RedeemerEvaluation| Action {
68                index: r.redeemer_index as u32,
69                budget: Budget {
70                    mem: r.ex_units.mem as u64,
71                    steps: r.ex_units.steps as u64,
72                },
73                tag: match r.redeemer_tag.as_str() {
74                    "spend" => RedeemerTag::Spend,
75                    "mint" => RedeemerTag::Mint,
76                    "cert" => RedeemerTag::Cert,
77                    "wdrl" => RedeemerTag::Reward,
78                    _ => panic!("Unknown redeemer tag from maestro service"),
79                },
80            })
81            .collect();
82        Ok(result)
83    }
84}