UNPKG

hsd

Version:
165 lines (124 loc) 2.94 kB
/*! * common.js - commonly required functions for wallet. * Copyright (c) 2017-2018, Christopher Jeffrey (MIT License). * https://github.com/handshake-org/hsd */ 'use strict'; const {BufferMap} = require('buffer-map'); /** @typedef {import('../primitives/tx')} TX */ /** @typedef {import('../primitives/txmeta')} TXMeta */ /** @typedef {import('../primitives/coin')} Coin */ /** * @exports wallet/common */ const common = exports; /** * Test whether a string is eligible * to be used as a name or ID. * @param {String} key * @returns {Boolean} */ common.isName = function isName(key) { if (typeof key !== 'string') return false; if (key.length === 0) return false; if (!/^[\-\._0-9A-Za-z]+$/.test(key)) return false; // Prevents __proto__ // from being used. switch (key[0]) { case '_': case '-': case '.': return false; } switch (key[key.length - 1]) { case '_': case '-': case '.': return false; } return key.length >= 1 && key.length <= 40; }; /** * Sort an array of transactions by time. * @param {TXMeta[]} txs * @returns {TXMeta[]} */ common.sortTX = function sortTX(txs) { return txs.sort((a, b) => { return a.mtime - b.mtime; }); }; /** * Sort an array of coins by height. * @param {Coin[]} coins * @returns {Coin[]} */ common.sortCoins = function sortCoins(coins) { return coins.sort((a, b) => { const ah = a.height === -1 ? 0x7fffffff : a.height; const bh = b.height === -1 ? 0x7fffffff : b.height; return ah - bh; }); }; /** * Sort an array of transactions in dependency order. * @param {TX[]} txs * @returns {TX[]} */ common.sortDeps = function sortDeps(txs) { const map = new BufferMap(); for (const tx of txs) { const hash = tx.hash(); map.set(hash, tx); } const depMap = new BufferMap(); const depCount = new BufferMap(); const top = []; for (const [hash, tx] of map) { depCount.set(hash, 0); let hasDeps = false; for (const input of tx.inputs) { const prev = input.prevout.hash; if (!map.has(prev)) continue; const count = depCount.get(hash); depCount.set(hash, count + 1); hasDeps = true; if (!depMap.has(prev)) depMap.set(prev, []); depMap.get(prev).push(tx); } if (hasDeps) continue; top.push(tx); } const result = []; for (const tx of top) { const hash = tx.hash(); const deps = depMap.get(hash); result.push(tx); if (!deps) continue; for (const tx of deps) { const hash = tx.hash(); let count = depCount.get(hash); if (--count === 0) top.push(tx); depCount.set(hash, count); } } return result; }; /** * Wallet coin selection types. * @enum {String} */ common.coinSelectionTypes = { DB_ALL: 'db-all', DB_VALUE: 'db-value', DB_SWEEPDUST: 'db-sweepdust', DB_AGE: 'db-age' };