partner_chains_cardano_offchain/reserve/
deposit.rs1use super::{ReserveData, TokenAmount, reserve_utxo_input_with_validator_script_reference};
19use crate::{
20 await_tx::AwaitTx,
21 cardano_keys::CardanoPaymentSigningKey,
22 csl::{
23 CostStore, Costs, MultiAssetExt, OgmiosUtxoExt, TransactionBuilderExt, TransactionContext,
24 TransactionExt, TransactionOutputAmountBuilderExt, get_builder_config,
25 },
26 governance::GovernanceData,
27 multisig::{MultiSigSmartContractResult, submit_or_create_tx_to_sign},
28 scripts_data::ReserveScripts,
29};
30use cardano_serialization_lib::{
31 JsError, MultiAsset, Transaction, TransactionBuilder, TransactionOutput,
32 TransactionOutputBuilder,
33};
34use ogmios_client::{
35 query_ledger_state::{QueryLedgerState, QueryUtxoByUtxoId},
36 query_network::QueryNetwork,
37 transactions::Transactions,
38 types::OgmiosUtxo,
39};
40use partner_chains_plutus_data::reserve::ReserveRedeemer;
41use sidechain_domain::{AssetId, UtxoId};
42
43pub async fn deposit_to_reserve<
45 T: QueryLedgerState + Transactions + QueryNetwork + QueryUtxoByUtxoId,
46 A: AwaitTx,
47>(
48 amount: u64,
49 genesis_utxo: UtxoId,
50 payment_key: &CardanoPaymentSigningKey,
51 client: &T,
52 await_tx: &A,
53) -> anyhow::Result<MultiSigSmartContractResult> {
54 let payment_context = TransactionContext::for_payment_key(payment_key, client).await?;
55 let governance = GovernanceData::get(genesis_utxo, client).await?;
56 let reserve = ReserveData::get(genesis_utxo, &payment_context, client).await?;
57 let reserve_utxo = reserve.get_reserve_utxo(&payment_context, client).await?;
58 let utxo = reserve_utxo.utxo;
59 let token = reserve_utxo.datum.immutable_settings.token;
60 let current_amount = get_token_amount(&utxo, &token);
61 let token_amount = TokenAmount { token, amount: current_amount + amount };
62
63 submit_or_create_tx_to_sign(
64 &governance,
65 payment_context,
66 |costs, ctx| {
67 deposit_to_reserve_tx(&token_amount, &utxo, &reserve, &governance, costs, &ctx)
68 },
69 "Deposit to Reserve",
70 client,
71 await_tx,
72 )
73 .await
74}
75
76fn get_token_amount(utxo: &OgmiosUtxo, token: &AssetId) -> u64 {
77 let AssetId { policy_id, asset_name } = token;
78 utxo.value
79 .native_tokens
80 .get(&policy_id.0)
81 .and_then(|assets| assets.iter().find(|asset| asset.name == asset_name.0.to_vec()))
82 .map(|asset| asset.amount)
83 .unwrap_or(0) }
85
86fn deposit_to_reserve_tx(
87 parameters: &TokenAmount,
88 current_utxo: &OgmiosUtxo,
89 reserve: &ReserveData,
90 governance: &GovernanceData,
91 costs: Costs,
92 ctx: &TransactionContext,
93) -> anyhow::Result<Transaction> {
94 let mut tx_builder = TransactionBuilder::new(&get_builder_config(ctx)?);
95
96 tx_builder.add_output(&validator_output(parameters, current_utxo, &reserve.scripts, ctx)?)?;
97
98 tx_builder.set_inputs(&reserve_utxo_input_with_validator_script_reference(
99 current_utxo,
100 reserve,
101 ReserveRedeemer::DepositToReserve,
102 &costs.get_one_spend(),
103 )?);
104
105 tx_builder.add_mint_one_script_token_using_reference_script(
106 &governance.policy.script(),
107 &governance.utxo_id_as_tx_input(),
108 &costs,
109 )?;
110
111 tx_builder.add_script_reference_input(
112 &reserve.auth_policy_version_utxo.to_csl_tx_input(),
113 reserve.scripts.auth_policy.bytes.len(),
114 );
115 tx_builder.add_script_reference_input(
116 &reserve.illiquid_circulation_supply_validator_version_utxo.to_csl_tx_input(),
117 reserve.scripts.illiquid_circulation_supply_validator.bytes.len(),
118 );
119 Ok(tx_builder.balance_update_and_build(ctx)?.remove_native_script_witnesses())
120}
121
122fn validator_output(
124 token_amount: &TokenAmount,
125 current_utxo: &OgmiosUtxo,
126 scripts: &ReserveScripts,
127 ctx: &TransactionContext,
128) -> Result<TransactionOutput, JsError> {
129 let amount_builder = TransactionOutputBuilder::new()
130 .with_address(&scripts.validator.address(ctx.network))
131 .with_plutus_data(
132 ¤t_utxo
133 .get_plutus_data()
134 .expect("Current UTXO datum was parsed hence it exists"),
135 )
136 .next()?;
137 let ma = MultiAsset::new()
138 .with_asset_amount(&token_amount.token, token_amount.amount)?
139 .with_asset_amount(&scripts.auth_policy.empty_name_asset(), 1u64)?;
140
141 amount_builder.with_minimum_ada_and_asset(&ma, ctx)?.build()
142}