diff --git a/cardano_clusterlib/structs.py b/cardano_clusterlib/structs.py index 71a399c..b92ce1d 100644 --- a/cardano_clusterlib/structs.py +++ b/cardano_clusterlib/structs.py @@ -248,6 +248,8 @@ class TxRawOutput: mint: OptionalMint = () # Minting data (Tx outputs, script, etc.) invalid_hereafter: tp.Optional[int] = None # Validity interval upper bound invalid_before: tp.Optional[int] = None # Validity interval lower bound + current_treasury_value: tp.Optional[int] = None # Current treasury value + treasury_donation: tp.Optional[int] = None # Amount of funds that will be donated to treasury withdrawals: OptionalTxOuts = () # All withdrawals (including those combined with scripts) change_address: str = "" # Address for change return_collateral_txouts: OptionalTxOuts = () # Tx outputs for returning collateral diff --git a/cardano_clusterlib/transaction_group.py b/cardano_clusterlib/transaction_group.py index 06ff90c..b6be2bb 100644 --- a/cardano_clusterlib/transaction_group.py +++ b/cardano_clusterlib/transaction_group.py @@ -167,6 +167,8 @@ def build_raw_tx_bare( # noqa: C901 script_votes: structs.OptionalScriptVotes = (), invalid_hereafter: tp.Optional[int] = None, invalid_before: tp.Optional[int] = None, + current_treasury_value: tp.Optional[int] = None, + treasury_donation: tp.Optional[int] = None, script_valid: bool = True, join_txouts: bool = True, ) -> structs.TxRawOutput: @@ -202,6 +204,8 @@ def build_raw_tx_bare( # noqa: C901 script_votes: An iterable of `ScriptVote`, specifying vote script data (optional). invalid_hereafter: A last block when the transaction is still valid (optional). invalid_before: A first block when the transaction is valid (optional). + current_treasury_value: The current treasury value (optional). + treasury_donation: A donation to the treasury to perform (optional). script_valid: A bool indicating that the script is valid (True by default). join_txouts: A bool indicating whether to aggregate transaction outputs by payment address (True by default). @@ -210,6 +214,10 @@ def build_raw_tx_bare( # noqa: C901 structs.TxRawOutput: A tuple with transaction output details. """ # pylint: disable=too-many-arguments,too-many-branches,too-many-locals,too-many-statements + if (treasury_donation is not None) != (current_treasury_value is not None): + msg="Both `treasury_donation` and `current_treasury_value` must be specified together." + raise ValueError(msg) + if tx_files.certificate_files and complex_certs: LOGGER.warning( "Mixing `tx_files.certificate_files` and `complex_certs`, " @@ -252,6 +260,11 @@ def build_raw_tx_bare( # noqa: C901 # `--ttl` and `--invalid-hereafter` are the same misc_args.extend(["--ttl", str(ttl)]) + if current_treasury_value is not None: + misc_args.extend(["--current-treasury-value", str(current_treasury_value)]) + if treasury_donation is not None: + misc_args.extend(["--treasury-donation", str(treasury_donation)]) + if not script_valid: misc_args.append("--script-invalid") @@ -340,6 +353,8 @@ def build_raw_tx_bare( # noqa: C901 mint=mint, invalid_hereafter=invalid_hereafter or ttl, invalid_before=invalid_before, + current_treasury_value=current_treasury_value, + treasury_donation=treasury_donation, withdrawals=withdrawals, return_collateral_txouts=return_collateral_txouts, total_collateral_amount=total_collateral_amount, @@ -378,6 +393,8 @@ def build_raw_tx( script_withdrawals: structs.OptionalScriptWithdrawals = (), script_votes: structs.OptionalScriptVotes = (), deposit: tp.Optional[int] = None, + current_treasury_value: tp.Optional[int] = None, + treasury_donation: tp.Optional[int] = None, invalid_hereafter: tp.Optional[int] = None, invalid_before: tp.Optional[int] = None, join_txouts: bool = True, @@ -416,6 +433,8 @@ def build_raw_tx( data (optional). script_votes: An iterable of `ScriptVote`, specifying vote script data (optional). deposit: A deposit amount needed by the transaction (optional). + current_treasury_value: The current treasury value (optional). + treasury_donation: A donation to the treasury to perform (optional). invalid_hereafter: A last block when the transaction is still valid (optional). invalid_before: A first block when the transaction is valid (optional). join_txouts: A bool indicating whether to aggregate transaction outputs @@ -426,6 +445,10 @@ def build_raw_tx( structs.TxRawOutput: A tuple with transaction output details. """ # pylint: disable=too-many-arguments + if (treasury_donation is not None) != (current_treasury_value is not None): + msg="Both `treasury_donation` and `current_treasury_value` must be specified together." + raise ValueError(msg) + destination_dir = pl.Path(destination_dir).expanduser() out_file = destination_dir / f"{tx_name}_tx.body" clusterlib_helpers._check_files_exist(out_file, clusterlib_obj=self._clusterlib_obj) @@ -446,6 +469,7 @@ def build_raw_tx( withdrawals=withdrawals, script_withdrawals=script_withdrawals, deposit=deposit, + treasury_donation=treasury_donation, ) if ( @@ -478,6 +502,8 @@ def build_raw_tx( script_votes=script_votes, invalid_hereafter=invalid_hereafter or ttl, invalid_before=invalid_before, + current_treasury_value=current_treasury_value, + treasury_donation=treasury_donation, join_txouts=join_txouts, ) @@ -556,6 +582,8 @@ def calculate_tx_fee( script_withdrawals: structs.OptionalScriptWithdrawals = (), script_votes: structs.OptionalScriptVotes = (), deposit: tp.Optional[int] = None, + current_treasury_value: tp.Optional[int] = None, + treasury_donation: tp.Optional[int] = None, invalid_hereafter: tp.Optional[int] = None, invalid_before: tp.Optional[int] = None, witness_count_add: int = 0, @@ -595,6 +623,8 @@ def calculate_tx_fee( data (optional). script_votes: An iterable of `ScriptVote`, specifying vote script data (optional). deposit: A deposit amount needed by the transaction (optional). + current_treasury_value: The current treasury value (optional). + treasury_donation: A donation to the treasury to perform (optional). invalid_hereafter: A last block when the transaction is still valid (optional). invalid_before: A first block when the transaction is valid (optional). witness_count_add: A number of witnesses to add - workaround to make the fee @@ -607,6 +637,10 @@ def calculate_tx_fee( int: An estimated fee. """ # pylint: disable=too-many-arguments + if (treasury_donation is not None) != (current_treasury_value is not None): + msg="Both `treasury_donation` and `current_treasury_value` must be specified together." + raise ValueError(msg) + tx_files = tx_files or structs.TxFiles() tx_name = f"{tx_name}_estimate" @@ -641,6 +675,8 @@ def calculate_tx_fee( invalid_hereafter=invalid_hereafter or ttl, invalid_before=invalid_before, deposit=deposit, + current_treasury_value=current_treasury_value, + treasury_donation=treasury_donation, join_txouts=join_txouts, destination_dir=destination_dir, ) @@ -768,6 +804,7 @@ def build_tx( # noqa: C901 script_withdrawals: structs.OptionalScriptWithdrawals = (), script_votes: structs.OptionalScriptVotes = (), deposit: tp.Optional[int] = None, + treasury_donation: tp.Optional[int] = None, invalid_hereafter: tp.Optional[int] = None, invalid_before: tp.Optional[int] = None, witness_override: tp.Optional[int] = None, @@ -810,6 +847,7 @@ def build_tx( # noqa: C901 data (optional). script_votes: An iterable of `ScriptVote`, specifying vote script data (optional). deposit: A deposit amount needed by the transaction (optional). + treasury_donation: A donation to the treasury to perform (optional). invalid_hereafter: A last block when the transaction is still valid (optional). invalid_before: A first block when the transaction is valid (optional). witness_override: An integer indicating real number of witnesses. Can be used to fix @@ -892,6 +930,9 @@ def build_tx( # noqa: C901 if invalid_hereafter is not None: misc_args.extend(["--invalid-hereafter", str(invalid_hereafter)]) + if treasury_donation is not None: + misc_args.extend(["--treasury-donation", str(treasury_donation)]) + if not script_valid: misc_args.append("--script-invalid") @@ -980,6 +1021,7 @@ def build_tx( # noqa: C901 mint=mint, invalid_hereafter=invalid_hereafter, invalid_before=invalid_before, + treasury_donation=treasury_donation, withdrawals=collected_data.withdrawals, change_address=change_address or src_address, return_collateral_txouts=return_collateral_txouts, diff --git a/cardano_clusterlib/txtools.py b/cardano_clusterlib/txtools.py index a0548c2..7a4113b 100644 --- a/cardano_clusterlib/txtools.py +++ b/cardano_clusterlib/txtools.py @@ -150,6 +150,7 @@ def _balance_txouts( # noqa: C901 fee: int, withdrawals: structs.OptionalTxOuts, deposit: int = 0, + treasury_donation: int = 0, lovelace_balanced: bool = False, skip_asset_balancing: bool = False, ) -> tp.List[structs.TxOut]: @@ -191,7 +192,7 @@ def _balance_txouts( # noqa: C901 total_withdrawals_amount = functools.reduce(lambda x, y: x + y.amount, withdrawals, 0) funds_available = total_input_amount + total_withdrawals_amount funds_needed = total_output_amount + tx_fee + deposit - change = funds_available - funds_needed + change = funds_available - funds_needed - treasury_donation if change < 0: LOGGER.error( "Not enough funds to make the transaction - " @@ -492,6 +493,7 @@ def _get_tx_ins_outs( txouts: structs.OptionalTxOuts = (), fee: int = 0, deposit: tp.Optional[int] = None, + treasury_donation: tp.Optional[int] = None, withdrawals: structs.OptionalTxOuts = (), mint_txouts: structs.OptionalTxOuts = (), lovelace_balanced: bool = False, @@ -507,6 +509,7 @@ def _get_tx_ins_outs( txouts: A list (iterable) of `TxOuts`, specifying transaction outputs (optional). fee: A fee amount (optional). deposit: A deposit amount needed by the transaction (optional). + treasury_donation: A donation to the treasury to perform (optional). withdrawals: A list (iterable) of `TxOuts`, specifying reward withdrawals (optional). mint_txouts: A list (iterable) of `TxOuts`, specifying minted tokens (optional). lovelace_balanced: A bool indicating whether Lovelace ins/outs are balanced @@ -554,6 +557,8 @@ def _get_tx_ins_outs( else deposit ) + tx_treasury_donation = treasury_donation if treasury_donation is not None else 0 + if txins: # don't touch txins that were passed to the function txins_filtered = txins_all @@ -595,6 +600,7 @@ def _get_tx_ins_outs( fee=fee, withdrawals=withdrawals, deposit=tx_deposit, + treasury_donation=tx_treasury_donation, lovelace_balanced=lovelace_balanced, skip_asset_balancing=skip_asset_balancing, ) @@ -616,6 +622,7 @@ def collect_data_for_build( withdrawals: structs.OptionalTxOuts = (), script_withdrawals: structs.OptionalScriptWithdrawals = (), deposit: tp.Optional[int] = None, + treasury_donation: tp.Optional[int] = None, lovelace_balanced: bool = False, skip_asset_balancing: bool = False, ) -> structs.DataForBuild: @@ -639,6 +646,7 @@ def collect_data_for_build( script_withdrawals: An iterable of `ScriptWithdrawal`, specifying withdrawal script data (optional). deposit: A deposit amount needed by the transaction (optional). + treasury_donation: A donation to the treasury to perform (optional). lovelace_balanced: A bool indicating whether Lovelace ins/outs are balanced (by `build` command). skip_asset_balancing: A bool indicating if assets balancing should be skipped @@ -688,6 +696,7 @@ def collect_data_for_build( txouts=txouts, fee=fee, deposit=deposit, + treasury_donation=treasury_donation, withdrawals=withdrawals_txouts, mint_txouts=mint_txouts, lovelace_balanced=lovelace_balanced,