Refactor votingRoom updating (#83)
This commit is contained in:
parent
e3e608e922
commit
bd6f195b98
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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()}`)}>
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
|
|
|
@ -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 }
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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])
|
|
@ -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 }
|
||||
|
|
|
@ -30,7 +30,7 @@ function Proposals() {
|
|||
const config = useConfig()
|
||||
const waku = useWakuProposal(
|
||||
'test',
|
||||
'0x5795A64A70cde4073DBa9EEBC5C6b675B15C815a',
|
||||
'0x965a61B9A91400AdA142b591ab0E235024c94E3D',
|
||||
library,
|
||||
config?.multicallAddresses?.[chainId ?? 1337]
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue