Fix conflicts:
index.html
This commit is contained in:
commit
bc5c473752
26 changed files with 715 additions and 252 deletions
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('HeaderController',
|
||||
function($scope, $rootScope, $location, notification, $http, controllerUtils) {
|
||||
function($scope, $rootScope, $location, notification, $http, controllerUtils, backupService) {
|
||||
$scope.menu = [{
|
||||
'title': 'Addresses',
|
||||
'icon': 'fi-address-book',
|
||||
|
|
@ -51,10 +51,7 @@ angular.module('copayApp.controllers').controller('HeaderController',
|
|||
|
||||
$rootScope.$watch('insightError', function(status) {
|
||||
if (status === -1) {
|
||||
$rootScope.$flashMessage = {
|
||||
type: 'success',
|
||||
message: 'Networking Restored :)',
|
||||
};
|
||||
notification.success('Networking restored', 'Connection to insight restored');
|
||||
$rootScope.insightError = 0;
|
||||
}
|
||||
});
|
||||
|
|
@ -98,7 +95,6 @@ angular.module('copayApp.controllers').controller('HeaderController',
|
|||
|
||||
$scope.signout = function() {
|
||||
logout();
|
||||
$scope.clearFlashMessage();
|
||||
};
|
||||
|
||||
$scope.refresh = function() {
|
||||
|
|
@ -111,10 +107,6 @@ angular.module('copayApp.controllers').controller('HeaderController',
|
|||
}
|
||||
};
|
||||
|
||||
$scope.clearFlashMessage = function() {
|
||||
$rootScope.$flashMessage = {};
|
||||
};
|
||||
|
||||
$rootScope.isCollapsed = true;
|
||||
|
||||
$scope.toggleCollapse = function() {
|
||||
|
|
@ -135,4 +127,11 @@ angular.module('copayApp.controllers').controller('HeaderController',
|
|||
$scope.$on('$destroy', function() {
|
||||
window.onbeforeunload = undefined;
|
||||
});
|
||||
|
||||
$scope.backupAndOpen = function() {
|
||||
var w = $rootScope.wallet;
|
||||
w.offerBackup();
|
||||
backupService.download(w);
|
||||
};
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,24 +1,34 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('ImportController',
|
||||
function($scope, $rootScope, walletFactory, controllerUtils, Passphrase) {
|
||||
function($scope, $rootScope, walletFactory, controllerUtils, Passphrase, notification) {
|
||||
$scope.title = 'Import a backup';
|
||||
$scope.importStatus = 'Importing wallet - Reading backup...';
|
||||
|
||||
var reader = new FileReader();
|
||||
|
||||
var updateStatus = function(status) {
|
||||
$scope.importStatus = status;
|
||||
$scope.$digest();
|
||||
}
|
||||
|
||||
var _importBackup = function(encryptedObj) {
|
||||
Passphrase.getBase64Async($scope.password, function(passphrase) {
|
||||
walletFactory.import(encryptedObj, passphrase, function(err, w) {
|
||||
updateStatus('Importing wallet - Setting things up...');
|
||||
var w = walletFactory.import(encryptedObj, passphrase, function(err, w) {
|
||||
if (err) {
|
||||
$scope.loading = false;
|
||||
$rootScope.$flashMessage = {
|
||||
message: err.errMsg || 'Wrong password',
|
||||
type: 'error'
|
||||
};
|
||||
notification.error('Error', err.errMsg || 'Wrong password');
|
||||
$rootScope.$digest();
|
||||
return;
|
||||
}
|
||||
$rootScope.wallet = w;
|
||||
controllerUtils.startNetwork($rootScope.wallet, $scope);
|
||||
});
|
||||
|
||||
w.on('updatingIndexes', function(){
|
||||
updateStatus('Importing wallet - We are almost there...');
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -46,10 +56,7 @@ angular.module('copayApp.controllers').controller('ImportController',
|
|||
$scope.import = function(form) {
|
||||
if (form.$invalid) {
|
||||
$scope.loading = false;
|
||||
$rootScope.$flashMessage = {
|
||||
message: 'There is an error in the form. Please, try again',
|
||||
type: 'error'
|
||||
};
|
||||
notification.error('Error', 'There is an error in the form.');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -59,10 +66,7 @@ angular.module('copayApp.controllers').controller('ImportController',
|
|||
|
||||
if (!backupFile && !backupText) {
|
||||
$scope.loading = false;
|
||||
$rootScope.$flashMessage = {
|
||||
message: 'Please, select your backup file or paste the text',
|
||||
type: 'error'
|
||||
};
|
||||
notification.error('Error', 'Please, select your backup file or paste the file contents');
|
||||
$scope.loading = false;
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
var bitcore = require('bitcore');
|
||||
|
||||
angular.module('copayApp.controllers').controller('SendController',
|
||||
function($scope, $rootScope, $window, $location, $timeout, $anchorScroll, $modal, isMobile) {
|
||||
function($scope, $rootScope, $window, $location, $timeout, $anchorScroll, $modal, isMobile, notification) {
|
||||
$scope.title = 'Send';
|
||||
$scope.loading = false;
|
||||
var satToUnit = 1 / config.unitToSatoshi;
|
||||
|
|
@ -32,10 +32,8 @@ angular.module('copayApp.controllers').controller('SendController',
|
|||
|
||||
$scope.submitForm = function(form) {
|
||||
if (form.$invalid) {
|
||||
$rootScope.$flashMessage = {
|
||||
message: 'Unable to send a transaction proposal. Please, try again',
|
||||
type: 'error'
|
||||
};
|
||||
var message = 'Unable to send transaction proposal.';
|
||||
notification.error('Error', message);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -50,20 +48,16 @@ angular.module('copayApp.controllers').controller('SendController',
|
|||
w.createTx(address, amount, commentText, function(ntxid) {
|
||||
if (w.totalCopayers > 1) {
|
||||
$scope.loading = false;
|
||||
$rootScope.$flashMessage = {
|
||||
message: 'The transaction proposal has been created',
|
||||
type: 'success'
|
||||
};
|
||||
var message = 'The transaction proposal has been created';
|
||||
notification.success('Success!', message);
|
||||
$rootScope.$digest();
|
||||
} else {
|
||||
w.sendTx(ntxid, function(txid) {
|
||||
$rootScope.$flashMessage = txid ? {
|
||||
type: 'success',
|
||||
message: 'Transaction broadcasted. txid: ' + txid
|
||||
} : {
|
||||
type: 'error',
|
||||
message: 'There was an error sending the Transaction'
|
||||
};
|
||||
if (txid) {
|
||||
notification.success('Transaction broadcast', 'Transaction id: ' + txid);
|
||||
} else {
|
||||
notification.error('Error', 'There was an error sending the transaction.');
|
||||
}
|
||||
$scope.loading = false;
|
||||
});
|
||||
}
|
||||
|
|
@ -202,10 +196,11 @@ angular.module('copayApp.controllers').controller('SendController',
|
|||
errorMsg = e.message;
|
||||
}
|
||||
|
||||
$rootScope.$flashMessage = {
|
||||
message: errorMsg ? errorMsg : 'Entry removed successful',
|
||||
type: errorMsg ? 'error' : 'success'
|
||||
};
|
||||
if (errorMsg) {
|
||||
notification.error('Error', errorMsg);
|
||||
} else {
|
||||
notification.success('Success', 'Entry removed successfully');
|
||||
}
|
||||
$rootScope.$digest();
|
||||
}, 500);
|
||||
};
|
||||
|
|
@ -223,10 +218,7 @@ angular.module('copayApp.controllers').controller('SendController',
|
|||
|
||||
$scope.submitAddressBook = function(form) {
|
||||
if (form.$invalid) {
|
||||
$rootScope.$flashMessage = {
|
||||
message: 'Complete required fields, please',
|
||||
type: 'error'
|
||||
};
|
||||
notification.error('Form Error', 'Please complete required fields');
|
||||
return;
|
||||
}
|
||||
var entry = {
|
||||
|
|
@ -255,10 +247,11 @@ angular.module('copayApp.controllers').controller('SendController',
|
|||
errorMsg = e.message;
|
||||
}
|
||||
|
||||
$rootScope.$flashMessage = {
|
||||
message: errorMsg ? errorMsg : 'New entry has been created',
|
||||
type: errorMsg ? 'error' : 'success'
|
||||
};
|
||||
if (errorMsg) {
|
||||
notification.error('Error', errorMsg);
|
||||
} else {
|
||||
notification.success('Success', 'New entry has been created');
|
||||
}
|
||||
$rootScope.$digest();
|
||||
}, 500);
|
||||
$anchorScroll();
|
||||
|
|
@ -267,8 +260,12 @@ angular.module('copayApp.controllers').controller('SendController',
|
|||
});
|
||||
};
|
||||
|
||||
$scope.topAmount = function() {
|
||||
var maxSat = ($rootScope.availableBalance * config.unitToSatoshi).toFixed(0) - bitcore.TransactionBuilder.FEE_PER_1000B_SAT;
|
||||
$scope.amount = maxSat / config.unitToSatoshi;
|
||||
$scope.getAvailableAmount = function() {
|
||||
return ((($rootScope.availableBalance * config.unitToSatoshi).toFixed(0) - bitcore.TransactionBuilder.FEE_PER_1000B_SAT) / config.unitToSatoshi);
|
||||
};
|
||||
|
||||
$scope.topAmount = function(form) {
|
||||
$scope.amount = $scope.getAvailableAmount();
|
||||
form.amount.$pristine = false;
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ var valid_pairs = {
|
|||
};
|
||||
|
||||
angular.module('copayApp.controllers').controller('SetupController',
|
||||
function($scope, $rootScope, $location, $timeout, walletFactory, controllerUtils, Passphrase, backupService) {
|
||||
function($scope, $rootScope, $location, $timeout, walletFactory, controllerUtils, Passphrase, backupService, notification) {
|
||||
|
||||
$rootScope.videoInfo = {};
|
||||
$scope.loading = false;
|
||||
|
|
@ -68,10 +68,7 @@ angular.module('copayApp.controllers').controller('SetupController',
|
|||
|
||||
$scope.create = function(form) {
|
||||
if (form && form.$invalid) {
|
||||
$rootScope.$flashMessage = {
|
||||
message: 'Please, enter required fields',
|
||||
type: 'error'
|
||||
};
|
||||
notification.error('Error', 'Please enter the required fields');
|
||||
return;
|
||||
}
|
||||
$scope.loading = true;
|
||||
|
|
@ -84,7 +81,6 @@ angular.module('copayApp.controllers').controller('SetupController',
|
|||
passphrase: passphrase,
|
||||
};
|
||||
var w = walletFactory.create(opts);
|
||||
backupService.download(w);
|
||||
controllerUtils.startNetwork(w, $scope);
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('SigninController',
|
||||
function($scope, $rootScope, $location, walletFactory, controllerUtils, Passphrase, backupService) {
|
||||
function($scope, $rootScope, $location, walletFactory, controllerUtils, Passphrase, backupService, notification) {
|
||||
var cmp = function(o1, o2) {
|
||||
var v1 = o1.show.toLowerCase(),
|
||||
v2 = o2.show.toLowerCase();
|
||||
|
|
@ -15,10 +15,7 @@ angular.module('copayApp.controllers').controller('SigninController',
|
|||
|
||||
$scope.open = function(form) {
|
||||
if (form && form.$invalid) {
|
||||
$rootScope.$flashMessage = {
|
||||
message: 'Please, enter required fields',
|
||||
type: 'error'
|
||||
};
|
||||
notification.error('Error', 'Please enter the required fields');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -36,10 +33,7 @@ angular.module('copayApp.controllers').controller('SigninController',
|
|||
};
|
||||
if (!w) {
|
||||
$scope.loading = false;
|
||||
$rootScope.$flashMessage = {
|
||||
message: errMsg || 'Wrong password',
|
||||
type: 'error'
|
||||
};
|
||||
notification.error('Error', errMsg || 'Wrong password');
|
||||
$rootScope.$digest();
|
||||
return;
|
||||
}
|
||||
|
|
@ -49,10 +43,7 @@ angular.module('copayApp.controllers').controller('SigninController',
|
|||
|
||||
$scope.join = function(form) {
|
||||
if (form && form.$invalid) {
|
||||
$rootScope.$flashMessage = {
|
||||
message: 'Please, enter required fields',
|
||||
type: 'error'
|
||||
};
|
||||
notification.error('Error', 'Please enter the required fields');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -64,32 +55,17 @@ angular.module('copayApp.controllers').controller('SigninController',
|
|||
$scope.loading = false;
|
||||
if (err || !w) {
|
||||
if (err === 'joinError')
|
||||
$rootScope.$flashMessage = {
|
||||
message: 'Can\'t find peer'
|
||||
};
|
||||
notification.error('Can\'t find peer.');
|
||||
else if (err === 'walletFull')
|
||||
$rootScope.$flashMessage = {
|
||||
message: 'The wallet is full',
|
||||
type: 'error'
|
||||
};
|
||||
notification.error('The wallet is full');
|
||||
else if (err === 'badNetwork')
|
||||
$rootScope.$flashMessage = {
|
||||
message: 'The wallet your are trying to join uses a different Bitcoin Network. Check your settings.',
|
||||
type: 'error'
|
||||
};
|
||||
notification.error('Network Error', 'The wallet your are trying to join uses a different Bitcoin Network. Check your settings.');
|
||||
else if (err === 'badSecret')
|
||||
$rootScope.$flashMessage = {
|
||||
message: 'Bad secret secret string',
|
||||
type: 'error'
|
||||
};
|
||||
notification.error('Bad secret', 'The secret string you entered is invalid');
|
||||
else
|
||||
$rootScope.$flashMessage = {
|
||||
message: 'Unknown error',
|
||||
type: 'error'
|
||||
};
|
||||
notification.error('Unknown error');
|
||||
controllerUtils.onErrorDigest();
|
||||
} else {
|
||||
backupService.download(w);
|
||||
controllerUtils.startNetwork(w, $scope);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
var bitcore = require('bitcore');
|
||||
|
||||
angular.module('copayApp.controllers').controller('TransactionsController',
|
||||
function($scope, $rootScope, $timeout, controllerUtils) {
|
||||
function($scope, $rootScope, $timeout, controllerUtils, notification) {
|
||||
|
||||
$scope.title = 'Transactions';
|
||||
$scope.loading = false;
|
||||
|
|
@ -107,13 +107,11 @@ angular.module('copayApp.controllers').controller('TransactionsController',
|
|||
$rootScope.txAlertCount = 0;
|
||||
var w = $rootScope.wallet;
|
||||
w.sendTx(ntxid, function(txid) {
|
||||
$rootScope.$flashMessage = txid ? {
|
||||
type: 'success',
|
||||
message: 'Transaction broadcasted. txid: ' + txid
|
||||
} : {
|
||||
type: 'error',
|
||||
message: 'There was an error sending the Transaction'
|
||||
};
|
||||
if (!txid) {
|
||||
notification.error('Error', 'There was an error sending the transaction');
|
||||
} else {
|
||||
notification.success('Transaction broadcast', 'Transaction id: '+txid);
|
||||
}
|
||||
if (cb) return cb();
|
||||
else $scope.update();
|
||||
});
|
||||
|
|
@ -124,10 +122,7 @@ angular.module('copayApp.controllers').controller('TransactionsController',
|
|||
var w = $rootScope.wallet;
|
||||
w.sign(ntxid, function(ret) {
|
||||
if (!ret) {
|
||||
$rootScope.$flashMessage = {
|
||||
type: 'error',
|
||||
message: 'There was an error signing the Transaction',
|
||||
};
|
||||
notification.error('Error', 'There was an error signing the transaction');
|
||||
$scope.update();
|
||||
} else {
|
||||
var p = w.txProposals.getTxProposal(ntxid);
|
||||
|
|
@ -180,10 +175,7 @@ angular.module('copayApp.controllers').controller('TransactionsController',
|
|||
$rootScope.txAlertCount = 0;
|
||||
var w = $rootScope.wallet;
|
||||
w.reject(ntxid);
|
||||
$rootScope.$flashMessage = {
|
||||
type: 'warning',
|
||||
message: 'Transaction rejected by you'
|
||||
};
|
||||
notification.warning('Transaction rejected', 'You rejected the transaction successfully');
|
||||
$scope.loading = false;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ angular.module('copayApp.directives')
|
|||
link: function(scope, element, attrs, ctrl) {
|
||||
setTimeout(function() {
|
||||
scope.$apply(function() {
|
||||
$rootScope.$flashMessage = {};
|
||||
});
|
||||
}, 5000);
|
||||
}
|
||||
|
|
@ -40,12 +39,12 @@ angular.module('copayApp.directives')
|
|||
.directive('enoughAmount', ['$rootScope',
|
||||
function($rootScope) {
|
||||
var bitcore = require('bitcore');
|
||||
var feeSat = bitcore.TransactionBuilder.FEE_PER_1000B_SAT;
|
||||
var feeSat = Number(bitcore.TransactionBuilder.FEE_PER_1000B_SAT);
|
||||
return {
|
||||
require: 'ngModel',
|
||||
link: function(scope, element, attrs, ctrl) {
|
||||
var val = function(value) {
|
||||
var availableBalanceNum = ($rootScope.availableBalance * config.unitToSatoshi).toFixed(0);
|
||||
var availableBalanceNum = Number(($rootScope.availableBalance * config.unitToSatoshi).toFixed(0));
|
||||
var vNum = Number((value * config.unitToSatoshi).toFixed(0)) + feeSat;
|
||||
if (typeof vNum == "number" && vNum > 0) {
|
||||
if (availableBalanceNum < vNum) {
|
||||
|
|
|
|||
82
js/models/core/Message.js
Normal file
82
js/models/core/Message.js
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
'use strict';
|
||||
|
||||
var imports = require('soop').imports();
|
||||
var bitcore = require('bitcore');
|
||||
|
||||
/* Encrypted, authenticated messages to be shared between copayers */
|
||||
var Message = function() {
|
||||
};
|
||||
|
||||
Message.encode = function(topubkey, fromkey, payload) {
|
||||
var version = new Buffer([0]);
|
||||
var toencrypt = Buffer.concat([version, payload]);
|
||||
var encrypted = Message._encrypt(topubkey, toencrypt);
|
||||
var sig = Message._sign(fromkey, encrypted);
|
||||
var encoded = {
|
||||
pubkey: fromkey.public.toString('hex'),
|
||||
sig: sig.toString('hex'),
|
||||
encrypted: encrypted.toString('hex')
|
||||
};
|
||||
return encoded;
|
||||
};
|
||||
|
||||
Message.decode = function(key, encoded) {
|
||||
try {
|
||||
var frompubkey = new Buffer(encoded.pubkey, 'hex');
|
||||
} catch (e) {
|
||||
throw new Error('Error decoding public key: ' + e);
|
||||
}
|
||||
|
||||
try {
|
||||
var sig = new Buffer(encoded.sig, 'hex');
|
||||
var encrypted = new Buffer(encoded.encrypted, 'hex');
|
||||
} catch (e) {
|
||||
throw new Error('Error decoding data: ' + e);
|
||||
}
|
||||
|
||||
try {
|
||||
var v = Message._verify(frompubkey, sig, encrypted);
|
||||
} catch (e) {
|
||||
throw new Error('Error verifying signature: ' + e);
|
||||
}
|
||||
|
||||
if (!v)
|
||||
throw new Error('Invalid signature');
|
||||
|
||||
try {
|
||||
var decrypted = Message._decrypt(key.private, encrypted);
|
||||
} catch (e) {
|
||||
throw new Error('Cannot decrypt data: ' + e);
|
||||
}
|
||||
|
||||
if (decrypted[0] !== 0)
|
||||
throw new Error('Invalid version number');
|
||||
|
||||
if (decrypted.length === 0)
|
||||
throw new Error('No data present');
|
||||
|
||||
var payload = decrypted.slice(1);
|
||||
return payload;
|
||||
};
|
||||
|
||||
Message._encrypt = function(topubkey, payload, r, iv) {
|
||||
var encrypted = bitcore.ECIES.encrypt(topubkey, payload, r, iv);
|
||||
return encrypted;
|
||||
};
|
||||
|
||||
Message._decrypt = function(privkey, encrypted) {
|
||||
var decrypted = bitcore.ECIES.decrypt(privkey, encrypted);
|
||||
return decrypted;
|
||||
};
|
||||
|
||||
Message._sign = function(key, payload) {
|
||||
var sig = bitcore.Message.sign(payload, key);
|
||||
return sig;
|
||||
};
|
||||
|
||||
Message._verify = function(pubkey, signature, payload) {
|
||||
var v = bitcore.Message.verifyWithPubKey(pubkey, payload, signature);
|
||||
return v;
|
||||
};
|
||||
|
||||
module.exports = require('soop')(Message);
|
||||
|
|
@ -32,9 +32,17 @@ PrivateKey.prototype.getIdPriv = function() {
|
|||
return this.idpriv;
|
||||
};
|
||||
|
||||
PrivateKey.prototype.getIdKey = function() {
|
||||
if (!this.idkey) {
|
||||
this.cacheId();
|
||||
}
|
||||
return this.idkey;
|
||||
};
|
||||
|
||||
PrivateKey.prototype.cacheId = function() {
|
||||
var path = Structure.IdFullBranch;
|
||||
var idhk = this.bip.derive(path);
|
||||
this.idkey = idhk.eckey;
|
||||
this.id = idhk.eckey.public.toString('hex');
|
||||
this.idpriv = idhk.eckey.private.toString('hex');
|
||||
};
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ function Wallet(opts) {
|
|||
this.network.maxPeers = this.totalCopayers;
|
||||
this.registeredPeerIds = [];
|
||||
this.addressBook = opts.addressBook || {};
|
||||
this.backupOffered = opts.backupOffered || false;
|
||||
}
|
||||
|
||||
Wallet.parent = EventEmitter;
|
||||
|
|
@ -279,6 +280,7 @@ Wallet.prototype.netStart = function(callback) {
|
|||
|
||||
var myId = self.getMyCopayerId();
|
||||
var myIdPriv = self.getMyCopayerIdPriv();
|
||||
|
||||
var startOpts = {
|
||||
copayerId: myId,
|
||||
privkey: myIdPriv,
|
||||
|
|
@ -355,7 +357,8 @@ Wallet.prototype.toObj = function() {
|
|||
publicKeyRing: this.publicKeyRing.toObj(),
|
||||
txProposals: this.txProposals.toObj(),
|
||||
privateKey: this.privateKey ? this.privateKey.toObj() : undefined,
|
||||
addressBook: this.addressBook
|
||||
addressBook: this.addressBook,
|
||||
backupOffered: this.backupOffered,
|
||||
};
|
||||
|
||||
return walletObj;
|
||||
|
|
@ -364,6 +367,8 @@ Wallet.prototype.toObj = function() {
|
|||
Wallet.fromObj = function(o, storage, network, blockchain) {
|
||||
var opts = JSON.parse(JSON.stringify(o.opts));
|
||||
opts.addressBook = o.addressBook;
|
||||
opts.backupOffered = o.backupOffered;
|
||||
|
||||
opts.publicKeyRing = PublicKeyRing.fromObj(o.publicKeyRing);
|
||||
opts.txProposals = TxProposals.fromObj(o.txProposals);
|
||||
opts.privateKey = PrivateKey.fromObj(o.privateKey);
|
||||
|
|
@ -755,6 +760,7 @@ Wallet.prototype.updateIndexes = function(callback) {
|
|||
if (changeIndex != -1)
|
||||
self.publicKeyRing.indexes.changeIndex = changeIndex + 1;
|
||||
|
||||
self.emit('updatingIndexes');
|
||||
start = self.publicKeyRing.indexes.receiveIndex;
|
||||
self.indexDiscovery(start, false, 20, function(err, receiveIndex) {
|
||||
if (err) return callback(err);
|
||||
|
|
@ -850,4 +856,14 @@ Wallet.prototype.deleteAddressBook = function(key) {
|
|||
}
|
||||
};
|
||||
|
||||
Wallet.prototype.isReady = function() {
|
||||
var ret = this.publicKeyRing.isComplete() && this.backupOffered;
|
||||
return ret;
|
||||
};
|
||||
|
||||
Wallet.prototype.offerBackup = function() {
|
||||
this.backupOffered = true;
|
||||
this.store();
|
||||
};
|
||||
|
||||
module.exports = require('soop')(Wallet);
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ WalletFactory.prototype.import = function(base64, password, cb) {
|
|||
self.log('Indexes updated');
|
||||
cb(null, w);
|
||||
});
|
||||
return w;
|
||||
}
|
||||
|
||||
WalletFactory.prototype.read = function(walletId) {
|
||||
|
|
@ -99,6 +100,7 @@ WalletFactory.prototype.read = function(walletId) {
|
|||
obj.txProposals = s.get(walletId, 'txProposals');
|
||||
obj.privateKey = s.get(walletId, 'privateKey');
|
||||
obj.addressBook = s.get(walletId, 'addressBook');
|
||||
obj.backupOffered = s.get(walletId, 'backupOffered');
|
||||
|
||||
var w = this.fromObj(obj);
|
||||
return w;
|
||||
|
|
@ -222,7 +224,8 @@ WalletFactory.prototype.joinCreateSession = function(secret, nickname, passphras
|
|||
this.log('\t### PrivateKey Initialized');
|
||||
var opts = {
|
||||
copayerId: privateKey.getId(),
|
||||
privkey: privateKey.getIdPriv()
|
||||
privkey: privateKey.getIdPriv(),
|
||||
key: privateKey.getIdKey()
|
||||
};
|
||||
self.network.cleanUp();
|
||||
self.network.start(opts, function() {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ var EventEmitter = imports.EventEmitter || require('events').EventEmitter;
|
|||
var bitcore = require('bitcore');
|
||||
var util = bitcore.util;
|
||||
var extend = require('util')._extend;
|
||||
var Message = require('../core/Message');
|
||||
/*
|
||||
* Emits
|
||||
* 'connect'
|
||||
|
|
@ -45,6 +46,7 @@ Network.prototype.cleanUp = function() {
|
|||
this.connectedPeers = [];
|
||||
this.peerId = null;
|
||||
this.privkey = null; //TODO: hide privkey in a closure
|
||||
this.key = null;
|
||||
this.copayerId = null;
|
||||
this.signingKey = null;
|
||||
this.allowedCopayerIds = null;
|
||||
|
|
@ -151,16 +153,29 @@ Network.prototype._addConnectedCopayer = function(copayerId, isInbound) {
|
|||
this.emit('connect', copayerId);
|
||||
};
|
||||
|
||||
Network.prototype._onData = function(enchex, isInbound, peerId) {
|
||||
var sig, payload;
|
||||
var encUint8Array = new Uint8Array(enchex);
|
||||
Network.prototype.getKey = function() {
|
||||
if (!this.key) {
|
||||
var key = new bitcore.Key();
|
||||
key.private = new Buffer(this.privkey, 'hex');
|
||||
key.regenerateSync();
|
||||
this.key = key;
|
||||
}
|
||||
return this.key;
|
||||
};
|
||||
|
||||
Network.prototype._onData = function(enc, isInbound, peerId) {
|
||||
var encUint8Array = new Uint8Array(enc);
|
||||
var encbuf = new Buffer(encUint8Array);
|
||||
var encstr = encbuf.toString();
|
||||
|
||||
var privkey = this.privkey;
|
||||
var key = this.getKey();
|
||||
|
||||
try {
|
||||
var data = this._decrypt(privkey, encbuf);
|
||||
payload = JSON.parse(data);
|
||||
var encoded = JSON.parse(encstr);
|
||||
var databuf = this._decode(key, encoded);
|
||||
var datastr = databuf.toString();
|
||||
var payload = JSON.parse(datastr);
|
||||
} catch (e) {
|
||||
this._deletePeer(peerId);
|
||||
return;
|
||||
|
|
@ -169,6 +184,13 @@ Network.prototype._onData = function(enchex, isInbound, peerId) {
|
|||
if (isInbound && payload.type === 'hello') {
|
||||
var payloadStr = JSON.stringify(payload);
|
||||
|
||||
//ensure claimed public key is actually the public key of the peer
|
||||
//e.g., their public key should hash to be their peerId
|
||||
if (peerId.toString() !== this.peerFromCopayer(payload.copayerId) || peerId.toString() !== this.peerFromCopayer(encoded.pubkey)) {
|
||||
this._deletePeer(peerId, 'incorrect pubkey for peerId');
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.allowedCopayerIds && !this.allowedCopayerIds[payload.copayerId]) {
|
||||
this._deletePeer(peerId);
|
||||
return;
|
||||
|
|
@ -349,18 +371,20 @@ Network.prototype.getPeer = function() {
|
|||
return this.peer;
|
||||
};
|
||||
|
||||
Network.prototype._encrypt = function(pubkey, payload) {
|
||||
var encrypted = bitcore.ECIES.encrypt(pubkey, payload);
|
||||
return encrypted;
|
||||
Network.prototype._encode = function(topubkey, fromkey, payload) {
|
||||
var encoded = Message.encode(topubkey, fromkey, payload);
|
||||
return encoded;
|
||||
};
|
||||
|
||||
|
||||
Network.prototype._decrypt = function(privkey, encrypted) {
|
||||
var decrypted = bitcore.ECIES.decrypt(privkey, encrypted);
|
||||
return decrypted;
|
||||
Network.prototype._decode = function(key, encoded) {
|
||||
var payload = Message.decode(key, encoded);
|
||||
return payload;
|
||||
};
|
||||
|
||||
Network.prototype._sendToOne = function(copayerId, payload, sig, cb) {
|
||||
Network.prototype._sendToOne = function(copayerId, payload, cb) {
|
||||
if (!Buffer.isBuffer(payload))
|
||||
throw new Error('payload must be a buffer');
|
||||
var peerId = this.peerFromCopayer(copayerId);
|
||||
if (peerId !== this.peerId) {
|
||||
var dataConn = this.connections[peerId];
|
||||
|
|
@ -383,7 +407,6 @@ Network.prototype.send = function(copayerIds, payload, cb) {
|
|||
if (typeof copayerIds === 'string')
|
||||
copayerIds = [copayerIds];
|
||||
|
||||
var sig;
|
||||
var payloadStr = JSON.stringify(payload);
|
||||
var payloadBuf = new Buffer(payloadStr);
|
||||
|
||||
|
|
@ -391,8 +414,9 @@ Network.prototype.send = function(copayerIds, payload, cb) {
|
|||
var i = 0;
|
||||
copayerIds.forEach(function(copayerId) {
|
||||
var copayerIdBuf = new Buffer(copayerId, 'hex');
|
||||
var encPayload = self._encrypt(copayerIdBuf, payloadBuf);
|
||||
self._sendToOne(copayerId, encPayload, sig, function() {
|
||||
var encPayload = self._encode(copayerIdBuf, self.getKey(), payloadBuf);
|
||||
var enc = new Buffer(JSON.stringify(encPayload));
|
||||
self._sendToOne(copayerId, enc, function() {
|
||||
if (++i === l && typeof cb === 'function') cb();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -36,35 +36,27 @@ angular.module('copayApp.services')
|
|||
|
||||
root.onErrorDigest = function(scope, msg) {
|
||||
root.onError(scope);
|
||||
if (msg) $rootScope.$flashMessage = {
|
||||
type: 'error',
|
||||
message: msg
|
||||
};
|
||||
if (msg) {
|
||||
notification.error('Error', msg);
|
||||
}
|
||||
$rootScope.$digest();
|
||||
};
|
||||
|
||||
root.installStartupHandlers = function(wallet, $scope) {
|
||||
wallet.on('serverError', function(msg) {
|
||||
$rootScope.$flashMessage = {
|
||||
message: 'There was an error connecting to the PeerJS server.' + (msg || 'Check you settings and Internet connection.'),
|
||||
type: 'error',
|
||||
};
|
||||
notification.error('PeerJS Error', 'There was an error connecting to the PeerJS server.'
|
||||
+ (msg || 'Check you settings and Internet connection.'));
|
||||
root.onErrorDigest($scope);
|
||||
$location.path('addresses');
|
||||
});
|
||||
wallet.on('connectionError', function() {
|
||||
var message = "Looks like you are already connected to this wallet, please logout from it and try importing it again.";
|
||||
$rootScope.$flashMessage = {
|
||||
message: message,
|
||||
type: 'error'
|
||||
};
|
||||
var message = "Looks like you are already connected to this wallet, please logout and try importing it again.";
|
||||
notification.error('PeerJS Error', message);
|
||||
root.onErrorDigest($scope);
|
||||
});
|
||||
wallet.on('serverError', function() {
|
||||
$rootScope.$flashMessage = {
|
||||
message: 'The PeerJS server is not responding, please try again',
|
||||
type: 'error'
|
||||
};
|
||||
var message = 'The PeerJS server is not responding, please try again';
|
||||
notification.error('PeerJS Error', message);
|
||||
root.onErrorDigest($scope);
|
||||
});
|
||||
wallet.on('ready', function() {
|
||||
|
|
@ -79,10 +71,7 @@ angular.module('copayApp.services')
|
|||
$rootScope.isCollapsed = true;
|
||||
$rootScope.$watch('insightError', function(status) {
|
||||
if (status === -1) {
|
||||
$rootScope.$flashMessage = {
|
||||
type: 'success',
|
||||
message: 'Networking Restored :)',
|
||||
};
|
||||
notification.success('Networking restored', 'Connection to Insight re-established');
|
||||
$rootScope.insightError = 0;
|
||||
}
|
||||
});
|
||||
|
|
@ -117,10 +106,7 @@ angular.module('copayApp.services')
|
|||
notification.enableHtml5Mode(); // for chrome: if support, enable it
|
||||
|
||||
w.on('badMessage', function(peerId) {
|
||||
$rootScope.$flashMessage = {
|
||||
type: 'error',
|
||||
message: 'Received wrong message from peer id:' + peerId
|
||||
};
|
||||
notification.error('Error', 'Received wrong message from peer ' + peerId);
|
||||
});
|
||||
w.on('ready', function(myPeerID) {
|
||||
$rootScope.wallet = w;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ factory('notification', ['$timeout',
|
|||
enabled: true
|
||||
},
|
||||
error: {
|
||||
duration: 1e10,
|
||||
duration: 5000,
|
||||
enabled: true
|
||||
},
|
||||
success: {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue