mirror of https://github.com/BTCPrivate/copay.git
commit
e0ccb24b93
|
@ -1,19 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('BackupController',
|
|
||||||
function($scope, $rootScope, backupService, walletFactory, controllerUtils) {
|
|
||||||
|
|
||||||
$scope.downloadBackup = function() {
|
|
||||||
var w = $rootScope.wallet;
|
|
||||||
backupService.download(w);
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.deleteWallet = function() {
|
|
||||||
var w = $rootScope.wallet;
|
|
||||||
w.disconnect();
|
|
||||||
walletFactory.delete(w.id, function() {
|
|
||||||
controllerUtils.logout();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
});
|
|
|
@ -7,6 +7,7 @@ angular.module('copayApp.controllers').controller('ImportController',
|
||||||
|
|
||||||
$scope.title = 'Import a backup';
|
$scope.title = 'Import a backup';
|
||||||
$scope.importStatus = 'Importing wallet - Reading backup...';
|
$scope.importStatus = 'Importing wallet - Reading backup...';
|
||||||
|
$scope.hideAdv=true;
|
||||||
|
|
||||||
var reader = new FileReader();
|
var reader = new FileReader();
|
||||||
|
|
||||||
|
@ -20,9 +21,16 @@ angular.module('copayApp.controllers').controller('ImportController',
|
||||||
updateStatus('Importing wallet - Setting things up...');
|
updateStatus('Importing wallet - Setting things up...');
|
||||||
var w, errMsg;
|
var w, errMsg;
|
||||||
|
|
||||||
|
var skipFields = [];
|
||||||
|
if ($scope.skipPublicKeyRing)
|
||||||
|
skipFields.push('publicKeyRing');
|
||||||
|
|
||||||
|
if ($scope.skipTxProposals)
|
||||||
|
skipFields.push('txProposals');
|
||||||
|
|
||||||
// try to import encrypted wallet with passphrase
|
// try to import encrypted wallet with passphrase
|
||||||
try {
|
try {
|
||||||
w = walletFactory.import(encryptedObj, passphrase);
|
w = walletFactory.import(encryptedObj, passphrase, skipFields);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
errMsg = e.message;
|
errMsg = e.message;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,10 @@ angular.module('copayApp.controllers').controller('JoinController',
|
||||||
var context;
|
var context;
|
||||||
var localMediaStream;
|
var localMediaStream;
|
||||||
|
|
||||||
|
$scope.hideAdv=true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var _scan = function(evt) {
|
var _scan = function(evt) {
|
||||||
if (localMediaStream) {
|
if (localMediaStream) {
|
||||||
context.drawImage(video, 0, 0, 300, 225);
|
context.drawImage(video, 0, 0, 300, 225);
|
||||||
|
@ -112,7 +116,7 @@ angular.module('copayApp.controllers').controller('JoinController',
|
||||||
walletFactory.network.on('badSecret', function() {});
|
walletFactory.network.on('badSecret', function() {});
|
||||||
|
|
||||||
Passphrase.getBase64Async($scope.joinPassword, function(passphrase) {
|
Passphrase.getBase64Async($scope.joinPassword, function(passphrase) {
|
||||||
walletFactory.joinCreateSession($scope.connectionId, $scope.nickname, passphrase, function(err, w) {
|
walletFactory.joinCreateSession($scope.connectionId, $scope.nickname, passphrase, $scope.private, function(err, w) {
|
||||||
$scope.loading = false;
|
$scope.loading = false;
|
||||||
if (err || !w) {
|
if (err || !w) {
|
||||||
if (err === 'joinError')
|
if (err === 'joinError')
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('copayApp.controllers').controller('MoreController',
|
||||||
|
function($scope, $rootScope, $location, backupService, walletFactory, controllerUtils, notification) {
|
||||||
|
var w = $rootScope.wallet;
|
||||||
|
|
||||||
|
$scope.hideAdv=true;
|
||||||
|
$scope.hidePriv=true;
|
||||||
|
if (w)
|
||||||
|
$scope.priv = w.privateKey.toObj().extendedPrivateKeyString;
|
||||||
|
|
||||||
|
$scope.downloadBackup = function() {
|
||||||
|
var w = $rootScope.wallet;
|
||||||
|
backupService.download(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.deleteWallet = function() {
|
||||||
|
var w = $rootScope.wallet;
|
||||||
|
w.disconnect();
|
||||||
|
walletFactory.delete(w.id, function() {
|
||||||
|
controllerUtils.logout();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.purge = function(deleteAll) {
|
||||||
|
var w = $rootScope.wallet;
|
||||||
|
var removed = w.purgeTxProposals(deleteAll);
|
||||||
|
if (removed){
|
||||||
|
controllerUtils.updateBalance();
|
||||||
|
}
|
||||||
|
notification.info('Tx Proposals Purged', removed + ' transaction proposal purged');
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.updateIndexes = function() {
|
||||||
|
var w = $rootScope.wallet;
|
||||||
|
notification.info('Scaning for transactions','Using derived addresses from your wallet');
|
||||||
|
w.updateIndexes(function(err) {
|
||||||
|
notification.info('Scan Ended', 'Updating balance');
|
||||||
|
if (err) {
|
||||||
|
notification.error('Error', 'Error updating indexes: ' + err);
|
||||||
|
}
|
||||||
|
controllerUtils.updateAddressList();
|
||||||
|
controllerUtils.updateBalance(function(){
|
||||||
|
notification.info('Finished', 'The balance is updated using the derived addresses');
|
||||||
|
w.sendIndexes();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
});
|
|
@ -41,6 +41,7 @@ angular.module('copayApp.controllers').controller('SetupController',
|
||||||
$scope.loading = false;
|
$scope.loading = false;
|
||||||
$scope.walletPassword = $rootScope.walletPassword;
|
$scope.walletPassword = $rootScope.walletPassword;
|
||||||
$scope.isMobile = !!window.cordova;
|
$scope.isMobile = !!window.cordova;
|
||||||
|
$scope.hideAdv = true;
|
||||||
|
|
||||||
// ng-repeat defined number of times instead of repeating over array?
|
// ng-repeat defined number of times instead of repeating over array?
|
||||||
$scope.getNumber = function(num) {
|
$scope.getNumber = function(num) {
|
||||||
|
@ -82,6 +83,7 @@ angular.module('copayApp.controllers').controller('SetupController',
|
||||||
name: $scope.walletName,
|
name: $scope.walletName,
|
||||||
nickname: $scope.myNickname,
|
nickname: $scope.myNickname,
|
||||||
passphrase: passphrase,
|
passphrase: passphrase,
|
||||||
|
privateKeyHex: $scope.private,
|
||||||
};
|
};
|
||||||
var w = walletFactory.create(opts);
|
var w = walletFactory.create(opts);
|
||||||
controllerUtils.startNetwork(w, $scope);
|
controllerUtils.startNetwork(w, $scope);
|
||||||
|
|
|
@ -17,7 +17,7 @@ angular.module('copayApp.controllers').controller('SidebarController', function(
|
||||||
}, {
|
}, {
|
||||||
'title': 'More',
|
'title': 'More',
|
||||||
'icon': 'fi-download',
|
'icon': 'fi-download',
|
||||||
'link': 'backup'
|
'link': 'more'
|
||||||
}];
|
}];
|
||||||
|
|
||||||
$scope.signout = function() {
|
$scope.signout = function() {
|
||||||
|
|
|
@ -239,7 +239,7 @@ PublicKeyRing.prototype.getCosigner = function(pubKey) {
|
||||||
});
|
});
|
||||||
|
|
||||||
var index = sorted.indexOf(pubKey);
|
var index = sorted.indexOf(pubKey);
|
||||||
if (index == -1) throw new Error('no public key in ring');
|
if (index == -1) throw new Error('public key is not on the ring');
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,19 @@ TxProposal.prototype._check = function() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TxProposal.prototype.rejectCount = function() {
|
||||||
|
return Object.keys(this.rejectedBy).length;
|
||||||
|
};
|
||||||
|
|
||||||
|
TxProposal.prototype.isPending = function(maxRejectCount) {
|
||||||
|
preconditions.checkArgument(typeof maxRejectCount != 'undefined');
|
||||||
|
|
||||||
|
if (this.rejectCount() > maxRejectCount || this.sentTxid)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
TxProposal.prototype._updateSignedBy = function() {
|
TxProposal.prototype._updateSignedBy = function() {
|
||||||
this._inputSignatures = [];
|
this._inputSignatures = [];
|
||||||
|
|
|
@ -36,10 +36,25 @@ TxProposals.fromObj = function(o, forceOpts) {
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TxProposals.prototype.length = function() {
|
||||||
|
return Object.keys(this.txps).length;
|
||||||
|
};
|
||||||
|
|
||||||
TxProposals.prototype.getNtxids = function() {
|
TxProposals.prototype.getNtxids = function() {
|
||||||
return Object.keys(this.txps);
|
return Object.keys(this.txps);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TxProposals.prototype.deleteAll = function() {
|
||||||
|
this.txps = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
TxProposals.prototype.deletePending = function(maxRejectCount) {
|
||||||
|
for (var ntxid in this.txps) {
|
||||||
|
if (this.txps[ntxid].isPending(maxRejectCount))
|
||||||
|
delete this.txps[ntxid];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
TxProposals.prototype.toObj = function() {
|
TxProposals.prototype.toObj = function() {
|
||||||
var ret = [];
|
var ret = [];
|
||||||
for (var id in this.txps) {
|
for (var id in this.txps) {
|
||||||
|
@ -151,10 +166,11 @@ TxProposals.prototype.seen = function(ntxid, copayerId) {
|
||||||
TxProposals.prototype.getUsedUnspent = function(maxRejectCount) {
|
TxProposals.prototype.getUsedUnspent = function(maxRejectCount) {
|
||||||
var ret = {};
|
var ret = {};
|
||||||
for (var i in this.txps) {
|
for (var i in this.txps) {
|
||||||
|
if (!this.txps[i].isPending(maxRejectCount))
|
||||||
|
continue;
|
||||||
|
|
||||||
var u = this.txps[i].builder.getSelectedUnspent();
|
var u = this.txps[i].builder.getSelectedUnspent();
|
||||||
var p = this.getTxProposal(i);
|
var p = this.getTxProposal(i);
|
||||||
if (p.rejectCount > maxRejectCount || p.sentTxid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (var j in u) {
|
for (var j in u) {
|
||||||
ret[u[j].txid + ',' + u[j].vout] = 1;
|
ret[u[j].txid + ',' + u[j].vout] = 1;
|
||||||
|
|
|
@ -495,11 +495,11 @@ Wallet.prototype.getRegisteredPeerIds = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.keepAlive = function() {
|
Wallet.prototype.keepAlive = function() {
|
||||||
try{
|
try {
|
||||||
this.lock.keepAlive();
|
this.lock.keepAlive();
|
||||||
} catch(e){
|
} catch (e) {
|
||||||
this.log(e);
|
this.log(e);
|
||||||
this.emit('locked',null,'Wallet appears to be openned on other browser instance. Closing this one.' );
|
this.emit('locked', null, 'Wallet appears to be openned on other browser instance. Closing this one.');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -533,11 +533,36 @@ Wallet.prototype.toObj = function() {
|
||||||
// fromObj => from a trusted source
|
// fromObj => from a trusted source
|
||||||
Wallet.fromObj = function(o, storage, network, blockchain) {
|
Wallet.fromObj = function(o, storage, network, blockchain) {
|
||||||
var opts = JSON.parse(JSON.stringify(o.opts));
|
var opts = JSON.parse(JSON.stringify(o.opts));
|
||||||
|
|
||||||
opts.addressBook = o.addressBook;
|
opts.addressBook = o.addressBook;
|
||||||
|
|
||||||
opts.publicKeyRing = PublicKeyRing.fromObj(o.publicKeyRing);
|
if (o.privateKey)
|
||||||
opts.txProposals = TxProposals.fromObj(o.txProposals, Wallet.builderOpts);
|
|
||||||
opts.privateKey = PrivateKey.fromObj(o.privateKey);
|
opts.privateKey = PrivateKey.fromObj(o.privateKey);
|
||||||
|
else
|
||||||
|
opts.privateKey = new PrivateKey({
|
||||||
|
networkName: opts.networkName
|
||||||
|
});
|
||||||
|
|
||||||
|
if (o.publicKeyRing)
|
||||||
|
opts.publicKeyRing = PublicKeyRing.fromObj(o.publicKeyRing);
|
||||||
|
else {
|
||||||
|
opts.publicKeyRing = new PublicKeyRing({
|
||||||
|
networkName: opts.networkName,
|
||||||
|
requiredCopayers: opts.requiredCopayers,
|
||||||
|
totalCopayers: opts.totalCopayers,
|
||||||
|
});
|
||||||
|
opts.publicKeyRing.addCopayer(
|
||||||
|
opts.privateKey.deriveBIP45Branch().extendedPublicKeyString(),
|
||||||
|
opts.nickname
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o.txProposals)
|
||||||
|
opts.txProposals = TxProposals.fromObj(o.txProposals, Wallet.builderOpts);
|
||||||
|
else
|
||||||
|
opts.txProposals = new TxProposals({
|
||||||
|
networkName: this.networkName,
|
||||||
|
});
|
||||||
|
|
||||||
opts.storage = storage;
|
opts.storage = storage;
|
||||||
opts.network = network;
|
opts.network = network;
|
||||||
|
@ -681,6 +706,19 @@ Wallet.prototype.getTxProposals = function() {
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Wallet.prototype.purgeTxProposals = function(deleteAll) {
|
||||||
|
var m = this.txProposals.length();
|
||||||
|
|
||||||
|
if (deleteAll) {
|
||||||
|
this.txProposals.deleteAll();
|
||||||
|
} else {
|
||||||
|
this.txProposals.deletePending(this.maxRejectCount());
|
||||||
|
}
|
||||||
|
this.store();
|
||||||
|
|
||||||
|
var n = this.txProposals.length();
|
||||||
|
return m-n;
|
||||||
|
};
|
||||||
|
|
||||||
Wallet.prototype.reject = function(ntxid) {
|
Wallet.prototype.reject = function(ntxid) {
|
||||||
var txp = this.txProposals.reject(ntxid, this.getMyCopayerId());
|
var txp = this.txProposals.reject(ntxid, this.getMyCopayerId());
|
||||||
|
@ -1459,6 +1497,17 @@ Wallet.prototype.getBalance = function(cb) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// See
|
||||||
|
// https://github.com/bitpay/copay/issues/1056
|
||||||
|
//
|
||||||
|
// maxRejectCount should equal requiredCopayers
|
||||||
|
// strictly.
|
||||||
|
//
|
||||||
|
Wallet.prototype.maxRejectCount = function(cb) {
|
||||||
|
return this.totalCopayers - this.requiredCopayers;
|
||||||
|
};
|
||||||
|
|
||||||
Wallet.prototype.getUnspent = function(cb) {
|
Wallet.prototype.getUnspent = function(cb) {
|
||||||
var self = this;
|
var self = this;
|
||||||
this.blockchain.getUnspent(this.getAddressesStr(), function(err, unspentList) {
|
this.blockchain.getUnspent(this.getAddressesStr(), function(err, unspentList) {
|
||||||
|
@ -1468,8 +1517,7 @@ Wallet.prototype.getUnspent = function(cb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var safeUnspendList = [];
|
var safeUnspendList = [];
|
||||||
var maxRejectCount = self.totalCopayers - self.requiredCopayers;
|
var uu = self.txProposals.getUsedUnspent(self.maxRejectCount());
|
||||||
var uu = self.txProposals.getUsedUnspent(maxRejectCount);
|
|
||||||
|
|
||||||
for (var i in unspentList) {
|
for (var i in unspentList) {
|
||||||
var u = unspentList[i];
|
var u = unspentList[i];
|
||||||
|
|
|
@ -50,11 +50,22 @@ WalletFactory.prototype._checkRead = function(walletId) {
|
||||||
return !!ret;
|
return !!ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
WalletFactory.prototype.fromObj = function(obj) {
|
WalletFactory.prototype.fromObj = function(obj, skipFields) {
|
||||||
|
|
||||||
// not stored options
|
// not stored options
|
||||||
obj.opts.reconnectDelay = this.walletDefaults.reconnectDelay;
|
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]) {
|
||||||
|
delete obj[k];
|
||||||
|
} else
|
||||||
|
throw new Error('unknown field:' + k);
|
||||||
|
});
|
||||||
|
|
||||||
var w = Wallet.fromObj(obj, this.storage, this.network, this.blockchain);
|
var w = Wallet.fromObj(obj, this.storage, this.network, this.blockchain);
|
||||||
if (!w) return false;
|
if (!w) return false;
|
||||||
w.verbose = this.verbose;
|
w.verbose = this.verbose;
|
||||||
|
@ -63,23 +74,23 @@ WalletFactory.prototype.fromObj = function(obj) {
|
||||||
return w;
|
return w;
|
||||||
};
|
};
|
||||||
|
|
||||||
WalletFactory.prototype.fromEncryptedObj = function(base64, password) {
|
WalletFactory.prototype.fromEncryptedObj = function(base64, password, skipFields) {
|
||||||
this.storage._setPassphrase(password);
|
this.storage._setPassphrase(password);
|
||||||
var walletObj = this.storage.import(base64);
|
var walletObj = this.storage.import(base64);
|
||||||
if (!walletObj) return false;
|
if (!walletObj) return false;
|
||||||
var w = this.fromObj(walletObj);
|
var w = this.fromObj(walletObj, skipFields);
|
||||||
return w;
|
return w;
|
||||||
};
|
};
|
||||||
|
|
||||||
WalletFactory.prototype.import = function(base64, password) {
|
WalletFactory.prototype.import = function(base64, password, skipFields) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var w = self.fromEncryptedObj(base64, password);
|
var w = self.fromEncryptedObj(base64, password, skipFields);
|
||||||
|
|
||||||
if (!w) throw new Error('Wrong password');
|
if (!w) throw new Error('Wrong password');
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
WalletFactory.prototype.read = function(walletId) {
|
WalletFactory.prototype.read = function(walletId, skipFields) {
|
||||||
if (!this._checkRead(walletId))
|
if (!this._checkRead(walletId))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -94,7 +105,7 @@ WalletFactory.prototype.read = function(walletId) {
|
||||||
obj.addressBook = s.get(walletId, 'addressBook');
|
obj.addressBook = s.get(walletId, 'addressBook');
|
||||||
obj.backupOffered = s.get(walletId, 'backupOffered');
|
obj.backupOffered = s.get(walletId, 'backupOffered');
|
||||||
|
|
||||||
var w = this.fromObj(obj);
|
var w = this.fromObj(obj, skipFields);
|
||||||
return w;
|
return w;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -102,9 +113,15 @@ WalletFactory.prototype.create = function(opts) {
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
this.log('### CREATING NEW WALLET.' + (opts.id ? ' USING ID: ' + opts.id : ' NEW ID') + (opts.privateKey ? ' USING PrivateKey: ' + opts.privateKey.getId() : ' NEW PrivateKey'));
|
this.log('### CREATING NEW WALLET.' + (opts.id ? ' USING ID: ' + opts.id : ' NEW ID') + (opts.privateKey ? ' USING PrivateKey: ' + opts.privateKey.getId() : ' NEW PrivateKey'));
|
||||||
|
|
||||||
opts.privateKey = opts.privateKey || new PrivateKey({
|
var privOpts = {
|
||||||
networkName: this.networkName
|
networkName: this.networkName,
|
||||||
});
|
};
|
||||||
|
|
||||||
|
if (opts.privateKeyHex && opts.privateKeyHex.length>1) {
|
||||||
|
privOpts.extendedPrivateKeyString = opts.privateKeyHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.privateKey = opts.privateKey || new PrivateKey(privOpts);
|
||||||
|
|
||||||
var requiredCopayers = opts.requiredCopayers || this.walletDefaults.requiredCopayers;
|
var requiredCopayers = opts.requiredCopayers || this.walletDefaults.requiredCopayers;
|
||||||
var totalCopayers = opts.totalCopayers || this.walletDefaults.totalCopayers;
|
var totalCopayers = opts.totalCopayers || this.walletDefaults.totalCopayers;
|
||||||
|
@ -203,16 +220,22 @@ WalletFactory.prototype.decodeSecret = function(secret) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
WalletFactory.prototype.joinCreateSession = function(secret, nickname, passphrase, cb) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
|
WalletFactory.prototype.joinCreateSession = function(secret, nickname, passphrase, privateHex, cb) {
|
||||||
|
var self = this;
|
||||||
var s = self.decodeSecret(secret);
|
var s = self.decodeSecret(secret);
|
||||||
if (!s) return cb('badSecret');
|
if (!s) return cb('badSecret');
|
||||||
|
|
||||||
|
var privOpts = {
|
||||||
|
networkName: this.networkName,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (privateHex && privateHex.length>1) {
|
||||||
|
privOpts.extendedPrivateKeyString = privateHex;
|
||||||
|
}
|
||||||
|
|
||||||
//Create our PrivateK
|
//Create our PrivateK
|
||||||
var privateKey = new PrivateKey({
|
var privateKey = new PrivateKey(privOpts);
|
||||||
networkName: this.networkName
|
|
||||||
});
|
|
||||||
this.log('\t### PrivateKey Initialized');
|
this.log('\t### PrivateKey Initialized');
|
||||||
var opts = {
|
var opts = {
|
||||||
copayerId: privateKey.getId(),
|
copayerId: privateKey.getId(),
|
||||||
|
|
|
@ -42,8 +42,8 @@ angular
|
||||||
templateUrl: 'views/send.html',
|
templateUrl: 'views/send.html',
|
||||||
validate: true
|
validate: true
|
||||||
})
|
})
|
||||||
.when('/backup', {
|
.when('/more', {
|
||||||
templateUrl: 'views/backup.html',
|
templateUrl: 'views/more.html',
|
||||||
validate: true
|
validate: true
|
||||||
})
|
})
|
||||||
.when('/settings', {
|
.when('/settings', {
|
||||||
|
|
|
@ -6,6 +6,12 @@ if (is_browser) {
|
||||||
}
|
}
|
||||||
var Wallet = copay.Wallet;
|
var Wallet = copay.Wallet;
|
||||||
|
|
||||||
|
var FakePrivateKey = function () {
|
||||||
|
};
|
||||||
|
|
||||||
|
FakePrivateKey.prototype.toObj = function() {
|
||||||
|
return extendedPublicKeyString = 'privHex';
|
||||||
|
};
|
||||||
|
|
||||||
var FakeWallet = function() {
|
var FakeWallet = function() {
|
||||||
this.id = 'testID';
|
this.id = 'testID';
|
||||||
|
@ -30,6 +36,8 @@ var FakeWallet = function() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.privateKey = new FakePrivateKey();
|
||||||
};
|
};
|
||||||
|
|
||||||
FakeWallet.prototype.createTx = function(toAddress, amountSatStr, comment, opts, cb) {
|
FakeWallet.prototype.createTx = function(toAddress, amountSatStr, comment, opts, cb) {
|
||||||
|
|
|
@ -139,6 +139,7 @@ describe('TxProposal', function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
describe('#setSent', function() {
|
describe('#setSent', function() {
|
||||||
it('should set txid and timestamp', function() {
|
it('should set txid and timestamp', function() {
|
||||||
var now = Date.now();
|
var now = Date.now();
|
||||||
|
@ -430,4 +431,33 @@ describe('TxProposal', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('micelaneous functions', function() {
|
||||||
|
it('should report rejectCount', function() {
|
||||||
|
var txp = dummyProposal;
|
||||||
|
txp.rejectCount().should.equal(0);
|
||||||
|
txp.setRejected(['juan'])
|
||||||
|
txp.rejectCount().should.equal(1);
|
||||||
|
});
|
||||||
|
it('should report isPending 1', function() {
|
||||||
|
var txp = dummyProposal;
|
||||||
|
txp.rejectedBy=[];
|
||||||
|
txp.sentTxid=1;
|
||||||
|
txp.isPending(3).should.equal(false);
|
||||||
|
});
|
||||||
|
it('should report isPending 2', function() {
|
||||||
|
var txp = dummyProposal;
|
||||||
|
txp.rejectedBy=[];
|
||||||
|
txp.sentTxid=null;
|
||||||
|
txp.isPending(3).should.equal(true);
|
||||||
|
});
|
||||||
|
it('should report isPending 3', function() {
|
||||||
|
var txp = dummyProposal;
|
||||||
|
txp.rejectedBy=[1,2,3,4];
|
||||||
|
txp.sentTxid=null;
|
||||||
|
txp.isPending(3).should.equal(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -357,6 +357,44 @@ describe('Wallet model', function() {
|
||||||
throw();
|
throw();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('#maxRejectCount', function() {
|
||||||
|
var w = cachedCreateW();
|
||||||
|
w.maxRejectCount().should.equal(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('#purgeTxProposals', function() {
|
||||||
|
it('should delete all', function() {
|
||||||
|
var w = cachedCreateW();
|
||||||
|
var spy1 = sinon.spy(w.txProposals, 'deleteAll');
|
||||||
|
var spy2 = sinon.spy(w.txProposals, 'deletePending');
|
||||||
|
w.purgeTxProposals(1);
|
||||||
|
spy1.callCount.should.equal(1);
|
||||||
|
spy2.callCount.should.equal(0);
|
||||||
|
spy1.restore();
|
||||||
|
spy2.restore();
|
||||||
|
});
|
||||||
|
it('should delete pending', function() {
|
||||||
|
var w = cachedCreateW();
|
||||||
|
var spy1 = sinon.spy(w.txProposals, 'deleteAll');
|
||||||
|
var spy2 = sinon.spy(w.txProposals, 'deletePending');
|
||||||
|
w.purgeTxProposals();
|
||||||
|
spy1.callCount.should.equal(0);
|
||||||
|
spy2.callCount.should.equal(1);
|
||||||
|
spy1.restore();
|
||||||
|
spy2.restore();
|
||||||
|
});
|
||||||
|
it('should count deletions', function() {
|
||||||
|
var w = cachedCreateW();
|
||||||
|
var s = sinon.stub(w.txProposals, 'length').returns(10);
|
||||||
|
var n = w.purgeTxProposals();
|
||||||
|
n.should.equal(0);
|
||||||
|
s.restore();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
//this test fails randomly
|
//this test fails randomly
|
||||||
it.skip('call reconnect after interval', function(done) {
|
it.skip('call reconnect after interval', function(done) {
|
||||||
this.timeout(10000);
|
this.timeout(10000);
|
||||||
|
@ -378,6 +416,8 @@ describe('Wallet model', function() {
|
||||||
w.isShared().should.equal(false);
|
w.isShared().should.equal(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
it('#isReady', function() {
|
it('#isReady', function() {
|
||||||
var w = createW();
|
var w = createW();
|
||||||
w.publicKeyRing.isComplete().should.equal(false);
|
w.publicKeyRing.isComplete().should.equal(false);
|
||||||
|
|
|
@ -138,6 +138,27 @@ describe('WalletFactory model', function() {
|
||||||
var w = wf.create();
|
var w = wf.create();
|
||||||
should.exist(w);
|
should.exist(w);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be able to create wallets with given pk', function() {
|
||||||
|
var wf = new WalletFactory(config, '0.0.1');
|
||||||
|
var priv = 'tprv8ZgxMBicQKsPdEqHcA7RjJTayxA3gSSqeRTttS1JjVbgmNDZdSk9EHZK5pc52GY5xFmwcakmUeKWUDzGoMLGAhrfr5b3MovMUZUTPqisL2m';
|
||||||
|
var w = wf.create({
|
||||||
|
privateKeyHex:priv,
|
||||||
|
});
|
||||||
|
w.privateKey.toObj().extendedPrivateKeyString.should.equal(priv);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to create wallets with random pk', function() {
|
||||||
|
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
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should be able to get wallets', function() {
|
it('should be able to get wallets', function() {
|
||||||
var wf = new WalletFactory(config, '0.0.1');
|
var wf = new WalletFactory(config, '0.0.1');
|
||||||
var w = wf.create();
|
var w = wf.create();
|
||||||
|
@ -175,6 +196,19 @@ describe('WalletFactory model', function() {
|
||||||
assertObjectEqual(w.toObj(), JSON.parse(o));
|
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() {
|
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 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"},"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":{}}';
|
||||||
|
@ -391,9 +425,17 @@ describe('WalletFactory model', function() {
|
||||||
var wf = new WalletFactory(config, '0.0.1');
|
var wf = new WalletFactory(config, '0.0.1');
|
||||||
wf.network.cleanUp = sinon.spy();
|
wf.network.cleanUp = sinon.spy();
|
||||||
wf.network.start = sinon.spy();
|
wf.network.start = sinon.spy();
|
||||||
wf.joinCreateSession('8WtTuiFTkhP5ao7AF2QErSwV39Cbur6pdMebKzQXFqL59RscXM', 'test', null, undefined);
|
wf.joinCreateSession('8WtTuiFTkhP5ao7AF2QErSwV39Cbur6pdMebKzQXFqL59RscXM', 'test');
|
||||||
wf.network.start.calledOnce.should.equal(true);
|
wf.network.start.calledOnce.should.equal(true);
|
||||||
});
|
});
|
||||||
|
it('should accept a priv key a input', function() {
|
||||||
|
var wf = new WalletFactory(config, '0.0.1');
|
||||||
|
var privHex = 'tprv8ZgxMBicQKsPf7MCvCjnhnr4uiR2Z2gyNC27vgd9KUu98F9mM1tbaRrWMyddVju36GxLbeyntuSadBAttriwGGMWUkRgVmUUCg5nFioGZsd';
|
||||||
|
wf.network.cleanUp = sinon.spy();
|
||||||
|
wf.network.start = sinon.spy();
|
||||||
|
wf.joinCreateSession('8WtTuiFTkhP5ao7AF2QErSwV39Cbur6pdMebKzQXFqL59RscXM', 'test', null, privHex);
|
||||||
|
wf.network.start.getCall(0).args[0].privkey.should.equal('ddc2fa8c583a73c4b2a24630ec7c283df4e7c230a02c4e48bc36ec61687afd7d');
|
||||||
|
});
|
||||||
it('should call network.start with private key', function() {
|
it('should call network.start with private key', function() {
|
||||||
var wf = new WalletFactory(config, '0.0.1');
|
var wf = new WalletFactory(config, '0.0.1');
|
||||||
wf.network.cleanUp = sinon.spy();
|
wf.network.cleanUp = sinon.spy();
|
||||||
|
|
|
@ -38,7 +38,7 @@ describe("Unit: Controllers", function() {
|
||||||
scope = $rootScope.$new();
|
scope = $rootScope.$new();
|
||||||
|
|
||||||
$rootScope.wallet = new FakeWallet(config);
|
$rootScope.wallet = new FakeWallet(config);
|
||||||
ctrl = $controller('BackupController', {
|
ctrl = $controller('MoreController', {
|
||||||
$scope: scope,
|
$scope: scope,
|
||||||
$modal: {},
|
$modal: {},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
<div class="backup" ng-controller="BackupController">
|
|
||||||
<h1>Backup & Delete </h1>
|
|
||||||
<div class="oh large-12 columns panel">
|
|
||||||
<h3><i class="fi-download m10r"></i> Backup </h3>
|
|
||||||
<p class="large-8 columns text-gray"> Its important to back up your wallet so that you can recover your wallet in case of disaster </p>
|
|
||||||
<div class="large-4 columns">
|
|
||||||
<a class="button primary expand" ng-click="downloadBackup()">Download File</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="large-12 columns line-dashed-h m15b"> </div>
|
|
||||||
<div>
|
|
||||||
<div class="oh large-12 columns panel">
|
|
||||||
<h3><i class="fi-minus-circle m10r"></i> Delete Wallet </h3>
|
|
||||||
<p class="large-8 columns text-gray"> If all funds have been removed from your wallet and you do not wish to have the wallet data stored on your computer anymore, you can delete your wallet. </p>
|
|
||||||
<div class="large-4 columns">
|
|
||||||
<a class="button warning expand" ng-really-message="Are you sure to delete this wallet from this computer?" ng-really-click="deleteWallet()"> Delete</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
|
@ -3,23 +3,50 @@
|
||||||
<i class="size-60 fi-bitcoin-circle icon-rotate spinner"></i>
|
<i class="size-60 fi-bitcoin-circle icon-rotate spinner"></i>
|
||||||
{{ importStatus }}
|
{{ importStatus }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row" ng-init="choosefile=0; pastetext=0" ng-show="!loading">
|
<div class="row" ng-init="choosefile=0; pastetext=0" ng-show="!loading">
|
||||||
<div class="large-4 columns logo-setup">
|
<div class="large-4 columns logo-setup">
|
||||||
<img src="img/logo-negative-beta.svg" alt="Copay" width="146" height="59">
|
<img src="img/logo-negative-beta.svg" alt="Copay" width="146" height="59">
|
||||||
<div ng-include="'views/includes/version.html'"></div>
|
<div ng-include="'views/includes/version.html'"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="large-8 columns line-dashed-setup-v">
|
<div class="large-8 columns line-dashed-setup-v">
|
||||||
|
|
||||||
<div class="box-setup">
|
<div class="box-setup">
|
||||||
<h1 class="text-white line-sidebar-b">{{title}}</h1>
|
<h1 class="text-white line-sidebar-b">{{title}}</h1>
|
||||||
<form name="importForm" ng-submit="import(importForm)" novalidate>
|
<form name="importForm" ng-submit="import(importForm)" novalidate>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend for="backupFile" class="m10b"> Choose backup file from your computer <i class="fi-laptop"></i></legend>
|
<legend for="backupFile" class="m10b"> Choose backup file from your computer <i class="fi-laptop"></i></legend>
|
||||||
<input type="file" class="form-control" placeholder="Select a backup file" name="backupFile" ng-model="backupFile" ng-file-select>
|
<input type="file" class="form-control" placeholder="Select a backup file" name="backupFile" ng-model="backupFile" ng-file-select>
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<label for="password">Password <small>Required</small></label>
|
<label for="password">Password <small>Required</small></label>
|
||||||
<input type="password" class="form-control" placeholder="Your wallet password" name="password" ng-model="password" required>
|
<input type="password" class="form-control" placeholder="Your wallet password" name="password" ng-model="password" required>
|
||||||
|
|
||||||
|
<a class="expand small" ng-click="hideAdv=!hideAdv">
|
||||||
|
<span ng-hide="!hideAdv">Show</span>
|
||||||
|
<span ng-hide="hideAdv">Hide</span>
|
||||||
|
advanced options
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<div ng-hide="hideAdv">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" class="form-control" name="skipPublicKeyRing" ng-model="skipPublicKeyRing"> Skip public keys from peers
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" class="form-control" name="skipTxProposals" ng-model="skipTxProposals"> Skip transaction proposals from Backup
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</fieldset>
|
||||||
|
<div data-alert ng-show="skipFields">
|
||||||
|
<i class="size-18 fi-alert"></i>
|
||||||
|
Skipping fields: {{skipFields}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
<a class="back-button text-white m20r" href="#!/">« Back</a>
|
<a class="back-button text-white m20r" href="#!/">« Back</a>
|
||||||
<button type="submit" class="button primary m0" ng-disabled="importForm.$invalid" loading="Importing">
|
<button type="submit" class="button primary m0" ng-disabled="importForm.$invalid" loading="Importing">
|
||||||
|
|
|
@ -67,10 +67,28 @@
|
||||||
name="joinPasswordConfirm"
|
name="joinPasswordConfirm"
|
||||||
ng-model="joinPasswordConfirm"
|
ng-model="joinPasswordConfirm"
|
||||||
match="joinPassword" required>
|
match="joinPassword" required>
|
||||||
|
<a class="expand small" ng-click="hideAdv=!hideAdv">
|
||||||
|
<span ng-hide="!hideAdv">Show</span>
|
||||||
|
<span ng-hide="hideAdv">Hide</span>
|
||||||
|
advanced options
|
||||||
|
</a>
|
||||||
|
<div ng-hide="hideAdv">
|
||||||
|
<p>
|
||||||
|
<input type="text"
|
||||||
|
placeholder="Private Key (Hex)"
|
||||||
|
name="private"
|
||||||
|
ng-model="$parent.private"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
<a href="#!/" class="back-button text-primary m20r">« Back</a>
|
<a href="#!/" class="back-button text-primary m20r">« Back</a>
|
||||||
<button type="submit" class="button primary m0" ng-disabled="joinForm.$invalid || loading" loading="Joining">Join</button>
|
<button type="submit" class="button primary m0" ng-disabled="joinForm.$invalid || loading" loading="Joining">Join</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
<div class="backup" ng-controller="MoreController">
|
||||||
|
<h1>Backup & Delete </h1>
|
||||||
|
<div class="oh large-12 columns panel">
|
||||||
|
<h3><i class="fi-download m10r"></i> Backup </h3>
|
||||||
|
<p class="large-8 columns text-gray"> Its important to back up your wallet so that you can recover your wallet in case of disaster </p>
|
||||||
|
<div class="large-4 columns">
|
||||||
|
<a class="button primary expand" ng-click="downloadBackup()">Download File</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="large-12 columns line-dashed-h m15b"> </div>
|
||||||
|
<div>
|
||||||
|
<div class="oh large-12 columns panel">
|
||||||
|
<h3><i class="fi-minus-circle m10r"></i> Delete Wallet </h3>
|
||||||
|
<p class="large-8 columns text-gray"> If all funds have been removed from your wallet and you do not wish to have the wallet data stored on your computer anymore, you can delete your wallet. </p>
|
||||||
|
<div class="large-4 columns">
|
||||||
|
<a class="button warning expand" ng-really-message="Are you sure to delete this wallet from this computer?" ng-really-click="deleteWallet()"> Delete</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a class="expand small" ng-click="hideAdv=!hideAdv">
|
||||||
|
<span ng-hide="!hideAdv">Show</span>
|
||||||
|
<span ng-hide="hideAdv">Hide</span>
|
||||||
|
advanced options
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<div ng-hide="hideAdv">
|
||||||
|
<div class="oh large-12 columns panel">
|
||||||
|
<h3><i class="fi-minus-circle m10r"></i> Master Private Key </h3>
|
||||||
|
<p class="large-8 columns text-gray"> Your master private key contains the information to sign <b>any</b> transaction on this wallet. Handle with care.
|
||||||
|
<div class="large-4 columns">
|
||||||
|
<a class="button primary expand" ng-click="hidePriv=!hidePriv">
|
||||||
|
<span ng-hide="!hidePriv">Show</span>
|
||||||
|
<span ng-hide="hidePriv">Hide</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<textarea ng-hide="hidePriv" readonly>{{priv}}</textarea>
|
||||||
|
</div>
|
||||||
|
<div class="oh large-12 columns panel">
|
||||||
|
<h3><i class="fi-minus-circle m10r"></i> Scan Wallet Addresses </h3>
|
||||||
|
<p class="large-8 columns text-gray"> This will scan the blockchain looking for addresses derived from your wallet, in case you have funds in addresses not yet generated (e.g.: you restored an old backup). This will also trigger a syncronization of addresses to other connected peers.
|
||||||
|
<div class="large-4 columns">
|
||||||
|
<a class="button primary expand" ng-click="updateIndexes()">
|
||||||
|
Scan
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="oh large-12 columns panel">
|
||||||
|
<h3><i class="fi-minus-circle m10r"></i> Purge Pending Transaction Proposals </h3>
|
||||||
|
<p class="large-8 columns text-gray"> Pending Transactions Proposals will be discarted. This need to be done on <b>ALL<b> peers of a wallet, to prevent the old proposals to be resynced again.
|
||||||
|
<div class="large-4 columns">
|
||||||
|
<a class="button warning expand" ng-click="purge()">
|
||||||
|
Purge
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="oh large-12 columns panel">
|
||||||
|
<h3><i class="fi-minus-circle m10r"></i> Purge ALL Transaction Proposals </h3>
|
||||||
|
<p class="large-8 columns text-gray"> ALL Transactions Proposals will be discarted. This need to be done on <b>ALL<b> peers of a wallet, to prevent the old proposals to be resynced again.
|
||||||
|
<div class="large-4 columns">
|
||||||
|
<a class="button warning expand" ng-click="purge(true)">
|
||||||
|
Purge All
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
|
@ -44,6 +44,21 @@
|
||||||
match="walletPassword"
|
match="walletPassword"
|
||||||
required>
|
required>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<a class="expand small" ng-click="hideAdv=!hideAdv">
|
||||||
|
<span ng-hide="!hideAdv">Show</span>
|
||||||
|
<span ng-hide="hideAdv">Hide</span>
|
||||||
|
advanced options
|
||||||
|
</a>
|
||||||
|
<div ng-hide="hideAdv">
|
||||||
|
<p>
|
||||||
|
<input type="text"
|
||||||
|
placeholder="Private Key (Hex)"
|
||||||
|
name="private"
|
||||||
|
ng-model="private"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="row" ng-show="!isSetupWalletPage">
|
<div class="row" ng-show="!isSetupWalletPage">
|
||||||
<div class="large-6 medium-6 columns">
|
<div class="large-6 medium-6 columns">
|
||||||
|
@ -68,7 +83,7 @@
|
||||||
width="50px">
|
width="50px">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="comment" ng-show="totalCopayers>1">(*) The limits are imposed by the bitcoin network.</p>
|
<p class="comment" ng-show="totalCopayers>1 && !isSetupWalletPage">(*) The limits are imposed by the bitcoin network.</p>
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
<a ng-show="!isSetupWalletPage" class="back-button m20r" href="#!/">« Back</a>
|
<a ng-show="!isSetupWalletPage" class="back-button m20r" href="#!/">« Back</a>
|
||||||
<a ng-show="isSetupWalletPage" class="back-button m20r"
|
<a ng-show="isSetupWalletPage" class="back-button m20r"
|
||||||
|
|
Loading…
Reference in New Issue