mirror of https://github.com/BTCPrivate/copay.git
refactor lock warning and add tests
This commit is contained in:
parent
fb3a7191e5
commit
35ab711846
|
@ -112,6 +112,7 @@
|
||||||
<script src="js/controllers/settings.js"></script>
|
<script src="js/controllers/settings.js"></script>
|
||||||
<script src="js/controllers/uriPayment.js"></script>
|
<script src="js/controllers/uriPayment.js"></script>
|
||||||
<script src="js/controllers/version.js"></script>
|
<script src="js/controllers/version.js"></script>
|
||||||
|
<script src="js/controllers/warning.js"></script>
|
||||||
|
|
||||||
<!-- PLACEHOLDER: CORDOVA SRIPT -->
|
<!-- PLACEHOLDER: CORDOVA SRIPT -->
|
||||||
<script src="js/mobile.js"></script>
|
<script src="js/mobile.js"></script>
|
||||||
|
|
|
@ -1,90 +1,77 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('SidebarController',
|
angular.module('copayApp.controllers').controller('SidebarController', function($scope, $rootScope, $sce, $location, $http, notification, controllerUtils) {
|
||||||
function($scope, $rootScope, $sce, $location, $http, notification, controllerUtils) {
|
|
||||||
|
|
||||||
$scope.menu = [{
|
$scope.menu = [{
|
||||||
'title': 'Receive',
|
'title': 'Receive',
|
||||||
'icon': 'fi-arrow-left',
|
'icon': 'fi-arrow-left',
|
||||||
'link': 'receive'
|
'link': 'receive'
|
||||||
}, {
|
}, {
|
||||||
'title': 'Send',
|
'title': 'Send',
|
||||||
'icon': 'fi-arrow-right',
|
'icon': 'fi-arrow-right',
|
||||||
'link': 'send'
|
'link': 'send'
|
||||||
}, {
|
}, {
|
||||||
'title': 'History',
|
'title': 'History',
|
||||||
'icon': 'fi-clipboard-pencil',
|
'icon': 'fi-clipboard-pencil',
|
||||||
'link': 'history'
|
'link': 'history'
|
||||||
}, {
|
}, {
|
||||||
'title': 'More',
|
'title': 'More',
|
||||||
'icon': 'fi-download',
|
'icon': 'fi-download',
|
||||||
'link': 'backup'
|
'link': 'backup'
|
||||||
}];
|
}];
|
||||||
|
|
||||||
$scope.signout = function() {
|
$scope.signout = function() {
|
||||||
logout();
|
logout();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ensures a graceful disconnect
|
// Ensures a graceful disconnect
|
||||||
window.onbeforeunload = logout;
|
window.onbeforeunload = function() {
|
||||||
|
controllerUtils.logout();
|
||||||
|
};
|
||||||
|
|
||||||
$scope.$on('$destroy', function() {
|
$scope.$on('$destroy', function() {
|
||||||
window.onbeforeunload = undefined;
|
window.onbeforeunload = undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$scope.refresh = function() {
|
||||||
|
var w = $rootScope.wallet;
|
||||||
|
w.connectToAll();
|
||||||
|
if ($rootScope.addrInfos.length > 0) {
|
||||||
|
controllerUtils.updateBalance(function() {
|
||||||
|
$rootScope.$digest();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.isActive = function(item) {
|
||||||
|
return item.link && item.link == $location.path().split('/')[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
function logout() {
|
||||||
|
var w = $rootScope.wallet;
|
||||||
|
if (w) {
|
||||||
|
w.disconnect();
|
||||||
|
controllerUtils.logout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ng-repeat defined number of times instead of repeating over array?
|
||||||
|
$scope.getNumber = function(num) {
|
||||||
|
return new Array(num);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init socket handlers (with no wallet yet)
|
||||||
|
controllerUtils.setSocketHandlers();
|
||||||
|
|
||||||
|
if ($rootScope.wallet) {
|
||||||
|
$scope.$on('$idleStart', function(a) {
|
||||||
|
notification.warning('Session will be closed', 'Your session is about to expire due to inactivity');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$scope.$on('$idleTimeout', function() {
|
||||||
$scope.refresh = function() {
|
$scope.signout();
|
||||||
var w = $rootScope.wallet;
|
notification.warning('Session closed', 'Session closed because a long time of inactivity');
|
||||||
w.connectToAll();
|
});
|
||||||
if ($rootScope.addrInfos.length > 0) {
|
}
|
||||||
controllerUtils.updateBalance(function() {
|
});
|
||||||
$rootScope.$digest();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.isActive = function(item) {
|
|
||||||
return item.link && item.link == $location.path().split('/')[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
function logout() {
|
|
||||||
var w = $rootScope.wallet;
|
|
||||||
if (w) {
|
|
||||||
w.disconnect();
|
|
||||||
controllerUtils.logout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ng-repeat defined number of times instead of repeating over array?
|
|
||||||
$scope.getNumber = function(num) {
|
|
||||||
return new Array(num);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init socket handlers (with no wallet yet)
|
|
||||||
controllerUtils.setSocketHandlers();
|
|
||||||
|
|
||||||
if ($rootScope.wallet) {
|
|
||||||
$scope.$on('$idleStart', function(a) {
|
|
||||||
notification.warning('Session will be closed', 'Your session is about to expire due to inactivity');
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.$on('$idleTimeout', function() {
|
|
||||||
$scope.signout();
|
|
||||||
notification.warning('Session closed', 'Session closed because a long time of inactivity');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.checkIfWarning = function() {
|
|
||||||
if ($rootScope.wallet && !$rootScope.wallet.isLocked) {
|
|
||||||
controllerUtils.redirIfLogged();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.ignoreLocked = function() {
|
|
||||||
if ($rootScope.wallet) {
|
|
||||||
$rootScope.wallet.isLocked = false;
|
|
||||||
controllerUtils.redirIfLogged();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
'use strict';
|
||||||
|
angular.module('copayApp.controllers').controller('WarningController', function($scope, $rootScope, $location, controllerUtils) {
|
||||||
|
|
||||||
|
|
||||||
|
$scope.checkLock = function() {
|
||||||
|
if (!$rootScope.tmp || !$rootScope.tmp.getLock()) {
|
||||||
|
controllerUtils.redirIfLogged();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
$scope.signout = function() {
|
||||||
|
controllerUtils.logout();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.ignoreLock = function() {
|
||||||
|
var w = $rootScope.tmp;
|
||||||
|
delete $rootScope['tmp'];
|
||||||
|
|
||||||
|
if (!w) {
|
||||||
|
$location.path('/');
|
||||||
|
} else {
|
||||||
|
w.ignoreLock = 1;
|
||||||
|
$scope.loading = true;
|
||||||
|
controllerUtils.startNetwork(w, $scope);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
|
@ -43,8 +43,8 @@ function Wallet(opts) {
|
||||||
|
|
||||||
this.id = opts.id || Wallet.getRandomId();
|
this.id = opts.id || Wallet.getRandomId();
|
||||||
this.name = opts.name;
|
this.name = opts.name;
|
||||||
this.isLocked = false;
|
|
||||||
|
|
||||||
|
this.ignoreLock = opts.ignoreLock;
|
||||||
this.verbose = opts.verbose;
|
this.verbose = opts.verbose;
|
||||||
this.publicKeyRing.walletId = this.id;
|
this.publicKeyRing.walletId = this.id;
|
||||||
this.txProposals.walletId = this.id;
|
this.txProposals.walletId = this.id;
|
||||||
|
@ -93,25 +93,25 @@ Wallet.prototype.connectToAll = function() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.getIsOpen = function() {
|
Wallet.prototype.getLock = function() {
|
||||||
return this.storage.getIsOpen(this.id);
|
return this.storage.getLock(this.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.setIsOpen = function() {
|
Wallet.prototype.setLock = function() {
|
||||||
return this.storage.setIsOpen(this.id);
|
return this.storage.setLock(this.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.closeIfOpen = function() {
|
Wallet.prototype.unlock = function() {
|
||||||
this.storage.removeIsOpen(this.id);
|
this.storage.removeLock(this.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype._checkLocked = function() {
|
Wallet.prototype.checkAndLock = function() {
|
||||||
if (this.getIsOpen()) {
|
if (this.getLock()) {
|
||||||
this.isLocked = true;
|
return true;
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.setIsOpen();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.setLock();
|
||||||
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype._handleIndexes = function(senderId, data, isInbound) {
|
Wallet.prototype._handleIndexes = function(senderId, data, isInbound) {
|
||||||
|
@ -432,6 +432,12 @@ Wallet.prototype.netStart = function(callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var net = this.network;
|
var net = this.network;
|
||||||
|
|
||||||
|
if (this.checkAndLock() && !this.ignoreLock) {
|
||||||
|
|
||||||
|
console.log('[Wallet.js.436] LOCKED' ); //TODO
|
||||||
|
this.emit('locked');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
net.removeAllListeners();
|
net.removeAllListeners();
|
||||||
net.on('connect', self._handleConnect.bind(self));
|
net.on('connect', self._handleConnect.bind(self));
|
||||||
|
@ -464,7 +470,6 @@ Wallet.prototype.netStart = function(callback) {
|
||||||
self.scheduleConnect();
|
self.scheduleConnect();
|
||||||
self.emit('txProposalsUpdated');
|
self.emit('txProposalsUpdated');
|
||||||
}, 10);
|
}, 10);
|
||||||
self._checkLocked();
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1018,9 +1023,7 @@ Wallet.prototype.indexDiscovery = function(start, change, cosigner, gap, cb) {
|
||||||
|
|
||||||
Wallet.prototype.disconnect = function() {
|
Wallet.prototype.disconnect = function() {
|
||||||
this.log('## DISCONNECTING');
|
this.log('## DISCONNECTING');
|
||||||
if (!this.isLocked) {
|
this.unlock();
|
||||||
this.closeIfOpen();
|
|
||||||
}
|
|
||||||
this.network.disconnect();
|
this.network.disconnect();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,8 @@ function Storage(opts) {
|
||||||
if (opts.localStorage) {
|
if (opts.localStorage) {
|
||||||
this.localStorage = opts.localStorage;
|
this.localStorage = opts.localStorage;
|
||||||
} else if (localStorage) {
|
} else if (localStorage) {
|
||||||
this.localStorage = localStorage;
|
this.localStorage = localStorage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var pps = {};
|
var pps = {};
|
||||||
|
@ -180,16 +180,16 @@ Storage.prototype.getLastOpened = function() {
|
||||||
return this.getGlobal('lastOpened');
|
return this.getGlobal('lastOpened');
|
||||||
}
|
}
|
||||||
|
|
||||||
Storage.prototype.setIsOpen = function(walletId) {
|
Storage.prototype.setLock = function(walletId) {
|
||||||
this.setGlobal(this._key(walletId, 'isOpen'), true);
|
this.setGlobal(this._key(walletId, 'Lock'), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Storage.prototype.getIsOpen = function(walletId) {
|
Storage.prototype.getLock = function(walletId) {
|
||||||
return this.getGlobal(this._key(walletId, 'isOpen'));
|
return this.getGlobal(this._key(walletId, 'Lock'));
|
||||||
}
|
}
|
||||||
|
|
||||||
Storage.prototype.removeIsOpen = function(walletId) {
|
Storage.prototype.removeLock = function(walletId) {
|
||||||
this.localStorage.removeItem(this._key(walletId, 'isOpen'));
|
this.removeGlobal(this._key(walletId, 'Lock'));
|
||||||
}
|
}
|
||||||
|
|
||||||
//obj contains keys to be set
|
//obj contains keys to be set
|
||||||
|
|
191
js/routes.js
191
js/routes.js
|
@ -2,100 +2,113 @@
|
||||||
|
|
||||||
//Setting up route
|
//Setting up route
|
||||||
angular
|
angular
|
||||||
.module('copayApp')
|
.module('copayApp')
|
||||||
.config(function($routeProvider) {
|
.config(function($routeProvider) {
|
||||||
|
|
||||||
$routeProvider
|
$routeProvider
|
||||||
.when('/', {
|
.when('/', {
|
||||||
templateUrl: 'views/home.html',
|
templateUrl: 'views/home.html',
|
||||||
validate: false
|
validate: false
|
||||||
})
|
})
|
||||||
.when('/open', {
|
.when('/open', {
|
||||||
templateUrl: 'views/open.html',
|
templateUrl: 'views/open.html',
|
||||||
validate: false
|
validate: false
|
||||||
})
|
})
|
||||||
.when('/join', {
|
.when('/join', {
|
||||||
templateUrl: 'views/join.html',
|
templateUrl: 'views/join.html',
|
||||||
validate: false
|
validate: false
|
||||||
})
|
})
|
||||||
.when('/import', {
|
.when('/import', {
|
||||||
templateUrl: 'views/import.html',
|
templateUrl: 'views/import.html',
|
||||||
validate: false
|
validate: false
|
||||||
})
|
})
|
||||||
.when('/setup', {
|
.when('/setup', {
|
||||||
templateUrl: 'views/setup.html',
|
templateUrl: 'views/setup.html',
|
||||||
validate: false
|
validate: false
|
||||||
})
|
})
|
||||||
.when('/copayers', {
|
.when('/copayers', {
|
||||||
templateUrl: 'views/copayers.html',
|
templateUrl: 'views/copayers.html',
|
||||||
validate: true
|
validate: true
|
||||||
})
|
})
|
||||||
.when('/receive', {
|
.when('/receive', {
|
||||||
templateUrl: 'views/addresses.html',
|
templateUrl: 'views/addresses.html',
|
||||||
validate: true
|
validate: true
|
||||||
})
|
})
|
||||||
.when('/history', {
|
.when('/history', {
|
||||||
templateUrl: 'views/transactions.html',
|
templateUrl: 'views/transactions.html',
|
||||||
validate: true
|
validate: true
|
||||||
})
|
})
|
||||||
.when('/send', {
|
.when('/send', {
|
||||||
templateUrl: 'views/send.html',
|
templateUrl: 'views/send.html',
|
||||||
validate: true
|
validate: true
|
||||||
})
|
})
|
||||||
.when('/backup', {
|
.when('/backup', {
|
||||||
templateUrl: 'views/backup.html',
|
templateUrl: 'views/backup.html',
|
||||||
validate: true
|
validate: true
|
||||||
})
|
})
|
||||||
.when('/settings', {
|
.when('/settings', {
|
||||||
templateUrl: 'views/settings.html',
|
templateUrl: 'views/settings.html',
|
||||||
validate: false
|
validate: false
|
||||||
})
|
})
|
||||||
.when('/unsupported', {
|
.when('/unsupported', {
|
||||||
templateUrl: 'views/unsupported.html'
|
templateUrl: 'views/unsupported.html'
|
||||||
})
|
})
|
||||||
.when('/uri-payment/:data', {
|
.when('/uri-payment/:data', {
|
||||||
templateUrl: 'views/uri-payment.html'
|
templateUrl: 'views/uri-payment.html'
|
||||||
})
|
})
|
||||||
.when('/warning', {
|
.when('/warning', {
|
||||||
templateUrl: 'views/warning.html',
|
templateUrl: 'views/warning.html',
|
||||||
validate: true
|
validate: true
|
||||||
})
|
})
|
||||||
.otherwise({
|
.otherwise({
|
||||||
templateUrl: 'views/errors/404.html',
|
templateUrl: 'views/errors/404.html',
|
||||||
title: 'Error'
|
title: 'Error'
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
//Setting HTML5 Location Mode
|
//Setting HTML5 Location Mode
|
||||||
angular
|
angular
|
||||||
.module('copayApp')
|
.module('copayApp')
|
||||||
.config(function($locationProvider, $idleProvider) {
|
.config(function($locationProvider, $idleProvider) {
|
||||||
$locationProvider
|
$locationProvider
|
||||||
.html5Mode(false)
|
.html5Mode(false)
|
||||||
.hashPrefix('!');
|
.hashPrefix('!');
|
||||||
// IDLE timeout
|
// IDLE timeout
|
||||||
$idleProvider.idleDuration(15 * 60); // in seconds
|
$idleProvider.idleDuration(15 * 60); // in seconds
|
||||||
$idleProvider.warningDuration(10); // in seconds
|
$idleProvider.warningDuration(10); // in seconds
|
||||||
})
|
})
|
||||||
.run(function($rootScope, $location, $idle) {
|
.run(function($rootScope, $location, $idle) {
|
||||||
$idle.watch();
|
$idle.watch();
|
||||||
$rootScope.$on('$routeChangeStart', function(event, next, current) {
|
$rootScope.$on('$routeChangeStart', function(event, next, current) {
|
||||||
if (!util.supports.data) {
|
if (!util.supports.data) {
|
||||||
$location.path('unsupported');
|
$location.path('unsupported');
|
||||||
} else {
|
} else {
|
||||||
if ((!$rootScope.wallet || !$rootScope.wallet.id) && next.validate) {
|
|
||||||
$idle.unwatch();
|
// Locked?
|
||||||
$location.path('/');
|
if ($rootScope.showLockWarning) {
|
||||||
}
|
if ($rootScope.tmp) {
|
||||||
if ($rootScope.wallet && !$rootScope.wallet.isReady()) {
|
if ($location.path() !== '/warning') {
|
||||||
$location.path('/copayers');
|
$location.path('/warning');
|
||||||
}
|
}
|
||||||
if ($rootScope.wallet && $rootScope.wallet.isLocked) {
|
else {
|
||||||
$location.path('/warning');
|
delete $rootScope['showLockWarning'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
})
|
if ((!$rootScope.wallet || !$rootScope.wallet.id) && next.validate) {
|
||||||
.config(function($compileProvider) {
|
$idle.unwatch();
|
||||||
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|tel|chrome-extension|resource):/);
|
$location.path('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
// In creation?
|
||||||
|
if ($rootScope.wallet && !$rootScope.wallet.isReady()) {
|
||||||
|
$location.path('/copayers');
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
.config(function($compileProvider) {
|
||||||
|
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|tel|chrome-extension|resource):/);
|
||||||
|
});
|
||||||
|
|
|
@ -2,371 +2,381 @@
|
||||||
var bitcore = require('bitcore');
|
var bitcore = require('bitcore');
|
||||||
|
|
||||||
angular.module('copayApp.services')
|
angular.module('copayApp.services')
|
||||||
.factory('controllerUtils', function($rootScope, $sce, $location, notification, $timeout, Socket, video, uriHandler) {
|
.factory('controllerUtils', function($rootScope, $sce, $location, notification, $timeout, Socket, video, uriHandler) {
|
||||||
var root = {};
|
var root = {};
|
||||||
root.getVideoMutedStatus = function(copayer) {
|
root.getVideoMutedStatus = function(copayer) {
|
||||||
if (!$rootScope.videoInfo) return;
|
if (!$rootScope.videoInfo) return;
|
||||||
|
|
||||||
var vi = $rootScope.videoInfo[copayer]
|
var vi = $rootScope.videoInfo[copayer]
|
||||||
if (!vi) {
|
if (!vi) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
return vi.muted;
|
||||||
|
};
|
||||||
|
|
||||||
|
root.redirIfLogged = function() {
|
||||||
|
if ($rootScope.wallet) {
|
||||||
|
$rootScope.wallet.path('receive');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
root.logout = function() {
|
||||||
|
if ($rootScope.wallet)
|
||||||
|
$rootScope.wallet.disconnect();
|
||||||
|
|
||||||
|
Socket.removeAllListeners();
|
||||||
|
|
||||||
|
$rootScope.wallet = $rootScope.tmp = null;
|
||||||
|
delete $rootScope['wallet'];
|
||||||
|
|
||||||
|
video.close();
|
||||||
|
// Clear rootScope
|
||||||
|
for (var i in $rootScope) {
|
||||||
|
if (i.charAt(0) != '$') {
|
||||||
|
delete $rootScope[i];
|
||||||
}
|
}
|
||||||
return vi.muted;
|
|
||||||
};
|
|
||||||
|
|
||||||
root.redirIfLogged = function() {
|
|
||||||
var w = $rootScope.wallet;
|
|
||||||
if (w) {
|
|
||||||
$location.path('receive');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
root.logout = function() {
|
|
||||||
Socket.removeAllListeners();
|
|
||||||
|
|
||||||
$rootScope.wallet = null;
|
|
||||||
delete $rootScope['wallet'];
|
|
||||||
video.close();
|
|
||||||
// Clear rootScope
|
|
||||||
for (var i in $rootScope) {
|
|
||||||
if (i.charAt(0) != '$') {
|
|
||||||
delete $rootScope[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$location.path('/');
|
|
||||||
};
|
|
||||||
|
|
||||||
root.onError = function(scope) {
|
|
||||||
if (scope) scope.loading = false;
|
|
||||||
root.logout();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
root.onErrorDigest = function(scope, msg) {
|
$location.path('/');
|
||||||
root.onError(scope);
|
};
|
||||||
if (msg) {
|
|
||||||
notification.error('Error', msg);
|
|
||||||
}
|
|
||||||
$rootScope.$digest();
|
|
||||||
};
|
|
||||||
|
|
||||||
root.installStartupHandlers = function(wallet, $scope) {
|
root.onError = function(scope) {
|
||||||
wallet.on('connectionError', function() {
|
if (scope) scope.loading = false;
|
||||||
var message = "Looks like you are already connected to this wallet, please logout and try importing it again.";
|
root.logout();
|
||||||
notification.error('PeerJS Error', message);
|
}
|
||||||
root.onErrorDigest($scope);
|
|
||||||
});
|
|
||||||
wallet.on('serverError', function(m) {
|
|
||||||
var message = m || 'The PeerJS server is not responding, please try again';
|
|
||||||
$location.path('receive');
|
|
||||||
root.onErrorDigest($scope, message);
|
|
||||||
});
|
|
||||||
wallet.on('ready', function() {
|
|
||||||
$scope.loading = false;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
root.setupRootVariables = function() {
|
root.onErrorDigest = function(scope, msg) {
|
||||||
uriHandler.register();
|
root.onError(scope);
|
||||||
$rootScope.unitName = config.unitName;
|
if (msg) {
|
||||||
$rootScope.txAlertCount = 0;
|
notification.error('Error', msg);
|
||||||
$rootScope.insightError = 0;
|
|
||||||
$rootScope.isCollapsed = true;
|
|
||||||
$rootScope.$watch('txAlertCount', function(txAlertCount) {
|
|
||||||
if (txAlertCount && txAlertCount > 0) {
|
|
||||||
|
|
||||||
notification.info('New Transaction', ($rootScope.txAlertCount == 1) ? 'You have a pending transaction proposal' : 'You have ' + $rootScope.txAlertCount + ' pending transaction proposals', txAlertCount);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
$rootScope.$watch('receivedFund', function(receivedFund) {
|
|
||||||
if (receivedFund) {
|
|
||||||
var currentAddr;
|
|
||||||
for (var i = 0; i < $rootScope.addrInfos.length; i++) {
|
|
||||||
var addrinfo = $rootScope.addrInfos[i];
|
|
||||||
if (addrinfo.address.toString() == receivedFund[1] && !addrinfo.isChange) {
|
|
||||||
currentAddr = addrinfo.address.toString();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (currentAddr) {
|
|
||||||
//var beep = new Audio('sound/transaction.mp3');
|
|
||||||
notification.funds('Received fund', currentAddr, receivedFund);
|
|
||||||
//beep.play();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
root.startNetwork = function(w, $scope) {
|
|
||||||
Socket.removeAllListeners();
|
|
||||||
|
|
||||||
root.setupRootVariables();
|
|
||||||
root.installStartupHandlers(w, $scope);
|
|
||||||
root.setSocketHandlers();
|
|
||||||
|
|
||||||
var handlePeerVideo = function(err, peerID, url) {
|
|
||||||
if (err) {
|
|
||||||
delete $rootScope.videoInfo[peerID];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$rootScope.videoInfo[peerID] = {
|
|
||||||
url: encodeURI(url),
|
|
||||||
muted: peerID === w.network.peerId
|
|
||||||
};
|
|
||||||
$rootScope.$digest();
|
|
||||||
};
|
|
||||||
|
|
||||||
notification.enableHtml5Mode(); // for chrome: if support, enable it
|
|
||||||
|
|
||||||
w.on('badMessage', function(peerId) {
|
|
||||||
notification.error('Error', 'Received wrong message from peer ' + peerId);
|
|
||||||
});
|
|
||||||
w.on('ready', function(myPeerID) {
|
|
||||||
$rootScope.wallet = w;
|
|
||||||
if ($rootScope.pendingPayment) {
|
|
||||||
$location.path('send');
|
|
||||||
} else {
|
|
||||||
$location.path('receive');
|
|
||||||
}
|
|
||||||
if (!config.disableVideo)
|
|
||||||
video.setOwnPeer(myPeerID, w, handlePeerVideo);
|
|
||||||
});
|
|
||||||
|
|
||||||
w.on('publicKeyRingUpdated', function(dontDigest) {
|
|
||||||
root.setSocketHandlers();
|
|
||||||
if (!dontDigest) {
|
|
||||||
$rootScope.$digest();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
w.on('txProposalsUpdated', function(dontDigest) {
|
|
||||||
root.updateTxs();
|
|
||||||
// give sometime to the tx to propagate.
|
|
||||||
$timeout(function() {
|
|
||||||
root.updateBalance(function() {
|
|
||||||
if (!dontDigest) {
|
|
||||||
$rootScope.$digest();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, 3000);
|
|
||||||
});
|
|
||||||
w.on('txProposalEvent', function(e) {
|
|
||||||
var user = w.publicKeyRing.nicknameForCopayer(e.cId);
|
|
||||||
switch (e.type) {
|
|
||||||
case 'signed':
|
|
||||||
notification.info('Transaction Update', 'A transaction was signed by ' + user);
|
|
||||||
break;
|
|
||||||
case 'rejected':
|
|
||||||
notification.info('Transaction Update', 'A transaction was rejected by ' + user);
|
|
||||||
break;
|
|
||||||
case 'corrupt':
|
|
||||||
notification.error('Transaction Error', 'Received corrupt transaction from '+user);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
w.on('addressBookUpdated', function(dontDigest) {
|
|
||||||
if (!dontDigest) {
|
|
||||||
$rootScope.$digest();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
w.on('connectionError', function(msg) {
|
|
||||||
root.onErrorDigest(null, msg);
|
|
||||||
});
|
|
||||||
w.on('connect', function(peerID) {
|
|
||||||
if (peerID && !config.disableVideo) {
|
|
||||||
video.callPeer(peerID, handlePeerVideo);
|
|
||||||
}
|
|
||||||
$rootScope.$digest();
|
|
||||||
});
|
|
||||||
w.on('disconnect', function(peerID) {
|
|
||||||
$rootScope.$digest();
|
|
||||||
});
|
|
||||||
w.on('close', root.onErrorDigest);
|
|
||||||
w.netStart();
|
|
||||||
};
|
|
||||||
|
|
||||||
root.updateAddressList = function() {
|
|
||||||
var w = $rootScope.wallet;
|
|
||||||
if (w && w.isReady())
|
|
||||||
$rootScope.addrInfos = w.getAddressesInfo();
|
|
||||||
};
|
|
||||||
|
|
||||||
root.updateBalance = function(cb) {
|
|
||||||
var w = $rootScope.wallet;
|
|
||||||
if (!w) return root.onErrorDigest();
|
|
||||||
if (!w.isReady()) return;
|
|
||||||
|
|
||||||
$rootScope.balanceByAddr = {};
|
|
||||||
$rootScope.updatingBalance = true;
|
|
||||||
|
|
||||||
w.getBalance(function(err, balanceSat, balanceByAddrSat, safeBalanceSat) {
|
|
||||||
if (err) {
|
|
||||||
console.error('Error: ' + err.message); //TODO
|
|
||||||
root._setCommError();
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
root._clearCommError();
|
|
||||||
}
|
|
||||||
|
|
||||||
var satToUnit = 1 / config.unitToSatoshi;
|
|
||||||
var COIN = bitcore.util.COIN;
|
|
||||||
|
|
||||||
$rootScope.totalBalance = balanceSat * satToUnit;
|
|
||||||
$rootScope.totalBalanceBTC = (balanceSat / COIN);
|
|
||||||
$rootScope.availableBalance = safeBalanceSat * satToUnit;
|
|
||||||
$rootScope.availableBalanceBTC = (safeBalanceSat / COIN);
|
|
||||||
|
|
||||||
$rootScope.lockedBalance = (balanceSat - safeBalanceSat) * satToUnit;
|
|
||||||
$rootScope.lockedBalanceBTC = (balanceSat - safeBalanceSat) / COIN;
|
|
||||||
|
|
||||||
var balanceByAddr = {};
|
|
||||||
for (var ii in balanceByAddrSat) {
|
|
||||||
balanceByAddr[ii] = balanceByAddrSat[ii] * satToUnit;
|
|
||||||
}
|
|
||||||
$rootScope.balanceByAddr = balanceByAddr;
|
|
||||||
root.updateAddressList();
|
|
||||||
$rootScope.updatingBalance = false;
|
|
||||||
return cb ? cb() : null;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
root.updateTxs = function(opts) {
|
|
||||||
var w = $rootScope.wallet;
|
|
||||||
if (!w) return;
|
|
||||||
opts = opts || $rootScope.txsOpts || {};
|
|
||||||
|
|
||||||
var satToUnit = 1 / config.unitToSatoshi;
|
|
||||||
var myCopayerId = w.getMyCopayerId();
|
|
||||||
var pendingForUs = 0;
|
|
||||||
var inT = w.getTxProposals().sort(function(t1, t2) {
|
|
||||||
return t2.createdTs - t1.createdTs
|
|
||||||
});
|
|
||||||
var txs = [];
|
|
||||||
|
|
||||||
inT.forEach(function(i, index) {
|
|
||||||
if (opts.skip && (index < opts.skip[0] || index >= opts.skip[1])) {
|
|
||||||
return txs.push(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (myCopayerId != i.creator && !i.finallyRejected && !i.sentTs && !i.rejectedByUs && !i.signedByUs) {
|
|
||||||
pendingForUs++;
|
|
||||||
}
|
|
||||||
if (!i.finallyRejected && !i.sentTs) {
|
|
||||||
i.isPending = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!!opts.pending == !!i.isPending) {
|
|
||||||
var tx = i.builder.build();
|
|
||||||
var outs = [];
|
|
||||||
tx.outs.forEach(function(o) {
|
|
||||||
var addr = bitcore.Address.fromScriptPubKey(o.getScript(), config.networkName)[0].toString();
|
|
||||||
if (!w.addressIsOwn(addr, {
|
|
||||||
excludeMain: true
|
|
||||||
})) {
|
|
||||||
outs.push({
|
|
||||||
address: addr,
|
|
||||||
value: bitcore.util.valueToBigInt(o.getValue()) * satToUnit,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// extra fields
|
|
||||||
i.outs = outs;
|
|
||||||
i.fee = i.builder.feeSat * satToUnit;
|
|
||||||
i.missingSignatures = tx.countInputMissingSignatures(0);
|
|
||||||
i.actionList = getActionList(i.peerActions);
|
|
||||||
txs.push(i);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$rootScope.txs = txs;
|
|
||||||
$rootScope.txsOpts = opts;
|
|
||||||
if ($rootScope.pendingTxCount < pendingForUs) {
|
|
||||||
$rootScope.txAlertCount = pendingForUs;
|
|
||||||
}
|
|
||||||
$rootScope.pendingTxCount = pendingForUs;
|
|
||||||
};
|
|
||||||
|
|
||||||
function getActionList(actions) {
|
|
||||||
var peers = Object.keys(actions).map(function(i) {
|
|
||||||
return {cId: i, actions: actions[i] }
|
|
||||||
});
|
|
||||||
|
|
||||||
return peers.sort(function(a, b) {
|
|
||||||
return !!b.actions.create - !!a.actions.create;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
$rootScope.$digest();
|
||||||
|
};
|
||||||
|
|
||||||
$rootScope.$watch('insightError', function(status) {
|
root.installStartupHandlers = function(wallet, $scope) {
|
||||||
if (status) {
|
wallet.on('connectionError', function() {
|
||||||
if (status === -1) {
|
var message = "Looks like you are already connected to this wallet, please logout and try importing it again.";
|
||||||
notification.success('Networking restored', 'Connection to Insight re-established');
|
notification.error('PeerJS Error', message);
|
||||||
} else if (!isNaN(status)) {
|
root.onErrorDigest($scope);
|
||||||
notification.error('Networking problem', 'Connection to Insight lost, reconnecting (attempt number ' + status + ')');
|
});
|
||||||
|
wallet.on('serverError', function(m) {
|
||||||
|
var message = m || 'The PeerJS server is not responding, please try again';
|
||||||
|
$location.path('receive');
|
||||||
|
root.onErrorDigest($scope, message);
|
||||||
|
});
|
||||||
|
wallet.on('ready', function() {
|
||||||
|
$scope.loading = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
root.setupRootVariables = function() {
|
||||||
|
uriHandler.register();
|
||||||
|
$rootScope.unitName = config.unitName;
|
||||||
|
$rootScope.showLockWarning = false;
|
||||||
|
$rootScope.txAlertCount = 0;
|
||||||
|
$rootScope.insightError = 0;
|
||||||
|
$rootScope.isCollapsed = true;
|
||||||
|
$rootScope.$watch('txAlertCount', function(txAlertCount) {
|
||||||
|
if (txAlertCount && txAlertCount > 0) {
|
||||||
|
|
||||||
|
notification.info('New Transaction', ($rootScope.txAlertCount == 1) ? 'You have a pending transaction proposal' : 'You have ' + $rootScope.txAlertCount + ' pending transaction proposals', txAlertCount);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$rootScope.$watch('receivedFund', function(receivedFund) {
|
||||||
|
if (receivedFund) {
|
||||||
|
var currentAddr;
|
||||||
|
for (var i = 0; i < $rootScope.addrInfos.length; i++) {
|
||||||
|
var addrinfo = $rootScope.addrInfos[i];
|
||||||
|
if (addrinfo.address.toString() == receivedFund[1] && !addrinfo.isChange) {
|
||||||
|
currentAddr = addrinfo.address.toString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currentAddr) {
|
||||||
|
//var beep = new Audio('sound/transaction.mp3');
|
||||||
|
notification.funds('Received fund', currentAddr, receivedFund);
|
||||||
|
//beep.play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
root._setCommError = function(e) {
|
};
|
||||||
if ($rootScope.insightError < 0)
|
|
||||||
$rootScope.insightError = 0;
|
|
||||||
$rootScope.insightError++;
|
root.startNetwork = function(w, $scope) {
|
||||||
|
Socket.removeAllListeners();
|
||||||
|
|
||||||
|
root.setupRootVariables();
|
||||||
|
root.installStartupHandlers(w, $scope);
|
||||||
|
root.setSocketHandlers();
|
||||||
|
|
||||||
|
var handlePeerVideo = function(err, peerID, url) {
|
||||||
|
if (err) {
|
||||||
|
delete $rootScope.videoInfo[peerID];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$rootScope.videoInfo[peerID] = {
|
||||||
|
url: encodeURI(url),
|
||||||
|
muted: peerID === w.network.peerId
|
||||||
|
};
|
||||||
|
$rootScope.$digest();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
notification.enableHtml5Mode(); // for chrome: if support, enable it
|
||||||
|
w.on('locked', function() {
|
||||||
|
$rootScope.tmp = w;
|
||||||
|
$rootScope.showLockWarning=true;
|
||||||
|
$location.path('/warning');
|
||||||
|
$rootScope.$digest();
|
||||||
|
});
|
||||||
|
|
||||||
root._clearCommError = function(e) {
|
w.on('badMessage', function(peerId) {
|
||||||
if ($rootScope.insightError > 0)
|
notification.error('Error', 'Received wrong message from peer ' + peerId);
|
||||||
$rootScope.insightError = -1;
|
});
|
||||||
else
|
w.on('ready', function(myPeerID) {
|
||||||
$rootScope.insightError = 0;
|
$rootScope.wallet = w;
|
||||||
};
|
if ($rootScope.pendingPayment) {
|
||||||
|
$location.path('send');
|
||||||
root.setSocketHandlers = function() {
|
} else {
|
||||||
root.updateAddressList();
|
$location.path('receive');
|
||||||
if (!Socket.sysEventsSet) {
|
|
||||||
Socket.sysOn('error', root._setCommError);
|
|
||||||
Socket.sysOn('reconnect_error', root._setCommError);
|
|
||||||
Socket.sysOn('reconnect_failed', root._setCommError);
|
|
||||||
Socket.sysOn('connect', root._clearCommError);
|
|
||||||
Socket.sysOn('reconnect', root._clearCommError);
|
|
||||||
Socket.sysEventsSet = true;
|
|
||||||
}
|
}
|
||||||
if (!$rootScope.wallet) return;
|
if (!config.disableVideo)
|
||||||
|
video.setOwnPeer(myPeerID, w, handlePeerVideo);
|
||||||
|
});
|
||||||
|
|
||||||
var currentAddrs = Socket.getListeners();
|
w.on('publicKeyRingUpdated', function(dontDigest) {
|
||||||
var allAddrs = $rootScope.addrInfos;
|
root.setSocketHandlers();
|
||||||
|
if (!dontDigest) {
|
||||||
var newAddrs = [];
|
$rootScope.$digest();
|
||||||
for (var i in allAddrs) {
|
|
||||||
var a = allAddrs[i];
|
|
||||||
if (!currentAddrs[a.addressStr])
|
|
||||||
newAddrs.push(a);
|
|
||||||
}
|
}
|
||||||
for (var i = 0; i < newAddrs.length; i++) {
|
});
|
||||||
Socket.emit('subscribe', newAddrs[i].addressStr);
|
w.on('txProposalsUpdated', function(dontDigest) {
|
||||||
}
|
root.updateTxs();
|
||||||
newAddrs.forEach(function(a) {
|
// give sometime to the tx to propagate.
|
||||||
Socket.on(a.addressStr, function(txid) {
|
$timeout(function() {
|
||||||
|
root.updateBalance(function() {
|
||||||
if (!a.isChange)
|
if (!dontDigest) {
|
||||||
notification.funds('Funds received!', a.addressStr);
|
|
||||||
|
|
||||||
root.updateBalance(function() {
|
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}, 3000);
|
||||||
|
});
|
||||||
|
w.on('txProposalEvent', function(e) {
|
||||||
|
var user = w.publicKeyRing.nicknameForCopayer(e.cId);
|
||||||
|
switch (e.type) {
|
||||||
|
case 'signed':
|
||||||
|
notification.info('Transaction Update', 'A transaction was signed by ' + user);
|
||||||
|
break;
|
||||||
|
case 'rejected':
|
||||||
|
notification.info('Transaction Update', 'A transaction was rejected by ' + user);
|
||||||
|
break;
|
||||||
|
case 'corrupt':
|
||||||
|
notification.error('Transaction Error', 'Received corrupt transaction from '+user);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
w.on('addressBookUpdated', function(dontDigest) {
|
||||||
|
if (!dontDigest) {
|
||||||
|
$rootScope.$digest();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
w.on('connectionError', function(msg) {
|
||||||
|
root.onErrorDigest(null, msg);
|
||||||
|
});
|
||||||
|
w.on('connect', function(peerID) {
|
||||||
|
if (peerID && !config.disableVideo) {
|
||||||
|
video.callPeer(peerID, handlePeerVideo);
|
||||||
|
}
|
||||||
|
$rootScope.$digest();
|
||||||
|
});
|
||||||
|
w.on('disconnect', function(peerID) {
|
||||||
|
$rootScope.$digest();
|
||||||
|
});
|
||||||
|
w.on('close', root.onErrorDigest);
|
||||||
|
w.netStart();
|
||||||
|
};
|
||||||
|
|
||||||
|
root.updateAddressList = function() {
|
||||||
|
var w = $rootScope.wallet;
|
||||||
|
if (w && w.isReady())
|
||||||
|
$rootScope.addrInfos = w.getAddressesInfo();
|
||||||
|
};
|
||||||
|
|
||||||
|
root.updateBalance = function(cb) {
|
||||||
|
var w = $rootScope.wallet;
|
||||||
|
if (!w) return root.onErrorDigest();
|
||||||
|
if (!w.isReady()) return;
|
||||||
|
|
||||||
|
$rootScope.balanceByAddr = {};
|
||||||
|
$rootScope.updatingBalance = true;
|
||||||
|
|
||||||
|
w.getBalance(function(err, balanceSat, balanceByAddrSat, safeBalanceSat) {
|
||||||
|
if (err) {
|
||||||
|
console.error('Error: ' + err.message); //TODO
|
||||||
|
root._setCommError();
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
root._clearCommError();
|
||||||
|
}
|
||||||
|
|
||||||
|
var satToUnit = 1 / config.unitToSatoshi;
|
||||||
|
var COIN = bitcore.util.COIN;
|
||||||
|
|
||||||
|
$rootScope.totalBalance = balanceSat * satToUnit;
|
||||||
|
$rootScope.totalBalanceBTC = (balanceSat / COIN);
|
||||||
|
$rootScope.availableBalance = safeBalanceSat * satToUnit;
|
||||||
|
$rootScope.availableBalanceBTC = (safeBalanceSat / COIN);
|
||||||
|
|
||||||
|
$rootScope.lockedBalance = (balanceSat - safeBalanceSat) * satToUnit;
|
||||||
|
$rootScope.lockedBalanceBTC = (balanceSat - safeBalanceSat) / COIN;
|
||||||
|
|
||||||
|
var balanceByAddr = {};
|
||||||
|
for (var ii in balanceByAddrSat) {
|
||||||
|
balanceByAddr[ii] = balanceByAddrSat[ii] * satToUnit;
|
||||||
|
}
|
||||||
|
$rootScope.balanceByAddr = balanceByAddr;
|
||||||
|
root.updateAddressList();
|
||||||
|
$rootScope.updatingBalance = false;
|
||||||
|
return cb ? cb() : null;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
root.updateTxs = function(opts) {
|
||||||
|
var w = $rootScope.wallet;
|
||||||
|
if (!w) return;
|
||||||
|
opts = opts || $rootScope.txsOpts || {};
|
||||||
|
|
||||||
|
var satToUnit = 1 / config.unitToSatoshi;
|
||||||
|
var myCopayerId = w.getMyCopayerId();
|
||||||
|
var pendingForUs = 0;
|
||||||
|
var inT = w.getTxProposals().sort(function(t1, t2) {
|
||||||
|
return t2.createdTs - t1.createdTs
|
||||||
|
});
|
||||||
|
var txs = [];
|
||||||
|
|
||||||
|
inT.forEach(function(i, index) {
|
||||||
|
if (opts.skip && (index < opts.skip[0] || index >= opts.skip[1])) {
|
||||||
|
return txs.push(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myCopayerId != i.creator && !i.finallyRejected && !i.sentTs && !i.rejectedByUs && !i.signedByUs) {
|
||||||
|
pendingForUs++;
|
||||||
|
}
|
||||||
|
if (!i.finallyRejected && !i.sentTs) {
|
||||||
|
i.isPending = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!!opts.pending == !!i.isPending) {
|
||||||
|
var tx = i.builder.build();
|
||||||
|
var outs = [];
|
||||||
|
tx.outs.forEach(function(o) {
|
||||||
|
var addr = bitcore.Address.fromScriptPubKey(o.getScript(), config.networkName)[0].toString();
|
||||||
|
if (!w.addressIsOwn(addr, {
|
||||||
|
excludeMain: true
|
||||||
|
})) {
|
||||||
|
outs.push({
|
||||||
|
address: addr,
|
||||||
|
value: bitcore.util.valueToBigInt(o.getValue()) * satToUnit,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// extra fields
|
||||||
|
i.outs = outs;
|
||||||
|
i.fee = i.builder.feeSat * satToUnit;
|
||||||
|
i.missingSignatures = tx.countInputMissingSignatures(0);
|
||||||
|
i.actionList = getActionList(i.peerActions);
|
||||||
|
txs.push(i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$rootScope.txs = txs;
|
||||||
|
$rootScope.txsOpts = opts;
|
||||||
|
if ($rootScope.pendingTxCount < pendingForUs) {
|
||||||
|
$rootScope.txAlertCount = pendingForUs;
|
||||||
|
}
|
||||||
|
$rootScope.pendingTxCount = pendingForUs;
|
||||||
|
};
|
||||||
|
|
||||||
|
function getActionList(actions) {
|
||||||
|
var peers = Object.keys(actions).map(function(i) {
|
||||||
|
return {cId: i, actions: actions[i] }
|
||||||
|
});
|
||||||
|
|
||||||
|
return peers.sort(function(a, b) {
|
||||||
|
return !!b.actions.create - !!a.actions.create;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$rootScope.$watch('insightError', function(status) {
|
||||||
|
if (status) {
|
||||||
|
if (status === -1) {
|
||||||
|
notification.success('Networking restored', 'Connection to Insight re-established');
|
||||||
|
} else if (!isNaN(status)) {
|
||||||
|
notification.error('Networking problem', 'Connection to Insight lost, reconnecting (attempt number ' + status + ')');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
root._setCommError = function(e) {
|
||||||
|
if ($rootScope.insightError < 0)
|
||||||
|
$rootScope.insightError = 0;
|
||||||
|
$rootScope.insightError++;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
root._clearCommError = function(e) {
|
||||||
|
if ($rootScope.insightError > 0)
|
||||||
|
$rootScope.insightError = -1;
|
||||||
|
else
|
||||||
|
$rootScope.insightError = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
root.setSocketHandlers = function() {
|
||||||
|
root.updateAddressList();
|
||||||
|
if (!Socket.sysEventsSet) {
|
||||||
|
Socket.sysOn('error', root._setCommError);
|
||||||
|
Socket.sysOn('reconnect_error', root._setCommError);
|
||||||
|
Socket.sysOn('reconnect_failed', root._setCommError);
|
||||||
|
Socket.sysOn('connect', root._clearCommError);
|
||||||
|
Socket.sysOn('reconnect', root._clearCommError);
|
||||||
|
Socket.sysEventsSet = true;
|
||||||
|
}
|
||||||
|
if (!$rootScope.wallet) return;
|
||||||
|
|
||||||
|
var currentAddrs = Socket.getListeners();
|
||||||
|
var allAddrs = $rootScope.addrInfos;
|
||||||
|
|
||||||
|
var newAddrs = [];
|
||||||
|
for (var i in allAddrs) {
|
||||||
|
var a = allAddrs[i];
|
||||||
|
if (!currentAddrs[a.addressStr])
|
||||||
|
newAddrs.push(a);
|
||||||
|
}
|
||||||
|
for (var i = 0; i < newAddrs.length; i++) {
|
||||||
|
Socket.emit('subscribe', newAddrs[i].addressStr);
|
||||||
|
}
|
||||||
|
newAddrs.forEach(function(a) {
|
||||||
|
Socket.on(a.addressStr, function(txid) {
|
||||||
|
|
||||||
|
if (!a.isChange)
|
||||||
|
notification.funds('Funds received!', a.addressStr);
|
||||||
|
|
||||||
|
root.updateBalance(function() {
|
||||||
|
$rootScope.$digest();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
if (!$rootScope.wallet.spendUnconfirmed && !Socket.isListeningBlocks()) {
|
if (!$rootScope.wallet.spendUnconfirmed && !Socket.isListeningBlocks()) {
|
||||||
Socket.emit('subscribe', 'inv');
|
Socket.emit('subscribe', 'inv');
|
||||||
Socket.on('block', function(block) {
|
Socket.on('block', function(block) {
|
||||||
root.updateBalance(function() {
|
root.updateBalance(function() {
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
};
|
}
|
||||||
return root;
|
};
|
||||||
});
|
return root;
|
||||||
|
});
|
||||||
|
|
|
@ -27,16 +27,16 @@ FakeStorage.prototype.getLastOpened = function() {
|
||||||
return this.storage['lastOpened'];
|
return this.storage['lastOpened'];
|
||||||
};
|
};
|
||||||
|
|
||||||
FakeStorage.prototype.setIsOpen = function(id) {
|
FakeStorage.prototype.setLock = function(id) {
|
||||||
this.storage[id + '::isOpen'] = true;
|
this.storage[id + '::lock'] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
FakeStorage.prototype.getIsOpen = function(id) {
|
FakeStorage.prototype.getLock = function(id) {
|
||||||
return this.storage[id + '::isOpen'];
|
return this.storage[id + '::lock'];
|
||||||
}
|
}
|
||||||
|
|
||||||
FakeStorage.prototype.removeIsOpen = function(id) {
|
FakeStorage.prototype.removeLock = function(id) {
|
||||||
delete this[id + '::isOpen'];
|
delete this.storage[id + '::lock'];
|
||||||
}
|
}
|
||||||
|
|
||||||
FakeStorage.prototype.removeGlobal = function(id) {
|
FakeStorage.prototype.removeGlobal = function(id) {
|
||||||
|
|
|
@ -181,6 +181,7 @@ describe('Wallet model', function() {
|
||||||
cachedW2obj.opts.reconnectDelay = 100;
|
cachedW2obj.opts.reconnectDelay = 100;
|
||||||
}
|
}
|
||||||
var w = Wallet.fromObj(cachedW2obj, cachedW2.storage, cachedW2.network, cachedW2.blockchain);
|
var w = Wallet.fromObj(cachedW2obj, cachedW2.storage, cachedW2.network, cachedW2.blockchain);
|
||||||
|
w.unlock();
|
||||||
return w;
|
return w;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1024,11 +1025,34 @@ describe('Wallet model', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should check if wallet is already opened', function() {
|
it('should check if wallet is already opened', function() {
|
||||||
var w = createW();
|
var w = cachedCreateW2();
|
||||||
w._checkLocked();
|
should.not.exist(w.getLock());
|
||||||
w.isLocked.should.equal(false);
|
w.checkAndLock().should.equal(false);
|
||||||
w._checkLocked();
|
w.getLock().should.equal(true);
|
||||||
w.isLocked.should.equal(true);
|
});
|
||||||
|
it('should check if wallet is already opened', function() {
|
||||||
|
var w = cachedCreateW2();
|
||||||
|
should.not.exist(w.getLock());
|
||||||
|
w.checkAndLock().should.equal(false);
|
||||||
|
w.getLock().should.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should not start if locked', function() {
|
||||||
|
var w = cachedCreateW2();
|
||||||
|
w.netStart();
|
||||||
|
w.emit = sinon.spy();
|
||||||
|
w.netStart();
|
||||||
|
w.emit.getCall(0).args[0].should.equal('locked');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should accept ignoreLocked', function() {
|
||||||
|
var w = cachedCreateW2();
|
||||||
|
w.netStart();
|
||||||
|
w.network.start = sinon.spy();
|
||||||
|
w.ignoreLock=1;
|
||||||
|
w.netStart();
|
||||||
|
w.network.start.getCall(0).args[0].privkey.length.should.equal(64);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -160,16 +160,16 @@ describe('Storage/LocalEncrypted model', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#WalletIsOpened', function() {
|
describe('#WalletLock', function() {
|
||||||
it('should get/set/remove opened', function() {
|
it('should get/set/remove opened', function() {
|
||||||
var s = new LocalEncrypted({
|
var s = new LocalEncrypted({
|
||||||
localStorage: localMock,
|
localStorage: localMock,
|
||||||
password: 'password'
|
password: 'password'
|
||||||
});
|
});
|
||||||
s.setIsOpen('walletId');
|
s.setLock('walletId');
|
||||||
s.getIsOpen('walletId').should.equal(true);
|
s.getLock('walletId').should.equal(true);
|
||||||
s.removeIsOpen('walletId');
|
s.removeLock('walletId');
|
||||||
should.not.exist(s.getIsOpen('walletId'));
|
should.not.exist(s.getLock('walletId'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -225,15 +225,15 @@ describe("Unit: Controllers", function() {
|
||||||
beforeEach(inject(function($controller, $injector) {
|
beforeEach(inject(function($controller, $injector) {
|
||||||
$httpBackend = $injector.get('$httpBackend');
|
$httpBackend = $injector.get('$httpBackend');
|
||||||
$httpBackend.when('GET', GH)
|
$httpBackend.when('GET', GH)
|
||||||
.respond([{
|
.respond([{
|
||||||
name: "v100.1.6",
|
name: "v100.1.6",
|
||||||
zipball_url: "https://api.github.com/repos/bitpay/copay/zipball/v0.0.6",
|
zipball_url: "https://api.github.com/repos/bitpay/copay/zipball/v0.0.6",
|
||||||
tarball_url: "https://api.github.com/repos/bitpay/copay/tarball/v0.0.6",
|
tarball_url: "https://api.github.com/repos/bitpay/copay/tarball/v0.0.6",
|
||||||
commit: {
|
commit: {
|
||||||
sha: "ead7352bf2eca705de58d8b2f46650691f2bc2c7",
|
sha: "ead7352bf2eca705de58d8b2f46650691f2bc2c7",
|
||||||
url: "https://api.github.com/repos/bitpay/copay/commits/ead7352bf2eca705de58d8b2f46650691f2bc2c7"
|
url: "https://api.github.com/repos/bitpay/copay/commits/ead7352bf2eca705de58d8b2f46650691f2bc2c7"
|
||||||
}
|
}
|
||||||
}]);
|
}]);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
var rootScope;
|
var rootScope;
|
||||||
|
@ -303,11 +303,6 @@ describe("Unit: Controllers", function() {
|
||||||
expect(array.length).equal(n);
|
expect(array.length).equal(n);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should ignore if wallet is locked', function() {
|
|
||||||
scope.ignoreLocked();
|
|
||||||
expect(rootScope.wallet.isLocked).equal(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Send Controller', function() {
|
describe('Send Controller', function() {
|
||||||
|
@ -428,4 +423,18 @@ describe("Unit: Controllers", function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Warning Controller', function() {
|
||||||
|
var what;
|
||||||
|
beforeEach(inject(function($controller, $rootScope) {
|
||||||
|
scope = $rootScope.$new();
|
||||||
|
what = $controller('WarningController', {
|
||||||
|
$scope: scope,
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should exist', function() {
|
||||||
|
should.exist(what);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -97,14 +97,14 @@ var createBundle = function(opts) {
|
||||||
expose: '../js/models/core/HDPath'
|
expose: '../js/models/core/HDPath'
|
||||||
});
|
});
|
||||||
|
|
||||||
if (opts.dontminify) {
|
if (opts.debug) {
|
||||||
//include dev dependencies
|
//include dev dependencies
|
||||||
b.require('sinon');
|
b.require('sinon');
|
||||||
b.require('blanket');
|
b.require('blanket');
|
||||||
b.require('soop');
|
b.require('soop');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!opts.dontminify) {
|
if (!opts.debug) {
|
||||||
b.transform({
|
b.transform({
|
||||||
global: true
|
global: true
|
||||||
}, 'uglifyify');
|
}, 'uglifyify');
|
||||||
|
@ -120,7 +120,7 @@ if (require.main === module) {
|
||||||
var program = require('commander');
|
var program = require('commander');
|
||||||
program
|
program
|
||||||
.version('0.0.1')
|
.version('0.0.1')
|
||||||
.option('-d, --dontminify', 'Development. Don\'t minify the code.')
|
.option('-d, --debug', 'Development. Don\'t minify the codem and include debug packages.')
|
||||||
.option('-o, --stdout', 'Specify output as stdout')
|
.option('-o, --stdout', 'Specify output as stdout')
|
||||||
.parse(process.argv);
|
.parse(process.argv);
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
<div class="wide-page" ng-controller="SidebarController"
|
<div class="wide-page" ng-controller="WarningController"
|
||||||
ng-init="checkIfWarning()">
|
ng-init="checkLock()">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<img src="img/logo-negative-beta.svg" alt="Copay">
|
<img src="img/logo-negative-beta.svg" alt="Copay">
|
||||||
<div class="text-white" ng-include="'views/includes/version.html'"></div>
|
<div class="text-white" ng-include="'views/includes/version.html'"></div>
|
||||||
</div>
|
</div>
|
||||||
<h1 class="text-center text-warning">Warning!</h1>
|
<h1 class="text-center text-warning">Warning!</h1>
|
||||||
<h3 class="text-center text-white">
|
<h3 class="text-center text-white">
|
||||||
This wallet appear to be open on an other tab at your browser. Are you sure
|
This wallet appears to be currently open.
|
||||||
you want to proceed? (*)
|
<br>
|
||||||
|
Opening the wallet in multiple browser tabs could lead to unexpected results
|
||||||
</h3>
|
</h3>
|
||||||
<div class="text-center m30v large-12 columns">
|
<div class="text-center m30v large-12 columns">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="large-6 medium-6 small-6 columns text-center">
|
<div class="large-12 columns medium-12 small-12 text-center">
|
||||||
<a href class="button gray" ng-click="signout()">No, I am not sure.</a>
|
<a href class="button sucess" ng-click="signout()">Go back</a>
|
||||||
</div>
|
<br>
|
||||||
<div class="large-6 columns medium-6 small-6 text-center">
|
<br>
|
||||||
<a href class="button warning" ng-click="ignoreLocked()">I am. Go!</a>
|
<a href ng-click="ignoreLock()">Continue anyways</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-center text-gray small cb">
|
<div class="text-center text-gray small cb">
|
||||||
(*) Opening the wallet in multiple tabs could lead to unexpected results
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue