diff --git a/lib/address.js b/lib/address.js index 2dade14..84191bd 100644 --- a/lib/address.js +++ b/lib/address.js @@ -3,6 +3,7 @@ var base58check = require('./encoding/base58check'); var Networks = require('./networks'); var Hash = require('./crypto/hash'); +var jsUtil = require('./util/js'); /** * Instantiate an address from an address String or Buffer, a public key or script hash Buffer, @@ -305,6 +306,20 @@ Address.fromString = function(str, network, type) { return new Address(info.hashBuffer, info.network, info.type); }; +/** + * Instantiate an address from JSON + * + * @param {String} json - An JSON string or Object with keys: hash, network and type + * @returns {Address} A new valid instance of an Address + */ +Address.fromJSON = function fromJSON(json) { + if (jsUtil.isValidJson(json)) { + json = JSON.parse(json); + } + var hashBuffer = new Buffer(json.hash, 'hex'); + return new Address(hashBuffer, json.network, json.type); +}; + /** * Will return a validation error if exists * @@ -372,6 +387,17 @@ Address.prototype.toBuffer = function() { return buf; }; +/** + * @returns {Object} An object of the address + */ +Address.prototype.toJSON = function toJSON() { + return { + hash: this.hashBuffer.toString('hex'), + type: this.type, + network: this.network.toString() + }; +}; + /** * Will return a the string representation of the address * diff --git a/lib/block.js b/lib/block.js index a9c807e..142a1ca 100644 --- a/lib/block.js +++ b/lib/block.js @@ -121,6 +121,15 @@ Block.fromBuffer = function fromBuffer(buf) { return Block.fromBufferReader(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 @@ -158,6 +167,13 @@ 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 diff --git a/lib/blockheader.js b/lib/blockheader.js index 9531609..4b10931 100644 --- a/lib/blockheader.js +++ b/lib/blockheader.js @@ -103,6 +103,15 @@ BlockHeader.fromBuffer = function fromBuffer(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 @@ -150,6 +159,13 @@ 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 BufferWriter representation of the BlockHeader diff --git a/lib/networks.js b/lib/networks.js index 1452d7a..74806bf 100644 --- a/lib/networks.js +++ b/lib/networks.js @@ -2,6 +2,7 @@ var _ = require('lodash'); var BufferUtil = require('./util/buffer'); +var jsUtil = require('./util/js'); /** * A network is merely a map containing values that correspond to version diff --git a/lib/unit.js b/lib/unit.js index c1abffe..61329bc 100644 --- a/lib/unit.js +++ b/lib/unit.js @@ -1,5 +1,7 @@ 'use strict'; +var jsUtil = require('./util/js'); + /** * * Bitcore Unit @@ -27,6 +29,9 @@ function Unit(amount, code) { return new Unit(amount, code); } + this._amount = amount; + this._code = code; + this._value = this._from(amount, code); var self = this; @@ -51,9 +56,20 @@ Object.keys(UNITS).forEach(function(key) { Unit[key] = key; }); +/** + * Will return a Unit instance created from JSON string or object + * + * @param {String|Object} json - JSON with keys: amount and code + * @returns {Unit} A Unit instance + */ +Unit.fromJSON = function fromJSON(json){ + if (jsUtil.isValidJson(json)) { + json = JSON.parse(json); + } + return new Unit(json.amount, json.code); +}; /** - * * Will return a Unit instance created from an amount in BTC * * @param {Number} amount - The amount in BTC @@ -64,7 +80,6 @@ Unit.fromBTC = function(amount) { }; /** - * * Will return a Unit instance created from an amount in mBTC * * @param {Number} amount - The amount in mBTC @@ -75,7 +90,6 @@ Unit.fromMilis = function(amount) { }; /** - * * Will return a Unit instance created from an amount in bits * * @param {Number} amount - The amount in bits @@ -86,7 +100,6 @@ Unit.fromBits = function(amount) { }; /** - * * Will return a Unit instance created from an amount in satoshis * * @param {Number} amount - The amount in satoshis @@ -103,7 +116,6 @@ Unit.prototype._from = function(amount, code) { }; /** - * * Will return the value represented in the specified unit * * @param {string} code - The unit code @@ -117,7 +129,6 @@ Unit.prototype.to = function(code) { }; /** - * * Will return the value represented in BTC * * @returns {Number} The value converted to BTC @@ -137,7 +148,6 @@ Unit.prototype.toMilis = function(code) { }; /** - * * Will return the value represented in bits * * @returns {Number} The value converted to bits @@ -147,7 +157,6 @@ Unit.prototype.toBits = function(code) { }; /** - * * Will return the value represented in satoshis * * @returns {Number} The value converted to satoshis @@ -157,7 +166,6 @@ Unit.prototype.toSatoshis = function() { }; /** - * * Will return a the string representation of the value in satoshis * * @returns {String} the value in satoshis @@ -167,7 +175,18 @@ Unit.prototype.toString = function() { }; /** + * Will return a the JSON object representation of the unit * + * @returns {Object} An object with the keys: amount and code + */ +Unit.prototype.toJSON = function toJSON(){ + return { + amount: this._amount, + code: this._code + }; +}; + +/** * Will return a string formatted for the console * * @returns {String} the value in satoshis diff --git a/lib/uri.js b/lib/uri.js index 6356d44..c3cf847 100644 --- a/lib/uri.js +++ b/lib/uri.js @@ -5,9 +5,9 @@ var URL = require('url'); var Address = require('./address'); var Unit = require('./unit'); +var jsUtil = require('./util/js'); /** - * * Bitcore URI * * Instantiate an URI from a bitcoin URI String or an Object. An URI instance @@ -35,11 +35,13 @@ var URI = function(data, knownParams) { this.knownParams = knownParams || []; this.address = this.network = this.amount = this.message = null; - if (typeof(data) == 'string') { + if (typeof(data) === 'string') { var params = URI.parse(data); - if (params.amount) params.amount = this._parseAmount(params.amount); + if (params.amount) { + params.amount = this._parseAmount(params.amount); + } this._fromObject(params); - } else if (typeof(data) == 'object') { + } else if (typeof(data) === 'object') { this._fromObject(data); } else { throw new TypeError('Unrecognized data format.'); @@ -47,7 +49,32 @@ var URI = function(data, knownParams) { }; /** + * Instantiate a URI from a String * + * @param {String} str - JSON string or object of the URI + * @returns {URI} A new instance of a URI + */ +URI.fromString = function fromString(str) { + if (typeof(str) !== 'string') { + throw TypeError('Expected a string'); + } + return new URI(str); +}; + +/** + * Instantiate a URI from JSON + * + * @param {String|Object} json - JSON string or object of the URI + * @returns {URI} A new instance of a URI + */ +URI.fromJSON = function fromJSON(json) { + if (jsUtil.isValidJson(json)) { + json = JSON.parse(json); + } + return new URI(json); +}; + +/** * Check if an bitcoin URI string is valid * * @example @@ -69,7 +96,6 @@ URI.isValid = function(arg, knownParams) { }; /** - * * Convert a bitcoin URI string into a simple object. * * @param {string} uri - A bitcoin URI string @@ -90,8 +116,9 @@ URI.parse = function(uri) { return info.query; }; +URI.Members = ['address', 'amount', 'message', 'label', 'r']; + /** - * * Internal function to load the URI instance with an object. * * @param {Object} obj - Object with the information @@ -100,9 +127,10 @@ URI.parse = function(uri) { * @throws {Error} Unknown required argument */ URI.prototype._fromObject = function(obj) { - var members = ['address', 'amount', 'message', 'label', 'r']; - if (!Address.isValid(obj.address)) throw new TypeError('Invalid bitcoin address'); + if (!Address.isValid(obj.address)) { + throw new TypeError('Invalid bitcoin address'); + } this.address = new Address(obj.address); this.network = this.address.network; @@ -115,13 +143,12 @@ URI.prototype._fromObject = function(obj) { throw Error('Unknown required argument ' + key); } - var destination = members.indexOf(key) > -1 ? this : this.extras; + var destination = URI.Members.indexOf(key) > -1 ? this : this.extras; destination[key] = obj[key]; } }; /** - * * Internal function to transform a BTC string amount into satoshis * * @param {String} amount - Amount BTC string @@ -129,21 +156,49 @@ URI.prototype._fromObject = function(obj) { * @returns {Object} Amount represented in satoshis */ URI.prototype._parseAmount = function(amount) { - var amount = Number(amount); - if (isNaN(amount)) throw new TypeError('Invalid amount'); + amount = Number(amount); + if (isNaN(amount)) { + throw new TypeError('Invalid amount'); + } return Unit.fromBTC(amount).toSatoshis(); }; +URI.prototype.toJSON = function() { + var json = {}; + for(var i=0;i'; -} +}; module.exports = URI; diff --git a/test/address.js b/test/address.js index 919bdfa..704a3c3 100644 --- a/test/address.js +++ b/test/address.js @@ -355,6 +355,21 @@ describe('Address', function() { }); + describe('#json', function() { + + it('should output/input a JSON object', function() { + var address = Address.fromJSON(new Address(str).toJSON()); + address.toString().should.equal(str); + }); + + it('should output/input a JSON string', function() { + var json = JSON.stringify(new Address(str).toJSON()); + var address = Address.fromJSON(json); + address.toString().should.equal(str); + }); + + }); + describe('#toString', function() { it('should output a livenet pubkeyhash address', function() { diff --git a/test/block.js b/test/block.js index a72f541..fdd421e 100644 --- a/test/block.js +++ b/test/block.js @@ -118,6 +118,15 @@ describe('Block', function() { }); + describe('#fromString/#toString', function() { + + it('should output/input a block hex string', function() { + var b = Block.fromString(blockhex); + b.toString().should.equal(blockhex); + }); + + }); + describe('#fromBuffer', function() { it('should make a block from this known buffer', function() { diff --git a/test/blockheader.js b/test/blockheader.js index dc0127c..4fed3a1 100644 --- a/test/blockheader.js +++ b/test/blockheader.js @@ -122,6 +122,15 @@ describe('BlockHeader', function() { }); + describe('#fromString/#toString', function() { + + it('should output/input a block hex string', function() { + var b = BlockHeader.fromString(bhhex); + b.toString().should.equal(bhhex); + }); + + }); + describe('#fromBuffer', function() { it('should parse this known buffer', function() { diff --git a/test/unit.js b/test/unit.js index c91aeae..87fc82f 100644 --- a/test/unit.js +++ b/test/unit.js @@ -123,6 +123,12 @@ describe('Unit', function() { unit.toString().should.be.a('string'); }); + it('should input/output JSON', function() { + var json = {amount:1.3, code:'BTC'}; + var unit = Unit.fromJSON(json); + unit.toJSON().should.deep.equal(json); + }); + it('should have an inspect method', function() { var unit = new Unit(1.3, 'BTC'); should.exist(unit.inspect); diff --git a/test/uri.js b/test/uri.js index 21ff08f..e0b135e 100644 --- a/test/uri.js +++ b/test/uri.js @@ -65,6 +65,11 @@ describe('URI', function() { uri.address.should.be.instanceof(bitcore.Address); uri.network.should.equal(Networks.livenet); + uri = URI.fromString('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=123.22'); + uri.address.toString().should.equal('1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj'); + uri.amount.should.equal(12322000000); + expect(uri.otherParam).to.be.undefined; + uri = new URI('bitcoin:mkYY5NRvikVBY1EPtaq9fAFgquesdjqECw'); uri.address.should.be.instanceof(bitcore.Address); uri.network.should.equal(Networks.testnet); @@ -135,6 +140,21 @@ describe('URI', function() { uri.address.toString().should.equal('1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj'); }); + it('should input/output String', function() { + var str = 'bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?message=Donation%20for%20project%20xyz&label=myLabel&other=xD'; + URI.fromString(str).toString().should.equal(str); + }); + + it('should input/output JSON', function() { + var json = { + address: '1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj', + message: 'Donation for project xyz', + label: 'myLabel', + other: 'xD' + }; + URI.fromJSON(json).toJSON().should.deep.equal(json); + }); + it('should support numeric amounts', function() { var uri = new URI('bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=12.10001'); expect(uri.amount).to.be.equal(1210001000); @@ -166,7 +186,7 @@ describe('URI', function() { message: 'Hello World', something: 'else' }).toString().should.equal( - 'bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?something=else&amount=1.10001&message=Hello%20World' + 'bitcoin:1DP69gMMvSuYhbnxsi4EJEFufUAbDrEQfj?amount=1.10001&message=Hello%20World&something=else' ); });