How to calculate the minimum fee for a transaction

On this page, you’ll learn:

  • How to calculate the minimum fee for a given transaction

  • How to dry-run a transaction to verify the fee

To compute the minimum fee for a transaction, use the API client. Create a small script called compute-minfee.js as described in the following sections.

See the complete code example of the script in the Klayr SDK examples repository: https://github.com/KlayrHQ/klayr-sdk-examples/blob/development/guides/calculate-minfee/

To compute the minimum fee for a transaction without a connection to the API client, the user can also use directly the @klayr/transactions package. In this case, the user needs to provide the transaction object and the corresponding transaction schema to the function.

Connect the API client to a node

The Klayr API client is a JS package that allows to connect to a node API through WS and IPC protocols.

It can be used inside of JS or TS script to connect to a blockchain node API in order to calculate the minimum fee for a transaction conveniently.

To use the Klayr API client, install the klayr-client package with NPM:

npm install @klayr/client
  • WS API client example

  • IPC API client example

Create a file api-client.js which will export the function getClient().

Adjust nodeAPIURL to point to the node you want to post the transaction to.

api-client.js
const { apiClient } = require('@klayr/client');
let clientCache;
const nodeAPIURL = 'ws://localhost:7887/rpc-ws'

/**
 * Connects to a node API via WS
 *
 * @returns The API client
 */
const getClient = async () => {
	if (!clientCache) {
		clientCache = await apiClient.createWSClient(nodeAPIURL);
	}
	return clientCache;
};

Create a file api-client.js which will export the function getClient().

Adjust DATA_PATH to point to the blockchain client data path.

api-client.js
const { apiClient } = require('@klayr/client');

const DATA_PATH = '~/.klayr/hello_client';
let clientCache;

const getClient = async () => {
    if (!clientCache) {
        clientCache = await apiClient.createIPCClient(DATA_PATH);
    }
    return clientCache;
};

module.exports = { getClient };

Create the transaction

Next, create the transaction as JSON, for which the minimum required fee shall be calculated.

Use 0 or anothe random value for the fee.

Use the --json flag to retrieve the transaction in the JSON format, as desired.

For more information about the different ways to create transactions, check out the corresponding guide How to create and sign a transaction.
./bin/run transaction:create token transfer 0 --json
{"transaction":{"module":"token","command":"transfer","fee":"0","nonce":"3","senderPublicKey":"ec10255d3e78b2977f04e59ea9afd3e9a2ce9a6b44619ef9f6c47c29695b1df3","signatures":["500d192a25a2c7b340b5ae03471c329b174d7fb3b05d47aefd71f0c4b76e220fe2edc79efcc16b9f89ac61708bcb9755f78262f1b00439f52972422a94f69a07"],"params":{"tokenID":"0000000000000000","amount":"1000000000","recipientAddress":"klyoytn4jcgs2pjpy2vfsttt7g8eb9wwbaf6hxc27","data":"Happy Birthday!"},"id":"0f81c6442ad49313046d73a8eb96178ff0c16ee2d353c4005f982310cdbbe39e"}}

Compute minimumFee

Create a new script getMinFee.js to calculate the minimum required transaction fee. Import the getClient() function and use the API client to calculate the minimum fee, as shown in the snippet below.

getMinFee.js
const { getClient } = require('./api-client');
/**
 * Returns the minimum fee for a transaction.
 *
 * @param txJSON The transaction to calculate the minimum fee for in JSON format
 * @returns The minimum fee for the given transaction
 */
const getMinFee = async (txJSON) => {
	const client = await getClient();
	const minFee = client.transaction.computeMinFee(txJSON);
	return minFee;
};

Dry-run the transaction

Create a new script dryRun.js to verify the transaction with the calculated minimum fee. Import the getClient() function and use the API client to perform a dry-run on the transaction, as shown in the snippet below.

const { getClient } = require('./api-client');

/**
 * Performs a dry-run for a given transaction.
 *
 * @param txJSON The transaction to dry-run in JSON format
 * @returns The result of the dry-run
 */
const dryRun = async (txJSON) => {
	const client = await getClient();

	const tx = client.transaction.fromJSON(txJSON);
	const encodedTx = client.transaction.encode(tx);

	const result = await client.invoke('txpool_dryRunTransaction',{"transaction":encodedTx.toString("hex") })

	return result;
};

Execute

Create a new script index.js.

Import all the above created script into index.js and use the functions to calculate the fee for any given transaction, and to verify the fee with a dry-run in one go:

index.js
const { transactions } = require('@klayr/client');
const { getMinFee } = require('./getMinFee');
const { dryRun } = require('./dry-run');

