You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

153 lines
4.3 KiB

/*!
* lib/remote-importer/sources-testnet.js
* Copyright © 2019 – Katana Cryptographic Ltd. All Rights Reserved.
*/
'use strict'
const addrHelper = require('../bitcoin/addresses-helper')
const network = require('../bitcoin/network')
const util = require('../util')
const Logger = require('../logger')
const keys = require('../../keys')[network.key]
const Sources = require('./sources')
const BitcoindWrapper = require('./bitcoind-wrapper')
const InsightWrapper = require('./insight-wrapper')
const BtcComWrapper = require('./btccom-wrapper')
/**
* Remote data sources for testnet polled round-robin to spread load
*/
class SourcesTestnet extends Sources {
/**
* Constructor
*/
constructor() {
super()
this.sources = []
this.index = 0
this.sourceBech32 = null
this.isBitcoindActive = false
// Initializes external sources
this._initSources()
}
/**
* Initialize the external data sources
*/
_initSources() {
if (keys.explorers.bitcoind == 'active') {
// If local bitcoind option is activated
// we'll use the local node as our unique source
this.sourceBech32 = new BitcoindWrapper()
this.sources.push(this.sourceBech32)
this.isBitcoindActive = true
} else {
// Otherwise, we use a set of insight servers + btc.com for bech32 addresses
this.sourceBech32 = new BtcComWrapper(keys.explorers.btccom)
for (let url of keys.explorers.insight)
this.sources.push(new InsightWrapper(url))
this.isBitcoindActive = false
}
}
/**
* Get the next source index
* @returns {integer} returns the next source index
*/
nextIndex() {
this.index++
if (this.index >= this.sources.length)
this.index = 0
return this.index
}
/**
* Retrieve information for a given address
* @param {string} address - bitcoin address
* @param {boolean} filterAddr - True if an upper bound should be used
* for #transactions associated to the address, False otherwise
* @returns {Promise} returns an object
* { address: <bitcoin_address>, txids: <txids>, ntx: <total_nb_txs>}
*/
async getAddress(address, filterAddr) {
let source = ''
const isBech32 = addrHelper.isBech32(address)
const ret = {
address,
txids: [],
ntx: 0
}
try {
source = isBech32 ? this.sourceBech32 : this.sources[this.nextIndex()]
const result = await source.getAddress(address, filterAddr)
if (result.ntx)
ret.ntx = result.ntx
else if (result.txids)
ret.ntx = result.txids.length
if (result.txids)
ret.txids = result.txids
return ret
} catch(e) {
Logger.error(e, `SourcesTestnet.getAddress() : ${address} from ${source.base}`)
if (!isBech32 && this.sources.length > 1) {
// Try again with another source
return this.getAddress(address, filterAddr)
} else {
return ret
}
}
}
/**
* Retrieve information for a list of addresses
* @param {string[]} addresses - array of bitcoin address
* @param {boolean} filterAddr - True if an upper bound should be used
* for #transactions associated to the address, False otherwise
* @returns {Promise} returns an object
* { address: <bitcoin_address>, txids: <txids>, ntx: <total_nb_txs>}
*/
async getAddresses(addresses, filterAddr) {
const ret = []
try {
if (this.isBitcoindActive) {
const source = this.sources[0]
const results = await source.getAddresses(addresses, filterAddr)
for (let r of results) {
// Filter addresses with too many txs
if (!filterAddr || (r.ntx <= keys.addrFilterThreshold))
ret.push(r)
}
} else {
const lists = util.splitList(addresses, this.sources.length)
await util.seriesCall(lists, async list => {
const results = await Promise.all(list.map(a => {
return this.getAddress(a, filterAddr)
}))
for (let r of results) {
// Filter addresses with too many txs
if (!filterAddr || (r.ntx <= keys.addrFilterThreshold))
ret.push(r)
}
})
}
} catch (e) {
Logger.error(e, `SourcesTestnet.getAddresses() : Addr list = ${addresses}`)
} finally {
return ret
}
}
}
module.exports = SourcesTestnet