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.
 
 
 
 
 
 

162 lines
4.6 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) {
Logger.error(e, 'API : ApiHelper.parseEntities() : Invalid arguments')
}
}
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()