UNPKG

@owstack/wallet-service

Version:

A service for multisignature HD wallets

151 lines (127 loc) 3.89 kB
const owsCommon = require('@owstack/ows-common'); const BufferReader = owsCommon.encoding.BufferReader; const Hash = owsCommon.Hash; const secp256k1 = require('secp256k1'); const lodash = owsCommon.deps.lodash; const $ = require('preconditions').singleton(); class Utils { constructor(context) { // Context defines the coin network and is set by the implementing service in // order to instance this base service; e.g., btc-service. context.inject(this); // Set some frequently used contant values based on context. this.atomicsAccessor = this.ctx.Unit().atomicsAccessor(); } } Utils.prototype.formatAmount = function (atomic, code, opts) { $.shouldBeNumber(atomic); return this.ctx.Unit(atomic, 'atomic').toString(code, opts); }; Utils.prototype.formatAmountInStandard = function (atomic) { $.shouldBeNumber(atomic); return this.ctx.Unit(atomic, 'atomic').toString('standard'); }; Utils.prototype.formatUtxos = function (utxos) { const self = this; if (lodash.isEmpty(utxos)) { return 'none'; } return lodash.map([].concat(utxos), function (i) { const amount = self.formatAmountInStandard(i[self.atomicsAccessor]); const confirmations = i.confirmations ? `${i.confirmations }c` : 'u'; return `${amount }/${ confirmations}`; }).join(', '); }; Utils.getMissingFields = function (obj, args) { args = [].concat(args); if (!lodash.isObject(obj)) { return args; } const missing = lodash.filter(args, function (arg) { return !obj.hasOwnProperty(arg); }); return missing; }; /** * @desc rounds a Javascript number * @param number * @return {number} */ Utils.strip = function (number) { return parseFloat(number.toPrecision(12)); }; Utils.hashMessage = function (text, noReverse) { $.checkArgument(text); const buf = Buffer.from(text); let ret = Hash.sha256sha256(buf); if (!noReverse) { ret = new BufferReader(ret).readReverse(); } return ret; }; Utils.verifyMessage = function (text, signature, publicKey) { $.checkArgument(text); const hash = Utils.hashMessage(text, true); const sig = this._tryImportSignature(signature); if (!sig) { return false; } const publicKeyBuffer = this._tryImportPublicKey(publicKey); if (!publicKeyBuffer) { return false; } return this._tryVerifyMessage(hash, sig, publicKeyBuffer); }; Utils._tryImportPublicKey = function (publicKey) { let publicKeyBuffer = publicKey; try { if (!Buffer.isBuffer(publicKey)) { publicKeyBuffer = Buffer.from(publicKey, 'hex'); } return publicKeyBuffer; } catch (e) { return false; } }; Utils._tryImportSignature = function (signature) { try { let signatureBuffer = signature; if (!Buffer.isBuffer(signature)) { signatureBuffer = Buffer.from(signature, 'hex'); } return secp256k1.signatureImport(signatureBuffer); } catch (e) { return false; } }; Utils._tryVerifyMessage = function (hash, sig, publicKeyBuffer) { try { return secp256k1.verify(hash, sig, publicKeyBuffer); } catch (e) { return false; } }; Utils.formatRatio = function (ratio) { return `${(ratio * 100.).toFixed(4) }%`; }; Utils.formatSize = function (size) { return `${(size / 1000.).toFixed(4) }kB`; }; Utils.parseVersion = function (version) { const v = {}; if (!version) { return null; } let x = version.split('-'); if (x.length != 2) { v.agent = version; return v; } v.agent = lodash.includes(['wc', 'ws'], x[0]) ? 'wc' : x[0]; x = x[1].split('.'); v.major = parseInt(x[0]); v.minor = parseInt(x[1]); v.patch = parseInt(x[2]); return v; }; module.exports = Utils;