From 1ce3f82d0a88ab262fb8eaf8b9206a06ae8b0095 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 1 Sep 2014 15:13:23 -0300 Subject: [PATCH 01/45] add angular-load --- Gruntfile.js | 1 + config.js | 9 +++++++++ js/app.js | 13 ++++++++++++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index 8844d8e30..e4d0a51ef 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -115,6 +115,7 @@ module.exports = function(grunt) { 'lib/angular-foundation/mm-foundation.min.js', 'lib/angular-foundation/mm-foundation-tpls.min.js', 'lib/angular-gettext/dist/angular-gettext.min.js' + 'lib/angular-load/angular-load.min.js', ], dest: 'lib/angularjs-all.js' }, diff --git a/config.js b/config.js index a22baad87..fe4031e42 100644 --- a/config.js +++ b/config.js @@ -50,6 +50,15 @@ var defaultConfig = { updateFrequencySeconds: 60 * 60 }, + verbose: 1, + + plugins: { + googleDrive: true, + }, + + googleDrive: { + clientId: '1', + }, }; if (typeof module !== 'undefined') module.exports = defaultConfig; diff --git a/js/app.js b/js/app.js index 177755b2a..a5c169307 100644 --- a/js/app.js +++ b/js/app.js @@ -18,7 +18,13 @@ if (localConfig) { } } +var log = function() { + if (config.verbose) console.log(arguments); +} var copayApp = window.copayApp = angular.module('copayApp', [ + + +var modules = [ 'ngRoute', 'angularMoment', 'mm.foundation', @@ -29,7 +35,12 @@ var copayApp = window.copayApp = angular.module('copayApp', [ 'copayApp.services', 'copayApp.controllers', 'copayApp.directives', -]); +]; + +if (config.plugins.googleDrive) + modules.push('angularLoad'); + +var copayApp = window.copayApp = angular.module('copayApp', modules); copayApp.config(function($sceDelegateProvider) { $sceDelegateProvider.resourceUrlWhitelist([ From 2849f773e2df1c098b2de36355bf36e7220ef60a Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 1 Sep 2014 15:40:31 -0300 Subject: [PATCH 02/45] change name to Encrypted --- Gruntfile.js | 5 +- bower.json | 3 +- copay.js | 2 +- js/app.js | 10 +++- js/models/core/WalletFactory.js | 4 +- .../{LocalEncrypted.js => Encrypted.js} | 27 +++++---- ...st.LocalEncrypted.js => test.Encrypted.js} | 60 +++++++++---------- util/build.js | 4 ++ 8 files changed, 66 insertions(+), 49 deletions(-) rename js/models/storage/{LocalEncrypted.js => Encrypted.js} (89%) rename test/{test.LocalEncrypted.js => test.Encrypted.js} (84%) diff --git a/Gruntfile.js b/Gruntfile.js index e4d0a51ef..fc4b77dee 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -42,7 +42,8 @@ module.exports = function(grunt) { }, scripts: { files: [ - 'js/models/**/*.js' + 'js/models/**/*.js', + 'plugins/*.js', ], tasks: ['shell:dev'] }, @@ -129,7 +130,7 @@ module.exports = function(grunt) { 'js/controllers/*.js', 'js/translations.js', 'js/mobile.js', // PLACEHOLDER: CORDOVA SRIPT - 'js/init.js' + 'js/init.js', ], dest: 'js/copayMain.js' } diff --git a/bower.json b/bower.json index 9300e2b27..cccd15f07 100644 --- a/bower.json +++ b/bower.json @@ -24,7 +24,8 @@ "zeroclipboard": "~1.3.5", "ng-idle": "*", "underscore": "~1.7.0", - "inherits": "~0.0.1" + "inherits": "~0.0.1", + "angular-load": "0.2.0" }, "resolutions": { "angular": "=1.2.19" diff --git a/copay.js b/copay.js index 5f058d6ab..e821f7918 100644 --- a/copay.js +++ b/copay.js @@ -11,7 +11,7 @@ module.exports.HDParams = require('./js/models/core/HDParams'); // components var Async = module.exports.Async = require('./js/models/network/Async'); var Insight = module.exports.Insight = require('./js/models/blockchain/Insight'); -var StorageLocalEncrypted = module.exports.StorageLocalEncrypted = require('./js/models/storage/LocalEncrypted'); +var StorageEncrypted = module.exports.StorageEncrypted = require('./js/models/storage/Encrypted'); module.exports.WalletFactory = require('./js/models/core/WalletFactory'); module.exports.Wallet = require('./js/models/core/Wallet'); diff --git a/js/app.js b/js/app.js index a5c169307..e7b038516 100644 --- a/js/app.js +++ b/js/app.js @@ -37,9 +37,17 @@ var modules = [ 'copayApp.directives', ]; -if (config.plugins.googleDrive) +if (config.plugins.length) modules.push('angularLoad'); +if (config.plugins.googleDrive) { + var googleDrive = require('../plugins/googleDrive'); + var a = new googleDrive(); + a.init(); +console.log('[app.js.41:new:]',a); //TODO +} + + var copayApp = window.copayApp = angular.module('copayApp', modules); copayApp.config(function($sceDelegateProvider) { diff --git a/js/models/core/WalletFactory.js b/js/models/core/WalletFactory.js index b91853657..adf542ae1 100644 --- a/js/models/core/WalletFactory.js +++ b/js/models/core/WalletFactory.js @@ -8,7 +8,7 @@ var _ = require('underscore'); var log = require('../../log'); var Async = module.exports.Async = require('../network/Async'); var Insight = module.exports.Insight = require('../blockchain/Insight'); -var StorageLocalEncrypted = module.exports.StorageLocalEncrypted = require('../storage/LocalEncrypted'); +var StorageEncrypted = module.exports.StorageEncrypted = require('../storage/Encrypted'); var preconditions = require('preconditions').singleton(); /** @@ -36,7 +36,7 @@ function WalletFactory(config, version) { var self = this; config = config || {}; - this.Storage = config.Storage || StorageLocalEncrypted; + this.Storage = config.Storage || StorageEncrypted; this.Network = config.Network || Async; this.Blockchain = config.Blockchain || Insight; diff --git a/js/models/storage/LocalEncrypted.js b/js/models/storage/Encrypted.js similarity index 89% rename from js/models/storage/LocalEncrypted.js rename to js/models/storage/Encrypted.js index b093eaaa4..1997f7841 100644 --- a/js/models/storage/LocalEncrypted.js +++ b/js/models/storage/Encrypted.js @@ -13,9 +13,12 @@ function Storage(opts) { this._setPassphrase(opts.password); try { - this.localStorage = opts.localStorage || localStorage; + this.storage = opts.storage || localStorage; this.sessionStorage = opts.sessionStorage || sessionStorage; - } catch (e) {} + } catch (e) { + console.log('Error in storage:', e); //TODO + }; + preconditions.checkState(this.localStorage, 'No localstorage found'); preconditions.checkState(this.sessionStorage, 'No sessionStorage found'); } @@ -54,7 +57,7 @@ Storage.prototype._decrypt = function(base64) { Storage.prototype._read = function(k) { var ret; - ret = this.localStorage.getItem(k); + ret = this.storage.getItem(k); if (!ret) return null; ret = this._decrypt(ret); if (!ret) return null; @@ -67,23 +70,23 @@ Storage.prototype._write = function(k, v) { v = JSON.stringify(v); v = this._encrypt(v); - this.localStorage.setItem(k, v); + this.storage.setItem(k, v); }; // get value by key Storage.prototype.getGlobal = function(k) { - var item = this.localStorage.getItem(k); + var item = this.storage.getItem(k); return item == 'undefined' ? undefined : item; }; // set value for key Storage.prototype.setGlobal = function(k, v) { - this.localStorage.setItem(k, typeof v === 'object' ? JSON.stringify(v) : v); + this.storage.setItem(k, typeof v === 'object' ? JSON.stringify(v) : v); }; // remove value for key Storage.prototype.removeGlobal = function(k) { - this.localStorage.removeItem(k); + this.storage.removeItem(k); }; Storage.prototype.getSessionId = function() { @@ -127,8 +130,8 @@ Storage.prototype.getWalletIds = function() { var walletIds = []; var uniq = {}; - for (var i = 0; i < this.localStorage.length; i++) { - var key = this.localStorage.key(i); + for (var i = 0; i < this.storage.length; i++) { + var key = this.storage.key(i); var split = key.split('::'); if (split.length == 2) { var walletId = split[0]; @@ -162,8 +165,8 @@ Storage.prototype.deleteWallet = function(walletId) { var toDelete = {}; toDelete['nameFor::' + walletId] = 1; - for (var i = 0; i < this.localStorage.length; i++) { - var key = this.localStorage.key(i); + for (var i = 0; i < this.storage.length; i++) { + var key = this.storage.key(i); var split = key.split('::'); if (split.length == 2 && split[0] === walletId) { toDelete[key] = 1; @@ -192,7 +195,7 @@ Storage.prototype.setFromObj = function(walletId, obj) { // remove all values Storage.prototype.clearAll = function() { - this.localStorage.clear(); + this.storage.clear(); }; Storage.prototype.import = function(base64) { diff --git a/test/test.LocalEncrypted.js b/test/test.Encrypted.js similarity index 84% rename from test/test.LocalEncrypted.js rename to test/test.Encrypted.js index 32149e58f..bfe2fcd18 100644 --- a/test/test.LocalEncrypted.js +++ b/test/test.Encrypted.js @@ -3,7 +3,7 @@ var chai = chai || require('chai'); var should = chai.should(); var is_browser = typeof process == 'undefined' || typeof process.versions === 'undefined'; var copay = copay || require('../copay'); -var LocalEncrypted = copay.StorageLocalEncrypted; +var Encrypted = copay.StorageEncrypted; var fakeWallet = 'fake-wallet-id'; var timeStamp = Date.now(); @@ -11,23 +11,23 @@ var localMock = require('./mocks/FakeLocalStorage'); var sessionMock = require('./mocks/FakeLocalStorage'); -describe('Storage/LocalEncrypted model', function() { - var s = new LocalEncrypted({ - localStorage: localMock, +describe('Storage/Encrypted model', function() { + var s = new Encrypted({ + storage: localMock, sessionStorage: sessionMock, }); s._setPassphrase('mysupercoolpassword'); it('should create an instance', function() { - var s2 = new LocalEncrypted({ - localStorage: localMock, + var s2 = new Encrypted({ + storage: localMock, sessionStorage: sessionMock, }); should.exist(s2); }); it('should fail when encrypting without a password', function() { - var s2 = new LocalEncrypted({ - localStorage: localMock, + var s2 = new Encrypted({ + storage: localMock, sessionStorage: sessionMock, }); (function() { @@ -71,8 +71,8 @@ describe('Storage/LocalEncrypted model', function() { describe('#export', function() { it('should export the encrypted wallet', function() { - var storage = new LocalEncrypted({ - localStorage: localMock, + var storage = new Encrypted({ + storage: localMock, sessionStorage: sessionMock, password: 'password', }); @@ -89,8 +89,8 @@ describe('Storage/LocalEncrypted model', function() { describe('#remove', function() { it('should remove an item', function() { - var s = new LocalEncrypted({ - localStorage: localMock, + var s = new Encrypted({ + storage: localMock, sessionStorage: sessionMock, password: 'password' }); @@ -105,8 +105,8 @@ describe('Storage/LocalEncrypted model', function() { describe('#getWalletIds', function() { it('should get wallet ids', function() { - var s = new LocalEncrypted({ - localStorage: localMock, + var s = new Encrypted({ + storage: localMock, sessionStorage: sessionMock, password: 'password' }); @@ -118,8 +118,8 @@ describe('Storage/LocalEncrypted model', function() { describe('#getName #setName', function() { it('should get/set names', function() { - var s = new LocalEncrypted({ - localStorage: localMock, + var s = new Encrypted({ + storage: localMock, sessionStorage: sessionMock, password: 'password' }); @@ -130,8 +130,8 @@ describe('Storage/LocalEncrypted model', function() { describe('#getLastOpened #setLastOpened', function() { it('should get/set names', function() { - var s = new LocalEncrypted({ - localStorage: localMock, + var s = new Encrypted({ + storage: localMock, sessionStorage: sessionMock, password: 'password' }); @@ -143,8 +143,8 @@ describe('Storage/LocalEncrypted model', function() { if (is_browser) { describe('#getSessionId', function() { it('should get SessionId', function() { - var s = new LocalEncrypted({ - localStorage: localMock, + var s = new Encrypted({ + storage: localMock, sessionStorage: sessionMock, password: 'password' }); @@ -158,8 +158,8 @@ describe('Storage/LocalEncrypted model', function() { describe('#getWallets', function() { it('should retreive wallets from storage', function() { - var s = new LocalEncrypted({ - localStorage: localMock, + var s = new Encrypted({ + storage: localMock, sessionStorage: sessionMock, password: 'password' }); @@ -178,8 +178,8 @@ describe('Storage/LocalEncrypted model', function() { }); describe('#deleteWallet', function() { it('should delete a wallet', function() { - var s = new LocalEncrypted({ - localStorage: localMock, + var s = new Encrypted({ + storage: localMock, sessionStorage: sessionMock, password: 'password' }); @@ -198,8 +198,8 @@ describe('Storage/LocalEncrypted model', function() { describe('#setFromObj', function() { it('set localstorage from an object', function() { - var s = new LocalEncrypted({ - localStorage: localMock, + var s = new Encrypted({ + storage: localMock, sessionStorage: sessionMock, password: 'password' }); @@ -218,8 +218,8 @@ describe('Storage/LocalEncrypted model', function() { describe('#globals', function() { it('should set, get and remove keys', function() { - var s = new LocalEncrypted({ - localStorage: localMock, + var s = new Encrypted({ + storage: localMock, sessionStorage: sessionMock, password: 'password' }); @@ -237,8 +237,8 @@ describe('Storage/LocalEncrypted model', function() { describe('session storage', function() { it('should get a session ID', function() { - var s = new LocalEncrypted({ - localStorage: localMock, + var s = new Encrypted({ + storage: localMock, sessionStorage: sessionMock, password: 'password' }); diff --git a/util/build.js b/util/build.js index b60af799b..21e2afda8 100644 --- a/util/build.js +++ b/util/build.js @@ -83,6 +83,10 @@ var createBundle = function(opts) { b.require('./js/models/core/HDPath', { expose: '../js/models/core/HDPath' }); + b.require('./plugins/googleDrive', { + expose: '../plugins/googleDrive' + }); + b.require('./config', { expose: '../config' }); From c0360e7beb7915580f27c9bb761fe2464c92140f Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 1 Sep 2014 16:31:35 -0300 Subject: [PATCH 03/45] plugin system v0 --- Gruntfile.js | 1 + config.js | 4 +-- copay.js | 1 + js/app.js | 6 ----- js/controllers/home.js | 2 +- js/models/core/PluginManager.js | 46 +++++++++++++++++++++++++++++++++ js/services/pluginManager.js | 3 +++ plugins/googleDrive.js | 11 ++++++++ util/build.js | 10 +++++-- 9 files changed, 73 insertions(+), 11 deletions(-) create mode 100644 js/models/core/PluginManager.js create mode 100644 js/services/pluginManager.js create mode 100644 plugins/googleDrive.js diff --git a/Gruntfile.js b/Gruntfile.js index fc4b77dee..04078ba62 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -44,6 +44,7 @@ module.exports = function(grunt) { files: [ 'js/models/**/*.js', 'plugins/*.js', + 'copay.js' ], tasks: ['shell:dev'] }, diff --git a/config.js b/config.js index fe4031e42..6b7e5f30f 100644 --- a/config.js +++ b/config.js @@ -53,10 +53,10 @@ var defaultConfig = { verbose: 1, plugins: { - googleDrive: true, + GoogleDrive: true, }, - googleDrive: { + GoogleDrive: { clientId: '1', }, }; diff --git a/copay.js b/copay.js index e821f7918..2f0107816 100644 --- a/copay.js +++ b/copay.js @@ -16,6 +16,7 @@ var StorageEncrypted = module.exports.StorageEncrypted = require('./js/models/st module.exports.WalletFactory = require('./js/models/core/WalletFactory'); module.exports.Wallet = require('./js/models/core/Wallet'); module.exports.WalletLock = require('./js/models/core/WalletLock'); +module.exports.PluginManager = require('./js/models/core/PluginManager'); module.exports.version = require('./version').version; module.exports.commitHash = require('./version').commitHash; diff --git a/js/app.js b/js/app.js index e7b038516..e1a3826ee 100644 --- a/js/app.js +++ b/js/app.js @@ -40,12 +40,6 @@ var modules = [ if (config.plugins.length) modules.push('angularLoad'); -if (config.plugins.googleDrive) { - var googleDrive = require('../plugins/googleDrive'); - var a = new googleDrive(); - a.init(); -console.log('[app.js.41:new:]',a); //TODO -} var copayApp = window.copayApp = angular.module('copayApp', modules); diff --git a/js/controllers/home.js b/js/controllers/home.js index 2ac3e7381..a8d367d44 100644 --- a/js/controllers/home.js +++ b/js/controllers/home.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('copayApp.controllers').controller('HomeController', - function($scope, $rootScope, $location, walletFactory, notification, controllerUtils) { + function($scope, $rootScope, $location, walletFactory, notification, controllerUtils, pluginManager) { controllerUtils.redirIfLogged(); diff --git a/js/models/core/PluginManager.js b/js/models/core/PluginManager.js new file mode 100644 index 000000000..995470481 --- /dev/null +++ b/js/models/core/PluginManager.js @@ -0,0 +1,46 @@ +'use strict'; +var preconditions = require('preconditions').singleton(); + +function PluginManager(config) { + this.registered = {}; + + for(var ii in config.plugins){ + var pluginName = ii; + + if (!config.plugins[pluginName]) + continue; + + console.log('Loading ' + pluginName); + var pluginClass = require('../plugins/' + pluginName); + var pluginObj = new pluginClass(); + pluginObj.init(); + this._register(pluginObj); + } +}; + +var KIND_UNIQUE = PluginManager.KIND_UNIQUE = 1; +var KIND_MULTIPLE = PluginManager.KIND_MULTIPLE = 2; + +PluginManager.TYPE = {}; +PluginManager.TYPE['STORAGE'] = KIND_UNIQUE; + +PluginManager.prototype._register = function(obj) { + preconditions.checkArgument(obj.type,'Plugin has not type'); + var type = obj.type; +console.log('[PluginManager.js.29:type:]',type); //TODO + + var kind = PluginManager.TYPE[type]; + preconditions.checkArgument(kind, 'Plugin has unkown type'); + preconditions.checkState(kind !== PluginManager.KIND_UNIQUE || !this.registered[type], 'Plugin kind already registered'); + + if (kind === PluginManager.KIND_UNIQUE) { + this.registered[type] = obj; + } else { + this.registered[type] = this.registered[type] || []; + this.registered[type].push(obj); + } +}; + +PluginManager.prototype.getOne = function(type) {}; + +module.exports = PluginManager; diff --git a/js/services/pluginManager.js b/js/services/pluginManager.js new file mode 100644 index 000000000..b3371c0cd --- /dev/null +++ b/js/services/pluginManager.js @@ -0,0 +1,3 @@ +'use strict'; + +angular.module('copayApp.services').value('pluginManager', new copay.PluginManager(config)); diff --git a/plugins/googleDrive.js b/plugins/googleDrive.js new file mode 100644 index 000000000..6be0c2c55 --- /dev/null +++ b/plugins/googleDrive.js @@ -0,0 +1,11 @@ +'use strict'; + +function GoogleDrive() { + this.type = 'STORAGE'; +}; + +GoogleDrive.prototype.init = function() { + console.log('[googleDrive.js.3] init'); //TODO +}; + +module.exports = GoogleDrive; diff --git a/util/build.js b/util/build.js index 21e2afda8..b9160cc7f 100644 --- a/util/build.js +++ b/util/build.js @@ -83,9 +83,15 @@ var createBundle = function(opts) { b.require('./js/models/core/HDPath', { expose: '../js/models/core/HDPath' }); - b.require('./plugins/googleDrive', { - expose: '../plugins/googleDrive' + b.require('./js/models/core/PluginManager', { + expose: '../js/models/core/PluginManager' }); + + if (!opts.disablePlugins) { + b.require('./plugins/GoogleDrive', { + expose: '../plugins/GoogleDrive' + }); + } b.require('./config', { expose: '../config' From b9881c114767f8c4e9f8c9e4ed0c7e2451232ff6 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 1 Sep 2014 23:44:35 -0300 Subject: [PATCH 04/45] add LocalStorage plugin --- Gruntfile.js | 3 ++- config.js | 3 ++- js/controllers/home.js | 2 +- js/models/core/PluginManager.js | 18 +++++++------- js/models/core/WalletFactory.js | 6 +++-- js/models/storage/Encrypted.js | 2 ++ js/services/pluginManager.js | 4 +++- plugins/LocalStorage.js | 42 +++++++++++++++++++++++++++++++++ plugins/googleDrive.js | 33 +++++++++++++++++++++++++- util/build.js | 4 ++++ 10 files changed, 101 insertions(+), 16 deletions(-) create mode 100644 plugins/LocalStorage.js diff --git a/Gruntfile.js b/Gruntfile.js index 04078ba62..099cd23bd 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -44,7 +44,8 @@ module.exports = function(grunt) { files: [ 'js/models/**/*.js', 'plugins/*.js', - 'copay.js' + 'copay.js', + 'utils/*.js' ], tasks: ['shell:dev'] }, diff --git a/config.js b/config.js index 6b7e5f30f..10b5dafe7 100644 --- a/config.js +++ b/config.js @@ -53,7 +53,8 @@ var defaultConfig = { verbose: 1, plugins: { - GoogleDrive: true, + LocalStorage: true, + // GoogleDrive: true, }, GoogleDrive: { diff --git a/js/controllers/home.js b/js/controllers/home.js index a8d367d44..2ac3e7381 100644 --- a/js/controllers/home.js +++ b/js/controllers/home.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('copayApp.controllers').controller('HomeController', - function($scope, $rootScope, $location, walletFactory, notification, controllerUtils, pluginManager) { + function($scope, $rootScope, $location, walletFactory, notification, controllerUtils) { controllerUtils.redirIfLogged(); diff --git a/js/models/core/PluginManager.js b/js/models/core/PluginManager.js index 995470481..23b3c2a77 100644 --- a/js/models/core/PluginManager.js +++ b/js/models/core/PluginManager.js @@ -10,11 +10,11 @@ function PluginManager(config) { if (!config.plugins[pluginName]) continue; - console.log('Loading ' + pluginName); + console.log('Loading plugin: ' + pluginName); var pluginClass = require('../plugins/' + pluginName); var pluginObj = new pluginClass(); pluginObj.init(); - this._register(pluginObj); + this._register(pluginObj, pluginName); } }; @@ -24,14 +24,12 @@ var KIND_MULTIPLE = PluginManager.KIND_MULTIPLE = 2; PluginManager.TYPE = {}; PluginManager.TYPE['STORAGE'] = KIND_UNIQUE; -PluginManager.prototype._register = function(obj) { - preconditions.checkArgument(obj.type,'Plugin has not type'); +PluginManager.prototype._register = function(obj, name) { + preconditions.checkArgument(obj.type,'Plugin has not type:' + name); var type = obj.type; -console.log('[PluginManager.js.29:type:]',type); //TODO - var kind = PluginManager.TYPE[type]; - preconditions.checkArgument(kind, 'Plugin has unkown type'); - preconditions.checkState(kind !== PluginManager.KIND_UNIQUE || !this.registered[type], 'Plugin kind already registered'); + preconditions.checkArgument(kind, 'Plugin has unkown type' + name); + preconditions.checkState(kind !== PluginManager.KIND_UNIQUE || !this.registered[type], 'Plugin kind already registered: ' + name); if (kind === PluginManager.KIND_UNIQUE) { this.registered[type] = obj; @@ -41,6 +39,8 @@ console.log('[PluginManager.js.29:type:]',type); //TODO } }; -PluginManager.prototype.getOne = function(type) {}; +PluginManager.prototype.get = function(type) { + return this.registered[type]; +}; module.exports = PluginManager; diff --git a/js/models/core/WalletFactory.js b/js/models/core/WalletFactory.js index adf542ae1..ef88b6a52 100644 --- a/js/models/core/WalletFactory.js +++ b/js/models/core/WalletFactory.js @@ -36,11 +36,13 @@ function WalletFactory(config, version) { var self = this; config = config || {}; - this.Storage = config.Storage || StorageEncrypted; + this.pluginManager = new copay.PluginManager(config); + + this.Storage = config.Storage || StorageEncrypted; this.Network = config.Network || Async; this.Blockchain = config.Blockchain || Insight; + this.storage = new this.Storage({storage: this.pluginManager.get('STORAGE')}); - this.storage = new this.Storage(config.storage); this.networks = { 'livenet': new this.Network(config.network.livenet), 'testnet': new this.Network(config.network.testnet), diff --git a/js/models/storage/Encrypted.js b/js/models/storage/Encrypted.js index 1997f7841..6a0c378e7 100644 --- a/js/models/storage/Encrypted.js +++ b/js/models/storage/Encrypted.js @@ -130,6 +130,8 @@ Storage.prototype.getWalletIds = function() { var walletIds = []; var uniq = {}; +console.log('[Encrypted.js.144]', this.storage); //TODO +console.log('[Encrypted.js.144]', this.storage.length); //TODO for (var i = 0; i < this.storage.length; i++) { var key = this.storage.key(i); var split = key.split('::'); diff --git a/js/services/pluginManager.js b/js/services/pluginManager.js index b3371c0cd..c67b16846 100644 --- a/js/services/pluginManager.js +++ b/js/services/pluginManager.js @@ -1,3 +1,5 @@ 'use strict'; -angular.module('copayApp.services').value('pluginManager', new copay.PluginManager(config)); +angular.module('copayApp.services').factory('pluginManager', function(angularLoad){ + return new copay.PluginManager(config); +}); diff --git a/plugins/LocalStorage.js b/plugins/LocalStorage.js new file mode 100644 index 000000000..3f050f64f --- /dev/null +++ b/plugins/LocalStorage.js @@ -0,0 +1,42 @@ +'use strict'; + +function LocalStorage() { + this.type = 'STORAGE'; +}; + +LocalStorage.prototype.init = function() { + console.log(' init LocalStorage'); //TODO +}; + + +LocalStorage.prototype.getItem = function(k) { + return localStorage.getItem(k); +}; + +LocalStorage.prototype.setItem = function(k,v) { + localStorage.setItem(k,v); +}; + +LocalStorage.prototype.removeItem = function(k) { + localStorage.removeItem(k); +}; + +LocalStorage.prototype.clear = function() { + localStorage.clear(); +}; + +delete LocalStorage.prototype.length; + +Object.defineProperty(LocalStorage.prototype, 'length', { + get: function() { + return localStorage.length; + } +}); + +LocalStorage.prototype.key = function(k) { + var v = localStorage.key(k); + return v; +}; + + +module.exports = LocalStorage; diff --git a/plugins/googleDrive.js b/plugins/googleDrive.js index 6be0c2c55..7d7544b79 100644 --- a/plugins/googleDrive.js +++ b/plugins/googleDrive.js @@ -5,7 +5,38 @@ function GoogleDrive() { }; GoogleDrive.prototype.init = function() { - console.log('[googleDrive.js.3] init'); //TODO + console.log('[googleDrive.js.3] init GoogleDrive'); //TODO }; + +GoogleDrive.prototype.getItem = function(k) { + return localStorage.getItem(k); +}; + +GoogleDrive.prototype.setItem = function(k,v) { + localStorage.setItem(k,v); +}; + +GoogleDrive.prototype.removeItem = function(k) { + localStorage.removeItem(k); +}; + +GoogleDrive.prototype.clear = function() { + localStorage.clear(); +}; + +delete GoogleDrive.prototype.length; + +Object.defineProperty(GoogleDrive.prototype, 'length', { + get: function() { + return localStorage.length; + } +}); + +GoogleDrive.prototype.key = function(k) { + var v = localStorage.key(k); + return v; +}; + + module.exports = GoogleDrive; diff --git a/util/build.js b/util/build.js index b9160cc7f..080c1e47e 100644 --- a/util/build.js +++ b/util/build.js @@ -91,6 +91,10 @@ var createBundle = function(opts) { b.require('./plugins/GoogleDrive', { expose: '../plugins/GoogleDrive' }); + b.require('./plugins/LocalStorage', { + expose: '../plugins/LocalStorage' + }); + } b.require('./config', { From bbd762a1fe3fd582b7a620b4f792b1de162a5aee Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 1 Sep 2014 23:49:13 -0300 Subject: [PATCH 05/45] rm encrypted to storage --- copay.js | 2 +- .../{storage/Encrypted.js => Storage.js} | 0 js/models/core/WalletFactory.js | 7 ++-- test/{test.Encrypted.js => test.Storage.js} | 32 +++++++++---------- util/build.js | 1 - 5 files changed, 21 insertions(+), 21 deletions(-) rename js/models/{storage/Encrypted.js => Storage.js} (100%) rename test/{test.Encrypted.js => test.Storage.js} (92%) diff --git a/copay.js b/copay.js index 2f0107816..6bba1b613 100644 --- a/copay.js +++ b/copay.js @@ -11,7 +11,7 @@ module.exports.HDParams = require('./js/models/core/HDParams'); // components var Async = module.exports.Async = require('./js/models/network/Async'); var Insight = module.exports.Insight = require('./js/models/blockchain/Insight'); -var StorageEncrypted = module.exports.StorageEncrypted = require('./js/models/storage/Encrypted'); +var Storage = module.exports.Storage = require('./js/models/Storage'); module.exports.WalletFactory = require('./js/models/core/WalletFactory'); module.exports.Wallet = require('./js/models/core/Wallet'); diff --git a/js/models/storage/Encrypted.js b/js/models/Storage.js similarity index 100% rename from js/models/storage/Encrypted.js rename to js/models/Storage.js diff --git a/js/models/core/WalletFactory.js b/js/models/core/WalletFactory.js index ef88b6a52..2efea81de 100644 --- a/js/models/core/WalletFactory.js +++ b/js/models/core/WalletFactory.js @@ -6,10 +6,11 @@ var PrivateKey = require('./PrivateKey'); var Wallet = require('./Wallet'); var _ = require('underscore'); var log = require('../../log'); +var PluginManager = require('./PluginManager'); var Async = module.exports.Async = require('../network/Async'); var Insight = module.exports.Insight = require('../blockchain/Insight'); -var StorageEncrypted = module.exports.StorageEncrypted = require('../storage/Encrypted'); var preconditions = require('preconditions').singleton(); +var Storage = module.exports.Storage = require('../Storage'); /** * @desc @@ -36,9 +37,9 @@ function WalletFactory(config, version) { var self = this; config = config || {}; - this.pluginManager = new copay.PluginManager(config); + this.pluginManager = new PluginManager(config); - this.Storage = config.Storage || StorageEncrypted; + this.Storage = config.Storage || Storage; this.Network = config.Network || Async; this.Blockchain = config.Blockchain || Insight; this.storage = new this.Storage({storage: this.pluginManager.get('STORAGE')}); diff --git a/test/test.Encrypted.js b/test/test.Storage.js similarity index 92% rename from test/test.Encrypted.js rename to test/test.Storage.js index bfe2fcd18..0ad668bff 100644 --- a/test/test.Encrypted.js +++ b/test/test.Storage.js @@ -3,7 +3,7 @@ var chai = chai || require('chai'); var should = chai.should(); var is_browser = typeof process == 'undefined' || typeof process.versions === 'undefined'; var copay = copay || require('../copay'); -var Encrypted = copay.StorageEncrypted; +var Storage = copay.Storage; var fakeWallet = 'fake-wallet-id'; var timeStamp = Date.now(); @@ -11,22 +11,22 @@ var localMock = require('./mocks/FakeLocalStorage'); var sessionMock = require('./mocks/FakeLocalStorage'); -describe('Storage/Encrypted model', function() { - var s = new Encrypted({ +describe('Storage model', function() { + var s = new Storage({ storage: localMock, sessionStorage: sessionMock, }); s._setPassphrase('mysupercoolpassword'); it('should create an instance', function() { - var s2 = new Encrypted({ + var s2 = new Storage({ storage: localMock, sessionStorage: sessionMock, }); should.exist(s2); }); it('should fail when encrypting without a password', function() { - var s2 = new Encrypted({ + var s2 = new Storage({ storage: localMock, sessionStorage: sessionMock, }); @@ -71,7 +71,7 @@ describe('Storage/Encrypted model', function() { describe('#export', function() { it('should export the encrypted wallet', function() { - var storage = new Encrypted({ + var storage = new Storage({ storage: localMock, sessionStorage: sessionMock, password: 'password', @@ -89,7 +89,7 @@ describe('Storage/Encrypted model', function() { describe('#remove', function() { it('should remove an item', function() { - var s = new Encrypted({ + var s = new Storage({ storage: localMock, sessionStorage: sessionMock, password: 'password' @@ -105,7 +105,7 @@ describe('Storage/Encrypted model', function() { describe('#getWalletIds', function() { it('should get wallet ids', function() { - var s = new Encrypted({ + var s = new Storage({ storage: localMock, sessionStorage: sessionMock, password: 'password' @@ -118,7 +118,7 @@ describe('Storage/Encrypted model', function() { describe('#getName #setName', function() { it('should get/set names', function() { - var s = new Encrypted({ + var s = new Storage({ storage: localMock, sessionStorage: sessionMock, password: 'password' @@ -130,7 +130,7 @@ describe('Storage/Encrypted model', function() { describe('#getLastOpened #setLastOpened', function() { it('should get/set names', function() { - var s = new Encrypted({ + var s = new Storage({ storage: localMock, sessionStorage: sessionMock, password: 'password' @@ -143,7 +143,7 @@ describe('Storage/Encrypted model', function() { if (is_browser) { describe('#getSessionId', function() { it('should get SessionId', function() { - var s = new Encrypted({ + var s = new Storage({ storage: localMock, sessionStorage: sessionMock, password: 'password' @@ -158,7 +158,7 @@ describe('Storage/Encrypted model', function() { describe('#getWallets', function() { it('should retreive wallets from storage', function() { - var s = new Encrypted({ + var s = new Storage({ storage: localMock, sessionStorage: sessionMock, password: 'password' @@ -178,7 +178,7 @@ describe('Storage/Encrypted model', function() { }); describe('#deleteWallet', function() { it('should delete a wallet', function() { - var s = new Encrypted({ + var s = new Storage({ storage: localMock, sessionStorage: sessionMock, password: 'password' @@ -198,7 +198,7 @@ describe('Storage/Encrypted model', function() { describe('#setFromObj', function() { it('set localstorage from an object', function() { - var s = new Encrypted({ + var s = new Storage({ storage: localMock, sessionStorage: sessionMock, password: 'password' @@ -218,7 +218,7 @@ describe('Storage/Encrypted model', function() { describe('#globals', function() { it('should set, get and remove keys', function() { - var s = new Encrypted({ + var s = new Storage({ storage: localMock, sessionStorage: sessionMock, password: 'password' @@ -237,7 +237,7 @@ describe('Storage/Encrypted model', function() { describe('session storage', function() { it('should get a session ID', function() { - var s = new Encrypted({ + var s = new Storage({ storage: localMock, sessionStorage: sessionMock, password: 'password' diff --git a/util/build.js b/util/build.js index 080c1e47e..2c078f458 100644 --- a/util/build.js +++ b/util/build.js @@ -94,7 +94,6 @@ var createBundle = function(opts) { b.require('./plugins/LocalStorage', { expose: '../plugins/LocalStorage' }); - } b.require('./config', { From 6efa4f86de7f14482fdcec586a1178439162c71d Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 3 Sep 2014 01:25:08 -0300 Subject: [PATCH 06/45] wallet listing working --- Gruntfile.js | 1 + config.js | 7 +- js/app.js | 3 +- js/controllers/home.js | 13 +- js/controllers/open.js | 34 ++--- js/models/Storage.js | 174 +++++++++++++++-------- js/models/core/PluginManager.js | 11 +- js/models/core/Wallet.js | 36 +++-- js/models/core/WalletFactory.js | 154 ++++++++++---------- js/models/core/WalletLock.js | 57 ++++---- js/services/pluginManager.js | 16 ++- js/services/walletFactory.js | 6 +- plugins/LocalStorage.js | 28 ++-- plugins/googleDrive.js | 242 ++++++++++++++++++++++++++++++-- 14 files changed, 540 insertions(+), 242 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 099cd23bd..540a676b0 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -43,6 +43,7 @@ module.exports = function(grunt) { scripts: { files: [ 'js/models/**/*.js', + 'js/models/*.js', 'plugins/*.js', 'copay.js', 'utils/*.js' diff --git a/config.js b/config.js index 10b5dafe7..94dc2a829 100644 --- a/config.js +++ b/config.js @@ -53,12 +53,13 @@ var defaultConfig = { verbose: 1, plugins: { - LocalStorage: true, - // GoogleDrive: true, +// LocalStorage: true, + GoogleDrive: true, }, GoogleDrive: { - clientId: '1', + clientId: '232630733383-29u1khqf5i8qubhf0homhpb2m14b5lja.apps.googleusercontent.com', + home: 'copay' }, }; if (typeof module !== 'undefined') diff --git a/js/app.js b/js/app.js index e1a3826ee..216553f20 100644 --- a/js/app.js +++ b/js/app.js @@ -37,11 +37,10 @@ var modules = [ 'copayApp.directives', ]; -if (config.plugins.length) +if (Object.keys(config.plugins).length) modules.push('angularLoad'); - var copayApp = window.copayApp = angular.module('copayApp', modules); copayApp.config(function($sceDelegateProvider) { diff --git a/js/controllers/home.js b/js/controllers/home.js index 2ac3e7381..c8a73d862 100644 --- a/js/controllers/home.js +++ b/js/controllers/home.js @@ -1,10 +1,13 @@ 'use strict'; -angular.module('copayApp.controllers').controller('HomeController', - function($scope, $rootScope, $location, walletFactory, notification, controllerUtils) { - - controllerUtils.redirIfLogged(); +angular.module('copayApp.controllers').controller('HomeController', function($scope, $rootScope, $location, walletFactory, notification, controllerUtils) { + controllerUtils.redirIfLogged(); + + $scope.loading = true; + + walletFactory.getWallets(function(ret) { $scope.loading = false; - $scope.hasWallets = (walletFactory.getWallets() && walletFactory.getWallets().length > 0) ? true : false; + $scope.hasWallets = (ret && ret.length > 0) ? true : false; }); +}); diff --git a/js/controllers/open.js b/js/controllers/open.js index 019932988..005bba83d 100644 --- a/js/controllers/open.js +++ b/js/controllers/open.js @@ -14,12 +14,18 @@ angular.module('copayApp.controllers').controller('OpenController', function($sc }; $rootScope.fromSetup = false; $scope.loading = false; - $scope.wallets = walletFactory.getWallets().sort(cmp); - $scope.selectedWalletId = walletFactory.storage.getLastOpened() || ($scope.wallets[0] && $scope.wallets[0].id); + walletFactory.getWallets(function(wallets) { + $scope.wallets = wallets.sort(cmp); + }); + + walletFactory.storage.getLastOpened(function(ret) { + $scope.selectedWalletId = ret || ($scope.wallets[0] && $scope.wallets[0].id); + }); + $scope.openPassword = ''; $scope.isMobile = !!window.cordova; - if (!$scope.wallets.length){ + if (!$scope.wallets.length) { $location.path('/'); } @@ -34,19 +40,15 @@ angular.module('copayApp.controllers').controller('OpenController', function($sc Passphrase.getBase64Async(password, function(passphrase) { var w, errMsg; - try { - w = walletFactory.open($scope.selectedWalletId, passphrase); - } catch (e) { - errMsg = e.message; - }; - if (!w) { - $scope.loading = false; - notification.error('Error', errMsg || 'Wrong password'); - $rootScope.$digest(); - return; - } - $rootScope.updatingBalance = true; - controllerUtils.startNetwork(w, $scope); + walletFactory.open($scope.selectedWalletId, passphrase, function(err, w) { + if (!w) { + $scope.loading = false; + notification.error('Error', err.errMsg || 'Wrong password'); + $rootScope.$digest(); + } + $rootScope.updatingBalance = true; + controllerUtils.startNetwork(w, $scope); + }); }); }; diff --git a/js/models/Storage.js b/js/models/Storage.js index 6a0c378e7..17757192f 100644 --- a/js/models/Storage.js +++ b/js/models/Storage.js @@ -1,5 +1,5 @@ 'use strict'; - +var preconditions = require('preconditions').singleton(); var CryptoJS = require('node-cryptojs-aes').CryptoJS; var bitcore = require('bitcore'); var preconditions = require('preconditions').instance(); @@ -55,38 +55,50 @@ Storage.prototype._decrypt = function(base64) { }; -Storage.prototype._read = function(k) { - var ret; - ret = this.storage.getItem(k); - if (!ret) return null; - ret = this._decrypt(ret); - if (!ret) return null; - ret = ret.toString(CryptoJS.enc.Utf8); - ret = JSON.parse(ret); - return ret; +Storage.prototype._read = function(k, cb) { + preconditions.checkArgument(cb); + + var self = this; + this.storage.getItem(k, function(ret) { + if (!ret) return cb(null); + var ret = self._decrypt(ret); + if (!ret) return cb(null); + + ret = ret.toString(CryptoJS.enc.Utf8); + ret = JSON.parse(ret); + return cb(ret); + }); }; -Storage.prototype._write = function(k, v) { +Storage.prototype._write = function(k, v, cb) { + preconditions.checkArgument(cb); + v = JSON.stringify(v); v = this._encrypt(v); - - this.storage.setItem(k, v); + this.storage.setItem(k, v, cb); }; // get value by key -Storage.prototype.getGlobal = function(k) { - var item = this.storage.getItem(k); - return item == 'undefined' ? undefined : item; +Storage.prototype.getGlobal = function(k, cb) { + preconditions.checkArgument(cb); + + this.storage.getItem(k, function(item) { + cb(item == 'undefined' ? undefined : item); + }); }; // set value for key -Storage.prototype.setGlobal = function(k, v) { - this.storage.setItem(k, typeof v === 'object' ? JSON.stringify(v) : v); +Storage.prototype.setGlobal = function(k, v, cb) { + preconditions.checkArgument(cb); + + this.storage.setItem(k, typeof v === 'object' ? JSON.stringify(v) : v, cb); }; // remove value for key -Storage.prototype.removeGlobal = function(k) { - this.storage.removeItem(k); +Storage.prototype.removeGlobal = function(k, cb) { + preconditions.checkArgument(cb); + + this.storage.removeItem(k, cb); }; Storage.prototype.getSessionId = function() { @@ -102,23 +114,38 @@ Storage.prototype._key = function(walletId, k) { return walletId + '::' + k; }; // get value by key -Storage.prototype.get = function(walletId, k) { - var ret = this._read(this._key(walletId, k)); - return ret; +Storage.prototype.get = function(walletId, k, cb) { + this._read(this._key(walletId, k), cb); +}; + +Storage.prototype.getMany = function(walletId, keys, cb) { + preconditions.checkArgument(cb); + + var self = this; + var ret = {}; + + var l = keys.length - 1; + for (var ii in keys) { + var k = keys[ii]; + this._read(this._key(walletId, k), function(v) { + ret[k] = v; + if (ii == l) return cb(ret); + }); + } }; // set value for key -Storage.prototype.set = function(walletId, k, v) { - this._write(this._key(walletId, k), v); +Storage.prototype.set = function(walletId, k, v, cb) { + this._write(this._key(walletId, k), v, cb); }; // remove value for key -Storage.prototype.remove = function(walletId, k) { - this.removeGlobal(this._key(walletId, k)); +Storage.prototype.remove = function(walletId, k, cb) { + this.removeGlobal(this._key(walletId, k), cb); }; -Storage.prototype.setName = function(walletId, name) { - this.setGlobal('nameFor::' + walletId, name); +Storage.prototype.setName = function(walletId, name, cb) { + this.setGlobal('nameFor::' + walletId, name, cb); }; Storage.prototype.getName = function(walletId) { @@ -126,41 +153,54 @@ Storage.prototype.getName = function(walletId) { return ret; }; -Storage.prototype.getWalletIds = function() { +Storage.prototype.getWalletIds = function(cb) { var walletIds = []; var uniq = {}; -console.log('[Encrypted.js.144]', this.storage); //TODO -console.log('[Encrypted.js.144]', this.storage.length); //TODO - for (var i = 0; i < this.storage.length; i++) { - var key = this.storage.key(i); - var split = key.split('::'); - if (split.length == 2) { - var walletId = split[0]; + this.storage.allKeys(function(keys) { +console.log('[Storage.js.170:keys:]',keys); //TODO - if (!walletId || walletId === 'nameFor' || walletId === 'lock') - continue; + for (var ii in keys) { + var key = keys[ii]; +console.log('[Storage.js.174:key:]',key); //TODO + var split = key.split('::'); + if (split.length == 2) { + var walletId = split[0]; - if (typeof uniq[walletId] === 'undefined') { - walletIds.push(walletId); - uniq[walletId] = 1; + if (!walletId || walletId === 'nameFor' || walletId === 'lock') + continue; + + if (typeof uniq[walletId] === 'undefined') { + walletIds.push(walletId); + uniq[walletId] = 1; + } } } - } - return walletIds; + return cb(walletIds); + }); }; -Storage.prototype.getWallets = function() { +Storage.prototype.getWallets = function(cb) { var wallets = []; - var ids = this.getWalletIds(); + var self = this; - for (var i in ids) { - wallets.push({ - id: ids[i], - name: this.getName(ids[i]), - }); - } - return wallets; + this.getWalletIds(function(ids) { + var l = ids.length - 1; + if (!l) + return cb([]); + + for (var i in ids) { + self.getName(ids[i], function(name) { + wallets.push({ + id: ids[i], + name: name, + }); + if (i == l) { + return cb(wallets); + } + }) + } + }); }; Storage.prototype.deleteWallet = function(walletId) { @@ -179,25 +219,35 @@ Storage.prototype.deleteWallet = function(walletId) { } }; -Storage.prototype.setLastOpened = function(walletId) { - this.setGlobal('lastOpened', walletId); +Storage.prototype.setLastOpened = function(walletId, cb) { + this.setGlobal('lastOpened', walletId, cb); } -Storage.prototype.getLastOpened = function() { - return this.getGlobal('lastOpened'); +Storage.prototype.getLastOpened = function(cb) { + this.getGlobal('lastOpened', cb); } //obj contains keys to be set -Storage.prototype.setFromObj = function(walletId, obj) { +Storage.prototype.setFromObj = function(walletId, obj, cb) { + preconditions.checkArgument(cb); + var self = this; + + console.log('[Storage.js.241]'); //TODO + var l = Object.keys(obj).length, + i = 0; for (var k in obj) { - this.set(walletId, k, obj[k]); + console.log('[Storage.js.247]', k, i, l); //TODO + self.set(walletId, k, obj[k], function() { + if (++i == l) { + self.setName(walletId, obj.opts.name, cb); + } + }); } - this.setName(walletId, obj.opts.name); }; // remove all values -Storage.prototype.clearAll = function() { - this.storage.clear(); +Storage.prototype.clearAll = function(cb) { + this.storage.clear(cb); }; Storage.prototype.import = function(base64) { diff --git a/js/models/core/PluginManager.js b/js/models/core/PluginManager.js index 23b3c2a77..bce94e464 100644 --- a/js/models/core/PluginManager.js +++ b/js/models/core/PluginManager.js @@ -3,8 +3,9 @@ var preconditions = require('preconditions').singleton(); function PluginManager(config) { this.registered = {}; + this.scripts = []; - for(var ii in config.plugins){ + for (var ii in config.plugins) { var pluginName = ii; if (!config.plugins[pluginName]) @@ -12,7 +13,7 @@ function PluginManager(config) { console.log('Loading plugin: ' + pluginName); var pluginClass = require('../plugins/' + pluginName); - var pluginObj = new pluginClass(); + var pluginObj = new pluginClass(config[pluginName]); pluginObj.init(); this._register(pluginObj, pluginName); } @@ -25,9 +26,10 @@ PluginManager.TYPE = {}; PluginManager.TYPE['STORAGE'] = KIND_UNIQUE; PluginManager.prototype._register = function(obj, name) { - preconditions.checkArgument(obj.type,'Plugin has not type:' + name); + preconditions.checkArgument(obj.type, 'Plugin has not type:' + name); var type = obj.type; var kind = PluginManager.TYPE[type]; + preconditions.checkArgument(kind, 'Plugin has unkown type' + name); preconditions.checkState(kind !== PluginManager.KIND_UNIQUE || !this.registered[type], 'Plugin kind already registered: ' + name); @@ -37,8 +39,11 @@ PluginManager.prototype._register = function(obj, name) { this.registered[type] = this.registered[type] || []; this.registered[type].push(obj); } + + this.scripts = this.scripts.concat(obj.scripts || []); }; + PluginManager.prototype.get = function(type) { return this.registered[type]; }; diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index 61e81b137..6ab010c5a 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -821,21 +821,28 @@ Wallet.prototype.getRegisteredPeerIds = function() { * @emits locked - in case the wallet is opened in another instance */ Wallet.prototype.keepAlive = function() { - try { - this.lock.keepAlive(); - } catch (e) { - log.debug(e); - this.emit('locked', null, 'Wallet appears to be openned on other browser instance. Closing this one.'); - } + var self = this; + + this.lock.keepAlive(function(err) { + if (err) { + log.debug(err); + self.emit('locked', null, 'Wallet appears to be openned on other browser instance. Closing this one.'); + } + }); }; /** * @desc Store the wallet's state + * @param {function} callback (err) */ -Wallet.prototype.store = function() { +Wallet.prototype.store = function(cb) { + var self = this; this.keepAlive(); - this.storage.setFromObj(this.id, this.toObj()); - log.debug('Wallet stored'); + this.storage.setFromObj(this.id, this.toObj(), function(err) { + log.debug('Wallet stored'); + if (cb) + cb(err); + }); }; /** @@ -2339,11 +2346,14 @@ Wallet.prototype.indexDiscovery = function(start, change, copayerIndex, gap, cb) /** * @desc Closes the wallet and disconnects all services */ -Wallet.prototype.close = function() { +Wallet.prototype.close = function(cb) { + var self =this; log.debug('## CLOSING'); - this.lock.release(); - this.network.cleanUp(); - this.blockchain.destroy(); + this.lock.release(function() { + self.network.cleanUp(); + self.blockchain.destroy(); + if (cb) return cb(); + }); }; /** diff --git a/js/models/core/WalletFactory.js b/js/models/core/WalletFactory.js index 2efea81de..f164c533f 100644 --- a/js/models/core/WalletFactory.js +++ b/js/models/core/WalletFactory.js @@ -1,4 +1,5 @@ 'use strict'; +var preconditions = require('preconditions').singleton(); var TxProposals = require('./TxProposals'); var PublicKeyRing = require('./PublicKeyRing'); @@ -6,7 +7,7 @@ var PrivateKey = require('./PrivateKey'); var Wallet = require('./Wallet'); var _ = require('underscore'); var log = require('../../log'); -var PluginManager = require('./PluginManager'); +var PluginManager = require('./PluginManager'); var Async = module.exports.Async = require('../network/Async'); var Insight = module.exports.Insight = require('../blockchain/Insight'); var preconditions = require('preconditions').singleton(); @@ -33,16 +34,24 @@ var Storage = module.exports.Storage = require('../Storage'); * @param {string} version - the version of copay for which this wallet was generated (for example, 0.4.7) * @constructor */ -function WalletFactory(config, version) { + +function WalletFactory(config, version, pluginManager) { var self = this; config = config || {}; - this.pluginManager = new PluginManager(config); - - this.Storage = config.Storage || Storage; + this.Storage = config.Storage || Storage; this.Network = config.Network || Async; this.Blockchain = config.Blockchain || Insight; - this.storage = new this.Storage({storage: this.pluginManager.get('STORAGE')}); + + var storageOpts = {}; + + if (pluginManager) { + storageOpts = { + storage: pluginManager.get('STORAGE') + }; + } + + this.storage = new this.Storage(storageOpts); this.networks = { 'livenet': new this.Network(config.network.livenet), @@ -57,27 +66,6 @@ function WalletFactory(config, version) { this.version = version; }; -/** - * @desc - * Returns true if the storage instance can retrieve the following keys using a given walletId - *
    - *
  • publicKeyRing
  • - *
  • txProposals
  • - *
  • opts
  • - *
  • privateKey
  • - *
- * @param {string} walletId - * @return {boolean} true if all the keys are present in the storage instance - */ -WalletFactory.prototype._checkRead = function(walletId) { - var s = this.storage; - var ret = - s.get(walletId, 'publicKeyRing') && - s.get(walletId, 'txProposals') && - s.get(walletId, 'opts') && - s.get(walletId, 'privateKey'); - return !!ret; -}; /** * @desc obtain network name from serialized wallet @@ -100,9 +88,14 @@ WalletFactory.prototype.obtainNetworkName = function(obj) { WalletFactory.prototype.fromObj = function(obj, skipFields) { var networkName = this.obtainNetworkName(obj); preconditions.checkState(networkName); + preconditions.checkArgument(obj); + obj.opts.reconnectDelay = this.walletDefaults.reconnectDelay; + // this is only used if private key or public key ring is skipped + obj.opts.networkName = this.networkName; + skipFields = skipFields || []; skipFields.forEach(function(k) { if (obj[k]) { @@ -155,20 +148,17 @@ WalletFactory.prototype.import = function(base64, password, skipFields) { * @param {string[]} skipFields - parameters to ignore when importing * @return {Wallet} */ -WalletFactory.prototype.read = function(walletId, skipFields) { - if (!this._checkRead(walletId)) - return false; - +WalletFactory.prototype.read = function(walletId, skipFields, cb) { + var self = this; var obj = {}; - var s = this.storage; - obj.id = walletId; - _.each(Wallet.PERSISTED_PROPERTIES, function(value) { - obj[value] = s.get(walletId, value); - }); - var w = this.fromObj(obj, skipFields); - return w; + this.storage.getMany(walletId, Wallet.PERSISTED_PROPERTIES, function(ret) { + for (var ii in ret) { + obj[ii] = ret[ii]; + } + return cb(self.fromObj(obj, skipFields)); + }); }; /** @@ -269,29 +259,29 @@ WalletFactory.prototype._checkVersion = function(inVersion) { * @desc Retrieve a wallet from the storage * @param {string} walletId - the id of the wallet * @param {string} passphrase - the passphrase to decode it - * @return {Wallet} + * @param {function} callback (err, {Wallet}) + * @return */ -WalletFactory.prototype.open = function(walletId, passphrase) { - this.storage._setPassphrase(passphrase); - var w = this.read(walletId); - if (w) { - w.store(); - } - - this.storage.setLastOpened(walletId); - return w; +WalletFactory.prototype.open = function(walletId, passphrase, cb) { + var self = this, + err; + self.storage._setPassphrase(passphrase); + self.read(walletId, null, function(w) { + w.store(function() { + self.storage.setLastOpened(walletId, function() { + return cb(err, w); + }); + }); + }); }; -/** - * @desc Retrieve all wallets stored without encription in the storage instance - * @returns {Wallet[]} - */ -WalletFactory.prototype.getWallets = function() { - var ret = this.storage.getWallets(); - ret.forEach(function(i) { - i.show = i.name ? ((i.name + ' <' + i.id + '>')) : i.id; +WalletFactory.prototype.getWallets = function(cb) { + var ret = this.storage.getWallets(function(ret) { + ret.forEach(function(i) { + i.show = i.name ? ((i.name + ' <' + i.id + '>')) : i.id; + }); + return cb(ret); }); - return ret; }; /** @@ -374,30 +364,32 @@ WalletFactory.prototype.joinCreateSession = function(secret, nickname, passphras connectedOnce = true; }); - joinNetwork.on('serverError', function() { - return cb('joinError'); - }); + << << << < HEAD + joinNetwork.on('serverError', function() { === === = + self.network.on('serverError', function() { >>> >>> > wallet listing working + return cb('joinError'); + }); - joinNetwork.start(opts, function() { - joinNetwork.greet(decodedSecret.pubKey, opts.secretNumber); - joinNetwork.on('data', function(sender, data) { - if (data.type === 'walletId') { - if (data.networkName !== decodedSecret.networkName) { - return cb('badNetwork'); - } + joinNetwork.start(opts, function() { + joinNetwork.greet(decodedSecret.pubKey, opts.secretNumber); + joinNetwork.on('data', function(sender, data) { + if (data.type === 'walletId') { + if (data.networkName !== decodedSecret.networkName) { + return cb('badNetwork'); + } - data.opts.privateKey = privateKey; - data.opts.nickname = nickname; - data.opts.passphrase = passphrase; - data.opts.id = data.walletId; - var w = self.create(data.opts); - w.sendWalletReady(decodedSecret.pubKey); - return cb(null, w); - } else { - return cb('walletFull', w); - } - }); - }); -}; + data.opts.privateKey = privateKey; + data.opts.nickname = nickname; + data.opts.passphrase = passphrase; + data.opts.id = data.walletId; + var w = self.create(data.opts); + w.sendWalletReady(decodedSecret.pubKey); + return cb(null, w); + } else { + return cb('walletFull', w); + } + }); + }); + }; -module.exports = WalletFactory; + module.exports = WalletFactory; diff --git a/js/models/core/WalletLock.js b/js/models/core/WalletLock.js index edd2bf67d..ef33fa196 100644 --- a/js/models/core/WalletLock.js +++ b/js/models/core/WalletLock.js @@ -10,46 +10,51 @@ function WalletLock(storage, walletId, timeoutMin) { this.storage = storage; this.timeoutMin = timeoutMin || 5; this.key = WalletLock._keyFor(walletId); - this._setLock(); + this._setLock(function() {}); } WalletLock._keyFor = function(walletId) { return 'lock' + '::' + walletId; }; -WalletLock.prototype._isLockedByOther = function() { - var json = this.storage.getGlobal(this.key); - var wl = json ? JSON.parse(json) : null; - var t = wl ? (Date.now() - wl.expireTs) : false; - // is not locked? - if (!wl || t > 0 || wl.sessionId === this.sessionId) - return false; +WalletLock.prototype._isLockedByOther = function(cb) { + var self=this; + this.storage.getGlobal(this.key, function(json) { + var wl = json ? JSON.parse(json) : null; + var t = wl ? (Date.now() - wl.expireTs) : false; + // is not locked? + if (!wl || t > 0 || wl.sessionId === self.sessionId) + return cb(false); - // Seconds remainding - return parseInt(-t/1000.); -}; - - -WalletLock.prototype._setLock = function() { - this.storage.setGlobal(this.key, { - sessionId: this.sessionId, - expireTs: Date.now() + this.timeoutMin * 60 * 1000, + // Seconds remainding + return cb(parseInt(-t / 1000.)); }); }; -WalletLock.prototype.keepAlive = function() { - preconditions.checkState(this.sessionId); - - var t = this._isLockedByOther(); - if (t) - throw new Error('Wallet is already open. Close it to proceed or wait '+ t + ' seconds if you close it already' ); - this._setLock(); +WalletLock.prototype._setLock = function(cb) { + this.storage.setGlobal(this.key, { + sessionId: this.sessionId, + expireTs: Date.now() + this.timeoutMin * 60 * 1000, + }, cb); }; -WalletLock.prototype.release = function() { - this.storage.removeGlobal(this.key); +WalletLock.prototype.keepAlive = function(cb) { + preconditions.checkState(this.sessionId); + var self = this; + + this._isLockedByOther(function(t) { + if (t) + return cb(new Error('Wallet is already open. Close it to proceed or wait ' + t + ' seconds if you close it already')); + + self._setLock(cb); + }); +}; + + +WalletLock.prototype.release = function(cb) { + this.storage.removeGlobal(this.key, cb); }; diff --git a/js/services/pluginManager.js b/js/services/pluginManager.js index c67b16846..f5e6e165c 100644 --- a/js/services/pluginManager.js +++ b/js/services/pluginManager.js @@ -1,5 +1,19 @@ 'use strict'; angular.module('copayApp.services').factory('pluginManager', function(angularLoad){ - return new copay.PluginManager(config); + var pm = new copay.PluginManager(config); + + var scripts = pm.scripts; + + for(var ii in scripts){ + var src = scripts[ii].src; + + console.log('\tLoading ',src); //TODO + angularLoad.loadScript(src) + .then(scripts[ii].then || null) + .catch(function() { + throw new Error('Loading ' + src); + }) + } + return pm; }); diff --git a/js/services/walletFactory.js b/js/services/walletFactory.js index 16580af9d..7a6b96ea6 100644 --- a/js/services/walletFactory.js +++ b/js/services/walletFactory.js @@ -1,3 +1,7 @@ 'use strict'; +angular.module('copayApp.services').factory('walletFactory', function(pluginManager){ + +console.log('[walletFactory.js.3]'); //TODO + return new copay.WalletFactory(config, copay.version, pluginManager); +}); -angular.module('copayApp.services').value('walletFactory', new copay.WalletFactory(config, copay.version)); diff --git a/plugins/LocalStorage.js b/plugins/LocalStorage.js index 3f050f64f..a811cfcf4 100644 --- a/plugins/LocalStorage.js +++ b/plugins/LocalStorage.js @@ -9,33 +9,33 @@ LocalStorage.prototype.init = function() { }; -LocalStorage.prototype.getItem = function(k) { - return localStorage.getItem(k); +LocalStorage.prototype.getItem = function(k,cb) { + return cb(localStorage.getItem(k)); }; -LocalStorage.prototype.setItem = function(k,v) { +LocalStorage.prototype.setItem = function(k,v,cb) { localStorage.setItem(k,v); + return cb(); }; -LocalStorage.prototype.removeItem = function(k) { +LocalStorage.prototype.removeItem = function(k,cb) { localStorage.removeItem(k); + return cb(); }; -LocalStorage.prototype.clear = function() { +LocalStorage.prototype.clear = function(cb) { localStorage.clear(); + return cb(); }; -delete LocalStorage.prototype.length; +LocalStorage.prototype.allKeys = function(cb) { + var l = localStorage.length; + var ret = []; -Object.defineProperty(LocalStorage.prototype, 'length', { - get: function() { - return localStorage.length; - } -}); + for(var i=0; i Date: Wed, 3 Sep 2014 15:43:27 -0300 Subject: [PATCH 07/45] working! --- js/controllers/create.js | 5 +- js/controllers/open.js | 14 +-- js/models/Storage.js | 45 ++++++--- js/models/core/WalletFactory.js | 51 +++++----- js/models/core/WalletLock.js | 12 ++- js/routes.js | 4 +- plugins/googleDrive.js | 173 ++++++++++++++++++++++---------- 7 files changed, 201 insertions(+), 103 deletions(-) diff --git a/js/controllers/create.js b/js/controllers/create.js index 52db78e95..6631dcce9 100644 --- a/js/controllers/create.js +++ b/js/controllers/create.js @@ -86,8 +86,9 @@ angular.module('copayApp.controllers').controller('CreateController', privateKeyHex: $scope.private, networkName: $scope.networkName, }; - var w = walletFactory.create(opts); - controllerUtils.startNetwork(w, $scope); + walletFactory.create(opts, function(err, w) { + controllerUtils.startNetwork(w, $scope); + }); }); }; diff --git a/js/controllers/open.js b/js/controllers/open.js index 005bba83d..403f4f9fd 100644 --- a/js/controllers/open.js +++ b/js/controllers/open.js @@ -16,19 +16,19 @@ angular.module('copayApp.controllers').controller('OpenController', function($sc $scope.loading = false; walletFactory.getWallets(function(wallets) { $scope.wallets = wallets.sort(cmp); - }); - walletFactory.storage.getLastOpened(function(ret) { - $scope.selectedWalletId = ret || ($scope.wallets[0] && $scope.wallets[0].id); + if (!$scope.wallets.length) { + $location.path('/'); + } + + walletFactory.storage.getLastOpened(function(ret) { + $scope.selectedWalletId = ret || ($scope.wallets[0] && $scope.wallets[0].id); + }); }); $scope.openPassword = ''; $scope.isMobile = !!window.cordova; - if (!$scope.wallets.length) { - $location.path('/'); - } - $scope.open = function(form) { if (form && form.$invalid) { notification.error('Error', 'Please enter the required fields'); diff --git a/js/models/Storage.js b/js/models/Storage.js index 17757192f..e23ab530d 100644 --- a/js/models/Storage.js +++ b/js/models/Storage.js @@ -83,6 +83,7 @@ Storage.prototype.getGlobal = function(k, cb) { preconditions.checkArgument(cb); this.storage.getItem(k, function(item) { +console.log('[Storage.js.96:item:]',item); //TODO cb(item == 'undefined' ? undefined : item); }); }; @@ -118,18 +119,34 @@ Storage.prototype.get = function(walletId, k, cb) { this._read(this._key(walletId, k), cb); }; + +Storage.prototype._readHelper = function(walletId, k, cb) { +console.log('[Storage.js.134:walletId:]',walletId,k); //TODO + var wk = this._key(walletId, k); + + this._read(wk, function(v){ + return cb(v,k); + }); +}; + Storage.prototype.getMany = function(walletId, keys, cb) { preconditions.checkArgument(cb); var self = this; var ret = {}; +console.log('[Storage.js.142:keys:]',keys); //TODO + + var l = keys.length, i=0; - var l = keys.length - 1; for (var ii in keys) { - var k = keys[ii]; - this._read(this._key(walletId, k), function(v) { + this._readHelper(walletId, keys[ii], function(v, k) { ret[k] = v; - if (ii == l) return cb(ret); +console.log('[Storage.js.144:ret:]',k,i,l,v); //TODO + if (++i == l) { + +console.log('[Storage.js.157] LKIST', ret); //TODO + return cb(ret); + } }); } }; @@ -148,9 +165,8 @@ Storage.prototype.setName = function(walletId, name, cb) { this.setGlobal('nameFor::' + walletId, name, cb); }; -Storage.prototype.getName = function(walletId) { - var ret = this.getGlobal('nameFor::' + walletId); - return ret; +Storage.prototype.getName = function(walletId, cb) { + this.getGlobal('nameFor::' + walletId, cb); }; Storage.prototype.getWalletIds = function(cb) { @@ -185,17 +201,21 @@ Storage.prototype.getWallets = function(cb) { var self = this; this.getWalletIds(function(ids) { - var l = ids.length - 1; +console.log('[Storage.js.197:ids:]',ids); //TODO + var l = ids.length, i=0; if (!l) return cb([]); - for (var i in ids) { - self.getName(ids[i], function(name) { + for (var ii in ids) { + var id = ids[ii]; +console.log('[Storage.js.206:id:]',id); //TODO + self.getName(id, function(name) { wallets.push({ - id: ids[i], + id: id, name: name, }); - if (i == l) { +console.log('[Storage.js.208:wallets:]',wallets); //TODO + if (++i == l) { return cb(wallets); } }) @@ -232,7 +252,6 @@ Storage.prototype.setFromObj = function(walletId, obj, cb) { preconditions.checkArgument(cb); var self = this; - console.log('[Storage.js.241]'); //TODO var l = Object.keys(obj).length, i = 0; for (var k in obj) { diff --git a/js/models/core/WalletFactory.js b/js/models/core/WalletFactory.js index f164c533f..18d5ed063 100644 --- a/js/models/core/WalletFactory.js +++ b/js/models/core/WalletFactory.js @@ -178,10 +178,10 @@ WalletFactory.prototype.read = function(walletId, skipFields, cb) { * @TODO: Figure out in what unit is this reconnect delay. * @param {number} opts.reconnectDelay milliseconds? * @param {number=} opts.version + * @param {callback} opts.version * @return {Wallet} */ -WalletFactory.prototype.create = function(opts) { - +WalletFactory.prototype.create = function(opts, cb) { opts = opts || {}; opts.networkName = opts.networkName || 'testnet'; @@ -230,9 +230,12 @@ WalletFactory.prototype.create = function(opts) { opts.version = opts.version || this.version; var w = new Wallet(opts); - w.store(); - this.storage.setLastOpened(w.id); - return w; + var self = this; + w.store(function() { + self.storage.setLastOpened(w.id, function() { + return cb(null, w); + }); + }); }; /** @@ -364,15 +367,13 @@ WalletFactory.prototype.joinCreateSession = function(secret, nickname, passphras connectedOnce = true; }); - << << << < HEAD - joinNetwork.on('serverError', function() { === === = - self.network.on('serverError', function() { >>> >>> > wallet listing working - return cb('joinError'); - }); + joinNetwork.on('serverError', function() { + return cb('joinError'); + }); - joinNetwork.start(opts, function() { - joinNetwork.greet(decodedSecret.pubKey, opts.secretNumber); - joinNetwork.on('data', function(sender, data) { + joinNetwork.start(opts, function() { + joinNetwork.greet(decodedSecret.pubKey, opts.secretNumber); + joinNetwork.on('data', function(sender, data) { if (data.type === 'walletId') { if (data.networkName !== decodedSecret.networkName) { return cb('badNetwork'); @@ -382,14 +383,18 @@ WalletFactory.prototype.joinCreateSession = function(secret, nickname, passphras data.opts.nickname = nickname; data.opts.passphrase = passphrase; data.opts.id = data.walletId; - var w = self.create(data.opts); - w.sendWalletReady(decodedSecret.pubKey); - return cb(null, w); - } else { - return cb('walletFull', w); - } - }); - }); - }; + self.create(data.opts, function(err, w) { + if (!err & w) { + w.sendWalletReady(s.pubKey); + } else { + if (!err) err = 'walletFull'; + } + return cb(err, w); + }); - module.exports = WalletFactory; + }); + }); + }; +}; + +module.exports = WalletFactory; diff --git a/js/models/core/WalletLock.js b/js/models/core/WalletLock.js index ef33fa196..a8a1729b7 100644 --- a/js/models/core/WalletLock.js +++ b/js/models/core/WalletLock.js @@ -10,7 +10,7 @@ function WalletLock(storage, walletId, timeoutMin) { this.storage = storage; this.timeoutMin = timeoutMin || 5; this.key = WalletLock._keyFor(walletId); - this._setLock(function() {}); + // this._setLock(function() {}); } WalletLock._keyFor = function(walletId) { @@ -18,7 +18,9 @@ WalletLock._keyFor = function(walletId) { }; WalletLock.prototype._isLockedByOther = function(cb) { - var self=this; + var self = this; + + console.log('[WalletLock.js.22]'); //TODO this.storage.getGlobal(this.key, function(json) { var wl = json ? JSON.parse(json) : null; var t = wl ? (Date.now() - wl.expireTs) : false; @@ -33,10 +35,13 @@ WalletLock.prototype._isLockedByOther = function(cb) { WalletLock.prototype._setLock = function(cb) { + this.storage.setGlobal(this.key, { sessionId: this.sessionId, expireTs: Date.now() + this.timeoutMin * 60 * 1000, - }, cb); + }, function() { + cb(null); + }); }; @@ -45,6 +50,7 @@ WalletLock.prototype.keepAlive = function(cb) { var self = this; this._isLockedByOther(function(t) { + if (t) return cb(new Error('Wallet is already open. Close it to proceed or wait ' + t + ' seconds if you close it already')); diff --git a/js/routes.js b/js/routes.js index 02c036251..6f01ffc23 100644 --- a/js/routes.js +++ b/js/routes.js @@ -76,8 +76,8 @@ angular // IDLE timeout var timeout = config.wallet.idleDurationMin * 60 || 300; $idleProvider.idleDuration(timeout); // in seconds - $idleProvider.warningDuration(20); // in seconds - $keepaliveProvider.interval(2); // in seconds + $idleProvider.warningDuration(40); // in seconds + $keepaliveProvider.interval(30); // in seconds }) .run(function($rootScope, $location, $idle, gettextCatalog) { gettextCatalog.currentLanguage = config.defaultLanguage; diff --git a/plugins/googleDrive.js b/plugins/googleDrive.js index 7811640b9..8cf41d72e 100644 --- a/plugins/googleDrive.js +++ b/plugins/googleDrive.js @@ -25,7 +25,7 @@ function GoogleDrive(config) { window.InitGoogleDrive = function() { - console.log('[googleDrive.js.18] setting loaded'); //TODO + // console.log('[googleDrive.js.18] setting loaded'); //TODO loaded = 1; }; @@ -47,7 +47,7 @@ GoogleDrive.prototype.initLoaded = function() { */ GoogleDrive.prototype.checkAuth = function() { - console.log('\tChecking google Auth'); //TODO + console.log('\tChecking google Auth'); gapi.auth.authorize({ 'client_id': this.clientId, 'scope': SCOPES, @@ -61,7 +61,7 @@ GoogleDrive.prototype.checkAuth = function() { */ GoogleDrive.prototype.handleAuthResult = function(authResult) { var self = this; - console.log('[googleDrive.js.39:authResult:]', authResult); //TODO + // console.log('[googleDrive.js.39:authResult:]', authResult); //TODO if (authResult.error) { if (authResult.error) { @@ -81,61 +81,121 @@ GoogleDrive.prototype.checkReady = function() { throw new Error('goggle drive is not ready!'); }; -GoogleDrive.prototype.getItem = function(k) { - this.checkReady(); - throw new Error('getItem not implemented'); +GoogleDrive.prototype._httpGet = function(theUrl) { + var accessToken = gapi.auth.getToken().access_token; + var xmlHttp = null; + + xmlHttp = new XMLHttpRequest(); + xmlHttp.open("GET", theUrl, false); + xmlHttp.setRequestHeader('Authorization', 'Bearer ' + accessToken); + xmlHttp.send(null); + return xmlHttp.responseText; +} + +GoogleDrive.prototype.getItem = function(k, cb) { + console.log('[googleDrive.js.95:getItem:]', k); //TODO + var self = this; + + self.checkReady(); + self._idForName(k, function(kId) { + // console.log('[googleDrive.js.89:kId:]', kId); //TODO + if (!kId) + return cb(null); + + + var args = { + 'path': '/drive/v2/files/' + kId, + 'method': 'GET', + }; + // console.log('[googleDrive.js.95:args:]', args); //TODO + + var request = gapi.client.request(args); + request.execute(function(res) { + // console.log('[googleDrive.js.175:res:]', res); //TODO + if (!res || !res.downloadUrl) + return cb(null); + + return cb(self._httpGet(res.downloadUrl)); + }); + + }); }; GoogleDrive.prototype.setItem = function(k, v, cb) { + // console.log('[googleDrive.js.111:setItem:]', k, v); //TODO var self = this; - this.checkReady(); + self.checkReady(); + self._idForName(this.home, function(parentId) { + preconditions.checkState(parentId); + // console.log('[googleDrive.js.118:parentId:]', parentId); //TODO + self._idForName(k, function(kId) { - var parendId = self._idForName[this.home]; - preconditions.checkState(parentId); + // console.log('[googleDrive.js.105]', parentId, kId); //TODO - var boundary = '-------314159265358979323846'; - var delimiter = "\r\n--" + boundary + "\r\n"; - var close_delim = "\r\n--" + boundary + "--"; + var boundary = '-------314159265358979323846'; + var delimiter = "\r\n--" + boundary + "\r\n"; + var close_delim = "\r\n--" + boundary + "--"; - var metadata = { - 'title': k, - 'mimeType': 'application/octet-stream', - 'parents': [parentId], - }; + var metadata = { + 'title': k, + 'mimeType': 'application/octet-stream', + 'parents': [{ + 'id': parentId + }], + }; - var base64Data = btoa(v); - var multipartRequestBody = - delimiter + - 'Content-Type: application/json\r\n\r\n' + - JSON.stringify(metadata) + - delimiter + - 'Content-Type: application/octet-stream \r\n' + - 'Content-Transfer-Encoding: base64\r\n' + - '\r\n' + - base64Data + - close_delim; -console.log('[googleDrive.js.105:multipartRequestBody:]',multipartRequestBody); //TODO + var base64Data = btoa(v); + var multipartRequestBody = + delimiter + + 'Content-Type: application/json\r\n\r\n' + + JSON.stringify(metadata) + + delimiter + + 'Content-Type: application/octet-stream \r\n' + + 'Content-Transfer-Encoding: base64\r\n' + + '\r\n' + + base64Data + + close_delim; - var request = gapi.client.request({ - 'path': '/upload/drive/v2/files', - 'method': 'POST', - 'params': { - 'uploadType': 'multipart', - }, - 'headers': { - 'Content-Type': 'multipart/mixed; boundary="' + boundary + '"' - }, - 'body': multipartRequestBody + var args = { + 'path': '/upload/drive/v2/files' + (kId ? '/' + kId : ''), + 'method': kId ? 'PUT' : 'POST', + 'params': { + 'uploadType': 'multipart', + }, + 'headers': { + 'Content-Type': 'multipart/mixed; boundary="' + boundary + '"' + }, + 'body': multipartRequestBody + } + // console.log('[googleDrive.js.148:args:]', args); //TODO + + var request = gapi.client.request(args); + request.execute(cb); + }); }); - request.execute(cb); }; -GoogleDrive.prototype.removeItem = function(k) { - this.checkReady(); +GoogleDrive.prototype.removeItem = function(k, cb) { + var self = this; - throw new Error('removeItem not implemented'); + self.checkReady(); + self._idForName(this.home, function(parentId) { + preconditions.checkState(parentId); + self._idForName(k, function(kId) { + + var args = { + 'path': '/drive/v2/files/' + kId, + 'method': 'DELETE', + }; + var request = gapi.client.request(args); + request.execute(function() { + if (cb) + cb(); + }); + }); + }); }; GoogleDrive.prototype.clear = function() { @@ -158,13 +218,14 @@ GoogleDrive.prototype._mkdir = function(cb) { 'mimeType': "application/vnd.google-apps.folder", }), }); - request.execute(function(){ - self._idForName(this.home, cb); + request.execute(function() { + self._idForName(self.home, cb); }); }; GoogleDrive.prototype._idForName = function(name, cb) { + // console.log('[googleDrive.js.199:_idForName:]', name); //TODO preconditions.checkArgument(name); preconditions.checkArgument(cb); var self = this; @@ -174,17 +235,24 @@ GoogleDrive.prototype._idForName = function(name, cb) { self.ts = self.ts * 1.5; return setTimeout(self._idForName.bind(self, name, cb), self.ts); } -console.log('[googleDrive.js.178:name:]',name); //TODO + // console.log('[googleDrive.js.178:name:]', name); //TODO - if (self.idCache[name]) + if (self.idCache[name]) { + // console.log('[googleDrive.js.212:] FROM CACHE', name, self.idCache[name]); //TODO return cb(self.idCache[name]); + } console.log('Querying for: ', name); //TODO var args; - var idParent = name == this.home ? 'root' : self.idCache[this.home] ; + var idParent = name == this.home ? 'root' : self.idCache[this.home]; -console.log('[googleDrive.js.177:idParent:]',idParent); //TODO + if (!idParent) { + return self._mkdir(function() { + self._idForName(name, cb); + }); + } + // console.log('[googleDrive.js.177:idParent:]', idParent); //TODO preconditions.checkState(idParent); args = { @@ -195,13 +263,12 @@ console.log('[googleDrive.js.177:idParent:]',idParent); //TODO } }; - console.log('[googleDrive.js.196:args:]', args); //TODO var request = gapi.client.request(args); request.execute(function(res) { - console.log('[googleDrive.js.175:res:]', res); //TODO var i = res.items && res.items[0] ? res.items[0].id : false; if (i) self.idCache[name] = i; + // console.log('[googleDrive.js.238] CACHING ' + name + ':' + i); //TODO return cb(self.idCache[name]); }); }; @@ -232,13 +299,13 @@ GoogleDrive.prototype.allKeys = function(cb) { }, }); request.execute(function(res) { - console.log('[googleDrive.js.152:res:]', res); //TODO + // console.log('[googleDrive.js.152:res:]', res); //TODO if (res.error) throw new Error(res.error.message); var ret = []; for (var ii in res.items) { - ret.push(res[ii].id); + ret.push(res.items[ii].title); } return cb(ret); }); From da1266e5f9d4920209b8c9d78fec24d03ed00eac Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 3 Sep 2014 17:05:19 -0300 Subject: [PATCH 08/45] renamed foo to FOO --- plugins/{googleDrive.js => GoogleDrive.js} | 0 plugins/kk | 321 +++++++++++++++++++++ 2 files changed, 321 insertions(+) rename plugins/{googleDrive.js => GoogleDrive.js} (100%) create mode 100644 plugins/kk diff --git a/plugins/googleDrive.js b/plugins/GoogleDrive.js similarity index 100% rename from plugins/googleDrive.js rename to plugins/GoogleDrive.js diff --git a/plugins/kk b/plugins/kk new file mode 100644 index 000000000..8cf41d72e --- /dev/null +++ b/plugins/kk @@ -0,0 +1,321 @@ +'use strict'; + +var preconditions = require('preconditions').singleton(); +var loaded = 0; +var SCOPES = 'https://www.googleapis.com/auth/drive'; + +function GoogleDrive(config) { + preconditions.checkArgument(config && config.clientId, 'No clientId at GoogleDrive config'); + + this.clientId = config.clientId; + this.home = config.home || 'copay'; + this.idCache = {}; + + this.type = 'STORAGE'; + + this.scripts = [{ + then: this.initLoaded.bind(this), + src: 'https://apis.google.com/js/client.js?onload=InitGoogleDrive' + }]; + + this.isReady = false; + this.useImmediate = true; + this.ts = 100; +}; + +window.InitGoogleDrive = function() { + + // console.log('[googleDrive.js.18] setting loaded'); //TODO + loaded = 1; +}; + +GoogleDrive.prototype.init = function() {}; + +/** + * Called when the client library is loaded to start the auth flow. + */ +GoogleDrive.prototype.initLoaded = function() { + if (!loaded) { + window.setTimeout(this.initLoaded.bind(this), 500); + } else { + window.setTimeout(this.checkAuth.bind(this), 1); + } +} + +/** + * Check if the current user has authorized the application. + */ +GoogleDrive.prototype.checkAuth = function() { + + console.log('\tChecking google Auth'); + gapi.auth.authorize({ + 'client_id': this.clientId, + 'scope': SCOPES, + 'immediate': this.useImmediate, + }, + this.handleAuthResult.bind(this)); +}; + +/** + * Called when authorization server replies. + */ +GoogleDrive.prototype.handleAuthResult = function(authResult) { + var self = this; + // console.log('[googleDrive.js.39:authResult:]', authResult); //TODO + + if (authResult.error) { + if (authResult.error) { + self.useImmediate = false; + return this.checkAuth(); + }; + throw new Error(authResult.error); + } + + gapi.client.load('drive', 'v2', function() { + self.isReady = true; + }); +} + +GoogleDrive.prototype.checkReady = function() { + if (!this.isReady) + throw new Error('goggle drive is not ready!'); +}; + +GoogleDrive.prototype._httpGet = function(theUrl) { + var accessToken = gapi.auth.getToken().access_token; + var xmlHttp = null; + + xmlHttp = new XMLHttpRequest(); + xmlHttp.open("GET", theUrl, false); + xmlHttp.setRequestHeader('Authorization', 'Bearer ' + accessToken); + xmlHttp.send(null); + return xmlHttp.responseText; +} + +GoogleDrive.prototype.getItem = function(k, cb) { + console.log('[googleDrive.js.95:getItem:]', k); //TODO + var self = this; + + self.checkReady(); + self._idForName(k, function(kId) { + // console.log('[googleDrive.js.89:kId:]', kId); //TODO + if (!kId) + return cb(null); + + + var args = { + 'path': '/drive/v2/files/' + kId, + 'method': 'GET', + }; + // console.log('[googleDrive.js.95:args:]', args); //TODO + + var request = gapi.client.request(args); + request.execute(function(res) { + // console.log('[googleDrive.js.175:res:]', res); //TODO + if (!res || !res.downloadUrl) + return cb(null); + + return cb(self._httpGet(res.downloadUrl)); + }); + + }); +}; + +GoogleDrive.prototype.setItem = function(k, v, cb) { + // console.log('[googleDrive.js.111:setItem:]', k, v); //TODO + var self = this; + + self.checkReady(); + self._idForName(this.home, function(parentId) { + preconditions.checkState(parentId); + // console.log('[googleDrive.js.118:parentId:]', parentId); //TODO + self._idForName(k, function(kId) { + + // console.log('[googleDrive.js.105]', parentId, kId); //TODO + + + var boundary = '-------314159265358979323846'; + var delimiter = "\r\n--" + boundary + "\r\n"; + var close_delim = "\r\n--" + boundary + "--"; + + var metadata = { + 'title': k, + 'mimeType': 'application/octet-stream', + 'parents': [{ + 'id': parentId + }], + }; + + var base64Data = btoa(v); + var multipartRequestBody = + delimiter + + 'Content-Type: application/json\r\n\r\n' + + JSON.stringify(metadata) + + delimiter + + 'Content-Type: application/octet-stream \r\n' + + 'Content-Transfer-Encoding: base64\r\n' + + '\r\n' + + base64Data + + close_delim; + + var args = { + 'path': '/upload/drive/v2/files' + (kId ? '/' + kId : ''), + 'method': kId ? 'PUT' : 'POST', + 'params': { + 'uploadType': 'multipart', + }, + 'headers': { + 'Content-Type': 'multipart/mixed; boundary="' + boundary + '"' + }, + 'body': multipartRequestBody + } + // console.log('[googleDrive.js.148:args:]', args); //TODO + + var request = gapi.client.request(args); + request.execute(cb); + }); + }); +}; + +GoogleDrive.prototype.removeItem = function(k, cb) { + var self = this; + + self.checkReady(); + self._idForName(this.home, function(parentId) { + preconditions.checkState(parentId); + self._idForName(k, function(kId) { + + var args = { + 'path': '/drive/v2/files/' + kId, + 'method': 'DELETE', + }; + var request = gapi.client.request(args); + request.execute(function() { + if (cb) + cb(); + }); + }); + }); +}; + +GoogleDrive.prototype.clear = function() { + this.checkReady(); + throw new Error('clear not implemented'); +}; + + +GoogleDrive.prototype._mkdir = function(cb) { + preconditions.checkArgument(cb); + var self = this; + + console.log('Creating drive folder ' + this.home); + + var request = gapi.client.request({ + 'path': '/drive/v2/files', + 'method': 'POST', + 'body': JSON.stringify({ + 'title': this.home, + 'mimeType': "application/vnd.google-apps.folder", + }), + }); + request.execute(function() { + self._idForName(self.home, cb); + }); +}; + + +GoogleDrive.prototype._idForName = function(name, cb) { + // console.log('[googleDrive.js.199:_idForName:]', name); //TODO + preconditions.checkArgument(name); + preconditions.checkArgument(cb); + var self = this; + + if (!self.isReady) { + console.log('\tWaiting for Drive'); + self.ts = self.ts * 1.5; + return setTimeout(self._idForName.bind(self, name, cb), self.ts); + } + // console.log('[googleDrive.js.178:name:]', name); //TODO + + if (self.idCache[name]) { + // console.log('[googleDrive.js.212:] FROM CACHE', name, self.idCache[name]); //TODO + return cb(self.idCache[name]); + } + + console.log('Querying for: ', name); //TODO + var args; + + var idParent = name == this.home ? 'root' : self.idCache[this.home]; + + if (!idParent) { + return self._mkdir(function() { + self._idForName(name, cb); + }); + } + // console.log('[googleDrive.js.177:idParent:]', idParent); //TODO + preconditions.checkState(idParent); + + args = { + 'path': '/drive/v2/files', + 'method': 'GET', + 'params': { + 'q': "title='" + name + "' and trashed = false and '" + idParent + "' in parents", + } + }; + + var request = gapi.client.request(args); + request.execute(function(res) { + var i = res.items && res.items[0] ? res.items[0].id : false; + if (i) + self.idCache[name] = i; + // console.log('[googleDrive.js.238] CACHING ' + name + ':' + i); //TODO + return cb(self.idCache[name]); + }); +}; + +GoogleDrive.prototype._checkHomeDir = function(cb) { + var self = this; + + this._idForName(this.home, function(homeId) { + if (!homeId) + return self._mkdir(cb); + + return cb(homeId); + }); +}; + +GoogleDrive.prototype.allKeys = function(cb) { + var self = this; + + this._checkHomeDir(function(homeId) { + preconditions.checkState(homeId); + + var request = gapi.client.request({ + 'path': '/drive/v2/files', + 'method': 'GET', + 'params': { + 'q': "'" + homeId + "' in parents and trashed = false", + 'fields': 'items(id,title)' + }, + }); + request.execute(function(res) { + // console.log('[googleDrive.js.152:res:]', res); //TODO + if (res.error) + throw new Error(res.error.message); + + var ret = []; + for (var ii in res.items) { + ret.push(res.items[ii].title); + } + return cb(ret); + }); + }); +}; + +GoogleDrive.prototype.key = function(k) { + var v = localStorage.key(k); + return v; +}; + + +module.exports = GoogleDrive; From fe37bcc9e90599c0abe4415344fa1e93dd161d0d Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 3 Sep 2014 17:05:49 -0300 Subject: [PATCH 09/45] . --- plugins/kk | 321 ----------------------------------------------------- 1 file changed, 321 deletions(-) delete mode 100644 plugins/kk diff --git a/plugins/kk b/plugins/kk deleted file mode 100644 index 8cf41d72e..000000000 --- a/plugins/kk +++ /dev/null @@ -1,321 +0,0 @@ -'use strict'; - -var preconditions = require('preconditions').singleton(); -var loaded = 0; -var SCOPES = 'https://www.googleapis.com/auth/drive'; - -function GoogleDrive(config) { - preconditions.checkArgument(config && config.clientId, 'No clientId at GoogleDrive config'); - - this.clientId = config.clientId; - this.home = config.home || 'copay'; - this.idCache = {}; - - this.type = 'STORAGE'; - - this.scripts = [{ - then: this.initLoaded.bind(this), - src: 'https://apis.google.com/js/client.js?onload=InitGoogleDrive' - }]; - - this.isReady = false; - this.useImmediate = true; - this.ts = 100; -}; - -window.InitGoogleDrive = function() { - - // console.log('[googleDrive.js.18] setting loaded'); //TODO - loaded = 1; -}; - -GoogleDrive.prototype.init = function() {}; - -/** - * Called when the client library is loaded to start the auth flow. - */ -GoogleDrive.prototype.initLoaded = function() { - if (!loaded) { - window.setTimeout(this.initLoaded.bind(this), 500); - } else { - window.setTimeout(this.checkAuth.bind(this), 1); - } -} - -/** - * Check if the current user has authorized the application. - */ -GoogleDrive.prototype.checkAuth = function() { - - console.log('\tChecking google Auth'); - gapi.auth.authorize({ - 'client_id': this.clientId, - 'scope': SCOPES, - 'immediate': this.useImmediate, - }, - this.handleAuthResult.bind(this)); -}; - -/** - * Called when authorization server replies. - */ -GoogleDrive.prototype.handleAuthResult = function(authResult) { - var self = this; - // console.log('[googleDrive.js.39:authResult:]', authResult); //TODO - - if (authResult.error) { - if (authResult.error) { - self.useImmediate = false; - return this.checkAuth(); - }; - throw new Error(authResult.error); - } - - gapi.client.load('drive', 'v2', function() { - self.isReady = true; - }); -} - -GoogleDrive.prototype.checkReady = function() { - if (!this.isReady) - throw new Error('goggle drive is not ready!'); -}; - -GoogleDrive.prototype._httpGet = function(theUrl) { - var accessToken = gapi.auth.getToken().access_token; - var xmlHttp = null; - - xmlHttp = new XMLHttpRequest(); - xmlHttp.open("GET", theUrl, false); - xmlHttp.setRequestHeader('Authorization', 'Bearer ' + accessToken); - xmlHttp.send(null); - return xmlHttp.responseText; -} - -GoogleDrive.prototype.getItem = function(k, cb) { - console.log('[googleDrive.js.95:getItem:]', k); //TODO - var self = this; - - self.checkReady(); - self._idForName(k, function(kId) { - // console.log('[googleDrive.js.89:kId:]', kId); //TODO - if (!kId) - return cb(null); - - - var args = { - 'path': '/drive/v2/files/' + kId, - 'method': 'GET', - }; - // console.log('[googleDrive.js.95:args:]', args); //TODO - - var request = gapi.client.request(args); - request.execute(function(res) { - // console.log('[googleDrive.js.175:res:]', res); //TODO - if (!res || !res.downloadUrl) - return cb(null); - - return cb(self._httpGet(res.downloadUrl)); - }); - - }); -}; - -GoogleDrive.prototype.setItem = function(k, v, cb) { - // console.log('[googleDrive.js.111:setItem:]', k, v); //TODO - var self = this; - - self.checkReady(); - self._idForName(this.home, function(parentId) { - preconditions.checkState(parentId); - // console.log('[googleDrive.js.118:parentId:]', parentId); //TODO - self._idForName(k, function(kId) { - - // console.log('[googleDrive.js.105]', parentId, kId); //TODO - - - var boundary = '-------314159265358979323846'; - var delimiter = "\r\n--" + boundary + "\r\n"; - var close_delim = "\r\n--" + boundary + "--"; - - var metadata = { - 'title': k, - 'mimeType': 'application/octet-stream', - 'parents': [{ - 'id': parentId - }], - }; - - var base64Data = btoa(v); - var multipartRequestBody = - delimiter + - 'Content-Type: application/json\r\n\r\n' + - JSON.stringify(metadata) + - delimiter + - 'Content-Type: application/octet-stream \r\n' + - 'Content-Transfer-Encoding: base64\r\n' + - '\r\n' + - base64Data + - close_delim; - - var args = { - 'path': '/upload/drive/v2/files' + (kId ? '/' + kId : ''), - 'method': kId ? 'PUT' : 'POST', - 'params': { - 'uploadType': 'multipart', - }, - 'headers': { - 'Content-Type': 'multipart/mixed; boundary="' + boundary + '"' - }, - 'body': multipartRequestBody - } - // console.log('[googleDrive.js.148:args:]', args); //TODO - - var request = gapi.client.request(args); - request.execute(cb); - }); - }); -}; - -GoogleDrive.prototype.removeItem = function(k, cb) { - var self = this; - - self.checkReady(); - self._idForName(this.home, function(parentId) { - preconditions.checkState(parentId); - self._idForName(k, function(kId) { - - var args = { - 'path': '/drive/v2/files/' + kId, - 'method': 'DELETE', - }; - var request = gapi.client.request(args); - request.execute(function() { - if (cb) - cb(); - }); - }); - }); -}; - -GoogleDrive.prototype.clear = function() { - this.checkReady(); - throw new Error('clear not implemented'); -}; - - -GoogleDrive.prototype._mkdir = function(cb) { - preconditions.checkArgument(cb); - var self = this; - - console.log('Creating drive folder ' + this.home); - - var request = gapi.client.request({ - 'path': '/drive/v2/files', - 'method': 'POST', - 'body': JSON.stringify({ - 'title': this.home, - 'mimeType': "application/vnd.google-apps.folder", - }), - }); - request.execute(function() { - self._idForName(self.home, cb); - }); -}; - - -GoogleDrive.prototype._idForName = function(name, cb) { - // console.log('[googleDrive.js.199:_idForName:]', name); //TODO - preconditions.checkArgument(name); - preconditions.checkArgument(cb); - var self = this; - - if (!self.isReady) { - console.log('\tWaiting for Drive'); - self.ts = self.ts * 1.5; - return setTimeout(self._idForName.bind(self, name, cb), self.ts); - } - // console.log('[googleDrive.js.178:name:]', name); //TODO - - if (self.idCache[name]) { - // console.log('[googleDrive.js.212:] FROM CACHE', name, self.idCache[name]); //TODO - return cb(self.idCache[name]); - } - - console.log('Querying for: ', name); //TODO - var args; - - var idParent = name == this.home ? 'root' : self.idCache[this.home]; - - if (!idParent) { - return self._mkdir(function() { - self._idForName(name, cb); - }); - } - // console.log('[googleDrive.js.177:idParent:]', idParent); //TODO - preconditions.checkState(idParent); - - args = { - 'path': '/drive/v2/files', - 'method': 'GET', - 'params': { - 'q': "title='" + name + "' and trashed = false and '" + idParent + "' in parents", - } - }; - - var request = gapi.client.request(args); - request.execute(function(res) { - var i = res.items && res.items[0] ? res.items[0].id : false; - if (i) - self.idCache[name] = i; - // console.log('[googleDrive.js.238] CACHING ' + name + ':' + i); //TODO - return cb(self.idCache[name]); - }); -}; - -GoogleDrive.prototype._checkHomeDir = function(cb) { - var self = this; - - this._idForName(this.home, function(homeId) { - if (!homeId) - return self._mkdir(cb); - - return cb(homeId); - }); -}; - -GoogleDrive.prototype.allKeys = function(cb) { - var self = this; - - this._checkHomeDir(function(homeId) { - preconditions.checkState(homeId); - - var request = gapi.client.request({ - 'path': '/drive/v2/files', - 'method': 'GET', - 'params': { - 'q': "'" + homeId + "' in parents and trashed = false", - 'fields': 'items(id,title)' - }, - }); - request.execute(function(res) { - // console.log('[googleDrive.js.152:res:]', res); //TODO - if (res.error) - throw new Error(res.error.message); - - var ret = []; - for (var ii in res.items) { - ret.push(res.items[ii].title); - } - return cb(ret); - }); - }); -}; - -GoogleDrive.prototype.key = function(k) { - var v = localStorage.key(k); - return v; -}; - - -module.exports = GoogleDrive; From 9ad326cd30a281f9309ec0b378546d3e58e44885 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Thu, 4 Sep 2014 16:23:37 -0300 Subject: [PATCH 10/45] working! --- config.js | 8 +++++--- js/controllers/home.js | 4 ++-- js/controllers/open.js | 2 ++ js/models/Storage.js | 11 ----------- js/services/walletFactory.js | 2 -- plugins/LocalStorage.js | 1 - views/home.html | 6 +++++- views/open.html | 8 ++++++-- 8 files changed, 20 insertions(+), 22 deletions(-) diff --git a/config.js b/config.js index 94dc2a829..7b67351bd 100644 --- a/config.js +++ b/config.js @@ -53,12 +53,14 @@ var defaultConfig = { verbose: 1, plugins: { -// LocalStorage: true, - GoogleDrive: true, + LocalStorage: true, + // GoogleDrive: true, }, GoogleDrive: { - clientId: '232630733383-29u1khqf5i8qubhf0homhpb2m14b5lja.apps.googleusercontent.com', + // for localhost: + clientId: '232630733383-a35gcnovnkgka94394i88gq60vtjb4af.apps.googleusercontent.com', + // clientId: '232630733383-29u1khqf5i8qubhf0homhpb2m14b5lja.apps.googleusercontent.com', home: 'copay' }, }; diff --git a/js/controllers/home.js b/js/controllers/home.js index c8a73d862..b0d325448 100644 --- a/js/controllers/home.js +++ b/js/controllers/home.js @@ -4,10 +4,10 @@ angular.module('copayApp.controllers').controller('HomeController', function($sc controllerUtils.redirIfLogged(); - $scope.loading = true; + $scope.retreiving = true; walletFactory.getWallets(function(ret) { - $scope.loading = false; + $scope.retreiving = false; $scope.hasWallets = (ret && ret.length > 0) ? true : false; }); }); diff --git a/js/controllers/open.js b/js/controllers/open.js index 403f4f9fd..e06519e1f 100644 --- a/js/controllers/open.js +++ b/js/controllers/open.js @@ -14,6 +14,7 @@ angular.module('copayApp.controllers').controller('OpenController', function($sc }; $rootScope.fromSetup = false; $scope.loading = false; + $scope.retreiving = true; walletFactory.getWallets(function(wallets) { $scope.wallets = wallets.sort(cmp); @@ -23,6 +24,7 @@ angular.module('copayApp.controllers').controller('OpenController', function($sc walletFactory.storage.getLastOpened(function(ret) { $scope.selectedWalletId = ret || ($scope.wallets[0] && $scope.wallets[0].id); + $scope.retreiving = false; }); }); diff --git a/js/models/Storage.js b/js/models/Storage.js index e23ab530d..f4e19a350 100644 --- a/js/models/Storage.js +++ b/js/models/Storage.js @@ -83,7 +83,6 @@ Storage.prototype.getGlobal = function(k, cb) { preconditions.checkArgument(cb); this.storage.getItem(k, function(item) { -console.log('[Storage.js.96:item:]',item); //TODO cb(item == 'undefined' ? undefined : item); }); }; @@ -121,9 +120,7 @@ Storage.prototype.get = function(walletId, k, cb) { Storage.prototype._readHelper = function(walletId, k, cb) { -console.log('[Storage.js.134:walletId:]',walletId,k); //TODO var wk = this._key(walletId, k); - this._read(wk, function(v){ return cb(v,k); }); @@ -141,10 +138,7 @@ console.log('[Storage.js.142:keys:]',keys); //TODO for (var ii in keys) { this._readHelper(walletId, keys[ii], function(v, k) { ret[k] = v; -console.log('[Storage.js.144:ret:]',k,i,l,v); //TODO if (++i == l) { - -console.log('[Storage.js.157] LKIST', ret); //TODO return cb(ret); } }); @@ -174,11 +168,9 @@ Storage.prototype.getWalletIds = function(cb) { var uniq = {}; this.storage.allKeys(function(keys) { -console.log('[Storage.js.170:keys:]',keys); //TODO for (var ii in keys) { var key = keys[ii]; -console.log('[Storage.js.174:key:]',key); //TODO var split = key.split('::'); if (split.length == 2) { var walletId = split[0]; @@ -201,20 +193,17 @@ Storage.prototype.getWallets = function(cb) { var self = this; this.getWalletIds(function(ids) { -console.log('[Storage.js.197:ids:]',ids); //TODO var l = ids.length, i=0; if (!l) return cb([]); for (var ii in ids) { var id = ids[ii]; -console.log('[Storage.js.206:id:]',id); //TODO self.getName(id, function(name) { wallets.push({ id: id, name: name, }); -console.log('[Storage.js.208:wallets:]',wallets); //TODO if (++i == l) { return cb(wallets); } diff --git a/js/services/walletFactory.js b/js/services/walletFactory.js index 7a6b96ea6..a592470d2 100644 --- a/js/services/walletFactory.js +++ b/js/services/walletFactory.js @@ -1,7 +1,5 @@ 'use strict'; angular.module('copayApp.services').factory('walletFactory', function(pluginManager){ - -console.log('[walletFactory.js.3]'); //TODO return new copay.WalletFactory(config, copay.version, pluginManager); }); diff --git a/plugins/LocalStorage.js b/plugins/LocalStorage.js index a811cfcf4..0035fc12b 100644 --- a/plugins/LocalStorage.js +++ b/plugins/LocalStorage.js @@ -5,7 +5,6 @@ function LocalStorage() { }; LocalStorage.prototype.init = function() { - console.log(' init LocalStorage'); //TODO }; diff --git a/views/home.html b/views/home.html index 972b2618c..7018435e9 100644 --- a/views/home.html +++ b/views/home.html @@ -1,5 +1,9 @@
-
+
+ + Retreiving information from storage... +
+
Copay
diff --git a/views/open.html b/views/open.html index 8cf125ff2..e7ca352a1 100644 --- a/views/open.html +++ b/views/open.html @@ -1,9 +1,13 @@
-
+
+ + Retreiving information from storage... +
+
Connecting...
-
+
Copay
From e0db19a40a787929a2ee5c214e336ba4f63bcf9b Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Thu, 4 Sep 2014 16:38:22 -0300 Subject: [PATCH 11/45] rebased --- js/models/Storage.js | 1 - 1 file changed, 1 deletion(-) diff --git a/js/models/Storage.js b/js/models/Storage.js index f4e19a350..b9cb9fa75 100644 --- a/js/models/Storage.js +++ b/js/models/Storage.js @@ -168,7 +168,6 @@ Storage.prototype.getWalletIds = function(cb) { var uniq = {}; this.storage.allKeys(function(keys) { - for (var ii in keys) { var key = keys[ii]; var split = key.split('::'); From b3ed2a2ea82a174dbd5e3997423585b956333387 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Thu, 4 Sep 2014 18:07:09 -0300 Subject: [PATCH 12/45] start fixing tests --- js/models/Storage.js | 18 +++++- js/models/core/WalletLock.js | 1 - test/mocks/FakeLocalStorage.js | 17 +++--- test/test.Storage.js | 105 +++++++++++++++++++++------------ 4 files changed, 89 insertions(+), 52 deletions(-) diff --git a/js/models/Storage.js b/js/models/Storage.js index b9cb9fa75..4d24928f7 100644 --- a/js/models/Storage.js +++ b/js/models/Storage.js @@ -3,6 +3,8 @@ var preconditions = require('preconditions').singleton(); var CryptoJS = require('node-cryptojs-aes').CryptoJS; var bitcore = require('bitcore'); var preconditions = require('preconditions').instance(); +var _ = require('underscore'); + var id = 0; function Storage(opts) { @@ -19,14 +21,14 @@ function Storage(opts) { console.log('Error in storage:', e); //TODO }; - preconditions.checkState(this.localStorage, 'No localstorage found'); - preconditions.checkState(this.sessionStorage, 'No sessionStorage found'); + preconditions.checkState(this.storage, 'No storage defined'); + preconditions.checkState(this.sessionStorage, 'No sessionStorage defined'); } var pps = {}; Storage.prototype._getPassphrase = function() { if (!pps[this.__uniqueid]) - throw new Error('No passprase set'); + throw new Error('NOPASSPHRASE: No passphrase set'); return pps[this.__uniqueid]; } @@ -147,23 +149,29 @@ console.log('[Storage.js.142:keys:]',keys); //TODO // set value for key Storage.prototype.set = function(walletId, k, v, cb) { + preconditions.checkArgument(walletId && k && !_.isUndefined(v) && cb); + this._write(this._key(walletId, k), v, cb); }; // remove value for key Storage.prototype.remove = function(walletId, k, cb) { + preconditions.checkArgument(walletId && k && cb); this.removeGlobal(this._key(walletId, k), cb); }; Storage.prototype.setName = function(walletId, name, cb) { + preconditions.checkArgument(walletId && name && cb); this.setGlobal('nameFor::' + walletId, name, cb); }; Storage.prototype.getName = function(walletId, cb) { + preconditions.checkArgument(walletId && cb); this.getGlobal('nameFor::' + walletId, cb); }; Storage.prototype.getWalletIds = function(cb) { + preconditions.checkArgument(cb); var walletIds = []; var uniq = {}; @@ -188,6 +196,8 @@ Storage.prototype.getWalletIds = function(cb) { }; Storage.prototype.getWallets = function(cb) { + preconditions.checkArgument(cb); + var wallets = []; var self = this; @@ -212,6 +222,8 @@ Storage.prototype.getWallets = function(cb) { }; Storage.prototype.deleteWallet = function(walletId) { + preconditions.checkArgument(walletId); + var toDelete = {}; toDelete['nameFor::' + walletId] = 1; diff --git a/js/models/core/WalletLock.js b/js/models/core/WalletLock.js index a8a1729b7..66e2458d2 100644 --- a/js/models/core/WalletLock.js +++ b/js/models/core/WalletLock.js @@ -20,7 +20,6 @@ WalletLock._keyFor = function(walletId) { WalletLock.prototype._isLockedByOther = function(cb) { var self = this; - console.log('[WalletLock.js.22]'); //TODO this.storage.getGlobal(this.key, function(json) { var wl = json ? JSON.parse(json) : null; var t = wl ? (Date.now() - wl.expireTs) : false; diff --git a/test/mocks/FakeLocalStorage.js b/test/mocks/FakeLocalStorage.js index e39280719..a276abaec 100644 --- a/test/mocks/FakeLocalStorage.js +++ b/test/mocks/FakeLocalStorage.js @@ -1,27 +1,26 @@ //localstorage Mock ls = {}; -function LocalStorage(opts) {} +function LocalStorage(opts) { +} FakeLocalStorage = {}; FakeLocalStorage.length = 0; FakeLocalStorage.removeItem = function(key) { delete ls[key]; - this.length = Object.keys(ls).length; }; -FakeLocalStorage.getItem = function(k) { - return ls[k]; +FakeLocalStorage.getItem = function(k,cb) { + return cb(ls[k]); }; -FakeLocalStorage.key = function(i) { - return Object.keys(ls)[i]; +FakeLocalStorage.allKeys = function(cb) { + return cb(Object.keys(ls)); }; -FakeLocalStorage.setItem = function(k, v) { +FakeLocalStorage.setItem = function(k, v,cb) { ls[k] = v; - this.key[this.length] = k; - this.length = Object.keys(ls).length; + return cb(); }; module.exports = FakeLocalStorage; diff --git a/test/test.Storage.js b/test/test.Storage.js index 0ad668bff..fd03c8cee 100644 --- a/test/test.Storage.js +++ b/test/test.Storage.js @@ -26,22 +26,29 @@ describe('Storage model', function() { should.exist(s2); }); it('should fail when encrypting without a password', function() { + var s2 = new Storage({ storage: localMock, sessionStorage: sessionMock, }); (function() { - s2.set(fakeWallet, timeStamp, 1); - }).should.throw(); + s2.set(fakeWallet, timeStamp, 1, function() {}); + }).should.throw('NOPASSPHRASE'); }); - it('should be able to encrypt and decrypt', function() { - s._write(fakeWallet + timeStamp, 'value'); - s._read(fakeWallet + timeStamp).should.equal('value'); - localMock.removeItem(fakeWallet + timeStamp); + it('should be able to encrypt and decrypt', function(done) { + s._write(fakeWallet + timeStamp, 'value', function() { + s._read(fakeWallet + timeStamp, function(v) { + v.should.equal('value'); + localMock.removeItem(fakeWallet + timeStamp); + done(); + }); + }); }); - it('should be able to set a value', function() { - s.set(fakeWallet, timeStamp, 1); - localMock.removeItem(fakeWallet + '::' + timeStamp); + it('should be able to set a value', function(done) { + s.set(fakeWallet, timeStamp, 1, function() { + localMock.removeItem(fakeWallet + '::' + timeStamp); + done(); + }); }); var getSetData = [ 1, 1000, -15, -1000, @@ -62,81 +69,101 @@ describe('Storage model', function() { ]; getSetData.forEach(function(obj) { it('should be able to set a value and get it for ' + JSON.stringify(obj), function() { - s.set(fakeWallet, timeStamp, obj); - var obj2 = s.get(fakeWallet, timeStamp); - JSON.stringify(obj2).should.equal(JSON.stringify(obj)); - localMock.removeItem(fakeWallet + '::' + timeStamp); + s.set(fakeWallet, timeStamp, obj, function() { + s.get(fakeWallet, timeStamp, function(obj2) { + JSON.stringify(obj2).should.equal(JSON.stringify(obj)); + localMock.removeItem(fakeWallet + '::' + timeStamp); + }); + }); }); }); describe('#export', function() { - it('should export the encrypted wallet', function() { + it('should export the encrypted wallet', function(done) { var storage = new Storage({ storage: localMock, sessionStorage: sessionMock, password: 'password', }); - storage.set(fakeWallet, timeStamp, 'testval'); - var obj = { - test: 'testval' - }; - var encrypted = storage.export(obj); - encrypted.length.should.be.greaterThan(10); - localMock.removeItem(fakeWallet + '::' + timeStamp); - //encrypted.slice(0,6).should.equal("53616c"); + storage.set(fakeWallet, timeStamp, 'testval', function() { + var obj = { + test: 'testval' + }; + var encrypted = storage.export(obj); + encrypted.length.should.be.greaterThan(10); + localMock.removeItem(fakeWallet + '::' + timeStamp); + done(); + + }); }); }); - describe('#remove', function() { + describe('#remove', function(done) { it('should remove an item', function() { var s = new Storage({ storage: localMock, sessionStorage: sessionMock, password: 'password' }); - s.set('1', "hola", 'juan'); - s.get('1', 'hola').should.equal('juan'); - s.remove('1', 'hola'); - - should.not.exist(s.get('1', 'hola')); + s.set('1', "hola", 'juan', function() { + s.get('1', 'hola', function(v) { + v.should.equal('juan'); + s.remove('1', 'hola', function() { + should.not.exist(s.get('1', 'hola')); + done(); + }); + }) + }) }); }); describe('#getWalletIds', function() { - it('should get wallet ids', function() { + it('should get wallet ids', function(done) { var s = new Storage({ storage: localMock, sessionStorage: sessionMock, password: 'password' }); - s.set('1', "hola", 'juan'); - s.set('2', "hola", 'juan'); - s.getWalletIds().should.deep.equal(['1', '2']); + s.set('1', "hola", 'juan', function() { + s.set('2', "hola", 'juan', function() { + s.getWalletIds(function(v) { + v.should.deep.equal(['1', '2']); + done(); + }); + }); + }); }); }); describe('#getName #setName', function() { - it('should get/set names', function() { + it('should get/set names', function(done) { var s = new Storage({ storage: localMock, sessionStorage: sessionMock, password: 'password' }); - s.setName(1, 'hola'); - s.getName(1).should.equal('hola'); + s.setName(1, 'hola', function() { + s.getName(1, function(v) { + v.should.equal('hola'); + done(); + }); + }); }); }); describe('#getLastOpened #setLastOpened', function() { - it('should get/set names', function() { + it('should get/set last opened', function() { var s = new Storage({ storage: localMock, sessionStorage: sessionMock, password: 'password' }); - s.setLastOpened('hey'); - s.getLastOpened().should.equal('hey'); + s.setLastOpened('hey', function() { + s.getLastOpened(function(v) { + v.should.equal('hey'); + }); + }); }); }); @@ -243,7 +270,7 @@ describe('Storage model', function() { password: 'password' }); s.getSessionId().length.should.equal(16); - (new Buffer(s.getSessionId(),'hex')).length.should.equal(8); + (new Buffer(s.getSessionId(), 'hex')).length.should.equal(8); }); }); }); From f1e6d6cfc6d0c973afd8afbadfbb2774e7981968 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 8 Sep 2014 10:46:57 -0300 Subject: [PATCH 13/45] fix walletLock test --- js/models/Storage.js | 58 ++++++++------ js/models/core/WalletFactory.js | 5 ++ js/models/core/WalletLock.js | 51 ++++++++++--- test/mocks/FakeLocalStorage.js | 3 +- test/mocks/FakeStorage.js | 62 ++++++++------- test/test.Storage.js | 130 +++++++++++++++++++------------- test/test.WalletFactory.js | 17 +++-- test/test.WalletLock.js | 102 ++++++++++++++++--------- 8 files changed, 272 insertions(+), 156 deletions(-) diff --git a/js/models/Storage.js b/js/models/Storage.js index 4d24928f7..4d842e431 100644 --- a/js/models/Storage.js +++ b/js/models/Storage.js @@ -99,17 +99,22 @@ Storage.prototype.setGlobal = function(k, v, cb) { // remove value for key Storage.prototype.removeGlobal = function(k, cb) { preconditions.checkArgument(cb); - this.storage.removeItem(k, cb); }; -Storage.prototype.getSessionId = function() { - var sessionId = this.sessionStorage.getItem('sessionId'); - if (!sessionId) { +Storage.prototype.getSessionId = function(cb) { + preconditions.checkArgument(cb); + var self = this; + + self.sessionStorage.getItem('sessionId', function(sessionId) { + if (sessionId) + return cb(sessionId); + sessionId = bitcore.SecureRandom.getRandomBuffer(8).toString('hex'); - this.sessionStorage.setItem('sessionId', sessionId); - } - return sessionId; + self.sessionStorage.setItem('sessionId', sessionId, function(){ + return cb(sessionId); + }); + }); }; Storage.prototype._key = function(walletId, k) { @@ -117,14 +122,15 @@ Storage.prototype._key = function(walletId, k) { }; // get value by key Storage.prototype.get = function(walletId, k, cb) { + preconditions.checkArgument(walletId, k, cb); this._read(this._key(walletId, k), cb); }; Storage.prototype._readHelper = function(walletId, k, cb) { var wk = this._key(walletId, k); - this._read(wk, function(v){ - return cb(v,k); + this._read(wk, function(v) { + return cb(v, k); }); }; @@ -133,15 +139,15 @@ Storage.prototype.getMany = function(walletId, keys, cb) { var self = this; var ret = {}; -console.log('[Storage.js.142:keys:]',keys); //TODO - var l = keys.length, i=0; + var l = keys.length, + i = 0; for (var ii in keys) { this._readHelper(walletId, keys[ii], function(v, k) { ret[k] = v; if (++i == l) { - return cb(ret); + return cb(ret); } }); } @@ -202,7 +208,8 @@ Storage.prototype.getWallets = function(cb) { var self = this; this.getWalletIds(function(ids) { - var l = ids.length, i=0; + var l = ids.length, + i = 0; if (!l) return cb([]); @@ -221,21 +228,29 @@ Storage.prototype.getWallets = function(cb) { }); }; -Storage.prototype.deleteWallet = function(walletId) { +Storage.prototype.deleteWallet = function(walletId, cb) { preconditions.checkArgument(walletId); + preconditions.checkArgument(cb); var toDelete = {}; toDelete['nameFor::' + walletId] = 1; - for (var i = 0; i < this.storage.length; i++) { - var key = this.storage.key(i); - var split = key.split('::'); - if (split.length == 2 && split[0] === walletId) { - toDelete[key] = 1; + this.storage.allKeys(function(allKeys) { + for (var key in allKeys) { + var split = key.split('::'); + if (split.length == 2 && split[0] === walletId) { + toDelete[key] = 1; + }; } - } + }); + + var l = toDelete.length, + i = 0; for (var i in toDelete) { - this.removeGlobal(i); + this.removeGlobal(i, function() { + if (++i == l) + return cb(); + }); } }; @@ -255,7 +270,6 @@ Storage.prototype.setFromObj = function(walletId, obj, cb) { var l = Object.keys(obj).length, i = 0; for (var k in obj) { - console.log('[Storage.js.247]', k, i, l); //TODO self.set(walletId, k, obj[k], function() { if (++i == l) { self.setName(walletId, obj.opts.name, cb); diff --git a/js/models/core/WalletFactory.js b/js/models/core/WalletFactory.js index 18d5ed063..eb0c432af 100644 --- a/js/models/core/WalletFactory.js +++ b/js/models/core/WalletFactory.js @@ -182,6 +182,8 @@ WalletFactory.prototype.read = function(walletId, skipFields, cb) { * @return {Wallet} */ WalletFactory.prototype.create = function(opts, cb) { + preconditions.checkArgument(cb); + opts = opts || {}; opts.networkName = opts.networkName || 'testnet'; @@ -229,6 +231,7 @@ WalletFactory.prototype.create = function(opts, cb) { opts.totalCopayers = totalCopayers; opts.version = opts.version || this.version; +console.log('[WalletFactory.js.165]'); //TODO var w = new Wallet(opts); var self = this; w.store(function() { @@ -266,6 +269,7 @@ WalletFactory.prototype._checkVersion = function(inVersion) { * @return */ WalletFactory.prototype.open = function(walletId, passphrase, cb) { + preconditions.checkArgument(cb); var self = this, err; self.storage._setPassphrase(passphrase); @@ -334,6 +338,7 @@ WalletFactory.prototype.decodeSecret = function(secret) { * @param {walletCreationCallback} cb - a callback */ WalletFactory.prototype.joinCreateSession = function(secret, nickname, passphrase, privateHex, cb) { + preconditions.checkArgument(cb); var self = this; var decodedSecret = this.decodeSecret(secret); if (!decodedSecret || !decodedSecret.networkName || !decodedSecret.pubKey) { diff --git a/js/models/core/WalletLock.js b/js/models/core/WalletLock.js index 66e2458d2..fa449b855 100644 --- a/js/models/core/WalletLock.js +++ b/js/models/core/WalletLock.js @@ -6,13 +6,24 @@ function WalletLock(storage, walletId, timeoutMin) { preconditions.checkArgument(storage); preconditions.checkArgument(walletId); - this.sessionId = storage.getSessionId(); this.storage = storage; this.timeoutMin = timeoutMin || 5; this.key = WalletLock._keyFor(walletId); - // this._setLock(function() {}); } + +WalletLock.prototype.init = function(cb) { + preconditions.checkArgument(cb); + var self = this; + + self.storage.getSessionId(function(sid) { + preconditions.checkState(sid); + + self.sessionId = sid; + cb(); + }); +}; + WalletLock._keyFor = function(walletId) { return 'lock' + '::' + walletId; }; @@ -22,18 +33,27 @@ WalletLock.prototype._isLockedByOther = function(cb) { this.storage.getGlobal(this.key, function(json) { var wl = json ? JSON.parse(json) : null; - var t = wl ? (Date.now() - wl.expireTs) : false; - // is not locked? - if (!wl || t > 0 || wl.sessionId === self.sessionId) + if (!wl || !wl.expireTs) + return cb(false); + + var expiredSince = Date.now() - wl.expireTs; + if (expiredSince >= 0) + return cb(false); + + var isMyself = wl.sessionId === self.sessionId; + + if (isMyself) return cb(false); // Seconds remainding - return cb(parseInt(-t / 1000.)); + return cb(parseInt(-expiredSince / 1000)); }); }; WalletLock.prototype._setLock = function(cb) { + preconditions.checkArgument(cb); + preconditions.checkState(this.sessionId); this.storage.setGlobal(this.key, { sessionId: this.sessionId, @@ -44,20 +64,33 @@ WalletLock.prototype._setLock = function(cb) { }; -WalletLock.prototype.keepAlive = function(cb) { +WalletLock.prototype._doKeepAlive = function(cb) { + preconditions.checkArgument(cb); preconditions.checkState(this.sessionId); + var self = this; this._isLockedByOther(function(t) { - if (t) - return cb(new Error('Wallet is already open. Close it to proceed or wait ' + t + ' seconds if you close it already')); + return cb(new Error('LOCKED: Wallet is locked for ' + t + ' srcs')); self._setLock(cb); }); }; + +WalletLock.prototype.keepAlive = function(cb) { + var self = this; + + if (!self.sessionId) { + return self.init(self._doKeepAlive.bind(self, cb)); + }; + + return this._doKeepAlive(cb); +}; + + WalletLock.prototype.release = function(cb) { this.storage.removeGlobal(this.key, cb); }; diff --git a/test/mocks/FakeLocalStorage.js b/test/mocks/FakeLocalStorage.js index a276abaec..fba5e7dfd 100644 --- a/test/mocks/FakeLocalStorage.js +++ b/test/mocks/FakeLocalStorage.js @@ -5,8 +5,9 @@ function LocalStorage(opts) { FakeLocalStorage = {}; FakeLocalStorage.length = 0; -FakeLocalStorage.removeItem = function(key) { +FakeLocalStorage.removeItem = function(key,cb) { delete ls[key]; + cb(); }; FakeLocalStorage.getItem = function(k,cb) { diff --git a/test/mocks/FakeStorage.js b/test/mocks/FakeStorage.js index 9aea4d2ea..39a4b2ade 100644 --- a/test/mocks/FakeStorage.js +++ b/test/mocks/FakeStorage.js @@ -11,57 +11,65 @@ FakeStorage.prototype._setPassphrase = function(password) { this.storage.passphrase = password; }; -FakeStorage.prototype.setGlobal = function(id, v) { +FakeStorage.prototype.setGlobal = function(id, v, cb) { this.storage[id] = typeof v === 'object' ? JSON.stringify(v) : v; + cb(); }; -FakeStorage.prototype.getGlobal = function(id) { - return this.storage[id]; +FakeStorage.prototype.getGlobal = function(id, cb) { + return cb(this.storage[id]); }; -FakeStorage.prototype.setLastOpened = function(val) { +FakeStorage.prototype.setLastOpened = function(val, cb) { this.storage['lastOpened'] = val; + return cb(); }; -FakeStorage.prototype.getLastOpened = function() { - return this.storage['lastOpened']; +FakeStorage.prototype.getLastOpened = function(cb) { + return cb(this.storage['lastOpened']); }; FakeStorage.prototype.setLock = function(id) { this.storage[id + '::lock'] = true; + return cb(); } -FakeStorage.prototype.getLock = function(id) { - return this.storage[id + '::lock']; +FakeStorage.prototype.getLock = function(id,cb) { + return cb(this.storage[id + '::lock']); } -FakeStorage.prototype.getSessionId = function() { - return this.sessionId || 'aSessionId'; +FakeStorage.prototype.getSessionId = function(cb) { + this.sessionId = this.sessionId || 'aSessionId'; + return cb(this.sessionId); }; -FakeStorage.prototype.removeLock = function(id) { +FakeStorage.prototype.removeLock = function(id,cb) { delete this.storage[id + '::lock']; + cb(); } -FakeStorage.prototype.removeGlobal = function(id) { +FakeStorage.prototype.removeGlobal = function(id,cb) { delete this.storage[id]; + cb(); }; -FakeStorage.prototype.set = function(wid, id, payload) { +FakeStorage.prototype.set = function(wid, id, payload, cb) { this.storage[wid + '::' + id] = payload; + if (cb) return cb(); }; -FakeStorage.prototype.get = function(wid, id) { - return this.storage[wid + '::' + id]; +FakeStorage.prototype.get = function(wid, id, cb) { + return cb(this.storage[wid + '::' + id]); }; -FakeStorage.prototype.clear = function() { +FakeStorage.prototype.clear = function(cb) { delete this['storage']; + cb(); }; -FakeStorage.prototype.getWalletIds = function() { +FakeStorage.prototype.getWalletIds = function(cb) { var walletIds = []; var uniq = {}; @@ -79,10 +87,10 @@ FakeStorage.prototype.getWalletIds = function() { } } } - return walletIds; + return cb(walletIds); }; -FakeStorage.prototype.deleteWallet = function(walletId) { +FakeStorage.prototype.deleteWallet = function(walletId, cb) { var toDelete = {}; toDelete['nameFor::' + walletId] = 1; @@ -98,17 +106,17 @@ FakeStorage.prototype.deleteWallet = function(walletId) { }; -FakeStorage.prototype.getName = function(walletId) { - return this.getGlobal('nameFor::' + walletId); +FakeStorage.prototype.getName = function(walletId,cb) { + return this.getGlobal('nameFor::' + walletId,cb); }; -FakeStorage.prototype.setName = function(walletId, name) { - this.setGlobal('nameFor::' + walletId, name); +FakeStorage.prototype.setName = function(walletId, name, cb) { + this.setGlobal('nameFor::' + walletId, name, cb); }; -FakeStorage.prototype.getWallets = function() { +FakeStorage.prototype.getWallets = function(cb) { var wallets = []; var ids = this.getWalletIds(); @@ -118,14 +126,14 @@ FakeStorage.prototype.getWallets = function() { name: this.getName(ids[i]), }); } - return wallets; + return cb(wallets); }; -FakeStorage.prototype.setFromObj = function(walletId, obj) { +FakeStorage.prototype.setFromObj = function(walletId, obj, cb) { for (var k in obj) { this.set(walletId, k, obj[k]); } - this.setName(walletId, obj.opts.name); + this.setName(walletId, obj.opts.name, cb); }; module.exports = FakeStorage; diff --git a/test/test.Storage.js b/test/test.Storage.js index fd03c8cee..0363108ab 100644 --- a/test/test.Storage.js +++ b/test/test.Storage.js @@ -39,15 +39,13 @@ describe('Storage model', function() { s._write(fakeWallet + timeStamp, 'value', function() { s._read(fakeWallet + timeStamp, function(v) { v.should.equal('value'); - localMock.removeItem(fakeWallet + timeStamp); - done(); + localMock.removeItem(fakeWallet + timeStamp, done); }); }); }); it('should be able to set a value', function(done) { s.set(fakeWallet, timeStamp, 1, function() { - localMock.removeItem(fakeWallet + '::' + timeStamp); - done(); + localMock.removeItem(fakeWallet + '::' + timeStamp, done); }); }); var getSetData = [ @@ -68,11 +66,11 @@ describe('Storage model', function() { null ]; getSetData.forEach(function(obj) { - it('should be able to set a value and get it for ' + JSON.stringify(obj), function() { + it('should be able to set a value and get it for ' + JSON.stringify(obj), function(done) { s.set(fakeWallet, timeStamp, obj, function() { s.get(fakeWallet, timeStamp, function(obj2) { JSON.stringify(obj2).should.equal(JSON.stringify(obj)); - localMock.removeItem(fakeWallet + '::' + timeStamp); + localMock.removeItem(fakeWallet + '::' + timeStamp, done); }); }); }); @@ -91,15 +89,13 @@ describe('Storage model', function() { }; var encrypted = storage.export(obj); encrypted.length.should.be.greaterThan(10); - localMock.removeItem(fakeWallet + '::' + timeStamp); - done(); - + localMock.removeItem(fakeWallet + '::' + timeStamp, done); }); }); }); - describe('#remove', function(done) { - it('should remove an item', function() { + describe('#remove', function() { + it('should remove an item', function(done) { var s = new Storage({ storage: localMock, sessionStorage: sessionMock, @@ -109,8 +105,10 @@ describe('Storage model', function() { s.get('1', 'hola', function(v) { v.should.equal('juan'); s.remove('1', 'hola', function() { - should.not.exist(s.get('1', 'hola')); - done(); + s.get('1', 'hola', function(v) { + should.not.exist(v); + done(); + }); }); }) }) @@ -169,62 +167,75 @@ describe('Storage model', function() { if (is_browser) { describe('#getSessionId', function() { - it('should get SessionId', function() { + it('should get SessionId', function(done) { var s = new Storage({ storage: localMock, sessionStorage: sessionMock, password: 'password' }); - var sid = s.getSessionId(); - should.exist(sid); - var sid2 = s.getSessionId(); - sid2.should.equal(sid); + s.getSessionId(function(sid) { + should.exist(sid); + s.getSessionId(function(sid2) { + sid2.should.equal(sid); + done(); + }); + }); }); }); } describe('#getWallets', function() { - it('should retreive wallets from storage', function() { + it('should retreive wallets from storage', function(done) { var s = new Storage({ storage: localMock, sessionStorage: sessionMock, password: 'password' }); - s.set('1', "hola", 'juan'); - s.set('2', "hola", 'juan'); - s.setName(1, 'hola'); - s.getWallets()[0].should.deep.equal({ - id: '1', - name: 'hola', - }); - s.getWallets()[1].should.deep.equal({ - id: '2', - name: undefined + s.set('1', "hola", 'juan', function() { + s.set('2', "hola", 'juan', function() { + s.setName(1, 'hola', function() { + s.getWallets(function(ws) { + ws[0].should.deep.equal({ + id: '1', + name: 'hola', + }); + ws[1].should.deep.equal({ + id: '2', + name: undefined + }); + done(); + }); + }); + }); }); }); }); - describe('#deleteWallet', function() { + describe('#deleteWallet', function(done) { it('should delete a wallet', function() { var s = new Storage({ storage: localMock, sessionStorage: sessionMock, password: 'password' }); - s.set('1', "hola", 'juan'); - s.set('2', "hola", 'juan'); - s.setName(1, 'hola'); - - s.deleteWallet('1'); - s.getWallets().length.should.equal(1); - s.getWallets()[0].should.deep.equal({ - id: '2', - name: undefined + s.set('1', "hola", 'juan', function() { + s.set('2', "hola", 'juan', function() { + s.deleteWallet('1', function() { + s.getWallets(function(ws) { + s.getWallets().length.should.equal(1); + ws[0].should.deep.equal({ + id: '2', + name: undefined + }); + done(); + }); + }); + }); }); }); }); describe('#setFromObj', function() { - it('set localstorage from an object', function() { + it('set localstorage from an object', function(done) { var s = new Storage({ storage: localMock, sessionStorage: sessionMock, @@ -235,42 +246,57 @@ describe('Storage model', function() { 'opts': { 'name': 'nameid1' }, + }, function() { + s.get('id1', 'key', function(v) { + v.should.equal('val'); + done(); + }); }); - - s.get('id1', 'key').should.equal('val'); - }); }); describe('#globals', function() { - it('should set, get and remove keys', function() { + it('should set, get and remove keys', function(done) { var s = new Storage({ storage: localMock, sessionStorage: sessionMock, password: 'password' }); + s.setGlobal('a', { b: 1 + }, function() { + s.getGlobal('a', function(v) { + + JSON.parse(v).should.deep.equal({ + b: 1 + }); + s.removeGlobal('a', function() { + s.getGlobal('a', function(v) { + should.not.exist(v); + done(); + }); + }); + }); }); - JSON.parse(s.getGlobal('a')).should.deep.equal({ - b: 1 - }); - s.removeGlobal('a'); - should.not.exist(s.getGlobal('a')); }); }); describe('session storage', function() { - it('should get a session ID', function() { + it('should get a session ID', function(done) { var s = new Storage({ storage: localMock, sessionStorage: sessionMock, password: 'password' }); - s.getSessionId().length.should.equal(16); - (new Buffer(s.getSessionId(), 'hex')).length.should.equal(8); + s.getSessionId(function(s) { + should.exist(s); + s.length.should.equal(16); + (new Buffer(s, 'hex')).length.should.equal(8); + done(); + }); }); }); }); diff --git a/test/test.WalletFactory.js b/test/test.WalletFactory.js index 8712c4121..f736c339f 100644 --- a/test/test.WalletFactory.js +++ b/test/test.WalletFactory.js @@ -117,16 +117,17 @@ describe('WalletFactory model', function() { wf.version.should.equal('0.0.1'); }); - 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() { + it('should be able to create wallets', function(done) { var wf = new WalletFactory(config, '0.0.1'); - var w = wf.create(); - should.exist(w); + wf.create(null, function(err, w) { + +console.log('[test.WalletFactory.js.123]'); //TODO + should.not.exist(err); + should.exist(w); + w.should.be.instanceof('WalletFactory'); + done(); + }); }); it('should be able to create wallets with given pk', function() { diff --git a/test/test.WalletLock.js b/test/test.WalletLock.js index f3ccf051d..e8e418a96 100644 --- a/test/test.WalletLock.js +++ b/test/test.WalletLock.js @@ -15,8 +15,11 @@ var WalletLock = copay.WalletLock; var PrivateKey = copay.PrivateKey; var Storage = require('./mocks/FakeStorage'); +var storage; describe('WalletLock model', function() { - var storage = new Storage(); + beforeEach(function() { + storage = new Storage(); + }); it('should fail with missing args', function() { (function() { @@ -36,45 +39,70 @@ describe('WalletLock model', function() { should.exist(w); }); - it('should NOT fail if locked already', function() { - var w = new WalletLock(storage, 'walletId'); - storage.sessionId = 'xxx'; - var w2= new WalletLock(storage, 'walletId'); - should.exist(w2); + + it('should generate a sessionId with init', function(done) { + var w = new WalletLock(storage, 'id'); + var spy = sinon.spy(storage, 'getSessionId'); + w.init(function() { + spy.calledOnce.should.equal(true); + done(); + }); }); - it('should change status of previously openned wallet', function() { + it('#keepAlive should call getsessionId if not called before', function(done) { + var w = new WalletLock(storage, 'id'); + var spy = sinon.spy(storage, 'getSessionId'); + w.keepAlive(function() { + spy.calledOnce.should.equal(true); + done(); + }); + }); + + it('should NOT fail if locked already by me', function(done) { + var w = new WalletLock(storage, 'walletId2'); + w.keepAlive(function() { + var w2 = new WalletLock(storage, 'walletId2'); + w2.init(function() { + w2.keepAlive(function() { + w.sessionId.should.equal(w2.sessionId); + should.exist(w2); + done(); + }); + }); + }) + }); + + it('should FAIL if locked by someone else', function(done) { storage.sessionId = 'session1'; var w = new WalletLock(storage, 'walletId'); - storage.sessionId = 'xxx'; - var w2= new WalletLock(storage, 'walletId'); - w2.keepAlive(); - (function() {w.keepAlive();}).should.throw('already open'); - - }); - - - it('should not fail if locked by me', function() { - var s = new Storage(); - var w = new WalletLock(s, 'walletId'); - var w2 = new WalletLock(s, 'walletId') - w2.keepAlive(); - should.exist(w2); - }); - - it('should not fail if expired', function() { - var s = new Storage(); - var w = new WalletLock(s, 'walletId'); - var k = Object.keys(s.storage)[0]; - var v = JSON.parse(s.storage[k]); - v.expireTs = Date.now() - 60 * 6 * 1000; - s.storage[k] = JSON.stringify(v); - - s.sessionId = 'xxx'; - var w2 = new WalletLock(s, 'walletId') - should.exist(w2); - }); - - + w.keepAlive(function() { + storage.sessionId = 'session2'; + var w2 = new WalletLock(storage, 'walletId'); + w2.keepAlive(function(locked) { + w2.sessionId.should.equal('session2'); + should.exist(locked); + locked.message.should.contain('LOCKED'); + done(); + }); + }); + }) + it('should FAIL if locked by someone else but expired', function(done) { + storage.sessionId = 'session1'; + var w = new WalletLock(storage, 'walletId'); + w.keepAlive(function() { + storage.sessionId = 'session2'; + var json = JSON.parse(storage.storage['lock::walletId']); + json.expireTs -= 3600 * 1000; + storage.storage['lock::walletId'] = JSON.stringify(json); + var w2 = new WalletLock(storage, 'walletId'); + w2.keepAlive(function(locked) { + w2.sessionId.should.equal('session2'); + should.not.exist(locked); + done(); + }); + }); + }) }); + + From f48898033fd840fe238ee09230afbf5cf2860362 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 8 Sep 2014 14:24:57 -0300 Subject: [PATCH 14/45] more tests fixes --- js/models/core/WalletFactory.js | 3 ++- test/mocks/FakeStorage.js | 25 +++++++++++++----- test/test.WalletFactory.js | 45 ++++++++++++++++++--------------- 3 files changed, 46 insertions(+), 27 deletions(-) diff --git a/js/models/core/WalletFactory.js b/js/models/core/WalletFactory.js index eb0c432af..4ba0ed31a 100644 --- a/js/models/core/WalletFactory.js +++ b/js/models/core/WalletFactory.js @@ -91,6 +91,8 @@ WalletFactory.prototype.fromObj = function(obj, skipFields) { preconditions.checkArgument(obj); + // not stored options + obj.opts = obj.opts || {}; obj.opts.reconnectDelay = this.walletDefaults.reconnectDelay; // this is only used if private key or public key ring is skipped @@ -231,7 +233,6 @@ WalletFactory.prototype.create = function(opts, cb) { opts.totalCopayers = totalCopayers; opts.version = opts.version || this.version; -console.log('[WalletFactory.js.165]'); //TODO var w = new Wallet(opts); var self = this; w.store(function() { diff --git a/test/mocks/FakeStorage.js b/test/mocks/FakeStorage.js index 39a4b2ade..ef8b33b3c 100644 --- a/test/mocks/FakeStorage.js +++ b/test/mocks/FakeStorage.js @@ -20,6 +20,19 @@ FakeStorage.prototype.getGlobal = function(id, cb) { return cb(this.storage[id]); }; +FakeStorage.prototype.getMany = function(wid, fields, cb) { + var self= this; + var ret = []; + for(var ii in fields){ + var k = fields[ii]; + ret[k] = this.storage[wid + '::' + k]; + } + + return cb(ret); +}; + + + FakeStorage.prototype.setLastOpened = function(val, cb) { this.storage['lastOpened'] = val; return cb(); @@ -34,7 +47,7 @@ FakeStorage.prototype.setLock = function(id) { return cb(); } -FakeStorage.prototype.getLock = function(id,cb) { +FakeStorage.prototype.getLock = function(id, cb) { return cb(this.storage[id + '::lock']); } @@ -44,12 +57,12 @@ FakeStorage.prototype.getSessionId = function(cb) { }; -FakeStorage.prototype.removeLock = function(id,cb) { +FakeStorage.prototype.removeLock = function(id, cb) { delete this.storage[id + '::lock']; cb(); } -FakeStorage.prototype.removeGlobal = function(id,cb) { +FakeStorage.prototype.removeGlobal = function(id, cb) { delete this.storage[id]; cb(); }; @@ -78,7 +91,7 @@ FakeStorage.prototype.getWalletIds = function(cb) { if (split.length == 2) { var walletId = split[0]; - if (!walletId || walletId === 'nameFor' || walletId ==='lock') + if (!walletId || walletId === 'nameFor' || walletId === 'lock') continue; if (typeof uniq[walletId] === 'undefined') { @@ -106,8 +119,8 @@ FakeStorage.prototype.deleteWallet = function(walletId, cb) { }; -FakeStorage.prototype.getName = function(walletId,cb) { - return this.getGlobal('nameFor::' + walletId,cb); +FakeStorage.prototype.getName = function(walletId, cb) { + return this.getGlobal('nameFor::' + walletId, cb); }; diff --git a/test/test.WalletFactory.js b/test/test.WalletFactory.js index f736c339f..5148734cf 100644 --- a/test/test.WalletFactory.js +++ b/test/test.WalletFactory.js @@ -85,6 +85,7 @@ function assertObjectEqual(a, b, msg) { describe('WalletFactory model', function() { + var config = { Network: FakeNetwork, Blockchain: FakeBlockchain, @@ -121,42 +122,46 @@ describe('WalletFactory model', function() { it('should be able to create wallets', function(done) { var wf = new WalletFactory(config, '0.0.1'); wf.create(null, function(err, w) { - -console.log('[test.WalletFactory.js.123]'); //TODO - should.not.exist(err); should.exist(w); - w.should.be.instanceof('WalletFactory'); + should.not.exist(err); done(); }); }); - it('should be able to create wallets with given pk', function() { + it('should be able to create wallets with given pk', function(done) { var wf = new WalletFactory(config, '0.0.1'); var priv = 'tprv8ZgxMBicQKsPdEqHcA7RjJTayxA3gSSqeRTttS1JjVbgmNDZdSk9EHZK5pc52GY5xFmwcakmUeKWUDzGoMLGAhrfr5b3MovMUZUTPqisL2m'; - var w = wf.create({ + wf.create({ privateKeyHex: priv, + }, function(err, w) { + w.privateKey.toObj().extendedPrivateKeyString.should.equal(priv); + should.not.exist(err); + done(); }); - w.privateKey.toObj().extendedPrivateKeyString.should.equal(priv); }); - it('should be able to create wallets with random pk', function() { + it('should be able to create wallets with random pk', function(done) { var wf = new WalletFactory(config, '0.0.1'); - var priv = 'tprv8ZgxMBicQKsPdEqHcA7RjJTayxA3gSSqeRTttS1JjVbgmNDZdSk9EHZK5pc52GY5xFmwcakmUeKWUDzGoMLGAhrfr5b3MovMUZUTPqisL2m'; - var w1 = wf.create(); - var w2 = wf.create(); - w1.privateKey.toObj().extendedPrivateKeyString.should.not.equal( - w2.privateKey.toObj().extendedPrivateKeyString - ); + wf.create(null, function(err, w1) { + wf.create(null, function(err, w2) { + w1.privateKey.toObj().extendedPrivateKeyString.should.not.equal( + w2.privateKey.toObj().extendedPrivateKeyString + ); + done(); + }); + }); }); - it('should be able to get wallets', function() { + it.only('should be able to get wallets', function(done) { var wf = new WalletFactory(config, '0.0.1'); - var w = wf.create(); - - var w2 = wf.read(w.id); - should.exist(w2); - w2.id.should.equal(w.id); + wf.create(null, function(err,w){ + wf.read(w.id, [], function(err, w2){ + should.exist(w2); + w2.id.should.equal(w.id); + done(); + }); + }); }); From 9f30c9ade5c7d70669849f69bc083fc6ce966420 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 8 Sep 2014 14:58:23 -0300 Subject: [PATCH 15/45] fix more tests en wallet f --- js/models/core/WalletFactory.js | 13 +++++++------ test/test.WalletFactory.js | 11 +++++++---- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/js/models/core/WalletFactory.js b/js/models/core/WalletFactory.js index 4ba0ed31a..eca5e656b 100644 --- a/js/models/core/WalletFactory.js +++ b/js/models/core/WalletFactory.js @@ -151,7 +151,7 @@ WalletFactory.prototype.import = function(base64, password, skipFields) { * @return {Wallet} */ WalletFactory.prototype.read = function(walletId, skipFields, cb) { - var self = this; + var self = this, err; var obj = {}; obj.id = walletId; @@ -159,7 +159,7 @@ WalletFactory.prototype.read = function(walletId, skipFields, cb) { for (var ii in ret) { obj[ii] = ret[ii]; } - return cb(self.fromObj(obj, skipFields)); + return cb(err, self.fromObj(obj, skipFields)); }); }; @@ -271,11 +271,12 @@ WalletFactory.prototype._checkVersion = function(inVersion) { */ WalletFactory.prototype.open = function(walletId, passphrase, cb) { preconditions.checkArgument(cb); - var self = this, - err; + var self = this; self.storage._setPassphrase(passphrase); - self.read(walletId, null, function(w) { - w.store(function() { + self.read(err, walletId, null, function(w) { + if (err) return cb(err); + + w.store(function(err) { self.storage.setLastOpened(walletId, function() { return cb(err, w); }); diff --git a/test/test.WalletFactory.js b/test/test.WalletFactory.js index 5148734cf..36c032b80 100644 --- a/test/test.WalletFactory.js +++ b/test/test.WalletFactory.js @@ -153,7 +153,7 @@ describe('WalletFactory model', function() { }); - it.only('should be able to get wallets', function(done) { + it('should be able to get wallets', function(done) { var wf = new WalletFactory(config, '0.0.1'); wf.create(null, function(err,w){ wf.read(w.id, [], function(err, w2){ @@ -273,7 +273,7 @@ describe('WalletFactory model', function() { }).should.throw(); }); - it('BIP32 length problem', function() { + it('BIP32 length problem', function(done) { var sconfig = { Network: FakeNetwork, Blockchain: FakeBlockchain, @@ -312,8 +312,11 @@ describe('WalletFactory model', function() { 'requiredCopayers': 2, 'totalCopayers': 3 }; - var w = wf.create(opts); - + wf.create(opts, function(err,w){ + should.not.exist(err); + should.exist(w); + done(); + }); }); it('should be able to get current wallets', function() { From 90e8231aca54fad93f78db63b173a7c67f775121 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Fri, 12 Sep 2014 15:29:20 -0300 Subject: [PATCH 16/45] fix grunt file --- Gruntfile.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 540a676b0..a63da775d 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -118,8 +118,8 @@ module.exports = function(grunt) { 'lib/ng-idle/angular-idle.min.js', 'lib/angular-foundation/mm-foundation.min.js', 'lib/angular-foundation/mm-foundation-tpls.min.js', - 'lib/angular-gettext/dist/angular-gettext.min.js' - 'lib/angular-load/angular-load.min.js', + 'lib/angular-gettext/dist/angular-gettext.min.js', + 'lib/angular-load/angular-load.min.js' ], dest: 'lib/angularjs-all.js' }, From c3574ae57ffbfde8daf45f46a2d58607a7a921be Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Sat, 13 Sep 2014 10:25:13 -0300 Subject: [PATCH 17/45] refactor WalletFactory test to use sinon instead of mocks WIP --- .gitignore | 3 + js/app.js | 2 - js/models/Storage.js | 15 ++- js/models/core/PluginManager.js | 3 +- js/models/core/Wallet.js | 2 +- js/models/core/WalletFactory.js | 45 +++++-- package.json | 13 +- test/mocks/FakeStorage.js | 36 +++-- test/test.WalletFactory.js | 232 +++++++++++++++++++++----------- 9 files changed, 230 insertions(+), 121 deletions(-) diff --git a/.gitignore b/.gitignore index f7555ecd4..8aa3d8515 100644 --- a/.gitignore +++ b/.gitignore @@ -77,5 +77,8 @@ dist/windows dist/*.dmg dist/*.tar.gz dist/*.exe +<<<<<<< HEAD doc/ +/node_modules +/*-cov diff --git a/js/app.js b/js/app.js index 216553f20..a9e3c39f0 100644 --- a/js/app.js +++ b/js/app.js @@ -21,8 +21,6 @@ if (localConfig) { var log = function() { if (config.verbose) console.log(arguments); } -var copayApp = window.copayApp = angular.module('copayApp', [ - var modules = [ 'ngRoute', diff --git a/js/models/Storage.js b/js/models/Storage.js index 4d842e431..5750eb428 100644 --- a/js/models/Storage.js +++ b/js/models/Storage.js @@ -12,7 +12,7 @@ function Storage(opts) { this.__uniqueid = ++id; if (opts.password) - this._setPassphrase(opts.password); + this.setPassphrase(opts.password); try { this.storage = opts.storage || localStorage; @@ -33,7 +33,7 @@ Storage.prototype._getPassphrase = function() { return pps[this.__uniqueid]; } -Storage.prototype._setPassphrase = function(password) { +Storage.prototype.setPassphrase = function(password) { pps[this.__uniqueid] = password; } @@ -231,6 +231,7 @@ Storage.prototype.getWallets = function(cb) { Storage.prototype.deleteWallet = function(walletId, cb) { preconditions.checkArgument(walletId); preconditions.checkArgument(cb); + var err; var toDelete = {}; toDelete['nameFor::' + walletId] = 1; @@ -245,11 +246,15 @@ Storage.prototype.deleteWallet = function(walletId, cb) { }); var l = toDelete.length, - i = 0; + j = 0; + + if (!l) + return cb(new Error('WNOTFOUND: Wallet not found')); + for (var i in toDelete) { this.removeGlobal(i, function() { - if (++i == l) - return cb(); + if (++j == l) + return cb(err); }); } }; diff --git a/js/models/core/PluginManager.js b/js/models/core/PluginManager.js index bce94e464..7aced3b49 100644 --- a/js/models/core/PluginManager.js +++ b/js/models/core/PluginManager.js @@ -1,5 +1,6 @@ 'use strict'; var preconditions = require('preconditions').singleton(); +var log = require('../../log'); function PluginManager(config) { this.registered = {}; @@ -11,7 +12,7 @@ function PluginManager(config) { if (!config.plugins[pluginName]) continue; - console.log('Loading plugin: ' + pluginName); + log.info('Loading plugin: ' + pluginName); var pluginClass = require('../plugins/' + pluginName); var pluginObj = new pluginClass(config[pluginName]); pluginObj.init(); diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index 6ab010c5a..c14a568fe 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -64,7 +64,7 @@ function Wallet(opts) { 'publicKeyRing', 'txProposals', 'privateKey', 'version', 'reconnectDelay' ].forEach(function(k) { - preconditions.checkArgument(!_.isUndefined(opts[k]), 'missing required option for Wallet: ' + k); + preconditions.checkArgument(!_.isUndefined(opts[k]), 'MISSOPT: missing required option for Wallet: ' + k); self[k] = opts[k]; }); preconditions.checkArgument(!copayConfig.forceNetwork || this.getNetworkName() === copayConfig.networkName, diff --git a/js/models/core/WalletFactory.js b/js/models/core/WalletFactory.js index eca5e656b..15e4eee16 100644 --- a/js/models/core/WalletFactory.js +++ b/js/models/core/WalletFactory.js @@ -120,7 +120,7 @@ WalletFactory.prototype.fromObj = function(obj, skipFields) { * @return {Wallet} */ WalletFactory.prototype.fromEncryptedObj = function(base64, password, skipFields) { - this.storage._setPassphrase(password); + this.storage.setPassphrase(password); var walletObj = this.storage.import(base64); if (!walletObj) return false; var w = this.fromObj(walletObj, skipFields); @@ -148,18 +148,34 @@ WalletFactory.prototype.import = function(base64, password, skipFields) { * @desc Retrieve a wallet from storage * @param {string} walletId - the wallet id * @param {string[]} skipFields - parameters to ignore when importing - * @return {Wallet} + * @param {function} callback - {err, Wallet} */ WalletFactory.prototype.read = function(walletId, skipFields, cb) { - var self = this, err; + var self = this, + err; var obj = {}; - obj.id = walletId; this.storage.getMany(walletId, Wallet.PERSISTED_PROPERTIES, function(ret) { for (var ii in ret) { obj[ii] = ret[ii]; } - return cb(err, self.fromObj(obj, skipFields)); + + if (!_.any(_.values(obj))) + return cb(new Error('Wallet not found')); + + var w, err; + obj.id = walletId; + try { + w = self.fromObj(obj, skipFields); + } catch (e) { + if (e && e.message && e.message.indexOf('MISSOPTS')) { + err = new Error('Could not read: ' + walletId); + } else { + err = e; + } + w = null; + } + return cb(err, w); }); }; @@ -221,7 +237,7 @@ WalletFactory.prototype.create = function(opts, cb) { }); log.debug('\t### TxProposals Initialized'); - this.storage._setPassphrase(opts.passphrase); + this.storage.setPassphrase(opts.passphrase); opts.storage = this.storage; opts.network = this.networks[opts.networkName]; @@ -272,8 +288,8 @@ WalletFactory.prototype._checkVersion = function(inVersion) { WalletFactory.prototype.open = function(walletId, passphrase, cb) { preconditions.checkArgument(cb); var self = this; - self.storage._setPassphrase(passphrase); - self.read(err, walletId, null, function(w) { + self.storage.setPassphrase(passphrase); + self.read(walletId, null, function(err, w) { if (err) return cb(err); w.store(function(err) { @@ -285,11 +301,11 @@ WalletFactory.prototype.open = function(walletId, passphrase, cb) { }; WalletFactory.prototype.getWallets = function(cb) { - var ret = this.storage.getWallets(function(ret) { + this.storage.getWallets(function(ret) { ret.forEach(function(i) { i.show = i.name ? ((i.name + ' <' + i.id + '>')) : i.id; }); - return cb(ret); + return cb(null, ret); }); }; @@ -303,9 +319,12 @@ WalletFactory.prototype.getWallets = function(cb) { */ WalletFactory.prototype.delete = function(walletId, cb) { var s = this.storage; - s.deleteWallet(walletId); - s.setLastOpened(undefined); - return cb(); + s.deleteWallet(walletId, function(err) { + if (err) return cb(err); + s.setLastOpened(null, function(err) { + return cb(err); + }); + }); }; /** diff --git a/package.json b/package.json index 7248c5c0f..248cac974 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "dependencies": { "browser-request": "^0.3.2", "inherits": "^2.0.1", - "mocha": "^1.18.2", + "mocha": "^1.21.4", "mocha-lcov-reporter": "0.0.1", "optimist": "^0.6.1", "preconditions": "^1.0.7", @@ -27,12 +27,14 @@ "chrome": "source browser-extensions/chrome/build.sh", "setup-shell": "node shell/scripts/download-atom-shell.js", "start": "node server.js", - "coverage": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- --reporter spec test", - "test": "sh test/run.sh", + "coverage": "mochacoverage", + "test": "mocha --ui exports --reporter spec", "dist": "node shell/scripts/dist.js", "sign": "gpg -u 1112CFA1 --output browser-extensions/firefox/copay.xpi.sig --detach-sig browser-extensions/firefox/copay.xpi; gpg -u 1112CFA1 --output browser-extensions/chrome/copay-chrome-extension.zip.sig --detach-sig browser-extensions/chrome/copay-chrome-extension.zip", "verify": "gpg --verify browser-extensions/firefox/copay.xpi.sig browser-extensions/firefox/copay.xpi; gpg --verify browser-extensions/chrome/copay-chrome-extension.zip.sig browser-extensions/chrome/copay-chrome-extension.zip", - "postinstall": "./node_modules/.bin/grunt" + "postinstall": "./node_modules/.bin/grunt", + "monitor": "mocha --ui exports --reporter min --watch", + "debugtest": "mocha --debug-brk --ui exports --reporter spec" }, "keywords": [ "wallet", @@ -81,7 +83,8 @@ "shelljs": "0.3.0", "socket.io-client": "1.0.6", "travis-cov": "0.2.5", - "uglifyify": "1.2.3" + "uglifyify": "1.2.3", + "mochawrapper": "" }, "main": "app.js", "homepage": "https://github.com/bitpay/copay", diff --git a/test/mocks/FakeStorage.js b/test/mocks/FakeStorage.js index ef8b33b3c..ba64b382a 100644 --- a/test/mocks/FakeStorage.js +++ b/test/mocks/FakeStorage.js @@ -21,9 +21,9 @@ FakeStorage.prototype.getGlobal = function(id, cb) { }; FakeStorage.prototype.getMany = function(wid, fields, cb) { - var self= this; + var self = this; var ret = []; - for(var ii in fields){ + for (var ii in fields) { var k = fields[ii]; ret[k] = this.storage[wid + '::' + k]; } @@ -113,14 +113,23 @@ FakeStorage.prototype.deleteWallet = function(walletId, cb) { toDelete[key] = 1; } } + var l = toDelete.length, + j = 0; + + if (!l) + return cb(new Error('WNOTFOUND: Wallet not found')); + for (var i in toDelete) { - this.removeGlobal(i); + this.removeGlobal(i, cb); + if (++j == l) + return cb(err); + } }; FakeStorage.prototype.getName = function(walletId, cb) { - return this.getGlobal('nameFor::' + walletId, cb); + this.getGlobal('nameFor::' + walletId, cb); }; @@ -131,15 +140,16 @@ FakeStorage.prototype.setName = function(walletId, name, cb) { FakeStorage.prototype.getWallets = function(cb) { var wallets = []; - var ids = this.getWalletIds(); - - for (var i in ids) { - wallets.push({ - id: ids[i], - name: this.getName(ids[i]), - }); - } - return cb(wallets); + var self= this; + this.getWalletIds(function(ids) { + for (var i in ids) { + wallets.push({ + id: ids[i], + name: self.storage['nameFor::' + ids[i]], + }); + } + return cb(wallets); + }); }; FakeStorage.prototype.setFromObj = function(walletId, obj, cb) { diff --git a/test/test.WalletFactory.js b/test/test.WalletFactory.js index 36c032b80..be09931d6 100644 --- a/test/test.WalletFactory.js +++ b/test/test.WalletFactory.js @@ -155,8 +155,8 @@ describe('WalletFactory model', function() { it('should be able to get wallets', function(done) { var wf = new WalletFactory(config, '0.0.1'); - wf.create(null, function(err,w){ - wf.read(w.id, [], function(err, w2){ + wf.create(null, function(err, w) { + wf.read(w.id, [], function(err, w2) { should.exist(w2); w2.id.should.equal(w.id); done(); @@ -312,107 +312,177 @@ describe('WalletFactory model', function() { 'requiredCopayers': 2, 'totalCopayers': 3 }; - wf.create(opts, function(err,w){ + wf.create(opts, function(err, w) { should.not.exist(err); should.exist(w); done(); }); }); - it('should be able to get current wallets', function() { + it('should be able to get current wallets', function(done) { var wf = new WalletFactory(config, '0.0.1'); - var ws = wf.getWallets(); - - var w = wf.create({ + wf.create({ name: 'test wallet' - }); + }, function(err, ws) { + should.not.exist(err); - ws = wf.getWallets(); - 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(); + wf.getWallets(function(err, ws) { + should.not.exist(err); + ws.length.should.equal(1); + ws[0].name.should.equal('test wallet'); + done(); + }); }); }); - it('should clean lastOpened on delete wallet', function(done) { - var wf = new WalletFactory(config, '0.0.1'); - var w = wf.create({ - name: 'test wallet' + describe('#delete', function() { + it('should call deleteWallet', function(done) { + var wf = new WalletFactory(config, '0.0.1'); + var s1 = sinon.spy(wf.storage, 'deleteWallet'); + + wf.delete('xxx', function() { + s1.getCall(0).args[0].should.equal('xxx'); + done(); + }); }); - wf.storage.setLastOpened(w.id); - wf.delete(w.id, function() { - var last = wf.storage.getLastOpened(); - should.equal(last, undefined); - done(); + it('should call lastOpened', function(done) { + var wf = new WalletFactory(config, '0.0.1'); + var s1 = sinon.stub(wf.storage, 'deleteWallet').yields(null); + var s2 = sinon.stub(wf.storage, 'setLastOpened').yields(null); + wf.delete('xxx', function() { + s2.calledOnce.should.equal(true); + should.not.exist(s2.getCall(0).args[0]); + done(); + }); }); }); - it('should return false if wallet does not exist', function() { + + describe('#read', function() { + it('should fail to read unexisting wallet', function(done) { + var wf = new WalletFactory(config, '0.0.1'); + wf.read('id', [], function(err, w) { + should.not.exist(w); + should.exist(err); + should.exist(err.message); + var m = err.message.toString(); + m.should.to.have.string('Wallet not found'); + done(); + }); + }); + it('should fail to read broken wallet', function(done) { + var wf = new WalletFactory(config, '0.0.1'); + wf.storage.getMany = sinon.stub().yields({ + 'opts': 1 + }); + wf.read('id', [], function(err, w) { + should.not.exist(w); + should.exist(err); + should.exist(err.message); + var m = err.message.toString(); + m.should.to.have.string('Could not read'); + done(); + }); + }); + it('should read existing wallet', function(done) { + var wf = new WalletFactory(config, '0.0.1'); + wf.storage.getMany = sinon.stub().yields({ + 'opts': 1 + }); + wf.fromObj = sinon.stub().returns('ok'); + wf.read('id', [], function(err, w) { + should.not.exist(err); + should.exist(w); + done(); + }); + }); + }); + + + describe('#open', function() { var opts = { - 'requiredCopayers': 2, - 'totalCopayers': 3 + 'requiredcopayers': 2, + 'totalcopayers': 3 }; - var wf = new WalletFactory(config, '0.0.1'); - var w = wf.open('dummy', opts); - should.exist(w); + it('should call setPassphrase', function(done) { + var wf = new WalletFactory(config, '0.0.1'); + wf.storage.setPassphrase = sinon.spy(); + + var s1 = sinon.stub(); + s1.store = sinon.stub().yields(null); + wf.read = sinon.stub().yields(null, s1); + wf.storage.setLastOpened = sinon.stub().yields(null); + + wf.open('dummy', 'xxx', function(err, w) { + wf.storage.setPassphrase.calledOnce.should.equal(true); + wf.storage.setPassphrase.getCall(0).args[0].should.equal('xxx'); + done(); + }); + }); + + it('should call return wallet', function(done) { + var wf = new WalletFactory(config, '0.0.1'); + wf.storage.setPassphrase = sinon.spy(); + + var s1 = sinon.stub(); + s1.store = sinon.stub().yields(null); + wf.read = sinon.stub().yields(null, s1); + wf.storage.setLastOpened = sinon.stub().yields(null); + + wf.open('dummy', 'xxx', function(err, w) { + w.should.equal(s1); + s1.store.calledOnce.should.equal(true); + done(); + }); + }); + + + it('should call #store', function(done) { + var wf = new WalletFactory(config, '0.0.1'); + wf.storage.setPassphrase = sinon.spy(); + + var s1 = sinon.stub(); + s1.store = sinon.stub().yields(null); + wf.read = sinon.stub().yields(null, s1); + wf.storage.setLastOpened = sinon.stub().yields(null); + + wf.open('dummy', 'xxx', function(err, w) { + s1.store.calledOnce.should.equal(true); + done(); + }); + }); + + it('should call #setLastOpened', function(done) { + var wf = new WalletFactory(config, '0.0.1'); + wf.storage.setPassphrase = sinon.spy(); + + var s1 = sinon.stub(); + s1.store = sinon.stub().yields(null); + wf.read = sinon.stub().yields(null, s1); + wf.storage.setLastOpened = sinon.stub().yields(null); + + wf.open('dummy', 'xxx', function(err, w) { + wf.storage.setLastOpened.calledOnce.should.equal(true); + wf.storage.setLastOpened.getCall(0).args[0].should.equal('dummy'); + done(); + }); + }); }); - 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; - - wf.read = sinon.stub().withArgs(walletId).returns(w); - var wo = wf.open(walletId, opts); - should.exist(wo); - wf.read.calledWith(walletId).should.be.true; - }); - - 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); - }); - - 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); - (function() { - wf._checkNetwork('livenet'); - }).should.throw(); + describe.only('#create', function() { + 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, function(err, w) { + err.should.to.have.string('Wallet not found'); + should.not.exist(w); + }); + }); }); describe('#joinCreateSession', function() { From ad22b24d83f226ab2bcd475f1a6d11c656b73752 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Sun, 14 Sep 2014 13:52:43 -0300 Subject: [PATCH 18/45] more tests --- js/controllers/join.js | 7 +- js/models/core/WalletFactory.js | 46 ++- test/mocks/FakeStorage.js | 2 +- test/test.WalletFactory.js | 487 +++++++++++++++----------------- 4 files changed, 272 insertions(+), 270 deletions(-) diff --git a/js/controllers/join.js b/js/controllers/join.js index 2de8fa49a..3d54d59f0 100644 --- a/js/controllers/join.js +++ b/js/controllers/join.js @@ -119,7 +119,12 @@ angular.module('copayApp.controllers').controller('JoinController', $scope.loading = true; Passphrase.getBase64Async($scope.joinPassword, function(passphrase) { - walletFactory.joinCreateSession($scope.connectionId, $scope.nickname, passphrase, $scope.private, function(err, w) { + walletFactory.joinCreateSession({ + secret: $scope.connectionId, + nickname: $scope.nickname, + passphrase: passphrase, + privateHex: $scope.private, + }, function(err, w) { $scope.loading = false; if (err || !w) { if (err === 'joinError') diff --git a/js/models/core/WalletFactory.js b/js/models/core/WalletFactory.js index 15e4eee16..eacfeb48f 100644 --- a/js/models/core/WalletFactory.js +++ b/js/models/core/WalletFactory.js @@ -123,8 +123,7 @@ WalletFactory.prototype.fromEncryptedObj = function(base64, password, skipFields this.storage.setPassphrase(password); var walletObj = this.storage.import(base64); if (!walletObj) return false; - var w = this.fromObj(walletObj, skipFields); - return w; + return this.fromObj(walletObj, skipFields); }; /** @@ -179,8 +178,21 @@ WalletFactory.prototype.read = function(walletId, skipFields, cb) { }); }; + /** - * @desc This method instantiates a wallet + * @desc This method instantiates a wallet. Usefull for stubbing. + * + * @param {opts} opts, ready for new Wallet(opts) + * + */ + + +WalletFactory.prototype._getWallet = function(opts) { + return new Wallet(opts); +}; + +/** + * @desc This method prepares options for a new Wallet * * @param {Object} opts * @param {string} opts.id @@ -249,11 +261,12 @@ WalletFactory.prototype.create = function(opts, cb) { opts.totalCopayers = totalCopayers; opts.version = opts.version || this.version; - var w = new Wallet(opts); + var w = this._getWallet(opts); var self = this; - w.store(function() { - self.storage.setLastOpened(w.id, function() { - return cb(null, w); + w.store(function(err) { + if (err) return cb(err); + self.storage.setLastOpened(w.id, function(err) { + return cb(err, w); }); }); }; @@ -352,16 +365,21 @@ WalletFactory.prototype.decodeSecret = function(secret) { * information locally using passphrase. privateHex is the * private extended master key. cb has two params: error and wallet. * - * @param {string} secret - the wallet secret - * @param {string} nickname - a nickname for the current user - * @param {string} passphrase - a passphrase to use to encrypt the wallet for persistance - * @param {string} privateHex - the private extended master key + * @param {object} opts + * @param {string} opts.secret - the wallet secret + * @param {string} opts.passphrase - a passphrase to use to encrypt the wallet for persistance + * @param {string} opts.nickname - a nickname for the current user + * @param {string} opts.privateHex - the private extended master key * @param {walletCreationCallback} cb - a callback */ -WalletFactory.prototype.joinCreateSession = function(secret, nickname, passphrase, privateHex, cb) { +WalletFactory.prototype.joinCreateSession = function(opts, cb) { + preconditions.checkArgument(opts); + preconditions.checkArgument(opts.secret); + preconditions.checkArgument(opts.passphrase); + preconditions.checkArgument(opts.nickname); preconditions.checkArgument(cb); var self = this; - var decodedSecret = this.decodeSecret(secret); + var decodedSecret = this.decodeSecret(opts.secret); if (!decodedSecret || !decodedSecret.networkName || !decodedSecret.pubKey) { return cb('badSecret'); } @@ -370,7 +388,7 @@ WalletFactory.prototype.joinCreateSession = function(secret, nickname, passphras networkName: decodedSecret.networkName, }; - if (privateHex && privateHex.length > 1) { + if (opts.privateHex && opts.privateHex.length > 1) { privOpts.extendedPrivateKeyString = privateHex; } diff --git a/test/mocks/FakeStorage.js b/test/mocks/FakeStorage.js index ba64b382a..7bb9de7b6 100644 --- a/test/mocks/FakeStorage.js +++ b/test/mocks/FakeStorage.js @@ -7,7 +7,7 @@ FakeStorage.prototype.reset = function(password) { this.storage = {}; }; -FakeStorage.prototype._setPassphrase = function(password) { +FakeStorage.prototype.setPassphrase = function(password) { this.storage.passphrase = password; }; diff --git a/test/test.WalletFactory.js b/test/test.WalletFactory.js index be09931d6..78dca9aff 100644 --- a/test/test.WalletFactory.js +++ b/test/test.WalletFactory.js @@ -3,12 +3,11 @@ var chai = chai || require('chai'); var should = chai.should(); -var FakeStorage = require('./mocks/FakeLocalStorage'); var copay = copay || require('../copay'); var sinon = require('sinon'); var FakeNetwork = require('./mocks/FakeNetwork'); var FakeBlockchain = require('./mocks/FakeBlockchain'); -var FakeStorage = require('./mocks/FakeStorage'); +var FakeStorage = function FakeStorage() {}; var WalletFactory = require('../js/models/core/WalletFactory'); var Passphrase = require('../js/models/core/Passphrase'); var LocalEncrypted = copay.StorageLocalEncrypted; @@ -78,7 +77,7 @@ function assertObjectEqual(a, b, msg) { var orderedA = reconstructObject(a, getKeys(a).sort()), orderedB = reconstructObject(b, getKeys(b).sort()); - // compare as strings for diff tools to show us the difference + // compare as strings for diff tolls to show us the difference JSON.stringify(orderedA).should.equal(JSON.stringify(orderedB), msg) } } @@ -86,6 +85,31 @@ function assertObjectEqual(a, b, msg) { describe('WalletFactory model', function() { + var wf; + + beforeEach(function() { + wf = new WalletFactory(config, '0.0.1'); + wf.storage.setPassphrase = sinon.spy(); + wf.storage.getSessionId = sinon.spy(); + wf.storage.setFromObj = sinon.spy(); + wf.storage.setLastOpened = sinon.stub().yields(null); + + var w = sinon.stub(); + w.store = sinon.stub().yields(null); + + wf._getWallet = sinon.stub().returns(w); + + + wf.network.setHexNonce = sinon.spy(); + }); + + + afterEach(function() { + wf = undefined; + }); + + + var config = { Network: FakeNetwork, Blockchain: FakeBlockchain, @@ -95,14 +119,12 @@ describe('WalletFactory model', function() { totalCopayers: 5, spendUnconfirmed: 1, reconnectDelay: 100, + }, - network: { - testnet: { - url: 'https://test-insight.bitpay.com:443' - }, - livenet: { - url: 'https://insight.bitpay.com:443' - }, + blockchain: { + host: 'test.insight.is', + port: 80, + schema: 'https' }, networkName: 'testnet', passphrase: { @@ -111,225 +133,143 @@ describe('WalletFactory model', function() { }, }; - it('should create the factory', function() { - var wf = new WalletFactory(config, '0.0.1'); - should.exist(wf); - wf.walletDefaults.should.deep.equal(config.wallet); - wf.version.should.equal('0.0.1'); + describe('#constructor', function() { + it('should create the factory', function() { + var wf = new WalletFactory(config, '0.0.1'); + should.exist(wf); + wf.networkName.should.equal(config.networkName); + wf.walletDefaults.should.deep.equal(config.wallet); + wf.version.should.equal('0.0.1'); + }); }); + describe('#fromObj / #toObj', function() { + it('round trip', function() { + var w = wf.fromObj(JSON.parse(o)); - it('should be able to create wallets', function(done) { - var wf = new WalletFactory(config, '0.0.1'); - wf.create(null, function(err, w) { should.exist(w); - should.not.exist(err); - done(); + w.id.should.equal("dbfe10c3fae71cea"); + should.exist(w.publicKeyRing.getCopayerId); + should.exist(w.txProposals.toObj()); + should.exist(w.privateKey.toObj()); + + assertObjectEqual(w.toObj(), JSON.parse(o)); }); - }); - it('should be able to create wallets with given pk', function(done) { - var wf = new WalletFactory(config, '0.0.1'); - var priv = 'tprv8ZgxMBicQKsPdEqHcA7RjJTayxA3gSSqeRTttS1JjVbgmNDZdSk9EHZK5pc52GY5xFmwcakmUeKWUDzGoMLGAhrfr5b3MovMUZUTPqisL2m'; - wf.create({ - privateKeyHex: priv, - }, function(err, w) { - w.privateKey.toObj().extendedPrivateKeyString.should.equal(priv); - should.not.exist(err); - done(); - }); - }); + it('round trip, using old copayerIndex', function() { + var wf = new WalletFactory(config, '0.0.5'); + var w = wf.fromObj(JSON.parse(o)); - it('should be able to create wallets with random pk', function(done) { - var wf = new WalletFactory(config, '0.0.1'); - wf.create(null, function(err, w1) { - wf.create(null, function(err, w2) { - w1.privateKey.toObj().extendedPrivateKeyString.should.not.equal( - w2.privateKey.toObj().extendedPrivateKeyString - ); - done(); - }); - }); - }); - - - it('should be able to get wallets', function(done) { - var wf = new WalletFactory(config, '0.0.1'); - wf.create(null, function(err, w) { - wf.read(w.id, [], function(err, w2) { - should.exist(w2); - w2.id.should.equal(w.id); - done(); - }); - }); - }); - - - it('#fromObj #toObj round trip', function() { - 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()); - - assertObjectEqual(w.toObj(), JSON.parse(o)); - }); - - - - it('#fromObj #toObj round trip, using old copayerIndex', function() { - 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()); - assertObjectEqual(w.toObj(), JSON.parse(o)); - }); - - - it('#fromObj, skipping fields', function() { - var wf = new WalletFactory(config, '0.0.5'); - var w = wf.fromObj(JSON.parse(o), ['publicKeyRing']); - - should.exist(w); - w.id.should.equal("dbfe10c3fae71cea"); - should.exist(w.publicKeyRing.getCopayerId); - should.exist(w.txProposals.toObj()); - should.exist(w.privateKey.toObj()); - (function() { - assertObjectEqual(w.toObj(), JSON.parse(o)) - }).should.throw(); - }); - - it('support old index schema: #fromObj #toObj round trip', function() { - - var o3 = '{"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"},"addressBook":{},"settings":{"unitName":"BTC","unitToSatoshi":100000000,"unitDecimals":8,"alternativeName":"Argentine Peso","alternativeIsoCode":"ARS"}}'; - var o4 = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5","networkName":"testnet"},"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"},"addressBook":{},"settings":{"unitName":"BTC","unitToSatoshi":100000000,"unitDecimals":8,"alternativeName":"Argentine Peso","alternativeIsoCode":"ARS"}}'; - var wf = new WalletFactory(config, '0.0.5'); - var w = wf.fromObj(JSON.parse(o3)); - - should.exist(w); - w.id.should.equal("dbfe10c3fae71cea"); - should.exist(w.publicKeyRing.getCopayerId); - should.exist(w.txProposals.toObj); - should.exist(w.privateKey.toObj); - - var expected = JSON.parse(o4.replace(/cosigner/g, 'copayerIndex')); - assertObjectEqual(w.toObj(), expected); - }); - - it('should create wallet from encrypted object', function() { - var wf = new WalletFactory(config, '0.0.1'); - 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); - wf.storage._setPassphrase = sinon.spy(); - wf.storage.import = sinon.spy(); - 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.false; - }); - - it('should import and update indexes', function() { - var wf = new WalletFactory(config, '0.0.1'); - var wallet = { - id: "fake wallet", - updateIndexes: function(cb) { - cb(); - } - }; - wf.fromEncryptedObj = sinon.stub().returns(wallet); - - var w = wf.import("encrypted", "password"); - - should.exist(w); - wallet.should.equal(w); - - wf.fromEncryptedObj = sinon.stub().returns(null); - (function() { - wf.import("encrypted", "password") - }).should.throw(); - }); - - it('BIP32 length problem', function(done) { - var sconfig = { - Network: FakeNetwork, - Blockchain: FakeBlockchain, - Storage: FakeStorage, - "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, - "reconnectDelay": 100, - "spendUnconfirmed": 1, - }, - "blockchain": { - "host": "test.insight.is", - "port": 3001 - }, - "socket": { - "host": "test.insight.is", - "port": 3001 - }, - "themes": ["default"], - }; - var wf = new WalletFactory(sconfig, '0.0.1'); - var opts = { - 'requiredCopayers': 2, - 'totalCopayers': 3 - }; - wf.create(opts, function(err, w) { - should.not.exist(err); should.exist(w); - done(); + w.id.should.equal("dbfe10c3fae71cea"); + should.exist(w.publicKeyRing.getCopayerId); + should.exist(w.txProposals.toObj()); + should.exist(w.privateKey.toObj()); + assertObjectEqual(w.toObj(), JSON.parse(o)); + }); + + it('#fromObj, skipping fields', function() { + var wf = new WalletFactory(config, '0.0.5'); + var w = wf.fromObj(JSON.parse(o), ['publicKeyRing']); + + should.exist(w); + w.id.should.equal("dbfe10c3fae71cea"); + should.exist(w.publicKeyRing.getCopayerId); + should.exist(w.txProposals.toObj()); + should.exist(w.privateKey.toObj()); + (function() { + assertObjectEqual(w.toObj(), JSON.parse(o)) + }).should.throw(); + }); + + it('support old index schema: #fromObj #toObj round trip', function() { + 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"},"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"},"addressBook":{}}'; + + 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); + + // + var expected = JSON.parse(o2.replace(/cosigner/g, 'copayerIndex')); + assertObjectEqual(w.toObj(), expected); }); }); - it('should be able to get current wallets', function(done) { - var wf = new WalletFactory(config, '0.0.1'); - wf.create({ - name: 'test wallet' - }, function(err, ws) { - should.not.exist(err); + describe('#fromEncryptedObj', function() { + it('should create wallet from encrypted object', function() { + wf.storage.setPassphrase = sinon.spy(); + wf.storage.import = sinon.stub().withArgs('base64').returns('walletObj'); + wf.fromObj = sinon.stub().withArgs('walletObj').returns('ok'); + + var w = wf.fromEncryptedObj("encrypted object", "123"); + + w.should.equal('ok'); + wf.storage.setPassphrase.calledOnce.should.be.true; + wf.storage.setPassphrase.getCall(0).args[0].should.equal('123'); + wf.storage.import.calledOnce.should.be.true; + wf.fromObj.calledWith('walletObj').should.be.true; + }); + }); + + describe('#import', function() { + it('should import and update indexes', function() { + var wallet = { + id: "fake wallet", + updateIndexes: function(cb) { + cb(); + } + }; + wf.fromEncryptedObj = sinon.stub().returns(wallet); + + var w = wf.import("encrypted", "password"); + + should.exist(w); + wallet.should.equal(w); + + wf.fromEncryptedObj = sinon.stub().returns(null); + (function() { + wf.import("encrypted", "password") + }).should.throw(); + }); + }); + + describe('#getWallets', function() { + it('should return empty array if no wallets', function(done) { + wf.storage.getWallets = sinon.stub().yields([]); wf.getWallets(function(err, ws) { should.not.exist(err); - ws.length.should.equal(1); - ws[0].name.should.equal('test wallet'); + ws.should.deep.equal([]); + done(); + }); + }); + + it('should be able to get current wallets', function(done) { + wf.storage.getWallets = sinon.stub().yields([{ + name: 'w1', + id: 'id1', + }, { + name: 'w', + id: 'id2', + }]); + + wf.getWallets(function(err, ws) { + should.not.exist(err); + ws.should.deep.equal([{ + name: 'w1', + id: 'id1', + show: 'w1 ' + }, { + name: 'w', + id: 'id2', + show: 'w ' + }]); done(); }); }); @@ -337,22 +277,19 @@ describe('WalletFactory model', function() { describe('#delete', function() { it('should call deleteWallet', function(done) { - var wf = new WalletFactory(config, '0.0.1'); - var s1 = sinon.spy(wf.storage, 'deleteWallet'); - + wf.storage.deleteWallet = sinon.stub().yields(null); wf.delete('xxx', function() { - s1.getCall(0).args[0].should.equal('xxx'); + wf.storage.deleteWallet.getCall(0).args[0].should.equal('xxx'); done(); }); }); it('should call lastOpened', function(done) { - var wf = new WalletFactory(config, '0.0.1'); - var s1 = sinon.stub(wf.storage, 'deleteWallet').yields(null); - var s2 = sinon.stub(wf.storage, 'setLastOpened').yields(null); + wf.storage.deleteWallet = sinon.stub().yields(null); + wf.storage.setLastOpened = sinon.stub().yields(null); wf.delete('xxx', function() { - s2.calledOnce.should.equal(true); - should.not.exist(s2.getCall(0).args[0]); + wf.storage.setLastOpened.calledOnce.should.equal(true); + should.not.exist(wf.storage.setLastOpened.getCall(0).args[0]); done(); }); }); @@ -361,7 +298,8 @@ describe('WalletFactory model', function() { describe('#read', function() { it('should fail to read unexisting wallet', function(done) { - var wf = new WalletFactory(config, '0.0.1'); + wf.storage.getMany = sinon.stub().yields({}); + wf.read('id', [], function(err, w) { should.not.exist(w); should.exist(err); @@ -372,7 +310,6 @@ describe('WalletFactory model', function() { }); }); it('should fail to read broken wallet', function(done) { - var wf = new WalletFactory(config, '0.0.1'); wf.storage.getMany = sinon.stub().yields({ 'opts': 1 }); @@ -471,42 +408,86 @@ describe('WalletFactory model', function() { }); }); - describe.only('#create', function() { - 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, function(err, w) { - err.should.to.have.string('Wallet not found'); - should.not.exist(w); + describe('#create', function() { + it('should create wallet', function(done) { + wf.create(null, function(err, w) { + should.exist(w); + should.not.exist(err); + done(); + }); + }); + + it('should be able to create wallets with given pk', function(done) { + var priv = 'tprv8ZgxMBicQKsPdEqHcA7RjJTayxA3gSSqeRTttS1JjVbgmNDZdSk9EHZK5pc52GY5xFmwcakmUeKWUDzGoMLGAhrfr5b3MovMUZUTPqisL2m'; + wf.create({ + privateKeyHex: priv, + }, function(err, w) { + wf._getWallet.getCall(0).args[0].privateKey.toObj().extendedPrivateKeyString.should.equal(priv); + should.not.exist(err); + done(); + }); + }); + + it('should be able to create wallets with random pk', function(done) { + wf.create(null, function(err, w1) { + wf.create(null, function(err, w2) { + wf._getWallet.getCall(0).args[0].privateKey.toObj().extendedPrivateKeyString.should.not.equal( + wf._getWallet.getCall(1).args[0].privateKey.toObj().extendedPrivateKeyString + ); + done(); + }); }); }); }); describe('#joinCreateSession', function() { - it('should call network.start', function() { - var wf = new WalletFactory(config, '0.0.1'); - wf.networks.testnet.cleanUp = sinon.spy(); - wf.networks.testnet.start = sinon.spy(); - wf.joinCreateSession('CA1e4HJpSmx9i97i2NigZ6j6F8C5pSaZX9XrAUwQERYAxNpQ4jsBEkr8iS', 'test'); - wf.networks.testnet.start.calledOnce.should.equal(true); + var opts = { + secret: '8WtTuiFTkhP5ao7AF2QErSwV39Cbur6pdMebKzQXFqL59RscXM', + nickname: 'test', + passphrase: 'pass' + }; + it('should yield network error', function(done) { + opts.privHex = undefined; + wf.network.on = sinon.stub().withArgs('serverError').yields(null); + wf.joinCreateSession(opts, function(err, w) { + err.should.equal('joinError'); + done(); + }); }); + + + it('should call network.start', function(done) { + opts.privHex = undefined; + wf.network.cleanUp = sinon.spy(); + wf.network.greet = sinon.spy(); + wf.network.on = sinon.stub().withArgs('connected').yields(null); + + wf.network.start = sinon.stub().yields(null); + wf.joinCreateSession(opts, function(err, w) { + console.log('[test.WalletFactory.js.454:err:]', err); //TODO + wf.network.start.calledOnce.should.equal(true); + done(); + }); + + }); + it('should accept a priv key a input', function() { var wf = new WalletFactory(config, '0.0.1'); - var privHex = 'tprv8ZgxMBicQKsPf7MCvCjnhnr4uiR2Z2gyNC27vgd9KUu98F9mM1tbaRrWMyddVju36GxLbeyntuSadBAttriwGGMWUkRgVmUUCg5nFioGZsd'; - wf.networks.testnet.cleanUp = sinon.spy(); - wf.networks.testnet.start = sinon.spy(); - wf.joinCreateSession('CA1e4HJpSmx9i97i2NigZ6j6F8C5pSaZX9XrAUwQERYAxNpQ4jsBEkr8iS', 'test', null, privHex); - wf.networks.testnet.start.getCall(0).args[0].privkey.should.equal('ddc2fa8c583a73c4b2a24630ec7c283df4e7c230a02c4e48bc36ec61687afd7d'); + opts.privHex = 'tprv8ZgxMBicQKsPf7MCvCjnhnr4uiR2Z2gyNC27vgd9KUu98F9mM1tbaRrWMyddVju36GxLbeyntuSadBAttriwGGMWUkRgVmUUCg5nFioGZsd'; + wf.network.cleanUp = sinon.spy(); + wf.network.start = sinon.spy(); + wf.joinCreateSession(opts, function(err, w) { + wf.network.start.getCall(0).args[0].privkey.should.equal('ddc2fa8c583a73c4b2a24630ec7c283df4e7c230a02c4e48bc36ec61687afd7d'); + }); }); it('should call network.start with private key', function() { + opts.privHex = undefined; var wf = new WalletFactory(config, '0.0.1'); - wf.networks.testnet.cleanUp = sinon.spy(); - wf.networks.testnet.start = sinon.spy(); - wf.joinCreateSession('8WtTuiFTkhP5ao7AF2QErSwV39Cbur6pdMebKzQXFqL59RscXM', 'test', null, undefined); - wf.networks.testnet.start.getCall(0).args[0].privkey.length.should.equal(64); //privkey is hex of private key buffer + wf.network.cleanUp = sinon.spy(); + wf.network.start = sinon.spy(); + wf.joinCreateSession(opts, function(err, w) { + wf.network.start.getCall(0).args[0].privkey.length.should.equal(64); //privkey is hex of private key buffer + }); }); }); describe('dont break backwards compatibility of wallets', function() { @@ -524,7 +505,6 @@ describe('WalletFactory model', function() { it('should be able to import simple 1-of-1 encrypted legacy testnet wallet', function(done) { var pp = new Passphrase(config.passphrase); var alternateConfig = JSON.parse(JSON.stringify(config)); - alternateConfig.Blockchain = FakeBlockchain; alternateConfig.Storage = LocalEncrypted; alternateConfig.storage = { localStorage: mockLocalStorage, @@ -566,8 +546,7 @@ describe('WalletFactory model', function() { }); -var o = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5","networkName":"testnet"},"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"},"addressBook":{},"settings":{"unitName":"BTC","un itToSatoshi":100000000,"unitDecimals":8,"alternativeName":"Argentine Peso","alternativeIsoCode":"ARS"}}'; -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"},"addressBook":{},"settings":{"unitName":"BTC","unitToSatoshi":100000000,"unitDecimals":8,"alternativeName":"Argentine Peso","alternativeIsoCode":"ARS"}}'; +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"},"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","030920a8b8e88c4db2871a7df0878a86cf0695f6d96bb50c701c3454f3df25176a"],"m/2147483647/1/7":["036bf329fc19bce10cf1999fae5bfa80290ff7b44776b49c7b0dc9eec6cffcfa21","03955a549875b4f7b9be28b9ff4bcd51ad2bc224430b1634baef890585885d5e1b"],"m/2147483647/1/8":["024879c9c9a261b3141ecfa1c79c4efc25278c844ecd1dcfcb95d9c19581fbdd25","03fb4a5fdb91239df3ccf7f61a5b99e7e72483101e21c9d1ee0d85544e9354c6c7"],"m/2147483647/1/9":["035928a107ec01f78cd586914d5a49710fd42e352b1312e3ad0eeb2c9666fdf8e7","03a54c03093797854829c75357f092356352a109042bbb83bdac20cb4e5eca27ea"],"m/2147483647/1/10":["021e7a3a7efe888c5e820b5cf0f03317b2b4bf438d8563449aeb7a77cade97f136","03ec0960b3d1df52ca3cc2c82b7d97063400da4dd051bba2f9bab6cb44aee01efa"],"m/2147483647/1/11":["035d70c26b7f429861f555f7c0d99947411b23b7f95303fb8d5de5b82a95aa30fc","038b922f7024f5446d6b48e5253643543b35c006d90fd37688105c6cefcd8adb8a"],"m/2147483647/1/12":["02158d6503891c6c65a606221dbf5c68d0832288975914007968419939588ecb24","0248264cb1763a3f4de9b34787b4bc5443ec92ef915927494bb9f1c1c0b498c7ca"],"m/2147483647/1/13":["0349965eea38a25ae0c061faeac4c4e57e648bc4c0f059d07b3b8b7962cbc0dde5","0352243d9269565ce2a1ffdd0b8e43a442c6dd1c9edda86eaaf2cba5a4a95c40f1"],"m/2147483647/1/14":["030fa6e3d0c5cedc0581955395c77cbe134c912a47971023b9695332df3f7bb200","03f2cf09e33326fb59bf3f13e6298d2d5d29c9eae3b872e5a851e8d8d77259c883"],"m/2147483647/1/15":["02bf0d45e41339f552df6f8baf4392142921fd38b0f2a4388a905ff6cbacbc278a","03fabe46bb6706a1b8edfd28c046a8891b4530bbe5305080b72b0d08ebdf7b8c0a"],"m/2147483647/1/16":["03a4e3146ed34d6a8af4e4379e6edcff32cb0373ba232b3d746af3052f674133ac","030311b73c6f5c46ddffc0cfce6e5ed0b671d94267d8e52cd8837f2a479916eb91"],"m/2147483647/1/17":["03233df93c762d2f06c7f5f388e4e0a8dbdb13302acba0d2d6995c487d8aec9f2f","024badfdcb7e772ac7fc1c46d3943b07500edbbece105cdeff3eb9e9fcc9f54782"],"m/2147483647/1/18":["0364035475a098e00eb010c500cad3c90af3e81a4bd613144bc9433a150f14718b","028223dc8142154e7477ce000b3dc13e1d15a901553d9b18864c8645b582b38fe6"],"m/2147483647/1/19":["03971b74b4ac4bdaadf636baa4caa82fe5355471ed6ea05a9cbe5fc6c9e4b9db76","0202ebffacd01f83849e5bc5c0e2c317bc5fb2fbcb2d6d4482a5235f9f1308b61a"],"m/0/1/4":["03005ee9ff028c98fd132e531023f2f2b61ff0d26022f979dd98088d2ba167b031","0345ea82e8dfe38277f0c3aee18d2dd93edb63e8663ac83328a7934d2ca57006f6"],"m/0/1/5":["0391bc4990b71d8a3f156ae7107929ed6372b0b4ba8a868253f71ba7189d1efa02","0312a74cf2e7c0dd41897d04fabfd8cc3187b84a28305cfc79315b24e6fe23a6b4"],"m/0/1/6":["021a38c492607ff9684a4fec445e47b5b7100d3ef9e9dc0d0b37c0a646d28d4f77","03ae0b46ab36f97447ebaa53f2b5c8f090f15395378785f2fd285eeba17fbf3f65"],"m/0/1/7":["0308cdec88c1ffe16edc98853d9c08dbd4ba2541ba566668ca17bda19d7eb3481f","02dd622267c2e68287287b8b61724f76fbe84096a56aa5054af92f8fe25380e2d1"],"m/0/1/8":["039647da9ad725836bcb28a3e0497659a28d7749d1416c421a0a01c62d237ee962","022e22aa61eafda0dd8820427f1a06314d352a15ea8645e7ab9b80920017084d82"],"m/0/1/9":["03a4ade946076c6962b70c70ac7fad3a87efb59a1d0a4e32bda13a6d47fe9df961","029a07235aba04ab69526e117d836d5b3fae5cfc8c5e72b10c6d1afd261ccc19f3"],"m/0/1/10":["03c78e9b6493b22790db1acea20df9444e0f9c424fc5756e7a32c290ae01783953","0254c130ee467a96570c9f5ebea89de04f0b1db1686b164f2694339bef8f25dd88"],"m/0/1/11":["03a762c43318ef8d4840fab04c8db73797dc648825fac60f2730b4c76678df1cf3","0212c684a4de8e750ad2dfe2b136370ab9803eca178ed9a27b3990c29b067de35c"],"m/0/1/12":["02702d221f9b15c5cf75ac2f497a6c63e60213087c3d2d3be46768e3ebd238e26e","03ed58580744deb357258e44548212038670769d8d51e385d4fb8414311fd01b52"],"m/0/1/13":["0320e0597b54c62768352f433389cee4725d6094d7bcb5c72265edcc0933829aff","02c5706f11b9a85f3176c572842b7c9812c2195058d24d945bc026b00312740e76"],"m/0/1/14":["02fe43077676b844226d3aaa62e8a86d237710d92f882366944acbde0c8992fcaf","039a6a8662abb8910741cf331320549665e9feb28ca94d1ab6a43c84fa330b94ee"],"m/0/1/15":["0369f99f72847af93d50ab8ee75b6e7e912d26e27be96f6d6b7215cf7daeff7ba5","02521700cc07c953ba5aa586fb0e4795a34dffc68c5fb43e038be3866e40f4daed"],"m/0/1/16":["02f67d1d89bd8fe2f91c5b973cbdacfb4ba440e7656bce284cf73d549625607347","035da9cfac5a803dcb2b283b02a2515a4a1bcbf3d19e0d180aee8fc30193bc0555"],"m/0/1/17":["02c024ec199d240e8d6c66276b94b91071f7cdf2bef540c29d6d18d25de7b1cf7c","02190865f9dafae3f7f05c093463be5632946422ddda0a6fef6904390792516067"],"m/0/1/18":["035ed504d7704ad984a333b8eb0fceb8be043da9284de31ed84d9e68d90c75507d","033303c415b50421732402df00f4baa219f334647a7eb5014b9f8079864d6ab558"],"m/0/1/19":["02ce49fe86b0eee73663b1ee867b16b97c876af26f12764c528a2e6d0eb55ad3d7","03ab969bc81796b88e44c340d854df955fc60ea17ea92db5d3115595d6dec890d8"],"m/0/1/20":["03e2fa915378cbdffa0d919b0fb50c7256ca731b9d571b3365e486893a1d43079c","038d058b895cf084dccfcc9367e4796a5cf4ddceed6c35f6885d75c80119613350"],"m/0/1/21":["02fcb1bf644446b5b42205272af72f0aeab9e92ca29aafa91c5fb69142764017aa","035c5fe5c8811603279a5b72b6c30735d702817db1eab937c622269e28192ffa90"],"m/0/1/22":["03b39d61dc9a504b13ae480049c140dcffa23a6cc9c09d12d6d1f332fee5e18ca5","022929f515c5cf967474322468c3bd945bb6f281225b2c884b465680ef3052c07e"],"m/0/1/23":["03f40b82fe8cacff08879f13c45f443a3dc3ea98e1d75d5f32a19f5e5a8f7a905b","028415ee458e4dcfd440ce969726f3b58ae74fb6cf3995ced099579211e7419844"],"m/1/1/5":["032748a6282e21f571b8c8dd49e775deb83c90fcf88dc4ba81d878536973709c3f","020837cd68f14ce571b335eecd1b6fa0af43e1576dd9721aaca2a8ab639ac6b7cd"],"m/1/1/6":["0337032efb013dc92bb8dccfbdda9f5c28f0039a9c60953d41003d095e9f9778af","03ceed2da6b9603297061dc8eb930112ba726b2ccf5eec67f4866a05ca4049a22b"],"m/1/1/7":["0383c96ac2af7d203f69133b2fab6b68366b5075ad6957fa06759df3b20fbfec70","0311385f79834cedaf2230a48c0f9dc8e794da1869fc595db2518d62debb85579a"],"m/1/1/8":["03efc649680280f4e4df96da923bc88330275004125ebe5483c2f3e05ca52e19a4","02803c02d197d780388259afbd001ae41fa3eb3e2bac9627aff540521c184c3b23"],"m/1/1/9":["03af2fe6aa027a76b42c1c4050a040bfd026ad2daec1bb96a5fe2d026a7df919de","02ce14163047c640228796fb1f72bbe3afb05819ad141598a4f021058a6f79dd3b"],"m/1/1/10":["033770378bd762cf0408e44e4e604bef77e336170428c506949b1a4f1f2963e574","02c58ed43946f699dbd3e36d3e9aab2714cadeb19ecd3a56e4328c50336b4a76cb"],"m/1/1/11":["02898a1545fa19bdca92adc498698d27b86529cd4c08946d9d29604734b86f31af","02b402767a045ede072600924401c0d720000b2ed59fa444bfdbef4a5f1cead745"],"m/1/1/12":["039b8659430be49913e2cd869aa8c99ccf49a13df35837370b792033dadb891483","03264e63df292257cc76babb15d15bef620d1c2f8c3bbc78d6ea02d127e5ee7386"],"m/1/1/13":["02381a559791b8e86bf546e2c718ae63cf24eed0518a58e4d4a4b310adf2cd38fa","02d7f8283a4418d912508901b4a3db0d2103206dfdd74b3c75648671e20ecfd445"],"m/1/1/14":["020376e8c550b7d9faa0b2da947a2a36fab22c6e8190b6f99460b6022017bb97d7","03fbc5299190e6628de28c92aaa12e3a131b21eb7266462c46fbedeb86fa878055"],"m/1/1/15":["027209fd3b0cf7368180a5dbb16b928c997d33fccb78505d48440c7d23eadf5460","03450bfb22858726cd7e228e6733f69457546978a95188565c53e0d1c0d6070ea8"],"m/1/1/16":["03cb355ba04f64293793855121bab5831f84a3a3edf7cd31fccaa6d67c407a4912","028bc897a39c1224610b765a80f4cd8ab79cb37776f58fec9c10ac6f649d1f3c72"],"m/1/1/17":["03f4cb0564d7e2c6b85673503b7954db22779f29a8f3374904573984e318a96bf1","037c11b6ee906d84aa7eed359d758d986d912b6f8e5cbb1acf0982a77b3ef812c4"],"m/1/1/18":["02d2e5798f33f6889472857744316f2d253f25f88379610063f40cfe5798d9858f","0253cefdfe9ca987cbf1c950b6246d5b7a194d8dfad47c3a78dbbc5c1d01511d97"],"m/1/1/19":["0336c325f5aed366ffc10d553f2bfd4d69e66cbe1688d77af14efc8827aea2e318","0378b1b9a6074f9f2ab4fa9ad1e14649c621b0c8124a1b148914d3c10e6ab390c6"],"m/1/1/20":["03ea55740a734689ce778a8c00df8ebf4274c8f66de7d05646fe5c927773ff7f2e","02275b558d49aef955b6dee51a3c0a53f4b076b97bb3f26abcc82540168ec87cac"],"m/1/1/21":["03c77869c9984664eac9c238f4b6d806c9f48ca8a736c48450f398834db2aa915c","02d984f548c7f60c09dad3287cfc48807bc8157123989636c713be61be6a2e9ced"],"m/1/1/22":["03ed7c6a3c854c1f9459891691cc32671402f9e47126919878251e568dbdf353f8","02a113dab22cd9e46967b3fd76b9b9ec1d227d88817a9300e42d332cca2a0877fd"],"m/1/1/23":["02ee186432dcf69fda50a6fdbd94651817d8a271c273a5b70cab3ec4ae77a3753b","02291370aad9de0dac676355ced64e268b0c431a51f42f12d13f5144940fce4285"],"m/1/1/24":["02bf71435e84e66547c8c583d5ba226a5ac4d935e0a9f9603ecd8925c3e847e91a","03578d8657d285a89d9d597632db662cfef9baccfb55c76b1e87948a94fc9de30d"],"m/2147483647/0/0":["02a8425bbe23426219065969f695a6c3e242b24e57226bffdd542be8fd6be968c9","03057a42fdb6569fb1615b173ccb702453db2eac5be4291b82d4511461eafbed87"],"m/2147483647/0/1":["0250c3d3e86e332010c5233c2ec3bc728026002f0037cb3382d6318409b0e70796","02cfac1e7c4c88191201080f8316af52d9faa6ba624a6e160279e9fac4d1cf79a9"],"m/2147483647/0/2":["02a8c266a5b92eb50c8be91f95e4d1ad968b2f57d527377fd642d63fb84474f61a","028cc954ab31bd179ff80b8a05f95430ae534e61b3ff35f5284fa2fbe1832ceccb"],"m/2147483647/0/3":["02f719e1a7ab00ea98611453fb03d44c1da04655bed74af392534d70099039b4c2","03bfa548bfd4718c50bfce173f780eadcfb679d9c0206c91a2fa1879a9cf7558b2"],"m/2147483647/0/4":["0362c0695d397ca26bf47f0e641bb3cfb06ff29ccac2e1d56ded3afcf88b1e688d","02f9d87b05bdb3b9e82f506b43f813041c0e403274adc23d11e5e1651e34b606c2"],"m/2147483647/0/5":["033731323032d4ee08e858fc71f93970444333e183a1d5052e1d08cfb511e262c8","023e12556cef67ade35b7758916b5e1a3ebe074ccd35c5d8eff6b01321f63eb495"],"m/2147483647/0/6":["025d11b90081972bc1c258c9d6f476dfc2f95b69f0e9935322bf9c21deb580ff64","02b065f56a378907354f0738a0ed74f10660c6b5dd68c9f992093b75ce3d7d8b72"],"m/2147483647/0/7":["0210e721e8a35db9d8c855a0d346f60c09208f3be80b39e03af2c29db777332c71","0277f352969fadb1f1835f9a0fa99c6a3c7b6c281be5b2794c88a708eb177ea33d"],"m/2147483647/0/8":["02998d8d41e4215cd2a961a415a3ed0b1f984f1627719a7b102a75864943c4d87b","03d8ed7fc8f68a77f68d3afd007b7aa4c89944195143630ce183f0fa5438f2b559"],"m/2147483647/0/9":["0324fa91737588e4f85937303ce65c3b91b5f2ae506a72d92b83e3f5f9aeeb3c6f","02a011be72c4a400319212228106af278823a97acfe0a67e1ecd866d446b315114"],"m/2147483647/0/10":["025886ba287922a904881c7315e6fcc410a7976741771a5937d3a1a01b529f21fd","0243bb91ceed9d29d0c2ca66a8ab77e82110bbcc023beb4106f787964f44a0b972"],"m/2147483647/0/11":["0369d21684894cc2d4b2f5e581ede3cac9e8db4161a08e7737c1be129bb673d3d5","03c9ef27e3cd3dadc078fdfd9936a7ad9bf7954747085cf8f8a2a5bb3431f68a9f"],"m/2147483647/0/12":["03a73b8fd859bf6acebffdfffa2597199091daedd2c011ac67fc3494d8a1a8ceb6","025a213f7771c8be03f43f2e7f469ad4ef2cf6907ea284b227a786d1f55dfa7144"],"m/2147483647/0/13":["03a09f7ca257e1ab263cd5e6b0addc3ff868b93df132321d98775ca3505efb576f","03454c715739164bc55f347a651439cdf3ec146b35d2927beb60e8290b3916e082"],"m/2147483647/0/14":["03a64b1f7bd94a6b1a6e84ea444e0ba04e9deb86460934ccc37c0615a134a8257b","02794f09210b1811a455f3e1c7bcd35c76dff2523190fef9615eb27e2376acac1c"],"m/2147483647/0/15":["0392dca2fd9a3bc2b2a7d90a848719069fbc5f22bff7327bb8186c032514085263","032ee8a33ea76d70c7ae839448ca6c5b1af89146f2922e23ba1822df42dbc7e66a"],"m/2147483647/0/16":["031a22a1a3c1abad7c4d782ef6ba3cc00f2e8fe549eb33e0732200aff6d3174831","03bdce9781289e0c31cf727f4c93fe46f7930dd8fd68f818ce241f1ede268e8e0e"],"m/2147483647/0/17":["03b12d27e9aea2c2ad598e54e40860a705ac2ca2427aa511b501b38ec368ea5c7d","03e60d35d84d4536cad895215256b312bb4879a8d417251c279995e58f25da3d54"],"m/2147483647/0/18":["0380266cc9a9673676ad6a1b2e7148766df9c25b4dce299e5edc4f65b72aa58e64","0329e2a8a48c06c0c45dfdd2ab33e6455551557d8ebaf8c12fdf7470f8c45f1d28"],"m/2147483647/0/19":["036fe62af85560d7eea7c7af55e60b32a97dca80134d0aedffb19eb2705b9d6e01","02381c2c30b9f81e2a53c69028fbe11803acad0420b267719b7a80870be0baaeb7"],"m/0/0/2":["027bf94b8fc4e9b42683af25fda125ccab8760040717d100270dd4afd032692daf","026382c6c9357250d96dc21e43c053857a64efeac1887fdcbc107fbe3ecfc6115a"],"m/0/0/3":["03fd203acbd9af3cbbfb709458f8952078234a36094f12d00372e4b2b14cfdf419","03f2e5db59aea5dc89f53ac2a9f4ef66d41265c45afc5d763e0ca61ab70c7c61ec"],"m/0/0/4":["02a1d7cf4fcdbbf4de4002b844c3bff1639073f1cd6e5c4a4e02596b45d3f518c2","03b5fba813294e6ae096ea158833453caa5a945609b0a554696091b9b152bb0f7d"],"m/0/0/5":["0261d37e3b56ef4e106c59753037f516a4b1c45e056b2a3e00f8b77f15aaa7f8a5","0256a55e66e0de1603f0d600c0eb5f5486cf3512a776a36f3ab0d1941fc0dc9b09"],"m/0/0/6":["031db2826af215fe6cbe3f6e121b0497840fc49be133cff0a4d4eab679d6b99d70","021dd722c3f35dd04fcdb57f09b76c723d521fb36751de03ffd08096ddf1dc1f86"],"m/0/0/7":["0354ea75bdd9eb5beae7262e4a5eeb58bd10103ee0185e85b749ea39f6615d0f62","03f2c8f3b6478c0501a8578d5caf5ac2974f8213fc5e699d62dd2af58fbe8781d4"],"m/0/0/8":["0282e67df3bcd1e1662469b4c3151fb50ee1e46b75d787d91184c16b9803131f82","02921a7054af1e425f4137a5eb6b34d1f2b9d81c2625230194bc30657bb4277e11"],"m/0/0/9":["033e7e387933983ceab37c8388bd8ebc5119760f493ffe6f083bef0e5dfe22891d","02d660d60cc55d80912e0745cb142a8596a4604fbf72f9aadec0599aa2ed62461a"],"m/0/0/10":["022ce5b2750ae34512199856eab9e912dc25281cd8b88e7688a46c3b9a389701cb","02f14aa1608fce3b6088148709eb5fe72b61699c931fa8d95a45fab1106859d1b0"],"m/0/0/11":["0288dbef3302c1bc5556028adb33e2f9e03c119dbad4f706befb8ce86cea459f2b","03f13ced465e2e0a3aaa8895f3185d5711e0bebdaf507610b7a669ac8fc82da8fe"],"m/0/0/12":["031ab4677885340d2f927ccc9747f4346b79e4eb6c750695095a8a2524610fa94a","038c881910fbd8b50d193db4e0c84f5b7840820397f92cf0718a8e06d027125503"],"m/0/0/13":["031b568452cba22eb7a88c6085489e53e35abd16068882e71a140e47e12dee9c61","020d09885ee362101d12d34ce0918d41593634db1b9413e5415c6755753b9330e8"],"m/0/0/14":["024177bc9aa03cfc72eda2dfddffd7fe9d0c2f007fc3ba1a48280feae2b9fb117a","03394ad321668440c08da76eb35475ba3a8c0e8cbe0ed81468673a8c72d38fe457"],"m/0/0/15":["02037b1cc696ffbe9eba3684edd53653386ef6cd7728401c40120037593a4c2ae2","020ab8d6900ec9c11ca5d96dfc0ce7cf0ee71653a7c45118e89abb4b113147e53a"],"m/0/0/16":["023bcbb8d4726a546087cdb83740adf0ace879b7195a572c652fa8ce4dbe195a04","0392721b230d5163d28b27fc7e059b875711f12b3da448eabe7229bde57530e637"],"m/0/0/17":["02498ee74e849d3e9261dd1863038caf83d6a3bc2eeebecf17055d4bab44dee77f","03d4dc104b2e0981693e8097437de9b05334a85e2c8edb02783897859bdbc93e32"],"m/0/0/18":["0218a9f524fe54abf8c3afd21314296cfd93eaa9227acbd457e6c9a742dc233cf4","03760f3d0c5db969bda698ff9352e3b7c332216c34825f4c6e857e39c9aee7cd35"],"m/0/0/19":["033dd51f7737f0e9db79f5c38e4298bf3396346904ef3933d290a22e5b77048d9e","0221b2eedccb9a37515263071550069b3b349a166f0f131d0028e8600d9a2251b9"],"m/0/0/20":["02cb6c39161f3244d7769f7ab96346cae2cf21cb6f4538f5e7382d363dc2f836c7","034f7bda4d1e9ed6a3774608a4d6cd8582ab59fe3187f8a7a7cf914d89426ebe28"],"m/0/0/21":["035490549d65f1360f10340037250b171470ff4c86966318a2b1eead6d8b969aea","03f6a04f6fcd07a4f32c82d53710ed30e0f54d43d41c67c661d158b3d0830c3ea2"],"m/1/0/2":["02972eae7e4302e319c266578e14a07839c1e788296a92906e6d66d938211dad5f","039ed6b488f1571ad6527acd6b6c5b8453eacf6665dc5cb7852e33d1c8ea73f9fe"],"m/1/0/3":["02bec4728888c2c045108353994bae5731ec7a7b41459023b0023e10b8d616bd30","03ce1efe16214c9eac595382e46a68143dd11a335b3f7c971ddd719ac544a5fc4b"],"m/1/0/4":["030e2df1d341568225d8dfbe5d07e98dae9f90e0f43e19dcc68c998a6ed7bcc1f0","0380f4c07dc84faf42d51779f104aa6e3b5c3ce2d7684b3cb76d49faeefc2b69d6"],"m/1/0/5":["029a54ddaa25f433b493f4b72df8c1d41be2c4d2963b8b61ee63cc86d16c12d066","021567c95e0317442e7367aa4e3378dd46c5bcef5860f789272fea83b917de0669"],"m/1/0/6":["03590320d80b61cc0874b579f467c9b5ccc50d9ef875bcf6bdd12e2d0c211e8973","03ee4677b6ee89a9d355851f2230506c6897ff219062c0df4ad9a85c60f3535f93"],"m/1/0/7":["03caf98ab1c9b79d1dc8029453a6137c08787b04043b79af3cb42d41d2d3f1338f","023f39ae4e2f4f3887d5fc58e0d3a0d7ee267dc04aa257c75b6b2d67d2f5580f81"],"m/1/0/8":["0352a2a3ea8209c9a2b633d788796ac2d16c08022440e04a77ab2835c7f971d266","0291bc248b3da997f35e8fae98a75a91fdac2819d74c4e270899338d48f7389e87"],"m/1/0/9":["02468d32d9c3c62418d506d4cd0da6cd2022d5bcafdb5f847cf7bde7a48ec6848b","032713d90d12eb6a072f3c1db6c0d3b680d3f78883016135fc0f78e8193d41d4b4"],"m/1/0/10":["034863cc6bab9b059be53413ba75c5fc286647c20d7f9e5512ef4754ea301dd1ce","03a33ab9c32a2264ee2464ebbb5892f0e34acf0fdede4f87395a89e9dacdd4930e"],"m/1/0/11":["031e19296695bfe8a96ba3bf58afa805ee1bd5471fddb3929b1678d69d442d69c9","0270feb33956fd9e937019d629523e26437493c0856514011e6aec88baf7721295"],"m/1/0/12":["03cce695d3c3843bf73e851b2446a77d7e235e5b80b4f4474f9946292eb8218742","039ea96c8822f0ec7ed28308d277f3e730480d7573579cd11b89aef4364cd9ffeb"],"m/1/0/13":["02ab4ac38eb405e822d12c0f0f354f04f9ee1d991dde887a5c1171096fe503158f","036809e60cae1203da8884ea1f85d4669ce6e053f8ba605d775e271b70ab4f6787"],"m/1/0/14":["039d61da23a8610fa0ee58eb37d7cea7ea9396c79153da97280ccf5e46718e3bac","03015c27bcc778682781fd6ad30aa6041db0b7e24270818cdceece0043ccc34b26"],"m/1/0/15":["03c088ed669132835d2728b0ecf294271c8388988c6ae264d43ca24f50e4005f81","03e2c118c9445a2ddc4c8afeb0ba49e21be3f818a483d346418b8922b8a371a2b7"],"m/1/0/16":["02bba7df9847f463c6b23eca37a4bd6efa3801a52b8ddfad804d902e783b70c81c","03764b657f23996e31c64a701facc1cbeb0c9edfdd605e2c1ed36cf48197565d45"],"m/1/0/17":["020445179c522295b89bf4bfd582eb03422e3fa20dcd29263925e9f44282d476d8","036e47bdd32f3061aed1c1f8c2a32b038c7b72391cb1f80ebfc150e58f88372766"],"m/1/0/18":["024d88c4bfcbba713d49e1edcd035234aaa1ee76ad7bcf75bf074a16658a6b0b6d","02b861e7a20d89f6875d2e44c78dbadb99503e282e5e60e9f65657af6fea81d425"],"m/1/0/19":["023a8ca9d5300181f157e1930d3b0800eebe7683d8df72e6cbf28834dbf1be5d60","026053c4f84c10d15890c0b254522972931bc2d5b7cdf9c1f9f3137c22edf3ecd3"],"m/1/0/20":["03137c66e9f3d61aba659f408d77a293fa0f3fea4ccb911074a681d6f61a55d023","0291aa1bbfbef59b16b0e37e185a706c589d448cb02e860c5df9c9d7242ecc739f"],"m/1/0/21":["03c08673e0cae55318bc9dcc4b5f11eb3ff71d42de04015e255dde3fd8cba7e09e","02423d4eab06cd5b26e71d145283523c011d58032700c517f00b328d2c90cf109f"]}},"txProposals":{"txps":[{"creator":"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5","createdTs":1405543144016,"seenBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543144016,"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543144645},"signedBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543144016},"rejectedBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543170040},"sentTs":null,"sentTxid":null,"inputChainPaths":["m/45\'/0/0/0"],"comment":"blablabla","builderObj":{"valueInSat":"29000000","valueOutSat":"8900000","feeSat":"10000","remainderSat":"20090000","hashToScriptMap":{"2NBtv6DdXj8HBunyGqpW9H8bUtW5x3rfVTj":"5221028a4b63f26253f3a8731577b8e1ee480950ad5833ebbf106fe3463bfc07cc3b90210332efa054c08cb77506a35ee0762cb7156f244566703ec08e433568ec0397bec852ae"},"selectedUtxos":[{"address":"2NBtv6DdXj8HBunyGqpW9H8bUtW5x3rfVTj","txid":"a9f4dda3f092e37244bc4e77ea921fed01d5b8ea49613dfdc0dc8afdd70190b5","vout":1,"ts":1405543855,"scriptPubKey":"a914cc93216398b77b5f8c451ca3a357bef961678be987","amount":0.29,"confirmations":0,"confirmationsFromCache":false}],"inputsSigned":0,"signaturesAdded":1,"signhash":1,"spendUnconfirmed":true,"tx":"0100000001b59001d7fd8adcc0fd3d6149eab8d501ed1f92ea774ebc4472e392f0a3ddf4a9010000009300493046022100ccbb8f398f74a76236629b8499ffc6f9518a2091f5a61a9a352c0a10f615961e022100b8f0769c76cf33bec3d7f81d9da2b74cf6e8a5e0a24ee5f48172854d8bcdbfa101475221028a4b63f26253f3a8731577b8e1ee480950ad5833ebbf106fe3463bfc07cc3b90210332efa054c08cb77506a35ee0762cb7156f244566703ec08e433568ec0397bec852aeffffffff02a0cd8700000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288ac908c32010000000017a914560c292066792531164149c5ed63ad2793a61b928700000000"}},{"creator":"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5","createdTs":1405543188745,"seenBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543188745,"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543189341},"signedBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543188745,"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543206819},"rejectedBy":{},"sentTs":1405543207304,"sentTxid":"169bc92693dd2e27724eeba81e54210e842035bd3af6c52e6a6a5e908f1a4f66","inputChainPaths":["m/45\'/0/0/0"],"comment":"que parece","builderObj":{"valueInSat":"29000000","valueOutSat":"9000000","feeSat":"10000","remainderSat":"19990000","hashToScriptMap":{"2NBtv6DdXj8HBunyGqpW9H8bUtW5x3rfVTj":"5221028a4b63f26253f3a8731577b8e1ee480950ad5833ebbf106fe3463bfc07cc3b90210332efa054c08cb77506a35ee0762cb7156f244566703ec08e433568ec0397bec852ae"},"selectedUtxos":[{"address":"2NBtv6DdXj8HBunyGqpW9H8bUtW5x3rfVTj","txid":"a9f4dda3f092e37244bc4e77ea921fed01d5b8ea49613dfdc0dc8afdd70190b5","vout":1,"ts":1405543855,"scriptPubKey":"a914cc93216398b77b5f8c451ca3a357bef961678be987","amount":0.29,"confirmations":1,"confirmationsFromCache":false}],"inputsSigned":1,"signaturesAdded":2,"signhash":1,"spendUnconfirmed":true,"tx":"0100000001b59001d7fd8adcc0fd3d6149eab8d501ed1f92ea774ebc4472e392f0a3ddf4a901000000da00483045022035423cc74824ba904907678dda3b62a20a787b96d1b3e9f3e9546f9c57f4e45902210080a1ff1c39f458ac1642b9e948bd62fd70563b5252e749cc8fc642cd763ee830014730440220524a13f36cfb03caa246d7d84de634ec9386f2c39c19bfa926037f48da86262b022050e58a6503d105ad2805f86806810a1aa7f20d6271e1340b42fa91ab6a30f3e801475221028a4b63f26253f3a8731577b8e1ee480950ad5833ebbf106fe3463bfc07cc3b90210332efa054c08cb77506a35ee0762cb7156f244566703ec08e433568ec0397bec852aeffffffff0240548900000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288acf00531010000000017a9146130a9d51f996b7a1b9d3e10c80930834251909d8700000000"}},{"creator":"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba","createdTs":1405543505848,"seenBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543505848,"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543590221},"signedBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543505848,"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543590221},"rejectedBy":{},"sentTs":1405543610315,"sentTxid":"6fe851b54b777a75fe80fa204dc674395e2af69efb1f7c0017e909eb82c3d914","inputChainPaths":["m/45\'/0/1/1"],"comment":"mandaaaaaaa","builderObj":{"valueInSat":"19990000","valueOutSat":"19980000","feeSat":"10000","remainderSat":"0","hashToScriptMap":{"2N277q5r8Ab6XLJNCjXXFdh5itDJRQCv9ts":"5221020389327ee8ae7d0ee3f8187842d23a4070bdd8a27c0bcddd05d80ef39009253d21025c9b49bdf17d97bd82ea1b87793082f857247f0f9b999937a166ec994bb1b41f52ae"},"selectedUtxos":[{"address":"2N277q5r8Ab6XLJNCjXXFdh5itDJRQCv9ts","txid":"169bc92693dd2e27724eeba81e54210e842035bd3af6c52e6a6a5e908f1a4f66","vout":1,"ts":1405543157,"scriptPubKey":"a9146130a9d51f996b7a1b9d3e10c80930834251909d87","amount":0.1999,"confirmationsFromCache":false}],"inputsSigned":1,"signaturesAdded":2,"signhash":1,"spendUnconfirmed":true,"tx":"0100000001664f1a8f905e6a6a2ec5f63abd3520840e21541ea8eb4e72272edd9326c99b1601000000db0048304502206b18b3dba2646c552469d8ef52d7656f6a65f563032530f622abdfd8bd4c5cee022100e804b406eddebbc827646141e74dc64c76a770ed4e35183ffd35d265ad9f7d3b01483045022100f6c013638ff0a316b1baa93dfffba6a98cf3033c133e8bd899e933c9c3e47ce10220530f40e7ea52ae58bec695edbec6d566d2ee8e7b5f33f95e33093ad1e29a125401475221020389327ee8ae7d0ee3f8187842d23a4070bdd8a27c0bcddd05d80ef39009253d21025c9b49bdf17d97bd82ea1b87793082f857247f0f9b999937a166ec994bb1b41f52aeffffffff01e0de3001000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288ac00000000"}},{"creator":"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba","createdTs":1405543781381,"seenBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543781381,"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543782017},"signedBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543781381},"rejectedBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543794590},"sentTs":null,"sentTxid":null,"inputChainPaths":["m/45\'/0/0/1"],"comment":"1","builderObj":{"valueInSat":"29000000","valueOutSat":"1000000","feeSat":"10000","remainderSat":"27990000","hashToScriptMap":{"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb":"52210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352ae"},"selectedUtxos":[{"address":"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb","txid":"6c9da5b0da4bab0d576033325e987b10ccf2b9bf479d306b6aae36efeaa56892","vout":0,"ts":1405543698,"scriptPubKey":"a9147d274ac50968d7823b6cbc1b38770deb7157995387","amount":0.29,"confirmationsFromCache":false}],"inputsSigned":0,"signaturesAdded":1,"signhash":1,"spendUnconfirmed":true,"tx":"01000000019268a5eaef36ae6a6b309d47bfb9f2cc107b985e323360570dab4bdab0a59d6c000000009200483045022064d877bc5171fbaef909c2a1a924e0023b3ccc0b530cb46653f06ecb230283e8022100bc6658d60ad4f7120d9226c8f6eada87f3b0388f73c458011988bab36e78ba15014752210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352aeffffffff0240420f00000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288acf017ab010000000017a91421c4a435d9ac263ec55b35a1a5ca95e979639b9b8700000000"}},{"creator":"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5","createdTs":1405543835343,"seenBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543835343,"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543835968},"signedBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543835343},"rejectedBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543850998},"sentTs":null,"sentTxid":null,"inputChainPaths":["m/45\'/0/0/1"],"comment":"2","builderObj":{"valueInSat":"29000000","valueOutSat":"1000000","feeSat":"10000","remainderSat":"27990000","hashToScriptMap":{"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb":"52210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352ae"},"selectedUtxos":[{"address":"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb","txid":"6c9da5b0da4bab0d576033325e987b10ccf2b9bf479d306b6aae36efeaa56892","vout":0,"ts":1405543698,"scriptPubKey":"a9147d274ac50968d7823b6cbc1b38770deb7157995387","amount":0.29,"confirmationsFromCache":false}],"inputsSigned":0,"signaturesAdded":1,"signhash":1,"spendUnconfirmed":true,"tx":"01000000019268a5eaef36ae6a6b309d47bfb9f2cc107b985e323360570dab4bdab0a59d6c0000000092004830450220302baae7de2e0f102bf3af2d5f450f673e51bd143020141a769ccdcdf16af188022100e7abc087c76050ed649e7139a5a136969e74e24a8d8f6223d3219ad033a26451014752210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352aeffffffff0240420f00000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288acf017ab010000000017a9148b102abba0729fb0690c61cf7187064d692d43d78700000000"}},{"creator":"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba","createdTs":1405543869803,"seenBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543869803,"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543870411},"signedBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543869803,"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543890406},"rejectedBy":{},"sentTs":1405543890913,"sentTxid":"6a0f61574ad65e537e7e99298968db565f97b894b61f4c8f8fac8fcaedb83e2b","inputChainPaths":["m/45\'/0/0/1"],"comment":"3","builderObj":{"valueInSat":"29000000","valueOutSat":"1100000","feeSat":"10000","remainderSat":"27890000","hashToScriptMap":{"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb":"52210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352ae"},"selectedUtxos":[{"address":"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb","txid":"6c9da5b0da4bab0d576033325e987b10ccf2b9bf479d306b6aae36efeaa56892","vout":0,"ts":1405543698,"scriptPubKey":"a9147d274ac50968d7823b6cbc1b38770deb7157995387","amount":0.29,"confirmationsFromCache":false}],"inputsSigned":1,"signaturesAdded":2,"signhash":1,"spendUnconfirmed":true,"tx":"01000000019268a5eaef36ae6a6b309d47bfb9f2cc107b985e323360570dab4bdab0a59d6c00000000db00483045022100a8ce7907f9fd7dd41dd65c2dec425e008efea06ee7c80787c10c0e210fbf181302207712c0fdd1cb25836ac1fc2fd303c1e26b85e8980417719b9ed50e977a9693ec01483045022100d1780c4f028cd898920aca3eaceba352ed9306cd17f019ae2f634e8facad149a02203c84ab2093da8e22577e93f27a732f0728d4e6db0c749f3cd3d898d6a025152a014752210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352aeffffffff02e0c81000000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288ac5091a9010000000017a914cc1cab78458b1a951b91c6dcd7eeeeb682f506388700000000"}}],"walletId":"55d4bd062d32f90a","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPdWUAmaaopPftevC72Jtiu19V8ee5XijL9JvogqfR95uVrL85f8yBdQMq3KyQtG3Q91yWQb3XDbWWpcdWFDAmJ7Xy2XWkGJu","networkName":"testnet","privateKeyCache":{"m/45\'/0/0/0":"b6fd8d1a079efd523da34f31ba81f544fc3d0a728a8a98299d8980682518e79c","m/45\'/0/1/1":"0f4d52d2a99e4c8c1c2edf09fef12407c3abd2304b961198c3f131a8c8443a13","m/45\'/0/0/1":"de5c191c343bd6017b98708c03344849624a14e2c167cfd6eb8dcb075d139293"}},"addressBook":{"msj42CCGruhRsFrGATiUuh25dtxYtnpbTx":{"hidden":false,"createdTs":1405543109222,"copayerId":"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba","label":"faucet","signature":"3045022067576e5b37f2707a8dc66e57511ad9b10a3125bd95193fff6f8f6402969c3bf3022100adff9f417db07d88face13b3d13f422740d4421440cade1a205684dfdc5d733a"}}}'; var encryptedLegacyO = 'U2FsdGVkX19yGM1uBAIzQa8Po/dvUicmxt1YyRk/S97PcZ6I6rHMp9dMagIrehg4Qd6JHn/ustmFHS7vmBYj0EBpf6rdXiQezaWnVAJS9/xYjAO36EFUbl+NmUanuwujAxgYdSP/sNssRLeInvExmZYW993EEclxkwL6YUyX66kKsxGQo2oWng0NreBJNhFmrbOEWeFje2PiWP57oUjKsurFzwpluAAarUTYSLud+nXeabC7opzOP5yqniWBMJz0Ou8gpNCWCMhG/P9F9ccVPY7juyd0Hf41FVse8nd2++axKB57+paozLdO+HRfV6zkMqC3h8gWY7LkS75j3bvqcTw9LhXmzE0Sz21n9yDnRpA4chiAvtwQvvBGgj1pFMKhNQU6Obac9ZwKYzUTgdDn3Uzg1UlDzgyOh9S89rbRTV84WB+hXwhuVluWzbNNYV3vXe5PFrocVktIrtS3xQh+k/7my4A6/gRRrzNYpKrUASJqDS/9u9WBkG35xD63J/qXjtG2M0YPwbI57BK1IK4K510b8V72lz5U2XQrIC4ldBwni1rpSavwCJV9xF6hUdOmNV8fZsVHP0NeN1PYlLkSb2QgfuoWnkcsJerwuFR7GZC/i6efrswtpO0wMEQr/J0CLbeXlHAru6xxjCBhWoJvZpMGw72zgnDLoyMNsEVglNhx/VlV9ZMYkkdaEYAxPOEIyZdQ5MS+2jEAlXf818n/xzJSVrniCn9be8EPePvkw35pivprvy09vbW4cKsWBKvgIyoT6A3OhUOCCS8E9cg0WAjjav2EymrbKmGWRHaiD+EoJqaDg6s20zhHn1YEa/YwvGGSB5+Hg8baLHD8ZASvxz4cFFAAVZrBUedRFgHzqwaMUlFXLgueivWUj7RXlIw6GuNhLoo1QkhZMacf23hrFxxQYvGBRw1hekBuDmcsGWljA28udBxBd5f9i+3gErttMLJ6IPaud590uvrxRIclu0Sz9R2EQX64YJxqDtLpMY0PjddSMu8vaDRpK9/ZSrnz/xrXsyabaafz4rE/ItFXjwFUFkvtmuauHTz6nmuKjVfxvNLNAiKb/gI7vQyUhnTbKIApe7XyJsjedNDtZqsPoJRIzdDmrZYxGStbAZ7HThqFJlSJ9NPNhH+E2jm3TwL5mwt0fFZ5h+p497lHMtIcKffESo7KNa2juSVNMDREk0NcyxGXGiVB2FWl4sLdvyhcsVq0I7tmW6OGZKRf8W49GCJXq6Ie69DJ9LB1DO67NV1jsYbsLx9uhE2yEmpWZ3jkoCV/Eas4grxt0CGN6EavzQ=='; var legacyPassword = '1'; From 5cf4fe0b665bba6c2c58de2b2ad8c99e28ef2731 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 15 Sep 2014 13:56:38 -0300 Subject: [PATCH 19/45] ALL TEST PASSING!!! --- js/models/Storage.js | 33 ++++--- js/models/core/WalletFactory.js | 8 +- test/test.Passphrase.js | 1 - test/test.Storage.js | 66 ++++++++++++-- test/test.WalletFactory.js | 147 +++++++++++++++++++++----------- 5 files changed, 184 insertions(+), 71 deletions(-) diff --git a/js/models/Storage.js b/js/models/Storage.js index 5750eb428..3433589bf 100644 --- a/js/models/Storage.js +++ b/js/models/Storage.js @@ -111,7 +111,7 @@ Storage.prototype.getSessionId = function(cb) { return cb(sessionId); sessionId = bitcore.SecureRandom.getRandomBuffer(8).toString('hex'); - self.sessionStorage.setItem('sessionId', sessionId, function(){ + self.sessionStorage.setItem('sessionId', sessionId, function() { return cb(sessionId); }); }); @@ -232,31 +232,36 @@ Storage.prototype.deleteWallet = function(walletId, cb) { preconditions.checkArgument(walletId); preconditions.checkArgument(cb); var err; + var self = this; var toDelete = {}; - toDelete['nameFor::' + walletId] = 1; this.storage.allKeys(function(allKeys) { - for (var key in allKeys) { + for (var ii in allKeys) { + var key = allKeys[ii]; var split = key.split('::'); if (split.length == 2 && split[0] === walletId) { toDelete[key] = 1; }; } + var l = Object.keys(toDelete).length, + j = 0; + if (!l) + return cb(new Error('WNOTFOUND: Wallet not found')); + + toDelete['nameFor::' + walletId] = 1; + l++; + + for (var i in toDelete) { + self.removeGlobal(i, function() { + if (++j == l) + return cb(err); + }); + + } }); - var l = toDelete.length, - j = 0; - if (!l) - return cb(new Error('WNOTFOUND: Wallet not found')); - - for (var i in toDelete) { - this.removeGlobal(i, function() { - if (++j == l) - return cb(err); - }); - } }; Storage.prototype.setLastOpened = function(walletId, cb) { diff --git a/js/models/core/WalletFactory.js b/js/models/core/WalletFactory.js index eacfeb48f..48010d1c7 100644 --- a/js/models/core/WalletFactory.js +++ b/js/models/core/WalletFactory.js @@ -53,6 +53,7 @@ function WalletFactory(config, version, pluginManager) { this.storage = new this.Storage(storageOpts); +<<<<<<< HEAD this.networks = { 'livenet': new this.Network(config.network.livenet), 'testnet': new this.Network(config.network.testnet), @@ -63,6 +64,10 @@ function WalletFactory(config, version, pluginManager) { }; this.walletDefaults = config.wallet; +======= + this.networkName = config.networkName; + this.walletDefaults = config.wallet || {}; +>>>>>>> ALL TEST PASSING!!! this.version = version; }; @@ -90,7 +95,6 @@ WalletFactory.prototype.fromObj = function(obj, skipFields) { preconditions.checkState(networkName); preconditions.checkArgument(obj); - // not stored options obj.opts = obj.opts || {}; obj.opts.reconnectDelay = this.walletDefaults.reconnectDelay; @@ -418,7 +422,7 @@ WalletFactory.prototype.joinCreateSession = function(opts, cb) { joinNetwork.start(opts, function() { joinNetwork.greet(decodedSecret.pubKey, opts.secretNumber); joinNetwork.on('data', function(sender, data) { - if (data.type === 'walletId') { + if (data.type === 'walletId' && data.opts) { if (data.networkName !== decodedSecret.networkName) { return cb('badNetwork'); } diff --git a/test/test.Passphrase.js b/test/test.Passphrase.js index 75074108b..dd249f283 100644 --- a/test/test.Passphrase.js +++ b/test/test.Passphrase.js @@ -36,5 +36,4 @@ describe('Passphrase model', function() { done(); }); }); - }); diff --git a/test/test.Storage.js b/test/test.Storage.js index 0363108ab..170235f13 100644 --- a/test/test.Storage.js +++ b/test/test.Storage.js @@ -16,7 +16,7 @@ describe('Storage model', function() { storage: localMock, sessionStorage: sessionMock, }); - s._setPassphrase('mysupercoolpassword'); + s.setPassphrase('mysupercoolpassword'); it('should create an instance', function() { var s2 = new Storage({ @@ -210,8 +210,8 @@ describe('Storage model', function() { }); }); }); - describe('#deleteWallet', function(done) { - it('should delete a wallet', function() { + describe('#deleteWallet', function() { + it('should fail to delete a unexisting wallet', function(done) { var s = new Storage({ storage: localMock, sessionStorage: sessionMock, @@ -219,9 +219,26 @@ describe('Storage model', function() { }); s.set('1', "hola", 'juan', function() { s.set('2', "hola", 'juan', function() { - s.deleteWallet('1', function() { + s.deleteWallet('3', function(err) { + err.toString().should.include('WNOTFOUND'); + done(); + }); + }); + }); + }); + + it('should delete a wallet', function(done) { + var s = new Storage({ + storage: localMock, + sessionStorage: sessionMock, + password: 'password' + }); + s.set('1', "hola", 'juan', function() { + s.set('2', "hola", 'juan', function() { + s.deleteWallet('1', function(err) { + should.not.exist(err); s.getWallets(function(ws) { - s.getWallets().length.should.equal(1); + ws.length.should.equal(1); ws[0].should.deep.equal({ id: '2', name: undefined @@ -299,4 +316,43 @@ describe('Storage model', function() { }); }); }); + + describe('#import', function() { + it('should be able to decrypt an old backup', function() { + var s = new Storage({ + storage: localMock, + sessionStorage: sessionMock, + password: legacyPassword1 , + }); + var wo = s.import(encryptedLegacy1); + should.exist(wo); + wo.opts.id.should.equal('48ba2f1ffdfe9708'); + wo.opts.spendUnconfirmed.should.equal(true); + wo.opts.requiredCopayers.should.equal(1); + wo.opts.totalCopayers.should.equal(1); + wo.opts.name.should.equal('pepe wallet'); + wo.opts.version.should.equal('0.4.7'); + wo.publicKeyRing.walletId.should.equal('48ba2f1ffdfe9708'); + wo.publicKeyRing.networkName.should.equal('testnet'); + wo.publicKeyRing.requiredCopayers.should.equal(1); + wo.publicKeyRing.totalCopayers.should.equal(1); + wo.publicKeyRing.indexes.length.should.equal(2); + JSON.stringify(wo.publicKeyRing.indexes[0]).should.equal('{"copayerIndex":2147483647,"changeIndex":0,"receiveIndex":1}'); + JSON.stringify(wo.publicKeyRing.indexes[1]).should.equal('{"copayerIndex":0,"changeIndex":0,"receiveIndex":1}'); + wo.publicKeyRing.copayersBackup.length.should.equal(1); + wo.publicKeyRing.copayersBackup[0].should.equal('0298f65b2694c55f9048bc05f10368242727c7f9d2065cbd788c3ecde1ec57f33f'); + wo.publicKeyRing.copayersExtPubKeys.length.should.equal(1); + wo.publicKeyRing.copayersExtPubKeys[0].should.equal('tpubD9SGoP7CXsqSKTiQxCZSCpicDcophqnE4yuqjfw5M9tAR3fSjT9GDGwPEUFCN7SSmRKGDLZgKQePYFaLWyK32akeSan45TNTd8sgef9Ymh6'); + wo.privateKey.extendedPrivateKeyString.should.equal('tprv8ZgxMBicQKsPfQCscb7CtJKzixxcVSyrCVcfr3WCFbtT8kYTzNubhjQ5R7AuYJgPCcSH4R8T34YVxeohKGhAB9wbB4eFBbQFjUpjGCqptHm'); + wo.privateKey.networkName.should.equal('testnet'); + + + }); + }); + }); + +var legacyPassword1 = '1DUpLRbuVpgLkcEY8gY8iod/SmA7+OheGZJ9PtvmTlvNE0FkEWpCKW9STdzXYJqbn0wiAapE4ojHNYj2hjYYAQ=='; +var encryptedLegacy1 = 'U2FsdGVkX19yGM1uBAIzQa8Po/dvUicmxt1YyRk/S97PcZ6I6rHMp9dMagIrehg4Qd6JHn/ustmFHS7vmBYj0EBpf6rdXiQezaWnVAJS9/xYjAO36EFUbl+NmUanuwujAxgYdSP/sNssRLeInvExmZYW993EEclxkwL6YUyX66kKsxGQo2oWng0NreBJNhFmrbOEWeFje2PiWP57oUjKsurFzwpluAAarUTYSLud+nXeabC7opzOP5yqniWBMJz0Ou8gpNCWCMhG/P9F9ccVPY7juyd0Hf41FVse8nd2++axKB57+paozLdO+HRfV6zkMqC3h8gWY7LkS75j3bvqcTw9LhXmzE0Sz21n9yDnRpA4chiAvtwQvvBGgj1pFMKhNQU6Obac9ZwKYzUTgdDn3Uzg1UlDzgyOh9S89rbRTV84WB+hXwhuVluWzbNNYV3vXe5PFrocVktIrtS3xQh+k/7my4A6/gRRrzNYpKrUASJqDS/9u9WBkG35xD63J/qXjtG2M0YPwbI57BK1IK4K510b8V72lz5U2XQrIC4ldBwni1rpSavwCJV9xF6hUdOmNV8fZsVHP0NeN1PYlLkSb2QgfuoWnkcsJerwuFR7GZC/i6efrswtpO0wMEQr/J0CLbeXlHAru6xxjCBhWoJvZpMGw72zgnDLoyMNsEVglNhx/VlV9ZMYkkdaEYAxPOEIyZdQ5MS+2jEAlXf818n/xzJSVrniCn9be8EPePvkw35pivprvy09vbW4cKsWBKvgIyoT6A3OhUOCCS8E9cg0WAjjav2EymrbKmGWRHaiD+EoJqaDg6s20zhHn1YEa/YwvGGSB5+Hg8baLHD8ZASvxz4cFFAAVZrBUedRFgHzqwaMUlFXLgueivWUj7RXlIw6GuNhLoo1QkhZMacf23hrFxxQYvGBRw1hekBuDmcsGWljA28udBxBd5f9i+3gErttMLJ6IPaud590uvrxRIclu0Sz9R2EQX64YJxqDtLpMY0PjddSMu8vaDRpK9/ZSrnz/xrXsyabaafz4rE/ItFXjwFUFkvtmuauHTz6nmuKjVfxvNLNAiKb/gI7vQyUhnTbKIApe7XyJsjedNDtZqsPoJRIzdDmrZYxGStbAZ7HThqFJlSJ9NPNhH+E2jm3TwL5mwt0fFZ5h+p497lHMtIcKffESo7KNa2juSVNMDREk0NcyxGXGiVB2FWl4sLdvyhcsVq0I7tmW6OGZKRf8W49GCJXq6Ie69DJ9LB1DO67NV1jsYbsLx9uhE2yEmpWZ3jkoCV/Eas4grxt0CGN6EavzQ=='; + + diff --git a/test/test.WalletFactory.js b/test/test.WalletFactory.js index 78dca9aff..2ec67e64a 100644 --- a/test/test.WalletFactory.js +++ b/test/test.WalletFactory.js @@ -1,5 +1,6 @@ 'use strict'; + var chai = chai || require('chai'); var should = chai.should(); @@ -10,7 +11,6 @@ var FakeBlockchain = require('./mocks/FakeBlockchain'); var FakeStorage = function FakeStorage() {}; var WalletFactory = require('../js/models/core/WalletFactory'); var Passphrase = require('../js/models/core/Passphrase'); -var LocalEncrypted = copay.StorageLocalEncrypted; var mockLocalStorage = require('./mocks/FakeLocalStorage'); var mockSessionStorage = require('./mocks/FakeLocalStorage'); @@ -89,18 +89,18 @@ describe('WalletFactory model', function() { beforeEach(function() { wf = new WalletFactory(config, '0.0.1'); + wf.storage.setPassphrase = sinon.spy(); wf.storage.getSessionId = sinon.spy(); wf.storage.setFromObj = sinon.spy(); wf.storage.setLastOpened = sinon.stub().yields(null); + + var w = sinon.stub(); w.store = sinon.stub().yields(null); wf._getWallet = sinon.stub().returns(w); - - - wf.network.setHexNonce = sinon.spy(); }); @@ -145,6 +145,7 @@ describe('WalletFactory model', function() { describe('#fromObj / #toObj', function() { it('round trip', function() { + var wf = new WalletFactory(config, '0.0.5'); var w = wf.fromObj(JSON.parse(o)); should.exist(w); @@ -446,9 +447,32 @@ describe('WalletFactory model', function() { nickname: 'test', passphrase: 'pass' }; - it('should yield network error', function(done) { + + it('should yield bad network error', function(done) { + wf.network.greet = sinon.stub(); + wf.network.on = sinon.stub(); + wf.network.on.withArgs('data').yields('senderId', { + type: 'walletId', + networkName: 'aWeirdNetworkName', + opts: {}, + }); opts.privHex = undefined; - wf.network.on = sinon.stub().withArgs('serverError').yields(null); + wf.joinCreateSession(opts, function(err, w) { + err.should.equal('badNetwork'); + done(); + }); + }); + + + it('should yield to join error', function(done) { + opts.privHex = undefined; + wf.network.greet = sinon.stub(); + wf.network.on = sinon.stub(); + wf.network.on.withArgs('serverError').yields(null); + wf.network.on.withArgs('data').yields('senderId', { + type: 'walletId', + networkName: wf.networkName, + }); wf.joinCreateSession(opts, function(err, w) { err.should.equal('joinError'); done(); @@ -456,19 +480,45 @@ describe('WalletFactory model', function() { }); - it('should call network.start', function(done) { + it('should call network.start / create', function(done) { opts.privHex = undefined; wf.network.cleanUp = sinon.spy(); wf.network.greet = sinon.spy(); - wf.network.on = sinon.stub().withArgs('connected').yields(null); - wf.network.start = sinon.stub().yields(null); + + wf.network.on = sinon.stub(); + wf.network.on.withArgs('connected').yields(null); + wf.network.on.withArgs('data').yields('senderId', { + type: 'walletId', + networkName: wf.networkName, + opts: {}, + }); + wf.create = sinon.stub().yields(null, 'wallet'); wf.joinCreateSession(opts, function(err, w) { - console.log('[test.WalletFactory.js.454:err:]', err); //TODO wf.network.start.calledOnce.should.equal(true); + wf.create.calledOnce.should.equal(true); done(); }); + }); + it('should return walletFull', function(done) { + opts.privHex = undefined; + wf.network.cleanUp = sinon.spy(); + wf.network.greet = sinon.spy(); + wf.network.start = sinon.stub().yields(null); + + wf.network.on = sinon.stub(); + wf.network.on.withArgs('connected').yields(null); + wf.network.on.withArgs('data').yields('senderId', { + type: 'walletId', + networkName: wf.networkName, + opts: {}, + }); + wf.create = sinon.stub().yields(null, null); + wf.joinCreateSession(opts, function(err, w) { + err.should.equal('walletFull'); + done(); + }); }); it('should accept a priv key a input', function() { @@ -490,7 +540,9 @@ describe('WalletFactory model', function() { }); }); }); - describe('dont break backwards compatibility of wallets', function() { + + + describe('Backwards compatibility tests', function() { it('should be able to import unencrypted legacy wallet TxProposal: v0', function() { var wf = new WalletFactory(config, '0.0.5'); var w = wf.fromObj(JSON.parse(legacyO)); @@ -502,43 +554,38 @@ describe('WalletFactory model', function() { should.exist(w.privateKey.toObj()); }); - it('should be able to import simple 1-of-1 encrypted legacy testnet wallet', function(done) { - var pp = new Passphrase(config.passphrase); - var alternateConfig = JSON.parse(JSON.stringify(config)); - alternateConfig.Storage = LocalEncrypted; - alternateConfig.storage = { - localStorage: mockLocalStorage, - sessionStorage: mockSessionStorage - }; - var wf = new WalletFactory(alternateConfig, '0.4.7'); + it('should be able to import simple 1-of-1 encrypted legacy testnet wallet', function() { - pp.getBase64Async(legacyPassword, function(passphrase) { - var w, errMsg; - w = wf.import(encryptedLegacyO, passphrase); - should.exist(w); - w.isReady().should.equal(true); - var wo = w.toObj(); - wo.opts.id.should.equal('48ba2f1ffdfe9708'); - wo.opts.spendUnconfirmed.should.equal(true); - wo.opts.requiredCopayers.should.equal(1); - wo.opts.totalCopayers.should.equal(1); - wo.opts.name.should.equal('pepe wallet'); - wo.opts.version.should.equal('0.4.7'); - wo.publicKeyRing.walletId.should.equal('48ba2f1ffdfe9708'); - wo.publicKeyRing.networkName.should.equal('testnet'); - wo.publicKeyRing.requiredCopayers.should.equal(1); - wo.publicKeyRing.totalCopayers.should.equal(1); - wo.publicKeyRing.indexes.length.should.equal(2); - JSON.stringify(wo.publicKeyRing.indexes[0]).should.equal('{"copayerIndex":2147483647,"changeIndex":0,"receiveIndex":1}'); - JSON.stringify(wo.publicKeyRing.indexes[1]).should.equal('{"copayerIndex":0,"changeIndex":0,"receiveIndex":1}'); - wo.publicKeyRing.copayersBackup.length.should.equal(1); - wo.publicKeyRing.copayersBackup[0].should.equal('0298f65b2694c55f9048bc05f10368242727c7f9d2065cbd788c3ecde1ec57f33f'); - wo.publicKeyRing.copayersExtPubKeys.length.should.equal(1); - wo.publicKeyRing.copayersExtPubKeys[0].should.equal('tpubD9SGoP7CXsqSKTiQxCZSCpicDcophqnE4yuqjfw5M9tAR3fSjT9GDGwPEUFCN7SSmRKGDLZgKQePYFaLWyK32akeSan45TNTd8sgef9Ymh6'); - wo.privateKey.extendedPrivateKeyString.should.equal('tprv8ZgxMBicQKsPfQCscb7CtJKzixxcVSyrCVcfr3WCFbtT8kYTzNubhjQ5R7AuYJgPCcSH4R8T34YVxeohKGhAB9wbB4eFBbQFjUpjGCqptHm'); - wo.privateKey.networkName.should.equal('testnet'); - done(); - }); + wf.storage.import = sinon.stub(); + wf.storage.setPassphrase = sinon.spy(); + wf.storage.import.withArgs('dummy').returns(JSON.parse(legacy1)); + + var w = wf.import('dummy', 'xxx'); + should.exist(w); + wf.storage.setPassphrase.calledOnce.should.equal(true); + wf.storage.setPassphrase.getCall(0).args[0].should.equal('xxx'); + + w.isReady().should.equal(true); + var wo = w.toObj(); + wo.opts.id.should.equal('48ba2f1ffdfe9708'); + wo.opts.spendUnconfirmed.should.equal(true); + wo.opts.requiredCopayers.should.equal(1); + wo.opts.totalCopayers.should.equal(1); + wo.opts.name.should.equal('pepe wallet'); + wo.opts.version.should.equal('0.4.7'); + wo.publicKeyRing.walletId.should.equal('48ba2f1ffdfe9708'); + wo.publicKeyRing.networkName.should.equal('testnet'); + wo.publicKeyRing.requiredCopayers.should.equal(1); + wo.publicKeyRing.totalCopayers.should.equal(1); + wo.publicKeyRing.indexes.length.should.equal(2); + JSON.stringify(wo.publicKeyRing.indexes[0]).should.equal('{"copayerIndex":2147483647,"changeIndex":0,"receiveIndex":1}'); + JSON.stringify(wo.publicKeyRing.indexes[1]).should.equal('{"copayerIndex":0,"changeIndex":0,"receiveIndex":1}'); + wo.publicKeyRing.copayersBackup.length.should.equal(1); + wo.publicKeyRing.copayersBackup[0].should.equal('0298f65b2694c55f9048bc05f10368242727c7f9d2065cbd788c3ecde1ec57f33f'); + wo.publicKeyRing.copayersExtPubKeys.length.should.equal(1); + wo.publicKeyRing.copayersExtPubKeys[0].should.equal('tpubD9SGoP7CXsqSKTiQxCZSCpicDcophqnE4yuqjfw5M9tAR3fSjT9GDGwPEUFCN7SSmRKGDLZgKQePYFaLWyK32akeSan45TNTd8sgef9Ymh6'); + wo.privateKey.extendedPrivateKeyString.should.equal('tprv8ZgxMBicQKsPfQCscb7CtJKzixxcVSyrCVcfr3WCFbtT8kYTzNubhjQ5R7AuYJgPCcSH4R8T34YVxeohKGhAB9wbB4eFBbQFjUpjGCqptHm'); + wo.privateKey.networkName.should.equal('testnet'); }); }); @@ -548,5 +595,7 @@ describe('WalletFactory model', function() { 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"},"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","030920a8b8e88c4db2871a7df0878a86cf0695f6d96bb50c701c3454f3df25176a"],"m/2147483647/1/7":["036bf329fc19bce10cf1999fae5bfa80290ff7b44776b49c7b0dc9eec6cffcfa21","03955a549875b4f7b9be28b9ff4bcd51ad2bc224430b1634baef890585885d5e1b"],"m/2147483647/1/8":["024879c9c9a261b3141ecfa1c79c4efc25278c844ecd1dcfcb95d9c19581fbdd25","03fb4a5fdb91239df3ccf7f61a5b99e7e72483101e21c9d1ee0d85544e9354c6c7"],"m/2147483647/1/9":["035928a107ec01f78cd586914d5a49710fd42e352b1312e3ad0eeb2c9666fdf8e7","03a54c03093797854829c75357f092356352a109042bbb83bdac20cb4e5eca27ea"],"m/2147483647/1/10":["021e7a3a7efe888c5e820b5cf0f03317b2b4bf438d8563449aeb7a77cade97f136","03ec0960b3d1df52ca3cc2c82b7d97063400da4dd051bba2f9bab6cb44aee01efa"],"m/2147483647/1/11":["035d70c26b7f429861f555f7c0d99947411b23b7f95303fb8d5de5b82a95aa30fc","038b922f7024f5446d6b48e5253643543b35c006d90fd37688105c6cefcd8adb8a"],"m/2147483647/1/12":["02158d6503891c6c65a606221dbf5c68d0832288975914007968419939588ecb24","0248264cb1763a3f4de9b34787b4bc5443ec92ef915927494bb9f1c1c0b498c7ca"],"m/2147483647/1/13":["0349965eea38a25ae0c061faeac4c4e57e648bc4c0f059d07b3b8b7962cbc0dde5","0352243d9269565ce2a1ffdd0b8e43a442c6dd1c9edda86eaaf2cba5a4a95c40f1"],"m/2147483647/1/14":["030fa6e3d0c5cedc0581955395c77cbe134c912a47971023b9695332df3f7bb200","03f2cf09e33326fb59bf3f13e6298d2d5d29c9eae3b872e5a851e8d8d77259c883"],"m/2147483647/1/15":["02bf0d45e41339f552df6f8baf4392142921fd38b0f2a4388a905ff6cbacbc278a","03fabe46bb6706a1b8edfd28c046a8891b4530bbe5305080b72b0d08ebdf7b8c0a"],"m/2147483647/1/16":["03a4e3146ed34d6a8af4e4379e6edcff32cb0373ba232b3d746af3052f674133ac","030311b73c6f5c46ddffc0cfce6e5ed0b671d94267d8e52cd8837f2a479916eb91"],"m/2147483647/1/17":["03233df93c762d2f06c7f5f388e4e0a8dbdb13302acba0d2d6995c487d8aec9f2f","024badfdcb7e772ac7fc1c46d3943b07500edbbece105cdeff3eb9e9fcc9f54782"],"m/2147483647/1/18":["0364035475a098e00eb010c500cad3c90af3e81a4bd613144bc9433a150f14718b","028223dc8142154e7477ce000b3dc13e1d15a901553d9b18864c8645b582b38fe6"],"m/2147483647/1/19":["03971b74b4ac4bdaadf636baa4caa82fe5355471ed6ea05a9cbe5fc6c9e4b9db76","0202ebffacd01f83849e5bc5c0e2c317bc5fb2fbcb2d6d4482a5235f9f1308b61a"],"m/0/1/4":["03005ee9ff028c98fd132e531023f2f2b61ff0d26022f979dd98088d2ba167b031","0345ea82e8dfe38277f0c3aee18d2dd93edb63e8663ac83328a7934d2ca57006f6"],"m/0/1/5":["0391bc4990b71d8a3f156ae7107929ed6372b0b4ba8a868253f71ba7189d1efa02","0312a74cf2e7c0dd41897d04fabfd8cc3187b84a28305cfc79315b24e6fe23a6b4"],"m/0/1/6":["021a38c492607ff9684a4fec445e47b5b7100d3ef9e9dc0d0b37c0a646d28d4f77","03ae0b46ab36f97447ebaa53f2b5c8f090f15395378785f2fd285eeba17fbf3f65"],"m/0/1/7":["0308cdec88c1ffe16edc98853d9c08dbd4ba2541ba566668ca17bda19d7eb3481f","02dd622267c2e68287287b8b61724f76fbe84096a56aa5054af92f8fe25380e2d1"],"m/0/1/8":["039647da9ad725836bcb28a3e0497659a28d7749d1416c421a0a01c62d237ee962","022e22aa61eafda0dd8820427f1a06314d352a15ea8645e7ab9b80920017084d82"],"m/0/1/9":["03a4ade946076c6962b70c70ac7fad3a87efb59a1d0a4e32bda13a6d47fe9df961","029a07235aba04ab69526e117d836d5b3fae5cfc8c5e72b10c6d1afd261ccc19f3"],"m/0/1/10":["03c78e9b6493b22790db1acea20df9444e0f9c424fc5756e7a32c290ae01783953","0254c130ee467a96570c9f5ebea89de04f0b1db1686b164f2694339bef8f25dd88"],"m/0/1/11":["03a762c43318ef8d4840fab04c8db73797dc648825fac60f2730b4c76678df1cf3","0212c684a4de8e750ad2dfe2b136370ab9803eca178ed9a27b3990c29b067de35c"],"m/0/1/12":["02702d221f9b15c5cf75ac2f497a6c63e60213087c3d2d3be46768e3ebd238e26e","03ed58580744deb357258e44548212038670769d8d51e385d4fb8414311fd01b52"],"m/0/1/13":["0320e0597b54c62768352f433389cee4725d6094d7bcb5c72265edcc0933829aff","02c5706f11b9a85f3176c572842b7c9812c2195058d24d945bc026b00312740e76"],"m/0/1/14":["02fe43077676b844226d3aaa62e8a86d237710d92f882366944acbde0c8992fcaf","039a6a8662abb8910741cf331320549665e9feb28ca94d1ab6a43c84fa330b94ee"],"m/0/1/15":["0369f99f72847af93d50ab8ee75b6e7e912d26e27be96f6d6b7215cf7daeff7ba5","02521700cc07c953ba5aa586fb0e4795a34dffc68c5fb43e038be3866e40f4daed"],"m/0/1/16":["02f67d1d89bd8fe2f91c5b973cbdacfb4ba440e7656bce284cf73d549625607347","035da9cfac5a803dcb2b283b02a2515a4a1bcbf3d19e0d180aee8fc30193bc0555"],"m/0/1/17":["02c024ec199d240e8d6c66276b94b91071f7cdf2bef540c29d6d18d25de7b1cf7c","02190865f9dafae3f7f05c093463be5632946422ddda0a6fef6904390792516067"],"m/0/1/18":["035ed504d7704ad984a333b8eb0fceb8be043da9284de31ed84d9e68d90c75507d","033303c415b50421732402df00f4baa219f334647a7eb5014b9f8079864d6ab558"],"m/0/1/19":["02ce49fe86b0eee73663b1ee867b16b97c876af26f12764c528a2e6d0eb55ad3d7","03ab969bc81796b88e44c340d854df955fc60ea17ea92db5d3115595d6dec890d8"],"m/0/1/20":["03e2fa915378cbdffa0d919b0fb50c7256ca731b9d571b3365e486893a1d43079c","038d058b895cf084dccfcc9367e4796a5cf4ddceed6c35f6885d75c80119613350"],"m/0/1/21":["02fcb1bf644446b5b42205272af72f0aeab9e92ca29aafa91c5fb69142764017aa","035c5fe5c8811603279a5b72b6c30735d702817db1eab937c622269e28192ffa90"],"m/0/1/22":["03b39d61dc9a504b13ae480049c140dcffa23a6cc9c09d12d6d1f332fee5e18ca5","022929f515c5cf967474322468c3bd945bb6f281225b2c884b465680ef3052c07e"],"m/0/1/23":["03f40b82fe8cacff08879f13c45f443a3dc3ea98e1d75d5f32a19f5e5a8f7a905b","028415ee458e4dcfd440ce969726f3b58ae74fb6cf3995ced099579211e7419844"],"m/1/1/5":["032748a6282e21f571b8c8dd49e775deb83c90fcf88dc4ba81d878536973709c3f","020837cd68f14ce571b335eecd1b6fa0af43e1576dd9721aaca2a8ab639ac6b7cd"],"m/1/1/6":["0337032efb013dc92bb8dccfbdda9f5c28f0039a9c60953d41003d095e9f9778af","03ceed2da6b9603297061dc8eb930112ba726b2ccf5eec67f4866a05ca4049a22b"],"m/1/1/7":["0383c96ac2af7d203f69133b2fab6b68366b5075ad6957fa06759df3b20fbfec70","0311385f79834cedaf2230a48c0f9dc8e794da1869fc595db2518d62debb85579a"],"m/1/1/8":["03efc649680280f4e4df96da923bc88330275004125ebe5483c2f3e05ca52e19a4","02803c02d197d780388259afbd001ae41fa3eb3e2bac9627aff540521c184c3b23"],"m/1/1/9":["03af2fe6aa027a76b42c1c4050a040bfd026ad2daec1bb96a5fe2d026a7df919de","02ce14163047c640228796fb1f72bbe3afb05819ad141598a4f021058a6f79dd3b"],"m/1/1/10":["033770378bd762cf0408e44e4e604bef77e336170428c506949b1a4f1f2963e574","02c58ed43946f699dbd3e36d3e9aab2714cadeb19ecd3a56e4328c50336b4a76cb"],"m/1/1/11":["02898a1545fa19bdca92adc498698d27b86529cd4c08946d9d29604734b86f31af","02b402767a045ede072600924401c0d720000b2ed59fa444bfdbef4a5f1cead745"],"m/1/1/12":["039b8659430be49913e2cd869aa8c99ccf49a13df35837370b792033dadb891483","03264e63df292257cc76babb15d15bef620d1c2f8c3bbc78d6ea02d127e5ee7386"],"m/1/1/13":["02381a559791b8e86bf546e2c718ae63cf24eed0518a58e4d4a4b310adf2cd38fa","02d7f8283a4418d912508901b4a3db0d2103206dfdd74b3c75648671e20ecfd445"],"m/1/1/14":["020376e8c550b7d9faa0b2da947a2a36fab22c6e8190b6f99460b6022017bb97d7","03fbc5299190e6628de28c92aaa12e3a131b21eb7266462c46fbedeb86fa878055"],"m/1/1/15":["027209fd3b0cf7368180a5dbb16b928c997d33fccb78505d48440c7d23eadf5460","03450bfb22858726cd7e228e6733f69457546978a95188565c53e0d1c0d6070ea8"],"m/1/1/16":["03cb355ba04f64293793855121bab5831f84a3a3edf7cd31fccaa6d67c407a4912","028bc897a39c1224610b765a80f4cd8ab79cb37776f58fec9c10ac6f649d1f3c72"],"m/1/1/17":["03f4cb0564d7e2c6b85673503b7954db22779f29a8f3374904573984e318a96bf1","037c11b6ee906d84aa7eed359d758d986d912b6f8e5cbb1acf0982a77b3ef812c4"],"m/1/1/18":["02d2e5798f33f6889472857744316f2d253f25f88379610063f40cfe5798d9858f","0253cefdfe9ca987cbf1c950b6246d5b7a194d8dfad47c3a78dbbc5c1d01511d97"],"m/1/1/19":["0336c325f5aed366ffc10d553f2bfd4d69e66cbe1688d77af14efc8827aea2e318","0378b1b9a6074f9f2ab4fa9ad1e14649c621b0c8124a1b148914d3c10e6ab390c6"],"m/1/1/20":["03ea55740a734689ce778a8c00df8ebf4274c8f66de7d05646fe5c927773ff7f2e","02275b558d49aef955b6dee51a3c0a53f4b076b97bb3f26abcc82540168ec87cac"],"m/1/1/21":["03c77869c9984664eac9c238f4b6d806c9f48ca8a736c48450f398834db2aa915c","02d984f548c7f60c09dad3287cfc48807bc8157123989636c713be61be6a2e9ced"],"m/1/1/22":["03ed7c6a3c854c1f9459891691cc32671402f9e47126919878251e568dbdf353f8","02a113dab22cd9e46967b3fd76b9b9ec1d227d88817a9300e42d332cca2a0877fd"],"m/1/1/23":["02ee186432dcf69fda50a6fdbd94651817d8a271c273a5b70cab3ec4ae77a3753b","02291370aad9de0dac676355ced64e268b0c431a51f42f12d13f5144940fce4285"],"m/1/1/24":["02bf71435e84e66547c8c583d5ba226a5ac4d935e0a9f9603ecd8925c3e847e91a","03578d8657d285a89d9d597632db662cfef9baccfb55c76b1e87948a94fc9de30d"],"m/2147483647/0/0":["02a8425bbe23426219065969f695a6c3e242b24e57226bffdd542be8fd6be968c9","03057a42fdb6569fb1615b173ccb702453db2eac5be4291b82d4511461eafbed87"],"m/2147483647/0/1":["0250c3d3e86e332010c5233c2ec3bc728026002f0037cb3382d6318409b0e70796","02cfac1e7c4c88191201080f8316af52d9faa6ba624a6e160279e9fac4d1cf79a9"],"m/2147483647/0/2":["02a8c266a5b92eb50c8be91f95e4d1ad968b2f57d527377fd642d63fb84474f61a","028cc954ab31bd179ff80b8a05f95430ae534e61b3ff35f5284fa2fbe1832ceccb"],"m/2147483647/0/3":["02f719e1a7ab00ea98611453fb03d44c1da04655bed74af392534d70099039b4c2","03bfa548bfd4718c50bfce173f780eadcfb679d9c0206c91a2fa1879a9cf7558b2"],"m/2147483647/0/4":["0362c0695d397ca26bf47f0e641bb3cfb06ff29ccac2e1d56ded3afcf88b1e688d","02f9d87b05bdb3b9e82f506b43f813041c0e403274adc23d11e5e1651e34b606c2"],"m/2147483647/0/5":["033731323032d4ee08e858fc71f93970444333e183a1d5052e1d08cfb511e262c8","023e12556cef67ade35b7758916b5e1a3ebe074ccd35c5d8eff6b01321f63eb495"],"m/2147483647/0/6":["025d11b90081972bc1c258c9d6f476dfc2f95b69f0e9935322bf9c21deb580ff64","02b065f56a378907354f0738a0ed74f10660c6b5dd68c9f992093b75ce3d7d8b72"],"m/2147483647/0/7":["0210e721e8a35db9d8c855a0d346f60c09208f3be80b39e03af2c29db777332c71","0277f352969fadb1f1835f9a0fa99c6a3c7b6c281be5b2794c88a708eb177ea33d"],"m/2147483647/0/8":["02998d8d41e4215cd2a961a415a3ed0b1f984f1627719a7b102a75864943c4d87b","03d8ed7fc8f68a77f68d3afd007b7aa4c89944195143630ce183f0fa5438f2b559"],"m/2147483647/0/9":["0324fa91737588e4f85937303ce65c3b91b5f2ae506a72d92b83e3f5f9aeeb3c6f","02a011be72c4a400319212228106af278823a97acfe0a67e1ecd866d446b315114"],"m/2147483647/0/10":["025886ba287922a904881c7315e6fcc410a7976741771a5937d3a1a01b529f21fd","0243bb91ceed9d29d0c2ca66a8ab77e82110bbcc023beb4106f787964f44a0b972"],"m/2147483647/0/11":["0369d21684894cc2d4b2f5e581ede3cac9e8db4161a08e7737c1be129bb673d3d5","03c9ef27e3cd3dadc078fdfd9936a7ad9bf7954747085cf8f8a2a5bb3431f68a9f"],"m/2147483647/0/12":["03a73b8fd859bf6acebffdfffa2597199091daedd2c011ac67fc3494d8a1a8ceb6","025a213f7771c8be03f43f2e7f469ad4ef2cf6907ea284b227a786d1f55dfa7144"],"m/2147483647/0/13":["03a09f7ca257e1ab263cd5e6b0addc3ff868b93df132321d98775ca3505efb576f","03454c715739164bc55f347a651439cdf3ec146b35d2927beb60e8290b3916e082"],"m/2147483647/0/14":["03a64b1f7bd94a6b1a6e84ea444e0ba04e9deb86460934ccc37c0615a134a8257b","02794f09210b1811a455f3e1c7bcd35c76dff2523190fef9615eb27e2376acac1c"],"m/2147483647/0/15":["0392dca2fd9a3bc2b2a7d90a848719069fbc5f22bff7327bb8186c032514085263","032ee8a33ea76d70c7ae839448ca6c5b1af89146f2922e23ba1822df42dbc7e66a"],"m/2147483647/0/16":["031a22a1a3c1abad7c4d782ef6ba3cc00f2e8fe549eb33e0732200aff6d3174831","03bdce9781289e0c31cf727f4c93fe46f7930dd8fd68f818ce241f1ede268e8e0e"],"m/2147483647/0/17":["03b12d27e9aea2c2ad598e54e40860a705ac2ca2427aa511b501b38ec368ea5c7d","03e60d35d84d4536cad895215256b312bb4879a8d417251c279995e58f25da3d54"],"m/2147483647/0/18":["0380266cc9a9673676ad6a1b2e7148766df9c25b4dce299e5edc4f65b72aa58e64","0329e2a8a48c06c0c45dfdd2ab33e6455551557d8ebaf8c12fdf7470f8c45f1d28"],"m/2147483647/0/19":["036fe62af85560d7eea7c7af55e60b32a97dca80134d0aedffb19eb2705b9d6e01","02381c2c30b9f81e2a53c69028fbe11803acad0420b267719b7a80870be0baaeb7"],"m/0/0/2":["027bf94b8fc4e9b42683af25fda125ccab8760040717d100270dd4afd032692daf","026382c6c9357250d96dc21e43c053857a64efeac1887fdcbc107fbe3ecfc6115a"],"m/0/0/3":["03fd203acbd9af3cbbfb709458f8952078234a36094f12d00372e4b2b14cfdf419","03f2e5db59aea5dc89f53ac2a9f4ef66d41265c45afc5d763e0ca61ab70c7c61ec"],"m/0/0/4":["02a1d7cf4fcdbbf4de4002b844c3bff1639073f1cd6e5c4a4e02596b45d3f518c2","03b5fba813294e6ae096ea158833453caa5a945609b0a554696091b9b152bb0f7d"],"m/0/0/5":["0261d37e3b56ef4e106c59753037f516a4b1c45e056b2a3e00f8b77f15aaa7f8a5","0256a55e66e0de1603f0d600c0eb5f5486cf3512a776a36f3ab0d1941fc0dc9b09"],"m/0/0/6":["031db2826af215fe6cbe3f6e121b0497840fc49be133cff0a4d4eab679d6b99d70","021dd722c3f35dd04fcdb57f09b76c723d521fb36751de03ffd08096ddf1dc1f86"],"m/0/0/7":["0354ea75bdd9eb5beae7262e4a5eeb58bd10103ee0185e85b749ea39f6615d0f62","03f2c8f3b6478c0501a8578d5caf5ac2974f8213fc5e699d62dd2af58fbe8781d4"],"m/0/0/8":["0282e67df3bcd1e1662469b4c3151fb50ee1e46b75d787d91184c16b9803131f82","02921a7054af1e425f4137a5eb6b34d1f2b9d81c2625230194bc30657bb4277e11"],"m/0/0/9":["033e7e387933983ceab37c8388bd8ebc5119760f493ffe6f083bef0e5dfe22891d","02d660d60cc55d80912e0745cb142a8596a4604fbf72f9aadec0599aa2ed62461a"],"m/0/0/10":["022ce5b2750ae34512199856eab9e912dc25281cd8b88e7688a46c3b9a389701cb","02f14aa1608fce3b6088148709eb5fe72b61699c931fa8d95a45fab1106859d1b0"],"m/0/0/11":["0288dbef3302c1bc5556028adb33e2f9e03c119dbad4f706befb8ce86cea459f2b","03f13ced465e2e0a3aaa8895f3185d5711e0bebdaf507610b7a669ac8fc82da8fe"],"m/0/0/12":["031ab4677885340d2f927ccc9747f4346b79e4eb6c750695095a8a2524610fa94a","038c881910fbd8b50d193db4e0c84f5b7840820397f92cf0718a8e06d027125503"],"m/0/0/13":["031b568452cba22eb7a88c6085489e53e35abd16068882e71a140e47e12dee9c61","020d09885ee362101d12d34ce0918d41593634db1b9413e5415c6755753b9330e8"],"m/0/0/14":["024177bc9aa03cfc72eda2dfddffd7fe9d0c2f007fc3ba1a48280feae2b9fb117a","03394ad321668440c08da76eb35475ba3a8c0e8cbe0ed81468673a8c72d38fe457"],"m/0/0/15":["02037b1cc696ffbe9eba3684edd53653386ef6cd7728401c40120037593a4c2ae2","020ab8d6900ec9c11ca5d96dfc0ce7cf0ee71653a7c45118e89abb4b113147e53a"],"m/0/0/16":["023bcbb8d4726a546087cdb83740adf0ace879b7195a572c652fa8ce4dbe195a04","0392721b230d5163d28b27fc7e059b875711f12b3da448eabe7229bde57530e637"],"m/0/0/17":["02498ee74e849d3e9261dd1863038caf83d6a3bc2eeebecf17055d4bab44dee77f","03d4dc104b2e0981693e8097437de9b05334a85e2c8edb02783897859bdbc93e32"],"m/0/0/18":["0218a9f524fe54abf8c3afd21314296cfd93eaa9227acbd457e6c9a742dc233cf4","03760f3d0c5db969bda698ff9352e3b7c332216c34825f4c6e857e39c9aee7cd35"],"m/0/0/19":["033dd51f7737f0e9db79f5c38e4298bf3396346904ef3933d290a22e5b77048d9e","0221b2eedccb9a37515263071550069b3b349a166f0f131d0028e8600d9a2251b9"],"m/0/0/20":["02cb6c39161f3244d7769f7ab96346cae2cf21cb6f4538f5e7382d363dc2f836c7","034f7bda4d1e9ed6a3774608a4d6cd8582ab59fe3187f8a7a7cf914d89426ebe28"],"m/0/0/21":["035490549d65f1360f10340037250b171470ff4c86966318a2b1eead6d8b969aea","03f6a04f6fcd07a4f32c82d53710ed30e0f54d43d41c67c661d158b3d0830c3ea2"],"m/1/0/2":["02972eae7e4302e319c266578e14a07839c1e788296a92906e6d66d938211dad5f","039ed6b488f1571ad6527acd6b6c5b8453eacf6665dc5cb7852e33d1c8ea73f9fe"],"m/1/0/3":["02bec4728888c2c045108353994bae5731ec7a7b41459023b0023e10b8d616bd30","03ce1efe16214c9eac595382e46a68143dd11a335b3f7c971ddd719ac544a5fc4b"],"m/1/0/4":["030e2df1d341568225d8dfbe5d07e98dae9f90e0f43e19dcc68c998a6ed7bcc1f0","0380f4c07dc84faf42d51779f104aa6e3b5c3ce2d7684b3cb76d49faeefc2b69d6"],"m/1/0/5":["029a54ddaa25f433b493f4b72df8c1d41be2c4d2963b8b61ee63cc86d16c12d066","021567c95e0317442e7367aa4e3378dd46c5bcef5860f789272fea83b917de0669"],"m/1/0/6":["03590320d80b61cc0874b579f467c9b5ccc50d9ef875bcf6bdd12e2d0c211e8973","03ee4677b6ee89a9d355851f2230506c6897ff219062c0df4ad9a85c60f3535f93"],"m/1/0/7":["03caf98ab1c9b79d1dc8029453a6137c08787b04043b79af3cb42d41d2d3f1338f","023f39ae4e2f4f3887d5fc58e0d3a0d7ee267dc04aa257c75b6b2d67d2f5580f81"],"m/1/0/8":["0352a2a3ea8209c9a2b633d788796ac2d16c08022440e04a77ab2835c7f971d266","0291bc248b3da997f35e8fae98a75a91fdac2819d74c4e270899338d48f7389e87"],"m/1/0/9":["02468d32d9c3c62418d506d4cd0da6cd2022d5bcafdb5f847cf7bde7a48ec6848b","032713d90d12eb6a072f3c1db6c0d3b680d3f78883016135fc0f78e8193d41d4b4"],"m/1/0/10":["034863cc6bab9b059be53413ba75c5fc286647c20d7f9e5512ef4754ea301dd1ce","03a33ab9c32a2264ee2464ebbb5892f0e34acf0fdede4f87395a89e9dacdd4930e"],"m/1/0/11":["031e19296695bfe8a96ba3bf58afa805ee1bd5471fddb3929b1678d69d442d69c9","0270feb33956fd9e937019d629523e26437493c0856514011e6aec88baf7721295"],"m/1/0/12":["03cce695d3c3843bf73e851b2446a77d7e235e5b80b4f4474f9946292eb8218742","039ea96c8822f0ec7ed28308d277f3e730480d7573579cd11b89aef4364cd9ffeb"],"m/1/0/13":["02ab4ac38eb405e822d12c0f0f354f04f9ee1d991dde887a5c1171096fe503158f","036809e60cae1203da8884ea1f85d4669ce6e053f8ba605d775e271b70ab4f6787"],"m/1/0/14":["039d61da23a8610fa0ee58eb37d7cea7ea9396c79153da97280ccf5e46718e3bac","03015c27bcc778682781fd6ad30aa6041db0b7e24270818cdceece0043ccc34b26"],"m/1/0/15":["03c088ed669132835d2728b0ecf294271c8388988c6ae264d43ca24f50e4005f81","03e2c118c9445a2ddc4c8afeb0ba49e21be3f818a483d346418b8922b8a371a2b7"],"m/1/0/16":["02bba7df9847f463c6b23eca37a4bd6efa3801a52b8ddfad804d902e783b70c81c","03764b657f23996e31c64a701facc1cbeb0c9edfdd605e2c1ed36cf48197565d45"],"m/1/0/17":["020445179c522295b89bf4bfd582eb03422e3fa20dcd29263925e9f44282d476d8","036e47bdd32f3061aed1c1f8c2a32b038c7b72391cb1f80ebfc150e58f88372766"],"m/1/0/18":["024d88c4bfcbba713d49e1edcd035234aaa1ee76ad7bcf75bf074a16658a6b0b6d","02b861e7a20d89f6875d2e44c78dbadb99503e282e5e60e9f65657af6fea81d425"],"m/1/0/19":["023a8ca9d5300181f157e1930d3b0800eebe7683d8df72e6cbf28834dbf1be5d60","026053c4f84c10d15890c0b254522972931bc2d5b7cdf9c1f9f3137c22edf3ecd3"],"m/1/0/20":["03137c66e9f3d61aba659f408d77a293fa0f3fea4ccb911074a681d6f61a55d023","0291aa1bbfbef59b16b0e37e185a706c589d448cb02e860c5df9c9d7242ecc739f"],"m/1/0/21":["03c08673e0cae55318bc9dcc4b5f11eb3ff71d42de04015e255dde3fd8cba7e09e","02423d4eab06cd5b26e71d145283523c011d58032700c517f00b328d2c90cf109f"]}},"txProposals":{"txps":[{"creator":"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5","createdTs":1405543144016,"seenBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543144016,"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543144645},"signedBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543144016},"rejectedBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543170040},"sentTs":null,"sentTxid":null,"inputChainPaths":["m/45\'/0/0/0"],"comment":"blablabla","builderObj":{"valueInSat":"29000000","valueOutSat":"8900000","feeSat":"10000","remainderSat":"20090000","hashToScriptMap":{"2NBtv6DdXj8HBunyGqpW9H8bUtW5x3rfVTj":"5221028a4b63f26253f3a8731577b8e1ee480950ad5833ebbf106fe3463bfc07cc3b90210332efa054c08cb77506a35ee0762cb7156f244566703ec08e433568ec0397bec852ae"},"selectedUtxos":[{"address":"2NBtv6DdXj8HBunyGqpW9H8bUtW5x3rfVTj","txid":"a9f4dda3f092e37244bc4e77ea921fed01d5b8ea49613dfdc0dc8afdd70190b5","vout":1,"ts":1405543855,"scriptPubKey":"a914cc93216398b77b5f8c451ca3a357bef961678be987","amount":0.29,"confirmations":0,"confirmationsFromCache":false}],"inputsSigned":0,"signaturesAdded":1,"signhash":1,"spendUnconfirmed":true,"tx":"0100000001b59001d7fd8adcc0fd3d6149eab8d501ed1f92ea774ebc4472e392f0a3ddf4a9010000009300493046022100ccbb8f398f74a76236629b8499ffc6f9518a2091f5a61a9a352c0a10f615961e022100b8f0769c76cf33bec3d7f81d9da2b74cf6e8a5e0a24ee5f48172854d8bcdbfa101475221028a4b63f26253f3a8731577b8e1ee480950ad5833ebbf106fe3463bfc07cc3b90210332efa054c08cb77506a35ee0762cb7156f244566703ec08e433568ec0397bec852aeffffffff02a0cd8700000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288ac908c32010000000017a914560c292066792531164149c5ed63ad2793a61b928700000000"}},{"creator":"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5","createdTs":1405543188745,"seenBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543188745,"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543189341},"signedBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543188745,"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543206819},"rejectedBy":{},"sentTs":1405543207304,"sentTxid":"169bc92693dd2e27724eeba81e54210e842035bd3af6c52e6a6a5e908f1a4f66","inputChainPaths":["m/45\'/0/0/0"],"comment":"que parece","builderObj":{"valueInSat":"29000000","valueOutSat":"9000000","feeSat":"10000","remainderSat":"19990000","hashToScriptMap":{"2NBtv6DdXj8HBunyGqpW9H8bUtW5x3rfVTj":"5221028a4b63f26253f3a8731577b8e1ee480950ad5833ebbf106fe3463bfc07cc3b90210332efa054c08cb77506a35ee0762cb7156f244566703ec08e433568ec0397bec852ae"},"selectedUtxos":[{"address":"2NBtv6DdXj8HBunyGqpW9H8bUtW5x3rfVTj","txid":"a9f4dda3f092e37244bc4e77ea921fed01d5b8ea49613dfdc0dc8afdd70190b5","vout":1,"ts":1405543855,"scriptPubKey":"a914cc93216398b77b5f8c451ca3a357bef961678be987","amount":0.29,"confirmations":1,"confirmationsFromCache":false}],"inputsSigned":1,"signaturesAdded":2,"signhash":1,"spendUnconfirmed":true,"tx":"0100000001b59001d7fd8adcc0fd3d6149eab8d501ed1f92ea774ebc4472e392f0a3ddf4a901000000da00483045022035423cc74824ba904907678dda3b62a20a787b96d1b3e9f3e9546f9c57f4e45902210080a1ff1c39f458ac1642b9e948bd62fd70563b5252e749cc8fc642cd763ee830014730440220524a13f36cfb03caa246d7d84de634ec9386f2c39c19bfa926037f48da86262b022050e58a6503d105ad2805f86806810a1aa7f20d6271e1340b42fa91ab6a30f3e801475221028a4b63f26253f3a8731577b8e1ee480950ad5833ebbf106fe3463bfc07cc3b90210332efa054c08cb77506a35ee0762cb7156f244566703ec08e433568ec0397bec852aeffffffff0240548900000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288acf00531010000000017a9146130a9d51f996b7a1b9d3e10c80930834251909d8700000000"}},{"creator":"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba","createdTs":1405543505848,"seenBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543505848,"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543590221},"signedBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543505848,"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543590221},"rejectedBy":{},"sentTs":1405543610315,"sentTxid":"6fe851b54b777a75fe80fa204dc674395e2af69efb1f7c0017e909eb82c3d914","inputChainPaths":["m/45\'/0/1/1"],"comment":"mandaaaaaaa","builderObj":{"valueInSat":"19990000","valueOutSat":"19980000","feeSat":"10000","remainderSat":"0","hashToScriptMap":{"2N277q5r8Ab6XLJNCjXXFdh5itDJRQCv9ts":"5221020389327ee8ae7d0ee3f8187842d23a4070bdd8a27c0bcddd05d80ef39009253d21025c9b49bdf17d97bd82ea1b87793082f857247f0f9b999937a166ec994bb1b41f52ae"},"selectedUtxos":[{"address":"2N277q5r8Ab6XLJNCjXXFdh5itDJRQCv9ts","txid":"169bc92693dd2e27724eeba81e54210e842035bd3af6c52e6a6a5e908f1a4f66","vout":1,"ts":1405543157,"scriptPubKey":"a9146130a9d51f996b7a1b9d3e10c80930834251909d87","amount":0.1999,"confirmationsFromCache":false}],"inputsSigned":1,"signaturesAdded":2,"signhash":1,"spendUnconfirmed":true,"tx":"0100000001664f1a8f905e6a6a2ec5f63abd3520840e21541ea8eb4e72272edd9326c99b1601000000db0048304502206b18b3dba2646c552469d8ef52d7656f6a65f563032530f622abdfd8bd4c5cee022100e804b406eddebbc827646141e74dc64c76a770ed4e35183ffd35d265ad9f7d3b01483045022100f6c013638ff0a316b1baa93dfffba6a98cf3033c133e8bd899e933c9c3e47ce10220530f40e7ea52ae58bec695edbec6d566d2ee8e7b5f33f95e33093ad1e29a125401475221020389327ee8ae7d0ee3f8187842d23a4070bdd8a27c0bcddd05d80ef39009253d21025c9b49bdf17d97bd82ea1b87793082f857247f0f9b999937a166ec994bb1b41f52aeffffffff01e0de3001000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288ac00000000"}},{"creator":"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba","createdTs":1405543781381,"seenBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543781381,"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543782017},"signedBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543781381},"rejectedBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543794590},"sentTs":null,"sentTxid":null,"inputChainPaths":["m/45\'/0/0/1"],"comment":"1","builderObj":{"valueInSat":"29000000","valueOutSat":"1000000","feeSat":"10000","remainderSat":"27990000","hashToScriptMap":{"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb":"52210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352ae"},"selectedUtxos":[{"address":"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb","txid":"6c9da5b0da4bab0d576033325e987b10ccf2b9bf479d306b6aae36efeaa56892","vout":0,"ts":1405543698,"scriptPubKey":"a9147d274ac50968d7823b6cbc1b38770deb7157995387","amount":0.29,"confirmationsFromCache":false}],"inputsSigned":0,"signaturesAdded":1,"signhash":1,"spendUnconfirmed":true,"tx":"01000000019268a5eaef36ae6a6b309d47bfb9f2cc107b985e323360570dab4bdab0a59d6c000000009200483045022064d877bc5171fbaef909c2a1a924e0023b3ccc0b530cb46653f06ecb230283e8022100bc6658d60ad4f7120d9226c8f6eada87f3b0388f73c458011988bab36e78ba15014752210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352aeffffffff0240420f00000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288acf017ab010000000017a91421c4a435d9ac263ec55b35a1a5ca95e979639b9b8700000000"}},{"creator":"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5","createdTs":1405543835343,"seenBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543835343,"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543835968},"signedBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543835343},"rejectedBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543850998},"sentTs":null,"sentTxid":null,"inputChainPaths":["m/45\'/0/0/1"],"comment":"2","builderObj":{"valueInSat":"29000000","valueOutSat":"1000000","feeSat":"10000","remainderSat":"27990000","hashToScriptMap":{"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb":"52210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352ae"},"selectedUtxos":[{"address":"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb","txid":"6c9da5b0da4bab0d576033325e987b10ccf2b9bf479d306b6aae36efeaa56892","vout":0,"ts":1405543698,"scriptPubKey":"a9147d274ac50968d7823b6cbc1b38770deb7157995387","amount":0.29,"confirmationsFromCache":false}],"inputsSigned":0,"signaturesAdded":1,"signhash":1,"spendUnconfirmed":true,"tx":"01000000019268a5eaef36ae6a6b309d47bfb9f2cc107b985e323360570dab4bdab0a59d6c0000000092004830450220302baae7de2e0f102bf3af2d5f450f673e51bd143020141a769ccdcdf16af188022100e7abc087c76050ed649e7139a5a136969e74e24a8d8f6223d3219ad033a26451014752210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352aeffffffff0240420f00000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288acf017ab010000000017a9148b102abba0729fb0690c61cf7187064d692d43d78700000000"}},{"creator":"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba","createdTs":1405543869803,"seenBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543869803,"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543870411},"signedBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543869803,"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543890406},"rejectedBy":{},"sentTs":1405543890913,"sentTxid":"6a0f61574ad65e537e7e99298968db565f97b894b61f4c8f8fac8fcaedb83e2b","inputChainPaths":["m/45\'/0/0/1"],"comment":"3","builderObj":{"valueInSat":"29000000","valueOutSat":"1100000","feeSat":"10000","remainderSat":"27890000","hashToScriptMap":{"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb":"52210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352ae"},"selectedUtxos":[{"address":"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb","txid":"6c9da5b0da4bab0d576033325e987b10ccf2b9bf479d306b6aae36efeaa56892","vout":0,"ts":1405543698,"scriptPubKey":"a9147d274ac50968d7823b6cbc1b38770deb7157995387","amount":0.29,"confirmationsFromCache":false}],"inputsSigned":1,"signaturesAdded":2,"signhash":1,"spendUnconfirmed":true,"tx":"01000000019268a5eaef36ae6a6b309d47bfb9f2cc107b985e323360570dab4bdab0a59d6c00000000db00483045022100a8ce7907f9fd7dd41dd65c2dec425e008efea06ee7c80787c10c0e210fbf181302207712c0fdd1cb25836ac1fc2fd303c1e26b85e8980417719b9ed50e977a9693ec01483045022100d1780c4f028cd898920aca3eaceba352ed9306cd17f019ae2f634e8facad149a02203c84ab2093da8e22577e93f27a732f0728d4e6db0c749f3cd3d898d6a025152a014752210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352aeffffffff02e0c81000000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288ac5091a9010000000017a914cc1cab78458b1a951b91c6dcd7eeeeb682f506388700000000"}}],"walletId":"55d4bd062d32f90a","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPdWUAmaaopPftevC72Jtiu19V8ee5XijL9JvogqfR95uVrL85f8yBdQMq3KyQtG3Q91yWQb3XDbWWpcdWFDAmJ7Xy2XWkGJu","networkName":"testnet","privateKeyCache":{"m/45\'/0/0/0":"b6fd8d1a079efd523da34f31ba81f544fc3d0a728a8a98299d8980682518e79c","m/45\'/0/1/1":"0f4d52d2a99e4c8c1c2edf09fef12407c3abd2304b961198c3f131a8c8443a13","m/45\'/0/0/1":"de5c191c343bd6017b98708c03344849624a14e2c167cfd6eb8dcb075d139293"}},"addressBook":{"msj42CCGruhRsFrGATiUuh25dtxYtnpbTx":{"hidden":false,"createdTs":1405543109222,"copayerId":"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba","label":"faucet","signature":"3045022067576e5b37f2707a8dc66e57511ad9b10a3125bd95193fff6f8f6402969c3bf3022100adff9f417db07d88face13b3d13f422740d4421440cade1a205684dfdc5d733a"}}}'; -var encryptedLegacyO = 'U2FsdGVkX19yGM1uBAIzQa8Po/dvUicmxt1YyRk/S97PcZ6I6rHMp9dMagIrehg4Qd6JHn/ustmFHS7vmBYj0EBpf6rdXiQezaWnVAJS9/xYjAO36EFUbl+NmUanuwujAxgYdSP/sNssRLeInvExmZYW993EEclxkwL6YUyX66kKsxGQo2oWng0NreBJNhFmrbOEWeFje2PiWP57oUjKsurFzwpluAAarUTYSLud+nXeabC7opzOP5yqniWBMJz0Ou8gpNCWCMhG/P9F9ccVPY7juyd0Hf41FVse8nd2++axKB57+paozLdO+HRfV6zkMqC3h8gWY7LkS75j3bvqcTw9LhXmzE0Sz21n9yDnRpA4chiAvtwQvvBGgj1pFMKhNQU6Obac9ZwKYzUTgdDn3Uzg1UlDzgyOh9S89rbRTV84WB+hXwhuVluWzbNNYV3vXe5PFrocVktIrtS3xQh+k/7my4A6/gRRrzNYpKrUASJqDS/9u9WBkG35xD63J/qXjtG2M0YPwbI57BK1IK4K510b8V72lz5U2XQrIC4ldBwni1rpSavwCJV9xF6hUdOmNV8fZsVHP0NeN1PYlLkSb2QgfuoWnkcsJerwuFR7GZC/i6efrswtpO0wMEQr/J0CLbeXlHAru6xxjCBhWoJvZpMGw72zgnDLoyMNsEVglNhx/VlV9ZMYkkdaEYAxPOEIyZdQ5MS+2jEAlXf818n/xzJSVrniCn9be8EPePvkw35pivprvy09vbW4cKsWBKvgIyoT6A3OhUOCCS8E9cg0WAjjav2EymrbKmGWRHaiD+EoJqaDg6s20zhHn1YEa/YwvGGSB5+Hg8baLHD8ZASvxz4cFFAAVZrBUedRFgHzqwaMUlFXLgueivWUj7RXlIw6GuNhLoo1QkhZMacf23hrFxxQYvGBRw1hekBuDmcsGWljA28udBxBd5f9i+3gErttMLJ6IPaud590uvrxRIclu0Sz9R2EQX64YJxqDtLpMY0PjddSMu8vaDRpK9/ZSrnz/xrXsyabaafz4rE/ItFXjwFUFkvtmuauHTz6nmuKjVfxvNLNAiKb/gI7vQyUhnTbKIApe7XyJsjedNDtZqsPoJRIzdDmrZYxGStbAZ7HThqFJlSJ9NPNhH+E2jm3TwL5mwt0fFZ5h+p497lHMtIcKffESo7KNa2juSVNMDREk0NcyxGXGiVB2FWl4sLdvyhcsVq0I7tmW6OGZKRf8W49GCJXq6Ie69DJ9LB1DO67NV1jsYbsLx9uhE2yEmpWZ3jkoCV/Eas4grxt0CGN6EavzQ=='; -var legacyPassword = '1'; + + + +var legacy1 = '{"opts":{"id":"48ba2f1ffdfe9708","spendUnconfirmed":true,"requiredCopayers":1,"totalCopayers":1,"name":"pepe wallet","version":"0.4.7"},"networkNonce":"5405f06b00000001","networkNonces":[],"publicKeyRing":{"walletId":"48ba2f1ffdfe9708","networkName":"testnet","requiredCopayers":1,"totalCopayers":1,"indexes":[{"copayerIndex":2147483647,"changeIndex":0,"receiveIndex":1},{"copayerIndex":0,"changeIndex":0,"receiveIndex":1}],"copayersBackup":["0298f65b2694c55f9048bc05f10368242727c7f9d2065cbd788c3ecde1ec57f33f"],"copayersExtPubKeys":["tpubD9SGoP7CXsqSKTiQxCZSCpicDcophqnE4yuqjfw5M9tAR3fSjT9GDGwPEUFCN7SSmRKGDLZgKQePYFaLWyK32akeSan45TNTd8sgef9Ymh6"],"nicknameFor":{}},"txProposals":{"txps":[],"walletId":"48ba2f1ffdfe9708","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPfQCscb7CtJKzixxcVSyrCVcfr3WCFbtT8kYTzNubhjQ5R7AuYJgPCcSH4R8T34YVxeohKGhAB9wbB4eFBbQFjUpjGCqptHm","networkName":"testnet"},"addressBook":{}}'; From 64072f83bc2d24f2db65376341830f0d99be9d13 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 15 Sep 2014 14:25:09 -0300 Subject: [PATCH 20/45] rebased! --- js/models/core/WalletFactory.js | 52 +++++++++++++++------------------ 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/js/models/core/WalletFactory.js b/js/models/core/WalletFactory.js index 48010d1c7..c3c2b505b 100644 --- a/js/models/core/WalletFactory.js +++ b/js/models/core/WalletFactory.js @@ -53,7 +53,6 @@ function WalletFactory(config, version, pluginManager) { this.storage = new this.Storage(storageOpts); -<<<<<<< HEAD this.networks = { 'livenet': new this.Network(config.network.livenet), 'testnet': new this.Network(config.network.testnet), @@ -63,11 +62,7 @@ function WalletFactory(config, version, pluginManager) { 'testnet': new this.Blockchain(config.network.testnet), }; - this.walletDefaults = config.wallet; -======= - this.networkName = config.networkName; - this.walletDefaults = config.wallet || {}; ->>>>>>> ALL TEST PASSING!!! + this.walletDefaults = config.walle || {}; this.version = version; }; @@ -100,7 +95,7 @@ WalletFactory.prototype.fromObj = function(obj, skipFields) { obj.opts.reconnectDelay = this.walletDefaults.reconnectDelay; // this is only used if private key or public key ring is skipped - obj.opts.networkName = this.networkName; + obj.opts.networkName = networkName; skipFields = skipFields || []; skipFields.forEach(function(k) { @@ -420,29 +415,28 @@ WalletFactory.prototype.joinCreateSession = function(opts, cb) { }); joinNetwork.start(opts, function() { - joinNetwork.greet(decodedSecret.pubKey, opts.secretNumber); - joinNetwork.on('data', function(sender, data) { - if (data.type === 'walletId' && data.opts) { - if (data.networkName !== decodedSecret.networkName) { - return cb('badNetwork'); - } + joinNetwork.greet(decodedSecret.pubKey, opts.secretNumber); + joinNetwork.on('data', function(sender, data) { + if (data.type === 'walletId' && data.opts) { + if (data.networkName !== decodedSecret.networkName) { + return cb('badNetwork'); + } - data.opts.privateKey = privateKey; - data.opts.nickname = nickname; - data.opts.passphrase = passphrase; - data.opts.id = data.walletId; - self.create(data.opts, function(err, w) { - if (!err & w) { - w.sendWalletReady(s.pubKey); - } else { - if (!err) err = 'walletFull'; - } - return cb(err, w); - }); - - }); - }); - }; + data.opts.privateKey = privateKey; + data.opts.nickname = nickname; + data.opts.passphrase = passphrase; + data.opts.id = data.walletId; + self.create(data.opts, function(err, w) { + if (!err & w) { + w.sendWalletReady(s.pubKey); + } else { + if (!err) err = 'walletFull'; + } + return cb(err, w); + }); + } + }); + }); }; module.exports = WalletFactory; From 52a8423df9a5a60b5670222806c1765ec796b1f5 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 15 Sep 2014 16:11:26 -0300 Subject: [PATCH 21/45] trying to fix tests --- js/models/core/WalletFactory.js | 8 +++----- test/test.WalletFactory.js | 29 +++++++++++++++++++---------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/js/models/core/WalletFactory.js b/js/models/core/WalletFactory.js index c3c2b505b..702ae499e 100644 --- a/js/models/core/WalletFactory.js +++ b/js/models/core/WalletFactory.js @@ -37,7 +37,8 @@ var Storage = module.exports.Storage = require('../Storage'); function WalletFactory(config, version, pluginManager) { var self = this; - config = config || {}; + preconditions.checkArgument(config); + preconditions.checkArgument(config.network); this.Storage = config.Storage || Storage; this.Network = config.Network || Async; @@ -62,7 +63,7 @@ function WalletFactory(config, version, pluginManager) { 'testnet': new this.Blockchain(config.network.testnet), }; - this.walletDefaults = config.walle || {}; + this.walletDefaults = config.wallet || {}; this.version = version; }; @@ -94,9 +95,6 @@ WalletFactory.prototype.fromObj = function(obj, skipFields) { obj.opts = obj.opts || {}; obj.opts.reconnectDelay = this.walletDefaults.reconnectDelay; - // this is only used if private key or public key ring is skipped - obj.opts.networkName = networkName; - skipFields = skipFields || []; skipFields.forEach(function(k) { if (obj[k]) { diff --git a/test/test.WalletFactory.js b/test/test.WalletFactory.js index 2ec67e64a..44d4fd517 100644 --- a/test/test.WalletFactory.js +++ b/test/test.WalletFactory.js @@ -131,30 +131,39 @@ describe('WalletFactory model', function() { iterations: 100, storageSalt: 'mjuBtGybi/4=', }, + + // network layer config + network: { + testnet: { + url: 'https://test-insight.bitpay.com:443' + }, + livenet: { + url: 'https://insight.bitpay.com:443' + }, + }, + }; describe('#constructor', function() { it('should create the factory', function() { var wf = new WalletFactory(config, '0.0.1'); should.exist(wf); - wf.networkName.should.equal(config.networkName); wf.walletDefaults.should.deep.equal(config.wallet); wf.version.should.equal('0.0.1'); }); }); describe('#fromObj / #toObj', function() { - it('round trip', function() { + it.only('round trip', function() { var wf = new WalletFactory(config, '0.0.5'); - var w = wf.fromObj(JSON.parse(o)); + var original = JSON.parse(o); + var o2 = wf.fromObj(original).toObj(); - should.exist(w); - w.id.should.equal("dbfe10c3fae71cea"); - should.exist(w.publicKeyRing.getCopayerId); - should.exist(w.txProposals.toObj()); - should.exist(w.privateKey.toObj()); - - assertObjectEqual(w.toObj(), JSON.parse(o)); +console.log('[test.WalletFactory.js.169]', original.opts); //TODO + ['addressBook', 'networkNonce','networkNonces', 'opts', 'privateKey','copayersExtPubKeys'].forEach(function(k){ + o2[k].should.be.deep.equal(original[k], k + ' differs'); + }) + //assertObjectEqual(w.toObj(), JSON.parse(o)); }); it('round trip, using old copayerIndex', function() { From 2562490b4d104bef82841e6185c150db1d72dc2a Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 15 Sep 2014 16:16:02 -0300 Subject: [PATCH 22/45] rm comment --- js/models/core/Wallet.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index c14a568fe..873d14bf8 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -884,7 +884,7 @@ Wallet.prototype.toObj = function() { */ Wallet.fromObj = function(o, storage, network, blockchain) { - // TODO: What is this supposed to do? + // clone opts var opts = JSON.parse(JSON.stringify(o.opts)); opts.addressBook = o.addressBook; From b38c26fbd4e04de90d8caa6265229935c9fcd578 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 15 Sep 2014 16:42:45 -0300 Subject: [PATCH 23/45] . --- test/test.WalletFactory.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/test.WalletFactory.js b/test/test.WalletFactory.js index 44d4fd517..eaaa526fc 100644 --- a/test/test.WalletFactory.js +++ b/test/test.WalletFactory.js @@ -161,7 +161,9 @@ describe('WalletFactory model', function() { console.log('[test.WalletFactory.js.169]', original.opts); //TODO ['addressBook', 'networkNonce','networkNonces', 'opts', 'privateKey','copayersExtPubKeys'].forEach(function(k){ +console.log('[test.WalletFactory.js.166:original:]',k,original[k]); //TODO o2[k].should.be.deep.equal(original[k], k + ' differs'); + }) //assertObjectEqual(w.toObj(), JSON.parse(o)); }); @@ -602,7 +604,7 @@ console.log('[test.WalletFactory.js.169]', original.opts); //TODO }); -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"},"addressBook":{}}'; +var o = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5","networkName":"testnet"},"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"},"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","030920a8b8e88c4db2871a7df0878a86cf0695f6d96bb50c701c3454f3df25176a"],"m/2147483647/1/7":["036bf329fc19bce10cf1999fae5bfa80290ff7b44776b49c7b0dc9eec6cffcfa21","03955a549875b4f7b9be28b9ff4bcd51ad2bc224430b1634baef890585885d5e1b"],"m/2147483647/1/8":["024879c9c9a261b3141ecfa1c79c4efc25278c844ecd1dcfcb95d9c19581fbdd25","03fb4a5fdb91239df3ccf7f61a5b99e7e72483101e21c9d1ee0d85544e9354c6c7"],"m/2147483647/1/9":["035928a107ec01f78cd586914d5a49710fd42e352b1312e3ad0eeb2c9666fdf8e7","03a54c03093797854829c75357f092356352a109042bbb83bdac20cb4e5eca27ea"],"m/2147483647/1/10":["021e7a3a7efe888c5e820b5cf0f03317b2b4bf438d8563449aeb7a77cade97f136","03ec0960b3d1df52ca3cc2c82b7d97063400da4dd051bba2f9bab6cb44aee01efa"],"m/2147483647/1/11":["035d70c26b7f429861f555f7c0d99947411b23b7f95303fb8d5de5b82a95aa30fc","038b922f7024f5446d6b48e5253643543b35c006d90fd37688105c6cefcd8adb8a"],"m/2147483647/1/12":["02158d6503891c6c65a606221dbf5c68d0832288975914007968419939588ecb24","0248264cb1763a3f4de9b34787b4bc5443ec92ef915927494bb9f1c1c0b498c7ca"],"m/2147483647/1/13":["0349965eea38a25ae0c061faeac4c4e57e648bc4c0f059d07b3b8b7962cbc0dde5","0352243d9269565ce2a1ffdd0b8e43a442c6dd1c9edda86eaaf2cba5a4a95c40f1"],"m/2147483647/1/14":["030fa6e3d0c5cedc0581955395c77cbe134c912a47971023b9695332df3f7bb200","03f2cf09e33326fb59bf3f13e6298d2d5d29c9eae3b872e5a851e8d8d77259c883"],"m/2147483647/1/15":["02bf0d45e41339f552df6f8baf4392142921fd38b0f2a4388a905ff6cbacbc278a","03fabe46bb6706a1b8edfd28c046a8891b4530bbe5305080b72b0d08ebdf7b8c0a"],"m/2147483647/1/16":["03a4e3146ed34d6a8af4e4379e6edcff32cb0373ba232b3d746af3052f674133ac","030311b73c6f5c46ddffc0cfce6e5ed0b671d94267d8e52cd8837f2a479916eb91"],"m/2147483647/1/17":["03233df93c762d2f06c7f5f388e4e0a8dbdb13302acba0d2d6995c487d8aec9f2f","024badfdcb7e772ac7fc1c46d3943b07500edbbece105cdeff3eb9e9fcc9f54782"],"m/2147483647/1/18":["0364035475a098e00eb010c500cad3c90af3e81a4bd613144bc9433a150f14718b","028223dc8142154e7477ce000b3dc13e1d15a901553d9b18864c8645b582b38fe6"],"m/2147483647/1/19":["03971b74b4ac4bdaadf636baa4caa82fe5355471ed6ea05a9cbe5fc6c9e4b9db76","0202ebffacd01f83849e5bc5c0e2c317bc5fb2fbcb2d6d4482a5235f9f1308b61a"],"m/0/1/4":["03005ee9ff028c98fd132e531023f2f2b61ff0d26022f979dd98088d2ba167b031","0345ea82e8dfe38277f0c3aee18d2dd93edb63e8663ac83328a7934d2ca57006f6"],"m/0/1/5":["0391bc4990b71d8a3f156ae7107929ed6372b0b4ba8a868253f71ba7189d1efa02","0312a74cf2e7c0dd41897d04fabfd8cc3187b84a28305cfc79315b24e6fe23a6b4"],"m/0/1/6":["021a38c492607ff9684a4fec445e47b5b7100d3ef9e9dc0d0b37c0a646d28d4f77","03ae0b46ab36f97447ebaa53f2b5c8f090f15395378785f2fd285eeba17fbf3f65"],"m/0/1/7":["0308cdec88c1ffe16edc98853d9c08dbd4ba2541ba566668ca17bda19d7eb3481f","02dd622267c2e68287287b8b61724f76fbe84096a56aa5054af92f8fe25380e2d1"],"m/0/1/8":["039647da9ad725836bcb28a3e0497659a28d7749d1416c421a0a01c62d237ee962","022e22aa61eafda0dd8820427f1a06314d352a15ea8645e7ab9b80920017084d82"],"m/0/1/9":["03a4ade946076c6962b70c70ac7fad3a87efb59a1d0a4e32bda13a6d47fe9df961","029a07235aba04ab69526e117d836d5b3fae5cfc8c5e72b10c6d1afd261ccc19f3"],"m/0/1/10":["03c78e9b6493b22790db1acea20df9444e0f9c424fc5756e7a32c290ae01783953","0254c130ee467a96570c9f5ebea89de04f0b1db1686b164f2694339bef8f25dd88"],"m/0/1/11":["03a762c43318ef8d4840fab04c8db73797dc648825fac60f2730b4c76678df1cf3","0212c684a4de8e750ad2dfe2b136370ab9803eca178ed9a27b3990c29b067de35c"],"m/0/1/12":["02702d221f9b15c5cf75ac2f497a6c63e60213087c3d2d3be46768e3ebd238e26e","03ed58580744deb357258e44548212038670769d8d51e385d4fb8414311fd01b52"],"m/0/1/13":["0320e0597b54c62768352f433389cee4725d6094d7bcb5c72265edcc0933829aff","02c5706f11b9a85f3176c572842b7c9812c2195058d24d945bc026b00312740e76"],"m/0/1/14":["02fe43077676b844226d3aaa62e8a86d237710d92f882366944acbde0c8992fcaf","039a6a8662abb8910741cf331320549665e9feb28ca94d1ab6a43c84fa330b94ee"],"m/0/1/15":["0369f99f72847af93d50ab8ee75b6e7e912d26e27be96f6d6b7215cf7daeff7ba5","02521700cc07c953ba5aa586fb0e4795a34dffc68c5fb43e038be3866e40f4daed"],"m/0/1/16":["02f67d1d89bd8fe2f91c5b973cbdacfb4ba440e7656bce284cf73d549625607347","035da9cfac5a803dcb2b283b02a2515a4a1bcbf3d19e0d180aee8fc30193bc0555"],"m/0/1/17":["02c024ec199d240e8d6c66276b94b91071f7cdf2bef540c29d6d18d25de7b1cf7c","02190865f9dafae3f7f05c093463be5632946422ddda0a6fef6904390792516067"],"m/0/1/18":["035ed504d7704ad984a333b8eb0fceb8be043da9284de31ed84d9e68d90c75507d","033303c415b50421732402df00f4baa219f334647a7eb5014b9f8079864d6ab558"],"m/0/1/19":["02ce49fe86b0eee73663b1ee867b16b97c876af26f12764c528a2e6d0eb55ad3d7","03ab969bc81796b88e44c340d854df955fc60ea17ea92db5d3115595d6dec890d8"],"m/0/1/20":["03e2fa915378cbdffa0d919b0fb50c7256ca731b9d571b3365e486893a1d43079c","038d058b895cf084dccfcc9367e4796a5cf4ddceed6c35f6885d75c80119613350"],"m/0/1/21":["02fcb1bf644446b5b42205272af72f0aeab9e92ca29aafa91c5fb69142764017aa","035c5fe5c8811603279a5b72b6c30735d702817db1eab937c622269e28192ffa90"],"m/0/1/22":["03b39d61dc9a504b13ae480049c140dcffa23a6cc9c09d12d6d1f332fee5e18ca5","022929f515c5cf967474322468c3bd945bb6f281225b2c884b465680ef3052c07e"],"m/0/1/23":["03f40b82fe8cacff08879f13c45f443a3dc3ea98e1d75d5f32a19f5e5a8f7a905b","028415ee458e4dcfd440ce969726f3b58ae74fb6cf3995ced099579211e7419844"],"m/1/1/5":["032748a6282e21f571b8c8dd49e775deb83c90fcf88dc4ba81d878536973709c3f","020837cd68f14ce571b335eecd1b6fa0af43e1576dd9721aaca2a8ab639ac6b7cd"],"m/1/1/6":["0337032efb013dc92bb8dccfbdda9f5c28f0039a9c60953d41003d095e9f9778af","03ceed2da6b9603297061dc8eb930112ba726b2ccf5eec67f4866a05ca4049a22b"],"m/1/1/7":["0383c96ac2af7d203f69133b2fab6b68366b5075ad6957fa06759df3b20fbfec70","0311385f79834cedaf2230a48c0f9dc8e794da1869fc595db2518d62debb85579a"],"m/1/1/8":["03efc649680280f4e4df96da923bc88330275004125ebe5483c2f3e05ca52e19a4","02803c02d197d780388259afbd001ae41fa3eb3e2bac9627aff540521c184c3b23"],"m/1/1/9":["03af2fe6aa027a76b42c1c4050a040bfd026ad2daec1bb96a5fe2d026a7df919de","02ce14163047c640228796fb1f72bbe3afb05819ad141598a4f021058a6f79dd3b"],"m/1/1/10":["033770378bd762cf0408e44e4e604bef77e336170428c506949b1a4f1f2963e574","02c58ed43946f699dbd3e36d3e9aab2714cadeb19ecd3a56e4328c50336b4a76cb"],"m/1/1/11":["02898a1545fa19bdca92adc498698d27b86529cd4c08946d9d29604734b86f31af","02b402767a045ede072600924401c0d720000b2ed59fa444bfdbef4a5f1cead745"],"m/1/1/12":["039b8659430be49913e2cd869aa8c99ccf49a13df35837370b792033dadb891483","03264e63df292257cc76babb15d15bef620d1c2f8c3bbc78d6ea02d127e5ee7386"],"m/1/1/13":["02381a559791b8e86bf546e2c718ae63cf24eed0518a58e4d4a4b310adf2cd38fa","02d7f8283a4418d912508901b4a3db0d2103206dfdd74b3c75648671e20ecfd445"],"m/1/1/14":["020376e8c550b7d9faa0b2da947a2a36fab22c6e8190b6f99460b6022017bb97d7","03fbc5299190e6628de28c92aaa12e3a131b21eb7266462c46fbedeb86fa878055"],"m/1/1/15":["027209fd3b0cf7368180a5dbb16b928c997d33fccb78505d48440c7d23eadf5460","03450bfb22858726cd7e228e6733f69457546978a95188565c53e0d1c0d6070ea8"],"m/1/1/16":["03cb355ba04f64293793855121bab5831f84a3a3edf7cd31fccaa6d67c407a4912","028bc897a39c1224610b765a80f4cd8ab79cb37776f58fec9c10ac6f649d1f3c72"],"m/1/1/17":["03f4cb0564d7e2c6b85673503b7954db22779f29a8f3374904573984e318a96bf1","037c11b6ee906d84aa7eed359d758d986d912b6f8e5cbb1acf0982a77b3ef812c4"],"m/1/1/18":["02d2e5798f33f6889472857744316f2d253f25f88379610063f40cfe5798d9858f","0253cefdfe9ca987cbf1c950b6246d5b7a194d8dfad47c3a78dbbc5c1d01511d97"],"m/1/1/19":["0336c325f5aed366ffc10d553f2bfd4d69e66cbe1688d77af14efc8827aea2e318","0378b1b9a6074f9f2ab4fa9ad1e14649c621b0c8124a1b148914d3c10e6ab390c6"],"m/1/1/20":["03ea55740a734689ce778a8c00df8ebf4274c8f66de7d05646fe5c927773ff7f2e","02275b558d49aef955b6dee51a3c0a53f4b076b97bb3f26abcc82540168ec87cac"],"m/1/1/21":["03c77869c9984664eac9c238f4b6d806c9f48ca8a736c48450f398834db2aa915c","02d984f548c7f60c09dad3287cfc48807bc8157123989636c713be61be6a2e9ced"],"m/1/1/22":["03ed7c6a3c854c1f9459891691cc32671402f9e47126919878251e568dbdf353f8","02a113dab22cd9e46967b3fd76b9b9ec1d227d88817a9300e42d332cca2a0877fd"],"m/1/1/23":["02ee186432dcf69fda50a6fdbd94651817d8a271c273a5b70cab3ec4ae77a3753b","02291370aad9de0dac676355ced64e268b0c431a51f42f12d13f5144940fce4285"],"m/1/1/24":["02bf71435e84e66547c8c583d5ba226a5ac4d935e0a9f9603ecd8925c3e847e91a","03578d8657d285a89d9d597632db662cfef9baccfb55c76b1e87948a94fc9de30d"],"m/2147483647/0/0":["02a8425bbe23426219065969f695a6c3e242b24e57226bffdd542be8fd6be968c9","03057a42fdb6569fb1615b173ccb702453db2eac5be4291b82d4511461eafbed87"],"m/2147483647/0/1":["0250c3d3e86e332010c5233c2ec3bc728026002f0037cb3382d6318409b0e70796","02cfac1e7c4c88191201080f8316af52d9faa6ba624a6e160279e9fac4d1cf79a9"],"m/2147483647/0/2":["02a8c266a5b92eb50c8be91f95e4d1ad968b2f57d527377fd642d63fb84474f61a","028cc954ab31bd179ff80b8a05f95430ae534e61b3ff35f5284fa2fbe1832ceccb"],"m/2147483647/0/3":["02f719e1a7ab00ea98611453fb03d44c1da04655bed74af392534d70099039b4c2","03bfa548bfd4718c50bfce173f780eadcfb679d9c0206c91a2fa1879a9cf7558b2"],"m/2147483647/0/4":["0362c0695d397ca26bf47f0e641bb3cfb06ff29ccac2e1d56ded3afcf88b1e688d","02f9d87b05bdb3b9e82f506b43f813041c0e403274adc23d11e5e1651e34b606c2"],"m/2147483647/0/5":["033731323032d4ee08e858fc71f93970444333e183a1d5052e1d08cfb511e262c8","023e12556cef67ade35b7758916b5e1a3ebe074ccd35c5d8eff6b01321f63eb495"],"m/2147483647/0/6":["025d11b90081972bc1c258c9d6f476dfc2f95b69f0e9935322bf9c21deb580ff64","02b065f56a378907354f0738a0ed74f10660c6b5dd68c9f992093b75ce3d7d8b72"],"m/2147483647/0/7":["0210e721e8a35db9d8c855a0d346f60c09208f3be80b39e03af2c29db777332c71","0277f352969fadb1f1835f9a0fa99c6a3c7b6c281be5b2794c88a708eb177ea33d"],"m/2147483647/0/8":["02998d8d41e4215cd2a961a415a3ed0b1f984f1627719a7b102a75864943c4d87b","03d8ed7fc8f68a77f68d3afd007b7aa4c89944195143630ce183f0fa5438f2b559"],"m/2147483647/0/9":["0324fa91737588e4f85937303ce65c3b91b5f2ae506a72d92b83e3f5f9aeeb3c6f","02a011be72c4a400319212228106af278823a97acfe0a67e1ecd866d446b315114"],"m/2147483647/0/10":["025886ba287922a904881c7315e6fcc410a7976741771a5937d3a1a01b529f21fd","0243bb91ceed9d29d0c2ca66a8ab77e82110bbcc023beb4106f787964f44a0b972"],"m/2147483647/0/11":["0369d21684894cc2d4b2f5e581ede3cac9e8db4161a08e7737c1be129bb673d3d5","03c9ef27e3cd3dadc078fdfd9936a7ad9bf7954747085cf8f8a2a5bb3431f68a9f"],"m/2147483647/0/12":["03a73b8fd859bf6acebffdfffa2597199091daedd2c011ac67fc3494d8a1a8ceb6","025a213f7771c8be03f43f2e7f469ad4ef2cf6907ea284b227a786d1f55dfa7144"],"m/2147483647/0/13":["03a09f7ca257e1ab263cd5e6b0addc3ff868b93df132321d98775ca3505efb576f","03454c715739164bc55f347a651439cdf3ec146b35d2927beb60e8290b3916e082"],"m/2147483647/0/14":["03a64b1f7bd94a6b1a6e84ea444e0ba04e9deb86460934ccc37c0615a134a8257b","02794f09210b1811a455f3e1c7bcd35c76dff2523190fef9615eb27e2376acac1c"],"m/2147483647/0/15":["0392dca2fd9a3bc2b2a7d90a848719069fbc5f22bff7327bb8186c032514085263","032ee8a33ea76d70c7ae839448ca6c5b1af89146f2922e23ba1822df42dbc7e66a"],"m/2147483647/0/16":["031a22a1a3c1abad7c4d782ef6ba3cc00f2e8fe549eb33e0732200aff6d3174831","03bdce9781289e0c31cf727f4c93fe46f7930dd8fd68f818ce241f1ede268e8e0e"],"m/2147483647/0/17":["03b12d27e9aea2c2ad598e54e40860a705ac2ca2427aa511b501b38ec368ea5c7d","03e60d35d84d4536cad895215256b312bb4879a8d417251c279995e58f25da3d54"],"m/2147483647/0/18":["0380266cc9a9673676ad6a1b2e7148766df9c25b4dce299e5edc4f65b72aa58e64","0329e2a8a48c06c0c45dfdd2ab33e6455551557d8ebaf8c12fdf7470f8c45f1d28"],"m/2147483647/0/19":["036fe62af85560d7eea7c7af55e60b32a97dca80134d0aedffb19eb2705b9d6e01","02381c2c30b9f81e2a53c69028fbe11803acad0420b267719b7a80870be0baaeb7"],"m/0/0/2":["027bf94b8fc4e9b42683af25fda125ccab8760040717d100270dd4afd032692daf","026382c6c9357250d96dc21e43c053857a64efeac1887fdcbc107fbe3ecfc6115a"],"m/0/0/3":["03fd203acbd9af3cbbfb709458f8952078234a36094f12d00372e4b2b14cfdf419","03f2e5db59aea5dc89f53ac2a9f4ef66d41265c45afc5d763e0ca61ab70c7c61ec"],"m/0/0/4":["02a1d7cf4fcdbbf4de4002b844c3bff1639073f1cd6e5c4a4e02596b45d3f518c2","03b5fba813294e6ae096ea158833453caa5a945609b0a554696091b9b152bb0f7d"],"m/0/0/5":["0261d37e3b56ef4e106c59753037f516a4b1c45e056b2a3e00f8b77f15aaa7f8a5","0256a55e66e0de1603f0d600c0eb5f5486cf3512a776a36f3ab0d1941fc0dc9b09"],"m/0/0/6":["031db2826af215fe6cbe3f6e121b0497840fc49be133cff0a4d4eab679d6b99d70","021dd722c3f35dd04fcdb57f09b76c723d521fb36751de03ffd08096ddf1dc1f86"],"m/0/0/7":["0354ea75bdd9eb5beae7262e4a5eeb58bd10103ee0185e85b749ea39f6615d0f62","03f2c8f3b6478c0501a8578d5caf5ac2974f8213fc5e699d62dd2af58fbe8781d4"],"m/0/0/8":["0282e67df3bcd1e1662469b4c3151fb50ee1e46b75d787d91184c16b9803131f82","02921a7054af1e425f4137a5eb6b34d1f2b9d81c2625230194bc30657bb4277e11"],"m/0/0/9":["033e7e387933983ceab37c8388bd8ebc5119760f493ffe6f083bef0e5dfe22891d","02d660d60cc55d80912e0745cb142a8596a4604fbf72f9aadec0599aa2ed62461a"],"m/0/0/10":["022ce5b2750ae34512199856eab9e912dc25281cd8b88e7688a46c3b9a389701cb","02f14aa1608fce3b6088148709eb5fe72b61699c931fa8d95a45fab1106859d1b0"],"m/0/0/11":["0288dbef3302c1bc5556028adb33e2f9e03c119dbad4f706befb8ce86cea459f2b","03f13ced465e2e0a3aaa8895f3185d5711e0bebdaf507610b7a669ac8fc82da8fe"],"m/0/0/12":["031ab4677885340d2f927ccc9747f4346b79e4eb6c750695095a8a2524610fa94a","038c881910fbd8b50d193db4e0c84f5b7840820397f92cf0718a8e06d027125503"],"m/0/0/13":["031b568452cba22eb7a88c6085489e53e35abd16068882e71a140e47e12dee9c61","020d09885ee362101d12d34ce0918d41593634db1b9413e5415c6755753b9330e8"],"m/0/0/14":["024177bc9aa03cfc72eda2dfddffd7fe9d0c2f007fc3ba1a48280feae2b9fb117a","03394ad321668440c08da76eb35475ba3a8c0e8cbe0ed81468673a8c72d38fe457"],"m/0/0/15":["02037b1cc696ffbe9eba3684edd53653386ef6cd7728401c40120037593a4c2ae2","020ab8d6900ec9c11ca5d96dfc0ce7cf0ee71653a7c45118e89abb4b113147e53a"],"m/0/0/16":["023bcbb8d4726a546087cdb83740adf0ace879b7195a572c652fa8ce4dbe195a04","0392721b230d5163d28b27fc7e059b875711f12b3da448eabe7229bde57530e637"],"m/0/0/17":["02498ee74e849d3e9261dd1863038caf83d6a3bc2eeebecf17055d4bab44dee77f","03d4dc104b2e0981693e8097437de9b05334a85e2c8edb02783897859bdbc93e32"],"m/0/0/18":["0218a9f524fe54abf8c3afd21314296cfd93eaa9227acbd457e6c9a742dc233cf4","03760f3d0c5db969bda698ff9352e3b7c332216c34825f4c6e857e39c9aee7cd35"],"m/0/0/19":["033dd51f7737f0e9db79f5c38e4298bf3396346904ef3933d290a22e5b77048d9e","0221b2eedccb9a37515263071550069b3b349a166f0f131d0028e8600d9a2251b9"],"m/0/0/20":["02cb6c39161f3244d7769f7ab96346cae2cf21cb6f4538f5e7382d363dc2f836c7","034f7bda4d1e9ed6a3774608a4d6cd8582ab59fe3187f8a7a7cf914d89426ebe28"],"m/0/0/21":["035490549d65f1360f10340037250b171470ff4c86966318a2b1eead6d8b969aea","03f6a04f6fcd07a4f32c82d53710ed30e0f54d43d41c67c661d158b3d0830c3ea2"],"m/1/0/2":["02972eae7e4302e319c266578e14a07839c1e788296a92906e6d66d938211dad5f","039ed6b488f1571ad6527acd6b6c5b8453eacf6665dc5cb7852e33d1c8ea73f9fe"],"m/1/0/3":["02bec4728888c2c045108353994bae5731ec7a7b41459023b0023e10b8d616bd30","03ce1efe16214c9eac595382e46a68143dd11a335b3f7c971ddd719ac544a5fc4b"],"m/1/0/4":["030e2df1d341568225d8dfbe5d07e98dae9f90e0f43e19dcc68c998a6ed7bcc1f0","0380f4c07dc84faf42d51779f104aa6e3b5c3ce2d7684b3cb76d49faeefc2b69d6"],"m/1/0/5":["029a54ddaa25f433b493f4b72df8c1d41be2c4d2963b8b61ee63cc86d16c12d066","021567c95e0317442e7367aa4e3378dd46c5bcef5860f789272fea83b917de0669"],"m/1/0/6":["03590320d80b61cc0874b579f467c9b5ccc50d9ef875bcf6bdd12e2d0c211e8973","03ee4677b6ee89a9d355851f2230506c6897ff219062c0df4ad9a85c60f3535f93"],"m/1/0/7":["03caf98ab1c9b79d1dc8029453a6137c08787b04043b79af3cb42d41d2d3f1338f","023f39ae4e2f4f3887d5fc58e0d3a0d7ee267dc04aa257c75b6b2d67d2f5580f81"],"m/1/0/8":["0352a2a3ea8209c9a2b633d788796ac2d16c08022440e04a77ab2835c7f971d266","0291bc248b3da997f35e8fae98a75a91fdac2819d74c4e270899338d48f7389e87"],"m/1/0/9":["02468d32d9c3c62418d506d4cd0da6cd2022d5bcafdb5f847cf7bde7a48ec6848b","032713d90d12eb6a072f3c1db6c0d3b680d3f78883016135fc0f78e8193d41d4b4"],"m/1/0/10":["034863cc6bab9b059be53413ba75c5fc286647c20d7f9e5512ef4754ea301dd1ce","03a33ab9c32a2264ee2464ebbb5892f0e34acf0fdede4f87395a89e9dacdd4930e"],"m/1/0/11":["031e19296695bfe8a96ba3bf58afa805ee1bd5471fddb3929b1678d69d442d69c9","0270feb33956fd9e937019d629523e26437493c0856514011e6aec88baf7721295"],"m/1/0/12":["03cce695d3c3843bf73e851b2446a77d7e235e5b80b4f4474f9946292eb8218742","039ea96c8822f0ec7ed28308d277f3e730480d7573579cd11b89aef4364cd9ffeb"],"m/1/0/13":["02ab4ac38eb405e822d12c0f0f354f04f9ee1d991dde887a5c1171096fe503158f","036809e60cae1203da8884ea1f85d4669ce6e053f8ba605d775e271b70ab4f6787"],"m/1/0/14":["039d61da23a8610fa0ee58eb37d7cea7ea9396c79153da97280ccf5e46718e3bac","03015c27bcc778682781fd6ad30aa6041db0b7e24270818cdceece0043ccc34b26"],"m/1/0/15":["03c088ed669132835d2728b0ecf294271c8388988c6ae264d43ca24f50e4005f81","03e2c118c9445a2ddc4c8afeb0ba49e21be3f818a483d346418b8922b8a371a2b7"],"m/1/0/16":["02bba7df9847f463c6b23eca37a4bd6efa3801a52b8ddfad804d902e783b70c81c","03764b657f23996e31c64a701facc1cbeb0c9edfdd605e2c1ed36cf48197565d45"],"m/1/0/17":["020445179c522295b89bf4bfd582eb03422e3fa20dcd29263925e9f44282d476d8","036e47bdd32f3061aed1c1f8c2a32b038c7b72391cb1f80ebfc150e58f88372766"],"m/1/0/18":["024d88c4bfcbba713d49e1edcd035234aaa1ee76ad7bcf75bf074a16658a6b0b6d","02b861e7a20d89f6875d2e44c78dbadb99503e282e5e60e9f65657af6fea81d425"],"m/1/0/19":["023a8ca9d5300181f157e1930d3b0800eebe7683d8df72e6cbf28834dbf1be5d60","026053c4f84c10d15890c0b254522972931bc2d5b7cdf9c1f9f3137c22edf3ecd3"],"m/1/0/20":["03137c66e9f3d61aba659f408d77a293fa0f3fea4ccb911074a681d6f61a55d023","0291aa1bbfbef59b16b0e37e185a706c589d448cb02e860c5df9c9d7242ecc739f"],"m/1/0/21":["03c08673e0cae55318bc9dcc4b5f11eb3ff71d42de04015e255dde3fd8cba7e09e","02423d4eab06cd5b26e71d145283523c011d58032700c517f00b328d2c90cf109f"]}},"txProposals":{"txps":[{"creator":"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5","createdTs":1405543144016,"seenBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543144016,"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543144645},"signedBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543144016},"rejectedBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543170040},"sentTs":null,"sentTxid":null,"inputChainPaths":["m/45\'/0/0/0"],"comment":"blablabla","builderObj":{"valueInSat":"29000000","valueOutSat":"8900000","feeSat":"10000","remainderSat":"20090000","hashToScriptMap":{"2NBtv6DdXj8HBunyGqpW9H8bUtW5x3rfVTj":"5221028a4b63f26253f3a8731577b8e1ee480950ad5833ebbf106fe3463bfc07cc3b90210332efa054c08cb77506a35ee0762cb7156f244566703ec08e433568ec0397bec852ae"},"selectedUtxos":[{"address":"2NBtv6DdXj8HBunyGqpW9H8bUtW5x3rfVTj","txid":"a9f4dda3f092e37244bc4e77ea921fed01d5b8ea49613dfdc0dc8afdd70190b5","vout":1,"ts":1405543855,"scriptPubKey":"a914cc93216398b77b5f8c451ca3a357bef961678be987","amount":0.29,"confirmations":0,"confirmationsFromCache":false}],"inputsSigned":0,"signaturesAdded":1,"signhash":1,"spendUnconfirmed":true,"tx":"0100000001b59001d7fd8adcc0fd3d6149eab8d501ed1f92ea774ebc4472e392f0a3ddf4a9010000009300493046022100ccbb8f398f74a76236629b8499ffc6f9518a2091f5a61a9a352c0a10f615961e022100b8f0769c76cf33bec3d7f81d9da2b74cf6e8a5e0a24ee5f48172854d8bcdbfa101475221028a4b63f26253f3a8731577b8e1ee480950ad5833ebbf106fe3463bfc07cc3b90210332efa054c08cb77506a35ee0762cb7156f244566703ec08e433568ec0397bec852aeffffffff02a0cd8700000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288ac908c32010000000017a914560c292066792531164149c5ed63ad2793a61b928700000000"}},{"creator":"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5","createdTs":1405543188745,"seenBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543188745,"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543189341},"signedBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543188745,"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543206819},"rejectedBy":{},"sentTs":1405543207304,"sentTxid":"169bc92693dd2e27724eeba81e54210e842035bd3af6c52e6a6a5e908f1a4f66","inputChainPaths":["m/45\'/0/0/0"],"comment":"que parece","builderObj":{"valueInSat":"29000000","valueOutSat":"9000000","feeSat":"10000","remainderSat":"19990000","hashToScriptMap":{"2NBtv6DdXj8HBunyGqpW9H8bUtW5x3rfVTj":"5221028a4b63f26253f3a8731577b8e1ee480950ad5833ebbf106fe3463bfc07cc3b90210332efa054c08cb77506a35ee0762cb7156f244566703ec08e433568ec0397bec852ae"},"selectedUtxos":[{"address":"2NBtv6DdXj8HBunyGqpW9H8bUtW5x3rfVTj","txid":"a9f4dda3f092e37244bc4e77ea921fed01d5b8ea49613dfdc0dc8afdd70190b5","vout":1,"ts":1405543855,"scriptPubKey":"a914cc93216398b77b5f8c451ca3a357bef961678be987","amount":0.29,"confirmations":1,"confirmationsFromCache":false}],"inputsSigned":1,"signaturesAdded":2,"signhash":1,"spendUnconfirmed":true,"tx":"0100000001b59001d7fd8adcc0fd3d6149eab8d501ed1f92ea774ebc4472e392f0a3ddf4a901000000da00483045022035423cc74824ba904907678dda3b62a20a787b96d1b3e9f3e9546f9c57f4e45902210080a1ff1c39f458ac1642b9e948bd62fd70563b5252e749cc8fc642cd763ee830014730440220524a13f36cfb03caa246d7d84de634ec9386f2c39c19bfa926037f48da86262b022050e58a6503d105ad2805f86806810a1aa7f20d6271e1340b42fa91ab6a30f3e801475221028a4b63f26253f3a8731577b8e1ee480950ad5833ebbf106fe3463bfc07cc3b90210332efa054c08cb77506a35ee0762cb7156f244566703ec08e433568ec0397bec852aeffffffff0240548900000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288acf00531010000000017a9146130a9d51f996b7a1b9d3e10c80930834251909d8700000000"}},{"creator":"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba","createdTs":1405543505848,"seenBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543505848,"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543590221},"signedBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543505848,"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543590221},"rejectedBy":{},"sentTs":1405543610315,"sentTxid":"6fe851b54b777a75fe80fa204dc674395e2af69efb1f7c0017e909eb82c3d914","inputChainPaths":["m/45\'/0/1/1"],"comment":"mandaaaaaaa","builderObj":{"valueInSat":"19990000","valueOutSat":"19980000","feeSat":"10000","remainderSat":"0","hashToScriptMap":{"2N277q5r8Ab6XLJNCjXXFdh5itDJRQCv9ts":"5221020389327ee8ae7d0ee3f8187842d23a4070bdd8a27c0bcddd05d80ef39009253d21025c9b49bdf17d97bd82ea1b87793082f857247f0f9b999937a166ec994bb1b41f52ae"},"selectedUtxos":[{"address":"2N277q5r8Ab6XLJNCjXXFdh5itDJRQCv9ts","txid":"169bc92693dd2e27724eeba81e54210e842035bd3af6c52e6a6a5e908f1a4f66","vout":1,"ts":1405543157,"scriptPubKey":"a9146130a9d51f996b7a1b9d3e10c80930834251909d87","amount":0.1999,"confirmationsFromCache":false}],"inputsSigned":1,"signaturesAdded":2,"signhash":1,"spendUnconfirmed":true,"tx":"0100000001664f1a8f905e6a6a2ec5f63abd3520840e21541ea8eb4e72272edd9326c99b1601000000db0048304502206b18b3dba2646c552469d8ef52d7656f6a65f563032530f622abdfd8bd4c5cee022100e804b406eddebbc827646141e74dc64c76a770ed4e35183ffd35d265ad9f7d3b01483045022100f6c013638ff0a316b1baa93dfffba6a98cf3033c133e8bd899e933c9c3e47ce10220530f40e7ea52ae58bec695edbec6d566d2ee8e7b5f33f95e33093ad1e29a125401475221020389327ee8ae7d0ee3f8187842d23a4070bdd8a27c0bcddd05d80ef39009253d21025c9b49bdf17d97bd82ea1b87793082f857247f0f9b999937a166ec994bb1b41f52aeffffffff01e0de3001000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288ac00000000"}},{"creator":"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba","createdTs":1405543781381,"seenBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543781381,"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543782017},"signedBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543781381},"rejectedBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543794590},"sentTs":null,"sentTxid":null,"inputChainPaths":["m/45\'/0/0/1"],"comment":"1","builderObj":{"valueInSat":"29000000","valueOutSat":"1000000","feeSat":"10000","remainderSat":"27990000","hashToScriptMap":{"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb":"52210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352ae"},"selectedUtxos":[{"address":"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb","txid":"6c9da5b0da4bab0d576033325e987b10ccf2b9bf479d306b6aae36efeaa56892","vout":0,"ts":1405543698,"scriptPubKey":"a9147d274ac50968d7823b6cbc1b38770deb7157995387","amount":0.29,"confirmationsFromCache":false}],"inputsSigned":0,"signaturesAdded":1,"signhash":1,"spendUnconfirmed":true,"tx":"01000000019268a5eaef36ae6a6b309d47bfb9f2cc107b985e323360570dab4bdab0a59d6c000000009200483045022064d877bc5171fbaef909c2a1a924e0023b3ccc0b530cb46653f06ecb230283e8022100bc6658d60ad4f7120d9226c8f6eada87f3b0388f73c458011988bab36e78ba15014752210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352aeffffffff0240420f00000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288acf017ab010000000017a91421c4a435d9ac263ec55b35a1a5ca95e979639b9b8700000000"}},{"creator":"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5","createdTs":1405543835343,"seenBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543835343,"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543835968},"signedBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543835343},"rejectedBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543850998},"sentTs":null,"sentTxid":null,"inputChainPaths":["m/45\'/0/0/1"],"comment":"2","builderObj":{"valueInSat":"29000000","valueOutSat":"1000000","feeSat":"10000","remainderSat":"27990000","hashToScriptMap":{"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb":"52210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352ae"},"selectedUtxos":[{"address":"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb","txid":"6c9da5b0da4bab0d576033325e987b10ccf2b9bf479d306b6aae36efeaa56892","vout":0,"ts":1405543698,"scriptPubKey":"a9147d274ac50968d7823b6cbc1b38770deb7157995387","amount":0.29,"confirmationsFromCache":false}],"inputsSigned":0,"signaturesAdded":1,"signhash":1,"spendUnconfirmed":true,"tx":"01000000019268a5eaef36ae6a6b309d47bfb9f2cc107b985e323360570dab4bdab0a59d6c0000000092004830450220302baae7de2e0f102bf3af2d5f450f673e51bd143020141a769ccdcdf16af188022100e7abc087c76050ed649e7139a5a136969e74e24a8d8f6223d3219ad033a26451014752210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352aeffffffff0240420f00000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288acf017ab010000000017a9148b102abba0729fb0690c61cf7187064d692d43d78700000000"}},{"creator":"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba","createdTs":1405543869803,"seenBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543869803,"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543870411},"signedBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543869803,"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543890406},"rejectedBy":{},"sentTs":1405543890913,"sentTxid":"6a0f61574ad65e537e7e99298968db565f97b894b61f4c8f8fac8fcaedb83e2b","inputChainPaths":["m/45\'/0/0/1"],"comment":"3","builderObj":{"valueInSat":"29000000","valueOutSat":"1100000","feeSat":"10000","remainderSat":"27890000","hashToScriptMap":{"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb":"52210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352ae"},"selectedUtxos":[{"address":"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb","txid":"6c9da5b0da4bab0d576033325e987b10ccf2b9bf479d306b6aae36efeaa56892","vout":0,"ts":1405543698,"scriptPubKey":"a9147d274ac50968d7823b6cbc1b38770deb7157995387","amount":0.29,"confirmationsFromCache":false}],"inputsSigned":1,"signaturesAdded":2,"signhash":1,"spendUnconfirmed":true,"tx":"01000000019268a5eaef36ae6a6b309d47bfb9f2cc107b985e323360570dab4bdab0a59d6c00000000db00483045022100a8ce7907f9fd7dd41dd65c2dec425e008efea06ee7c80787c10c0e210fbf181302207712c0fdd1cb25836ac1fc2fd303c1e26b85e8980417719b9ed50e977a9693ec01483045022100d1780c4f028cd898920aca3eaceba352ed9306cd17f019ae2f634e8facad149a02203c84ab2093da8e22577e93f27a732f0728d4e6db0c749f3cd3d898d6a025152a014752210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352aeffffffff02e0c81000000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288ac5091a9010000000017a914cc1cab78458b1a951b91c6dcd7eeeeb682f506388700000000"}}],"walletId":"55d4bd062d32f90a","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPdWUAmaaopPftevC72Jtiu19V8ee5XijL9JvogqfR95uVrL85f8yBdQMq3KyQtG3Q91yWQb3XDbWWpcdWFDAmJ7Xy2XWkGJu","networkName":"testnet","privateKeyCache":{"m/45\'/0/0/0":"b6fd8d1a079efd523da34f31ba81f544fc3d0a728a8a98299d8980682518e79c","m/45\'/0/1/1":"0f4d52d2a99e4c8c1c2edf09fef12407c3abd2304b961198c3f131a8c8443a13","m/45\'/0/0/1":"de5c191c343bd6017b98708c03344849624a14e2c167cfd6eb8dcb075d139293"}},"addressBook":{"msj42CCGruhRsFrGATiUuh25dtxYtnpbTx":{"hidden":false,"createdTs":1405543109222,"copayerId":"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba","label":"faucet","signature":"3045022067576e5b37f2707a8dc66e57511ad9b10a3125bd95193fff6f8f6402969c3bf3022100adff9f417db07d88face13b3d13f422740d4421440cade1a205684dfdc5d733a"}}}'; From fd97b12c4deb58edbb3ddf014ac1765b5740a75b Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 15 Sep 2014 16:46:24 -0300 Subject: [PATCH 24/45] . --- test/test.WalletFactory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test.WalletFactory.js b/test/test.WalletFactory.js index eaaa526fc..f759fd5cd 100644 --- a/test/test.WalletFactory.js +++ b/test/test.WalletFactory.js @@ -161,7 +161,7 @@ describe('WalletFactory model', function() { console.log('[test.WalletFactory.js.169]', original.opts); //TODO ['addressBook', 'networkNonce','networkNonces', 'opts', 'privateKey','copayersExtPubKeys'].forEach(function(k){ -console.log('[test.WalletFactory.js.166:original:]',k,original[k]); //TODO +console.log('[test.WalletFactory.js.166:original:]',k,original[k], o2[k]); //TODO o2[k].should.be.deep.equal(original[k], k + ' differs'); }) From 415861df29c45d9dfbf5a2af99cb5ac5f6417ef0 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 15 Sep 2014 17:45:06 -0300 Subject: [PATCH 25/45] all test passing, after rebasing --- js/models/core/WalletFactory.js | 12 +-- test/test.WalletFactory.js | 153 ++++++++++---------------------- 2 files changed, 55 insertions(+), 110 deletions(-) diff --git a/js/models/core/WalletFactory.js b/js/models/core/WalletFactory.js index 702ae499e..b1594937c 100644 --- a/js/models/core/WalletFactory.js +++ b/js/models/core/WalletFactory.js @@ -86,10 +86,12 @@ WalletFactory.prototype.obtainNetworkName = function(obj) { * @param {string[]} skipFields - fields to skip when importing * @return {Wallet} */ -WalletFactory.prototype.fromObj = function(obj, skipFields) { - var networkName = this.obtainNetworkName(obj); +WalletFactory.prototype.fromObj = function(inObj, skipFields) { + var networkName = this.obtainNetworkName(inObj); preconditions.checkState(networkName); - preconditions.checkArgument(obj); + preconditions.checkArgument(inObj); + + var obj = JSON.parse(JSON.stringify(inObj)); // not stored options obj.opts = obj.opts || {}; @@ -421,8 +423,8 @@ WalletFactory.prototype.joinCreateSession = function(opts, cb) { } data.opts.privateKey = privateKey; - data.opts.nickname = nickname; - data.opts.passphrase = passphrase; + data.opts.nickname = opts.nickname; + data.opts.passphrase = opts.passphrase; data.opts.id = data.walletId; self.create(data.opts, function(err, w) { if (!err & w) { diff --git a/test/test.WalletFactory.js b/test/test.WalletFactory.js index f759fd5cd..55f5239f6 100644 --- a/test/test.WalletFactory.js +++ b/test/test.WalletFactory.js @@ -1,6 +1,7 @@ 'use strict'; +var _ = require('underscore'); var chai = chai || require('chai'); var should = chai.should(); @@ -15,71 +16,14 @@ var mockLocalStorage = require('./mocks/FakeLocalStorage'); var mockSessionStorage = require('./mocks/FakeLocalStorage'); -/** - * A better way to compare two objects in Javascript - **/ -function getKeys(obj) { - var keys; - if (obj.keys) { - keys = obj.keys(); - } else { - keys = []; +var PERSISTED_PROPERTIES = require('../js/models/core/Wallet').PERSISTED_PROPERTIES; - for (var k in obj) { - if (Object.prototype.hasOwnProperty.call(obj, k)) { - keys.push(k); - } +function assertObjectEqual(a, b) { + PERSISTED_PROPERTIES.forEach(function(k) { + if (a[k] && b[k]) { + _.omit(a[k],'name').should.be.deep.equal(b[k], k + ' differs'); } - } - - 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) - } + }) } @@ -153,19 +97,13 @@ describe('WalletFactory model', function() { }); }); + // TODO this is a WALLET TEST! not Wallet Factory. Move it. describe('#fromObj / #toObj', function() { - it.only('round trip', function() { + it('round trip', function() { var wf = new WalletFactory(config, '0.0.5'); var original = JSON.parse(o); var o2 = wf.fromObj(original).toObj(); - -console.log('[test.WalletFactory.js.169]', original.opts); //TODO - ['addressBook', 'networkNonce','networkNonces', 'opts', 'privateKey','copayersExtPubKeys'].forEach(function(k){ -console.log('[test.WalletFactory.js.166:original:]',k,original[k], o2[k]); //TODO - o2[k].should.be.deep.equal(original[k], k + ' differs'); - - }) - //assertObjectEqual(w.toObj(), JSON.parse(o)); + assertObjectEqual(o2, original); }); it('round trip, using old copayerIndex', function() { @@ -196,7 +134,7 @@ console.log('[test.WalletFactory.js.166:original:]',k,original[k], o2[k]); //TOD it('support old index schema: #fromObj #toObj round trip', function() { 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"},"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"},"addressBook":{}}'; + var o2 = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5","networkName":"testnet"},"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"},"addressBook":{}}'; var wf = new WalletFactory(config, '0.0.5'); var w = wf.fromObj(JSON.parse(o)); @@ -207,9 +145,7 @@ console.log('[test.WalletFactory.js.166:original:]',k,original[k], o2[k]); //TOD should.exist(w.txProposals.toObj); should.exist(w.privateKey.toObj); - // - var expected = JSON.parse(o2.replace(/cosigner/g, 'copayerIndex')); - assertObjectEqual(w.toObj(), expected); + assertObjectEqual(w.toObj(), JSON.parse(o2)); }); }); @@ -460,9 +396,10 @@ console.log('[test.WalletFactory.js.166:original:]',k,original[k], o2[k]); //TOD }; it('should yield bad network error', function(done) { - wf.network.greet = sinon.stub(); - wf.network.on = sinon.stub(); - wf.network.on.withArgs('data').yields('senderId', { + var net = wf.networks['testnet']; + net.greet = sinon.stub(); + net.on = sinon.stub(); + net.on.withArgs('data').yields('senderId', { type: 'walletId', networkName: 'aWeirdNetworkName', opts: {}, @@ -477,10 +414,11 @@ console.log('[test.WalletFactory.js.166:original:]',k,original[k], o2[k]); //TOD it('should yield to join error', function(done) { opts.privHex = undefined; - wf.network.greet = sinon.stub(); - wf.network.on = sinon.stub(); - wf.network.on.withArgs('serverError').yields(null); - wf.network.on.withArgs('data').yields('senderId', { + var net = wf.networks['testnet']; + net.greet = sinon.stub(); + net.on = sinon.stub(); + net.on.withArgs('serverError').yields(null); + net.on.withArgs('data').yields('senderId', { type: 'walletId', networkName: wf.networkName, }); @@ -493,20 +431,21 @@ console.log('[test.WalletFactory.js.166:original:]',k,original[k], o2[k]); //TOD it('should call network.start / create', function(done) { opts.privHex = undefined; - wf.network.cleanUp = sinon.spy(); - wf.network.greet = sinon.spy(); - wf.network.start = sinon.stub().yields(null); + var net = wf.networks['testnet']; + net.cleanUp = sinon.spy(); + net.greet = sinon.spy(); + net.start = sinon.stub().yields(null); - wf.network.on = sinon.stub(); - wf.network.on.withArgs('connected').yields(null); - wf.network.on.withArgs('data').yields('senderId', { + net.on = sinon.stub(); + net.on.withArgs('connected').yields(null); + net.on.withArgs('data').yields('senderId', { type: 'walletId', - networkName: wf.networkName, + networkName: 'testnet', opts: {}, }); wf.create = sinon.stub().yields(null, 'wallet'); wf.joinCreateSession(opts, function(err, w) { - wf.network.start.calledOnce.should.equal(true); + net.start.calledOnce.should.equal(true); wf.create.calledOnce.should.equal(true); done(); }); @@ -514,15 +453,16 @@ console.log('[test.WalletFactory.js.166:original:]',k,original[k], o2[k]); //TOD it('should return walletFull', function(done) { opts.privHex = undefined; - wf.network.cleanUp = sinon.spy(); - wf.network.greet = sinon.spy(); - wf.network.start = sinon.stub().yields(null); + var net = wf.networks['testnet']; + net.cleanUp = sinon.spy(); + net.greet = sinon.spy(); + net.start = sinon.stub().yields(null); - wf.network.on = sinon.stub(); - wf.network.on.withArgs('connected').yields(null); - wf.network.on.withArgs('data').yields('senderId', { + net.on = sinon.stub(); + net.on.withArgs('connected').yields(null); + net.on.withArgs('data').yields('senderId', { type: 'walletId', - networkName: wf.networkName, + networkName: 'testnet', opts: {}, }); wf.create = sinon.stub().yields(null, null); @@ -535,19 +475,21 @@ console.log('[test.WalletFactory.js.166:original:]',k,original[k], o2[k]); //TOD it('should accept a priv key a input', function() { var wf = new WalletFactory(config, '0.0.1'); opts.privHex = 'tprv8ZgxMBicQKsPf7MCvCjnhnr4uiR2Z2gyNC27vgd9KUu98F9mM1tbaRrWMyddVju36GxLbeyntuSadBAttriwGGMWUkRgVmUUCg5nFioGZsd'; - wf.network.cleanUp = sinon.spy(); - wf.network.start = sinon.spy(); + var net = wf.networks['testnet']; + net.cleanUp = sinon.spy(); + net.start = sinon.spy(); wf.joinCreateSession(opts, function(err, w) { - wf.network.start.getCall(0).args[0].privkey.should.equal('ddc2fa8c583a73c4b2a24630ec7c283df4e7c230a02c4e48bc36ec61687afd7d'); + net.start.getCall(0).args[0].privkey.should.equal('ddc2fa8c583a73c4b2a24630ec7c283df4e7c230a02c4e48bc36ec61687afd7d'); }); }); it('should call network.start with private key', function() { opts.privHex = undefined; var wf = new WalletFactory(config, '0.0.1'); - wf.network.cleanUp = sinon.spy(); - wf.network.start = sinon.spy(); + var net = wf.networks['testnet']; + net.cleanUp = sinon.spy(); + net.start = sinon.spy(); wf.joinCreateSession(opts, function(err, w) { - wf.network.start.getCall(0).args[0].privkey.length.should.equal(64); //privkey is hex of private key buffer + net.start.getCall(0).args[0].privkey.length.should.equal(64); //privkey is hex of private key buffer }); }); }); @@ -604,7 +546,8 @@ console.log('[test.WalletFactory.js.166:original:]',k,original[k], o2[k]); //TOD }); -var o = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5","networkName":"testnet"},"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"},"addressBook":{}}'; +var o = '{"opts":{"id":"dbfe10c3fae71cea", "spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5","networkName":"testnet"},"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"},"addressBook":{},"settings":{"unitName":"BTC","unitToSatoshi":100000000,"unitDecimals":8,"alternativeName":"Argentine Peso","alternativeIsoCode":"ARS"}}'; + 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","030920a8b8e88c4db2871a7df0878a86cf0695f6d96bb50c701c3454f3df25176a"],"m/2147483647/1/7":["036bf329fc19bce10cf1999fae5bfa80290ff7b44776b49c7b0dc9eec6cffcfa21","03955a549875b4f7b9be28b9ff4bcd51ad2bc224430b1634baef890585885d5e1b"],"m/2147483647/1/8":["024879c9c9a261b3141ecfa1c79c4efc25278c844ecd1dcfcb95d9c19581fbdd25","03fb4a5fdb91239df3ccf7f61a5b99e7e72483101e21c9d1ee0d85544e9354c6c7"],"m/2147483647/1/9":["035928a107ec01f78cd586914d5a49710fd42e352b1312e3ad0eeb2c9666fdf8e7","03a54c03093797854829c75357f092356352a109042bbb83bdac20cb4e5eca27ea"],"m/2147483647/1/10":["021e7a3a7efe888c5e820b5cf0f03317b2b4bf438d8563449aeb7a77cade97f136","03ec0960b3d1df52ca3cc2c82b7d97063400da4dd051bba2f9bab6cb44aee01efa"],"m/2147483647/1/11":["035d70c26b7f429861f555f7c0d99947411b23b7f95303fb8d5de5b82a95aa30fc","038b922f7024f5446d6b48e5253643543b35c006d90fd37688105c6cefcd8adb8a"],"m/2147483647/1/12":["02158d6503891c6c65a606221dbf5c68d0832288975914007968419939588ecb24","0248264cb1763a3f4de9b34787b4bc5443ec92ef915927494bb9f1c1c0b498c7ca"],"m/2147483647/1/13":["0349965eea38a25ae0c061faeac4c4e57e648bc4c0f059d07b3b8b7962cbc0dde5","0352243d9269565ce2a1ffdd0b8e43a442c6dd1c9edda86eaaf2cba5a4a95c40f1"],"m/2147483647/1/14":["030fa6e3d0c5cedc0581955395c77cbe134c912a47971023b9695332df3f7bb200","03f2cf09e33326fb59bf3f13e6298d2d5d29c9eae3b872e5a851e8d8d77259c883"],"m/2147483647/1/15":["02bf0d45e41339f552df6f8baf4392142921fd38b0f2a4388a905ff6cbacbc278a","03fabe46bb6706a1b8edfd28c046a8891b4530bbe5305080b72b0d08ebdf7b8c0a"],"m/2147483647/1/16":["03a4e3146ed34d6a8af4e4379e6edcff32cb0373ba232b3d746af3052f674133ac","030311b73c6f5c46ddffc0cfce6e5ed0b671d94267d8e52cd8837f2a479916eb91"],"m/2147483647/1/17":["03233df93c762d2f06c7f5f388e4e0a8dbdb13302acba0d2d6995c487d8aec9f2f","024badfdcb7e772ac7fc1c46d3943b07500edbbece105cdeff3eb9e9fcc9f54782"],"m/2147483647/1/18":["0364035475a098e00eb010c500cad3c90af3e81a4bd613144bc9433a150f14718b","028223dc8142154e7477ce000b3dc13e1d15a901553d9b18864c8645b582b38fe6"],"m/2147483647/1/19":["03971b74b4ac4bdaadf636baa4caa82fe5355471ed6ea05a9cbe5fc6c9e4b9db76","0202ebffacd01f83849e5bc5c0e2c317bc5fb2fbcb2d6d4482a5235f9f1308b61a"],"m/0/1/4":["03005ee9ff028c98fd132e531023f2f2b61ff0d26022f979dd98088d2ba167b031","0345ea82e8dfe38277f0c3aee18d2dd93edb63e8663ac83328a7934d2ca57006f6"],"m/0/1/5":["0391bc4990b71d8a3f156ae7107929ed6372b0b4ba8a868253f71ba7189d1efa02","0312a74cf2e7c0dd41897d04fabfd8cc3187b84a28305cfc79315b24e6fe23a6b4"],"m/0/1/6":["021a38c492607ff9684a4fec445e47b5b7100d3ef9e9dc0d0b37c0a646d28d4f77","03ae0b46ab36f97447ebaa53f2b5c8f090f15395378785f2fd285eeba17fbf3f65"],"m/0/1/7":["0308cdec88c1ffe16edc98853d9c08dbd4ba2541ba566668ca17bda19d7eb3481f","02dd622267c2e68287287b8b61724f76fbe84096a56aa5054af92f8fe25380e2d1"],"m/0/1/8":["039647da9ad725836bcb28a3e0497659a28d7749d1416c421a0a01c62d237ee962","022e22aa61eafda0dd8820427f1a06314d352a15ea8645e7ab9b80920017084d82"],"m/0/1/9":["03a4ade946076c6962b70c70ac7fad3a87efb59a1d0a4e32bda13a6d47fe9df961","029a07235aba04ab69526e117d836d5b3fae5cfc8c5e72b10c6d1afd261ccc19f3"],"m/0/1/10":["03c78e9b6493b22790db1acea20df9444e0f9c424fc5756e7a32c290ae01783953","0254c130ee467a96570c9f5ebea89de04f0b1db1686b164f2694339bef8f25dd88"],"m/0/1/11":["03a762c43318ef8d4840fab04c8db73797dc648825fac60f2730b4c76678df1cf3","0212c684a4de8e750ad2dfe2b136370ab9803eca178ed9a27b3990c29b067de35c"],"m/0/1/12":["02702d221f9b15c5cf75ac2f497a6c63e60213087c3d2d3be46768e3ebd238e26e","03ed58580744deb357258e44548212038670769d8d51e385d4fb8414311fd01b52"],"m/0/1/13":["0320e0597b54c62768352f433389cee4725d6094d7bcb5c72265edcc0933829aff","02c5706f11b9a85f3176c572842b7c9812c2195058d24d945bc026b00312740e76"],"m/0/1/14":["02fe43077676b844226d3aaa62e8a86d237710d92f882366944acbde0c8992fcaf","039a6a8662abb8910741cf331320549665e9feb28ca94d1ab6a43c84fa330b94ee"],"m/0/1/15":["0369f99f72847af93d50ab8ee75b6e7e912d26e27be96f6d6b7215cf7daeff7ba5","02521700cc07c953ba5aa586fb0e4795a34dffc68c5fb43e038be3866e40f4daed"],"m/0/1/16":["02f67d1d89bd8fe2f91c5b973cbdacfb4ba440e7656bce284cf73d549625607347","035da9cfac5a803dcb2b283b02a2515a4a1bcbf3d19e0d180aee8fc30193bc0555"],"m/0/1/17":["02c024ec199d240e8d6c66276b94b91071f7cdf2bef540c29d6d18d25de7b1cf7c","02190865f9dafae3f7f05c093463be5632946422ddda0a6fef6904390792516067"],"m/0/1/18":["035ed504d7704ad984a333b8eb0fceb8be043da9284de31ed84d9e68d90c75507d","033303c415b50421732402df00f4baa219f334647a7eb5014b9f8079864d6ab558"],"m/0/1/19":["02ce49fe86b0eee73663b1ee867b16b97c876af26f12764c528a2e6d0eb55ad3d7","03ab969bc81796b88e44c340d854df955fc60ea17ea92db5d3115595d6dec890d8"],"m/0/1/20":["03e2fa915378cbdffa0d919b0fb50c7256ca731b9d571b3365e486893a1d43079c","038d058b895cf084dccfcc9367e4796a5cf4ddceed6c35f6885d75c80119613350"],"m/0/1/21":["02fcb1bf644446b5b42205272af72f0aeab9e92ca29aafa91c5fb69142764017aa","035c5fe5c8811603279a5b72b6c30735d702817db1eab937c622269e28192ffa90"],"m/0/1/22":["03b39d61dc9a504b13ae480049c140dcffa23a6cc9c09d12d6d1f332fee5e18ca5","022929f515c5cf967474322468c3bd945bb6f281225b2c884b465680ef3052c07e"],"m/0/1/23":["03f40b82fe8cacff08879f13c45f443a3dc3ea98e1d75d5f32a19f5e5a8f7a905b","028415ee458e4dcfd440ce969726f3b58ae74fb6cf3995ced099579211e7419844"],"m/1/1/5":["032748a6282e21f571b8c8dd49e775deb83c90fcf88dc4ba81d878536973709c3f","020837cd68f14ce571b335eecd1b6fa0af43e1576dd9721aaca2a8ab639ac6b7cd"],"m/1/1/6":["0337032efb013dc92bb8dccfbdda9f5c28f0039a9c60953d41003d095e9f9778af","03ceed2da6b9603297061dc8eb930112ba726b2ccf5eec67f4866a05ca4049a22b"],"m/1/1/7":["0383c96ac2af7d203f69133b2fab6b68366b5075ad6957fa06759df3b20fbfec70","0311385f79834cedaf2230a48c0f9dc8e794da1869fc595db2518d62debb85579a"],"m/1/1/8":["03efc649680280f4e4df96da923bc88330275004125ebe5483c2f3e05ca52e19a4","02803c02d197d780388259afbd001ae41fa3eb3e2bac9627aff540521c184c3b23"],"m/1/1/9":["03af2fe6aa027a76b42c1c4050a040bfd026ad2daec1bb96a5fe2d026a7df919de","02ce14163047c640228796fb1f72bbe3afb05819ad141598a4f021058a6f79dd3b"],"m/1/1/10":["033770378bd762cf0408e44e4e604bef77e336170428c506949b1a4f1f2963e574","02c58ed43946f699dbd3e36d3e9aab2714cadeb19ecd3a56e4328c50336b4a76cb"],"m/1/1/11":["02898a1545fa19bdca92adc498698d27b86529cd4c08946d9d29604734b86f31af","02b402767a045ede072600924401c0d720000b2ed59fa444bfdbef4a5f1cead745"],"m/1/1/12":["039b8659430be49913e2cd869aa8c99ccf49a13df35837370b792033dadb891483","03264e63df292257cc76babb15d15bef620d1c2f8c3bbc78d6ea02d127e5ee7386"],"m/1/1/13":["02381a559791b8e86bf546e2c718ae63cf24eed0518a58e4d4a4b310adf2cd38fa","02d7f8283a4418d912508901b4a3db0d2103206dfdd74b3c75648671e20ecfd445"],"m/1/1/14":["020376e8c550b7d9faa0b2da947a2a36fab22c6e8190b6f99460b6022017bb97d7","03fbc5299190e6628de28c92aaa12e3a131b21eb7266462c46fbedeb86fa878055"],"m/1/1/15":["027209fd3b0cf7368180a5dbb16b928c997d33fccb78505d48440c7d23eadf5460","03450bfb22858726cd7e228e6733f69457546978a95188565c53e0d1c0d6070ea8"],"m/1/1/16":["03cb355ba04f64293793855121bab5831f84a3a3edf7cd31fccaa6d67c407a4912","028bc897a39c1224610b765a80f4cd8ab79cb37776f58fec9c10ac6f649d1f3c72"],"m/1/1/17":["03f4cb0564d7e2c6b85673503b7954db22779f29a8f3374904573984e318a96bf1","037c11b6ee906d84aa7eed359d758d986d912b6f8e5cbb1acf0982a77b3ef812c4"],"m/1/1/18":["02d2e5798f33f6889472857744316f2d253f25f88379610063f40cfe5798d9858f","0253cefdfe9ca987cbf1c950b6246d5b7a194d8dfad47c3a78dbbc5c1d01511d97"],"m/1/1/19":["0336c325f5aed366ffc10d553f2bfd4d69e66cbe1688d77af14efc8827aea2e318","0378b1b9a6074f9f2ab4fa9ad1e14649c621b0c8124a1b148914d3c10e6ab390c6"],"m/1/1/20":["03ea55740a734689ce778a8c00df8ebf4274c8f66de7d05646fe5c927773ff7f2e","02275b558d49aef955b6dee51a3c0a53f4b076b97bb3f26abcc82540168ec87cac"],"m/1/1/21":["03c77869c9984664eac9c238f4b6d806c9f48ca8a736c48450f398834db2aa915c","02d984f548c7f60c09dad3287cfc48807bc8157123989636c713be61be6a2e9ced"],"m/1/1/22":["03ed7c6a3c854c1f9459891691cc32671402f9e47126919878251e568dbdf353f8","02a113dab22cd9e46967b3fd76b9b9ec1d227d88817a9300e42d332cca2a0877fd"],"m/1/1/23":["02ee186432dcf69fda50a6fdbd94651817d8a271c273a5b70cab3ec4ae77a3753b","02291370aad9de0dac676355ced64e268b0c431a51f42f12d13f5144940fce4285"],"m/1/1/24":["02bf71435e84e66547c8c583d5ba226a5ac4d935e0a9f9603ecd8925c3e847e91a","03578d8657d285a89d9d597632db662cfef9baccfb55c76b1e87948a94fc9de30d"],"m/2147483647/0/0":["02a8425bbe23426219065969f695a6c3e242b24e57226bffdd542be8fd6be968c9","03057a42fdb6569fb1615b173ccb702453db2eac5be4291b82d4511461eafbed87"],"m/2147483647/0/1":["0250c3d3e86e332010c5233c2ec3bc728026002f0037cb3382d6318409b0e70796","02cfac1e7c4c88191201080f8316af52d9faa6ba624a6e160279e9fac4d1cf79a9"],"m/2147483647/0/2":["02a8c266a5b92eb50c8be91f95e4d1ad968b2f57d527377fd642d63fb84474f61a","028cc954ab31bd179ff80b8a05f95430ae534e61b3ff35f5284fa2fbe1832ceccb"],"m/2147483647/0/3":["02f719e1a7ab00ea98611453fb03d44c1da04655bed74af392534d70099039b4c2","03bfa548bfd4718c50bfce173f780eadcfb679d9c0206c91a2fa1879a9cf7558b2"],"m/2147483647/0/4":["0362c0695d397ca26bf47f0e641bb3cfb06ff29ccac2e1d56ded3afcf88b1e688d","02f9d87b05bdb3b9e82f506b43f813041c0e403274adc23d11e5e1651e34b606c2"],"m/2147483647/0/5":["033731323032d4ee08e858fc71f93970444333e183a1d5052e1d08cfb511e262c8","023e12556cef67ade35b7758916b5e1a3ebe074ccd35c5d8eff6b01321f63eb495"],"m/2147483647/0/6":["025d11b90081972bc1c258c9d6f476dfc2f95b69f0e9935322bf9c21deb580ff64","02b065f56a378907354f0738a0ed74f10660c6b5dd68c9f992093b75ce3d7d8b72"],"m/2147483647/0/7":["0210e721e8a35db9d8c855a0d346f60c09208f3be80b39e03af2c29db777332c71","0277f352969fadb1f1835f9a0fa99c6a3c7b6c281be5b2794c88a708eb177ea33d"],"m/2147483647/0/8":["02998d8d41e4215cd2a961a415a3ed0b1f984f1627719a7b102a75864943c4d87b","03d8ed7fc8f68a77f68d3afd007b7aa4c89944195143630ce183f0fa5438f2b559"],"m/2147483647/0/9":["0324fa91737588e4f85937303ce65c3b91b5f2ae506a72d92b83e3f5f9aeeb3c6f","02a011be72c4a400319212228106af278823a97acfe0a67e1ecd866d446b315114"],"m/2147483647/0/10":["025886ba287922a904881c7315e6fcc410a7976741771a5937d3a1a01b529f21fd","0243bb91ceed9d29d0c2ca66a8ab77e82110bbcc023beb4106f787964f44a0b972"],"m/2147483647/0/11":["0369d21684894cc2d4b2f5e581ede3cac9e8db4161a08e7737c1be129bb673d3d5","03c9ef27e3cd3dadc078fdfd9936a7ad9bf7954747085cf8f8a2a5bb3431f68a9f"],"m/2147483647/0/12":["03a73b8fd859bf6acebffdfffa2597199091daedd2c011ac67fc3494d8a1a8ceb6","025a213f7771c8be03f43f2e7f469ad4ef2cf6907ea284b227a786d1f55dfa7144"],"m/2147483647/0/13":["03a09f7ca257e1ab263cd5e6b0addc3ff868b93df132321d98775ca3505efb576f","03454c715739164bc55f347a651439cdf3ec146b35d2927beb60e8290b3916e082"],"m/2147483647/0/14":["03a64b1f7bd94a6b1a6e84ea444e0ba04e9deb86460934ccc37c0615a134a8257b","02794f09210b1811a455f3e1c7bcd35c76dff2523190fef9615eb27e2376acac1c"],"m/2147483647/0/15":["0392dca2fd9a3bc2b2a7d90a848719069fbc5f22bff7327bb8186c032514085263","032ee8a33ea76d70c7ae839448ca6c5b1af89146f2922e23ba1822df42dbc7e66a"],"m/2147483647/0/16":["031a22a1a3c1abad7c4d782ef6ba3cc00f2e8fe549eb33e0732200aff6d3174831","03bdce9781289e0c31cf727f4c93fe46f7930dd8fd68f818ce241f1ede268e8e0e"],"m/2147483647/0/17":["03b12d27e9aea2c2ad598e54e40860a705ac2ca2427aa511b501b38ec368ea5c7d","03e60d35d84d4536cad895215256b312bb4879a8d417251c279995e58f25da3d54"],"m/2147483647/0/18":["0380266cc9a9673676ad6a1b2e7148766df9c25b4dce299e5edc4f65b72aa58e64","0329e2a8a48c06c0c45dfdd2ab33e6455551557d8ebaf8c12fdf7470f8c45f1d28"],"m/2147483647/0/19":["036fe62af85560d7eea7c7af55e60b32a97dca80134d0aedffb19eb2705b9d6e01","02381c2c30b9f81e2a53c69028fbe11803acad0420b267719b7a80870be0baaeb7"],"m/0/0/2":["027bf94b8fc4e9b42683af25fda125ccab8760040717d100270dd4afd032692daf","026382c6c9357250d96dc21e43c053857a64efeac1887fdcbc107fbe3ecfc6115a"],"m/0/0/3":["03fd203acbd9af3cbbfb709458f8952078234a36094f12d00372e4b2b14cfdf419","03f2e5db59aea5dc89f53ac2a9f4ef66d41265c45afc5d763e0ca61ab70c7c61ec"],"m/0/0/4":["02a1d7cf4fcdbbf4de4002b844c3bff1639073f1cd6e5c4a4e02596b45d3f518c2","03b5fba813294e6ae096ea158833453caa5a945609b0a554696091b9b152bb0f7d"],"m/0/0/5":["0261d37e3b56ef4e106c59753037f516a4b1c45e056b2a3e00f8b77f15aaa7f8a5","0256a55e66e0de1603f0d600c0eb5f5486cf3512a776a36f3ab0d1941fc0dc9b09"],"m/0/0/6":["031db2826af215fe6cbe3f6e121b0497840fc49be133cff0a4d4eab679d6b99d70","021dd722c3f35dd04fcdb57f09b76c723d521fb36751de03ffd08096ddf1dc1f86"],"m/0/0/7":["0354ea75bdd9eb5beae7262e4a5eeb58bd10103ee0185e85b749ea39f6615d0f62","03f2c8f3b6478c0501a8578d5caf5ac2974f8213fc5e699d62dd2af58fbe8781d4"],"m/0/0/8":["0282e67df3bcd1e1662469b4c3151fb50ee1e46b75d787d91184c16b9803131f82","02921a7054af1e425f4137a5eb6b34d1f2b9d81c2625230194bc30657bb4277e11"],"m/0/0/9":["033e7e387933983ceab37c8388bd8ebc5119760f493ffe6f083bef0e5dfe22891d","02d660d60cc55d80912e0745cb142a8596a4604fbf72f9aadec0599aa2ed62461a"],"m/0/0/10":["022ce5b2750ae34512199856eab9e912dc25281cd8b88e7688a46c3b9a389701cb","02f14aa1608fce3b6088148709eb5fe72b61699c931fa8d95a45fab1106859d1b0"],"m/0/0/11":["0288dbef3302c1bc5556028adb33e2f9e03c119dbad4f706befb8ce86cea459f2b","03f13ced465e2e0a3aaa8895f3185d5711e0bebdaf507610b7a669ac8fc82da8fe"],"m/0/0/12":["031ab4677885340d2f927ccc9747f4346b79e4eb6c750695095a8a2524610fa94a","038c881910fbd8b50d193db4e0c84f5b7840820397f92cf0718a8e06d027125503"],"m/0/0/13":["031b568452cba22eb7a88c6085489e53e35abd16068882e71a140e47e12dee9c61","020d09885ee362101d12d34ce0918d41593634db1b9413e5415c6755753b9330e8"],"m/0/0/14":["024177bc9aa03cfc72eda2dfddffd7fe9d0c2f007fc3ba1a48280feae2b9fb117a","03394ad321668440c08da76eb35475ba3a8c0e8cbe0ed81468673a8c72d38fe457"],"m/0/0/15":["02037b1cc696ffbe9eba3684edd53653386ef6cd7728401c40120037593a4c2ae2","020ab8d6900ec9c11ca5d96dfc0ce7cf0ee71653a7c45118e89abb4b113147e53a"],"m/0/0/16":["023bcbb8d4726a546087cdb83740adf0ace879b7195a572c652fa8ce4dbe195a04","0392721b230d5163d28b27fc7e059b875711f12b3da448eabe7229bde57530e637"],"m/0/0/17":["02498ee74e849d3e9261dd1863038caf83d6a3bc2eeebecf17055d4bab44dee77f","03d4dc104b2e0981693e8097437de9b05334a85e2c8edb02783897859bdbc93e32"],"m/0/0/18":["0218a9f524fe54abf8c3afd21314296cfd93eaa9227acbd457e6c9a742dc233cf4","03760f3d0c5db969bda698ff9352e3b7c332216c34825f4c6e857e39c9aee7cd35"],"m/0/0/19":["033dd51f7737f0e9db79f5c38e4298bf3396346904ef3933d290a22e5b77048d9e","0221b2eedccb9a37515263071550069b3b349a166f0f131d0028e8600d9a2251b9"],"m/0/0/20":["02cb6c39161f3244d7769f7ab96346cae2cf21cb6f4538f5e7382d363dc2f836c7","034f7bda4d1e9ed6a3774608a4d6cd8582ab59fe3187f8a7a7cf914d89426ebe28"],"m/0/0/21":["035490549d65f1360f10340037250b171470ff4c86966318a2b1eead6d8b969aea","03f6a04f6fcd07a4f32c82d53710ed30e0f54d43d41c67c661d158b3d0830c3ea2"],"m/1/0/2":["02972eae7e4302e319c266578e14a07839c1e788296a92906e6d66d938211dad5f","039ed6b488f1571ad6527acd6b6c5b8453eacf6665dc5cb7852e33d1c8ea73f9fe"],"m/1/0/3":["02bec4728888c2c045108353994bae5731ec7a7b41459023b0023e10b8d616bd30","03ce1efe16214c9eac595382e46a68143dd11a335b3f7c971ddd719ac544a5fc4b"],"m/1/0/4":["030e2df1d341568225d8dfbe5d07e98dae9f90e0f43e19dcc68c998a6ed7bcc1f0","0380f4c07dc84faf42d51779f104aa6e3b5c3ce2d7684b3cb76d49faeefc2b69d6"],"m/1/0/5":["029a54ddaa25f433b493f4b72df8c1d41be2c4d2963b8b61ee63cc86d16c12d066","021567c95e0317442e7367aa4e3378dd46c5bcef5860f789272fea83b917de0669"],"m/1/0/6":["03590320d80b61cc0874b579f467c9b5ccc50d9ef875bcf6bdd12e2d0c211e8973","03ee4677b6ee89a9d355851f2230506c6897ff219062c0df4ad9a85c60f3535f93"],"m/1/0/7":["03caf98ab1c9b79d1dc8029453a6137c08787b04043b79af3cb42d41d2d3f1338f","023f39ae4e2f4f3887d5fc58e0d3a0d7ee267dc04aa257c75b6b2d67d2f5580f81"],"m/1/0/8":["0352a2a3ea8209c9a2b633d788796ac2d16c08022440e04a77ab2835c7f971d266","0291bc248b3da997f35e8fae98a75a91fdac2819d74c4e270899338d48f7389e87"],"m/1/0/9":["02468d32d9c3c62418d506d4cd0da6cd2022d5bcafdb5f847cf7bde7a48ec6848b","032713d90d12eb6a072f3c1db6c0d3b680d3f78883016135fc0f78e8193d41d4b4"],"m/1/0/10":["034863cc6bab9b059be53413ba75c5fc286647c20d7f9e5512ef4754ea301dd1ce","03a33ab9c32a2264ee2464ebbb5892f0e34acf0fdede4f87395a89e9dacdd4930e"],"m/1/0/11":["031e19296695bfe8a96ba3bf58afa805ee1bd5471fddb3929b1678d69d442d69c9","0270feb33956fd9e937019d629523e26437493c0856514011e6aec88baf7721295"],"m/1/0/12":["03cce695d3c3843bf73e851b2446a77d7e235e5b80b4f4474f9946292eb8218742","039ea96c8822f0ec7ed28308d277f3e730480d7573579cd11b89aef4364cd9ffeb"],"m/1/0/13":["02ab4ac38eb405e822d12c0f0f354f04f9ee1d991dde887a5c1171096fe503158f","036809e60cae1203da8884ea1f85d4669ce6e053f8ba605d775e271b70ab4f6787"],"m/1/0/14":["039d61da23a8610fa0ee58eb37d7cea7ea9396c79153da97280ccf5e46718e3bac","03015c27bcc778682781fd6ad30aa6041db0b7e24270818cdceece0043ccc34b26"],"m/1/0/15":["03c088ed669132835d2728b0ecf294271c8388988c6ae264d43ca24f50e4005f81","03e2c118c9445a2ddc4c8afeb0ba49e21be3f818a483d346418b8922b8a371a2b7"],"m/1/0/16":["02bba7df9847f463c6b23eca37a4bd6efa3801a52b8ddfad804d902e783b70c81c","03764b657f23996e31c64a701facc1cbeb0c9edfdd605e2c1ed36cf48197565d45"],"m/1/0/17":["020445179c522295b89bf4bfd582eb03422e3fa20dcd29263925e9f44282d476d8","036e47bdd32f3061aed1c1f8c2a32b038c7b72391cb1f80ebfc150e58f88372766"],"m/1/0/18":["024d88c4bfcbba713d49e1edcd035234aaa1ee76ad7bcf75bf074a16658a6b0b6d","02b861e7a20d89f6875d2e44c78dbadb99503e282e5e60e9f65657af6fea81d425"],"m/1/0/19":["023a8ca9d5300181f157e1930d3b0800eebe7683d8df72e6cbf28834dbf1be5d60","026053c4f84c10d15890c0b254522972931bc2d5b7cdf9c1f9f3137c22edf3ecd3"],"m/1/0/20":["03137c66e9f3d61aba659f408d77a293fa0f3fea4ccb911074a681d6f61a55d023","0291aa1bbfbef59b16b0e37e185a706c589d448cb02e860c5df9c9d7242ecc739f"],"m/1/0/21":["03c08673e0cae55318bc9dcc4b5f11eb3ff71d42de04015e255dde3fd8cba7e09e","02423d4eab06cd5b26e71d145283523c011d58032700c517f00b328d2c90cf109f"]}},"txProposals":{"txps":[{"creator":"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5","createdTs":1405543144016,"seenBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543144016,"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543144645},"signedBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543144016},"rejectedBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543170040},"sentTs":null,"sentTxid":null,"inputChainPaths":["m/45\'/0/0/0"],"comment":"blablabla","builderObj":{"valueInSat":"29000000","valueOutSat":"8900000","feeSat":"10000","remainderSat":"20090000","hashToScriptMap":{"2NBtv6DdXj8HBunyGqpW9H8bUtW5x3rfVTj":"5221028a4b63f26253f3a8731577b8e1ee480950ad5833ebbf106fe3463bfc07cc3b90210332efa054c08cb77506a35ee0762cb7156f244566703ec08e433568ec0397bec852ae"},"selectedUtxos":[{"address":"2NBtv6DdXj8HBunyGqpW9H8bUtW5x3rfVTj","txid":"a9f4dda3f092e37244bc4e77ea921fed01d5b8ea49613dfdc0dc8afdd70190b5","vout":1,"ts":1405543855,"scriptPubKey":"a914cc93216398b77b5f8c451ca3a357bef961678be987","amount":0.29,"confirmations":0,"confirmationsFromCache":false}],"inputsSigned":0,"signaturesAdded":1,"signhash":1,"spendUnconfirmed":true,"tx":"0100000001b59001d7fd8adcc0fd3d6149eab8d501ed1f92ea774ebc4472e392f0a3ddf4a9010000009300493046022100ccbb8f398f74a76236629b8499ffc6f9518a2091f5a61a9a352c0a10f615961e022100b8f0769c76cf33bec3d7f81d9da2b74cf6e8a5e0a24ee5f48172854d8bcdbfa101475221028a4b63f26253f3a8731577b8e1ee480950ad5833ebbf106fe3463bfc07cc3b90210332efa054c08cb77506a35ee0762cb7156f244566703ec08e433568ec0397bec852aeffffffff02a0cd8700000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288ac908c32010000000017a914560c292066792531164149c5ed63ad2793a61b928700000000"}},{"creator":"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5","createdTs":1405543188745,"seenBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543188745,"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543189341},"signedBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543188745,"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543206819},"rejectedBy":{},"sentTs":1405543207304,"sentTxid":"169bc92693dd2e27724eeba81e54210e842035bd3af6c52e6a6a5e908f1a4f66","inputChainPaths":["m/45\'/0/0/0"],"comment":"que parece","builderObj":{"valueInSat":"29000000","valueOutSat":"9000000","feeSat":"10000","remainderSat":"19990000","hashToScriptMap":{"2NBtv6DdXj8HBunyGqpW9H8bUtW5x3rfVTj":"5221028a4b63f26253f3a8731577b8e1ee480950ad5833ebbf106fe3463bfc07cc3b90210332efa054c08cb77506a35ee0762cb7156f244566703ec08e433568ec0397bec852ae"},"selectedUtxos":[{"address":"2NBtv6DdXj8HBunyGqpW9H8bUtW5x3rfVTj","txid":"a9f4dda3f092e37244bc4e77ea921fed01d5b8ea49613dfdc0dc8afdd70190b5","vout":1,"ts":1405543855,"scriptPubKey":"a914cc93216398b77b5f8c451ca3a357bef961678be987","amount":0.29,"confirmations":1,"confirmationsFromCache":false}],"inputsSigned":1,"signaturesAdded":2,"signhash":1,"spendUnconfirmed":true,"tx":"0100000001b59001d7fd8adcc0fd3d6149eab8d501ed1f92ea774ebc4472e392f0a3ddf4a901000000da00483045022035423cc74824ba904907678dda3b62a20a787b96d1b3e9f3e9546f9c57f4e45902210080a1ff1c39f458ac1642b9e948bd62fd70563b5252e749cc8fc642cd763ee830014730440220524a13f36cfb03caa246d7d84de634ec9386f2c39c19bfa926037f48da86262b022050e58a6503d105ad2805f86806810a1aa7f20d6271e1340b42fa91ab6a30f3e801475221028a4b63f26253f3a8731577b8e1ee480950ad5833ebbf106fe3463bfc07cc3b90210332efa054c08cb77506a35ee0762cb7156f244566703ec08e433568ec0397bec852aeffffffff0240548900000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288acf00531010000000017a9146130a9d51f996b7a1b9d3e10c80930834251909d8700000000"}},{"creator":"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba","createdTs":1405543505848,"seenBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543505848,"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543590221},"signedBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543505848,"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543590221},"rejectedBy":{},"sentTs":1405543610315,"sentTxid":"6fe851b54b777a75fe80fa204dc674395e2af69efb1f7c0017e909eb82c3d914","inputChainPaths":["m/45\'/0/1/1"],"comment":"mandaaaaaaa","builderObj":{"valueInSat":"19990000","valueOutSat":"19980000","feeSat":"10000","remainderSat":"0","hashToScriptMap":{"2N277q5r8Ab6XLJNCjXXFdh5itDJRQCv9ts":"5221020389327ee8ae7d0ee3f8187842d23a4070bdd8a27c0bcddd05d80ef39009253d21025c9b49bdf17d97bd82ea1b87793082f857247f0f9b999937a166ec994bb1b41f52ae"},"selectedUtxos":[{"address":"2N277q5r8Ab6XLJNCjXXFdh5itDJRQCv9ts","txid":"169bc92693dd2e27724eeba81e54210e842035bd3af6c52e6a6a5e908f1a4f66","vout":1,"ts":1405543157,"scriptPubKey":"a9146130a9d51f996b7a1b9d3e10c80930834251909d87","amount":0.1999,"confirmationsFromCache":false}],"inputsSigned":1,"signaturesAdded":2,"signhash":1,"spendUnconfirmed":true,"tx":"0100000001664f1a8f905e6a6a2ec5f63abd3520840e21541ea8eb4e72272edd9326c99b1601000000db0048304502206b18b3dba2646c552469d8ef52d7656f6a65f563032530f622abdfd8bd4c5cee022100e804b406eddebbc827646141e74dc64c76a770ed4e35183ffd35d265ad9f7d3b01483045022100f6c013638ff0a316b1baa93dfffba6a98cf3033c133e8bd899e933c9c3e47ce10220530f40e7ea52ae58bec695edbec6d566d2ee8e7b5f33f95e33093ad1e29a125401475221020389327ee8ae7d0ee3f8187842d23a4070bdd8a27c0bcddd05d80ef39009253d21025c9b49bdf17d97bd82ea1b87793082f857247f0f9b999937a166ec994bb1b41f52aeffffffff01e0de3001000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288ac00000000"}},{"creator":"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba","createdTs":1405543781381,"seenBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543781381,"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543782017},"signedBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543781381},"rejectedBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543794590},"sentTs":null,"sentTxid":null,"inputChainPaths":["m/45\'/0/0/1"],"comment":"1","builderObj":{"valueInSat":"29000000","valueOutSat":"1000000","feeSat":"10000","remainderSat":"27990000","hashToScriptMap":{"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb":"52210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352ae"},"selectedUtxos":[{"address":"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb","txid":"6c9da5b0da4bab0d576033325e987b10ccf2b9bf479d306b6aae36efeaa56892","vout":0,"ts":1405543698,"scriptPubKey":"a9147d274ac50968d7823b6cbc1b38770deb7157995387","amount":0.29,"confirmationsFromCache":false}],"inputsSigned":0,"signaturesAdded":1,"signhash":1,"spendUnconfirmed":true,"tx":"01000000019268a5eaef36ae6a6b309d47bfb9f2cc107b985e323360570dab4bdab0a59d6c000000009200483045022064d877bc5171fbaef909c2a1a924e0023b3ccc0b530cb46653f06ecb230283e8022100bc6658d60ad4f7120d9226c8f6eada87f3b0388f73c458011988bab36e78ba15014752210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352aeffffffff0240420f00000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288acf017ab010000000017a91421c4a435d9ac263ec55b35a1a5ca95e979639b9b8700000000"}},{"creator":"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5","createdTs":1405543835343,"seenBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543835343,"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543835968},"signedBy":{"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543835343},"rejectedBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543850998},"sentTs":null,"sentTxid":null,"inputChainPaths":["m/45\'/0/0/1"],"comment":"2","builderObj":{"valueInSat":"29000000","valueOutSat":"1000000","feeSat":"10000","remainderSat":"27990000","hashToScriptMap":{"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb":"52210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352ae"},"selectedUtxos":[{"address":"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb","txid":"6c9da5b0da4bab0d576033325e987b10ccf2b9bf479d306b6aae36efeaa56892","vout":0,"ts":1405543698,"scriptPubKey":"a9147d274ac50968d7823b6cbc1b38770deb7157995387","amount":0.29,"confirmationsFromCache":false}],"inputsSigned":0,"signaturesAdded":1,"signhash":1,"spendUnconfirmed":true,"tx":"01000000019268a5eaef36ae6a6b309d47bfb9f2cc107b985e323360570dab4bdab0a59d6c0000000092004830450220302baae7de2e0f102bf3af2d5f450f673e51bd143020141a769ccdcdf16af188022100e7abc087c76050ed649e7139a5a136969e74e24a8d8f6223d3219ad033a26451014752210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352aeffffffff0240420f00000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288acf017ab010000000017a9148b102abba0729fb0690c61cf7187064d692d43d78700000000"}},{"creator":"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba","createdTs":1405543869803,"seenBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543869803,"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543870411},"signedBy":{"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba":1405543869803,"02b0c868a3889cd0cfc0e7fef9eaa6d85d7cf6f7573ae5c9d1d13645d22e2eb7e5":1405543890406},"rejectedBy":{},"sentTs":1405543890913,"sentTxid":"6a0f61574ad65e537e7e99298968db565f97b894b61f4c8f8fac8fcaedb83e2b","inputChainPaths":["m/45\'/0/0/1"],"comment":"3","builderObj":{"valueInSat":"29000000","valueOutSat":"1100000","feeSat":"10000","remainderSat":"27890000","hashToScriptMap":{"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb":"52210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352ae"},"selectedUtxos":[{"address":"2N4eyXKikdnnUT4S74MRNAYqXChhUYmZ1Sb","txid":"6c9da5b0da4bab0d576033325e987b10ccf2b9bf479d306b6aae36efeaa56892","vout":0,"ts":1405543698,"scriptPubKey":"a9147d274ac50968d7823b6cbc1b38770deb7157995387","amount":0.29,"confirmationsFromCache":false}],"inputsSigned":1,"signaturesAdded":2,"signhash":1,"spendUnconfirmed":true,"tx":"01000000019268a5eaef36ae6a6b309d47bfb9f2cc107b985e323360570dab4bdab0a59d6c00000000db00483045022100a8ce7907f9fd7dd41dd65c2dec425e008efea06ee7c80787c10c0e210fbf181302207712c0fdd1cb25836ac1fc2fd303c1e26b85e8980417719b9ed50e977a9693ec01483045022100d1780c4f028cd898920aca3eaceba352ed9306cd17f019ae2f634e8facad149a02203c84ab2093da8e22577e93f27a732f0728d4e6db0c749f3cd3d898d6a025152a014752210359c6d0d0d31f83301169901a6ffad9535f14014b5ab3b43561dbb2436a7b813821037d06f713f13a11967fd5edca265ff4c77528693a712c482256505693e4890d9352aeffffffff02e0c81000000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288ac5091a9010000000017a914cc1cab78458b1a951b91c6dcd7eeeeb682f506388700000000"}}],"walletId":"55d4bd062d32f90a","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPdWUAmaaopPftevC72Jtiu19V8ee5XijL9JvogqfR95uVrL85f8yBdQMq3KyQtG3Q91yWQb3XDbWWpcdWFDAmJ7Xy2XWkGJu","networkName":"testnet","privateKeyCache":{"m/45\'/0/0/0":"b6fd8d1a079efd523da34f31ba81f544fc3d0a728a8a98299d8980682518e79c","m/45\'/0/1/1":"0f4d52d2a99e4c8c1c2edf09fef12407c3abd2304b961198c3f131a8c8443a13","m/45\'/0/0/1":"de5c191c343bd6017b98708c03344849624a14e2c167cfd6eb8dcb075d139293"}},"addressBook":{"msj42CCGruhRsFrGATiUuh25dtxYtnpbTx":{"hidden":false,"createdTs":1405543109222,"copayerId":"02c7b87033e4357d8afc6ab7fe31fff054772ea6251f0d9c8a835b1c1ac74f6fba","label":"faucet","signature":"3045022067576e5b37f2707a8dc66e57511ad9b10a3125bd95193fff6f8f6402969c3bf3022100adff9f417db07d88face13b3d13f422740d4421440cade1a205684dfdc5d733a"}}}'; From 7f17918ed93f0c51e4a65390e3e53464341d936e Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 15 Sep 2014 18:19:12 -0300 Subject: [PATCH 26/45] fix storage set --- js/models/Storage.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/models/Storage.js b/js/models/Storage.js index 3433589bf..103cb9a8d 100644 --- a/js/models/Storage.js +++ b/js/models/Storage.js @@ -155,7 +155,9 @@ Storage.prototype.getMany = function(walletId, keys, cb) { // set value for key Storage.prototype.set = function(walletId, k, v, cb) { - preconditions.checkArgument(walletId && k && !_.isUndefined(v) && cb); + preconditions.checkArgument(walletId && k && cb); + + if (_.isUndefined(v)) return cb(); this._write(this._key(walletId, k), v, cb); }; From 3e345fa60093b967dce5f011e33c7aec76221e69 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 17 Sep 2014 06:33:26 -0300 Subject: [PATCH 27/45] fix gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 8aa3d8515..640ac6f20 100644 --- a/.gitignore +++ b/.gitignore @@ -77,7 +77,6 @@ dist/windows dist/*.dmg dist/*.tar.gz dist/*.exe -<<<<<<< HEAD doc/ /node_modules From 5886af5420cac7f70d0d8d57a0904aa7f47bd176 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 17 Sep 2014 08:58:23 -0300 Subject: [PATCH 28/45] WIP karma tests --- test/test.Storage.js | 2 +- test/test.WalletFactory.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test.Storage.js b/test/test.Storage.js index 170235f13..5a3032030 100644 --- a/test/test.Storage.js +++ b/test/test.Storage.js @@ -25,7 +25,7 @@ describe('Storage model', function() { }); should.exist(s2); }); - it('should fail when encrypting without a password', function() { + it.only('should fail when encrypting without a password', function() { var s2 = new Storage({ storage: localMock, diff --git a/test/test.WalletFactory.js b/test/test.WalletFactory.js index 55f5239f6..517bf44bd 100644 --- a/test/test.WalletFactory.js +++ b/test/test.WalletFactory.js @@ -16,7 +16,7 @@ var mockLocalStorage = require('./mocks/FakeLocalStorage'); var mockSessionStorage = require('./mocks/FakeLocalStorage'); -var PERSISTED_PROPERTIES = require('../js/models/core/Wallet').PERSISTED_PROPERTIES; +var PERSISTED_PROPERTIES = (copay.Wallet || require('../js/models/core/Wallet')).PERSISTED_PROPERTIES; function assertObjectEqual(a, b) { PERSISTED_PROPERTIES.forEach(function(k) { From 8bc1eb15e4c9e20e0c7e296f3c22abe1437a1726 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 17 Sep 2014 09:42:23 -0300 Subject: [PATCH 29/45] burn in hell fake storage --- Gruntfile.js | 4 +- index.html | 3 - js/models/Storage.js | 1 + karma.conf.js | 2 + package.json | 13 ++- test/mocks/FakeStorage.js | 162 -------------------------------------- test/test.PayPro.js | 9 ++- test/test.Storage.js | 3 +- test/test.Wallet.js | 8 +- test/test.WalletLock.js | 11 ++- util/build.js | 3 - 11 files changed, 34 insertions(+), 185 deletions(-) delete mode 100644 test/mocks/FakeStorage.js diff --git a/Gruntfile.js b/Gruntfile.js index a63da775d..a043256b8 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -45,8 +45,6 @@ module.exports = function(grunt) { 'js/models/**/*.js', 'js/models/*.js', 'plugins/*.js', - 'copay.js', - 'utils/*.js' ], tasks: ['shell:dev'] }, @@ -181,7 +179,7 @@ module.exports = function(grunt) { }, jsdoc: { dist : { - src: ['js/models/core/*.js'], + src: ['js/models/core/*.js', 'js/models/*.js', 'plugins/*.js'], options: { destination: 'doc', configure: 'jsdoc.conf.json', diff --git a/index.html b/index.html index 40b22b4da..9a79d3090 100644 --- a/index.html +++ b/index.html @@ -22,9 +22,6 @@
-
- -

diff --git a/js/models/Storage.js b/js/models/Storage.js index 103cb9a8d..17a422bdb 100644 --- a/js/models/Storage.js +++ b/js/models/Storage.js @@ -27,6 +27,7 @@ function Storage(opts) { var pps = {}; Storage.prototype._getPassphrase = function() { + if (!pps[this.__uniqueid]) throw new Error('NOPASSPHRASE: No passphrase set'); diff --git a/karma.conf.js b/karma.conf.js index e9c89b577..052e215fb 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -60,6 +60,8 @@ module.exports = function(config) { 'test/mocks/FakeWallet.js', 'test/mocks/FakeBlockchainSocket.js', 'test/mocks/FakePayProServer.js', + 'test/mocks/FakeLocalStorage.js', + 'test/mocks/FakeStorage.js', 'test/mocha.conf.js', diff --git a/package.json b/package.json index 248cac974..7248c5c0f 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "dependencies": { "browser-request": "^0.3.2", "inherits": "^2.0.1", - "mocha": "^1.21.4", + "mocha": "^1.18.2", "mocha-lcov-reporter": "0.0.1", "optimist": "^0.6.1", "preconditions": "^1.0.7", @@ -27,14 +27,12 @@ "chrome": "source browser-extensions/chrome/build.sh", "setup-shell": "node shell/scripts/download-atom-shell.js", "start": "node server.js", - "coverage": "mochacoverage", - "test": "mocha --ui exports --reporter spec", + "coverage": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- --reporter spec test", + "test": "sh test/run.sh", "dist": "node shell/scripts/dist.js", "sign": "gpg -u 1112CFA1 --output browser-extensions/firefox/copay.xpi.sig --detach-sig browser-extensions/firefox/copay.xpi; gpg -u 1112CFA1 --output browser-extensions/chrome/copay-chrome-extension.zip.sig --detach-sig browser-extensions/chrome/copay-chrome-extension.zip", "verify": "gpg --verify browser-extensions/firefox/copay.xpi.sig browser-extensions/firefox/copay.xpi; gpg --verify browser-extensions/chrome/copay-chrome-extension.zip.sig browser-extensions/chrome/copay-chrome-extension.zip", - "postinstall": "./node_modules/.bin/grunt", - "monitor": "mocha --ui exports --reporter min --watch", - "debugtest": "mocha --debug-brk --ui exports --reporter spec" + "postinstall": "./node_modules/.bin/grunt" }, "keywords": [ "wallet", @@ -83,8 +81,7 @@ "shelljs": "0.3.0", "socket.io-client": "1.0.6", "travis-cov": "0.2.5", - "uglifyify": "1.2.3", - "mochawrapper": "" + "uglifyify": "1.2.3" }, "main": "app.js", "homepage": "https://github.com/bitpay/copay", diff --git a/test/mocks/FakeStorage.js b/test/mocks/FakeStorage.js deleted file mode 100644 index 7bb9de7b6..000000000 --- a/test/mocks/FakeStorage.js +++ /dev/null @@ -1,162 +0,0 @@ -var FakeStorage = function() { - this.reset(); -}; - - -FakeStorage.prototype.reset = function(password) { - this.storage = {}; -}; - -FakeStorage.prototype.setPassphrase = function(password) { - this.storage.passphrase = password; -}; - -FakeStorage.prototype.setGlobal = function(id, v, cb) { - this.storage[id] = typeof v === 'object' ? JSON.stringify(v) : v; - cb(); -}; - -FakeStorage.prototype.getGlobal = function(id, cb) { - return cb(this.storage[id]); -}; - -FakeStorage.prototype.getMany = function(wid, fields, cb) { - var self = this; - var ret = []; - for (var ii in fields) { - var k = fields[ii]; - ret[k] = this.storage[wid + '::' + k]; - } - - return cb(ret); -}; - - - -FakeStorage.prototype.setLastOpened = function(val, cb) { - this.storage['lastOpened'] = val; - return cb(); -}; - -FakeStorage.prototype.getLastOpened = function(cb) { - return cb(this.storage['lastOpened']); -}; - -FakeStorage.prototype.setLock = function(id) { - this.storage[id + '::lock'] = true; - return cb(); -} - -FakeStorage.prototype.getLock = function(id, cb) { - return cb(this.storage[id + '::lock']); -} - -FakeStorage.prototype.getSessionId = function(cb) { - this.sessionId = this.sessionId || 'aSessionId'; - return cb(this.sessionId); -}; - - -FakeStorage.prototype.removeLock = function(id, cb) { - delete this.storage[id + '::lock']; - cb(); -} - -FakeStorage.prototype.removeGlobal = function(id, cb) { - delete this.storage[id]; - cb(); -}; - - -FakeStorage.prototype.set = function(wid, id, payload, cb) { - this.storage[wid + '::' + id] = payload; - if (cb) return cb(); -}; - -FakeStorage.prototype.get = function(wid, id, cb) { - return cb(this.storage[wid + '::' + id]); -}; - -FakeStorage.prototype.clear = function(cb) { - delete this['storage']; - cb(); -}; - -FakeStorage.prototype.getWalletIds = function(cb) { - var walletIds = []; - var uniq = {}; - - for (var ii in this.storage) { - var split = ii.split('::'); - if (split.length == 2) { - var walletId = split[0]; - - if (!walletId || walletId === 'nameFor' || walletId === 'lock') - continue; - - if (typeof uniq[walletId] === 'undefined') { - walletIds.push(walletId); - uniq[walletId] = 1; - } - } - } - return cb(walletIds); -}; - -FakeStorage.prototype.deleteWallet = function(walletId, cb) { - var toDelete = {}; - toDelete['nameFor::' + walletId] = 1; - - for (var key in this.storage) { - var split = key.split('::'); - if (split.length == 2 && split[0] === walletId) { - toDelete[key] = 1; - } - } - var l = toDelete.length, - j = 0; - - if (!l) - return cb(new Error('WNOTFOUND: Wallet not found')); - - for (var i in toDelete) { - this.removeGlobal(i, cb); - if (++j == l) - return cb(err); - - } -}; - - -FakeStorage.prototype.getName = function(walletId, cb) { - this.getGlobal('nameFor::' + walletId, cb); -}; - - -FakeStorage.prototype.setName = function(walletId, name, cb) { - this.setGlobal('nameFor::' + walletId, name, cb); -}; - - -FakeStorage.prototype.getWallets = function(cb) { - var wallets = []; - var self= this; - this.getWalletIds(function(ids) { - for (var i in ids) { - wallets.push({ - id: ids[i], - name: self.storage['nameFor::' + ids[i]], - }); - } - return cb(wallets); - }); -}; - -FakeStorage.prototype.setFromObj = function(walletId, obj, cb) { - for (var k in obj) { - this.set(walletId, k, obj[k]); - } - this.setName(walletId, obj.opts.name, cb); -}; - -module.exports = FakeStorage; diff --git a/test/test.PayPro.js b/test/test.PayPro.js index 77872c23e..997b8e9cb 100644 --- a/test/test.PayPro.js +++ b/test/test.PayPro.js @@ -11,7 +11,6 @@ if (is_browser) { } var Wallet = copay.Wallet; var PrivateKey = copay.PrivateKey; -var Storage = require('./mocks/FakeStorage'); var Network = require('./mocks/FakeNetwork'); var Blockchain = require('./mocks/FakeBlockchain'); var bitcore = bitcore || require('bitcore'); @@ -21,6 +20,10 @@ var Address = bitcore.Address; var PayPro = bitcore.PayPro; var bignum = bitcore.Bignum; var startServer = copay.FakePayProServer; // TODO should be require('./mocks/FakePayProServer'); +var localMock = require('./mocks/FakeLocalStorage'); +var sessionMock = require('./mocks/FakeLocalStorage'); +var Storage = copay.Storage; + var server; @@ -30,6 +33,10 @@ var walletConfig = { spendUnconfirmed: true, reconnectDelay: 100, networkName: 'testnet', + storage: { + storage: localMock, + sessionStorage: sessionMock, + } }; var getNewEpk = function() { diff --git a/test/test.Storage.js b/test/test.Storage.js index 5a3032030..c7e75e2db 100644 --- a/test/test.Storage.js +++ b/test/test.Storage.js @@ -25,8 +25,7 @@ describe('Storage model', function() { }); should.exist(s2); }); - it.only('should fail when encrypting without a password', function() { - + it('should fail when encrypting without a password', function() { var s2 = new Storage({ storage: localMock, sessionStorage: sessionMock, diff --git a/test/test.Wallet.js b/test/test.Wallet.js index c8ae349e5..056d5e4bb 100644 --- a/test/test.Wallet.js +++ b/test/test.Wallet.js @@ -13,7 +13,7 @@ if (is_browser) { var copayConfig = require('../config'); var Wallet = copay.Wallet; var PrivateKey = copay.PrivateKey; -var Storage = require('./mocks/FakeStorage'); +var Storage = copay.Storage; var Network = require('./mocks/FakeNetwork'); var Blockchain = require('./mocks/FakeBlockchain'); var Builder = require('./mocks/FakeBuilder'); @@ -21,6 +21,8 @@ var bitcore = bitcore || require('bitcore'); var TransactionBuilder = bitcore.TransactionBuilder; var Transaction = bitcore.Transaction; var Address = bitcore.Address; +var localMock = require('./mocks/FakeLocalStorage'); +var sessionMock = require('./mocks/FakeLocalStorage'); var walletConfig = { requiredCopayers: 3, @@ -28,6 +30,10 @@ var walletConfig = { spendUnconfirmed: true, reconnectDelay: 100, networkName: 'testnet', + storage: { + storage: localMock, + sessionStorage: sessionMock, + } }; var getNewEpk = function() { diff --git a/test/test.WalletLock.js b/test/test.WalletLock.js index e8e418a96..abf2af9fd 100644 --- a/test/test.WalletLock.js +++ b/test/test.WalletLock.js @@ -13,12 +13,19 @@ var copayConfig = require('../config'); var WalletLock = copay.WalletLock; var PrivateKey = copay.PrivateKey; -var Storage = require('./mocks/FakeStorage'); +var localMock = require('./mocks/FakeLocalStorage'); +var sessionMock = require('./mocks/FakeLocalStorage'); +var Storage = copay.Storage; + + var storage; describe('WalletLock model', function() { beforeEach(function() { - storage = new Storage(); + storage = new Storage({ + storage: localMock, + sessionStorage: sessionMock, + }); }); it('should fail with missing args', function() { diff --git a/util/build.js b/util/build.js index 2c078f458..0d5b0f44e 100644 --- a/util/build.js +++ b/util/build.js @@ -104,9 +104,6 @@ var createBundle = function(opts) { //include dev dependencies b.require('sinon'); b.require('blanket'); - b.require('./test/mocks/FakeStorage', { - expose: './mocks/FakeStorage' - }); b.require('./test/mocks/FakeLocalStorage', { expose: './mocks/FakeLocalStorage' }); From 1ab7a4f8e83f194814246a5e03547e267053cbef Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 17 Sep 2014 12:10:26 -0300 Subject: [PATCH 30/45] fix walletlock tests --- js/models/Storage.js | 9 +- js/models/core/WalletLock.js | 2 + test/mocks/FakeLocalStorage.js | 32 +++--- test/test.PayPro.js | 7 +- test/test.Storage.js | 195 +++++++++++---------------------- test/test.Wallet.js | 5 +- test/test.WalletLock.js | 50 ++++----- 7 files changed, 123 insertions(+), 177 deletions(-) diff --git a/js/models/Storage.js b/js/models/Storage.js index 17a422bdb..4c8c658cb 100644 --- a/js/models/Storage.js +++ b/js/models/Storage.js @@ -118,6 +118,10 @@ Storage.prototype.getSessionId = function(cb) { }); }; +Storage.prototype.setSessionId = function(sessionId, cb) { + this.sessionStorage.setItem('sessionId', sessionId, cb); +}; + Storage.prototype._key = function(walletId, k) { return walletId + '::' + k; }; @@ -285,7 +289,10 @@ Storage.prototype.setFromObj = function(walletId, obj, cb) { for (var k in obj) { self.set(walletId, k, obj[k], function() { if (++i == l) { - self.setName(walletId, obj.opts.name, cb); + if (obj.opts.name) + self.setName(walletId, obj.opts.name, cb); + else + return cb(); } }); } diff --git a/js/models/core/WalletLock.js b/js/models/core/WalletLock.js index fa449b855..0b1fe503d 100644 --- a/js/models/core/WalletLock.js +++ b/js/models/core/WalletLock.js @@ -54,11 +54,13 @@ WalletLock.prototype._isLockedByOther = function(cb) { WalletLock.prototype._setLock = function(cb) { preconditions.checkArgument(cb); preconditions.checkState(this.sessionId); + var self = this; this.storage.setGlobal(this.key, { sessionId: this.sessionId, expireTs: Date.now() + this.timeoutMin * 60 * 1000, }, function() { + cb(null); }); }; diff --git a/test/mocks/FakeLocalStorage.js b/test/mocks/FakeLocalStorage.js index fba5e7dfd..c2ae7ce14 100644 --- a/test/mocks/FakeLocalStorage.js +++ b/test/mocks/FakeLocalStorage.js @@ -1,27 +1,33 @@ //localstorage Mock -ls = {}; -function LocalStorage(opts) { -} -FakeLocalStorage = {}; -FakeLocalStorage.length = 0; -FakeLocalStorage.removeItem = function(key,cb) { - delete ls[key]; +function FakeLocalStorage() { + this.ls = {}; +}; +FakeLocalStorage.prototype.removeItem = function(key, cb) { + delete this.ls[key]; cb(); }; -FakeLocalStorage.getItem = function(k,cb) { - return cb(ls[k]); +FakeLocalStorage.prototype.getItem = function(k, cb) { + return cb(this.ls[k]); }; -FakeLocalStorage.allKeys = function(cb) { - return cb(Object.keys(ls)); +FakeLocalStorage.prototype.allKeys = function(cb) { + return cb(Object.keys(this.ls)); }; -FakeLocalStorage.setItem = function(k, v,cb) { - ls[k] = v; +FakeLocalStorage.prototype.setItem = function(k, v, cb) { + this.ls[k] = v; return cb(); }; +FakeLocalStorage.prototype.clear = function() { + this.ls = {}; +} module.exports = FakeLocalStorage; + +module.exports.storageParams = { + storage: new FakeLocalStorage(), + sessionStorage: new FakeLocalStorage(), +}; diff --git a/test/test.PayPro.js b/test/test.PayPro.js index 997b8e9cb..e1d3d88ea 100644 --- a/test/test.PayPro.js +++ b/test/test.PayPro.js @@ -33,10 +33,7 @@ var walletConfig = { spendUnconfirmed: true, reconnectDelay: 100, networkName: 'testnet', - storage: { - storage: localMock, - sessionStorage: sessionMock, - } + storage: require('./mocks/FakeLocalStorage').storageParams, }; var getNewEpk = function() { @@ -48,6 +45,7 @@ var getNewEpk = function() { }; describe('PayPro (in Wallet) model', function() { + if (!is_browser) { var createW = function(N, conf) { var c = JSON.parse(JSON.stringify(conf || walletConfig)); @@ -71,6 +69,7 @@ describe('PayPro (in Wallet) model', function() { }); var storage = new Storage(walletConfig.storage); + storage.setPassphrase('xxx'); var network = new Network(walletConfig.network); var blockchain = new Blockchain(walletConfig.blockchain); c.storage = storage; diff --git a/test/test.Storage.js b/test/test.Storage.js index c7e75e2db..186a30070 100644 --- a/test/test.Storage.js +++ b/test/test.Storage.js @@ -7,99 +7,84 @@ var Storage = copay.Storage; var fakeWallet = 'fake-wallet-id'; var timeStamp = Date.now(); -var localMock = require('./mocks/FakeLocalStorage'); -var sessionMock = require('./mocks/FakeLocalStorage'); - describe('Storage model', function() { - var s = new Storage({ - storage: localMock, - sessionStorage: sessionMock, - }); - s.setPassphrase('mysupercoolpassword'); - it('should create an instance', function() { - var s2 = new Storage({ - storage: localMock, - sessionStorage: sessionMock, + var s; + beforeEach(function() { + s = new Storage(require('./mocks/FakeLocalStorage').storageParams); + s.setPassphrase('mysupercoolpassword'); + s.storage.clear(); + s.sessionStorage.clear(); }); - should.exist(s2); - }); - it('should fail when encrypting without a password', function() { - var s2 = new Storage({ - storage: localMock, - sessionStorage: sessionMock, + + + it('should create an instance', function() { + var s2 = new Storage(require('./mocks/FakeLocalStorage').storageParams); + should.exist(s2); }); - (function() { - s2.set(fakeWallet, timeStamp, 1, function() {}); - }).should.throw('NOPASSPHRASE'); - }); - it('should be able to encrypt and decrypt', function(done) { - s._write(fakeWallet + timeStamp, 'value', function() { - s._read(fakeWallet + timeStamp, function(v) { - v.should.equal('value'); - localMock.removeItem(fakeWallet + timeStamp, done); - }); + it('should fail when encrypting without a password', function() { + var s2 = new Storage(require('./mocks/FakeLocalStorage').storageParams); + (function() { + s2.set(fakeWallet, timeStamp, 1, function() {}); + }).should.throw('NOPASSPHRASE'); }); - }); - it('should be able to set a value', function(done) { - s.set(fakeWallet, timeStamp, 1, function() { - localMock.removeItem(fakeWallet + '::' + timeStamp, done); - }); - }); - var getSetData = [ - 1, 1000, -15, -1000, - 0.1, -0.5, -0.5e-10, Math.PI, - 'hi', 'auydoaiusyodaisudyoa', '0b5b8556a0c2ce828c9ccfa58b3dd0a1ae879b9b', - '1CjPR7Z5ZSyWk6WtXvSFgkptmpoi4UM9BC', 'OP_DUP OP_HASH160 80ad90d4035', [1, 2, 3, 4, 5, 6], { - x: 1, - y: 2 - }, { - x: 'hi', - y: null - }, { - a: {}, - b: [], - c: [1, 2, 'hi'] - }, - null - ]; - getSetData.forEach(function(obj) { - it('should be able to set a value and get it for ' + JSON.stringify(obj), function(done) { - s.set(fakeWallet, timeStamp, obj, function() { - s.get(fakeWallet, timeStamp, function(obj2) { - JSON.stringify(obj2).should.equal(JSON.stringify(obj)); - localMock.removeItem(fakeWallet + '::' + timeStamp, done); + it('should be able to encrypt and decrypt', function(done) { + s._write(fakeWallet + timeStamp, 'value', function() { + s._read(fakeWallet + timeStamp, function(v) { + v.should.equal('value'); + done(); }); }); }); - }); + it('should be able to set a value', function(done) { + s.set(fakeWallet, timeStamp, 1, function() { + done(); + }); + }); + var getSetData = [ + 1, 1000, -15, -1000, + 0.1, -0.5, -0.5e-10, Math.PI, + 'hi', 'auydoaiusyodaisudyoa', '0b5b8556a0c2ce828c9ccfa58b3dd0a1ae879b9b', + '1CjPR7Z5ZSyWk6WtXvSFgkptmpoi4UM9BC', 'OP_DUP OP_HASH160 80ad90d4035', [1, 2, 3, 4, 5, 6], { + x: 1, + y: 2 + }, { + x: 'hi', + y: null + }, { + a: {}, + b: [], + c: [1, 2, 'hi'] + }, + null + ]; + getSetData.forEach(function(obj) { + it('should be able to set a value and get it for ' + JSON.stringify(obj), function(done) { + s.set(fakeWallet, timeStamp, obj, function() { + s.get(fakeWallet, timeStamp, function(obj2) { + JSON.stringify(obj2).should.equal(JSON.stringify(obj)); + done(); + }); + }); + }); + }); describe('#export', function() { it('should export the encrypted wallet', function(done) { - var storage = new Storage({ - storage: localMock, - sessionStorage: sessionMock, - password: 'password', - }); - storage.set(fakeWallet, timeStamp, 'testval', function() { + s.set(fakeWallet, timeStamp, 'testval', function() { var obj = { test: 'testval' }; - var encrypted = storage.export(obj); + var encrypted = s.export(obj); encrypted.length.should.be.greaterThan(10); - localMock.removeItem(fakeWallet + '::' + timeStamp, done); + done(); }); }); }); describe('#remove', function() { it('should remove an item', function(done) { - var s = new Storage({ - storage: localMock, - sessionStorage: sessionMock, - password: 'password' - }); s.set('1', "hola", 'juan', function() { s.get('1', 'hola', function(v) { v.should.equal('juan'); @@ -117,11 +102,6 @@ describe('Storage model', function() { describe('#getWalletIds', function() { it('should get wallet ids', function(done) { - var s = new Storage({ - storage: localMock, - sessionStorage: sessionMock, - password: 'password' - }); s.set('1', "hola", 'juan', function() { s.set('2', "hola", 'juan', function() { s.getWalletIds(function(v) { @@ -135,11 +115,6 @@ describe('Storage model', function() { describe('#getName #setName', function() { it('should get/set names', function(done) { - var s = new Storage({ - storage: localMock, - sessionStorage: sessionMock, - password: 'password' - }); s.setName(1, 'hola', function() { s.getName(1, function(v) { v.should.equal('hola'); @@ -151,11 +126,6 @@ describe('Storage model', function() { describe('#getLastOpened #setLastOpened', function() { it('should get/set last opened', function() { - var s = new Storage({ - storage: localMock, - sessionStorage: sessionMock, - password: 'password' - }); s.setLastOpened('hey', function() { s.getLastOpened(function(v) { v.should.equal('hey'); @@ -167,11 +137,6 @@ describe('Storage model', function() { if (is_browser) { describe('#getSessionId', function() { it('should get SessionId', function(done) { - var s = new Storage({ - storage: localMock, - sessionStorage: sessionMock, - password: 'password' - }); s.getSessionId(function(sid) { should.exist(sid); s.getSessionId(function(sid2) { @@ -185,11 +150,6 @@ describe('Storage model', function() { describe('#getWallets', function() { it('should retreive wallets from storage', function(done) { - var s = new Storage({ - storage: localMock, - sessionStorage: sessionMock, - password: 'password' - }); s.set('1', "hola", 'juan', function() { s.set('2', "hola", 'juan', function() { s.setName(1, 'hola', function() { @@ -208,14 +168,8 @@ describe('Storage model', function() { }); }); }); - }); - describe('#deleteWallet', function() { + }); describe('#deleteWallet', function() { it('should fail to delete a unexisting wallet', function(done) { - var s = new Storage({ - storage: localMock, - sessionStorage: sessionMock, - password: 'password' - }); s.set('1', "hola", 'juan', function() { s.set('2', "hola", 'juan', function() { s.deleteWallet('3', function(err) { @@ -227,11 +181,6 @@ describe('Storage model', function() { }); it('should delete a wallet', function(done) { - var s = new Storage({ - storage: localMock, - sessionStorage: sessionMock, - password: 'password' - }); s.set('1', "hola", 'juan', function() { s.set('2', "hola", 'juan', function() { s.deleteWallet('1', function(err) { @@ -252,11 +201,6 @@ describe('Storage model', function() { describe('#setFromObj', function() { it('set localstorage from an object', function(done) { - var s = new Storage({ - storage: localMock, - sessionStorage: sessionMock, - password: 'password' - }); s.setFromObj('id1', { 'key': 'val', 'opts': { @@ -274,12 +218,6 @@ describe('Storage model', function() { describe('#globals', function() { it('should set, get and remove keys', function(done) { - var s = new Storage({ - storage: localMock, - sessionStorage: sessionMock, - password: 'password' - }); - s.setGlobal('a', { b: 1 }, function() { @@ -302,11 +240,6 @@ describe('Storage model', function() { describe('session storage', function() { it('should get a session ID', function(done) { - var s = new Storage({ - storage: localMock, - sessionStorage: sessionMock, - password: 'password' - }); s.getSessionId(function(s) { should.exist(s); s.length.should.equal(16); @@ -317,12 +250,14 @@ describe('Storage model', function() { }); describe('#import', function() { + it('should not be able to decrypt with wrong password', function() { + s.setPassphrase('xxx'); + var wo = s.import(encryptedLegacy1); + should.not.exist(wo); + }); + it('should be able to decrypt an old backup', function() { - var s = new Storage({ - storage: localMock, - sessionStorage: sessionMock, - password: legacyPassword1 , - }); + s.setPassphrase(legacyPassword1); var wo = s.import(encryptedLegacy1); should.exist(wo); wo.opts.id.should.equal('48ba2f1ffdfe9708'); @@ -353,5 +288,3 @@ describe('Storage model', function() { var legacyPassword1 = '1DUpLRbuVpgLkcEY8gY8iod/SmA7+OheGZJ9PtvmTlvNE0FkEWpCKW9STdzXYJqbn0wiAapE4ojHNYj2hjYYAQ=='; var encryptedLegacy1 = 'U2FsdGVkX19yGM1uBAIzQa8Po/dvUicmxt1YyRk/S97PcZ6I6rHMp9dMagIrehg4Qd6JHn/ustmFHS7vmBYj0EBpf6rdXiQezaWnVAJS9/xYjAO36EFUbl+NmUanuwujAxgYdSP/sNssRLeInvExmZYW993EEclxkwL6YUyX66kKsxGQo2oWng0NreBJNhFmrbOEWeFje2PiWP57oUjKsurFzwpluAAarUTYSLud+nXeabC7opzOP5yqniWBMJz0Ou8gpNCWCMhG/P9F9ccVPY7juyd0Hf41FVse8nd2++axKB57+paozLdO+HRfV6zkMqC3h8gWY7LkS75j3bvqcTw9LhXmzE0Sz21n9yDnRpA4chiAvtwQvvBGgj1pFMKhNQU6Obac9ZwKYzUTgdDn3Uzg1UlDzgyOh9S89rbRTV84WB+hXwhuVluWzbNNYV3vXe5PFrocVktIrtS3xQh+k/7my4A6/gRRrzNYpKrUASJqDS/9u9WBkG35xD63J/qXjtG2M0YPwbI57BK1IK4K510b8V72lz5U2XQrIC4ldBwni1rpSavwCJV9xF6hUdOmNV8fZsVHP0NeN1PYlLkSb2QgfuoWnkcsJerwuFR7GZC/i6efrswtpO0wMEQr/J0CLbeXlHAru6xxjCBhWoJvZpMGw72zgnDLoyMNsEVglNhx/VlV9ZMYkkdaEYAxPOEIyZdQ5MS+2jEAlXf818n/xzJSVrniCn9be8EPePvkw35pivprvy09vbW4cKsWBKvgIyoT6A3OhUOCCS8E9cg0WAjjav2EymrbKmGWRHaiD+EoJqaDg6s20zhHn1YEa/YwvGGSB5+Hg8baLHD8ZASvxz4cFFAAVZrBUedRFgHzqwaMUlFXLgueivWUj7RXlIw6GuNhLoo1QkhZMacf23hrFxxQYvGBRw1hekBuDmcsGWljA28udBxBd5f9i+3gErttMLJ6IPaud590uvrxRIclu0Sz9R2EQX64YJxqDtLpMY0PjddSMu8vaDRpK9/ZSrnz/xrXsyabaafz4rE/ItFXjwFUFkvtmuauHTz6nmuKjVfxvNLNAiKb/gI7vQyUhnTbKIApe7XyJsjedNDtZqsPoJRIzdDmrZYxGStbAZ7HThqFJlSJ9NPNhH+E2jm3TwL5mwt0fFZ5h+p497lHMtIcKffESo7KNa2juSVNMDREk0NcyxGXGiVB2FWl4sLdvyhcsVq0I7tmW6OGZKRf8W49GCJXq6Ie69DJ9LB1DO67NV1jsYbsLx9uhE2yEmpWZ3jkoCV/Eas4grxt0CGN6EavzQ=='; - - diff --git a/test/test.Wallet.js b/test/test.Wallet.js index 056d5e4bb..b9592b64c 100644 --- a/test/test.Wallet.js +++ b/test/test.Wallet.js @@ -87,6 +87,7 @@ describe('Wallet model', function() { }); var storage = new Storage(walletConfig.storage); + storage.setPassphrase('xxx'); var network = new Network(walletConfig.network); var blockchain = new Blockchain(walletConfig.blockchain); c.storage = storage; @@ -347,8 +348,10 @@ describe('Wallet model', function() { // non stored options o.opts.reconnectDelay = 100; + var s = new Storage(walletConfig.storage); + s.setPassphrase('xxx'); var w2 = Wallet.fromObj(o, - new Storage(walletConfig.storage), + s, new Network(walletConfig.network), new Blockchain(walletConfig.blockchain)); should.exist(w2); diff --git a/test/test.WalletLock.js b/test/test.WalletLock.js index abf2af9fd..6b2cb3ee2 100644 --- a/test/test.WalletLock.js +++ b/test/test.WalletLock.js @@ -11,21 +11,19 @@ if (is_browser) { } var copayConfig = require('../config'); var WalletLock = copay.WalletLock; - var PrivateKey = copay.PrivateKey; -var localMock = require('./mocks/FakeLocalStorage'); -var sessionMock = require('./mocks/FakeLocalStorage'); var Storage = copay.Storage; var storage; describe('WalletLock model', function() { + beforeEach(function() { - storage = new Storage({ - storage: localMock, - sessionStorage: sessionMock, - }); + storage = new Storage(require('./mocks/FakeLocalStorage').storageParams); + storage.setPassphrase('mysupercoolpassword'); + storage.storage.clear(); + storage.sessionStorage.clear(); }); it('should fail with missing args', function() { @@ -80,36 +78,34 @@ describe('WalletLock model', function() { }); it('should FAIL if locked by someone else', function(done) { - storage.sessionId = 'session1'; var w = new WalletLock(storage, 'walletId'); w.keepAlive(function() { - storage.sessionId = 'session2'; - var w2 = new WalletLock(storage, 'walletId'); - w2.keepAlive(function(locked) { - w2.sessionId.should.equal('session2'); - should.exist(locked); - locked.message.should.contain('LOCKED'); - done(); + storage.setSessionId('session2', function() { + var w2 = new WalletLock(storage, 'walletId'); + w2.keepAlive(function(locked) { + should.exist(locked); + locked.message.should.contain('LOCKED'); + done(); + }); }); }); }) it('should FAIL if locked by someone else but expired', function(done) { - storage.sessionId = 'session1'; var w = new WalletLock(storage, 'walletId'); w.keepAlive(function() { - storage.sessionId = 'session2'; - var json = JSON.parse(storage.storage['lock::walletId']); - json.expireTs -= 3600 * 1000; - storage.storage['lock::walletId'] = JSON.stringify(json); - var w2 = new WalletLock(storage, 'walletId'); - w2.keepAlive(function(locked) { - w2.sessionId.should.equal('session2'); - should.not.exist(locked); - done(); + storage.setSessionId('session2', function() { + + var json = JSON.parse(storage.storage.ls['lock::walletId']); + json.expireTs -= 3600 * 1000; + storage.storage.ls['lock::walletId'] = JSON.stringify(json); + var w2 = new WalletLock(storage, 'walletId'); + w2.keepAlive(function(locked) { + w2.sessionId.should.equal('session2'); + should.not.exist(locked); + done(); + }); }); }); }) }); - - From 7fd93d4ffd010576c4f2370bd7c34a27f1157cab Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 17 Sep 2014 12:11:33 -0300 Subject: [PATCH 31/45] fix all tests in mocha --- test/test.Wallet.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/test/test.Wallet.js b/test/test.Wallet.js index b9592b64c..b4f2a7347 100644 --- a/test/test.Wallet.js +++ b/test/test.Wallet.js @@ -21,8 +21,6 @@ var bitcore = bitcore || require('bitcore'); var TransactionBuilder = bitcore.TransactionBuilder; var Transaction = bitcore.Transaction; var Address = bitcore.Address; -var localMock = require('./mocks/FakeLocalStorage'); -var sessionMock = require('./mocks/FakeLocalStorage'); var walletConfig = { requiredCopayers: 3, @@ -30,10 +28,7 @@ var walletConfig = { spendUnconfirmed: true, reconnectDelay: 100, networkName: 'testnet', - storage: { - storage: localMock, - sessionStorage: sessionMock, - } + storage: require('./mocks/FakeLocalStorage').storageParams, }; var getNewEpk = function() { From c7378c90ec8d4e4c1457328f0796cf819a29cad7 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 17 Sep 2014 13:03:12 -0300 Subject: [PATCH 32/45] karma passing again! --- Gruntfile.js | 1 + js/controllers/open.js | 16 +++++++++------- karma.conf.js | 2 +- test/unit/controllers/controllersSpec.js | 1 + test/unit/services/servicesSpec.js | 2 ++ 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index a043256b8..ab545d23b 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -118,6 +118,7 @@ module.exports = function(grunt) { 'lib/angular-foundation/mm-foundation-tpls.min.js', 'lib/angular-gettext/dist/angular-gettext.min.js', 'lib/angular-load/angular-load.min.js' + // If you add libs here, remember to add it too to karma.conf ], dest: 'lib/angularjs-all.js' }, diff --git a/js/controllers/open.js b/js/controllers/open.js index e06519e1f..8fb5df483 100644 --- a/js/controllers/open.js +++ b/js/controllers/open.js @@ -15,17 +15,19 @@ angular.module('copayApp.controllers').controller('OpenController', function($sc $rootScope.fromSetup = false; $scope.loading = false; $scope.retreiving = true; + walletFactory.getWallets(function(wallets) { - $scope.wallets = wallets.sort(cmp); - if (!$scope.wallets.length) { + if (!wallets || !wallets.length) { $location.path('/'); - } + } else { + $scope.wallets = wallets.sort(cmp); - walletFactory.storage.getLastOpened(function(ret) { - $scope.selectedWalletId = ret || ($scope.wallets[0] && $scope.wallets[0].id); - $scope.retreiving = false; - }); + walletFactory.storage.getLastOpened(function(ret) { + $scope.selectedWalletId = ret || ($scope.wallets[0] && $scope.wallets[0].id); + $scope.retreiving = false; + }); + } }); $scope.openPassword = ''; diff --git a/karma.conf.js b/karma.conf.js index 052e215fb..06b14adcf 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -28,6 +28,7 @@ module.exports = function(config) { 'lib/angular-route/angular-route.min.js', 'lib/angular-foundation/mm-foundation.min.js', 'lib/angular-foundation/mm-foundation-tpls.min.js', + 'lib/angular-load/angular-load.min.js', 'lib/angular-gettext/dist/angular-gettext.min.js', 'lib/inherits/inherits.js', 'lib/bitcore.js', @@ -61,7 +62,6 @@ module.exports = function(config) { 'test/mocks/FakeBlockchainSocket.js', 'test/mocks/FakePayProServer.js', 'test/mocks/FakeLocalStorage.js', - 'test/mocks/FakeStorage.js', 'test/mocha.conf.js', diff --git a/test/unit/controllers/controllersSpec.js b/test/unit/controllers/controllersSpec.js index 48214a907..9d06092d2 100644 --- a/test/unit/controllers/controllersSpec.js +++ b/test/unit/controllers/controllersSpec.js @@ -25,6 +25,7 @@ describe("Unit: Controllers", function() { beforeEach(module('copayApp.services')); beforeEach(module('copayApp.controllers')); + beforeEach(angular.mock.module('copayApp')); var walletConfig = { requiredCopayers: 3, diff --git a/test/unit/services/servicesSpec.js b/test/unit/services/servicesSpec.js index 9a5b73faf..2d827c6fd 100644 --- a/test/unit/services/servicesSpec.js +++ b/test/unit/services/servicesSpec.js @@ -6,6 +6,8 @@ var sinon = require('sinon'); var preconditions = require('preconditions').singleton(); +beforeEach(angular.mock.module('copayApp')); + describe("Unit: Walletfactory Service", function() { beforeEach(angular.mock.module('copayApp.services')); it('should contain a walletFactory service', inject(function(walletFactory) { From 56a7a7b5c5d626ea28c41b7be0a7b7cf6fed565d Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Thu, 18 Sep 2014 16:15:23 -0300 Subject: [PATCH 33/45] rename setPassphrase --- js/models/Storage.js | 10 +++++----- js/models/core/WalletFactory.js | 6 +++--- test/test.PayPro.js | 2 +- test/test.Storage.js | 6 +++--- test/test.Wallet.js | 4 ++-- test/test.WalletFactory.js | 28 ++++++++++++++-------------- test/test.WalletLock.js | 2 +- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/js/models/Storage.js b/js/models/Storage.js index 4c8c658cb..6c1441580 100644 --- a/js/models/Storage.js +++ b/js/models/Storage.js @@ -12,7 +12,7 @@ function Storage(opts) { this.__uniqueid = ++id; if (opts.password) - this.setPassphrase(opts.password); + this.setPassword(opts.password); try { this.storage = opts.storage || localStorage; @@ -26,7 +26,7 @@ function Storage(opts) { } var pps = {}; -Storage.prototype._getPassphrase = function() { +Storage.prototype._getPassword = function() { if (!pps[this.__uniqueid]) throw new Error('NOPASSPHRASE: No passphrase set'); @@ -34,12 +34,12 @@ Storage.prototype._getPassphrase = function() { return pps[this.__uniqueid]; } -Storage.prototype.setPassphrase = function(password) { +Storage.prototype.setPassword = function(password) { pps[this.__uniqueid] = password; } Storage.prototype._encrypt = function(string) { - var encrypted = CryptoJS.AES.encrypt(string, this._getPassphrase()); + var encrypted = CryptoJS.AES.encrypt(string, this._getPassword()); var encryptedBase64 = encrypted.toString(); return encryptedBase64; }; @@ -47,7 +47,7 @@ Storage.prototype._encrypt = function(string) { Storage.prototype._decrypt = function(base64) { var decryptedStr = null; try { - var decrypted = CryptoJS.AES.decrypt(base64, this._getPassphrase()); + var decrypted = CryptoJS.AES.decrypt(base64, this._getPassword()); if (decrypted) decryptedStr = decrypted.toString(CryptoJS.enc.Utf8); } catch (e) { diff --git a/js/models/core/WalletFactory.js b/js/models/core/WalletFactory.js index b1594937c..192827567 100644 --- a/js/models/core/WalletFactory.js +++ b/js/models/core/WalletFactory.js @@ -119,7 +119,7 @@ WalletFactory.prototype.fromObj = function(inObj, skipFields) { * @return {Wallet} */ WalletFactory.prototype.fromEncryptedObj = function(base64, password, skipFields) { - this.storage.setPassphrase(password); + this.storage.setPassword(password); var walletObj = this.storage.import(base64); if (!walletObj) return false; return this.fromObj(walletObj, skipFields); @@ -248,7 +248,7 @@ WalletFactory.prototype.create = function(opts, cb) { }); log.debug('\t### TxProposals Initialized'); - this.storage.setPassphrase(opts.passphrase); + this.storage.setPassword(opts.passphrase); opts.storage = this.storage; opts.network = this.networks[opts.networkName]; @@ -300,7 +300,7 @@ WalletFactory.prototype._checkVersion = function(inVersion) { WalletFactory.prototype.open = function(walletId, passphrase, cb) { preconditions.checkArgument(cb); var self = this; - self.storage.setPassphrase(passphrase); + self.storage.setPassword(passphrase); self.read(walletId, null, function(err, w) { if (err) return cb(err); diff --git a/test/test.PayPro.js b/test/test.PayPro.js index e1d3d88ea..bf218d4b0 100644 --- a/test/test.PayPro.js +++ b/test/test.PayPro.js @@ -69,7 +69,7 @@ describe('PayPro (in Wallet) model', function() { }); var storage = new Storage(walletConfig.storage); - storage.setPassphrase('xxx'); + storage.setPassword('xxx'); var network = new Network(walletConfig.network); var blockchain = new Blockchain(walletConfig.blockchain); c.storage = storage; diff --git a/test/test.Storage.js b/test/test.Storage.js index 186a30070..120aa3de1 100644 --- a/test/test.Storage.js +++ b/test/test.Storage.js @@ -13,7 +13,7 @@ describe('Storage model', function() { var s; beforeEach(function() { s = new Storage(require('./mocks/FakeLocalStorage').storageParams); - s.setPassphrase('mysupercoolpassword'); + s.setPassword('mysupercoolpassword'); s.storage.clear(); s.sessionStorage.clear(); }); @@ -251,13 +251,13 @@ describe('Storage model', function() { describe('#import', function() { it('should not be able to decrypt with wrong password', function() { - s.setPassphrase('xxx'); + s.setPassword('xxx'); var wo = s.import(encryptedLegacy1); should.not.exist(wo); }); it('should be able to decrypt an old backup', function() { - s.setPassphrase(legacyPassword1); + s.setPassword(legacyPassword1); var wo = s.import(encryptedLegacy1); should.exist(wo); wo.opts.id.should.equal('48ba2f1ffdfe9708'); diff --git a/test/test.Wallet.js b/test/test.Wallet.js index b4f2a7347..be2e59cd5 100644 --- a/test/test.Wallet.js +++ b/test/test.Wallet.js @@ -82,7 +82,7 @@ describe('Wallet model', function() { }); var storage = new Storage(walletConfig.storage); - storage.setPassphrase('xxx'); + storage.setPassword('xxx'); var network = new Network(walletConfig.network); var blockchain = new Blockchain(walletConfig.blockchain); c.storage = storage; @@ -344,7 +344,7 @@ describe('Wallet model', function() { o.opts.reconnectDelay = 100; var s = new Storage(walletConfig.storage); - s.setPassphrase('xxx'); + s.setPassword('xxx'); var w2 = Wallet.fromObj(o, s, new Network(walletConfig.network), diff --git a/test/test.WalletFactory.js b/test/test.WalletFactory.js index 517bf44bd..537f69ecb 100644 --- a/test/test.WalletFactory.js +++ b/test/test.WalletFactory.js @@ -34,7 +34,7 @@ describe('WalletFactory model', function() { beforeEach(function() { wf = new WalletFactory(config, '0.0.1'); - wf.storage.setPassphrase = sinon.spy(); + wf.storage.setPassword = sinon.spy(); wf.storage.getSessionId = sinon.spy(); wf.storage.setFromObj = sinon.spy(); wf.storage.setLastOpened = sinon.stub().yields(null); @@ -151,15 +151,15 @@ describe('WalletFactory model', function() { describe('#fromEncryptedObj', function() { it('should create wallet from encrypted object', function() { - wf.storage.setPassphrase = sinon.spy(); + wf.storage.setPassword = sinon.spy(); wf.storage.import = sinon.stub().withArgs('base64').returns('walletObj'); wf.fromObj = sinon.stub().withArgs('walletObj').returns('ok'); var w = wf.fromEncryptedObj("encrypted object", "123"); w.should.equal('ok'); - wf.storage.setPassphrase.calledOnce.should.be.true; - wf.storage.setPassphrase.getCall(0).args[0].should.equal('123'); + wf.storage.setPassword.calledOnce.should.be.true; + wf.storage.setPassword.getCall(0).args[0].should.equal('123'); wf.storage.import.calledOnce.should.be.true; wf.fromObj.calledWith('walletObj').should.be.true; }); @@ -291,9 +291,9 @@ describe('WalletFactory model', function() { 'totalcopayers': 3 }; - it('should call setPassphrase', function(done) { + it('should call setPassword', function(done) { var wf = new WalletFactory(config, '0.0.1'); - wf.storage.setPassphrase = sinon.spy(); + wf.storage.setPassword = sinon.spy(); var s1 = sinon.stub(); s1.store = sinon.stub().yields(null); @@ -301,15 +301,15 @@ describe('WalletFactory model', function() { wf.storage.setLastOpened = sinon.stub().yields(null); wf.open('dummy', 'xxx', function(err, w) { - wf.storage.setPassphrase.calledOnce.should.equal(true); - wf.storage.setPassphrase.getCall(0).args[0].should.equal('xxx'); + wf.storage.setPassword.calledOnce.should.equal(true); + wf.storage.setPassword.getCall(0).args[0].should.equal('xxx'); done(); }); }); it('should call return wallet', function(done) { var wf = new WalletFactory(config, '0.0.1'); - wf.storage.setPassphrase = sinon.spy(); + wf.storage.setPassword = sinon.spy(); var s1 = sinon.stub(); s1.store = sinon.stub().yields(null); @@ -326,7 +326,7 @@ describe('WalletFactory model', function() { it('should call #store', function(done) { var wf = new WalletFactory(config, '0.0.1'); - wf.storage.setPassphrase = sinon.spy(); + wf.storage.setPassword = sinon.spy(); var s1 = sinon.stub(); s1.store = sinon.stub().yields(null); @@ -341,7 +341,7 @@ describe('WalletFactory model', function() { it('should call #setLastOpened', function(done) { var wf = new WalletFactory(config, '0.0.1'); - wf.storage.setPassphrase = sinon.spy(); + wf.storage.setPassword = sinon.spy(); var s1 = sinon.stub(); s1.store = sinon.stub().yields(null); @@ -510,13 +510,13 @@ describe('WalletFactory model', function() { it('should be able to import simple 1-of-1 encrypted legacy testnet wallet', function() { wf.storage.import = sinon.stub(); - wf.storage.setPassphrase = sinon.spy(); + wf.storage.setPassword = sinon.spy(); wf.storage.import.withArgs('dummy').returns(JSON.parse(legacy1)); var w = wf.import('dummy', 'xxx'); should.exist(w); - wf.storage.setPassphrase.calledOnce.should.equal(true); - wf.storage.setPassphrase.getCall(0).args[0].should.equal('xxx'); + wf.storage.setPassword.calledOnce.should.equal(true); + wf.storage.setPassword.getCall(0).args[0].should.equal('xxx'); w.isReady().should.equal(true); var wo = w.toObj(); diff --git a/test/test.WalletLock.js b/test/test.WalletLock.js index 6b2cb3ee2..018d151d9 100644 --- a/test/test.WalletLock.js +++ b/test/test.WalletLock.js @@ -21,7 +21,7 @@ describe('WalletLock model', function() { beforeEach(function() { storage = new Storage(require('./mocks/FakeLocalStorage').storageParams); - storage.setPassphrase('mysupercoolpassword'); + storage.setPassword('mysupercoolpassword'); storage.storage.clear(); storage.sessionStorage.clear(); }); From 9bfc0dd1937682cbe560103f2fcff04ee14e1a20 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Thu, 18 Sep 2014 16:38:18 -0300 Subject: [PATCH 34/45] revert to setPassphrase --- js/models/Storage.js | 10 +++++----- js/models/core/WalletFactory.js | 6 +++--- test/test.PayPro.js | 2 +- test/test.Storage.js | 6 +++--- test/test.Wallet.js | 4 ++-- test/test.WalletFactory.js | 28 ++++++++++++++-------------- test/test.WalletLock.js | 2 +- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/js/models/Storage.js b/js/models/Storage.js index 6c1441580..4c8c658cb 100644 --- a/js/models/Storage.js +++ b/js/models/Storage.js @@ -12,7 +12,7 @@ function Storage(opts) { this.__uniqueid = ++id; if (opts.password) - this.setPassword(opts.password); + this.setPassphrase(opts.password); try { this.storage = opts.storage || localStorage; @@ -26,7 +26,7 @@ function Storage(opts) { } var pps = {}; -Storage.prototype._getPassword = function() { +Storage.prototype._getPassphrase = function() { if (!pps[this.__uniqueid]) throw new Error('NOPASSPHRASE: No passphrase set'); @@ -34,12 +34,12 @@ Storage.prototype._getPassword = function() { return pps[this.__uniqueid]; } -Storage.prototype.setPassword = function(password) { +Storage.prototype.setPassphrase = function(password) { pps[this.__uniqueid] = password; } Storage.prototype._encrypt = function(string) { - var encrypted = CryptoJS.AES.encrypt(string, this._getPassword()); + var encrypted = CryptoJS.AES.encrypt(string, this._getPassphrase()); var encryptedBase64 = encrypted.toString(); return encryptedBase64; }; @@ -47,7 +47,7 @@ Storage.prototype._encrypt = function(string) { Storage.prototype._decrypt = function(base64) { var decryptedStr = null; try { - var decrypted = CryptoJS.AES.decrypt(base64, this._getPassword()); + var decrypted = CryptoJS.AES.decrypt(base64, this._getPassphrase()); if (decrypted) decryptedStr = decrypted.toString(CryptoJS.enc.Utf8); } catch (e) { diff --git a/js/models/core/WalletFactory.js b/js/models/core/WalletFactory.js index 192827567..b1594937c 100644 --- a/js/models/core/WalletFactory.js +++ b/js/models/core/WalletFactory.js @@ -119,7 +119,7 @@ WalletFactory.prototype.fromObj = function(inObj, skipFields) { * @return {Wallet} */ WalletFactory.prototype.fromEncryptedObj = function(base64, password, skipFields) { - this.storage.setPassword(password); + this.storage.setPassphrase(password); var walletObj = this.storage.import(base64); if (!walletObj) return false; return this.fromObj(walletObj, skipFields); @@ -248,7 +248,7 @@ WalletFactory.prototype.create = function(opts, cb) { }); log.debug('\t### TxProposals Initialized'); - this.storage.setPassword(opts.passphrase); + this.storage.setPassphrase(opts.passphrase); opts.storage = this.storage; opts.network = this.networks[opts.networkName]; @@ -300,7 +300,7 @@ WalletFactory.prototype._checkVersion = function(inVersion) { WalletFactory.prototype.open = function(walletId, passphrase, cb) { preconditions.checkArgument(cb); var self = this; - self.storage.setPassword(passphrase); + self.storage.setPassphrase(passphrase); self.read(walletId, null, function(err, w) { if (err) return cb(err); diff --git a/test/test.PayPro.js b/test/test.PayPro.js index bf218d4b0..e1d3d88ea 100644 --- a/test/test.PayPro.js +++ b/test/test.PayPro.js @@ -69,7 +69,7 @@ describe('PayPro (in Wallet) model', function() { }); var storage = new Storage(walletConfig.storage); - storage.setPassword('xxx'); + storage.setPassphrase('xxx'); var network = new Network(walletConfig.network); var blockchain = new Blockchain(walletConfig.blockchain); c.storage = storage; diff --git a/test/test.Storage.js b/test/test.Storage.js index 120aa3de1..186a30070 100644 --- a/test/test.Storage.js +++ b/test/test.Storage.js @@ -13,7 +13,7 @@ describe('Storage model', function() { var s; beforeEach(function() { s = new Storage(require('./mocks/FakeLocalStorage').storageParams); - s.setPassword('mysupercoolpassword'); + s.setPassphrase('mysupercoolpassword'); s.storage.clear(); s.sessionStorage.clear(); }); @@ -251,13 +251,13 @@ describe('Storage model', function() { describe('#import', function() { it('should not be able to decrypt with wrong password', function() { - s.setPassword('xxx'); + s.setPassphrase('xxx'); var wo = s.import(encryptedLegacy1); should.not.exist(wo); }); it('should be able to decrypt an old backup', function() { - s.setPassword(legacyPassword1); + s.setPassphrase(legacyPassword1); var wo = s.import(encryptedLegacy1); should.exist(wo); wo.opts.id.should.equal('48ba2f1ffdfe9708'); diff --git a/test/test.Wallet.js b/test/test.Wallet.js index be2e59cd5..b4f2a7347 100644 --- a/test/test.Wallet.js +++ b/test/test.Wallet.js @@ -82,7 +82,7 @@ describe('Wallet model', function() { }); var storage = new Storage(walletConfig.storage); - storage.setPassword('xxx'); + storage.setPassphrase('xxx'); var network = new Network(walletConfig.network); var blockchain = new Blockchain(walletConfig.blockchain); c.storage = storage; @@ -344,7 +344,7 @@ describe('Wallet model', function() { o.opts.reconnectDelay = 100; var s = new Storage(walletConfig.storage); - s.setPassword('xxx'); + s.setPassphrase('xxx'); var w2 = Wallet.fromObj(o, s, new Network(walletConfig.network), diff --git a/test/test.WalletFactory.js b/test/test.WalletFactory.js index 537f69ecb..517bf44bd 100644 --- a/test/test.WalletFactory.js +++ b/test/test.WalletFactory.js @@ -34,7 +34,7 @@ describe('WalletFactory model', function() { beforeEach(function() { wf = new WalletFactory(config, '0.0.1'); - wf.storage.setPassword = sinon.spy(); + wf.storage.setPassphrase = sinon.spy(); wf.storage.getSessionId = sinon.spy(); wf.storage.setFromObj = sinon.spy(); wf.storage.setLastOpened = sinon.stub().yields(null); @@ -151,15 +151,15 @@ describe('WalletFactory model', function() { describe('#fromEncryptedObj', function() { it('should create wallet from encrypted object', function() { - wf.storage.setPassword = sinon.spy(); + wf.storage.setPassphrase = sinon.spy(); wf.storage.import = sinon.stub().withArgs('base64').returns('walletObj'); wf.fromObj = sinon.stub().withArgs('walletObj').returns('ok'); var w = wf.fromEncryptedObj("encrypted object", "123"); w.should.equal('ok'); - wf.storage.setPassword.calledOnce.should.be.true; - wf.storage.setPassword.getCall(0).args[0].should.equal('123'); + wf.storage.setPassphrase.calledOnce.should.be.true; + wf.storage.setPassphrase.getCall(0).args[0].should.equal('123'); wf.storage.import.calledOnce.should.be.true; wf.fromObj.calledWith('walletObj').should.be.true; }); @@ -291,9 +291,9 @@ describe('WalletFactory model', function() { 'totalcopayers': 3 }; - it('should call setPassword', function(done) { + it('should call setPassphrase', function(done) { var wf = new WalletFactory(config, '0.0.1'); - wf.storage.setPassword = sinon.spy(); + wf.storage.setPassphrase = sinon.spy(); var s1 = sinon.stub(); s1.store = sinon.stub().yields(null); @@ -301,15 +301,15 @@ describe('WalletFactory model', function() { wf.storage.setLastOpened = sinon.stub().yields(null); wf.open('dummy', 'xxx', function(err, w) { - wf.storage.setPassword.calledOnce.should.equal(true); - wf.storage.setPassword.getCall(0).args[0].should.equal('xxx'); + wf.storage.setPassphrase.calledOnce.should.equal(true); + wf.storage.setPassphrase.getCall(0).args[0].should.equal('xxx'); done(); }); }); it('should call return wallet', function(done) { var wf = new WalletFactory(config, '0.0.1'); - wf.storage.setPassword = sinon.spy(); + wf.storage.setPassphrase = sinon.spy(); var s1 = sinon.stub(); s1.store = sinon.stub().yields(null); @@ -326,7 +326,7 @@ describe('WalletFactory model', function() { it('should call #store', function(done) { var wf = new WalletFactory(config, '0.0.1'); - wf.storage.setPassword = sinon.spy(); + wf.storage.setPassphrase = sinon.spy(); var s1 = sinon.stub(); s1.store = sinon.stub().yields(null); @@ -341,7 +341,7 @@ describe('WalletFactory model', function() { it('should call #setLastOpened', function(done) { var wf = new WalletFactory(config, '0.0.1'); - wf.storage.setPassword = sinon.spy(); + wf.storage.setPassphrase = sinon.spy(); var s1 = sinon.stub(); s1.store = sinon.stub().yields(null); @@ -510,13 +510,13 @@ describe('WalletFactory model', function() { it('should be able to import simple 1-of-1 encrypted legacy testnet wallet', function() { wf.storage.import = sinon.stub(); - wf.storage.setPassword = sinon.spy(); + wf.storage.setPassphrase = sinon.spy(); wf.storage.import.withArgs('dummy').returns(JSON.parse(legacy1)); var w = wf.import('dummy', 'xxx'); should.exist(w); - wf.storage.setPassword.calledOnce.should.equal(true); - wf.storage.setPassword.getCall(0).args[0].should.equal('xxx'); + wf.storage.setPassphrase.calledOnce.should.equal(true); + wf.storage.setPassphrase.getCall(0).args[0].should.equal('xxx'); w.isReady().should.equal(true); var wo = w.toObj(); diff --git a/test/test.WalletLock.js b/test/test.WalletLock.js index 018d151d9..6b2cb3ee2 100644 --- a/test/test.WalletLock.js +++ b/test/test.WalletLock.js @@ -21,7 +21,7 @@ describe('WalletLock model', function() { beforeEach(function() { storage = new Storage(require('./mocks/FakeLocalStorage').storageParams); - storage.setPassword('mysupercoolpassword'); + storage.setPassphrase('mysupercoolpassword'); storage.storage.clear(); storage.sessionStorage.clear(); }); From 238d36c0a724dc881bb07f7f1653faf751623840 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Thu, 18 Sep 2014 18:29:00 -0300 Subject: [PATCH 35/45] fix pubkey param. add test --- js/models/core/WalletFactory.js | 42 +++++++++++++++++++-------------- test/test.WalletFactory.js | 9 ++++++- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/js/models/core/WalletFactory.js b/js/models/core/WalletFactory.js index b1594937c..88770d0d8 100644 --- a/js/models/core/WalletFactory.js +++ b/js/models/core/WalletFactory.js @@ -114,12 +114,12 @@ WalletFactory.prototype.fromObj = function(inObj, skipFields) { /** * @desc Imports a wallet from an encrypted base64 object * @param {string} base64 - the base64 encoded object - * @param {string} password - password to decrypt it + * @param {string} passphrase - passphrase to decrypt it * @param {string[]} skipFields - fields to ignore when importing * @return {Wallet} */ -WalletFactory.prototype.fromEncryptedObj = function(base64, password, skipFields) { - this.storage.setPassphrase(password); +WalletFactory.prototype.fromEncryptedObj = function(base64, passphrase, skipFields) { + this.storage.setPassphrase(passphrase); var walletObj = this.storage.import(base64); if (!walletObj) return false; return this.fromObj(walletObj, skipFields); @@ -130,15 +130,15 @@ WalletFactory.prototype.fromEncryptedObj = function(base64, password, skipFields * @TODO: this is essentialy the same method as {@link WalletFactory#fromEncryptedObj}! * @desc Imports a wallet from an encrypted base64 object * @param {string} base64 - the base64 encoded object - * @param {string} password - password to decrypt it + * @param {string} passphrase - passphrase to decrypt it * @param {string[]} skipFields - fields to ignore when importing * @return {Wallet} */ -WalletFactory.prototype.import = function(base64, password, skipFields) { +WalletFactory.prototype.import = function(base64, passphrase, skipFields) { var self = this; - var w = self.fromEncryptedObj(base64, password, skipFields); + var w = self.fromEncryptedObj(base64, passphrase, skipFields); - if (!w) throw new Error('Wrong password'); + if (!w) throw new Error('Wrong passphrase'); return w; }; @@ -248,7 +248,6 @@ WalletFactory.prototype.create = function(opts, cb) { }); log.debug('\t### TxProposals Initialized'); - this.storage.setPassphrase(opts.passphrase); opts.storage = this.storage; opts.network = this.networks[opts.networkName]; @@ -260,6 +259,7 @@ WalletFactory.prototype.create = function(opts, cb) { opts.totalCopayers = totalCopayers; opts.version = opts.version || this.version; + this.storage.setPassphrase(opts.passphrase); var w = this._getWallet(opts); var self = this; w.store(function(err) { @@ -394,7 +394,7 @@ WalletFactory.prototype.joinCreateSession = function(opts, cb) { //Create our PrivateK var privateKey = new PrivateKey(privOpts); log.debug('\t### PrivateKey Initialized'); - var opts = { + var joinOpts = { copayerId: privateKey.getId(), privkey: privateKey.getIdPriv(), key: privateKey.getIdKey(), @@ -414,23 +414,29 @@ WalletFactory.prototype.joinCreateSession = function(opts, cb) { return cb('joinError'); }); - joinNetwork.start(opts, function() { - joinNetwork.greet(decodedSecret.pubKey, opts.secretNumber); + joinNetwork.start(joinOpts, function() { + + joinNetwork.greet(decodedSecret.pubKey, joinOpts.secretNumber); joinNetwork.on('data', function(sender, data) { if (data.type === 'walletId' && data.opts) { if (data.networkName !== decodedSecret.networkName) { return cb('badNetwork'); } - data.opts.privateKey = privateKey; - data.opts.nickname = opts.nickname; - data.opts.passphrase = opts.passphrase; - data.opts.id = data.walletId; - self.create(data.opts, function(err, w) { - if (!err & w) { - w.sendWalletReady(s.pubKey); + var walletOpts = _.clone(data.opts); + walletOpts.id = data.walletId; + + walletOpts.privateKey = privateKey; + walletOpts.nickname = opts.nickname; + walletOpts.passphrase = opts.passphrase; + + self.create(walletOpts, function(err, w) { + + if (w) { + w.sendWalletReady(decodedSecret.pubKey); } else { if (!err) err = 'walletFull'; + log.info(err); } return cb(err, w); }); diff --git a/test/test.WalletFactory.js b/test/test.WalletFactory.js index 517bf44bd..0b1a16d3a 100644 --- a/test/test.WalletFactory.js +++ b/test/test.WalletFactory.js @@ -443,10 +443,17 @@ describe('WalletFactory model', function() { networkName: 'testnet', opts: {}, }); - wf.create = sinon.stub().yields(null, 'wallet'); + + var w = sinon.stub(); + w.sendWalletReady = sinon.spy(); + wf.create = sinon.stub().yields(null, w); wf.joinCreateSession(opts, function(err, w) { net.start.calledOnce.should.equal(true); wf.create.calledOnce.should.equal(true); + wf.create.calledOnce.should.equal(true); + + w.sendWalletReady.calledOnce.should.equal(true); + w.sendWalletReady.getCall(0).args[0].should.equal('03ddbc4711534bc62ccf576ab05f2a0afd11f9e2f4016781f3f5a88de9543a229a'); done(); }); }); From 409cef4d4be81550009dfb2d3066493fb53f87e2 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Thu, 18 Sep 2014 19:20:00 -0300 Subject: [PATCH 36/45] fix interfase and loggin --- config.js | 4 ++-- js/controllers/home.js | 3 +-- js/controllers/open.js | 18 +++++++++++++----- js/models/Storage.js | 8 +++++++- js/models/core/TxProposals.js | 1 - plugins/GoogleDrive.js | 17 ++++++++--------- views/home.html | 2 +- 7 files changed, 32 insertions(+), 21 deletions(-) diff --git a/config.js b/config.js index 7b67351bd..d4772c096 100644 --- a/config.js +++ b/config.js @@ -53,8 +53,8 @@ var defaultConfig = { verbose: 1, plugins: { - LocalStorage: true, - // GoogleDrive: true, + //LocalStorage: true, + GoogleDrive: true, }, GoogleDrive: { diff --git a/js/controllers/home.js b/js/controllers/home.js index b0d325448..23119ded1 100644 --- a/js/controllers/home.js +++ b/js/controllers/home.js @@ -5,8 +5,7 @@ angular.module('copayApp.controllers').controller('HomeController', function($sc controllerUtils.redirIfLogged(); $scope.retreiving = true; - - walletFactory.getWallets(function(ret) { + walletFactory.getWallets(function(err,ret) { $scope.retreiving = false; $scope.hasWallets = (ret && ret.length > 0) ? true : false; }); diff --git a/js/controllers/open.js b/js/controllers/open.js index 8fb5df483..a98ff6a5e 100644 --- a/js/controllers/open.js +++ b/js/controllers/open.js @@ -16,16 +16,23 @@ angular.module('copayApp.controllers').controller('OpenController', function($sc $scope.loading = false; $scope.retreiving = true; - walletFactory.getWallets(function(wallets) { + walletFactory.getWallets(function(err, wallets) { - if (!wallets || !wallets.length) { + if (err || !wallets || !wallets.length) { $location.path('/'); } else { + $scope.retreiving = false; $scope.wallets = wallets.sort(cmp); walletFactory.storage.getLastOpened(function(ret) { + if (ret && _.indexOf(_.pluck($scope.wallets, 'id')) == -1) + ret = null; + $scope.selectedWalletId = ret || ($scope.wallets[0] && $scope.wallets[0].id); - $scope.retreiving = false; + + setTimeout(function() { + $rootScope.$digest(); + }, 0); }); } }); @@ -49,9 +56,10 @@ angular.module('copayApp.controllers').controller('OpenController', function($sc $scope.loading = false; notification.error('Error', err.errMsg || 'Wrong password'); $rootScope.$digest(); + } else { + $rootScope.updatingBalance = true; + controllerUtils.startNetwork(w, $scope); } - $rootScope.updatingBalance = true; - controllerUtils.startNetwork(w, $scope); }); }); }; diff --git a/js/models/Storage.js b/js/models/Storage.js index 4c8c658cb..36d5f5fda 100644 --- a/js/models/Storage.js +++ b/js/models/Storage.js @@ -4,12 +4,13 @@ var CryptoJS = require('node-cryptojs-aes').CryptoJS; var bitcore = require('bitcore'); var preconditions = require('preconditions').instance(); var _ = require('underscore'); - +var CACHE_DURATION = 1000 * 60 * 5; var id = 0; function Storage(opts) { opts = opts || {}; + this.wListCache = {}; this.__uniqueid = ++id; if (opts.password) this.setPassphrase(opts.password); @@ -211,6 +212,9 @@ Storage.prototype.getWalletIds = function(cb) { Storage.prototype.getWallets = function(cb) { preconditions.checkArgument(cb); + if (this.wListCache.ts > Date.now()) + return cb(this.wListCache.data) + var wallets = []; var self = this; @@ -228,6 +232,8 @@ Storage.prototype.getWallets = function(cb) { name: name, }); if (++i == l) { + self.wListCache.data = wallets; + self.wListCache.ts = Date.now() + CACHE_DURATION; return cb(wallets); } }) diff --git a/js/models/core/TxProposals.js b/js/models/core/TxProposals.js index 44f1f9bb7..80e3648c5 100644 --- a/js/models/core/TxProposals.js +++ b/js/models/core/TxProposals.js @@ -50,7 +50,6 @@ TxProposals.prototype.getNtxidsSince = function(sinceTs) { if (txp.createdTs >= sinceTs) ret.push(ii); } -console.log('[TxProposals.js.52:ret:]',ret); //TODO return ret; }; diff --git a/plugins/GoogleDrive.js b/plugins/GoogleDrive.js index 8cf41d72e..ee4260ea5 100644 --- a/plugins/GoogleDrive.js +++ b/plugins/GoogleDrive.js @@ -3,6 +3,7 @@ var preconditions = require('preconditions').singleton(); var loaded = 0; var SCOPES = 'https://www.googleapis.com/auth/drive'; +var log = require('../js/log'); function GoogleDrive(config) { preconditions.checkArgument(config && config.clientId, 'No clientId at GoogleDrive config'); @@ -24,8 +25,7 @@ function GoogleDrive(config) { }; window.InitGoogleDrive = function() { - - // console.log('[googleDrive.js.18] setting loaded'); //TODO + log.debug('googleDrive loadeded'); //TODO loaded = 1; }; @@ -47,7 +47,7 @@ GoogleDrive.prototype.initLoaded = function() { */ GoogleDrive.prototype.checkAuth = function() { - console.log('\tChecking google Auth'); + log.debug('Google Drive: Checking Auth'); gapi.auth.authorize({ 'client_id': this.clientId, 'scope': SCOPES, @@ -61,7 +61,7 @@ GoogleDrive.prototype.checkAuth = function() { */ GoogleDrive.prototype.handleAuthResult = function(authResult) { var self = this; - // console.log('[googleDrive.js.39:authResult:]', authResult); //TODO + log.debug('Google Drive: authResult', authResult); //TODO if (authResult.error) { if (authResult.error) { @@ -93,7 +93,7 @@ GoogleDrive.prototype._httpGet = function(theUrl) { } GoogleDrive.prototype.getItem = function(k, cb) { - console.log('[googleDrive.js.95:getItem:]', k); //TODO + //console.log('[googleDrive.js.95:getItem:]', k); //TODO var self = this; self.checkReady(); @@ -208,7 +208,7 @@ GoogleDrive.prototype._mkdir = function(cb) { preconditions.checkArgument(cb); var self = this; - console.log('Creating drive folder ' + this.home); + log.debug('Creating drive folder ' + this.home); var request = gapi.client.request({ 'path': '/drive/v2/files', @@ -231,18 +231,17 @@ GoogleDrive.prototype._idForName = function(name, cb) { var self = this; if (!self.isReady) { - console.log('\tWaiting for Drive'); + log.debug('Waiting for Google Drive'); self.ts = self.ts * 1.5; return setTimeout(self._idForName.bind(self, name, cb), self.ts); } - // console.log('[googleDrive.js.178:name:]', name); //TODO if (self.idCache[name]) { // console.log('[googleDrive.js.212:] FROM CACHE', name, self.idCache[name]); //TODO return cb(self.idCache[name]); } - console.log('Querying for: ', name); //TODO + log.debug('GoogleDrive Querying for: ', name); //TODO var args; var idParent = name == this.home ? 'root' : self.idCache[this.home]; diff --git a/views/home.html b/views/home.html index 7018435e9..7c1c71e11 100644 --- a/views/home.html +++ b/views/home.html @@ -3,7 +3,7 @@ Retreiving information from storage...

-
+
Copay
From 4bf7bbe73fcd8e6dbde2352d2c0f70a2c6cabb7b Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Thu, 18 Sep 2014 19:34:27 -0300 Subject: [PATCH 37/45] defaults to localStorage --- config.js | 4 ++-- js/controllers/more.js | 1 + js/services/pluginManager.js | 1 - test/unit/controllers/controllersSpec.js | 5 ++++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/config.js b/config.js index d4772c096..811431cd6 100644 --- a/config.js +++ b/config.js @@ -53,8 +53,8 @@ var defaultConfig = { verbose: 1, plugins: { - //LocalStorage: true, - GoogleDrive: true, + LocalStorage: true, + //GoogleDrive: true, }, GoogleDrive: { diff --git a/js/controllers/more.js b/js/controllers/more.js index 5bd705d90..4fb673256 100644 --- a/js/controllers/more.js +++ b/js/controllers/more.js @@ -25,6 +25,7 @@ angular.module('copayApp.controllers').controller('MoreController', value: 100000000, decimals: 8 }]; + $scope.selectedAlternative = { name: w.settings.alternativeName, isoCode: w.settings.alternativeIsoCode diff --git a/js/services/pluginManager.js b/js/services/pluginManager.js index f5e6e165c..1b85d15a6 100644 --- a/js/services/pluginManager.js +++ b/js/services/pluginManager.js @@ -2,7 +2,6 @@ angular.module('copayApp.services').factory('pluginManager', function(angularLoad){ var pm = new copay.PluginManager(config); - var scripts = pm.scripts; for(var ii in scripts){ diff --git a/test/unit/controllers/controllersSpec.js b/test/unit/controllers/controllersSpec.js index 9d06092d2..748ae7a5d 100644 --- a/test/unit/controllers/controllersSpec.js +++ b/test/unit/controllers/controllersSpec.js @@ -15,12 +15,14 @@ saveAs = function(blob, filename) { var startServer = require('../../mocks/FakePayProServer'); describe("Unit: Controllers", function() { + config.plugins.LocalStorage=null; + config.plugins.GoogleDrive=null; + var invalidForm = { $invalid: true }; var scope; - var server; beforeEach(module('copayApp.services')); @@ -37,6 +39,7 @@ describe("Unit: Controllers", function() { alternativeIsoCode: 'LOL' }; + describe('More Controller', function() { var ctrl; beforeEach(inject(function($controller, $rootScope) { From e48e6e3fd571e0f2766582b323fa23f7d9d85701 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Fri, 19 Sep 2014 11:37:28 -0300 Subject: [PATCH 38/45] fix karma tests --- js/models/Storage.js | 1 - test/unit/controllers/controllersSpec.js | 7 +------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/js/models/Storage.js b/js/models/Storage.js index 36d5f5fda..6d5be0046 100644 --- a/js/models/Storage.js +++ b/js/models/Storage.js @@ -188,7 +188,6 @@ Storage.prototype.getWalletIds = function(cb) { preconditions.checkArgument(cb); var walletIds = []; var uniq = {}; - this.storage.allKeys(function(keys) { for (var ii in keys) { var key = keys[ii]; diff --git a/test/unit/controllers/controllersSpec.js b/test/unit/controllers/controllersSpec.js index 748ae7a5d..8b3eedb6f 100644 --- a/test/unit/controllers/controllersSpec.js +++ b/test/unit/controllers/controllersSpec.js @@ -15,7 +15,7 @@ saveAs = function(blob, filename) { var startServer = require('../../mocks/FakePayProServer'); describe("Unit: Controllers", function() { - config.plugins.LocalStorage=null; + config.plugins.LocalStorage=true; config.plugins.GoogleDrive=null; var invalidForm = { @@ -76,11 +76,6 @@ describe("Unit: Controllers", function() { expect(saveAsLastCall.filename).equal('myTESTwullet-testID-keybackup.json.aes'); }); - it('Backup controller #delete', function() { - expect(scope.wallet).not.equal(undefined); - scope.deleteWallet(); - expect(scope.wallet).equal(undefined); - }); }); describe('Create Controller', function() { From 4b56e06472aea840337605b8aab4a02262250112 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Fri, 19 Sep 2014 15:00:38 -0300 Subject: [PATCH 39/45] fix async getName calls --- config.js | 4 ++-- js/models/Storage.js | 25 ++++++++++++++----------- test/test.Storage.js | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/config.js b/config.js index 811431cd6..d4772c096 100644 --- a/config.js +++ b/config.js @@ -53,8 +53,8 @@ var defaultConfig = { verbose: 1, plugins: { - LocalStorage: true, - //GoogleDrive: true, + //LocalStorage: true, + GoogleDrive: true, }, GoogleDrive: { diff --git a/js/models/Storage.js b/js/models/Storage.js index 6d5be0046..8ccd4cda5 100644 --- a/js/models/Storage.js +++ b/js/models/Storage.js @@ -224,18 +224,21 @@ Storage.prototype.getWallets = function(cb) { return cb([]); for (var ii in ids) { - var id = ids[ii]; - self.getName(id, function(name) { - wallets.push({ - id: id, - name: name, + // Create a closure for async calls. + (function() { + var id = ids[ii]; + self.getName(id, function(name) { + wallets.push({ + id: id, + name: name, + }); + if (++i == l) { + self.wListCache.data = wallets; + self.wListCache.ts = Date.now() + CACHE_DURATION; + return cb(wallets); + } }); - if (++i == l) { - self.wListCache.data = wallets; - self.wListCache.ts = Date.now() + CACHE_DURATION; - return cb(wallets); - } - }) + })(); } }); }; diff --git a/test/test.Storage.js b/test/test.Storage.js index 186a30070..559dae141 100644 --- a/test/test.Storage.js +++ b/test/test.Storage.js @@ -1,5 +1,6 @@ 'use strict'; var chai = chai || require('chai'); +var sinon = require('sinon'); var should = chai.should(); var is_browser = typeof process == 'undefined' || typeof process.versions === 'undefined'; var copay = copay || require('../copay'); @@ -153,6 +154,7 @@ describe('Storage model', function() { s.set('1', "hola", 'juan', function() { s.set('2', "hola", 'juan', function() { s.setName(1, 'hola', function() { + s.getWallets(function(ws) { ws[0].should.deep.equal({ id: '1', @@ -168,7 +170,36 @@ describe('Storage model', function() { }); }); }); - }); describe('#deleteWallet', function() { + it('should retreive wallets from storage (with delay)', function(done) { + s.set('1', "hola", 'juan', function() { + s.set('2', "hola", 'juan', function() { + s.setName(1, 'hola', function() { + + var orig = s.getName.bind(s); + s.getName = function(wid, cb) { + setTimeout(function() { + orig(wid, cb); + },1); + }; + + s.getWallets(function(ws) { + ws[0].should.deep.equal({ + id: '1', + name: 'hola', + }); + ws[1].should.deep.equal({ + id: '2', + name: undefined + }); + done(); + }); + }); + }); + }); + }); + }); + + describe('#deleteWallet', function() { it('should fail to delete a unexisting wallet', function(done) { s.set('1', "hola", 'juan', function() { s.set('2', "hola", 'juan', function() { From 810ce0bf5dab22fcd4191f45a251912fc04df619 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Fri, 19 Sep 2014 15:26:57 -0300 Subject: [PATCH 40/45] small refactor --- js/models/Storage.js | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/js/models/Storage.js b/js/models/Storage.js index 8ccd4cda5..35cf1f976 100644 --- a/js/models/Storage.js +++ b/js/models/Storage.js @@ -223,23 +223,19 @@ Storage.prototype.getWallets = function(cb) { if (!l) return cb([]); - for (var ii in ids) { - // Create a closure for async calls. - (function() { - var id = ids[ii]; - self.getName(id, function(name) { - wallets.push({ - id: id, - name: name, - }); - if (++i == l) { - self.wListCache.data = wallets; - self.wListCache.ts = Date.now() + CACHE_DURATION; - return cb(wallets); - } + _.each(ids, function(id) { + self.getName(id, function(name) { + wallets.push({ + id: id, + name: name, }); - })(); - } + if (++i == l) { + self.wListCache.data = wallets; + self.wListCache.ts = Date.now() + CACHE_DURATION; + return cb(wallets); + } + }); + }); }); }; From d3918178191231be59b239eeef3cb3b27bb540d8 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Fri, 19 Sep 2014 16:04:27 -0300 Subject: [PATCH 41/45] fix error handling in google drive --- plugins/GoogleDrive.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/GoogleDrive.js b/plugins/GoogleDrive.js index ee4260ea5..4c8783ac6 100644 --- a/plugins/GoogleDrive.js +++ b/plugins/GoogleDrive.js @@ -172,7 +172,9 @@ GoogleDrive.prototype.setItem = function(k, v, cb) { // console.log('[googleDrive.js.148:args:]', args); //TODO var request = gapi.client.request(args); - request.execute(cb); + request.execute(function(ret) { + return cb(ret.kind === 'drive#file' ? null : new Error('error saving file on drive')); + }); }); }); }; From 2bb809f2ce2b7364a7b4a0786e3b22c682d8b4cb Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Fri, 19 Sep 2014 17:30:56 -0300 Subject: [PATCH 42/45] default localstorage --- config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.js b/config.js index d4772c096..811431cd6 100644 --- a/config.js +++ b/config.js @@ -53,8 +53,8 @@ var defaultConfig = { verbose: 1, plugins: { - //LocalStorage: true, - GoogleDrive: true, + LocalStorage: true, + //GoogleDrive: true, }, GoogleDrive: { From 6326abebe2dca1190fc56613fea7b1997837c8d0 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Sat, 20 Sep 2014 07:30:02 -0300 Subject: [PATCH 43/45] add comments to config --- config.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/config.js b/config.js index 811431cd6..d6a7eb7dc 100644 --- a/config.js +++ b/config.js @@ -58,10 +58,19 @@ var defaultConfig = { }, GoogleDrive: { - // for localhost: + home: 'copay', + + /* + * This clientId was generated at: + * https://console.developers.google.com/project + * To run Copay with Google Drive at your domain you need + * to generata your own Id. + */ + // for localhost:3001 you can use you can: clientId: '232630733383-a35gcnovnkgka94394i88gq60vtjb4af.apps.googleusercontent.com', - // clientId: '232630733383-29u1khqf5i8qubhf0homhpb2m14b5lja.apps.googleusercontent.com', - home: 'copay' + + // for copay.io: + // clientId: '1036948132229-biqm3b8sirik9lt5rtvjo9kjjpotn4ac.apps.googleusercontent.com', }, }; if (typeof module !== 'undefined') From 6a4409ad85f80c2db27aafac8571b44f7958d13c Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Sat, 20 Sep 2014 07:36:05 -0300 Subject: [PATCH 44/45] use logging system --- js/models/core/PluginManager.js | 2 +- js/services/pluginManager.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/js/models/core/PluginManager.js b/js/models/core/PluginManager.js index 7aced3b49..c7574e794 100644 --- a/js/models/core/PluginManager.js +++ b/js/models/core/PluginManager.js @@ -31,7 +31,7 @@ PluginManager.prototype._register = function(obj, name) { var type = obj.type; var kind = PluginManager.TYPE[type]; - preconditions.checkArgument(kind, 'Plugin has unkown type' + name); + preconditions.checkArgument(kind, 'Plugin has unknown type' + name); preconditions.checkState(kind !== PluginManager.KIND_UNIQUE || !this.registered[type], 'Plugin kind already registered: ' + name); if (kind === PluginManager.KIND_UNIQUE) { diff --git a/js/services/pluginManager.js b/js/services/pluginManager.js index 1b85d15a6..3d31ec3ce 100644 --- a/js/services/pluginManager.js +++ b/js/services/pluginManager.js @@ -7,7 +7,7 @@ angular.module('copayApp.services').factory('pluginManager', function(angularLoa for(var ii in scripts){ var src = scripts[ii].src; - console.log('\tLoading ',src); //TODO + log.info('\tLoading ',src); //TODO angularLoad.loadScript(src) .then(scripts[ii].then || null) .catch(function() { From 3f37509b863912c9ab9f875cec0d246ad2860f2e Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 22 Sep 2014 09:35:41 -0300 Subject: [PATCH 45/45] no log on services --- js/services/pluginManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/services/pluginManager.js b/js/services/pluginManager.js index 3d31ec3ce..1b85d15a6 100644 --- a/js/services/pluginManager.js +++ b/js/services/pluginManager.js @@ -7,7 +7,7 @@ angular.module('copayApp.services').factory('pluginManager', function(angularLoa for(var ii in scripts){ var src = scripts[ii].src; - log.info('\tLoading ',src); //TODO + console.log('\tLoading ',src); //TODO angularLoad.loadScript(src) .then(scripts[ii].then || null) .catch(function() {