From d338d0adca9983fea21d2f900cf396c4fb85812e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Oliveira?= Date: Sun, 4 Apr 2021 21:45:09 +0100 Subject: [PATCH] feat: rbf checking in blockcypher plugin --- lib/plugins/wallet/bitcoind/bitcoind.js | 14 ++++++- .../zero-conf/blockcypher/blockcypher.js | 39 +++++++++++++------ lib/wallet.js | 4 +- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/lib/plugins/wallet/bitcoind/bitcoind.js b/lib/plugins/wallet/bitcoind/bitcoind.js index 238fcca1..9ab76622 100644 --- a/lib/plugins/wallet/bitcoind/bitcoind.js +++ b/lib/plugins/wallet/bitcoind/bitcoind.js @@ -126,11 +126,23 @@ function cryptoNetwork (account, cryptoCode) { .then(() => parseInt(rpcConfig.port, 10) === 18332 ? 'test' : 'main') } +function fetchRBF (txId) { + return fetch('getmempoolentry', [txId]) + .then((res) => _.assign(_.pick(['bip125-replaceable'], res)), { tx_hash: txId }) + .catch(err => { + if (err.code === -5) console.log(`${err.message}`) + const result = { tx_hash: txId } + result['bip125-replaceable'] = true + return result + }) +} + module.exports = { balance, sendCoins, newAddress, getStatus, newFunding, - cryptoNetwork + cryptoNetwork, + fetchRBF } diff --git a/lib/plugins/zero-conf/blockcypher/blockcypher.js b/lib/plugins/zero-conf/blockcypher/blockcypher.js index ea00067a..3b0829ed 100644 --- a/lib/plugins/zero-conf/blockcypher/blockcypher.js +++ b/lib/plugins/zero-conf/blockcypher/blockcypher.js @@ -2,36 +2,51 @@ const qs = require('querystring') const axios = require('axios') const _ = require('lodash/fp') -module.exports = {authorize} +const { fetchRBF } = require('../../wallet/bitcoind/bitcoind') +module.exports = { authorize } function highConfidence (confidence, txref) { if (txref.double_spend) return 0 + if (txref.rbf) return 0 if (txref.confirmations > 0 || txref.confidence * 100 >= confidence) return txref.value return 0 } -function authorize (account, toAddress, cryptoAtoms, cryptoCode) { +function authorize (account, toAddress, cryptoAtoms, cryptoCode, isBitcoindAvailable) { + var promise = [] return Promise.resolve() .then(() => { if (cryptoCode !== 'BTC') throw new Error('Unsupported crypto: ' + cryptoCode) - const query = qs.stringify({ token: account.token, includeConfidence: true }) - const confidence = account.confidenceFactor - + const verifyRBF = account.rbf const url = `https://api.blockcypher.com/v1/btc/main/addrs/${toAddress}?${query}` - return axios.get(url) .then(r => { const data = r.data - const sumTxRefs = txrefs => _.sumBy(txref => highConfidence(confidence, txref), txrefs) - - const authorizedValue = sumTxRefs(data.txrefs) + sumTxRefs(data.unconfirmed_txrefs) - - return cryptoAtoms.lte(authorizedValue) + if (isBitcoindAvailable && verifyRBF && data.unconfirmed_txrefs) { + _.map(unconfirmedTxref => { + promise.push(new Promise((resolve, reject) => { resolve(fetchRBF(unconfirmedTxref.tx_hash)) })) + }, data.unconfirmed_txrefs) + return Promise.all(promise) + .then(values => { + _.map(rbfInfo => { + _.map(unconfirmedTxref => { + if (rbfInfo.tx_hash === unconfirmedTxref.tx_hash) unconfirmedTxref.rbf = rbfInfo['bip125-replaceable'] + }, data.unconfirmed_txrefs) + }, values) + const sumTxRefs = txrefs => _.sumBy(txref => highConfidence(confidence, txref), txrefs) + const authorizedValue = sumTxRefs(data.txrefs) + sumTxRefs(data.unconfirmed_txrefs) + return cryptoAtoms.lte(authorizedValue) + }) + } else { + const sumTxRefs = txrefs => _.sumBy(txref => highConfidence(confidence, txref), txrefs) + const authorizedValue = sumTxRefs(data.txrefs) + sumTxRefs(data.unconfirmed_txrefs) + return cryptoAtoms.lte(authorizedValue) + } }) }) -} +} \ No newline at end of file diff --git a/lib/wallet.js b/lib/wallet.js index 6334e621..fe122d1d 100644 --- a/lib/wallet.js +++ b/lib/wallet.js @@ -132,6 +132,8 @@ function getWalletStatus (settings, tx) { function authorizeZeroConf (settings, tx, machineId) { const plugin = configManager.getWalletSettings(tx.cryptoCode, settings.config).zeroConf + const isBitcoindAvailable = + configManager.getWalletSettings(tx.cryptoCode, settings.config).wallet === 'bitcoind' const cashOutConfig = configManager.getCashOut(machineId, settings.config) const zeroConfLimit = cashOutConfig.zeroConfLimit @@ -148,7 +150,7 @@ function authorizeZeroConf (settings, tx, machineId) { const zeroConf = ph.load(ph.ZERO_CONF, plugin) const account = settings.accounts[plugin] - return zeroConf.authorize(account, tx.toAddress, tx.cryptoAtoms, tx.cryptoCode) + return zeroConf.authorize(account, tx.toAddress, tx.cryptoAtoms, tx.cryptoCode, isBitcoindAvailable) } function getStatus (settings, tx, machineId) {