8

I realize that the CLI has commands for calculating a minimum fee based on a transaction size, but I'm wanting to do a calculation manually. The documentation states that the formula for calculating the transaction minimum fee is a * size(tx) + b where a & b are protocol parameters, and size(tx) is the transaction size in bytes.

Is there a way to calculate the transaction size if I know the number of consumed and output UTxOs? Also, are a and b in the genesis file?

3 Answers 3

2

Here is my bash script

fee=$(cardano-cli transaction calculate-min-fee \
                    --tx-body-file tx.tmp \
                    --tx-in-count 1 \
                    --tx-out-count 1 \
                    --mainnet \
                    --witness-count 1 \
                    --byron-witness-count 0 \
                    --protocol-params-file protocol.json | awk '{ print $1 }') >> $log

In your case, it depends how many TX_in and TX_outs you will have.

1
  • tx.tmp will create it by : cardano-cli transaction build-raw \ --fee 200000 \ --tx-in ${tx_in} \ --tx-out ${in_addr}+${utxo_balance} \ --invalid-hereafter $(( ${currentSlot} + 2000)) \ --out-file tx.tmp >> $log
    – TTS17
    Jan 26 at 6:25
2

The a and b fees parameters are protocol parameters, so you should probably check the current epoch, even they are unlikely to change suddenly.

$ curl -s  -H "project_id: $BLOCKFROST_PROJECT_ID" https://cardano-mainnet.blockfrost.io/api/v0/epochs/latest/parameters | jq '. | .min_fee_a, .min_fee_b'
44
155381

Then, all your need to do to calculate your fees is:

a × size (in bytes) + b

Read more on docs.cardano.org.

4
  • 2
    To get the exact size in bytes, you're going to want to build the transaction and include a dummy value for the fee even though you don't know it yet. Then you can get the exact number of bytes the transaction will take instead of doing estimates based on UTxO counts and such. Then, just calculate as @Marek showed and re-build the Tx a second time with the exact fees. Aug 30, 2021 at 20:04
  • Thanks, you've both been helpful. I guess I probably also wasn't perfectly clear. I'm trying to figure out how to get the size(tx) value. I was wandering if I could do it without the CLI? I'm assuming its not the size of the ASCII characters in bytes but formatted differently. I couldn't find the exact info in the docs (although I'm sure its there somewhere).
    – nalyd88
    Aug 30, 2021 at 23:18
  • Thanks Marek, I forgot to check the protocol parameters file. I was looking in the genesis files but of course it can change!
    – nalyd88
    Aug 31, 2021 at 2:41
  • @nalyd88 The only way to get the size of the transaction without using cardano-cli is to build the cbor for everything yourself. I do this with my firehose project, but it's quite involved. Even cardano-cli doesn't give you exactly the minfee value. It just does a best guess estimate and pads it a bit. Things like stake vs enterprise output addresses can change the size of cbor and affect fees. Sep 22, 2021 at 12:55
2

there are two options that do come to my mind to calculate a transaction size:

starting from the fees

since we know that the fees are calulated as a * size(tx) + b == fees using some simple algebra we can see that size(tx) == (fees - b) / a

this should be the most reliable way, but you need the fees in order to calculate the size, so it shouldn't fit you request

use the CBOR size

when builing a transaction using either cardano-cli transaction build or cardano-cli transaction build-raw you need to specify an --out-file which turns out to be a .json file with the following chema:

{
    "type": "Tx AlonzoEra",
    "description": "",
    "cborHex": "<some hex value>"
}

ultimately the cborHex value is what goes on-chain that value is an hexadecimal string and represents the bytes of the CBOR message

since we know that each byte can have a value from 0 to 255 the hex representation must take 2 hexadecimal digits per byte

this way you could calculate the tx size in bytes as half the length of the cborHex string

in nodejs

"<some hex value>".length / 2

however, this approach returns usually a value smaller by ~400/~500 bytes in contrast to the first approach, so I might be missing some data

P.S. cardano-serialization-library

using the cardano-serialization-library it should be enough to use the Transaction.to_bytes() method and get the length

e.g.

myTx.to_bytes().length

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.