UNPKG

datapay

Version:

post data over bitcoin sv

1,602 lines (1,431 loc) 2.79 MB
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.datapay = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ (function (Buffer){ const mingo = require("mingo") const _Buffer = require('buffer/') const bitcoin = require('bsv'); const explorer = require('bitcore-explorers'); const defaults = { rpc: "api.mattercloud.net", fee: 400, feeb: 1.4 } // The end goal of 'build' is to create a hex formated transaction object // therefore this function must end with _tx() for all cases // and return a hex formatted string of either a tranaction or a script var build = function(options, callback) { let script = null; let rpcaddr = (options.pay && options.pay.rpc) ? options.pay.rpc : defaults.rpc; if (options.tx) { // if tx exists, check to see if it's already been signed. // if it's a signed transaction // and the request is trying to override using 'data' or 'pay', // we should throw an error let tx = new bitcoin.Transaction(options.tx) // transaction is already signed if (tx.inputs.length > 0 && tx.inputs[0].script) { if (options.pay || options.data) { callback(new Error("the transaction is already signed and cannot be modified")) return; } } } else { // construct script only if transaction doesn't exist // if a 'transaction' attribute exists, the 'data' should be ignored to avoid confusion if (options.data) { script = _script(options) } } // Instantiate pay if (options.pay && options.pay.key) { // key exists => create a signed transaction let key = options.pay.key; const privateKey = new bitcoin.PrivateKey(key); const address = privateKey.toAddress(); const insight = new explorer.Insight(rpcaddr) insight.getUnspentUtxos(address, function (err, res) { if (err) { callback(err); return; } if (options.pay.filter && options.pay.filter.q && options.pay.filter.q.find) { let f = new mingo.Query(options.pay.filter.q.find) res = res.filter(function(item) { return f.test(item) }) } let tx = new bitcoin.Transaction(options.tx).from(res); if (script) { tx.addOutput(new bitcoin.Transaction.Output({ script: script, satoshis: 0 })); } if (options.pay.to && Array.isArray(options.pay.to)) { options.pay.to.forEach(function(receiver) { tx.to(receiver.address, receiver.value) }) } tx.fee(defaults.fee).change(address); let opt_pay = options.pay || {}; let myfee = opt_pay.fee || Math.ceil(tx._estimateSize()* (opt_pay.feeb || defaults.feeb)); tx.fee(myfee); //Check all the outputs for dust for(var i=0;i<tx.outputs.length;i++){ if(tx.outputs[i]._satoshis>0 && tx.outputs[i]._satoshis<546){ tx.outputs.splice(i,1); i--; } } let transaction = tx.sign(privateKey); callback(null, transaction); }) } else { // key doesn't exist => create an unsigned transaction let fee = (options.pay && options.pay.fee) ? options.pay.fee : defaults.fee; let tx = new bitcoin.Transaction(options.tx).fee(fee); if (script) { tx.addOutput(new bitcoin.Transaction.Output({ script: script, satoshis: 0 })); } callback(null, tx) } } var send = function(options, callback) { if (!callback) { callback = function() {}; } build(options, function(err, tx) { if (err) { callback(err); return; } let rpcaddr = (options.pay && options.pay.rpc) ? options.pay.rpc : defaults.rpc; const insight = new explorer.Insight(rpcaddr) insight.broadcast(tx.toString(), callback) }) } // compose script var _script = function(options) { var s = null; if (options.data) { if (Array.isArray(options.data)) { s = new bitcoin.Script(); if (!options.hasOwnProperty("safe")) { options.safe = true; } if (options.safe) { s.add(bitcoin.Opcode.OP_FALSE); } // Add op_return s.add(bitcoin.Opcode.OP_RETURN); options.data.forEach(function(item) { // add push data if (item.constructor.name === 'ArrayBuffer') { let buffer = _Buffer.Buffer.from(item) s.add(buffer) } else if (item.constructor.name === 'Buffer') { s.add(item) } else if (typeof item === 'string') { if (/^0x/i.test(item)) { // ex: 0x6d02 s.add(Buffer.from(item.slice(2), "hex")) } else { // ex: "hello" s.add(Buffer.from(item)) } } else if (typeof item === 'object' && item.hasOwnProperty('op')) { s.add({ opcodenum: item.op }) } }) } else if (typeof options.data === 'string') { // Exported transaction s = bitcoin.Script.fromHex(options.data); } } return s; } var connect = function(endpoint) { var rpc = endpoint ? endpoint : defaults.rpc; return new explorer.Insight(rpc); } module.exports = { build: build, send: send, bsv: bitcoin, connect: connect, } }).call(this,require("buffer").Buffer) },{"bitcore-explorers":3,"bsv":89,"buffer":218,"buffer/":82,"mingo":84}],2:[function(require,module,exports){ 'use strict' exports.byteLength = byteLength exports.toByteArray = toByteArray exports.fromByteArray = fromByteArray var lookup = [] var revLookup = [] var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' for (var i = 0, len = code.length; i < len; ++i) { lookup[i] = code[i] revLookup[code.charCodeAt(i)] = i } // Support decoding URL-safe base64 strings, as Node.js does. // See: https://en.wikipedia.org/wiki/Base64#URL_applications revLookup['-'.charCodeAt(0)] = 62 revLookup['_'.charCodeAt(0)] = 63 function getLens (b64) { var len = b64.length if (len % 4 > 0) { throw new Error('Invalid string. Length must be a multiple of 4') } // Trim off extra bytes after placeholder bytes are found // See: https://github.com/beatgammit/base64-js/issues/42 var validLen = b64.indexOf('=') if (validLen === -1) validLen = len var placeHoldersLen = validLen === len ? 0 : 4 - (validLen % 4) return [validLen, placeHoldersLen] } // base64 is 4/3 + up to two characters of the original data function byteLength (b64) { var lens = getLens(b64) var validLen = lens[0] var placeHoldersLen = lens[1] return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen } function _byteLength (b64, validLen, placeHoldersLen) { return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen } function toByteArray (b64) { var tmp var lens = getLens(b64) var validLen = lens[0] var placeHoldersLen = lens[1] var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) var curByte = 0 // if there are placeholders, only get up to the last complete 4 chars var len = placeHoldersLen > 0 ? validLen - 4 : validLen for (var i = 0; i < len; i += 4) { tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)] arr[curByte++] = (tmp >> 16) & 0xFF arr[curByte++] = (tmp >> 8) & 0xFF arr[curByte++] = tmp & 0xFF } if (placeHoldersLen === 2) { tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4) arr[curByte++] = tmp & 0xFF } if (placeHoldersLen === 1) { tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2) arr[curByte++] = (tmp >> 8) & 0xFF arr[curByte++] = tmp & 0xFF } return arr } function tripletToBase64 (num) { return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F] } function encodeChunk (uint8, start, end) { var tmp var output = [] for (var i = start; i < end; i += 3) { tmp = ((uint8[i] << 16) & 0xFF0000) + ((uint8[i + 1] << 8) & 0xFF00) + (uint8[i + 2] & 0xFF) output.push(tripletToBase64(tmp)) } return output.join('') } function fromByteArray (uint8) { var tmp var len = uint8.length var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes var parts = [] var maxChunkLength = 16383 // must be multiple of 3 // go through the array every three bytes, we'll deal with trailing stuff later for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { parts.push(encodeChunk( uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength) )) } // pad the end with zeros, but make sure to not forget the extra bytes if (extraBytes === 1) { tmp = uint8[len - 1] parts.push( lookup[tmp >> 2] + lookup[(tmp << 4) & 0x3F] + '==' ) } else if (extraBytes === 2) { tmp = (uint8[len - 2] << 8) + uint8[len - 1] parts.push( lookup[tmp >> 10] + lookup[(tmp >> 4) & 0x3F] + lookup[(tmp << 2) & 0x3F] + '=' ) } return parts.join('') } },{}],3:[function(require,module,exports){ module.exports = require('./lib'); },{"./lib":4}],4:[function(require,module,exports){ module.exports = { models: require('./models'), Insight: require('./insight') }; },{"./insight":5,"./models":7}],5:[function(require,module,exports){ 'use strict'; var request = require('request'); var bitcore = require('bitcore-lib'); var _ = bitcore.deps._; var $ = bitcore.util.preconditions; var Address = bitcore.Address; var JSUtil = bitcore.util.js; var Networks = bitcore.Networks; var Transaction = bitcore.Transaction; var UnspentOutput = Transaction.UnspentOutput; var AddressInfo = require('./models/addressinfo'); /** * Allows the retrieval of information regarding the state of the blockchain * (and broadcasting of transactions) from/to a trusted Insight server. * @param {string=} url the url of the Insight server * @param {Network=} network whether to use livenet or testnet * @constructor */ function Insight(url, network) { if (!url && !network) { return new Insight(Networks.defaultNetwork); } if (Networks.get(url)) { network = Networks.get(url); if (network === Networks.livenet) { url = 'https://insight.bitpay.com'; } else { url = 'https://test-insight.bitpay.com'; } } JSUtil.defineImmutable(this, { url: url, network: Networks.get(network) || Networks.defaultNetwork }); this.request = request; return this; } /** * @callback Insight.GetUnspentUtxosCallback * @param {Error} err * @param {Array.UnspentOutput} utxos */ /** * Retrieve a list of unspent outputs associated with an address or set of addresses * @param {Address|string|Array.Address|Array.string} addresses * @param {GetUnspentUtxosCallback} callback */ Insight.prototype.getUnspentUtxos = function(addresses, callback) { $.checkArgument(_.isFunction(callback)); if (!_.isArray(addresses)) { addresses = [addresses]; } addresses = _.map(addresses, function(address) { return new Address(address); }); this.requestPost('/api/addrs/utxo', { addrs: _.map(addresses, function(address) { return address.toString(); }).join(',') }, function(err, res, unspent) { if (err || res.statusCode !== 200) { return callback(err || res); } try { unspent = _.map(unspent, UnspentOutput); } catch (ex) { if (ex instanceof bitcore.errors.InvalidArgument) { return callback(ex); } } return callback(null, unspent); }); }; /** * @callback Insight.BroadcastCallback * @param {Error} err * @param {string} txid */ /** * Broadcast a transaction to the bitcoin network * @param {transaction|string} transaction * @param {BroadcastCallback} callback */ Insight.prototype.broadcast = function(transaction, callback) { $.checkArgument(JSUtil.isHexa(transaction) || transaction instanceof Transaction); $.checkArgument(_.isFunction(callback)); if (transaction instanceof Transaction) { transaction = transaction.serialize(); } this.requestPost('/api/tx/send', { rawtx: transaction }, function(err, res, body) { if (err || res.statusCode !== 200) { return callback(err || body); } return callback(null, body ? body.txid : null); }); }; /** * @callback Insight.AddressCallback * @param {Error} err * @param {AddressInfo} info */ /** * Retrieve information about an address * @param {Address|string} address * @param {AddressCallback} callback */ Insight.prototype.address = function(address, callback) { $.checkArgument(_.isFunction(callback)); address = new Address(address); this.requestGet('/api/addr/' + address.toString(), function(err, res, body) { if (err || res.statusCode !== 200) { return callback(err || body); } var info; try { info = AddressInfo.fromInsight(body); } catch (e) { if (e instanceof SyntaxError) { return callback(e); } throw e; } return callback(null, info); }); }; /** * Internal function to make a post request to the server * @param {string} path * @param {?} data * @param {function} callback * @private */ Insight.prototype.requestPost = function(path, data, callback) { $.checkArgument(_.isString(path)); $.checkArgument(_.isFunction(callback)); this.request({ method: 'POST', url: this.url + path, json: data }, callback); }; /** * Internal function to make a get request with no params to the server * @param {string} path * @param {function} callback * @private */ Insight.prototype.requestGet = function(path, callback) { $.checkArgument(_.isString(path)); $.checkArgument(_.isFunction(callback)); this.request({ method: 'GET', url: this.url + path }, callback); }; module.exports = Insight; },{"./models/addressinfo":6,"bitcore-lib":8,"request":81}],6:[function(require,module,exports){ 'use strict'; var bitcore = require('bitcore-lib'); var _ = bitcore.deps._; var $ = bitcore.util.preconditions; var Address = bitcore.Address; var JSUtil = bitcore.util.js; function AddressInfo(param) { if (!(this instanceof AddressInfo)) { return new AddressInfo(param); } if (param instanceof AddressInfo) { return param; } $.checkArgument(param.address instanceof Address); $.checkArgument(_.isNumber(param.balance)); $.checkArgument(_.isNumber(param.totalSent)); $.checkArgument(_.isNumber(param.totalReceived)); $.checkArgument(_.isNumber(param.unconfirmedBalance)); $.checkArgument(_.isArray(param.transactionIds)); $.checkArgument(_.all(_.map(param.transactionIds, JSUtil.isHexa))); JSUtil.defineImmutable(this, param); } AddressInfo.fromInsight = function(param) { if (_.isString(param)) { param = JSON.parse(param); } return new AddressInfo({ address: new Address(param.addrStr), balance: param.balanceSat, totalReceived: param.totalReceivedSat, totalSent: param.totalSentSat, unconfirmedBalance: param.unconfirmedBalanceSat, transactionIds: param.transactions }); }; module.exports = AddressInfo; },{"bitcore-lib":8}],7:[function(require,module,exports){ module.exports = { AddressInfo: require('./addressinfo') }; },{"./addressinfo":6}],8:[function(require,module,exports){ (function (global,Buffer){ 'use strict'; var bitcore = module.exports; // module information bitcore.version = 'v' + require('./package.json').version; bitcore.versionGuard = function(version) { if (version !== undefined) { var message = 'More than one instance of bitcore-lib found. ' + 'Please make sure to require bitcore-lib and check that submodules do' + ' not also include their own bitcore-lib dependency.'; throw new Error(message); } }; bitcore.versionGuard(global._bitcore); global._bitcore = bitcore.version; // crypto bitcore.crypto = {}; bitcore.crypto.BN = require('./lib/crypto/bn'); bitcore.crypto.ECDSA = require('./lib/crypto/ecdsa'); bitcore.crypto.Hash = require('./lib/crypto/hash'); bitcore.crypto.Random = require('./lib/crypto/random'); bitcore.crypto.Point = require('./lib/crypto/point'); bitcore.crypto.Signature = require('./lib/crypto/signature'); // encoding bitcore.encoding = {}; bitcore.encoding.Base58 = require('./lib/encoding/base58'); bitcore.encoding.Base58Check = require('./lib/encoding/base58check'); bitcore.encoding.BufferReader = require('./lib/encoding/bufferreader'); bitcore.encoding.BufferWriter = require('./lib/encoding/bufferwriter'); bitcore.encoding.Varint = require('./lib/encoding/varint'); // utilities bitcore.util = {}; bitcore.util.buffer = require('./lib/util/buffer'); bitcore.util.js = require('./lib/util/js'); bitcore.util.preconditions = require('./lib/util/preconditions'); // errors thrown by the library bitcore.errors = require('./lib/errors'); // main bitcoin library bitcore.Address = require('./lib/address'); bitcore.Block = require('./lib/block'); bitcore.MerkleBlock = require('./lib/block/merkleblock'); bitcore.BlockHeader = require('./lib/block/blockheader'); bitcore.HDPrivateKey = require('./lib/hdprivatekey.js'); bitcore.HDPublicKey = require('./lib/hdpublickey.js'); bitcore.Networks = require('./lib/networks'); bitcore.Opcode = require('./lib/opcode'); bitcore.PrivateKey = require('./lib/privatekey'); bitcore.PublicKey = require('./lib/publickey'); bitcore.Script = require('./lib/script'); bitcore.Transaction = require('./lib/transaction'); bitcore.URI = require('./lib/uri'); bitcore.Unit = require('./lib/unit'); // dependencies, subject to change bitcore.deps = {}; 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._HDKeyCache = require('./lib/hdkeycache'); bitcore.Transaction.sighash = require('./lib/transaction/sighash'); }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer) },{"./lib/address":9,"./lib/block":12,"./lib/block/blockheader":11,"./lib/block/merkleblock":13,"./lib/crypto/bn":14,"./lib/crypto/ecdsa":15,"./lib/crypto/hash":16,"./lib/crypto/point":17,"./lib/crypto/random":18,"./lib/crypto/signature":19,"./lib/encoding/base58":20,"./lib/encoding/base58check":21,"./lib/encoding/bufferreader":22,"./lib/encoding/bufferwriter":23,"./lib/encoding/varint":24,"./lib/errors":25,"./lib/hdkeycache":27,"./lib/hdprivatekey.js":28,"./lib/hdpublickey.js":29,"./lib/networks":30,"./lib/opcode":31,"./lib/privatekey":32,"./lib/publickey":33,"./lib/script":34,"./lib/transaction":37,"./lib/transaction/sighash":45,"./lib/unit":49,"./lib/uri":50,"./lib/util/buffer":51,"./lib/util/js":52,"./lib/util/preconditions":53,"./package.json":80,"bn.js":54,"bs58":55,"buffer":218,"elliptic":57,"lodash":79}],9:[function(require,module,exports){ (function (Buffer){ 'use strict'; var _ = require('lodash'); var $ = require('./util/preconditions'); var errors = require('./errors'); var Base58Check = require('./encoding/base58check'); var Networks = require('./networks'); var Hash = require('./crypto/hash'); var JSUtil = require('./util/js'); var PublicKey = require('./publickey'); /** * Instantiate an address from an address String or Buffer, a public key or script hash Buffer, * or an instance of {@link PublicKey} or {@link Script}. * * This is an immutable class, and if the first parameter provided to this constructor is an * `Address` instance, the same argument will be returned. * * An address has two key properties: `network` and `type`. The type is either * `Address.PayToPublicKeyHash` (value is the `'pubkeyhash'` string) * or `Address.PayToScriptHash` (the string `'scripthash'`). The network is an instance of {@link Network}. * You can quickly check whether an address is of a given kind by using the methods * `isPayToPublicKeyHash` and `isPayToScriptHash` * * @example * ```javascript * // validate that an input field is valid * var error = Address.getValidationError(input, 'testnet'); * if (!error) { * var address = Address(input, 'testnet'); * } else { * // invalid network or checksum (typo?) * var message = error.messsage; * } * * // get an address from a public key * var address = Address(publicKey, 'testnet').toString(); * ``` * * @param {*} data - The encoded data in various formats * @param {Network|String|number=} network - The network: 'livenet' or 'testnet' * @param {string=} type - The type of address: 'script' or 'pubkey' * @returns {Address} A new valid and frozen instance of an Address * @constructor */ function Address(data, network, type) { /* jshint maxcomplexity: 12 */ /* jshint maxstatements: 20 */ if (!(this instanceof Address)) { return new Address(data, network, type); } if (_.isArray(data) && _.isNumber(network)) { return Address.createMultisig(data, network, type); } if (data instanceof Address) { // Immutable instance return data; } $.checkArgument(data, 'First argument is required, please include address data.', 'guide/address.html'); if (network && !Networks.get(network)) { throw new TypeError('Second argument must be "livenet" or "testnet".'); } if (type && (type !== Address.PayToPublicKeyHash && type !== Address.PayToScriptHash)) { throw new TypeError('Third argument must be "pubkeyhash" or "scripthash".'); } var info = this._classifyArguments(data, network, type); // set defaults if not set info.network = info.network || Networks.get(network) || Networks.defaultNetwork; info.type = info.type || type || Address.PayToPublicKeyHash; JSUtil.defineImmutable(this, { hashBuffer: info.hashBuffer, network: info.network, type: info.type }); return this; } /** * Internal function used to split different kinds of arguments of the constructor * @param {*} data - The encoded data in various formats * @param {Network|String|number=} network - The network: 'livenet' or 'testnet' * @param {string=} type - The type of address: 'script' or 'pubkey' * @returns {Object} An "info" object with "type", "network", and "hashBuffer" */ Address.prototype._classifyArguments = function(data, network, type) { /* jshint maxcomplexity: 10 */ // transform and validate input data if ((data instanceof Buffer || data instanceof Uint8Array) && data.length === 20) { return Address._transformHash(data); } else if ((data instanceof Buffer || data instanceof Uint8Array) && data.length === 21) { return Address._transformBuffer(data, network, type); } else if (data instanceof PublicKey) { return Address._transformPublicKey(data); } else if (data instanceof Script) { return Address._transformScript(data, network); } else if (typeof(data) === 'string') { return Address._transformString(data, network, type); } else if (_.isObject(data)) { return Address._transformObject(data); } else { throw new TypeError('First argument is an unrecognized data format.'); } }; /** @static */ Address.PayToPublicKeyHash = 'pubkeyhash'; /** @static */ Address.PayToScriptHash = 'scripthash'; /** * @param {Buffer} hash - An instance of a hash Buffer * @returns {Object} An object with keys: hashBuffer * @private */ Address._transformHash = function(hash) { var info = {}; if (!(hash instanceof Buffer) && !(hash instanceof Uint8Array)) { throw new TypeError('Address supplied is not a buffer.'); } if (hash.length !== 20) { throw new TypeError('Address hashbuffers must be exactly 20 bytes.'); } info.hashBuffer = hash; return info; }; /** * Deserializes an address serialized through `Address#toObject()` * @param {Object} data * @param {string} data.hash - the hash that this address encodes * @param {string} data.type - either 'pubkeyhash' or 'scripthash' * @param {Network=} data.network - the name of the network associated * @return {Address} */ Address._transformObject = function(data) { $.checkArgument(data.hash || data.hashBuffer, 'Must provide a `hash` or `hashBuffer` property'); $.checkArgument(data.type, 'Must provide a `type` property'); return { hashBuffer: data.hash ? new Buffer(data.hash, 'hex') : data.hashBuffer, network: Networks.get(data.network) || Networks.defaultNetwork, type: data.type }; }; /** * Internal function to discover the network and type based on the first data byte * * @param {Buffer} buffer - An instance of a hex encoded address Buffer * @returns {Object} An object with keys: network and type * @private */ Address._classifyFromVersion = function(buffer) { var version = {}; var pubkeyhashNetwork = Networks.get(buffer[0], 'pubkeyhash'); var scripthashNetwork = Networks.get(buffer[0], 'scripthash'); if (pubkeyhashNetwork) { version.network = pubkeyhashNetwork; version.type = Address.PayToPublicKeyHash; } else if (scripthashNetwork) { version.network = scripthashNetwork; version.type = Address.PayToScriptHash; } return version; }; /** * Internal function to transform a bitcoin address buffer * * @param {Buffer} buffer - An instance of a hex encoded address Buffer * @param {string=} network - The network: 'livenet' or 'testnet' * @param {string=} type - The type: 'pubkeyhash' or 'scripthash' * @returns {Object} An object with keys: hashBuffer, network and type * @private */ Address._transformBuffer = function(buffer, network, type) { /* jshint maxcomplexity: 9 */ var info = {}; if (!(buffer instanceof Buffer) && !(buffer instanceof Uint8Array)) { throw new TypeError('Address supplied is not a buffer.'); } if (buffer.length !== 1 + 20) { throw new TypeError('Address buffers must be exactly 21 bytes.'); } network = Networks.get(network); var bufferVersion = Address._classifyFromVersion(buffer); if (!bufferVersion.network || (network && network !== bufferVersion.network)) { throw new TypeError('Address has mismatched network type.'); } if (!bufferVersion.type || (type && type !== bufferVersion.type)) { throw new TypeError('Address has mismatched type.'); } info.hashBuffer = buffer.slice(1); info.network = bufferVersion.network; info.type = bufferVersion.type; return info; }; /** * Internal function to transform a {@link PublicKey} * * @param {PublicKey} pubkey - An instance of PublicKey * @returns {Object} An object with keys: hashBuffer, type * @private */ Address._transformPublicKey = function(pubkey) { var info = {}; if (!(pubkey instanceof PublicKey)) { throw new TypeError('Address must be an instance of PublicKey.'); } info.hashBuffer = Hash.sha256ripemd160(pubkey.toBuffer()); info.type = Address.PayToPublicKeyHash; return info; }; /** * Internal function to transform a {@link Script} into a `info` object. * * @param {Script} script - An instance of Script * @returns {Object} An object with keys: hashBuffer, type * @private */ Address._transformScript = function(script, network) { $.checkArgument(script instanceof Script, 'script must be a Script instance'); var info = script.getAddressInfo(network); if (!info) { throw new errors.Script.CantDeriveAddress(script); } return info; }; /** * Creates a P2SH address from a set of public keys and a threshold. * * The addresses will be sorted lexicographically, as that is the trend in bitcoin. * To create an address from unsorted public keys, use the {@link Script#buildMultisigOut} * interface. * * @param {Array} publicKeys - a set of public keys to create an address * @param {number} threshold - the number of signatures needed to release the funds * @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' * @return {Address} */ Address.createMultisig = function(publicKeys, threshold, network) { network = network || publicKeys[0].network || Networks.defaultNetwork; return Address.payingTo(Script.buildMultisigOut(publicKeys, threshold), network); }; /** * Internal function to transform a bitcoin address string * * @param {string} data * @param {String|Network=} network - either a Network instance, 'livenet', or 'testnet' * @param {string=} type - The type: 'pubkeyhash' or 'scripthash' * @returns {Object} An object with keys: hashBuffer, network and type * @private */ Address._transformString = function(data, network, type) { if (typeof(data) !== 'string') { throw new TypeError('data parameter supplied is not a string.'); } data = data.trim(); var addressBuffer = Base58Check.decode(data); var info = Address._transformBuffer(addressBuffer, network, type); return info; }; /** * Instantiate an address from a PublicKey instance * * @param {PublicKey} data * @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' * @returns {Address} A new valid and frozen instance of an Address */ Address.fromPublicKey = function(data, network) { var info = Address._transformPublicKey(data); network = network || Networks.defaultNetwork; return new Address(info.hashBuffer, network, info.type); }; /** * Instantiate an address from a ripemd160 public key hash * * @param {Buffer} hash - An instance of buffer of the hash * @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' * @returns {Address} A new valid and frozen instance of an Address */ Address.fromPublicKeyHash = function(hash, network) { var info = Address._transformHash(hash); return new Address(info.hashBuffer, network, Address.PayToPublicKeyHash); }; /** * Instantiate an address from a ripemd160 script hash * * @param {Buffer} hash - An instance of buffer of the hash * @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' * @returns {Address} A new valid and frozen instance of an Address */ Address.fromScriptHash = function(hash, network) { $.checkArgument(hash, 'hash parameter is required'); var info = Address._transformHash(hash); return new Address(info.hashBuffer, network, Address.PayToScriptHash); }; /** * Builds a p2sh address paying to script. This will hash the script and * use that to create the address. * If you want to extract an address associated with a script instead, * see {{Address#fromScript}} * * @param {Script} script - An instance of Script * @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' * @returns {Address} A new valid and frozen instance of an Address */ Address.payingTo = function(script, network) { $.checkArgument(script, 'script is required'); $.checkArgument(script instanceof Script, 'script must be instance of Script'); return Address.fromScriptHash(Hash.sha256ripemd160(script.toBuffer()), network); }; /** * Extract address from a Script. The script must be of one * of the following types: p2pkh input, p2pkh output, p2sh input * or p2sh output. * This will analyze the script and extract address information from it. * If you want to transform any script to a p2sh Address paying * to that script's hash instead, use {{Address#payingTo}} * * @param {Script} script - An instance of Script * @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' * @returns {Address} A new valid and frozen instance of an Address */ Address.fromScript = function(script, network) { $.checkArgument(script instanceof Script, 'script must be a Script instance'); var info = Address._transformScript(script, network); return new Address(info.hashBuffer, network, info.type); }; /** * Instantiate an address from a buffer of the address * * @param {Buffer} buffer - An instance of buffer of the address * @param {String|Network=} network - either a Network instance, 'livenet', or 'testnet' * @param {string=} type - The type of address: 'script' or 'pubkey' * @returns {Address} A new valid and frozen instance of an Address */ Address.fromBuffer = function(buffer, network, type) { var info = Address._transformBuffer(buffer, network, type); return new Address(info.hashBuffer, info.network, info.type); }; /** * Instantiate an address from an address string * * @param {string} str - An string of the bitcoin address * @param {String|Network=} network - either a Network instance, 'livenet', or 'testnet' * @param {string=} type - The type of address: 'script' or 'pubkey' * @returns {Address} A new valid and frozen instance of an Address */ Address.fromString = function(str, network, type) { var info = Address._transformString(str, network, type); return new Address(info.hashBuffer, info.network, info.type); }; /** * Instantiate an address from an Object * * @param {string} json - An JSON string or Object with keys: hash, network and type * @returns {Address} A new valid instance of an Address */ Address.fromObject = function fromObject(obj) { $.checkState( JSUtil.isHexa(obj.hash), 'Unexpected hash property, "' + obj.hash + '", expected to be hex.' ); var hashBuffer = new Buffer(obj.hash, 'hex'); return new Address(hashBuffer, obj.network, obj.type); }; /** * Will return a validation error if exists * * @example * ```javascript * // a network mismatch error * var error = Address.getValidationError('15vkcKf7gB23wLAnZLmbVuMiiVDc1Nm4a2', 'testnet'); * ``` * * @param {string} data - The encoded data * @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' * @param {string} type - The type of address: 'script' or 'pubkey' * @returns {null|Error} The corresponding error message */ Address.getValidationError = function(data, network, type) { var error; try { /* jshint nonew: false */ new Address(data, network, type); } catch (e) { error = e; } return error; }; /** * Will return a boolean if an address is valid * * @example * ```javascript * assert(Address.isValid('15vkcKf7gB23wLAnZLmbVuMiiVDc1Nm4a2', 'livenet')); * ``` * * @param {string} data - The encoded data * @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' * @param {string} type - The type of address: 'script' or 'pubkey' * @returns {boolean} The corresponding error message */ Address.isValid = function(data, network, type) { return !Address.getValidationError(data, network, type); }; /** * Returns true if an address is of pay to public key hash type * @return boolean */ Address.prototype.isPayToPublicKeyHash = function() { return this.type === Address.PayToPublicKeyHash; }; /** * Returns true if an address is of pay to script hash type * @return boolean */ Address.prototype.isPayToScriptHash = function() { return this.type === Address.PayToScriptHash; }; /** * Will return a buffer representation of the address * * @returns {Buffer} Bitcoin address buffer */ Address.prototype.toBuffer = function() { var version = new Buffer([this.network[this.type]]); var buf = Buffer.concat([version, this.hashBuffer]); return buf; }; /** * @returns {Object} A plain object with the address information */ Address.prototype.toObject = Address.prototype.toJSON = function toObject() { return { hash: this.hashBuffer.toString('hex'), type: this.type, network: this.network.toString() }; }; /** * Will return a the string representation of the address * * @returns {string} Bitcoin address */ Address.prototype.toString = function() { return Base58Check.encode(this.toBuffer()); }; /** * Will return a string formatted for the console * * @returns {string} Bitcoin address */ Address.prototype.inspect = function() { return '<Address: ' + this.toString() + ', type: ' + this.type + ', network: ' + this.network + '>'; }; module.exports = Address; var Script = require('./script'); }).call(this,require("buffer").Buffer) },{"./crypto/hash":16,"./encoding/base58check":21,"./errors":25,"./networks":30,"./publickey":33,"./script":34,"./util/js":52,"./util/preconditions":53,"buffer":218,"lodash":79}],10:[function(require,module,exports){ (function (Buffer){ 'use strict'; var _ = require('lodash'); var BlockHeader = require('./blockheader'); var BN = require('../crypto/bn'); var BufferUtil = require('../util/buffer'); var BufferReader = require('../encoding/bufferreader'); var BufferWriter = require('../encoding/bufferwriter'); var Hash = require('../crypto/hash'); var Transaction = require('../transaction'); var $ = require('../util/preconditions'); /** * Instantiate a Block from a Buffer, JSON object, or Object with * the properties of the Block * * @param {*} - A Buffer, JSON string, or Object * @returns {Block} * @constructor */ function Block(arg) { if (!(this instanceof Block)) { return new Block(arg); } _.extend(this, Block._from(arg)); return this; } // https://github.com/bitcoin/bitcoin/blob/b5fa132329f0377d787a4a21c1686609c2bfaece/src/primitives/block.h#L14 Block.MAX_BLOCK_SIZE = 1000000; /** * @param {*} - A Buffer, JSON string or Object * @returns {Object} - An object representing block data * @throws {TypeError} - If the argument was not recognized * @private */ Block._from = function _from(arg) { var info = {}; if (BufferUtil.isBuffer(arg)) { info = Block._fromBufferReader(BufferReader(arg)); } else if (_.isObject(arg)) { info = Block._fromObject(arg); } else { throw new TypeError('Unrecognized argument for Block'); } return info; }; /** * @param {Object} - A plain JavaScript object * @returns {Object} - An object representing block data * @private */ Block._fromObject = function _fromObject(data) { var transactions = []; data.transactions.forEach(function(tx) { if (tx instanceof Transaction) { transactions.push(tx); } else { transactions.push(Transaction().fromObject(tx)); } }); var info = { header: BlockHeader.fromObject(data.header), transactions: transactions }; return info; }; /** * @param {Object} - A plain JavaScript object * @returns {Block} - An instance of block */ Block.fromObject = function fromObject(obj) { var info = Block._fromObject(obj); return new Block(info); }; /** * @param {BufferReader} - Block data * @returns {Object} - An object representing the block data * @private */ Block._fromBufferReader = function _fromBufferReader(br) { var info = {}; $.checkState(!br.finished(), 'No block data received'); info.header = BlockHeader.fromBufferReader(br); var transactions = br.readVarintNum(); info.transactions = []; for (var i = 0; i < transactions; i++) { info.transactions.push(Transaction().fromBufferReader(br)); } return info; }; /** * @param {BufferReader} - A buffer reader of the block * @returns {Block} - An instance of block */ Block.fromBufferReader = function fromBufferReader(br) { $.checkArgument(br, 'br is required'); var info = Block._fromBufferReader(br); return new Block(info); }; /** * @param {Buffer} - A buffer of the block * @returns {Block} - An instance of block */ Block.fromBuffer = function fromBuffer(buf) { return Block.fromBufferReader(new BufferReader(buf)); }; /** * @param {string} - str - A hex encoded string of the block * @returns {Block} - A hex encoded string of the block */ Block.fromString = function fromString(str) { var buf = new Buffer(str, 'hex'); return Block.fromBuffer(buf); }; /** * @param {Binary} - Raw block binary data or buffer * @returns {Block} - An instance of block */ Block.fromRawBlock = function fromRawBlock(data) { if (!BufferUtil.isBuffer(data)) { data = new Buffer(data, 'binary'); } var br = BufferReader(data); br.pos = Block.Values.START_OF_BLOCK; var info = Block._fromBufferReader(br); return new Block(info); }; /** * @returns {Object} - A plain object with the block properties */ Block.prototype.toObject = Block.prototype.toJSON = function toObject() { var transactions = []; this.transactions.forEach(function(tx) { transactions.push(tx.toObject()); }); return { header: this.header.toObject(), transactions: transactions }; }; /** * @returns {Buffer} - A buffer of the block */ Block.prototype.toBuffer = function toBuffer() { return this.toBufferWriter().concat(); }; /** * @returns {string} - A hex encoded string of the block */ Block.prototype.toString = function toString() { return this.toBuffer().toString('hex'); }; /** * @param {BufferWriter} - An existing instance of BufferWriter * @returns {BufferWriter} - An instance of BufferWriter representation of the Block */ Block.prototype.toBufferWriter = function toBufferWriter(bw) { if (!bw) { bw = new BufferWriter(); } bw.write(this.header.toBuffer()); bw.writeVarintNum(this.transactions.length); for (var i = 0; i < this.transactions.length; i++) { this.transactions[i].toBufferWriter(bw); } return bw; }; /** * Will iterate through each transaction and return an array of hashes * @returns {Array} - An array with transaction hashes */ Block.prototype.getTransactionHashes = function getTransactionHashes() { var hashes = []; if (this.transactions.length === 0) { return [Block.Values.NULL_HASH]; } for (var t = 0; t < this.transactions.length; t++) { hashes.push(this.transactions[t]._getHash()); } return hashes; }; /** * Will build a merkle tree of all the transactions, ultimately arriving at * a single point, the merkle root. * @link https://en.bitcoin.it/wiki/Protocol_specification#Merkle_Trees * @returns {Array} - An array with each level of the tree after the other. */ Block.prototype.getMerkleTree = function getMerkleTree() { var tree = this.getTransactionHashes(); var j = 0; for (var size = this.transactions.length; size > 1; size = Math.floor((size + 1) / 2)) { for (var i = 0; i < size; i += 2) { var i2 = Math.min(i + 1, size - 1); var buf = Buffer.concat([tree[j + i], tree[j + i2]]); tree.push(Hash.sha256sha256(buf)); } j += size; } return tree; }; /** * Calculates the merkleRoot from the transactions. * @returns {Buffer} - A buffer of the merkle root hash */ Block.prototype.getMerkleRoot = function getMerkleRoot() { var tree = this.getMerkleTree(); return tree[tree.length - 1]; }; /** * Verifies that the transactions in the block match the header merkle root * @returns {Boolean} - If the merkle roots match */ Block.prototype.validMerkleRoot = function validMerkleRoot() { var h = new BN(this.header.merkleRoot.toString('hex'), 'hex'); var c = new BN(this.getMerkleRoot().toString('hex'), 'hex'); if (h.cmp(c) !== 0) { return false; } return true; }; /** * @returns {Buffer} - The little endian hash buffer of the header */ Block.prototype._getHash = function() { return this.header._getHash(); }; var idProperty = { configurable: false, enumerable: true, /** * @returns {string} - The big endian hash buffer of the header */ get: function() { if (!this._id) { this._id = this.header.id; } return this._id; }, set: _.noop }; Object.defineProperty(Block.prototype, 'id', idProperty); Object.defineProperty(Block.prototype, 'hash', idProperty); /** * @returns {string} - A string formatted for the console */ Block.prototype.inspect = function inspect() { return '<Block ' + this.id + '>'; }; Block.Values = { START_OF_BLOCK: 8, // Start of block in raw block data NULL_HASH: new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex') }; module.exports = Block; }).call(this,require("buffer").Buffer) },{"../crypto/bn":14,"../crypto/hash":16,"../encoding/bufferreader":22,"../encoding/bufferwriter":23,"../transaction":37,"../util/buffer":51,"../util/preconditions":53,"./blockheader":11,"buffer":218,"lodash":79}],11:[function(require,module,exports){ (function (Buffer){ 'use strict'; var _ = require('lodash'); var BN = require('../crypto/bn'); 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 $ = require('../util/preconditions'); var GENESIS_BITS = 0x1d00ffff; /** * Instantiate a BlockHeader from a Buffer, JSON object, or Object with * the properties of the BlockHeader * * @param {*} - A Buffer, JSON string, or Object * @returns {BlockHeader} - An instance of block header * @constructor */ var BlockHeader = function BlockHeader(arg) { if (!(this instanceof BlockHeader)) { return new BlockHeader(arg); } var info = BlockHeader._from(arg); this.version = info.version; this.prevHash = info.prevHash; this.merkleRoot = info.merkleRoot; this.time = info.time; this.timestamp = info.time; this.bits = info.bits; this.nonce = info.nonce; if (info.hash) { $.checkState( this.hash === info.hash, 'Argument object hash property does not match block hash.' ); } return this; }; /** * @param {*} - A Buffer, JSON string or Object * @returns {Object} - An object representing block header data * @throws {TypeError} - If the argument was not recognized * @private */ BlockHeader._from = function _from(arg) { var info = {}; if (BufferUtil.isBuffer(arg)) { info = BlockHeader._fromBufferReader(BufferReader(arg)); } else if (_.isObject(arg)) { info = BlockHeader._fromObject(arg); } else { throw new TypeError('Unrecognized argument for BlockHeader'); } return info; }; /** * @param {Object} - A JSON string * @returns {Object} - An object representing block header data * @private */ BlockHeader._fromObject = function _fromObject(data) { $.checkArgument(data, 'data is required'); var prevHash = data.prevHash; var merkleRoot = data.merkleRoot; if (_.isString(data.prevHash)) { prevHash = BufferUtil.reverse(new Buffer(data.prevHash, 'hex')); } if (_.isString(data.merkleRoot)) { merkleRoot = BufferUtil.reverse(new Buffer(data.merkleRoot, 'hex')); } var info = { hash: data.hash, version: data.version, prevHash: prevHash, merkleRoot: merkleRoot, time: data.time, timestamp: data.time, bits: data.bits, nonce: data.nonce }; return info; }; /** * @param {Object} - A plain JavaScript object * @returns {BlockHeader} - An instance of block header */ BlockHeader.fromObject = function fromObject(obj) { var info = BlockHeader._fromObject(obj); return new BlockHeader(info); }; /** * @param {Binary} - Raw block binary data or buffer * @returns {BlockHeader} - An instance of block header */ BlockHeader.fromRawBlock = function fromRawBlock(data) { if (!BufferUtil.isBuffer(data)) { data = new Buffer(data, 'binary'); } var br = BufferReader(data); br.pos = BlockHeader.Constants.START_OF_HEADER; var info = BlockHeader._fromBufferReader(br); return new BlockHeader(info); }; /** * @param {Buffer} - A buffer of the block header * @returns {BlockHeader} - An instance of block header */ BlockHeader.fromBuffer = function fromBuffer(buf) { var info = BlockHeader._fromBufferReader(BufferReader(buf)); return new BlockHeader(info); }; /** * @param {string} - A hex encoded buffer of the block header * @returns {BlockHeader} - An instance of block header */ BlockHeader.fromString = function fromString(str) { var buf = new Buffer(str, 'hex'); return BlockHeader.fromBuffer(buf); }; /** * @param {BufferReader} - A BufferReader of the block header * @returns {Object} - An object representing block header data * @private */ BlockHeader._fromBufferReader = function _fromBufferReader(br) { var info = {}; info.version = br.readUInt32LE(); info.prevHash = br.read(32); info.merkleRoot = br.read(32); info.time = br.readUInt32LE(); info.bits = br.readUInt32LE(); info.nonce = br.readUInt32LE(); return info; }; /** * @param {BufferReader} - A BufferReader of the block header * @returns {BlockHeader} - An instance of block header */ BlockHeader.fromBufferReader = function fromBufferReader(br) { var info = BlockHeader._fromBufferReader(br); return new BlockHeader(info); }; /** * @returns {Object} - A plain object of the BlockHeader */ BlockHeader.prototype.toObject = BlockHeader.prototype.toJSON = function toObject() { return { hash: this.hash, version: this.version, prevHash: BufferUtil.reverse(this.prevHash).toString('hex'), merkleRoot: BufferUtil.reverse(this.merkleRoot).toString('hex'), time: this.time, bits: this.bits, nonce: this.nonce }; }; /** * @returns {Buffer} - A Buffer of the BlockHeader */ BlockHeader.prototype.toBuffer = function toBuffer() { return this.toBufferWriter().concat(); }; /** * @returns {string} - A hex encoded string of the BlockHeader */ BlockHeader.prototype.toString = function toString() { return this.toBuffer().toString('hex'); }; /** * @param {BufferWriter} - An existing instance BufferWriter * @returns {BufferWriter} - An instance of BufferW