10 Commits

Author SHA1 Message Date
poma
414fb28a5e more general fix for tx error 2020-11-26 10:34:40 +03:00
Alexey
780df01b43 _handleSendError fix 2020-11-25 22:36:51 +01:00
Alexey
c5e4d76dc5 new 'nonce to low' error; remove console.log 2020-11-25 21:33:34 +01:00
Alexey
8cb2bb0fbe THROW_ON_REVERT feature 2020-11-19 20:33:58 +03:00
Alexey
6bb265d3b9 fix: throw error if transaction execution was failed 2020-11-19 14:37:18 +03:00
Alexey
b940fad5e0 remove an anoying console.log 2020-10-30 11:56:24 +03:00
poma
1634e5fb16 update gas price oracle 2020-10-20 09:39:28 +03:00
poma
62bcd2aa95 fix gas price 2020-10-20 09:28:59 +03:00
poma
1eec6aa329 simplify min and max 2020-10-17 14:37:22 +03:00
poma
715ad59273 fix repository 2020-10-17 05:29:46 +03:00
7 changed files with 44 additions and 26 deletions

1
.gitignore vendored
View File

@@ -1 +1,2 @@
node_modules node_modules
.env

View File

@@ -1,6 +1,6 @@
{ {
"name": "tx-manager", "name": "tx-manager",
"version": "0.2.0", "version": "0.2.9",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
@@ -13,15 +13,17 @@
"keywords": [], "keywords": [],
"author": "Roman Semenov <semenov.roma@gmail.com>", "author": "Roman Semenov <semenov.roma@gmail.com>",
"license": "ISC", "license": "ISC",
"repository": "https://github.com/tornadocash/tx-manager", "repository": {
"type": "git",
"url": "git://github.com/tornadocash/tx-manager.git"
},
"files": [ "files": [
"src/*" "src/*"
], ],
"dependencies": { "dependencies": {
"async-mutex": "^0.2.4", "async-mutex": "^0.2.4",
"bn.js": "^5.1.3",
"ethers": "^5.0.17", "ethers": "^5.0.17",
"gas-price-oracle": "^0.1.5", "gas-price-oracle": "^0.2.0",
"web3-core-promievent": "^1.3.0" "web3-core-promievent": "^1.3.0"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -4,21 +4,23 @@ const BigNumber = ethers.BigNumber
const PromiEvent = require('web3-core-promievent') const PromiEvent = require('web3-core-promievent')
const { sleep, min, max } = require('./utils') const { sleep, min, max } = require('./utils')
// prettier-ignore
const nonceErrors = [ const nonceErrors = [
'Transaction nonce is too low. Try incrementing the nonce.', 'Transaction nonce is too low. Try incrementing the nonce.',
'nonce too low' 'nonce too low',
'nonce has already been used',
] ]
const gasPriceErrors = [ const gasPriceErrors = [
'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.', '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.',
'replacement transaction underpriced', 'replacement transaction underpriced',
'transaction underpriced',
/Transaction gas price \d+wei is too low. There is another transaction with same nonce in the queue with gas price: \d+wei. Try increasing the gas price or incrementing the nonce./, /Transaction gas price \d+wei is too low. There is another transaction with same nonce in the queue with gas price: \d+wei. Try increasing the gas price or incrementing the nonce./,
] ]
// prettier-ignore // prettier-ignore
const sameTxErrors = [ const sameTxErrors = [
'Transaction with the same hash was already imported.', 'Transaction with the same hash was already imported.',
'already known',
] ]
class Transaction { class Transaction {
@@ -154,7 +156,6 @@ class Transaction {
this._emitter.emit('transactionHash', txHash) this._emitter.emit('transactionHash', txHash)
console.log(`Broadcasted transaction ${txHash}`) console.log(`Broadcasted transaction ${txHash}`)
console.log(this.tx)
} }
/** /**
@@ -183,6 +184,9 @@ class Transaction {
this._emitter.emit('confirmations', confirmations) this._emitter.emit('confirmations', confirmations)
if (confirmations >= this.config.CONFIRMATIONS) { if (confirmations >= this.config.CONFIRMATIONS) {
// Tx is mined and has enough confirmations // Tx is mined and has enough confirmations
if (this.config.THROW_ON_REVERT && Number(receipt.status) === 0) {
throw new Error('EVM execution failed, so the transaction was reverted.')
}
return receipt return receipt
} }
@@ -235,7 +239,6 @@ class Transaction {
} }
} }
console.log('Mined. Start waiting for confirmations...')
this._emitter.emit('mined', receipt) this._emitter.emit('mined', receipt)
this.currentTxHash = receipt.transactionHash this.currentTxHash = receipt.transactionHash
} }
@@ -267,11 +270,13 @@ class Transaction {
} }
_handleSendError(e) { _handleSendError(e) {
console.log('Got error', e) if (e.error.error) {
// Sometimes ethers wraps known errors, unwrap it in this case
e = e.error
}
if (e.code === 'SERVER_ERROR' && e.error) { if (e.error && e.code === 'SERVER_ERROR') {
const message = e.error.message const message = e.error.message
console.log('Error', e.error.code, e.error.message)
// nonce is too low, trying to increase and resubmit // nonce is too low, trying to increase and resubmit
if (this._hasError(message, nonceErrors)) { if (this._hasError(message, nonceErrors)) {
@@ -341,7 +346,7 @@ class Transaction {
const gasPrices = await this._gasPriceOracle.gasPrices() const gasPrices = await this._gasPriceOracle.gasPrices()
const result = gasPrices[type].toString() const result = gasPrices[type].toString()
console.log(`${type} gas price is now ${result} gwei`) console.log(`${type} gas price is now ${result} gwei`)
return parseUnits(gasPrices[type], 'gwei').toHexString() return parseUnits(result, 'gwei').toHexString()
} }
/** /**

View File

@@ -13,6 +13,7 @@ const defaultConfig = {
POLL_INTERVAL: 5000, POLL_INTERVAL: 5000,
CONFIRMATIONS: 8, CONFIRMATIONS: 8,
ESTIMATE_GAS: true, ESTIMATE_GAS: true,
THROW_ON_REVERT: true,
} }
class TxManager { class TxManager {

View File

@@ -1,14 +1,11 @@
const BN = require('bn.js')
const { BigNumber } = require('ethers')
/** /**
* A promise that resolves after `ms` milliseconds * A promise that resolves after `ms` milliseconds
*/ */
const sleep = ms => new Promise(res => setTimeout(res, ms)) const sleep = ms => new Promise(res => setTimeout(res, ms))
const max = (a, b) => BigNumber.from(BN.max(new BN(a.toString()), new BN(b.toString())).toString()) const max = (a, b) => (a.gt(b) ? a : b)
const min = (a, b) => BigNumber.from(BN.min(new BN(a.toString()), new BN(b.toString())).toString()) const min = (a, b) => (a.lt(b) ? a : b)
module.exports = { module.exports = {
sleep, sleep,

View File

@@ -32,6 +32,11 @@ describe('TxManager', () => {
to: '0x0039F22efB07A647557C7C5d17854CFD6D489eF3', to: '0x0039F22efB07A647557C7C5d17854CFD6D489eF3',
} }
const tx4 = {
value: 1,
to: '0xA43Ce8Cc89Eff3AA5593c742fC56A30Ef2427CB0',
}
describe('#transaction', () => { describe('#transaction', () => {
it('should work', async () => { it('should work', async () => {
const tx = manager.createTx(tx1) const tx = manager.createTx(tx1)
@@ -45,6 +50,18 @@ describe('TxManager', () => {
console.log('receipt', receipt) console.log('receipt', receipt)
}) })
it('should fetch gas price', async () => {
const tx = manager.createTx(tx4)
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)
})
it('should bump gas price', async () => { it('should bump gas price', async () => {
const tx = manager.createTx(tx2) const tx = manager.createTx(tx2)

View File

@@ -593,11 +593,6 @@ bn.js@^4.4.0:
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828"
integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==
bn.js@^5.1.3:
version "5.1.3"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b"
integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==
brace-expansion@^1.1.7: brace-expansion@^1.1.7:
version "1.1.11" version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@@ -1146,10 +1141,10 @@ functional-red-black-tree@^1.0.1:
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
gas-price-oracle@^0.1.5: gas-price-oracle@^0.2.0:
version "0.1.5" version "0.2.0"
resolved "https://registry.yarnpkg.com/gas-price-oracle/-/gas-price-oracle-0.1.5.tgz#09dd0d9806465c2f5e63b682e6742f96f6eb525c" resolved "https://registry.yarnpkg.com/gas-price-oracle/-/gas-price-oracle-0.2.0.tgz#981926c96089497115113162b03151aacfe44a5a"
integrity sha512-fkaTXnxJcSVco/tMPEcN5gieoUNs8O6JYMXflGLN2+3YeGZAucUI0fgCliazM3nRVAk//bBEm9819/Zb83xhrw== integrity sha512-2+mMyunV/pMJrmKl/IeEtX860NaE/bQ7H4D8PO2dc0OQd8ZAj/e4WJ+C9F/uOeG3dwm8SEFjofOvcYRHeGxo/Q==
dependencies: dependencies:
axios "^0.19.2" axios "^0.19.2"
bignumber.js "^9.0.0" bignumber.js "^9.0.0"