import { EthApi } from "@joincivil/ethapi" ; import { CivilErrors , getDefaultFromBlock } from "@joincivil/utils" ; import { EthAddress , Param , BigNumber , ParamProposalState } from "@joincivil/typescript-types" ; import * as Debug from "debug" ; import { Observable } from "rxjs" ; import { TwoStepEthTransaction } from "../../types" ; import { BaseWrapper } from "../basewrapper" ; import { GovernmentContract } from "../generated/wrappers/government" ; import { Multisig } from "../multisig/multisig" ; import { Voting } from "./voting" ; import { createTwoStepSimple } from "../utils/contracts" ; const debug = Debug ( "civil:tcr" ) ; export const enum GovtParameters { requestAppealLen = "requestAppealLen" , judgeAppealLen = "judgeAppealLen" , appealFee = "appealFee" , appealVotePercentage = "appealVotePercentage" , govtPCommitStageLen = "govtPCommitStageLen" , govtPRevealStageLen = "govtPRevealStageLen" } /**
 * The Government contract is where parameters related to appeals are stored and where
 * the controlling entities can update them and update the controlling entities as well
 */ export class Government extends BaseWrapper < GovernmentContract > { public static async singleton ( ethApi , multisigAddress ) { const instance = await GovernmentContract . singletonTrusted ( ethApi ) ; if ( ! instance ) { debug ( "Smart-contract wrapper for Parameterizer returned null, unsupported network" ) ; throw new Error ( CivilErrors . UnsupportedNetwork ) ; } const multisig = Multisig . atUntrusted ( ethApi , multisigAddress ) ; const defaultBlock = getDefaultFromBlock ( await ethApi . network ( ) ) ; return new Government ( ethApi , instance , multisig , defaultBlock ) ; } public static async atUntrusted ( web3wrapper , address ) { const instance = GovernmentContract . atUntrusted ( web3wrapper , address ) ; const appellateAddr = await instance . appellate . callAsync ( ) ; const multisig = Multisig . atUntrusted ( web3wrapper , appellateAddr ) ; const defaultBlock = getDefaultFromBlock ( await web3wrapper . network ( ) ) ; return new Government ( web3wrapper , instance , multisig , defaultBlock ) ; } private multisig : Multisig ; private constructor ( ethApi , instance , multisig , defaultBlock ) { super ( ethApi , instance , defaultBlock ) ; this . multisig = multisig ; } /**
     * Returns Voting instance associated with this Government
     */ public async getVoting ( ) { return Voting . atUntrusted ( this . ethApi , await this . getVotingAddress ( ) ) ; } /**
     * Get address for voting contract used with this Government
     */ public async getVotingAddress ( ) { return this . instance . voting . callAsync ( ) ; } /**
     * Gets an unending stream of parameters being set
     */ public getParameterSet ( fromBlock = this . defaultBlock ) { return this . instance . _ParameterSetStream ( { } , { fromBlock } ) . map ( e => { return { paramName : e . returnValues . name , value : new BigNumber ( e . returnValues . value ) , } ; } ) ; } public async getAppealFee ( ) { return this . getParameterValue ( "appealFee" ) ; } param parameter public async getParameterValue ( parameter ) { return this . instance . get . callAsync ( parameter ) . then ( d => new BigNumber ( d ) ) ; } param paramName param newValue public async set ( paramName , newValue ) { const txdata = await this . instance . proposeReparameterization . getRaw ( paramName , newValue . toString ( ) , { gas : 0 } ) ; return this . multisig . submitTransaction ( this . instance . address , this . ethApi . toBigNumber ( 0 ) , txdata . data ! ) ; } public async processProposal ( propID ) { return createTwoStepSimple ( this . ethApi , await this . instance . processProposal . sendTransactionAsync ( propID ) ) ; } /**
     * Get the URI of the Civil Constitution
     */ public async getConstitutionURI ( ) { return this . instance . constitutionURI . callAsync ( ) ; } /**
     * Get the hash of the Civil Constitution
     */ public async getConstitutionHash ( ) { return this . instance . constitutionHash . callAsync ( ) ; } public async getAppellate ( ) { return this . instance . getAppellate . callAsync ( ) ; } public async getController ( ) { return this . instance . getGovernmentController . callAsync ( ) ; } param fromBlock returns public propIDsInCommitPhase ( fromBlock = this . defaultBlock ) { return this . instance . _GovtReparameterizationProposalStream ( { } , { fromBlock } ) . map ( e => e . returnValues . propID ) . concatFilter ( async ( propID ) => this . isPropInCommitPhase ( propID ) ) ; } param fromBlock returns public propIDsInRevealPhase ( fromBlock = this . defaultBlock ) { return this . instance . _GovtReparameterizationProposalStream ( { } , { fromBlock } ) . map ( e => e . returnValues . propID ) . concatFilter ( async ( propID ) => this . isPropInRevealPhase ( propID ) ) ; } param fromBlock returns public propIDsToProcess ( fromBlock = this . defaultBlock ) { return this . instance . _GovtReparameterizationProposalStream ( { } , { fromBlock } ) . map ( e => e . returnValues . propID ) . concatFilter ( async ( propID ) => this . isPropInResolvePhase ( propID ) ) ; } public async getPropState ( propID ) { if ( ! ( await this . instance . propExists . callAsync ( propID ) ) ) { return ParamProposalState . NOT_FOUND ; } else if ( await this . isPropInCommitPhase ( propID ) ) { return ParamProposalState . CHALLENGED_IN_COMMIT_VOTE_PHASE ; } else if ( await this . isPropInRevealPhase ( propID ) ) { return ParamProposalState . CHALLENGED_IN_REVEAL_VOTE_PHASE ; } else if ( await this . isPropInResolvePhase ( propID ) ) { return ParamProposalState . READY_TO_RESOLVE_CHALLENGE ; } else { return ParamProposalState . NOT_FOUND ; } } param propID public async isPropInCommitPhase ( propID ) { if ( ! ( await this . instance . propExists . callAsync ( propID ) ) ) { return false ; } const [ challengeID ] = await this . instance . proposals . callAsync ( propID ) ; if ( new BigNumber ( challengeID ) . isZero ( ) ) { return false ; } const voting = await this . getVoting ( ) ; return voting . isCommitPeriodActive ( new BigNumber ( challengeID ) ) ; } param propID public async isPropInRevealPhase ( propID ) { if ( ! ( await this . instance . propExists . callAsync ( propID ) ) ) { return false ; } const [ challengeID ] = await this . instance . proposals . callAsync ( propID ) ; if ( new BigNumber ( challengeID ) . isZero ( ) ) { return false ; } const voting = await this . getVoting ( ) ; return voting . isRevealPeriodActive ( new BigNumber ( challengeID ) ) ; } param propID public async isPropInResolvePhase ( propID ) { if ( ! ( await this . instance . propExists . callAsync ( propID ) ) ) { return false ; } const [ challengeID ] = await this . instance . proposals . callAsync ( propID ) ; if ( new BigNumber ( challengeID ) . isZero ( ) ) { return false ; } const voting = await this . getVoting ( ) ; return voting . hasPollEnded ( new BigNumber ( challengeID ) ) ; } param parameter public async getChallengeID ( parameter ) { const [ challengeID ] = await this . instance . proposals . callAsync ( parameter ) ; return new BigNumber ( challengeID ) ; } param propID throws public async getPropCommitExpiry ( propID ) { const challengeID = await this . getChallengeID ( propID ) ; if ( challengeID . isZero ( ) ) { throw CivilErrors . NoChallenge ; } const voting = await this . getVoting ( ) ; const poll = await voting . getPoll ( challengeID ) ; const expiryTimestamp = poll . commitEndDate ; return new Date ( expiryTimestamp . toNumber ( ) * 1000 ) ; } param propID throws public async getPropRevealExpiry ( propID ) { const challengeID = await this . getChallengeID ( propID ) ; if ( challengeID . isZero ( ) ) { throw CivilErrors . NoChallenge ; } const voting = await this . getVoting ( ) ; const poll = await voting . getPoll ( challengeID ) ; const expiryTimestamp = poll . revealEndDate ; return new Date ( expiryTimestamp . toNumber ( ) * 1000 ) ; } param propID public async getPropProcessBy ( propID ) { const [ , , expiryTimestamp ] = await this . instance . proposals . callAsync ( propID ) ; return new Date ( new BigNumber ( expiryTimestamp ) . toNumber ( ) * 1000 ) ; } param propID public async getPropName ( propID ) { const [ , name ] = await this . instance . proposals . callAsync ( propID ) ; return name ; } param propID public async getPropValue ( propID ) { const [ , , , value ] = await this . instance . proposals . callAsync ( propID ) ; return new BigNumber ( value ) ; } }