2014-04-16 13:50:10 -07:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
var chai = chai || require('chai');
|
|
|
|
var should = chai.should();
|
|
|
|
|
2014-07-08 15:52:47 -07:00
|
|
|
var FakeStorage = require('./mocks/FakeLocalStorage');
|
2014-06-17 10:02:39 -07:00
|
|
|
var copay = copay || require('../copay');
|
|
|
|
var sinon = require('sinon');
|
2014-04-18 10:40:16 -07:00
|
|
|
var FakeNetwork = require('./mocks/FakeNetwork');
|
2014-06-17 10:02:39 -07:00
|
|
|
var FakeBlockchain = require('./mocks/FakeBlockchain');
|
2014-04-16 16:58:57 -07:00
|
|
|
var FakeStorage = require('./mocks/FakeStorage');
|
2014-06-15 20:55:23 -07:00
|
|
|
var WalletFactory = require('../js/models/core/WalletFactory');
|
2014-07-25 06:50:18 -07:00
|
|
|
var Passphrase = require('../js/models/core/Passphrase');
|
2014-04-16 13:50:10 -07:00
|
|
|
|
2014-07-02 12:55:41 -07:00
|
|
|
|
2014-07-29 09:33:54 -07:00
|
|
|
/**
|
|
|
|
* A better way to compare two objects in Javascript
|
|
|
|
**/
|
|
|
|
function getKeys(obj) {
|
|
|
|
var keys;
|
|
|
|
if(obj.keys) {
|
|
|
|
keys = obj.keys();
|
|
|
|
} else {
|
|
|
|
keys = [];
|
|
|
|
|
|
|
|
for(var k in obj) {
|
|
|
|
if(Object.prototype.hasOwnProperty.call(obj, k)) {
|
|
|
|
keys.push(k);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return keys;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a new object so the keys appear in the provided order.
|
|
|
|
* @param {Object} obj The object to be the base for the new object
|
|
|
|
* @param {Array} keys The order in which properties of the new object should appear
|
|
|
|
**/
|
|
|
|
function reconstructObject(obj, keys) {
|
|
|
|
var result = {};
|
|
|
|
for (var i = 0, l = keys.length; i < l; i++) {
|
|
|
|
if (Object.prototype.hasOwnProperty.call(obj, keys[i])) {
|
|
|
|
result[keys[i]] = obj[keys[i]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
function assertObjectEqual(a, b, msg) {
|
|
|
|
msg = msg || '';
|
|
|
|
if( Object.prototype.toString.call( a ) === '[object Array]' && Object.prototype.toString.call( b ) === '[object Array]') {
|
|
|
|
// special case: array of objects
|
|
|
|
if (a.filter(function(e) { return Object.prototype.toString.call( e ) === '[object Object]' }).length > 0 ||
|
|
|
|
b.filter(function(e) { return Object.prototype.toString.call( e ) === '[object Object]' }).length > 0 ){
|
|
|
|
|
|
|
|
if (a.length !== b.length) {
|
|
|
|
JSON.stringify(a).should.equal(JSON.stringify(b), msg);
|
|
|
|
} else {
|
|
|
|
for(var i = 0, l = a.length; i < l; i++) {
|
|
|
|
assertObjectEqual(a[i], b[i], msg + '[elements at index ' + i + ' should be equal]');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// simple array of primitives
|
|
|
|
} else {
|
|
|
|
JSON.stringify(a).should.equal(JSON.stringify(b), msg);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
var orderedA = reconstructObject(a, getKeys(a).sort()),
|
|
|
|
orderedB = reconstructObject(b, getKeys(b).sort());
|
|
|
|
|
|
|
|
// compare as strings for diff tolls to show us the difference
|
|
|
|
JSON.stringify(orderedA).should.equal(JSON.stringify(orderedB), msg)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-16 13:50:10 -07:00
|
|
|
describe('WalletFactory model', function() {
|
|
|
|
var config = {
|
2014-06-15 20:55:23 -07:00
|
|
|
Network: FakeNetwork,
|
2014-06-17 12:25:38 -07:00
|
|
|
Blockchain: FakeBlockchain,
|
2014-06-15 20:55:23 -07:00
|
|
|
Storage: FakeStorage,
|
2014-04-16 13:50:10 -07:00
|
|
|
wallet: {
|
|
|
|
requiredCopayers: 3,
|
|
|
|
totalCopayers: 5,
|
|
|
|
spendUnconfirmed: 1,
|
2014-06-03 08:40:28 -07:00
|
|
|
reconnectDelay: 100,
|
2014-06-15 20:55:23 -07:00
|
|
|
|
2014-04-16 13:50:10 -07:00
|
|
|
},
|
|
|
|
blockchain: {
|
|
|
|
host: 'test.insight.is',
|
|
|
|
port: 80
|
|
|
|
},
|
|
|
|
networkName: 'testnet',
|
2014-05-01 11:12:38 -07:00
|
|
|
passphrase: 'test',
|
2014-06-17 10:02:39 -07:00
|
|
|
storageObj: new FakeStorage(),
|
|
|
|
networkObj: new FakeNetwork(),
|
|
|
|
blockchainObj: new FakeBlockchain(),
|
2014-04-16 13:50:10 -07:00
|
|
|
};
|
|
|
|
|
2014-06-17 10:02:39 -07:00
|
|
|
beforeEach(function() {
|
|
|
|
config.storageObj.reset();
|
|
|
|
});
|
|
|
|
|
2014-04-29 13:44:35 -07:00
|
|
|
it('should create the factory', function() {
|
2014-06-17 10:02:39 -07:00
|
|
|
var wf = new WalletFactory(config, '0.0.1');
|
2014-04-29 13:44:35 -07:00
|
|
|
should.exist(wf);
|
2014-06-17 10:02:39 -07:00
|
|
|
wf.networkName.should.equal(config.networkName);
|
|
|
|
wf.walletDefaults.should.deep.equal(config.wallet);
|
|
|
|
wf.version.should.equal('0.0.1');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should log', function() {
|
|
|
|
var c2 = JSON.parse(JSON.stringify(config));
|
|
|
|
c2.verbose = 1;
|
2014-07-25 06:50:18 -07:00
|
|
|
c2.Storage = FakeStorage;
|
2014-06-17 10:02:39 -07:00
|
|
|
var wf = new WalletFactory(c2, '0.0.1');
|
2014-06-18 09:32:19 -07:00
|
|
|
var save_console_log = console.log;
|
|
|
|
console.log = function() {};
|
2014-06-17 10:02:39 -07:00
|
|
|
var spy = sinon.spy(console, 'log');
|
|
|
|
wf.log('ok');
|
|
|
|
sinon.assert.callCount(spy, 1);
|
|
|
|
spy.getCall(0).args[0].should.equal('ok');
|
2014-06-18 09:32:19 -07:00
|
|
|
console.log = save_console_log;
|
2014-04-29 13:44:35 -07:00
|
|
|
});
|
2014-06-17 10:02:39 -07:00
|
|
|
|
|
|
|
|
2014-04-29 13:44:35 -07:00
|
|
|
it('#_checkRead should return false', function() {
|
|
|
|
var wf = new WalletFactory(config);
|
|
|
|
wf._checkRead('dummy').should.equal(false);
|
|
|
|
wf.read('dummy').should.equal(false);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should be able to create wallets', function() {
|
2014-05-14 17:02:01 -07:00
|
|
|
var wf = new WalletFactory(config, '0.0.1');
|
2014-04-29 13:44:35 -07:00
|
|
|
var w = wf.create();
|
|
|
|
should.exist(w);
|
|
|
|
});
|
|
|
|
it('should be able to get wallets', function() {
|
2014-05-14 17:02:01 -07:00
|
|
|
var wf = new WalletFactory(config, '0.0.1');
|
2014-04-29 13:44:35 -07:00
|
|
|
var w = wf.create();
|
|
|
|
|
|
|
|
var w2 = wf.read(w.id);
|
|
|
|
should.exist(w2);
|
|
|
|
w2.id.should.equal(w.id);
|
|
|
|
});
|
|
|
|
|
2014-07-29 09:33:54 -07:00
|
|
|
|
2014-04-29 13:44:35 -07:00
|
|
|
it('#fromObj #toObj round trip', function() {
|
2014-05-14 17:02:01 -07:00
|
|
|
var wf = new WalletFactory(config, '0.0.5');
|
2014-08-19 08:48:29 -07:00
|
|
|
var w = wf.fromObj(JSON.parse(o));
|
2014-04-29 13:44:35 -07:00
|
|
|
|
|
|
|
should.exist(w);
|
|
|
|
w.id.should.equal("dbfe10c3fae71cea");
|
|
|
|
should.exist(w.publicKeyRing.getCopayerId);
|
2014-07-25 06:50:18 -07:00
|
|
|
should.exist(w.txProposals.toObj());
|
|
|
|
should.exist(w.privateKey.toObj());
|
2014-08-19 08:48:29 -07:00
|
|
|
assertObjectEqual(w.toObj(), JSON.parse(o));
|
2014-07-29 09:33:54 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-08-19 08:48:29 -07:00
|
|
|
it('#fromObj #toObj round trip, using old copayerIndex', function() {
|
2014-07-29 09:33:54 -07:00
|
|
|
var wf = new WalletFactory(config, '0.0.5');
|
|
|
|
var w = wf.fromObj(JSON.parse(o));
|
2014-06-16 13:37:33 -07:00
|
|
|
|
2014-07-29 09:33:54 -07:00
|
|
|
should.exist(w);
|
|
|
|
w.id.should.equal("dbfe10c3fae71cea");
|
|
|
|
should.exist(w.publicKeyRing.getCopayerId);
|
|
|
|
should.exist(w.txProposals.toObj());
|
|
|
|
should.exist(w.privateKey.toObj());
|
2014-08-19 08:48:29 -07:00
|
|
|
assertObjectEqual(w.toObj(), JSON.parse(o));
|
2014-04-29 13:44:35 -07:00
|
|
|
});
|
|
|
|
|
2014-07-01 05:41:28 -07:00
|
|
|
it('support old index schema: #fromObj #toObj round trip', function() {
|
2014-08-19 08:48:29 -07:00
|
|
|
var o = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5"},"networkNonce":"0000000000000001","networkNonces":[],"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"indexes":{"changeIndex":0,"receiveIndex":0},"copayersBackup":[],"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet","privateKeyCache":{}},"addressBook":{}}';
|
|
|
|
var o2 = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5"},"networkNonce":"0000000000000001","networkNonces":[],"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"indexes":[{"copayerIndex":2147483647,"changeIndex":0,"receiveIndex":0},{"copayerIndex":0,"changeIndex":0,"receiveIndex":0},{"copayerIndex":1,"changeIndex":0,"receiveIndex":0},{"copayerIndex":2,"changeIndex":0,"receiveIndex":0},{"copayerIndex":3,"changeIndex":0,"receiveIndex":0},{"copayerIndex":4,"changeIndex":0,"receiveIndex":0}],"copayersBackup":[],"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet","privateKeyCache":{}},"addressBook":{}}';
|
2014-07-01 05:41:28 -07:00
|
|
|
|
|
|
|
var wf = new WalletFactory(config, '0.0.5');
|
|
|
|
var w = wf.fromObj(JSON.parse(o));
|
|
|
|
|
|
|
|
should.exist(w);
|
|
|
|
w.id.should.equal("dbfe10c3fae71cea");
|
|
|
|
should.exist(w.publicKeyRing.getCopayerId);
|
|
|
|
should.exist(w.txProposals.toObj);
|
|
|
|
should.exist(w.privateKey.toObj);
|
2014-07-29 09:33:54 -07:00
|
|
|
|
|
|
|
//
|
|
|
|
var expected = JSON.parse(o2.replace(/cosigner/g,'copayerIndex'));
|
|
|
|
assertObjectEqual(w.toObj(), expected);
|
2014-07-01 05:41:28 -07:00
|
|
|
});
|
|
|
|
|
2014-06-26 06:08:40 -07:00
|
|
|
it('should create wallet from encrypted object', function() {
|
|
|
|
var wf = new WalletFactory(config, '0.0.1');
|
2014-07-02 12:55:41 -07:00
|
|
|
var walletObj = JSON.parse(o);
|
|
|
|
wf.storage._setPassphrase = sinon.spy();
|
|
|
|
wf.storage.import = sinon.stub().withArgs("encrypted object").returns(walletObj);
|
|
|
|
wf.fromObj = sinon.stub().withArgs(walletObj).returns(walletObj);
|
|
|
|
|
|
|
|
var w = wf.fromEncryptedObj("encrypted object", "password");
|
|
|
|
should.exist(w);
|
|
|
|
wf.storage._setPassphrase.called.should.be.true;
|
|
|
|
wf.storage.import.called.should.be.true;
|
|
|
|
wf.fromObj.calledWith(walletObj).should.be.true;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should return false if decrypted object is wrong', function() {
|
|
|
|
var wf = new WalletFactory(config, '0.0.1');
|
|
|
|
var walletObj = JSON.parse(o);
|
2014-06-26 06:08:40 -07:00
|
|
|
wf.storage._setPassphrase = sinon.spy();
|
|
|
|
wf.storage.import = sinon.spy();
|
2014-07-02 12:55:41 -07:00
|
|
|
wf.fromObj = sinon.stub().withArgs(walletObj).returns(walletObj);
|
2014-06-26 06:08:40 -07:00
|
|
|
|
|
|
|
var w = wf.fromEncryptedObj("encrypted object", "password");
|
|
|
|
should.exist(w);
|
|
|
|
wf.storage._setPassphrase.called.should.be.true;
|
|
|
|
wf.storage.import.called.should.be.true;
|
2014-07-02 12:55:41 -07:00
|
|
|
wf.fromObj.calledWith(walletObj).should.be.false;
|
2014-06-26 06:08:40 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should import and update indexes', function() {
|
|
|
|
var wf = new WalletFactory(config, '0.0.1');
|
2014-07-08 15:52:47 -07:00
|
|
|
var wallet = {
|
|
|
|
id: "fake wallet",
|
|
|
|
updateIndexes: function(cb) {
|
|
|
|
cb();
|
|
|
|
}
|
|
|
|
};
|
2014-06-26 06:08:40 -07:00
|
|
|
wf.fromEncryptedObj = sinon.stub().returns(wallet);
|
|
|
|
|
2014-07-02 06:44:20 -07:00
|
|
|
var w = wf.import("encrypted", "password");
|
2014-06-26 06:08:40 -07:00
|
|
|
|
|
|
|
should.exist(w);
|
|
|
|
wallet.should.equal(w);
|
2014-07-02 06:44:20 -07:00
|
|
|
|
|
|
|
wf.fromEncryptedObj = sinon.stub().returns(null);
|
|
|
|
(function() {
|
|
|
|
wf.import("encrypted", "password")
|
|
|
|
}).should.throw();
|
2014-06-26 06:08:40 -07:00
|
|
|
});
|
2014-04-29 13:44:35 -07:00
|
|
|
|
|
|
|
it('BIP32 length problem', function() {
|
2014-06-03 08:40:28 -07:00
|
|
|
var sconfig = {
|
2014-06-15 20:55:23 -07:00
|
|
|
Network: FakeNetwork,
|
2014-06-17 12:25:38 -07:00
|
|
|
Blockchain: FakeBlockchain,
|
2014-06-15 20:55:23 -07:00
|
|
|
Storage: FakeStorage,
|
2014-06-03 08:40:28 -07:00
|
|
|
"networkName": "testnet",
|
|
|
|
"network": {
|
|
|
|
"key": "g23ihfh82h35rf",
|
|
|
|
"host": "162.242.219.26",
|
|
|
|
"port": 10009,
|
|
|
|
"path": "/",
|
|
|
|
"maxPeers": 15,
|
|
|
|
"debug": 3
|
|
|
|
},
|
|
|
|
"limits": {
|
|
|
|
"totalCopayers": 10,
|
|
|
|
"mPlusN": 15
|
|
|
|
},
|
|
|
|
"wallet": {
|
|
|
|
"requiredCopayers": 2,
|
|
|
|
"totalCopayers": 3,
|
2014-06-16 13:37:33 -07:00
|
|
|
"reconnectDelay": 100,
|
2014-06-03 08:40:28 -07:00
|
|
|
"spendUnconfirmed": 1,
|
|
|
|
"verbose": 0
|
|
|
|
},
|
|
|
|
"blockchain": {
|
|
|
|
"host": "test.insight.is",
|
|
|
|
"port": 3001
|
|
|
|
},
|
|
|
|
"socket": {
|
|
|
|
"host": "test.insight.is",
|
|
|
|
"port": 3001
|
|
|
|
},
|
|
|
|
"verbose": 0,
|
2014-06-17 10:02:39 -07:00
|
|
|
"themes": ["default"],
|
|
|
|
storageObj: new FakeStorage(),
|
|
|
|
networkObj: new FakeNetwork(),
|
|
|
|
blockchainObj: new FakeBlockchain(),
|
2014-06-03 08:40:28 -07:00
|
|
|
};
|
2014-05-14 17:02:01 -07:00
|
|
|
var wf = new WalletFactory(sconfig, '0.0.1');
|
2014-06-03 08:40:28 -07:00
|
|
|
var opts = {
|
|
|
|
'requiredCopayers': 2,
|
|
|
|
'totalCopayers': 3
|
|
|
|
};
|
2014-04-29 13:44:35 -07:00
|
|
|
var w = wf.create(opts);
|
|
|
|
|
2014-04-16 13:50:10 -07:00
|
|
|
});
|
|
|
|
|
2014-06-16 13:37:33 -07:00
|
|
|
it('should be able to get current wallets', function() {
|
|
|
|
var wf = new WalletFactory(config, '0.0.1');
|
2014-06-17 10:02:39 -07:00
|
|
|
var ws = wf.getWallets();
|
|
|
|
|
2014-06-16 13:37:33 -07:00
|
|
|
var w = wf.create({
|
|
|
|
name: 'test wallet'
|
|
|
|
});
|
2014-08-15 06:57:47 -07:00
|
|
|
|
2014-08-06 14:07:01 -07:00
|
|
|
ws = wf.getWallets();
|
2014-06-16 13:37:33 -07:00
|
|
|
ws.length.should.equal(1);
|
|
|
|
ws[0].name.should.equal('test wallet');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should be able to delete wallet', function(done) {
|
|
|
|
var wf = new WalletFactory(config, '0.0.1');
|
|
|
|
var w = wf.create({
|
|
|
|
name: 'test wallet'
|
|
|
|
});
|
|
|
|
var ws = wf.getWallets();
|
|
|
|
ws.length.should.equal(1);
|
|
|
|
wf.delete(ws[0].id, function() {
|
|
|
|
ws = wf.getWallets();
|
|
|
|
ws.length.should.equal(0);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2014-08-04 11:10:01 -07:00
|
|
|
it('should clean lastOpened on delete wallet', function(done) {
|
|
|
|
var wf = new WalletFactory(config, '0.0.1');
|
|
|
|
var w = wf.create({
|
|
|
|
name: 'test wallet'
|
|
|
|
});
|
|
|
|
|
|
|
|
wf.storage.setLastOpened(w.id);
|
|
|
|
wf.delete(w.id, function() {
|
|
|
|
var last = wf.storage.getLastOpened();
|
|
|
|
should.equal(last, undefined);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2014-07-02 12:55:41 -07:00
|
|
|
it('should return false if wallet does not exist', function() {
|
|
|
|
var opts = {
|
|
|
|
'requiredCopayers': 2,
|
|
|
|
'totalCopayers': 3
|
|
|
|
};
|
|
|
|
var wf = new WalletFactory(config, '0.0.1');
|
|
|
|
|
|
|
|
var w = wf.open('dummy', opts);
|
|
|
|
should.exist(w);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should open a wallet', function() {
|
|
|
|
var opts = {
|
|
|
|
'requiredCopayers': 2,
|
|
|
|
'totalCopayers': 3
|
|
|
|
};
|
|
|
|
var wf = new WalletFactory(config, '0.0.1');
|
|
|
|
var w = wf.create(opts);
|
|
|
|
var walletId = w.id;
|
2014-07-08 15:52:47 -07:00
|
|
|
|
2014-07-02 12:55:41 -07:00
|
|
|
wf.read = sinon.stub().withArgs(walletId).returns(w);
|
|
|
|
var wo = wf.open(walletId, opts);
|
|
|
|
should.exist(wo);
|
|
|
|
wf.read.calledWith(walletId).should.be.true;
|
|
|
|
});
|
|
|
|
|
2014-08-04 11:10:01 -07:00
|
|
|
it('should save lastOpened on create/open a wallet', function() {
|
|
|
|
var opts = {
|
|
|
|
'requiredCopayers': 2,
|
|
|
|
'totalCopayers': 3
|
|
|
|
};
|
|
|
|
var wf = new WalletFactory(config, '0.0.1');
|
|
|
|
var w = wf.create(opts);
|
|
|
|
var last = wf.storage.getLastOpened();
|
|
|
|
should.equal(last, w.id);
|
|
|
|
|
|
|
|
wf.storage.setLastOpened('other_id');
|
|
|
|
|
|
|
|
var wo = wf.open(w.id, opts);
|
|
|
|
last = wf.storage.getLastOpened();
|
|
|
|
should.equal(last, w.id);
|
|
|
|
});
|
|
|
|
|
2014-07-02 12:55:41 -07:00
|
|
|
it('should return error if network are differents', function() {
|
|
|
|
var opts = {
|
|
|
|
'requiredCopayers': 2,
|
|
|
|
'totalCopayers': 3
|
|
|
|
};
|
|
|
|
var wf = new WalletFactory(config, '0.0.1');
|
|
|
|
var w = wf.create(opts);
|
2014-07-08 15:52:47 -07:00
|
|
|
(function() {
|
2014-07-02 12:55:41 -07:00
|
|
|
wf._checkNetwork('livenet');
|
|
|
|
}).should.throw();
|
|
|
|
});
|
|
|
|
|
2014-06-19 12:34:05 -07:00
|
|
|
describe('#joinCreateSession', function() {
|
|
|
|
it('should call network.start', function() {
|
|
|
|
var wf = new WalletFactory(config, '0.0.1');
|
|
|
|
wf.network.cleanUp = sinon.spy();
|
|
|
|
wf.network.start = sinon.spy();
|
|
|
|
wf.joinCreateSession('8WtTuiFTkhP5ao7AF2QErSwV39Cbur6pdMebKzQXFqL59RscXM', 'test', null, undefined);
|
|
|
|
wf.network.start.calledOnce.should.equal(true);
|
|
|
|
});
|
|
|
|
it('should call network.start with private key', function() {
|
|
|
|
var wf = new WalletFactory(config, '0.0.1');
|
|
|
|
wf.network.cleanUp = sinon.spy();
|
|
|
|
wf.network.start = sinon.spy();
|
|
|
|
wf.joinCreateSession('8WtTuiFTkhP5ao7AF2QErSwV39Cbur6pdMebKzQXFqL59RscXM', 'test', null, undefined);
|
|
|
|
wf.network.start.getCall(0).args[0].privkey.length.should.equal(64); //privkey is hex of private key buffer
|
|
|
|
});
|
|
|
|
});
|
2014-07-25 06:50:18 -07:00
|
|
|
describe('dont break backwards compatibility of wallets', function() {
|
2014-07-25 07:13:48 -07:00
|
|
|
it('should be able to import unencrypted legacy wallet TxProposal: v0', function() {
|
2014-07-25 06:50:18 -07:00
|
|
|
var wf = new WalletFactory(config, '0.0.5');
|
|
|
|
var w = wf.fromObj(JSON.parse(legacyO));
|
|
|
|
|
|
|
|
should.exist(w);
|
|
|
|
w.id.should.equal('55d4bd062d32f90a');
|
|
|
|
should.exist(w.publicKeyRing.getCopayerId);
|
|
|
|
should.exist(w.txProposals.toObj());
|
|
|
|
should.exist(w.privateKey.toObj());
|
|
|
|
});
|
2014-07-25 07:13:48 -07:00
|
|
|
|
2014-07-25 06:50:18 -07:00
|
|
|
it.skip('should be able to import encrypted legacy wallet', function(done) {
|
|
|
|
var pp = new Passphrase(config.passphrase);
|
|
|
|
var wf = new WalletFactory(config, '0.0.1');
|
|
|
|
// TODO: refactor this code from frontend to core and call a function
|
|
|
|
// see: js/controllers/import.js:~16
|
|
|
|
|
|
|
|
pp.getBase64Async(legacyPassword, function(passphrase) {
|
|
|
|
var w, errMsg;
|
|
|
|
try {
|
|
|
|
w = wf.import(encryptedObj, passphrase);
|
|
|
|
} catch (e) {
|
|
|
|
errMsg = e.message;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!w.isReady()) {
|
|
|
|
throw 'NOT READY';
|
|
|
|
}
|
|
|
|
|
|
|
|
w.updateIndexes(function(err) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
should(w).exist();
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
});
|
2014-06-19 12:34:05 -07:00
|
|
|
|
2014-04-16 13:50:10 -07:00
|
|
|
});
|
2014-07-25 07:13:48 -07:00
|
|
|
|
|
|
|
|
2014-08-19 08:48:29 -07:00
|
|
|
var o = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5"},"networkNonce":"0000000000000001","networkNonces":[],"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"indexes":[{"copayerIndex":2,"changeIndex":0,"receiveIndex":0}],"copayersBackup":[],"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet","privateKeyCache":{}},"addressBook":{}}';
|
|
|
|
var legacyO = '{"opts":{"id":"55d4bd062d32f90a","spendUnconfirmed":true,"requiredCopayers":2,"totalCopayers":2,"name":"xcvzxcv","version":"0.3.2"},"networkNonce":"53d25e8600000009","networkNonces":[],"publicKeyRing":{"walletId":"55d4bd062d32f90a","networkName":"testnet","requiredCopayers":2,"totalCopayers":2,"indexes":[{"copayerIndex":2147483647,"changeIndex":0,"receiveIndex":0},{"copayerIndex":0,"changeIndex":4,"receiveIndex":2},{"copayerIndex":1,"changeIndex":5,"receiveIndex":2}],"copayersBackup":["02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba","02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5"],"copayersExtPubKeys":["tpubD94LTzAUiW99mpA59nyf6fAHh4xKGmnwbgCV4gU2bRpeN9CRiMSurqme22px5NmJAo6FdcdH883Zu98VbqyhesCJ86kUEjH3Zpufy5FfcaC","tpubDA2U9H6LkRHDRbRxHBp4VTbxPc7JqsvtcLxrE5QJF8z1iT6hMJ1pXSVf57GWRcxXutYvpoXRurDVGsscJauMtnJBkYAWBVExYmm91XQE2zz"],"nicknameFor":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":"asdf","02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":"qwerqw"},"publicKeysCache":{"m/0/0/0":["028a4b63f26253f3a8731577b8e1ee480950ad5833ebbf106fe3463bfc07cc3b90","0332efa054c08cb77506a35ee0762cb7156f244566703ec08e433568ec0397bec8"],"m/1/0/0":["0220ad514cf593d0c3905d3bb49bc5767a9410823bf9b77ea5ef2cf1d1016d77a8","02fd42cf66f1dbdc7bbb9ae09aecea72df479ffe5a0c4641301067e331d12e416d"],"m/1/0/1":["0315f7868eaf1f9b7127e3f7e0222c5e473eea003e34700f4758b6873c525d6723","02a2e8ed5e90dd39e3842fc790e06178997dbca319987f365317589e2a71a93658"],"m/0/1/0":["0244a25a0b97b26707fd855c15b046b901be85a3b70a781d0678608e633440eeca","0358cdcbc528ddfb7173b0dab283f702be82546ff031e4a832a7270080cb875959"],"m/0/1/1":["025c9b49bdf17d97bd82ea1b87793082f857247f0f9b999937a166ec994bb1b41f","020389327ee8ae7d0ee3f8187842d23a4070bdd8a27c0bcddd05d80ef39009253d"],"m/1/1/0":["02fd0e7c62b7b58d1ea7bb4cb84d53b019df99d3703a42aed73a2cfa15f3af5d08","0355a15912e76072ef50e6643376b8a9da8422ed4f8ea07b1d84d4989be5a39b2e"],"m/1/1/1":["03bc3e1f4db32efd8eb1fd44a1665938d59628429c67e1e8b7054ab5717f4e6750","03c4c817b633ac31f44f16f390af831d35f7d98744a52a0f23e9598967342255f8"],"m/1/1/2":["02826fe7e9da408480ddeb1d4414c5100b350f862ca718e27122681e1a0ca35077","02bd25af907bb3edbf6b2cd1ea90eaa92cc93ec47bea7d339af44c1d2c05708e99"],"m/0/1/2":["0337a1a70364b94745d6e26d2d28919cf528304f52765f12ef43e3d6da0a6c8dc0","039d83db9aa43e6e00e0304e6971b6079d79dc12d8d55ce2e6fc24a52ba8d41329"],"m/0/0/1":["0359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b8138","037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d93"],"m/1/1/3":["02600e5c41670773a213a4cb58c8f2fa3e83840784bc7f0b56925e1075e06632c2","036d01867af5f61371151ef7d9026fa0400a623f6924e404ee0b856625268972f9"],"m/0/1/3":["03e5a9b039b187ca8e065627df402e4a5b196b94198542da7036879de08be63d2d","0304f3e0b70f696d80e5785dc7747d6dcb55ba24c31f2d80bf184b4e582e6b47fc"],"m/1/1/4":["03741afa5bd50d6ba5801064c810fae84f6a4557d6a88ddc8591d0d4eb68a8fc41","0214dd6ce6073b05999fb887098ca6f7e1d0b4fdc0760557786907df353df90d1c"],"m/2147483647/1/0":["033e072a53ea835763a03c66e35c35384736210a1bb7d7ee6d9a3e109e82426b30","02e37b5570c053da8a8ee587be86fc629775c4db890aba2745ccc4e4dcc8c31041"],"m/2147483647/1/1":["0228a6de42ef421c263d1efd9f28d9a7d15a261995028a24eff6b9f1c3fc46e6bf","0226cff885cb0d607cc9cf69a7608316eb3fb2ec344c0c9956246ba776116fc396"],"m/2147483647/1/2":["034fe2a8f0b98445eb5810fe36572ad2f64ed9bf64dc9de624f99c0142cb07c682","02f2c5c758e32293f5c193fd69afadbba83abafb397db01e6f2b447690e900475a"],"m/2147483647/1/3":["02b25ef9434446c51f10678f787e4913de582e34d164bd3b06af7732c5476df1a8","025d51a1efd59bcff22ee2e0af61b21a7ba5f639e20dfdf25690e926005177dd0c"],"m/2147483647/1/4":["03e5734e1d29b2f684d0446b7a2ffbd0ba8952570a502d0d14b1efd8f24b61be53","0258fc28a324848d8d0154e8614815e35c668d274a8f01957bb99aab8dc8f386c0"],"m/2147483647/1/5":["021f9e775246765e1cfba0ae453b4eae6cd4ae5a57a09c319edbe89d4dbbf23be3","02857f66571a1c3eb9e72d22ae88e734c03d448bced4dcfd345c2059468124c741"],"m/2147483647/1/6":["02c072f329391a25255dc6452e5f5220966869dbf736ba8a8c3ae9d273a84bc3fd","030920a8b8e88c4db
|