whisky_provider/maestro/
evaluator.rs1use async_trait::async_trait;
2use whisky_csl::{calculate_tx_hash, CSLParser};
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], 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 tx_hash = calculate_tx_hash(tx).unwrap();
38 let utxos = CSLParser::extract_output_cbors(tx).unwrap();
39 utxos
40 .into_iter()
41 .enumerate()
42 .map(|(index, txout_cbor)| AdditionalUtxo {
43 tx_hash: tx_hash.clone(),
44 index: index as u32,
45 txout_cbor,
46 })
47 .collect::<Vec<AdditionalUtxo>>()
48 })
49 .collect();
50
51 let url = "/transactions/evaluate";
52 let body = EvaluateTx {
53 cbor: tx.to_string(),
54 additional_utxos: tx_out_cbors,
55 };
56
57 let resp = self
58 .maestro_client
59 .post(url, &body)
60 .await
61 .map_err(WError::from_err("Maestro - evaluate_tx"))?;
62
63 let result: Vec<Action> = serde_json::from_str::<Vec<RedeemerEvaluation>>(&resp)
64 .map_err(WError::from_err("Maestro - evaluate_tx"))?
65 .iter()
66 .map(|r: &RedeemerEvaluation| Action {
67 index: r.redeemer_index as u32,
68 budget: Budget {
69 mem: r.ex_units.mem as u64,
70 steps: r.ex_units.steps as u64,
71 },
72 tag: match r.redeemer_tag.as_str() {
73 "spend" => RedeemerTag::Spend,
74 "mint" => RedeemerTag::Mint,
75 "cert" => RedeemerTag::Cert,
76 "wdrl" => RedeemerTag::Reward,
77 _ => panic!("Unknown redeemer tag from maestro service"),
78 },
79 })
80 .collect();
81 Ok(result)
82 }
83}