Refactor core (#49)
This commit is contained in:
parent
10632fa3e5
commit
427e2cb1bd
|
@ -0,0 +1,73 @@
|
||||||
|
import { Waku } from 'js-waku'
|
||||||
|
import { JsonRpcSigner } from '@ethersproject/providers'
|
||||||
|
import { PollInitMsg } from '../models/PollInitMsg'
|
||||||
|
import { PollType } from '../types/PollType'
|
||||||
|
import { BigNumber, Wallet } from 'ethers'
|
||||||
|
import { WakuMessage } from 'js-waku'
|
||||||
|
import { TimedPollVoteMsg } from '../models/TimedPollVoteMsg'
|
||||||
|
import { DetailedTimedPoll } from '../models/DetailedTimedPoll'
|
||||||
|
import { createWaku } from '../utils/createWaku'
|
||||||
|
import { WakuVoting } from './WakuVoting'
|
||||||
|
|
||||||
|
export class WakuPolling extends WakuVoting {
|
||||||
|
protected constructor(appName: string, tokenAddress: string, waku: Waku) {
|
||||||
|
super(appName, tokenAddress, waku)
|
||||||
|
this.wakuMessages['pollInit'] = {
|
||||||
|
topic: `/${this.appName}/waku-polling/timed-polls-init/proto/`,
|
||||||
|
hashMap: {},
|
||||||
|
arr: [],
|
||||||
|
updateFunction: (msg: WakuMessage[]) =>
|
||||||
|
this.decodeMsgAndSetArray(
|
||||||
|
msg,
|
||||||
|
PollInitMsg.decode,
|
||||||
|
this.wakuMessages['pollInit'],
|
||||||
|
(e) => e.endTime > Date.now()
|
||||||
|
),
|
||||||
|
}
|
||||||
|
this.wakuMessages['pollVote'] = {
|
||||||
|
topic: `/${this.appName}/waku-polling/votes/proto/`,
|
||||||
|
hashMap: {},
|
||||||
|
arr: [],
|
||||||
|
updateFunction: (msg: WakuMessage[]) =>
|
||||||
|
this.decodeMsgAndSetArray(msg, TimedPollVoteMsg.decode, this.wakuMessages['pollVote']),
|
||||||
|
}
|
||||||
|
this.setObserver()
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async create(appName: string, tokenAddress: string, waku?: Waku) {
|
||||||
|
const wakuPolling = new WakuPolling(appName, tokenAddress, await createWaku(waku))
|
||||||
|
return wakuPolling
|
||||||
|
}
|
||||||
|
|
||||||
|
public async createTimedPoll(
|
||||||
|
signer: JsonRpcSigner | Wallet,
|
||||||
|
question: string,
|
||||||
|
answers: string[],
|
||||||
|
pollType: PollType,
|
||||||
|
minToken?: BigNumber,
|
||||||
|
endTime?: number
|
||||||
|
) {
|
||||||
|
const pollInit = await PollInitMsg.create(signer, question, answers, pollType, minToken, endTime)
|
||||||
|
await this.sendWakuMessage(this.wakuMessages['pollInit'], pollInit)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async sendTimedPollVote(
|
||||||
|
signer: JsonRpcSigner | Wallet,
|
||||||
|
pollId: string,
|
||||||
|
selectedAnswer: number,
|
||||||
|
tokenAmount?: BigNumber
|
||||||
|
) {
|
||||||
|
const pollVote = await TimedPollVoteMsg.create(signer, pollId, selectedAnswer, tokenAmount)
|
||||||
|
await this.sendWakuMessage(this.wakuMessages['pollVote'], pollVote)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getDetailedTimedPolls() {
|
||||||
|
return this.wakuMessages['pollInit'].arr.map(
|
||||||
|
(poll) =>
|
||||||
|
new DetailedTimedPoll(
|
||||||
|
poll,
|
||||||
|
this.wakuMessages['pollVote'].arr.filter((vote) => vote.pollId === poll.id)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
import { Waku } from 'js-waku'
|
||||||
|
import { WakuMessage } from 'js-waku'
|
||||||
|
import { createWaku } from '../utils/createWaku'
|
||||||
|
|
||||||
|
type WakuMessageStore = {
|
||||||
|
topic: string
|
||||||
|
hashMap: { [id: string]: boolean }
|
||||||
|
arr: any[]
|
||||||
|
updateFunction: (msg: WakuMessage[]) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
type WakuMessageStores = {
|
||||||
|
[messageType: string]: WakuMessageStore
|
||||||
|
}
|
||||||
|
|
||||||
|
export class WakuVoting {
|
||||||
|
protected appName: string
|
||||||
|
protected waku: Waku
|
||||||
|
public tokenAddress: string
|
||||||
|
|
||||||
|
protected wakuMessages: WakuMessageStores = {}
|
||||||
|
protected observers: { callback: (msg: WakuMessage) => void; topics: string[] }[] = []
|
||||||
|
protected constructor(appName: string, tokenAddress: string, waku: Waku) {
|
||||||
|
this.appName = appName
|
||||||
|
this.tokenAddress = tokenAddress
|
||||||
|
this.waku = waku
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async create(appName: string, tokenAddress: string, waku?: Waku) {
|
||||||
|
return new WakuVoting(appName, tokenAddress, await createWaku(waku))
|
||||||
|
}
|
||||||
|
|
||||||
|
public cleanUp() {
|
||||||
|
this.observers.forEach((observer) => this.waku.relay.deleteObserver(observer.callback, observer.topics))
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async setObserver() {
|
||||||
|
await Promise.all(
|
||||||
|
Object.values(this.wakuMessages).map(async (msgObj) => {
|
||||||
|
const storeMessages = await this.waku?.store.queryHistory([msgObj.topic])
|
||||||
|
if (storeMessages) {
|
||||||
|
msgObj.updateFunction(storeMessages)
|
||||||
|
}
|
||||||
|
this.waku.relay.addObserver((msg) => msgObj.updateFunction([msg]), [msgObj.topic])
|
||||||
|
this.observers.push({ callback: (msg) => msgObj.updateFunction([msg]), topics: [msgObj.topic] })
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected decodeMsgAndSetArray<T extends { id: string; timestamp: number }>(
|
||||||
|
messages: WakuMessage[],
|
||||||
|
decode: (payload: Uint8Array | undefined, timestamp: Date | undefined) => T | undefined,
|
||||||
|
msgObj: WakuMessageStore,
|
||||||
|
filterFunction?: (e: T) => boolean
|
||||||
|
) {
|
||||||
|
messages
|
||||||
|
.map((msg) => decode(msg.payload, msg.timestamp))
|
||||||
|
.sort((a, b) => ((a?.timestamp ?? new Date(0)) > (b?.timestamp ?? new Date(0)) ? 1 : -1))
|
||||||
|
.forEach((e) => {
|
||||||
|
if (e) {
|
||||||
|
if (filterFunction ? filterFunction(e) : true && !msgObj.hashMap?.[e.id]) {
|
||||||
|
msgObj.arr.unshift(e)
|
||||||
|
msgObj.hashMap[e.id] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async sendWakuMessage<T extends { encode: () => Uint8Array | undefined; timestamp: number }>(
|
||||||
|
msgObj: WakuMessageStore,
|
||||||
|
decodedMsg: T | undefined
|
||||||
|
) {
|
||||||
|
const payload = decodedMsg?.encode()
|
||||||
|
if (payload && decodedMsg) {
|
||||||
|
const wakuMessage = await WakuMessage.fromBytes(payload, msgObj.topic, {
|
||||||
|
timestamp: new Date(decodedMsg.timestamp),
|
||||||
|
})
|
||||||
|
await this.waku?.relay.send(wakuMessage)
|
||||||
|
msgObj.updateFunction([wakuMessage])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,151 +1,4 @@
|
||||||
import { Waku } from 'js-waku'
|
import { WakuPolling } from './classes/WakuPolling'
|
||||||
import { JsonRpcSigner } from '@ethersproject/providers'
|
import { WakuVoting } from './classes/WakuVoting'
|
||||||
import { PollInitMsg } from './models/PollInitMsg'
|
|
||||||
import { PollType } from './types/PollType'
|
|
||||||
import { BigNumber, Wallet } from 'ethers'
|
|
||||||
import { WakuMessage, StoreCodec } from 'js-waku'
|
|
||||||
import { TimedPollVoteMsg } from './models/TimedPollVoteMsg'
|
|
||||||
import { DetailedTimedPoll } from './models/DetailedTimedPoll'
|
|
||||||
import { isTruthy } from './utils'
|
|
||||||
import { createWaku } from './utils/createWaku'
|
|
||||||
|
|
||||||
type WakuMessageStore = {
|
|
||||||
topic: string
|
|
||||||
hashMap: { [id: string]: boolean }
|
|
||||||
arr: any[]
|
|
||||||
updateFunction: (msg: WakuMessage[]) => void
|
|
||||||
}
|
|
||||||
|
|
||||||
type WakuMessageStores = {
|
|
||||||
[messageType: string]: WakuMessageStore
|
|
||||||
}
|
|
||||||
|
|
||||||
class WakuVoting {
|
|
||||||
protected appName: string
|
|
||||||
protected waku: Waku
|
|
||||||
public tokenAddress: string
|
|
||||||
|
|
||||||
protected wakuMessages: WakuMessageStores = {}
|
|
||||||
protected observers: { callback: (msg: WakuMessage) => void; topics: string[] }[] = []
|
|
||||||
protected constructor(appName: string, tokenAddress: string, waku: Waku) {
|
|
||||||
this.appName = appName
|
|
||||||
this.tokenAddress = tokenAddress
|
|
||||||
this.waku = waku
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async create(appName: string, tokenAddress: string, waku?: Waku) {
|
|
||||||
return new WakuVoting(appName, tokenAddress, await createWaku(waku))
|
|
||||||
}
|
|
||||||
|
|
||||||
public cleanUp() {
|
|
||||||
this.observers.forEach((observer) => this.waku.relay.deleteObserver(observer.callback, observer.topics))
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async setObserver(msgObj: WakuMessageStore) {
|
|
||||||
const storeMessages = await this.waku?.store.queryHistory([msgObj.topic])
|
|
||||||
if (storeMessages) {
|
|
||||||
msgObj.updateFunction(storeMessages)
|
|
||||||
}
|
|
||||||
this.waku.relay.addObserver((msg) => msgObj.updateFunction([msg]), [msgObj.topic])
|
|
||||||
this.observers.push({ callback: (msg) => msgObj.updateFunction([msg]), topics: [msgObj.topic] })
|
|
||||||
}
|
|
||||||
|
|
||||||
protected decodeMsgAndSetArray<T extends { id: string; timestamp: number }>(
|
|
||||||
messages: WakuMessage[],
|
|
||||||
decode: (payload: Uint8Array | undefined, timestamp: Date | undefined) => T | undefined,
|
|
||||||
msgObj: WakuMessageStore,
|
|
||||||
filterFunction?: (e: T) => boolean
|
|
||||||
) {
|
|
||||||
messages
|
|
||||||
.map((msg) => decode(msg.payload, msg.timestamp))
|
|
||||||
.sort((a, b) => ((a?.timestamp ?? new Date(0)) > (b?.timestamp ?? new Date(0)) ? 1 : -1))
|
|
||||||
.forEach((e) => {
|
|
||||||
if (e) {
|
|
||||||
if (filterFunction ? filterFunction(e) : true && !msgObj.hashMap?.[e.id]) {
|
|
||||||
msgObj.arr.unshift(e)
|
|
||||||
msgObj.hashMap[e.id] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async sendWakuMessage<T extends { encode: () => Uint8Array | undefined; timestamp: number }>(
|
|
||||||
msgObj: WakuMessageStore,
|
|
||||||
decodedMsg: T | undefined
|
|
||||||
) {
|
|
||||||
const payload = decodedMsg?.encode()
|
|
||||||
if (payload && decodedMsg) {
|
|
||||||
const wakuMessage = await WakuMessage.fromBytes(payload, msgObj.topic, {
|
|
||||||
timestamp: new Date(decodedMsg.timestamp),
|
|
||||||
})
|
|
||||||
await this.waku?.relay.send(wakuMessage)
|
|
||||||
msgObj.updateFunction([wakuMessage])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class WakuPolling extends WakuVoting {
|
|
||||||
protected constructor(appName: string, tokenAddress: string, waku: Waku) {
|
|
||||||
super(appName, tokenAddress, waku)
|
|
||||||
this.wakuMessages['pollInit'] = {
|
|
||||||
topic: `/${this.appName}/waku-polling/timed-polls-init/proto/`,
|
|
||||||
hashMap: {},
|
|
||||||
arr: [],
|
|
||||||
updateFunction: (msg: WakuMessage[]) =>
|
|
||||||
this.decodeMsgAndSetArray(
|
|
||||||
msg,
|
|
||||||
PollInitMsg.decode,
|
|
||||||
this.wakuMessages['pollInit'],
|
|
||||||
(e) => e.endTime > Date.now()
|
|
||||||
),
|
|
||||||
}
|
|
||||||
this.wakuMessages['pollVote'] = {
|
|
||||||
topic: `/${this.appName}/waku-polling/votes/proto/`,
|
|
||||||
hashMap: {},
|
|
||||||
arr: [],
|
|
||||||
updateFunction: (msg: WakuMessage[]) =>
|
|
||||||
this.decodeMsgAndSetArray(msg, TimedPollVoteMsg.decode, this.wakuMessages['pollVote']),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async create(appName: string, tokenAddress: string, waku?: Waku) {
|
|
||||||
const wakuPolling = new WakuPolling(appName, tokenAddress, await createWaku(waku))
|
|
||||||
wakuPolling.setObserver(wakuPolling.wakuMessages['pollInit'])
|
|
||||||
wakuPolling.setObserver(wakuPolling.wakuMessages['pollVote'])
|
|
||||||
return wakuPolling
|
|
||||||
}
|
|
||||||
|
|
||||||
public async createTimedPoll(
|
|
||||||
signer: JsonRpcSigner | Wallet,
|
|
||||||
question: string,
|
|
||||||
answers: string[],
|
|
||||||
pollType: PollType,
|
|
||||||
minToken?: BigNumber,
|
|
||||||
endTime?: number
|
|
||||||
) {
|
|
||||||
const pollInit = await PollInitMsg.create(signer, question, answers, pollType, minToken, endTime)
|
|
||||||
await this.sendWakuMessage(this.wakuMessages['pollInit'], pollInit)
|
|
||||||
}
|
|
||||||
|
|
||||||
public async sendTimedPollVote(
|
|
||||||
signer: JsonRpcSigner | Wallet,
|
|
||||||
pollId: string,
|
|
||||||
selectedAnswer: number,
|
|
||||||
tokenAmount?: BigNumber
|
|
||||||
) {
|
|
||||||
const pollVote = await TimedPollVoteMsg.create(signer, pollId, selectedAnswer, tokenAmount)
|
|
||||||
await this.sendWakuMessage(this.wakuMessages['pollVote'], pollVote)
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getDetailedTimedPolls() {
|
|
||||||
return this.wakuMessages['pollInit'].arr.map(
|
|
||||||
(poll) =>
|
|
||||||
new DetailedTimedPoll(
|
|
||||||
poll,
|
|
||||||
this.wakuMessages['pollVote'].arr.filter((vote) => vote.pollId === poll.id)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export { WakuVoting, WakuPolling }
|
export { WakuVoting, WakuPolling }
|
||||||
|
|
|
@ -3,7 +3,6 @@ import { BigNumber, utils, Wallet } from 'ethers'
|
||||||
import { JsonRpcSigner } from '@ethersproject/providers'
|
import { JsonRpcSigner } from '@ethersproject/providers'
|
||||||
import protons, { PollInit } from 'protons'
|
import protons, { PollInit } from 'protons'
|
||||||
import { createSignedMsg } from '../utils/createSignedMsg'
|
import { createSignedMsg } from '../utils/createSignedMsg'
|
||||||
import { recoverTypedSignature_v4 } from 'eth-sig-util'
|
|
||||||
import { verifySignature } from '../utils/verifySignature'
|
import { verifySignature } from '../utils/verifySignature'
|
||||||
|
|
||||||
const proto = protons(`
|
const proto = protons(`
|
||||||
|
|
|
@ -3,7 +3,6 @@ import { JsonRpcSigner } from '@ethersproject/providers'
|
||||||
import protons, { TimedPollVote } from 'protons'
|
import protons, { TimedPollVote } from 'protons'
|
||||||
import { Wallet } from 'ethers'
|
import { Wallet } from 'ethers'
|
||||||
import { createSignedMsg } from '../utils/createSignedMsg'
|
import { createSignedMsg } from '../utils/createSignedMsg'
|
||||||
import { recoverTypedSignature_v4 } from 'eth-sig-util'
|
|
||||||
import { verifySignature } from '../utils/verifySignature'
|
import { verifySignature } from '../utils/verifySignature'
|
||||||
|
|
||||||
const proto = protons(`
|
const proto = protons(`
|
||||||
|
|
Loading…
Reference in New Issue