refactor duplicate
This commit is contained in:
parent
acc1549633
commit
7349e8237a
8 changed files with 149 additions and 52 deletions
|
|
@ -56,7 +56,7 @@
|
||||||
"bezier-easing": "^2.0.3",
|
"bezier-easing": "^2.0.3",
|
||||||
"bhttp": "1.2.1",
|
"bhttp": "1.2.1",
|
||||||
"bitauth": "^0.2.1",
|
"bitauth": "^0.2.1",
|
||||||
"bitcore-wallet-client": "6.0.1",
|
"bitcore-wallet-client": "6.1.0",
|
||||||
"bower": "^1.7.9",
|
"bower": "^1.7.9",
|
||||||
"cordova-android": "5.1.1",
|
"cordova-android": "5.1.1",
|
||||||
"cordova-custom-config": "^3.0.5",
|
"cordova-custom-config": "^3.0.5",
|
||||||
|
|
|
||||||
|
|
@ -1,48 +1,62 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('cashScanController',
|
angular.module('copayApp.controllers').controller('cashScanController',
|
||||||
function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, $window, gettextCatalog, lodash, popupService, ongoingProcess, profileService, walletService, configService, $log, txFormatService, bwcError, pushNotificationsService, bwcService) {
|
function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, $window, gettextCatalog, lodash, popupService, ongoingProcess, profileService, walletService, configService, $log, txFormatService, bwcError, pushNotificationsService, bwcService) {
|
||||||
var wallet;
|
var wallet;
|
||||||
var errors = bwcService.getErrors();
|
var errors = bwcService.getErrors();
|
||||||
$scope.error = null;
|
$scope.error = null;
|
||||||
|
|
||||||
$scope.$on("$ionicView.enter", function(event, data) {
|
$scope.$on("$ionicView.enter", function(event, data) {
|
||||||
updateAllWallets();
|
updateAllWallets();
|
||||||
});
|
});
|
||||||
|
|
||||||
var updateAllWallets = function() {
|
var updateAllWallets = function() {
|
||||||
var wallets = profileService.getWallets({coin:'btc', onlyComplete:true, network: 'livenet' });
|
var wallets1 = profileService.getWallets({
|
||||||
|
coin: 'btc',
|
||||||
|
onlyComplete: true,
|
||||||
|
network: 'livenet'
|
||||||
|
});
|
||||||
|
|
||||||
|
if (lodash.isEmpty(wallets1)) {
|
||||||
|
$state.go('tabs.home');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter out already duplicated wallets
|
||||||
|
var walletsBCH = profileService.getWallets({
|
||||||
|
coin: 'bch',
|
||||||
|
network: 'livenet'
|
||||||
|
});
|
||||||
|
var xPubKeyIndex = lodash.indexBy(walletsBCH, "credentials.xPubKey");
|
||||||
|
|
||||||
|
wallets1 = lodash.filter(wallets1, function(w) {
|
||||||
|
return !xPubKeyIndex[w.credentials.xPubKey];
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
var kk = lodash.indexBy(wallets,"credentials.xPubKey");
|
// Filter out non BIP44 wallets
|
||||||
|
var wallets = lodash.filter(wallets1, function(w) {
|
||||||
|
return w.credentials.derivationStrategy == 'BIP44'
|
||||||
// TODO ?
|
});
|
||||||
if (lodash.isEmpty(wallets)) return;
|
|
||||||
|
|
||||||
|
|
||||||
var walletsBCH = profileService.getWallets({coin:'bch', network: 'livenet' });
|
|
||||||
var xPubKeyIndex = lodash.indexBy(walletsBCH,"credentials.xPubKey");
|
|
||||||
|
|
||||||
// wallets= lodash.filter(wallets,function(w) { return !xPubKeyIndex[w.credentials.xPubKey]; });
|
|
||||||
|
|
||||||
$scope.wallets = wallets;
|
$scope.wallets = wallets;
|
||||||
|
$scope.nonBIP44 = wallets1.length != wallets.length;
|
||||||
|
|
||||||
var i = wallets.length;
|
var i = wallets.length;
|
||||||
var j = 0;
|
var j = 0;
|
||||||
lodash.each(wallets, function(wallet) {
|
lodash.each(wallets, function(wallet) {
|
||||||
walletService.getBalance(wallet, {coin:'bch'}, function(err, balance) {
|
walletService.getBalance(wallet, {
|
||||||
|
coin: 'bch'
|
||||||
|
}, function(err, balance) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
||||||
wallet.error = (err === 'WALLET_NOT_REGISTERED') ? gettextCatalog.getString('Wallet not registered') : bwcError.msg(err);
|
wallet.error = (err === 'WALLET_NOT_REGISTERED') ? gettextCatalog.getString('Wallet not registered') : bwcError.msg(err);
|
||||||
|
|
||||||
$log.error(err);
|
$log.error(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
|
||||||
console.log('[otherBalance.js.28:balance:]',balance); //TODO
|
|
||||||
wallet.error = null;
|
wallet.error = null;
|
||||||
wallet.bchBalance = txFormatService.formatAmountStr('bch', balance.availableAmount);
|
wallet.bchBalance = txFormatService.formatAmountStr('bch', balance.availableAmount);
|
||||||
if (++j == i) {
|
if (++j == i) {
|
||||||
|
|
@ -58,24 +72,26 @@ console.log('[otherBalance.js.28:balance:]',balance); //TODO
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.duplicate = function(wallet) {
|
$scope.duplicate = function(wallet) {
|
||||||
$scope.error = null;
|
$scope.error = null;
|
||||||
$log.debug('Duplicating wallet for BCH:' + wallet.id + ':' + wallet.name);
|
$log.debug('Duplicating wallet for BCH:' + wallet.id + ':' + wallet.name);
|
||||||
|
|
||||||
var opts = {};
|
var opts = {};
|
||||||
opts.name = wallet.name + '[BCH]';
|
opts.name = wallet.name + '[BCH]';
|
||||||
opts.m = wallet.m;
|
opts.m = wallet.m;
|
||||||
opts.n = wallet.n;
|
opts.n = wallet.n;
|
||||||
opts.myName = wallet.credentials.copayerName;
|
opts.myName = wallet.credentials.copayerName;
|
||||||
opts.networkName = wallet.network;
|
opts.networkName = wallet.network;
|
||||||
opts.coin = 'bch';
|
opts.coin = 'bch';
|
||||||
|
opts.walletPrivKey = wallet.credentials.walletPrivKey;
|
||||||
|
opts.compliantDerivation = wallet.credentials.compliantDerivation;
|
||||||
|
|
||||||
// TODO: finger print / decrypt
|
|
||||||
$log.warn('TODO finger print / decrypt');
|
|
||||||
opts.extendedPrivateKey = wallet.credentials.xPrivKey;
|
|
||||||
|
|
||||||
function setErr(err, cb) {
|
function setErr(err, cb) {
|
||||||
$scope.error = bwcError.cb(err, gettextCatalog.getString('Could not duplicate'), function() {
|
|
||||||
return cb(err);
|
if (!cb) cb = function() {};
|
||||||
|
|
||||||
|
$scope.error = bwcError.cb(err, gettextCatalog.getString('Could not duplicate'), function() {
|
||||||
|
return cb(err);
|
||||||
});
|
});
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
$rootScope.$apply();
|
$rootScope.$apply();
|
||||||
|
|
@ -83,35 +99,70 @@ console.log('[otherBalance.js.28:balance:]',balance); //TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
function importOrCreate(cb) {
|
function importOrCreate(cb) {
|
||||||
walletService.getStatus(wallet, {}, function(err, status){
|
walletService.getStatus(wallet, {}, function(err, status) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
|
||||||
opts.singleAddress = status.wallet.singleAddress;
|
opts.singleAddress = status.wallet.singleAddress;
|
||||||
|
|
||||||
// first try to import
|
// first try to import
|
||||||
profileService.importExtendedPrivateKey(opts.extendedPrivateKey, opts, function(err, client) {
|
profileService.importExtendedPrivateKey(opts.extendedPrivateKey, opts, function(err, newWallet) {
|
||||||
if (err && !(err instanceof errors.NOT_AUTHORIZED) ) {
|
if (err && !(err instanceof errors.NOT_AUTHORIZED)) {
|
||||||
return setErr(err, cb);
|
return setErr(err, cb);
|
||||||
}
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
// create and store a wallet
|
// create and store a wallet
|
||||||
return profileService.createWallet(opts, function(err, client) {
|
return profileService.createWallet(opts, function(err, newWallet) {
|
||||||
if (err) return setErr(err, cb);
|
if (err) return setErr(err, cb);
|
||||||
return cb(null, client, true);
|
return cb(null, newWallet, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return cb(null, client);
|
return cb(null, newWallet);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Multisig wallets? add Copayers
|
||||||
|
function addCopayers(newWallet, isNew, cb) {
|
||||||
|
if (!isNew) return cb();
|
||||||
|
if (wallet.n == 1) return cb();
|
||||||
|
|
||||||
importOrCreate(function(err, client, isNew) {
|
$log.info('Adding copayers for BCH wallet config:' + wallet.m + '-' + wallet.n);
|
||||||
if (err) return;
|
|
||||||
walletService.updateRemotePreferences(client);
|
walletService.copyCopayers(wallet, newWallet, function(err) {
|
||||||
pushNotificationsService.updateSubscription(client);
|
if (err) return setErr(err, cb);
|
||||||
walletService.startScan(wallet, function() { });
|
|
||||||
$state.go('tabs.home');
|
return cb();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
walletService.getKeys(wallet,function(err,keys) {
|
||||||
|
if (err) {
|
||||||
|
$scope.error = err;
|
||||||
|
return $timeout(function() {
|
||||||
|
$rootScope.$apply();
|
||||||
|
}, 10);
|
||||||
|
}
|
||||||
|
opts.extendedPrivateKey = keys.xPrivKey;
|
||||||
|
ongoingProcess.set('duplicatingWallet', true);
|
||||||
|
importOrCreate(function(err, newWallet, isNew) {
|
||||||
|
if (err) {
|
||||||
|
ongoingProcess.set('duplicatingWallet', false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
walletService.updateRemotePreferences(newWallet);
|
||||||
|
pushNotificationsService.updateSubscription(newWallet);
|
||||||
|
|
||||||
|
addCopayers(newWallet, isNew, function(err) {
|
||||||
|
ongoingProcess.set('duplicatingWallet', false);
|
||||||
|
if (err)
|
||||||
|
return setErr(err);
|
||||||
|
|
||||||
|
if (isNew)
|
||||||
|
walletService.startScan(newWallet, function() {});
|
||||||
|
|
||||||
|
$state.go('tabs.home');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -224,6 +224,7 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
||||||
wallet.error = null;
|
wallet.error = null;
|
||||||
wallet.status = status;
|
wallet.status = status;
|
||||||
|
|
||||||
|
wallet.updating = status && status.wallet && status.wallet.scanStatus == 'running';
|
||||||
// TODO service refactor? not in profile service
|
// TODO service refactor? not in profile service
|
||||||
profileService.setLastKnownBalance(wallet.id, wallet.status.totalBalanceStr, function() {});
|
profileService.setLastKnownBalance(wallet.id, wallet.status.totalBalanceStr, function() {});
|
||||||
}
|
}
|
||||||
|
|
@ -242,6 +243,7 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
wallet.status = status;
|
wallet.status = status;
|
||||||
|
wallet.updating = status && status.wallet && status.wallet.scanStatus == 'running';
|
||||||
updateTxps();
|
updateTxps();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,8 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti
|
||||||
'cancelingGiftCard': 'Canceling Gift Card...',
|
'cancelingGiftCard': 'Canceling Gift Card...',
|
||||||
'creatingGiftCard': 'Creating Gift Card...',
|
'creatingGiftCard': 'Creating Gift Card...',
|
||||||
'buyingGiftCard': 'Buying Gift Card...',
|
'buyingGiftCard': 'Buying Gift Card...',
|
||||||
'topup': gettext('Top up in progress...')
|
'topup': gettext('Top up in progress...'),
|
||||||
|
'duplicatingWallet': gettext('Duplicating wallet...'),
|
||||||
};
|
};
|
||||||
|
|
||||||
root.clear = function() {
|
root.clear = function() {
|
||||||
|
|
|
||||||
|
|
@ -386,7 +386,6 @@ angular.module('copayApp.services')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cb(null, walletClient);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Creates a wallet on BWC/BWS
|
// Creates a wallet on BWC/BWS
|
||||||
|
|
|
||||||
|
|
@ -259,6 +259,8 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
};
|
};
|
||||||
|
|
||||||
function cacheStatus(status) {
|
function cacheStatus(status) {
|
||||||
|
if (status.wallet && status.wallet.scanStatus == 'running') return;
|
||||||
|
|
||||||
wallet.cachedStatus = status || {};
|
wallet.cachedStatus = status || {};
|
||||||
var cache = wallet.cachedStatus;
|
var cache = wallet.cachedStatus;
|
||||||
cache.statusUpdatedOn = Date.now();
|
cache.statusUpdatedOn = Date.now();
|
||||||
|
|
@ -931,15 +933,17 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
|
|
||||||
// Approx utxo amount, from which the uxto is economically redeemable
|
// Approx utxo amount, from which the uxto is economically redeemable
|
||||||
root.getLowAmount = function(wallet, feeLevels, nbOutputs) {
|
root.getLowAmount = function(wallet, feeLevels, nbOutputs) {
|
||||||
var minFee = root.getMinFee(wallet,feeLevels, nbOutputs);
|
var minFee = root.getMinFee(wallet, feeLevels, nbOutputs);
|
||||||
return parseInt( minFee / LOW_AMOUNT_RATIO);
|
return parseInt(minFee / LOW_AMOUNT_RATIO);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
root.getLowUtxos = function(wallet, levels, cb) {
|
root.getLowUtxos = function(wallet, levels, cb) {
|
||||||
|
|
||||||
wallet.getUtxos({coin: wallet.coin}, function(err, resp) {
|
wallet.getUtxos({
|
||||||
|
coin: wallet.coin
|
||||||
|
}, function(err, resp) {
|
||||||
if (err || !resp || !resp.length) return cb();
|
if (err || !resp || !resp.length) return cb();
|
||||||
|
|
||||||
var minFee = root.getMinFee(wallet, levels, resp.length);
|
var minFee = root.getMinFee(wallet, levels, resp.length);
|
||||||
|
|
@ -955,7 +959,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
var totalLow = lodash.sum(lowUtxos, 'satoshis');
|
var totalLow = lodash.sum(lowUtxos, 'satoshis');
|
||||||
|
|
||||||
return cb(err, {
|
return cb(err, {
|
||||||
allUtxos: resp || [],
|
allUtxos: resp || [],
|
||||||
lowUtxos: lowUtxos || [],
|
lowUtxos: lowUtxos || [],
|
||||||
warning: minFee / balance > TOTAL_LOW_WARNING_RATIO,
|
warning: minFee / balance > TOTAL_LOW_WARNING_RATIO,
|
||||||
minFee: minFee,
|
minFee: minFee,
|
||||||
|
|
@ -1237,5 +1241,33 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
else return 'bitcoin';
|
else return 'bitcoin';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
root.copyCopayers = function(wallet, newWallet, cb) {
|
||||||
|
var c = wallet.credentials;
|
||||||
|
|
||||||
|
var walletPrivKey = bitcore.PrivateKey.fromString(c.walletPrivKey);
|
||||||
|
|
||||||
|
var copayer = 1,
|
||||||
|
i = 0,
|
||||||
|
l = c.publicKeyRing.length;
|
||||||
|
var mainErr = null;
|
||||||
|
|
||||||
|
lodash.each(c.publicKeyRing, function(item) {
|
||||||
|
var name = item.copayerName || ('copayer ' + copayer++);
|
||||||
|
newWallet._doJoinWallet(newWallet.credentials.walletId, walletPrivKey, item.xPubKey, item.requestPubKey, name, {
|
||||||
|
coin: newWallet.credentials.coin,
|
||||||
|
}, function(err) {
|
||||||
|
//Ignore error is copayer already in wallet
|
||||||
|
if (err && !(err instanceof errors.COPAYER_IN_WALLET)) {
|
||||||
|
mainErr = err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++i == l) {
|
||||||
|
return cb(mainErr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,17 @@
|
||||||
<span translate>BTC Wallets</span>
|
<span translate>BTC Wallets</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="assertive" ng-if="wallet.error">{{wallet.error}}</span>
|
<div class="item" ng-if="error">
|
||||||
|
<span class="assertive" >{{error}}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="item" ng-if="nonBIP44">
|
||||||
|
<span class="assertive" translate>Some of you wallets are not elegible for Bitcon Cash support because there where created before Copay v1.2. Please use our recovery tool to access your Bitcoin Cash balance for those wallets</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div ng-repeat="wallet in wallets track by $index"
|
<div ng-repeat="wallet in wallets track by $index"
|
||||||
class="item item-sub item-icon-left item-big-icon-left item-icon-right wallet"
|
class="item item-sub item-icon-left item-big-icon-left item-button-right wallet"
|
||||||
>
|
>
|
||||||
<i class="icon big-icon-svg">
|
<i class="icon big-icon-svg">
|
||||||
<img ng-src="img/{{wallet.network == 'testnet' ? 'icon-wallet-testnet' : (wallet.coin == 'btc' ? 'icon-btc' : 'icon-bch')}}.svg" ng-class="{'wallet-background-color-default': !wallet.color}" ng-style="{'background-color': wallet.color}" class="bg wallet"/>
|
<img ng-src="img/{{wallet.network == 'testnet' ? 'icon-wallet-testnet' : (wallet.coin == 'btc' ? 'icon-btc' : 'icon-bch')}}.svg" ng-class="{'wallet-background-color-default': !wallet.color}" ng-style="{'background-color': wallet.color}" class="bg wallet"/>
|
||||||
|
|
@ -26,16 +33,20 @@
|
||||||
{{wallet.name || wallet.id}}
|
{{wallet.name || wallet.id}}
|
||||||
</span>
|
</span>
|
||||||
<p>
|
<p>
|
||||||
<span > {{wallet.bchBalance || 'Checking...'}} </span>
|
|
||||||
|
|
||||||
|
<span class="balanced" > {{wallet.bchBalance || 'Checking...'}} </span>
|
||||||
<span class="tab-home__wallet__multisig-number" ng-if="wallet.n > 1">
|
<span class="tab-home__wallet__multisig-number" ng-if="wallet.n > 1">
|
||||||
{{wallet.m}}-of-{{wallet.n}}
|
{{wallet.m}}-of-{{wallet.n}}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
<button ng-click="duplicate(wallet)">
|
|
||||||
Duplicate for BCH
|
|
||||||
</button>
|
<div class="buttons">
|
||||||
|
<button ng-click="duplicate(wallet)" class="button button-small button-outline button-primary" translate>
|
||||||
|
Duplicate for BCH
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -95,9 +95,10 @@ TODO Remove:
|
||||||
Incomplete
|
Incomplete
|
||||||
</span>
|
</span>
|
||||||
<span ng-if="wallet.isComplete()">
|
<span ng-if="wallet.isComplete()">
|
||||||
<span ng-if="!wallet.balanceHidden"> {{wallet.status.totalBalanceStr ? wallet.status.totalBalanceStr : ( wallet.cachedBalance ? wallet.cachedBalance + (wallet.cachedBalanceUpdatedOn ? ' · ' + ( wallet.cachedBalanceUpdatedOn * 1000 | amTimeAgo) : '') : '' ) }} </span>
|
<span ng-if="!wallet.balanceHidden && !wallet.updating"> {{wallet.status.totalBalanceStr ? wallet.status.totalBalanceStr : ( wallet.cachedBalance ? wallet.cachedBalance + (wallet.cachedBalanceUpdatedOn ? ' · ' + ( wallet.cachedBalanceUpdatedOn * 1000 | amTimeAgo) : '') : '' ) }} </span>
|
||||||
|
<span ng-if="wallet.updating" translate> Scanning for funds... </span>
|
||||||
|
|
||||||
<span ng-if="wallet.balanceHidden" translate>[Balance Hidden]</span>
|
<span ng-if="wallet.balanceHidden && !wallet.updating" translate>[Balance Hidden]</span>
|
||||||
<span class="tab-home__wallet__multisig-number" ng-if="wallet.n > 1">
|
<span class="tab-home__wallet__multisig-number" ng-if="wallet.n > 1">
|
||||||
{{wallet.m}}-of-{{wallet.n}}
|
{{wallet.m}}-of-{{wallet.n}}
|
||||||
</span>
|
</span>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue