From 4152d1db398bc79069eae01c51c9bf2f75545e1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Salgado?= Date: Mon, 12 Sep 2022 20:34:04 +0100 Subject: [PATCH] feat: add force-sweeping ETH script --- bin/lamassu-eth-sweep-old-addresses.js | 75 ++++++++++++++++++++++++++ lib/plugins/wallet/geth/base.js | 4 +- 2 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 bin/lamassu-eth-sweep-old-addresses.js diff --git a/bin/lamassu-eth-sweep-old-addresses.js b/bin/lamassu-eth-sweep-old-addresses.js new file mode 100644 index 00000000..dcd88dd7 --- /dev/null +++ b/bin/lamassu-eth-sweep-old-addresses.js @@ -0,0 +1,75 @@ +require('../lib/environment-helper') + +const hdkey = require('ethereumjs-wallet/hdkey') +const _ = require('lodash/fp') +const hkdf = require('futoin-hkdf') +const pify = require('pify') +const fs = pify(require('fs')) +const Web3 = require('web3') +const web3 = new Web3() + +const db = require('../lib/db') +const configManager = require('../lib/new-config-manager') +const { loadLatest } = require('../lib/new-settings-loader') +const mnemonicHelpers = require('../lib/mnemonic-helpers') +const { sweep } = require('../lib/wallet') +const ph = require('../lib/plugin-helper') + +const MNEMONIC_PATH = process.env.MNEMONIC_PATH + +function fetchWallet (settings, cryptoCode) { + return fs.readFile(MNEMONIC_PATH, 'utf8') + .then(mnemonic => { + const masterSeed = mnemonicHelpers.toEntropyBuffer(mnemonic) + const plugin = configManager.getWalletSettings(cryptoCode, settings.config).wallet + const wallet = ph.load(ph.WALLET, plugin) + const rawAccount = settings.accounts[plugin] + const account = _.set('seed', computeSeed(masterSeed), rawAccount) + if (_.isFunction(wallet.run)) wallet.run(account) + return { wallet, account } + }) +} + +function computeSeed (masterSeed) { + return hkdf(masterSeed, 32, { salt: 'lamassu-server-salt', info: 'wallet-seed' }) +} + +function paymentHdNode (account) { + const masterSeed = account.seed + if (!masterSeed) throw new Error('No master seed!') + const key = hdkey.fromMasterSeed(masterSeed) + return key.derivePath("m/44'/60'/0'/0'") +} + +const getHdIndices = db => { + const sql = `SELECT id, crypto_code, hd_index FROM cash_out_txs WHERE hd_index IS NOT NULL AND status IN ('confirmed', 'instant') AND crypto_code = 'ETH'` + return db.any(sql) +} + +const getCashoutAddresses = (settings, indices) => { + return Promise.all(_.map(it => { + return fetchWallet(settings, it.crypto_code) + .then(({ wallet, account }) => Promise.all([wallet, paymentHdNode(account).deriveChild(it.hd_index).getWallet().getChecksumAddressString()])) + .then(([wallet, address]) => Promise.all([address, wallet._balance(false, address, 'ETH')])) + .then(([address, balance]) => ({ address, balance: balance.toNumber(), cryptoCode: it.crypto_code, index: it.hd_index, txId: it.id })) + }, indices)) +} + +Promise.all([getHdIndices(db), loadLatest()]) + .then(([indices, settings]) => Promise.all([settings, getCashoutAddresses(settings, indices)])) + .then(([settings, addresses]) => { + console.log('Found these cash-out addresses for ETH:') + console.log(addresses) + + return Promise.all(_.map(it => { + // If the address only has dust in it, don't bother sweeping + if (web3.utils.fromWei(it.balance.toString()) > 0.00001) { + console.log(`Address ${it.address} found to have ${web3.utils.fromWei(it.balance.toString())} ETH in it. Sweeping...`) + return sweep(settings, it.txId, it.cryptoCode, it.index) + } + + console.log(`Address ${it.address} contains no significant balance (${web3.utils.fromWei(it.balance.toString())}). Skipping the sweep process...`) + return Promise.resolve() + }, addresses)) + }) + .then(() => console.log('Process finished!')) diff --git a/lib/plugins/wallet/geth/base.js b/lib/plugins/wallet/geth/base.js index e8536a13..2eeb7a1c 100644 --- a/lib/plugins/wallet/geth/base.js +++ b/lib/plugins/wallet/geth/base.js @@ -10,7 +10,6 @@ const Tx = require('ethereumjs-tx') const { default: PQueue } = require('p-queue') const util = require('ethereumjs-util') const coins = require('@lamassu/coins') -const { default: PQueue } = require('p-queue') const _pify = require('pify') const BN = require('../../../bn') @@ -36,7 +35,8 @@ module.exports = { isStrictAddress, connect, checkBlockchainStatus, - getTxHashesByAddress + getTxHashesByAddress, + _balance } const SWEEP_QUEUE = new PQueue({