Add proposal voting (#78)
This commit is contained in:
parent
9502bc67b2
commit
e1a1203a58
|
@ -87,8 +87,17 @@ export class WakuMessaging {
|
||||||
) {
|
) {
|
||||||
const { decodeFunction, filterFunction, name } = setupData
|
const { decodeFunction, filterFunction, name } = setupData
|
||||||
const { arr, hashMap } = this.wakuMessages[name]
|
const { arr, hashMap } = this.wakuMessages[name]
|
||||||
messages
|
const decodedMessages = messages.map(decodeFunction).filter((e): e is T => !!e)
|
||||||
.map(decodeFunction)
|
|
||||||
|
const addressesToUpdate: string[] = []
|
||||||
|
decodedMessages.forEach((message: any) => {
|
||||||
|
setupData.tokenCheckArray.forEach((property) => {
|
||||||
|
addressesToUpdate.push(message?.[property])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
this.updateBalances(addressesToUpdate)
|
||||||
|
|
||||||
|
decodedMessages
|
||||||
.sort((a, b) => ((a?.timestamp ?? new Date(0)) > (b?.timestamp ?? new Date(0)) ? 1 : -1))
|
.sort((a, b) => ((a?.timestamp ?? new Date(0)) > (b?.timestamp ?? new Date(0)) ? 1 : -1))
|
||||||
.forEach((e) => {
|
.forEach((e) => {
|
||||||
if (e) {
|
if (e) {
|
||||||
|
@ -117,7 +126,7 @@ export class WakuMessaging {
|
||||||
protected addressesBalances: { [address: string]: BigNumber | undefined } = {}
|
protected addressesBalances: { [address: string]: BigNumber | undefined } = {}
|
||||||
protected lastBlockBalances = 0
|
protected lastBlockBalances = 0
|
||||||
|
|
||||||
protected async updateBalances(newAddress?: string) {
|
protected async updateBalances(newAddresses?: string[]) {
|
||||||
const addressesToUpdate: { [addr: string]: boolean } = {}
|
const addressesToUpdate: { [addr: string]: boolean } = {}
|
||||||
|
|
||||||
const addAddressToUpdate = (addr: string) => {
|
const addAddressToUpdate = (addr: string) => {
|
||||||
|
@ -130,22 +139,11 @@ export class WakuMessaging {
|
||||||
|
|
||||||
if (this.lastBlockBalances != currentBlock) {
|
if (this.lastBlockBalances != currentBlock) {
|
||||||
Object.keys(this.addressesBalances).forEach(addAddressToUpdate)
|
Object.keys(this.addressesBalances).forEach(addAddressToUpdate)
|
||||||
if (newAddress) addAddressToUpdate(newAddress)
|
newAddresses?.forEach(addAddressToUpdate)
|
||||||
Object.values(this.wakuMessages).forEach((wakuMessage) =>
|
|
||||||
wakuMessage.arr.forEach((msg) => wakuMessage.tokenCheckArray.forEach((field) => addAddressToUpdate(msg[field])))
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
Object.values(this.wakuMessages).forEach((wakuMessage) =>
|
newAddresses?.forEach((newAddress) => {
|
||||||
wakuMessage.arr.forEach((msg) =>
|
if (!this.addressesBalances[newAddress]) addAddressToUpdate(newAddress)
|
||||||
wakuMessage.tokenCheckArray.forEach((field) => {
|
})
|
||||||
const address = msg[field]
|
|
||||||
if (!this.addressesBalances[address]) {
|
|
||||||
addAddressToUpdate(address)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if (newAddress && !this.addressesBalances[newAddress]) addAddressToUpdate(newAddress)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const addressesToUpdateArray = Object.keys(addressesToUpdate)
|
const addressesToUpdateArray = Object.keys(addressesToUpdate)
|
||||||
|
@ -170,7 +168,7 @@ export class WakuMessaging {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getTokenBalance(address: string) {
|
public async getTokenBalance(address: string) {
|
||||||
await this.updateBalances(address)
|
await this.updateBalances([address])
|
||||||
return this.addressesBalances[address] ?? undefined
|
return this.addressesBalances[address] ?? undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ export class WakuPolling extends WakuMessaging {
|
||||||
endTime?: number
|
endTime?: number
|
||||||
) {
|
) {
|
||||||
const address = await signer.getAddress()
|
const address = await signer.getAddress()
|
||||||
await this.updateBalances(address)
|
await this.updateBalances([address])
|
||||||
if (this.addressesBalances[address] && this.addressesBalances[address]?.gt(minToken ?? BigNumber.from(0))) {
|
if (this.addressesBalances[address] && this.addressesBalances[address]?.gt(minToken ?? BigNumber.from(0))) {
|
||||||
const pollInit = await PollInitMsg.create(signer, question, answers, pollType, this.chainId, minToken, endTime)
|
const pollInit = await PollInitMsg.create(signer, question, answers, pollType, this.chainId, minToken, endTime)
|
||||||
if (pollInit) {
|
if (pollInit) {
|
||||||
|
@ -94,7 +94,7 @@ export class WakuPolling extends WakuMessaging {
|
||||||
const address = await signer.getAddress()
|
const address = await signer.getAddress()
|
||||||
const poll = this.wakuMessages['pollInit'].arr.find((poll: PollInitMsg): poll is PollInitMsg => poll.id === pollId)
|
const poll = this.wakuMessages['pollInit'].arr.find((poll: PollInitMsg): poll is PollInitMsg => poll.id === pollId)
|
||||||
if (poll) {
|
if (poll) {
|
||||||
await this.updateBalances(address)
|
await this.updateBalances([address])
|
||||||
if (this.addressesBalances[address] && this.addressesBalances[address]?.gt(poll.minToken ?? BigNumber.from(0))) {
|
if (this.addressesBalances[address] && this.addressesBalances[address]?.gt(poll.minToken ?? BigNumber.from(0))) {
|
||||||
const pollVote = await TimedPollVoteMsg.create(signer, pollId, selectedAnswer, this.chainId, tokenAmount)
|
const pollVote = await TimedPollVoteMsg.create(signer, pollId, selectedAnswer, this.chainId, tokenAmount)
|
||||||
if (pollVote) {
|
if (pollVote) {
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import { VotingContract } from '@status-waku-voting/contracts/abi'
|
import { VotingContract } from '@status-waku-voting/contracts/abi'
|
||||||
import { WakuMessaging } from './WakuMessaging'
|
import { WakuMessaging } from './WakuMessaging'
|
||||||
import { Contract, Wallet, BigNumber, ethers } from 'ethers'
|
import { Contract, Wallet, BigNumber, ethers, utils } from 'ethers'
|
||||||
import { Waku, WakuMessage } from 'js-waku'
|
import { Waku, WakuMessage } from 'js-waku'
|
||||||
import { createWaku } from '../utils/createWaku'
|
import { createWaku } from '../utils/createWaku'
|
||||||
import { JsonRpcSigner, Web3Provider } from '@ethersproject/providers'
|
import { JsonRpcSigner, Web3Provider } from '@ethersproject/providers'
|
||||||
import { VoteMsg } from '../models/VoteMsg'
|
import { VoteMsg } from '../models/VoteMsg'
|
||||||
import { VotingRoom } from '../types/PollType'
|
import { VotingRoom } from '../types/PollType'
|
||||||
|
import { DetailedVotingRoom } from '../models/DetailedVotingRoom'
|
||||||
|
|
||||||
const ABI = [
|
const ABI = [
|
||||||
'function aggregate(tuple(address target, bytes callData)[] calls) view returns (uint256 blockNumber, bytes[] returnData)',
|
'function aggregate(tuple(address target, bytes callData)[] calls) view returns (uint256 blockNumber, bytes[] returnData)',
|
||||||
|
@ -90,7 +91,11 @@ export class WakuVoting extends WakuMessaging {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getVotingRoom(id: number) {
|
public async getVotingRoom(id: number) {
|
||||||
return (await this.getVotingRooms())[id]
|
try {
|
||||||
|
return (await this.getVotingRooms())[id]
|
||||||
|
} catch {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async sendVote(roomId: number, selectedAnswer: number, tokenAmount: BigNumber) {
|
public async sendVote(roomId: number, selectedAnswer: number, tokenAmount: BigNumber) {
|
||||||
|
@ -105,4 +110,46 @@ export class WakuVoting extends WakuMessaging {
|
||||||
)
|
)
|
||||||
await this.sendWakuMessage(this.wakuMessages['vote'], vote)
|
await this.sendWakuMessage(this.wakuMessages['vote'], vote)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async commitVotes(votes: VoteMsg[]) {
|
||||||
|
const signer = this.provider.getSigner()
|
||||||
|
const mappedVotes = votes.map((vote) => {
|
||||||
|
const sig = utils.splitSignature(vote.signature)
|
||||||
|
return [vote.voter, BigNumber.from(vote.roomId).mul(2).add(vote.answer), vote.tokenAmount, sig.r, sig._vs]
|
||||||
|
})
|
||||||
|
this.votingContract = this.votingContract.connect(signer)
|
||||||
|
this.votingContract.castVotes(mappedVotes)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getRoomWakuVotes(id: number) {
|
||||||
|
await this.updateBalances()
|
||||||
|
const votingRoom = await this.getVotingRoom(id)
|
||||||
|
if (!votingRoom || votingRoom.timeLeft < 0) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
const votersHashMap: { [voter: string]: boolean } = {}
|
||||||
|
votingRoom.voters.forEach((voter) => (votersHashMap[voter] = true))
|
||||||
|
const newVotingRoom: VotingRoom = { ...votingRoom }
|
||||||
|
const wakuVotes = this.wakuMessages['vote'].arr.filter((vote: VoteMsg) => {
|
||||||
|
if (
|
||||||
|
vote.roomId === id &&
|
||||||
|
this.addressesBalances[vote.voter] &&
|
||||||
|
this.addressesBalances[vote.voter]?.gt(vote.tokenAmount)
|
||||||
|
) {
|
||||||
|
if (!votersHashMap[vote.voter]) {
|
||||||
|
votersHashMap[vote.voter] = true
|
||||||
|
if (vote.answer === 0) {
|
||||||
|
newVotingRoom.totalVotesAgainst = newVotingRoom.totalVotesAgainst.add(vote.tokenAmount)
|
||||||
|
} else {
|
||||||
|
newVotingRoom.totalVotesFor = newVotingRoom.totalVotesFor.add(vote.tokenAmount)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}) as VoteMsg[]
|
||||||
|
|
||||||
|
const sum = wakuVotes.reduce((prev, curr) => prev.add(curr.tokenAmount), BigNumber.from(0))
|
||||||
|
return { sum, wakuVotes, newVotingRoom }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { BigNumber } from 'ethers'
|
||||||
|
import { VotingRoom } from '../types/PollType'
|
||||||
|
import { VoteMsg } from './VoteMsg'
|
||||||
|
|
||||||
|
export class DetailedVotingRoom {
|
||||||
|
public messages: VoteMsg[] = []
|
||||||
|
public votingRoom: VotingRoom
|
||||||
|
public sum: BigNumber = BigNumber.from(0)
|
||||||
|
|
||||||
|
constructor(votingRoom: VotingRoom, voteMessages: VoteMsg[]) {
|
||||||
|
this.votingRoom = votingRoom
|
||||||
|
this.sum = voteMessages.reduce((prev, curr) => prev.add(curr.tokenAmount), BigNumber.from(0))
|
||||||
|
const votersHashMap: { [voter: string]: boolean } = {}
|
||||||
|
votingRoom.voters.forEach((voter) => (votersHashMap[voter] = true))
|
||||||
|
|
||||||
|
voteMessages.forEach((vote) => {
|
||||||
|
if (!votersHashMap[vote.voter]) {
|
||||||
|
votersHashMap[vote.voter] = true
|
||||||
|
this.messages.push(vote)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,7 +26,7 @@ type Message = {
|
||||||
export function createSignMsgParams(message: Message, chainId: number, verifyingContract: string) {
|
export function createSignMsgParams(message: Message, chainId: number, verifyingContract: string) {
|
||||||
const msgParams: any = {
|
const msgParams: any = {
|
||||||
domain: {
|
domain: {
|
||||||
name: 'Waku proposal',
|
name: 'Voting Contract',
|
||||||
version: '1',
|
version: '1',
|
||||||
chainId,
|
chainId,
|
||||||
verifyingContract,
|
verifyingContract,
|
||||||
|
@ -43,9 +43,9 @@ export function createSignMsgParams(message: Message, chainId: number, verifying
|
||||||
{ name: 'verifyingContract', type: 'address' },
|
{ name: 'verifyingContract', type: 'address' },
|
||||||
],
|
],
|
||||||
Vote: [
|
Vote: [
|
||||||
{ name: 'roomIdAndType', type: 'string' },
|
{ name: 'roomIdAndType', type: 'uint256' },
|
||||||
{ name: 'tokenAmount', type: 'string' },
|
{ name: 'tokenAmount', type: 'uint256' },
|
||||||
{ name: 'voter', type: 'string' },
|
{ name: 'voter', type: 'address' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { Theme } from '@status-waku-voting/react-components'
|
||||||
import { ProposalInfo } from './ProposalInfo'
|
import { ProposalInfo } from './ProposalInfo'
|
||||||
import { ProposalVote } from './ProposalVoteCard/ProposalVote'
|
import { ProposalVote } from './ProposalVoteCard/ProposalVote'
|
||||||
import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
||||||
|
import { WakuVoting } from '@status-waku-voting/core'
|
||||||
|
|
||||||
interface ProposalCardProps {
|
interface ProposalCardProps {
|
||||||
votingRoom: VotingRoom
|
votingRoom: VotingRoom
|
||||||
|
@ -12,15 +13,16 @@ interface ProposalCardProps {
|
||||||
theme: Theme
|
theme: Theme
|
||||||
hideModalFunction?: (val: boolean) => void
|
hideModalFunction?: (val: boolean) => void
|
||||||
availableAmount: number
|
availableAmount: number
|
||||||
|
wakuVoting: WakuVoting
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ProposalCard({ theme, votingRoom, mobileVersion, availableAmount }: ProposalCardProps) {
|
export function ProposalCard({ theme, votingRoom, mobileVersion, availableAmount, wakuVoting }: ProposalCardProps) {
|
||||||
const history = useHistory()
|
const history = useHistory()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card onClick={() => mobileVersion && history.push(`/votingRoom/${votingRoom.id.toString()}`)}>
|
<Card onClick={() => mobileVersion && history.push(`/votingRoom/${votingRoom.id.toString()}`)}>
|
||||||
<ProposalInfo votingRoom={votingRoom} />
|
<ProposalInfo votingRoom={votingRoom} />
|
||||||
<ProposalVote votingRoom={votingRoom} theme={theme} availableAmount={availableAmount} />
|
<ProposalVote votingRoom={votingRoom} theme={theme} availableAmount={availableAmount} wakuVoting={wakuVoting} />
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ export function ProposalList({ theme, wakuVoting, votes, availableAmount }: Prop
|
||||||
key={votingRoom.id}
|
key={votingRoom.id}
|
||||||
mobileVersion={mobileVersion}
|
mobileVersion={mobileVersion}
|
||||||
availableAmount={availableAmount}
|
availableAmount={availableAmount}
|
||||||
|
wakuVoting={wakuVoting}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { useEthers } from '@usedapp/core'
|
import { useEthers } from '@usedapp/core'
|
||||||
import { FinalBtn, VoteBtnAgainst, VoteBtnFor } from '../Buttons'
|
import { FinalBtn, VoteBtnAgainst, VoteBtnFor } from '../Buttons'
|
||||||
|
@ -9,15 +9,18 @@ import { Modal, Theme } from '@status-waku-voting/react-components'
|
||||||
import { VoteModal } from '../VoteModal'
|
import { VoteModal } from '../VoteModal'
|
||||||
import { VoteAnimatedModal } from '../VoteAnimatedModal'
|
import { VoteAnimatedModal } from '../VoteAnimatedModal'
|
||||||
import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
||||||
|
import { WakuVoting } from '@status-waku-voting/core'
|
||||||
|
import { useRoomWakuVotes } from '@status-waku-voting/proposal-hooks'
|
||||||
|
|
||||||
interface ProposalVoteProps {
|
interface ProposalVoteProps {
|
||||||
theme: Theme
|
theme: Theme
|
||||||
votingRoom: VotingRoom
|
votingRoom: VotingRoom
|
||||||
availableAmount: number
|
availableAmount: number
|
||||||
hideModalFunction?: (val: boolean) => void
|
hideModalFunction?: (val: boolean) => void
|
||||||
|
wakuVoting: WakuVoting
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ProposalVote({ votingRoom, theme, availableAmount, hideModalFunction }: ProposalVoteProps) {
|
export function ProposalVote({ votingRoom, theme, availableAmount, hideModalFunction, wakuVoting }: ProposalVoteProps) {
|
||||||
const { account } = useEthers()
|
const { account } = useEthers()
|
||||||
const [showVoteModal, setShowVoteModal] = useState(false)
|
const [showVoteModal, setShowVoteModal] = useState(false)
|
||||||
const [showConfirmModal, setShowConfirmModal] = useState(false)
|
const [showConfirmModal, setShowConfirmModal] = useState(false)
|
||||||
|
@ -36,24 +39,27 @@ export function ProposalVote({ votingRoom, theme, availableAmount, hideModalFunc
|
||||||
setShowConfirmModal(val)
|
setShowConfirmModal(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { votes, sum, modifiedVotingRoom } = useRoomWakuVotes(votingRoom, wakuVoting)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
{showVoteModal && (
|
{showVoteModal && (
|
||||||
<Modal heading={votingRoom.question} setShowModal={setShowVoteModal} theme={theme}>
|
<Modal heading={votingRoom.question} setShowModal={setShowVoteModal} theme={theme}>
|
||||||
<VoteModal
|
<VoteModal
|
||||||
votingRoom={votingRoom}
|
votingRoom={modifiedVotingRoom}
|
||||||
availableAmount={availableAmount}
|
availableAmount={availableAmount}
|
||||||
selectedVote={selectedVoted}
|
selectedVote={selectedVoted}
|
||||||
proposingAmount={proposingAmount}
|
proposingAmount={proposingAmount}
|
||||||
setShowConfirmModal={setNext}
|
setShowConfirmModal={setNext}
|
||||||
setProposingAmount={setProposingAmount}
|
setProposingAmount={setProposingAmount}
|
||||||
|
wakuVoting={wakuVoting}
|
||||||
/>{' '}
|
/>{' '}
|
||||||
</Modal>
|
</Modal>
|
||||||
)}
|
)}
|
||||||
{showConfirmModal && (
|
{showConfirmModal && (
|
||||||
<Modal heading={votingRoom.question} setShowModal={hideConfirm} theme={theme}>
|
<Modal heading={votingRoom.question} setShowModal={hideConfirm} theme={theme}>
|
||||||
<VoteAnimatedModal
|
<VoteAnimatedModal
|
||||||
votingRoom={votingRoom}
|
votingRoom={modifiedVotingRoom}
|
||||||
selectedVote={selectedVoted}
|
selectedVote={selectedVoted}
|
||||||
setShowModal={hideConfirm}
|
setShowModal={hideConfirm}
|
||||||
proposingAmount={proposingAmount}
|
proposingAmount={proposingAmount}
|
||||||
|
@ -66,7 +72,7 @@ export function ProposalVote({ votingRoom, theme, availableAmount, hideModalFunc
|
||||||
<CardHeading />
|
<CardHeading />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<VoteChart votingRoom={votingRoom} selectedVote={selectedVoted} />
|
<VoteChart votingRoom={modifiedVotingRoom} selectedVote={selectedVoted} />
|
||||||
|
|
||||||
<CardButtons>
|
<CardButtons>
|
||||||
{votingRoom.voteWinner ? (
|
{votingRoom.voteWinner ? (
|
||||||
|
@ -100,7 +106,7 @@ export function ProposalVote({ votingRoom, theme, availableAmount, hideModalFunc
|
||||||
{' '}
|
{' '}
|
||||||
<ViewLink address={'#'} />
|
<ViewLink address={'#'} />
|
||||||
</CardViewLink>
|
</CardViewLink>
|
||||||
<VoteSubmitButton votes={15} disabled={!account} />
|
<VoteSubmitButton votes={sum.toNumber()} disabled={!account} onClick={() => wakuVoting.commitVotes(votes)} />
|
||||||
</CardVoteBottom>
|
</CardVoteBottom>
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,11 +5,17 @@ import { VoteSendingBtn } from '../Buttons'
|
||||||
interface VoteSubmitButtonProps {
|
interface VoteSubmitButtonProps {
|
||||||
votes: number
|
votes: number
|
||||||
disabled: boolean
|
disabled: boolean
|
||||||
|
onClick: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function VoteSubmitButton({ votes, disabled }: VoteSubmitButtonProps) {
|
export function VoteSubmitButton({ votes, disabled, onClick }: VoteSubmitButtonProps) {
|
||||||
if (votes > 0) {
|
if (votes > 0) {
|
||||||
return <VoteSendingBtn disabled={disabled}> {addCommas(votes)} votes need saving</VoteSendingBtn>
|
return (
|
||||||
|
<VoteSendingBtn onClick={onClick} disabled={disabled}>
|
||||||
|
{' '}
|
||||||
|
{addCommas(votes)} votes need saving
|
||||||
|
</VoteSendingBtn>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ import { VoteChart } from './ProposalVoteCard/VoteChart'
|
||||||
import { DisabledButton, VoteBtnAgainst, VoteBtnFor } from './Buttons'
|
import { DisabledButton, VoteBtnAgainst, VoteBtnFor } from './Buttons'
|
||||||
import { VotePropose } from './VotePropose'
|
import { VotePropose } from './VotePropose'
|
||||||
import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
||||||
|
import { WakuVoting } from '@status-waku-voting/core'
|
||||||
|
import { BigNumber } from 'ethers'
|
||||||
|
|
||||||
export interface VoteModalProps {
|
export interface VoteModalProps {
|
||||||
votingRoom: VotingRoom
|
votingRoom: VotingRoom
|
||||||
|
@ -12,6 +14,7 @@ export interface VoteModalProps {
|
||||||
proposingAmount: number
|
proposingAmount: number
|
||||||
setShowConfirmModal: (show: boolean) => void
|
setShowConfirmModal: (show: boolean) => void
|
||||||
setProposingAmount: (val: number) => void
|
setProposingAmount: (val: number) => void
|
||||||
|
wakuVoting: WakuVoting
|
||||||
}
|
}
|
||||||
|
|
||||||
export function VoteModal({
|
export function VoteModal({
|
||||||
|
@ -21,6 +24,7 @@ export function VoteModal({
|
||||||
proposingAmount,
|
proposingAmount,
|
||||||
setShowConfirmModal,
|
setShowConfirmModal,
|
||||||
setProposingAmount,
|
setProposingAmount,
|
||||||
|
wakuVoting,
|
||||||
}: VoteModalProps) {
|
}: VoteModalProps) {
|
||||||
const disabled = proposingAmount === 0
|
const disabled = proposingAmount === 0
|
||||||
const funds = availableAmount > 0
|
const funds = availableAmount > 0
|
||||||
|
@ -36,16 +40,17 @@ export function VoteModal({
|
||||||
|
|
||||||
{!funds && <DisabledButton>Not enought ABC to vote</DisabledButton>}
|
{!funds && <DisabledButton>Not enought ABC to vote</DisabledButton>}
|
||||||
|
|
||||||
{funds &&
|
{funds && (
|
||||||
(selectedVote === 0 ? (
|
<ModalVoteBtnAgainst
|
||||||
<ModalVoteBtnAgainst disabled={disabled} onClick={() => setShowConfirmModal(true)}>
|
disabled={disabled}
|
||||||
Vote Against
|
onClick={async () => {
|
||||||
</ModalVoteBtnAgainst>
|
wakuVoting.sendVote(votingRoom.id, selectedVote, BigNumber.from(proposingAmount))
|
||||||
) : (
|
setShowConfirmModal(true)
|
||||||
<ModalVoteBtnFor disabled={disabled} onClick={() => setShowConfirmModal(true)}>
|
}}
|
||||||
Vote For
|
>
|
||||||
</ModalVoteBtnFor>
|
{selectedVote === 0 ? `Vote Against` : `Vote For`}
|
||||||
))}
|
</ModalVoteBtnAgainst>
|
||||||
|
)}
|
||||||
</Column>
|
</Column>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ export function ProposalVoteMobile({ wakuVoting, availableAmount }: ProposalVote
|
||||||
|
|
||||||
<CardVoteBottom>
|
<CardVoteBottom>
|
||||||
{' '}
|
{' '}
|
||||||
<VoteSubmitButton votes={15} disabled={!account} />
|
<VoteSubmitButton votes={15} disabled={!account} onClick={() => null} />
|
||||||
</CardVoteBottom>
|
</CardVoteBottom>
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
|
@ -80,6 +80,8 @@ export const Card = styled.div`
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
width: 100vw;
|
||||||
|
margin: 0px;
|
||||||
padding: 88px 16px 32px;
|
padding: 88px 16px 32px;
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import React, { useState, useRef, useEffect } from 'react'
|
||||||
|
import { WakuVoting } from '@status-waku-voting/core'
|
||||||
|
import { VoteMsg } from '@status-waku-voting/core/dist/esm/src/models/VoteMsg'
|
||||||
|
import { utils, BigNumber } from 'ethers'
|
||||||
|
import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
||||||
|
|
||||||
|
export function useRoomWakuVotes(votingRoom: VotingRoom, wakuVoting: WakuVoting) {
|
||||||
|
const [votes, setVotes] = useState<VoteMsg[]>([])
|
||||||
|
const [sum, setSum] = useState(BigNumber.from(0))
|
||||||
|
const [modifiedVotingRoom, setModifiedVotingRoom] = useState(votingRoom)
|
||||||
|
const hash = useRef('')
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const updateVotes = async () => {
|
||||||
|
const newVotes = await wakuVoting.getRoomWakuVotes(votingRoom.id)
|
||||||
|
if (newVotes) {
|
||||||
|
const newHash = utils.id(newVotes.wakuVotes.map((vote) => vote.id).join(''))
|
||||||
|
if (newHash != hash.current) {
|
||||||
|
hash.current = newHash
|
||||||
|
setVotes(newVotes.wakuVotes)
|
||||||
|
setSum(newVotes.sum)
|
||||||
|
setModifiedVotingRoom(newVotes.newVotingRoom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateVotes()
|
||||||
|
const interval = setInterval(updateVotes, 10000)
|
||||||
|
return () => clearInterval(interval)
|
||||||
|
}, [wakuVoting])
|
||||||
|
|
||||||
|
return { votes, sum, modifiedVotingRoom }
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
import { useWakuProposal } from './hooks/useWakuProposal'
|
import { useWakuProposal } from './hooks/useWakuProposal'
|
||||||
import { useVotingRoom } from './hooks/useVotingRoom'
|
import { useVotingRoom } from './hooks/useVotingRoom'
|
||||||
import { useVotingRooms } from './hooks/useVotingRooms'
|
import { useVotingRooms } from './hooks/useVotingRooms'
|
||||||
export { useWakuProposal, useVotingRoom, useVotingRooms }
|
import { useRoomWakuVotes } from './hooks/useRoomWakuVotes'
|
||||||
|
export { useWakuProposal, useVotingRoom, useVotingRooms, useRoomWakuVotes }
|
||||||
|
|
Loading…
Reference in New Issue