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