partner_chains_cardano_offchain/reserve/
mod.rs1use crate::{
4 csl::{OgmiosUtxoExt, OgmiosValueExt, TransactionContext},
5 scripts_data,
6 versioning_system::find_script_utxo,
7};
8use anyhow::anyhow;
9use cardano_serialization_lib::{
10 ExUnits, JsError, PlutusScriptSource, PlutusWitness, Redeemer, RedeemerTag, TxInputsBuilder,
11};
12use ogmios_client::{query_ledger_state::QueryLedgerState, types::OgmiosUtxo};
13use partner_chains_plutus_data::reserve::{ReserveDatum, ReserveRedeemer};
14use sidechain_domain::{AssetId, AssetName, UtxoId};
15
16pub mod create;
17pub mod deposit;
18pub mod handover;
19pub mod init;
20pub mod release;
21pub mod update_settings;
22
23#[derive(Clone, Debug)]
24pub(crate) struct ReserveData {
25 pub(crate) scripts: scripts_data::ReserveScripts,
26 pub(crate) auth_policy_version_utxo: OgmiosUtxo,
27 pub(crate) validator_version_utxo: OgmiosUtxo,
28}
29
30#[derive(Clone, Debug)]
31pub(crate) struct ReserveUtxo {
32 pub(crate) utxo: OgmiosUtxo,
33 pub(crate) datum: ReserveDatum,
34}
35
36impl ReserveData {
37 pub(crate) async fn get<T: QueryLedgerState>(
38 genesis_utxo: UtxoId,
39 ctx: &TransactionContext,
40 client: &T,
41 ) -> Result<Self, anyhow::Error> {
42 let version_oracle = scripts_data::version_oracle(genesis_utxo, ctx.network)?;
43 let auth_policy_version_utxo = find_script_utxo(
44 raw_scripts::ScriptId::ReserveAuthPolicy,
45 &version_oracle,
46 ctx,
47 client,
48 )
49 .await?
50 .ok_or_else(|| {
51 anyhow!(
52 "Reserve Auth Version Utxo not found, is the Reserve Token Management initialized?"
53 )
54 })?;
55 let validator_version_utxo =
56 find_script_utxo(raw_scripts::ScriptId::ReserveValidator, &version_oracle, ctx, client)
57 .await?
58 .ok_or_else(|| {
59 anyhow!(
60 "Reserve Validator Version Utxo not found, is the Reserve Token Management initialized?"
61 )
62 })?;
63 let scripts = scripts_data::reserve_scripts(genesis_utxo, ctx.network)?;
64 Ok(ReserveData { scripts, auth_policy_version_utxo, validator_version_utxo })
65 }
66
67 pub(crate) async fn get_reserve_utxo<T: QueryLedgerState>(
68 &self,
69 ctx: &TransactionContext,
70 client: &T,
71 ) -> Result<ReserveUtxo, anyhow::Error> {
72 let validator_address = self.scripts.validator.address(ctx.network).to_bech32(None)?;
73 let validator_utxos = client.query_utxos(&[validator_address]).await?;
74
75 let auth_token_asset_id = AssetId {
76 policy_id: self.scripts.auth_policy.policy_id(),
77 asset_name: AssetName::empty(),
78 };
79
80 let (reserve_utxo, reserve_settings) = validator_utxos
81 .into_iter()
82 .find_map(|utxo| {
83 if utxo.get_asset_amount(&auth_token_asset_id) != 1u64 {
84 return None;
85 }
86 utxo.get_plutus_data()
87 .and_then(|d| ReserveDatum::try_from(d).ok())
88 .map(|d| (utxo, d))
89 })
90 .ok_or_else(|| {
91 anyhow!("Reserve Utxo not found, is the Reserve Token Management initialized?")
92 })?;
93
94 Ok(ReserveUtxo { utxo: reserve_utxo, datum: reserve_settings })
95 }
96}
97
98pub(crate) fn reserve_utxo_input_with_validator_script_reference(
99 reserve_utxo: &OgmiosUtxo,
100 reserve: &ReserveData,
101 redeemer: ReserveRedeemer,
102 cost: &ExUnits,
103) -> Result<TxInputsBuilder, JsError> {
104 let mut inputs = TxInputsBuilder::new();
105 add_reserve_utxo_input_with_validator_script_reference(
106 &mut inputs,
107 reserve_utxo,
108 reserve,
109 redeemer,
110 cost,
111 )?;
112 Ok(inputs)
113}
114
115pub(crate) fn add_reserve_utxo_input_with_validator_script_reference(
116 inputs: &mut TxInputsBuilder,
117 reserve_utxo: &OgmiosUtxo,
118 reserve: &ReserveData,
119 redeemer: ReserveRedeemer,
120 cost: &ExUnits,
121) -> Result<(), JsError> {
122 let input = reserve_utxo.to_csl_tx_input();
123 let amount = reserve_utxo.value.to_csl()?;
124 let script = &reserve.scripts.validator;
125 let witness = PlutusWitness::new_with_ref_without_datum(
126 &PlutusScriptSource::new_ref_input(
127 &script.csl_script_hash(),
128 &reserve.validator_version_utxo.to_csl_tx_input(),
129 &script.language,
130 script.bytes.len(),
131 ),
132 &Redeemer::new(&RedeemerTag::new_spend(), &0u32.into(), &redeemer.into(), cost),
133 );
134 inputs.add_plutus_script_input(&witness, &input, &amount);
135 Ok(())
136}