partner_chains_cardano_offchain/reserve/
create.rs1use super::ReserveData;
19use crate::csl::unit_plutus_data;
20use crate::reserve::create::Script::Plutus;
21use crate::{
22 await_tx::AwaitTx,
23 cardano_keys::CardanoPaymentSigningKey,
24 csl::{
25 Costs, MultiAssetExt, OgmiosUtxoExt, Script, TransactionBuilderExt, TransactionContext,
26 TransactionExt, TransactionOutputAmountBuilderExt, get_builder_config,
27 },
28 governance::GovernanceData,
29 multisig::{MultiSigSmartContractResult, submit_or_create_tx_to_sign},
30 scripts_data::ReserveScripts,
31};
32use cardano_serialization_lib::{
33 Int, JsError, MultiAsset, Transaction, TransactionBuilder, TransactionOutput,
34 TransactionOutputBuilder,
35};
36use ogmios_client::{
37 query_ledger_state::{QueryLedgerState, QueryUtxoByUtxoId},
38 query_network::QueryNetwork,
39 transactions::Transactions,
40};
41use partner_chains_plutus_data::reserve::{
42 ReserveDatum, ReserveImmutableSettings, ReserveMutableSettings, ReserveStats,
43};
44use sidechain_domain::{AssetId, PolicyId, UtxoId};
45use std::num::NonZero;
46
47pub async fn create_reserve_utxo<
49 T: QueryLedgerState + Transactions + QueryNetwork + QueryUtxoByUtxoId,
50 A: AwaitTx,
51>(
52 parameters: ReserveParameters,
53 genesis_utxo: UtxoId,
54 payment_key: &CardanoPaymentSigningKey,
55 client: &T,
56 await_tx: &A,
57) -> anyhow::Result<MultiSigSmartContractResult> {
58 let payment_ctx = TransactionContext::for_payment_key(payment_key, client).await?;
59 let governance = GovernanceData::get(genesis_utxo, client).await?;
60 let reserve = ReserveData::get(genesis_utxo, &payment_ctx, client).await?;
61
62 submit_or_create_tx_to_sign(
63 &governance,
64 payment_ctx,
65 |costs, ctx| create_reserve_tx(¶meters, &reserve, &governance, costs, &ctx),
66 "Create Reserve",
67 client,
68 await_tx,
69 )
70 .await
71}
72
73pub struct ReserveParameters {
75 pub total_accrued_function_script_hash: PolicyId,
77 pub token: AssetId,
79 pub initial_deposit: u64,
81 pub ics_initial_utxos_amount: NonZero<u64>,
83}
84
85impl From<&ReserveParameters> for ReserveDatum {
86 fn from(value: &ReserveParameters) -> Self {
87 ReserveDatum {
88 immutable_settings: ReserveImmutableSettings { token: value.token.clone() },
89 mutable_settings: ReserveMutableSettings {
90 total_accrued_function_asset_name: value.total_accrued_function_script_hash.clone(),
91 initial_incentive: 0,
94 },
95 stats: ReserveStats { token_total_amount_transferred: 0 },
96 }
97 }
98}
99
100fn create_reserve_tx(
101 parameters: &ReserveParameters,
102 reserve: &ReserveData,
103 governance: &GovernanceData,
104 costs: Costs,
105 ctx: &TransactionContext,
106) -> anyhow::Result<Transaction> {
107 let mut tx_builder = TransactionBuilder::new(&get_builder_config(ctx)?);
108
109 tx_builder.add_mint_one_script_token_using_reference_script(
110 &Script::Plutus(reserve.scripts.auth_policy.clone()),
111 &reserve.auth_policy_version_utxo.to_csl_tx_input(),
112 &costs,
113 )?;
114 tx_builder.add_output(&reserve_validator_output(parameters, &reserve.scripts, ctx)?)?;
115
116 let gov_tx_input = governance.utxo_id_as_tx_input();
117 tx_builder.add_mint_one_script_token_using_reference_script(
118 &governance.policy.script(),
119 &gov_tx_input,
120 &costs,
121 )?;
122 tx_builder.add_script_reference_input(
123 &reserve.validator_version_utxo.to_csl_tx_input(),
124 reserve.scripts.validator.bytes.len(),
125 );
126
127 tx_builder.add_mint_script_token_using_reference_script(
128 &Plutus(reserve.scripts.illiquid_circulation_supply_auth_token_policy.clone()),
129 &reserve
130 .illiquid_circulation_supply_authority_token_policy_version_utxo
131 .to_csl_tx_input(),
132 &Int::new(¶meters.ics_initial_utxos_amount.get().into()),
133 &costs,
134 )?;
135 for _ in 0..parameters.ics_initial_utxos_amount.into() {
138 tx_builder.add_output(&ics_validator_output(&reserve.scripts, ctx)?)?;
139 }
140
141 let tx = tx_builder.balance_update_and_build(ctx)?.remove_native_script_witnesses();
142
143 Ok(tx)
144}
145
146fn reserve_validator_output(
148 parameters: &ReserveParameters,
149 scripts: &ReserveScripts,
150 ctx: &TransactionContext,
151) -> Result<TransactionOutput, JsError> {
152 let amount_builder = TransactionOutputBuilder::new()
153 .with_address(&scripts.validator.address(ctx.network))
154 .with_plutus_data(&ReserveDatum::from(parameters).into())
155 .next()?;
156 let ma = MultiAsset::new()
157 .with_asset_amount(&scripts.auth_policy.empty_name_asset(), 1u64)?
158 .with_asset_amount(¶meters.token, parameters.initial_deposit)?;
159
160 amount_builder.with_minimum_ada_and_asset(&ma, ctx)?.build()
161}
162
163fn ics_validator_output(
164 scripts: &ReserveScripts,
165 ctx: &TransactionContext,
166) -> Result<TransactionOutput, JsError> {
167 let amount_builder = TransactionOutputBuilder::new()
168 .with_address(&scripts.illiquid_circulation_supply_validator.address(ctx.network))
169 .with_plutus_data(&unit_plutus_data())
170 .next()?;
171 let ma = MultiAsset::new().with_asset_amount(
172 &scripts.illiquid_circulation_supply_auth_token_policy.empty_name_asset(),
173 1u64,
174 )?;
175
176 amount_builder.with_minimum_ada_and_asset(&ma, ctx)?.build()
177}