Add waku init poll mock (#5)
This commit is contained in:
parent
624f126f72
commit
c1b326ab9c
|
@ -1,30 +1,67 @@
|
|||
import { Waku, getStatusFleetNodes } from 'js-waku'
|
||||
import { JsonRpcSigner } from '@ethersproject/providers'
|
||||
import { PollInitMsg } from './models/PollInitMsg'
|
||||
import { PollType } from './types/PollType'
|
||||
import { BigNumber, Wallet } from 'ethers'
|
||||
import PollInit from './utils/proto/PollInit'
|
||||
import { WakuMessage } from 'js-waku'
|
||||
|
||||
class WakuVoting {
|
||||
private appName: string
|
||||
private waku: Waku | undefined
|
||||
public tokenAddress: string
|
||||
private pollInitTopic: string
|
||||
|
||||
private async createWaku() {
|
||||
this.waku = await Waku.create()
|
||||
private static async createWaku() {
|
||||
const waku = await Waku.create()
|
||||
const nodes = await getStatusFleetNodes()
|
||||
await Promise.all(
|
||||
nodes.map((addr) => {
|
||||
if (this.waku) {
|
||||
return this.waku.dial(addr)
|
||||
if (waku) {
|
||||
return waku.dial(addr)
|
||||
}
|
||||
})
|
||||
)
|
||||
return waku
|
||||
}
|
||||
|
||||
constructor(appName: string, tokenAddress: string, waku?: Waku) {
|
||||
private constructor(appName: string, tokenAddress: string, waku: Waku) {
|
||||
this.appName = appName
|
||||
this.tokenAddress = tokenAddress
|
||||
if (waku) {
|
||||
this.waku = waku
|
||||
} else {
|
||||
this.createWaku()
|
||||
this.pollInitTopic = `/${this.appName}/waku-polling/timed-polls-init/proto/`
|
||||
this.waku = waku
|
||||
}
|
||||
|
||||
public static async create(appName: string, tokenAddress: string, waku?: Waku) {
|
||||
if (!waku) {
|
||||
waku = await this.createWaku()
|
||||
}
|
||||
return new WakuVoting(appName, tokenAddress, waku)
|
||||
}
|
||||
|
||||
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)
|
||||
const payload = PollInit.encode(pollInit)
|
||||
if (payload && pollInit) {
|
||||
const wakuMessage = await WakuMessage.fromBytes(payload, this.pollInitTopic, {
|
||||
timestamp: new Date(pollInit.timestamp),
|
||||
})
|
||||
await this.waku?.relay.send(wakuMessage)
|
||||
}
|
||||
}
|
||||
|
||||
public 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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { PollType } from '../types/PollType'
|
||||
import { BigNumber, utils } from 'ethers'
|
||||
import { JsonRpcSigner } from '@ethersproject/providers'
|
||||
|
||||
import { PollInit } from 'protons'
|
||||
import { Wallet } from 'ethers'
|
||||
export class PollInitMsg {
|
||||
public owner: string
|
||||
public timestamp: number
|
||||
|
@ -34,7 +35,7 @@ export class PollInitMsg {
|
|||
}
|
||||
|
||||
static async create(
|
||||
signer: JsonRpcSigner,
|
||||
signer: JsonRpcSigner | Wallet,
|
||||
question: string,
|
||||
answers: string[],
|
||||
pollType: PollType,
|
||||
|
@ -72,4 +73,42 @@ export class PollInitMsg {
|
|||
|
||||
return new PollInitMsg(owner, signature, timestamp, question, answers, pollType, newEndTime, minToken)
|
||||
}
|
||||
|
||||
static fromProto(payload: PollInit) {
|
||||
const owner = utils.getAddress(utils.hexlify(payload.owner))
|
||||
const timestamp = payload.timestamp
|
||||
const question = payload.question
|
||||
const answers = payload.answers
|
||||
const pollType = payload.pollType
|
||||
const endTime = payload.endTime
|
||||
const signature = utils.hexlify(payload.signature)
|
||||
let minToken = payload.minToken ? BigNumber.from(payload.minToken) : undefined
|
||||
|
||||
const msg: (string | number | BigNumber | PollType)[] = [
|
||||
owner,
|
||||
timestamp,
|
||||
question,
|
||||
answers.join(),
|
||||
pollType,
|
||||
endTime,
|
||||
]
|
||||
const types = ['address', 'uint256', 'string', 'string', 'uint8', 'uint256']
|
||||
if (pollType === PollType.NON_WEIGHTED) {
|
||||
if (minToken) {
|
||||
msg.push(minToken)
|
||||
types.push('uint256')
|
||||
} else {
|
||||
return undefined
|
||||
}
|
||||
} else {
|
||||
minToken = undefined
|
||||
}
|
||||
const packedData = utils.arrayify(utils.solidityPack(types, msg))
|
||||
const verifiedAddress = utils.verifyMessage(packedData, signature)
|
||||
if (verifiedAddress != owner) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return new PollInitMsg(owner, signature, timestamp, question, answers, pollType, endTime, minToken)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import protons, { PollInit } from 'protons'
|
||||
import { PollType } from '../../types/PollType'
|
||||
import { utils, BigNumber } from 'ethers'
|
||||
import { utils } from 'ethers'
|
||||
import { PollInitMsg } from '../../models/PollInitMsg'
|
||||
|
||||
const proto = protons(`
|
||||
|
@ -46,9 +46,12 @@ export function encode(pollInit: PollInitMsg) {
|
|||
}
|
||||
}
|
||||
|
||||
export function decode(payload: Uint8Array) {
|
||||
export function decode(payload: Uint8Array, timestamp: Date | undefined) {
|
||||
try {
|
||||
const msg = proto.PollInit.decode(payload)
|
||||
if (!timestamp || timestamp.getTime() != msg.timestamp) {
|
||||
return undefined
|
||||
}
|
||||
if (
|
||||
msg.owner &&
|
||||
msg.timestamp &&
|
||||
|
@ -58,24 +61,7 @@ export function decode(payload: Uint8Array) {
|
|||
msg.endTime &&
|
||||
msg.signature
|
||||
) {
|
||||
const pollInit: PollInitMsg = {
|
||||
owner: utils.hexlify(msg.owner),
|
||||
timestamp: msg.timestamp,
|
||||
question: msg.question,
|
||||
answers: msg.answers,
|
||||
pollType: msg.pollType,
|
||||
endTime: msg.endTime,
|
||||
signature: utils.hexlify(msg.signature),
|
||||
}
|
||||
|
||||
if (msg.pollType === PollType.NON_WEIGHTED) {
|
||||
if (msg.minToken) {
|
||||
pollInit.minToken = BigNumber.from(msg.minToken)
|
||||
return pollInit
|
||||
}
|
||||
} else {
|
||||
return pollInit
|
||||
}
|
||||
return PollInitMsg.fromProto(msg)
|
||||
}
|
||||
} catch {
|
||||
return undefined
|
||||
|
|
|
@ -4,7 +4,7 @@ import WakuVoting from '../src'
|
|||
|
||||
describe('WakuVoting', () => {
|
||||
it('success', async () => {
|
||||
const wakuVoting = new WakuVoting('test', '0x0', {} as unknown as Waku)
|
||||
const wakuVoting = await WakuVoting.create('test', '0x0', {} as unknown as Waku)
|
||||
|
||||
expect(wakuVoting).to.not.be.undefined
|
||||
})
|
||||
|
|
|
@ -2,7 +2,6 @@ import { expect } from 'chai'
|
|||
import { PollInitMsg } from '../../src/models/PollInitMsg'
|
||||
import { MockProvider } from 'ethereum-waffle'
|
||||
import { PollType } from '../../src/types/PollType'
|
||||
import { JsonRpcSigner } from '@ethersproject/providers'
|
||||
import { BigNumber, utils } from 'ethers'
|
||||
|
||||
describe('PollInitMsg', () => {
|
||||
|
@ -10,12 +9,7 @@ describe('PollInitMsg', () => {
|
|||
const [alice] = provider.getWallets()
|
||||
|
||||
it('success', async () => {
|
||||
const poll = await PollInitMsg.create(
|
||||
alice as unknown as JsonRpcSigner,
|
||||
'test',
|
||||
['one', 'two', 'three'],
|
||||
PollType.WEIGHTED
|
||||
)
|
||||
const poll = await PollInitMsg.create(alice, 'test', ['one', 'two', 'three'], PollType.WEIGHTED)
|
||||
|
||||
expect(poll).to.not.be.undefined
|
||||
expect(poll.owner).to.eq(alice.address)
|
||||
|
@ -35,7 +29,7 @@ describe('PollInitMsg', () => {
|
|||
|
||||
it('success NON_WEIGHTED', async () => {
|
||||
const poll = await PollInitMsg.create(
|
||||
alice as unknown as JsonRpcSigner,
|
||||
alice,
|
||||
'test',
|
||||
['one', 'two', 'three'],
|
||||
PollType.NON_WEIGHTED,
|
||||
|
@ -61,12 +55,7 @@ describe('PollInitMsg', () => {
|
|||
})
|
||||
|
||||
it('NON_WEIGHTED no minToken', async () => {
|
||||
const poll = await PollInitMsg.create(
|
||||
alice as unknown as JsonRpcSigner,
|
||||
'test',
|
||||
['one', 'two', 'three'],
|
||||
PollType.NON_WEIGHTED
|
||||
)
|
||||
const poll = await PollInitMsg.create(alice, 'test', ['one', 'two', 'three'], PollType.NON_WEIGHTED)
|
||||
|
||||
expect(poll?.minToken?.toNumber()).to.eq(1)
|
||||
|
||||
|
@ -87,14 +76,7 @@ describe('PollInitMsg', () => {
|
|||
})
|
||||
|
||||
it('specific end time', async () => {
|
||||
const poll = await PollInitMsg.create(
|
||||
alice as unknown as JsonRpcSigner,
|
||||
'test',
|
||||
['one', 'two', 'three'],
|
||||
PollType.NON_WEIGHTED,
|
||||
undefined,
|
||||
100
|
||||
)
|
||||
const poll = await PollInitMsg.create(alice, 'test', ['one', 'two', 'three'], PollType.NON_WEIGHTED, undefined, 100)
|
||||
|
||||
expect(poll?.endTime).to.eq(100)
|
||||
})
|
||||
|
|
|
@ -3,29 +3,24 @@ import { PollType } from '../../../src/types/PollType'
|
|||
import PollInit from '../../../src/utils/proto/PollInit'
|
||||
import { BigNumber } from 'ethers'
|
||||
import { PollInitMsg } from '../../../src/models/PollInitMsg'
|
||||
import { MockProvider } from 'ethereum-waffle'
|
||||
|
||||
describe('PollInit', () => {
|
||||
const provider = new MockProvider()
|
||||
const [alice] = provider.getWallets()
|
||||
it('success', async () => {
|
||||
const data: PollInitMsg = {
|
||||
owner: '0x02',
|
||||
answers: ['ab', 'cd', 'ef'],
|
||||
endTime: 10,
|
||||
pollType: PollType.WEIGHTED,
|
||||
question: 'whats up',
|
||||
signature: '0x11',
|
||||
timestamp: 10,
|
||||
}
|
||||
const data = await PollInitMsg.create(alice, 'whats up', ['ab', 'cd', 'ef'], PollType.WEIGHTED)
|
||||
|
||||
const payload = PollInit.encode(data)
|
||||
|
||||
expect(payload).to.not.be.undefined
|
||||
if (payload) {
|
||||
expect(PollInit.decode(payload)).to.deep.eq(data)
|
||||
expect(PollInit.decode(payload, new Date(data.timestamp))).to.deep.eq(data)
|
||||
}
|
||||
})
|
||||
|
||||
it('random decode', async () => {
|
||||
expect(PollInit.decode(new Uint8Array([12, 12, 3, 32, 31, 212, 31, 32, 23]))).to.be.undefined
|
||||
expect(PollInit.decode(new Uint8Array([12, 12, 3, 32, 31, 212, 31, 32, 23]), new Date(10))).to.be.undefined
|
||||
})
|
||||
|
||||
it('random data', async () => {
|
||||
|
@ -33,36 +28,29 @@ describe('PollInit', () => {
|
|||
})
|
||||
|
||||
it('NON_WEIGHTED init', async () => {
|
||||
const data: PollInitMsg = {
|
||||
owner: '0x02',
|
||||
answers: ['ab', 'cd', 'ef'],
|
||||
endTime: 10,
|
||||
pollType: PollType.NON_WEIGHTED,
|
||||
minToken: BigNumber.from(10),
|
||||
question: 'whats up',
|
||||
signature: '0x11',
|
||||
timestamp: 10,
|
||||
}
|
||||
const data = await PollInitMsg.create(
|
||||
alice,
|
||||
'whats up',
|
||||
['ab', 'cd', 'ef'],
|
||||
PollType.NON_WEIGHTED,
|
||||
BigNumber.from(10)
|
||||
)
|
||||
|
||||
const payload = PollInit.encode(data)
|
||||
expect(payload).to.not.be.undefined
|
||||
if (payload) {
|
||||
expect(PollInit.decode(payload)).to.deep.eq(data)
|
||||
expect(PollInit.decode(payload, new Date(data.timestamp))).to.deep.eq(data)
|
||||
}
|
||||
})
|
||||
|
||||
it('NON_WEIGHTED no min token', async () => {
|
||||
const data: PollInitMsg = {
|
||||
owner: '0x02',
|
||||
answers: ['ab', 'cd', 'ef'],
|
||||
endTime: 10,
|
||||
pollType: PollType.NON_WEIGHTED,
|
||||
question: 'whats up',
|
||||
signature: '0x11',
|
||||
timestamp: 10,
|
||||
}
|
||||
const data = await PollInitMsg.create(alice, 'whats up', ['ab', 'cd', 'ef'], PollType.NON_WEIGHTED)
|
||||
|
||||
const payload = PollInit.encode(data)
|
||||
|
||||
expect(payload).to.be.undefined
|
||||
expect(payload).to.not.be.undefined
|
||||
if (payload) {
|
||||
expect(PollInit.decode(payload, new Date(data.timestamp))).to.deep.eq({ ...data, minToken: BigNumber.from(1) })
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue