import { EthApi , requireAccount } from "@joincivil/ethapi" ; import { CivilErrors , getDefaultFromBlock } from "@joincivil/utils" ; import { Bytes32 , EthAddress , PollData , BigNumber , DecodedLogEntryEvent } from "@joincivil/typescript-types" ; import * as Debug from "debug" ; import { Observable } from "rxjs" ; import { TwoStepEthTransaction } from "../../types" ; import { BaseWrapper } from "../basewrapper" ; import { CivilPLCRVotingContract , CivilPLCRVoting } from "../generated/wrappers/civil_p_l_c_r_voting" ; import { createTwoStepSimple } from "../utils/contracts" ; const debug = Debug ( "civil:tcr" ) ; /**
 * Voting allows user to interface with polls, either from the
 * Parameterizer or the Registry
 */ export class Voting extends BaseWrapper < CivilPLCRVotingContract > { public static async singleton ( ethApi ) { const instance = await CivilPLCRVotingContract . singletonTrusted ( ethApi ) ; if ( ! instance ) { debug ( "Smart-contract wrapper for Voting returned null, unsupported network" ) ; throw new Error ( CivilErrors . UnsupportedNetwork ) ; } const defaultBlock = getDefaultFromBlock ( await ethApi . network ( ) ) ; return new Voting ( ethApi , instance , defaultBlock ) ; } public static async atUntrusted ( web3wrapper , address ) { const instance = CivilPLCRVotingContract . atUntrusted ( web3wrapper , address ) ; const defaultBlock = getDefaultFromBlock ( await web3wrapper . network ( ) ) ; return new Voting ( web3wrapper , instance , defaultBlock ) ; } private constructor ( ethApi , instance , defaultBlock ) { super ( ethApi , instance , defaultBlock ) ; } /**
     * Event Streams
     */ param fromBlock returns public activePolls ( fromBlock = this . defaultBlock , toBlock ? ) { return this . instance . _PollCreatedStream ( { } , { fromBlock , toBlock } ) . map ( e => e . returnValues . pollID ) . concatFilter ( async ( pollID ) => this . instance . pollExists . callAsync ( pollID ) ) . map ( e => new BigNumber ( e ) ) ; } param fromBlock param user public votesCommitted ( fromBlock = this . defaultBlock , user ? , toBlock ? ) { return this . instance . _VoteCommittedStream ( { voter : user } , { fromBlock , toBlock } ) . map ( e => new BigNumber ( e . returnValues . pollID ) ) ; } param fromBlock param user public votesRevealed ( fromBlock = this . defaultBlock , user ? , toBlock ? ) { return this . instance . _VoteRevealedStream ( { voter : user } , { fromBlock , toBlock } ) . map ( e => new BigNumber ( e . returnValues . pollID ) ) ; } param fromBlock param user public votesRescued ( fromBlock = this . defaultBlock , user ? , toBlock ? ) { return this . instance . _TokensRescuedStream ( { voter : user } , { fromBlock , toBlock } ) . map ( e => new BigNumber ( e . returnValues . pollID ) ) ; } public balanceUpdate ( fromBlock = this . defaultBlock , user ) { return this . instance . _VotingRightsGrantedStream ( { voter : user } , { fromBlock } ) . merge ( this . instance . _VotingRightsWithdrawnStream ( { voter : user } , { fromBlock } ) ) . concatMap ( async ( e ) => this . getNumVotingRights ( user ) ) ; } /**
     * Contract Transactions
     */ param numTokens public async withdrawVotingRights ( numTokens ) { return createTwoStepSimple ( this . ethApi , await this . instance . withdrawVotingRights . sendTransactionAsync ( this . ethApi . toBigNumber ( numTokens ) ) ) ; } param numTokens public async requestVotingRights ( numTokens ) { return createTwoStepSimple ( this . ethApi , await this . instance . requestVotingRights . sendTransactionAsync ( numTokens . toString ( ) ) ) ; } param user param pollID public async canRescueTokens ( user , pollID ) { return new Promise < boolean > ( async ( res , rej ) => { try { await this . instance . rescueTokens . estimateGasAsync ( pollID . toString ( ) , { from : user } ) ; console . log ( "can rescue tokens. pollID: " + pollID ) ; res ( true ) ; } catch ( ex ) { console . log ( "cannot rescue tokens. pollID:" + pollID ) ; res ( false ) ; } } ) ; } param pollID public async rescueTokens ( pollID ) { return createTwoStepSimple ( this . ethApi , await this . instance . rescueTokens . sendTransactionAsync ( this . ethApi . toBigNumber ( pollID ) ) ) ; } param pollIDs public async rescueTokensInMultiplePolls ( pollIDs ) { const pollIDsBN = pollIDs . map ( ( pollID , index ) => this . ethApi . toBigNumber ( pollID ) ) ; return createTwoStepSimple ( this . ethApi , await this . instance . rescueTokensInMultiplePolls . sendTransactionAsync ( pollIDsBN ) ) ; } param pollID param secretHash param numTokens param prevPollID public async commitVote ( pollID , secretHash , numTokens , prevPollID ) { return createTwoStepSimple ( this . ethApi , await this . instance . commitVote . sendTransactionAsync ( pollID . toString ( ) , secretHash , numTokens . toString ( ) , prevPollID . toString ( ) ) ) ; } param pollID param voteOption param salt public async revealVote ( pollID , voteOption , salt ) { return createTwoStepSimple ( this . ethApi , await this . instance . revealVote . sendTransactionAsync ( pollID . toString ( ) , voteOption . toString ( ) , salt . toString ( ) ) ) ; } public async getRevealedVote ( pollID , voter ) { if ( await this . didRevealVote ( voter , pollID ) ) { const reveal = await this . instance . _VoteRevealedStream ( { pollID , voter } , { fromBlock : this . defaultBlock } ) . first ( ) . toPromise ( ) ; return new BigNumber ( reveal . returnValues . choice ) ; } return undefined ; } public async isVoterWinner ( pollID , voter ) { const vote = await this . getRevealedVote ( pollID , voter ) ; if ( vote ) { const isPollPassed = await this . instance . isPassed . callAsync ( pollID . toString ( ) ) ; if ( vote . eq ( this . ethApi . toBigNumber ( 1 ) ) && isPollPassed ) { return true ; } else if ( vote . eq ( this . ethApi . toBigNumber ( 0 ) ) && ! isPollPassed ) { return true ; } } return false ; } public async getRevealedVoteEvent ( pollID , voter ) { if ( await this . didRevealVote ( voter , pollID ) ) { const reveal = await this . instance . _VoteRevealedStream ( { pollID , voter } , { fromBlock : this . defaultBlock } ) . first ( ) . toPromise ( ) ; return reveal ; } return undefined ; } /**
     * Contract Getters
     */ param tokenOwner public async getNumVotingRights ( tokenOwner ? ) { let who = tokenOwner ; if ( ! who ) { who = await requireAccount ( this . ethApi ) . toPromise ( ) ; } const balance = await this . instance . voteTokenBalance . callAsync ( who ) ; return new BigNumber ( balance ) ; } param voterAddress param pollID public async hasVoteBeenRevealed ( pollID , voter ? ) { let who = voter ; if ( ! who ) { who = await requireAccount ( this . ethApi ) . toPromise ( ) ; } return this . didRevealVote ( who , pollID ) ; } param pollID public async isRevealPeriodActive ( pollID ) { return this . instance . revealPeriodActive . callAsync ( pollID . toString ( ) ) ; } param pollID public async isCommitPeriodActive ( pollID ) { return this . instance . commitPeriodActive . callAsync ( pollID . toString ( ) ) ; } public async didCommitVote ( user , pollID ) { return this . instance . didCommit . callAsync ( user , pollID . toString ( ) ) ; } public async didRevealVote ( user , pollID ) { return this . instance . didReveal . callAsync ( user , pollID . toString ( ) ) ; } param pollID public async hasPollEnded ( pollID ) { return this . instance . pollEnded . callAsync ( pollID . toString ( ) ) ; } param pollID public async getTotalTokensForWinners ( pollID ) { const tokens = await this . instance . getTotalNumberOfTokensForWinningOption . callAsync ( pollID . toString ( ) ) ; return new BigNumber ( tokens ) ; } param voterAddress param pollID param salt public async getNumPassingTokens ( pollID , salt , voter ) { return this . instance . getNumPassingTokens . callAsync ( voter , pollID . toString ( ) , salt . toString ( ) ) . then ( e => new BigNumber ( e ) ) ; } public async getNumLosingTokens ( pollID , salt , voter ) { return this . instance . getNumLosingTokens . callAsync ( voter , pollID . toString ( ) , salt . toString ( ) ) . then ( e => new BigNumber ( e ) ) ; } public async getNumTokens ( pollID , voter ) { return this . instance . getNumTokens . callAsync ( voter , pollID . toString ( ) ) . then ( e => new BigNumber ( e ) ) ; } param pollID public async isPollPassed ( pollID ) { return this . instance . isPassed . callAsync ( pollID . toString ( ) ) ; } param tokens param account public async getPrevPollID ( tokens , pollID , account ? ) { let who = account ; if ( ! who ) { who = await requireAccount ( this . ethApi ) . toPromise ( ) ; } return this . instance . getInsertPointForNumTokens . callAsync ( who , tokens . toString ( ) , pollID . toString ( ) ) . then ( e => new BigNumber ( e ) ) ; } public async getPoll ( pollID ) { const [ commitEndDate , revealEndDate , voteQuorum , votesFor , votesAgainst ] = await this . instance . pollMap . callAsync ( pollID . toString ( ) ) ; return { commitEndDate : new BigNumber ( commitEndDate ) , revealEndDate : new BigNumber ( revealEndDate ) , voteQuorum : new BigNumber ( voteQuorum ) , votesFor : new BigNumber ( votesFor ) , votesAgainst : new BigNumber ( votesAgainst ) , } ; } }