diff --git a/packages/bitcore-lib/docs/networks.md b/packages/bitcore-lib/docs/networks.md index d4487914104..a4cd1ff646f 100644 --- a/packages/bitcore-lib/docs/networks.md +++ b/packages/bitcore-lib/docs/networks.md @@ -33,7 +33,7 @@ Take a look at this modified snippet from [networks.js](https://github.com/bitpa ```javascript var livenet = new Network(); -_.extend(livenet, { +Object.assign(livenet, { name: 'livenet', alias: 'mainnet', pubkeyhash: 0x00, @@ -45,7 +45,7 @@ _.extend(livenet, { }); var testnet = new Network(); -_.extend(testnet, { +Object.assign(testnet, { name: 'testnet', alias: 'testnet', pubkeyhash: 0x6f, diff --git a/packages/bitcore-lib/index.js b/packages/bitcore-lib/index.js index 4cbe6bf2ac6..a3328541913 100644 --- a/packages/bitcore-lib/index.js +++ b/packages/bitcore-lib/index.js @@ -64,7 +64,6 @@ bitcore.deps.bnjs = require('bn.js'); bitcore.deps.bs58 = require('bs58'); bitcore.deps.Buffer = Buffer; bitcore.deps.elliptic = require('elliptic'); -bitcore.deps._ = require('lodash'); // Internal usage, exposed for testing/advanced tweaking bitcore.Transaction.sighash = require('./lib/transaction/sighash'); diff --git a/packages/bitcore-lib/lib/address.js b/packages/bitcore-lib/lib/address.js index ead78aaab0b..b11aacf2630 100644 --- a/packages/bitcore-lib/lib/address.js +++ b/packages/bitcore-lib/lib/address.js @@ -1,6 +1,5 @@ 'use strict'; -var _ = require('lodash'); var $ = require('./util/preconditions'); var errors = require('./errors'); var Base58Check = require('./encoding/base58check'); @@ -57,7 +56,7 @@ function Address(data, network, type, multisigType) { return new Address(data, network, type); } - if (_.isArray(data) && _.isNumber(network)) { + if (Array.isArray(data) && typeof network === 'number') { return Address.createMultisig(data, network, type, false, multisigType); } @@ -116,7 +115,7 @@ Address.prototype._classifyArguments = function(data, network, type) { return Address._transformScript(data, network); } else if (typeof(data) === 'string') { return Address._transformString(data, network, type); - } else if (_.isObject(data)) { + } else if (typeof data === 'object') { return Address._transformObject(data); } else { throw new TypeError('First argument is an unrecognized data format.'); @@ -334,9 +333,9 @@ Address.createMultisig = function(publicKeys, threshold, network, nestedWitness, throw new TypeError('Type must be either scripthash or witnessscripthash to create multisig.'); } if (nestedWitness || type === Address.PayToWitnessScriptHash) { - publicKeys = _.map(publicKeys, PublicKey); - for (var i = 0; i < publicKeys.length; i++) { - if (!publicKeys[i].compressed) { + publicKeys = publicKeys.map(pubKey => PublicKey(pubKey)); + for (let { compressed } of publicKeys) { + if (!compressed) { throw new TypeError('Witness addresses must use compressed public keys.'); } } diff --git a/packages/bitcore-lib/lib/block/block.js b/packages/bitcore-lib/lib/block/block.js index 7f0a024f4d2..fd1d4eb7764 100644 --- a/packages/bitcore-lib/lib/block/block.js +++ b/packages/bitcore-lib/lib/block/block.js @@ -1,6 +1,5 @@ 'use strict'; -var _ = require('lodash'); var BlockHeader = require('./blockheader'); var BN = require('../crypto/bn'); var BufferUtil = require('../util/buffer'); @@ -22,7 +21,7 @@ function Block(arg) { if (!(this instanceof Block)) { return new Block(arg); } - _.extend(this, Block._from(arg)); + Object.assign(this, Block._from(arg)); return this; } @@ -39,7 +38,7 @@ Block._from = function _from(arg) { var info = {}; if (BufferUtil.isBuffer(arg)) { info = Block._fromBufferReader(BufferReader(arg)); - } else if (_.isObject(arg)) { + } else if (typeof arg === 'object') { info = Block._fromObject(arg); } else { throw new TypeError('Unrecognized argument for Block'); @@ -261,7 +260,7 @@ var idProperty = { } return this._id; }, - set: _.noop + set: () => {} }; Object.defineProperty(Block.prototype, 'id', idProperty); Object.defineProperty(Block.prototype, 'hash', idProperty); diff --git a/packages/bitcore-lib/lib/block/blockheader.js b/packages/bitcore-lib/lib/block/blockheader.js index 44931228a70..e0717acbe56 100644 --- a/packages/bitcore-lib/lib/block/blockheader.js +++ b/packages/bitcore-lib/lib/block/blockheader.js @@ -1,6 +1,5 @@ 'use strict'; -var _ = require('lodash'); var BN = require('../crypto/bn'); var BufferUtil = require('../util/buffer'); var BufferReader = require('../encoding/bufferreader'); @@ -52,7 +51,7 @@ BlockHeader._from = function _from(arg) { var info = {}; if (BufferUtil.isBuffer(arg)) { info = BlockHeader._fromBufferReader(BufferReader(arg)); - } else if (_.isObject(arg)) { + } else if (typeof arg === 'object') { info = BlockHeader._fromObject(arg); } else { throw new TypeError('Unrecognized argument for BlockHeader'); @@ -69,10 +68,10 @@ BlockHeader._fromObject = function _fromObject(data) { $.checkArgument(data, 'data is required'); var prevHash = data.prevHash; var merkleRoot = data.merkleRoot; - if (_.isString(data.prevHash)) { + if (typeof data.prevHash === 'string') { prevHash = BufferUtil.reverse(Buffer.from(data.prevHash, 'hex')); } - if (_.isString(data.merkleRoot)) { + if (typeof data.merkleRoot === 'string') { merkleRoot = BufferUtil.reverse(Buffer.from(data.merkleRoot, 'hex')); } var info = { @@ -251,7 +250,7 @@ var idProperty = { } return this._id; }, - set: _.noop + set: () => {} }; Object.defineProperty(BlockHeader.prototype, 'id', idProperty); Object.defineProperty(BlockHeader.prototype, 'hash', idProperty); diff --git a/packages/bitcore-lib/lib/block/merkleblock.js b/packages/bitcore-lib/lib/block/merkleblock.js index 1b949c3f942..3bb33fe298e 100644 --- a/packages/bitcore-lib/lib/block/merkleblock.js +++ b/packages/bitcore-lib/lib/block/merkleblock.js @@ -1,12 +1,10 @@ 'use strict'; -var _ = require('lodash'); var BlockHeader = require('./blockheader'); var BufferUtil = require('../util/buffer'); var BufferReader = require('../encoding/bufferreader'); var BufferWriter = require('../encoding/bufferwriter'); var Hash = require('../crypto/hash'); -var JSUtil = require('../util/js'); var Transaction = require('../transaction'); var errors = require('../errors'); var $ = require('../util/preconditions'); @@ -29,7 +27,7 @@ function MerkleBlock(arg) { var info = {}; if (BufferUtil.isBuffer(arg)) { info = MerkleBlock._fromBufferReader(BufferReader(arg)); - } else if (_.isObject(arg)) { + } else if (typeof arg === 'object') { var header; if(arg.header instanceof BlockHeader) { header = arg.header; @@ -61,7 +59,7 @@ function MerkleBlock(arg) { } else { throw new TypeError('Unrecognized argument for MerkleBlock'); } - _.extend(this,info); + Object.assign(this, info); this._flagBitsUsed = 0; this._hashesUsed = 0; @@ -129,8 +127,8 @@ MerkleBlock.prototype.toObject = MerkleBlock.prototype.toJSON = function toObjec * @returns {Boolean} - True/False whether this MerkleBlock is Valid */ MerkleBlock.prototype.validMerkleTree = function validMerkleTree() { - $.checkState(_.isArray(this.flags), 'MerkleBlock flags is not an array'); - $.checkState(_.isArray(this.hashes), 'MerkleBlock hashes is not an array'); + $.checkState(Array.isArray(this.flags), 'MerkleBlock flags is not an array'); + $.checkState(Array.isArray(this.hashes), 'MerkleBlock hashes is not an array'); // Can't have more hashes than numTransactions if(this.hashes.length > this.numTransactions) { @@ -156,8 +154,8 @@ MerkleBlock.prototype.validMerkleTree = function validMerkleTree() { * @returns {Array} - txs hash that match the filter */ MerkleBlock.prototype.filterdTxsHash = function filterdTxsHash() { - $.checkState(_.isArray(this.flags), 'MerkleBlock flags is not an array'); - $.checkState(_.isArray(this.hashes), 'MerkleBlock hashes is not an array'); + $.checkState(Array.isArray(this.flags), 'MerkleBlock flags is not an array'); + $.checkState(Array.isArray(this.hashes), 'MerkleBlock hashes is not an array'); // Can't have more hashes than numTransactions if(this.hashes.length > this.numTransactions) { @@ -263,7 +261,7 @@ MerkleBlock.prototype._calcTreeHeight = function calcTreeHeight() { * @private */ MerkleBlock.prototype.hasTransaction = function hasTransaction(tx) { - $.checkArgument(!_.isUndefined(tx), 'tx cannot be undefined'); + $.checkArgument(tx !== undefined, 'tx cannot be undefined'); $.checkArgument(tx instanceof Transaction || typeof tx === 'string', 'Invalid tx given, tx must be a "string" or "Transaction"'); diff --git a/packages/bitcore-lib/lib/crypto/bn.js b/packages/bitcore-lib/lib/crypto/bn.js index b296c00368e..c838970659b 100644 --- a/packages/bitcore-lib/lib/crypto/bn.js +++ b/packages/bitcore-lib/lib/crypto/bn.js @@ -2,7 +2,6 @@ var BN = require('bn.js'); var $ = require('../util/preconditions'); -var _ = require('lodash'); var reversebuf = function(buf) { var buf2 = Buffer.alloc(buf.length); @@ -17,17 +16,17 @@ BN.One = new BN(1); BN.Minus1 = new BN(-1); BN.fromNumber = function(n) { - $.checkArgument(_.isNumber(n)); + $.checkArgument(typeof n === 'number'); return new BN(n); }; BN.fromString = function(str, base) { - $.checkArgument(_.isString(str)); + $.checkArgument(typeof str === 'string'); return new BN(str, base); }; BN.fromBuffer = function(buf, opts) { - if (typeof opts !== 'undefined' && opts.endian === 'little') { + if (opts !== undefined && opts.endian === 'little') { buf = reversebuf(buf); } var hex = buf.toString('hex'); @@ -87,7 +86,7 @@ BN.prototype.toBuffer = function(opts) { buf = Buffer.from(hex, 'hex'); } - if (typeof opts !== 'undefined' && opts.endian === 'little') { + if (opts !== undefined && opts.endian === 'little') { buf = reversebuf(buf); } diff --git a/packages/bitcore-lib/lib/crypto/ecdsa.js b/packages/bitcore-lib/lib/crypto/ecdsa.js index 6bea796b8a1..c59ff92d038 100644 --- a/packages/bitcore-lib/lib/crypto/ecdsa.js +++ b/packages/bitcore-lib/lib/crypto/ecdsa.js @@ -7,7 +7,6 @@ var PublicKey = require('../publickey'); var Random = require('./random'); var Hash = require('./hash'); var BufferUtil = require('../util/buffer'); -var _ = require('lodash'); var $ = require('../util/preconditions'); var ECDSA = function ECDSA(obj) { @@ -73,14 +72,11 @@ ECDSA.prototype.randomK = function() { // https://tools.ietf.org/html/rfc6979#section-3.2 -ECDSA.prototype.deterministicK = function(badrs) { +ECDSA.prototype.deterministicK = function(badrs = 0) { /* jshint maxstatements: 25 */ // if r or s were invalid when this function was used in signing, // we do not want to actually compute r, s here for efficiency, so, // we can increment badrs. explained at end of RFC 6979 section 3.2 - if (_.isUndefined(badrs)) { - badrs = 0; - } var v = Buffer.alloc(32); v.fill(0x01); var k = Buffer.alloc(32); diff --git a/packages/bitcore-lib/lib/crypto/signature.js b/packages/bitcore-lib/lib/crypto/signature.js index 6ba6053177d..611ee4e2856 100644 --- a/packages/bitcore-lib/lib/crypto/signature.js +++ b/packages/bitcore-lib/lib/crypto/signature.js @@ -1,7 +1,6 @@ 'use strict'; var BN = require('./bn'); -var _ = require('lodash'); var $ = require('../util/preconditions'); var BufferUtil = require('../util/buffer'); var JSUtil = require('../util/js'); @@ -26,8 +25,8 @@ Signature.prototype.set = function(obj) { this.r = obj.r || this.r || undefined; this.s = obj.s || this.s || undefined; - this.i = typeof obj.i !== 'undefined' ? obj.i : this.i; //public key recovery parameter in range [0, 3] - this.compressed = typeof obj.compressed !== 'undefined' ? + this.i = obj.i !== undefined ? obj.i : this.i; //public key recovery parameter in range [0, 3] + this.compressed = obj.compressed !== undefined ? obj.compressed : this.compressed; //whether the recovered pubkey is compressed this.nhashtype = obj.nhashtype || this.nhashtype || undefined; return this; @@ -88,11 +87,8 @@ Signature.fromString = function(str) { /** * In order to mimic the non-strict DER encoding of OpenSSL, set strict = false. */ -Signature.parseDER = function(buf, strict) { +Signature.parseDER = function(buf, strict = true) { $.checkArgument(BufferUtil.isBuffer(buf), new Error('DER formatted signature should be a buffer')); - if (_.isUndefined(strict)) { - strict = true; - } var header = buf[0]; $.checkArgument(header === 0x30, new Error('Header byte should be 0x30')); diff --git a/packages/bitcore-lib/lib/encoding/base58.js b/packages/bitcore-lib/lib/encoding/base58.js index a2b606fa19b..30c7c8a5547 100644 --- a/packages/bitcore-lib/lib/encoding/base58.js +++ b/packages/bitcore-lib/lib/encoding/base58.js @@ -1,6 +1,5 @@ 'use strict'; -var _ = require('lodash'); var bs58 = require('bs58'); var buffer = require('buffer'); @@ -26,7 +25,7 @@ Base58.validCharacters = function validCharacters(chars) { if (buffer.Buffer.isBuffer(chars)) { chars = chars.toString(); } - return _.every(_.map(chars, function(char) { return _.includes(ALPHABET, char); })); + return [...chars].every(char => ALPHABET.includes(char)); }; Base58.prototype.set = function(obj) { diff --git a/packages/bitcore-lib/lib/encoding/base58check.js b/packages/bitcore-lib/lib/encoding/base58check.js index d768ec3c9c5..86c75d3b8a5 100644 --- a/packages/bitcore-lib/lib/encoding/base58check.js +++ b/packages/bitcore-lib/lib/encoding/base58check.js @@ -1,6 +1,5 @@ 'use strict'; -var _ = require('lodash'); var Base58 = require('./base58'); var buffer = require('buffer'); var sha256sha256 = require('../crypto/hash').sha256sha256; @@ -25,10 +24,10 @@ Base58Check.prototype.set = function(obj) { }; Base58Check.validChecksum = function validChecksum(data, checksum) { - if (_.isString(data)) { + if (typeof data === 'string') { data = Buffer.from(Base58.decode(data)); } - if (_.isString(checksum)) { + if (typeof checksum === 'string') { checksum = Buffer.from(Base58.decode(checksum)); } if (!checksum) { diff --git a/packages/bitcore-lib/lib/encoding/bufferreader.js b/packages/bitcore-lib/lib/encoding/bufferreader.js index 6818e4d8a96..472b60f21f2 100644 --- a/packages/bitcore-lib/lib/encoding/bufferreader.js +++ b/packages/bitcore-lib/lib/encoding/bufferreader.js @@ -1,6 +1,5 @@ 'use strict'; -var _ = require('lodash'); var $ = require('../util/preconditions'); var BufferUtil = require('../util/buffer'); var BN = require('../crypto/bn'); @@ -9,18 +8,18 @@ var BufferReader = function BufferReader(buf) { if (!(this instanceof BufferReader)) { return new BufferReader(buf); } - if (_.isUndefined(buf)) { + if (buf === undefined) { return; } if (Buffer.isBuffer(buf)) { this.set({ buf: buf }); - } else if (_.isString(buf)) { + } else if (typeof buf === 'string') { this.set({ buf: Buffer.from(buf, 'hex'), }); - } else if (_.isObject(buf)) { + } else if (typeof buf === 'object') { var obj = buf; this.set(obj); } else { @@ -45,7 +44,7 @@ BufferReader.prototype.eof = function() { BufferReader.prototype.finished = BufferReader.prototype.eof; BufferReader.prototype.read = function(len) { - $.checkArgument(!_.isUndefined(len), 'Must specify a length'); + $.checkArgument(len !== undefined, 'Must specify a length'); var buf = this.buf.slice(this.pos, this.pos + len); this.pos = this.pos + len; return buf; @@ -136,7 +135,6 @@ BufferReader.prototype.readVarintNum = function() { } else { throw new Error('number too large to retain precision - use readVarintBN'); } - break; default: return first; } @@ -191,7 +189,7 @@ BufferReader.prototype.reverse = function() { }; BufferReader.prototype.readReverse = function(len) { - if (_.isUndefined(len)) { + if (len === undefined) { len = this.buf.length; } var buf = this.buf.slice(this.pos, this.pos + len); diff --git a/packages/bitcore-lib/lib/errors/index.js b/packages/bitcore-lib/lib/errors/index.js index de6f7311ecf..1fad51848e4 100644 --- a/packages/bitcore-lib/lib/errors/index.js +++ b/packages/bitcore-lib/lib/errors/index.js @@ -1,7 +1,5 @@ 'use strict'; -var _ = require('lodash'); - function format(message, args) { return message .replace('{0}', args[0]) @@ -10,9 +8,9 @@ function format(message, args) { } var traverseNode = function(parent, errorDefinition) { var NodeError = function() { - if (_.isString(errorDefinition.message)) { + if (typeof errorDefinition.message === 'string') { this.message = format(errorDefinition.message, arguments); - } else if (_.isFunction(errorDefinition.message)) { + } else if (typeof errorDefinition.message === 'function') { this.message = errorDefinition.message.apply(null, arguments); } else { throw new Error('Invalid error definition for ' + errorDefinition.name); @@ -29,10 +27,10 @@ var traverseNode = function(parent, errorDefinition) { }; /* jshint latedef: false */ -var childDefinitions = function(parent, childDefinitions) { - _.each(childDefinitions, function(childDefinition) { +const childDefinitions = function(parent, childDefinitions) { + for (let childDefinition of childDefinitions) { traverseNode(parent, childDefinition); - }); + } }; /* jshint latedef: true */ diff --git a/packages/bitcore-lib/lib/hdprivatekey.js b/packages/bitcore-lib/lib/hdprivatekey.js index 8fc3f6c6654..efd6ab69d14 100644 --- a/packages/bitcore-lib/lib/hdprivatekey.js +++ b/packages/bitcore-lib/lib/hdprivatekey.js @@ -3,7 +3,6 @@ var assert = require('assert'); var buffer = require('buffer'); -var _ = require('lodash'); var $ = require('./util/preconditions'); var BN = require('./crypto/bn'); @@ -47,7 +46,7 @@ function HDPrivateKey(arg) { if (Network.get(arg)) { return this._generateRandomly(arg); - } else if (_.isString(arg) || BufferUtil.isBuffer(arg)) { + } else if (typeof arg === 'string' || BufferUtil.isBuffer(arg)) { if (HDPrivateKey.isValidSerialized(arg)) { this._buildFromSerialized(arg); } else if (JSUtil.isValidJSON(arg)) { @@ -57,7 +56,7 @@ function HDPrivateKey(arg) { } else { throw HDPrivateKey.getSerializedError(arg); } - } else if (_.isObject(arg)) { + } else if (typeof arg === 'object') { this._buildFromObject(arg); } else { throw new hdErrors.UnrecognizedArgument(arg); @@ -72,12 +71,12 @@ function HDPrivateKey(arg) { * @return {boolean} */ HDPrivateKey.isValidPath = function(arg, hardened) { - if (_.isString(arg)) { + if (typeof arg === 'string') { var indexes = HDPrivateKey._getDerivationIndexes(arg); - return indexes !== null && _.every(indexes, HDPrivateKey.isValidPath); + return indexes !== null && indexes.every(HDPrivateKey.isValidPath); } - if (_.isNumber(arg)) { + if (typeof arg === 'number' && !isNaN(arg)) { if (arg < HDPrivateKey.Hardened && hardened === true) { arg += HDPrivateKey.Hardened; } @@ -99,11 +98,11 @@ HDPrivateKey._getDerivationIndexes = function(path) { var steps = path.split('/'); // Special cases: - if (_.includes(HDPrivateKey.RootElementAlias, path)) { + if (HDPrivateKey.RootElementAlias.includes(path)) { return []; } - if (!_.includes(HDPrivateKey.RootElementAlias, steps[0])) { + if (!HDPrivateKey.RootElementAlias.includes(steps[0])) { return null; } @@ -123,7 +122,7 @@ HDPrivateKey._getDerivationIndexes = function(path) { return index; }); - return _.some(indexes, isNaN) ? null : indexes; + return indexes.some(isNaN) ? null : indexes; }; /** @@ -186,9 +185,9 @@ HDPrivateKey.prototype.derive = function(arg, hardened) { * @param {boolean?} hardened */ HDPrivateKey.prototype.deriveChild = function(arg, hardened) { - if (_.isNumber(arg)) { + if (typeof arg === 'number') { return this._deriveWithNumber(arg, hardened); - } else if (_.isString(arg)) { + } else if (typeof arg === 'string') { return this._deriveFromString(arg); } else { throw new hdErrors.InvalidDerivationArgument(arg); @@ -212,9 +211,9 @@ HDPrivateKey.prototype.deriveChild = function(arg, hardened) { * @param {boolean?} hardened */ HDPrivateKey.prototype.deriveNonCompliantChild = function(arg, hardened) { - if (_.isNumber(arg)) { + if (typeof arg === 'number') { return this._deriveWithNumber(arg, hardened, true); - } else if (_.isString(arg)) { + } else if (typeof arg === 'string') { return this._deriveFromString(arg, true); } else { throw new hdErrors.InvalidDerivationArgument(arg); @@ -312,7 +311,7 @@ HDPrivateKey.isValidSerialized = function(data, network) { */ HDPrivateKey.getSerializedError = function(data, network) { /* jshint maxcomplexity: 10 */ - if (!(_.isString(data) || BufferUtil.isBuffer(data))) { + if (typeof data !== 'string' && !BufferUtil.isBuffer(data)) { return new hdErrors.UnrecognizedArgument('Expected string or buffer'); } if (!Base58.validCharacters(data)) { @@ -326,7 +325,7 @@ HDPrivateKey.getSerializedError = function(data, network) { if (data.length !== HDPrivateKey.DataLength) { return new hdErrors.InvalidLength(data); } - if (!_.isUndefined(network)) { + if (network !== undefined) { var error = HDPrivateKey._validateNetwork(data, network); if (error) { return error; @@ -348,12 +347,12 @@ HDPrivateKey._validateNetwork = function(data, networkArg) { }; HDPrivateKey.fromString = function(arg) { - $.checkArgument(_.isString(arg), 'No valid string was provided'); + $.checkArgument(typeof arg === 'string', 'No valid string was provided'); return new HDPrivateKey(arg); }; HDPrivateKey.fromObject = function(arg) { - $.checkArgument(_.isObject(arg), 'No valid argument was provided'); + $.checkArgument(JSUtil.isObject(arg), 'No valid argument was provided'); return new HDPrivateKey(arg); }; @@ -366,11 +365,11 @@ HDPrivateKey.prototype._buildFromObject = function(arg) { // TODO: Type validation var buffers = { version: arg.network ? BufferUtil.integerAsBuffer(Network.get(arg.network).xprivkey) : arg.version, - depth: _.isNumber(arg.depth) ? BufferUtil.integerAsSingleByteBuffer(arg.depth) : arg.depth, - parentFingerPrint: _.isNumber(arg.parentFingerPrint) ? BufferUtil.integerAsBuffer(arg.parentFingerPrint) : arg.parentFingerPrint, - childIndex: _.isNumber(arg.childIndex) ? BufferUtil.integerAsBuffer(arg.childIndex) : arg.childIndex, - chainCode: _.isString(arg.chainCode) ? Buffer.from(arg.chainCode,'hex') : arg.chainCode, - privateKey: (_.isString(arg.privateKey) && JSUtil.isHexa(arg.privateKey)) ? Buffer.from(arg.privateKey,'hex') : arg.privateKey, + depth: typeof arg.depth === 'number' ? BufferUtil.integerAsSingleByteBuffer(arg.depth) : arg.depth, + parentFingerPrint: typeof arg.parentFingerPrint === 'number' ? BufferUtil.integerAsBuffer(arg.parentFingerPrint) : arg.parentFingerPrint, + childIndex: typeof arg.childIndex === 'number' ? BufferUtil.integerAsBuffer(arg.childIndex) : arg.childIndex, + chainCode: typeof arg.chainCode === 'string' ? Buffer.from(arg.chainCode,'hex') : arg.chainCode, + privateKey: (typeof arg.privateKey === 'string' && JSUtil.isHexa(arg.privateKey)) ? Buffer.from(arg.privateKey,'hex') : arg.privateKey, checksum: arg.checksum ? (arg.checksum.length ? arg.checksum : BufferUtil.integerAsBuffer(arg.checksum)) : undefined }; return this._buildFromBuffers(buffers); diff --git a/packages/bitcore-lib/lib/hdpublickey.js b/packages/bitcore-lib/lib/hdpublickey.js index 2e26c8c9777..cec0d211404 100644 --- a/packages/bitcore-lib/lib/hdpublickey.js +++ b/packages/bitcore-lib/lib/hdpublickey.js @@ -1,6 +1,5 @@ 'use strict'; -var _ = require('lodash'); var $ = require('./util/preconditions'); var BN = require('./crypto/bn'); @@ -38,7 +37,7 @@ function HDPublicKey(arg) { return new HDPublicKey(arg); } if (arg) { - if (_.isString(arg) || BufferUtil.isBuffer(arg)) { + if (typeof arg === 'string' || BufferUtil.isBuffer(arg)) { var error = HDPublicKey.getSerializedError(arg); if (!error) { return this._buildFromSerialized(arg); @@ -51,7 +50,7 @@ function HDPublicKey(arg) { throw error; } } else { - if (_.isObject(arg)) { + if (typeof arg === 'object') { if (arg instanceof HDPrivateKey) { return this._buildFromPrivate(arg); } else { @@ -73,12 +72,12 @@ function HDPublicKey(arg) { * @return {boolean} */ HDPublicKey.isValidPath = function(arg) { - if (_.isString(arg)) { + if (typeof arg === 'string') { var indexes = HDPrivateKey._getDerivationIndexes(arg); - return indexes !== null && _.every(indexes, HDPublicKey.isValidPath); + return indexes !== null && indexes.every(HDPublicKey.isValidPath); } - if (_.isNumber(arg)) { + if (typeof arg === 'number') { return arg >= 0 && arg < HDPublicKey.Hardened; } @@ -140,9 +139,9 @@ HDPublicKey.prototype.derive = function(arg, hardened) { * @param {string|number} arg */ HDPublicKey.prototype.deriveChild = function(arg, hardened) { - if (_.isNumber(arg)) { + if (typeof arg === 'number' && !isNaN(arg)) { return this._deriveWithNumber(arg, hardened); - } else if (_.isString(arg)) { + } else if (typeof arg === 'string') { return this._deriveFromString(arg); } else { throw new hdErrors.InvalidDerivationArgument(arg); @@ -184,7 +183,7 @@ HDPublicKey.prototype._deriveWithNumber = function(index, hardened) { HDPublicKey.prototype._deriveFromString = function(path) { /* jshint maxcomplexity: 8 */ - if (_.includes(path, "'")) { + if (path.includes("'")) { throw new hdErrors.InvalidIndexCantDeriveHardened(); } else if (!HDPublicKey.isValidPath(path)) { throw new hdErrors.InvalidPath(path); @@ -208,7 +207,7 @@ HDPublicKey.prototype._deriveFromString = function(path) { * @return {boolean} */ HDPublicKey.isValidSerialized = function(data, network) { - return _.isNull(HDPublicKey.getSerializedError(data, network)); + return HDPublicKey.getSerializedError(data, network) === null; }; /** @@ -223,7 +222,7 @@ HDPublicKey.isValidSerialized = function(data, network) { HDPublicKey.getSerializedError = function(data, network) { /* jshint maxcomplexity: 10 */ /* jshint maxstatements: 20 */ - if (!(_.isString(data) || BufferUtil.isBuffer(data))) { + if (typeof data !== 'string' && !BufferUtil.isBuffer(data)) { return new hdErrors.UnrecognizedArgument('expected buffer or string'); } if (!Base58.validCharacters(data)) { @@ -237,7 +236,7 @@ HDPublicKey.getSerializedError = function(data, network) { if (data.length !== HDPublicKey.DataSize) { return new hdErrors.InvalidLength(data); } - if (!_.isUndefined(network)) { + if (network !== undefined) { var error = HDPublicKey._validateNetwork(data, network); if (error) { return error; @@ -262,15 +261,17 @@ HDPublicKey._validateNetwork = function(data, networkArg) { return null; }; -HDPublicKey.prototype._buildFromPrivate = function (arg) { - var args = _.clone(arg._buffers); - var point = Point.getG().mul(BN.fromBuffer(args.privateKey)); - args.publicKey = Point.pointToCompressed(point); - args.version = BufferUtil.integerAsBuffer(Network.get(BufferUtil.integerFromBuffer(args.version)).xpubkey); - args.privateKey = undefined; - args.checksum = undefined; - args.xprivkey = undefined; - return this._buildFromBuffers(args); +HDPublicKey.prototype._buildFromPrivate = function(arg) { + let args = { ...arg._buffers }; + let point = Point.getG().mul(BN.fromBuffer(args.privateKey)); + return this._buildFromBuffers({ + ...args, + publicKey: Point.pointToCompressed(point), + version: BufferUtil.integerAsBuffer(Network.get(BufferUtil.integerFromBuffer(args.version)).xpubkey), + privateKey: undefined, + checksum: undefined, + xprivkey: undefined + }); }; HDPublicKey.prototype._buildFromObject = function(arg) { @@ -278,13 +279,13 @@ HDPublicKey.prototype._buildFromObject = function(arg) { // TODO: Type validation var buffers = { version: arg.network ? BufferUtil.integerAsBuffer(Network.get(arg.network).xpubkey) : arg.version, - depth: _.isNumber(arg.depth) ? BufferUtil.integerAsSingleByteBuffer(arg.depth) : arg.depth, - parentFingerPrint: _.isNumber(arg.parentFingerPrint) ? BufferUtil.integerAsBuffer(arg.parentFingerPrint) : arg.parentFingerPrint, - childIndex: _.isNumber(arg.childIndex) ? BufferUtil.integerAsBuffer(arg.childIndex) : arg.childIndex, - chainCode: _.isString(arg.chainCode) ? Buffer.from(arg.chainCode,'hex') : arg.chainCode, - publicKey: _.isString(arg.publicKey) ? Buffer.from(arg.publicKey,'hex') : + depth: typeof arg.depth === 'number' ? BufferUtil.integerAsSingleByteBuffer(arg.depth) : arg.depth, + parentFingerPrint: typeof arg.parentFingerPrint === 'number' ? BufferUtil.integerAsBuffer(arg.parentFingerPrint) : arg.parentFingerPrint, + childIndex: typeof arg.childIndex === 'number' ? BufferUtil.integerAsBuffer(arg.childIndex) : arg.childIndex, + chainCode: typeof arg.chainCode === 'string' ? Buffer.from(arg.chainCode,'hex') : arg.chainCode, + publicKey: typeof arg.publicKey === 'string' ? Buffer.from(arg.publicKey,'hex') : BufferUtil.isBuffer(arg.publicKey) ? arg.publicKey : arg.publicKey.toBuffer(), - checksum: _.isNumber(arg.checksum) ? BufferUtil.integerAsBuffer(arg.checksum) : arg.checksum + checksum: typeof arg.checksum === 'number' ? BufferUtil.integerAsBuffer(arg.checksum) : arg.checksum }; return this._buildFromBuffers(buffers); }; @@ -386,12 +387,12 @@ HDPublicKey._validateBufferArguments = function(arg) { }; HDPublicKey.fromString = function(arg) { - $.checkArgument(_.isString(arg), 'No valid string was provided'); + $.checkArgument(typeof arg === 'string', 'No valid string was provided'); return new HDPublicKey(arg); }; HDPublicKey.fromObject = function(arg) { - $.checkArgument(_.isObject(arg), 'No valid argument was provided'); + $.checkArgument(JSUtil.isObject(arg), 'No valid argument was provided'); return new HDPublicKey(arg); }; diff --git a/packages/bitcore-lib/lib/message.js b/packages/bitcore-lib/lib/message.js index b24e5a7cc80..1020b9eb27e 100644 --- a/packages/bitcore-lib/lib/message.js +++ b/packages/bitcore-lib/lib/message.js @@ -1,6 +1,5 @@ 'use strict'; -var _ = require('lodash'); var PrivateKey = require('./privatekey'); var PublicKey = require('./publickey'); var Address = require('./address'); @@ -15,7 +14,7 @@ function Message(message) { if (!(this instanceof Message)) { return new Message(message); } - $.checkArgument(_.isString(message), 'First argument should be a string'); + $.checkArgument(typeof message === 'string', 'First argument should be a string'); this.message = message; return this; @@ -76,9 +75,9 @@ Message.prototype._verify = function _verify(publicKey, signature) { */ Message.prototype.verify = function verify(bitcoinAddress, signatureString) { $.checkArgument(bitcoinAddress); - $.checkArgument(signatureString && _.isString(signatureString)); + $.checkArgument(signatureString && typeof signatureString === 'string'); - if (_.isString(bitcoinAddress)) { + if (typeof bitcoinAddress === 'string') { bitcoinAddress = Address.fromString(bitcoinAddress); } var signature = Signature.fromCompact(Buffer.from(signatureString, 'base64')); @@ -110,9 +109,9 @@ Message.prototype.verify = function verify(bitcoinAddress, signatureString) { */ Message.prototype.recoverPublicKey = function recoverPublicKey(bitcoinAddress, signatureString) { $.checkArgument(bitcoinAddress); - $.checkArgument(signatureString && _.isString(signatureString)); + $.checkArgument(signatureString && typeof signatureString === 'string'); - if (_.isString(bitcoinAddress)) { + if (typeof bitcoinAddress === 'string') { bitcoinAddress = Address.fromString(bitcoinAddress); } var signature = Signature.fromCompact(Buffer.from(signatureString, 'base64')); diff --git a/packages/bitcore-lib/lib/networks.js b/packages/bitcore-lib/lib/networks.js index cb880053370..d5fcdb189e4 100644 --- a/packages/bitcore-lib/lib/networks.js +++ b/packages/bitcore-lib/lib/networks.js @@ -1,5 +1,4 @@ 'use strict'; -var _ = require('lodash'); var BufferUtil = require('./util/buffer'); var JSUtil = require('./util/js'); @@ -31,14 +30,11 @@ function get(arg, keys) { return arg; } if (keys) { - if (!_.isArray(keys)) { + if (!Array.isArray(keys)) { keys = [keys]; } - var containsArg = function(key) { - return networks[index][key] === arg; - }; for (var index in networks) { - if (_.some(keys, containsArg)) { + if (keys.some(key => networks[index][key] === arg)) { return networks[index]; } } @@ -101,14 +97,13 @@ function addNetwork(data) { dnsSeeds: data.dnsSeeds }); } - _.each(network, function(value) { - if (!_.isUndefined(value) && !_.isObject(value)) { - if(!networkMaps[value]) { - networkMaps[value] = []; - } + + for (let value of Object.values(network)) { + if (!['undefined', 'object'].includes(typeof value)) { + networkMaps[value] = networkMaps[value] || []; networkMaps[value].push(network); } - }); + } networks.push(network); diff --git a/packages/bitcore-lib/lib/opcode.js b/packages/bitcore-lib/lib/opcode.js index 1b3a0b40f21..61bef3a0666 100644 --- a/packages/bitcore-lib/lib/opcode.js +++ b/packages/bitcore-lib/lib/opcode.js @@ -1,6 +1,5 @@ 'use strict'; -var _ = require('lodash'); var $ = require('./util/preconditions'); var BufferUtil = require('./util/buffer'); var JSUtil = require('./util/js'); @@ -12,9 +11,9 @@ function Opcode(num) { var value; - if (_.isNumber(num)) { + if (typeof num === 'number') { value = num; - } else if (_.isString(num)) { + } else if (typeof num === 'string') { value = Opcode.map[num]; } else { throw new TypeError('Unrecognized num type: "' + typeof(num) + '" for Opcode'); @@ -33,14 +32,14 @@ Opcode.fromBuffer = function(buf) { }; Opcode.fromNumber = function(num) { - $.checkArgument(_.isNumber(num)); + $.checkArgument(typeof num === 'number'); return new Opcode(num); }; Opcode.fromString = function(str) { - $.checkArgument(_.isString(str)); + $.checkArgument(typeof str === 'string'); var value = Opcode.map[str]; - if (typeof value === 'undefined') { + if (value === undefined) { throw new TypeError('Invalid opcodestr'); } return new Opcode(value); @@ -60,14 +59,14 @@ Opcode.prototype.toNumber = function() { Opcode.prototype.toString = function() { var str = Opcode.reverseMap[this.num]; - if (typeof str === 'undefined') { + if (str === undefined) { throw new Error('Opcode does not have a string representation'); } return str; }; Opcode.smallInt = function(n) { - $.checkArgument(_.isNumber(n), 'Invalid Argument: n should be number'); + $.checkArgument(typeof n === 'number' && !isNaN(n), 'Invalid Argument: n should be number'); $.checkArgument(n >= 0 && n <= 16, 'Invalid Argument: n must be between 0 and 16'); if (n === 0) { return Opcode('OP_0'); @@ -224,7 +223,7 @@ for (var k in Opcode.map) { } // Easier access to opcodes -_.extend(Opcode, Opcode.map); +Object.assign(Opcode, Opcode.map); /** * @returns true if opcode is one of OP_0, OP_1, ..., OP_16 diff --git a/packages/bitcore-lib/lib/privatekey.js b/packages/bitcore-lib/lib/privatekey.js index 6ff21050594..31f2b0549b7 100644 --- a/packages/bitcore-lib/lib/privatekey.js +++ b/packages/bitcore-lib/lib/privatekey.js @@ -1,6 +1,5 @@ 'use strict'; -var _ = require('lodash'); var Address = require('./address'); var Base58Check = require('./encoding/base58check'); var BN = require('./crypto/bn'); @@ -54,7 +53,7 @@ function PrivateKey(data, network) { if (!info.bn.lt(Point.getN())) { throw new TypeError('Number must be less than N'); } - if (typeof(info.network) === 'undefined') { + if (!info.network) { throw new TypeError('Must specify the network ("livenet" or "testnet")'); } @@ -90,7 +89,7 @@ PrivateKey.prototype._classifyArguments = function(data, network) { }; // detect type of data - if (_.isUndefined(data) || _.isNull(data)){ + if (data === undefined || data === null) { info.bn = PrivateKey._getRandomBN(); } else if (data instanceof BN) { info.bn = data; @@ -232,7 +231,7 @@ PrivateKey._transformObject = function(json) { * @returns {PrivateKey} A new valid instance of PrivateKey */ PrivateKey.fromString = PrivateKey.fromWIF = function(str) { - $.checkArgument(_.isString(str), 'First argument is expected to be a string.'); + $.checkArgument(typeof str === 'string', 'First argument is expected to be a string.'); return new PrivateKey(str); }; @@ -242,7 +241,7 @@ PrivateKey.fromString = PrivateKey.fromWIF = function(str) { * @param {Object} obj - The output from privateKey.toObject() */ PrivateKey.fromObject = function(obj) { - $.checkArgument(_.isObject(obj), 'First argument is expected to be an object.'); + $.checkArgument(typeof obj === 'object', 'First argument is expected to be an object.'); return new PrivateKey(obj); }; diff --git a/packages/bitcore-lib/lib/publickey.js b/packages/bitcore-lib/lib/publickey.js index f9c48a1ff1b..fe739e727c4 100644 --- a/packages/bitcore-lib/lib/publickey.js +++ b/packages/bitcore-lib/lib/publickey.js @@ -5,7 +5,6 @@ var Point = require('./crypto/point'); var Hash = require('./crypto/hash'); var JSUtil = require('./util/js'); var Network = require('./networks'); -var _ = require('lodash'); var $ = require('./util/preconditions'); /** @@ -69,7 +68,7 @@ function PublicKey(data, extra) { PublicKey.prototype._classifyArgs = function(data, extra) { /* jshint maxcomplexity: 10 */ var info = { - compressed: _.isUndefined(extra.compressed) || extra.compressed + compressed: extra.compressed === undefined || extra.compressed }; // detect type of data @@ -87,7 +86,7 @@ PublicKey.prototype._classifyArgs = function(data, extra) { throw new TypeError('First argument is an unrecognized data format.'); } if (!info.network) { - info.network = _.isUndefined(extra.network) ? undefined : Network.get(extra.network); + info.network = extra.network === undefined ? undefined : Network.get(extra.network); } return info; }; @@ -145,7 +144,7 @@ PublicKey._transformDER = function(buf, strict) { $.checkArgument(PublicKey._isBuffer(buf), 'Must be a hex buffer of DER encoded public key'); var info = {}; - strict = _.isUndefined(strict) ? true : strict; + strict = strict === undefined ? true : strict; var x; var y; diff --git a/packages/bitcore-lib/lib/script/interpreter.js b/packages/bitcore-lib/lib/script/interpreter.js index d158bf8ed33..40455afdd77 100644 --- a/packages/bitcore-lib/lib/script/interpreter.js +++ b/packages/bitcore-lib/lib/script/interpreter.js @@ -1,7 +1,5 @@ 'use strict'; -var _ = require('lodash'); - var Script = require('./script'); var Opcode = require('../opcode'); var BN = require('../crypto/bn'); @@ -127,24 +125,19 @@ Interpreter.prototype.verifyWitnessProgram = function(version, program, witness, * * Translated from bitcoind's VerifyScript */ -Interpreter.prototype.verify = function(scriptSig, scriptPubkey, tx, nin, flags, witness, satoshis) { - +Interpreter.prototype.verify = function( + scriptSig, + scriptPubkey, + tx, + nin = 0, + flags = 0, + witness = null, + satoshis = 0 +) { var Transaction = require('../transaction'); - if (_.isUndefined(tx)) { + if (tx === undefined) { tx = new Transaction(); } - if (_.isUndefined(nin)) { - nin = 0; - } - if (_.isUndefined(flags)) { - flags = 0; - } - if (_.isUndefined(witness)) { - witness = null; - } - if (_.isUndefined(satoshis)) { - satoshis = 0; - } this.set({ script: scriptSig, @@ -318,17 +311,17 @@ Interpreter.prototype.initialize = function(obj) { Interpreter.prototype.set = function(obj) { this.script = obj.script || this.script; this.tx = obj.tx || this.tx; - this.nin = typeof obj.nin !== 'undefined' ? obj.nin : this.nin; + this.nin = obj.nin !== undefined ? obj.nin : this.nin; this.stack = obj.stack || this.stack; this.altstack = obj.altack || this.altstack; - this.pc = typeof obj.pc !== 'undefined' ? obj.pc : this.pc; - this.pbegincodehash = typeof obj.pbegincodehash !== 'undefined' ? obj.pbegincodehash : this.pbegincodehash; - this.sigversion = typeof obj.sigversion !== 'undefined' ? obj.sigversion : this.sigversion; - this.satoshis = typeof obj.satoshis !== 'undefined' ? obj.satoshis : this.satoshis; - this.nOpCount = typeof obj.nOpCount !== 'undefined' ? obj.nOpCount : this.nOpCount; + this.pc = obj.pc !== undefined ? obj.pc : this.pc; + this.pbegincodehash = obj.pbegincodehash !== undefined ? obj.pbegincodehash : this.pbegincodehash; + this.sigversion = obj.sigversion !== undefined ? obj.sigversion : this.sigversion; + this.satoshis = obj.satoshis !== undefined ? obj.satoshis : this.satoshis; + this.nOpCount = obj.nOpCount !== undefined ? obj.nOpCount : this.nOpCount; this.vfExec = obj.vfExec || this.vfExec; this.errstr = obj.errstr || this.errstr; - this.flags = typeof obj.flags !== 'undefined' ? obj.flags : this.flags; + this.flags = obj.flags !== undefined ? obj.flags : this.flags; }; Interpreter.true = Buffer.from([1]); @@ -676,7 +669,7 @@ Interpreter.prototype.step = function() { var chunk = this.script.chunks[this.pc]; this.pc++; var opcodenum = chunk.opcodenum; - if (_.isUndefined(opcodenum)) { + if (opcodenum === undefined) { this.errstr = 'SCRIPT_ERR_UNDEFINED_OPCODE'; return false; } @@ -954,7 +947,6 @@ Interpreter.prototype.step = function() { this.errstr = 'SCRIPT_ERR_OP_RETURN'; return false; } - break; // diff --git a/packages/bitcore-lib/lib/script/script.js b/packages/bitcore-lib/lib/script/script.js index b86a2ef650d..3bd49406a72 100644 --- a/packages/bitcore-lib/lib/script/script.js +++ b/packages/bitcore-lib/lib/script/script.js @@ -9,7 +9,6 @@ var PublicKey = require('../publickey'); var Signature = require('../crypto/signature'); var Networks = require('../networks'); var $ = require('../util/preconditions'); -var _ = require('lodash'); var errors = require('../errors'); var buffer = require('buffer'); var BufferUtil = require('../util/buffer'); @@ -36,9 +35,9 @@ var Script = function Script(from) { return Script.fromAddress(from); } else if (from instanceof Script) { return Script.fromBuffer(from.toBuffer()); - } else if (_.isString(from)) { + } else if (typeof from === 'string') { return Script.fromString(from); - } else if (_.isObject(from) && _.isArray(from.chunks)) { + } else if (JSUtil.isObject(from) && Array.isArray(from.chunks)) { this.set(from); } }; @@ -47,8 +46,8 @@ Script.VERIFY_TAPROOT = (1 << 17); Script.prototype.set = function(obj) { - $.checkArgument(_.isObject(obj)); - $.checkArgument(_.isArray(obj.chunks)); + $.checkArgument(JSUtil.isObject(obj)); + $.checkArgument(Array.isArray(obj.chunks)); this.chunks = obj.chunks; return this; }; @@ -147,7 +146,7 @@ Script.fromASM = function(str) { var opcode = Opcode(token); var opcodenum = opcode.toNumber(); - if (_.isUndefined(opcodenum)) { + if (opcodenum === undefined) { var buf = Buffer.from(tokens[i], 'hex'); script.chunks.push({ buf: buf, @@ -192,7 +191,7 @@ Script.fromString = function(str) { var opcode = Opcode(token); var opcodenum = opcode.toNumber(); - if (_.isUndefined(opcodenum)) { + if (opcodenum === undefined) { opcodenum = parseInt(token); if (opcodenum > 0 && opcodenum < Opcode.OP_PUSHDATA1) { script.chunks.push({ @@ -232,7 +231,7 @@ Script.prototype._chunkToString = function(chunk, type) { var str = ''; if (!chunk.buf) { // no data chunk - if (typeof Opcode.reverseMap[opcodenum] !== 'undefined') { + if (Opcode.reverseMap[opcodenum] !== undefined) { if (asm) { // A few cases where the opcode name differs from reverseMap // aside from 1 to 16 data pushes. @@ -538,7 +537,7 @@ Script.prototype.isDataOut = function() { */ Script.prototype.getData = function() { if (this.isDataOut() || this.isScriptHashOut() || this.isWitnessScriptHashOut() || this.isWitnessPublicKeyHashOut() || this.isTaproot()) { - if (_.isUndefined(this.chunks[1])) { + if (this.chunks[1] === undefined) { return Buffer.alloc(0); } else { return Buffer.from(this.chunks[1].buf); @@ -555,7 +554,7 @@ Script.prototype.getData = function() { * opcodes or small int opcodes (OP_0, OP_1, ..., OP_16) */ Script.prototype.isPushOnly = function() { - return _.every(this.chunks, function(chunk) { + return this.chunks.every(function(chunk) { return chunk.opcodenum <= Opcode.OP_16; }); }; @@ -771,33 +770,39 @@ Script.prototype.removeCodeseparators = function() { // high level script builder methods /** - * @returns {Script} a new Multisig output script for given public keys, - * requiring m of those public keys to spend - * @param {PublicKey[]} publicKeys - list of all public keys controlling the output - * @param {number} threshold - amount of required signatures to spend the output - * @param {Object=} opts - Several options: - * - noSorting: defaults to false, if true, don't sort the given - * public keys before creating the script + * @description creates a multisig output script for given public keys, requiring m signatures to spend + * @param {PublicKey[]} publicKeys list of all public keys controlling the output + * @param {Number} threshold amount of required signatures to spend the output + * @param {Object} [opts] optional parameters + * @param {Boolean} [opts.noSorting] if set, no sorting is applied to public keys when building the script + * @returns {Script} */ -Script.buildMultisigOut = function(publicKeys, threshold, opts) { - $.checkArgument(threshold <= publicKeys.length, - 'Number of required signatures must be less than or equal to the number of public keys'); - opts = opts || {}; - var script = new Script(); +Script.buildMultisigOut = function(publicKeys, threshold, opts = {}) { + $.checkArgument( + threshold <= publicKeys.length, + 'Number of required signatures must be less than or equal to the number of public keys' + ); + + const script = new Script(); + + // add opcode for the threshold to script script.add(Opcode.smallInt(threshold)); - publicKeys = _.map(publicKeys, PublicKey); - var sorted = publicKeys; + + // add pubkey buffers to script + let pubKeys = publicKeys.map(PublicKey); if (!opts.noSorting) { - sorted = _.sortBy(publicKeys, function(publicKey) { - return publicKey.toString('hex'); - }); + JSUtil.sort(pubKeys); } - for (var i = 0; i < sorted.length; i++) { - var publicKey = sorted[i]; - script.add(publicKey.toBuffer()); + for (let pubKey of pubKeys) { + script.add(pubKey.toBuffer()); } - script.add(Opcode.smallInt(publicKeys.length)); + + // add opcode for the number of keys to script + script.add(Opcode.smallInt(pubKeys.length)); + + // add opcode for multisig check to script script.add(Opcode.OP_CHECKMULTISIG); + return script; }; @@ -825,17 +830,17 @@ Script.buildWitnessMultisigOutFromScript = function(script) { * @returns {Script} */ Script.buildMultisigIn = function(pubkeys, threshold, signatures, opts) { - $.checkArgument(_.isArray(pubkeys)); - $.checkArgument(_.isNumber(threshold)); - $.checkArgument(_.isArray(signatures)); + $.checkArgument(Array.isArray(pubkeys)); + $.checkArgument(typeof threshold === 'number'); + $.checkArgument(Array.isArray(signatures)); opts = opts || {}; var s = new Script(); s.add(Opcode.OP_0); - _.each(signatures, function(signature) { - $.checkArgument(BufferUtil.isBuffer(signature), 'Signatures must be an array of Buffers'); + for (let signature of signatures) { // TODO: allow signatures to be an array of Signature objects + $.checkArgument(BufferUtil.isBuffer(signature), 'Signatures must be an array of Buffers'); s.add(signature); - }); + } return s; }; @@ -852,17 +857,17 @@ Script.buildMultisigIn = function(pubkeys, threshold, signatures, opts) { * @returns {Script} */ Script.buildP2SHMultisigIn = function(pubkeys, threshold, signatures, opts) { - $.checkArgument(_.isArray(pubkeys)); - $.checkArgument(_.isNumber(threshold)); - $.checkArgument(_.isArray(signatures)); + $.checkArgument(Array.isArray(pubkeys)); + $.checkArgument(typeof threshold === 'number' && !isNaN(threshold)); + $.checkArgument(Array.isArray(signatures)); opts = opts || {}; var s = new Script(); s.add(Opcode.OP_0); - _.each(signatures, function(signature) { - $.checkArgument(BufferUtil.isBuffer(signature), 'Signatures must be an array of Buffers'); + for (let signature of signatures) { // TODO: allow signatures to be an array of Signature objects + $.checkArgument(BufferUtil.isBuffer(signature), 'Signatures must be an array of Buffers'); s.add(signature); - }); + } s.add((opts.cachedMultisig || Script.buildMultisigOut(pubkeys, threshold, opts)).toBuffer()); return s; }; @@ -873,11 +878,11 @@ Script.buildP2SHMultisigIn = function(pubkeys, threshold, signatures, opts) { * @param {(Address|PublicKey)} to - destination address or public key */ Script.buildPublicKeyHashOut = function(to) { - $.checkArgument(!_.isUndefined(to)); - $.checkArgument(to instanceof PublicKey || to instanceof Address || _.isString(to)); + $.checkArgument(to !== undefined); + $.checkArgument(to instanceof PublicKey || to instanceof Address || typeof to === 'string'); if (to instanceof PublicKey) { to = to.toAddress(); - } else if (_.isString(to)) { + } else if (typeof to === 'string') { to = new Address(to); } var s = new Script(); @@ -896,11 +901,11 @@ Script.buildPublicKeyHashOut = function(to) { * @param {(Address|PublicKey)} to - destination address */ Script.buildWitnessV0Out = function(to) { - $.checkArgument(!_.isUndefined(to)); - $.checkArgument(to instanceof PublicKey || to instanceof Address || _.isString(to)); + $.checkArgument(to !== undefined); + $.checkArgument(to instanceof PublicKey || to instanceof Address || typeof to === 'string'); if (to instanceof PublicKey) { to = to.toAddress(null, Address.PayToWitnessPublicKeyHash); - } else if (_.isString(to)) { + } else if (typeof to === 'string') { to = new Address(to); } var s = new Script(); @@ -928,13 +933,13 @@ Script.buildPublicKeyOut = function(pubkey) { * @param {(string)} encoding - the type of encoding of the string */ Script.buildDataOut = function(data, encoding) { - $.checkArgument(_.isUndefined(data) || _.isString(data) || BufferUtil.isBuffer(data)); - if (_.isString(data)) { + $.checkArgument(data === undefined || typeof data === 'string' || BufferUtil.isBuffer(data)); + if (typeof data === 'string') { data = Buffer.from(data, encoding); } var s = new Script(); s.add(Opcode.OP_RETURN); - if (!_.isUndefined(data)) { + if (data !== undefined) { s.add(data); } return s; @@ -965,7 +970,7 @@ Script.buildScriptHashOut = function(script) { */ Script.buildPublicKeyIn = function(signature, sigtype) { $.checkArgument(signature instanceof Signature || BufferUtil.isBuffer(signature)); - $.checkArgument(_.isUndefined(sigtype) || _.isNumber(sigtype)); + $.checkArgument(['undefined', 'number'].includes(typeof sigtype)); if (signature instanceof Signature) { signature = signature.toBuffer(); } @@ -987,7 +992,7 @@ Script.buildPublicKeyIn = function(signature, sigtype) { */ Script.buildPublicKeyHashIn = function(publicKey, signature, sigtype) { $.checkArgument(signature instanceof Signature || BufferUtil.isBuffer(signature)); - $.checkArgument(_.isUndefined(sigtype) || _.isNumber(sigtype)); + $.checkArgument(['undefined', 'number'].includes(typeof sigtype)); if (signature instanceof Signature) { signature = signature.toBuffer(); } @@ -1184,29 +1189,24 @@ Script.prototype._decodeOP_N = function(opcode) { }; /** - * Comes from bitcoind's script GetSigOpCount(boolean) function - * @param {boolean} use current (true) or pre-version-0.6 (false) logic + * @description Comes from bitcoind's script GetSigOpCount(boolean) function + * @param {boolean} accurate use current (true) or pre-version-0.6 (false) logic * @returns {number} number of signature operations required by this script */ -Script.prototype.getSignatureOperationsCount = function(accurate) { - accurate = (_.isUndefined(accurate) ? true : accurate); - var self = this; - var n = 0; - var lastOpcode = Opcode.OP_INVALIDOPCODE; - _.each(self.chunks, function getChunk(chunk) { - var opcode = chunk.opcodenum; + Script.prototype.getSignatureOperationsCount = function(accurate = true) { + const { n: opsCount } = this.chunks.reduce(({ n, lastOpcode }, { opcodenum: opcode }) => { if (opcode == Opcode.OP_CHECKSIG || opcode == Opcode.OP_CHECKSIGVERIFY) { n++; } else if (opcode == Opcode.OP_CHECKMULTISIG || opcode == Opcode.OP_CHECKMULTISIGVERIFY) { if (accurate && lastOpcode >= Opcode.OP_1 && lastOpcode <= Opcode.OP_16) { - n += self._decodeOP_N(lastOpcode); + n += this._decodeOP_N(lastOpcode); } else { n += 20; } } - lastOpcode = opcode; - }); - return n; + return { n, lastOpcode: opcode }; + }, { n: 0, lastOpcode: Opcode.OP_INVALIDOPCODE }); + return opsCount; }; module.exports = Script; diff --git a/packages/bitcore-lib/lib/transaction/input/input.js b/packages/bitcore-lib/lib/transaction/input/input.js index 7ea866bf0f6..f433a9f6118 100644 --- a/packages/bitcore-lib/lib/transaction/input/input.js +++ b/packages/bitcore-lib/lib/transaction/input/input.js @@ -1,6 +1,5 @@ 'use strict'; -var _ = require('lodash'); var $ = require('../../util/preconditions'); const errors = require('../../errors'); var BufferWriter = require('../../encoding/bufferwriter'); @@ -53,14 +52,14 @@ Object.defineProperty(Input.prototype, 'script', { }); Input.fromObject = function(obj) { - $.checkArgument(_.isObject(obj)); + $.checkArgument(JSUtil.isObject(obj)); var input = new Input(); return input._fromObject(obj); }; Input.prototype._fromObject = function(params) { var prevTxId; - if (_.isString(params.prevTxId) && JSUtil.isHexa(params.prevTxId)) { + if (typeof params.prevTxId === 'string' && JSUtil.isHexa(params.prevTxId)) { prevTxId = Buffer.from(params.prevTxId, 'hex'); } else { prevTxId = params.prevTxId; @@ -69,10 +68,10 @@ Input.prototype._fromObject = function(params) { this.output = params.output ? (params.output instanceof Output ? params.output : new Output(params.output)) : undefined; this.prevTxId = prevTxId || params.txidbuf; - this.outputIndex = _.isUndefined(params.outputIndex) ? params.txoutnum : params.outputIndex; - this.sequenceNumber = _.isUndefined(params.sequenceNumber) ? - (_.isUndefined(params.seqnum) ? DEFAULT_SEQNUMBER : params.seqnum) : params.sequenceNumber; - if (_.isUndefined(params.script) && _.isUndefined(params.scriptBuffer)) { + this.outputIndex = params.outputIndex === undefined ? params.txoutnum : params.outputIndex; + this.sequenceNumber = params.sequenceNumber === undefined ? + (params.seqnum === undefined ? DEFAULT_SEQNUMBER : params.seqnum) : params.sequenceNumber; + if (params.script === undefined && params.scriptBuffer === undefined) { throw new errors.Transaction.Input.MissingScript(); } this.setScript(params.scriptBuffer || params.script); @@ -129,7 +128,7 @@ Input.prototype.setScript = function(script) { } else if (JSUtil.isHexa(script)) { // hex string script this._scriptBuffer = Buffer.from(script, 'hex'); - } else if (_.isString(script)) { + } else if (typeof script === 'string') { // human readable string script this._script = new Script(script); this._script._isInput = true; @@ -234,7 +233,7 @@ Input.prototype._estimateSize = function() { * @return {Transaction} this */ Input.prototype.lockForSeconds = function(seconds) { - $.checkArgument(_.isNumber(seconds)); + $.checkArgument(typeof seconds === 'number'); if (seconds < 0 || seconds >= SEQUENCE_LOCKTIME_GRANULARITY * SEQUENCE_LOCKTIME_MASK) { throw new errors.Transaction.Input.LockTimeRange(); } @@ -252,7 +251,7 @@ Input.prototype.lockForSeconds = function(seconds) { * @return {Transaction} this */ Input.prototype.lockUntilBlockHeight = function(heightDiff) { - $.checkArgument(_.isNumber(heightDiff)); + $.checkArgument(typeof heightDiff === 'number' && !isNaN(heightDiff)); if (heightDiff < 0 || heightDiff >= SEQUENCE_BLOCKDIFF_LIMIT) { throw new errors.Transaction.Input.BlockHeightOutOfRange(); } diff --git a/packages/bitcore-lib/lib/transaction/input/multisig.js b/packages/bitcore-lib/lib/transaction/input/multisig.js index 4a60362b04b..f462504f564 100644 --- a/packages/bitcore-lib/lib/transaction/input/multisig.js +++ b/packages/bitcore-lib/lib/transaction/input/multisig.js @@ -1,6 +1,5 @@ 'use strict'; -var _ = require('lodash'); var inherits = require('inherits'); var Transaction = require('../transaction'); var Input = require('./input'); @@ -12,6 +11,7 @@ var Signature = require('../../crypto/signature'); var Sighash = require('../sighash'); var PublicKey = require('../../publickey'); var BufferUtil = require('../../util/buffer'); +var JSUtil = require('../../util/js'); var TransactionSignature = require('../signature'); /** @@ -20,21 +20,17 @@ var TransactionSignature = require('../signature'); function MultiSigInput(input, pubkeys, threshold, signatures, opts) { opts = opts || {}; Input.apply(this, arguments); - var self = this; pubkeys = pubkeys || input.publicKeys; threshold = threshold || input.threshold; signatures = signatures || input.signatures; - if (opts.noSorting) { - this.publicKeys = pubkeys - } else { - this.publicKeys = _.sortBy(pubkeys, function(publicKey) { return publicKey.toString('hex'); }); + if (!opts.noSorting) { + JSUtil.sort(pubkeys); } + this.publicKeys = pubkeys; $.checkState(Script.buildMultisigOut(this.publicKeys, threshold).equals(this.output.script), 'Provided public keys don\'t match to the provided output script'); this.publicKeyIndex = {}; - _.each(this.publicKeys, function(publicKey, index) { - self.publicKeyIndex[publicKey.toString()] = index; - }); + this.publicKeys.forEach((publicKey, index) => this.publicKeyIndex[publicKey.toString()] = index); this.threshold = threshold; // Empty array of signatures this.signatures = signatures ? this._deserializeSignatures(signatures) : new Array(this.publicKeys.length); @@ -44,27 +40,17 @@ inherits(MultiSigInput, Input); MultiSigInput.prototype.toObject = function() { var obj = Input.prototype.toObject.apply(this, arguments); obj.threshold = this.threshold; - obj.publicKeys = _.map(this.publicKeys, function(publicKey) { return publicKey.toString(); }); + obj.publicKeys = this.publicKeys.map(publicKey => publicKey.toString()); obj.signatures = this._serializeSignatures(); return obj; }; MultiSigInput.prototype._deserializeSignatures = function(signatures) { - return _.map(signatures, function(signature) { - if (!signature) { - return undefined; - } - return new TransactionSignature(signature); - }); + return signatures.map(signature => signature ? new TransactionSignature(signature) : undefined); }; MultiSigInput.prototype._serializeSignatures = function() { - return _.map(this.signatures, function(signature) { - if (!signature) { - return undefined; - } - return signature.toObject(); - }); + return this.signatures.map(signature => signature ? signature.toObject() : undefined); }; MultiSigInput.prototype.getSignatures = function(transaction, privateKey, index, sigtype, hashData, signingMethod) { @@ -74,7 +60,7 @@ MultiSigInput.prototype.getSignatures = function(transaction, privateKey, index, var self = this; var results = []; - _.each(this.publicKeys, function(publicKey) { + this.publicKeys.forEach(function(publicKey) { if (publicKey.toString() === privateKey.publicKey.toString()) { results.push(new TransactionSignature({ publicKey: privateKey.publicKey, @@ -92,8 +78,7 @@ MultiSigInput.prototype.getSignatures = function(transaction, privateKey, index, MultiSigInput.prototype.addSignature = function(transaction, signature, signingMethod) { $.checkState(!this.isFullySigned(), 'All needed signatures have already been added'); - $.checkArgument(!_.isUndefined(this.publicKeyIndex[signature.publicKey.toString()], "Signature Undefined"), - 'Signature has no matching public key'); + $.checkArgument(this.publicKeyIndex[signature.publicKey.toString()] !== undefined, 'Signature has no matching public key'); $.checkState(this.isValidSignature(transaction, signature, signingMethod), "Invalid Signature"); this.signatures[this.publicKeyIndex[signature.publicKey.toString()]] = signature; this._updateScript(); @@ -110,16 +95,12 @@ MultiSigInput.prototype._updateScript = function() { }; MultiSigInput.prototype._createSignatures = function() { - return _.map( - _.filter(this.signatures, function(signature) { return !_.isUndefined(signature); }), + return this.signatures.filter(signature => signature !== undefined) // Future signature types may need refactor of toDER - function(signature) { - return BufferUtil.concat([ - signature.signature.toDER(), - BufferUtil.integerAsSingleByteBuffer(signature.sigtype) - ]); - } - ); + .map(signature => BufferUtil.concat([ + signature.signature.toDER(), + BufferUtil.integerAsSingleByteBuffer(signature.sigtype) + ])); }; MultiSigInput.prototype.clearSignatures = function() { @@ -136,16 +117,11 @@ MultiSigInput.prototype.countMissingSignatures = function() { }; MultiSigInput.prototype.countSignatures = function() { - return _.reduce(this.signatures, function(sum, signature) { - return sum + (!!signature); - }, 0); + return this.signatures.reduce((sum, signature) => sum + !!signature, 0); }; MultiSigInput.prototype.publicKeysWithoutSignature = function() { - var self = this; - return _.filter(this.publicKeys, function(publicKey) { - return !(self.signatures[self.publicKeyIndex[publicKey.toString()]]); - }); + return this.publicKeys.filter(publicKey => !this.signatures[this.publicKeyIndex[publicKey.toString()]]); }; MultiSigInput.prototype.isValidSignature = function(transaction, signature, signingMethod) { diff --git a/packages/bitcore-lib/lib/transaction/input/multisigscripthash.js b/packages/bitcore-lib/lib/transaction/input/multisigscripthash.js index 6169c191a3e..0e3dcf37582 100644 --- a/packages/bitcore-lib/lib/transaction/input/multisigscripthash.js +++ b/packages/bitcore-lib/lib/transaction/input/multisigscripthash.js @@ -2,7 +2,6 @@ /* jshint maxparams:5 */ -var _ = require('lodash'); var inherits = require('inherits'); var Input = require('./input'); var Output = require('../output'); @@ -15,24 +14,22 @@ var Sighash = require('../sighash'); var SighashWitness = require('../sighashwitness'); var BufferWriter = require('../../encoding/bufferwriter'); var BufferUtil = require('../../util/buffer'); +var JSUtil = require('../../util/js'); var TransactionSignature = require('../signature'); /** * @constructor */ -function MultiSigScriptHashInput(input, pubkeys, threshold, signatures, opts) { +function MultiSigScriptHashInput(input, pubkeys, threshold, signatures, opts = {}) { /* jshint maxstatements:20 */ - opts = opts || {}; Input.apply(this, arguments); - var self = this; pubkeys = pubkeys || input.publicKeys; threshold = threshold || input.threshold; signatures = signatures || input.signatures; - if (opts.noSorting) { - this.publicKeys = pubkeys; - } else { - this.publicKeys = _.sortBy(pubkeys, function(publicKey) { return publicKey.toString('hex'); }); + if (!opts.noSorting) { + JSUtil.sort(pubkeys); } + this.publicKeys = pubkeys; this.redeemScript = Script.buildMultisigOut(this.publicKeys, threshold, opts); var nested = Script.buildWitnessMultisigOutFromScript(this.redeemScript); if (nested.equals(this.output.script)) { @@ -54,10 +51,7 @@ function MultiSigScriptHashInput(input, pubkeys, threshold, signatures, opts) { this.setScript(scriptSig); } - this.publicKeyIndex = {}; - _.each(this.publicKeys, function(publicKey, index) { - self.publicKeyIndex[publicKey.toString()] = index; - }); + this.publicKeyIndex = this.publicKeys.reduce((keyIndex, publicKey, index) => ({ ...keyIndex, [publicKey.toString()]: index }), {}); this.threshold = threshold; // Empty array of signatures this.signatures = signatures ? this._deserializeSignatures(signatures) : new Array(this.publicKeys.length); @@ -67,13 +61,13 @@ inherits(MultiSigScriptHashInput, Input); MultiSigScriptHashInput.prototype.toObject = function() { var obj = Input.prototype.toObject.apply(this, arguments); obj.threshold = this.threshold; - obj.publicKeys = _.map(this.publicKeys, function(publicKey) { return publicKey.toString(); }); + obj.publicKeys = this.publicKeys.map(function(publicKey) { return publicKey.toString(); }); obj.signatures = this._serializeSignatures(); return obj; }; MultiSigScriptHashInput.prototype._deserializeSignatures = function(signatures) { - return _.map(signatures, function(signature) { + return signatures.map(function(signature) { if (!signature) { return undefined; } @@ -82,7 +76,7 @@ MultiSigScriptHashInput.prototype._deserializeSignatures = function(signatures) }; MultiSigScriptHashInput.prototype._serializeSignatures = function() { - return _.map(this.signatures, function(signature) { + return this.signatures.map(function(signature) { if (!signature) { return undefined; } @@ -122,7 +116,7 @@ MultiSigScriptHashInput.prototype.getSignatures = function(transaction, privateK var self = this; var results = []; - _.each(this.publicKeys, function(publicKey) { + this.publicKeys.forEach(function(publicKey) { if (publicKey.toString() === privateKey.publicKey.toString()) { var signature; if (self.nestedWitness || self.type === Address.PayToWitnessScriptHash) { @@ -147,8 +141,7 @@ MultiSigScriptHashInput.prototype.getSignatures = function(transaction, privateK MultiSigScriptHashInput.prototype.addSignature = function(transaction, signature, signingMethod) { $.checkState(!this.isFullySigned(), 'All needed signatures have already been added'); - $.checkArgument(!_.isUndefined(this.publicKeyIndex[signature.publicKey.toString()]), - 'Signature has no matching public key'); + $.checkArgument(this.publicKeyIndex[signature.publicKey.toString()] !== undefined, 'Signature has no matching public key'); $.checkState(this.isValidSignature(transaction, signature, signingMethod), "Invalid Signature!"); this.signatures[this.publicKeyIndex[signature.publicKey.toString()]] = signature; this._updateScript(); @@ -179,15 +172,12 @@ MultiSigScriptHashInput.prototype._updateScript = function() { }; MultiSigScriptHashInput.prototype._createSignatures = function() { - return _.map( - _.filter(this.signatures, function(signature) { return !_.isUndefined(signature); }), - function(signature) { - return BufferUtil.concat([ - signature.signature.toDER(), - BufferUtil.integerAsSingleByteBuffer(signature.sigtype) - ]); - } - ); + return this.signatures + .filter(signature => !!signature) + .map(signature => BufferUtil.concat([ + signature.signature.toDER(), + BufferUtil.integerAsSingleByteBuffer(signature.sigtype) + ])); }; MultiSigScriptHashInput.prototype.clearSignatures = function() { @@ -204,14 +194,12 @@ MultiSigScriptHashInput.prototype.countMissingSignatures = function() { }; MultiSigScriptHashInput.prototype.countSignatures = function() { - return _.reduce(this.signatures, function(sum, signature) { - return sum + (!!signature); - }, 0); + return this.signatures.reduce((sum, signature) => sum + (!!signature), 0); }; MultiSigScriptHashInput.prototype.publicKeysWithoutSignature = function() { var self = this; - return _.filter(this.publicKeys, function(publicKey) { + return this.publicKeys.filter(function(publicKey) { return !(self.signatures[self.publicKeyIndex[publicKey.toString()]]); }); }; diff --git a/packages/bitcore-lib/lib/transaction/output.js b/packages/bitcore-lib/lib/transaction/output.js index 4fcdce4b24d..4ce1d78d37a 100644 --- a/packages/bitcore-lib/lib/transaction/output.js +++ b/packages/bitcore-lib/lib/transaction/output.js @@ -1,6 +1,5 @@ 'use strict'; -var _ = require('lodash'); var BN = require('../crypto/bn'); var buffer = require('buffer'); var bufferUtil = require('../util/buffer'); @@ -16,13 +15,13 @@ function Output(args) { if (!(this instanceof Output)) { return new Output(args); } - if (_.isObject(args)) { + if (typeof args === 'object') { this.satoshis = args.satoshis; if (bufferUtil.isBuffer(args.script)) { this._scriptBuffer = args.script; } else { var script; - if (_.isString(args.script) && JSUtil.isHexa(args.script)) { + if (typeof args.script === 'string' && JSUtil.isHexa(args.script)) { script = Buffer.from(args.script, 'hex'); } else { script = args.script; @@ -58,7 +57,7 @@ Object.defineProperty(Output.prototype, 'satoshis', { if (num instanceof BN) { this._satoshisBN = num; this._satoshis = num.toNumber(); - } else if (_.isString(num)) { + } else if (typeof num === 'string') { this._satoshis = parseInt(num); this._satoshisBN = BN.fromNumber(this._satoshis); } else { @@ -120,7 +119,7 @@ Output.prototype.setScript = function(script) { this._scriptBuffer = script.toBuffer(); this._script = script; this._script._isOutput = true; - } else if (_.isString(script)) { + } else if (typeof script === 'string') { this._script = Script.fromString(script); this._scriptBuffer = this._script.toBuffer(); this._script._isOutput = true; diff --git a/packages/bitcore-lib/lib/transaction/sighash.js b/packages/bitcore-lib/lib/transaction/sighash.js index 275f2668385..346988d9931 100644 --- a/packages/bitcore-lib/lib/transaction/sighash.js +++ b/packages/bitcore-lib/lib/transaction/sighash.js @@ -9,7 +9,6 @@ var BN = require('../crypto/bn'); var Hash = require('../crypto/hash'); var ECDSA = require('../crypto/ecdsa'); var $ = require('../util/preconditions'); -var _ = require('lodash'); const schnorr = require('bip-schnorr'); var SIGHASH_SINGLE_BUG = '0000000000000000000000000000000000000000000000000000000000000001'; @@ -131,8 +130,8 @@ function sign(transaction, privateKey, sighashType, inputIndex, subscript, signi * @return {boolean} */ function verify(transaction, signature, publicKey, inputIndex, subscript, signingMethod) { - $.checkArgument(!_.isUndefined(transaction), "Transaction Undefined"); - $.checkArgument(!_.isUndefined(signature) && !_.isUndefined(signature.nhashtype), "Signature Undefined"); + $.checkArgument(transaction !== undefined, 'Transaction Undefined'); + $.checkArgument(signature !== undefined && signature.nhashtype !== undefined, "Signature Undefined"); signingMethod = signingMethod || 'ecdsa'; let hashbuf = sighash(transaction, signature.nhashtype, inputIndex, subscript); diff --git a/packages/bitcore-lib/lib/transaction/sighashwitness.js b/packages/bitcore-lib/lib/transaction/sighashwitness.js index 96ee142b0dd..099aa2c1542 100644 --- a/packages/bitcore-lib/lib/transaction/sighashwitness.js +++ b/packages/bitcore-lib/lib/transaction/sighashwitness.js @@ -11,7 +11,6 @@ var BN = require('../crypto/bn'); var Hash = require('../crypto/hash'); var ECDSA = require('../crypto/ecdsa'); var $ = require('../util/preconditions'); -var _ = require('lodash'); /** * Returns a buffer of length 32 bytes with the hash that needs to be signed @@ -140,16 +139,15 @@ function sign(transaction, privateKey, sighashType, inputIndex, scriptCode, sato * @param {String} signingMethod - method used to sign - 'ecdsa' or 'schnorr' (future signing method) * @return {boolean} */ -function verify(transaction, signature, publicKey, inputIndex, scriptCode, satoshisBuffer, signingMethod) { - $.checkArgument(!_.isUndefined(transaction)); - $.checkArgument(!_.isUndefined(signature) && !_.isUndefined(signature.nhashtype)); - signingMethod = signingMethod || 'ecdsa'; +function verify(transaction, signature, publicKey, inputIndex, scriptCode, satoshisBuffer, signingMethod = 'ecdsa') { + $.checkArgument(transaction && signature && signature.nhashtype, 'Missing required argument(s)'); if (signingMethod === 'ecdsa') { let hashbuf = sighash(transaction, signature.nhashtype, inputIndex, scriptCode, satoshisBuffer); return ECDSA.verify(hashbuf, signature, publicKey); } - throw new Error("signingMethod not supported ", signingMethod); + + throw new Error(`signingMethod not supported ${signingMethod}`); } /** diff --git a/packages/bitcore-lib/lib/transaction/signature.js b/packages/bitcore-lib/lib/transaction/signature.js index 5e40f990298..6a913d2d051 100644 --- a/packages/bitcore-lib/lib/transaction/signature.js +++ b/packages/bitcore-lib/lib/transaction/signature.js @@ -1,6 +1,5 @@ 'use strict'; -var _ = require('lodash'); var $ = require('../util/preconditions'); var inherits = require('inherits'); var BufferUtil = require('../util/buffer'); @@ -24,7 +23,7 @@ function TransactionSignature(arg) { if (arg instanceof TransactionSignature) { return arg; } - if (_.isObject(arg)) { + if (typeof arg === 'object') { return this._fromObject(arg); } throw new errors.InvalidArgument('TransactionSignatures must be instantiated from an object'); @@ -46,10 +45,10 @@ TransactionSignature.prototype._fromObject = function(arg) { TransactionSignature.prototype._checkObjectArgs = function(arg) { $.checkArgument(PublicKey(arg.publicKey), 'publicKey'); - $.checkArgument(!_.isUndefined(arg.inputIndex), 'inputIndex'); - $.checkArgument(!_.isUndefined(arg.outputIndex), 'outputIndex'); - $.checkState(_.isNumber(arg.inputIndex), 'inputIndex must be a number'); - $.checkState(_.isNumber(arg.outputIndex), 'outputIndex must be a number'); + $.checkArgument(arg.inputIndex !== undefined, 'inputIndex'); + $.checkArgument(arg.outputIndex !== undefined, 'outputIndex'); + $.checkState(typeof arg.inputIndex === 'number', 'inputIndex must be a number'); + $.checkState(typeof arg.outputIndex === 'number', 'outputIndex must be a number'); $.checkArgument(arg.signature, 'signature'); $.checkArgument(arg.prevTxId, 'prevTxId'); $.checkState(arg.signature instanceof Signature || @@ -58,7 +57,7 @@ TransactionSignature.prototype._checkObjectArgs = function(arg) { $.checkState(BufferUtil.isBuffer(arg.prevTxId) || JSUtil.isHexa(arg.prevTxId), 'prevTxId must be a buffer or hexa value'); $.checkArgument(arg.sigtype, 'sigtype'); - $.checkState(_.isNumber(arg.sigtype), 'sigtype must be a number'); + $.checkState(typeof arg.sigtype === 'number', 'sigtype must be a number'); }; /** diff --git a/packages/bitcore-lib/lib/transaction/transaction.js b/packages/bitcore-lib/lib/transaction/transaction.js index ff5ac6c9ad6..090e5365994 100644 --- a/packages/bitcore-lib/lib/transaction/transaction.js +++ b/packages/bitcore-lib/lib/transaction/transaction.js @@ -1,6 +1,5 @@ 'use strict'; -var _ = require('lodash'); var $ = require('../util/preconditions'); var buffer = require('buffer'); var compare = Buffer.compare || require('buffer-compare'); @@ -26,6 +25,7 @@ var Output = require('./output'); var Script = require('../script'); var PrivateKey = require('../privatekey'); var BN = require('../crypto/bn'); +const { collapseTextChangeRangesAcrossMultipleVersions } = require('typescript'); /** * Represents a transaction, a set of inputs and outputs to change ownership of tokens @@ -49,7 +49,7 @@ function Transaction(serialized, opts) { this.fromString(serialized); } else if (BufferUtil.isBuffer(serialized)) { this.fromBuffer(serialized); - } else if (_.isObject(serialized)) { + } else if (typeof serialized === 'object') { this.fromObject(serialized, opts); } else { throw new errors.InvalidArgument('Must provide an object or string to deserialize a transaction'); @@ -231,8 +231,7 @@ Transaction.prototype.getSerializationError = function(opts) { }; Transaction.prototype._hasFeeError = function(opts, unspent) { - - if (!_.isUndefined(this._fee) && this._fee !== unspent) { + if (this._fee !== undefined && this._fee !== unspent) { return new errors.Transaction.FeeError.Different( 'Unspent value is ' + unspent + ' but specified fee is ' + this._fee ); @@ -317,22 +316,22 @@ Transaction.prototype.toBufferWriter = function(writer, noWitness) { writer.writeVarintNum(this.inputs.length); - _.each(this.inputs, function(input) { + this.inputs.forEach(function(input) { input.toBufferWriter(writer); }); writer.writeVarintNum(this.outputs.length); - _.each(this.outputs, function(output) { + this.outputs.forEach(function(output) { output.toBufferWriter(writer); }); if (hasWitnesses && !noWitness) { - _.each(this.inputs, function(input) { + this.inputs.forEach(function(input) { var witnesses = input.getWitnesses(); writer.writeVarintNum(witnesses.length); - for (var j = 0; j < witnesses.length; j++) { - writer.writeVarintNum(witnesses[j].length); - writer.write(witnesses[j]); + for (let witness of witnesses) { + writer.writeVarintNum(witness.length); + writer.write(witness); } }); } @@ -407,10 +406,10 @@ Transaction.prototype.toObject = Transaction.prototype.toJSON = function toObjec if (this._changeScript) { obj.changeScript = this._changeScript.toString(); } - if (!_.isUndefined(this._changeIndex)) { + if (this._changeIndex !== undefined) { obj.changeIndex = this._changeIndex; } - if (!_.isUndefined(this._fee)) { + if (this._fee !== undefined) { obj.fee = this._fee; } return obj; @@ -418,18 +417,17 @@ Transaction.prototype.toObject = Transaction.prototype.toJSON = function toObjec Transaction.prototype.fromObject = function fromObject(arg, opts) { /* jshint maxstatements: 20 */ - $.checkArgument(_.isObject(arg) || arg instanceof Transaction); - var self = this; + $.checkArgument(JSUtil.isObject(arg) || arg instanceof Transaction); var transaction; if (arg instanceof Transaction) { transaction = transaction.toObject(); } else { transaction = arg; } - _.each(transaction.inputs, function(input) { + for (let input of transaction.inputs || []) { if (!input.output || !input.output.script) { - self.uncheckedAddInput(new Input(input)); - return; + this.uncheckedAddInput(new Input(input)); + continue; } var script = new Script(input.output.script); var txin; @@ -444,11 +442,11 @@ Transaction.prototype.fromObject = function fromObject(arg, opts) { } else { throw new errors.Transaction.Input.UnsupportedScript(input.output.script); } - self.addInput(txin); - }); - _.each(transaction.outputs, function(output) { - self.addOutput(new Output(output)); - }); + this.addInput(txin); + } + for (let output of transaction.outputs || []) { + this.addOutput(new Output(output)); + } if (transaction.changeIndex) { this._changeIndex = transaction.changeIndex; } @@ -465,7 +463,7 @@ Transaction.prototype.fromObject = function fromObject(arg, opts) { }; Transaction.prototype._checkConsistency = function(arg) { - if (!_.isUndefined(this._changeIndex)) { + if (this._changeIndex !== undefined) { $.checkState(this._changeScript, 'Change script is expected.'); $.checkState(this.outputs[this._changeIndex], 'Change index points to undefined output.'); $.checkState(this.outputs[this._changeIndex].script.toString() === @@ -485,10 +483,10 @@ Transaction.prototype._checkConsistency = function(arg) { */ Transaction.prototype.lockUntilDate = function(time) { $.checkArgument(time); - if (_.isNumber(time) && time < Transaction.NLOCKTIME_BLOCKHEIGHT_LIMIT) { + if (typeof time === 'number' && time < Transaction.NLOCKTIME_BLOCKHEIGHT_LIMIT) { throw new errors.Transaction.LockTimeTooEarly(); } - if (_.isDate(time)) { + if (time instanceof Date) { time = time.getTime() / 1000; } @@ -510,7 +508,7 @@ Transaction.prototype.lockUntilDate = function(time) { * @return {Transaction} this */ Transaction.prototype.lockUntilBlockHeight = function(height) { - $.checkArgument(_.isNumber(height)); + $.checkArgument(typeof height === 'number' && !isNaN(height)); if (height >= Transaction.NLOCKTIME_BLOCKHEIGHT_LIMIT) { throw new errors.Transaction.BlockHeightTooHigh(); } @@ -610,14 +608,13 @@ Transaction.prototype._newTransaction = function() { * sort the given public keys before creating the script */ Transaction.prototype.from = function(utxo, pubkeys, threshold, opts) { - if (_.isArray(utxo)) { - var self = this; - _.each(utxo, function(utxo) { - self.from(utxo, pubkeys, threshold, opts); - }); + if (Array.isArray(utxo)) { + for (let u of utxo) { + this.from(u, pubkeys, threshold, opts); + } return this; } - var exists = _.some(this.inputs, function(input) { + var exists = this.inputs.some(function(input) { // TODO: Maybe prevTxId should be a string? Or defined as read only property? return input.prevTxId.toString('hex') === utxo.txId && input.outputIndex === utxo.outputIndex; }); @@ -716,10 +713,10 @@ Transaction.prototype._fromMultisigUtxo = function(utxo, pubkeys, threshold, opt */ Transaction.prototype.addInput = function(input, outputScript, satoshis) { $.checkArgumentType(input, Input, 'input'); - if (!input.output && (_.isUndefined(outputScript) || _.isUndefined(satoshis))) { + if (!input.output && (outputScript === undefined || satoshis === undefined)) { throw new errors.Transaction.NeedMoreInfo('Need information about the UTXO script and satoshis'); } - if (!input.output && outputScript && !_.isUndefined(satoshis)) { + if (!input.output && outputScript && satoshis !== undefined) { outputScript = outputScript instanceof Script ? outputScript : new Script(outputScript); $.checkArgumentType(satoshis, 'number', 'satoshis'); input.output = new Output({ @@ -751,9 +748,7 @@ Transaction.prototype.uncheckedAddInput = function(input) { * @return {boolean} */ Transaction.prototype.hasAllUtxoInfo = function() { - return _.every(this.inputs.map(function(input) { - return !!input.output; - })); + return this.inputs.every(input => !!input.output); }; /** @@ -765,7 +760,7 @@ Transaction.prototype.hasAllUtxoInfo = function() { * @return {Transaction} this, for chaining */ Transaction.prototype.fee = function(amount) { - $.checkArgument(_.isNumber(amount), 'amount must be a number'); + $.checkArgument(typeof amount === 'number' && !isNaN(amount), 'amount must be a number'); this._fee = amount; this._updateChangeOutput(); return this; @@ -780,7 +775,7 @@ Transaction.prototype.fee = function(amount) { * @return {Transaction} this, for chaining */ Transaction.prototype.feePerKb = function(amount) { - $.checkArgument(_.isNumber(amount), 'amount must be a number'); + $.checkArgument(typeof amount === 'number' && !isNaN(amount), 'amount must be a number'); this._feePerKb = amount; this._updateChangeOutput(); return this; @@ -796,7 +791,7 @@ Transaction.prototype.feePerKb = function(amount) { * @return {Transaction} this, for chaining */ Transaction.prototype.feePerByte = function (amount) { - $.checkArgument(_.isNumber(amount), 'amount must be a number'); + $.checkArgument(typeof amount === 'number' && !isNaN(amount), 'amount must be a number'); this._feePerByte = amount; this._updateChangeOutput(); return this; @@ -825,10 +820,7 @@ Transaction.prototype.change = function(address) { * @return {Output} change output, if it exists */ Transaction.prototype.getChangeOutput = function() { - if (!_.isUndefined(this._changeIndex)) { - return this.outputs[this._changeIndex]; - } - return null; + return this.outputs[this._changeIndex] || null; }; /** @@ -848,9 +840,9 @@ Transaction.prototype.getChangeOutput = function() { * @return {Transaction} this, for chaining */ Transaction.prototype.to = function(address, amount) { - if (_.isArray(address)) { + if (Array.isArray(address)) { var self = this; - _.each(address, function(to) { + address.forEach(function(to) { self.to(to.address, to.satoshis); }); return this; @@ -927,10 +919,10 @@ Transaction.prototype._addOutput = function(output) { * @return {Number} the transaction total output amount */ Transaction.prototype._getOutputAmount = function() { - if (_.isUndefined(this._outputAmount)) { + if (this._outputAmount === undefined) { var self = this; this._outputAmount = 0; - _.each(this.outputs, function(output) { + this.outputs.forEach(function(output) { self._outputAmount += output.satoshis; }); } @@ -944,13 +936,13 @@ Transaction.prototype._getOutputAmount = function() { * @return {Number} the transaction total input amount */ Transaction.prototype._getInputAmount = function() { - if (_.isUndefined(this._inputAmount)) { - this._inputAmount = _.sumBy(this.inputs, function(input) { - if (_.isUndefined(input.output)) { + if (this._inputAmount === undefined) { + this._inputAmount = this.inputs.reduce(function(total, input) { + if (!input.output || !input.output.satoshis) { throw new errors.Transaction.Input.MissingPreviousOutput(); } - return input.output.satoshis; - }); + return total + input.output.satoshis; + }, 0); } return this._inputAmount; }; @@ -960,7 +952,7 @@ Transaction.prototype._updateChangeOutput = function() { return; } this._clearSignatures(); - if (!_.isUndefined(this._changeIndex)) { + if (this._changeIndex !== undefined) { this._removeOutput(this._changeIndex); } var available = this._getUnspentValue(); @@ -998,7 +990,7 @@ Transaction.prototype.getFee = function() { if (this.isCoinbase()) { return 0; } - if (!_.isUndefined(this._fee)) { + if (this._fee !== undefined) { return this._fee; } // if no change output is set, fees should equal all the unspent amount @@ -1031,26 +1023,25 @@ Transaction.prototype._getUnspentValue = function() { }; Transaction.prototype._clearSignatures = function() { - _.each(this.inputs, function(input) { + this.inputs.forEach(function(input) { input.clearSignatures(); }); }; Transaction.prototype._estimateSize = function() { var result = Transaction.MAXIMUM_EXTRA_SIZE; - _.each(this.inputs, function(input) { + this.inputs.forEach(function(input) { result += 32 + 4; // prevout size:w result += input._estimateSize(); }); - _.each(this.outputs, function(output) { + this.outputs.forEach(function(output) { result += output.script.toBuffer().length + 9; }); return Math.ceil(result); }; Transaction.prototype._removeOutput = function(index) { - var output = this.outputs[index]; - this.outputs = _.without(this.outputs, output); + this.outputs.splice(index, 1); this._outputAmount = undefined; }; @@ -1093,12 +1084,12 @@ Transaction.prototype.sort = function() { /** * Randomize this transaction's outputs ordering. The shuffling algorithm is a - * version of the Fisher-Yates shuffle, provided by lodash's _.shuffle(). + * version of the Fisher-Yates shuffle. * * @return {Transaction} this */ Transaction.prototype.shuffleOutputs = function() { - return this.sortOutputs(_.shuffle); + return this.sortOutputs(JSUtil.shuffle); }; /** @@ -1130,15 +1121,15 @@ Transaction.prototype.sortInputs = function(sortingFunction) { }; Transaction.prototype._newOutputOrder = function(newOutputs) { - var isInvalidSorting = (this.outputs.length !== newOutputs.length || - _.difference(this.outputs, newOutputs).length !== 0); - if (isInvalidSorting) { + // the new order is invalid if the length does not match or if any output is missing + if (this.outputs.length !== newOutputs.length || + this.outputs.find(o => newOutputs.findIndex(out => JSON.stringify(out) === JSON.stringify(o)) === -1)) { throw new errors.Transaction.InvalidSorting(); } - if (!_.isUndefined(this._changeIndex)) { + if (this._changeIndex !== undefined) { var changeOutput = this.outputs[this._changeIndex]; - this._changeIndex = _.findIndex(newOutputs, changeOutput); + this._changeIndex = newOutputs.findIndex(output => output.script.toString() === changeOutput.script.toString()); } this.outputs = newOutputs; @@ -1146,19 +1137,14 @@ Transaction.prototype._newOutputOrder = function(newOutputs) { }; Transaction.prototype.removeInput = function(txId, outputIndex) { - var index; - if (!outputIndex && _.isNumber(txId)) { - index = txId; - } else { - index = _.findIndex(this.inputs, function(input) { + var index = (!outputIndex && typeof txId === 'number') ? + txId : this.inputs.findIndex(function(input) { return input.prevTxId.toString('hex') === txId && input.outputIndex === outputIndex; }); - } if (index < 0 || index >= this.inputs.length) { throw new errors.Transaction.InvalidIndex(index, this.inputs.length); } - var input = this.inputs[index]; - this.inputs = _.without(this.inputs, input); + this.inputs.splice(index, 1); this._inputAmount = undefined; this._updateChangeOutput(); }; @@ -1178,31 +1164,30 @@ Transaction.prototype.removeInput = function(txId, outputIndex) { */ Transaction.prototype.sign = function(privateKey, sigtype, signingMethod) { $.checkState(this.hasAllUtxoInfo(), 'Not all utxo information is available to sign the transaction.'); - var self = this; - if (_.isArray(privateKey)) { - _.each(privateKey, function(privateKey) { - self.sign(privateKey, sigtype, signingMethod); + + if (Array.isArray(privateKey)) { + privateKey.forEach(privateKey => this.sign(privateKey, sigtype, signingMethod)); + } else { + this.getSignatures(privateKey, sigtype, signingMethod).forEach((signature) => { + try { + this.applySignature(signature, signingMethod); + } catch (err) { + console.error(err); + } }); - return this; } - _.each(this.getSignatures(privateKey, sigtype, signingMethod), function(signature) { - self.applySignature(signature, signingMethod); - }); + return this; }; Transaction.prototype.getSignatures = function(privKey, sigtype, signingMethod) { privKey = new PrivateKey(privKey); sigtype = sigtype || Signature.SIGHASH_ALL; - var transaction = this; - var results = []; - var hashData = Hash.sha256ripemd160(privKey.publicKey.toBuffer()); - _.each(this.inputs, function forEachInput(input, index) { - _.each(input.getSignatures(transaction, privKey, index, sigtype, hashData, signingMethod), function(signature) { - results.push(signature); - }); - }); - return results; + let hashData = Hash.sha256ripemd160(privKey.publicKey.toBuffer()); + return this.inputs.reduce((results, input, index) => ([ + ...results, + ...input.getSignatures(this, privKey, index, sigtype, hashData, signingMethod), + ]), []); }; /** @@ -1222,7 +1207,7 @@ Transaction.prototype.applySignature = function(signature, signingMethod) { }; Transaction.prototype.isFullySigned = function() { - _.each(this.inputs, function(input) { + this.inputs.forEach(function(input) { if (input.isFullySigned === Input.prototype.isFullySigned) { throw new errors.Transaction.UnableToVerifySignature( 'Unrecognized script kind, or not enough information to execute script.' + @@ -1230,32 +1215,26 @@ Transaction.prototype.isFullySigned = function() { ); } }); - return _.every(_.map(this.inputs, function(input) { + return this.inputs.every(function(input) { return input.isFullySigned(); - })); + }); }; Transaction.prototype.isValidSignature = function(signature, signingMethod) { - var self = this; if (this.inputs[signature.inputIndex].isValidSignature === Input.prototype.isValidSignature) { throw new errors.Transaction.UnableToVerifySignature( 'Unrecognized script kind, or not enough information to execute script.' + 'This usually happens when creating a transaction from a serialized transaction' ); } - return this.inputs[signature.inputIndex].isValidSignature(self, signature, signingMethod); + return this.inputs[signature.inputIndex].isValidSignature(this, signature, signingMethod); }; /** * @param {String} signingMethod method used to sign - 'ecdsa' or 'schnorr' (future signing method) * @returns {bool} whether the signature is valid for this transaction input */ -Transaction.prototype.verifySignature = function(sig, pubkey, nin, subscript, sigversion, satoshis, signingMethod) { - - if (_.isUndefined(sigversion)) { - sigversion = 0; - } - +Transaction.prototype.verifySignature = function(sig, pubkey, nin, subscript, sigversion = 0, satoshis, signingMethod) { if (sigversion === 1) { var subscriptBuffer = subscript.toBuffer(); var scriptCodeWriter = new BufferWriter(); @@ -1327,7 +1306,7 @@ Transaction.prototype.verify = function() { var txin = this.inputs[i]; var inputid = txin.prevTxId + ':' + txin.outputIndex; - if (!_.isUndefined(txinmap[inputid])) { + if (txinmap[inputid] !== undefined) { return 'transaction input ' + i + ' duplicate input'; } txinmap[inputid] = true; diff --git a/packages/bitcore-lib/lib/transaction/unspentoutput.js b/packages/bitcore-lib/lib/transaction/unspentoutput.js index f9464f03120..010d0e6280f 100644 --- a/packages/bitcore-lib/lib/transaction/unspentoutput.js +++ b/packages/bitcore-lib/lib/transaction/unspentoutput.js @@ -1,6 +1,5 @@ 'use strict'; -var _ = require('lodash'); var $ = require('../util/preconditions'); var JSUtil = require('../util/js'); @@ -30,24 +29,24 @@ function UnspentOutput(data) { if (!(this instanceof UnspentOutput)) { return new UnspentOutput(data); } - $.checkArgument(_.isObject(data), 'Must provide an object from where to extract data'); + $.checkArgument(JSUtil.isObject(data), 'Must provide an object from where to extract data'); var address = data.address ? new Address(data.address) : undefined; var txId = data.txid ? data.txid : data.txId; if (!txId || !JSUtil.isHexaString(txId) || txId.length > 64) { // TODO: Use the errors library throw new Error('Invalid TXID in object', data); } - var outputIndex = _.isUndefined(data.vout) ? data.outputIndex : data.vout; - if (!_.isNumber(outputIndex)) { + var outputIndex = data.vout === undefined ? data.outputIndex : data.vout; + if (typeof outputIndex !== 'number') { throw new Error('Invalid outputIndex, received ' + outputIndex); } - $.checkArgument(!_.isUndefined(data.scriptPubKey) || !_.isUndefined(data.script), + $.checkArgument(data.scriptPubKey !== undefined || data.script !== undefined, 'Must provide the scriptPubKey for that output!'); var script = new Script(data.scriptPubKey || data.script); - $.checkArgument(!_.isUndefined(data.amount) || !_.isUndefined(data.satoshis), + $.checkArgument(data.amount !== undefined || data.satoshis !== undefined, 'Must provide an amount for the output'); - var amount = !_.isUndefined(data.amount) ? new Unit.fromBTC(data.amount).toSatoshis() : data.satoshis; - $.checkArgument(_.isNumber(amount), 'Amount must be a number'); + var amount = data.amount !== undefined ? new Unit.fromBTC(data.amount).toSatoshis() : data.satoshis; + $.checkArgument(typeof amount === 'number', 'Amount must be a number'); JSUtil.defineImmutable(this, { address: address, txId: txId, diff --git a/packages/bitcore-lib/lib/unit.js b/packages/bitcore-lib/lib/unit.js index b5dee297051..73acbfbb31b 100644 --- a/packages/bitcore-lib/lib/unit.js +++ b/packages/bitcore-lib/lib/unit.js @@ -1,7 +1,5 @@ 'use strict'; -var _ = require('lodash'); - var errors = require('./errors'); var $ = require('./util/preconditions'); @@ -43,7 +41,7 @@ function Unit(amount, code) { } // convert fiat to BTC - if (_.isNumber(code)) { + if (typeof code === 'number' && ! isNaN(code)) { if (code <= 0) { throw new errors.Unit.InvalidRate(code); } @@ -75,7 +73,7 @@ Object.keys(UNITS).forEach(function(key) { * @returns {Unit} A Unit instance */ Unit.fromObject = function fromObject(data){ - $.checkArgument(_.isObject(data), 'Argument is expected to be an object'); + $.checkArgument(typeof data === 'object', 'Argument is expected to be an object'); return new Unit(data.amount, data.code); }; @@ -144,7 +142,7 @@ Unit.prototype._from = function(amount, code) { * @returns {Number} The converted value */ Unit.prototype.to = function(code) { - if (_.isNumber(code)) { + if (typeof code === 'number' && !isNaN(code)) { if (code <= 0) { throw new errors.Unit.InvalidRate(code); } diff --git a/packages/bitcore-lib/lib/uri.js b/packages/bitcore-lib/lib/uri.js index 912a0c3dbaf..71aa0e5020b 100644 --- a/packages/bitcore-lib/lib/uri.js +++ b/packages/bitcore-lib/lib/uri.js @@ -1,6 +1,5 @@ 'use strict'; -var _ = require('lodash'); var URL = require('url'); var Address = require('./address'); @@ -175,11 +174,11 @@ URI.prototype.toObject = URI.prototype.toJSON = function toObject() { var json = {}; for (var i = 0; i < URI.Members.length; i++) { var m = URI.Members[i]; - if (this.hasOwnProperty(m) && typeof(this[m]) !== 'undefined') { + if (this.hasOwnProperty(m) && this[m] !== undefined) { json[m] = this[m].toString(); } } - _.extend(json, this.extras); + Object.assign(json, this.extras); return json; }; @@ -202,7 +201,7 @@ URI.prototype.toString = function() { if (this.r) { query.r = this.r; } - _.extend(query, this.extras); + Object.assign(query, this.extras); return URL.format({ protocol: 'bitcoin:', diff --git a/packages/bitcore-lib/lib/util/js.js b/packages/bitcore-lib/lib/util/js.js index c53e1e1720f..47df71a5636 100644 --- a/packages/bitcore-lib/lib/util/js.js +++ b/packages/bitcore-lib/lib/util/js.js @@ -1,7 +1,5 @@ 'use strict'; -var _ = require('lodash'); - /** * Determines whether a string contains only hexadecimal values * @@ -10,7 +8,7 @@ var _ = require('lodash'); * @return {boolean} true if the string is the hexa representation of a number */ var isHexa = function isHexa(value) { - if (!_.isString(value)) { + if (typeof value !== 'string') { return false; } return /^[0-9a-fA-F]+$/.test(value); @@ -29,7 +27,7 @@ module.exports = { */ isValidJSON: function isValidJSON(arg) { var parsed; - if (!_.isString(arg)) { + if (typeof arg !== 'string') { return false; } try { @@ -80,5 +78,33 @@ module.exports = { isFinite(value) && Math.floor(value) === value && value >= 0; + }, + + /** + * @description sort an array in place based on toString values + * @param {*[]} array + */ + sort: array => array.sort((a, b) => a.toString() > b.toString() ? 1 : a.toString() < b.toString() ? -1 : 0), + + /** + * @description returns true for non-null objects and false otherwise + * @param {*} obj + * @returns {Boolean} + */ + isObject: obj => typeof obj === 'object' && !!obj, + + /** + * @description an implementation of Fisher-Yates shuffling algorithm + * @param {*[]} array + */ + shuffle: array => { + let arr = array, i = arr.length, j, temp; + while (--i > 0) { + j = Math.floor(Math.random() * (i + 1)); + temp = arr[j]; + arr[j] = arr[i]; + arr[i] = temp; + } + return arr; } }; diff --git a/packages/bitcore-lib/lib/util/preconditions.js b/packages/bitcore-lib/lib/util/preconditions.js index 43afc045faf..c4b92c21dee 100644 --- a/packages/bitcore-lib/lib/util/preconditions.js +++ b/packages/bitcore-lib/lib/util/preconditions.js @@ -1,7 +1,6 @@ 'use strict'; var errors = require('../errors'); -var _ = require('lodash'); module.exports = { checkState: function(condition, message) { @@ -16,7 +15,7 @@ module.exports = { }, checkArgumentType: function(argument, type, argumentName) { argumentName = argumentName || '(unknown name)'; - if (_.isString(type)) { + if (typeof type === 'string') { if (type === 'Buffer') { var buffer = require('buffer'); // './buffer' fails on cordova & RN if (!buffer.Buffer.isBuffer(argument)) { diff --git a/packages/bitcore-lib/test/crypto/signature.js b/packages/bitcore-lib/test/crypto/signature.js index 0f65f3c3da6..7e5d708cd26 100644 --- a/packages/bitcore-lib/test/crypto/signature.js +++ b/packages/bitcore-lib/test/crypto/signature.js @@ -1,6 +1,5 @@ 'use strict'; -var _ = require('lodash'); var should = require('chai').should(); var bitcore = require('../..'); var BN = bitcore.crypto.BN; @@ -330,7 +329,7 @@ describe('Signature', function() { [(Signature.SIGHASH_ANYONECANPAY | Signature.SIGHASH_SINGLE) + 1, false], [(Signature.SIGHASH_ANYONECANPAY | Signature.SIGHASH_ALL) - 1, false], ]; - _.each(testCases, function(testCase) { + testCases.forEach(function(testCase) { sig.nhashtype = testCase[0]; sig.hasDefinedHashtype().should.equal(testCase[1]); }); diff --git a/packages/bitcore-lib/test/hdkeys.js b/packages/bitcore-lib/test/hdkeys.js index 0cc0d9edcf8..ce9512d842d 100644 --- a/packages/bitcore-lib/test/hdkeys.js +++ b/packages/bitcore-lib/test/hdkeys.js @@ -10,7 +10,6 @@ /* jshint maxstatements: 100 */ /* jshint unused: false */ -var _ = require('lodash'); var should = require('chai').should(); var expect = require('chai').expect; var sinon = require('sinon'); @@ -20,10 +19,7 @@ var HDPrivateKey = bitcore.HDPrivateKey; var HDPublicKey = bitcore.HDPublicKey; describe('HDKeys building with static methods', function() { - var classes = [HDPublicKey, HDPrivateKey]; - var clazz, index; - - _.each(classes, function(clazz) { + [HDPublicKey, HDPrivateKey].forEach(function(clazz) { var expectStaticMethodFail = function(staticMethod, argument, message) { expect(clazz[staticMethod].bind(null, argument)).to.throw(message); }; diff --git a/packages/bitcore-lib/test/hdprivatekey.js b/packages/bitcore-lib/test/hdprivatekey.js index 7947f826ead..fb66c6c35c3 100644 --- a/packages/bitcore-lib/test/hdprivatekey.js +++ b/packages/bitcore-lib/test/hdprivatekey.js @@ -1,13 +1,10 @@ 'use strict'; /* jshint unused: false */ -var _ = require('lodash'); -var assert = require('assert'); var should = require('chai').should(); var expect = require('chai').expect; var bitcore = require('..'); var errors = bitcore.errors; var hdErrors = errors.HDPrivateKey; -var buffer = require('buffer'); var Networks = bitcore.Networks; var BufferUtil = bitcore.util.buffer; var HDPrivateKey = bitcore.HDPrivateKey; @@ -73,10 +70,7 @@ describe('HDPrivate key interface', function() { }); it('builds a json keeping the structure and same members', function() { - assert(_.isEqual( - new HDPrivateKey(json).toJSON(), - new HDPrivateKey(xprivkey).toJSON() - )); + (new HDPrivateKey(json)).toJSON().should.deep.equal(new HDPrivateKey(xprivkey).toJSON()); }); describe('instantiation', function() { @@ -290,9 +284,7 @@ describe('HDPrivate key interface', function() { it('toObject leaves no Buffer instances', function() { var privKey = new HDPrivateKey(xprivkey); var object = privKey.toObject(); - _.each(_.values(object), function(value) { - expect(BufferUtil.isBuffer(value)).to.equal(false); - }); + Object.values(object).forEach(value => BufferUtil.isBuffer(value).should.equal(false)); }); it('roundtrips toObject', function() { expect(HDPrivateKey.fromObject(new HDPrivateKey(xprivkey).toObject()).xprivkey).to.equal(xprivkey); diff --git a/packages/bitcore-lib/test/hdpublickey.js b/packages/bitcore-lib/test/hdpublickey.js index 29369d2b94b..86afa6646ea 100644 --- a/packages/bitcore-lib/test/hdpublickey.js +++ b/packages/bitcore-lib/test/hdpublickey.js @@ -1,8 +1,6 @@ 'use strict'; /* jshint unused: false */ -var _ = require('lodash'); -var assert = require('assert'); var should = require('chai').should(); var expect = require('chai').expect; var bitcore = require('..'); @@ -98,10 +96,7 @@ describe('HDPublicKey interface', function() { }); it('can generate a json that has a particular structure', function() { - assert(_.isEqual( - new HDPublicKey(JSON.parse(json)).toJSON(), - new HDPublicKey(xpubkey).toJSON() - )); + new HDPublicKey(JSON.parse(json)).toJSON().should.deep.equal(new HDPublicKey(xpubkey).toJSON()); }); it('builds from a buffer object', function() { diff --git a/packages/bitcore-lib/test/opcode.js b/packages/bitcore-lib/test/opcode.js index e28fc511bea..d0b374b7e9b 100644 --- a/packages/bitcore-lib/test/opcode.js +++ b/packages/bitcore-lib/test/opcode.js @@ -1,6 +1,5 @@ 'use strict'; -var _ = require('lodash'); var chai = require('chai'); var should = chai.should(); var expect = chai.expect; @@ -86,7 +85,7 @@ describe('Opcode', function() { describe('@map', function() { it('should have a map containing 118 elements', function() { - _.size(Opcode.map).should.equal(118); + Object.keys(Opcode.map).length.should.equal(118); }); }); diff --git a/packages/bitcore-lib/test/script/interpreter.js b/packages/bitcore-lib/test/script/interpreter.js index d36999ebe5a..155c617893e 100644 --- a/packages/bitcore-lib/test/script/interpreter.js +++ b/packages/bitcore-lib/test/script/interpreter.js @@ -10,7 +10,6 @@ var Script = bitcore.Script; var BN = bitcore.crypto.BN; var BufferWriter = bitcore.encoding.BufferWriter; var Opcode = bitcore.Opcode; -var _ = require('lodash'); var script_tests = require('../data/bitcoind/script_tests'); var tx_valid = require('../data/bitcoind/tx_valid'); @@ -37,7 +36,7 @@ Script.fromBitcoindString = function(str) { var cbuf = Buffer.from(tstr); tbuf = Script().add(cbuf).toBuffer(); bw.write(tbuf); - } else if (typeof Opcode['OP_' + token] !== 'undefined') { + } else if (Opcode['OP_' + token] !== undefined) { opstr = 'OP_' + token; opcodenum = Opcode[opstr]; bw.writeUInt8(opcodenum); @@ -376,7 +375,7 @@ describe('Interpreter', function() { c++; var witness, amount; - if (_.isArray(vector[0])) { + if (Array.isArray(vector[0])) { var extra = vector.shift(); amount = extra.pop() * 1e8; witness = extra.map(function(x) { diff --git a/packages/bitcore-lib/test/transaction/input/input.js b/packages/bitcore-lib/test/transaction/input/input.js index a8343c96020..787b1da8e7e 100644 --- a/packages/bitcore-lib/test/transaction/input/input.js +++ b/packages/bitcore-lib/test/transaction/input/input.js @@ -2,7 +2,6 @@ var should = require('chai').should(); var expect = require('chai').expect; -var _ = require('lodash'); var bitcore = require('../../..'); var errors = bitcore.errors; @@ -52,12 +51,10 @@ describe('Transaction.Input', function() { }); it('has abstract methods: "getSignatures", "isFullySigned", "addSignature", "clearSignatures"', function() { - var input = new Input(output); - _.each(['getSignatures', 'isFullySigned', 'addSignature', 'clearSignatures'], function(method) { - expect(function() { - return input[method](); - }).to.throw(errors.AbstractMethodInvoked); - }); + let input = new Input(output); + for (let method of ['getSignatures', 'isFullySigned', 'addSignature', 'clearSignatures']) { + expect(input[method]).to.throw(errors.AbstractMethodInvoked); + } }); it('detects coinbase transactions', function() { new Input(output).isNull().should.equal(false); diff --git a/packages/bitcore-lib/test/transaction/input/multisig.js b/packages/bitcore-lib/test/transaction/input/multisig.js index 16a63b0d3c5..03708d7e8b6 100644 --- a/packages/bitcore-lib/test/transaction/input/multisig.js +++ b/packages/bitcore-lib/test/transaction/input/multisig.js @@ -2,8 +2,6 @@ /* jshint unused: false */ var should = require('chai').should(); -var expect = require('chai').expect; -var _ = require('lodash'); var bitcore = require('../../..'); var Transaction = bitcore.Transaction; @@ -71,14 +69,14 @@ describe('MultiSigInput', function() { .to(address, 1000000); var input = transaction.inputs[0]; - _.every(input.publicKeysWithoutSignature(), function(publicKeyMissing) { + input.publicKeysWithoutSignature().every(function(publicKeyMissing) { var serialized = publicKeyMissing.toString(); return serialized === public1.toString() || serialized === public2.toString() || serialized === public3.toString(); }).should.equal(true); transaction.sign(privateKey1); - _.every(input.publicKeysWithoutSignature(), function(publicKeyMissing) { + input.publicKeysWithoutSignature().every(function(publicKeyMissing) { var serialized = publicKeyMissing.toString(); return serialized === public2.toString() || serialized === public3.toString(); diff --git a/packages/bitcore-lib/test/transaction/input/multisigscripthash.js b/packages/bitcore-lib/test/transaction/input/multisigscripthash.js index 1b87718733e..6142dd87b02 100644 --- a/packages/bitcore-lib/test/transaction/input/multisigscripthash.js +++ b/packages/bitcore-lib/test/transaction/input/multisigscripthash.js @@ -2,9 +2,6 @@ /* jshint unused: false */ var should = require('chai').should(); -var expect = require('chai').expect; -var _ = require('lodash'); - var bitcore = require('../../..'); var Transaction = bitcore.Transaction; var PrivateKey = bitcore.PrivateKey; @@ -64,14 +61,14 @@ describe('MultiSigScriptHashInput', function() { .to(address, 1000000); var input = transaction.inputs[0]; - _.every(input.publicKeysWithoutSignature(), function(publicKeyMissing) { + input.publicKeysWithoutSignature().every(function(publicKeyMissing) { var serialized = publicKeyMissing.toString(); return serialized === public1.toString() || serialized === public2.toString() || serialized === public3.toString(); }).should.equal(true); transaction.sign(privateKey1); - _.every(input.publicKeysWithoutSignature(), function(publicKeyMissing) { + input.publicKeysWithoutSignature().every(function(publicKeyMissing) { var serialized = publicKeyMissing.toString(); return serialized === public2.toString() || serialized === public3.toString(); @@ -179,14 +176,14 @@ describe('MultiSigScriptHashInput', function() { .to(address, 1000000); var input = transaction.inputs[0]; - _.every(input.publicKeysWithoutSignature(), function(publicKeyMissing) { + input.publicKeysWithoutSignature().every(function(publicKeyMissing) { var serialized = publicKeyMissing.toString(); return serialized === public1.toString() || serialized === public2.toString() || serialized === public3.toString(); }).should.equal(true); transaction.sign(privateKey1); - _.every(input.publicKeysWithoutSignature(), function(publicKeyMissing) { + input.publicKeysWithoutSignature().every(function(publicKeyMissing) { var serialized = publicKeyMissing.toString(); return serialized === public2.toString() || serialized === public3.toString(); diff --git a/packages/bitcore-lib/test/transaction/input/publickeyhash.js b/packages/bitcore-lib/test/transaction/input/publickeyhash.js index f733604f02b..8db4b20c542 100644 --- a/packages/bitcore-lib/test/transaction/input/publickeyhash.js +++ b/packages/bitcore-lib/test/transaction/input/publickeyhash.js @@ -3,7 +3,6 @@ var should = require('chai').should(); var expect = require('chai').expect; -var _ = require('lodash'); var bitcore = require('../../..'); var Transaction = bitcore.Transaction; diff --git a/packages/bitcore-lib/test/transaction/output.js b/packages/bitcore-lib/test/transaction/output.js index 51f5af60955..1ac4b33cb5b 100644 --- a/packages/bitcore-lib/test/transaction/output.js +++ b/packages/bitcore-lib/test/transaction/output.js @@ -3,8 +3,6 @@ /* jshint unused: false */ /* jshint latedef: false */ var should = require("chai").should(); -var expect = require("chai").expect; -var _ = require("lodash"); var bitcore = require("../.."); var BN = bitcore.crypto.BN; diff --git a/packages/bitcore-lib/test/transaction/signature.js b/packages/bitcore-lib/test/transaction/signature.js index f0d52bed70f..d7e4d31e2c6 100644 --- a/packages/bitcore-lib/test/transaction/signature.js +++ b/packages/bitcore-lib/test/transaction/signature.js @@ -4,7 +4,6 @@ /* jshint latedef: false */ var should = require('chai').should(); var expect = require('chai').expect; -var _ = require('lodash'); var bitcore = require('../..'); var Transaction = bitcore.Transaction; diff --git a/packages/bitcore-lib/test/transaction/transaction.js b/packages/bitcore-lib/test/transaction/transaction.js index 56dd9d6e4d3..2c6f3c0861c 100644 --- a/packages/bitcore-lib/test/transaction/transaction.js +++ b/packages/bitcore-lib/test/transaction/transaction.js @@ -4,8 +4,8 @@ /* jshint latedef: false */ var should = require('chai').should(); var expect = require('chai').expect; -var _ = require('lodash'); var sinon = require('sinon'); +var JSUtil = require('../util/js'); var bitcore = require('../..'); var BN = bitcore.crypto.BN; @@ -16,7 +16,6 @@ var PrivateKey = bitcore.PrivateKey; var Script = bitcore.Script; var Interpreter = bitcore.Script.Interpreter; var Address = bitcore.Address; -var Networks = bitcore.Networks; var Opcode = bitcore.Opcode; var errors = bitcore.errors; @@ -131,7 +130,7 @@ describe('Transaction', function() { }); it('fromObject with pay-to-public-key previous outputs', function() { - var tx = bitcore.Transaction({ + var tx = new Transaction({ hash: '132856bf03d6415562a556437d22ac63c37a4595fd986c796eb8e02dc031aa25', version: 1, inputs: [ @@ -159,7 +158,7 @@ describe('Transaction', function() { ], nLockTime: 139 }); - tx.inputs[0].should.be.instanceof(bitcore.Transaction.Input.PublicKey); + tx.inputs[0].should.be.instanceof(Transaction.Input.PublicKey); tx.inputs[0].output.satoshis.should.equal(5000000000); tx.inputs[0].output.script.toHex().should.equal('2103b1c65d65f1ff3fe145a4ede692460ae0606671d04e8449e99dd11c66ab55a7feac'); }); @@ -509,84 +508,64 @@ describe('Transaction', function() { transaction.outputs.length.should.equal(2); transaction.outputs[1].satoshis.should.equal(10000); }); - it('fee per kb can be set up manually', function() { - var inputs = _.map(_.range(10), function(i) { - var utxo = _.clone(simpleUtxoWith100000Satoshis); - utxo.outputIndex = i; - return utxo; + describe('inputs', function() { + let transaction; + let inputs = []; + + before(function() { + for (let i = 0; i < 10; i++) { + inputs.push({ ...simpleUtxoWith100000Satoshis, outputIndex: i }) + } }); - var transaction = new Transaction() - .from(inputs) - .to(toAddress, 950000) - .feePerKb(8000) - .change(changeAddress) - .sign(privateKey); - transaction._estimateSize().should.be.within(1000, 1999); - transaction.outputs.length.should.equal(2); - transaction.outputs[1].satoshis.should.equal(37584); - }); - it('fee per byte (low fee) can be set up manually', function () { - var inputs = _.map(_.range(10), function (i) { - var utxo = _.clone(simpleUtxoWith100000Satoshis); - utxo.outputIndex = i; - return utxo; + + beforeEach(function() { + transaction = (new Transaction()).from(inputs).change(changeAddress); }); - var transaction = new Transaction() - .from(inputs) - .to(toAddress, 950000) - .feePerByte(1) - .change(changeAddress) - .sign(privateKey); - transaction._estimateSize().should.be.within(1000, 1999); - transaction.outputs.length.should.equal(2); - transaction.outputs[1].satoshis.should.be.within(48001, 49000); - }); - it('fee per byte (high fee) can be set up manually', function () { - var inputs = _.map(_.range(10), function (i) { - var utxo = _.clone(simpleUtxoWith100000Satoshis); - utxo.outputIndex = i; - return utxo; + + it('fee per kb can be set up manually', function() { + transaction + .to(toAddress, 950000) + .feePerKb(8000) + .sign(privateKey); + transaction._estimateSize().should.be.within(1000, 1999); + transaction.outputs.length.should.equal(2); + transaction.outputs[1].satoshis.should.equal(37584); }); - var transaction = new Transaction() - .from(inputs) - .to(toAddress, 950000) - .feePerByte(2) - .change(changeAddress) - .sign(privateKey); - transaction._estimateSize().should.be.within(1000, 1999); - transaction.outputs.length.should.equal(2); - transaction.outputs[1].satoshis.should.be.within(46002, 48000); - }); - it('fee per byte can be set up manually', function () { - var inputs = _.map(_.range(10), function (i) { - var utxo = _.clone(simpleUtxoWith100000Satoshis); - utxo.outputIndex = i; - return utxo; + it('fee per byte (low fee) can be set up manually', function () { + transaction + .to(toAddress, 950000) + .feePerByte(1) + .sign(privateKey); + transaction._estimateSize().should.be.within(1000, 1999); + transaction.outputs.length.should.equal(2); + transaction.outputs[1].satoshis.should.be.within(48001, 49000); }); - var transaction = new Transaction() - .from(inputs) - .to(toAddress, 950000) - .feePerByte(13) - .change(changeAddress) - .sign(privateKey); - transaction._estimateSize().should.be.within(1000, 1999); - transaction.outputs.length.should.equal(2); - transaction.outputs[1].satoshis.should.be.within(24013, 37000); - }); - it('fee per byte not enough for change', function () { - var inputs = _.map(_.range(10), function (i) { - var utxo = _.clone(simpleUtxoWith100000Satoshis); - utxo.outputIndex = i; - return utxo; + it('fee per byte (high fee) can be set up manually', function () { + transaction + .to(toAddress, 950000) + .feePerByte(2) + .sign(privateKey); + transaction._estimateSize().should.be.within(1000, 1999); + transaction.outputs.length.should.equal(2); + transaction.outputs[1].satoshis.should.be.within(46002, 48000); + }); + it('fee per byte can be set up manually', function () { + transaction + .to(toAddress, 950000) + .feePerByte(13) + .sign(privateKey); + transaction._estimateSize().should.be.within(1000, 1999); + transaction.outputs.length.should.equal(2); + transaction.outputs[1].satoshis.should.be.within(24013, 37000); + }); + it('fee per byte not enough for change', function () { + transaction + .to(toAddress, 999999) + .feePerByte(1) + .sign(privateKey); + transaction._estimateSize().should.be.within(1000, 1999); + transaction.outputs.length.should.equal(1); }); - var transaction = new Transaction() - .from(inputs) - .to(toAddress, 999999) - .feePerByte(1) - .change(changeAddress) - .sign(privateKey); - transaction._estimateSize().should.be.within(1000, 1999); - transaction.outputs.length.should.equal(1); }); it('if satoshis are invalid', function() { var transaction = new Transaction() @@ -1203,18 +1182,12 @@ describe('Transaction', function() { }); it('allows the user to randomize the output order', function() { - var shuffle = sinon.stub(_, 'shuffle'); - shuffle.onFirstCall().returns([out2, out1, out4, out3]); - transaction._changeIndex.should.equal(3); transaction.shuffleOutputs(); - transaction.outputs[0].should.equal(out2); - transaction.outputs[1].should.equal(out1); - transaction.outputs[2].should.equal(out4); - transaction.outputs[3].should.equal(out3); - transaction._changeIndex.should.equal(2); - - _.shuffle.restore(); + transaction.outputs.should.include(out1); + transaction.outputs.should.include(out2); + transaction.outputs.should.include(out3); + transaction.outputs.should.include(out4); }); it('fails if the provided function does not work as expected', function() { @@ -1316,6 +1289,12 @@ describe('Transaction', function() { }); describe('bitcoinjs fixtures', function() { + before(function() { + sinon.stub(Input.prototype, 'clearSignatures'); + }); + after(function() { + Input.prototype.clearSignatures.restore(); + }); var fixture = require('../data/bip69.json'); @@ -1335,7 +1314,6 @@ describe('Transaction', function() { script: new Script(), output: new Output({ script: new Script(), satoshis: 0 }) }); - input.clearSignatures = function () {}; return input; }); tx.inputs = inputSet.inputs; @@ -1834,8 +1812,8 @@ describe('Transaction', function() { var flags; var check; var interpreter; - var output1 = bitcore.Transaction('01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff01010000000000000017a9147b615f35c476c8f3c555b4d52e54760b2873742f8700000000'); - var input2 = bitcore.Transaction('01000000000101eefb67109c118e958d81f3f98638d48bc6c14eae97cedfce7c397eabb92b4e320000000017160014eff6eebd0dcd3923ca3ab3ea57071fa82ea1faa5ffffffff010100000000000000000247304402200ed4fa4bc8fbae2d1e88bbe8691b21233c23770e5eebf9767853de8579f5790a022015cb3f3dc88720199ee1ed5a9f4cf3186a29a0c361512f03b648c9998b3da7b4014104dfaee8168fe5d1ead2e0c8bb12e2d3ba500ade4f6c4983f3dbe5b70ffeaca1551d43c6c962b69fb8d2f4c02faaf1d4571aae7bbd209df5f3b8cd153e60e1627300000000'); + var output1 = Transaction('01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff01010000000000000017a9147b615f35c476c8f3c555b4d52e54760b2873742f8700000000'); + var input2 = Transaction('01000000000101eefb67109c118e958d81f3f98638d48bc6c14eae97cedfce7c397eabb92b4e320000000017160014eff6eebd0dcd3923ca3ab3ea57071fa82ea1faa5ffffffff010100000000000000000247304402200ed4fa4bc8fbae2d1e88bbe8691b21233c23770e5eebf9767853de8579f5790a022015cb3f3dc88720199ee1ed5a9f4cf3186a29a0c361512f03b648c9998b3da7b4014104dfaee8168fe5d1ead2e0c8bb12e2d3ba500ade4f6c4983f3dbe5b70ffeaca1551d43c6c962b69fb8d2f4c02faaf1d4571aae7bbd209df5f3b8cd153e60e1627300000000'); var scriptPubkey = output1.outputs[0].script; var scriptSig = input2.inputs[0].script; var witnesses = input2.inputs[0].getWitnesses(); diff --git a/packages/bitcore-lib/test/transaction/unspentoutput.js b/packages/bitcore-lib/test/transaction/unspentoutput.js index b9c707aa56e..3e8e988be71 100644 --- a/packages/bitcore-lib/test/transaction/unspentoutput.js +++ b/packages/bitcore-lib/test/transaction/unspentoutput.js @@ -1,6 +1,5 @@ 'use strict'; -var _ = require('lodash'); var chai = require('chai'); var should = chai.should(); var expect = chai.expect; @@ -40,11 +39,7 @@ describe('UnspentOutput', function() { }); it('fails if vout is not a number', function() { - var sample = _.cloneDeep(sampleData2); - sample.vout = '1'; - expect(function() { - return new UnspentOutput(sample); - }).to.throw(); + expect(() => new UnspentOutput({ ...sampleData2, vout: '1' })).to.throw(); }); it('displays nicely on the console', function() { diff --git a/packages/bitcore-mnemonic/lib/mnemonic.js b/packages/bitcore-mnemonic/lib/mnemonic.js index 8d40e823b5b..693239af5d1 100644 --- a/packages/bitcore-mnemonic/lib/mnemonic.js +++ b/packages/bitcore-mnemonic/lib/mnemonic.js @@ -3,7 +3,6 @@ const bitcore = require('bitcore-lib'); const BN = bitcore.crypto.BN; const unorm = require('unorm'); -const _ = bitcore.deps._; const pbkdf2 = require('./pbkdf2'); const errors = require('./errors'); @@ -40,7 +39,7 @@ var Mnemonic = function(data, wordlist) { return new Mnemonic(data, wordlist); } - if (_.isArray(data)) { + if (Array.isArray(data)) { wordlist = data; data = null; } @@ -51,9 +50,9 @@ var Mnemonic = function(data, wordlist) { if (Buffer.isBuffer(data)) { seed = data; ent = seed.length * 8; - } else if (_.isString(data)) { + } else if (typeof data === 'string') { phrase = unorm.nfkd(data); - } else if (_.isNumber(data)) { + } else if (typeof data === 'number' && !isNaN(data)) { ent = data; } else if (data) { throw new bitcore.errors.InvalidArgument('data', 'Must be a Buffer, a string or an integer'); @@ -193,7 +192,7 @@ Mnemonic.prototype.toSeed = function(passphrase) { */ Mnemonic.fromSeed = function(seed, wordlist) { $.checkArgument(Buffer.isBuffer(seed), 'seed must be a Buffer.'); - $.checkArgument(_.isArray(wordlist) || _.isString(wordlist), 'wordlist must be a string or an array.'); + $.checkArgument(Array.isArray(wordlist) || typeof wordlist === 'string', 'wordlist must be a string or an array.'); return new Mnemonic(seed, wordlist); }; diff --git a/packages/bitcore-p2p/integration/bitcoind.js b/packages/bitcore-p2p/integration/bitcoind.js index e24ed0119a3..632ae46094b 100644 --- a/packages/bitcore-p2p/integration/bitcoind.js +++ b/packages/bitcore-p2p/integration/bitcoind.js @@ -4,21 +4,16 @@ var chai = require('chai'); /* jshint unused: false */ var should = chai.should(); -var sinon = require('sinon'); var bitcore = require('bitcore-lib'); -var _ = bitcore.deps._; var Random = bitcore.crypto.Random; var BN = bitcore.crypto.BN; -var BufferUtil = bitcore.util.buffer; var p2p = require('../'); var Peer = p2p.Peer; -var Pool = p2p.Pool; var Networks = bitcore.Networks; var Messages = p2p.Messages; var Inventory = p2p.Inventory; var Block = bitcore.Block; -var Transaction = bitcore.Transaction; // config var network = process.env.NETWORK === 'testnet' ? Networks.testnet : Networks.livenet; @@ -74,9 +69,9 @@ describe('Integration with ' + network.name + ' bitcoind', function() { }; it('connects', function(cb) { connect(function(peer) { - peer.version.should.be.above(70000); - _.isString(peer.subversion).should.equal(true); - _.isNumber(peer.bestHeight).should.equal(true); + peer.version.should.be.a('number').above(70000); + peer.subversion.should.be.a('string'); + peer.bestHeight.should.be.a('number'); cb(); }); }); diff --git a/packages/bitcore-p2p/lib/inventory.js b/packages/bitcore-p2p/lib/inventory.js index dd21d601ef8..c54192e35c8 100644 --- a/packages/bitcore-p2p/lib/inventory.js +++ b/packages/bitcore-p2p/lib/inventory.js @@ -5,7 +5,6 @@ var $ = bitcore.util.preconditions; var BufferUtil = bitcore.util.buffer; var BufferReader = bitcore.encoding.BufferReader; var BufferWriter = bitcore.encoding.BufferWriter; -var _ = bitcore.deps._; /** * A constructor for inventory related Bitcoin messages such as @@ -31,7 +30,7 @@ function Inventory(obj) { */ Inventory.forItem = function(type, hash) { $.checkArgument(hash); - if (_.isString(hash)) { + if (typeof hash === 'string') { hash = new Buffer(hash, 'hex'); hash = BufferUtil.reverse(hash); } diff --git a/packages/bitcore-p2p/lib/messages/commands/addr.js b/packages/bitcore-p2p/lib/messages/commands/addr.js index 19ba1aa228a..5458a26f02b 100644 --- a/packages/bitcore-p2p/lib/messages/commands/addr.js +++ b/packages/bitcore-p2p/lib/messages/commands/addr.js @@ -5,7 +5,6 @@ var inherits = require('util').inherits; var bitcore = require('bitcore-lib'); var utils = require('../utils'); var $ = bitcore.util.preconditions; -var _ = bitcore.deps._; var BufferReader = bitcore.encoding.BufferReader; var BufferWriter = bitcore.encoding.BufferWriter; @@ -19,11 +18,12 @@ function AddrMessage(arg, options) { Message.call(this, options); this.command = 'addr'; $.checkArgument( - _.isUndefined(arg) || - (Array.isArray(arg) && - !_.isUndefined(arg[0].services) && - !_.isUndefined(arg[0].ip) && - !_.isUndefined(arg[0].port)), + arg === undefined || ( + Array.isArray(arg) && + arg[0].services && + arg[0].ip && + arg[0].port + ), 'First argument is expected to be an array of addrs' ); this.addresses = arg; diff --git a/packages/bitcore-p2p/lib/messages/commands/block.js b/packages/bitcore-p2p/lib/messages/commands/block.js index c4a15aa7610..8828813efcd 100644 --- a/packages/bitcore-p2p/lib/messages/commands/block.js +++ b/packages/bitcore-p2p/lib/messages/commands/block.js @@ -4,7 +4,6 @@ var Message = require('../message'); var inherits = require('util').inherits; var bitcore = require('bitcore-lib'); var $ = bitcore.util.preconditions; -var _ = bitcore.deps._; /** * @param {Block=} arg - An instance of a Block @@ -18,7 +17,7 @@ function BlockMessage(arg, options) { this.Block = options.Block; this.command = 'block'; $.checkArgument( - _.isUndefined(arg) || arg instanceof this.Block, + arg === undefined || arg instanceof this.Block, 'An instance of Block or undefined is expected' ); this.block = arg; diff --git a/packages/bitcore-p2p/lib/messages/commands/filteradd.js b/packages/bitcore-p2p/lib/messages/commands/filteradd.js index 7012ce76b8e..ba64f97f236 100644 --- a/packages/bitcore-p2p/lib/messages/commands/filteradd.js +++ b/packages/bitcore-p2p/lib/messages/commands/filteradd.js @@ -8,7 +8,6 @@ var BufferUtil = bitcore.util.buffer; var BufferWriter = bitcore.encoding.BufferWriter; var BufferReader = bitcore.encoding.BufferReader; var $ = bitcore.util.preconditions; -var _ = bitcore.deps._; /** * Request peer to add data to a bloom filter already set by 'filterload' @@ -21,7 +20,7 @@ function FilteraddMessage(arg, options) { Message.call(this, options); this.command = 'filteradd'; $.checkArgument( - _.isUndefined(arg) || BufferUtil.isBuffer(arg), + arg === undefined || BufferUtil.isBuffer(arg), 'First argument is expected to be a Buffer or undefined' ); this.data = arg || BufferUtil.EMPTY_BUFFER; diff --git a/packages/bitcore-p2p/lib/messages/commands/filterload.js b/packages/bitcore-p2p/lib/messages/commands/filterload.js index b8dbcae0554..a23fb78640b 100644 --- a/packages/bitcore-p2p/lib/messages/commands/filterload.js +++ b/packages/bitcore-p2p/lib/messages/commands/filterload.js @@ -6,7 +6,6 @@ var bitcore = require('bitcore-lib'); var BufferUtil = bitcore.util.buffer; var BloomFilter = require('../../bloomfilter'); var $ = bitcore.util.preconditions; -var _ = bitcore.deps._; /** * Request peer to send inv messages based on a bloom filter @@ -19,7 +18,7 @@ function FilterloadMessage(arg, options) { Message.call(this, options); this.command = 'filterload'; $.checkArgument( - _.isUndefined(arg) || arg instanceof BloomFilter, + arg === undefined || arg instanceof BloomFilter, 'An instance of BloomFilter or undefined is expected' ); this.filter = arg; diff --git a/packages/bitcore-p2p/lib/messages/commands/getdata.js b/packages/bitcore-p2p/lib/messages/commands/getdata.js index 61088546334..fe83f3a696c 100644 --- a/packages/bitcore-p2p/lib/messages/commands/getdata.js +++ b/packages/bitcore-p2p/lib/messages/commands/getdata.js @@ -6,7 +6,6 @@ var bitcore = require('bitcore-lib'); var utils = require('../utils'); var BufferReader = bitcore.encoding.BufferReader; var BufferWriter = bitcore.encoding.BufferWriter; -var _ = bitcore.deps._; /** * @param {Object|Array=} - options - If options is an array will use as "inventory" diff --git a/packages/bitcore-p2p/lib/messages/commands/headers.js b/packages/bitcore-p2p/lib/messages/commands/headers.js index 5fbd54cc966..7c534f4eb08 100644 --- a/packages/bitcore-p2p/lib/messages/commands/headers.js +++ b/packages/bitcore-p2p/lib/messages/commands/headers.js @@ -6,7 +6,6 @@ var bitcore = require('bitcore-lib'); var utils = require('../utils'); var BufferReader = bitcore.encoding.BufferReader; var BufferWriter = bitcore.encoding.BufferWriter; -var _ = bitcore.deps._; var $ = bitcore.util.preconditions; /** @@ -24,7 +23,7 @@ function HeadersMessage(arg, options) { this.BlockHeader = options.BlockHeader; this.command = 'headers'; $.checkArgument( - _.isUndefined(arg) || (Array.isArray(arg) && arg[0] instanceof this.BlockHeader), + arg === undefined || (Array.isArray(arg) && arg[0] instanceof this.BlockHeader), 'First argument is expected to be an array of BlockHeader instances' ); this.headers = arg; diff --git a/packages/bitcore-p2p/lib/messages/commands/inv.js b/packages/bitcore-p2p/lib/messages/commands/inv.js index 7ebf9197c0f..1f1810f4677 100644 --- a/packages/bitcore-p2p/lib/messages/commands/inv.js +++ b/packages/bitcore-p2p/lib/messages/commands/inv.js @@ -6,7 +6,6 @@ var bitcore = require('bitcore-lib'); var utils = require('../utils'); var BufferReader = bitcore.encoding.BufferReader; var BufferWriter = bitcore.encoding.BufferWriter; -var _ = bitcore.deps._; /** * @param {Array=} arg - An array of inventory diff --git a/packages/bitcore-p2p/lib/messages/commands/merkleblock.js b/packages/bitcore-p2p/lib/messages/commands/merkleblock.js index e04e58e0c2a..9e72fcb9c17 100644 --- a/packages/bitcore-p2p/lib/messages/commands/merkleblock.js +++ b/packages/bitcore-p2p/lib/messages/commands/merkleblock.js @@ -5,7 +5,6 @@ var inherits = require('util').inherits; var bitcore = require('bitcore-lib'); var BufferUtil = bitcore.util.buffer; var $ = bitcore.util.preconditions; -var _ = bitcore.deps._; /** * Contains information about a MerkleBlock @@ -21,7 +20,7 @@ function MerkleblockMessage(arg, options) { this.MerkleBlock = options.MerkleBlock; // constructor this.command = 'merkleblock'; $.checkArgument( - _.isUndefined(arg) || arg instanceof this.MerkleBlock, + arg === undefined || arg instanceof this.MerkleBlock, 'An instance of MerkleBlock or undefined is expected' ); this.merkleBlock = arg; diff --git a/packages/bitcore-p2p/lib/messages/commands/notfound.js b/packages/bitcore-p2p/lib/messages/commands/notfound.js index fd99c244eb3..f7a6710bddb 100644 --- a/packages/bitcore-p2p/lib/messages/commands/notfound.js +++ b/packages/bitcore-p2p/lib/messages/commands/notfound.js @@ -6,7 +6,6 @@ var bitcore = require('bitcore-lib'); var utils = require('../utils'); var BufferReader = bitcore.encoding.BufferReader; var BufferWriter = bitcore.encoding.BufferWriter; -var _ = bitcore.deps._; /** * @param {Array} arg - An array of inventory diff --git a/packages/bitcore-p2p/lib/messages/commands/ping.js b/packages/bitcore-p2p/lib/messages/commands/ping.js index c616522bc6c..74fac2333cd 100644 --- a/packages/bitcore-p2p/lib/messages/commands/ping.js +++ b/packages/bitcore-p2p/lib/messages/commands/ping.js @@ -5,7 +5,6 @@ var inherits = require('util').inherits; var bitcore = require('bitcore-lib'); var utils = require('../utils'); var $ = bitcore.util.preconditions; -var _ = bitcore.deps._; var BufferUtil = bitcore.util.buffer; var BufferReader = bitcore.encoding.BufferReader; @@ -20,7 +19,7 @@ function PingMessage(arg, options) { Message.call(this, options); this.command = 'ping'; $.checkArgument( - _.isUndefined(arg) || (BufferUtil.isBuffer(arg) && arg.length === 8), + arg === undefined || (BufferUtil.isBuffer(arg) && arg.length === 8), 'First argument is expected to be an 8 byte buffer' ); this.nonce = arg || utils.getNonce(); diff --git a/packages/bitcore-p2p/lib/messages/commands/pong.js b/packages/bitcore-p2p/lib/messages/commands/pong.js index 57af37c520a..f099a0b12bf 100644 --- a/packages/bitcore-p2p/lib/messages/commands/pong.js +++ b/packages/bitcore-p2p/lib/messages/commands/pong.js @@ -5,7 +5,6 @@ var inherits = require('util').inherits; var bitcore = require('bitcore-lib'); var utils = require('../utils'); var $ = bitcore.util.preconditions; -var _ = bitcore.deps._; var BufferUtil = bitcore.util.buffer; var BufferReader = bitcore.encoding.BufferReader; @@ -20,7 +19,7 @@ function PongMessage(arg, options) { Message.call(this, options); this.command = 'pong'; $.checkArgument( - _.isUndefined(arg) || (BufferUtil.isBuffer(arg) && arg.length === 8), + arg === undefined || (BufferUtil.isBuffer(arg) && arg.length === 8), 'First argument is expected to be an 8 byte buffer' ); this.nonce = arg || utils.getNonce(); diff --git a/packages/bitcore-p2p/lib/messages/commands/tx.js b/packages/bitcore-p2p/lib/messages/commands/tx.js index 1d4c46b6748..384ae1e3d8e 100644 --- a/packages/bitcore-p2p/lib/messages/commands/tx.js +++ b/packages/bitcore-p2p/lib/messages/commands/tx.js @@ -4,7 +4,6 @@ var Message = require('../message'); var inherits = require('util').inherits; var bitcore = require('bitcore-lib'); var $ = bitcore.util.preconditions; -var _ = bitcore.deps._; /** * @param {Transaction=} arg - An instance of Transaction @@ -17,7 +16,7 @@ function TransactionMessage(arg, options) { this.command = 'tx'; this.Transaction = options.Transaction; $.checkArgument( - _.isUndefined(arg) || arg instanceof this.Transaction, + arg === undefined || arg instanceof this.Transaction, 'An instance of Transaction or undefined is expected' ); this.transaction = arg; diff --git a/packages/bitcore-p2p/lib/messages/utils.js b/packages/bitcore-p2p/lib/messages/utils.js index 9c27cf6474b..1c1693267ed 100644 --- a/packages/bitcore-p2p/lib/messages/utils.js +++ b/packages/bitcore-p2p/lib/messages/utils.js @@ -3,15 +3,14 @@ var bitcore = require('bitcore-lib'); var BufferUtil = bitcore.util.buffer; var $ = bitcore.util.preconditions; -var _ = bitcore.deps._; var utils; module.exports = utils = { checkInventory: function(arg) { $.checkArgument( - _.isUndefined(arg) || + arg === undefined || (Array.isArray(arg) && arg.length === 0) || - (Array.isArray(arg) && !_.isUndefined(arg[0].type) && !_.isUndefined(arg[0].hash)), + (Array.isArray(arg) && arg[0] && arg[0].type && arg[0].hash), 'Argument is expected to be an array of inventory objects' ); }, @@ -33,7 +32,7 @@ module.exports = utils = { } }, writeAddr: function writeAddr(addr, bw) { - if (_.isUndefined(addr)) { + if (!addr) { var pad = new Buffer(Array(26)); bw.write(pad); return; @@ -81,12 +80,12 @@ module.exports = utils = { sanitizeStartStop: function sanitizeStartStop(obj) { /* jshint maxcomplexity: 10 */ /* jshint maxstatements: 20 */ - $.checkArgument(_.isUndefined(obj.starts) || _.isArray(obj.starts)); + $.checkArgument(!obj.starts || Array.isArray(obj.starts)); var starts = obj.starts; var stop = obj.stop; if (starts) { starts = starts.map(function(hash) { - if (_.isString(hash)) { + if (typeof hash === 'string') { return BufferUtil.reverse(new Buffer(hash, 'hex')); } else { return hash; @@ -103,7 +102,7 @@ module.exports = utils = { } stop = obj.stop; - if (_.isString(stop)) { + if (typeof stop === 'string') { stop = BufferUtil.reverse(new Buffer(stop, 'hex')); } if (!stop) { diff --git a/packages/bitcore-p2p/test/peer.js b/packages/bitcore-p2p/test/peer.js index eac75e5fead..f701691f4cb 100644 --- a/packages/bitcore-p2p/test/peer.js +++ b/packages/bitcore-p2p/test/peer.js @@ -59,7 +59,7 @@ describe('Peer', function() { }); var check = function(message) { received[message.command]++; - if (_.isEqual(received, expected)) { + if (JSON.stringify(received) === JSON.stringify(expected)) { callback(); } };