Source code for cometa.transaction_builder.fee

"""
Copyright 2025 Biglup Labs.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""

from __future__ import annotations

from typing import Union, List, Optional, TYPE_CHECKING

from .._ffi import ffi, lib
from ..errors import CardanoError

if TYPE_CHECKING:
    from ..transaction import Transaction
    from ..transaction_body import TransactionOutput
    from ..protocol_params import ProtocolParameters, ExUnitPrices
    from ..common import UtxoList, Utxo, UnitInterval, ExUnits
    from ..witness_set import RedeemerList
    from ..scripts import Script


[docs] def compute_transaction_fee( transaction: "Transaction", resolved_ref_inputs: Optional[Union["UtxoList", List["Utxo"]]] = None, protocol_params: Optional["ProtocolParameters"] = None, ) -> int: """ Compute the minimum transaction fee. This function computes the minimum required transaction fee for the provided transaction, based on the resolved inputs and protocol parameters. The calculated fee considers factors such as the transaction size, execution units consumed by Plutus scripts, and size of included reference scripts. Args: transaction: The transaction to compute the fee for. resolved_ref_inputs: Resolved UTXOs that will be referenced by the transaction. protocol_params: Protocol parameters for fee calculation. Returns: The computed transaction fee in lovelace. Raises: CardanoError: If fee computation fails. Example: >>> from cometa import Transaction >>> from cometa.transaction_builder import compute_transaction_fee >>> tx = Transaction.from_cbor(...) >>> fee = compute_transaction_fee(tx, resolved_ref_inputs, params) """ from ..common.utxo_list import UtxoList ref_inputs_ptr = ffi.NULL if resolved_ref_inputs is not None: if isinstance(resolved_ref_inputs, list): resolved_ref_inputs = UtxoList.from_list(resolved_ref_inputs) ref_inputs_ptr = resolved_ref_inputs._ptr params_ptr = ffi.NULL if protocol_params is not None: params_ptr = protocol_params._ptr fee_out = ffi.new("uint64_t*") err = lib.cardano_compute_transaction_fee( transaction._ptr, ref_inputs_ptr, params_ptr, fee_out ) if err != 0: raise CardanoError(f"Failed to compute transaction fee (error code: {err})") return int(fee_out[0])
[docs] def compute_min_ada_required( output: "TransactionOutput", coins_per_utxo_byte: int, ) -> int: """ Compute the minimum ADA required for a transaction output. This function calculates the minimum amount of ADA (in lovelace) that must be present in a UTXO, based on its size and the coins_per_utxo_byte parameter from the protocol. Args: output: The transaction output to calculate minimum ADA for. coins_per_utxo_byte: Protocol parameter specifying cost in lovelace per byte. Returns: The minimum ADA required in lovelace. Raises: CardanoError: If computation fails. Example: >>> from cometa.transaction_body import TransactionOutput >>> from cometa.transaction_builder import compute_min_ada_required >>> output = TransactionOutput.new(address, 0) >>> min_ada = compute_min_ada_required(output, 4310) """ lovelace_out = ffi.new("uint64_t*") err = lib.cardano_compute_min_ada_required( output._ptr, coins_per_utxo_byte, lovelace_out ) if err != 0: raise CardanoError(f"Failed to compute min ADA required (error code: {err})") return int(lovelace_out[0])
[docs] def compute_min_script_fee( transaction: "Transaction", prices: "ExUnitPrices", resolved_reference_inputs: Optional[Union["UtxoList", List["Utxo"]]] = None, coins_per_ref_script_byte: Optional["UnitInterval"] = None, ) -> int: """ Compute the minimum fee required for a transaction with Plutus scripts. This function calculates the minimum fee required for a transaction that contains Plutus scripts. The fee is based on execution units, prices, and reference script sizes. Args: transaction: The transaction to calculate script fee for. prices: Prices for execution units (memory and steps). resolved_reference_inputs: Resolved UTXOs used by transaction reference inputs. coins_per_ref_script_byte: Cost per byte of reference scripts. Returns: The minimum script fee in lovelace. Raises: CardanoError: If computation fails. """ from ..common.utxo_list import UtxoList ref_inputs_ptr = ffi.NULL if resolved_reference_inputs is not None: if isinstance(resolved_reference_inputs, list): resolved_reference_inputs = UtxoList.from_list(resolved_reference_inputs) ref_inputs_ptr = resolved_reference_inputs._ptr coins_per_byte_ptr = ffi.NULL if coins_per_ref_script_byte is not None: coins_per_byte_ptr = coins_per_ref_script_byte._ptr min_fee_out = ffi.new("uint64_t*") err = lib.cardano_compute_min_script_fee( transaction._ptr, prices._ptr, ref_inputs_ptr, coins_per_byte_ptr, min_fee_out ) if err != 0: raise CardanoError(f"Failed to compute min script fee (error code: {err})") return int(min_fee_out[0])
[docs] def compute_min_fee_without_scripts( transaction: "Transaction", min_fee_constant: int, min_fee_coefficient: int, ) -> int: """ Compute the minimum fee for a transaction without considering script costs. The fee is computed as: min_fee = min_fee_constant + (min_fee_coefficient * tx_size) where tx_size is the size of the transaction in bytes. Args: transaction: The transaction to calculate fee for. min_fee_constant: The constant fee factor (A) from protocol parameters. min_fee_coefficient: The fee-per-byte coefficient (B) from protocol parameters. Returns: The minimum fee in lovelace. Raises: CardanoError: If computation fails. Example: >>> fee = compute_min_fee_without_scripts(tx, 155381, 44) """ min_fee_out = ffi.new("uint64_t*") err = lib.cardano_compute_min_fee_without_scripts( transaction._ptr, min_fee_constant, min_fee_coefficient, min_fee_out ) if err != 0: raise CardanoError( f"Failed to compute min fee without scripts (error code: {err})" ) return int(min_fee_out[0])
[docs] def compute_script_ref_fee( resolved_reference_inputs: Union["UtxoList", List["Utxo"]], coins_per_ref_script_byte: "UnitInterval", ) -> int: """ Compute the script reference fee for transaction inputs. This function calculates the fee component contributed by reference scripts on the inputs of a transaction. Args: resolved_reference_inputs: Resolved reference inputs containing reference scripts. coins_per_ref_script_byte: Fee cost per byte of reference script data. Returns: The reference script fee in lovelace. Raises: CardanoError: If computation fails. """ from ..common.utxo_list import UtxoList if isinstance(resolved_reference_inputs, list): resolved_reference_inputs = UtxoList.from_list(resolved_reference_inputs) script_ref_fee_out = ffi.new("uint64_t*") err = lib.cardano_compute_script_ref_fee( resolved_reference_inputs._ptr, coins_per_ref_script_byte._ptr, script_ref_fee_out, ) if err != 0: raise CardanoError(f"Failed to compute script ref fee (error code: {err})") return int(script_ref_fee_out[0])
[docs] def get_total_ex_units_in_redeemers(redeemers: "RedeemerList") -> "ExUnits": """ Compute the total execution units from a list of redeemers. This function aggregates the total execution units consumed by all redeemers. Execution units include both memory and CPU units. Args: redeemers: The list of redeemers to aggregate. Returns: The total execution units (memory and CPU). Raises: CardanoError: If computation fails. Example: >>> total_units = get_total_ex_units_in_redeemers(redeemer_list) >>> print(f"Memory: {total_units.mem}, Steps: {total_units.steps}") """ from ..common.ex_units import ExUnits total_out = ffi.new("cardano_ex_units_t**") err = lib.cardano_get_total_ex_units_in_redeemers(redeemers._ptr, total_out) if err != 0: raise CardanoError( f"Failed to get total ex units in redeemers (error code: {err})" ) return ExUnits(total_out[0])
[docs] def get_serialized_coin_size(lovelace: int) -> int: """ Compute the serialized size of a given amount of lovelace. Args: lovelace: The amount of lovelace. Returns: The size in bytes required to serialize the lovelace amount. Raises: CardanoError: If computation fails. """ size_out = ffi.new("size_t*") err = lib.cardano_get_serialized_coin_size(lovelace, size_out) if err != 0: raise CardanoError(f"Failed to get serialized coin size (error code: {err})") return int(size_out[0])
[docs] def get_serialized_output_size(output: "TransactionOutput") -> int: """ Compute the serialized size of a transaction output. Args: output: The transaction output. Returns: The size in bytes required to serialize the output. Raises: CardanoError: If computation fails. """ size_out = ffi.new("size_t*") err = lib.cardano_get_serialized_output_size(output._ptr, size_out) if err != 0: raise CardanoError(f"Failed to get serialized output size (error code: {err})") return int(size_out[0])
[docs] def get_serialized_script_size(script: "Script") -> int: """ Compute the serialized size of a script. Args: script: The script object. Returns: The size in bytes required to serialize the script. Raises: CardanoError: If computation fails. """ size_out = ffi.new("size_t*") err = lib.cardano_get_serialized_script_size(script._ptr, size_out) if err != 0: raise CardanoError(f"Failed to get serialized script size (error code: {err})") return int(size_out[0])
[docs] def get_serialized_transaction_size(transaction: "Transaction") -> int: """ Compute the serialized size of a transaction. Args: transaction: The transaction object. Returns: The size in bytes required to serialize the transaction. Raises: CardanoError: If computation fails. Example: >>> tx_size = get_serialized_transaction_size(tx) >>> print(f"Transaction size: {tx_size} bytes") """ size_out = ffi.new("size_t*") err = lib.cardano_get_serialized_transaction_size(transaction._ptr, size_out) if err != 0: raise CardanoError( f"Failed to get serialized transaction size (error code: {err})" ) return int(size_out[0])