diff --git a/src/controller.js b/src/controller.js index 9605c4b..72c640d 100644 --- a/src/controller.js +++ b/src/controller.js @@ -1,4 +1,4 @@ -const { getTornadoWithdrawInputError } = require('./validator') +const { getTornadoWithdrawInputError } = require('./modules/validator') const { postJob } = require('./queue') const { jobType } = require('./constants') diff --git a/src/healthWatcher.js b/src/healthWatcher.js index c60d95d..0dde5bc 100644 --- a/src/healthWatcher.js +++ b/src/healthWatcher.js @@ -1,12 +1,10 @@ const Web3 = require('web3') -const Redis = require('ioredis') const { toBN, fromWei } = require('web3-utils') - const { setSafeInterval } = require('./utils') -const { redisUrl, httpRpcUrl, privateKey, minimumBalance, nativeCurrency, instances } = require('./config') +const { httpRpcUrl, privateKey, minimumBalance, nativeCurrency, instances } = require('./config') const web3 = new Web3(httpRpcUrl) -const redis = new Redis(redisUrl) +const { redis } = require('modules/redis') async function main() { try { diff --git a/src/modules/redis.js b/src/modules/redis.js new file mode 100644 index 0000000..f639e1f --- /dev/null +++ b/src/modules/redis.js @@ -0,0 +1,9 @@ +const { createClient } = require('ioredis') +const { redisUrl } = require('../config') + +const redis = createClient(redisUrl) + +module.exports = { + redis, + redisUrl, +} diff --git a/src/validator.js b/src/modules/validator.js similarity index 98% rename from src/validator.js rename to src/modules/validator.js index 092b9f1..577dc24 100644 --- a/src/validator.js +++ b/src/modules/validator.js @@ -1,6 +1,6 @@ const { isAddress, toChecksumAddress } = require('web3-utils') -const { getInstance } = require('./utils') -const { rewardAccount } = require('./config') +const { getInstance } = require('../utils') +const { rewardAccount } = require('../config') const Ajv = require('ajv') const ajv = new Ajv({ format: 'fast' }) diff --git a/src/queue.js b/src/queue.js index dbd2ad4..7935e01 100644 --- a/src/queue.js +++ b/src/queue.js @@ -1,9 +1,7 @@ const { v4: uuid } = require('uuid') const Queue = require('bull') -const Redis = require('ioredis') -const { redisUrl } = require('./config') const { status } = require('./constants') -const redis = new Redis(redisUrl) +const { redis, redisUrl } = require('./modules/redis') const queue = new Queue('proofs', redisUrl, { lockDuration: 300000, // Key expiration time for job locks. diff --git a/src/router.js b/src/router.js new file mode 100644 index 0000000..85cd7f7 --- /dev/null +++ b/src/router.js @@ -0,0 +1,27 @@ +const { controller, status } = require('./contollers') +const router = require('express').Router() + +// Add CORS headers +router.use((req, res, next) => { + res.header('Access-Control-Allow-Origin', '*') + res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept') + next() +}) + +// Log error to console but don't send it to the client to avoid leaking data +router.use((err, req, res, next) => { + if (err) { + console.error(err) + return res.sendStatus(500) + } + next() +}) + +router.get('/', status.index) +router.get('/v1/status', status.status) +router.get('/v1/jobs/:id', status.getJob) +router.post('/v1/tornadoWithdraw', controller.tornadoWithdraw) +router.get('/status', status.status) +router.post('/relay', controller.tornadoWithdraw) + +module.exports = router diff --git a/src/server.js b/src/server.js index 29e73bf..bfdc58d 100644 --- a/src/server.js +++ b/src/server.js @@ -1,39 +1,16 @@ const express = require('express') -const status = require('./status') -const controller = require('./controller') +const router = require('./router') const { port, rewardAccount } = require('./config') const { version } = require('../package.json') const { isAddress } = require('web3-utils') -const app = express() -app.use(express.json()) - -// Add CORS headers -app.use((req, res, next) => { - res.header('Access-Control-Allow-Origin', '*') - res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept') - next() -}) - -// Log error to console but don't send it to the client to avoid leaking data -app.use((err, req, res, next) => { - if (err) { - console.error(err) - return res.sendStatus(500) - } - next() -}) - -app.get('/', status.index) -app.get('/v1/status', status.status) -app.get('/v1/jobs/:id', status.getJob) -app.post('/v1/tornadoWithdraw', controller.tornadoWithdraw) -app.get('/status', status.status) -app.post('/relay', controller.tornadoWithdraw) - if (!isAddress(rewardAccount)) { throw new Error('No REWARD_ACCOUNT specified') } +const app = express() +app.use(express.json()) +app.use(router) + app.listen(port) console.log(`Relayer ${version} started on port ${port}`) diff --git a/src/status.js b/src/status.js index 7c419e9..ca8d1fe 100644 --- a/src/status.js +++ b/src/status.js @@ -2,11 +2,12 @@ const queue = require('./queue') const { netId, tornadoServiceFee, instances, redisUrl, rewardAccount } = require('./config') const { version } = require('../package.json') const Redis = require('ioredis') +const { readRelayerErrors } = require('./utils') const redis = new Redis(redisUrl) async function status(req, res) { const health = await redis.hgetall('health') - + health.errorsLog = readRelayerErrors(redis) const { waiting: currentQueue } = await queue.queue.getJobCounts() res.json({ diff --git a/src/utils.js b/src/utils.js index 5160683..49fe59b 100644 --- a/src/utils.js +++ b/src/utils.js @@ -70,8 +70,24 @@ function fromDecimals(value, decimals) { return new BN(wei.toString(10), 10) } +const logRelayerError = async (redis, e) => { + await redis.zadd('errors', 'INCR', 1, e.message) +} + +const readRelayerErrors = async redis => { + const set = await redis.zrevrange('errors', 0, -1, 'WITHSCORES') + const errors = [] + while (set.length) { + const [message, score] = set.splice(0, 2) + errors.push({ message, score }) + } + return errors +} + module.exports = { getInstance, setSafeInterval, fromDecimals, + logRelayerError, + readRelayerErrors, } diff --git a/src/worker.js b/src/worker.js index e5848be..f12665b 100644 --- a/src/worker.js +++ b/src/worker.js @@ -1,10 +1,10 @@ const Web3 = require('web3') const { GasPriceOracle } = require('gas-price-oracle') const { toBN, toWei, fromWei, toHex } = require('web3-utils') - +const { redis } = require('modules/redis') const proxyLightABI = require('../abis/proxyLightABI.json') const { queue } = require('./queue') -const { getInstance, fromDecimals } = require('./utils') +const { getInstance, fromDecimals, logRelayerError } = require('./utils') const { jobType, status } = require('./constants') const { netId, @@ -46,6 +46,7 @@ function start() { queue.process(processJob) console.log('Worker started') } catch (e) { + logRelayerError(redis, e.message) console.error('error on start worker', e.message) } } diff --git a/test/validator.js b/test/validator.js index 4915dcd..7a1b25e 100644 --- a/test/validator.js +++ b/test/validator.js @@ -1,6 +1,6 @@ require('chai').should() -const { getTornadoWithdrawInputError } = require('../src/validator') +const { getTornadoWithdrawInputError } = require('../src/modules/validator') describe('Validator', () => { describe('#getTornadoWithdrawInputError', () => {