tornado-relayer/src/utils.js

170 lines
3.9 KiB
JavaScript
Raw Normal View History

2020-10-06 13:20:26 +02:00
const { instances, netId } = require('./config')
2020-09-28 04:28:34 +02:00
const { poseidon } = require('circomlib')
const { toBN, toChecksumAddress, BN, fromWei, isAddress, toWei } = require('web3-utils')
2020-10-02 14:09:33 +02:00
2021-03-17 13:39:34 +01:00
const TOKENS = {
torn: {
tokenAddress: '0x77777FeDdddFfC19Ff86DB637967013e6C6A116C',
symbol: 'TORN',
decimals: 18,
},
2021-02-09 18:14:37 +01:00
}
2022-04-18 07:40:45 +02:00
const addressMap = new Map()
const instance = instances[`netId${netId}`]
for (const [currency, { instanceAddress, symbol, decimals }] of Object.entries(instance)) {
Object.entries(instanceAddress).forEach(([amount, address]) =>
addressMap.set(`${netId}_${address}`, {
currency,
amount,
symbol,
decimals,
}),
)
2022-04-18 07:40:45 +02:00
}
2020-10-02 12:26:05 +02:00
const sleep = ms => new Promise(res => setTimeout(res, ms))
2020-09-29 05:17:42 +02:00
2020-09-28 04:28:34 +02:00
function getInstance(address) {
2022-04-18 08:45:34 +02:00
const key = `${netId}_${toChecksumAddress(address)}`
if (addressMap.has(key)) {
return addressMap.get(key)
2022-04-18 07:40:45 +02:00
} else {
throw new Error('Unknown contact address')
2019-09-19 21:56:45 +02:00
}
2019-12-18 20:25:09 +01:00
}
2020-10-02 12:26:05 +02:00
const poseidonHash = items => toBN(poseidon(items).toString())
2020-09-28 04:28:34 +02:00
const poseidonHash2 = (a, b) => poseidonHash([a, b])
2019-11-15 10:01:59 +01:00
2020-09-28 04:28:34 +02:00
function setSafeInterval(func, interval) {
2020-09-29 22:13:45 +02:00
func()
.catch(console.error)
.finally(() => {
setTimeout(() => setSafeInterval(func, interval), interval)
})
2019-12-02 13:49:24 +01:00
}
2020-09-29 05:17:42 +02:00
/**
* A promise that resolves when the source emits specified event
*/
function when(source, event) {
2020-09-29 22:13:45 +02:00
return new Promise((resolve, reject) => {
source
2020-10-02 12:26:05 +02:00
.once(event, payload => {
2020-09-29 22:13:45 +02:00
resolve(payload)
})
2020-10-02 12:26:05 +02:00
.on('error', error => {
2020-09-29 22:13:45 +02:00
reject(error)
})
2020-09-29 05:17:42 +02:00
})
}
2020-10-05 16:22:52 +02:00
function getArgsForOracle() {
2021-02-09 18:14:37 +01:00
const tokens = {
...instances.netId1,
2021-03-17 13:39:34 +01:00
...TOKENS,
2021-02-09 18:14:37 +01:00
}
2020-10-05 16:22:52 +02:00
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 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)
}
class RelayerError extends Error {
constructor(message, score = 0) {
super(message)
this.score = score
}
}
2022-04-08 12:29:37 +02:00
const logRelayerError = async (redis, e) => {
2022-04-20 07:41:59 +02:00
await redis.zadd('errors', 'INCR', e.score || 1, e.message)
2022-04-08 12:29:37 +02:00
}
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
}
2020-08-04 09:39:56 +02:00
module.exports = {
2020-09-28 04:28:34 +02:00
getInstance,
setSafeInterval,
poseidonHash2,
2020-09-29 05:17:42 +02:00
sleep,
when,
2020-10-05 16:22:52 +02:00
getArgsForOracle,
fromDecimals,
toBN,
toChecksumAddress,
fromWei,
toWei,
BN,
isAddress,
RelayerError,
2022-04-08 12:29:37 +02:00
logRelayerError,
readRelayerErrors,
2020-08-04 09:39:56 +02:00
}