Announcing transactions have an associated cost. This cost is necessary to provide an incentive for the harvesters who secure the network and run the infrastructure.
By default, fees are paid in the underlying currency of the Symbol network.
Network type | Mosaic name |
---|---|
MIJIN_TEST | cat.currency |
TEST_NET | symbol.xym |
Private chains can edit the network configuration to eliminate fees or use another mosaic that better suits their needs.
The fee associated with a transaction primarily depends on the size of the transaction. The effective fee deducted from the account sending the transaction is calculated as the product of the size of the transaction and a fee multiplier set by the node that harvests the block.
A node owner can configure the fee multiplier to all positive values, including zero. The fee_multiplier
is stored in the block header when the node harvests a new block, determining which was the effective fee paid for every transaction included.
Before announcing the transaction, the sender must specify during the transaction definition a max_fee
, indicating the maximum fee the account allows to spend for this transaction.
If the effective_fee
is smaller or equal to the max_fee
, a harvester could opt to include the transaction in the block. The harvesting nodes can set their transaction inclusion strategy:
To ensure that the transaction will get included without setting a max_fee
unnecessarily high, the sender of the transaction can ask the REST Gateway for the median, average, highest, or lowest multiplier of the network over the last N blocks. For example, the sender could set the transaction max_fee as follows:
const publicAccount1 = Account.generateNewAccount(NetworkType.TEST_NET).publicAccount;
const publicAccount2 = Account.generateNewAccount(NetworkType.TEST_NET).publicAccount;
// Get median fee multiplier
const nodeUrl = 'http://api-01.us-east-1.096x.symboldev.network:3000';
const repositoryHttp = new RepositoryFactoryHttp(nodeUrl);
const networkHttp = repositoryHttp.createNetworkRepository();
const medianFeeMultiplier = (await networkHttp.getTransactionFees().toPromise()).medianFeeMultiplier;
// Define transaction and set max fee
const rawAddress = 'TB6Q5E-YACWBP-CXKGIL-I6XWCH-DRFLTB-KUK34I-YJQ';
const recipientAddress = Address.createFromRawAddress(rawAddress);
const transferTransaction = TransferTransaction.create(
Deadline.create(),
recipientAddress,
[],
PlainMessage.create('This is a test message'),
NetworkType.TEST_NET)
.setMaxFee(medianFeeMultiplier);
const publicAccount1 = symbol_sdk_1.Account.generateNewAccount(symbol_sdk_1.NetworkType.TEST_NET).publicAccount;
const publicAccount2 = symbol_sdk_1.Account.generateNewAccount(symbol_sdk_1.NetworkType.TEST_NET).publicAccount;
// Get median fee multiplier
const nodeUrl = 'http://api-01.us-east-1.096x.symboldev.network:3000';
const repositoryHttp = new symbol_sdk_1.RepositoryFactoryHttp(nodeUrl);
const networkHttp = repositoryHttp.createNetworkRepository();
const medianFeeMultiplier = (yield networkHttp.getTransactionFees().toPromise()).medianFeeMultiplier;
// Define transaction and set max fee
const rawAddress = 'TB6Q5E-YACWBP-CXKGIL-I6XWCH-DRFLTB-KUK34I-YJQ';
const recipientAddress = symbol_sdk_1.Address.createFromRawAddress(rawAddress);
const transferTransaction = symbol_sdk_1.TransferTransaction.create(symbol_sdk_1.Deadline.create(), recipientAddress, [], symbol_sdk_1.PlainMessage.create('This is a test message'), symbol_sdk_1.NetworkType.TEST_NET)
.setMaxFee(medianFeeMultiplier);
Note
It is not guaranteed that the transaction will get confirmed if the multiplier used is to low. To have better chances, the sender of the transaction could opt to use any value between medianNetworkFeeMultiplier and highestFeeMultiplier instead.
To determine an aggregate bonded transaction size, it is required to know beforehand the number of participant accounts that will need to cosign the transaction.
// Define transaction and set max fee
const requiredCosignatures = 1;
const aggregateTransaction = AggregateTransaction
.createBonded(
Deadline.create(),
[transferTransaction.toAggregate(publicAccount1),
transferTransaction.toAggregate(publicAccount2)],
NetworkType.TEST_NET,
[])
.setMaxFeeForAggregate(medianFeeMultiplier, 1);
// Define transaction and set max fee
const requiredCosignatures = 1;
const aggregateTransaction = symbol_sdk_1.AggregateTransaction
.createBonded(symbol_sdk_1.Deadline.create(), [transferTransaction.toAggregate(publicAccount1),
transferTransaction.toAggregate(publicAccount2)], symbol_sdk_1.NetworkType.TEST_NET, [])
.setMaxFeeForAggregate(medianFeeMultiplier, 1);
Accounts willing to register a namespace or a mosaic have to pay a rental fee in addition to the transaction fee. The effective rental fee is adjusted dynamically based on the median network multiplier over last maxDifficultyBlocks.
For more information, see how the network calculates the effective rental fee for mosaics and namespaces.
Continue: Receipt.
Did you find what you were looking for? Give us your feedback.