|
|
@ -4,21 +4,21 @@ var _ = require('lodash'); |
|
|
|
var chai = require('chai'); |
|
|
|
var sinon = require('sinon'); |
|
|
|
var should = chai.should(); |
|
|
|
var TXP = require('../../lib/model/txproposal'); |
|
|
|
var TxProposal = require('../../lib/model/txproposal'); |
|
|
|
var Bitcore = require('bitcore-wallet-utils').Bitcore; |
|
|
|
var WalletUtils = require('bitcore-wallet-utils'); |
|
|
|
|
|
|
|
describe('TXProposal', function() { |
|
|
|
|
|
|
|
describe('#create', function() { |
|
|
|
it('should create a TXP', function() { |
|
|
|
var txp = TXP.create(aTxpOpts()); |
|
|
|
it('should create a TxProposal', function() { |
|
|
|
var txp = TxProposal.create(aTxpOpts()); |
|
|
|
should.exist(txp); |
|
|
|
should.exist(txp.toAddress); |
|
|
|
should.not.exist(txp.outputs); |
|
|
|
}); |
|
|
|
it('should create a multiple-outputs TXP', function() { |
|
|
|
var txp = TXP.create(aTxpOpts(TXP.Types.MULTIPLEOUTPUTS)); |
|
|
|
it('should create a multiple-outputs TxProposal', function() { |
|
|
|
var txp = TxProposal.create(aTxpOpts(TxProposal.Types.MULTIPLEOUTPUTS)); |
|
|
|
should.exist(txp); |
|
|
|
should.not.exist(txp.toAddress); |
|
|
|
should.exist(txp.outputs); |
|
|
@ -26,26 +26,26 @@ describe('TXProposal', function() { |
|
|
|
}); |
|
|
|
|
|
|
|
describe('#fromObj', function() { |
|
|
|
it('should copy a TXP', function() { |
|
|
|
var txp = TXP.fromObj(aTXP()); |
|
|
|
it('should copy a TxProposal', function() { |
|
|
|
var txp = TxProposal.fromObj(aTXP()); |
|
|
|
should.exist(txp); |
|
|
|
txp.toAddress.should.equal(aTXP().toAddress); |
|
|
|
}); |
|
|
|
it('should copy a multiple-outputs TXP', function() { |
|
|
|
var txp = TXP.fromObj(aTXP(TXP.Types.MULTIPLEOUTPUTS)); |
|
|
|
it('should copy a multiple-outputs TxProposal', function() { |
|
|
|
var txp = TxProposal.fromObj(aTXP(TxProposal.Types.MULTIPLEOUTPUTS)); |
|
|
|
should.exist(txp); |
|
|
|
txp.outputs.should.deep.equal(aTXP(TXP.Types.MULTIPLEOUTPUTS).outputs); |
|
|
|
txp.outputs.should.deep.equal(aTXP(TxProposal.Types.MULTIPLEOUTPUTS).outputs); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
describe('#getBitcoreTx', function() { |
|
|
|
it('should create a valid bitcore TX', function() { |
|
|
|
var txp = TXP.fromObj(aTXP()); |
|
|
|
var txp = TxProposal.fromObj(aTXP()); |
|
|
|
var t = txp.getBitcoreTx(); |
|
|
|
should.exist(t); |
|
|
|
}); |
|
|
|
it('should order outputs as specified by outputOrder', function() { |
|
|
|
var txp = TXP.fromObj(aTXP()); |
|
|
|
var txp = TxProposal.fromObj(aTXP()); |
|
|
|
|
|
|
|
txp.outputOrder = [0, 1]; |
|
|
|
var t = txp.getBitcoreTx(); |
|
|
@ -56,7 +56,7 @@ describe('TXProposal', function() { |
|
|
|
t.getChangeOutput().should.deep.equal(t.outputs[0]); |
|
|
|
}); |
|
|
|
it('should create a bitcore TX with multiple outputs', function() { |
|
|
|
var txp = TXP.fromObj(aTXP(TXP.Types.MULTIPLEOUTPUTS)); |
|
|
|
var txp = TxProposal.fromObj(aTXP(TxProposal.Types.MULTIPLEOUTPUTS)); |
|
|
|
txp.outputOrder = [0, 1, 2]; |
|
|
|
var t = txp.getBitcoreTx(); |
|
|
|
t.getChangeOutput().should.deep.equal(t.outputs[2]); |
|
|
@ -65,14 +65,14 @@ describe('TXProposal', function() { |
|
|
|
|
|
|
|
describe('#getHeader', function() { |
|
|
|
it('should be compatible with simple proposal legacy header', function() { |
|
|
|
var x = TXP.fromObj(aTXP()); |
|
|
|
var x = TxProposal.fromObj(aTXP()); |
|
|
|
var proposalHeader = x.getHeader(); |
|
|
|
var pH = WalletUtils.getProposalHash.apply(WalletUtils, proposalHeader); |
|
|
|
var uH = WalletUtils.getProposalHash(x.toAddress, x.amount, x.message, x.payProUrl); |
|
|
|
pH.should.equal(uH); |
|
|
|
}); |
|
|
|
it('should handle multiple-outputs', function() { |
|
|
|
var x = TXP.fromObj(aTXP(TXP.Types.MULTIPLEOUTPUTS)); |
|
|
|
var x = TxProposal.fromObj(aTXP(TxProposal.Types.MULTIPLEOUTPUTS)); |
|
|
|
var proposalHeader = x.getHeader(); |
|
|
|
should.exist(proposalHeader); |
|
|
|
var pH = WalletUtils.getProposalHash.apply(WalletUtils, proposalHeader); |
|
|
@ -82,21 +82,23 @@ describe('TXProposal', function() { |
|
|
|
|
|
|
|
describe('#getTotalAmount', function() { |
|
|
|
it('should be compatible with simple proposal legacy amount', function() { |
|
|
|
var x = TXP.fromObj(aTXP()); |
|
|
|
var x = TxProposal.fromObj(aTXP()); |
|
|
|
var total = x.getTotalAmount(); |
|
|
|
total.should.equal(x.amount); |
|
|
|
}); |
|
|
|
it('should handle multiple-outputs', function() { |
|
|
|
var x = TXP.fromObj(aTXP(TXP.Types.MULTIPLEOUTPUTS)); |
|
|
|
var x = TxProposal.fromObj(aTXP(TxProposal.Types.MULTIPLEOUTPUTS)); |
|
|
|
var totalOutput = 0; |
|
|
|
_.each(x.outputs, function(o) { totalOutput += o.amount }); |
|
|
|
_.each(x.outputs, function(o) { |
|
|
|
totalOutput += o.amount |
|
|
|
}); |
|
|
|
x.getTotalAmount().should.equal(totalOutput); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
describe('#sign', function() { |
|
|
|
it('should sign 2-2', function() { |
|
|
|
var txp = TXP.fromObj(aTXP()); |
|
|
|
var txp = TxProposal.fromObj(aTXP()); |
|
|
|
txp.sign('1', theSignatures, theXPub); |
|
|
|
txp.isAccepted().should.equal(false); |
|
|
|
txp.isRejected().should.equal(false); |
|
|
@ -108,7 +110,7 @@ describe('TXProposal', function() { |
|
|
|
|
|
|
|
describe('#getRawTx', function() { |
|
|
|
it('should generate correct raw transaction for signed 2-2', function() { |
|
|
|
var txp = TXP.fromObj(aTXP()); |
|
|
|
var txp = TxProposal.fromObj(aTXP()); |
|
|
|
txp.sign('1', theSignatures, theXPub); |
|
|
|
txp.getRawTx().should.equal('0100000001ab069f7073be9b491bb1ad4233a45d2e383082ccc7206df905662d6d8499e66e080000009200483045022100896aeb8db75fec22fddb5facf791927a996eb3aee23ee6deaa15471ea46047de02204c0c33f42a9d3ff93d62738712a8c8a5ecd21b45393fdd144e7b01b5a186f1f9014752210319008ffe1b3e208f5ebed8f46495c056763f87b07930a7027a92ee477fb0cb0f2103b5f035af8be40d0db5abb306b7754949ab39032cf99ad177691753b37d10130152aeffffffff0280f0fa02000000001976a91451224bca38efcaa31d5340917c3f3f713b8b20e488ac70c9fa020000000017a914778192003f0e9e1d865c082179cc3dae5464b03d8700000000'); |
|
|
|
}); |
|
|
@ -118,7 +120,7 @@ describe('TXProposal', function() { |
|
|
|
|
|
|
|
describe('#reject', function() { |
|
|
|
it('should reject 2-2', function() { |
|
|
|
var txp = TXP.fromObj(aTXP()); |
|
|
|
var txp = TxProposal.fromObj(aTXP()); |
|
|
|
txp.reject('1'); |
|
|
|
txp.isAccepted().should.equal(false); |
|
|
|
txp.isRejected().should.equal(true); |
|
|
@ -128,7 +130,7 @@ describe('TXProposal', function() { |
|
|
|
|
|
|
|
describe('#reject & #sign', function() { |
|
|
|
it('should finally reject', function() { |
|
|
|
var txp = TXP.fromObj(aTXP()); |
|
|
|
var txp = TxProposal.fromObj(aTXP()); |
|
|
|
txp.sign('1', theSignatures); |
|
|
|
txp.isAccepted().should.equal(false); |
|
|
|
txp.isRejected().should.equal(false); |
|
|
@ -151,19 +153,16 @@ var aTxpOpts = function(type) { |
|
|
|
amount: 50000000, |
|
|
|
message: 'some message' |
|
|
|
}; |
|
|
|
if (type == TXP.Types.MULTIPLEOUTPUTS) { |
|
|
|
opts.outputs = [ |
|
|
|
{ |
|
|
|
toAddress: "18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7", |
|
|
|
amount: 10000000, |
|
|
|
message: "first message" |
|
|
|
}, |
|
|
|
{ |
|
|
|
toAddress: "18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7", |
|
|
|
amount: 20000000, |
|
|
|
message: "second message" |
|
|
|
}, |
|
|
|
]; |
|
|
|
if (type == TxProposal.Types.MULTIPLEOUTPUTS) { |
|
|
|
opts.outputs = [{ |
|
|
|
toAddress: "18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7", |
|
|
|
amount: 10000000, |
|
|
|
message: "first message" |
|
|
|
}, { |
|
|
|
toAddress: "18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7", |
|
|
|
amount: 20000000, |
|
|
|
message: "second message" |
|
|
|
}, ]; |
|
|
|
delete opts.toAddress; |
|
|
|
delete opts.amount; |
|
|
|
} |
|
|
@ -171,8 +170,18 @@ var aTxpOpts = function(type) { |
|
|
|
}; |
|
|
|
|
|
|
|
var aTXP = function(type) { |
|
|
|
var version; |
|
|
|
switch (type) { |
|
|
|
case TxProposal.Types.MULTIPLEOUTPUTS: |
|
|
|
version = '1.0.1'; |
|
|
|
break; |
|
|
|
default: |
|
|
|
version = '1.0.0'; |
|
|
|
break |
|
|
|
} |
|
|
|
|
|
|
|
var txp = { |
|
|
|
"version": "1.0.0", |
|
|
|
"version": version, |
|
|
|
"type": type, |
|
|
|
"createdOn": 1423146231, |
|
|
|
"id": "75c34f49-1ed6-255f-e9fd-0c71ae75ed1e", |
|
|
@ -209,19 +218,16 @@ var aTXP = function(type) { |
|
|
|
"actions": [], |
|
|
|
"outputOrder": [0, 1], |
|
|
|
}; |
|
|
|
if (type == TXP.Types.MULTIPLEOUTPUTS) { |
|
|
|
txp.outputs = [ |
|
|
|
{ |
|
|
|
toAddress: "18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7", |
|
|
|
amount: 10000000, |
|
|
|
message: "first message" |
|
|
|
}, |
|
|
|
{ |
|
|
|
toAddress: "18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7", |
|
|
|
amount: 20000000, |
|
|
|
message: "second message" |
|
|
|
}, |
|
|
|
]; |
|
|
|
if (type == TxProposal.Types.MULTIPLEOUTPUTS) { |
|
|
|
txp.outputs = [{ |
|
|
|
toAddress: "18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7", |
|
|
|
amount: 10000000, |
|
|
|
message: "first message" |
|
|
|
}, { |
|
|
|
toAddress: "18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7", |
|
|
|
amount: 20000000, |
|
|
|
message: "second message" |
|
|
|
}, ]; |
|
|
|
txp.outputOrder = [0, 1, 2]; |
|
|
|
delete txp.toAddress; |
|
|
|
delete txp.amount; |
|
|
|