Browse Source

Microoptimizations and JSdoc improvements

Pavel Ševčík 3 years ago
parent
commit
1ace9d6fe9
No known key found for this signature in database GPG Key ID: CFA54E4C0CD58DF0
  1. 2
      accounts/fees-rest-api.js
  2. 2
      accounts/headers-rest-api.js
  3. 51
      accounts/multiaddr-rest-api.js
  4. 14
      accounts/notifications-service.js
  5. 2
      accounts/status-rest-api.js
  6. 6
      accounts/status.js
  7. 18
      accounts/support-rest-api.js
  8. 4
      accounts/transactions-rest-api.js
  9. 2
      accounts/unspent-rest-api.js
  10. 2
      accounts/wallet-rest-api.js
  11. 16
      accounts/xpub-rest-api.js
  12. 2
      docker/my-dojo/node/keys.index.js
  13. 6
      lib/auth/authorizations-manager.js
  14. 3
      lib/auth/localapikey-strategy-configurator.js
  15. 36
      lib/bitcoin/addresses-helper.js
  16. 12
      lib/bitcoin/addresses-service.js
  17. 46
      lib/bitcoin/hd-accounts-helper.js
  18. 32
      lib/bitcoin/hd-accounts-service.js
  19. 10
      lib/bitcoin/parallel-address-derivation.js
  20. 4
      lib/bitcoind-rpc/fees.js
  21. 2
      lib/bitcoind-rpc/rpc-client.js
  22. 12
      lib/bitcoind-rpc/transactions.js
  23. 159
      lib/db/mysql-db-wrapper.js
  24. 3
      lib/http-server/http-server.js
  25. 11
      lib/indexer-rpc/rpc-client.js
  26. 4
      lib/remote-importer/esplora-wrapper.js
  27. 2
      lib/remote-importer/local-indexer-wrapper.js
  28. 2
      lib/remote-importer/local-rest-indexer-wrapper.js
  29. 4
      lib/remote-importer/oxt-wrapper.js
  30. 14
      lib/remote-importer/remote-importer.js
  31. 6
      lib/remote-importer/sources-mainnet.js
  32. 6
      lib/remote-importer/sources-testnet.js
  33. 3
      lib/remote-importer/wrapper.js
  34. 118
      lib/util.js
  35. 34
      lib/wallet/address-info.js
  36. 37
      lib/wallet/hd-account-info.js
  37. 21
      lib/wallet/wallet-entities.js
  38. 48
      lib/wallet/wallet-info.js
  39. 28
      lib/wallet/wallet-service.js
  40. 8
      pushtx/orchestrator.js
  41. 4
      pushtx/pushtx-processor.js
  42. 4
      pushtx/pushtx-rest-api.js
  43. 8
      pushtx/transactions-scheduler.js
  44. 14
      scripts/patches/revert-hd-accounts.js
  45. 20
      scripts/patches/translate-hd-accounts.js
  46. 2
      static/admin/dmt/index.js
  47. 10
      static/admin/dmt/status/status.js
  48. 8
      static/admin/dmt/xpubs-tools/xpubs-tools.js
  49. 4
      static/admin/lib/auth-utils.js
  50. 8
      static/admin/lib/common-script.js
  51. 2
      static/admin/lib/errors-utils.js
  52. 2
      static/admin/lib/format-utils.js
  53. 10
      tracker/block-worker.js
  54. 16
      tracker/block.js
  55. 26
      tracker/blockchain-processor.js
  56. 8
      tracker/blocks-processor.js
  57. 15
      tracker/mempool-processor.js
  58. 2
      tracker/tracker.js
  59. 16
      tracker/transaction.js
  60. 17
      tracker/transactions-bundle.js

2
accounts/fees-rest-api.js

