Changes behavior of `toJSON` to work as expected with `JSON.stringify`

- see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#toJSON%28%29_behavior
- Updates CONTRIBUTING with changes to Stardard Methods
- Aliases toJSON for toObject
- Removes all `fromJSON` methods, and many cases replaces with `fromObject`
- Constructors expect an object parsed via `JSON.parse` for JSON input
This commit is contained in:
Braydon Fuller 2015-08-12 17:37:28 -04:00
parent 79db9cc372
commit a50fccef4d
32 changed files with 166 additions and 424 deletions

View File

@ -85,16 +85,28 @@ var bufferUtil = require('./util/buffer');
#### G7 - Standard Methods
When possible, bitcore objects should have standard methods on an instance prototype:
* `toObject` - A plain JavaScript object that can be JSON stringified
* `toJSON` - A JSON stringified object of the instance
* `toObject/toJSON` - A plain JavaScript object that `JSON.stringify` can call
* `toString` - A string representation of the instance
* `toBuffer` - A hex Buffer
These should have a matching static method that can be used for instantiation:
* `fromJSON` - Should handle both JSON from `toJSON` and plain JavaScript object from `toObject`
* `fromObject` - Should be able to instatiate with the output from `toObject/toJSON`
* `fromString` - Should be able to instantiate with output from `toString`
* `fromBuffer` - Should likewise be able to instantiate from output from `toBuffer`
`JSON.stringify` and `JSON.parse` are expected to be handled outside of the scope of Bitcore methods. For example, calling `JSON.stringify` on an Bitcore object will behave as expected and call `transaction.toJSON()` and then stringify it:
```javascript
var transactionString = JSON.stringify(transaction);
```
Likewise to instantiate a transaction from that string:
```javascript
var data = JSON.parse(transactionString);
var tx = new Transaction(data);
```
### Errors
#### E1 - Use bitcore.Errors

View File

