Refactor waku messagning (#68)
This commit is contained in:
parent
283edd8613
commit
5b200bc60e
|
@ -1,10 +1,18 @@
|
|||
import { Waku } from 'js-waku'
|
||||
import { WakuMessage } from 'js-waku'
|
||||
import { BigNumber } from 'ethers'
|
||||
import { Provider } from '@ethersproject/providers'
|
||||
import { Contract } from '@ethersproject/contracts'
|
||||
import { Interface } from '@ethersproject/abi'
|
||||
import { ERC20 } from '../abi'
|
||||
const ABI = [
|
||||
'function aggregate(tuple(address target, bytes callData)[] calls) view returns (uint256 blockNumber, bytes[] returnData)',
|
||||
]
|
||||
|
||||
type WakuMessageStore = {
|
||||
topic: string
|
||||
hashMap: { [id: string]: boolean }
|
||||
tokenCheckArray: string[]
|
||||
arr: any[]
|
||||
updateFunction: (msg: WakuMessage[]) => void
|
||||
}
|
||||
|
@ -21,13 +29,22 @@ export class WakuMessaging {
|
|||
protected chainId = 0
|
||||
protected wakuMessages: WakuMessageStores = {}
|
||||
protected observers: { callback: (msg: WakuMessage) => void; topics: string[] }[] = []
|
||||
protected multicall: Contract
|
||||
|
||||
protected constructor(appName: string, tokenAddress: string, waku: Waku, provider: Provider, chainId: number) {
|
||||
protected constructor(
|
||||
appName: string,
|
||||
tokenAddress: string,
|
||||
waku: Waku,
|
||||
provider: Provider,
|
||||
chainId: number,
|
||||
multicall: string
|
||||
) {
|
||||
this.appName = appName
|
||||
this.tokenAddress = tokenAddress
|
||||
this.waku = waku
|
||||
this.provider = provider
|
||||
this.chainId = chainId
|
||||
this.multicall = new Contract(multicall, ABI, this.provider)
|
||||
}
|
||||
|
||||
public cleanUp() {
|
||||
|
@ -80,4 +97,55 @@ export class WakuMessaging {
|
|||
msgObj.updateFunction([wakuMessage])
|
||||
}
|
||||
}
|
||||
|
||||
protected addressesBalances: { [address: string]: BigNumber } = {}
|
||||
protected lastBlockBalances = 0
|
||||
|
||||
protected async updateBalances(newAddress?: string) {
|
||||
const addressesToUpdate: { [addr: string]: boolean } = {}
|
||||
|
||||
const addAddressToUpdate = (addr: string) => {
|
||||
if (!addressesToUpdate[addr]) {
|
||||
addressesToUpdate[addr] = true
|
||||
}
|
||||
}
|
||||
|
||||
const currentBlock = await this.provider.getBlockNumber()
|
||||
|
||||
if (this.lastBlockBalances != currentBlock) {
|
||||
Object.keys(this.addressesBalances).forEach(addAddressToUpdate)
|
||||
if (newAddress) addAddressToUpdate(newAddress)
|
||||
Object.values(this.wakuMessages).forEach((wakuMessage) =>
|
||||
wakuMessage.arr.forEach((msg) => wakuMessage.tokenCheckArray.forEach((field) => addAddressToUpdate(msg[field])))
|
||||
)
|
||||
} else {
|
||||
Object.values(this.wakuMessages).forEach((wakuMessage) =>
|
||||
wakuMessage.arr.forEach((msg) =>
|
||||
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)
|
||||
if (addressesToUpdateArray.length > 0) {
|
||||
const erc20 = new Interface(ERC20.abi)
|
||||
const callData = addressesToUpdateArray.map((addr) => {
|
||||
return [this.tokenAddress, erc20.encodeFunctionData('balanceOf', [addr])]
|
||||
})
|
||||
const result = (await this.multicall.aggregate(callData))[1].map((data: any) =>
|
||||
erc20.decodeFunctionResult('balanceOf', data)
|
||||
)
|
||||
|
||||
result.forEach((e: any, idx: number) => {
|
||||
this.addressesBalances[addressesToUpdateArray[idx]] = e[0]
|
||||
})
|
||||
this.lastBlockBalances = currentBlock
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,12 +9,6 @@ import { DetailedTimedPoll } from '../models/DetailedTimedPoll'
|
|||
import { createWaku } from '../utils/createWaku'
|
||||
import { WakuMessaging } from './WakuMessaging'
|
||||
import { Provider } from '@ethersproject/providers'
|
||||
import { Contract } from '@ethersproject/contracts'
|
||||
import { Interface } from '@ethersproject/abi'
|
||||
import { ERC20 } from '../abi'
|
||||
const ABI = [
|
||||
'function aggregate(tuple(address target, bytes callData)[] calls) view returns (uint256 blockNumber, bytes[] returnData)',
|
||||
]
|
||||
|
||||
export enum MESSEGAGE_SENDING_RESULT {
|
||||
ok = 0,
|
||||
|
@ -24,8 +18,6 @@ export enum MESSEGAGE_SENDING_RESULT {
|
|||
}
|
||||
|
||||
export class WakuPolling extends WakuMessaging {
|
||||
protected multicall: string
|
||||
|
||||
protected constructor(
|
||||
appName: string,
|
||||
tokenAddress: string,
|
||||
|
@ -34,11 +26,11 @@ export class WakuPolling extends WakuMessaging {
|
|||
chainId: number,
|
||||
multicall: string
|
||||
) {
|
||||
super(appName, tokenAddress, waku, provider, chainId)
|
||||
this.multicall = multicall
|
||||
super(appName, tokenAddress, waku, provider, chainId, multicall)
|
||||
this.wakuMessages['pollInit'] = {
|
||||
topic: `/${this.appName}/waku-polling/timed-polls-init/proto/`,
|
||||
hashMap: {},
|
||||
tokenCheckArray: ['owner'],
|
||||
arr: [],
|
||||
updateFunction: (msg: WakuMessage[]) =>
|
||||
this.decodeMsgAndSetArray(
|
||||
|
@ -51,6 +43,7 @@ export class WakuPolling extends WakuMessaging {
|
|||
this.wakuMessages['pollVote'] = {
|
||||
topic: `/${this.appName}/waku-polling/votes/proto/`,
|
||||
hashMap: {},
|
||||
tokenCheckArray: ['voter'],
|
||||
arr: [],
|
||||
updateFunction: (msg: WakuMessage[]) =>
|
||||
this.decodeMsgAndSetArray(msg, TimedPollVoteMsg.decode, this.wakuMessages['pollVote']),
|
||||
|
@ -125,54 +118,6 @@ export class WakuPolling extends WakuMessaging {
|
|||
}
|
||||
}
|
||||
|
||||
protected addressesBalances: { [address: string]: BigNumber } = {}
|
||||
protected lastBlockBalances = 0
|
||||
|
||||
protected async updateBalances(newAddress?: string) {
|
||||
const addresses: string[] = [
|
||||
...this.wakuMessages['pollInit'].arr.map((msg) => msg.owner),
|
||||
...this.wakuMessages['pollVote'].arr.map((msg) => msg.voter),
|
||||
]
|
||||
|
||||
if (newAddress) addresses.push(newAddress)
|
||||
const addressesToUpdate: { [addr: string]: boolean } = {}
|
||||
|
||||
const addAddressToUpdate = (addr: string) => {
|
||||
if (!addressesToUpdate[addr]) {
|
||||
addressesToUpdate[addr] = true
|
||||
}
|
||||
}
|
||||
|
||||
const currentBlock = await this.provider.getBlockNumber()
|
||||
if (this.lastBlockBalances != currentBlock) {
|
||||
Object.keys(this.addressesBalances).forEach(addAddressToUpdate)
|
||||
addresses.forEach(addAddressToUpdate)
|
||||
} else {
|
||||
addresses.forEach((address) => {
|
||||
if (!this.addressesBalances[address]) {
|
||||
addAddressToUpdate(address)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const addressesToUpdateArray = Object.keys(addressesToUpdate)
|
||||
if (addressesToUpdateArray.length > 0) {
|
||||
const erc20 = new Interface(ERC20.abi)
|
||||
const contract = new Contract(this.multicall, ABI, this.provider)
|
||||
const callData = addressesToUpdateArray.map((addr) => {
|
||||
return [this.tokenAddress, erc20.encodeFunctionData('balanceOf', [addr])]
|
||||
})
|
||||
const result = (await contract.aggregate(callData))[1].map((data: any) =>
|
||||
erc20.decodeFunctionResult('balanceOf', data)
|
||||
)
|
||||
|
||||
result.forEach((e: any, idx: number) => {
|
||||
this.addressesBalances[addressesToUpdateArray[idx]] = e[0]
|
||||
})
|
||||
this.lastBlockBalances = currentBlock
|
||||
}
|
||||
}
|
||||
|
||||
public async getDetailedTimedPolls() {
|
||||
await this.updateBalances()
|
||||
return this.wakuMessages['pollInit'].arr
|
||||
|
|
|
@ -6,13 +6,13 @@ import { Provider } from '@ethersproject/abstract-provider'
|
|||
import { createWaku } from '../utils/createWaku'
|
||||
import { JsonRpcSigner } from '@ethersproject/providers'
|
||||
import { VoteMsg } from '../models/VoteMsg'
|
||||
import { VotingRoom } from '../types/PollType'
|
||||
|
||||
const ABI = [
|
||||
'function aggregate(tuple(address target, bytes callData)[] calls) view returns (uint256 blockNumber, bytes[] returnData)',
|
||||
]
|
||||
|
||||
export class WakuVoting extends WakuMessaging {
|
||||
private multicall: Contract
|
||||
private votingContract: Contract
|
||||
|
||||
constructor(
|
||||
|
@ -24,13 +24,13 @@ export class WakuVoting extends WakuMessaging {
|
|||
chainId: number,
|
||||
multicallAddress: string
|
||||
) {
|
||||
super(appName, token, waku, provider, chainId)
|
||||
super(appName, token, waku, provider, chainId, multicallAddress)
|
||||
this.votingContract = votingContract
|
||||
this.multicall = new Contract(multicallAddress, ABI, this.provider)
|
||||
this.wakuMessages['vote'] = {
|
||||
topic: `/${this.appName}/waku-voting/votes/proto/`,
|
||||
hashMap: {},
|
||||
arr: [],
|
||||
tokenCheckArray: ['voter'],
|
||||
updateFunction: (msg: WakuMessage[]) =>
|
||||
this.decodeMsgAndSetArray(
|
||||
msg,
|
||||
|
@ -71,14 +71,26 @@ export class WakuVoting extends WakuMessaging {
|
|||
await this.votingContract.initializeVotingRoom(question, descripiton, tokenAmount)
|
||||
}
|
||||
|
||||
private lastPolls: any[] = []
|
||||
private lastPolls: VotingRoom[] = []
|
||||
private lastGetPollsBlockNumber = 0
|
||||
|
||||
public async getVotes() {
|
||||
public async getVotingRooms() {
|
||||
const blockNumber = await this.provider.getBlockNumber()
|
||||
if (blockNumber != this.lastGetPollsBlockNumber) {
|
||||
this.lastGetPollsBlockNumber = blockNumber
|
||||
this.lastPolls = await this.votingContract.getVotingRooms()
|
||||
const polls = await this.votingContract.getVotingRooms()
|
||||
this.lastPolls = polls.map((poll: any, idx: number): VotingRoom => {
|
||||
return {
|
||||
startBlock: poll[0],
|
||||
endAt: poll[1],
|
||||
question: poll[2],
|
||||
description: poll[3],
|
||||
totalVotesFor: poll[4],
|
||||
totalVotesAgainst: poll[5],
|
||||
voters: poll[6],
|
||||
id: idx,
|
||||
}
|
||||
})
|
||||
}
|
||||
return this.lastPolls
|
||||
}
|
||||
|
|
|
@ -1,4 +1,17 @@
|
|||
import { BigNumber } from 'ethers'
|
||||
|
||||
export enum PollType {
|
||||
WEIGHTED = 0,
|
||||
NON_WEIGHTED = 1,
|
||||
}
|
||||
|
||||
export type VotingRoom = {
|
||||
startBlock: BigNumber
|
||||
endAt: BigNumber
|
||||
question: string
|
||||
description: string
|
||||
totalVotesFor: BigNumber
|
||||
totalVotesAgainst: BigNumber
|
||||
voters: string[]
|
||||
id: number
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ export function Proposal({ wakuVoting }: ProposalProps) {
|
|||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(async () => {
|
||||
setVotes(await wakuVoting.getVotes())
|
||||
setVotes(await wakuVoting.getVotingRooms())
|
||||
}, 10000)
|
||||
return () => clearInterval(interval)
|
||||
}, [])
|
||||
|
|
|
@ -3,6 +3,8 @@ import styled from 'styled-components'
|
|||
import { Theme } from '@status-waku-voting/react-components'
|
||||
import { ProposalCard } from './ProposalCard'
|
||||
import { WakuVoting } from '@status-waku-voting/core'
|
||||
import { VotingEmpty } from './VotingEmpty'
|
||||
import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
||||
|
||||
type ProposalListProps = {
|
||||
theme: Theme
|
||||
|
@ -12,8 +14,17 @@ type ProposalListProps = {
|
|||
export function ProposalList({ theme, wakuVoting, votes }: ProposalListProps) {
|
||||
return (
|
||||
<List>
|
||||
{votes.map((vote, idx) => {
|
||||
return <ProposalCard heading={vote[2]} text={vote[3]} address={'#'} theme={theme} key={idx} id={idx} />
|
||||
{votes.map((vote) => {
|
||||
return (
|
||||
<ProposalCard
|
||||
heading={vote.question}
|
||||
text={vote.description}
|
||||
address={'#'}
|
||||
theme={theme}
|
||||
key={vote.id}
|
||||
id={vote.id}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</List>
|
||||
)
|
||||
|
|
|
@ -17,7 +17,7 @@ export function ProposalMainMobile({ wakuVoting }: ProposalMainMobileProps) {
|
|||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(async () => {
|
||||
setVotes(await wakuVoting.getVotes())
|
||||
setVotes(await wakuVoting.getVotingRooms())
|
||||
}, 10000)
|
||||
return () => clearInterval(interval)
|
||||
}, [])
|
||||
|
|
Loading…
Reference in New Issue