You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
160 lines
4.5 KiB
160 lines
4.5 KiB
/*!
|
|
* accounts/api-helper.js
|
|
* Copyright © 2019 – Katana Cryptographic Ltd. All Rights Reserved.
|
|
*/
|
|
'use strict'
|
|
|
|
const bitcoin = require('bitcoinjs-lib')
|
|
const validator = require('validator')
|
|
const Logger = require('../lib/logger')
|
|
const errors = require('../lib/errors')
|
|
const WalletEntities = require('../lib/wallet/wallet-entities')
|
|
const network = require('../lib/bitcoin/network')
|
|
const activeNet = network.network
|
|
const hdaHelper = require('../lib/bitcoin/hd-accounts-helper')
|
|
const addrHelper = require('../lib/bitcoin/addresses-helper')
|
|
const HttpServer = require('../lib/http-server/http-server')
|
|
|
|
|
|
/**
|
|
* A singleton providing util methods used by the API
|
|
*/
|
|
class ApiHelper {
|
|
|
|
/**
|
|
* Parse a string and extract (x|y|z|t|u|v)pubs, addresses and pubkeys
|
|
* @param {string} str - list of entities separated by '|'
|
|
* @returns {object} returns a WalletEntities object
|
|
*/
|
|
parseEntities(str) {
|
|
const ret = new WalletEntities()
|
|
|
|
if (typeof str !== 'string')
|
|
return ret
|
|
|
|
for (let item of str.split('|')) {
|
|
try {
|
|
|
|
if (hdaHelper.isValid(item) && !ret.hasXPub(item)) {
|
|
const xpub = hdaHelper.xlatXPUB(item)
|
|
|
|
if (hdaHelper.isYpub(item))
|
|
ret.addHdAccount(xpub, item, false)
|
|
else if (hdaHelper.isZpub(item))
|
|
ret.addHdAccount(xpub, false, item)
|
|
else
|
|
ret.addHdAccount(item, false, false)
|
|
|
|
} else if (addrHelper.isSupportedPubKey(item) && !ret.hasPubKey(item)) {
|
|
// Derive pubkey as 3 addresses (P1PKH, P2WPKH/P2SH, BECH32)
|
|
const bufItem = Buffer.from(item, 'hex')
|
|
|
|
const funcs = [
|
|
addrHelper.p2pkhAddress,
|
|
addrHelper.p2wpkhP2shAddress,
|
|
addrHelper.p2wpkhAddress
|
|
]
|
|
|
|
for (let f of funcs) {
|
|
const addr = f(bufItem)
|
|
if (ret.hasAddress(addr))
|
|
ret.updatePubKey(addr, item)
|
|
else
|
|
ret.addAddress(addr, item)
|
|
}
|
|
|
|
} else if (bitcoin.address.toOutputScript(item, activeNet) && !ret.hasAddress(item)) {
|
|
|
|
// Bech32 addresses are managed in lower case
|
|
if (addrHelper.isBech32(item))
|
|
item = item.toLowerCase()
|
|
ret.addAddress(item, false)
|
|
}
|
|
} catch(e) {}
|
|
}
|
|
|
|
return ret
|
|
}
|
|
|
|
/**
|
|
* Check entities passed as url params
|
|
* @param {object} params - request query or body object
|
|
* @returns {boolean} return true if conditions are met, false otherwise
|
|
*/
|
|
checkEntitiesParams(params) {
|
|
return params.active
|
|
|| params.new
|
|
|| params.pubkey
|
|
|| params.bip49
|
|
|| params.bip84
|
|
}
|
|
|
|
/**
|
|
* Parse the entities passed as arguments of an url
|
|
* @param {object} params - request query or body object
|
|
* @returns {object} return a mapping object
|
|
* {active:..., legacy:..., pubkey:..., bip49:..., bip84:...}
|
|
*/
|
|
parseEntitiesParams(params) {
|
|
return {
|
|
active: this.parseEntities(params.active),
|
|
legacy: this.parseEntities(params.new),
|
|
pubkey: this.parseEntities(params.pubkey),
|
|
bip49: this.parseEntities(params.bip49),
|
|
bip84: this.parseEntities(params.bip84)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Express middleware validating if entities params are well formed
|
|
* @param {object} req - http request object
|
|
* @param {object} res - http response object
|
|
* @param {function} next - next tiny-http middleware
|
|
*/
|
|
validateEntitiesParams(req, res, next) {
|
|
const params = this.checkEntitiesParams(req.query) ? req.query : req.body
|
|
|
|
let isValid = true
|
|
|
|
if (params.active && !this.subValidateEntitiesParams(params.active))
|
|
isValid &= false
|
|
|
|
if (params.new && !this.subValidateEntitiesParams(params.new))
|
|
isValid &= false
|
|
|
|
if (params.pubkey && !this.subValidateEntitiesParams(params.pubkey))
|
|
isValid &= false
|
|
|
|
if (params.bip49 && !this.subValidateEntitiesParams(params.bip49))
|
|
isValid &= false
|
|
|
|
if (params.bip84 && !this.subValidateEntitiesParams(params.bip84))
|
|
isValid &= false
|
|
|
|
if (isValid) {
|
|
next()
|
|
} else {
|
|
HttpServer.sendError(res, errors.body.INVDATA)
|
|
Logger.error(
|
|
params,
|
|
`API : ApiHelper.validateEntitiesParams() : Invalid arguments`
|
|
)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validate a request argument
|
|
* @param {string} arg - request argument
|
|
*/
|
|
subValidateEntitiesParams(arg) {
|
|
for (let item of arg.split('|')) {
|
|
const isValid = validator.isAlphanumeric(item)
|
|
if (!isValid)
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
}
|
|
|
|
module.exports = new ApiHelper()
|
|
|