diff --git a/.eslintrc.json b/.eslintrc.json index 41bfff8..8b3897c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -22,7 +22,13 @@ } ], "linebreak-style": ["error", "unix"], - "quotes": ["error", "single", { "avoidEscape": true }], + "quotes": [ + "error", + "single", + { + "avoidEscape": true + } + ], "semi": ["error", "never"], "object-curly-spacing": ["error", "always"], "require-await": "error", diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b8cffe3..32dad29 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,8 +2,8 @@ name: build on: push: - branches: [ '*' ] - tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] + branches: ['*'] + tags: ['v[0-9]+.[0-9]+.[0-9]+'] pull_request: jobs: diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..61bb45d --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +keys/TreeUpdate.json diff --git a/.prettierrc b/.prettierrc index 7d955c2..46222f4 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,6 +1,6 @@ { "semi": false, - "arrowParens": "always", + "arrowParens": "avoid", "singleQuote": true, "printWidth": 110, "trailingComma": "all" diff --git a/abis/PriceOracle.abi.json b/abis/PriceOracle.abi.json index 5b9f897..76c5c60 100644 --- a/abis/PriceOracle.abi.json +++ b/abis/PriceOracle.abi.json @@ -1,28 +1,28 @@ [ - { - "constant": true, - "inputs": [ - { - "internalType": "contract IERC20[]", - "name": "fromTokens", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "oneUnitAmounts", - "type": "uint256[]" - } - ], - "name": "getPricesInETH", - "outputs": [ - { - "internalType": "uint256[]", - "name": "prices", - "type": "uint256[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - } -] \ No newline at end of file + { + "constant": true, + "inputs": [ + { + "internalType": "contract IERC20[]", + "name": "fromTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "oneUnitAmounts", + "type": "uint256[]" + } + ], + "name": "getPricesInETH", + "outputs": [ + { + "internalType": "uint256[]", + "name": "prices", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] diff --git a/package.json b/package.json index f5b2f1d..9156753 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,10 @@ "scripts": { "server": "node src/server.js", "treeUpdater": "node src/treeWatcher", - "eslint": "npx eslint --ignore-path .gitignore .", + "eslint": "eslint --ext .js --ignore-path .gitignore .", + "prettier:check": "npx prettier --check . --config .prettierrc", + "prettier:fix": "npx prettier --write . --config .prettierrc", + "lint": "yarn eslint && yarn prettier:check", "test": "mocha" }, "author": "tornado.cash", @@ -34,6 +37,9 @@ "devDependencies": { "chai": "^4.2.0", "eslint": "^6.6.0", - "mocha": "^8.1.3" + "eslint-config-prettier": "^6.12.0", + "eslint-plugin-prettier": "^3.1.4", + "mocha": "^8.1.3", + "prettier": "^2.1.2" } } diff --git a/src.bak/Fetcher.js b/src.bak/Fetcher.js deleted file mode 100644 index 4bdbfed..0000000 --- a/src.bak/Fetcher.js +++ /dev/null @@ -1,56 +0,0 @@ -const Web3 = require('web3') -const { defaultGasPrice, oracleRpcUrl, oracleAddress } = require('../config') -const { getArgsForOracle } = require('./utils') -const { redisClient } = require('./redis') -const priceOracleABI = require('../abis/PriceOracle.abi.json') - -class Fetcher { - constructor(web3) { - this.web3 = web3 - this.oracleWeb3 = new Web3(oracleRpcUrl) - this.oracle = new this.oracleWeb3.eth.Contract(priceOracleABI, oracleAddress) - this.ethPrices = { - dai: '6700000000000000', // 0.0067 - cdai: '157380000000000', - cusdc: '164630000000000', - usdc: '7878580000000000', - usdt: '7864940000000000' - } - this.tokenAddresses - this.oneUintAmount - this.currencyLookup - this.gasPrices = { - fast: defaultGasPrice - } - - const { tokenAddresses, oneUintAmount, currencyLookup } = getArgsForOracle() - this.tokenAddresses = tokenAddresses - this.oneUintAmount = oneUintAmount - this.currencyLookup = currencyLookup - } - async fetchPrices() { - try { - let prices = await this.oracle.methods.getPricesInETH(this.tokenAddresses, this.oneUintAmount).call() - this.ethPrices = prices.reduce((acc, price, i) => { - acc[this.currencyLookup[this.tokenAddresses[i]]] = price - return acc - }, {}) - setTimeout(() => this.fetchPrices(), 1000 * 30) - } catch (e) { - console.error('fetchPrices', e.message) - setTimeout(() => this.fetchPrices(), 1000 * 30) - } - } - async fetchNonce() { - try { - const nonce = await this.web3.eth.getTransactionCount(this.web3.eth.defaultAccount) - await redisClient.set('nonce', nonce) - console.log(`Current nonce: ${nonce}`) - } catch (e) { - console.error('fetchNonce failed', e.message) - setTimeout(this.fetchNonce, 3000) - } - } -} - -module.exports = Fetcher diff --git a/src.bak/index.js b/src.bak/index.js deleted file mode 100644 index da70913..0000000 --- a/src.bak/index.js +++ /dev/null @@ -1,98 +0,0 @@ -const express = require('express') -const { - netId, - port, - relayerServiceFee, - gasBumpPercentage, - pendingTxTimeout, - watherInterval, - maxGasPrice -} = require('../config') -const relayController = require('./relayController') -const { fetcher, web3, gasPriceOracle } = require('./instances') -const { getMixers } = require('./utils') -const mixers = getMixers() -const { redisClient } = require('./redis') -const { version } = require('../package.json') -const app = express() -app.use(express.json()) - -app.use((err, req, res, next) => { - if (err) { - console.log('Invalid Request data') - res.send('Invalid Request data') - } else { - next() - } -}) - -app.use(function (req, res, next) { - res.header('Access-Control-Allow-Origin', '*') - res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept') - next() -}) - -app.get('/', function (req, res) { - // just for testing purposes - res.send( - 'This is tornado.cash Relayer service. Check the /status for settings' - ) -}) - -app.get('/status', async function (req, res) { - let nonce = await redisClient.get('nonce') - let latestBlock = null - try { - latestBlock = await web3.eth.getBlockNumber() - } catch (e) { - console.error('Problem with RPC', e) - } - const { ethPrices } = fetcher - res.json({ - relayerAddress: web3.eth.defaultAccount, - mixers, - gasPrices: await gasPriceOracle.gasPrices(), - netId, - ethPrices, - relayerServiceFee, - nonce, - version, - latestBlock - }) -}) - -app.post('/relay', relayController) -console.log('Version:', version) -let server = app.listen(port || 8000) -server.setTimeout(600000) -console.log('Gas price oracle started.') -fetcher.fetchPrices() -fetcher.fetchNonce() - -console.log('Relayer started on port', port || 8000) -console.log(`relayerAddress: ${web3.eth.defaultAccount}`) -console.log(`mixers: ${JSON.stringify(mixers)}`) -console.log(`netId: ${netId}`) -console.log(`ethPrices: ${JSON.stringify(fetcher.ethPrices)}`) - -const { - GAS_PRICE_BUMP_PERCENTAGE, - ALLOWABLE_PENDING_TX_TIMEOUT, - NONCE_WATCHER_INTERVAL, - MAX_GAS_PRICE -} = process.env -if (!NONCE_WATCHER_INTERVAL) { - console.log(`NONCE_WATCHER_INTERVAL is not set. Using default value ${watherInterval / 1000} sec`) -} - -if (!GAS_PRICE_BUMP_PERCENTAGE) { - console.log(`GAS_PRICE_BUMP_PERCENTAGE is not set. Using default value ${gasBumpPercentage}%`) -} - -if (!ALLOWABLE_PENDING_TX_TIMEOUT) { - console.log(`ALLOWABLE_PENDING_TX_TIMEOUT is not set. Using default value ${pendingTxTimeout / 1000} sec`) -} - -if (!MAX_GAS_PRICE) { - console.log(`ALLOWABLE_PENDING_TX_TIMEOUT is not set. Using default value ${maxGasPrice} Gwei`) -} diff --git a/src.bak/instances.js b/src.bak/instances.js deleted file mode 100644 index a87c675..0000000 --- a/src.bak/instances.js +++ /dev/null @@ -1,15 +0,0 @@ -const { rpcUrl } = require('../config') -const Fetcher = require('./Fetcher') -const Sender = require('./sender') -const { GasPriceOracle } = require('gas-price-oracle') -const web3 = require('./setupWeb3') -const fetcher = new Fetcher(web3) -const sender = new Sender(web3) -const gasPriceOracle = new GasPriceOracle({ defaultRpc: rpcUrl }) - -module.exports = { - fetcher, - web3, - sender, - gasPriceOracle -} diff --git a/src.bak/redis.js b/src.bak/redis.js deleted file mode 100644 index fa710e6..0000000 --- a/src.bak/redis.js +++ /dev/null @@ -1,19 +0,0 @@ -const { redisUrl } = require('../config') -const Redis = require('ioredis') -const redisClient = new Redis(redisUrl) -const subscriber = new Redis(redisUrl) - -const redisOpts = { - createClient: function (type) { - switch (type) { - case 'client': - return redisClient - case 'subscriber': - return subscriber - default: - return new Redis(redisUrl) - } - } -} - -module.exports = { redisOpts, redisClient } diff --git a/src.bak/relayController.js b/src.bak/relayController.js deleted file mode 100644 index 76affe3..0000000 --- a/src.bak/relayController.js +++ /dev/null @@ -1,164 +0,0 @@ -const Queue = require('bull') -const { numberToHex, toWei, toHex, toBN, toChecksumAddress } = require('web3-utils') -const mixerABI = require('../abis/mixerABI.json') -const { isValidProof, isValidArgs, isKnownContract, isEnoughFee } = require('./utils') -const config = require('../config') -const { redisClient, redisOpts } = require('./redis') -const { GasPriceOracle } = require('gas-price-oracle') -const gasPriceOracle = new GasPriceOracle({ defaultRpc: rpcUrl }) - -const { web3, fetcher, sender, gasPriceOracle } = require('./instances') -const withdrawQueue = new Queue('withdraw', redisOpts) - -const reponseCbs = {} -let respLambda = (job, { msg, status }) => { - const resp = reponseCbs[job.id] - resp.status(status).json(msg) - delete reponseCbs[job.id] -} -withdrawQueue.on('completed', respLambda) - -async function relayController(req, resp) { - let requestJob - - const { proof, args, contract } = req.body - let { valid, reason } = isValidProof(proof) - if (!valid) { - console.log('Proof is invalid:', reason) - return resp.status(400).json({ error: 'Proof format is invalid' }) - } - - // eslint-disable-next-line no-extra-semi - ;({ valid, reason } = isValidArgs(args)) - if (!valid) { - console.log('Args are invalid:', reason) - return resp.status(400).json({ error: 'Withdraw arguments are invalid' }) - } - - let currency, amount - ;({ valid, currency, amount } = isKnownContract(contract)) - if (!valid) { - console.log('Contract does not exist:', contract) - return resp.status(400).json({ error: 'This relayer does not support the token' }) - } - - const [root, nullifierHash, recipient, relayer, fee, refund] = [ - args[0], - args[1], - toChecksumAddress(args[2]), - toChecksumAddress(args[3]), - toBN(args[4]), - toBN(args[5]) - ] - console.log('fee, refund', fee.toString(), refund.toString(), recipient) - if (currency === 'eth' && !refund.isZero()) { - return resp.status(400).json({ error: 'Cannot send refund for eth currency.' }) - } - - if (relayer !== web3.eth.defaultAccount) { - console.log('This proof is for different relayer:', relayer) - return resp.status(400).json({ error: 'Relayer address is invalid' }) - } - - requestJob = await withdrawQueue.add( - { - contract, - nullifierHash, - root, - proof, - args, - currency, - amount, - fee: fee.toString(), - refund: refund.toString() - }, - { removeOnComplete: true } - ) - reponseCbs[requestJob.id] = resp -} - -withdrawQueue.process(async function (job, done) { - console.log(Date.now(), ' withdraw started', job.id) - const gasPrices = await gasPriceOracle.gasPrices() - const { contract, nullifierHash, root, proof, args, refund, currency, amount, fee } = job.data - console.log(JSON.stringify(job.data)) - // job.data contains the custom data passed when the job was created - // job.id contains id of this job. - try { - const mixer = new web3.eth.Contract(mixerABI, contract) - const isSpent = await mixer.methods.isSpent(nullifierHash).call() - if (isSpent) { - done(null, { - status: 400, - msg: { - error: 'The note has been spent.' - } - }) - return - } - const isKnownRoot = await mixer.methods.isKnownRoot(root).call() - if (!isKnownRoot) { - done(null, { - status: 400, - msg: { - error: 'The merkle root is too old or invalid.' - } - }) - return - } - - let gas = await mixer.methods.withdraw(proof, ...args).estimateGas({ - from: web3.eth.defaultAccount, - value: refund - }) - - gas += 50000 - const ethPrices = fetcher.ethPrices - const { isEnough, reason } = isEnoughFee({ - gas, - gasPrices, - currency, - amount, - refund: toBN(refund), - ethPrices, - fee: toBN(fee) - }) - if (!isEnough) { - console.log(`Wrong fee: ${reason}`) - done(null, { - status: 400, - msg: { error: reason } - }) - return - } - - const data = mixer.methods.withdraw(proof, ...args).encodeABI() - let nonce = Number(await redisClient.get('nonce')) - console.log('nonce', nonce) - const tx = { - from: web3.eth.defaultAccount, - value: numberToHex(refund), - gas: numberToHex(gas), - gasPrice: toHex(toWei(gasPrices.fast.toString(), 'gwei')), - // you can use this gasPrice to test watcher - // gasPrice: numberToHex(100000000), - to: mixer._address, - netId: config.netId, - data, - nonce - } - tx.date = Date.now() - await redisClient.set('tx:' + nonce, JSON.stringify(tx)) - nonce += 1 - await redisClient.set('nonce', nonce) - sender.sendTx(tx, done) - } catch (e) { - console.error(e, 'estimate gas failed') - done(null, { - status: 400, - msg: { error: 'Internal Relayer Error. Please use a different relayer service' } - }) - } -}) - -module.exports = relayController diff --git a/src.bak/sender.js b/src.bak/sender.js deleted file mode 100644 index f4dacdc..0000000 --- a/src.bak/sender.js +++ /dev/null @@ -1,81 +0,0 @@ -const { redisClient } = require('./redis') -const config = require('../config') -const { toBN, toHex, toWei, BN, fromWei } = require('web3-utils') - -class Sender { - constructor(web3) { - this.web3 = web3 - this.watherInterval = config.watherInterval - this.pendingTxTimeout = config.pendingTxTimeout - this.gasBumpPercentage = 100 + Number(config.gasBumpPercentage) - this.watcher() - } - - async watcher() { - try { - const networkNonce = await this.web3.eth.getTransactionCount(this.web3.eth.defaultAccount) - let tx = await redisClient.get('tx:' + networkNonce) - if (tx) { - tx = JSON.parse(tx) - if (Date.now() - tx.date > this.pendingTxTimeout) { - const newGasPrice = toBN(tx.gasPrice).mul(toBN(this.gasBumpPercentage)).div(toBN(100)) - const maxGasPrice = toBN(toWei(config.maxGasPrice.toString(), 'Gwei')) - tx.gasPrice = toHex(BN.min(newGasPrice, maxGasPrice)) - tx.date = Date.now() - await redisClient.set('tx:' + tx.nonce, JSON.stringify(tx)) - console.log('resubmitting with gas price', fromWei(tx.gasPrice.toString(), 'gwei'), ' gwei') - this.sendTx(tx, null, 9999) - } - } - } catch (e) { - console.error('watcher error:', e) - } finally { - setTimeout(() => this.watcher(), this.watherInterval) - } - } - - async sendTx(tx, done, retryAttempt = 1) { - let signedTx = await this.web3.eth.accounts.signTransaction(tx, config.privateKey) - let result = this.web3.eth.sendSignedTransaction(signedTx.rawTransaction) - - result - .once('transactionHash', (txHash) => { - console.log(`A new successfully sent tx ${txHash}`) - if (done) { - done(null, { - status: 200, - msg: { txHash } - }) - } - }) - .on('error', async (e) => { - console.log(`Error for tx with nonce ${tx.nonce}\n${e.message}`) - if ( - e.message === - 'Returned error: Transaction gas price supplied is too low. There is another transaction with same nonce in the queue. Try increasing the gas price or incrementing the nonce.' || - e.message === 'Returned error: Transaction nonce is too low. Try incrementing the nonce.' || - e.message === 'Returned error: nonce too low' || - e.message === 'Returned error: replacement transaction underpriced' - ) { - console.log('nonce too low, retrying') - if (retryAttempt <= 10) { - retryAttempt++ - const newNonce = tx.nonce + 1 - tx.nonce = newNonce - await redisClient.set('nonce', newNonce) - await redisClient.set('tx:' + newNonce, JSON.stringify(tx)) - this.sendTx(tx, done, retryAttempt) - return - } - } - if (done) { - done(null, { - status: 400, - msg: { error: 'Internal Relayer Error. Please use a different relayer service' } - }) - } - }) - } -} - -module.exports = Sender diff --git a/src.bak/setupWeb3.js b/src.bak/setupWeb3.js deleted file mode 100644 index e8f828f..0000000 --- a/src.bak/setupWeb3.js +++ /dev/null @@ -1,16 +0,0 @@ -const Web3 = require('web3') -const { rpcUrl, privateKey } = require('../config') - -function setup() { - try { - const 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 - return web3 - } catch (e) { - console.error('web3 failed') - } -} -const web3 = setup() -module.exports = web3 diff --git a/src.bak/treeUpdate.js b/src.bak/treeUpdate.js deleted file mode 100644 index cff24ec..0000000 --- a/src.bak/treeUpdate.js +++ /dev/null @@ -1,19 +0,0 @@ -const fs = require('fs') -const { Controller } = require('tornado-cash-anonymity-mining') -const { web3 } = require('./instances') -const { farmingAddress, farmingMerkleTreeHeight } = require('../config') - -const contract = web3.eth.contract(require('../abis/mining.abi.json'), farmingAddress) -const provingKeys = { - treeUpdateCircuit: require('.../keys/TreeUpdate.json'), - treeUpdateProvingKey: fs.readFileSync('../keys/TreeUpdate_proving_key.bin').buffer, -} -const controller = new Controller({ - contract, - provingKeys, - merkleTreeHeight: farmingMerkleTreeHeight, -}) - - -// await controller.init() -// await controller.treeUpdate(commitment) diff --git a/src.bak/utils.js b/src.bak/utils.js deleted file mode 100644 index 1482d43..0000000 --- a/src.bak/utils.js +++ /dev/null @@ -1,178 +0,0 @@ -const { isHexStrict, toBN, toWei, BN } = require('web3-utils') -const { netId, mixers, relayerServiceFee } = require('../config') - -function isValidProof(proof) { - // validator expects `websnarkUtils.toSolidityInput(proof)` output - - if (!proof) { - return { valid: false, reason: 'The proof is empty.' } - } - - if (!isHexStrict(proof) || proof.length !== 2 + 2 * 8 * 32) { - return { valid: false, reason: 'Corrupted proof' } - } - - return { valid: true } -} - -function isValidArgs(args) { - if (!args) { - return { valid: false, reason: 'Args are empty' } - } - - if (args.length !== 6) { - return { valid: false, reason: 'Length of args is lower than 6' } - } - - for (let signal of args) { - if (!isHexStrict(signal)) { - return { valid: false, reason: `Corrupted signal ${signal}` } - } - } - - if ( - args[0].length !== 66 || - args[1].length !== 66 || - args[2].length !== 42 || - args[3].length !== 42 || - args[4].length !== 66 || - args[5].length !== 66 - ) { - return { valid: false, reason: 'The length one of the signals is incorrect' } - } - - return { valid: true } -} - -function isKnownContract(contract) { - const mixers = getMixers() - for (let currency of Object.keys(mixers)) { - for (let amount of Object.keys(mixers[currency].mixerAddress)) { - if (mixers[currency].mixerAddress[amount] === contract) { - return { valid: true, currency, amount } - } - } - } - return { valid: false } -} - -function sleep(ms) { - return new Promise((resolve) => setTimeout(resolve, ms)) -} - -function fromDecimals(value, decimals) { - value = value.toString() - let ether = value.toString() - const base = new BN('10').pow(new BN(decimals)) - const baseLength = base.toString(10).length - 1 || 1 - - const negative = ether.substring(0, 1) === '-' - if (negative) { - ether = ether.substring(1) - } - - if (ether === '.') { - throw new Error('[ethjs-unit] while converting number ' + value + ' to wei, invalid value') - } - - // Split it into a whole and fractional part - const comps = ether.split('.') - if (comps.length > 2) { - throw new Error('[ethjs-unit] while converting number ' + value + ' to wei, too many decimal points') - } - - let whole = comps[0] - let fraction = comps[1] - - if (!whole) { - whole = '0' - } - if (!fraction) { - fraction = '0' - } - if (fraction.length > baseLength) { - throw new Error('[ethjs-unit] while converting number ' + value + ' to wei, too many decimal places') - } - - while (fraction.length < baseLength) { - fraction += '0' - } - - whole = new BN(whole) - fraction = new BN(fraction) - let wei = whole.mul(base).add(fraction) - - if (negative) { - wei = wei.mul(negative) - } - - return new BN(wei.toString(10), 10) -} - -function isEnoughFee({ gas, gasPrices, currency, amount, refund, ethPrices, fee }) { - const { decimals } = mixers[`netId${netId}`][currency] - const decimalsPoint = - Math.floor(relayerServiceFee) === relayerServiceFee - ? 0 - : relayerServiceFee.toString().split('.')[1].length - - const roundDecimal = 10 ** decimalsPoint - const feePercent = toBN(fromDecimals(amount, decimals)) - .mul(toBN(relayerServiceFee * roundDecimal)) - .div(toBN(roundDecimal * 100)) - const expense = toBN(toWei(gasPrices.fast.toString(), 'gwei')).mul(toBN(gas)) - let desiredFee - switch (currency) { - case 'eth': { - desiredFee = expense.add(feePercent) - break - } - default: { - desiredFee = expense - .add(refund) - .mul(toBN(10 ** decimals)) - .div(toBN(ethPrices[currency])) - desiredFee = desiredFee.add(feePercent) - break - } - } - console.log( - 'sent fee, desired fee, feePercent', - fee.toString(), - desiredFee.toString(), - feePercent.toString() - ) - if (fee.lt(desiredFee)) { - return { isEnough: false, reason: 'Not enough fee' } - } - return { isEnough: true } -} - -function getArgsForOracle() { - const tokens = mixers['netId1'] - const tokenAddresses = [] - const oneUintAmount = [] - const currencyLookup = {} - Object.entries(tokens).map(([currency, data]) => { - if (currency !== 'eth') { - tokenAddresses.push(data.tokenAddress) - oneUintAmount.push(toBN('10').pow(toBN(data.decimals.toString())).toString()) - currencyLookup[data.tokenAddress] = currency - } - }) - return { tokenAddresses, oneUintAmount, currencyLookup } -} - -function getMixers() { - return mixers[`netId${netId}`] -} - -module.exports = { - isValidProof, - isValidArgs, - sleep, - isKnownContract, - isEnoughFee, - getMixers, - getArgsForOracle -} diff --git a/src/controller.js b/src/controller.js index 0d370dc..68bd029 100644 --- a/src/controller.js +++ b/src/controller.js @@ -1,4 +1,8 @@ -const { getTornadoWithdrawInputError, getMiningRewardInputError, getMiningWithdrawInputError } = require('./validator') +const { + getTornadoWithdrawInputError, + getMiningRewardInputError, + getMiningWithdrawInputError, +} = require('./validator') const { postJob } = require('./queue') async function tornadoWithdraw(req, res) { diff --git a/src/treeWatcher.js b/src/treeWatcher.js index 009f83c..64a3877 100644 --- a/src/treeWatcher.js +++ b/src/treeWatcher.js @@ -18,7 +18,7 @@ async function fetchEvents(from = 0, to = 'latest') { }) return events .sort((a, b) => a.returnValues.index - b.returnValues.index) - .map((e) => toBN(e.returnValues.commitment)) + .map(e => toBN(e.returnValues.commitment)) } async function processNewEvent(err, event) { @@ -91,7 +91,7 @@ async function init() { init() -process.on('unhandledRejection', (error) => { +process.on('unhandledRejection', error => { console.error('Unhandled promise rejection', error) process.exit(1) }) diff --git a/src/utils.js b/src/utils.js index d5fb926..1201fee 100644 --- a/src/utils.js +++ b/src/utils.js @@ -2,7 +2,7 @@ const { instances, netId } = require('../config') const { poseidon } = require('circomlib') const { toBN, toChecksumAddress } = require('web3-utils') -const sleep = (ms) => new Promise((res) => setTimeout(res, ms)) +const sleep = ms => new Promise(res => setTimeout(res, ms)) function getInstance(address) { address = toChecksumAddress(address) @@ -27,7 +27,7 @@ function getInstance(address) { // } // } -const poseidonHash = (items) => toBN(poseidon(items).toString()) +const poseidonHash = items => toBN(poseidon(items).toString()) const poseidonHash2 = (a, b) => poseidonHash([a, b]) function setSafeInterval(func, interval) { @@ -44,10 +44,10 @@ function setSafeInterval(func, interval) { function when(source, event) { return new Promise((resolve, reject) => { source - .once(event, (payload) => { + .once(event, payload => { resolve(payload) }) - .on('error', (error) => { + .on('error', error => { reject(error) }) }) diff --git a/src/worker.js b/src/worker.js index ac97ece..9b2c1a5 100644 --- a/src/worker.js +++ b/src/worker.js @@ -115,7 +115,7 @@ async function processTornadoWithdraw(job) { await currentTx .send() .on('transactionHash', updateTxHash) - .on('mined', (receipt) => { + .on('mined', receipt => { console.log('Mined in block', receipt.blockNumber) }) .on('confirmations', updateConfirmations) @@ -141,7 +141,7 @@ async function processMiningReward(job) { await currentTx .send() .on('transactionHash', updateTxHash) - .on('mined', (receipt) => { + .on('mined', receipt => { console.log('Mined in block', receipt.blockNumber) }) .on('confirmations', updateConfirmations) @@ -167,7 +167,7 @@ async function processMiningWithdraw(job) { await currentTx .send() .on('transactionHash', updateTxHash) - .on('mined', (receipt) => { + .on('mined', receipt => { console.log('Mined in block', receipt.blockNumber) }) .on('confirmations', updateConfirmations) diff --git a/testTxManager.js b/testTxManager.js deleted file mode 100644 index 40d9072..0000000 --- a/testTxManager.js +++ /dev/null @@ -1,48 +0,0 @@ -const { toHex, toWei } = require('web3-utils') -const TxManager = require('./src/TxManager') -const { rpcUrl, privateKey } = require('./config') -const logHandles = require('why-is-node-running') - -const manager = new TxManager({ - privateKey, - rpcUrl, - config: { - CONFIRMATIONS: 1, - GAS_BUMP_INTERVAL: 1000 * 15, - }, -}) - -const tx1 = { - value: 1, - gasPrice: toHex(toWei('1', 'gwei')), - to: '0xA43Ce8Cc89Eff3AA5593c742fC56A30Ef2427CB0', -} - -const tx2 = { - value: 2, - // gasPrice: toHex(toWei('1', 'gwei')), - to: '0x0039F22efB07A647557C7C5d17854CFD6D489eF3', -} - -async function main() { - const tx = manager.createTx(tx1) - - setTimeout(() => tx.cancel(), 1000) - // setTimeout(() => tx.replace(tx2), 1000) - - const receipt = await tx.send() - .on('transactionHash', (hash) => { - console.log('hash', hash) - }) - .on('mined', (receipt) => { - console.log('Mined in block', receipt.blockNumber) - }) - .on('confirmations', (confirmations) => { - console.log('confirmations', confirmations) - }) - - console.log('receipt', receipt) - // setTimeout(logHandles, 100) -} - -main() diff --git a/yarn.lock b/yarn.lock index fd529fa..c7c5177 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1262,6 +1262,20 @@ escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +eslint-config-prettier@^6.12.0: + version "6.12.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.12.0.tgz#9eb2bccff727db1c52104f0b49e87ea46605a0d2" + integrity sha512-9jWPlFlgNwRUYVoujvWTQ1aMO8o6648r+K7qU7K5Jmkbyqav1fuEZC0COYpGBxyiAJb65Ra9hrmFx19xRGwXWw== + dependencies: + get-stdin "^6.0.0" + +eslint-plugin-prettier@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz#168ab43154e2ea57db992a2cd097c828171f75c2" + integrity sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg== + dependencies: + prettier-linter-helpers "^1.0.0" + eslint-scope@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" @@ -1673,6 +1687,11 @@ fast-deep-equal@^3.1.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -1876,6 +1895,11 @@ get-port@^5.1.1: resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ== +get-stdin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" + integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== + get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" @@ -3176,6 +3200,18 @@ prepend-http@^2.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.2.tgz#3050700dae2e4c8b67c4c3f666cdb8af405e1ce5" + integrity sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg== + process@~0.5.1: version "0.5.2" resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf"