Improve wakuMessage query performance (#13)
This commit is contained in:
parent
8cca55ccd5
commit
54e1ca8ca2
|
@ -9,12 +9,39 @@ import { TimedPollVoteMsg } from './models/TimedPollVoteMsg'
|
|||
import TimedPollVote from './utils/proto/TimedPollVote'
|
||||
import { DetailedTimedPoll } from './models/DetailedTimedPoll'
|
||||
|
||||
function decodeWakuMessages<T>(
|
||||
messages: WakuMessage[] | null | undefined,
|
||||
decoder: { decode: (payload: Uint8Array | undefined, timestamp: Date | undefined) => T | undefined }
|
||||
) {
|
||||
return (
|
||||
messages
|
||||
?.map((msg) => decoder.decode(msg.payload, msg.timestamp))
|
||||
.filter((poll: T | undefined): poll is T => !!poll) ?? []
|
||||
)
|
||||
}
|
||||
|
||||
async function receiveNewWakuMessages(lastTimestamp: number, topic: string, waku: Waku | undefined) {
|
||||
const messages = await waku?.store.queryHistory({ contentTopics: [topic] })
|
||||
|
||||
if (messages) {
|
||||
messages.sort((a, b) => (a.timestamp && b.timestamp && a.timestamp?.getTime() < b.timestamp?.getTime() ? 1 : -1))
|
||||
const lastMessageIndex = messages.findIndex((message) => message.timestamp?.getTime() === lastTimestamp)
|
||||
const newMessages = lastMessageIndex === -1 ? messages : messages.slice(0, lastMessageIndex)
|
||||
return newMessages
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
class WakuVoting {
|
||||
private appName: string
|
||||
private waku: Waku | undefined
|
||||
public tokenAddress: string
|
||||
private pollInitTopic: string
|
||||
private timedPollVoteTopic: string
|
||||
|
||||
private timedPollInitMessages: PollInitMsg[] = []
|
||||
private timedPollVotesMessages: TimedPollVoteMsg[] = []
|
||||
|
||||
private static async createWaku() {
|
||||
const waku = await Waku.create()
|
||||
const nodes = await getStatusFleetNodes()
|
||||
|
@ -64,13 +91,14 @@ class WakuVoting {
|
|||
}
|
||||
|
||||
private async getTimedPolls() {
|
||||
const messages = await this.waku?.store.queryHistory({ contentTopics: [this.pollInitTopic] })
|
||||
return (
|
||||
messages
|
||||
?.filter((e): e is WakuMessage & { payload: Uint8Array } => !!e?.payload)
|
||||
.map((msg) => PollInit.decode(msg.payload, msg.timestamp))
|
||||
.filter((poll): poll is PollInitMsg => !!poll) ?? []
|
||||
)
|
||||
const lastTimestamp = this.timedPollInitMessages?.[0]?.timestamp ?? 0
|
||||
|
||||
const newMessages = await receiveNewWakuMessages(lastTimestamp, this.pollInitTopic, this.waku)
|
||||
const newPollInitMessages = decodeWakuMessages(newMessages, PollInit)
|
||||
if (newPollInitMessages.length > 0) {
|
||||
this.timedPollInitMessages = [...newPollInitMessages, ...this.timedPollInitMessages]
|
||||
}
|
||||
return this.timedPollInitMessages
|
||||
}
|
||||
|
||||
public async sendTimedPollVote(
|
||||
|
@ -92,13 +120,14 @@ class WakuVoting {
|
|||
}
|
||||
|
||||
private async getTimedPollsVotes() {
|
||||
const messages = await this.waku?.store.queryHistory({ contentTopics: [this.timedPollVoteTopic] })
|
||||
return (
|
||||
messages
|
||||
?.filter((e): e is WakuMessage & { payload: Uint8Array } => !!e?.payload)
|
||||
.map((msg) => TimedPollVote.decode(msg.payload, msg.timestamp))
|
||||
.filter((poll): poll is TimedPollVoteMsg => !!poll) ?? []
|
||||
)
|
||||
const lastTimestamp = this.timedPollVotesMessages?.[0]?.timestamp ?? 0
|
||||
|
||||
const newMessages = await receiveNewWakuMessages(lastTimestamp, this.timedPollVoteTopic, this.waku)
|
||||
const newVoteMessages = decodeWakuMessages(newMessages, TimedPollVote)
|
||||
if (newVoteMessages.length > 0) {
|
||||
this.timedPollVotesMessages = [...newVoteMessages, ...this.timedPollVotesMessages]
|
||||
}
|
||||
return this.timedPollVotesMessages
|
||||
}
|
||||
|
||||
public async getDetailedTimedPolls() {
|
||||
|
|
|
@ -39,7 +39,7 @@ export function createSignMsgParams(message: Message) {
|
|||
|
||||
if (message.tokenAmount) {
|
||||
msgParams.message = { ...msgParams.message, tokenAmount: message.tokenAmount.toString() }
|
||||
msgParams.types.Mail.push({ name: 'minToken', type: 'uint256' })
|
||||
msgParams.types.Mail.push({ name: 'tokenAmount', type: 'uint256' })
|
||||
}
|
||||
return msgParams
|
||||
}
|
||||
|
|
|
@ -48,10 +48,13 @@ export function encode(pollInit: PollInitMsg) {
|
|||
}
|
||||
|
||||
export function decode(
|
||||
payload: Uint8Array,
|
||||
payload: Uint8Array | undefined,
|
||||
timestamp: Date | undefined,
|
||||
recoverFunction?: ({ data, sig }: { data: any; sig: string }) => string
|
||||
) {
|
||||
if (!payload) {
|
||||
return undefined
|
||||
}
|
||||
try {
|
||||
const msg = proto.PollInit.decode(payload)
|
||||
if (!timestamp || timestamp.getTime() != msg.timestamp) {
|
||||
|
|
|
@ -33,10 +33,13 @@ export function encode(timedPollVote: TimedPollVoteMsg) {
|
|||
}
|
||||
|
||||
export function decode(
|
||||
payload: Uint8Array,
|
||||
payload: Uint8Array | undefined,
|
||||
timestamp: Date | undefined,
|
||||
recoverFunction?: ({ data, sig }: { data: any; sig: string }) => string
|
||||
) {
|
||||
if (!payload) {
|
||||
return undefined
|
||||
}
|
||||
try {
|
||||
const msg = proto.TimedPollVote.decode(payload)
|
||||
if (!timestamp || timestamp.getTime() != msg.timestamp) {
|
||||
|
|
|
@ -16,11 +16,15 @@ export function Poll({ poll, wakuVoting, signer }: PollProps) {
|
|||
const [selectedAnswer, setSelectedAnswer] = useState(0)
|
||||
const [tokenAmount, setTokenAmount] = useState(0)
|
||||
const [address, setAddress] = useState('')
|
||||
|
||||
const [userInVoters, setUserInVoters] = useState(false)
|
||||
useEffect(() => {
|
||||
signer.getAddress().then((e) => setAddress(e))
|
||||
}, [signer])
|
||||
|
||||
useEffect(() => {
|
||||
setUserInVoters(!!poll.votesMessages.find((vote) => vote.voter === address))
|
||||
}, [poll])
|
||||
|
||||
return (
|
||||
<PollWrapper>
|
||||
<PollTitle>
|
||||
|
@ -28,7 +32,7 @@ export function Poll({ poll, wakuVoting, signer }: PollProps) {
|
|||
<PollTypeWrapper>{poll.poll.pollType === PollType.WEIGHTED ? 'WEIGHTED' : 'NON WEIGHTED'}</PollTypeWrapper>
|
||||
</PollTitle>
|
||||
<PollAnswersWrapper>
|
||||
{!poll.votesMessages.find((vote) => vote.voter === address) && (
|
||||
{!userInVoters && (
|
||||
<div>
|
||||
<div onChange={(e) => setSelectedAnswer(Number.parseInt((e.target as any).value ?? 0))}>
|
||||
{poll.poll.answers.map((answer, idx) => {
|
||||
|
@ -51,7 +55,7 @@ export function Poll({ poll, wakuVoting, signer }: PollProps) {
|
|||
)}
|
||||
</div>
|
||||
)}
|
||||
{poll.votesMessages.find((vote) => vote.voter === address) && (
|
||||
{userInVoters && (
|
||||
<div>
|
||||
Results
|
||||
{poll.answers.map((answer, idx) => {
|
||||
|
@ -65,21 +69,23 @@ export function Poll({ poll, wakuVoting, signer }: PollProps) {
|
|||
</div>
|
||||
)}
|
||||
</PollAnswersWrapper>
|
||||
<button
|
||||
onClick={() => {
|
||||
if (wakuVoting) {
|
||||
wakuVoting.sendTimedPollVote(
|
||||
signer,
|
||||
poll.poll.id,
|
||||
selectedAnswer,
|
||||
poll.poll.pollType === PollType.WEIGHTED ? BigNumber.from(tokenAmount) : undefined
|
||||
)
|
||||
}
|
||||
}}
|
||||
>
|
||||
{' '}
|
||||
Vote
|
||||
</button>
|
||||
{!userInVoters && (
|
||||
<button
|
||||
onClick={() => {
|
||||
if (wakuVoting) {
|
||||
wakuVoting.sendTimedPollVote(
|
||||
signer,
|
||||
poll.poll.id,
|
||||
selectedAnswer,
|
||||
poll.poll.pollType === PollType.WEIGHTED ? BigNumber.from(tokenAmount) : undefined
|
||||
)
|
||||
}
|
||||
}}
|
||||
>
|
||||
{' '}
|
||||
Vote
|
||||
</button>
|
||||
)}
|
||||
</PollWrapper>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ export function PollList({ wakuVoting, signer }: PollListProps) {
|
|||
if (wakuVoting) {
|
||||
setPolls(await wakuVoting.getDetailedTimedPolls())
|
||||
}
|
||||
}, 1000)
|
||||
}, 5000)
|
||||
return () => clearInterval(interval)
|
||||
}, [wakuVoting])
|
||||
|
||||
|
|
|
@ -30,9 +30,9 @@ function Example({ appName }: ExampleProps) {
|
|||
provider.send('eth_requestAccounts', [])
|
||||
}, [])
|
||||
return (
|
||||
<Wrapper>
|
||||
<Wrapper onClick={() => showNewPollBox && setShowNewPollBox(false)}>
|
||||
{showNewPollBox && (
|
||||
<NewPollBoxWrapper>
|
||||
<NewPollBoxWrapper onClick={(e) => e.stopPropagation()}>
|
||||
<NewPollBox>
|
||||
<NewPollBoxTitle>
|
||||
Question
|
||||
|
@ -83,7 +83,7 @@ function Example({ appName }: ExampleProps) {
|
|||
</NewPollBox>
|
||||
</NewPollBoxWrapper>
|
||||
)}
|
||||
<button onClick={() => setShowNewPollBox(true)}>New Poll </button>
|
||||
<button onClick={() => setShowNewPollBox(true)}>New Poll</button>
|
||||
<PollList wakuVoting={wakuVoting} signer={signer} />
|
||||
</Wrapper>
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue