Refactor votingRoom updating (#83)

This commit is contained in:
Szymon Szlachtowicz 2021-09-21 19:25:34 +02:00 committed by GitHub
parent e3e608e922
commit bd6f195b98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 285 additions and 112 deletions

View File

@ -22,6 +22,7 @@ contract VotingContract {
string description;
uint256 totalVotesFor;
uint256 totalVotesAgainst;
uint256 id;
address[] voters;
}
mapping(uint256 => mapping(address => bool)) private voted;
@ -52,6 +53,46 @@ contract VotingContract {
);
}
function getVotingRoomLength() public view returns (uint256) {
return votingRooms.length;
}
function getLastNVotingRooms(uint256 amount) public view returns (VotingRoom[] memory result) {
if (amount == 0) {
return new VotingRoom[](0);
}
uint256 votingRoomsLen = votingRooms.length;
uint256 limit;
if (amount > votingRoomsLen) {
limit = 0;
} else {
limit = votingRoomsLen - amount;
}
uint256 i = votingRoomsLen;
uint256 j = 0;
result = new VotingRoom[](amount);
while (i > 0 && i > limit) {
result[j++] = votingRooms[--i];
}
if (j < amount) {
assembly {
mstore(result, sub(mload(result), sub(amount, j)))
}
}
}
function getVotingRoomsFrom(uint256 id) public view returns (VotingRoom[] memory result) {
if (id + 1 > votingRooms.length) {
return new VotingRoom[](0);
}
result = new VotingRoom[](votingRooms.length - id);
uint256 i = id;
uint256 j = 0;
while (i < votingRooms.length) {
result[j++] = votingRooms[i++];
}
}
function getVotingRooms() public view returns (VotingRoom[] memory) {
return votingRooms;
}
@ -87,6 +128,7 @@ contract VotingContract {
newVotingRoom.question = question;
newVotingRoom.description = description;
newVotingRoom.totalVotesFor = voteAmount;
newVotingRoom.id = votingRooms.length;
voted[votingRooms.length][msg.sender] = true;
votingRooms.push(newVotingRoom);

View File

@ -137,17 +137,19 @@ describe('Contract', () => {
it('gets', async () => {
const { contract } = await loadFixture(fixture)
await contract.initializeVotingRoom('T1', 'short desc', BigNumber.from(100))
expect((await contract.votingRooms(0))[2]).to.eq('T1')
expect((await contract.votingRooms(0))[3]).to.eq('short desc')
expect((await contract.votingRooms(0))[4]).to.deep.eq(BigNumber.from(100))
expect((await contract.votingRooms(0))[5]).to.deep.eq(BigNumber.from(0))
const votingRoom0 = await contract.votingRooms(0)
expect(votingRoom0[2]).to.eq('T1')
expect(votingRoom0[3]).to.eq('short desc')
expect(votingRoom0[4]).to.deep.eq(BigNumber.from(100))
expect(votingRoom0[5]).to.deep.eq(BigNumber.from(0))
expect(votingRoom0[6]).to.deep.eq(BigNumber.from(0))
await contract.initializeVotingRoom('T2', 'long desc', BigNumber.from(200))
expect((await contract.votingRooms(1))[2]).to.eq('T2')
expect((await contract.votingRooms(1))[3]).to.eq('long desc')
expect((await contract.votingRooms(1))[4]).to.deep.eq(BigNumber.from(200))
expect((await contract.votingRooms(1))[5]).to.deep.eq(BigNumber.from(0))
expect((await contract.votingRooms(1))[6]).to.deep.eq(BigNumber.from(1))
})
it('reverts no room', async () => {
@ -190,6 +192,130 @@ describe('Contract', () => {
})
})
describe('helpers', () => {
describe('getLastNVotingRooms', () => {
it('get 0 voting empty', async () => {
const { contract } = await loadFixture(fixture)
expect((await contract.getLastNVotingRooms(0)).length).to.eq(0)
})
it('get 1 voting empty', async () => {
const { contract } = await loadFixture(fixture)
expect((await contract.getLastNVotingRooms(1)).length).to.eq(0)
})
it('get 1 voting 1', async () => {
const { contract } = await loadFixture(fixture)
await contract.initializeVotingRoom('T1', 't1', BigNumber.from(100))
expect((await contract.getLastNVotingRooms(1)).length).to.eq(1)
})
it('get 5 voting empty', async () => {
const { contract } = await loadFixture(fixture)
expect((await contract.getLastNVotingRooms(5)).length).to.eq(0)
})
it('get 5 voting 1', async () => {
const { contract } = await loadFixture(fixture)
await contract.initializeVotingRoom('T1', 't1', BigNumber.from(100))
expect((await contract.getLastNVotingRooms(5)).length).to.eq(1)
})
it('get 5 voting 2', async () => {
const { contract } = await loadFixture(fixture)
await contract.initializeVotingRoom('T1', 't1', BigNumber.from(100))
await contract.initializeVotingRoom('T2', 't2', BigNumber.from(200))
expect((await contract.getLastNVotingRooms(5)).length).to.eq(2)
})
it('get 5 voting 4', async () => {
const { contract } = await loadFixture(fixture)
await contract.initializeVotingRoom('T1', 't1', BigNumber.from(100))
await contract.initializeVotingRoom('T2', 't2', BigNumber.from(200))
await contract.initializeVotingRoom('T3', 't3', BigNumber.from(200))
await contract.initializeVotingRoom('T4', 't4', BigNumber.from(200))
expect((await contract.getLastNVotingRooms(5)).length).to.eq(4)
})
it('get 5 voting 5', async () => {
const { contract } = await loadFixture(fixture)
await contract.initializeVotingRoom('T1', 't1', BigNumber.from(100))
await contract.initializeVotingRoom('T2', 't2', BigNumber.from(200))
await contract.initializeVotingRoom('T3', 't3', BigNumber.from(200))
await contract.initializeVotingRoom('T4', 't4', BigNumber.from(200))
await contract.initializeVotingRoom('T5', 't5', BigNumber.from(200))
expect((await contract.getLastNVotingRooms(5)).length).to.eq(5)
})
it('get 5 voting 6', async () => {
const { contract } = await loadFixture(fixture)
await contract.initializeVotingRoom('T1', 't1', BigNumber.from(100))
await contract.initializeVotingRoom('T2', 't2', BigNumber.from(200))
await contract.initializeVotingRoom('T3', 't3', BigNumber.from(200))
await contract.initializeVotingRoom('T4', 't4', BigNumber.from(200))
await contract.initializeVotingRoom('T5', 't5', BigNumber.from(200))
await contract.initializeVotingRoom('T6', 't6', BigNumber.from(200))
await contract.initializeVotingRoom('T7', 't7', BigNumber.from(200))
expect((await contract.getLastNVotingRooms(5)).length).to.eq(5)
})
it('get 5 voting 7', async () => {
const { contract } = await loadFixture(fixture)
await contract.initializeVotingRoom('T1', 't1', BigNumber.from(100))
await contract.initializeVotingRoom('T2', 't2', BigNumber.from(200))
await contract.initializeVotingRoom('T3', 't3', BigNumber.from(200))
await contract.initializeVotingRoom('T4', 't4', BigNumber.from(200))
await contract.initializeVotingRoom('T5', 't5', BigNumber.from(200))
await contract.initializeVotingRoom('T6', 't6', BigNumber.from(200))
await contract.initializeVotingRoom('T7', 't7', BigNumber.from(200))
expect((await contract.getLastNVotingRooms(5)).length).to.eq(5)
})
})
describe('getVotingRoomsFrom', () => {
it('empty', async () => {
const { contract } = await loadFixture(fixture)
expect((await contract.getVotingRoomsFrom(1)).length).to.eq(0)
})
it('from 1 votingRooms 1', async () => {
const { contract } = await loadFixture(fixture)
await contract.initializeVotingRoom('T1', 't1', BigNumber.from(100))
expect((await contract.getVotingRoomsFrom(1)).length).to.eq(0)
})
it('from 1 votingRooms 2', async () => {
const { contract } = await loadFixture(fixture)
await contract.initializeVotingRoom('T1', 't1', BigNumber.from(100))
await contract.initializeVotingRoom('T2', 't2', BigNumber.from(200))
expect((await contract.getVotingRoomsFrom(1)).length).to.eq(1)
})
it('from 1 votingRooms 3', async () => {
const { contract } = await loadFixture(fixture)
await contract.initializeVotingRoom('T1', 't1', BigNumber.from(100))
await contract.initializeVotingRoom('T2', 't2', BigNumber.from(200))
await contract.initializeVotingRoom('T3', 't3', BigNumber.from(200))
expect((await contract.getVotingRoomsFrom(1)).length).to.eq(2)
})
it('from 0 votingRooms 0', async () => {
const { contract } = await loadFixture(fixture)
expect((await contract.getVotingRoomsFrom(0)).length).to.eq(0)
})
it('from 0 votingRooms 1', async () => {
const { contract } = await loadFixture(fixture)
await contract.initializeVotingRoom('T1', 't1', BigNumber.from(100))
expect((await contract.getVotingRoomsFrom(0)).length).to.eq(1)
})
it('from 0 votingRooms 2', async () => {
const { contract } = await loadFixture(fixture)
await contract.initializeVotingRoom('T1', 't1', BigNumber.from(100))
await contract.initializeVotingRoom('T2', 't2', BigNumber.from(100))
expect((await contract.getVotingRoomsFrom(0)).length).to.eq(2)
})
})
it('get voting rooms', async () => {
const { contract } = await loadFixture(fixture)
await contract.initializeVotingRoom('T1', 't1', BigNumber.from(100))

View File

@ -55,7 +55,7 @@ export class WakuVoting extends WakuMessaging {
const votingContract = new Contract(contractAddress, VotingContract.abi, provider)
const tokenAddress = await votingContract.token()
const providerName = (await provider.getNetwork()).name
return new WakuVoting(
const wakuVoting = new WakuVoting(
appName,
votingContract,
tokenAddress,
@ -65,6 +65,7 @@ export class WakuVoting extends WakuMessaging {
providerName,
waku
)
return wakuVoting
}
public async createVote(question: string, descripiton: string, tokenAmount: BigNumber) {
@ -77,26 +78,39 @@ export class WakuVoting extends WakuMessaging {
private lastPolls: VotingRoom[] = []
private lastGetPollsBlockNumber = 0
private lastActivePoll = 0
public async getVotingRooms() {
const blockNumber = await this.provider.getBlockNumber()
if (blockNumber != this.lastGetPollsBlockNumber) {
this.lastGetPollsBlockNumber = blockNumber
const polls = await this.votingContract.getVotingRooms()
this.lastPolls = polls.map((poll: any, idx: number): VotingRoom => {
const timeLeft = poll[1].toNumber() - Date.now() / 1000
return {
this.lastActivePoll = this.lastPolls.findIndex((poll) => poll.timeLeft > 0)
if (this.lastActivePoll < 0) {
this.lastActivePoll = this.lastPolls.length
}
const polls = await this.votingContract.getVotingRoomsFrom(this.lastActivePoll)
polls.forEach((poll: any) => {
const timeLeft = poll[1].toNumber() * 1000 - Date.now()
const votingRoom: VotingRoom = {
startBlock: poll[0],
endAt: poll[1],
question: poll[2],
description: poll[3],
totalVotesFor: poll[4],
totalVotesAgainst: poll[5],
voters: poll[6],
id: idx,
wakuTotalVotesFor: poll[4],
wakuTotalVotesAgainst: poll[5],
voters: poll[7],
id: BigNumber.from(poll[6]).toNumber(),
timeLeft,
voteWinner: timeLeft <= 0 ? (poll[5].gt(poll[4]) ? 1 : 2) : undefined,
}
if (this.lastPolls[votingRoom.id]) {
this.lastPolls[votingRoom.id] = votingRoom
} else {
this.lastPolls.push(votingRoom)
}
})
await Promise.all(
this.lastPolls.map(async (poll) => {
@ -112,15 +126,6 @@ export class WakuVoting extends WakuMessaging {
return this.lastPolls.slice().reverse()
}
public async getVotingRoom(id: number) {
try {
await this.getVotingRooms()
return this.lastPolls[id]
} catch {
return undefined
}
}
public async sendVote(roomId: number, selectedAnswer: number, tokenAmount: BigNumber) {
const signer = this.provider.getSigner()
const vote = await VoteMsg._createWithSignFunction(
@ -144,15 +149,26 @@ export class WakuVoting extends WakuMessaging {
this.votingContract.castVotes(mappedVotes)
}
public async getRoomWakuVotes(id: number) {
public async getVotingRoom(id: number) {
await this.updateBalances()
const votingRoom = await this.getVotingRoom(id)
if (!votingRoom || votingRoom.timeLeft < 0) {
let votingRoom: VotingRoom
try {
await this.getVotingRooms()
votingRoom = this.lastPolls[id]
votingRoom.wakuVotes = undefined
votingRoom.wakuTotalVotesAgainst = votingRoom.totalVotesAgainst
votingRoom.wakuTotalVotesFor = votingRoom.totalVotesFor
} catch {
return undefined
}
if (!votingRoom) {
return undefined
}
if (votingRoom.timeLeft < 0) {
return votingRoom
}
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 &&
@ -162,9 +178,9 @@ export class WakuVoting extends WakuMessaging {
if (!votersHashMap[vote.voter]) {
votersHashMap[vote.voter] = true
if (vote.answer === 0) {
newVotingRoom.totalVotesAgainst = newVotingRoom.totalVotesAgainst.add(vote.tokenAmount)
votingRoom.wakuTotalVotesAgainst = votingRoom.wakuTotalVotesAgainst.add(vote.tokenAmount)
} else {
newVotingRoom.totalVotesFor = newVotingRoom.totalVotesFor.add(vote.tokenAmount)
votingRoom.wakuTotalVotesFor = votingRoom.wakuTotalVotesFor.add(vote.tokenAmount)
}
return true
}
@ -173,6 +189,7 @@ export class WakuVoting extends WakuMessaging {
}) as VoteMsg[]
const sum = wakuVotes.reduce((prev, curr) => prev.add(curr.tokenAmount), BigNumber.from(0))
return { sum, wakuVotes, newVotingRoom }
votingRoom.wakuVotes = { sum, votes: wakuVotes }
return votingRoom
}
}

View File

@ -1,4 +1,5 @@
import { BigNumber } from 'ethers'
import { VoteMsg } from '../models/VoteMsg'
export enum PollType {
WEIGHTED = 0,
@ -12,6 +13,12 @@ export type VotingRoom = {
description: string
totalVotesFor: BigNumber
totalVotesAgainst: BigNumber
wakuTotalVotesFor: BigNumber
wakuTotalVotesAgainst: BigNumber
wakuVotes?: {
sum: BigNumber
votes: VoteMsg[]
}
voters: string[]
id: number
timeLeft: number

View File

@ -12,17 +12,17 @@ import { NewVoteModal } from './newVoteModal/NewVoteModal'
import { useEthers } from '@usedapp/core'
import { Modal, Networks, useMobileVersion, Theme } from '@status-waku-voting/react-components'
import { useHistory } from 'react-router'
import { useVotingRooms } from '@status-waku-voting/proposal-hooks'
import { useVotingRoomsId } from '@status-waku-voting/proposal-hooks'
type ProposalListHeaderProps = {
votes: VotingRoom[]
votesLength: number
theme: Theme
wakuVoting: WakuVoting
tokenBalance: number
account: string | null | undefined
}
function ProposalListHeader({ votes, theme, wakuVoting, tokenBalance, account }: ProposalListHeaderProps) {
function ProposalListHeader({ votesLength, theme, wakuVoting, tokenBalance, account }: ProposalListHeaderProps) {
const [showNewVoteModal, setShowNewVoteModal] = useState(false)
const [showConnectionModal, setShowConnectionModal] = useState(false)
const { activateBrowserWallet } = useEthers()
@ -54,7 +54,7 @@ function ProposalListHeader({ votes, theme, wakuVoting, tokenBalance, account }:
<Networks />
</Modal>
)}
{votes?.length === 0 ? (
{votesLength === 0 ? (
<VotingEmpty account={account} theme={theme} onConnectClick={onConnectClick} onCreateClick={onCreateClick} />
) : (
<ProposalHeader account={account} theme={theme} onConnectClick={onConnectClick} onCreateClick={onCreateClick} />
@ -69,14 +69,14 @@ type ProposalProps = {
}
export function Proposal({ wakuVoting, account }: ProposalProps) {
const votes = useVotingRooms(wakuVoting)
const votes = useVotingRoomsId(wakuVoting)
const tokenBalance = useTokenBalance(account, wakuVoting)
return (
<ProposalWrapper>
<ProposalVotesWrapper>
<ProposalListHeader
votes={votes}
votesLength={votes.length}
tokenBalance={tokenBalance}
theme={blueTheme}
account={account}

View File

@ -6,9 +6,10 @@ import { ProposalInfo } from './ProposalInfo'
import { ProposalVote } from './ProposalVoteCard/ProposalVote'
import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType'
import { WakuVoting } from '@status-waku-voting/core'
import { useVotingRoom } from '@status-waku-voting/proposal-hooks'
interface ProposalCardProps {
votingRoom: VotingRoom
votingRoomId: number
mobileVersion?: boolean
theme: Theme
hideModalFunction?: (val: boolean) => void
@ -20,12 +21,16 @@ interface ProposalCardProps {
export function ProposalCard({
account,
theme,
votingRoom,
votingRoomId,
mobileVersion,
availableAmount,
wakuVoting,
}: ProposalCardProps) {
const history = useHistory()
const votingRoom = useVotingRoom(votingRoomId, wakuVoting)
if (!votingRoom) {
return <></>
}
return (
<Card onClick={() => mobileVersion && history.push(`/votingRoom/${votingRoom.id.toString()}`)}>

View File

@ -9,7 +9,7 @@ import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType
type ProposalListProps = {
theme: Theme
wakuVoting: WakuVoting
votes: VotingRoom[]
votes: number[]
availableAmount: number
account: string | null | undefined
}
@ -22,9 +22,9 @@ export function ProposalList({ theme, wakuVoting, votes, availableAmount, accoun
return (
<ProposalCard
account={account}
votingRoom={votingRoom}
votingRoomId={votingRoom}
theme={theme}
key={votingRoom.id}
key={votingRoom}
mobileVersion={mobileVersion}
availableAmount={availableAmount}
wakuVoting={wakuVoting}

View File

@ -9,7 +9,6 @@ import { VoteModal } from '../VoteModal'
import { VoteAnimatedModal } from '../VoteAnimatedModal'
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 {
theme: Theme
@ -54,14 +53,12 @@ export function ProposalVote({
setShowConfirmModal(val)
}
const { votes, sum, modifiedVotingRoom } = useRoomWakuVotes(votingRoom, wakuVoting)
return (
<Card>
{showVoteModal && (
<Modal heading={votingRoom.question} setShowModal={setShowVoteModal} theme={theme}>
<VoteModal
votingRoom={modifiedVotingRoom ?? votingRoom}
votingRoom={votingRoom}
availableAmount={availableAmount}
selectedVote={selectedVoted}
proposingAmount={proposingAmount}
@ -87,7 +84,7 @@ export function ProposalVote({
<CardHeading />
)}
<VoteChart votingRoom={modifiedVotingRoom ?? votingRoom} selectedVote={selectedVoted} />
<VoteChart votingRoom={votingRoom} selectedVote={selectedVoted} />
<CardButtons>
{votingRoom.voteWinner ? (
@ -121,7 +118,11 @@ export function ProposalVote({
{' '}
<ViewLink address={'#'} />
</CardViewLink>
<VoteSubmitButton votes={sum.toNumber()} disabled={!account} onClick={() => wakuVoting.commitVotes(votes)} />
<VoteSubmitButton
votes={votingRoom?.wakuVotes?.sum.toNumber() ?? 0}
disabled={!account}
onClick={() => wakuVoting.commitVotes(votingRoom?.wakuVotes?.votes ?? [])}
/>
</CardVoteBottom>
</Card>
)

View File

@ -24,10 +24,10 @@ export function VoteChart({ votingRoom, proposingAmount, selectedVote, isAnimati
const mobileVersion = useMobileVersion(ref, 600)
const voteSum = useMemo(
() => votingRoom.totalVotesFor.add(votingRoom.totalVotesAgainst),
[votingRoom.totalVotesFor.toString(), votingRoom.totalVotesAgainst.toString()]
() => votingRoom.wakuTotalVotesFor.add(votingRoom.wakuTotalVotesAgainst),
[votingRoom.wakuTotalVotesFor.toString(), votingRoom.wakuTotalVotesAgainst.toString()]
)
const graphWidth = useMemo(() => votingRoom.totalVotesAgainst.mul(100).div(voteSum).toNumber(), [voteSum])
const graphWidth = useMemo(() => votingRoom.wakuTotalVotesAgainst.mul(100).div(voteSum).toNumber(), [voteSum])
const balanceWidth = useMemo(() => {
if (!proposingAmount) {
@ -35,12 +35,11 @@ export function VoteChart({ votingRoom, proposingAmount, selectedVote, isAnimati
} else {
const divider = voteSum.add(proposingAmount)
return selectedVote === 0
? votingRoom.totalVotesAgainst.add(proposingAmount).mul(100).div(divider).toNumber()
: votingRoom.totalVotesAgainst.mul(100).div(divider).toNumber()
? votingRoom.wakuTotalVotesAgainst.add(proposingAmount).mul(100).div(divider).toNumber()
: votingRoom.wakuTotalVotesAgainst.mul(100).div(divider).toNumber()
}
}, [graphWidth, voteSum, proposingAmount])
const timeLeft = useMemo(() => votingRoom.timeLeft * 1000, [votingRoom.timeLeft])
const voteWinner = useMemo(() => votingRoom.voteWinner, [votingRoom.voteWinner])
return (
<Votes ref={ref}>
@ -48,16 +47,18 @@ export function VoteChart({ votingRoom, proposingAmount, selectedVote, isAnimati
<VoteBox
voteType={2}
mobileVersion={mobileVersion}
totalVotes={votingRoom.totalVotesAgainst.toNumber()}
totalVotes={votingRoom.wakuTotalVotesAgainst.toNumber()}
won={voteWinner === 2}
selected={isAnimation && selectedVote === 0}
proposingAmount={proposingAmount}
/>
{!voteWinner && <TimeLeft className={selectedVote ? '' : 'notModal'}>{formatTimeLeft(timeLeft)}</TimeLeft>}
{!voteWinner && (
<TimeLeft className={selectedVote ? '' : 'notModal'}>{formatTimeLeft(votingRoom.timeLeft)}</TimeLeft>
)}
<VoteBox
voteType={1}
mobileVersion={mobileVersion}
totalVotes={votingRoom.totalVotesFor.toNumber()}
totalVotes={votingRoom.wakuTotalVotesFor.toNumber()}
won={voteWinner === 1}
selected={isAnimation && selectedVote === 1}
proposingAmount={proposingAmount}
@ -70,7 +71,9 @@ export function VoteChart({ votingRoom, proposingAmount, selectedVote, isAnimati
voteWinner={voteWinner}
isAnimation={isAnimation}
/>
<TimeLeftMobile className={selectedVote ? '' : 'notModal'}>{formatTimeLeft(timeLeft)}</TimeLeftMobile>
<TimeLeftMobile className={selectedVote ? '' : 'notModal'}>
{formatTimeLeft(votingRoom.timeLeft)}
</TimeLeftMobile>
</VoteGraphBarWrap>
</Votes>
)

View File

@ -8,7 +8,7 @@ import { VoteChart } from '../ProposalVoteCard/VoteChart'
import { ProposalInfo } from '../ProposalInfo'
import { VotePropose } from '../VotePropose'
import { VotesBtns } from '../ProposalVoteCard/ProposalVote'
import { useRoomWakuVotes, useVotingRoom } from '@status-waku-voting/proposal-hooks'
import { useVotingRoom } from '@status-waku-voting/proposal-hooks'
import { WakuVoting } from '@status-waku-voting/core'
import { BigNumber } from 'ethers'
interface ProposalVoteMobileProps {
@ -24,7 +24,6 @@ export function ProposalVoteMobile({ wakuVoting, availableAmount }: ProposalVote
const votingRoom = useVotingRoom(Number(id), wakuVoting)
const voteWinner = useMemo(() => votingRoom?.voteWinner, [votingRoom?.voteWinner])
const { votes, sum, modifiedVotingRoom } = useRoomWakuVotes(votingRoom, wakuVoting)
if (!votingRoom) {
return <>Loading</>
@ -34,7 +33,7 @@ export function ProposalVoteMobile({ wakuVoting, availableAmount }: ProposalVote
<Card>
<ProposalInfo votingRoom={votingRoom} mobileMode={true} providerName={wakuVoting.providerName} />
<VoteChartWrap>
<VoteChart votingRoom={modifiedVotingRoom ?? votingRoom} selectedVote={selectedVoted} />
<VoteChart votingRoom={votingRoom} selectedVote={selectedVoted} />
</VoteChartWrap>
{!voteWinner && (
<VotePropose
@ -73,7 +72,13 @@ export function ProposalVoteMobile({ wakuVoting, availableAmount }: ProposalVote
<CardVoteBottom>
{' '}
<VoteSubmitButton votes={sum.toNumber()} disabled={!account} onClick={() => wakuVoting.commitVotes(votes)} />
{votingRoom.wakuVotes && (
<VoteSubmitButton
votes={votingRoom.wakuVotes.sum.toNumber()}
disabled={!account}
onClick={() => wakuVoting.commitVotes(votingRoom?.wakuVotes?.votes ?? [])}
/>
)}
</CardVoteBottom>
</Card>
)

View File

@ -1,35 +0,0 @@
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 | undefined, 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 () => {
if (!votingRoom) {
return
}
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, 1000)
return () => clearInterval(interval)
}, [wakuVoting, votingRoom])
return { votes, sum, modifiedVotingRoom }
}

View File

@ -1,18 +1,22 @@
import React, { useEffect, useState } from 'react'
import React, { useEffect, useState, useRef } from 'react'
import { WakuVoting } from '@status-waku-voting/core'
import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType'
export function useVotingRoom(id: number, wakuVoting: WakuVoting) {
const [votingRoom, setVotingRoom] = useState<VotingRoom | undefined>(undefined)
const lastTimeLeft = useRef(1)
useEffect(() => {
const updateFunction = async () => {
setVotingRoom(await wakuVoting.getVotingRoom(id))
if (lastTimeLeft.current > 0) {
const votingRoom = await wakuVoting.getVotingRoom(id)
setVotingRoom(votingRoom)
lastTimeLeft.current = votingRoom?.timeLeft ?? 1
}
}
updateFunction()
const interval = setInterval(updateFunction, 10000)
const interval = setInterval(updateFunction, 1000)
return () => clearInterval(interval)
}, [id])
}, [id, wakuVoting])
return votingRoom
}

View File

@ -3,22 +3,21 @@ import { WakuVoting } from '@status-waku-voting/core'
import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType'
import React, { useEffect, useRef, useState } from 'react'
export function useVotingRooms(wakuVoting: WakuVoting) {
const [votes, setVotes] = useState<VotingRoom[]>([])
const hash = useRef('')
export function useVotingRoomsId(wakuVoting: WakuVoting) {
const [votes, setVotes] = useState<number[]>([])
const votesLength = useRef(0)
useEffect(() => {
const interval = setInterval(async () => {
const newRooms = await wakuVoting.getVotingRooms()
const newHash = id(newRooms.map((votingRoom) => votingRoom.id.toString()).join(''))
if (newHash != hash.current) {
const newRooms = (await wakuVoting.getVotingRooms()).map((e) => e.id)
if (newRooms.length != votesLength.current) {
setVotes(newRooms)
hash.current = newHash
votesLength.current = newRooms.length
}
}, 10000)
setVotes([])
wakuVoting.getVotingRooms().then((e) => {
setVotes(e)
hash.current = id(e.map((votingRoom) => votingRoom.id.toString()).join(''))
setVotes(e.map((vote) => vote.id))
votesLength.current = e.length
})
return () => clearInterval(interval)
}, [wakuVoting])

View File

@ -1,5 +1,4 @@
import { useWakuProposal } from './hooks/useWakuProposal'
import { useVotingRoom } from './hooks/useVotingRoom'
import { useVotingRooms } from './hooks/useVotingRooms'
import { useRoomWakuVotes } from './hooks/useRoomWakuVotes'
export { useWakuProposal, useVotingRoom, useVotingRooms, useRoomWakuVotes }
import { useVotingRoomsId } from './hooks/useVotingRoomsId'
export { useWakuProposal, useVotingRoom, useVotingRoomsId }

View File

@ -30,7 +30,7 @@ function Proposals() {
const config = useConfig()
const waku = useWakuProposal(
'test',
'0x5795A64A70cde4073DBa9EEBC5C6b675B15C815a',
'0x965a61B9A91400AdA142b591ab0E235024c94E3D',
library,
config?.multicallAddresses?.[chainId ?? 1337]
)