2020-09-28 05:28:34 +03:00
|
|
|
const Web3 = require('web3')
|
2020-09-30 18:35:48 +03:00
|
|
|
const { numberToHex, toBN } = require('web3-utils')
|
2020-09-28 05:28:34 +03:00
|
|
|
const MerkleTree = require('fixed-merkle-tree')
|
|
|
|
const Redis = require('ioredis')
|
|
|
|
const { GasPriceOracle } = require('gas-price-oracle')
|
2020-09-30 18:35:48 +03:00
|
|
|
|
|
|
|
const tornadoABI = require('../abis/tornadoABI.json')
|
|
|
|
const { queue } = require('./queue')
|
|
|
|
const { poseidonHash2 } = require('./utils')
|
|
|
|
const { rpcUrl, redisUrl, privateKey, updateConfig, rewardAccount } = require('../config')
|
|
|
|
const TxManager = require('./TxManager')
|
2020-09-28 05:28:34 +03:00
|
|
|
|
|
|
|
let web3
|
|
|
|
let currentTx
|
2020-09-29 06:17:42 +03:00
|
|
|
let currentJob
|
2020-09-28 05:28:34 +03:00
|
|
|
let tree
|
2020-09-30 18:35:48 +03:00
|
|
|
let txManager
|
|
|
|
const redis = new Redis(redisUrl)
|
|
|
|
const redisSubscribe = new Redis(redisUrl)
|
|
|
|
const gasPriceOracle = new GasPriceOracle({ defaultRpc: rpcUrl })
|
2020-09-28 05:28:34 +03:00
|
|
|
|
|
|
|
async function fetchTree() {
|
|
|
|
const elements = await redis.get('tree:elements')
|
2020-09-30 18:35:48 +03:00
|
|
|
const convert = (_, val) => (typeof val === 'string' ? toBN(val) : val)
|
2020-09-28 05:28:34 +03:00
|
|
|
tree = MerkleTree.deserialize(JSON.parse(elements, convert), poseidonHash2)
|
|
|
|
|
|
|
|
if (currentTx) {
|
|
|
|
// todo replace
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-30 18:35:48 +03:00
|
|
|
async function start() {
|
2020-09-28 05:28:34 +03:00
|
|
|
web3 = new Web3(rpcUrl, null, { transactionConfirmationBlocks: 1 })
|
|
|
|
const account = web3.eth.accounts.privateKeyToAccount('0x' + privateKey)
|
|
|
|
web3.eth.accounts.wallet.add('0x' + privateKey)
|
|
|
|
web3.eth.defaultAccount = account.address
|
2020-09-30 18:35:48 +03:00
|
|
|
updateConfig({ rewardAccount: account.address })
|
|
|
|
txManager = new TxManager({ privateKey, rpcUrl })
|
|
|
|
queue.process(process)
|
|
|
|
redisSubscribe.subscribe('treeUpdate', fetchTree)
|
2020-09-28 05:28:34 +03:00
|
|
|
await fetchTree()
|
2020-09-30 18:35:48 +03:00
|
|
|
console.log('Worker started')
|
2020-09-28 05:28:34 +03:00
|
|
|
}
|
|
|
|
|
2020-09-30 18:35:48 +03:00
|
|
|
async function checkTornadoFee(/* contract, fee, refund*/) {
|
|
|
|
const { fast } = await gasPriceOracle.gasPrices()
|
|
|
|
console.log('fast', fast)
|
2020-09-28 05:28:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
async function process(job) {
|
2020-09-30 18:35:48 +03:00
|
|
|
if (job.data.type !== 'tornadoWithdraw') {
|
2020-09-28 05:28:34 +03:00
|
|
|
throw new Error('not implemented')
|
|
|
|
}
|
2020-09-29 06:17:42 +03:00
|
|
|
currentJob = job
|
2020-09-28 05:28:34 +03:00
|
|
|
console.log(Date.now(), ' withdraw started', job.id)
|
2020-09-30 18:35:48 +03:00
|
|
|
const { proof, args, contract } = job.data.data
|
2020-09-28 05:28:34 +03:00
|
|
|
const fee = toBN(args[4])
|
|
|
|
const refund = toBN(args[5])
|
|
|
|
await checkTornadoFee(contract, fee, refund)
|
|
|
|
|
|
|
|
const instance = new web3.eth.Contract(tornadoABI, contract)
|
|
|
|
const data = instance.methods.withdraw(proof, ...args).encodeABI()
|
2020-09-30 18:35:48 +03:00
|
|
|
currentTx = await txManager.createTx({
|
2020-09-28 05:28:34 +03:00
|
|
|
value: numberToHex(refund),
|
|
|
|
to: contract,
|
|
|
|
data,
|
2020-09-30 18:35:48 +03:00
|
|
|
})
|
2020-09-28 05:28:34 +03:00
|
|
|
|
2020-09-29 06:17:42 +03:00
|
|
|
try {
|
2020-09-30 18:35:48 +03:00
|
|
|
await currentTx
|
|
|
|
.send()
|
|
|
|
.on('transactionHash', updateTxHash)
|
|
|
|
.on('mined', (receipt) => {
|
|
|
|
console.log('Mined in block', receipt.blockNumber)
|
|
|
|
})
|
|
|
|
.on('confirmations', updateConfirmations)
|
|
|
|
} catch (e) {
|
2020-09-29 06:17:42 +03:00
|
|
|
console.error('Revert', e)
|
|
|
|
throw new Error(`Revert by smart contract ${e.message}`)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function updateTxHash(txHash) {
|
|
|
|
console.log(`A new successfully sent tx ${txHash}`)
|
|
|
|
currentJob.data.txHash = txHash
|
|
|
|
await currentJob.update(currentJob.data)
|
|
|
|
}
|
|
|
|
|
2020-09-30 18:35:48 +03:00
|
|
|
async function updateConfirmations(confirmations) {
|
|
|
|
console.log(`Confirmations count ${confirmations}`)
|
|
|
|
currentJob.data.confirmations = confirmations
|
|
|
|
await currentJob.update(currentJob.data)
|
2020-09-28 05:28:34 +03:00
|
|
|
}
|
|
|
|
|
2020-09-30 18:35:48 +03:00
|
|
|
module.exports = { start, process }
|