(async () => {
	const txJSON = {"module":"token","command":"transfer","fee":"0","nonce":"3","senderPublicKey":"ec10255d3e78b2977f04e59ea9afd3e9a2ce9a6b44619ef9f6c47c29695b1df3","signatures":["500d192a25a2c7b340b5ae03471c329b174d7fb3b05d47aefd71f0c4b76e220fe2edc79efcc16b9f89ac61708bcb9755f78262f1b00439f52972422a94f69a07"],"params":{"tokenID":"0300000800000000","amount":"1000000000","recipientAddress":"klyoytn4jcgs2pjpy2vfsttt7g8eb9wwbaf6hxc27","data":"Happy Birthday!"},"id":"0f81c6442ad49313046d73a8eb96178ff0c16ee2d353c4005f982310cdbbe39e"};

	const minFee = await getMinFee(txJSON);

	console.log("The minimum fee for the given transaction is: ", minFee, " Beddows, i.e. ", transactions.convertBeddowsToKLY(minFee.toString()), " KLY.");

	const txWithFee = {
		...txJSON,
		fee: minFee.toString()
	}

	const result = await dryRun(txWithFee);

	console.log("Dry run result", result);
	process.exit(0);
})();

If the script is now executed in the terminal, it will display the minimum fee for the defined transaction.

Additionally, a dry-run is performed on the transaction using the calculated minimum fee. If the fee is too small, the dry-run will fail with an error.

To execute the script run the following command:

node index.js

The result will be displayed in the terminal like shown below:

Valid response example
The minimum fee for the given transaction is:  180000n  Beddows, i.e.  0.0018  KLY.
Dry run result {"result":1,"events":[{"data":"0a14fa892e1aa42a8af96c45dfd5afc428b3dba950e612036665651a0803000008000000002080ade2042800","index":0,"module":"token","name":"lock","topics":["8672ad60aca728cd1742862d02abb857b8329f3a74434e895e51504eaaaa3c52","fa892e1aa42a8af96c45dfd5afc428b3dba950e6"],"height":3967},{"data":"0a14fa892e1aa42a8af96c45dfd5afc428b3dba950e61214646674f07fde09c24702f6e739bbefb19b7b9b3e1a080300000800000000208094ebdc032800","index":1,"module":"token","name":"transfer","topics":["8672ad60aca728cd1742862d02abb857b8329f3a74434e895e51504eaaaa3c52","fa892e1aa42a8af96c45dfd5afc428b3dba950e6","646674f07fde09c24702f6e739bbefb19b7b9b3e"],"height":3967},{"data":"0a14fa892e1aa42a8af96c45dfd5afc428b3dba950e612036665651a0803000008000000002080ade2042800","index":2,"module":"token","name":"unlock","topics":["8672ad60aca728cd1742862d02abb857b8329f3a74434e895e51504eaaaa3c52","fa892e1aa42a8af96c45dfd5afc428b3dba950e6"],"height":3967},{"data":"0a14fa892e1aa42a8af96c45dfd5afc428b3dba950e6120803000008000000001888860b2000","index":3,"module":"token","name":"burn","topics":["8672ad60aca728cd1742862d02abb857b8329f3a74434e895e51504eaaaa3c52","fa892e1aa42a8af96c45dfd5afc428b3dba950e6"],"height":3967},{"data":"0a14fa892e1aa42a8af96c45dfd5afc428b3dba950e61214522e3ab2e804cd0d84bdfb585753bb9137e4812b1a08030000080000000020f8a6d7042800","index":4,"module":"token","name":"transfer","topics":["8672ad60aca728cd1742862d02abb857b8329f3a74434e895e51504eaaaa3c52","fa892e1aa42a8af96c45dfd5afc428b3dba950e6","522e3ab2e804cd0d84bdfb585753bb9137e4812b"],"height":3967},{"data":"0a14fa892e1aa42a8af96c45dfd5afc428b3dba950e61214522e3ab2e804cd0d84bdfb585753bb9137e4812b1888860b20f8a6d704","index":5,"module":"fee","name":"generatorFeeProcessed","topics":["8672ad60aca728cd1742862d02abb857b8329f3a74434e895e51504eaaaa3c52","fa892e1aa42a8af96c45dfd5afc428b3dba950e6","522e3ab2e804cd0d84bdfb585753bb9137e4812b"],"height":3967},{"data":"0801","index":6,"module":"token","name":"commandExecutionResult","topics":["8672ad60aca728cd1742862d02abb857b8329f3a74434e895e51504eaaaa3c52"],"height":3967}]}
Invalid response example
The minimum fee for the given transaction is:  180000n  Beddows, i.e.  0.0018  KLY.
Dry run result {
  result: -1,
  events: [],
  "errorMessage": "Insufficient transaction fee. Minimum required fee is 176000."
}