"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const Rule_1 = require("./Rule");
const ValidationException_1 = require("../validation/ValidationException");
const BlockchainConfig_1 = require("../blockchain/BlockchainConfig");
class ImposedRules {
    static getImposedRules(delegator, voter) {
        return [
        // new ImposedRules.NoDustRule(voter),
        // new ImposedRules.NoDustRule(delegator)
        ];
    }
}
exports.ImposedRules = ImposedRules;
(function (ImposedRules) {
    class NoDustRule extends Rule_1.Rule {
        constructor(voter) {
            super();
            this.voter = voter;
        }
        validate(voteorder, context) {
            return __awaiter(this, void 0, void 0, function* () {
                const dynamicGlobalProperties = yield context.getDynamicGlobalProperties();
                const accountInfo = yield context.getAccountInfo(this.voter);
                const last_vote_time_s = new Date(accountInfo.last_vote_time + "Z").getTime() / 1000;
                const head_block_time_s = new Date(dynamicGlobalProperties.time + "Z").getTime() / 1000;
                const votes_per_regeneration_period = dynamicGlobalProperties.vote_power_reserve_rate;
                const voter_effective_vesting_shares = this.vestsToFloat(accountInfo.vesting_shares)
                    - this.vestsToFloat(accountInfo.delegated_vesting_shares)
                    + this.vestsToFloat(accountInfo.received_vesting_shares);
                const elapsed_seconds = (head_block_time_s - last_vote_time_s);
                const regenerated_power = (BlockchainConfig_1.BlockchainConfig.STEEM_100_PERCENT * elapsed_seconds) / BlockchainConfig_1.BlockchainConfig.STEEM_VOTING_MANA_REGENERATION_SECONDS;
                const current_power = Math.min(accountInfo.voting_power + regenerated_power, BlockchainConfig_1.BlockchainConfig.STEEM_100_PERCENT);
                if (current_power <= 0)
                    throw new ValidationException_1.ValidationException("Account " + this.voter + " currently does not have voting power.");
                const abs_weight = Math.abs(voteorder.weight);
                let used_power = ((current_power * abs_weight) / BlockchainConfig_1.BlockchainConfig.STEEM_100_PERCENT) * (60 * 60 * 24);
                const max_vote_denom = votes_per_regeneration_period * BlockchainConfig_1.BlockchainConfig.STEEM_VOTING_MANA_REGENERATION_SECONDS;
                if (max_vote_denom <= 0)
                    throw new ValidationException_1.ValidationException("Account " + this.voter + ": max_vote_denom = " + max_vote_denom);
                used_power = (used_power + max_vote_denom - 1) / max_vote_denom;
                if (max_vote_denom <= 0)
                    throw new ValidationException_1.ValidationException("Account " + this.voter + " does not have enough power to vote.");
                let abs_rshares = (voter_effective_vesting_shares * used_power) / (BlockchainConfig_1.BlockchainConfig.STEEM_100_PERCENT);
                abs_rshares -= BlockchainConfig_1.BlockchainConfig.STEEM_VOTE_DUST_THRESHOLD;
                abs_rshares = Math.max(0, abs_rshares);
                if (abs_rshares <= BlockchainConfig_1.BlockchainConfig.STEEM_VOTE_DUST_THRESHOLD)
                    throw new ValidationException_1.ValidationException("Account " + this.voter + ": Voting weight is too small, please accumulate more voting power or steem power.");
            });
        }
        type() {
            throw new Error("This is and imposed rule. It cannot be added to a SetRules ruleset. It is only intended to be used during a voteorder validation");
        }
        vestsToFloat(vests) {
            const unitIndex = vests.indexOf(" VESTS");
            if (unitIndex === -1)
                throw new ValidationException_1.ValidationException("Got vests in bad format");
            else {
                return parseFloat(vests.substring(0, unitIndex));
            }
        }
        validateRuleObject(unprototypedObj) {
            throw new Error("This rule should not be prototyped.");
        }
        getDescription() {
            throw new Error("This is an internal rule");
        }
    }
    ImposedRules.NoDustRule = NoDustRule;
})(ImposedRules = exports.ImposedRules || (exports.ImposedRules = {}));
//# sourceMappingURL=ImposedRules.js.map