|
|
@ -302,7 +302,7 @@ describe('Copay server', function() { |
|
|
|
}; |
|
|
|
server.createWallet(opts, function(err, walletId) { |
|
|
|
should.not.exist(walletId); |
|
|
|
err.should.exist; |
|
|
|
should.exist(err); |
|
|
|
err.message.should.contain('name'); |
|
|
|
done(); |
|
|
|
}); |
|
|
@ -346,7 +346,20 @@ describe('Copay server', function() { |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
it.skip('should fail to create wallet with invalid pubKey argument', function(done) {}); |
|
|
|
it('should fail to create wallet with invalid pubKey argument', function(done) { |
|
|
|
var opts = { |
|
|
|
name: 'my wallet', |
|
|
|
m: 2, |
|
|
|
n: 3, |
|
|
|
pubKey: 'dummy', |
|
|
|
}; |
|
|
|
server.createWallet(opts, function(err, walletId) { |
|
|
|
should.not.exist(walletId); |
|
|
|
should.exist(err); |
|
|
|
err.message.should.contain('Invalid public key'); |
|
|
|
done(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
describe('#joinWallet', function() { |
|
|
@ -399,7 +412,7 @@ describe('Copay server', function() { |
|
|
|
}; |
|
|
|
server.joinWallet(copayerOpts, function(err, result) { |
|
|
|
should.not.exist(result); |
|
|
|
err.should.exist; |
|
|
|
should.exist(err); |
|
|
|
err.message.should.contain('name'); |
|
|
|
done(); |
|
|
|
}); |
|
|
@ -453,7 +466,39 @@ describe('Copay server', function() { |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
it.skip('should fail two wallets with same xPubKey', function(done) {}); |
|
|
|
it('should fail two wallets with same xPubKey', function(done) { |
|
|
|
var copayerOpts = { |
|
|
|
walletId: walletId, |
|
|
|
name: 'me', |
|
|
|
xPubKey: TestData.copayers[0].xPubKey, |
|
|
|
xPubKeySignature: TestData.copayers[0].xPubKeySignature, |
|
|
|
}; |
|
|
|
server.joinWallet(copayerOpts, function(err) { |
|
|
|
should.not.exist(err); |
|
|
|
|
|
|
|
var walletOpts = { |
|
|
|
name: 'my other wallet', |
|
|
|
m: 1, |
|
|
|
n: 1, |
|
|
|
pubKey: TestData.keyPair.pub, |
|
|
|
}; |
|
|
|
server.createWallet(walletOpts, function(err, walletId) { |
|
|
|
should.not.exist(err); |
|
|
|
copayerOpts = { |
|
|
|
walletId: walletId, |
|
|
|
name: 'me', |
|
|
|
xPubKey: TestData.copayers[0].xPubKey, |
|
|
|
xPubKeySignature: TestData.copayers[0].xPubKeySignature, |
|
|
|
}; |
|
|
|
server.joinWallet(copayerOpts, function(err) { |
|
|
|
should.exist(err); |
|
|
|
err.code.should.equal('CREGISTERED'); |
|
|
|
err.message.should.equal('Copayer ID already registered on server'); |
|
|
|
done(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
it('should fail to join with bad formated signature', function(done) { |
|
|
|
var copayerOpts = { |
|
|
@ -475,7 +520,7 @@ describe('Copay server', function() { |
|
|
|
xPubKey: TestData.copayers[0].xPubKey[0], |
|
|
|
}; |
|
|
|
server.joinWallet(copayerOpts, function(err) { |
|
|
|
err.should.exist; |
|
|
|
should.exist(err); |
|
|
|
err.message.should.contain('argument missing'); |
|
|
|
done(); |
|
|
|
}); |
|
|
@ -583,7 +628,7 @@ describe('Copay server', function() { |
|
|
|
it('should not create address if unable to store it', function(done) { |
|
|
|
sinon.stub(server.storage, 'storeAddressAndWallet').yields('dummy error'); |
|
|
|
server.createAddress({}, function(err, address) { |
|
|
|
err.should.exist; |
|
|
|
should.exist(err); |
|
|
|
should.not.exist(address); |
|
|
|
|
|
|
|
server.getMainAddresses({}, function(err, addresses) { |
|
|
@ -625,7 +670,7 @@ describe('Copay server', function() { |
|
|
|
helpers.getAuthServer(result.copayerId, function(server) { |
|
|
|
server.createAddress({}, function(err, address) { |
|
|
|
should.not.exist(address); |
|
|
|
err.should.exist; |
|
|
|
should.exist(err); |
|
|
|
err.message.should.contain('not complete'); |
|
|
|
done(); |
|
|
|
}); |
|
|
@ -656,7 +701,7 @@ describe('Copay server', function() { |
|
|
|
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 80, null, TestData.copayers[0].privKey); |
|
|
|
server.createTx(txOpts, function(err, tx) { |
|
|
|
should.not.exist(tx); |
|
|
|
err.should.exist; |
|
|
|
should.exist(err); |
|
|
|
err.message.should.contain('not complete'); |
|
|
|
done(); |
|
|
|
}); |
|
|
@ -714,7 +759,7 @@ describe('Copay server', function() { |
|
|
|
|
|
|
|
server.createTx(txOpts, function(err, tx) { |
|
|
|
should.not.exist(tx); |
|
|
|
err.should.exist; |
|
|
|
should.exist(err); |
|
|
|
err.message.should.equal('Invalid proposal signature'); |
|
|
|
done(); |
|
|
|
}); |
|
|
@ -727,7 +772,7 @@ describe('Copay server', function() { |
|
|
|
|
|
|
|
server.createTx(txOpts, function(err, tx) { |
|
|
|
should.not.exist(tx); |
|
|
|
err.should.exist; |
|
|
|
should.exist(err); |
|
|
|
err.message.should.equal('Invalid proposal signature'); |
|
|
|
done(); |
|
|
|
}); |
|
|
@ -740,7 +785,7 @@ describe('Copay server', function() { |
|
|
|
|
|
|
|
server.createTx(txOpts, function(err, tx) { |
|
|
|
should.not.exist(tx); |
|
|
|
err.should.exist; |
|
|
|
should.exist(err); |
|
|
|
err.code.should.equal('INVALIDADDRESS'); |
|
|
|
err.message.should.equal('Invalid address'); |
|
|
|
done(); |
|
|
@ -762,7 +807,15 @@ describe('Copay server', function() { |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
it.skip('should fail to create tx for invalid amount', function(done) {}); |
|
|
|
it('should fail to create tx for invalid amount', function(done) { |
|
|
|
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0, null, TestData.copayers[0].privKey); |
|
|
|
server.createTx(txOpts, function(err, tx) { |
|
|
|
should.not.exist(tx); |
|
|
|
should.exist(err); |
|
|
|
err.message.should.equal('Invalid amount'); |
|
|
|
done(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
it('should fail to create tx when insufficient funds', function(done) { |
|
|
|
helpers.stubUtxos(server, wallet, [100], function() { |
|
|
@ -809,7 +862,22 @@ describe('Copay server', function() { |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
it.skip('should fail gracefully when bitcore throws exception on raw tx creation', function(done) {}); |
|
|
|
it('should fail gracefully when bitcore throws exception on raw tx creation', function(done) { |
|
|
|
helpers.stubUtxos(server, wallet, [10], function() { |
|
|
|
var bitcoreStub = sinon.stub(Bitcore, 'Transaction'); |
|
|
|
bitcoreStub.throws({ |
|
|
|
name: 'dummy', |
|
|
|
message: 'dummy exception' |
|
|
|
}); |
|
|
|
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 2, null, TestData.copayers[0].privKey); |
|
|
|
server.createTx(txOpts, function(err, tx) { |
|
|
|
should.exist(err); |
|
|
|
err.message.should.equal('dummy exception'); |
|
|
|
bitcoreStub.restore(); |
|
|
|
done(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
it('should create tx when there is a pending tx and enough UTXOs', function(done) { |
|
|
|
helpers.stubUtxos(server, wallet, [10.1, 10.2, 10.3], function() { |
|
|
@ -897,7 +965,7 @@ describe('Copay server', function() { |
|
|
|
var server, wallet, txid; |
|
|
|
|
|
|
|
beforeEach(function(done) { |
|
|
|
helpers.createAndJoinWallet(2, 3, function(s, w) { |
|
|
|
helpers.createAndJoinWallet(2, 2, function(s, w) { |
|
|
|
server = s; |
|
|
|
wallet = w; |
|
|
|
helpers.stubUtxos(server, wallet, _.range(1, 9), function() { |
|
|
@ -924,22 +992,63 @@ describe('Copay server', function() { |
|
|
|
should.not.exist(err); |
|
|
|
server.getPendingTxs({}, function(err, txs) { |
|
|
|
should.not.exist(err); |
|
|
|
var tx = txs[0]; |
|
|
|
tx.id.should.equal(txid); |
|
|
|
|
|
|
|
var actors = tx.getActors(); |
|
|
|
actors.length.should.equal(1); |
|
|
|
actors[0].should.equal(wallet.copayers[0].id); |
|
|
|
var action = tx.getActionBy(wallet.copayers[0].id); |
|
|
|
action.type.should.equal('reject'); |
|
|
|
action.comment.should.equal('some reason'); |
|
|
|
done(); |
|
|
|
txs.should.be.empty; |
|
|
|
server.getTx({ |
|
|
|
id: txid |
|
|
|
}, function(err, tx) { |
|
|
|
var actors = tx.getActors(); |
|
|
|
actors.length.should.equal(1); |
|
|
|
actors[0].should.equal(wallet.copayers[0].id); |
|
|
|
var action = tx.getActionBy(wallet.copayers[0].id); |
|
|
|
action.type.should.equal('reject'); |
|
|
|
action.comment.should.equal('some reason'); |
|
|
|
done(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
it.skip('should fail to reject non-pending TX', function(done) {}); |
|
|
|
it('should fail to reject non-pending TX', function(done) { |
|
|
|
async.waterfall([ |
|
|
|
|
|
|
|
function(next) { |
|
|
|
server.getPendingTxs({}, function(err, txs) { |
|
|
|
var tx = txs[0]; |
|
|
|
tx.id.should.equal(txid); |
|
|
|
next(); |
|
|
|
}); |
|
|
|
}, |
|
|
|
function(next) { |
|
|
|
server.rejectTx({ |
|
|
|
txProposalId: txid, |
|
|
|
reason: 'some reason', |
|
|
|
}, function(err) { |
|
|
|
should.not.exist(err); |
|
|
|
next(); |
|
|
|
}); |
|
|
|
}, |
|
|
|
function(next) { |
|
|
|
server.getPendingTxs({}, function(err, txs) { |
|
|
|
should.not.exist(err); |
|
|
|
txs.should.be.empty; |
|
|
|
next(); |
|
|
|
}); |
|
|
|
}, |
|
|
|
function(next) { |
|
|
|
helpers.getAuthServer(wallet.copayers[1].id, function(server) { |
|
|
|
server.rejectTx({ |
|
|
|
txProposalId: txid, |
|
|
|
reason: 'some other reason', |
|
|
|
}, function(err) { |
|
|
|
should.exist(err); |
|
|
|
err.code.should.equal('TXNOTPENDING'); |
|
|
|
done(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}, |
|
|
|
]); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
describe('#signTx', function() { |
|
|
@ -1095,6 +1204,57 @@ describe('Copay server', function() { |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
it('should fail to sign a non-pending TX', function(done) { |
|
|
|
async.waterfall([ |
|
|
|
|
|
|
|
function(next) { |
|
|
|
server.rejectTx({ |
|
|
|
txProposalId: txid, |
|
|
|
reason: 'some reason', |
|
|
|
}, function(err) { |
|
|
|
should.not.exist(err); |
|
|
|
next(); |
|
|
|
}); |
|
|
|
}, |
|
|
|
function(next) { |
|
|
|
helpers.getAuthServer(wallet.copayers[1].id, function(server) { |
|
|
|
server.rejectTx({ |
|
|
|
txProposalId: txid, |
|
|
|
reason: 'some reason', |
|
|
|
}, function(err) { |
|
|
|
should.not.exist(err); |
|
|
|
next(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}, |
|
|
|
function(next) { |
|
|
|
server.getPendingTxs({}, function(err, txs) { |
|
|
|
should.not.exist(err); |
|
|
|
txs.should.be.empty; |
|
|
|
next(); |
|
|
|
}); |
|
|
|
}, |
|
|
|
function(next) { |
|
|
|
helpers.getAuthServer(wallet.copayers[2].id, function(server) { |
|
|
|
server.getTx({ |
|
|
|
id: txid |
|
|
|
}, function(err, tx) { |
|
|
|
should.not.exist(err); |
|
|
|
var signatures = helpers.clientSign(tx, TestData.copayers[2].xPrivKey); |
|
|
|
server.signTx({ |
|
|
|
txProposalId: txid, |
|
|
|
signatures: signatures, |
|
|
|
}, function(err) { |
|
|
|
should.exist(err); |
|
|
|
err.code.should.equal('TXNOTPENDING'); |
|
|
|
done(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}, |
|
|
|
]); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
describe.skip('#broadcastTx', function() { |
|
|
@ -1644,9 +1804,10 @@ describe('Copay server', function() { |
|
|
|
it('should allow creator to remove an signed TX by himself', function(done) { |
|
|
|
var signatures = helpers.clientSign(txp, TestData.copayers[0].xPrivKey); |
|
|
|
server.signTx({ |
|
|
|
txProposalId: txp[0], |
|
|
|
txProposalId: txp.id, |
|
|
|
signatures: signatures, |
|
|
|
}, function(err) { |
|
|
|
should.not.exist(err); |
|
|
|
server.removePendingTx({ |
|
|
|
txProposalId: txp.id |
|
|
|
}, function(err) { |
|
|
@ -1659,7 +1820,57 @@ describe('Copay server', function() { |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
it.skip('should fail to remove non-pending TX', function(done) {}); |
|
|
|
it('should fail to remove non-pending TX', function(done) { |
|
|
|
async.waterfall([ |
|
|
|
|
|
|
|
function(next) { |
|
|
|
var signatures = helpers.clientSign(txp, TestData.copayers[0].xPrivKey); |
|
|
|
server.signTx({ |
|
|
|
txProposalId: txp.id, |
|
|
|
signatures: signatures, |
|
|
|
}, function(err) { |
|
|
|
should.not.exist(err); |
|
|
|
next(); |
|
|
|
}); |
|
|
|
}, |
|
|
|
function(next) { |
|
|
|
helpers.getAuthServer(wallet.copayers[1].id, function(server) { |
|
|
|
server.rejectTx({ |
|
|
|
txProposalId: txp.id, |
|
|
|
}, function(err) { |
|
|
|
should.not.exist(err); |
|
|
|
next(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}, |
|
|
|
function(next) { |
|
|
|
helpers.getAuthServer(wallet.copayers[2].id, function(server) { |
|
|
|
server.rejectTx({ |
|
|
|
txProposalId: txp.id, |
|
|
|
}, function(err) { |
|
|
|
should.not.exist(err); |
|
|
|
next(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}, |
|
|
|
function(next) { |
|
|
|
server.getPendingTxs({}, function(err, txs) { |
|
|
|
should.not.exist(err); |
|
|
|
txs.should.be.empty; |
|
|
|
next(); |
|
|
|
}); |
|
|
|
}, |
|
|
|
function(next) { |
|
|
|
server.removePendingTx({ |
|
|
|
txProposalId: txp.id |
|
|
|
}, function(err) { |
|
|
|
should.exist(err); |
|
|
|
err.code.should.equal('TXNOTPENDING'); |
|
|
|
done(); |
|
|
|
}); |
|
|
|
}, |
|
|
|
]); |
|
|
|
}); |
|
|
|
|
|
|
|
it('should not allow non-creator copayer to remove an unsigned TX ', function(done) { |
|
|
|
helpers.getAuthServer(wallet.copayers[1].id, function(server2) { |
|
|
|