@ -381,21 +381,18 @@ Address.fromString = function(str, network, type) {
};
/**
* Instantiate an address from JSON
* 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.fromJSON = function fromJSON(json) {
if (JSUtil.isValidJSON(json)) {
json = JSON.parse(json);
}
Address.fromObject = function fromObject(obj) {
$.checkState(
JSUtil.isHexa(json.hash),
'Unexpected hash property, "' + json.hash + '", expected to be hex.'
JSUtil.isHexa(obj.hash),
'Unexpected hash property, "' + obj.hash + '", expected to be hex.'
);
var hashBuffer = new Buffer(json.hash, 'hex');
return new Address(hashBuffer, json.network, json.type);
var hashBuffer = new Buffer(obj.hash, 'hex');
return new Address(hashBuffer, obj.network, obj.type);
};
/**
@ -470,7 +467,7 @@ Address.prototype.toBuffer = function() {
/**
* @returns {Object} A plain object with the address information
*/
Address.prototype.toObject = function toObject() {
Address.prototype.toObject = Address.prototype.toJSON = function toObject() {
return {
hash: this.hashBuffer.toString('hex'),
type: this.type,
@ -478,13 +475,6 @@ Address.prototype.toObject = function toObject() {
};
};
/**
* @returns {string} A JSON representation of a plain object with the address information
*/
Address.prototype.toJSON = function toJSON() {
return JSON.stringify(this.toObject());
};
/**
* Will return a the string representation of the address
*

View File

@ -7,7 +7,6 @@ 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 $ = require('../util/preconditions');
@ -40,8 +39,6 @@ Block._from = function _from(arg) {
var info = {};
if (BufferUtil.isBuffer(arg)) {
info = Block._fromBufferReader(BufferReader(arg));
} else if (JSUtil.isValidJSON(arg)) {
info = Block._fromJSON(arg);
} else if (_.isObject(arg)) {
info = Block._fromObject(arg);
} else {
@ -50,17 +47,6 @@ Block._from = function _from(arg) {
return info;
};
/**
* @param {String} - A JSON string
* @returns {Object} - An object representing block data
* @private
*/
Block._fromJSON = function _fromJSON(data) {
$.checkArgument(JSUtil.isValidJSON(data), 'data must be valid JSON');
data = JSON.parse(data);
return Block._fromObject(data);
};
/**
* @param {Object} - A plain JavaScript object
* @returns {Object} - An object representing block data
@ -72,7 +58,7 @@ Block._fromObject = function _fromObject(data) {
if (tx instanceof Transaction) {
transactions.push(tx);
} else {
transactions.push(Transaction().fromJSON(tx));
transactions.push(Transaction().fromObject(tx));
}
});
var info = {
@ -82,15 +68,6 @@ Block._fromObject = function _fromObject(data) {
return info;
};
/**
* @param {String} - A JSON string
* @returns {Block} - An instance of block
*/
Block.fromJSON = function fromJSON(json) {
var info = Block._fromJSON(json);
return new Block(info);
};
/**
* @param {Object} - A plain JavaScript object
* @returns {Block} - An instance of block
@ -161,7 +138,7 @@ Block.fromRawBlock = function fromRawBlock(data) {
/**
* @returns {Object} - A plain object with the block properties
*/
Block.prototype.toObject = function toObject() {
Block.prototype.toObject = Block.prototype.toJSON = function toObject() {
var transactions = [];
this.transactions.forEach(function(tx) {
transactions.push(tx.toObject());
@ -172,13 +149,6 @@ Block.prototype.toObject = function toObject() {
};
};
/**
* @returns {string} - A JSON string
*/
Block.prototype.toJSON = function toJSON() {
return JSON.stringify(this.toObject());
};
/**
* @returns {Buffer} - A buffer of the block
*/

View File

@ -50,8 +50,6 @@ BlockHeader._from = function _from(arg) {
var info = {};
if (BufferUtil.isBuffer(arg)) {
info = BlockHeader._fromBufferReader(BufferReader(arg));
} else if (JSUtil.isValidJSON(arg)) {
info = BlockHeader._fromJSON(arg);
} else if (_.isObject(arg)) {
info = BlockHeader._fromObject(arg);
} else {
@ -60,17 +58,6 @@ BlockHeader._from = function _from(arg) {
return info;
};
/**
* @param {String} - A JSON string
* @returns {Object} - An object representing block header data
* @private
*/
BlockHeader._fromJSON = function _fromJSON(data) {
$.checkArgument(JSUtil.isValidJSON(data), 'data must be a valid JSON string');
data = JSON.parse(data);
return BlockHeader._fromObject(data);
};
/**
* @param {Object} - A JSON string
* @returns {Object} - An object representing block header data
@ -99,15 +86,6 @@ BlockHeader._fromObject = function _fromObject(data) {
return info;
};
/**
* @param {String} - A JSON string or object
* @returns {BlockHeader} - An instance of block header
*/
BlockHeader.fromJSON = function fromJSON(json) {
var info = BlockHeader._fromJSON(json);
return new BlockHeader(info);
};
/**
* @param {Object} - A plain JavaScript object
* @returns {BlockHeader} - An instance of block header
@ -177,7 +155,7 @@ BlockHeader.fromBufferReader = function fromBufferReader(br) {
/**
* @returns {Object} - A plain object of the BlockHeader
*/
BlockHeader.prototype.toObject = function toObject() {
BlockHeader.prototype.toObject = BlockHeader.prototype.toJSON = function toObject() {
return {
hash: this.hash,
version: this.version,
@ -189,13 +167,6 @@ BlockHeader.prototype.toObject = function toObject() {
};
};
/**
* @returns {string} - A JSON string
*/
BlockHeader.prototype.toJSON = function toJSON() {
return JSON.stringify(this.toObject());
};
/**
* @returns {Buffer} - A Buffer of the BlockHeader
*/

View File

@ -28,14 +28,12 @@ function MerkleBlock(arg) {
var info = {};
if (BufferUtil.isBuffer(arg)) {
info = MerkleBlock._fromBufferReader(BufferReader(arg));
} else if (JSUtil.isValidJSON(arg)) {
info = MerkleBlock._fromJSON(arg);
} else if (_.isObject(arg)) {
var header;
if(arg.header instanceof BlockHeader) {
header = arg.header;
} else {
header = BlockHeader.fromJSON(JSON.stringify(arg.header));
header = BlockHeader.fromObject(arg.header);
}
info = {
/**
@ -84,14 +82,6 @@ MerkleBlock.fromBufferReader = function fromBufferReader(br) {
return new MerkleBlock(MerkleBlock._fromBufferReader(br));
};
/**
* @param {String|Object} - A JSON String or Object
* @returns {MerkleBlock} - A MerkleBlock object
*/
MerkleBlock.fromJSON = function fromJSON(buf) {
return new MerkleBlock(MerkleBlock._fromJSON(buf));
};
/**
* @returns {Buffer} - A buffer of the block
*/
@ -123,7 +113,7 @@ MerkleBlock.prototype.toBufferWriter = function toBufferWriter(bw) {
/**
* @returns {Object} - A plain object with the MerkleBlock properties
*/
MerkleBlock.prototype.toObject = function toObject() {
MerkleBlock.prototype.toObject = MerkleBlock.prototype.toJSON = function toObject() {
return {
header: this.header.toObject(),
numTransactions: this.numTransactions,
@ -132,13 +122,6 @@ MerkleBlock.prototype.toObject = function toObject() {
};
};
/**
* @returns {String} - A JSON string of a MerkleBlock
*/
MerkleBlock.prototype.toJSON = function toJSON() {
return JSON.stringify(this.toObject());
};
/**
* Verify that the MerkleBlock is valid
* @returns {Boolean} - True/False whether this MerkleBlock is Valid
@ -279,21 +262,11 @@ MerkleBlock._fromBufferReader = function _fromBufferReader(br) {
};
/**
* @param {String|Object} - A JSON or String Object
* @returns {Object} - An Object representing merkleblock data
* @private
* @param {Object} - A plain JavaScript object
* @returns {Block} - An instance of block
*/
MerkleBlock._fromJSON = function _fromJSON(data) {
if (JSUtil.isValidJSON(data)) {
data = JSON.parse(data);
}
var info = {
header: BlockHeader.fromObject(data.header),
numTransactions: data.numTransactions,
hashes: data.hashes,
flags: data.flags,
};
return info;
MerkleBlock.fromObject = function fromObject(obj) {
return new MerkleBlock(obj);
};
module.exports = MerkleBlock;

View File

@ -278,11 +278,6 @@ HDPrivateKey._validateNetwork = function(data, networkArg) {
return null;
};
HDPrivateKey.fromJSON = function(arg) {
$.checkArgument(JSUtil.isValidJSON(arg), 'No valid JSON string was provided');
return new HDPrivateKey(arg);
};
HDPrivateKey.fromString = function(arg) {
$.checkArgument(_.isString(arg), 'No valid string was provided');
return new HDPrivateKey(arg);
@ -510,7 +505,7 @@ HDPrivateKey.prototype.inspect = function() {
* </ul>
* @return {Object}
*/
HDPrivateKey.prototype.toObject = function toObject() {
HDPrivateKey.prototype.toObject = HDPrivateKey.prototype.toJSON = function toObject() {
return {
network: Network.get(BufferUtil.integerFromBuffer(this._buffers.version), 'xprivkey').name,
depth: BufferUtil.integerFromSingleByteBuffer(this._buffers.depth),
@ -524,15 +519,6 @@ HDPrivateKey.prototype.toObject = function toObject() {
};
};
/**
* Returns a JSON representation of the HDPrivateKey
*
* @return {string}
*/
HDPrivateKey.prototype.toJSON = function toJSON() {
return JSON.stringify(this.toObject());
};
/**
* Build a HDPrivateKey from a buffer
*

View File

@ -43,8 +43,6 @@ function HDPublicKey(arg) {
var error = HDPublicKey.getSerializedError(arg);
if (!error) {
return this._buildFromSerialized(arg);
} else if (JSUtil.isValidJSON(arg)) {
return this._buildFromJSON(arg);
} else if (BufferUtil.isBuffer(arg) && !HDPublicKey.getSerializedError(arg.toString())) {
return this._buildFromSerialized(arg.toString());
} else {
@ -232,10 +230,6 @@ HDPublicKey._validateNetwork = function (data, networkArg) {
return null;
};
HDPublicKey.prototype._buildFromJSON = function (arg) {
return this._buildFromObject(JSON.parse(arg));
};
HDPublicKey.prototype._buildFromPrivate = function (arg) {
var args = _.clone(arg._buffers);
var point = Point.getG().mul(BN.fromBuffer(args.privateKey));
@ -359,8 +353,8 @@ HDPublicKey._validateBufferArguments = function (arg) {
}
};
HDPublicKey.fromJSON = function(arg) {
$.checkArgument(JSUtil.isValidJSON(arg), 'No valid JSON string was provided');
HDPublicKey.fromString = function(arg) {
$.checkArgument(_.isString(arg), 'No valid string was provided');
return new HDPublicKey(arg);
};
@ -369,11 +363,6 @@ HDPublicKey.fromObject = function(arg) {
return new HDPublicKey(arg);
};
HDPublicKey.fromString = function(arg) {
$.checkArgument(_.isString(arg), 'No valid string was provided');
return new HDPublicKey(arg);
};
/**
* Returns the base58 checked representation of the public key
* @return {string} a string starting with "xpub..." in livenet
@ -407,7 +396,7 @@ HDPublicKey.prototype.inspect = function() {
* <li> checksum: the base58 checksum of xpubkey
* </ul>
*/
HDPublicKey.prototype.toObject = function toObject() {
HDPublicKey.prototype.toObject = HDPublicKey.prototype.toJSON = function toObject() {
return {
network: Network.get(BufferUtil.integerFromBuffer(this._buffers.version)).name,
depth: BufferUtil.integerFromSingleByteBuffer(this._buffers.depth),
@ -421,14 +410,6 @@ HDPublicKey.prototype.toObject = function toObject() {
};
};
/**
* Serializes this object into a JSON string
* @return {string}
*/
HDPublicKey.prototype.toJSON = function toJSON() {
return JSON.stringify(this.toObject());
};
/**
* Create a HDPublicKey from a buffer argument
*

View File

@ -9,6 +9,7 @@ var Networks = require('./networks');
var Point = require('./crypto/point');
var PublicKey = require('./publickey');
var Random = require('./crypto/random');
var $ = require('./util/preconditions');
/**
* Instantiate a PrivateKey from a BN, Buffer and WIF.
@ -33,7 +34,7 @@ var Random = require('./crypto/random');
* @returns {PrivateKey} A new valid instance of an PrivateKey
* @constructor
*/
var PrivateKey = function PrivateKey(data, network) {
function PrivateKey(data, network) {
/* jshint maxstatements: 20 */
/* jshint maxcomplexity: 8 */
@ -95,8 +96,8 @@ PrivateKey.prototype._classifyArguments = function(data, network) {
info.bn = data;
} else if (data instanceof Buffer || data instanceof Uint8Array) {
info = PrivateKey._transformBuffer(data, network);
} else if (PrivateKey._isJSON(data)){
info = PrivateKey._transformJSON(data);
} else if (data.bn && data.network){
info = PrivateKey._transformObject(data);
} else if (!network && Networks.get(data)) {
info.bn = PrivateKey._getRandomBN();
info.network = Networks.get(data);
@ -129,17 +130,6 @@ PrivateKey._getRandomBN = function(){
return bn;
};
/**
* Internal function to detect if a param is a JSON string or plain object
*
* @param {*} param - value to test
* @returns {boolean}
* @private
*/
PrivateKey._isJSON = function(json) {
return JSUtil.isValidJSON(json) || (json.bn && json.network);
};
/**
* Internal function to transform a WIF Buffer into a private key
*
@ -206,20 +196,6 @@ PrivateKey._transformWIF = function(str, network) {
return PrivateKey._transformBuffer(Base58Check.decode(str), network);
};
/**
* Instantiate a PrivateKey from a JSON string
*
* @param {string} json - The JSON encoded private key string
* @returns {PrivateKey} A new valid instance of PrivateKey
*/
PrivateKey.fromJSON = function(json) {
if (!PrivateKey._isJSON(json)) {
throw new TypeError('Must be a valid JSON string or plain object');
}
return new PrivateKey(json);
};
/**
* Instantiate a PrivateKey from a Buffer with the DER or WIF representation
*
@ -239,10 +215,7 @@ PrivateKey.fromBuffer = function(arg, network) {
* @returns {Object} An object with keys: bn, network and compressed
* @private
*/
PrivateKey._transformJSON = function(json) {
if (JSUtil.isValidJSON(json)) {
json = JSON.parse(json);
}
PrivateKey._transformObject = function(json) {
var bn = new BN(json.bn, 'hex');
var network = Networks.get(json.network);
return {
@ -259,9 +232,20 @@ PrivateKey._transformJSON = 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.');
return new PrivateKey(str);
};
/**
* Instantiate a PrivateKey from a plain JavaScript object
*
* @param {Object} obj - The output from privateKey.toObject()
*/
PrivateKey.fromObject = function(obj) {
$.checkArgument(_.isObject(obj), 'First argument is expected to be an object.');
return new PrivateKey(obj);
};
/**
* Instantiate a PrivateKey from random bytes
*
@ -382,7 +366,7 @@ PrivateKey.prototype.toAddress = function(network) {
/**
* @returns {Object} A plain object representation
*/
PrivateKey.prototype.toObject = function toObject() {
PrivateKey.prototype.toObject = PrivateKey.prototype.toJSON = function toObject() {
return {
bn: this.bn.toString('hex'),
compressed: this.compressed,
@ -390,10 +374,6 @@ PrivateKey.prototype.toObject = function toObject() {
};
};
PrivateKey.prototype.toJSON = function toJSON() {
return JSON.stringify(this.toObject());
};
/**
* Will return a string formatted for the console
*

View File

@ -33,7 +33,7 @@ var $ = require('./util/preconditions');
* @returns {PublicKey} A new valid instance of an PublicKey
* @constructor
*/
var PublicKey = function PublicKey(data, extra) {
function PublicKey(data, extra) {
if (!(this instanceof PublicKey)) {
return new PublicKey(data, extra);
@ -75,8 +75,8 @@ PublicKey.prototype._classifyArgs = function(data, extra) {
// detect type of data
if (data instanceof Point) {
info.point = data;
} else if (PublicKey._isJSON(data)) {
info = PublicKey._transformJSON(data);
} else if (data.x && data.y) {
info = PublicKey._transformObject(data);
} else if (typeof(data) === 'string') {
info = PublicKey._transformDER(new Buffer(data, 'hex'));
} else if (PublicKey._isBuffer(data)) {
@ -115,17 +115,6 @@ PublicKey._isBuffer = function(param) {
return (param instanceof Buffer) || (param instanceof Uint8Array);
};
/**
* Internal function to detect if a param is a JSON string or plain object
*
* @param {*} json - value to test
* @returns {boolean}
* @private
*/
PublicKey._isJSON = function(json) {
return !!(JSUtil.isValidJSON(json) || (json.x && json.y));
};
/**
* Internal function to transform a private key into a public key point
*
@ -204,17 +193,6 @@ PublicKey._transformX = function(odd, x) {
return info;
};
/**
* Instantiate a PublicKey from JSON
*
* @param {string} json - A JSON string
* @returns {PublicKey} A new valid instance of PublicKey
*/
PublicKey.fromJSON = function(json) {
$.checkArgument(PublicKey._isJSON(json), 'Must be a valid JSON string or plain object');
return new PublicKey(json);
};
/**
* Internal function to transform a JSON into a public key point
*
@ -222,10 +200,7 @@ PublicKey.fromJSON = function(json) {
* @returns {Object} An object with keys: point and compressed
* @private
*/
PublicKey._transformJSON = function(json) {
if (JSUtil.isValidJSON(json)) {
json = JSON.parse(json);
}
PublicKey._transformObject = function(json) {
var x = new BN(json.x, 'hex');
var y = new BN(json.y, 'hex');
var point = new Point(x, y);
@ -336,7 +311,7 @@ PublicKey.isValid = function(data) {
/**
* @returns {Object} A plain object of the PublicKey
*/
PublicKey.prototype.toObject = function toObject() {
PublicKey.prototype.toObject = PublicKey.prototype.toJSON = function toObject() {
return {
x: this.point.getX().toString('hex', 2),
y: this.point.getY().toString('hex', 2),
@ -344,13 +319,6 @@ PublicKey.prototype.toObject = function toObject() {
};
};
/**
* @returns {string} A JSON string of the PublicKey
*/
PublicKey.prototype.toJSON = function toJSON() {
return JSON.stringify(this.toObject());
};
/**
* Will output the PublicKey to a DER Buffer
*

View File

@ -40,6 +40,12 @@ Object.defineProperty(Input.prototype, 'script', {
}
});
Input.fromObject = function(obj) {
$.checkArgument(_.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)) {
@ -60,7 +66,7 @@ Input.prototype._fromObject = function(params) {
return this;
};
Input.prototype.toObject = function toObject() {
Input.prototype.toObject = Input.prototype.toJSON = function toObject() {
var obj = {
prevTxId: this.prevTxId.toString('hex'),
outputIndex: this.outputIndex,
@ -77,21 +83,6 @@ Input.prototype.toObject = function toObject() {
return obj;
};
Input.fromObject = function(obj) {
$.checkArgument(_.isObject(obj));
var input = new Input();
return input._fromObject(obj);
};
Input.prototype.toJSON = function toJSON() {
return JSON.stringify(this.toObject());
};
Input.fromJSON = function(json) {
$.checkArgument(JSUtil.isValidJSON(json), 'Invalid JSON provided to Input.fromJSON');
return Input.fromObject(JSON.parse(json));
};
Input.fromBufferReader = function(br) {
var input = new Input();
input.prevTxId = br.readReverse(32);
@ -153,7 +144,7 @@ Input.prototype.setScript = function(script) {
Input.prototype.getSignatures = function() {
throw new errors.AbstractMethodInvoked(
'Trying to sign unsupported output type (only P2PKH and P2SH multisig inputs are supported)' +
' for input: ' + this.toJSON()
' for input: ' + JSON.stringify(this)
);
};

View File

@ -29,8 +29,6 @@ function Output(args) {
}
this.setScript(script);
}
} else if (JSUtil.isValidJSON(args)) {
return Output.fromJSON(args);
} else {
throw new TypeError('Unrecognized argument for Output');
}
@ -91,7 +89,7 @@ Output.prototype.invalidSatoshis = function() {
return false;
};
Output.prototype.toObject = function toObject() {
Output.prototype.toObject = Output.prototype.toJSON = function toObject() {
var obj = {
satoshis: this.satoshis
};
@ -99,17 +97,8 @@ Output.prototype.toObject = function toObject() {
return obj;
};
Output.prototype.toJSON = function toJSON() {
return JSON.stringify(this.toObject());
};
Output.fromJSON = function(data) {
$.checkArgument(JSUtil.isValidJSON(data), 'data must be valid JSON');
var json = JSON.parse(data);
return new Output({
satoshis: Number(json.satoshis),
script: new Script(json.script)
});
Output.fromObject = function(data) {
return new Output(data);
};
Output.prototype.setScriptFromBuffer = function(buffer) {

View File

@ -24,11 +24,6 @@ function TransactionSignature(arg) {
if (arg instanceof TransactionSignature) {
return arg;
}
if (_.isString(arg)) {
if (JSUtil.isValidJSON(arg)) {
return TransactionSignature.fromJSON(arg);
}
}
if (_.isObject(arg)) {
return this._fromObject(arg);
}
@ -70,7 +65,7 @@ TransactionSignature.prototype._checkObjectArgs = function(arg) {
* Serializes a transaction to a plain JS object
* @return {Object}
*/
TransactionSignature.prototype.toObject = function() {
TransactionSignature.prototype.toObject = TransactionSignature.prototype.toJSON = function toObject() {
return {
publicKey: this.publicKey.toString(),
prevTxId: this.prevTxId.toString('hex'),
@ -81,23 +76,6 @@ TransactionSignature.prototype.toObject = function() {
};
};
/**
* Serializes a transaction to a JSON string
* @return {string}
*/
TransactionSignature.prototype.toJSON = function() {
return JSON.stringify(this.toObject());
};
/**
* Builds a TransactionSignature from a JSON string
* @param {string} json
* @return {TransactionSignature}
*/
TransactionSignature.fromJSON = function(json) {
return new TransactionSignature(JSON.parse(json));
};
/**
* Builds a TransactionSignature from an object
* @param {Object} object

View File

@ -44,8 +44,6 @@ function Transaction(serialized) {
return Transaction.shallowCopy(serialized);
} else if (JSUtil.isHexa(serialized)) {
this.fromString(serialized);
} else if (JSUtil.isValidJSON(serialized)) {
this.fromJSON(serialized);
} else if (BufferUtil.isBuffer(serialized)) {
this.fromBuffer(serialized);
} else if (_.isObject(serialized)) {
@ -315,14 +313,7 @@ Transaction.prototype.fromBufferReader = function(reader) {
return this;
};
Transaction.prototype.fromJSON = function(json) {
if (JSUtil.isValidJSON(json)) {
json = JSON.parse(json);
}
return this.fromObject(json);
};
Transaction.prototype.toObject = function toObject() {
Transaction.prototype.toObject = Transaction.prototype.toJSON = function toObject() {
var inputs = [];
this.inputs.forEach(function(input) {
inputs.push(input.toObject());
@ -350,8 +341,9 @@ Transaction.prototype.toObject = function toObject() {
return obj;
};
Transaction.prototype.fromObject = function(arg) {
Transaction.prototype.fromObject = function fromObject(arg) {
/* jshint maxstatements: 20 */
$.checkArgument(_.isObject(arg) || arg instanceof Transaction);
var self = this;
var transaction;
if (arg instanceof Transaction) {
@ -462,10 +454,6 @@ Transaction.prototype.getLockTime = function() {
return new Date(1000 * this.nLockTime);
};
Transaction.prototype.toJSON = function toJSON() {
return JSON.stringify(this.toObject());
};
Transaction.prototype.fromString = function(string) {
this.fromBuffer(new buffer.Buffer(string, 'hex'));
};

View File

@ -75,30 +75,19 @@ UnspentOutput.prototype.toString = function() {
};
/**
* Deserialize an UnspentOutput from an object or JSON string
* Deserialize an UnspentOutput from an object
* @param {object|string} data
* @return UnspentOutput
*/
UnspentOutput.fromJSON = UnspentOutput.fromObject = function(data) {
if (JSUtil.isValidJSON(data)) {
data = JSON.parse(data);
}
UnspentOutput.fromObject = function(data) {
return new UnspentOutput(data);
};
/**
* Retrieve a string representation of this object
* @return {string}
*/
UnspentOutput.prototype.toJSON = function() {
return JSON.stringify(this.toObject());
};
/**
* Returns a plain object (no prototype or methods) with the associated infor for this output
* @return {object}
*/
UnspentOutput.prototype.toObject = function() {
UnspentOutput.prototype.toObject = UnspentOutput.prototype.toJSON = function toObject() {
return {
address: this.address ? this.address.toString() : undefined,
txid: this.txId,

View File

@ -3,7 +3,7 @@
var _ = require('lodash');
var errors = require('./errors');
var JSUtil = require('./util/js');
var $ = require('./util/preconditions');
var UNITS = {
'BTC' : [1e8, 8],
@ -74,11 +74,9 @@ Object.keys(UNITS).forEach(function(key) {
* @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);
Unit.fromObject = function fromObject(data){
$.checkArgument(_.isObject(data), 'Argument is expected to be an object');
return new Unit(data.amount, data.code);
};
/**
@ -221,17 +219,13 @@ Unit.prototype.toString = function() {
*
* @returns {Object} An object with the keys: amount and code
*/
Unit.prototype.toObject = function toObject() {
Unit.prototype.toObject = Unit.prototype.toJSON = function toObject() {
return {
amount: this.BTC,
code: Unit.BTC
};
};
Unit.prototype.toJSON = function toJSON() {
return JSON.stringify(this.toObject());
};
/**
* Returns a string formatted for the console
*

View File

@ -5,7 +5,6 @@ var URL = require('url');
var Address = require('./address');
var Unit = require('./unit');
var JSUtil = require('./util/js');
/**
* Bitcore URI
@ -69,15 +68,12 @@ URI.fromString = function fromString(str) {
};
/**
* Instantiate a URI from JSON
* Instantiate a URI from an Object
*
* @param {String|Object} json - JSON string or object of the URI
* @param {Object} data - 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);
}
URI.fromObject = function fromObject(json) {
return new URI(json);
};
@ -175,7 +171,7 @@ URI.prototype._parseAmount = function(amount) {
return Unit.fromBTC(amount).toSatoshis();
};
URI.prototype.toObject = function toObject() {
URI.prototype.toObject = URI.prototype.toJSON = function toObject() {
var json = {};
for (var i = 0; i < URI.Members.length; i++) {
var m = URI.Members[i];
@ -187,10 +183,6 @@ URI.prototype.toObject = function toObject() {
return json;
};
URI.prototype.toJSON = function toJSON() {
return JSON.stringify(this.toObject());
};
/**
* Will return a the string representation of the URI
*

View File

@ -445,18 +445,18 @@ describe('Address', function() {
});
describe('#json', function() {
describe('#object', function() {
it('roundtrip to-from-to', function() {
var json = new Address(str).toJSON();
var address = Address.fromJSON(json);
var obj = new Address(str).toObject();
var address = Address.fromObject(obj);
address.toString().should.equal(str);
});
it('checks that the string parameter is valid JSON', function() {
it('will fail with invalid state', function() {
expect(function() {
return Address.fromJSON('¹');
}).to.throw();
return Address.fromObject('¹');
}).to.throw(bitcore.errors.InvalidState);
});
});

View File

@ -25,7 +25,7 @@ describe('Block', function() {
var bh = BlockHeader.fromBuffer(new Buffer(data.blockheaderhex, 'hex'));
var txs = [];
JSON.parse(dataJson).transactions.forEach(function(tx) {
txs.push(new Transaction().fromJSON(tx));
txs.push(new Transaction().fromObject(tx));
});
var json = dataJson;
@ -86,14 +86,13 @@ describe('Block', function() {
describe('#fromJSON', function() {
it('should set these known values', function() {
var block = Block.fromJSON(json);
var block = Block.fromObject(JSON.parse(json));
should.exist(block.header);
should.exist(block.transactions);
});
it('should set these known values', function() {
var block = Block(json);
var block = new Block(JSON.parse(json));
should.exist(block.header);
should.exist(block.transactions);
});
@ -103,8 +102,8 @@ describe('Block', function() {
describe('#toJSON', function() {
it('should recover these known values', function() {
var block = Block.fromJSON(json);
var b = JSON.parse(block.toJSON());
var block = Block.fromObject(JSON.parse(json));
var b = block.toJSON();
should.exist(b.header);
should.exist(b.transactions);
});

View File

@ -79,17 +79,17 @@ describe('BlockHeader', function() {
});
describe('#fromJSON', function() {
describe('#fromObject', function() {
it('should set all the variables', function() {
var bh = BlockHeader.fromJSON(JSON.stringify({
var bh = BlockHeader.fromObject({
version: version,
prevHash: prevblockidbuf.toString('hex'),
merkleRoot: merklerootbuf.toString('hex'),
time: time,
bits: bits,
nonce: nonce
}));
});
should.exist(bh.version);
should.exist(bh.prevHash);
should.exist(bh.merkleRoot);
@ -103,7 +103,7 @@ describe('BlockHeader', function() {
describe('#toJSON', function() {
it('should set all the variables', function() {
var json = JSON.parse(bh.toJSON());
var json = bh.toJSON();
should.exist(json.version);
should.exist(json.prevHash);
should.exist(json.merkleRoot);
@ -127,7 +127,7 @@ describe('BlockHeader', function() {
nonce: nonce
});
var json = new BlockHeader(jsonString);
var json = new BlockHeader(JSON.parse(jsonString));
should.exist(json.version);
should.exist(json.prevHash);
should.exist(json.merkleRoot);

View File

@ -29,8 +29,8 @@ describe('MerkleBlock', function() {
});
it('should make a new merkleblock from JSON', function() {
var b = MerkleBlock(blockJSON);
b.toJSON().should.equal(blockJSON);
var b = MerkleBlock(JSON.parse(blockJSON));
JSON.stringify(b).should.equal(blockJSON);
});
it('should not make an empty block', function() {
@ -40,10 +40,10 @@ describe('MerkleBlock', function() {
});
});
describe('#fromJSON', function() {
describe('#fromObject', function() {
it('should set these known values', function() {
var block = MerkleBlock.fromJSON(blockJSON);
var block = MerkleBlock.fromObject(JSON.parse(blockJSON));
should.exist(block.header);
should.exist(block.numTransactions);
should.exist(block.hashes);
@ -51,7 +51,7 @@ describe('MerkleBlock', function() {
});
it('should set these known values', function() {
var block = MerkleBlock(blockJSON);
var block = MerkleBlock(JSON.parse(blockJSON));
should.exist(block.header);
should.exist(block.numTransactions);
should.exist(block.hashes);
@ -60,7 +60,7 @@ describe('MerkleBlock', function() {
it('accepts an object as argument', function() {
var block = MerkleBlock(blockbuf);
MerkleBlock.fromJSON(block.toObject()).should.exist();
MerkleBlock.fromObject(block.toObject()).should.exist();
});
});
@ -68,8 +68,8 @@ describe('MerkleBlock', function() {
describe('#toJSON', function() {
it('should recover these known values', function() {
var block = MerkleBlock.fromJSON(blockJSON);
var b = JSON.parse(block.toJSON());
var block = new MerkleBlock(JSON.parse(blockJSON));
var b = JSON.parse(JSON.stringify(block));
should.exist(block.header);
should.exist(block.numTransactions);
should.exist(block.hashes);
@ -128,14 +128,14 @@ describe('MerkleBlock', function() {
describe('#validMerkleTree', function() {
it('should validate good merkleblocks', function() {
data.JSON.forEach(function(json) {
var b = MerkleBlock(JSON.stringify(json));
data.JSON.forEach(function(data) {
var b = MerkleBlock(data);
b.validMerkleTree().should.equal(true);
});
});
it('should not validate merkleblocks with too many hashes', function() {
var b = MerkleBlock(JSON.stringify(data.JSON[0]));
var b = MerkleBlock(data.JSON[0]);
// Add too many hashes
var i = 0;
while(i <= b.numTransactions) {
@ -145,7 +145,7 @@ describe('MerkleBlock', function() {
});
it('should not validate merkleblocks with too few bit flags', function() {
var b = MerkleBlock(blockJSON);
var b = MerkleBlock(JSON.parse(blockJSON));
b.flags.pop();
b.validMerkleTree().should.equal(false);
});
@ -155,18 +155,18 @@ describe('MerkleBlock', function() {
describe('#hasTransaction', function() {
it('should find transactions via hash string', function() {
var json = data.JSON[0];
var txId = new Buffer(json.hashes[1],'hex').toString('hex');
var b = MerkleBlock(JSON.stringify(json));
var jsonData = data.JSON[0];
var txId = new Buffer(jsonData.hashes[1],'hex').toString('hex');
var b = MerkleBlock(jsonData);
b.hasTransaction(txId).should.equal(true);
b.hasTransaction(txId + 'abcd').should.equal(false);
});
it('should find transactions via Transaction object', function() {
var json = data.JSON[0];
var jsonData = data.JSON[0];
var txBuf = new Buffer(data.TXHEX[0][0],'hex');
var tx = new Transaction().fromBuffer(txBuf);
var b = MerkleBlock(JSON.stringify(json));
var b = MerkleBlock(jsonData);
b.hasTransaction(tx).should.equal(true);
});
@ -174,12 +174,12 @@ describe('MerkleBlock', function() {
// Reuse another transaction already in data/ dir
var serialized = transactionVector[0][7];
var tx = new Transaction().fromBuffer(new Buffer(serialized, 'hex'));
var b = MerkleBlock(JSON.stringify(data.JSON[0]));
var b = MerkleBlock(data.JSON[0]);
b.hasTransaction(tx).should.equal(false);
});
it('should not match with merkle nodes', function() {
var b = MerkleBlock(JSON.stringify(data.JSON[0]));
var b = MerkleBlock(data.JSON[0]);
var hashData = [
['3612262624047ee87660be1a707519a443b1c1ce3d248cbfc6c15870f6c5daa2', false],

View File

@ -27,13 +27,12 @@ describe('HDKeys building with static methods', function() {
expect(clazz[staticMethod].bind(null, argument)).to.throw(message);
};
it(clazz.name + ' fromJSON checks that a valid JSON is provided', function() {
var errorMessage = 'No valid JSON string was provided';
var method = 'fromJSON';
var errorMessage = 'Invalid Argument: No valid argument was provided';
var method = 'fromObject';
expectStaticMethodFail(method, undefined, errorMessage);
expectStaticMethodFail(method, null, errorMessage);
expectStaticMethodFail(method, 'invalid JSON', errorMessage);
expectStaticMethodFail(method, '{\'singlequotes\': true}', errorMessage);
expectStaticMethodFail(method, {}, errorMessage);
});
it(clazz.name + ' fromString checks that a string is provided', function() {
var errorMessage = 'No valid string was provided';

View File

@ -294,12 +294,12 @@ describe('HDPrivate key interface', function() {
expect(BufferUtil.isBuffer(value)).to.equal(false);
});
});
it('roundtrips toJSON', function() {
expect(HDPrivateKey.fromJSON(new HDPrivateKey(xprivkey).toJSON()).xprivkey).to.equal(xprivkey);
it('roundtrips toObject', function() {
expect(HDPrivateKey.fromObject(new HDPrivateKey(xprivkey).toObject()).xprivkey).to.equal(xprivkey);
});
it('roundtrips to JSON and to Object', function() {
var privkey = new HDPrivateKey(xprivkey);
expect(HDPrivateKey.fromJSON(privkey.toJSON()).xprivkey).to.equal(xprivkey);
expect(HDPrivateKey.fromObject(privkey.toJSON()).xprivkey).to.equal(xprivkey);
});
it('recovers state from JSON', function() {
new HDPrivateKey(JSON.stringify(plainObject)).xprivkey.should.equal(xprivkey);

View File

@ -103,12 +103,12 @@ describe('HDPublicKey interface', function() {
});
it('can be generated from a json', function() {
expect(new HDPublicKey(json).xpubkey).to.equal(xpubkey);
expect(new HDPublicKey(JSON.parse(json)).xpubkey).to.equal(xpubkey);
});
it('can generate a json that has a particular structure', function() {
assert(_.isEqual(
new HDPublicKey(json).toJSON(),
new HDPublicKey(JSON.parse(json)).toJSON(),
new HDPublicKey(xpubkey).toJSON()
));
});
@ -187,10 +187,7 @@ describe('HDPublicKey interface', function() {
};
it('roundtrips to JSON and to Object', function() {
var pubkey = new HDPublicKey(xpubkey);
expect(HDPublicKey.fromJSON(pubkey.toJSON()).xpubkey).to.equal(xpubkey);
});
it('recovers state from JSON', function() {
new HDPublicKey(JSON.stringify(plainObject)).xpubkey.should.equal(xpubkey);
expect(HDPublicKey.fromObject(pubkey.toJSON()).xpubkey).to.equal(xpubkey);
});
it('recovers state from Object', function() {
new HDPublicKey(plainObject).xpubkey.should.equal(xpubkey);

View File

@ -198,7 +198,7 @@ describe('PrivateKey', function() {
});
describe('#json', function() {
describe('#json/object', function() {
it('should input/output json', function() {
var json = JSON.stringify({
@ -206,24 +206,21 @@ describe('PrivateKey', function() {
compressed: false,
network: 'livenet'
});
PrivateKey.fromJSON(json).toJSON().should.deep.equal(json);
var key = PrivateKey.fromObject(JSON.parse(json));
JSON.stringify(key).should.equal(json);
});
it('input json should correctly initialize network field', function() {
['livenet', 'testnet', 'mainnet'].forEach(function (net) {
var pk = PrivateKey.fromJSON(JSON.stringify({
var pk = PrivateKey.fromObject({
bn: '96c132224121b509b7d0a16245e957d9192609c5637c6228311287b1be21627a',
compressed: false,
network: net
}));
});
pk.network.should.be.deep.equal(Networks.get(net));
});
});
it('an object with private key info can be also used as argument for "fromJSON"', function() {
expect(PrivateKey._isJSON({bn: true, network: true})).to.equal(true);
});
it('fails on invalid argument', function() {
expect(function() {
return PrivateKey.fromJSON('¹');
@ -232,7 +229,7 @@ describe('PrivateKey', function() {
it('also accepts an object as argument', function() {
expect(function() {
return PrivateKey.fromJSON(new PrivateKey().toObject());
return PrivateKey.fromObject(new PrivateKey().toObject());
}).to.not.throw();
});
});

View File

@ -169,7 +169,7 @@ describe('PublicKey', function() {
});
});
describe('#json', function() {
describe('#json/object', function() {
it('should input/ouput json', function() {
var json = JSON.stringify({
@ -177,15 +177,16 @@ describe('PublicKey', function() {
y: '7baad41d04514751e6851f5304fd243751703bed21b914f6be218c0fa354a341',
compressed: false
});
PublicKey.fromJSON(json).toJSON().should.deep.equal(json);
var pubkey = new PublicKey(JSON.parse(json));
JSON.stringify(pubkey).should.deep.equal(json);
});
it('fails if "y" is not provided', function() {
expect(function() {
return PublicKey.fromJSON('{"x": "1ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a"}');
return new PublicKey({
x: '1ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a'
});
}).to.throw();
// coverage
PublicKey._isJSON({x: '1ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a'}).should.equal(false);
});
it('fails if invalid JSON is provided', function() {

View File

@ -76,14 +76,15 @@ describe('Transaction.Input', function() {
input.toString();
}).to.throw('Need a script to create an input');
});
it('fromJSON should work', function() {
var input = Input.fromJSON(coinbaseJSON);
var otherInput = Input.fromJSON(otherJSON);
it('fromObject should work', function() {
var jsonData = JSON.parse(coinbaseJSON);
var input = Input.fromObject(jsonData);
should.exist(input);
should.exist(otherInput);
input.prevTxId.toString('hex').should.equal(jsonData.prevTxId);
input.outputIndex.should.equal(jsonData.outputIndex);
});
it('fromObject should work', function() {
var input = Input.fromJSON(coinbaseJSON);
var input = Input.fromObject(JSON.parse(coinbaseJSON));
var obj = input.toObject();
Input.fromObject(obj).should.deep.equal(input);
obj.script = 42;

View File

@ -94,8 +94,8 @@ describe('Output', function() {
expectEqualOutputs(output, deserialized);
});
it('can instantiate from JSON', function() {
var out = new Output(JSON.stringify(output.toObject()));
it('can instantiate from an object', function() {
var out = new Output(output.toObject());
should.exist(out);
});
@ -161,9 +161,9 @@ describe('Output', function() {
});
it('roundtrips to/from JSON', function() {
var json = output2.toJSON();
var o3 = new Output(json);
o3.toJSON().should.equal(json);
var json = JSON.stringify(output2);
var o3 = new Output(JSON.parse(json));
JSON.stringify(o3).should.equal(json);
});
it('setScript fails with invalid input', function() {

View File

@ -111,13 +111,14 @@ describe('TransactionSignature', function() {
it('can roundtrip to/from json', function() {
var signature = getSignatureFromTransaction();
var serialized = signature.toObject();
var json = signature.toJSON();
expect(TransactionSignature(json).toObject()).to.deep.equal(serialized);
expect(TransactionSignature.fromJSON(json).toObject()).to.deep.equal(serialized);
var json = JSON.stringify(signature);
expect(TransactionSignature(JSON.parse(json)).toObject()).to.deep.equal(serialized);
expect(TransactionSignature.fromObject(JSON.parse(json)).toObject()).to.deep.equal(serialized);
});
it('can parse a previously known json string', function() {
expect(JSON.parse(TransactionSignature(testJSON).toJSON())).to.deep.equal(JSON.parse(testJSON));
var str = JSON.stringify(TransactionSignature(JSON.parse(testJSON)));
expect(JSON.parse(str)).to.deep.equal(JSON.parse(testJSON));
});
it('can deserialize a previously known object', function() {

View File

@ -578,7 +578,7 @@ describe('Transaction', function() {
it('serializes the `change` information', function() {
var transaction = new Transaction();
transaction.change(changeAddress);
expect(JSON.parse(transaction.toJSON()).changeScript).to.equal(Script.fromAddress(changeAddress).toString());
expect(transaction.toJSON().changeScript).to.equal(Script.fromAddress(changeAddress).toString());
expect(new Transaction(transaction.toJSON()).uncheckedSerialize()).to.equal(transaction.uncheckedSerialize());
});
it('serializes correctly p2sh multisig signed tx', function() {
@ -759,7 +759,7 @@ describe('Transaction', function() {
it('handles unsupported utxo in tx object', function() {
var transaction = new Transaction();
transaction.fromJSON.bind(transaction, unsupportedTxObj)
transaction.fromObject.bind(transaction, JSON.parse(unsupportedTxObj))
.should.throw('Unsupported input script type: OP_1 OP_ADD OP_2 OP_EQUAL');
});

View File

@ -84,16 +84,11 @@ describe('UnspentOutput', function() {
it('to/from JSON roundtrip', function() {
var utxo = new UnspentOutput(sampleData2);
expect(
JSON.parse(
UnspentOutput.fromJSON(
UnspentOutput.fromObject(
UnspentOutput.fromJSON(
utxo.toJSON()
).toObject()
).toJSON()
).toJSON()
)
).to.deep.equal(sampleData2);
var obj = UnspentOutput.fromObject(utxo.toJSON()).toObject();
expect(obj).to.deep.equal(sampleData2);
var str = JSON.stringify(UnspentOutput.fromObject(obj));
expect(JSON.parse(str)).to.deep.equal(sampleData2);
var str2 = JSON.stringify(new UnspentOutput(JSON.parse(str)));
expect(JSON.parse(str2)).to.deep.equal(sampleData2);
});
});

View File

@ -157,8 +157,8 @@ describe('Unit', function() {
it('can be imported and exported from/to JSON', function() {
var json = JSON.stringify({amount:1.3, code:'BTC'});
var unit = Unit.fromJSON(json);
unit.toJSON().should.deep.equal(json);
var unit = Unit.fromObject(JSON.parse(json));
JSON.stringify(unit).should.deep.equal(json);
});
it('importing from invalid JSON fails quickly', function() {

View File

@ -183,7 +183,7 @@ describe('URI', function() {
label: 'myLabel',
other: 'xD'
});
URI.fromJSON(json).toJSON().should.deep.equal(json);
JSON.stringify(URI.fromObject(JSON.parse(json))).should.equal(json);
});
it('should support numeric amounts', function() {