@ -9,7 +9,7 @@ const rpcFees = require('../lib/bitcoind-rpc/fees')
const authMgr = require('../lib/auth/authorizations-manager')
const HttpServer = require('../lib/http-server/http-server')
const debugApi = !!(process.argv.indexOf('api-debug') > -1)
const debugApi = process.argv.indexOf('api-debug') > -1
/**

2
accounts/headers-rest-api.js

@ -12,7 +12,7 @@ const authMgr = require('../lib/auth/authorizations-manager')
const HttpServer = require('../lib/http-server/http-server')
const apiHelper = require('./api-helper')
const debugApi = !!(process.argv.indexOf('api-debug') > -1)
const debugApi = process.argv.indexOf('api-debug') > -1
/**

51
accounts/multiaddr-rest-api.js

@ -12,7 +12,7 @@ const authMgr = require('../lib/auth/authorizations-manager')
const HttpServer = require('../lib/http-server/http-server')
const apiHelper = require('./api-helper')
const debugApi = !!(process.argv.indexOf('api-debug') > -1)
const debugApi = process.argv.indexOf('api-debug') > -1
/**
@ -32,18 +32,20 @@ class MultiaddrRestApi {
const urlencodedParser = bodyParser.urlencoded({ extended: true })
this.httpServer.app.get(
'/multiaddr',
authMgr.checkAuthentication.bind(authMgr),
apiHelper.validateEntitiesParams.bind(apiHelper),
this.getMultiaddr.bind(this),
'/multiaddr',
authMgr.checkAuthentication.bind(authMgr),
apiHelper.validateEntitiesParams.bind(apiHelper),
this.getMultiaddr.bind(this),
HttpServer.sendAuthError
)
this.httpServer.app.post(
'/multiaddr',
urlencodedParser,
authMgr.checkAuthentication.bind(authMgr),
apiHelper.validateEntitiesParams.bind(apiHelper),
this.postMultiaddr.bind(this),
'/multiaddr',
urlencodedParser,
authMgr.checkAuthentication.bind(authMgr),
apiHelper.validateEntitiesParams.bind(apiHelper),
this.postMultiaddr.bind(this),
HttpServer.sendAuthError
)
}
@ -57,16 +59,19 @@ class MultiaddrRestApi {
// Check request params
if (!apiHelper.checkEntitiesParams(req.query))
return HttpServer.sendError(res, errors.multiaddr.NOACT)
//return HttpServer.sendError(res, '')
// Parse params
const entities = apiHelper.parseEntitiesParams(req.query)
if (entities.active.addrs.length === 1 || entities.active.addrs.length === 2 || entities.active.xpubs.length === 1)
return HttpServer.sendError(res, '')
const result = await walletService.getWalletInfo(
entities.active,
entities.legacy,
entities.bip49,
entities.bip84,
entities.pubkey
entities.active,
entities.legacy,
entities.bip49,
entities.bip84,
entities.pubkey
)
const ret = JSON.stringify(result, null, 2)
@ -78,7 +83,7 @@ class MultiaddrRestApi {
} finally {
if (debugApi) {
const strParams =
`${req.query.active ? req.query.active : ''} \
`${req.query.active ? req.query.active : ''} \
${req.query.new ? req.query.new : ''} \
${req.query.pubkey ? req.query.pubkey : ''} \
${req.query.bip49 ? req.query.bip49 : ''} \
@ -104,11 +109,11 @@ class MultiaddrRestApi {
const entities = apiHelper.parseEntitiesParams(req.body)
const result = await walletService.getWalletInfo(
entities.active,
entities.legacy,
entities.bip49,
entities.bip84,
entities.pubkey
entities.active,
entities.legacy,
entities.bip49,
entities.bip84,
entities.pubkey
)
HttpServer.sendOkDataOnly(res, result)
@ -119,7 +124,7 @@ class MultiaddrRestApi {
} finally {
if (debugApi) {
const strParams =
`${req.body.active ? req.body.active : ''} \
`${req.body.active ? req.body.active : ''} \
${req.body.new ? req.body.new : ''} \
${req.body.pubkey ? req.body.pubkey : ''} \
${req.body.bip49 ? req.body.bip49 : ''} \

14
accounts/notifications-service.js

@ -14,7 +14,7 @@ const apiHelper = require('./api-helper')
const status = require('./status')
const authMgr = require('../lib/auth/authorizations-manager')
const debug = !!(process.argv.indexOf('ws-debug') > -1)
const debug = process.argv.indexOf('ws-debug') > -1
/**
@ -80,7 +80,7 @@ class NotificationsService {
})
conn.on('message', msg => {
if (msg.type == 'utf8')
if (msg.type === 'utf8')
this._handleWSMessage(msg.utf8Data, conn)
else
this._closeWSConnection(conn, true)
@ -229,7 +229,7 @@ class NotificationsService {
/**
* Unsubscribe from a topic
* @param {string} topic - topic
* @param {int} cid - client id
* @param {number} cid - client id
*/
_unsub(topic, cid) {
if (!this.subs[topic])
@ -241,7 +241,7 @@ class NotificationsService {
this.subs[topic].splice(index, 1)
if (this.subs[topic].length == 0) {
if (this.subs[topic].length === 0) {
delete this.subs[topic]
if (this.cachePubKeys.hasOwnProperty(topic))
delete this.cachePubKeys[topic]
@ -391,7 +391,7 @@ class NotificationsService {
for (let cid of this.subs[topic]) {
if (!clients[cid])
clients[cid] = []
if (clients[cid].indexOf(topic) == -1)
if (clients[cid].indexOf(topic) === -1)
clients[cid].push(topic)
}
}
@ -429,7 +429,7 @@ class NotificationsService {
}
// Move on if the custom transaction has no inputs or outputs
if (ctx.inputs.length == 0 && ctx.out.length == 0)
if (ctx.inputs.length === 0 && ctx.out.length === 0)
continue
// Send custom transaction to client
@ -454,7 +454,7 @@ class NotificationsService {
/**
* Dispatch notification for an authentication error
* @param {string} err - error
* @param {integer} cid - connection id
* @param {number} cid - connection id
*/
notifyAuthError(err, cid) {
const data = {

2
accounts/status-rest-api.js

@ -11,7 +11,7 @@ const authMgr = require('../lib/auth/authorizations-manager')
const HttpServer = require('../lib/http-server/http-server')
const status = require('./status')
const debugApi = !!(process.argv.indexOf('api-debug') > -1)
const debugApi = process.argv.indexOf('api-debug') > -1
/**

6
accounts/status.js

@ -29,7 +29,7 @@ class Status {
/**
* Get current status
* @returns {Promise - object} status object
* @returns {Promise<object>} status object
*/
async getCurrent() {
const uptime = util.timePeriod((Date.now() - this.t0) / 1000, false)
@ -49,8 +49,8 @@ class Status {
let indexerMaxHeight = null
let indexerUrl = null
if (indexerType == 'third_party_explorer') {
indexerUrl = (network.key == 'bitcoin')
if (indexerType === 'third_party_explorer') {
indexerUrl = (network.key === 'bitcoin')
? keys.indexer.oxt
: keys.indexer.esplora
}

18
accounts/support-rest-api.js

@ -19,7 +19,7 @@ const AddressInfo = require('../lib/wallet/address-info')
const apiHelper = require('./api-helper')
const keys = require('../keys')[network.key]
const debugApi = !!(process.argv.indexOf('api-debug') > -1)
const debugApi = process.argv.indexOf('api-debug') > -1
/**
@ -94,7 +94,7 @@ class SupportRestApi {
try {
// Parse the entities passed as url params
const entities = apiHelper.parseEntities(req.params.addr).addrs
if (entities.length == 0)
if (entities.length === 0)
return HttpServer.sendError(res, errors.address.INVALID)
const address = entities[0]
@ -133,7 +133,7 @@ class SupportRestApi {
try {
// Parse the entities passed as url params
const entities = apiHelper.parseEntities(req.params.addr).addrs
if (entities.length == 0)
if (entities.length === 0)
return HttpServer.sendError(res, errors.address.INVALID)
const address = entities[0]
@ -162,7 +162,7 @@ class SupportRestApi {
try {
// Parse the entities passed as url params
const entities = apiHelper.parseEntities(req.params.xpub).xpubs
if (entities.length == 0)
if (entities.length === 0)
return HttpServer.sendError(res, errors.xpub.INVALID)
const xpub = entities[0]
@ -174,7 +174,7 @@ class SupportRestApi {
const ret = this._formatXpubInfoResult(info)
HttpServer.sendRawData(res, ret)
} catch(e) {
if(e == errors.db.ERROR_NO_HD_ACCOUNT) {
if(e === errors.db.ERROR_NO_HD_ACCOUNT) {
const ret = this._formatXpubInfoResult(info)
HttpServer.sendRawData(res, ret)
} else {
@ -210,7 +210,7 @@ class SupportRestApi {
try {
// Parse the entities passed as url params
const entities = apiHelper.parseEntities(req.params.xpub).xpubs
if (entities.length == 0)
if (entities.length === 0)
return HttpServer.sendError(res, errors.xpub.INVALID)
const xpub = entities[0]
@ -226,10 +226,10 @@ class SupportRestApi {
await hdaService.rescan(xpub, gapLimit, startIndex)
HttpServer.sendRawData(res, JSON.stringify(ret, null, 2))
} catch(e) {
if (e == errors.db.ERROR_NO_HD_ACCOUNT) {
if (e === errors.db.ERROR_NO_HD_ACCOUNT) {
ret.status = 'Error: Not tracking xpub'
HttpServer.sendRawData(res, JSON.stringify(ret, null, 2))
} else if (e == errors.xpub.OVERLAP) {
} else if (e === errors.xpub.OVERLAP) {
ret.status = 'Error: Rescan in progress'
HttpServer.sendRawData(res, JSON.stringify(ret, null, 2))
} else {
@ -256,7 +256,7 @@ class SupportRestApi {
try {
// Parse the entities passed as url params
const entities = apiHelper.parseEntities(req.params.xpub).xpubs
if (entities.length == 0)
if (entities.length === 0)
return HttpServer.sendError(res, errors.xpub.INVALID)
const xpub = entities[0]

4
accounts/transactions-rest-api.js

@ -15,7 +15,7 @@ const network = require('../lib/bitcoin/network')
const apiHelper = require('./api-helper')
const keys = require('../keys')[network.key]
const debugApi = !!(process.argv.indexOf('api-debug') > -1)
const debugApi = process.argv.indexOf('api-debug') > -1
/**
@ -86,7 +86,7 @@ class TransactionsRestApi {
const result = await walletService.getWalletTransactions(active, page, count)
if (excludeNullXfer) {
result.txs = result.txs.filter(tx => {
return tx['result'] != 0
return tx['result'] !== 0
})
}

2
accounts/unspent-rest-api.js

@ -12,7 +12,7 @@ const authMgr = require('../lib/auth/authorizations-manager')
const HttpServer = require('../lib/http-server/http-server')
const apiHelper = require('./api-helper')
const debugApi = !!(process.argv.indexOf('api-debug') > -1)
const debugApi = process.argv.indexOf('api-debug') > -1
/**

2
accounts/wallet-rest-api.js

@ -12,7 +12,7 @@ const authMgr = require('../lib/auth/authorizations-manager')
const HttpServer = require('../lib/http-server/http-server')
const apiHelper = require('./api-helper')
const debugApi = !!(process.argv.indexOf('api-debug') > -1)
const debugApi = process.argv.indexOf('api-debug') > -1
/**

16
accounts/xpub-rest-api.js

@ -113,9 +113,9 @@ class XPubRestApi {
if (argSegwit) {
const segwit = argSegwit.toLowerCase()
if (segwit == 'bip49')
if (segwit === 'bip49')
scheme = hdaHelper.BIP49
else if (segwit == 'bip84')
else if (segwit === 'bip84')
scheme = hdaHelper.BIP84
else
return HttpServer.sendError(res, errors.xpub.SEGWIT)
@ -125,7 +125,7 @@ class XPubRestApi {
const forceOverride = argForceOverride ? argForceOverride : false
// Process action
if (argAction == 'new') {
if (argAction === 'new') {
// New hd account
try {
await hdaService.createHdAccount(xpub, scheme)
@ -133,7 +133,7 @@ class XPubRestApi {
} catch(e) {
HttpServer.sendError(res, e)
}
} else if (argAction == 'restore') {
} else if (argAction === 'restore') {
// Restore hd account
try {
await hdaService.restoreHdAccount(xpub, scheme, forceOverride)
@ -229,7 +229,7 @@ class XPubRestApi {
if (status != null) {
ret['import_in_progress'] = true
ret['status'] = status['status']
if (ret['status'] == remoteImporter.STATUS_RESCAN)
if (ret['status'] === remoteImporter.STATUS_RESCAN)
ret['hits'] = status['txs_int'] + status['txs_ext']
else
ret['hits'] = status['txs']
@ -268,7 +268,7 @@ class XPubRestApi {
if (!req.body.message)
return HttpServer.sendError(res, errors.body.NOMSG)
if (!(req.body.message == 'lock' || req.body.message == 'unlock'))
if (!(req.body.message === 'lock' || req.body.message === 'unlock'))
return HttpServer.sendError(res, errors.sig.INVMSG)
// Extract arguments
@ -289,7 +289,7 @@ class XPubRestApi {
try {
// Check the signature and process the request
await hdaService.verifyXpubSignature(xpub, argAddr, argSig, argMsg, scheme)
const lock = (argMsg == 'unlock') ? false : true
const lock = argMsg !== 'unlock'
const ret = await hdaService.lockHdAccount(xpub, lock)
HttpServer.sendOkData(res, {derivation: ret})
} catch(e) {
@ -385,7 +385,7 @@ class XPubRestApi {
}
} catch(e) {
const err = (e == errors.xpub.PRIVKEY) ? e : errors.xpub.INVALID
const err = (e === errors.xpub.PRIVKEY) ? e : errors.xpub.INVALID
throw err
}
}

2
docker/my-dojo/node/keys.index.js

@ -14,7 +14,7 @@ const bitcoinNetwork = (process.env.COMMON_BTC_NETWORK == 'testnet')
let explorerActive = 'oxt'
let explorerUrl = 'https://oxt.me'
let explorerPassword = ''
if (process.env.EXPLORER_INSTALL == 'on') {
if (process.env.EXPLORER_INSTALL === 'on') {
try {
explorerUrl = fs.readFileSync('/var/lib/tor/hsv3explorer/hostname', 'utf8').replace('\n', '')
explorerPassword = process.env.EXPLORER_KEY

6
lib/auth/authorizations-manager.js

@ -162,7 +162,7 @@ class AuthorizationsManager {
try {
const decodedToken = this.isAuthenticated(token)
if (decodedToken['prf'] == this.TOKEN_PROFILE_ADMIN) {
if (decodedToken['prf'] === this.TOKEN_PROFILE_ADMIN) {
req.authorizations = {decoded_access_token: decodedToken}
next()
} else {
@ -249,7 +249,7 @@ class AuthorizationsManager {
{algorithms: [this.JWT_ALGO]}
)
if (payload['type'] != this.TOKEN_TYPE_ACCESS)
if (payload['type'] !== this.TOKEN_TYPE_ACCESS)
throw errors.auth.INVALID_JWT
return payload
@ -309,7 +309,7 @@ class AuthorizationsManager {
{algorithms: [this.JWT_ALGO]}
)
if (payload['type'] != this.TOKEN_TYPE_REFRESH)
if (payload['type'] !== this.TOKEN_TYPE_REFRESH)
throw errors.auth.INVALID_JWT
return payload

3
lib/auth/localapikey-strategy-configurator.js

@ -33,7 +33,6 @@ class LocalApiKeyStrategyConfigurator {
/**
* Authentication
* @param {object} req - http request object
* @param {string} apiKey - api key received
* @param {function} done - callback
*/
@ -41,7 +40,7 @@ class LocalApiKeyStrategyConfigurator {
const _adminKey = keys.auth.strategies[LocalApiKeyStrategyConfigurator.NAME].adminKey
const _apiKeys = keys.auth.strategies[LocalApiKeyStrategyConfigurator.NAME].apiKeys
if (apiKey == _adminKey) {
if (apiKey === _adminKey) {
// Check if received key is a valid api key
Logger.info('Auth : Successful authentication with an admin key')
return done(null, {'profile': authorzMgr.TOKEN_PROFILE_ADMIN})

36
lib/bitcoin/addresses-helper.js

@ -77,7 +77,7 @@ class AddressesHelper {
* @returns {boolean} return true if str is a supported pubkey format, false otherwise
*/
isSupportedPubKey(str) {
return (str.length == 66 && (str.startsWith('02') || str.startsWith('03')))
return (str.length === 66 && (str.startsWith('02') || str.startsWith('03')))
}
/**
@ -97,7 +97,7 @@ class AddressesHelper {
/**
* Get the script hash associated to a Bech32 address
* @param {string} str - bech32 address
* @returns {string} script hash in hex format
* @returns {string | null} script hash in hex format
*/
getScriptHashFromBech32(str) {
try {
@ -114,12 +114,12 @@ class AddressesHelper {
* @returns {boolean} return true if output is a P2PKH script, otherwise return false
*/
isP2pkhScript(scriptpubkey) {
return scriptpubkey.length == 25
&& scriptpubkey[0] == OPS.OP_DUP
&& scriptpubkey[1] == OPS.OP_HASH160
&& scriptpubkey[2] == 0x14
&& scriptpubkey[23] == OPS.OP_EQUALVERIFY
&& scriptpubkey[24] == OPS.OP_CHECKSIG
return scriptpubkey.length === 25
&& scriptpubkey[0] === OPS.OP_DUP
&& scriptpubkey[1] === OPS.OP_HASH160
&& scriptpubkey[2] === 0x14
&& scriptpubkey[23] === OPS.OP_EQUALVERIFY
&& scriptpubkey[24] === OPS.OP_CHECKSIG
}
/**
@ -128,10 +128,10 @@ class AddressesHelper {
* @returns {boolean} return true if output is a P2SH script, otherwise return false
*/
isP2shScript(scriptpubkey) {
return scriptpubkey.length == 23
&& scriptpubkey[0] == OPS.OP_HASH160
&& scriptpubkey[1] == 0x14
&& scriptpubkey[22] == OPS.OP_EQUAL
return scriptpubkey.length === 23
&& scriptpubkey[0] === OPS.OP_HASH160
&& scriptpubkey[1] === 0x14
&& scriptpubkey[22] === OPS.OP_EQUAL
}
/**
@ -140,9 +140,9 @@ class AddressesHelper {
* @returns {boolean} return true if output is a P2WPKH script, otherwise return false
*/
isP2wpkhScript(scriptpubkey) {
return scriptpubkey.length == 22
&& scriptpubkey[0] == OPS.OP_0
&& scriptpubkey[1] == 0x14
return scriptpubkey.length === 22
&& scriptpubkey[0] === OPS.OP_0
&& scriptpubkey[1] === 0x14
}
/**
@ -151,9 +151,9 @@ class AddressesHelper {
* @returns {boolean} return true if output is a P2WSH script, otherwise return false
*/
isP2wshScript(scriptpubkey) {
return scriptpubkey.length == 34
&& scriptpubkey[0] == OPS.OP_0
&& scriptpubkey[1] == 0x20
return scriptpubkey.length === 34
&& scriptpubkey[0] === OPS.OP_0
&& scriptpubkey[1] === 0x20
}
/**

12
lib/bitcoin/addresses-service.js

@ -21,24 +21,24 @@ class AddressesService {
/**
* Rescan the blockchain for an address
* @param {string} address - bitcoin address
* @returns {Promise}
* @returns {Promise<boolean | undefined>}
*/
async rescan(address) {
const hdaccount = await db.getUngroupedHDAccountsByAddresses([address])
// Don't filter addresses associated to an HDAccount
const filterAddr = !(hdaccount.length > 0 && hdaccount[0]['hdID'])
return remote.importAddresses([address], filterAddr)
return await remote.importAddresses([address], filterAddr)
}
/**
* Restore an address in db
* @param {string[]} addresses - array of bitcoin addresses
* @param {boolean} filterAddr - true if addresses should be filter, false otherwise
* @returns {Promise}
* @returns {Promise<boolean | undefined>}
*/
async restoreAddresses(address, filterAddr) {
return remote.importAddresses(address, filterAddr)
async restoreAddresses(addresses, filterAddr) {
return await remote.importAddresses(addresses, filterAddr)
}
}
module.exports = new AddressesService()
module.exports = new AddressesService()

46
lib/bitcoin/hd-accounts-helper.js

@ -81,7 +81,7 @@ class HDAccountsHelper {
* @returns {boolean} returns true if xpub encodes a xpub/tpub, false otherwise
*/
isXpub(xpub) {
return (xpub.indexOf('xpub') == 0) || (xpub.indexOf('tpub') == 0)
return (xpub.indexOf('xpub') === 0) || (xpub.indexOf('tpub') === 0)
}
/**
@ -90,7 +90,7 @@ class HDAccountsHelper {
* @returns {boolean} returns true if xpub encodes a ypub/upub, false otherwise
*/
isYpub(xpub) {
return (xpub.indexOf('ypub') == 0) || (xpub.indexOf('upub') == 0)
return (xpub.indexOf('ypub') === 0) || (xpub.indexOf('upub') === 0)
}
/**
@ -99,7 +99,7 @@ class HDAccountsHelper {
* @returns {boolean} returns true if xpub encodes a zpub/vpub, false otherwise
*/
isZpub(xpub) {
return (xpub.indexOf('zpub') == 0) || (xpub.indexOf('vpub') == 0)
return (xpub.indexOf('zpub') === 0) || (xpub.indexOf('vpub') === 0)
}
/**
@ -114,12 +114,12 @@ class HDAccountsHelper {
const ver = decoded.readInt32BE()
if (
ver != this.MAGIC_XPUB
&& ver != this.MAGIC_TPUB
&& ver != this.MAGIC_YPUB
&& ver != this.MAGIC_UPUB
&& ver != this.MAGIC_ZPUB
&& ver != this.MAGIC_VPUB
ver !== this.MAGIC_XPUB
&& ver !== this.MAGIC_TPUB
&& ver !== this.MAGIC_YPUB
&& ver !== this.MAGIC_UPUB
&& ver !== this.MAGIC_ZPUB
&& ver !== this.MAGIC_VPUB
) {
//Logger.error(null, 'HdAccountsHelper : xlatXPUB() : Incorrect format')
return ''
@ -165,7 +165,7 @@ class HDAccountsHelper {
/**
* Classify the hd account type retrieved from db
* @param {integer} v - HD Account type (db encoding)
* @param {number} v - HD Account type (db encoding)
* @returns {object} object storing the type and lock status of the hd account
*/
classify(v) {
@ -194,9 +194,9 @@ class HDAccountsHelper {
/**
* Encode hd account type and lock status in db format
* @param {integer} type - HD Account type (db encoding)
* @param {number} type - HD Account type (db encoding)
* @param {boolean} locked - lock status of the hd account
* @returns {integer}
* @returns {number}
*/
makeType(type, locked) {
let p =
@ -214,7 +214,7 @@ class HDAccountsHelper {
/**
* Return a string representation of the hd account type
* @param {integer} v - HD Account type (db encoding)
* @param {number} v - HD Account type (db encoding)
* @returns {string}
*/
typeString(v) {
@ -268,7 +268,7 @@ class HDAccountsHelper {
return true
} catch(e) {
if (e == errors.xpub.PRIVKEY) throw e
if (e === errors.xpub.PRIVKEY) throw e
return false
}
}
@ -287,12 +287,12 @@ class HDAccountsHelper {
/**
* Derives an address for an hd account
* @param {int} chain - chain to be derived
* @param {number} chain - chain to be derived
* must have a value on [0,1] for BIP44/BIP49/BIP84 derivation
* @param {bip32} chainNode - Parent bip32 used for derivation
* @param {int} index - index to be derived
* @param {int} type - type of derivation
* @returns {Promise - object} returns an object {address: '...', chain: <int>, index: <int>}
* @param {number} index - index to be derived
* @param {number} type - type of derivation
* @returns {Promise<object>} returns an object {address: '...', chain: <int>, index: <int>}
*/
async deriveAddress(chain, chainNode, index, type) {
// Derive M/chain/index
@ -321,11 +321,11 @@ class HDAccountsHelper {
/**
* Derives addresses for an hd account
* @param {string} xpub - hd account to be derived
* @param {int} chain - chain to be derived
* @param {number} chain - chain to be derived
* must have a value on [0,1] for BIP44/BIP49/BIP84 derivation
* @param {int[]} indices - array of indices to be derived
* @param {int} type - type of derivation
* @returns {Promise - object[]} array of {address: '...', chain: <int>, index: <int>}
* @param {number[]} indices - array of indices to be derived
* @param {number} type - type of derivation
* @returns {Promise<object[]>} array of {address: '...', chain: <int>, index: <int>}
*/
async deriveAddresses(xpub, chain, indices, type) {
const ret = []
@ -374,7 +374,7 @@ class HDAccountsHelper {
const msg = await this.derivationPool.exec('deriveAddresses', [data])
if (msg.status = 'ok') {
if (msg.status === 'ok') {
resolve(msg.addresses)
} else {
Logger.error(null, 'HdAccountsHelper : A problem was met during parallel addresses derivation')

32
lib/bitcoin/hd-accounts-service.js

@ -29,7 +29,7 @@ class HDAccountsService {
/**
* Create a new hd account in db
* @param {string} xpub - xpub
* @param {int} scheme - derivation scheme
* @param {number} scheme - derivation scheme
* @returns {Promise} returns true if success, false otherwise
*/
async createHdAccount(xpub, scheme) {
@ -37,8 +37,8 @@ class HDAccountsService {
await this.newHdAccount(xpub, scheme)
return true
} catch(e) {
const isInvalidXpub = (e == errors.xpub.INVALID || e == errors.xpub.PRIVKEY)
const isLockedXpub = (e == errors.xpub.LOCKED)
const isInvalidXpub = (e === errors.xpub.INVALID || e === errors.xpub.PRIVKEY)
const isLockedXpub = (e === errors.xpub.LOCKED)
const err = (isInvalidXpub || isLockedXpub) ? e : errors.xpub.CREATE
Logger.error(e, 'HdAccountsService : createHdAccount()' + err)
return Promise.reject(err)
@ -49,7 +49,7 @@ class HDAccountsService {
/**
* Restore a hd account in db
* @param {string} xpub - xpub
* @param {int} scheme - derivation scheme
* @param {number} scheme - derivation scheme
* @param {bool} forceOverride - force override of scheme even if hd account is locked
* @returns {Promise}
*/
@ -96,7 +96,7 @@ class HDAccountsService {
return hdaHelper.typeString(type)
} catch(e) {
const err = (e == errors.db.ERROR_NO_HD_ACCOUNT) ? errors.get.UNKNXPUB : errors.generic.DB
const err = (e === errors.db.ERROR_NO_HD_ACCOUNT) ? errors.get.UNKNXPUB : errors.generic.DB
return Promise.reject(err)
}
}
@ -110,7 +110,7 @@ class HDAccountsService {
try {
await db.deleteHDAccount(xpub)
} catch(e) {
const err = (e == errors.db.ERROR_NO_HD_ACCOUNT) ? errors.get.UNKNXPUB : errors.generic.DB
const err = (e === errors.db.ERROR_NO_HD_ACCOUNT) ? errors.get.UNKNXPUB : errors.generic.DB
return Promise.reject(err)
}
}
@ -134,11 +134,11 @@ class HDAccountsService {
let segwit = ''
if (scheme == hdaHelper.BIP49)
if (scheme === hdaHelper.BIP49)
segwit = ' SegWit (BIP49)'
else if (scheme == hdaHelper.BIP84)
else if (scheme === hdaHelper.BIP84)
segwit = ' SegWit (BIP84)'
Logger.info(`HdAccountsService : Created HD Account: ${xpub}${segwit}`)
const externalPrm = hdaHelper.deriveAddresses(xpub, 0, _.range(gap.external), scheme)
@ -152,8 +152,8 @@ class HDAccountsService {
/**
* Rescan the blockchain for a hd account
* @param {string} xpub - xpub
* @param {integer} gapLimit - (optional) gap limit for derivation
* @param {integer} startIndex - (optional) rescan shall start from this index
* @param {number} gapLimit - (optional) gap limit for derivation
* @param {number} startIndex - (optional) rescan shall start from this index
* @returns {Promise}
*/
async rescan(xpub, gapLimit, startIndex) {
@ -165,7 +165,7 @@ class HDAccountsService {
await remote.importHDAccount(xpub, account.hdType, gapLimit, startIndex)
} catch(e) {
return Promise.reject(e)
}
}
}
/**
@ -201,7 +201,7 @@ class HDAccountsService {
const info = hdaHelper.classify(account.hdType)
// If this account is already known in the database,
// check for a derivation scheme mismatch
if (info.type != scheme) {
if (info.type !== scheme) {
if (info.locked && !forceOverride) {
Logger.info(`HdAccountsService : Attempted override on locked account: ${xpub}`)
return Promise.reject(errors.xpub.LOCKED)
@ -224,7 +224,7 @@ class HDAccountsService {
* @param {string} address - address used to sign the message
* @param {string} sig - signature of the message
* @param {string} msg - signed message
* @param {integer} scheme - derivation scheme to be used for the xpub
* @param {number} scheme - derivation scheme to be used for the xpub
* @returns {Promise} returns the xpub if signature is valid, otherwise returns an error
*/
async verifyXpubSignature(xpub, address, sig, msg, scheme) {
@ -242,12 +242,12 @@ class HDAccountsService {
if (!addrHelper.verifySignature(msg, sigAddress, sig))
return Promise.reject(errors.sig.INVSIG)
// Check that adresses match
if (address != expectedAddress)
if (address !== expectedAddress)
return Promise.reject(errors.sig.INVADDR)
// Return the corresponding xpub
return xpub
} catch(err) {
const ret = (err == errors.db.ERROR_NO_HD_ACCOUNT) ? errors.get.UNKNXPUB : errors.generic.DB
const ret = (err === errors.db.ERROR_NO_HD_ACCOUNT) ? errors.get.UNKNXPUB : errors.generic.DB
return Promise.reject(ret)
}
}

10
lib/bitcoin/parallel-address-derivation.js

@ -20,12 +20,12 @@ const BIP84 = 2
/**
* Derives an address for an hd account
* @param {int} chain - chain to be derived
* @param {number} chain - chain to be derived
* must have a value on [0,1] for BIP44/BIP49/BIP84 derivation
* @param {bip32} chainNode - Parent bip32 used for derivation
* @param {int} index - index to be derived
* @param {int} type - type of derivation
* @returns {Promise - object} returns an object {address: '...', chain: <int>, index: <int>}
* @param {number} index - index to be derived
* @param {number} type - type of derivation
* @returns {Promise<object>} returns an object {address: '...', chain: <int>, index: <int>}
*/
async function deriveAddress(chain, chainNode, index, type) {
// Derive M/chain/index
@ -54,7 +54,7 @@ async function deriveAddress(chain, chainNode, index, type) {
/**
* Derives a set of addresses for an hd account
* @param {object} msg - parameters used for the derivation
* @returns {Promise - object[]}
* @returns {Promise<object[]>}
*/
async function deriveAddresses(msg) {
try {

4
lib/bitcoind-rpc/fees.js

@ -34,7 +34,7 @@ class Fees {
/**
* Refresh and return the current fees
* @returns {Promise}
* @returns {Promise<object>}
*/
async getFees() {
try {
@ -50,7 +50,7 @@ class Fees {
/**
* Refresh the current fees
* @returns {Promise}
* @returns {Promise<void>}
*/
async refresh() {
await util.parallelCall(this.targets, async tgt => {

2
lib/bitcoind-rpc/rpc-client.js

@ -30,7 +30,7 @@ const createRpcClient = () => {
* @returns {boolean} returns true if message related to a connection error
*/
const isConnectionError = (err) => {
if (typeof err != 'string')
if (typeof err !== 'string')
return false
const isTimeoutError = (err.indexOf('connect ETIMEDOUT') !== -1)

12
lib/bitcoind-rpc/transactions.js

@ -41,7 +41,7 @@ class Transactions {
* Get the transactions for a given array of txids
* @param {string[]} txids - txids of the transaction to be retrieved
* @param {boolean} fees - true if fees must be computed, false otherwise
* @returns {Promise} return an array of transactions (object[])
* @returns {Promise<object[]>} return an array of transactions (object[])
*/
async getTransactions(txids, fees) {
try {
@ -76,7 +76,7 @@ class Transactions {
* Get the transaction for a given txid
* @param {string} txid - txid of the transaction to be retrieved
* @param {boolean} fees - true if fees must be computed, false otherwise
* @returns {Promise}
* @returns {Promise<object[]>}
*/
async getTransaction(txid, fees) {
try {
@ -92,7 +92,7 @@ class Transactions {
* Formats a transaction object returned by the RPC API
* @param {object} tx - transaction
* @param {boolean} fees - true if fees must be computed, false otherwise
* @returns {Promise} return an array of inputs (object[])
* @returns {Promise<object[]>} return an array of inputs (object[])
*/
async _prepareTxResult(tx, fees) {
const ret = {
@ -148,7 +148,7 @@ class Transactions {
* Extract information about the inputs of a transaction
* @param {object} tx - transaction
* @param {boolean} fees - true if fees must be computed, false otherwise
* @returns {Promise} return an array of inputs (object[])
* @returns {Promise<object[]>} return an array of inputs (object[])
*/
async _getInputs(tx, fees) {
const inputs = []
@ -202,7 +202,7 @@ class Transactions {
/**
* Extract information about the outputs of a transaction
* @param {object} tx - transaction
* @returns {Promise} return an array of outputs (object[])
* @returns {Promise<object[]>} return an array of outputs (object[])
*/
async _getOutputs(tx) {
const outputs = []
@ -220,7 +220,7 @@ class Transactions {
}
if (pk.addresses) {
if (pk.addresses.length == 1)
if (pk.addresses.length === 1)
o.address = pk.addresses[0]
else
o.addresses = pk.addresses

159
lib/db/mysql-db-wrapper.js

@ -11,8 +11,8 @@ const errors = require('../errors')
const hdaHelper = require('../bitcoin/hd-accounts-helper')
const network = require('../bitcoin/network')
const keys = require('../../keys/')[network.key]
const debug = !!(process.argv.indexOf('db-debug') > -1)
const queryDebug = !!(process.argv.indexOf('dbquery-debug') > -1)
const debug = process.argv.indexOf('db-debug') > -1
const queryDebug = process.argv.indexOf('dbquery-debug') > -1
/**
@ -387,9 +387,9 @@ class MySqlDbWrapper {
this.pool.query(query, null, async (err, result, fields) => {
if (err) {
// Retry the request on lock errors
if ((err.code == 'ER_LOCK_DEADLOCK' ||
err.code == 'ER_LOCK_TIMEOUT' ||
err.code == 'ER_LOCK_WAIT_TIMEOUT') && (retries > 0)
if ((err.code === 'ER_LOCK_DEADLOCK' ||
err.code === 'ER_LOCK_TIMEOUT' ||
err.code === 'ER_LOCK_WAIT_TIMEOUT') && (retries > 0)
) {
try {
this.queryError('Lock detected. Retry request in a few ms', query)
@ -426,7 +426,7 @@ class MySqlDbWrapper {
/**
* Get the ID of an address
* @param {string} address - bitcoin address
* @returns {integer} returns the address id
* @returns {number} returns the address id
*/
async getAddressId(address) {
const sqlQuery = 'SELECT `addrID` FROM `addresses` WHERE `addrAddress` = ?'
@ -443,7 +443,7 @@ class MySqlDbWrapper {
/**
* Get the ID of an Address. Ensures that the address exists.
* @param {string} address - bitcoin address
* @returns {integer} returns the address id
* @returns {number} returns the address id
*/
async ensureAddressId(address) {
const sqlQuery = 'SELECT `addrID` FROM `addresses` WHERE `addrAddress` = ?'
@ -469,7 +469,7 @@ class MySqlDbWrapper {
async getAddressesIds(addresses) {
const ret = {}
if (addresses.length == 0)
if (addresses.length === 0)
return ret
const sqlQuery = 'SELECT * FROM `addresses` WHERE `addrAddress` IN (?)'
@ -488,7 +488,7 @@ class MySqlDbWrapper {
* @param {string[]} addresses - array of bitcoin addresses
*/
async addAddresses(addresses) {
if (addresses.length == 0)
if (addresses.length === 0)
return []
const sqlQuery = 'INSERT IGNORE INTO `addresses` (addrAddress) VALUES ?'
@ -502,7 +502,7 @@ class MySqlDbWrapper {
* @param {string[]} addresses - array of bitcoin addresses
*/
async getAddresses(addresses) {
if (addresses.length == 0)
if (addresses.length === 0)
return []
const sqlQuery = 'SELECT * FROM `addresses` WHERE `addrAddress` IN (?)'
@ -514,7 +514,7 @@ class MySqlDbWrapper {
/**
* Get address balance.
* @param {string} address - bitcoin address
* @returns {integer} returns the balance of the address
* @returns {number} returns the balance of the address
*/
async getAddressBalance(address) {
if (address == null)
@ -532,7 +532,7 @@ class MySqlDbWrapper {
const query = mysql.format(sqlQuery, params)
const results = await this._query(query)
if (results.length == 1) {
if (results.length === 1) {
const balance = results[0].balance
return (balance == null) ? 0 : balance
}
@ -543,7 +543,7 @@ class MySqlDbWrapper {
/**
* Get the number of transactions for an address.
* @param {string} address - bitcoin address
* @returns {integer} returns the number of transactions for the address
* @returns {number} returns the number of transactions for the address
*/
async getAddressNbTransactions(address) {
if(address == null)
@ -571,7 +571,7 @@ class MySqlDbWrapper {
const query = mysql.format(sqlQuery, params)
const results = await this._query(query)
if (results.length == 1) {
if (results.length === 1) {
const nbTxs = results[0].nbTxs
return (nbTxs == null) ? 0 : nbTxs
}
@ -582,7 +582,7 @@ class MySqlDbWrapper {
/**
* Get an HD account.
* @param {string} xpub - xpub
* @returns {integer} returns {hdID, hdXpub, hdCreated, hdType}
* @returns {number} returns {hdID, hdXpub, hdCreated, hdType}
* throws if no record of xpub
*/
async getHDAccount(xpub) {
@ -600,7 +600,7 @@ class MySqlDbWrapper {
/**
* Get the ID of an HD account
* @param {string} xpub - xpub
* @returns {integer} returns the id of the hd account
* @returns {number} returns the id of the hd account
*/
async getHDAccountId(xpub) {
const sqlQuery = 'SELECT `hdID` FROM `hd` WHERE `hdXpub` = ?'
@ -618,7 +618,7 @@ class MySqlDbWrapper {
* Get the ID of an HD account. Ensures that the account exists.
* @param {string} xpub - xpub
* @param {string} type - hd account type
* @returns {integer} returns the id of the hd account
* @returns {number} returns the id of the hd account
*/
async ensureHDAccountId(xpub, type) {
const info = hdaHelper.classify(type)
@ -650,15 +650,14 @@ class MySqlDbWrapper {
/**
* Lock the type of a hd account
* @param {string} xpub - xpub
* @param {boolean} locked - true for locking, false for unlocking
* @returns {boolean} locked - true for locking, false for unlocking
*/
async setLockHDAccountType(xpub, locked) {
locked = !!locked
const account = await this.getHDAccount(xpub)
const info = hdaHelper.classify(account.hdType)
if (info.locked == locked)
if (info.locked === locked)
return true
const hdType = hdaHelper.makeType(account.hdType, locked)
@ -700,7 +699,7 @@ class MySqlDbWrapper {
* Add an address a hd account
* @param {string} address - bitcoin address
* @param {string} xpub - xpub
* @param {integer} chain - derivation chain
* @param {number} chain - derivation chain
* @param {index} index - derivation index for the address
*/
async addAddressToHDAccount(address, xpub, chain, index) {
@ -733,7 +732,7 @@ class MySqlDbWrapper {
* which is the output of the HDAccountsHelper.deriveAddresses()
*/
async addAddressesToHDAccount(xpub, addressData) {
if (addressData.length == 0)
if (addressData.length === 0)
return
const addresses = addressData.map(d => d.address)
@ -769,7 +768,7 @@ class MySqlDbWrapper {
* @returns {object[]}
*/
async getUngroupedHDAccountsByAddresses(addresses) {
if (addresses.length == 0) return {}
if (addresses.length === 0) return {}
const sqlQuery = 'SELECT \
`hd`.`hdID`, \
@ -814,7 +813,7 @@ class MySqlDbWrapper {
loose: []
}
if (addresses.length == 0)
if (addresses.length === 0)
return ret
const sqlQuery = 'SELECT \
@ -865,7 +864,7 @@ class MySqlDbWrapper {
/**
* Get an HD account balance
* @param {string} xpub - xpub
* @returns {integer} returns the balance of the hd account
* @returns {number} returns the balance of the hd account
*/
async getHDAccountBalance(xpub) {
const sqlQuery = 'SELECT \
@ -882,7 +881,7 @@ class MySqlDbWrapper {
const query = mysql.format(sqlQuery, params)
const results = await this._query(query)
if (results.length == 1)
if (results.length === 1)
return (results[0].balance == null) ? 0 : results[0].balance
return null
@ -891,7 +890,7 @@ class MySqlDbWrapper {
/**
* Get next unused address indices for each HD chain of an account
* @param {string} xpub - xpub
* @returns {integer[]} returns an array of unused indices
* @returns {number[]} returns an array of unused indices
* [M/0/X, M/1/Y] -> [X,Y]
*/
async getHDAccountNextUnusedIndices(xpub) {
@ -921,7 +920,7 @@ class MySqlDbWrapper {
/**
* Get the maximum derived address index for each HD chain of an account
* @param {string} xpub - xpub
* @returns {integer[]} returns an array of derived indices
* @returns {number[]} returns an array of derived indices
* [M/0/X, M/1/Y] -> [X,Y]
*/
async getHDAccountDerivedIndices(xpub) {
@ -950,10 +949,10 @@ class MySqlDbWrapper {
/**
* Get the number of indices derived in an interval for a HD chain
* @param {string} xpub - xpub
* @param {integer} chain - HD chain (0 or 1)
* @param {integer} minIdx - min index of derivation
* @param {integer} maxIdx - max index of derivation
* @returns {integer[]} returns an array of number of derived indices
* @param {number} chain - HD chain (0 or 1)
* @param {number} minIdx - min index of derivation
* @param {number} maxIdx - max index of derivation
* @returns {number[]} returns an array of number of derived indices
*/
async getHDAccountNbDerivedIndices(xpub, chain, minIdx, maxIdx) {
const sqlQuery = 'SELECT \
@ -969,7 +968,7 @@ class MySqlDbWrapper {
const query = mysql.format(sqlQuery, params)
const results = await this._query(query)
if (results.length == 1) {
if (results.length === 1) {
const nbDerivedIndices = results[0].nbDerivedIndices
return (nbDerivedIndices == null) ? 0 : nbDerivedIndices
}
@ -980,7 +979,7 @@ class MySqlDbWrapper {
/**
* Get the number of transactions for an HD account
* @param {string} xpub - xpub
* @returns {integer} returns the balance of the hd account
* @returns {number} returns the balance of the hd account
*/
async getHDAccountNbTransactions(xpub) {
const sqlQuery = 'SELECT COUNT(DISTINCT `r`.`txnTxid`) AS nbTxs \
@ -1007,7 +1006,7 @@ class MySqlDbWrapper {
const query = mysql.format(sqlQuery, params)
const results = await this._query(query)
if (results.length == 1)
if (results.length === 1)
return (results[0].nbTxs == null) ? 0 : results[0].nbTxs
return null
@ -1017,12 +1016,12 @@ class MySqlDbWrapper {
* Get the number of transactions for a list of addresses and HD accounts
* @param {string[]} addresses - array of bitcoin addresses
* @param {string[]} xpubs - array of xpubs
* @returns {int} returns the number of transactions
* @returns {number} returns the number of transactions
*/
async getAddrAndXpubsNbTransactions(addresses, xpubs) {
if (
(!addresses || addresses.length == 0)
&& (!xpubs || xpubs.length == 0)
(!addresses || addresses.length === 0)
&& (!xpubs || xpubs.length === 0)
) {
return []
}
@ -1052,7 +1051,7 @@ class MySqlDbWrapper {
let query = mysql.format(sqlQuery)
const results = await this._query(query)
if (results.length == 1)
if (results.length === 1)
return (results[0].nbTxs == null) ? 0 : results[0].nbTxs
return null
@ -1062,12 +1061,14 @@ class MySqlDbWrapper {
* Get the transactions for a list of addresses and HD accounts
* @param {string[]} addresses - array of bitcoin addresses
* @param {string[]} xpubs - array of xpubs
* @param {number=} page - page
* @param {number=} nbTxsPerPage - number of transactions per page
* @returns {object[]} returns an array of transactions
*/
async getTxsByAddrAndXpubs(addresses, xpubs, page, nbTxsPerPage) {
if (
(!addresses || addresses.length == 0)
&& (!xpubs || xpubs.length == 0)
(!addresses || addresses.length === 0)
&& (!xpubs || xpubs.length === 0)
) {
return []
}
@ -1117,7 +1118,7 @@ class MySqlDbWrapper {
const txsIds = txs.map(t => t.txnID)
if (txsIds.length == 0)
if (txsIds.length === 0)
return []
// Prepares subqueries for
@ -1189,7 +1190,7 @@ class MySqlDbWrapper {
}
}
if (input.hdXpub && input.hdXpub !== null) {
if (input.hdXpub) {
ret.prev_out.xpub = {
m: input.hdXpub,
path: ['M', input.hdAddrChain, input.hdAddrIndex].join('/')
@ -1211,7 +1212,7 @@ class MySqlDbWrapper {
addr: output.outAddress
}
if (output.hdXpub && output.hdXpub !== null) {
if (output.hdXpub) {
ret.xpub = {
m: output.hdXpub,
path: ['M', output.hdAddrChain, output.hdAddrIndex].join('/')
@ -1294,7 +1295,7 @@ class MySqlDbWrapper {
async getXpubByAddresses(addresses) {
const ret = {}
if (addresses.length == 0)
if (addresses.length === 0)
return ret
const sqlQuery = 'SELECT `hd`.`hdXpub`, `addresses`.`addrAddress` \
@ -1316,7 +1317,7 @@ class MySqlDbWrapper {
/**
* Get the mysql ID of a transaction. Ensures that the transaction exists.
* @param {string} txid - txid of a transaction
* @returns {integer} returns the transaction id (mysql id)
* @returns {number} returns the transaction id (mysql id)
*/
async ensureTransactionId(txid) {
const sqlQuery = 'INSERT IGNORE INTO `transactions` SET ?'
@ -1346,14 +1347,14 @@ class MySqlDbWrapper {
/**
* Get the mysql ID of a transaction
* @param {string} txid - txid of a transaction
* @returns {integer} returns the transaction id (mysql id)
* @returns {number} returns the transaction id (mysql id)
*/
async getTransactionId(txid) {
const sqlQuery = 'SELECT `txnID` FROM `transactions` WHERE `txnTxid` = ?'
const params = txid
const query = mysql.format(sqlQuery, params)
const result = await this._query(query)
return (result.length == 0) ? null : result[0].txnID
return (result.length === 0) ? null : result[0].txnID
}
/**
@ -1362,7 +1363,7 @@ class MySqlDbWrapper {
* @returns {object[]} returns an array of {txnTxid: txnId}
*/
async getTransactionsIds(txids) {
if (txids.length == 0)
if (txids.length === 0)
return []
const sqlQuery = 'SELECT `txnID`, `txnTxid` FROM `transactions` WHERE `txnTxid` IN (?)'
@ -1378,11 +1379,11 @@ class MySqlDbWrapper {
/**
* Get the mysql IDs of a set of transactions
* @param {string[]} txid - array of transactions txids
* @returns {integer[]} returns an array of transaction ids (mysql ids)
* @param {string[]} txnIDs - array of transactions txids
* @returns {number[]} returns an array of transaction ids (mysql ids)
*/
async getTransactionsById(txnIDs) {
if (txnIDs.length == 0)
if (txnIDs.length === 0)
return []
const sqlQuery = 'SELECT * FROM `transactions` WHERE `txnID` IN (?)'
@ -1419,7 +1420,7 @@ class MySqlDbWrapper {
* @param {object[]} txs - array of {txid, version, locktime}
*/
async addTransactions(txs) {
if (txs.length == 0)
if (txs.length === 0)
return
const sqlQuery = 'INSERT INTO `transactions` \
@ -1567,10 +1568,10 @@ class MySqlDbWrapper {
/**
* Batch confirm txids in a block
* @param {string[]} txnTxidArray - array of transaction txids
* @param {integer} blockID - mysql id of the blck
* @param {number} blockID - mysql id of the blck
*/
async confirmTransactions(txnTxidArray, blockID) {
if (txnTxidArray.length == 0)
if (txnTxidArray.length === 0)
return
const sqlQuery = 'UPDATE `transactions` SET `blockID` = ? WHERE `txnTxid` IN (?)'
@ -1581,8 +1582,8 @@ class MySqlDbWrapper {
/**
* Get the transactions confirmed after a given height
* @param {integer]} height - block height
* @param {object[]} returns an array of transactions
* @param {number} height - block height
* @returns {object[]} returns an array of transactions
*/
async getTransactionsConfirmedAfterHeight(height) {
const sqlQuery = 'SELECT `transactions`.* FROM `transactions` \
@ -1595,7 +1596,7 @@ class MySqlDbWrapper {
/**
* Delete the transactions confirmed after a given height
* @param {integer]} height - block height
* @param {number} height - block height
*/
async deleteTransactionsConfirmedAfterHeight(height) {
const sqlQuery = 'DELETE `transactions`.* FROM `transactions` \
@ -1611,7 +1612,7 @@ class MySqlDbWrapper {
* @param {string[]} txnTxidArray - array of transaction txids
*/
async unconfirmTransactions(txnTxidArray) {
if (txnTxidArray.length == 0)
if (txnTxidArray.length === 0)
return
const sqlQuery = 'UPDATE `transactions` SET `blockID` = NULL WHERE `txnTxid` IN (?)'
@ -1633,10 +1634,10 @@ class MySqlDbWrapper {
/**
* Delete a set of transactions identified by their mysql ids
* @param {integer[]} txnIDs - mysql ids of the transactions
* @param {number[]} txnIDs - mysql ids of the transactions
*/
async deleteTransactionsByID(txnIDs) {
if (txnIDs.length == 0)
if (txnIDs.length === 0)
return []
const sqlQuery = 'DELETE `transactions`.* FROM `transactions` WHERE `transactions`.`txnID` in (?)'
@ -1650,7 +1651,7 @@ class MySqlDbWrapper {
* @param {object[]} outputs - array of {txnID, addrID, outIndex, outAmount, outScript}
*/
async addOutputs(outputs) {
if (outputs.length == 0)
if (outputs.length === 0)
return
const sqlQuery = 'INSERT IGNORE INTO `outputs` \
@ -1671,7 +1672,7 @@ class MySqlDbWrapper {
* {addrAddress, outID, outAmount, txnTxid, outIndex, spendingTxnID/null, spendingInID/null}
*/
async getOutputSpends(spends) {
if (spends.length == 0)
if (spends.length === 0)
return []
const whereClauses =
@ -1703,7 +1704,7 @@ class MySqlDbWrapper {
* {outID, txnTxid, outIndex}
*/
async getOutputIds(spends) {
if (spends.length == 0)
if (spends.length === 0)
return []
const whereClauses =
@ -1730,7 +1731,7 @@ class MySqlDbWrapper {
* {txnTxid, outIndex, outAmount, outScript, addrAddress}
*/
async getUnspentOutputs(addresses) {
if (addresses.length == 0)
if (addresses.length === 0)
return []
const sqlQuery = 'SELECT \
@ -1761,7 +1762,7 @@ class MySqlDbWrapper {
* {txnID, outID, inIndex, inSequence}
*/
async addInputs(inputs) {
if (inputs.length == 0)
if (inputs.length === 0)
return
const sqlQuery = 'INSERT INTO `inputs` \
@ -1811,7 +1812,7 @@ class MySqlDbWrapper {
const params = hash
const query = mysql.format(sqlQuery, params)
const result = await this._query(query)
return (result.length == 1) ? result[0] : null
return (result.length === 1) ? result[0] : null
}
/**
@ -1820,7 +1821,7 @@ class MySqlDbWrapper {
* @returns {object[]} returns the blocks
*/
async getBlocksByHashes(hashes) {
if (hashes.length == 0)
if (hashes.length === 0)
return []
const sqlQuery = 'SELECT * FROM `blocks` WHERE `blockHash` IN (?)'
@ -1831,7 +1832,7 @@ class MySqlDbWrapper {
/**
* Get details about all blocks at a given block height
* @param {integer} height - block height
* @param {number} height - block height
* @returns {object[]} returns an array of blocks
*/
async getBlocksByHeight(height) {
@ -1843,7 +1844,7 @@ class MySqlDbWrapper {
/**
* Delete the blocks after a given block height
* @param {integer} height - block height
* @param {number} height - block height
*/
async deleteBlocksAfterHeight(height) {
const sqlQuery = 'DELETE FROM `blocks` WHERE `blockHeight` > ?'
@ -1854,12 +1855,12 @@ class MySqlDbWrapper {
/**
* Gets the last block
* @returns {object} returns the last block
* @returns {object | null} returns the last block
*/
async getHighestBlock() {
try {
const results = await this.getLastBlocks(1)
if (results == null || results.length == 0)
if (results == null || results.length === 0)
return {
blockID: null,
blockHeight: 0
@ -1873,7 +1874,7 @@ class MySqlDbWrapper {
/**
* Gets the N last blocks
* @param {integer} n - number of blocks to be retrieved
* @param {number} n - number of blocks to be retrieved
* @returns {object[]} returns an array of the n last blocks
*/
async getLastBlocks(n) {
@ -1896,14 +1897,14 @@ class MySqlDbWrapper {
/**
* Get the mysql ID of a scheduled transaction
* @param {string} txid - txid of a scheduled transaction
* @returns {integer} returns the scheduled transaction id (mysql id)
* @returns {number} returns the scheduled transaction id (mysql id)
*/
async getScheduledTransactionId(txid) {
const sqlQuery = 'SELECT `schID` FROM `scheduled_transactions` WHERE `schTxid` = ?'
const params = txid
const query = mysql.format(sqlQuery, params)
const result = await this._query(query)
return (result.length == 0) ? null : result[0].txnID
return (result.length === 0) ? null : result[0].txnID
}
/**
@ -1952,7 +1953,7 @@ class MySqlDbWrapper {
/**
* Get scheduled transactions
* with a trigger lower than a given block height
* @param {integer} height - block height
* @param {number} height - block height
*/
async getActivatedScheduledTransactions(height) {
const sqlQuery = 'SELECT * FROM `scheduled_transactions` \
@ -1964,7 +1965,7 @@ class MySqlDbWrapper {
/**
* Get the scheduled transaction having a given parentID
* @param {integer} parentId - parent ID
* @param {number} parentId - parent ID
* @returns {object[]} returns an array of scheduled transactions
*/
async getNextScheduledTransactions(parentId) {
@ -1978,8 +1979,8 @@ class MySqlDbWrapper {
/**
* Update the trigger of a scheduled transaction
* identified by its ID
* @param {integer} id - id of the scheduled transaction
* @param {integer} trigger - new trigger
* @param {number} id - id of the scheduled transaction
* @param {number} trigger - new trigger
*/
async updateTriggerScheduledTransaction(id, trigger) {
const sqlQuery = 'UPDATE `scheduled_transactions` \

3
lib/http-server/http-server.js

@ -19,7 +19,7 @@ class HttpServer {
/**
* Constructor
* @param {int} port - port used by the http server
* @param {number} port - port used by the http server
* @param {string} host - host exposing the http server
*/
constructor(port, host) {
@ -95,6 +95,7 @@ class HttpServer {
/**
* Return a http response without status
* @param {object} res - http response object
* @param {object} data
*/
static sendOkDataOnly(res, data) {
res.status(200).json(data)

11
lib/indexer-rpc/rpc-client.js

@ -63,11 +63,11 @@ class RpcClient {
* @returns {boolean} returns true if message related to a connection error
*/
static isConnectionError(err) {
if (typeof err != 'string')
if (typeof err !== 'string')
return false
const isTimeoutError = (err.indexOf('connect ETIMEDOUT') != -1)
const isConnRejected = (err.indexOf('Connection Rejected') != -1)
const isTimeoutError = (err.indexOf('connect ETIMEDOUT') !== -1)
const isConnRejected = (err.indexOf('Connection Rejected') !== -1)
return (isTimeoutError || isConnRejected)
}
@ -122,6 +122,7 @@ class RpcClient {
/**
* Send requests (internal method)
* @param {Object[]} data - array of objects {method: ..., params: ...}
* @param {boolean=} batched - batch requests
* @returns {Promise}
*/
async _call(data, batched) {
@ -174,7 +175,7 @@ class RpcClient {
for (let c of chunk) {
response += c
// Detect the end of a response
if (c == '\n') {
if (c === '\n') {
try {
// Parse the response
let parsed = JSON.parse(response)
@ -190,7 +191,7 @@ class RpcClient {
response = ''
// If all responses have been received
// close the connection
if (responses.length == data.length)
if (responses.length === data.length)
conn.end()
} catch (err) {
reject(

4
lib/remote-importer/esplora-wrapper.js

@ -20,6 +20,8 @@ class EsploraWrapper extends Wrapper {
/**
* Constructor
* @constructor
* @param {string} url
*/
constructor(url) {
super(url, keys.indexer.socks5Proxy)
@ -87,7 +89,7 @@ class EsploraWrapper extends Wrapper {
while (true) {
const txids = await this._getTxsForAddress(address, lastSeenTxid)
if (txids.length == 0)
if (txids.length === 0)
// we have all the transactions
return ret

2
lib/remote-importer/local-indexer-wrapper.js

@ -104,7 +104,7 @@ class LocalIndexerWrapper extends Wrapper {
})
// Send the requests
const results = (keys.indexer.localIndexer.batchRequests == 'active')
const results = (keys.indexer.localIndexer.batchRequests === 'active')
? await this.client.sendBatch(commands)
: await this.client.sendRequests(commands)

2
lib/remote-importer/local-rest-indexer-wrapper.js

@ -22,6 +22,8 @@ class LocalRestIndexerWrapper extends Wrapper {
/**
* Constructor
* @constructor
* @param {string} url
*/
constructor(url) {
super(url, null)

4
lib/remote-importer/oxt-wrapper.js

@ -18,6 +18,8 @@ class OxtWrapper extends Wrapper {
/**
* Constructor
* @constructor
* @param {string} url
*/
constructor(url) {
super(url, keys.indexer.socks5Proxy)
@ -123,7 +125,7 @@ class OxtWrapper extends Wrapper {
async getChainTipHeight() {
let chainTipHeight = null
const result = await this._get(`/lastblock`)
if (result != null && result['data'].length == 1)
if (result != null && result['data'].length === 1)
chainTipHeight = parseInt(result['data'][0]['height'])
return {'chainTipHeight': chainTipHeight}
}

14
lib/remote-importer/remote-importer.js

@ -17,7 +17,7 @@ const gap = keys.gap
let Sources
if (network.key == 'bitcoin') {
if (network.key === 'bitcoin') {
Sources = require('./sources-mainnet')
} else {
Sources = require('./sources-testnet')
@ -64,8 +64,8 @@ class RemoteImporter {
* Import an HD account from remote sources
* @param {string} xpub - HD Account
* @param {string} type - type of HD Account
* @param {integer} gapLimit - (optional) gap limit for derivation
* @param {integer} startIndex - (optional) rescan shall start from this index
* @param {number} gapLimit - (optional) gap limit for derivation
* @param {number} startIndex - (optional) rescan shall start from this index
*/
async importHDAccount(xpub, type, gapLimit, startIndex) {
if (!hdaHelper.isValid(xpub))
@ -202,7 +202,7 @@ class RemoteImporter {
}
if (gotTransactions) {
const keyStatus = (c == 0) ? 'txs_ext' : 'txs_int'
const keyStatus = (c === 0) ? 'txs_ext' : 'txs_int'
this.importing[xpub][keyStatus] = Object.keys(txids).length
// We must go deeper
const result = await this.xpubScan(xpub, c, d, u, G, type, txids)
@ -236,7 +236,7 @@ class RemoteImporter {
const addresses = candidates.filter(c => !this.importing[c])
this.importing = addresses.reduce((m,a) => (m[a] = true, m), this.importing)
if (addresses.length == 0) return true
if (addresses.length === 0) return true
Logger.info(`Importer : Importing ${addresses.join(',')}`)
@ -318,8 +318,8 @@ class RemoteImporter {
const blocks = await db.getBlocksByHashes(blocksHashes)
return util.parallelCall(blocks, block => {
const filteredTxs = txs.filter(tx => (tx.block && tx.block.hash == block.blockHash))
if (filteredTxs.length == 0) return
const filteredTxs = txs.filter(tx => (tx.block && tx.block.hash === block.blockHash))
if (filteredTxs.length === 0) return
const txids = filteredTxs.map(tx => tx.txid)
return db.confirmTransactions(txids, block.blockID)
})

6
lib/remote-importer/sources-mainnet.js

@ -31,17 +31,17 @@ class SourcesMainnet extends Sources {
* Initialize the external data source
*/
_initSource() {
if (keys.indexer.active == 'local_bitcoind') {
if (keys.indexer.active === 'local_bitcoind') {
// If local bitcoind option is activated
// we'll use the local node as our unique source
this.source = new BitcoindWrapper()
Logger.info('Importer : Activated Bitcoind as the data source for imports')
} else if (keys.indexer.active == 'local_indexer') {
} else if (keys.indexer.active === 'local_indexer') {
// If local indexer option is activated
// we'll use the local indexer as our unique source
this.source = new LocalIndexerWrapper()
Logger.info('Importer : Activated local indexer as the data source for imports')
} else if (keys.indexer.active == 'local_rest_indexer') {
} else if (keys.indexer.active === 'local_rest_indexer') {
// If local rest indexer option is activated
// we'll use the local indexer as our unique source
const uri = `http://${keys.indexer.localIndexer.host}:${keys.indexer.localIndexer.port}`

6
lib/remote-importer/sources-testnet.js

@ -32,17 +32,17 @@ class SourcesTestnet extends Sources {
* Initialize the external data source
*/
_initSource() {
if (keys.indexer.active == 'local_bitcoind') {
if (keys.indexer.active === 'local_bitcoind') {
// If local bitcoind option is activated
// we'll use the local node as our unique source
this.source = new BitcoindWrapper()
Logger.info('Importer : Activated Bitcoind as the data source for imports')
} else if (keys.indexer.active == 'local_indexer') {
} else if (keys.indexer.active === 'local_indexer') {
// If local indexer option is activated
// we'll use the local indexer as our unique source
this.source = new LocalIndexerWrapper()
Logger.info('Importer : Activated local indexer as the data source for imports')
} else if (keys.indexer.active == 'local_rest_indexer') {
} else if (keys.indexer.active === 'local_rest_indexer') {
// If local rest indexer option is activated
// we'll use the local indexer as our unique source
const uri = `http://${keys.indexer.localIndexer.host}:${keys.indexer.localIndexer.port}`

3
lib/remote-importer/wrapper.js

@ -16,6 +16,9 @@ class Wrapper {
/**
* Constructor
* @constructor
* @param {string} url
* @param {string=} socks5Proxy
*/
constructor(url, socks5Proxy) {
this.base = url

118
lib/util.js

@ -5,18 +5,22 @@
'use strict'
/**
* Class providing utility functions as static methods
* @class Util
* @description Class providing utility functions as static methods
*/
class Util {
/**
* Constructor
* @constructor
*/
constructor() {}
/**
* Serialize a series of asynchronous calls to a function
* over a list of objects
* @description Serialize a series of asynchronous calls to a function over a list of objects
* @param {Array<any>} list
* @param {function} fn
* @returns {Promise<Array<any>>}
*/
static async seriesCall(list, fn) {
const results = []
@ -29,8 +33,10 @@ class Util {
}
/**
* Execute parallel asynchronous calls to a function
* over a list of objects
* @description Execute parallel asynchronous calls to a function over a list of objects
* @param {Array<any>} list
* @param {function} fn
* @returns {Promise<Array<any>>}
*/
static parallelCall(list, fn) {
const operations = list.map(item => { return fn(item) })
@ -38,16 +44,21 @@ class Util {
}
/**
* Delay the call to a function
* @description Delay the call to a function
* @param {number} ms
* @returns {Promise<void>}
*/
static delay(ms, v) {
static delay(ms) {
return new Promise(resolve => {
setTimeout(resolve.bind(null, v), ms)
setTimeout(() => resolve(), ms)
})
}
/**
* Splits a list into a list of lists each with maximum length LIMIT
* @description Splits a list into a list of lists each with maximum length LIMIT
* @param {Array<any>} list
* @param {number} limit
* @returns {Array<Array<any>>}
*/
static splitList(list, limit) {
const lists = []
@ -57,7 +68,9 @@ class Util {
}
/**
* Check if a string is a valid hex value
* @description Check if a string is a valid hex value
* @param {string} hash
* @returns {boolean}
*/
static isHashStr(hash) {
const hexRegExp = new RegExp(/^[0-9a-f]*$/, 'i')
@ -65,49 +78,64 @@ class Util {
}
/**
* Check if a string is a well formed 256 bits hash
* @description Check if a string is a well formed 256 bits hash
* @param {string} hash
* @returns {boolean}
*/
static is256Hash(hash) {
return Util.isHashStr(hash) && hash.length == 64
return Util.isHashStr(hash) && hash.length === 64
}
/**
* Sum an array of values
* @description Sum an array of values
* @param {Array<number>} arr
* @returns {number}
*/
static sum(arr) {
return arr.reduce((memo, val) => { return memo + val }, 0)
}
/**
* Mean of an array of values
* @description Mean of an array of values
* @param {Array<number>} arr
* @returns {number}
*/
static mean(arr) {
if (arr.length == 0)
if (arr.length === 0)
return NaN
return sum(arr) / arr.length
}
/**
* Compare 2 values (asc order)
* @description Compare 2 values (asc order)
* @param {number} a
* @param {number} b
* @returns {number}
*/
static cmpAsc(a, b) {
return a - b
}
/**
* Compare 2 values (desc order)
* @description Compare 2 values (desc order)
* @param {number} a
* @param {number} b
* @returns {number}
*/
static cmpDesc(a,b) {
return b - a
}
/**
* Median of an array of values
* @description Median of an array of values
* @param {Array<number>} arr
* @param {boolean=} sorted
* @returns {number}
*/
static median(arr, sorted) {
if (arr.length == 0) return NaN
if (arr.length == 1) return arr[0]
if (arr.length === 0) return NaN
if (arr.length === 1) return arr[0]
if (!sorted)
arr.sort(Util.cmpAsc)
@ -124,7 +152,10 @@ class Util {
}
/**
* Median Absolute Deviation of an array of values
* @description Median Absolute Deviation of an array of values
* @param {Array<number>} arr
* @param {boolean=} sorted
* @returns {number}
*/
static mad(arr, sorted) {
const med = Util.median(arr, sorted)
@ -136,7 +167,10 @@ class Util {
}
/**
* Quartiles of an array of values
* @description Quartiles of an array of values
* @param {Array<number>} arr
* @param {boolean=} sorted
* @returns {Array<number>}
*/
static quartiles(arr, sorted) {
const q = [NaN,NaN,NaN]
@ -156,10 +190,10 @@ class Util {
const mod4 = arr.length % 4
const n = Math.floor(arr.length / 4)
if (mod4 == 1) {
if (mod4 === 1) {
q[0] = (arr[n-1] + 3 * arr[n]) / 4
q[2] = (3 * arr[3*n] + arr[3*n+1]) / 4
} else if (mod4 == 3) {
} else if (mod4 === 3) {
q[0] = (3 * arr[n] + arr[n+1]) / 4
q[2] = (arr[3*n+1] + 3 * arr[3*n+2]) / 4
}
@ -174,7 +208,11 @@ class Util {
}
/**
* Obtain the value of the PCT-th percentile, where PCT on [0,100]
* @description Obtain the value of the PCT-th percentile, where PCT on [0,100]
* @param {Array<number>} arr
* @param {number} pct
* @param {boolean=} sorted
* @returns {number}
*/
static percentile(arr, pct, sorted) {
if (arr.length < 2) return NaN
@ -210,28 +248,35 @@ class Util {
}
/**
* Convert bytes to Mb
* @description Convert bytes to MB
* @param {number} bytes
* @returns {number}
*/
static toMb(bytes) {
return +(bytes / Util.MB).toFixed(0)
}
/**
* Convert a date to a unix timestamp
* @description Convert a date to a unix timestamp
* @returns {number}
*/
static unix() {
return (Date.now() / 1000) | 0
}
/**
* Convert a value to a padded string (10 chars)
* @description Convert a value to a padded string (10 chars)
* @param {number} v
* @returns {string}
*/
static pad10(v) {
return (v < 10) ? `0${v}` : `${v}`
}
/**
* Convert a value to a padded string (100 chars)
* @description Convert a value to a padded string (100 chars)
* @param {number} v
* @returns {string}
*/
static pad100(v) {
if (v < 10) return `00${v}`
@ -240,7 +285,9 @@ class Util {
}
/**
* Convert a value to a padded string (1000 chars)
* @description Convert a value to a padded string (1000 chars)
* @param {number} v
* @returns {string}
*/
static pad1000(v) {
if (v < 10) return `000${v}`
@ -250,7 +297,11 @@ class Util {
}
/**
* Left pad
* @description Left pad
* @param {number} number
* @param {number} places
* @param {string=} fill
* @returns {string}
*/
static leftPad(number, places, fill) {
number = Math.round(number)
@ -271,7 +322,10 @@ class Util {
}
/**
* Display a time period, in seconds, as DDD:HH:MM:SS[.MS]
* @description Display a time period, in seconds, as DDD:HH:MM:SS[.MS]
* @param {number} period
* @param {number} milliseconds
* @returns {string}
*/
static timePeriod(period, milliseconds) {
milliseconds = !!milliseconds

34
lib/wallet/address-info.js

@ -9,13 +9,15 @@ const hdaHelper = require('../bitcoin/hd-accounts-helper')
/**
* A class storing information about the actibity of an address
* @class AddressInfo
* @description A class storing information about the actibity of an address
*/
class AddressInfo {
/**
* Constructor
* @param {object} address - bitcoin address
* @constructor
* @param {string} address - bitcoin address
*/
constructor(address) {
// Initializes properties
@ -25,7 +27,7 @@ class AddressInfo {
this.nTx = 0
this.unspentOutputs = []
this.tracked = false,
this.tracked = false
this.type = 'untracked'
this.xpub = null
this.path = null
@ -34,8 +36,8 @@ class AddressInfo {
}
/**
* Load information about the address
* @returns {Promise}
* @description Load information about the address
* @returns {Promise<void[]>}
*/
async loadInfo() {
return Promise.all([
@ -57,9 +59,8 @@ class AddressInfo {
}
/**
* Load information about the address
* (extended form)
* @returns {Promise}
* @description Load information about the address (extended form)
* @returns {Promise<void[]>}
*/
async loadInfoExtended() {
const res = await db.getHDAccountsByAddresses([this.address])
@ -75,7 +76,7 @@ class AddressInfo {
}
for (let a of res.loose) {
if (a.addrAddress == this.address) {
if (a.addrAddress === this.address) {
this.tracked = true
this.type = 'loose'
break
@ -86,9 +87,9 @@ class AddressInfo {
}
/**
* Loads a partial list of transactions for this address
* @param {integer} page - page index
* @param {integer} count - number of transactions per page
* @description Loads a partial list of transactions for this address
* @param {number} page - page index
* @param {number} count - number of transactions per page
* @returns {Promise}
*/
async loadTransactions(page, count) {
@ -96,8 +97,8 @@ class AddressInfo {
}
/**
* Load the utxos associated to the address
* @returns {Promise - object[]}
* @description Load the utxos associated to the address
* @returns {Promise<object[]>}
*/
async loadUtxos() {
this.unspentOutputs = []
@ -118,7 +119,7 @@ class AddressInfo {
}
/**
* Return a plain old js object with address properties
* @description Return a plain old js object with address properties
* @returns {object}
*/
toPojo() {
@ -135,8 +136,7 @@ class AddressInfo {
}
/**
* Return a plain old js object with address properties
* (extended version)
* @description Return a plain old js object with address properties (extended version)
* @returns {object}
*/
toPojoExtended() {

37
lib/wallet/hd-account-info.js

@ -12,13 +12,14 @@ const rpcLatestBlock = require('../bitcoind-rpc/latest-block')
/**
* A class storing information about the actibity of a hd account
* @class HdAccountInfo
* @description A class storing information about the actibity of a hd account
*/
class HdAccountInfo {
/**
* Constructor
* @param {object} xpub - xpub
* @param {string} xpub - xpub
*/
constructor(xpub) {
// Initializes properties
@ -39,9 +40,8 @@ class HdAccountInfo {
}
/**
* Ensure the hd account exists in database
* Otherwise, tries to import it with BIP44 derivation
* @returns {Promise - integer} return the internal id of the hd account
* @description Ensure the hd account exists in database. Otherwise, tries to import it with BIP44 derivation
* @returns {Promise<number | null>} return the internal id of the hd account
* or null if it doesn't exist
*/
async ensureHdAccount() {
@ -49,7 +49,7 @@ class HdAccountInfo {
const id = await db.getHDAccountId(this.xpub)
return id
} catch(e) {
if (e == errors.db.ERROR_NO_HD_ACCOUNT) {
if (e === errors.db.ERROR_NO_HD_ACCOUNT) {
try {
// Default to BIP44 import
return hdaService.restoreHdAccount(this.xpub, hdaHelper.BIP44)
@ -62,8 +62,8 @@ class HdAccountInfo {
}
/**
* Load information about the hd account
* @returns {Promise}
* @description Load information about the hd account
* @returns {Promise<boolean>}
*/
async loadInfo() {
try {
@ -93,29 +93,41 @@ class HdAccountInfo {
this.depth = node[2].depth
}
/**
* @returns {Promise<void>}
*/
async _loadBalance() {
this.finalBalance = await db.getHDAccountBalance(this.xpub)
}
/**
* @returns {Promise<void>}
*/
async _loadUnusedIndices() {
const unusedIdx = await db.getHDAccountNextUnusedIndices(this.xpub)
this.accountIndex = unusedIdx[0]
this.changeIndex = unusedIdx[1]
}
/**
* @returns {Promise<void>}
*/
async _loadDerivedIndices() {
const derivedIdx = await db.getHDAccountDerivedIndices(this.xpub)
this.accountDerivedIndex = derivedIdx[0]
this.changeDerivedIndex = derivedIdx[1]
}
/**
* @returns {Promise<void>}
*/
async _loadNbTransactions() {
this.nTx = await db.getHDAccountNbTransactions(this.xpub)
}
/**
* Load the utxos associated to the hd account
* @returns {Promise - object[]}
* @description Load the utxos associated to the hd account
* @returns {Promise<object[]>}
*/
async loadUtxos() {
this.unspentOutputs = []
@ -153,7 +165,7 @@ class HdAccountInfo {
}
/**
* Return a plain old js object with hd account properties
* @description Return a plain old js object with hd account properties
* @returns {object}
*/
toPojo() {
@ -169,8 +181,7 @@ class HdAccountInfo {
}
/**
* Return a plain old js object with hd account properties
* (extended version)
* @description Return a plain old js object with hd account properties (extended version)
* @returns {object}
*/
toPojoExtended() {

21
lib/wallet/wallet-entities.js

@ -6,13 +6,13 @@
/**
* A class storing entities (xpubs, addresses, pubkeys)
* defining a (full|partial) wallet
* @class WalletEntities
* @description A class storing entities (xpubs, addresses, pubkeys) defining a (full|partial) wallet
*/
class WalletEntities {
/**
* Constructor
* @constructor
*/
constructor() {
this.pubkeys = []
@ -23,8 +23,7 @@ class WalletEntities {
}
/**
* Add a new hd account
* with its translation as an xpub
* @description Add a new hd account with its translation as an xpub
* @param {string} xpub - xpub or tpub
* @param {string} ypub - ypub or upub or false
* @param {string} zpub - zpub or vpub or false
@ -36,7 +35,7 @@ class WalletEntities {
}
/**
* Add a new address/pubkey
* @description Add a new address/pubkey
* @param {string} address - bitcoin address
* @param {string} pubkey - pubkey associated to the address or false
*/
@ -46,7 +45,7 @@ class WalletEntities {
}
/**
* Update the pubkey associated to a given address
* @description Update the pubkey associated to a given address
* @param {string} address - bitcoin address
* @param {string} pubkey - public key
*/
@ -57,7 +56,7 @@ class WalletEntities {
}
/**
* Checks if a xpub is already listed
* @description Checks if a xpub is already listed
* @param {string} xpub
* @returns {boolean} returns true if the xpub is already listed, false otherwise
*/
@ -66,7 +65,7 @@ class WalletEntities {
}
/**
* Checks if an address is already listed
* @description Checks if an address is already listed
* @param {string} address - bitcoin address
* @returns {boolean} returns true if the address is already listed, false otherwise
*/
@ -75,7 +74,7 @@ class WalletEntities {
}
/**
* Checks if a pubkey is already listed
* @description Checks if a pubkey is already listed
* @param {string} pubkey - public key
* @returns {boolean} returns true if the pubkey is already listed, false otherwise
*/
@ -85,4 +84,4 @@ class WalletEntities {
}
module.exports = WalletEntities
module.exports = WalletEntities

48
lib/wallet/wallet-info.js

@ -16,11 +16,13 @@ const AddressInfo = require('./address-info')
/**
* A class storing information about a (full|partial) wallet
* Provides a set of methods allowing to retrieve specific information
* @class WalletInfo
*/
class WalletInfo {
/**
* Constructor
* @constructor
* @param {object} entities - wallet entities (hdaccounts, addresses, pubkeys)
*/
constructor(entities) {
@ -49,7 +51,7 @@ class WalletInfo {
/**
* Ensure hd accounts exist in database
* @returns {Promise}
* @returns {Promise<Array<any>>}
*/
async ensureHdAccounts() {
return util.parallelCall(this.entities.xpubs, async xpub => {
@ -60,7 +62,7 @@ class WalletInfo {
/**
* Load information about the hd accounts
* @returns {Promise}
* @returns {Promise<Array<any>>}
*/
async loadHdAccountsInfo() {
return util.parallelCall(this.entities.xpubs, async xpub => {
@ -91,7 +93,7 @@ class WalletInfo {
/**
* Filter addresses that belong to an active hd account
* @returns {Promise}
* @returns {Promise<void>}
*/
async filterAddresses() {
const res = await db.getXpubByAddresses(this.entities.addrs)
@ -110,7 +112,7 @@ class WalletInfo {
/**
* Load information about the addresses
* @returns {Promise}
* @returns {Promise<Array<void>>}
*/
async loadAddressesInfo() {
return util.parallelCall(this.entities.addrs, async address => {
@ -123,11 +125,11 @@ class WalletInfo {
/**
* Loads a partial list of transactions for this wallet
* @param {integer} page - page index
* @param {integer} count - number of transactions per page
* @param {boolean} txBalance - True if past wallet balance
* @param {number} page - page index
* @param {number} count - number of transactions per page
* @param {boolean=} txBalance - True if past wallet balance
* should be computed for each transaction
* @returns {Promise}
* @returns {Promise<void>}
*/
async loadTransactions(page, count, txBalance) {
this.txs = await db.getTxsByAddrAndXpubs(
@ -149,7 +151,7 @@ class WalletInfo {
/**
* Loads the number of transactions for this wallet
* @returns {Promise}
* @returns {Promise<void>}
*/
async loadNbTransactions() {
const nbTxs = await db.getAddrAndXpubsNbTransactions(
@ -163,7 +165,7 @@ class WalletInfo {
/**
* Loads tinfo about the fee rates
* @returns {Promise}
* @returns {Promise<void>}
*/
async loadFeesInfo() {
this.info.fees = await rpcFees.getFees()
@ -171,7 +173,7 @@ class WalletInfo {
/**
* Loads the list of unspent outputs for this wallet
* @returns {Promise}
* @returns {Promise<void>}
*/
async loadUtxos() {
// Load the utxos for the hd accounts
@ -212,7 +214,7 @@ class WalletInfo {
/**
* Post process addresses and public keys
*/
postProcessAddresses() {
async postProcessAddresses() {
for (let b = 0; b < this.entities.pubkeys.length; b++) {
const pk = this.entities.pubkeys[b]
@ -221,7 +223,7 @@ class WalletInfo {
// Add pubkeys in this.addresses
for (let c = 0; c < this.addresses.length; c++) {
if (address == this.addresses[c].address)
if (address === this.addresses[c].address)
this.addresses[c].pubkey = pk
}
@ -229,30 +231,32 @@ class WalletInfo {
for (let d = 0; d < this.txs.length; d++) {
// inputs
for (let e = 0; e < this.txs[d].inputs.length; e++) {
if (address == this.txs[d].inputs[e].prev_out.addr)
if (address === this.txs[d].inputs[e].prev_out.addr)
this.txs[d].inputs[e].prev_out.pubkey = pk
}
// outputs
for (let e = 0; e < this.txs[d].out.length; e++) {
if (address == this.txs[d].out[e].addr)
if (address === this.txs[d].out[e].addr)
this.txs[d].out[e].pubkey = pk
}
}
// Add pubkeys in this.unspentOutputs
for (let f = 0; f < this.unspentOutputs.length; f++) {
if (address == this.unspentOutputs[f].addr) {
if (address === this.unspentOutputs[f].addr) {
this.unspentOutputs[f].pubkey = pk
}
}
}
}
return Promise.resolve()
}
/**
* Post process hd accounts (xpubs translations)
*/
postProcessHdAccounts() {
async postProcessHdAccounts() {
for (let b = 0; b < this.entities.xpubs.length; b++) {
const entityXPub = this.entities.xpubs[b]
const entityYPub = this.entities.ypubs[b]
@ -263,7 +267,7 @@ class WalletInfo {
// Translate xpub => ypub/zpub in this.addresses
for (let c = 0; c < this.addresses.length; c++) {
if (entityXPub == this.addresses[c].address)
if (entityXPub === this.addresses[c].address)
this.addresses[c].address = tgtXPub
}
@ -272,14 +276,14 @@ class WalletInfo {
// inputs
for (let e = 0; e < this.txs[d].inputs.length; e++) {
const xpub = this.txs[d].inputs[e].prev_out.xpub
if (xpub && (xpub.m == entityXPub))
if (xpub && (xpub.m === entityXPub))
this.txs[d].inputs[e].prev_out.xpub.m = tgtXPub
}
// outputs
for (let e = 0; e < this.txs[d].out.length; e++) {
const xpub = this.txs[d].out[e].xpub
if (xpub && (xpub.m == entityXPub))
if (xpub && (xpub.m === entityXPub))
this.txs[d].out[e].xpub.m = tgtXPub
}
}
@ -287,12 +291,14 @@ class WalletInfo {
// Translate xpub => ypub/zpub in this.unspentOutputs
for (let f = 0; f < this.unspentOutputs.length; f++) {
const xpub = this.unspentOutputs[f].xpub
if (xpub && (xpub.m == entityXPub)) {
if (xpub && (xpub.m === entityXPub)) {
this.unspentOutputs[f].xpub.m = tgtXPub
}
}
}
}
return Promise.resolve()
}
/**

28
lib/wallet/wallet-service.js

@ -72,7 +72,7 @@ class WalletService {
// Force import of addresses associated to paynyms
// if dojo relies on a local index
if (keys.indexer.active != 'third_party_explorer')
if (keys.indexer.active !== 'third_party_explorer')
await this._forceEnsureAddressesForActivePubkeys(active)
// Filter the addresses
@ -150,7 +150,7 @@ class WalletService {
await walletInfo.ensureAddresses()
// Force import of addresses associated to paynyms
// if dojo relies on a local index
if (keys.indexer.active != 'third_party_explorer')
if (keys.indexer.active !== 'third_party_explorer')
await this._forceEnsureAddressesForActivePubkeys(active)
// Filter the address and load them
await walletInfo.filterAddresses()
@ -252,7 +252,7 @@ class WalletService {
await walletInfo.ensureAddresses()
// Force import of addresses associated to paynyms
// if dojo relies on a local index
if (keys.indexer.active != 'third_party_explorer')
if (keys.indexer.active !== 'third_party_explorer')
await this._forceEnsureAddressesForActivePubkeys(active)
// Filter the addresses
await walletInfo.filterAddresses()
@ -274,8 +274,8 @@ class WalletService {
/**
* Get a subset of wallet transactions
* @param {object} entities - mapping of active entities
* @param {integer} page - page of transactions to be returned
* @param {integer} count - number of transactions returned per page
* @param {number} page - page of transactions to be returned
* @param {number} count - number of transactions returned per page
* @returns {Promise}
*/
async getWalletTransactions(entities, page, count) {
@ -287,7 +287,7 @@ class WalletService {
}
// Check parameters
if (entities.xpubs.length == 0 && entities.addrs.length == 0)
if (entities.xpubs.length === 0 && entities.addrs.length === 0)
return ret
// Initialize a WalletInfo object
@ -344,13 +344,13 @@ class WalletService {
* @returns {boolean} return true if conditions are met, false otherwise
*/
_checkEntities(active, legacy, bip49, bip84, pubkeys) {
const allEmpty = active.xpubs.length == 0
&& active.addrs.length == 0
&& legacy.xpubs.length == 0
&& legacy.addrs.length == 0
&& pubkeys.addrs.length == 0
&& bip49.xpubs.length == 0
&& bip84.xpubs.length == 0
const allEmpty = active.xpubs.length === 0
&& active.addrs.length === 0
&& legacy.xpubs.length === 0
&& legacy.addrs.length === 0
&& pubkeys.addrs.length === 0
&& bip49.xpubs.length === 0
&& bip84.xpubs.length === 0
return !allEmpty
}
@ -375,7 +375,7 @@ class WalletService {
const pubkey = source.pubkeys[idxSource]
const idxActive = active.addrs.indexOf(addr)
if (idxActive == -1) {
if (idxActive === -1) {
active.addrs.push(addr)
active.pubkeys.push(pubkey)
} else if (pubkey) {

8
pushtx/orchestrator.js

@ -94,7 +94,7 @@ class Orchestrator {
break
for (let tx of txs) {
let hasParentTx = (tx.schParentTxid != null) && (tx.schParentTxid != '')
let hasParentTx = (tx.schParentTxid != null) && (tx.schParentTxid !== '')
let parentTx = null
// Check if previous transaction has been confirmed
@ -158,11 +158,11 @@ class Orchestrator {
/**
* Update triggers in chain of transactions
* following a transaction identified by its txid
* @param {integer} parentId - parent id
* @param {integer} shift - delta to be added to the triggers
* @param {number} parentId - parent id
* @param {number} shift - delta to be added to the triggers
*/
async updateTriggers(parentId, shift) {
if (shift == 0)
if (shift === 0)
return
const txs = await db.getNextScheduledTransactions(parentId)

4
pushtx/pushtx-processor.js

@ -17,7 +17,7 @@ const keys = require('../keys')[network.key]
const status = require('./status')
let Sources
if (network.key == 'bitcoin') {
if (network.key === 'bitcoin') {
Sources = require('../lib/remote-importer/sources-mainnet')
} else {
Sources = require('../lib/remote-importer/sources-testnet')
@ -78,7 +78,7 @@ class PushTxProcessor {
}
// Checks with indexer if addresses are known and have been used
if (Object.keys(addrMap).length > 0) {
if (keys.indexer.active != 'local_bitcoind') {
if (keys.indexer.active !== 'local_bitcoind') {
const results = await this.sources.getAddresses(Object.keys(addrMap))
for (let r of results)
if (r.ntx > 0)

4
pushtx/pushtx-rest-api.js

@ -193,7 +193,7 @@ class PushTxRestApi {
HttpServer.sendOk(res)
} catch(e) {
// Returns code 200 if VIOLATION_STRICT_MODE_VOUTS
if (e.message && e.message.code && e.message.code == errors.pushtx.VIOLATION_STRICT_MODE_VOUTS) {
if (e.message && e.message.code && e.message.code === errors.pushtx.VIOLATION_STRICT_MODE_VOUTS) {
e.message = JSON.stringify(e.message)
this._traceError(res, e, 200)
} else {
@ -206,7 +206,7 @@ class PushTxRestApi {
* Trace an error during push
* @param {object} res - http response object
* @param {object} err - error object
* @param {int} errorCode - error code (optional)
* @param {number} errorCode - error code (optional)
*/
_traceError(res, err, errorCode) {
let ret = null

8
pushtx/transactions-scheduler.js

@ -68,13 +68,13 @@ class TransactionsScheduler {
// Decode the transaction
const tx = bitcoin.Transaction.fromHex(entry.tx)
// Check that nlocktimes are matching
if (!(tx.locktime && tx.locktime == entry.nlocktime)) {
if (!(tx.locktime && tx.locktime === entry.nlocktime)) {
const msg = `TransactionsScheduler.schedule() : nLockTime mismatch : ${tx.locktime} - ${entry.nlocktime}`
Logger.error(null, `PushTx : ${msg}`)
throw errors.pushtx.NLOCK_MISMATCH
}
// Check that order of hop and nlocktime values are consistent
if (entry.hop != lastHopProcessed) {
if (entry.hop !== lastHopProcessed) {
if (entry.nlocktime < lastLockTimeProcessed)
throw errors.pushtx.SCHEDULED_BAD_ORDER
}
@ -105,7 +105,7 @@ class TransactionsScheduler {
lastHopProcessed = entry.hop
lastLockTimeProcessed = entry.nlocktime
// Update scheduled height if needed
if (baseHeight != nltTx0)
if (baseHeight !== nltTx0)
entry.nlocktime = baseHeight + entry.delta
}
@ -123,7 +123,7 @@ class TransactionsScheduler {
let parentNlocktime = baseHeight
// Check if first transactions should be sent immediately
while ((script.length > 0) && (script[0].nlocktime <= lastHeight) && (script[0].delta == 0)) {
while ((script.length > 0) && (script[0].nlocktime <= lastHeight) && (script[0].delta === 0)) {
await pushTxProcessor.pushTx(script[0].tx)
const tx = bitcoin.Transaction.fromHex(script[0].tx)
parentTxid = tx.getId()

14
scripts/patches/revert-hd-accounts.js

@ -21,9 +21,9 @@ function xlatXPUB(xpub) {
let xlatVer = 0
if (ver == hdaHelper.MAGIC_XPUB || ver == hdaHelper.MAGIC_YPUB || ver == hdaHelper.MAGIC_ZPUB) {
xlatVer = hdaHelper.MAGIC_XPUB
} else if (ver == hdaHelper.MAGIC_TPUB || ver == hdaHelper.MAGIC_UPUB || ver == hdaHelper.MAGIC_VPUB) {
if (ver === hdaHelper.MAGIC_XPUB || ver === hdaHelper.MAGIC_YPUB || ver === hdaHelper.MAGIC_ZPUB) {
xlatVer = hdaHelper.MAGIC_XPUB
} else if (ver === hdaHelper.MAGIC_TPUB || ver === hdaHelper.MAGIC_UPUB || ver === hdaHelper.MAGIC_VPUB) {
xlatVer = hdaHelper.MAGIC_TPUB
}
@ -75,8 +75,8 @@ async function run() {
const xpub = account.hdXpub
const info = hdaHelper.classify(account.hdType)
const scheme = info.type
if ((scheme == hdaHelper.BIP49) || (scheme == hdaHelper.BIP84)) {
if ((scheme === hdaHelper.BIP49) || (scheme === hdaHelper.BIP84)) {
try {
const xlatedXpub = xlatXPUB(xpub)
await updateHdAccount(hdId, xlatedXpub)
@ -90,7 +90,7 @@ async function run() {
} catch(e) {
console.log('A problem was met')
console.log(e)
}
}
}
/**
@ -102,4 +102,4 @@ const startupTimeout = setTimeout(async function() {
return run().then(() => {
console.log('Process completed')
})
}, 1500)
}, 1500)

20
scripts/patches/translate-hd-accounts.js

@ -21,18 +21,18 @@ function xlatXPUB(xpub, targetType) {
let xlatVer = 0
if (ver == hdaHelper.MAGIC_XPUB) {
if (ver === hdaHelper.MAGIC_XPUB) {
if (targetType == hdaHelper.BIP49)
if (targetType === hdaHelper.BIP49)
xlatVer = hdaHelper.MAGIC_YPUB
else if (targetType == hdaHelper.BIP84)
else if (targetType === hdaHelper.BIP84)
xlatVer = hdaHelper.MAGIC_ZPUB
} else if (ver == hdaHelper.MAGIC_TPUB) {
} else if (ver === hdaHelper.MAGIC_TPUB) {
if (targetType == hdaHelper.BIP49)
if (targetType === hdaHelper.BIP49)
xlatVer = hdaHelper.MAGIC_UPUB
else if (targetType == hdaHelper.BIP84)
else if (targetType === hdaHelper.BIP84)
xlatVer = hdaHelper.MAGIC_VPUB
}
@ -84,8 +84,8 @@ async function run() {
const xpub = account.hdXpub
const info = hdaHelper.classify(account.hdType)
const scheme = info.type
if ((scheme == hdaHelper.BIP49) || (scheme == hdaHelper.BIP84)) {
if ((scheme === hdaHelper.BIP49) || (scheme === hdaHelper.BIP84)) {
const xlatedXpub = xlatXPUB(xpub, scheme)
await updateHdAccount(hdId, xlatedXpub)
console.log(`Updated ${hdId} (${xpub} => ${xlatedXpub})`)
@ -94,7 +94,7 @@ async function run() {
} catch(e) {
console.log('A problem was met')
console.log(e)
}
}
}
/**
@ -106,4 +106,4 @@ const startupTimeout = setTimeout(async function() {
return run().then(() => {
console.log('Process completed')
})
}, 1500)
}, 1500)

2
static/admin/dmt/index.js

@ -84,7 +84,7 @@ function preparePage() {
const activeTab = sessionStorage.getItem('activeTab')
for (let idxTab in tabs) {
const screen = screens[idxTab]
if (tabs[idxTab] == activeTab) {
if (tabs[idxTab] === activeTab) {
$(screen).show()
if (screenScripts.has(screen))
screenScripts.get(screen).preparePage()

10
static/admin/dmt/status/status.js

@ -95,7 +95,7 @@ const statusScript = {
this.chaintipBitcoind = data['bitcoind']['blocks']
$('#node-chaintip').text(data['bitcoind']['blocks'])
$('#node-version').text(data['bitcoind']['version'])
const network = data['bitcoind']['testnet'] == true ? 'testnet' : 'mainnet'
const network = data['bitcoind']['testnet'] === true ? 'testnet' : 'mainnet'
$('#node-network').text(network)
$('#node-conn').text(data['bitcoind']['conn'])
$('#node-relay-fee').text(data['bitcoind']['relayfee'])
@ -123,13 +123,13 @@ const statusScript = {
},
setStatusIndicator: function(id, status) {
if (status == 'ok') {
if (status === 'ok') {
$(id).html('&#10003;')
$(id).css('color', '#76d776')
} else if (status == 'ko') {
} else if (status === 'ko') {
$(id).html('X')
$(id).css('color', '#f77c7c')
} else if (status == 'desynchronized') {
} else if (status === 'desynchronized') {
$(id).html('&#10003;')
$(id).css('color', '#f0c649')
} else {
@ -140,4 +140,4 @@ const statusScript = {
}
screenScripts.set('#screen-status', statusScript)
screenScripts.set('#screen-status', statusScript)

8
static/admin/dmt/xpubs-tools/xpubs-tools.js

@ -31,8 +31,8 @@ const screenXpubsToolsScript = {
preparePage: function() {
// Disable custom lookahead if data source is a third party explorer
const isTPE = sessionStorage.getItem('indexerType') == 'third_party_explorer'
const isLRI = sessionStorage.getItem('indexerType') == 'local_rest_indexer'
const isTPE = sessionStorage.getItem('indexerType') === 'third_party_explorer'
const isLRI = sessionStorage.getItem('indexerType') === 'local_rest_indexer'
const disableLookahead = isTPE || isLRI
$('#rescan-lookahead').prop('disabled', disableLookahead)
@ -99,9 +99,9 @@ const screenXpubsToolsScript = {
}
const derivType = $('#import-deriv-type').val()
if (derivType == 'bip49' || derivType == 'bip84') {
if (derivType === 'bip49' || derivType === 'bip84') {
jsonData['segwit'] = derivType
} else if (derivType == 'auto') {
} else if (derivType === 'auto') {
if (this.currentXpub.startsWith('ypub'))
jsonData['segwit'] = 'bip49'
else if (this.currentXpub.startsWith('zpub'))

4
static/admin/lib/auth-utils.js

@ -98,7 +98,7 @@ const lib_auth = {
isAuthenticated: function() {
// Checks that an access token is stored in session storage
let token = this.getAccessToken()
return (token && (token != 'null')) ? true : false
return Boolean(token && (token !== 'null'))
},
/*
@ -128,7 +128,7 @@ const lib_auth = {
const payload = this.getPayloadAccessToken(token)
if (!payload)
return false
return (('prf' in payload) && (payload['prf'] == this.TOKEN_PROFILE_ADMIN))
return (('prf' in payload) && (payload['prf'] === this.TOKEN_PROFILE_ADMIN))
},
/*

8
static/admin/lib/common-script.js

@ -27,9 +27,9 @@ const lib_cmn = {
getExplorerTxUrl: function(txid, explorerInfo) {
if (explorerInfo == null)
return null
else if (explorerInfo['pairing']['type'] == 'explorer.oxt')
else if (explorerInfo['pairing']['type'] === 'explorer.oxt')
return `${explorerInfo['pairing']['url']}/transaction/${txid}`
else if (explorerInfo['pairing']['type'] == 'explorer.btc_rpc_explorer')
else if (explorerInfo['pairing']['type'] === 'explorer.btc_rpc_explorer')
return `http://${explorerInfo['pairing']['url']}/tx/${txid}`
else
return null
@ -46,7 +46,7 @@ const lib_cmn = {
if (file) {
xhttp = new XMLHttpRequest()
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
if (this.readyState === 4 && this.status === 200) {
elmnt.innerHTML = this.responseText
elmnt.removeAttribute('include-html')
self.includeHTML(cb)
@ -72,7 +72,7 @@ const lib_cmn = {
if (file) {
xhttp = new XMLHttpRequest()
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
if (this.readyState === 4 && this.status === 200) {
const newElmnt = document.createElement('script')
newElmnt.textContent = this.responseText
if (elmnt.parentNode) {

2
static/admin/lib/errors-utils.js

@ -14,7 +14,7 @@ const lib_errors = {
processError: function(e) {
const errorMsg = this.extractJqxhrErrorMsg(e)
// Redirect to sign in page if authentication error
if (errorMsg == 'Invalid JSON Web Token' || errorMsg == 'Missing JSON Web Token') {
if (errorMsg === 'Invalid JSON Web Token' || errorMsg === 'Missing JSON Web Token') {
lib_auth.logout()
} else {
lib_msg.displayErrors(errorMsg)

2
static/admin/lib/format-utils.js

@ -52,7 +52,7 @@ const lib_fmt = {
* Format a unix timestamp into a readable date/hour
*/
formatUnixTs: function(ts) {
if (ts == null || ts == 0)
if (ts == null || ts === 0)
return '-'
let tmpDate = new Date(ts*1000),

10
tracker/block-worker.js

@ -61,22 +61,22 @@ async function processMessage(msg) {
try {
switch(msg.op) {
case OP_INIT:
if (status != IDLE)
if (status !== IDLE)
throw 'Operation not allowed'
res = await initBlock(msg.header)
break
case OP_PROCESS_OUTPUTS:
if (status != INITIALIZED)
if (status !== INITIALIZED)
throw 'Operation not allowed'
res = await processOutputs()
break
case OP_PROCESS_INPUTS:
if (status != OUTPUTS_PROCESSED)
if (status !== OUTPUTS_PROCESSED)
throw 'Operation not allowed'
res = await processInputs()
break
case OP_CONFIRM:
if (status != INPUTS_PROCESSED)
if (status !== INPUTS_PROCESSED)
throw 'Operation not allowed'
res = await confirmTransactions(msg.blockId)
break
@ -130,7 +130,7 @@ async function processInputs() {
/**
* Confirm the transactions
* @param {integer} blockId - id of the block in db
* @param {number} blockId - id of the block in db
*/
async function confirmTransactions(blockId) {
status = TXS_CONFIRMED

16
tracker/block.js

@ -44,7 +44,7 @@ class Block extends TransactionsBundle {
* @dev This method isn't used anymore.
* It has been replaced by a parallel processing of blocks.
* (see blocks-processor and block-worker)
* @returns {Promise - object[]} returns an array of transactions to be broadcast
* @returns {Promise<object[]>} returns an array of transactions to be broadcast
*/
async processBlock() {
Logger.info('Tracker : Beginning to process new block.')
@ -77,7 +77,7 @@ class Block extends TransactionsBundle {
/**
* Process the transaction outputs
* @returns {Promise - object[]} returns an array of transactions to be broadcast
* @returns {Promise<object[]>} returns an array of transactions to be broadcast
*/
async processOutputs() {
const txsForBroadcast = new Set()
@ -93,7 +93,7 @@ class Block extends TransactionsBundle {
/**
* Process the transaction inputs
* @returns {Promise - object[]} returns an array of transactions to be broadcast
* @returns {Promise<object[]>} returns an array of transactions to be broadcast
*/
async processInputs() {
const txsForBroadcast = new Set()
@ -109,7 +109,7 @@ class Block extends TransactionsBundle {
/**
* Store the block in db
* @returns {Promise - int} returns the id of the block
* @returns {Promise<number>} returns the id of the block
*/
async registerBlock() {
const prevBlock = await db.getBlockByHash(this.header.previousblockhash)
@ -130,8 +130,8 @@ class Block extends TransactionsBundle {
/**
* Confirm the transactions in db
* @param {Set} txs - set of transactions stored in db
* @param {int} blockId - id of the block
* r@returns {Promise}
* @param {number} blockId - id of the block
* @returns {Promise}
*/
async confirmTransactions(txs, blockId) {
const txids = txs.map(t => t.getId())
@ -141,8 +141,8 @@ class Block extends TransactionsBundle {
/**
* Register the block header
* @param {int} prevBlockID - id of previous block
* @returns {Promise}
* @param {number} prevBlockID - id of previous block
* @returns {Promise<number>}
*/
async checkBlockHeader(prevBlockID) {
Logger.info('Tracker : Beginning to process new block header.')

26
tracker/blockchain-processor.js

@ -43,7 +43,7 @@ class BlockchainProcessor {
/**
* Start processing the blockchain
* @returns {Promise}
* @returns {Promise<void>}
*/
async start() {
await this.catchup()
@ -57,7 +57,7 @@ class BlockchainProcessor {
/**
* Tracker process startup
* @returns {Promise}
* @returns {Promise<void>}
*/
async catchup() {
const [highest, info] = await Promise.all([db.getHighestBlock(), this.client.getblockchaininfo()])
@ -78,7 +78,7 @@ class BlockchainProcessor {
* 2. Pull all block headers after database last known height
* 3. Process those block headers
*
* @returns {Promise}
* @returns {Promise<void>}
*/
async catchupIBDMode() {
try {
@ -93,7 +93,7 @@ class BlockchainProcessor {
let prevBlockId = highest.blockID
// If no header or block loaded by bitcoind => try later
if (daemonNbHeaders == 0 || daemonNbBlocks == 0) {
if (daemonNbHeaders === 0 || daemonNbBlocks === 0) {
Logger.info('Tracker : New attempt scheduled in 30s (waiting for block headers)')
return util.delay(30000).then(() => {
return this.catchupIBDMode()
@ -148,7 +148,7 @@ class BlockchainProcessor {
* 2. Pull all block headers after database last known height
* 3. Process those block headers
*
* @returns {Promise}
* @returns {Promise<void>}
*/
async catchupNormalMode() {
try {
@ -159,7 +159,7 @@ class BlockchainProcessor {
const daemonNbBlocks = info.blocks
if (highest == null) return null
if (daemonNbBlocks == highest.blockHeight) return null
if (daemonNbBlocks === highest.blockHeight) return null
const blockRange = _.range(highest.blockHeight, daemonNbBlocks + 1)
@ -225,7 +225,7 @@ class BlockchainProcessor {
* block confirmation.
*
* @param {Buffer} buf - block
* @returns {Promise}
* @returns {Promise<void>}
*/
async onBlockHash(buf) {
try {
@ -298,8 +298,8 @@ class BlockchainProcessor {
/**
* Cancel confirmation of transactions
* and delete blocks after a given height
* @param {integer} height - height of last block maintained
* @returns {Promise}
* @param {number} height - height of last block maintained
* @returns {Promise<void>}
*/
async rewind(height) {
// Retrieve transactions confirmed in reorg'd blocks
@ -317,8 +317,8 @@ class BlockchainProcessor {
/**
* Rescan a range of blocks
* @param {integer} fromHeight - height of first block
* @param {integer} toHeight - height of last block
* @param {number} fromHeight - height of first block
* @param {number} toHeight - height of last block
* @returns {Promise}
*/
async rescanBlocks(fromHeight, toHeight) {
@ -356,7 +356,7 @@ class BlockchainProcessor {
/**
* Process a range of blocks
* @param {int[]} heights - a range of block heights
* @param {number[]} heights - a range of block heights
*/
async processBlockRange(heights) {
const chunks = util.splitList(heights, blocksProcessor.nbWorkers)
@ -373,7 +373,7 @@ class BlockchainProcessor {
/**
* Process a block header
* @param {object} header - block header
* @param {int} prevBlockID - id of previous block
* @param {number} prevBlockID - id of previous block
* @returns {Promise}
*/
async processBlockHeader(header, prevBlockID) {

8
tracker/blocks-processor.js

@ -90,11 +90,11 @@ async function processWorkerMessage(msg) {
if (!msg.status) {
Logger.error(msg.res, 'Tracker : processWorkerMessage()')
} else if (msg.op == blockWorker.OP_CONFIRM) {
} else if (msg.op === blockWorker.OP_CONFIRM) {
txsForBroadcast = txsForBroadcast.concat(msg.res)
}
if (nbTasksCompleted == nbTasksEnqueued) {
if (nbTasksCompleted === nbTasksEnqueued) {
switch (msg.op) {
case blockWorker.OP_INIT:
// Process the transaction outputs
@ -139,7 +139,7 @@ async function processWorkerMessage(msg) {
/**
* Execute an operation processing a block
* @param {integer} op - operation
* @param {number} op - operation
* @param {*} args
*/
function processTask(op, args) {
@ -204,7 +204,7 @@ function notifyBlock(header) {
/**
* Store a block in db
* @param {object} header - block header
* @returns {Promise - int} returns the id of the block
* @returns {Promise<number>} returns the id of the block
*/
async function registerBlock(header) {
const prevBlock = await dbProcessor.getBlockByHash(header.previousblockhash)

15
tracker/mempool-processor.js

@ -47,7 +47,7 @@ class MempoolProcessor {
/**
* Start processing the mempool
* @returns {Promise}
* @returns {Promise<void>}
*/
async start() {
this.checkUnconfirmedId = setInterval(
@ -143,7 +143,7 @@ class MempoolProcessor {
/**
* Process transactions from the mempool buffer
* @returns {Promise}
* @returns {Promise<void>}
*/
async processMempool() {
// Refresh the isActive flag
@ -181,7 +181,7 @@ class MempoolProcessor {
/**
* On reception of a new transaction from bitcoind mempool
* @param {Buffer} buf - transaction
* @returns {Promise}
* @returns {Promise<void>}
*/
async onTx(buf) {
if (this.isActive) {
@ -201,7 +201,7 @@ class MempoolProcessor {
/**
* On reception of a new transaction from /pushtx
* @param {Buffer} buf - transaction
* @returns {Promise}
* @returns {Promise<void>}
*/
async onPushTx(buf) {
try {
@ -249,7 +249,7 @@ class MempoolProcessor {
/**
* Check unconfirmed transactions
* @returns {Promise}
* @returns {Promise<void>}
*/
async checkUnconfirmed() {
const t0 = Date.now()
@ -287,12 +287,13 @@ class MempoolProcessor {
// Logs
const ntx = unconfirmedTxs.length
const dt = ((Date.now() - t0) / 1000).toFixed(1)
const per = (ntx == 0) ? 0 : ((Date.now() - t0) / ntx).toFixed(0)
const per = (ntx === 0) ? 0 : ((Date.now() - t0) / ntx).toFixed(0)
Logger.info(`Tracker : Finished processing unconfirmed transactions ${dt}s, ${ntx} tx, ${per}ms/tx`)
}
/**
* Sets the isActive flag
* @private
*/
async _refreshActiveStatus() {
// Get highest header in the blockchain
@ -300,7 +301,7 @@ class MempoolProcessor {
const [highestBlock, info] = await Promise.all([db.getHighestBlock(), this.client.getblockchaininfo()])
const highestHeader = info.headers
if (highestBlock == null || highestBlock.blockHeight == 0) {
if (highestBlock == null || highestBlock.blockHeight === 0) {
this.isActive = false
return
}

2
tracker/tracker.js

@ -34,7 +34,7 @@ class Tracker {
/**
* Start the tracker
* @returns {Promise}
* @returns {Promise<void>}
*/
async start() {
if (!this.initialized) {

16
tracker/transaction.js

@ -96,7 +96,7 @@ class Transaction {
// Check if we find some inputs of interest
const results = await db.getOutputSpends(spends)
if (results.length == 0)
if (results.length === 0)
return null
// Flag the transaction for broadcast
@ -122,7 +122,7 @@ class Transaction {
})
// Detect potential double spends
if (r.spendingTxnID !== null && r.spendingTxnID != this.storedTxnID) {
if (r.spendingTxnID !== null && r.spendingTxnID !== this.storedTxnID) {
Logger.info(`Tracker : DOUBLE SPEND of ${r.txnTxid}-${r.outIndex} by ${this.txid}!`)
// Delete the existing transaction that has been double-spent:
// since the deepest block keeps its transactions, this will
@ -190,7 +190,7 @@ class Transaction {
const aHdAcctAddr = await this._processOutputsHdAccounts(result.hd, indexedOutputs)
fundedAddresses = fundedAddresses.concat(aHdAcctAddr)
if (fundedAddresses.length == 0)
if (fundedAddresses.length === 0)
return null
// Flag the transaction for broadcast
@ -219,7 +219,7 @@ class Transaction {
* Process outputs sending to tracked loose addresses
* @param {object[]} addresses - array of address objects
* @param {object} indexedOutputs - outputs indexed by address
* @returns {Promise - object[]} return an array of funded addresses
* @returns {Promise<object[]>} return an array of funded addresses
* {addrID: ..., outIndex: ..., outAmount: ..., outScript: ...}
*/
async _processOutputsLooseAddresses(addresses, indexedOutputs) {
@ -247,7 +247,7 @@ class Transaction {
* Process outputs sending to tracked hd accounts
* @param {object[]} hdAccounts - array of hd account objects
* @param {object} indexedOutputs - outputs indexed by address
* @returns {Promise - object[]} return an array of funded addresses
* @returns {Promise<object[]>} return an array of funded addresses
* {addrID: ..., outIndex: ..., outAmount: ..., outScript: ...}
*/
async _processOutputsHdAccounts(hdAccounts, indexedOutputs) {
@ -297,7 +297,7 @@ class Transaction {
* @param {string} xpub
* @param {object} hdAccount - hd account object
* @param {object} indexedOutputs - outputs indexed by address
* @returns {Promise - object[]} returns an array of the new addresses used
* @returns {Promise<object[]>} returns an array of the new addresses used
*/
async _deriveNewAddresses(xpub, hdAccount, indexedOutputs) {
const hdType = hdAccount.hdType
@ -317,10 +317,10 @@ class Transaction {
for (let chain of [0,1]) {
// Get addresses for this account that are on this chain
const chainAddresses = _.filter(hdAccount.addresses, v => {
return v.hdAddrChain == chain
return v.hdAddrChain === chain
})
if (chainAddresses.length == 0)
if (chainAddresses.length === 0)
continue
// Get the maximum used address on this chain

17
tracker/transactions-bundle.js

@ -18,7 +18,8 @@ class TransactionsBundle {
/**
* Constructor
* @param {object[]} txs - array of bitcoin transaction objects
* @constructor
* @param {object[]=} txs - array of bitcoin transaction objects
*/
constructor(txs) {
// List of transactions
@ -52,7 +53,7 @@ class TransactionsBundle {
/**
* Get the size of the bundle
* @returns {integer} return the number of transactions stored in the bundle
* @returns {number} return the number of transactions stored in the bundle
*/
size() {
return this.transactions.length
@ -61,7 +62,7 @@ class TransactionsBundle {
/**
* Find the transactions of interest
* based on theirs inputs
* @returns {object[]} returns an array of transactions objects
* @returns {Promise<object[]>} returns an array of transactions objects
*/
async prefilterByInputs() {
// Process transactions by slices of 5000 transactions
@ -74,7 +75,7 @@ class TransactionsBundle {
/**
* Find the transactions of interest
* based on theirs outputs
* @returns {object[]} returns an array of transactions objects
* @returns {Promise<object[]>} returns an array of transactions objects
*/
async prefilterByOutputs() {
// Process transactions by slices of 5000 transactions
@ -88,7 +89,7 @@ class TransactionsBundle {
* Find the transactions of interest
* based on theirs outputs (internal implementation)
* @params {object[]} txs - array of transactions objects
* @returns {object[]} returns an array of transactions objects
* @returns {Promise<object[]>} returns an array of transactions objects
*/
async _prefilterByOutputs(txs) {
let addresses = []
@ -122,7 +123,7 @@ class TransactionsBundle {
const idxTxs = indexedOutputs[key]
if (idxTxs) {
for (const idxTx of idxTxs)
if (filteredIdxTxs.indexOf(idxTx) == -1)
if (filteredIdxTxs.indexOf(idxTx) === -1)
filteredIdxTxs.push(idxTx)
}
}
@ -134,7 +135,7 @@ class TransactionsBundle {
* Find the transactions of interest
* based on theirs inputs (internal implementation)
* @params {object[]} txs - array of transactions objects
* @returns {object[]} returns an array of transactions objects
* @returns {Promise<object[]>} returns an array of transactions objects
*/
async _prefilterByInputs(txs) {
let inputs = []
@ -169,7 +170,7 @@ class TransactionsBundle {
const idxTxs = indexedInputs[key]
if (idxTxs) {
for (const idxTx of idxTxs)
if (filteredIdxTxs.indexOf(idxTx) == -1)
if (filteredIdxTxs.indexOf(idxTx) === -1)
filteredIdxTxs.push(idxTx)
}
}

Loading…
Cancel
Save