Make core dependent on chainId (#50)

This commit is contained in:
Szymon Szlachtowicz 2021-09-03 14:41:29 +02:00 committed by GitHub
parent 14a1141d8d
commit 1623d8e023
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 132 additions and 80 deletions

View File

@ -8,10 +8,11 @@ import { TimedPollVoteMsg } from '../models/TimedPollVoteMsg'
import { DetailedTimedPoll } from '../models/DetailedTimedPoll' import { DetailedTimedPoll } from '../models/DetailedTimedPoll'
import { createWaku } from '../utils/createWaku' import { createWaku } from '../utils/createWaku'
import { WakuVoting } from './WakuVoting' import { WakuVoting } from './WakuVoting'
import { Provider } from '@ethersproject/providers'
export class WakuPolling extends WakuVoting { export class WakuPolling extends WakuVoting {
protected constructor(appName: string, tokenAddress: string, waku: Waku) { protected constructor(appName: string, tokenAddress: string, waku: Waku, provider: Provider, chainId: number) {
super(appName, tokenAddress, waku) super(appName, tokenAddress, waku, provider, chainId)
this.wakuMessages['pollInit'] = { this.wakuMessages['pollInit'] = {
topic: `/${this.appName}/waku-polling/timed-polls-init/proto/`, topic: `/${this.appName}/waku-polling/timed-polls-init/proto/`,
hashMap: {}, hashMap: {},
@ -34,8 +35,9 @@ export class WakuPolling extends WakuVoting {
this.setObserver() this.setObserver()
} }
public static async create(appName: string, tokenAddress: string, waku?: Waku) { public static async create(appName: string, tokenAddress: string, provider: Provider, waku?: Waku) {
const wakuPolling = new WakuPolling(appName, tokenAddress, await createWaku(waku)) const network = await provider.getNetwork()
const wakuPolling = new WakuPolling(appName, tokenAddress, await createWaku(waku), provider, network.chainId)
return wakuPolling return wakuPolling
} }
@ -47,7 +49,7 @@ export class WakuPolling extends WakuVoting {
minToken?: BigNumber, minToken?: BigNumber,
endTime?: number endTime?: number
) { ) {
const pollInit = await PollInitMsg.create(signer, question, answers, pollType, minToken, endTime) const pollInit = await PollInitMsg.create(signer, question, answers, pollType, this.chainId, minToken, endTime)
await this.sendWakuMessage(this.wakuMessages['pollInit'], pollInit) await this.sendWakuMessage(this.wakuMessages['pollInit'], pollInit)
} }
@ -57,7 +59,7 @@ export class WakuPolling extends WakuVoting {
selectedAnswer: number, selectedAnswer: number,
tokenAmount?: BigNumber tokenAmount?: BigNumber
) { ) {
const pollVote = await TimedPollVoteMsg.create(signer, pollId, selectedAnswer, tokenAmount) const pollVote = await TimedPollVoteMsg.create(signer, pollId, selectedAnswer, this.chainId, tokenAmount)
await this.sendWakuMessage(this.wakuMessages['pollVote'], pollVote) await this.sendWakuMessage(this.wakuMessages['pollVote'], pollVote)
} }

View File

@ -1,6 +1,7 @@
import { Waku } from 'js-waku' import { Waku } from 'js-waku'
import { WakuMessage } from 'js-waku' import { WakuMessage } from 'js-waku'
import { createWaku } from '../utils/createWaku' import { createWaku } from '../utils/createWaku'
import { Provider } from '@ethersproject/providers'
type WakuMessageStore = { type WakuMessageStore = {
topic: string topic: string
@ -17,21 +18,27 @@ export class WakuVoting {
protected appName: string protected appName: string
protected waku: Waku protected waku: Waku
public tokenAddress: string public tokenAddress: string
protected provider: Provider
protected chainId = 0
protected wakuMessages: WakuMessageStores = {} protected wakuMessages: WakuMessageStores = {}
protected observers: { callback: (msg: WakuMessage) => void; topics: string[] }[] = [] protected observers: { callback: (msg: WakuMessage) => void; topics: string[] }[] = []
protected constructor(appName: string, tokenAddress: string, waku: Waku) { protected constructor(appName: string, tokenAddress: string, waku: Waku, provider: Provider, chainId: number) {
this.appName = appName this.appName = appName
this.tokenAddress = tokenAddress this.tokenAddress = tokenAddress
this.waku = waku this.waku = waku
this.provider = provider
this.chainId = chainId
} }
public static async create(appName: string, tokenAddress: string, waku?: Waku) { public static async create(appName: string, tokenAddress: string, provider: Provider, waku?: Waku) {
return new WakuVoting(appName, tokenAddress, await createWaku(waku)) const network = await provider.getNetwork()
const wakuVoting = new WakuVoting(appName, tokenAddress, await createWaku(waku), provider, network.chainId)
return wakuVoting
} }
public cleanUp() { public cleanUp() {
this.observers.forEach((observer) => this.waku.relay.deleteObserver(observer.callback, observer.topics)) this.observers.forEach((observer) => this.waku.relay.deleteObserver(observer.callback, observer.topics))
this.wakuMessages = {}
} }
protected async setObserver() { protected async setObserver() {
@ -49,12 +56,12 @@ export class WakuVoting {
protected decodeMsgAndSetArray<T extends { id: string; timestamp: number }>( protected decodeMsgAndSetArray<T extends { id: string; timestamp: number }>(
messages: WakuMessage[], messages: WakuMessage[],
decode: (payload: Uint8Array | undefined, timestamp: Date | undefined) => T | undefined, decode: (payload: Uint8Array | undefined, timestamp: Date | undefined, chainId: number) => T | undefined,
msgObj: WakuMessageStore, msgObj: WakuMessageStore,
filterFunction?: (e: T) => boolean filterFunction?: (e: T) => boolean
) { ) {
messages messages
.map((msg) => decode(msg.payload, msg.timestamp)) .map((msg) => decode(msg.payload, msg.timestamp, this.chainId))
.sort((a, b) => ((a?.timestamp ?? new Date(0)) > (b?.timestamp ?? new Date(0)) ? 1 : -1)) .sort((a, b) => ((a?.timestamp ?? new Date(0)) > (b?.timestamp ?? new Date(0)) ? 1 : -1))
.forEach((e) => { .forEach((e) => {
if (e) { if (e) {

View File

@ -2,7 +2,7 @@ import { PollType } from '../types/PollType'
import { BigNumber, utils, Wallet } from 'ethers' 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 { createSignFunction } from '../utils/createSignFunction'
import { verifySignature } from '../utils/verifySignature' import { verifySignature } from '../utils/verifySignature'
const proto = protons(` const proto = protons(`
@ -32,11 +32,12 @@ type Message = {
minToken?: BigNumber minToken?: BigNumber
} }
export function createSignMsgParams(message: Message) { export function createSignMsgParams(message: Message, chainId: number) {
const msgParams: any = { const msgParams: any = {
domain: { domain: {
name: 'Waku polling', name: 'Waku polling',
version: '1', version: '1',
chainId,
}, },
message: { message: {
...message, ...message,
@ -49,6 +50,7 @@ export function createSignMsgParams(message: Message) {
EIP712Domain: [ EIP712Domain: [
{ name: 'name', type: 'string' }, { name: 'name', type: 'string' },
{ name: 'version', type: 'string' }, { name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
], ],
Mail: [ Mail: [
{ name: 'owner', type: 'address' }, { name: 'owner', type: 'address' },
@ -78,8 +80,8 @@ export class PollInitMsg {
public endTime: number public endTime: number
public signature: string public signature: string
public id: string public id: string
public chainId: number
constructor(signature: string, msg: Message) { constructor(signature: string, msg: Message, chainId: number) {
this.id = utils.id([msg.owner, msg.timestamp, signature].join()) this.id = utils.id([msg.owner, msg.timestamp, signature].join())
this.signature = signature this.signature = signature
this.owner = msg.owner this.owner = msg.owner
@ -89,18 +91,16 @@ export class PollInitMsg {
this.pollType = msg.pollType this.pollType = msg.pollType
this.minToken = msg.minToken this.minToken = msg.minToken
this.endTime = msg.endTime this.endTime = msg.endTime
this.chainId = chainId
} }
static async _createWithSignFunction( static async _createWithSignFunction(
signFunction: ( signFunction: (params: string[]) => Promise<string | undefined>,
msg: any,
params: string[],
Class: new (sig: string, msg: any) => PollInitMsg
) => Promise<PollInitMsg | undefined>,
signer: JsonRpcSigner | Wallet, signer: JsonRpcSigner | Wallet,
question: string, question: string,
answers: string[], answers: string[],
pollType: PollType, pollType: PollType,
chainId: number,
minToken?: BigNumber, minToken?: BigNumber,
endTime?: number endTime?: number
): Promise<PollInitMsg | undefined> { ): Promise<PollInitMsg | undefined> {
@ -117,8 +117,13 @@ export class PollInitMsg {
endTime: endTime ? endTime : timestamp + 100000000, endTime: endTime ? endTime : timestamp + 100000000,
minToken, minToken,
} }
const params = [msg.owner, JSON.stringify(createSignMsgParams(msg))] const params = [msg.owner, JSON.stringify(createSignMsgParams(msg, chainId))]
return signFunction(msg, params, PollInitMsg) const signature = await signFunction(params)
if (signature) {
return new PollInitMsg(signature, msg, chainId)
} else {
return undefined
}
} }
static async create( static async create(
@ -126,10 +131,20 @@ export class PollInitMsg {
question: string, question: string,
answers: string[], answers: string[],
pollType: PollType, pollType: PollType,
chainId: number,
minToken?: BigNumber, minToken?: BigNumber,
endTime?: number endTime?: number
): Promise<PollInitMsg | undefined> { ): Promise<PollInitMsg | undefined> {
return this._createWithSignFunction(createSignedMsg(signer), signer, question, answers, pollType, minToken, endTime) return this._createWithSignFunction(
createSignFunction(signer),
signer,
question,
answers,
pollType,
chainId,
minToken,
endTime
)
} }
encode() { encode() {
@ -161,6 +176,7 @@ export class PollInitMsg {
static decode( static decode(
rawPayload: Uint8Array | undefined, rawPayload: Uint8Array | undefined,
timestamp: Date | undefined, timestamp: Date | undefined,
chainId: number,
verifyFunction?: (params: any, address: string) => boolean verifyFunction?: (params: any, address: string) => boolean
) { ) {
try { try {
@ -180,13 +196,13 @@ export class PollInitMsg {
} }
const signature = utils.hexlify(payload.signature) const signature = utils.hexlify(payload.signature)
const params = { const params = {
data: createSignMsgParams(msg), data: createSignMsgParams(msg, chainId),
sig: signature, sig: signature,
} }
if (verifyFunction ? !verifyFunction : !verifySignature(params, msg.owner)) { if (verifyFunction ? !verifyFunction : !verifySignature(params, msg.owner)) {
return undefined return undefined
} }
return new PollInitMsg(signature, msg) return new PollInitMsg(signature, msg, chainId)
} catch { } catch {
return undefined return undefined
} }

View File

@ -2,7 +2,7 @@ import { BigNumber, utils } from 'ethers'
import { JsonRpcSigner } from '@ethersproject/providers' 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 { createSignFunction } from '../utils/createSignFunction'
import { verifySignature } from '../utils/verifySignature' import { verifySignature } from '../utils/verifySignature'
const proto = protons(` const proto = protons(`
@ -24,11 +24,12 @@ type Message = {
tokenAmount?: BigNumber tokenAmount?: BigNumber
} }
export function createSignMsgParams(message: Message) { export function createSignMsgParams(message: Message, chainId: number) {
const msgParams: any = { const msgParams: any = {
domain: { domain: {
name: 'Waku polling', name: 'Waku polling',
version: '1', version: '1',
chainId,
}, },
message: { message: {
...message, ...message,
@ -39,6 +40,7 @@ export function createSignMsgParams(message: Message) {
EIP712Domain: [ EIP712Domain: [
{ name: 'name', type: 'string' }, { name: 'name', type: 'string' },
{ name: 'version', type: 'string' }, { name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
], ],
Mail: [ Mail: [
{ name: 'pollId', type: 'string' }, { name: 'pollId', type: 'string' },
@ -64,8 +66,8 @@ export class TimedPollVoteMsg {
public tokenAmount?: BigNumber public tokenAmount?: BigNumber
public signature: string public signature: string
public id: string public id: string
public chainId: number
constructor(signature: string, msg: Message) { constructor(signature: string, msg: Message, chainId: number) {
this.id = utils.id([msg.voter, msg.timestamp, signature].join()) this.id = utils.id([msg.voter, msg.timestamp, signature].join())
this.pollId = msg.pollId this.pollId = msg.pollId
this.voter = msg.voter this.voter = msg.voter
@ -73,31 +75,35 @@ export class TimedPollVoteMsg {
this.answer = msg.answer this.answer = msg.answer
this.tokenAmount = msg.tokenAmount this.tokenAmount = msg.tokenAmount
this.signature = signature this.signature = signature
this.chainId = chainId
} }
static async _createWithSignFunction( static async _createWithSignFunction(
signFunction: ( signFunction: (params: string[]) => Promise<string | undefined>,
msg: any,
params: string[],
Class: new (sig: string, msg: any) => TimedPollVoteMsg
) => Promise<TimedPollVoteMsg | undefined>,
signer: JsonRpcSigner | Wallet, signer: JsonRpcSigner | Wallet,
pollId: string, pollId: string,
answer: number, answer: number,
chainId: number,
tokenAmount?: BigNumber tokenAmount?: BigNumber
): Promise<TimedPollVoteMsg | undefined> { ): Promise<TimedPollVoteMsg | undefined> {
const voter = await signer.getAddress() const voter = await signer.getAddress()
const msg = { pollId, voter, timestamp: Date.now(), answer, tokenAmount } const msg = { pollId, voter, timestamp: Date.now(), answer, tokenAmount }
const params = [msg.voter, JSON.stringify(createSignMsgParams(msg))] const params = [msg.voter, JSON.stringify(createSignMsgParams(msg, chainId))]
return signFunction(msg, params, TimedPollVoteMsg) const signature = await signFunction(params)
if (signature) {
return new TimedPollVoteMsg(signature, msg, chainId)
} else {
return undefined
}
} }
static async create( static async create(
signer: JsonRpcSigner | Wallet, signer: JsonRpcSigner | Wallet,
pollId: string, pollId: string,
answer: number, answer: number,
chainId: number,
tokenAmount?: BigNumber tokenAmount?: BigNumber
): Promise<TimedPollVoteMsg | undefined> { ): Promise<TimedPollVoteMsg | undefined> {
return this._createWithSignFunction(createSignedMsg(signer), signer, pollId, answer, tokenAmount) return this._createWithSignFunction(createSignFunction(signer), signer, pollId, answer, chainId, tokenAmount)
} }
encode() { encode() {
@ -119,6 +125,7 @@ export class TimedPollVoteMsg {
static decode( static decode(
rawPayload: Uint8Array | undefined, rawPayload: Uint8Array | undefined,
timestamp: Date | undefined, timestamp: Date | undefined,
chainId: number,
verifyFunction?: (params: any, address: string) => boolean verifyFunction?: (params: any, address: string) => boolean
) { ) {
try { try {
@ -137,13 +144,13 @@ export class TimedPollVoteMsg {
} }
const params = { const params = {
data: createSignMsgParams(msg), data: createSignMsgParams(msg, chainId),
sig: signature, sig: signature,
} }
if (verifyFunction ? !verifyFunction : !verifySignature(params, msg.voter)) { if (verifyFunction ? !verifyFunction : !verifySignature(params, msg.voter)) {
return undefined return undefined
} }
return new TimedPollVoteMsg(signature, msg) return new TimedPollVoteMsg(signature, msg, chainId)
} catch { } catch {
return undefined return undefined
} }

View File

@ -1,13 +1,13 @@
import { JsonRpcSigner } from '@ethersproject/providers' import { JsonRpcSigner } from '@ethersproject/providers'
import { Wallet } from 'ethers' import { Wallet } from 'ethers'
export function createSignedMsg(signer: JsonRpcSigner | Wallet) { export function createSignFunction(signer: JsonRpcSigner | Wallet) {
return async <T>(msg: any, params: string[], Class: new (sig: string, msg: any) => T): Promise<T | undefined> => { return async (params: string[]) => {
if ('send' in signer.provider) { if ('send' in signer.provider) {
try { try {
const signature = await signer.provider.send('eth_signTypedData_v4', params) const signature = await signer.provider.send('eth_signTypedData_v4', params)
if (signature) { if (signature) {
return new Class(signature, msg) return signature
} }
} catch { } catch {
return undefined return undefined

View File

@ -1,10 +1,11 @@
import { MockProvider } from '@ethereum-waffle/provider'
import { expect } from 'chai' import { expect } from 'chai'
import { Waku } from 'js-waku' import { Waku } from 'js-waku'
import { WakuVoting } from '../src' import { WakuVoting } from '../src'
describe('WakuVoting', () => { describe('WakuVoting', () => {
it('success', async () => { it('success', async () => {
const wakuVoting = await WakuVoting.create('test', '0x0', {} as unknown as Waku) const wakuVoting = await WakuVoting.create('test', '0x0', new MockProvider(), {} as unknown as Waku)
expect(wakuVoting).to.not.be.undefined expect(wakuVoting).to.not.be.undefined
}) })

View File

@ -10,11 +10,12 @@ describe('PollInitMsg', () => {
describe('create', () => { describe('create', () => {
it('success', async () => { it('success', async () => {
const poll = await PollInitMsg._createWithSignFunction( const poll = await PollInitMsg._createWithSignFunction(
async (e) => new PollInitMsg('0x01', e), async () => '0x01',
alice, alice,
'test', 'test',
['one', 'two', 'three'], ['one', 'two', 'three'],
PollType.WEIGHTED PollType.WEIGHTED,
0
) )
expect(poll).to.not.be.undefined expect(poll).to.not.be.undefined
@ -32,11 +33,12 @@ describe('PollInitMsg', () => {
it('success NON_WEIGHTED', async () => { it('success NON_WEIGHTED', async () => {
const poll = await PollInitMsg._createWithSignFunction( const poll = await PollInitMsg._createWithSignFunction(
async (e) => new PollInitMsg('0x01', e), async () => '0x01',
alice, alice,
'test', 'test',
['one', 'two', 'three'], ['one', 'two', 'three'],
PollType.NON_WEIGHTED, PollType.NON_WEIGHTED,
0,
BigNumber.from(123) BigNumber.from(123)
) )
expect(poll).to.not.be.undefined expect(poll).to.not.be.undefined
@ -48,11 +50,12 @@ describe('PollInitMsg', () => {
it('NON_WEIGHTED no minToken', async () => { it('NON_WEIGHTED no minToken', async () => {
const poll = await PollInitMsg._createWithSignFunction( const poll = await PollInitMsg._createWithSignFunction(
async (e) => new PollInitMsg('0x01', e), async () => '0x01',
alice, alice,
'test', 'test',
['one', 'two', 'three'], ['one', 'two', 'three'],
PollType.NON_WEIGHTED PollType.NON_WEIGHTED,
0
) )
expect(poll?.minToken?.toNumber()).to.eq(1) expect(poll?.minToken?.toNumber()).to.eq(1)
@ -64,11 +67,12 @@ describe('PollInitMsg', () => {
it('specific end time', async () => { it('specific end time', async () => {
const poll = await PollInitMsg._createWithSignFunction( const poll = await PollInitMsg._createWithSignFunction(
async (e) => new PollInitMsg('0x01', e), async () => '0x01',
alice, alice,
'test', 'test',
['one', 'two', 'three'], ['one', 'two', 'three'],
PollType.NON_WEIGHTED, PollType.NON_WEIGHTED,
0,
undefined, undefined,
100 100
) )
@ -79,33 +83,35 @@ describe('PollInitMsg', () => {
describe('decode/encode', () => { describe('decode/encode', () => {
it('success', async () => { it('success', async () => {
const data = await PollInitMsg._createWithSignFunction( const data = await PollInitMsg._createWithSignFunction(
async (e) => new PollInitMsg('0x01', e), async () => '0x01',
alice, alice,
'whats up', 'whats up',
['ab', 'cd', 'ef'], ['ab', 'cd', 'ef'],
PollType.WEIGHTED PollType.WEIGHTED,
0
) )
expect(data).to.not.be.undefined expect(data).to.not.be.undefined
if (data) { if (data) {
const payload = data.encode() const payload = data.encode()
expect(payload).to.not.be.undefined expect(payload).to.not.be.undefined
if (payload) { if (payload) {
expect(PollInitMsg.decode(payload, new Date(data.timestamp), () => true)).to.deep.eq(data) expect(PollInitMsg.decode(payload, new Date(data.timestamp), 0, () => true)).to.deep.eq(data)
} }
} }
}) })
it('random decode', async () => { it('random decode', async () => {
expect(PollInitMsg.decode(new Uint8Array([12, 12, 3, 32, 31, 212, 31, 32, 23]), new Date(10))).to.be.undefined expect(PollInitMsg.decode(new Uint8Array([12, 12, 3, 32, 31, 212, 31, 32, 23]), new Date(10), 0)).to.be.undefined
}) })
it('NON_WEIGHTED init', async () => { it('NON_WEIGHTED init', async () => {
const data = await PollInitMsg._createWithSignFunction( const data = await PollInitMsg._createWithSignFunction(
async (e) => new PollInitMsg('0x01', e), async () => '0x01',
alice, alice,
'whats up', 'whats up',
['ab', 'cd', 'ef'], ['ab', 'cd', 'ef'],
PollType.NON_WEIGHTED, PollType.NON_WEIGHTED,
0,
BigNumber.from(10) BigNumber.from(10)
) )
expect(data).to.not.be.undefined expect(data).to.not.be.undefined
@ -113,18 +119,19 @@ describe('PollInitMsg', () => {
const payload = data.encode() const payload = data.encode()
expect(payload).to.not.be.undefined expect(payload).to.not.be.undefined
if (payload) { if (payload) {
expect(PollInitMsg.decode(payload, new Date(data.timestamp), () => true)).to.deep.eq(data) expect(PollInitMsg.decode(payload, new Date(data.timestamp), 0, () => true)).to.deep.eq(data)
} }
} }
}) })
it('NON_WEIGHTED no min token', async () => { it('NON_WEIGHTED no min token', async () => {
const data = await PollInitMsg._createWithSignFunction( const data = await PollInitMsg._createWithSignFunction(
async (e) => new PollInitMsg('0x01', e), async () => '0x01',
alice, alice,
'whats up', 'whats up',
['ab', 'cd', 'ef'], ['ab', 'cd', 'ef'],
PollType.NON_WEIGHTED PollType.NON_WEIGHTED,
0
) )
expect(data).to.not.be.undefined expect(data).to.not.be.undefined
if (data) { if (data) {
@ -132,7 +139,7 @@ describe('PollInitMsg', () => {
expect(payload).to.not.be.undefined expect(payload).to.not.be.undefined
if (payload) { if (payload) {
expect(PollInitMsg.decode(payload, new Date(data.timestamp), () => true)).to.deep.eq({ expect(PollInitMsg.decode(payload, new Date(data.timestamp), 0, () => true)).to.deep.eq({
...data, ...data,
minToken: BigNumber.from(1), minToken: BigNumber.from(1),
}) })

View File

@ -10,12 +10,7 @@ describe('TimedPollVoteMsg', () => {
describe('create', () => { describe('create', () => {
it('success', async () => { it('success', async () => {
const vote = await TimedPollVoteMsg._createWithSignFunction( const vote = await TimedPollVoteMsg._createWithSignFunction(async () => '0x01', alice, pollId, 0, 0)
async (e) => new TimedPollVoteMsg('0x01', e),
alice,
pollId,
0
)
if (vote) { if (vote) {
expect(vote.voter).to.eq(alice.address) expect(vote.voter).to.eq(alice.address)
@ -28,10 +23,11 @@ describe('TimedPollVoteMsg', () => {
it('success token amount', async () => { it('success token amount', async () => {
const vote = await TimedPollVoteMsg._createWithSignFunction( const vote = await TimedPollVoteMsg._createWithSignFunction(
async (e) => new TimedPollVoteMsg('0x01', e), async () => '0x01',
alice, alice,
pollId, pollId,
1, 1,
0,
BigNumber.from(100) BigNumber.from(100)
) )
@ -48,12 +44,7 @@ describe('TimedPollVoteMsg', () => {
describe('decode/encode', () => { describe('decode/encode', () => {
it('success', async () => { it('success', async () => {
const data = await TimedPollVoteMsg._createWithSignFunction( const data = await TimedPollVoteMsg._createWithSignFunction(async () => '0x01', alice, pollId, 0, 0)
async (e) => new TimedPollVoteMsg('0x01', e),
alice,
pollId,
0
)
expect(data).to.not.be.undefined expect(data).to.not.be.undefined
if (data) { if (data) {
@ -61,22 +52,23 @@ describe('TimedPollVoteMsg', () => {
expect(payload).to.not.be.undefined expect(payload).to.not.be.undefined
if (payload) { if (payload) {
expect(await TimedPollVoteMsg.decode(payload, new Date(data.timestamp), () => true)).to.deep.eq(data) expect(await TimedPollVoteMsg.decode(payload, new Date(data.timestamp), 0, () => true)).to.deep.eq(data)
} }
} }
}) })
it('random decode', async () => { it('random decode', async () => {
expect(TimedPollVoteMsg.decode(new Uint8Array([12, 12, 3, 32, 31, 212, 31, 32, 23]), new Date(10))).to.be expect(TimedPollVoteMsg.decode(new Uint8Array([12, 12, 3, 32, 31, 212, 31, 32, 23]), new Date(10), 0)).to.be
.undefined .undefined
}) })
it('data with token', async () => { it('data with token', async () => {
const data = await TimedPollVoteMsg._createWithSignFunction( const data = await TimedPollVoteMsg._createWithSignFunction(
async (e) => new TimedPollVoteMsg('0x01', e), async () => '0x01',
alice, alice,
pollId, pollId,
0, 0,
0,
BigNumber.from(120) BigNumber.from(120)
) )
expect(data).to.not.be.undefined expect(data).to.not.be.undefined
@ -85,7 +77,7 @@ describe('TimedPollVoteMsg', () => {
expect(payload).to.not.be.undefined expect(payload).to.not.be.undefined
if (payload) { if (payload) {
expect(TimedPollVoteMsg.decode(payload, new Date(data.timestamp), () => true)).to.deep.eq({ expect(TimedPollVoteMsg.decode(payload, new Date(data.timestamp), 0, () => true)).to.deep.eq({
...data, ...data,
tokenAmount: BigNumber.from(120), tokenAmount: BigNumber.from(120),
}) })

View File

@ -7,7 +7,9 @@
"license": "MIT", "license": "MIT",
"watch": { "watch": {
"build": { "build": {
"patterns": ["src"], "patterns": [
"src"
],
"extensions": "ts,tsx", "extensions": "ts,tsx",
"runOnChangeOnly": false "runOnChangeOnly": false
} }
@ -27,6 +29,7 @@
}, },
"dependencies": { "dependencies": {
"@status-waku-voting/core": "^0.1.0", "@status-waku-voting/core": "^0.1.0",
"@usedapp/core": "^0.4.7",
"ethers": "^5.4.4", "ethers": "^5.4.4",
"react": "^17.0.2", "react": "^17.0.2",
"styled-components": "^5.3.0" "styled-components": "^5.3.0"

View File

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