UNPKG

@swaptoshi/governance-module

Version:

Klayr governance on-chain module

179 lines 10.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.GovernanceInternalMethod = void 0; const klayr_framework_1 = require("klayr-framework"); const codec_1 = require("@klayr/codec"); const cryptography = require("@klayr/cryptography"); const constants_1 = require("./constants"); const treasury_mint_1 = require("./events/treasury_mint"); const treasury_block_reward_tax_1 = require("./events/treasury_block_reward_tax"); const config_1 = require("./config"); const context_1 = require("./stores/context"); const queue_1 = require("./stores/queue"); const schema_1 = require("./schema"); const delegated_vote_1 = require("./stores/delegated_vote"); const casted_vote_1 = require("./stores/casted_vote"); const proposal_1 = require("./stores/proposal"); const vote_score_1 = require("./stores/vote_score"); const boosted_account_1 = require("./stores/boosted_account"); const utils_1 = require("./utils"); class GovernanceInternalMethod extends klayr_framework_1.Modules.BaseMethod { addDependencies(token) { this._tokenMethod = token; } async updateVoteScoreAfterStake(context) { if (context.transaction.module === constants_1.POS_MODULE_NAME && context.transaction.command === constants_1.POS_STAKE_COMMAND_NAME) { let totalAddedStake = BigInt(0); let totalSubtractedStake = BigInt(0); const stakeParams = codec_1.codec.decode(schema_1.stakeCommandParamsSchema, context.transaction.params); for (const stakes of stakeParams.stakes) if (stakes.amount > BigInt(0)) totalAddedStake += stakes.amount; else totalSubtractedStake += stakes.amount * BigInt(-1); await this.updateProposalVoteSummaryByVoter(context, context.transaction.senderAddress, totalAddedStake, totalSubtractedStake); await this.stores.get(vote_score_1.VoteScoreStore).addVoteScore(context, context.transaction.senderAddress, totalAddedStake - totalSubtractedStake); } } async updateProposalVoteSummaryByVoter(context, voter, addedVote = BigInt(0), subtractedVote = BigInt(0), boostingHeight) { const delegatedVoteStore = this.stores.get(delegated_vote_1.DelegatedVoteStore); const boostedAccountStore = this.stores.get(boosted_account_1.BoostedAccountStore); const voterBoostingState = await boostedAccountStore.getOrDefault(context, voter); const voterBoostingHeight = voterBoostingState.targetHeight; const delegatedVote = await delegatedVoteStore.getOrDefault(context, voter); if (!delegatedVote.outgoingDelegation.equals(Buffer.alloc(0))) { await this.updateProposalVoteSummaryByVoter(context, delegatedVote.outgoingDelegation, addedVote, subtractedVote, boostingHeight !== null && boostingHeight !== void 0 ? boostingHeight : voterBoostingHeight); return; } const castedVoteStore = this.stores.get(casted_vote_1.CastedVoteStore); const proposalStore = this.stores.get(proposal_1.ProposalStore); const ctx = (0, context_1.methodGovernanceContext)(context, Buffer.alloc(0), 0); const castedVote = await castedVoteStore.getOrDefault(context, voter); for (const vote of castedVote.activeVote) { if (typeof addedVote === 'bigint' && addedVote > BigInt(0)) { await (await proposalStore.getMutableProposal(ctx, vote.proposalId)).addVote(addedVote, vote.decision, boostingHeight !== null && boostingHeight !== void 0 ? boostingHeight : voterBoostingHeight); } if (Array.isArray(addedVote)) { for (const addedVoteItem of addedVote) { if (addedVoteItem.voteScore > BigInt(0)) { await (await proposalStore.getMutableProposal(ctx, vote.proposalId)).addVote(addedVoteItem.voteScore, vote.decision, addedVoteItem.boostingHeight); } } } if (typeof subtractedVote === 'bigint' && subtractedVote > BigInt(0)) { await (await proposalStore.getMutableProposal(ctx, vote.proposalId)).subtractVote(subtractedVote, vote.decision, boostingHeight !== null && boostingHeight !== void 0 ? boostingHeight : voterBoostingHeight); } if (Array.isArray(subtractedVote)) { for (const subtractedVoteItem of subtractedVote) { if (subtractedVoteItem.voteScore > BigInt(0)) { await (await proposalStore.getMutableProposal(ctx, vote.proposalId)).subtractVote(subtractedVoteItem.voteScore, vote.decision, subtractedVoteItem.boostingHeight); } } } } } async executeQueuedProposal(context) { const proposalQueueStore = this.stores.get(queue_1.ProposalQueueStore); const ctx = (0, context_1.mutableBlockHookGovernanceContext)(context); const queue = await proposalQueueStore.getInstance(ctx); await queue.executeQueue(); } async addTreasuryReward(context) { if (!this._tokenMethod) throw new Error('GovernanceInternalMethod dependencies is not configured'); const config = await this._getGovernanceConfig(context); const dynamicReward = this._getRewardDeduction(context); const treasuryAddress = cryptography.address.getAddressFromKlayr32Address(config.treasuryAddress); const mintedTreasury = await this._getMintBracket(context, dynamicReward, context.header.height); if (mintedTreasury > BigInt(0)) { await this._tokenMethod.mint(context, treasuryAddress, Buffer.from(config.treasuryReward.tokenID, 'hex'), mintedTreasury); const events = this.events.get(treasury_mint_1.TreasuryMintEvent); events.add(context, { amount: mintedTreasury }, [treasuryAddress]); } const taxedBlockRewardForTreasury = await this._getBlockRewardTaxBracket(context, dynamicReward, context.header.height); if (taxedBlockRewardForTreasury > BigInt(0)) { if (!this.isThisModulePriority()) { throw new Error('Taxing block reward requires governance module to be registered before dynamicReward module'); } await this._tokenMethod.mint(context, treasuryAddress, Buffer.from(config.treasuryReward.tokenID, 'hex'), taxedBlockRewardForTreasury); this._setRewardContext(context, dynamicReward.blockReward - taxedBlockRewardForTreasury); const events = this.events.get(treasury_block_reward_tax_1.TreasuryBlockRewardTaxEvent); events.add(context, { amount: taxedBlockRewardForTreasury, generatorAddress: context.header.generatorAddress, }, [treasuryAddress, context.header.generatorAddress]); } } setModulePriorityStatus(context) { if (this._modulePriorityStatus === undefined) { const blockReward = this._getDynamicBlockRewardContext(context); const reduction = this._getDynamicBlockReductionContext(context); if (blockReward !== undefined && reduction !== undefined) { this._modulePriorityStatus = false; } else { this._modulePriorityStatus = true; } } } isThisModulePriority() { return !!this._modulePriorityStatus; } isAppRunning() { return this._modulePriorityStatus !== undefined; } async _getMintBracket(context, reward, height) { const config = await this._getGovernanceConfig(context); const bracket = await this._getBracket(context, config.treasuryReward.mintBracket, height); if (bracket === '0' || bracket === '0%') return BigInt(0); return (0, utils_1.parseBigintOrPercentage)(bracket, reward.blockReward); } async _getBlockRewardTaxBracket(context, reward, height) { const config = await this._getGovernanceConfig(context); const bracket = await this._getBracket(context, config.treasuryReward.blockRewardTaxBracket, height); if (bracket === '0' || bracket === '0%') return BigInt(0); return (0, utils_1.parseBigintOrPercentage)(bracket, reward.blockReward); } _getDynamicBlockRewardContext(context) { return context.contextStore.get(constants_1.CONTEXT_STORE_KEY_DYNAMIC_BLOCK_REWARD); } _getDynamicBlockReductionContext(context) { return context.contextStore.get(constants_1.CONTEXT_STORE_KEY_DYNAMIC_BLOCK_REDUCTION); } _getRewardDeduction(context) { const blockReward = this._getDynamicBlockRewardContext(context); const reduction = this._getDynamicBlockReductionContext(context); return { blockReward: blockReward === undefined ? BigInt(0) : blockReward, reduction: reduction === undefined ? 0 : reduction, }; } _setRewardContext(context, updatedReward) { context.contextStore.set(constants_1.CONTEXT_STORE_KEY_DYNAMIC_BLOCK_REWARD, updatedReward); } async _getBracketLocation(context, height) { const config = await this._getGovernanceConfig(context); if (height < config.treasuryReward.offset) { return 0; } const rewardDistance = Math.floor(config.treasuryReward.distance); const location = Math.trunc((height - config.treasuryReward.offset) / rewardDistance); return location; } async _getBracket(context, brackets, height) { if (brackets.length === 0) return '0'; const location = await this._getBracketLocation(context, height); const lastBracket = brackets[brackets.length - 1]; const bracket = location > brackets.length - 1 ? brackets.lastIndexOf(lastBracket) : location; return brackets[bracket]; } async _getGovernanceConfig(context) { const configStore = this.stores.get(config_1.GovernanceGovernableConfig); return configStore.getConfig(context); } } exports.GovernanceInternalMethod = GovernanceInternalMethod; //# sourceMappingURL=internal_method.js.map