Check tokens when creating polls and votes (#53)
This commit is contained in:
parent
d51b69a6a1
commit
d7cefb522b
|
@ -16,6 +16,13 @@ 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)',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
export enum MESSEGAGE_SENDING_RESULT {
|
||||||
|
ok = 0,
|
||||||
|
notEnoughToken = 1,
|
||||||
|
errorCreatingMessage = 2,
|
||||||
|
pollNotFound = 3,
|
||||||
|
}
|
||||||
|
|
||||||
export class WakuPolling extends WakuVoting {
|
export class WakuPolling extends WakuVoting {
|
||||||
protected multicall: string
|
protected multicall: string
|
||||||
|
|
||||||
|
@ -78,8 +85,19 @@ export class WakuPolling extends WakuVoting {
|
||||||
minToken?: BigNumber,
|
minToken?: BigNumber,
|
||||||
endTime?: number
|
endTime?: number
|
||||||
) {
|
) {
|
||||||
const pollInit = await PollInitMsg.create(signer, question, answers, pollType, this.chainId, minToken, endTime)
|
const address = await signer.getAddress()
|
||||||
await this.sendWakuMessage(this.wakuMessages['pollInit'], pollInit)
|
await this.updateBalances(address)
|
||||||
|
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)
|
||||||
|
if (pollInit) {
|
||||||
|
await this.sendWakuMessage(this.wakuMessages['pollInit'], pollInit)
|
||||||
|
return MESSEGAGE_SENDING_RESULT.ok
|
||||||
|
} else {
|
||||||
|
return MESSEGAGE_SENDING_RESULT.errorCreatingMessage
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return MESSEGAGE_SENDING_RESULT.notEnoughToken
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async sendTimedPollVote(
|
public async sendTimedPollVote(
|
||||||
|
@ -88,18 +106,35 @@ export class WakuPolling extends WakuVoting {
|
||||||
selectedAnswer: number,
|
selectedAnswer: number,
|
||||||
tokenAmount?: BigNumber
|
tokenAmount?: BigNumber
|
||||||
) {
|
) {
|
||||||
const pollVote = await TimedPollVoteMsg.create(signer, pollId, selectedAnswer, this.chainId, tokenAmount)
|
const address = await signer.getAddress()
|
||||||
await this.sendWakuMessage(this.wakuMessages['pollVote'], pollVote)
|
const poll = this.wakuMessages['pollInit'].arr.find((poll: PollInitMsg): poll is PollInitMsg => poll.id === pollId)
|
||||||
|
if (poll) {
|
||||||
|
await this.updateBalances(address)
|
||||||
|
if (this.addressesBalances[address] && this.addressesBalances[address]?.gt(poll.minToken ?? BigNumber.from(0))) {
|
||||||
|
const pollVote = await TimedPollVoteMsg.create(signer, pollId, selectedAnswer, this.chainId, tokenAmount)
|
||||||
|
if (pollVote) {
|
||||||
|
await this.sendWakuMessage(this.wakuMessages['pollVote'], pollVote)
|
||||||
|
} else {
|
||||||
|
return MESSEGAGE_SENDING_RESULT.errorCreatingMessage
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return MESSEGAGE_SENDING_RESULT.notEnoughToken
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return MESSEGAGE_SENDING_RESULT.pollNotFound
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected addressesBalances: { [address: string]: BigNumber } = {}
|
protected addressesBalances: { [address: string]: BigNumber } = {}
|
||||||
protected lastBlockBalances = 0
|
protected lastBlockBalances = 0
|
||||||
|
|
||||||
protected async updateBalances() {
|
protected async updateBalances(newAddress?: string) {
|
||||||
const addresses: string[] = [
|
const addresses: string[] = [
|
||||||
...this.wakuMessages['pollInit'].arr.map((msg) => msg.owner),
|
...this.wakuMessages['pollInit'].arr.map((msg) => msg.owner),
|
||||||
...this.wakuMessages['pollVote'].arr.map((msg) => msg.voter),
|
...this.wakuMessages['pollVote'].arr.map((msg) => msg.voter),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if (newAddress) addresses.push(newAddress)
|
||||||
const addressesToUpdate: { [addr: string]: boolean } = {}
|
const addressesToUpdate: { [addr: string]: boolean } = {}
|
||||||
|
|
||||||
const addAddressToUpdate = (addr: string) => {
|
const addAddressToUpdate = (addr: string) => {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import styled from 'styled-components'
|
||||||
import { RadioGroup, SmallButton } from '@status-waku-voting/react-components'
|
import { RadioGroup, SmallButton } from '@status-waku-voting/react-components'
|
||||||
import { PollResults } from './PollResults'
|
import { PollResults } from './PollResults'
|
||||||
import { useEthers } from '@usedapp/core'
|
import { useEthers } from '@usedapp/core'
|
||||||
|
import { Modal } from '@status-waku-voting/react-components'
|
||||||
type PollProps = {
|
type PollProps = {
|
||||||
poll: DetailedTimedPoll
|
poll: DetailedTimedPoll
|
||||||
wakuPolling: WakuPolling | undefined
|
wakuPolling: WakuPolling | undefined
|
||||||
|
@ -21,6 +21,7 @@ export function Poll({ poll, wakuPolling, signer }: PollProps) {
|
||||||
const [tokenAmount, setTokenAmount] = useState(0)
|
const [tokenAmount, setTokenAmount] = useState(0)
|
||||||
const [address, setAddress] = useState('')
|
const [address, setAddress] = useState('')
|
||||||
const [userInVoters, setUserInVoters] = useState(-1)
|
const [userInVoters, setUserInVoters] = useState(-1)
|
||||||
|
const [showNotEnoughTokens, setShowNotEnoughTokens] = useState(false)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (signer) {
|
if (signer) {
|
||||||
|
@ -63,14 +64,17 @@ export function Poll({ poll, wakuPolling, signer }: PollProps) {
|
||||||
{userInVoters < 0 && (
|
{userInVoters < 0 && (
|
||||||
<SmallButton
|
<SmallButton
|
||||||
disabled={!signer || !account}
|
disabled={!signer || !account}
|
||||||
onClick={() => {
|
onClick={async () => {
|
||||||
if (wakuPolling && signer) {
|
if (wakuPolling && signer) {
|
||||||
wakuPolling.sendTimedPollVote(
|
const result = await wakuPolling.sendTimedPollVote(
|
||||||
signer,
|
signer,
|
||||||
poll.poll.id,
|
poll.poll.id,
|
||||||
selectedAnswer ?? 0,
|
selectedAnswer ?? 0,
|
||||||
poll.poll.pollType === PollType.WEIGHTED ? BigNumber.from(tokenAmount) : undefined
|
poll.poll.pollType === PollType.WEIGHTED ? BigNumber.from(tokenAmount) : undefined
|
||||||
)
|
)
|
||||||
|
if (result === 1) {
|
||||||
|
setShowNotEnoughTokens(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -78,10 +82,20 @@ export function Poll({ poll, wakuPolling, signer }: PollProps) {
|
||||||
Vote
|
Vote
|
||||||
</SmallButton>
|
</SmallButton>
|
||||||
)}
|
)}
|
||||||
|
{showNotEnoughTokens && (
|
||||||
|
<Modal heading={''} setShowModal={setShowNotEnoughTokens}>
|
||||||
|
<ModalTextWrapper>You don't have enough tokens to vote</ModalTextWrapper>
|
||||||
|
</Modal>
|
||||||
|
)}
|
||||||
</PollWrapper>
|
</PollWrapper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ModalTextWrapper = styled.div`
|
||||||
|
text-align: center;
|
||||||
|
margin: 32px 0;
|
||||||
|
`
|
||||||
|
|
||||||
const VotingWrapper = styled.div`
|
const VotingWrapper = styled.div`
|
||||||
margin-top: 40px;
|
margin-top: 40px;
|
||||||
margin-left: 32px;
|
margin-left: 32px;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { ReactNode, useEffect, useState } from 'react'
|
||||||
import { Wallet } from 'ethers'
|
import { Wallet } from 'ethers'
|
||||||
import { JsonRpcSigner } from '@ethersproject/providers'
|
import { JsonRpcSigner } from '@ethersproject/providers'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
@ -13,6 +13,27 @@ function getLocaleIsoTime(dateTime: Date) {
|
||||||
return newDate.toISOString().slice(0, -8)
|
return newDate.toISOString().slice(0, -8)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ConfirmScreenProps = {
|
||||||
|
setShowModal: (val: boolean) => void
|
||||||
|
children: ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
function ConfirmScreen({ children, setShowModal }: ConfirmScreenProps) {
|
||||||
|
return (
|
||||||
|
<Confirmation>
|
||||||
|
<ConfirmationText>{children}</ConfirmationText>
|
||||||
|
<SmallButton
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
setShowModal(false)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</SmallButton>
|
||||||
|
</Confirmation>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
type PollCreationProps = {
|
type PollCreationProps = {
|
||||||
signer: JsonRpcSigner | Wallet
|
signer: JsonRpcSigner | Wallet
|
||||||
wakuPolling: WakuPolling | undefined
|
wakuPolling: WakuPolling | undefined
|
||||||
|
@ -23,13 +44,14 @@ export function PollCreation({ signer, wakuPolling, setShowPollCreation }: PollC
|
||||||
const [answers, setAnswers] = useState<string[]>(['', ''])
|
const [answers, setAnswers] = useState<string[]>(['', ''])
|
||||||
const [question, setQuestion] = useState('')
|
const [question, setQuestion] = useState('')
|
||||||
const [showCreateConfirmation, setShowCreateConfirmation] = useState(false)
|
const [showCreateConfirmation, setShowCreateConfirmation] = useState(false)
|
||||||
|
const [showNotEnoughTokens, setShowNotEnoughTokens] = useState(false)
|
||||||
const [selectedType, setSelectedType] = useState(PollType.NON_WEIGHTED)
|
const [selectedType, setSelectedType] = useState(PollType.NON_WEIGHTED)
|
||||||
const [endTimePicker, setEndTimePicker] = useState(new Date(new Date().getTime() + 10000000))
|
const [endTimePicker, setEndTimePicker] = useState(new Date(new Date().getTime() + 10000000))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal heading="Create a poll" setShowModal={setShowPollCreation}>
|
<Modal heading="Create a poll" setShowModal={setShowPollCreation}>
|
||||||
<NewPollBox>
|
<NewPollBox>
|
||||||
{!showCreateConfirmation && (
|
{!showCreateConfirmation && !showNotEnoughTokens && (
|
||||||
<PollForm>
|
<PollForm>
|
||||||
<Input
|
<Input
|
||||||
label={'Question or title of the poll'}
|
label={'Question or title of the poll'}
|
||||||
|
@ -65,7 +87,7 @@ export function PollCreation({ signer, wakuPolling, setShowPollCreation }: PollC
|
||||||
<SmallButton
|
<SmallButton
|
||||||
onClick={async (e) => {
|
onClick={async (e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
await wakuPolling?.createTimedPoll(
|
const result = await wakuPolling?.createTimedPoll(
|
||||||
signer,
|
signer,
|
||||||
question,
|
question,
|
||||||
answers,
|
answers,
|
||||||
|
@ -73,7 +95,12 @@ export function PollCreation({ signer, wakuPolling, setShowPollCreation }: PollC
|
||||||
undefined,
|
undefined,
|
||||||
endTimePicker.getTime()
|
endTimePicker.getTime()
|
||||||
)
|
)
|
||||||
setShowCreateConfirmation(true)
|
if (result === 0) {
|
||||||
|
setShowCreateConfirmation(true)
|
||||||
|
}
|
||||||
|
if (result === 1) {
|
||||||
|
setShowNotEnoughTokens(true)
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Create a poll
|
Create a poll
|
||||||
|
@ -82,21 +109,14 @@ export function PollCreation({ signer, wakuPolling, setShowPollCreation }: PollC
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{showCreateConfirmation && (
|
{showCreateConfirmation && (
|
||||||
<Confirmation>
|
<ConfirmScreen setShowModal={setShowPollCreation}>
|
||||||
<ConfirmationText>
|
Your poll has been created!
|
||||||
Your poll has been created!
|
<br />
|
||||||
<br />
|
It will appear at the top of the poll list.
|
||||||
It will appear at the top of the poll list.
|
</ConfirmScreen>
|
||||||
</ConfirmationText>
|
)}
|
||||||
<SmallButton
|
{showNotEnoughTokens && (
|
||||||
onClick={(e) => {
|
<ConfirmScreen setShowModal={setShowPollCreation}>You don't have enough tokens to create poll</ConfirmScreen>
|
||||||
e.preventDefault()
|
|
||||||
setShowPollCreation(false)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Close
|
|
||||||
</SmallButton>
|
|
||||||
</Confirmation>
|
|
||||||
)}
|
)}
|
||||||
</NewPollBox>{' '}
|
</NewPollBox>{' '}
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
Loading…
Reference in New Issue