"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const commonTypes_1 = require("../commonTypes");
const utils_1 = require("../utils");
const utilsInternal_1 = require("../utilsInternal");
const genesisProtocol_1 = require("../wrappers/genesisProtocol");
/* tslint:disable-next-line:no-var-requires */
const gasLimits = require("../../gasLimits.js");
const computeForgeOrgGasLimit = gasLimits.computeForgeOrgGasLimit;
const computeMaxGasLimit = gasLimits.computeMaxGasLimit;
/**
 * Migration callback
 */
class GenesisDaoCreator {
    constructor(web3, network) {
        this.web3 = web3;
        this.network = network;
    }
    /**
     * Forge the Genesis DAO.  Note this does not set the schemes.
     */
    forge(foundersConfigurationLocation) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const live = this.network === "live";
            /**
             * Genesis DAO parameters
             */
            const orgName = live ? "Genesis Alpha" : "Genesis Alpha";
            const tokenName = live ? "Genesis Alpha" : "Genesis Alpha";
            const tokenSymbol = "GDT";
            /**
             * Truffle Solidity artifact wrappers
             */
            const Avatar = yield utils_1.Utils.requireContract("Avatar");
            const DaoCreator = yield utils_1.Utils.requireContract("DaoCreator");
            const daoCreatorInst = yield DaoCreator.deployed();
            const UController = yield utils_1.Utils.requireContract("UController");
            const universalControllerInst = yield UController.deployed();
            const internalFoundersConfigLocation = "../../migrations/founders.json";
            const foundersConfig = require(internalFoundersConfigLocation).founders;
            const customFoundersConfigLocation = foundersConfigurationLocation || internalFoundersConfigLocation;
            if (internalFoundersConfigLocation !== customFoundersConfigLocation) {
                console.log(`merging custom founders from ${customFoundersConfigLocation}`);
                const customFoundersConfig = require(customFoundersConfigLocation).founders;
                // merge the two
                Object.assign(foundersConfig, customFoundersConfig);
            }
            const founders = foundersConfig[this.network];
            if (!founders || (founders.length === 0)) {
                throw new Error(`no founders were given for the network: ${this.network}`);
            }
            let gasLimit = computeForgeOrgGasLimit(founders.length);
            const maxGasLimit = yield computeMaxGasLimit(this.web3);
            gasLimit = Math.min(gasLimit, maxGasLimit);
            console.log(`Forging ${orgName} to ${this.network}, gasLimit: ${gasLimit} and ${founders.length} founders...`);
            /**
             * Create the Genesis DAO
             */
            const txForgeOrg = yield daoCreatorInst.forgeOrg(orgName, tokenName, tokenSymbol, founders.map((f) => f.address), founders.map((f) => this.web3.toWei(f.tokens)), founders.map((f) => this.web3.toWei(f.reputation)), universalControllerInst.address, this.web3.toWei(100000000), // token cap of one hundred million GEN, in Wei
            { gas: gasLimit });
            let avatarInst;
            while (!avatarInst) {
                yield Avatar.at(txForgeOrg.logs[0].args._avatar)
                    .then((address) => {
                    avatarInst = address;
                })
                    /* tslint:disable-next-line:no-empty */
                    .catch(() => {
                });
                if (!avatarInst) {
                    console.log("sleeping until Avatar is available...");
                    /**
                     * Sleep and retry until avatarInst is mined.  This is necessary
                     * virtually every time we run against mainnet.
                     */
                    yield utilsInternal_1.UtilsInternal.sleep(2000);
                }
            }
            console.log(`Avatar forged at: ${avatarInst.address}`);
            /** for use by setSchemes */
            return {
                avatarAddress: avatarInst.address,
                daoCreatorInst,
                orgName,
            };
        });
    }
    setSchemes(forgedDaoInfo) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            /**
             * Truffle Solidity artifact wrappers
             */
            const ContributionReward = yield utils_1.Utils.requireContract("ContributionReward");
            const GlobalConstraintRegistrar = yield utils_1.Utils.requireContract("GlobalConstraintRegistrar");
            const SchemeRegistrar = yield utils_1.Utils.requireContract("SchemeRegistrar");
            const UpgradeScheme = yield utils_1.Utils.requireContract("UpgradeScheme");
            const GenesisProtocol = yield utils_1.Utils.requireContract("GenesisProtocol");
            /**
             *  Genesis DAO parameters
             */
            const orgNativeTokenFee = 0;
            const defaultVotingMachineParams = yield genesisProtocol_1.GetDefaultGenesisProtocolParameters();
            const schemeRegistrarPermissions = commonTypes_1.SchemePermissions.toString(commonTypes_1.DefaultSchemePermissions.SchemeRegistrar);
            const globalConstraintRegistrarPermissions = commonTypes_1.SchemePermissions.toString(commonTypes_1.DefaultSchemePermissions.GlobalConstraintRegistrar);
            const upgradeSchemePermissions = commonTypes_1.SchemePermissions.toString(commonTypes_1.DefaultSchemePermissions.UpgradeScheme);
            const contributionRewardPermissions = commonTypes_1.SchemePermissions.toString(commonTypes_1.DefaultSchemePermissions.ContributionReward);
            const genesisProtocolPermissions = commonTypes_1.SchemePermissions.toString(commonTypes_1.DefaultSchemePermissions.GenesisProtocol);
            console.log(`Setting schemes for ${forgedDaoInfo.orgName} on ${this.network}...`);
            const genesisProtocolInst = yield GenesisProtocol.deployed();
            const schemeRegistrarInst = yield SchemeRegistrar.deployed();
            const upgradeSchemeInst = yield UpgradeScheme.deployed();
            const globalConstraintRegistrarInst = yield GlobalConstraintRegistrar.deployed();
            const contributionRewardInst = yield ContributionReward.deployed();
            /**
             * Set/get the GenesisProtocol voting parameters that will be used as defaults
             * for the schemes' voting machine as we add the schemes to the Genesis DAO, below.
             */
            const genesisProtocolParams = yield genesisProtocolInst.getParametersHash([
                defaultVotingMachineParams.preBoostedVoteRequiredPercentage,
                defaultVotingMachineParams.preBoostedVotePeriodLimit,
                defaultVotingMachineParams.boostedVotePeriodLimit,
                defaultVotingMachineParams.thresholdConstA,
                defaultVotingMachineParams.thresholdConstB,
                defaultVotingMachineParams.minimumStakingFee,
                defaultVotingMachineParams.quietEndingPeriod,
                defaultVotingMachineParams.proposingRepRewardConstA,
                defaultVotingMachineParams.proposingRepRewardConstB,
                defaultVotingMachineParams.stakerFeeRatioForVoters,
                defaultVotingMachineParams.votersReputationLossRatio,
                defaultVotingMachineParams.votersGainRepRatioFromLostRep,
                defaultVotingMachineParams.daoBountyConst,
                defaultVotingMachineParams.daoBountyLimit,
            ]);
            yield genesisProtocolInst.setParameters([
                defaultVotingMachineParams.preBoostedVoteRequiredPercentage,
                defaultVotingMachineParams.preBoostedVotePeriodLimit,
                defaultVotingMachineParams.boostedVotePeriodLimit,
                defaultVotingMachineParams.thresholdConstA,
                defaultVotingMachineParams.thresholdConstB,
                defaultVotingMachineParams.minimumStakingFee,
                defaultVotingMachineParams.quietEndingPeriod,
                defaultVotingMachineParams.proposingRepRewardConstA,
                defaultVotingMachineParams.proposingRepRewardConstB,
                defaultVotingMachineParams.stakerFeeRatioForVoters,
                defaultVotingMachineParams.votersReputationLossRatio,
                defaultVotingMachineParams.votersGainRepRatioFromLostRep,
                defaultVotingMachineParams.daoBountyConst,
                defaultVotingMachineParams.daoBountyLimit,
            ]);
            /**
             * Set/get the Genesis DAO's scheme parameters, using the GenesisProtocol voting machine
             * parameters that we just obtained above.
             */
            yield schemeRegistrarInst.setParameters(genesisProtocolParams, genesisProtocolParams, genesisProtocolInst.address);
            const schemeRegisterParams = yield schemeRegistrarInst.getParametersHash(genesisProtocolParams, genesisProtocolParams, genesisProtocolInst.address);
            yield globalConstraintRegistrarInst.setParameters(genesisProtocolParams, genesisProtocolInst.address);
            const schemeGCRegisterParams = yield globalConstraintRegistrarInst.getParametersHash(genesisProtocolParams, genesisProtocolInst.address);
            yield upgradeSchemeInst.setParameters(genesisProtocolParams, genesisProtocolInst.address);
            const schemeUpgradeParams = yield upgradeSchemeInst.getParametersHash(genesisProtocolParams, genesisProtocolInst.address);
            yield contributionRewardInst.setParameters(orgNativeTokenFee, genesisProtocolParams, genesisProtocolInst.address);
            const contributionRewardParams = yield contributionRewardInst.getParametersHash(orgNativeTokenFee, genesisProtocolParams, genesisProtocolInst.address);
            /**
             * Register the schemes with the Genesis DAO
             */
            const schemesArray = [
                schemeRegistrarInst.address,
                globalConstraintRegistrarInst.address,
                upgradeSchemeInst.address,
                contributionRewardInst.address,
                genesisProtocolInst.address
            ];
            const paramsArray = [
                schemeRegisterParams,
                schemeGCRegisterParams,
                schemeUpgradeParams,
                contributionRewardParams,
                genesisProtocolParams
            ];
            const permissionArray = [
                schemeRegistrarPermissions,
                globalConstraintRegistrarPermissions,
                upgradeSchemePermissions,
                contributionRewardPermissions,
                genesisProtocolPermissions,
            ];
            const daoCreatorInst = forgedDaoInfo.daoCreatorInst;
            return daoCreatorInst.setSchemes(forgedDaoInfo.avatarAddress, schemesArray, paramsArray, permissionArray);
        });
    }
}
exports.GenesisDaoCreator = GenesisDaoCreator;
//# sourceMappingURL=createGenesisDao.js.map