"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 dopts = require("default-options");
const commonTypes_1 = require("../commonTypes");
const configService_1 = require("../configService");
const contractWrapperBase_1 = require("../contractWrapperBase");
const contractWrapperFactory_1 = require("../contractWrapperFactory");
const utils_1 = require("../utils");
class GenesisProtocolWrapper extends contractWrapperBase_1.ContractWrapperBase {
    constructor() {
        super(...arguments);
        this.name = "GenesisProtocol";
        this.frendlyName = "Genesis Protocol";
        this.factory = exports.GenesisProtocolFactory;
        /**
         * Events
         */
        /* tslint:disable:max-line-length */
        this.NewProposal = this.createEventFetcherFactory("NewProposal");
        this.ExecuteProposal = this.createEventFetcherFactory("ExecuteProposal");
        this.VoteProposal = this.createEventFetcherFactory("VoteProposal");
        this.Stake = this.createEventFetcherFactory("Stake");
        this.Redeem = this.createEventFetcherFactory("Redeem");
        this.RedeemReputation = this.createEventFetcherFactory("RedeemReputation");
    }
    /* tslint:enable:max-line-length */
    /**
     * Create a proposal
     * @param {ProposeVoteConfig} options
     * @returns Promise<ArcTransactionProposalResult>
     */
    propose(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            /**
             * see GenesisProtocolProposeVoteConfig
             */
            const defaults = {
                avatar: undefined,
                executable: undefined,
                numOfChoices: 0,
                proposer: yield utils_1.Utils.getDefaultAccount(),
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.avatar) {
                throw new Error("avatar is not defined");
            }
            if (!options.executable) {
                throw new Error("executable is not defined");
            }
            if (!options.proposer) {
                throw new Error("proposer is not defined");
            }
            if ((options.numOfChoices < 1) || (options.numOfChoices > 10)) {
                throw new Error("numOfChoices must be between 1 and 10");
            }
            const tx = yield this.contract.propose(options.numOfChoices, utils_1.Utils.NULL_HASH, options.avatar, options.executable, options.proposer);
            return new contractWrapperBase_1.ArcTransactionProposalResult(tx);
        });
    }
    /**
     * Stake some tokens on the final outcome matching this vote.
     *
     * A transfer of tokens from the staker to this GenesisProtocol scheme
     * is automatically approved and executed on the token with which
     * this GenesisProtocol scheme was deployed.
     *
     * @param {StakeConfig} opts
     * @returns Promise<ArcTransactionResult>
     */
    stake(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                amount: undefined,
                onBehalfOf: null,
                proposalId: undefined,
                vote: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            this._validateVote(options.vote, options.proposalId);
            const amount = web3.toBigNumber(options.amount);
            if (amount <= 0) {
                throw new Error("amount must be > 0");
            }
            /**
             * approve immediate transfer of staked tokens from onBehalfOf to this scheme
             */
            if (configService_1.ConfigService.get("autoApproveTokenTransfers")) {
                const token = yield (yield utils_1.Utils.requireContract("StandardToken")).at(yield this.contract.stakingToken());
                yield token.approve(this.address, amount, { from: options.onBehalfOf ? options.onBehalfOf : yield utils_1.Utils.getDefaultAccount() });
            }
            const tx = yield this.contract.stake(options.proposalId, options.vote, amount, options.onBehalfOf ? {
                from: options.onBehalfOf ? options.onBehalfOf :
                    yield utils_1.Utils.getDefaultAccount(),
            } : undefined);
            return new contractWrapperBase_1.ArcTransactionResult(tx);
        });
    }
    /**
     * Vote on a proposal
     * @param {VoteConfig} opts
     * @returns Promise<ArcTransactionResult>
     */
    vote(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                onBehalfOf: null,
                proposalId: undefined,
                vote: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            this._validateVote(options.vote, options.proposalId);
            const tx = yield this.contract.vote(options.proposalId, options.vote, options.onBehalfOf ? { from: options.onBehalfOf } : undefined);
            return new contractWrapperBase_1.ArcTransactionResult(tx);
        });
    }
    /**
     * Vote on a proposal, staking some reputation that the final outcome will match this vote.
     * Reputation of 0 will stake all the voter's reputation.
     * @param {VoteWithSpecifiedAmountsConfig} opts
     * @returns Promise<ArcTransactionResult>
     */
    voteWithSpecifiedAmounts(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                proposalId: undefined,
                reputation: undefined,
                vote: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            this._validateVote(options.vote, options.proposalId);
            if (!options.reputation) {
                throw new Error("reputation is not defined");
            }
            const tx = yield this.contract.voteWithSpecifiedAmounts(options.proposalId, options.vote, options.reputation, 0);
            return new contractWrapperBase_1.ArcTransactionResult(tx);
        });
    }
    /**
     * Redeem any tokens and reputation that are due the beneficiary from the outcome of the proposal.
     * @param {RedeemConfig} opts
     * @returns Promise<ArcTransactionResult>
     */
    redeem(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                beneficiaryAddress: undefined,
                proposalId: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            if (!options.beneficiaryAddress) {
                throw new Error("beneficiaryAddress is not defined");
            }
            const tx = yield this.contract.redeem(options.proposalId, options.beneficiaryAddress);
            return new contractWrapperBase_1.ArcTransactionResult(tx);
        });
    }
    /**
     * Return whether a proposal should be shifted to the boosted phase.
     * @param {ShouldBoostConfig} opts
     * @returns Promise<boolean>
     */
    shouldBoost(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                proposalId: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            const shouldBoost = yield this.contract.shouldBoost(options.proposalId);
            return shouldBoost;
        });
    }
    /**
     * Return the current proposal score.
     * @param {GetScoreConfig} opts
     * @returns Promise<BigNumber.BigNumber>
     */
    getScore(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                proposalId: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            const score = yield this.contract.score(options.proposalId);
            // TODO: convert to number?
            return score;
        });
    }
    /**
     * Return the threshold that is required by a proposal to it shift it into boosted state.
     * The computation depends on the current number of boosted proposals in the DAO
     * as well as the GenesisProtocol parameters thresholdConstA and thresholdConstB.
     * @param {GetThresholdConfig} opts
     * @returns Promise<number>
     */
    getThreshold(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                avatar: undefined,
                proposalId: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.avatar) {
                throw new Error("avatar is not defined");
            }
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            const threshold = yield this.contract.threshold(options.proposalId, options.avatar);
            return threshold.toNumber();
        });
    }
    /**
     * Return the token amount to which the given staker is entitled in the event that the proposal is approved.
     * @param {GetRedeemableTokensStakerConfig} opts
     * @returns Promise<BigNumber.BigNumber>
     */
    getRedeemableTokensStaker(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                beneficiaryAddress: undefined,
                proposalId: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            if (!options.beneficiaryAddress) {
                throw new Error("beneficiaryAddress is not defined");
            }
            const redeemAmount = yield this.contract.getRedeemableTokensStaker(options.proposalId, options.beneficiaryAddress);
            return redeemAmount;
        });
    }
    /**
     * Return the reputation amount to which the proposal proposer is entitled in the event that the proposal is approved.
     * @param {GetRedeemableReputationProposerConfig} opts
     * @returns Promise<BigNumber.BigNumber>
     */
    getRedeemableReputationProposer(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                proposalId: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            const reputation = yield this.contract.getRedeemableReputationProposer(options.proposalId);
            return reputation;
        });
    }
    /**
     * Return the token amount to which the voter is entitled in the event that the proposal is approved.
     * @param {GetRedeemableTokensVoterConfig} opts
     * @returns Promise<BigNumber.BigNumber>
     */
    getRedeemableTokensVoter(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                beneficiaryAddress: undefined,
                proposalId: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            if (!options.beneficiaryAddress) {
                throw new Error("beneficiaryAddress is not defined");
            }
            const amount = yield this.contract.getRedeemableTokensVoter(options.proposalId, options.beneficiaryAddress);
            return amount;
        });
    }
    /**
     * Return the reputation amount to which the voter is entitled in the event that the proposal is approved.
     * @param {GetRedeemableReputationVoterConfig} opts
     * @returns Promise<BigNumber.BigNumber>
     */
    getRedeemableReputationVoter(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                beneficiaryAddress: undefined,
                proposalId: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            if (!options.beneficiaryAddress) {
                throw new Error("beneficiaryAddress is not defined");
            }
            const reputation = yield this.contract.getRedeemableReputationVoter(options.proposalId, options.beneficiaryAddress);
            return reputation;
        });
    }
    /**
     * Return the reputation amount to which the staker is entitled in the event that the proposal is approved.
     * @param {GetRedeemableReputationStakerConfig} opts
     * @returns Promise<BigNumber.BigNumber>
     */
    getRedeemableReputationStaker(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                beneficiaryAddress: undefined,
                proposalId: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            if (!options.beneficiaryAddress) {
                throw new Error("beneficiaryAddress is not defined");
            }
            const reputation = yield this.contract.getRedeemableReputationStaker(options.proposalId, options.beneficiaryAddress);
            return reputation;
        });
    }
    /**
     * Return the number of possible choices when voting for the proposal.
     * @param {GetNumberOfChoicesConfig} opts
     * @returns Promise<number>
     */
    getNumberOfChoices(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                proposalId: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            const numOfChoices = yield this.contract.getNumberOfChoices(options.proposalId);
            return numOfChoices.toNumber();
        });
    }
    /**
     * Return the vote and the amount of reputation of the voter committed to this proposal
     * @param {GetVoterInfoResult} opts
     * @returns Promise<GetVoterInfoResult>
     */
    getVoterInfo(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                proposalId: undefined,
                voter: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            if (!options.voter) {
                throw new Error("voter is not defined");
            }
            const result = yield this.contract.voteInfo(options.proposalId, options.voter);
            return {
                reputation: result[1],
                vote: result[0].toNumber(),
            };
        });
    }
    /**
     * Returns the reputation currently voted on the given choice.
     * @param {GetVoteStatusConfig} opts
     * @returns Promise<BigNumber.BigNumber>
     */
    getVoteStatus(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                proposalId: undefined,
                vote: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            this._validateVote(options.vote, options.proposalId);
            const reputation = yield this.contract.voteStatus(options.proposalId, options.vote);
            /**
             * an array of number counts for each vote choice
             */
            return reputation;
        });
    }
    /**
     * Return whether the proposal is in a votable state.
     * @param {IsVotableConfig} opts
     * @returns Promise<boolean>
     */
    isVotable(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                proposalId: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            const votable = yield this.contract.isVotable(options.proposalId);
            return votable;
        });
    }
    /**
     * Return the total votes, total staked, voter stakes and staker stakes for a given proposal
     * @param {GetProposalStatusConfig} opts
     * @returns Promise<GetProposalStatusResult>
     */
    getProposalStatus(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                proposalId: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            const result = yield this.contract.proposalStatus(options.proposalId);
            return {
                totalStaked: result[2],
                totalStakerStakes: result[1],
                totalVoterStakes: result[3],
                totalVotes: result[0],
            };
        });
    }
    /**
     * Return the DAO avatar address under which the proposal was made
     * @param {GetProposalAvatarConfig} opts
     * @returns Promise<string>
     */
    getProposalAvatar(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                proposalId: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            const avatar = yield this.contract.proposalAvatar(options.proposalId);
            return avatar;
        });
    }
    /**
     * Return the score threshold params for the given DAO.
     * @param {GetScoreThresholdParamsConfig} opts
     * @returns Promise<GetScoreThresholdParamsResult>
     */
    getScoreThresholdParams(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                avatar: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.avatar) {
                throw new Error("avatar is not defined");
            }
            const result = yield this.contract.scoreThresholdParams(options.avatar);
            return {
                thresholdConstA: result[0],
                thresholdConstB: result[1].toNumber(),
            };
        });
    }
    /**
     * Return the vote and stake amount for a given proposal and staker.
     * @param {GetStakerInfoConfig} opts
     * @returns Promise<GetStakerInfoResult>
     */
    getStakerInfo(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                proposalId: undefined,
                staker: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            if (!options.staker) {
                throw new Error("staker is not defined");
            }
            const result = yield this.contract.staker(options.proposalId, options.staker);
            return {
                stake: result[1],
                vote: result[0].toNumber(),
            };
        });
    }
    /**
     * Return the amount stakes behind a given proposal and vote.
     * @param {GetVoteStakeConfig} opts
     * @returns Promise<BigNumber.BigNumber>
     */
    getVoteStake(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                proposalId: undefined,
                vote: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            this._validateVote(options.vote, options.proposalId);
            const stake = yield this.contract.voteStake(options.proposalId, options.vote);
            return stake;
        });
    }
    /**
     * Return the winningVote for a given proposal.
     * @param {GetWinningVoteConfig} opts
     * @returns Promise<number>
     */
    getWinningVote(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                proposalId: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            const winningVote = yield this.contract.winningVote(options.proposalId);
            return winningVote.toNumber();
        });
    }
    /**
     * Return the current state of a given proposal.
     * @param {GetStateConfig} opts
     * @returns Promise<number>
     */
    getState(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                proposalId: undefined,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.proposalId) {
                throw new Error("proposalId is not defined");
            }
            const state = yield this.contract.state(options.proposalId);
            return state.toNumber();
        });
    }
    /**
     * Return all executed GenesisProtocol proposals created under the given avatar.
     * Filter by the optional proposalId.
     */
    getExecutedDaoProposals(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const defaults = {
                avatar: undefined,
                proposalId: null,
            };
            const options = dopts(opts, defaults, { allowUnknown: true });
            if (!options.avatar) {
                throw new Error("avatar address is not defined");
            }
            const proposals = new Array();
            const eventFetcher = this.ExecuteProposal({ _avatar: options.avatar, _proposalId: options.proposalId }, { fromBlock: 0 });
            yield new Promise((resolve) => {
                eventFetcher.get((err, log) => __awaiter(this, void 0, void 0, function* () {
                    for (const event of log) {
                        proposals.push({
                            decision: event.args._decision.toNumber(),
                            executionState: event.args._executionState.toNumber(),
                            proposalId: event.args._proposalId,
                            totalReputation: event.args._totalReputation,
                        });
                    }
                    resolve();
                }));
            });
            return proposals;
        });
    }
    /**
     * Set the contract parameters.
     * @param {GenesisProtocolParams} params
     * @returns parameters hash
     */
    setParameters(params) {
        const _super = name => super[name];
        return __awaiter(this, void 0, void 0, function* () {
            params = Object.assign({}, {
                boostedVotePeriodLimit: 604800,
                minimumStakingFee: 0,
                preBoostedVotePeriodLimit: 5184000,
                preBoostedVoteRequiredPercentage: 50,
                proposingRepRewardConstA: web3.toWei(5),
                proposingRepRewardConstB: web3.toWei(5),
                quietEndingPeriod: 7200,
                stakerFeeRatioForVoters: 1,
                thresholdConstA: web3.toWei(2),
                thresholdConstB: 10,
                votersGainRepRatioFromLostRep: 80,
                votersReputationLossRatio: 1,
            }, params);
            // in Wei
            const maxEthValue = web3.toBigNumber(10).pow(26);
            const proposingRepRewardConstA = web3.toBigNumber(params.proposingRepRewardConstA);
            if (proposingRepRewardConstA.lt(0)) {
                throw new Error("proposingRepRewardConstA must be greater than or equal to 0");
            }
            if (proposingRepRewardConstA.gt(maxEthValue)) {
                throw new Error(`proposingRepRewardConstA must be less than ${maxEthValue}`);
            }
            const proposingRepRewardConstB = web3.toBigNumber(params.proposingRepRewardConstB);
            if (proposingRepRewardConstB.lt(0)) {
                throw new Error("proposingRepRewardConstB must be greater than or equal to 0");
            }
            if (proposingRepRewardConstB.gt(maxEthValue)) {
                throw new Error(`proposingRepRewardConstB must be less than ${maxEthValue}`);
            }
            const thresholdConstA = web3.toBigNumber(params.thresholdConstA);
            if (thresholdConstA.lt(0)) {
                throw new Error("thresholdConstA must be greater than or equal to 0");
            }
            if (thresholdConstA.gt(maxEthValue)) {
                throw new Error(`thresholdConstA must be less than ${maxEthValue}`);
            }
            const thresholdConstB = web3.toBigNumber(params.thresholdConstB);
            if (thresholdConstB.lte(0)) {
                throw new Error("thresholdConstB must be greater than 0");
            }
            /**
             * thresholdConstB is a number, and is not supposed to be in Wei (unlike the other
             * params checked above), but we check this condition anyways as not everyone
             * may be using the type checking of TypeScript, and it is a condition in the Solidity code.
             */
            if (thresholdConstB.gt(maxEthValue)) {
                throw new Error(`thresholdConstB must be less than ${maxEthValue}`);
            }
            const preBoostedVoteRequiredPercentage = params.preBoostedVoteRequiredPercentage || 0;
            if ((preBoostedVoteRequiredPercentage <= 0) || (preBoostedVoteRequiredPercentage > 100)) {
                throw new Error("preBoostedVoteRequiredPercentage must be greater than 0 and less than or equal to 100");
            }
            const stakerFeeRatioForVoters = params.stakerFeeRatioForVoters || 0;
            if ((stakerFeeRatioForVoters < 0) || (stakerFeeRatioForVoters > 100)) {
                throw new Error("stakerFeeRatioForVoters must be greater than or equal to 0 and less than or equal to 100");
            }
            const votersGainRepRatioFromLostRep = params.votersGainRepRatioFromLostRep || 0;
            if ((votersGainRepRatioFromLostRep < 0) || (votersGainRepRatioFromLostRep > 100)) {
                throw new Error("votersGainRepRatioFromLostRep must be greater than or equal to 0 and less than or equal to 100");
            }
            const votersReputationLossRatio = params.votersReputationLossRatio || 0;
            if ((votersReputationLossRatio < 0) || (votersReputationLossRatio > 100)) {
                throw new Error("votersReputationLossRatio must be greater than or equal to  0 and less than or equal to 100");
            }
            return _super("setParameters").call(this, [
                preBoostedVoteRequiredPercentage,
                params.preBoostedVotePeriodLimit,
                params.boostedVotePeriodLimit,
                thresholdConstA,
                thresholdConstB,
                params.minimumStakingFee,
                params.quietEndingPeriod,
                proposingRepRewardConstA,
                proposingRepRewardConstB,
                stakerFeeRatioForVoters,
                votersReputationLossRatio,
                votersGainRepRatioFromLostRep,
            ]);
        });
    }
    getDefaultPermissions(overrideValue) {
        // return overrideValue || Utils.numberToPermissionsString(DefaultSchemePermissions.GenesisProtocol);
        return (overrideValue || commonTypes_1.DefaultSchemePermissions.GenesisProtocol);
    }
    getSchemePermissions(avatarAddress) {
        return __awaiter(this, void 0, void 0, function* () {
            return this._getSchemePermissions(avatarAddress);
        });
    }
    getSchemeParameters(avatarAddress) {
        return __awaiter(this, void 0, void 0, function* () {
            return this._getSchemeParameters(avatarAddress);
        });
    }
    getParameters(paramsHash) {
        return __awaiter(this, void 0, void 0, function* () {
            const params = yield this.getParametersArray(paramsHash);
            return {
                boostedVotePeriodLimit: params[2].toNumber(),
                minimumStakingFee: params[5].toNumber(),
                preBoostedVotePeriodLimit: params[1].toNumber(),
                preBoostedVoteRequiredPercentage: params[0].toNumber(),
                proposingRepRewardConstA: params[7],
                proposingRepRewardConstB: params[8],
                quietEndingPeriod: params[6].toNumber(),
                stakerFeeRatioForVoters: params[9].toNumber(),
                thresholdConstA: params[3],
                thresholdConstB: params[4].toNumber(),
                votersGainRepRatioFromLostRep: params[11].toNumber(),
                votersReputationLossRatio: params[10].toNumber(),
            };
        });
    }
    _validateVote(vote, proposalId) {
        return __awaiter(this, void 0, void 0, function* () {
            const numChoices = yield this.getNumberOfChoices({ proposalId });
            if (!Number.isInteger(vote) || (vote < 0) || (vote > numChoices)) {
                throw new Error("vote is not valid");
            }
        });
    }
}
exports.GenesisProtocolWrapper = GenesisProtocolWrapper;
exports.GenesisProtocolFactory = new contractWrapperFactory_1.default("GenesisProtocol", GenesisProtocolWrapper);
var ExecutionState;
(function (ExecutionState) {
    ExecutionState[ExecutionState["None"] = 0] = "None";
    ExecutionState[ExecutionState["PreBoostedTimeOut"] = 1] = "PreBoostedTimeOut";
    ExecutionState[ExecutionState["PreBoostedBarCrossed"] = 2] = "PreBoostedBarCrossed";
    ExecutionState[ExecutionState["BoostedTimeOut"] = 3] = "BoostedTimeOut";
    ExecutionState[ExecutionState["BoostedBarCrossed"] = 4] = "BoostedBarCrossed";
})(ExecutionState = exports.ExecutionState || (exports.ExecutionState = {}));
var ProposalState;
(function (ProposalState) {
    ProposalState[ProposalState["None"] = 0] = "None";
    ProposalState[ProposalState["Closed"] = 1] = "Closed";
    ProposalState[ProposalState["Executed"] = 2] = "Executed";
    ProposalState[ProposalState["PreBoosted"] = 3] = "PreBoosted";
    ProposalState[ProposalState["Boosted"] = 4] = "Boosted";
    ProposalState[ProposalState["QuietEndingPeriod"] = 5] = "QuietEndingPeriod";
})(ProposalState = exports.ProposalState || (exports.ProposalState = {}));
//# sourceMappingURL=genesisProtocol.js.map