UNPKG

lisk-framework

Version:

Lisk blockchain application platform

130 lines 6.88 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FeeModule = void 0; const lisk_utils_1 = require("@liskhq/lisk-utils"); const lisk_validator_1 = require("@liskhq/lisk-validator"); const lisk_cryptography_1 = require("@liskhq/lisk-cryptography"); const constants_1 = require("./constants"); const state_machine_1 = require("../../state_machine"); const method_1 = require("./method"); const endpoint_1 = require("./endpoint"); const schemas_1 = require("./schemas"); const generator_fee_processed_1 = require("./events/generator_fee_processed"); const relayer_fee_processed_1 = require("./events/relayer_fee_processed"); const insufficient_fee_1 = require("./events/insufficient_fee"); const cc_method_1 = require("./cc_method"); const base_interoperable_module_1 = require("../interoperability/base_interoperable_module"); class FeeModule extends base_interoperable_module_1.BaseInteroperableModule { constructor() { super(); this.method = new method_1.FeeMethod(this.stores, this.events); this.crossChainMethod = new cc_method_1.FeeInteroperableMethod(this.stores, this.events, this.name); this.configSchema = schemas_1.configSchema; this.endpoint = new endpoint_1.FeeEndpoint(this.stores, this.offchainStores); this.events.register(generator_fee_processed_1.GeneratorFeeProcessedEvent, new generator_fee_processed_1.GeneratorFeeProcessedEvent(this.name)); this.events.register(relayer_fee_processed_1.RelayerFeeProcessedEvent, new relayer_fee_processed_1.RelayerFeeProcessedEvent(this.name)); this.events.register(insufficient_fee_1.InsufficientFeeEvent, new insufficient_fee_1.InsufficientFeeEvent(this.name)); } addDependencies(tokenMethod, interopMethod) { this._tokenMethod = tokenMethod; this.crossChainMethod.addDependencies(interopMethod, tokenMethod); } metadata() { return { ...this.baseMetadata(), endpoints: [ { name: this.endpoint.getMinFeePerByte.name, response: schemas_1.getMinFeePerByteResponseSchema, }, { name: this.endpoint.getFeeTokenID.name, response: schemas_1.getFeeTokenIDResponseSchema, }, ], }; } async init(args) { const defaultFeeTokenID = `${args.genesisConfig.chainID}${Buffer.alloc(4).toString('hex')}`; const config = lisk_utils_1.objects.mergeDeep({}, { ...constants_1.defaultConfig, feeTokenID: defaultFeeTokenID }, args.moduleConfig); lisk_validator_1.validator.validate(schemas_1.configSchema, config); const moduleConfig = { ...config, feeTokenID: Buffer.from(config.feeTokenID, 'hex'), feePoolAddress: config.feePoolAddress ? lisk_cryptography_1.address.getAddressFromLisk32Address(config.feePoolAddress) : undefined, }; this.method.init(moduleConfig); this.endpoint.init(moduleConfig); this.crossChainMethod.init(moduleConfig); this._tokenID = moduleConfig.feeTokenID; this._minFeePerByte = moduleConfig.minFeePerByte; this._maxBlockHeightZeroFeePerByte = moduleConfig.maxBlockHeightZeroFeePerByte; this._feePoolAddress = moduleConfig.feePoolAddress; } async verifyTransaction(context) { const { getMethodContext, transaction, header } = context; const minFee = this._getMinFee(header.height, transaction.getBytes().length); if (transaction.fee < minFee) { throw new Error(`Insufficient transaction fee. Minimum required fee is ${minFee}.`); } const balance = await this._tokenMethod.getAvailableBalance(getMethodContext(), transaction.senderAddress, this._tokenID); if (transaction.fee > balance) { throw new Error(`Insufficient balance.`); } return { status: state_machine_1.VerifyStatus.OK }; } async beforeCommandExecute(context) { const { transaction, header } = context; const minFee = this._getMinFee(header.height, transaction.getBytes().length); const availableFee = transaction.fee - minFee; if (availableFee < 0) { throw new Error(`Insufficient transaction fee. Minimum required fee is ${minFee}.`); } const methodContext = context.getMethodContext(); await this._tokenMethod.lock(methodContext, transaction.senderAddress, this.name, this._tokenID, transaction.fee); context.contextStore.set(constants_1.CONTEXT_STORE_KEY_AVAILABLE_FEE, availableFee); } async afterCommandExecute(context) { const { header, transaction } = context; await this._tokenMethod.unlock(context.getMethodContext(), transaction.senderAddress, this.name, this._tokenID, transaction.fee); let availableFee = (0, state_machine_1.getContextStoreBigInt)(context.contextStore, constants_1.CONTEXT_STORE_KEY_AVAILABLE_FEE); const userSubstoreGeneratorExists = await this._tokenMethod.userSubstoreExists(context, header.generatorAddress, this._tokenID); if (userSubstoreGeneratorExists) { await this._tokenMethod.transfer(context.getMethodContext(), transaction.senderAddress, header.generatorAddress, this._tokenID, availableFee); } else { availableFee = BigInt(0); } let burnConsumedFee = true; if (this._feePoolAddress) { const userSubstoreFeePoolExists = await this._tokenMethod.userSubstoreExists(context, this._feePoolAddress, this._tokenID); if (userSubstoreFeePoolExists) { burnConsumedFee = false; } } const minFee = transaction.fee - availableFee; if (burnConsumedFee) { await this._tokenMethod.burn(context.getMethodContext(), transaction.senderAddress, this._tokenID, minFee); } else { await this._tokenMethod.transfer(context.getMethodContext(), transaction.senderAddress, this._feePoolAddress, this._tokenID, minFee); } this.events.get(generator_fee_processed_1.GeneratorFeeProcessedEvent).log(context, { burntAmount: transaction.fee - availableFee, generatorAddress: header.generatorAddress, generatorAmount: availableFee, senderAddress: transaction.senderAddress, }); context.contextStore.delete(constants_1.CONTEXT_STORE_KEY_AVAILABLE_FEE); } _getMinFee(blockHeight, transactionByteLength) { if (blockHeight < this._maxBlockHeightZeroFeePerByte) { return BigInt(0); } return BigInt(this._minFeePerByte) * BigInt(transactionByteLength); } } exports.FeeModule = FeeModule; //# sourceMappingURL=module.js.map