Refactor newVoteModal (#73)

This commit is contained in:
Szymon Szlachtowicz 2021-09-15 02:16:08 +02:00 committed by GitHub
parent 5acbc88487
commit d4c8a3c35e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 147 additions and 142 deletions

View File

@ -1,7 +1,7 @@
import { Waku } from 'js-waku'
import { WakuMessage } from 'js-waku'
import { BigNumber } from 'ethers'
import { Provider } from '@ethersproject/providers'
import { Web3Provider } from '@ethersproject/providers'
import { Contract } from '@ethersproject/contracts'
import { Interface } from '@ethersproject/abi'
import { ERC20 } from '../abi'
@ -26,7 +26,7 @@ export class WakuMessaging {
protected appName: string
protected waku: Waku | undefined
protected token: Contract
protected provider: Provider
protected provider: Web3Provider
protected chainId = 0
protected wakuMessages: WakuMessageStores = {}
protected observers: { callback: (msg: WakuMessage) => void; topics: string[] }[] = []
@ -36,7 +36,7 @@ export class WakuMessaging {
protected constructor(
appName: string,
tokenAddress: string,
provider: Provider,
provider: Web3Provider,
chainId: number,
multicall: string,
waku?: Waku

View File

@ -8,7 +8,7 @@ import { TimedPollVoteMsg } from '../models/TimedPollVoteMsg'
import { DetailedTimedPoll } from '../models/DetailedTimedPoll'
import { createWaku } from '../utils/createWaku'
import { WakuMessaging } from './WakuMessaging'
import { Provider } from '@ethersproject/providers'
import { Web3Provider } from '@ethersproject/providers'
export enum MESSEGAGE_SENDING_RESULT {
ok = 0,
@ -21,7 +21,7 @@ export class WakuPolling extends WakuMessaging {
protected constructor(
appName: string,
tokenAddress: string,
provider: Provider,
provider: Web3Provider,
chainId: number,
multicall: string,
waku?: Waku
@ -54,7 +54,7 @@ export class WakuPolling extends WakuMessaging {
public static async create(
appName: string,
tokenAddress: string,
provider: Provider,
provider: Web3Provider,
multicall: string,
waku?: Waku
) {

View File

@ -1,10 +1,9 @@
import { VotingContract } from '@status-waku-voting/contracts/abi'
import { WakuMessaging } from './WakuMessaging'
import { Contract, Wallet, BigNumber } from 'ethers'
import { Contract, Wallet, BigNumber, ethers } from 'ethers'
import { Waku, WakuMessage } from 'js-waku'
import { Provider } from '@ethersproject/abstract-provider'
import { createWaku } from '../utils/createWaku'
import { JsonRpcSigner } from '@ethersproject/providers'
import { JsonRpcSigner, Web3Provider } from '@ethersproject/providers'
import { VoteMsg } from '../models/VoteMsg'
import { VotingRoom } from '../types/PollType'
@ -19,7 +18,7 @@ export class WakuVoting extends WakuMessaging {
appName: string,
votingContract: Contract,
token: string,
provider: Provider,
provider: Web3Provider,
chainId: number,
multicallAddress: string,
waku?: Waku
@ -44,7 +43,7 @@ export class WakuVoting extends WakuMessaging {
public static async create(
appName: string,
contractAddress: string,
provider: Provider,
provider: Web3Provider,
multicall: string,
waku?: Waku
) {
@ -54,15 +53,13 @@ export class WakuVoting extends WakuMessaging {
return new WakuVoting(appName, votingContract, tokenAddress, provider, network.chainId, multicall, waku)
}
public async createVote(
signer: JsonRpcSigner | Wallet,
question: string,
descripiton: string,
tokenAmount: BigNumber
) {
public async createVote(question: string, descripiton: string, tokenAmount: BigNumber) {
if (this.provider) {
const signer = this.provider.getSigner()
this.votingContract = await this.votingContract.connect(signer)
await this.votingContract.initializeVotingRoom(question, descripiton, tokenAmount)
}
}
private lastPolls: VotingRoom[] = []
private lastGetPollsBlockNumber = 0
@ -95,12 +92,8 @@ export class WakuVoting extends WakuMessaging {
return (await this.getVotingRooms())[id]
}
public async sendVote(
signer: JsonRpcSigner | Wallet,
roomId: number,
selectedAnswer: number,
tokenAmount: BigNumber
) {
public async sendVote(roomId: number, selectedAnswer: number, tokenAmount: BigNumber) {
const signer = this.provider.getSigner()
const vote = await VoteMsg._createWithSignFunction(
signer,
roomId,

View File

@ -1,36 +1,33 @@
import { useEffect, useState, useRef } from 'react'
import { WakuPolling } from '@status-waku-voting/core'
import { useEthers, useConfig } from '@usedapp/core'
import { Provider } from '@ethersproject/providers'
import { Web3Provider } from '@ethersproject/providers'
export function useWakuPolling(appName: string, tokenAddress: string) {
export function useWakuPolling(
appName: string,
tokenAddress: string,
provider: Web3Provider | undefined,
multicallAddress: string | undefined
) {
const [wakuPolling, setWakuPolling] = useState<WakuPolling | undefined>(undefined)
const queue = useRef(0)
const queuePos = useRef(0)
const { library, chainId } = useEthers()
const config = useConfig()
useEffect(() => {
const createNewWaku = async (queuePosition: number) => {
while (queuePosition != queuePos.current) {
await new Promise((r) => setTimeout(r, 1000))
}
if (library && chainId && config.multicallAddresses && config.multicallAddresses[chainId]) {
wakuPolling?.cleanUp()
const newWakuPoll = await WakuPolling.create(
appName,
tokenAddress,
library as unknown as Provider,
config.multicallAddresses[chainId]
)
if (provider && multicallAddress) {
const newWakuPoll = await WakuPolling.create(appName, tokenAddress, provider, multicallAddress)
setWakuPolling(newWakuPoll)
queuePos.current++
}
}
if (library && chainId) {
if (provider) {
createNewWaku(queue.current++)
}
return () => wakuPolling?.cleanUp()
}, [library])
}, [provider, multicallAddress])
return wakuPolling
}

View File

@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react'
import { useEthers } from '@usedapp/core'
import { useConfig, useEthers } from '@usedapp/core'
import styled from 'styled-components'
import { PollList, PollCreation } from '@status-waku-voting/polling-components'
@ -15,10 +15,16 @@ type WakuPollingProps = {
}
export function WakuPolling({ appName, signer, theme }: WakuPollingProps) {
const { activateBrowserWallet, account } = useEthers()
const { activateBrowserWallet, account, library, chainId } = useEthers()
const config = useConfig()
const [showPollCreation, setShowPollCreation] = useState(false)
const [selectConnect, setSelectConnect] = useState(false)
const wakuPolling = useWakuPolling(appName, '0x80ee48b5ba5c3ea556b7ff6d850d2fb2c4bc7412')
const wakuPolling = useWakuPolling(
appName,
'0x80ee48b5ba5c3ea556b7ff6d850d2fb2c4bc7412',
library,
config?.multicallAddresses?.[chainId ?? 1337]
)
return (
<Wrapper>
{showPollCreation && signer && (

View File

@ -3,10 +3,9 @@ import styled from 'styled-components'
import { useEthers } from '@usedapp/core'
import { Modal, Networks, CreateButton } from '@status-waku-voting/react-components'
import { Theme } from '@status-waku-voting/react-components/dist/esm/src/style/themes'
import { ProposeModal } from './ProposeModal'
import { ProposeVoteModal } from './ProposeVoteModal'
import { WakuVoting } from '@status-waku-voting/core'
import { BigNumber } from 'ethers'
import { NewVoteModal } from './newVoteModal/NewVoteModal'
type ProposalHeaderProps = {
theme: Theme
@ -17,55 +16,29 @@ type ProposalHeaderProps = {
export function ProposalHeader({ theme, wakuVoting, availableAmount }: ProposalHeaderProps) {
const { activateBrowserWallet, account, library } = useEthers()
const [selectConnect, setSelectConnect] = useState(false)
const [showProposeModal, setShowProposeModal] = useState(false)
const [showProposeVoteModal, setShowProposeVoteModal] = useState(false)
const [title, setTitle] = useState('')
const [text, setText] = useState('')
const setNext = (val: boolean) => {
setShowProposeVoteModal(val)
setShowProposeModal(false)
}
const [showModal, setShowModal] = useState(false)
return (
<Wrapper>
<NewVoteModal
theme={theme}
availableAmount={availableAmount}
setShowModal={setShowModal}
showModal={showModal}
wakuVoting={wakuVoting}
/>
<Header>
<Heading>Your voice has real power</Heading>
<HeaderText>
Take part in a decentralised governance by voting on proposals provided by community or creating your own.
</HeaderText>
</Header>
{showProposeModal && (
<Modal heading="Create proposal" theme={theme} setShowModal={setShowProposeModal}>
<ProposeModal
title={title}
text={text}
setText={setText}
setTitle={setTitle}
availableAmount={availableAmount}
setShowProposeVoteModal={setNext}
/>
</Modal>
)}
{showProposeVoteModal && (
<Modal heading="Create proposal" theme={theme} setShowModal={setShowProposeVoteModal}>
<ProposeVoteModal
wakuVoting={wakuVoting}
title={title}
text={text}
availableAmount={availableAmount}
setShowModal={setShowProposeVoteModal}
setText={setText}
setTitle={setTitle}
/>
</Modal>
)}
{account ? (
<CreateButton
theme={theme}
onClick={() => {
setShowProposeModal(true)
setShowModal(true)
}}
>
Create proposal

View File

@ -3,9 +3,8 @@ import { useHistory } from 'react-router'
import { useEthers } from '@usedapp/core'
import styled from 'styled-components'
import { CreateButton, Modal, Networks, Theme, useMobileVersion } from '@status-waku-voting/react-components'
import { ProposeModal } from './ProposeModal'
import { ProposeVoteModal } from './ProposeVoteModal'
import { WakuVoting } from '@status-waku-voting/core'
import { NewVoteModal } from './newVoteModal/NewVoteModal'
type VotingEmptyProps = {
theme: Theme
@ -16,22 +15,21 @@ type VotingEmptyProps = {
export function VotingEmpty({ wakuVoting, theme, availableAmount }: VotingEmptyProps) {
const { account, activateBrowserWallet } = useEthers()
const [selectConnect, setSelectConnect] = useState(false)
const [showProposeModal, setShowProposeModal] = useState(false)
const [showProposeVoteModal, setShowProposeVoteModal] = useState(false)
const [title, setTitle] = useState('')
const [text, setText] = useState('')
const [showModal, setShowModal] = useState(false)
const history = useHistory()
const ref = useRef<HTMLHeadingElement>(null)
const mobileVersion = useMobileVersion(ref, 600)
const setNext = (val: boolean) => {
setShowProposeVoteModal(val)
setShowProposeModal(false)
}
return (
<VotingEmptyWrap ref={ref}>
<NewVoteModal
theme={theme}
availableAmount={availableAmount}
setShowModal={setShowModal}
showModal={showModal}
wakuVoting={wakuVoting}
/>
<EmptyWrap>
<EmptyHeading>There are no proposals at the moment!</EmptyHeading>
<EmptyText>
@ -39,37 +37,11 @@ export function VotingEmpty({ wakuVoting, theme, availableAmount }: VotingEmptyP
likes it!
</EmptyText>
</EmptyWrap>
{showProposeModal && (
<Modal heading="Create proposal" theme={theme} setShowModal={setShowProposeModal}>
<ProposeModal
title={title}
text={text}
setText={setText}
setTitle={setTitle}
availableAmount={availableAmount}
setShowProposeVoteModal={setNext}
/>
</Modal>
)}
{showProposeVoteModal && (
<Modal heading="Create proposal" theme={theme} setShowModal={setShowProposeVoteModal}>
<ProposeVoteModal
wakuVoting={wakuVoting}
title={title}
text={text}
availableAmount={availableAmount}
setShowModal={setShowProposeVoteModal}
setText={setText}
setTitle={setTitle}
/>
</Modal>
)}
{account ? (
<EmptyCreateButton
theme={theme}
onClick={() => {
mobileVersion ? history.push(`/creation`) : setShowProposeModal(true)
mobileVersion ? history.push(`/creation`) : setShowModal(true)
}}
>
Create proposal

View File

@ -4,7 +4,14 @@ import styled from 'styled-components'
import { useHistory } from 'react-router'
import { ProposingBtn } from '../Buttons'
import { CardHeading, CardText } from '../ProposalInfo'
import { InfoText, Label, ProposingData, ProposingInfo, ProposingInput, ProposingTextInput } from '../ProposeModal'
import {
InfoText,
Label,
ProposingData,
ProposingInfo,
ProposingInput,
ProposingTextInput,
} from '../newVoteModal/ProposeModal'
import { VotePropose } from '../VotePropose'
interface ProposeVoteModalProps {

View File

@ -0,0 +1,49 @@
import { WakuVoting } from '@status-waku-voting/core'
import { Modal, Theme } from '@status-waku-voting/react-components'
import React, { useState } from 'react'
import { ProposeModal } from './ProposeModal'
import { ProposeVoteModal } from './ProposeVoteModal'
type NewVoteModalProps = {
theme: Theme
showModal: boolean
setShowModal: (val: boolean) => void
availableAmount: number
wakuVoting: WakuVoting
}
export function NewVoteModal({ theme, showModal, setShowModal, availableAmount, wakuVoting }: NewVoteModalProps) {
const [screen, setScreen] = useState(1)
const [title, setTitle] = useState('')
const [text, setText] = useState('')
if (!showModal) {
return null
}
return (
<Modal heading="Create proposal" theme={theme} setShowModal={setShowModal}>
{screen === 1 && (
<ProposeModal
title={title}
text={text}
setText={setText}
setTitle={setTitle}
availableAmount={availableAmount}
setShowProposeVoteModal={() => setScreen(2)}
/>
)}
{screen === 2 && (
<ProposeVoteModal
wakuVoting={wakuVoting}
title={title}
text={text}
availableAmount={availableAmount}
setShowModal={setShowModal}
setText={setText}
setTitle={setTitle}
/>
)}
</Modal>
)
}

View File

@ -1,7 +1,7 @@
import React from 'react'
import React, { useMemo } from 'react'
import styled from 'styled-components'
import { ProposingBtn } from './Buttons'
import { TextArea } from './Input'
import { ProposingBtn } from '../Buttons'
import { TextArea } from '../Input'
import { blueTheme } from '@status-waku-voting/react-components/dist/esm/src/style/themes'
import { BigNumber } from 'ethers'
@ -22,7 +22,7 @@ export function ProposeModal({
setTitle,
setText,
}: ProposeModalProps) {
const insufficientFunds = availableAmount < 10000
const insufficientFunds = useMemo(() => availableAmount < 10000, [availableAmount])
return (
<ProposingData>

View File

@ -2,10 +2,10 @@ import { WakuVoting } from '@status-waku-voting/core'
import { useEthers } from '@usedapp/core'
import React, { useState } from 'react'
import styled from 'styled-components'
import { ProposingBtn } from './Buttons'
import { CardHeading, CardText } from './ProposalInfo'
import { ProposingBtn } from '../Buttons'
import { CardHeading, CardText } from '../ProposalInfo'
import { ProposingData } from './ProposeModal'
import { VotePropose } from './VotePropose'
import { VotePropose } from '../VotePropose'
import { BigNumber } from 'ethers'
interface ProposeVoteModalProps {
@ -44,7 +44,7 @@ export function ProposeVoteModal({
<ProposingBtn
onClick={() => {
if (library) wakuVoting.createVote(library.getSigner(), title, text, BigNumber.from(proposingAmount))
wakuVoting.createVote(title, text, BigNumber.from(proposingAmount))
setShowModal(false)
setTitle('')
setText('')

View File

@ -1,26 +1,27 @@
import { WakuVoting } from '@status-waku-voting/core'
import React, { useEffect, useState } from 'react'
import { providers } from 'ethers'
import { Web3Provider } from '@ethersproject/providers'
export function useWakuProposal() {
export function useWakuProposal(
appName: string,
contractAddress: string,
provider: Web3Provider | undefined,
multicallAddress: string | undefined
) {
const [waku, setWaku] = useState<WakuVoting | undefined>(undefined)
useEffect(() => {
;(window as any).ethereum.on('chainChanged', () => window.location.reload())
const createWaku = async () => {
const provider = new providers.Web3Provider((window as any).ethereum)
const wak = await WakuVoting.create(
'test',
'0x5795A64A70cde4073DBa9EEBC5C6b675B15C815a',
provider,
'0x53c43764255c17bd724f74c4ef150724ac50a3ed'
)
if (provider && multicallAddress) {
const wak = await WakuVoting.create(appName, contractAddress, provider, multicallAddress)
setWaku(wak)
}
}
createWaku()
return () => (window as any).ethereum.removeListener('chainChanged', () => window.location.reload())
}, [])
}, [provider, multicallAddress, contractAddress])
return waku
}

View File

@ -5,7 +5,7 @@ import { TopBar, GlobalStyle, useMobileVersion } from '@status-waku-voting/react
import votingIcon from './assets/images/voting.svg'
import styled from 'styled-components'
import { blueTheme } from '@status-waku-voting/react-components/dist/esm/src/style/themes'
import { DAppProvider, ChainId, useEthers } from '@usedapp/core'
import { DAppProvider, ChainId, useEthers, useConfig } from '@usedapp/core'
import { DEFAULT_CONFIG } from '@usedapp/core/dist/cjs/src/model/config/default'
const config = {
@ -14,7 +14,8 @@ const config = {
[ChainId.Ropsten]: 'https://ropsten.infura.io/v3/b4451d780cc64a078ccf2181e872cfcf',
},
multicallAddresses: {
...DEFAULT_CONFIG.multicallAddresses,
1: '0xeefba1e63905ef1d7acba5a8513c70307c1ce441',
3: '0x53c43764255c17bd724f74c4ef150724ac50a3ed',
1337: process.env.GANACHE_MULTICALL_CONTRACT ?? '0x0000000000000000000000000000000000000000',
},
supportedChains: [...DEFAULT_CONFIG.supportedChains, 1337],
@ -25,8 +26,14 @@ const config = {
}
function Proposals() {
const { account, activateBrowserWallet, deactivate } = useEthers()
const waku = useWakuProposal()
const { account, activateBrowserWallet, deactivate, library, chainId } = useEthers()
const config = useConfig()
const waku = useWakuProposal(
'test',
'0x5795A64A70cde4073DBa9EEBC5C6b675B15C815a',
library,
config?.multicallAddresses?.[chainId ?? 1337]
)
const ref = useRef<HTMLHeadingElement>(null)
const mobileVersion = useMobileVersion(ref, 600)