Refactor initMsg typed signing (#11)
This commit is contained in:
parent
f6203b783f
commit
ac0279fda3
|
@ -3,6 +3,16 @@ import { BigNumber, utils, Wallet } from 'ethers'
|
|||
import { JsonRpcSigner } from '@ethersproject/providers'
|
||||
import { PollInit } from 'protons'
|
||||
|
||||
function signFunction(signer: JsonRpcSigner | Wallet) {
|
||||
return async (params: string[]) => {
|
||||
if ('send' in signer.provider) {
|
||||
return signer.provider.send('eth_signTypedData_v4', params)
|
||||
} else {
|
||||
throw `No send function in provider`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Message = {
|
||||
owner: string
|
||||
timestamp: number
|
||||
|
@ -10,7 +20,7 @@ type Message = {
|
|||
answers: string[]
|
||||
pollType: PollType
|
||||
endTime: number
|
||||
minToken: BigNumber | undefined
|
||||
minToken?: BigNumber
|
||||
}
|
||||
|
||||
export function createSignMsgParams(message: Message) {
|
||||
|
@ -20,10 +30,8 @@ export function createSignMsgParams(message: Message) {
|
|||
version: '1',
|
||||
},
|
||||
message: {
|
||||
owner: message.owner,
|
||||
...message,
|
||||
timestamp: new Date(message.timestamp).toLocaleDateString(),
|
||||
question: message.question,
|
||||
answers: message.answers,
|
||||
pollType: message.pollType === PollType.WEIGHTED ? 'Weighted' : 'Non weighted',
|
||||
endTime: new Date(message.endTime).toLocaleDateString(),
|
||||
},
|
||||
|
@ -44,11 +52,9 @@ export function createSignMsgParams(message: Message) {
|
|||
},
|
||||
}
|
||||
|
||||
if (message.pollType === PollType.NON_WEIGHTED) {
|
||||
if (message.minToken) {
|
||||
msgParams.message = { ...msgParams.message, minToken: message.minToken.toString() }
|
||||
msgParams.types.Mail.push({ name: 'minToken', type: 'uint256' })
|
||||
}
|
||||
if (message.pollType === PollType.NON_WEIGHTED && message.minToken) {
|
||||
msgParams.message = { ...msgParams.message, minToken: message.minToken.toString() }
|
||||
msgParams.types.Mail.push({ name: 'minToken', type: 'uint256' })
|
||||
}
|
||||
return msgParams
|
||||
}
|
||||
|
@ -64,27 +70,16 @@ export class PollInitMsg {
|
|||
public signature: string
|
||||
public id: string
|
||||
|
||||
private constructor(
|
||||
id: string,
|
||||
owner: string,
|
||||
signature: string,
|
||||
timestamp: number,
|
||||
question: string,
|
||||
answers: string[],
|
||||
pollType: PollType,
|
||||
endTime: number,
|
||||
minToken?: BigNumber
|
||||
) {
|
||||
this.id = id
|
||||
this.owner = owner
|
||||
this.timestamp = timestamp
|
||||
this.question = question
|
||||
this.answers = answers
|
||||
this.pollType = pollType
|
||||
this.minToken = minToken
|
||||
this.endTime = endTime
|
||||
|
||||
private constructor(signature: string, msg: Message) {
|
||||
this.id = utils.id([msg.owner, msg.timestamp, signature].join())
|
||||
this.signature = signature
|
||||
this.owner = msg.owner
|
||||
this.timestamp = msg.timestamp
|
||||
this.question = msg.question
|
||||
this.answers = msg.answers
|
||||
this.pollType = msg.pollType
|
||||
this.minToken = msg.minToken
|
||||
this.endTime = msg.endTime
|
||||
}
|
||||
|
||||
static async _createWithSignFunction(
|
||||
|
@ -96,34 +91,31 @@ export class PollInitMsg {
|
|||
minToken?: BigNumber,
|
||||
endTime?: number
|
||||
): Promise<PollInitMsg | undefined> {
|
||||
const owner = await signer.getAddress()
|
||||
const timestamp = Date.now()
|
||||
let newEndTime = timestamp + 10000000
|
||||
if (endTime) {
|
||||
newEndTime = endTime
|
||||
}
|
||||
|
||||
if (pollType === PollType.NON_WEIGHTED && !minToken) {
|
||||
minToken = BigNumber.from(1)
|
||||
}
|
||||
|
||||
const params = createSignMsgParams({
|
||||
owner,
|
||||
const msg = {
|
||||
owner: await signer.getAddress(),
|
||||
timestamp,
|
||||
question,
|
||||
answers,
|
||||
pollType,
|
||||
endTime: newEndTime,
|
||||
endTime: endTime ? endTime : timestamp + 100000000,
|
||||
minToken,
|
||||
})
|
||||
|
||||
const signature = await signFunction([owner, JSON.stringify(params)])
|
||||
if (!signature) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const id = utils.solidityKeccak256(['address', 'uint256'], [owner, timestamp])
|
||||
return new PollInitMsg(id, owner, signature, timestamp, question, answers, pollType, newEndTime, minToken)
|
||||
const params = createSignMsgParams(msg)
|
||||
|
||||
try {
|
||||
const signature = await signFunction([msg.owner, JSON.stringify(params)])
|
||||
if (!signature) {
|
||||
return undefined
|
||||
}
|
||||
return new PollInitMsg(signature, msg)
|
||||
} catch {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
static async create(
|
||||
|
@ -134,43 +126,27 @@ export class PollInitMsg {
|
|||
minToken?: BigNumber,
|
||||
endTime?: number
|
||||
): Promise<PollInitMsg | undefined> {
|
||||
const signFunction = async (params: string[]) => {
|
||||
if ('send' in signer.provider) {
|
||||
return signer.provider.send('eth_signTypedData_v4', params)
|
||||
} else {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
return this._createWithSignFunction(signFunction, signer, question, answers, pollType, minToken, endTime)
|
||||
return this._createWithSignFunction(signFunction(signer), signer, question, answers, pollType, minToken, endTime)
|
||||
}
|
||||
|
||||
static fromProto(payload: PollInit, recoverFunction: ({ data, sig }: { data: any; sig: string }) => string) {
|
||||
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)
|
||||
const minToken = payload.minToken ? BigNumber.from(payload.minToken) : undefined
|
||||
|
||||
const params = createSignMsgParams({
|
||||
owner,
|
||||
timestamp,
|
||||
question,
|
||||
answers,
|
||||
endTime,
|
||||
minToken,
|
||||
pollType,
|
||||
})
|
||||
const msg = {
|
||||
...payload,
|
||||
owner: utils.getAddress(utils.hexlify(payload.owner)),
|
||||
minToken: payload.minToken ? BigNumber.from(payload.minToken) : undefined,
|
||||
}
|
||||
|
||||
const params = createSignMsgParams(msg)
|
||||
const verifiedAddress = recoverFunction({
|
||||
data: params,
|
||||
sig: signature,
|
||||
})
|
||||
if (verifiedAddress != owner) {
|
||||
if (verifiedAddress != msg.owner) {
|
||||
return undefined
|
||||
}
|
||||
const id = utils.solidityKeccak256(['address', 'uint256'], [owner, timestamp])
|
||||
return new PollInitMsg(id, owner, signature, timestamp, question, answers, pollType, endTime, minToken)
|
||||
|
||||
return new PollInitMsg(signature, msg)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ describe('PollInitMsg', () => {
|
|||
expect(poll).to.not.be.undefined
|
||||
if (poll) {
|
||||
expect(poll.owner).to.eq(alice.address)
|
||||
expect(poll.endTime).to.eq(poll.timestamp + 10000000)
|
||||
expect(poll.endTime).to.eq(poll.timestamp + 100000000)
|
||||
expect(poll.answers).to.deep.eq(['one', 'two', 'three'])
|
||||
expect(poll.minToken).to.be.undefined
|
||||
expect(poll.pollType).to.eq(PollType.WEIGHTED)
|
||||
|
@ -32,12 +32,12 @@ describe('PollInitMsg', () => {
|
|||
JSON.stringify(
|
||||
createSignMsgParams({
|
||||
owner: poll.owner,
|
||||
answers: poll.answers,
|
||||
endTime: poll.endTime,
|
||||
pollType: poll.pollType,
|
||||
minToken: poll.minToken,
|
||||
question: poll.question,
|
||||
timestamp: poll.timestamp,
|
||||
question: poll.question,
|
||||
answers: poll.answers,
|
||||
pollType: poll.pollType,
|
||||
endTime: poll.endTime,
|
||||
minToken: poll.minToken,
|
||||
})
|
||||
),
|
||||
].join()
|
||||
|
@ -63,12 +63,12 @@ describe('PollInitMsg', () => {
|
|||
JSON.stringify(
|
||||
createSignMsgParams({
|
||||
owner: poll.owner,
|
||||
answers: poll.answers,
|
||||
endTime: poll.endTime,
|
||||
pollType: poll.pollType,
|
||||
minToken: poll.minToken,
|
||||
question: poll.question,
|
||||
timestamp: poll.timestamp,
|
||||
question: poll.question,
|
||||
answers: poll.answers,
|
||||
pollType: poll.pollType,
|
||||
endTime: poll.endTime,
|
||||
minToken: poll.minToken,
|
||||
})
|
||||
),
|
||||
].join()
|
||||
|
@ -90,12 +90,12 @@ describe('PollInitMsg', () => {
|
|||
if (poll) {
|
||||
const msg = createSignMsgParams({
|
||||
owner: poll.owner,
|
||||
answers: poll.answers,
|
||||
endTime: poll.endTime,
|
||||
pollType: poll.pollType,
|
||||
minToken: poll.minToken,
|
||||
question: poll.question,
|
||||
timestamp: poll.timestamp,
|
||||
question: poll.question,
|
||||
answers: poll.answers,
|
||||
pollType: poll.pollType,
|
||||
endTime: poll.endTime,
|
||||
minToken: poll.minToken,
|
||||
})
|
||||
|
||||
expect(poll.signature).to.eq([poll.owner, JSON.stringify(msg)].join())
|
||||
|
|
|
@ -16,9 +16,11 @@ export function Poll({ poll, wakuVoting, signer }: PollProps) {
|
|||
const [selectedAnswer, setSelectedAnswer] = useState(0)
|
||||
const [tokenAmount, setTokenAmount] = useState(0)
|
||||
const [address, setAddress] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
signer.getAddress().then((e) => setAddress(e))
|
||||
}, [signer])
|
||||
|
||||
return (
|
||||
<PollWrapper>
|
||||
<PollTitle>
|
||||
|
|
|
@ -22,7 +22,7 @@ function Example({ appName }: ExampleProps) {
|
|||
const [selectedType, setSelectedType] = useState(PollType.WEIGHTED)
|
||||
|
||||
useEffect(() => {
|
||||
provider.on('accountsChanged', async () => {
|
||||
;(window as any).ethereum.on('accountsChanged', async () => {
|
||||
provider.send('eth_requestAccounts', [])
|
||||
setSigner(provider.getSigner())
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue