Browse Source

Merge branch 'feat_mydojo_rescan_progress' into 'develop'

track and display progress of import/rescan

See merge request dojo/samourai-dojo!175
use-env-var-docker
kenshin-samourai 4 years ago
parent
commit
754a92c9d5
  1. 25
      accounts/xpub-rest-api.js
  2. 11
      doc/GET_xpub_import_status.md
  3. 23
      lib/remote-importer/remote-importer.js
  4. 58
      static/admin/dmt/xpubs-tools/xpubs-tools.js

25
accounts/xpub-rest-api.js

@ -16,6 +16,7 @@ const RpcClient = require('../lib/bitcoind-rpc/rpc-client')
const HdAccountInfo = require('../lib/wallet/hd-account-info') const HdAccountInfo = require('../lib/wallet/hd-account-info')
const authMgr = require('../lib/auth/authorizations-manager') const authMgr = require('../lib/auth/authorizations-manager')
const HttpServer = require('../lib/http-server/http-server') const HttpServer = require('../lib/http-server/http-server')
const remoteImporter = require('../lib/remote-importer/remote-importer')
const debugApi = !!(process.argv.indexOf('api-debug') > -1) const debugApi = !!(process.argv.indexOf('api-debug') > -1)
const gap = require('../keys/')[network.key].gap const gap = require('../keys/')[network.key].gap
@ -230,8 +231,18 @@ class XPubRestApi {
return HttpServer.sendError(res, e) return HttpServer.sendError(res, e)
} }
const ret = { let ret = {
import_in_progress: hdaService.importInProgress(xpub) import_in_progress: false
}
const status = hdaService.importInProgress(xpub)
if (status != null) {
ret['import_in_progress'] = true
ret['status'] = status['status']
if (ret['status'] == remoteImporter.STATUS_RESCAN)
ret['hits'] = status['txs_int'] + status['txs_ext']
else
ret['hits'] = status['txs']
} }
HttpServer.sendOkData(res, ret) HttpServer.sendOkData(res, ret)
@ -275,7 +286,7 @@ class XPubRestApi {
const argAddr = req.body.address const argAddr = req.body.address
const argSig = req.body.signature const argSig = req.body.signature
const argMsg = req.body.message const argMsg = req.body.message
// Translate xpub if needed // Translate xpub if needed
try { try {
const ret = this.xlatHdAccount(argXpub) const ret = this.xlatHdAccount(argXpub)
@ -323,7 +334,7 @@ class XPubRestApi {
const argXpub = req.params.xpub const argXpub = req.params.xpub
const argAddr = req.body.address const argAddr = req.body.address
const argSig = req.body.signature const argSig = req.body.signature
// Translate xpub if needed // Translate xpub if needed
try { try {
const ret = this.xlatHdAccount(argXpub) const ret = this.xlatHdAccount(argXpub)
@ -398,15 +409,15 @@ class XPubRestApi {
validateArgsPostXpub(req, res, next) { validateArgsPostXpub(req, res, next) {
const isValidXpub = validator.isAlphanumeric(req.body.xpub) const isValidXpub = validator.isAlphanumeric(req.body.xpub)
const isValidSegwit = const isValidSegwit =
!req.body.segwit !req.body.segwit
|| validator.isAlphanumeric(req.body.segwit) || validator.isAlphanumeric(req.body.segwit)
const isValidType = const isValidType =
!req.body.type !req.body.type
|| validator.isAlphanumeric(req.body.type) || validator.isAlphanumeric(req.body.type)
const isValidForce = const isValidForce =
!req.body.force !req.body.force
|| validator.isAlphanumeric(req.body.force) || validator.isAlphanumeric(req.body.force)

11
doc/GET_xpub_import_status.md

@ -27,6 +27,17 @@ Status code 200 with JSON response:
} }
``` ```
```json
{
"status": "ok",
"data": {
"import_in_progress": true,
"status": "rescan",
"hits": 1143
}
}
```
#### Failure #### Failure
Status code 400 with JSON response: Status code 400 with JSON response:
```json ```json

23
lib/remote-importer/remote-importer.js

@ -34,6 +34,8 @@ class RemoteImporter {
* Constructor * Constructor
*/ */
constructor() { constructor() {
this.STATUS_RESCAN = 'rescan'
this.STATUS_IMPORT = 'import'
// Guard against overlapping imports // Guard against overlapping imports
this.importing = {} this.importing = {}
this.sources = new Sources() this.sources = new Sources()
@ -50,12 +52,12 @@ class RemoteImporter {
/** /**
* Check if a xpub is currently being imported or rescanned by Dojo * Check if a xpub is currently being imported or rescanned by Dojo
* Returns true if import/rescan is in progress, otherwise returns false * Returns infor about the operation if import/rescan is in progress, otherwise returns null
* @param {string} xpub - xpub * @param {string} xpub - xpub
* @returns {boolean} * @returns {object}
*/ */
importInProgress(xpub) { importInProgress(xpub) {
return this.importing[xpub] ? true : false return this.importing[xpub] ? this.importing[xpub] : null
} }
/** /**
@ -147,7 +149,11 @@ class RemoteImporter {
return Promise.reject(errors.xpub.OVERLAP) return Promise.reject(errors.xpub.OVERLAP)
} }
this.importing[xpub] = true this.importing[xpub] = {
'status': this.STATUS_RESCAN,
'txs_ext': 0,
'txs_int': 0
}
const ts = hdaHelper.typeString(type) const ts = hdaHelper.typeString(type)
Logger.info(`Importer : Importing ${xpub} ${ts}`) Logger.info(`Importer : Importing ${xpub} ${ts}`)
@ -182,6 +188,11 @@ class RemoteImporter {
addresses = addresses.concat(result.addresses) addresses = addresses.concat(result.addresses)
} }
this.importing[xpub] = {
'status': this.STATUS_IMPORT,
'txs': txns.length
}
// Store the hdaccount and the addresses into the database // Store the hdaccount and the addresses into the database
await db.ensureHDAccountId(xpub, type) await db.ensureHDAccountId(xpub, type)
await db.addAddressesToHDAccount(xpub, addresses) await db.addAddressesToHDAccount(xpub, addresses)
@ -290,6 +301,10 @@ class RemoteImporter {
} }
if (gotTransactions) { if (gotTransactions) {
if (c == 0)
this.importing[xpub]['txs_ext'] = Object.keys(txids).length
else
this.importing[xpub]['txs_int'] = Object.keys(txids).length
// We must go deeper // We must go deeper
const result = await this.xpubScan(xpub, c, d, u, G, type, txids) const result = await this.xpubScan(xpub, c, d, u, G, type, txids)
// Accumulate results from further down the rabbit hole // Accumulate results from further down the rabbit hole

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

@ -94,25 +94,17 @@ const screenXpubsToolsScript = {
jsonData['segwit'] = 'bip84' jsonData['segwit'] = 'bip84'
} }
return lib_api.postXpub(jsonData) try {
.then(result => { lib_api.postXpub(jsonData)
// Successful import // Wait for import completion and display progress
this.checkRescanStatus(() => {
this._searchXpub(this.currentXpub).then(() => { this._searchXpub(this.currentXpub).then(() => {
lib_msg.displayInfo('Import complete') lib_msg.displayInfo('Import complete')
}) })
}).catch(e => {
// Check if import has timeout'd or if we have an error
if (e['status'] == 502 || e['status'] == 504) {
// Wait for import completion
this.checkRescanStatus(() => {
this._searchXpub(this.currentXpub).then(() => {
lib_msg.displayInfo('Import complete')
})
})
} else {
lib_errors.processError(e)
}
}) })
} catch(e) {
lib_errors.processError(e)
}
}, },
rescanXpub: function() { rescanXpub: function() {
@ -121,35 +113,31 @@ const screenXpubsToolsScript = {
startIdx = (startIdx == null) ? 0 : parseInt(startIdx) startIdx = (startIdx == null) ? 0 : parseInt(startIdx)
let lookahead = $('#rescan-lookahead').val() let lookahead = $('#rescan-lookahead').val()
lookahead = (lookahead == null) ? 100 : parseInt(lookahead) lookahead = (lookahead == null) ? 100 : parseInt(lookahead)
return lib_api.getXpubRescan(this.currentXpub, lookahead, startIdx)
.then(() => { try {
// Successful rescan lib_api.getXpubRescan(this.currentXpub, lookahead, startIdx)
// Wait for rescan completion and display progress
this.checkRescanStatus(() => {
this.hideRescanForm() this.hideRescanForm()
this._searchXpub(this.currentXpub).then(() => { this._searchXpub(this.currentXpub).then(() => {
lib_msg.displayInfo('Rescan complete') lib_msg.displayInfo('Rescan complete')
}) })
}).catch(e => {
// Check if rescan has timeout'd or if we have an error
if (e['status'] == 502 || e['status'] == 504) {
// Wait for rescan completion
this.checkRescanStatus(() => {
this.hideRescanForm()
this._searchXpub(this.currentXpub).then(() => {
lib_msg.displayInfo('Rescan complete')
})
})
} else {
lib_errors.processError(e)
}
}) })
} catch(e) {
lib_errors.processError(e)
}
}, },
checkRescanStatus: function(callback) { checkRescanStatus: function(callback) {
this.rescanStatusTimerId = setTimeout(() => { this.rescanStatusTimerId = setTimeout(() => {
lib_api.getXpubRescanStatus(this.currentXpub) lib_api.getXpubRescanStatus(this.currentXpub)
.then(result => { .then(result => {
if (result['data']['import_in_progress']) { const data = result['data']
lib_msg.displayMessage('Rescan in progress. Please wait...'); if (data['import_in_progress']) {
const lblOp = (data['status'] == 'rescan') ? 'Rescan' : 'Import'
const lblHits = (data['status'] == 'rescan') ? 'hits detected' : 'transactions imported'
const msg = `${lblOp} in progress (${data['hits']} ${lblHits})`
lib_msg.displayMessage(msg)
return this.checkRescanStatus(callback) return this.checkRescanStatus(callback)
} else { } else {
clearTimeout(this.rescanStatusTimerId) clearTimeout(this.rescanStatusTimerId)
@ -157,10 +145,10 @@ const screenXpubsToolsScript = {
} }
}).catch(e => { }).catch(e => {
lib_errors.processError(e) lib_errors.processError(e)
lib_msg.displayMessage('Rescan in progress. Please wait...'); lib_msg.displayMessage('Rescan in progress. Please wait...')
return this.checkRescanStatus(callback) return this.checkRescanStatus(callback)
}) })
}, 10000) }, 1000)
}, },
setXpubDetails: function(xpubInfo) { setXpubDetails: function(xpubInfo) {

Loading…
Cancel
Save