Merge pull request #6667 from cmgustavo/feat/bitcoin-cash-01

Bitcoin Cash Support
This commit is contained in:
Matias Alejo Garcia 2017-08-31 16:30:21 -03:00 committed by GitHub
commit 0a8e785ef8
70 changed files with 845 additions and 537 deletions

View file

@ -56,7 +56,7 @@
"bezier-easing": "^2.0.3",
"bhttp": "1.2.1",
"bitauth": "^0.2.1",
"bitcore-wallet-client": "5.3.0",
"bitcore-wallet-client": "6.0.0",
"bower": "^1.7.9",
"cordova-android": "5.1.1",
"cordova-custom-config": "^3.0.5",

View file

@ -1,13 +1,8 @@
'use strict';
angular.module('copayApp.controllers').controller('addressesController', function($scope, $log, $stateParams, $state, $timeout, $ionicHistory, $ionicScrollDelegate, configService, popupService, gettextCatalog, ongoingProcess, lodash, profileService, walletService, bwcError, platformInfo, appConfigService, txFormatService, feeService) {
angular.module('copayApp.controllers').controller('addressesController', function($scope, $log, $stateParams, $state, $timeout, $ionicHistory, $ionicScrollDelegate, popupService, gettextCatalog, ongoingProcess, lodash, profileService, walletService, bwcError, platformInfo, appConfigService, txFormatService, feeService) {
var UNUSED_ADDRESS_LIMIT = 5;
var BALANCE_ADDRESS_LIMIT = 5;
var config = configService.getSync().wallet.settings;
var unitName = config.unitName;
var unitToSatoshi = config.unitToSatoshi;
var satToUnit = 1 / unitToSatoshi;
var unitDecimals = config.unitDecimals;
var withBalance, cachedWallet;
$scope.isCordova = platformInfo.isCordova;
@ -55,7 +50,7 @@ angular.module('copayApp.controllers').controller('addressesController', functio
$scope.latestWithBalance = lodash.slice(withBalance, 0, BALANCE_ADDRESS_LIMIT);
lodash.each(withBalance, function(a) {
a.balanceStr = txFormatService.formatAmount(a.amount);
a.balanceStr = txFormatService.formatAmountStr($scope.wallet.coin, a.amount);
});
$scope.viewAll = {
@ -75,11 +70,11 @@ angular.module('copayApp.controllers').controller('addressesController', functio
feeService.getFeeLevels(function(err, levels){
feeService.getFeeLevels($scope.wallet.coin, function(err, levels){
walletService.getLowUtxos($scope.wallet, levels, function(err, resp) {
if (err) return;
if (resp.allUtxos && resp.allUtxos.length) {
if (resp && resp.allUtxos && resp.allUtxos.length) {
var allSum = lodash.sum(resp.allUtxos || 0, 'satoshis');
@ -88,9 +83,9 @@ angular.module('copayApp.controllers').controller('addressesController', functio
$scope.lowWarning = resp.warning;
$scope.lowUtxosNb = resp.lowUtxos.length;
$scope.allUtxosNb = resp.allUtxos.length;
$scope.lowUtxosSum = txFormatService.formatAmountStr(lodash.sum(resp.lowUtxos || 0, 'satoshis'));
$scope.allUtxosSum = txFormatService.formatAmountStr(allSum);
$scope.minFee = txFormatService.formatAmountStr(resp.minFee || 0);
$scope.lowUtxosSum = txFormatService.formatAmountStr($scope.wallet.coin, lodash.sum(resp.lowUtxos || 0, 'satoshis'));
$scope.allUtxosSum = txFormatService.formatAmountStr($scope.wallet.coin, allSum);
$scope.minFee = txFormatService.formatAmountStr($scope.wallet.coin, resp.minFee || 0);
$scope.minFeePer = per.toFixed(2) + '%';

View file

@ -1,6 +1,6 @@
'use strict';
angular.module('copayApp.controllers').controller('advancedSettingsController', function($scope, $log, configService, platformInfo) {
angular.module('copayApp.controllers').controller('advancedSettingsController', function($scope, $log, configService, platformInfo, externalLinkService, gettextCatalog) {
var updateConfig = function() {
var config = configService.getSync();
@ -14,6 +14,10 @@ angular.module('copayApp.controllers').controller('advancedSettingsController',
$scope.hideNextSteps = {
value: config.hideNextSteps.enabled
};
$scope.cashSupport = {
value: config.cashSupport.enabled
};
};
$scope.spendUnconfirmedChange = function() {
@ -27,6 +31,19 @@ angular.module('copayApp.controllers').controller('advancedSettingsController',
});
};
$scope.cashSupportChange = function() {
var opts = {
cashSupport: {
enabled: $scope.cashSupport.value
}
};
configService.set(opts, function(err) {
if (err) $log.debug(err);
});
};
$scope.nextStepsChange = function() {
var opts = {
hideNextSteps: {
@ -49,6 +66,16 @@ angular.module('copayApp.controllers').controller('advancedSettingsController',
});
};
$scope.learnMore = function() {
var url = 'https://www.bitcoincash.org/';
var optIn = true;
var title = null;
var message = gettextCatalog.getString('Open bitcoincash.org?');
var okText = gettextCatalog.getString('Open');
var cancelText = gettextCatalog.getString('Go Back');
externalLinkService.open(url, optIn, title, message, okText, cancelText);
};
$scope.$on("$ionicView.beforeEnter", function(event, data) {
$scope.isWindowsPhoneApp = platformInfo.isCordova && platformInfo.isWP;
updateConfig();

View file

@ -9,6 +9,14 @@ angular.module('copayApp.controllers').controller('amountController', function($
var SMALL_FONT_SIZE_LIMIT = 10;
var LENGTH_EXPRESSION_LIMIT = 19;
var isNW = platformInfo.isNW;
var unitIndex = 0;
var altUnitIndex = 0;
var availableUnits = [];
var fiatCode;
var fixedUnit;
$scope.isChromeApp = platformInfo.isChromeApp;
$scope.$on('$ionicView.leave', function() {
@ -16,11 +24,82 @@ angular.module('copayApp.controllers').controller('amountController', function($
});
$scope.$on("$ionicView.beforeEnter", function(event, data) {
var config = configService.getSync().wallet.settings;
function setAvailableUnits() {
availableUnits = [{
name: 'Bitcoin',
id: 'btc',
shortName: 'BTC',
}];
var anyCashWallet = true; // TODO!!
if (anyCashWallet) {
availableUnits.push({
name: 'Bitcoin Cash',
id: 'bch',
shortName: 'BCH',
});
};
unitIndex = 0;
if (data.stateParams.coin) {
var coins = data.stateParams.coin.split(',');
var newAvailableUnits = [];
lodash.each(coins, function(c) {
var coin = lodash.find(availableUnits, {
id: c
});
if (!coin) {
$log.warn('Could not find desired coin:' + data.stateParams.coin)
} else {
newAvailableUnits.push(coin);
}
});
if (newAvailableUnits.length>0) {
availableUnits = newAvailableUnits;
}
}
// currency have preference
var fiat;
if (data.stateParams.currency) {
fiat = data.stateParams.currency;
altUnitIndex = unitIndex
unitIndex = availableUnits.length;
} else {
fiat = config.fiat || 'USD';
altUnitIndex = availableUnits.length;
}
availableUnits.push({
name: fiat, // TODO
id: fiat,
shortName: fiat,
isFiat: true,
});
fiatCode = fiat;
if (data.stateParams.fixedUnit) {
fixedUnit = true;
}
};
// Go to...
_id = data.stateParams.id; // Optional (BitPay Card ID or Wallet ID)
$scope.nextStep = data.stateParams.nextStep;
$scope.currency = data.stateParams.currency;
$scope.forceCurrency = data.stateParams.forceCurrency;
setAvailableUnits();
updateUnitUI();
$scope.showMenu = $ionicHistory.backView() && ($ionicHistory.backView().stateName == 'tabs.send' ||
$ionicHistory.backView().stateName == 'tabs.bitpayCard');
@ -28,7 +107,6 @@ angular.module('copayApp.controllers').controller('amountController', function($
$scope.toAddress = data.stateParams.toAddress;
$scope.toName = data.stateParams.toName;
$scope.toEmail = data.stateParams.toEmail;
$scope.showAlternativeAmount = !!$scope.nextStep;
$scope.toColor = data.stateParams.toColor;
$scope.showSendMax = false;
@ -61,14 +139,6 @@ angular.module('copayApp.controllers').controller('amountController', function($
$scope.$apply();
});
});
var config = configService.getSync().wallet.settings;
$scope.unitName = config.unitName;
if (data.stateParams.currency) {
$scope.alternativeIsoCode = data.stateParams.currency;
} else {
$scope.alternativeIsoCode = config.alternativeIsoCode || 'USD';
}
$scope.specificAmount = $scope.specificAlternativeAmount = '';
$scope.isCordova = platformInfo.isCordova;
unitToSatoshi = config.unitToSatoshi;
@ -114,16 +184,59 @@ angular.module('copayApp.controllers').controller('amountController', function($
$scope.finish();
};
$scope.toggleAlternative = function() {
if ($scope.forceCurrency) return;
$scope.showAlternativeAmount = !$scope.showAlternativeAmount;
$scope.toggleAlternative = function() {
if ($scope.amount && isExpression($scope.amount)) {
var amount = evaluate(format($scope.amount));
$scope.globalResult = '= ' + processResult(amount);
}
};
function updateUnitUI() {
$scope.unit = availableUnits[unitIndex].shortName;
$scope.alternativeUnit = availableUnits[altUnitIndex].shortName;
processAmount();
$log.debug('Update unit coin @amount unit:' + $scope.unit + " alternativeUnit:" + $scope.alternativeUnit);
};
$scope.changeUnit = function() {
if (fixedUnit) return;
unitIndex++;
if (unitIndex >= availableUnits.length) unitIndex = 0;
if (availableUnits[unitIndex].isFiat) {
// Always return to BTC... TODO?
altUnitIndex = 0;
} else {
altUnitIndex = lodash.findIndex(availableUnits, {
isFiat: true
});
}
updateUnitUI();
};
$scope.changeAlternativeUnit = function() {
// Do nothing is fiat is not main unit
if (!availableUnits[unitIndex].isFiat) return;
var nextCoin = lodash.findIndex(availableUnits, function(x) {
if (x.isFiat) return false;
if (x.id == availableUnits[altUnitIndex].id) return false;
return true;
});
if (nextCoin >= 0) {
altUnitIndex = nextCoin;
updateUnitUI();
}
};
function checkFontSize() {
if ($scope.amount && $scope.amount.length >= SMALL_FONT_SIZE_LIMIT) $scope.smallFont = true;
else $scope.smallFont = false;
@ -132,7 +245,7 @@ angular.module('copayApp.controllers').controller('amountController', function($
$scope.pushDigit = function(digit) {
if ($scope.amount && $scope.amount.length >= LENGTH_EXPRESSION_LIMIT) return;
if ($scope.amount.indexOf('.') > -1 && digit == '.') return;
if ($scope.showAlternativeAmount && $scope.amount.indexOf('.') > -1 && $scope.amount[$scope.amount.indexOf('.') + 2]) return;
if (availableUnits[unitIndex].isFiat && $scope.amount.indexOf('.') > -1 && $scope.amount[$scope.amount.indexOf('.') + 2]) return;
$scope.amount = ($scope.amount + digit).replace('..', '.');
checkFontSize();
@ -169,7 +282,7 @@ angular.module('copayApp.controllers').controller('amountController', function($
};
$scope.resetAmount = function() {
$scope.amount = $scope.alternativeResult = $scope.amountResult = $scope.globalResult = '';
$scope.amount = $scope.alternativeAmount = $scope.globalResult = '';
$scope.allowSend = false;
checkFontSize();
};
@ -180,24 +293,28 @@ angular.module('copayApp.controllers').controller('amountController', function($
$scope.allowSend = lodash.isNumber(result) && +result > 0;
if (lodash.isNumber(result)) {
$scope.globalResult = isExpression($scope.amount) ? '= ' + processResult(result) : '';
$scope.amountResult = $filter('formatFiatAmount')(toFiat(result));
$scope.alternativeResult = txFormatService.formatAmount(fromFiat(result) * unitToSatoshi, true);
if (availableUnits[unitIndex].isFiat) {
$scope.alternativeAmount = txFormatService.formatAmount(fromFiat(result) * unitToSatoshi, true);
} else {
$scope.alternativeAmount = $filter('formatFiatAmount')(toFiat(result));
}
}
};
function processResult(val) {
if ($scope.showAlternativeAmount)
if (availableUnits[unitIndex].isFiat)
return $filter('formatFiatAmount')(val);
else
return txFormatService.formatAmount(val.toFixed(unitDecimals) * unitToSatoshi, true);
};
function fromFiat(val) {
return parseFloat((rateService.fromFiat(val, $scope.alternativeIsoCode) * satToUnit).toFixed(unitDecimals));
return parseFloat((rateService.fromFiat(val, fiatCode, availableUnits[altUnitIndex].id) * satToUnit).toFixed(unitDecimals));
};
function toFiat(val) {
return parseFloat((rateService.toFiat(val * unitToSatoshi, $scope.alternativeIsoCode)).toFixed(2));
return parseFloat((rateService.toFiat(val * unitToSatoshi, fiatCode, availableUnits[unitIndex].id)).toFixed(2));
};
function evaluate(val) {
@ -212,6 +329,8 @@ angular.module('copayApp.controllers').controller('amountController', function($
};
function format(val) {
if (!val) return;
var result = val.toString();
if (isOperator(lodash.last(val)))
@ -221,24 +340,42 @@ angular.module('copayApp.controllers').controller('amountController', function($
};
$scope.finish = function() {
var unit = availableUnits[unitIndex];
var _amount = evaluate(format($scope.amount));
if ($scope.nextStep) {
var coin = unit.id;
if (unit.isFiat) {
coin = availableUnits[altUnitIndex].id;
}
$state.transitionTo($scope.nextStep, {
id: _id,
amount: $scope.useSendMax ? null : _amount,
currency: $scope.showAlternativeAmount ? $scope.alternativeIsoCode : $scope.unitName,
currency: unit.id.toUpperCase(),
coin: coin,
useSendMax: $scope.useSendMax
});
} else {
var amount = $scope.showAlternativeAmount ? fromFiat(_amount) : _amount;
var amount = _amount;
if (unit.isFiat) {
amount = fromFiat(_amount);
} else {
amount = (amount * unitToSatoshi).toFixed(0);
}
$state.transitionTo('tabs.send.confirm', {
recipientType: $scope.recipientType,
toAmount: $scope.useSendMax ? null : (amount * unitToSatoshi).toFixed(0),
toAmount: amount,
toAddress: $scope.toAddress,
toName: $scope.toName,
toEmail: $scope.toEmail,
toColor: $scope.toColor,
coin: unit.id,
useSendMax: $scope.useSendMax
});
}

View file

@ -2,6 +2,7 @@
angular.module('copayApp.controllers').controller('buyAmazonController', function($scope, $log, $state, $timeout, $filter, $ionicHistory, $ionicConfig, lodash, amazonService, popupService, profileService, ongoingProcess, configService, walletService, payproService, bwcError, externalLinkService, platformInfo, gettextCatalog, txFormatService) {
var coin = 'btc';
var amount;
var currency;
var createdTx;
@ -64,7 +65,7 @@ angular.module('copayApp.controllers').controller('buyAmazonController', functio
};
var satToFiat = function(sat, cb) {
txFormatService.toFiat(sat, $scope.currencyIsoCode, function(value) {
txFormatService.toFiat(coin, sat, $scope.currencyIsoCode, function(value) {
return cb(value);
});
};
@ -216,7 +217,7 @@ angular.module('copayApp.controllers').controller('buyAmazonController', functio
});
var initialize = function(wallet) {
var parsedAmount = txFormatService.parseAmount(amount, currency);
var parsedAmount = txFormatService.parseAmount(coin, amount, currency);
$scope.currencyIsoCode = parsedAmount.currency;
$scope.amountUnitStr = parsedAmount.amountUnitStr;
var dataSrc = {
@ -260,7 +261,7 @@ angular.module('copayApp.controllers').controller('buyAmazonController', functio
invoiceUrl: invoice.url,
invoiceTime: invoice.invoiceTime
};
$scope.totalAmountStr = txFormatService.formatAmountStr(ctxp.amount);
$scope.totalAmountStr = txFormatService.formatAmountStr(coin, ctxp.amount);
setTotalAmount(parsedAmount.amountSat, invoiceFeeSat, ctxp.fee);
});
});
@ -292,7 +293,8 @@ angular.module('copayApp.controllers').controller('buyAmazonController', functio
$scope.wallets = profileService.getWallets({
onlyComplete: true,
network: $scope.network,
hasFunds: true
hasFunds: true,
coin: coin
});
if (lodash.isEmpty($scope.wallets)) {
showErrorAndBack(null, gettextCatalog.getString('No wallets available'));

View file

@ -2,6 +2,7 @@
angular.module('copayApp.controllers').controller('buyCoinbaseController', function($scope, $log, $state, $timeout, $ionicHistory, $ionicScrollDelegate, $ionicConfig, lodash, coinbaseService, popupService, profileService, ongoingProcess, walletService, txFormatService) {
var coin = 'btc';
var amount;
var currency;
@ -33,46 +34,7 @@ angular.module('copayApp.controllers').controller('buyCoinbaseController', funct
}
};
$scope.$on("$ionicView.beforeLeave", function(event, data) {
$ionicConfig.views.swipeBackEnabled(true);
});
$scope.$on("$ionicView.enter", function(event, data) {
$ionicConfig.views.swipeBackEnabled(false);
});
$scope.$on("$ionicView.beforeEnter", function(event, data) {
$scope.isFiat = data.stateParams.currency != 'bits' && data.stateParams.currency != 'BTC' ? true : false;
var parsedAmount = txFormatService.parseAmount(
data.stateParams.amount,
data.stateParams.currency);
// Buy always in BTC
amount = (parsedAmount.amountSat / 100000000).toFixed(8);
currency = 'BTC';
$scope.amountUnitStr = parsedAmount.amountUnitStr;
ongoingProcess.set('calculatingFee', true);
coinbaseService.checkEnoughFundsForFee(amount, function(err) {
ongoingProcess.set('calculatingFee', false);
if (err) {
showErrorAndBack(err);
return;
}
$scope.network = coinbaseService.getNetwork();
$scope.wallets = profileService.getWallets({
onlyComplete: true,
network: $scope.network
});
if (lodash.isEmpty($scope.wallets)) {
showErrorAndBack('No wallets available');
return;
}
$scope.wallet = $scope.wallets[0]; // Default first wallet
var processPaymentInfo = function() {
ongoingProcess.set('connectingCoinbase', true);
coinbaseService.init(function(err, res) {
if (err) {
@ -116,7 +78,33 @@ angular.module('copayApp.controllers').controller('buyCoinbaseController', funct
$scope.buyRequest();
});
});
};
$scope.$on("$ionicView.beforeLeave", function(event, data) {
$ionicConfig.views.swipeBackEnabled(true);
});
$scope.$on("$ionicView.enter", function(event, data) {
$ionicConfig.views.swipeBackEnabled(false);
});
$scope.$on("$ionicView.beforeEnter", function(event, data) {
$scope.isFiat = data.stateParams.currency != 'BTC' ? true : false;
amount = data.stateParams.amount;
currency = data.stateParams.currency;
$scope.network = coinbaseService.getNetwork();
$scope.wallets = profileService.getWallets({
onlyComplete: true,
network: $scope.network,
coin: coin
});
if (lodash.isEmpty($scope.wallets)) {
showErrorAndBack('No wallets available');
return;
}
$scope.onWalletSelect($scope.wallets[0]); // Default first wallet
});
$scope.buyRequest = function() {
@ -248,6 +236,25 @@ angular.module('copayApp.controllers').controller('buyCoinbaseController', funct
$scope.onWalletSelect = function(wallet) {
$scope.wallet = wallet;
var parsedAmount = txFormatService.parseAmount(
coin,
amount,
currency);
// Buy always in BTC
amount = (parsedAmount.amountSat / 100000000).toFixed(8);
currency = 'BTC';
$scope.amountUnitStr = parsedAmount.amountUnitStr;
ongoingProcess.set('calculatingFee', true);
coinbaseService.checkEnoughFundsForFee(amount, function(err) {
ongoingProcess.set('calculatingFee', false);
if (err) {
showErrorAndBack(err);
return;
}
processPaymentInfo();
});
};
$scope.goBackHome = function() {

View file

@ -2,6 +2,7 @@
angular.module('copayApp.controllers').controller('buyGlideraController', function($scope, $log, $state, $timeout, $ionicHistory, $ionicConfig, lodash, glideraService, popupService, profileService, ongoingProcess, walletService, platformInfo, txFormatService) {
var coin = 'btc';
var amount;
var currency;
@ -35,36 +36,7 @@ angular.module('copayApp.controllers').controller('buyGlideraController', functi
}
};
$scope.$on("$ionicView.beforeLeave", function(event, data) {
$ionicConfig.views.swipeBackEnabled(true);
});
$scope.$on("$ionicView.enter", function(event, data) {
$ionicConfig.views.swipeBackEnabled(false);
});
$scope.$on("$ionicView.beforeEnter", function(event, data) {
$scope.isFiat = data.stateParams.currency != 'bits' && data.stateParams.currency != 'BTC' ? true : false;
var parsedAmount = txFormatService.parseAmount(
data.stateParams.amount,
data.stateParams.currency);
amount = parsedAmount.amount;
currency = parsedAmount.currency;
$scope.amountUnitStr = parsedAmount.amountUnitStr;
$scope.network = glideraService.getNetwork();
$scope.wallets = profileService.getWallets({
onlyComplete: true,
network: $scope.network
});
if (lodash.isEmpty($scope.wallets)) {
showErrorAndBack('No wallets available');
return;
}
$scope.wallet = $scope.wallets[0]; // Default first wallet
var processPaymentInfo = function() {
ongoingProcess.set('connectingGlidera', true);
glideraService.init(function(err, data) {
if (err) {
@ -88,6 +60,33 @@ angular.module('copayApp.controllers').controller('buyGlideraController', functi
$scope.buyInfo = buy;
});
});
};
$scope.$on("$ionicView.beforeLeave", function(event, data) {
$ionicConfig.views.swipeBackEnabled(true);
});
$scope.$on("$ionicView.enter", function(event, data) {
$ionicConfig.views.swipeBackEnabled(false);
});
$scope.$on("$ionicView.beforeEnter", function(event, data) {
$scope.isFiat = data.stateParams.currency != 'BTC' ? true : false;
amount = data.stateParams.amount;
currency = data.stateParams.currency;
$scope.network = glideraService.getNetwork();
$scope.wallets = profileService.getWallets({
onlyComplete: true,
network: $scope.network,
coin: coin
});
if (lodash.isEmpty($scope.wallets)) {
showErrorAndBack('No wallets available');
return;
}
$scope.onWalletSelect($scope.wallets[0]); // Default first wallet
});
var ask2FaCode = function(mode, cb) {
@ -162,6 +161,15 @@ angular.module('copayApp.controllers').controller('buyGlideraController', functi
$scope.onWalletSelect = function(wallet) {
$scope.wallet = wallet;
var parsedAmount = txFormatService.parseAmount(
coin,
amount,
currency);
amount = parsedAmount.amount;
currency = parsedAmount.currency;
$scope.amountUnitStr = parsedAmount.amountUnitStr;
processPaymentInfo();
};
$scope.goBackHome = function() {

View file

@ -2,6 +2,7 @@
angular.module('copayApp.controllers').controller('buyMercadoLibreController', function($scope, $log, $state, $timeout, $filter, $ionicHistory, $ionicConfig, lodash, mercadoLibreService, popupService, profileService, ongoingProcess, configService, walletService, payproService, bwcError, externalLinkService, platformInfo, txFormatService, gettextCatalog) {
var coin = 'btc';
var amount;
var currency;
var createdTx;
@ -64,7 +65,7 @@ angular.module('copayApp.controllers').controller('buyMercadoLibreController', f
};
var satToFiat = function(sat, cb) {
txFormatService.toFiat(sat, $scope.currencyIsoCode, function(value) {
txFormatService.toFiat(coin, sat, $scope.currencyIsoCode, function(value) {
return cb(value);
});
};
@ -214,7 +215,7 @@ angular.module('copayApp.controllers').controller('buyMercadoLibreController', f
});
var initialize = function(wallet) {
var parsedAmount = txFormatService.parseAmount(amount, currency);
var parsedAmount = txFormatService.parseAmount(coin, amount, currency);
$scope.currencyIsoCode = parsedAmount.currency;
$scope.amountUnitStr = parsedAmount.amountUnitStr;
var dataSrc = {
@ -258,7 +259,7 @@ angular.module('copayApp.controllers').controller('buyMercadoLibreController', f
invoiceUrl: invoice.url,
invoiceTime: invoice.invoiceTime
};
$scope.totalAmountStr = txFormatService.formatAmountStr(ctxp.amount);
$scope.totalAmountStr = txFormatService.formatAmountStr(coin, ctxp.amount);
setTotalAmount(parsedAmount.amountSat, invoiceFeeSat, ctxp.fee);
});
});
@ -284,7 +285,8 @@ angular.module('copayApp.controllers').controller('buyMercadoLibreController', f
$scope.network = mercadoLibreService.getNetwork();
$scope.wallets = profileService.getWallets({
onlyComplete: true,
network: $scope.network
network: $scope.network,
coin: coin
});
if (lodash.isEmpty($scope.wallets)) {
showErrorAndBack(null, gettextCatalog.getString('No wallets available'));

View file

@ -1,6 +1,6 @@
'use strict';
angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $interval, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, walletService, platformInfo, lodash, configService, rateService, $stateParams, $window, $state, $log, profileService, bitcore, txFormatService, ongoingProcess, $ionicModal, popupService, $ionicHistory, $ionicConfig, payproService, feeService, bwcError, txConfirmNotification) {
angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $interval, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, walletService, platformInfo, lodash, configService, $stateParams, $window, $state, $log, profileService, bitcore, txFormatService, ongoingProcess, $ionicModal, popupService, $ionicHistory, $ionicConfig, payproService, feeService, bwcError, txConfirmNotification) {
var countDown = null;
var CONFIRM_LIMIT_USD = 20;
@ -69,14 +69,15 @@ angular.module('copayApp.controllers').controller('confirmController', function(
$scope.$on("$ionicView.beforeEnter", function(event, data) {
function setWalletSelector(network, minAmount, cb) {
function setWalletSelector(coin, network, minAmount, cb) {
// no min amount? (sendMax) => look for no empty wallets
minAmount = minAmount || 1;
$scope.wallets = profileService.getWallets({
onlyComplete: true,
network: network
network: network,
coin: coin
});
if (!$scope.wallets || !$scope.wallets.length) {
@ -118,6 +119,11 @@ angular.module('copayApp.controllers').controller('confirmController', function(
});
};
// TODO: Default fee level for BCH
if (data.stateParams.coin == 'bch') {
configFeeLevel = 'normal';
}
// Setup $scope
// Grab stateParams
@ -137,20 +143,18 @@ angular.module('copayApp.controllers').controller('confirmController', function(
toEmail: data.stateParams.toEmail,
toColor: data.stateParams.toColor,
network: (new bitcore.Address(data.stateParams.toAddress)).network.name,
coin: data.stateParams.coin,
txp: {},
};
// Other Scope vars
$scope.isCordova = isCordova;
$scope.isWindowsPhoneApp = isWindowsPhoneApp;
$scope.showAddress = false;
updateTx(tx, null, {}, function() {
$scope.walletSelectorTitle = gettextCatalog.getString('Send from');
setWalletSelector(tx.network, tx.toAmount, function(err) {
setWalletSelector(tx.coin, tx.network, tx.toAmount, function(err) {
if (err) {
return exitWithError('Could not update wallets');
}
@ -163,7 +167,6 @@ angular.module('copayApp.controllers').controller('confirmController', function(
});
});
});
function getSendMaxInfo(tx, wallet, cb) {
@ -238,10 +241,10 @@ angular.module('copayApp.controllers').controller('confirmController', function(
if (!tx.toAmount) return;
// Amount
tx.amountStr = txFormatService.formatAmountStr(tx.toAmount);
tx.amountStr = txFormatService.formatAmountStr(wallet.coin, tx.toAmount);
tx.amountValueStr = tx.amountStr.split(' ')[0];
tx.amountUnitStr = tx.amountStr.split(' ')[1];
txFormatService.formatAlternativeStr(tx.toAmount, function(v) {
txFormatService.formatAlternativeStr(wallet.coin, tx.toAmount, function(v) {
tx.alternativeAmountStr = v;
});
}
@ -252,7 +255,7 @@ angular.module('copayApp.controllers').controller('confirmController', function(
// End of quick refresh, before wallet is selected.
if (!wallet) return cb();
feeService.getFeeRate(tx.network, tx.feeLevel, function(err, feeRate) {
feeService.getFeeRate(wallet.coin, tx.network, tx.feeLevel, function(err, feeRate) {
if (err) return cb(err);
if (!usingCustomFee) tx.feeRate = feeRate;
@ -280,7 +283,7 @@ angular.module('copayApp.controllers').controller('confirmController', function(
tx.sendMaxInfo = sendMaxInfo;
tx.toAmount = tx.sendMaxInfo.amount;
updateAmount();
showSendMaxWarning(sendMaxInfo);
showSendMaxWarning(wallet, sendMaxInfo);
}
// txp already generated for this wallet?
@ -292,8 +295,8 @@ angular.module('copayApp.controllers').controller('confirmController', function(
getTxp(lodash.clone(tx), wallet, opts.dryRun, function(err, txp) {
if (err) return cb(err);
txp.feeStr = txFormatService.formatAmountStr(txp.fee);
txFormatService.formatAlternativeStr(txp.fee, function(v) {
txp.feeStr = txFormatService.formatAmountStr(wallet.coin, txp.fee);
txFormatService.formatAlternativeStr(wallet.coin, txp.fee, function(v) {
txp.alternativeFeeStr = v;
});
@ -337,26 +340,26 @@ angular.module('copayApp.controllers').controller('confirmController', function(
};
function showSendMaxWarning(sendMaxInfo) {
function showSendMaxWarning(wallet, sendMaxInfo) {
function verifyExcludedUtxos() {
var warningMsg = [];
if (sendMaxInfo.utxosBelowFee > 0) {
warningMsg.push(gettextCatalog.getString("A total of {{amountBelowFeeStr}} were excluded. These funds come from UTXOs smaller than the network fee provided.", {
amountBelowFeeStr: txFormatService.formatAmountStr(sendMaxInfo.amountBelowFee)
amountBelowFeeStr: txFormatService.formatAmountStr(wallet.coin, sendMaxInfo.amountBelowFee)
}));
}
if (sendMaxInfo.utxosAboveMaxSize > 0) {
warningMsg.push(gettextCatalog.getString("A total of {{amountAboveMaxSizeStr}} were excluded. The maximum size allowed for a transaction was exceeded.", {
amountAboveMaxSizeStr: txFormatService.formatAmountStr(sendMaxInfo.amountAboveMaxSize)
amountAboveMaxSizeStr: txFormatService.formatAmountStr(wallet.coin, sendMaxInfo.amountAboveMaxSize)
}));
}
return warningMsg.join('\n');
};
var msg = gettextCatalog.getString("{{fee}} will be deducted for bitcoin networking fees.", {
fee: txFormatService.formatAmountStr(sendMaxInfo.fee)
fee: txFormatService.formatAmountStr(wallet.coin, sendMaxInfo.fee)
});
var warningMsg = verifyExcludedUtxos();
@ -483,7 +486,7 @@ angular.module('copayApp.controllers').controller('confirmController', function(
if (walletService.isEncrypted(wallet))
return cb();
var amountUsd = parseFloat(txFormatService.formatToUSD(txp.amount));
var amountUsd = parseFloat(txFormatService.formatToUSD(wallet.coin, txp.amount));
if (amountUsd <= CONFIRM_LIMIT_USD)
return cb();
@ -563,10 +566,13 @@ angular.module('copayApp.controllers').controller('confirmController', function(
$scope.chooseFeeLevel = function(tx, wallet) {
if (wallet.coin == 'bch') return;
var scope = $rootScope.$new(true);
scope.network = tx.network;
scope.feeLevel = tx.feeLevel;
scope.noSave = true;
scope.coin = wallet.coin;
if (usingCustomFee) {
scope.customFeePerKB = tx.feeRate;

View file

@ -22,11 +22,16 @@ angular.module('copayApp.controllers').controller('createController',
$scope.$on("$ionicView.beforeEnter", function(event, data) {
$scope.formData = {};
var defaults = configService.getDefaults();
var config = configService.getSync();
var tc = $state.current.name == 'tabs.add.create-personal' ? 1 : defaults.wallet.totalCopayers;
$scope.formData.account = 1;
$scope.formData.bwsurl = defaults.bws.url;
$scope.TCValues = lodash.range(2, defaults.limits.totalCopayers + 1);
$scope.formData.derivationPath = derivationPathHelper.default;
$scope.formData.coin = 'btc';
if (config.cashSupport.enabled) $scope.enableCash = true;
$scope.setTotalCopayers(tc);
updateRCSelect(tc);
resetPasswordFields();
@ -137,6 +142,7 @@ angular.module('copayApp.controllers').controller('createController',
bwsurl: $scope.formData.bwsurl,
singleAddress: $scope.formData.singleAddressEnabled,
walletPrivKey: $scope.formData._walletPrivKey, // Only for testing
coin: $scope.formData.coin
};
var setSeed = $scope.formData.seedSource.id == 'set';

View file

@ -28,7 +28,9 @@ angular.module('copayApp.controllers').controller('customAmountController', func
$scope.address = addr;
$scope.coin = data.stateParams.coin;
var parsedAmount = txFormatService.parseAmount(
$scope.wallet.coin,
data.stateParams.amount,
data.stateParams.currency);
@ -37,17 +39,17 @@ angular.module('copayApp.controllers').controller('customAmountController', func
var currency = parsedAmount.currency;
$scope.amountUnitStr = parsedAmount.amountUnitStr;
if (currency != 'BTC') {
// Convert to BTC
if (currency != 'BTC' && currency != 'BCH') {
// Convert to BTC or BCH
var config = configService.getSync().wallet.settings;
var amountUnit = txFormatService.satToUnit(parsedAmount.amountSat);
var btcParsedAmount = txFormatService.parseAmount(amountUnit, config.unitName);
var btcParsedAmount = txFormatService.parseAmount($scope.wallet.coin, amountUnit, $scope.wallet.coin);
$scope.amountBtc = btcParsedAmount.amount;
$scope.altAmountStr = btcParsedAmount.amountUnitStr;
} else {
$scope.amountBtc = amount; // BTC
$scope.altAmountStr = txFormatService.formatAlternativeStr(parsedAmount.amountSat);
$scope.amountBtc = amount; // BTC or BCH
$scope.altAmountStr = txFormatService.formatAlternativeStr($scope.wallet.coin, parsedAmount.amountSat);
}
});
});
@ -61,12 +63,12 @@ angular.module('copayApp.controllers').controller('customAmountController', func
$scope.shareAddress = function() {
if (!platformInfo.isCordova) return;
var data = 'bitcoin:' + $scope.address + '?amount=' + $scope.amountBtc;
var data = 'bitcoin:' + $scope.address + '?amount=' + $scope.amountBtc + '&coin=' + $scope.wallet.coin;
window.plugins.socialsharing.share(data, null, null, null);
}
$scope.copyToClipboard = function() {
return 'bitcoin:' + $scope.address + '?amount=' + $scope.amountBtc;
return 'bitcoin:' + $scope.address + '?amount=' + $scope.amountBtc + '&coin=' + $scope.wallet.coin;
};
});

View file

@ -5,6 +5,7 @@ angular.module('copayApp.controllers').controller('importController',
var reader = new FileReader();
var defaults = configService.getDefaults();
var config = configService.getSync();
var errors = bwcService.getErrors();
$scope.init = function() {
@ -15,10 +16,13 @@ angular.module('copayApp.controllers').controller('importController',
$scope.formData.bwsurl = defaults.bws.url;
$scope.formData.derivationPath = derivationPathHelper.default;
$scope.formData.account = 1;
$scope.formData.coin = 'btc';
$scope.importErr = false;
$scope.isCopay = appConfigService.name == 'copay';
$scope.fromHardwareWallet = { value: false };
if (config.cashSupport.enabled) $scope.enableCash = true;
if ($stateParams.code)
$scope.processWalletInfo($stateParams.code);
@ -203,6 +207,7 @@ angular.module('copayApp.controllers').controller('importController',
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
var opts = {};
opts.bwsurl = $scope.formData.bwsurl;
opts.coin = $scope.formData.coin;
_importBlob(evt.target.result, opts);
}
}
@ -228,6 +233,7 @@ angular.module('copayApp.controllers').controller('importController',
} else {
var opts = {};
opts.bwsurl = $scope.formData.bwsurl;
opts.coin = $scope.formData.coin;
_importBlob(backupText, opts);
}
};
@ -273,6 +279,7 @@ angular.module('copayApp.controllers').controller('importController',
}
opts.passphrase = $scope.formData.passphrase || null;
opts.coin = $scope.formData.coin;
if ($scope.fromHardwareWallet.value) {
$log.debug('Importing seed from hardware wallet');

View file

@ -5,11 +5,14 @@ angular.module('copayApp.controllers').controller('joinController',
$scope.$on("$ionicView.beforeEnter", function(event, data) {
var defaults = configService.getDefaults();
var config = configService.getSync();
$scope.formData = {};
$scope.formData.bwsurl = defaults.bws.url;
$scope.formData.derivationPath = derivationPathHelper.default;
$scope.formData.account = 1;
$scope.formData.secret = null;
$scope.formData.coin = 'btc';
if (config.cashSupport.enabled) $scope.enableCash = true;
resetPasswordFields();
updateSeedSourceSelect();
});
@ -103,7 +106,8 @@ angular.module('copayApp.controllers').controller('joinController',
var opts = {
secret: $scope.formData.secret,
myName: $scope.formData.myName,
bwsurl: $scope.formData.bwsurl
bwsurl: $scope.formData.bwsurl,
coin: $scope.formData.coin
}
var setSeed = $scope.formData.seedSource.id == 'set';

View file

@ -18,14 +18,14 @@ angular.module('copayApp.controllers').controller('feeLevelsController', functio
var value = lodash.find($scope.feeLevels[$scope.network], {
level: 'superEconomy'
});
return parseInt((value.feePerKB / 1000).toFixed());
return parseInt((value.feePerKb / 1000).toFixed());
};
var getMaxRecommended = function() {
var value = lodash.find($scope.feeLevels[$scope.network], {
level: 'urgent'
});
return parseInt((value.feePerKB / 1000).toFixed());
return parseInt((value.feePerKb / 1000).toFixed());
};
$scope.ok = function() {
@ -61,7 +61,7 @@ angular.module('copayApp.controllers').controller('feeLevelsController', functio
// If no custom fee
if (value) {
$scope.customFeePerKB = null;
$scope.feePerSatByte = (value.feePerKB / 1000).toFixed();
$scope.feePerSatByte = (value.feePerKb / 1000).toFixed();
$scope.avgConfirmationTime = value.nbBlocks * 10;
} else {
$scope.avgConfirmationTime = null;
@ -102,7 +102,7 @@ angular.module('copayApp.controllers').controller('feeLevelsController', functio
$scope.feeOpts = feeService.feeOpts;
$scope.loadingFee = true;
feeService.getFeeLevels(function(err, levels) {
feeService.getFeeLevels($scope.coin, function(err, levels) {
$scope.loadingFee = false;
if (err || lodash.isEmpty(levels)) {
showErrorAndClose(null, err);

View file

@ -23,7 +23,7 @@ angular.module('copayApp.controllers').controller('txpDetailsController', functi
};
function displayFeeValues() {
txFormatService.formatAlternativeStr($scope.tx.fee, function(v) {
txFormatService.formatAlternativeStr($scope.wallet.coin, $scope.tx.fee, function(v) {
$scope.tx.feeFiatStr = v;
});
$scope.tx.feeRateStr = ($scope.tx.fee / ($scope.tx.amount + $scope.tx.fee) * 100).toFixed(2) + '%';
@ -219,7 +219,7 @@ angular.module('copayApp.controllers').controller('txpDetailsController', functi
copayerId: $scope.wallet.credentials.copayerId
});
$scope.tx = txFormatService.processTx(tx);
$scope.tx = txFormatService.processTx($scope.wallet.coin, tx);
if (!action && tx.status == 'pending')
$scope.tx.pendingForUs = true;

View file

@ -27,7 +27,7 @@ angular.module('copayApp.controllers').controller('tourController',
rateService.whenAvailable(function() {
var localCurrency = 'USD';
var btcAmount = 1;
var rate = rateService.toFiat(btcAmount * 1e8, localCurrency);
var rate = rateService.toFiat(btcAmount * 1e8, localCurrency, 'btc');
$scope.localCurrencySymbol = '$';
$scope.localCurrencyPerBtc = $filter('formatFiatAmount')(parseFloat(rate.toFixed(2), 10));
$timeout(function() {

View file

@ -45,8 +45,7 @@ angular.module('copayApp.controllers').controller('paperWalletController',
$scope.balanceSat = balance;
if ($scope.balanceSat <= 0)
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Not funds found'));
var config = configService.getSync().wallet.settings;
$scope.balance = txFormatService.formatAmount(balance) + ' ' + config.unitName;
$scope.balance = txFormatService.formatAmountStr($scope.wallet.coin, balance);
}
$scope.$apply();
});
@ -60,9 +59,9 @@ angular.module('copayApp.controllers').controller('paperWalletController',
$scope.wallet.buildTxFromPrivateKey($scope.privateKey, destinationAddress, null, function(err, testTx) {
if (err) return cb(err);
var rawTxLength = testTx.serialize().length;
feeService.getCurrentFeeRate('livenet', function(err, feePerKB) {
feeService.getCurrentFeeRate('btc', 'livenet', function(err, feePerKb) {
var opts = {};
opts.fee = Math.round((feePerKB * rawTxLength) / 2000);
opts.fee = Math.round((feePerKb * rawTxLength) / 2000);
$scope.wallet.buildTxFromPrivateKey($scope.privateKey, destinationAddress, opts, function(err, tx) {
if (err) return cb(err);
$scope.wallet.broadcastRawTx({

View file

@ -32,11 +32,12 @@ angular.module('copayApp.controllers').controller('preferencesFeeController', fu
});
$scope.init = function() {
var coin = 'btc'; // TODO: only BTC in preferences
$scope.network = $scope.network || 'livenet';
$scope.feeOpts = feeService.feeOpts;
$scope.currentFeeLevel = $scope.feeLevel || feeService.getCurrentFeeLevel();
$scope.loadingFee = true;
feeService.getFeeLevels(function(err, levels) {
feeService.getFeeLevels(coin, function(err, levels) {
$scope.loadingFee = false;
if (err) {
//Error is already formatted
@ -66,7 +67,7 @@ angular.module('copayApp.controllers').controller('preferencesFeeController', fu
return;
}
$scope.feePerSatByte = (value.feePerKB / 1000).toFixed();
$scope.feePerSatByte = (value.feePerKb / 1000).toFixed();
$scope.avgConfirmationTime = value.nbBlocks * 10;
$scope.invalidCustomFeeEntered = false;
setMinWarning();
@ -97,7 +98,7 @@ angular.module('copayApp.controllers').controller('preferencesFeeController', fu
var value = lodash.find($scope.feeLevels[$scope.network], {
level: 'superEconomy'
});
return parseInt((value.feePerKB / 1000).toFixed());
return parseInt((value.feePerKb / 1000).toFixed());
};
var setMinWarning = function() {

View file

@ -1,43 +0,0 @@
'use strict';
angular.module('copayApp.controllers').controller('preferencesUnitController', function($scope, $log, configService, $ionicHistory, gettextCatalog, walletService, profileService) {
var config = configService.getSync();
$scope.unitList = [{
name: 'bits (1,000,000 bits = 1BTC)',
shortName: 'bits',
value: 100,
decimals: 2,
code: 'bit',
}, {
name: 'BTC',
shortName: 'BTC',
value: 100000000,
decimals: 8,
code: 'btc',
}];
$scope.save = function(newUnit) {
var opts = {
wallet: {
settings: {
unitName: newUnit.shortName,
unitToSatoshi: newUnit.value,
unitDecimals: newUnit.decimals,
unitCode: newUnit.code,
}
}
};
configService.set(opts, function(err) {
if (err) $log.warn(err);
$ionicHistory.goBack();
walletService.updateRemotePreferences(profileService.getWallets())
});
};
$scope.$on("$ionicView.enter", function(event, data){
$scope.currentUnit = config.wallet.settings.unitCode;
});
});

View file

@ -2,6 +2,7 @@
angular.module('copayApp.controllers').controller('sellCoinbaseController', function($scope, $log, $state, $timeout, $ionicHistory, $ionicScrollDelegate, $ionicConfig, lodash, coinbaseService, popupService, profileService, ongoingProcess, walletService, appConfigService, configService, txFormatService) {
var coin = 'btc';
var amount;
var currency;
@ -34,6 +35,51 @@ angular.module('copayApp.controllers').controller('sellCoinbaseController', func
}, onSendStatusChange);
};
var processPaymentInfo = function() {
ongoingProcess.set('connectingCoinbase', true);
coinbaseService.init(function(err, res) {
if (err) {
ongoingProcess.set('connectingCoinbase', false);
showErrorAndBack(err);
return;
}
var accessToken = res.accessToken;
coinbaseService.sellPrice(accessToken, coinbaseService.getAvailableCurrency(), function(err, s) {
$scope.sellPrice = s.data || null;
});
$scope.paymentMethods = [];
$scope.selectedPaymentMethodId = { value : null };
coinbaseService.getPaymentMethods(accessToken, function(err, p) {
if (err) {
ongoingProcess.set('connectingCoinbase', false);
showErrorAndBack(err);
return;
}
var hasPrimary;
var pm;
for(var i = 0; i < p.data.length; i++) {
pm = p.data[i];
if (pm.allow_sell) {
$scope.paymentMethods.push(pm);
}
if (pm.allow_sell && pm.primary_sell) {
hasPrimary = true;
$scope.selectedPaymentMethodId.value = pm.id;
}
}
if (lodash.isEmpty($scope.paymentMethods)) {
ongoingProcess.set('connectingCoinbase', false);
showErrorAndBack('No payment method available to sell');
return;
}
if (!hasPrimary) $scope.selectedPaymentMethodId.value = $scope.paymentMethods[0].id;
$scope.sellRequest();
});
});
};
var checkTransaction = lodash.throttle(function(count, txp) {
$log.warn('Check if transaction has been received by Coinbase. Try ' + count + '/5');
// TX amount in BTC
@ -125,14 +171,9 @@ angular.module('copayApp.controllers').controller('sellCoinbaseController', func
});
$scope.$on("$ionicView.beforeEnter", function(event, data) {
$scope.isFiat = data.stateParams.currency != 'bits' && data.stateParams.currency != 'BTC' ? true : false;
var parsedAmount = txFormatService.parseAmount(
data.stateParams.amount,
data.stateParams.currency);
amount = parsedAmount.amount;
currency = parsedAmount.currency;
$scope.amountUnitStr = parsedAmount.amountUnitStr;
$scope.isFiat = data.stateParams.currency != 'BTC' ? true : false;
amount = data.stateParams.amount;
currency = data.stateParams.currency;
$scope.priceSensitivity = coinbaseService.priceSensitivity;
$scope.selectedPriceSensitivity = { data: coinbaseService.selectedPriceSensitivity };
@ -143,57 +184,14 @@ angular.module('copayApp.controllers').controller('sellCoinbaseController', func
onlyComplete: true,
network: $scope.network,
hasFunds: true,
minAmount: parsedAmount.amountSat
coin: coin
});
if (lodash.isEmpty($scope.wallets)) {
showErrorAndBack('Insufficient funds');
return;
}
$scope.wallet = $scope.wallets[0]; // Default first wallet
ongoingProcess.set('connectingCoinbase', true);
coinbaseService.init(function(err, res) {
if (err) {
ongoingProcess.set('connectingCoinbase', false);
showErrorAndBack(err);
return;
}
var accessToken = res.accessToken;
coinbaseService.sellPrice(accessToken, coinbaseService.getAvailableCurrency(), function(err, s) {
$scope.sellPrice = s.data || null;
});
$scope.paymentMethods = [];
$scope.selectedPaymentMethodId = { value : null };
coinbaseService.getPaymentMethods(accessToken, function(err, p) {
if (err) {
ongoingProcess.set('connectingCoinbase', false);
showErrorAndBack(err);
return;
}
var hasPrimary;
var pm;
for(var i = 0; i < p.data.length; i++) {
pm = p.data[i];
if (pm.allow_sell) {
$scope.paymentMethods.push(pm);
}
if (pm.allow_sell && pm.primary_sell) {
hasPrimary = true;
$scope.selectedPaymentMethodId.value = pm.id;
}
}
if (lodash.isEmpty($scope.paymentMethods)) {
ongoingProcess.set('connectingCoinbase', false);
showErrorAndBack('No payment method available to sell');
return;
}
if (!hasPrimary) $scope.selectedPaymentMethodId.value = $scope.paymentMethods[0].id;
$scope.sellRequest();
});
});
$scope.onWalletSelect($scope.wallets[0]); // Default first wallet
});
$scope.sellRequest = function() {
@ -306,6 +304,15 @@ angular.module('copayApp.controllers').controller('sellCoinbaseController', func
$scope.onWalletSelect = function(wallet) {
$scope.wallet = wallet;
var parsedAmount = txFormatService.parseAmount(
coin,
amount,
currency);
amount = parsedAmount.amount;
currency = parsedAmount.currency;
$scope.amountUnitStr = parsedAmount.amountUnitStr;
processPaymentInfo();
};
$scope.goBackHome = function() {

View file

@ -2,6 +2,7 @@
angular.module('copayApp.controllers').controller('sellGlideraController', function($scope, $log, $state, $timeout, $ionicHistory, $ionicConfig, lodash, glideraService, popupService, profileService, ongoingProcess, walletService, configService, platformInfo, txFormatService) {
var coin = 'btc';
var amount;
var currency;
@ -35,39 +36,7 @@ angular.module('copayApp.controllers').controller('sellGlideraController', funct
}
};
$scope.$on("$ionicView.beforeLeave", function(event, data) {
$ionicConfig.views.swipeBackEnabled(true);
});
$scope.$on("$ionicView.enter", function(event, data) {
$ionicConfig.views.swipeBackEnabled(false);
});
$scope.$on("$ionicView.beforeEnter", function(event, data) {
$scope.isFiat = data.stateParams.currency != 'bits' && data.stateParams.currency != 'BTC' ? true : false;
var parsedAmount = txFormatService.parseAmount(
data.stateParams.amount,
data.stateParams.currency);
amount = parsedAmount.amount;
currency = parsedAmount.currency;
$scope.amountUnitStr = parsedAmount.amountUnitStr;
$scope.network = glideraService.getNetwork();
$scope.wallets = profileService.getWallets({
m: 1, // Only 1-signature wallet
onlyComplete: true,
network: $scope.network,
hasFunds: true,
minAmount: parsedAmount.amountSat
});
if (lodash.isEmpty($scope.wallets)) {
showErrorAndBack('Insufficient funds');
return;
}
$scope.wallet = $scope.wallets[0]; // Default first wallet
var processPaymentInfo = function() {
ongoingProcess.set('connectingGlidera', true);
glideraService.init(function(err, data) {
if (err) {
@ -91,6 +60,35 @@ angular.module('copayApp.controllers').controller('sellGlideraController', funct
$scope.sellInfo = sell;
});
});
};
$scope.$on("$ionicView.beforeLeave", function(event, data) {
$ionicConfig.views.swipeBackEnabled(true);
});
$scope.$on("$ionicView.enter", function(event, data) {
$ionicConfig.views.swipeBackEnabled(false);
});
$scope.$on("$ionicView.beforeEnter", function(event, data) {
$scope.isFiat = data.stateParams.currency != 'BTC' ? true : false;
amount = data.stateParams.amount;
currency = data.stateParams.currency;
$scope.network = glideraService.getNetwork();
$scope.wallets = profileService.getWallets({
m: 1, // Only 1-signature wallet
onlyComplete: true,
network: $scope.network,
hasFunds: true,
coin: coin
});
if (lodash.isEmpty($scope.wallets)) {
showErrorAndBack('Insufficient funds');
return;
}
$scope.onWalletSelect($scope.wallets[0]); // Default first wallet
});
var ask2FaCode = function(mode, cb) {
@ -231,6 +229,15 @@ angular.module('copayApp.controllers').controller('sellGlideraController', funct
$scope.onWalletSelect = function(wallet) {
$scope.wallet = wallet;
var parsedAmount = txFormatService.parseAmount(
coin,
amount,
currency);
amount = parsedAmount.amount;
currency = parsedAmount.currency;
$scope.amountUnitStr = parsedAmount.amountUnitStr;
processPaymentInfo();
};
$scope.goBackHome = function() {

View file

@ -8,7 +8,8 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
$scope.requestSpecificAmount = function() {
$state.go('tabs.paymentRequest.amount', {
id: $scope.wallet.credentials.walletId
id: $scope.wallet.credentials.walletId,
coin: $scope.wallet.coin
});
};

View file

@ -76,6 +76,7 @@ angular.module('copayApp.controllers').controller('tabSendController', function(
color: v.color,
name: v.name,
recipientType: 'wallet',
coin: v.coin,
getAddress: function(cb) {
walletService.getAddress(v, false, cb);
},
@ -186,7 +187,8 @@ angular.module('copayApp.controllers').controller('tabSendController', function(
toAddress: addr,
toName: item.name,
toEmail: item.email,
toColor: item.color
toColor: item.color,
coin: item.coin
})
});
});

View file

@ -10,7 +10,6 @@ angular.module('copayApp.controllers').controller('tabSettingsController', funct
$scope.buyAndSellServices = buyAndSellService.getLinked();
configService.whenAvailable(function(config) {
$scope.unitName = config.wallet.settings.unitName;
$scope.selectedAlternative = {
name: config.wallet.settings.alternativeName,
isoCode: config.wallet.settings.alternativeIsoCode

View file

@ -3,6 +3,7 @@
angular.module('copayApp.controllers').controller('topUpController', function($scope, $log, $state, $timeout, $ionicHistory, $ionicConfig, lodash, popupService, profileService, ongoingProcess, walletService, configService, platformInfo, bitpayService, bitpayCardService, payproService, bwcError, txFormatService, sendMaxService, gettextCatalog) {
$scope.isCordova = platformInfo.isCordova;
var coin = 'btc';
var cardId;
var useSendMax;
var amount;
@ -36,7 +37,7 @@ angular.module('copayApp.controllers').controller('topUpController', function($s
};
var satToFiat = function(sat, cb) {
txFormatService.toFiat(sat, $scope.currencyIsoCode, function(value) {
txFormatService.toFiat(coin, sat, $scope.currencyIsoCode, function(value) {
return cb(value);
});
};
@ -218,7 +219,7 @@ angular.module('copayApp.controllers').controller('topUpController', function($s
// Save TX in memory
createdTx = ctxp;
$scope.totalAmountStr = txFormatService.formatAmountStr(ctxp.amount);
$scope.totalAmountStr = txFormatService.formatAmountStr(coin, ctxp.amount);
setTotalAmount(parsedAmount.amountSat, invoiceFeeSat, ctxp.fee);
@ -256,7 +257,8 @@ angular.module('copayApp.controllers').controller('topUpController', function($s
$scope.wallets = profileService.getWallets({
onlyComplete: true,
network: bitpayService.getEnvironment().network,
hasFunds: true
hasFunds: true,
coin: coin
});
if (lodash.isEmpty($scope.wallets)) {
@ -319,7 +321,7 @@ angular.module('copayApp.controllers').controller('topUpController', function($s
});
return;
}
var parsedAmount = txFormatService.parseAmount(a, c);
var parsedAmount = txFormatService.parseAmount(coin, a, c);
initializeTopUp(wallet, parsedAmount);
});
};

View file

@ -5,6 +5,7 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
var txId;
var listeners = [];
var config = configService.getSync();
var blockexplorerUrl;
$scope.$on("$ionicView.beforeEnter", function(event, data) {
txId = data.stateParams.txid;
@ -15,6 +16,12 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
$scope.isShared = $scope.wallet.credentials.n > 1;
$scope.txsUnsubscribedForNotifications = config.confirmedTxsNotifications ? !config.confirmedTxsNotifications.enabled : true;
if ($scope.wallet.coin == 'bch') {
blockexplorerUrl = 'cashexplorer.bitcoin.com';
} else {
blockexplorerUrl = 'insight.bitpay.com';
}
txConfirmNotification.checkIfEnabled(txId, function(res) {
$scope.txNotification = {
value: res
@ -112,8 +119,8 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
return popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Transaction not available at this time'));
}
$scope.btx = txFormatService.processTx(tx);
txFormatService.formatAlternativeStr(tx.fees, function(v) {
$scope.btx = txFormatService.processTx($scope.wallet.coin, tx);
txFormatService.formatAlternativeStr($scope.wallet.coin, tx.fees, function(v) {
$scope.btx.feeFiatStr = v;
$scope.btx.feeRateStr = ($scope.btx.fees / ($scope.btx.amount + $scope.btx.fees) * 100).toFixed(2) + '%';
});
@ -131,7 +138,7 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
$scope.$digest();
});
feeService.getFeeLevels(function(err, levels) {
feeService.getFeeLevels($scope.wallet.coin, function(err, levels) {
if (err) return;
walletService.getLowAmount($scope.wallet, levels, function(err, amount) {
if (err) return;
@ -178,7 +185,7 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
$scope.viewOnBlockchain = function() {
var btx = $scope.btx;
var url = 'https://' + ($scope.getShortNetworkName() == 'test' ? 'test-' : '') + 'insight.bitpay.com/tx/' + btx.txid;
var url = 'https://' + ($scope.getShortNetworkName() == 'test' ? 'test-' : '') + blockexplorerUrl + '/tx/' + btx.txid;
var optIn = true;
var title = null;
var message = gettextCatalog.getString('View Transaction on Insight');

View file

@ -52,7 +52,7 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
var analyzeUtxos = function() {
if (analyzeUtxosDone) return;
feeService.getFeeLevels(function(err, levels) {
feeService.getFeeLevels($scope.wallet.coin, function(err, levels) {
if (err) return;
walletService.getLowUtxos($scope.wallet, levels, function(err, resp) {
if (err || !resp) return;
@ -169,7 +169,7 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
});
};
feeService.getFeeLevels(function(err, levels) {
feeService.getFeeLevels($scope.wallet.coin, function(err, levels) {
walletService.getTxHistory($scope.wallet, {
progressFn: progressFn,
feeLevels: levels,

View file

@ -27,12 +27,10 @@ angular.module('copayApp.filters', [])
}
})
.filter('formatFiatAmount', ['$filter', '$locale', 'configService',
function(filter, locale, configService) {
function(filter, locale) {
var numberFilter = filter('number');
var formats = locale.NUMBER_FORMATS;
var config = configService.getSync().wallet.settings;
return function(amount) {
if (!config) return amount;
var fractionSize = 2;
var value = numberFilter(amount, fractionSize);

View file

@ -287,7 +287,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
*/
.state('tabs.send.amount', {
url: '/amount/:recipientType/:toAddress/:toName/:toEmail/:toColor',
url: '/amount/:recipientType/:toAddress/:toName/:toEmail/:toColor/:coin/:fixedUnit',
views: {
'tab-send@tabs': {
controller: 'amountController',
@ -296,7 +296,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
}
})
.state('tabs.send.confirm', {
url: '/confirm/:recipientType/:toAddress/:toName/:toAmount/:toEmail/:toColor/:description/:useSendMax',
url: '/confirm/:recipientType/:toAddress/:toName/:toAmount/:toEmail/:toColor/:description/:coin/:useSendMax',
views: {
'tab-send@tabs': {
controller: 'confirmController',
@ -392,15 +392,6 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
}
}
})
.state('tabs.unit', {
url: '/unit',
views: {
'tab-settings@tabs': {
controller: 'preferencesUnitController',
templateUrl: 'views/preferencesUnit.html'
}
}
})
.state('tabs.fee', {
url: '/fee',
views: {
@ -676,12 +667,12 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
abstract: true,
params: {
id: null,
nextStep: 'tabs.paymentRequest.confirm'
nextStep: 'tabs.paymentRequest.confirm',
}
})
.state('tabs.paymentRequest.amount', {
url: '/amount',
url: '/amount/:coin',
views: {
'tab-receive@tabs': {
controller: 'amountController',
@ -690,7 +681,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
}
})
.state('tabs.paymentRequest.confirm', {
url: '/confirm/:amount/:currency',
url: '/confirm/:amount/:currency/:coin',
views: {
'tab-receive@tabs': {
controller: 'customAmountController',
@ -923,6 +914,9 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
controllerAs: 'glidera',
templateUrl: 'views/glidera.html'
}
},
params: {
coin: 'btc',
}
})
.state('tabs.buyandsell.glidera.amount', {
@ -976,6 +970,9 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
controllerAs: 'coinbase',
templateUrl: 'views/coinbase.html'
}
},
params: {
coin: 'btc',
}
})
.state('tabs.preferences.coinbase', {
@ -1064,7 +1061,8 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
params: {
nextStep: 'tabs.giftcards.mercadoLibre.buy',
currency: 'BRL',
forceCurrency: true
coin: 'btc',
fixedUnit: 1,
}
})
.state('tabs.giftcards.mercadoLibre.buy', {
@ -1115,7 +1113,8 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
params: {
nextStep: 'tabs.giftcards.amazon.buy',
currency: 'USD',
forceCurrency: true
coin: 'btc',
fixedUnit: true,
}
})
.state('tabs.giftcards.amazon.buy', {
@ -1155,6 +1154,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
params: {
id: null,
currency: 'USD',
coin: 'btc',
useSendMax: null
}
})

View file

@ -170,9 +170,9 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $
var _getNetAmount = function(amount, cb) {
// Fee Normal for a single transaction (450 bytes)
var txNormalFeeKB = 450 / 1000;
feeService.getFeeRate(null, 'normal', function(err, feePerKB) {
feeService.getFeeRate('btc', 'livenet', 'normal', function(err, feePerKb) {
if (err) return cb(err);
var feeBTC = (feePerKB * txNormalFeeKB / 100000000).toFixed(8);
var feeBTC = (feePerKb * txNormalFeeKB / 100000000).toFixed(8);
return cb(null, amount - feeBTC, feeBTC);
});

View file

@ -61,7 +61,10 @@ angular.module('copayApp.services').factory('configService', function(storageSer
bannedUntil: null,
},
// External services
cashSupport: {
enabled: false,
},
recentTransactions: {
enabled: true,
},
@ -133,6 +136,11 @@ angular.module('copayApp.services').factory('configService', function(storageSer
configCache.hideNextSteps = defaultConfig.hideNextSteps;
}
if (!configCache.cashSupport) {
configCache.cashSupport = defaultConfig.cashSupport;
}
if (!configCache.recentTransactions) {
configCache.recentTransactions = defaultConfig.recentTransactions;
}
@ -143,6 +151,14 @@ angular.module('copayApp.services').factory('configService', function(storageSer
configCache.bitpayAccount = defaultConfig.bitpayAccount;
}
if (configCache.wallet.settings.unitCode == 'bit') {
// Convert to BTC. Bits will be disabled
configCache.wallet.settings.unitName = defaultConfig.wallet.settings.unitName;
configCache.wallet.settings.unitToSatoshi = defaultConfig.wallet.settings.unitToSatoshi;
configCache.wallet.settings.unitDecimals = defaultConfig.wallet.settings.unitDecimals;
configCache.wallet.settings.unitCode = defaultConfig.wallet.settings.unitCode;
}
} else {
configCache = lodash.clone(defaultConfig);
};

View file

@ -24,20 +24,20 @@ angular.module('copayApp.services').factory('feeService', function($log, $timeou
};
root.getFeeRate = function(network, feeLevel, cb) {
root.getFeeRate = function(coin, network, feeLevel, cb) {
if (feeLevel == 'custom') return cb();
network = network || 'livenet';
root.getFeeLevels(function(err, levels, fromCache) {
root.getFeeLevels(coin, function(err, levels, fromCache) {
if (err) return cb(err);
var feeLevelRate = lodash.find(levels[network], {
level: feeLevel
});
if (!feeLevelRate || !feeLevelRate.feePerKB) {
if (!feeLevelRate || !feeLevelRate.feePerKb) {
return cb({
message: gettextCatalog.getString("Could not get dynamic fee for level: {{feeLevel}}", {
feeLevel: feeLevel
@ -45,29 +45,29 @@ angular.module('copayApp.services').factory('feeService', function($log, $timeou
});
}
var feeRate = feeLevelRate.feePerKB;
var feeRate = feeLevelRate.feePerKb;
if (!fromCache) $log.debug('Dynamic fee: ' + feeLevel + '/' + network + ' ' + (feeLevelRate.feePerKB / 1000).toFixed() + ' SAT/B');
if (!fromCache) $log.debug('Dynamic fee: ' + feeLevel + '/' + network + ' ' + (feeLevelRate.feePerKb / 1000).toFixed() + ' SAT/B');
return cb(null, feeRate);
});
};
root.getCurrentFeeRate = function(network, cb) {
return root.getFeeRate(network, root.getCurrentFeeLevel(), cb);
root.getCurrentFeeRate = function(coin, network, cb) {
return root.getFeeRate(coin, network, root.getCurrentFeeLevel(), cb);
};
root.getFeeLevels = function(cb) {
root.getFeeLevels = function(coin, cb) {
coin = coin || 'btc';
if (cache.updateTs > Date.now() - CACHE_TIME_TS * 1000) {
return cb(null, cache.data, true);
}
var walletClient = bwcService.getClient();
var unitName = configService.getSync().wallet.settings.unitName;
walletClient.getFeeLevels('livenet', function(errLivenet, levelsLivenet) {
walletClient.getFeeLevels('testnet', function(errTestnet, levelsTestnet) {
walletClient.getFeeLevels(coin, 'livenet', function(errLivenet, levelsLivenet) {
walletClient.getFeeLevels('btc', 'testnet', function(errTestnet, levelsTestnet) {
if (errLivenet || errTestnet) {
return cb(gettextCatalog.getString('Could not get dynamic fee'));
}

View file

@ -46,7 +46,7 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
return true;
}
function goSend(addr, amount, message) {
function goSend(addr, amount, message, coin) {
$state.go('tabs.send', {}, {
'reload': true,
'notify': $state.current.name == 'tabs.send' ? false : true
@ -57,11 +57,13 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
$state.transitionTo('tabs.send.confirm', {
toAmount: amount,
toAddress: addr,
description: message
description: message,
coin: coin
});
} else {
$state.transitionTo('tabs.send.amount', {
toAddress: addr
toAddress: addr,
coin: coin
});
}
}, 100);
@ -90,16 +92,17 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
var message = parsed.message;
var amount = parsed.amount ? parsed.amount : '';
var coin = parsed.extras && parsed.extras.coin ? parsed.extras.coin : '';
if (parsed.r) {
payproService.getPayProDetails(parsed.r, function(err, details) {
if (err) {
if (addr && amount) goSend(addr, amount, message);
if (addr && amount) goSend(addr, amount, message, coin);
else popupService.showAlert(gettextCatalog.getString('Error'), err);
} else handlePayPro(details);
});
} else {
goSend(addr, amount, message);
goSend(addr, amount, message, coin);
}
return true;

View file

@ -89,6 +89,7 @@ angular.module('copayApp.services')
wallet.copayerId = wallet.credentials.copayerId;
wallet.m = wallet.credentials.m;
wallet.n = wallet.credentials.n;
wallet.coin = wallet.credentials.coin;
root.updateWalletSettings(wallet);
root.wallet[walletId] = wallet;
@ -222,11 +223,12 @@ angular.module('copayApp.services')
return ((config.bwsFor && config.bwsFor[walletId]) || defaults.bws.url);
};
var client = bwcService.getClient(JSON.stringify(credentials), {
bwsurl: getBWSURL(credentials.walletId),
});
var skipKeyValidation = shouldSkipValidation(credentials.walletId);
if (!skipKeyValidation)
root.runValidation(client, 500);
@ -328,6 +330,7 @@ angular.module('copayApp.services')
passphrase: opts.passphrase,
account: opts.account || 0,
derivationStrategy: opts.derivationStrategy || 'BIP44',
coin: opts.coin
});
} catch (ex) {
@ -346,6 +349,7 @@ angular.module('copayApp.services')
walletClient.seedFromExtendedPublicKey(opts.extendedPublicKey, opts.externalSource, opts.entropySource, {
account: opts.account || 0,
derivationStrategy: opts.derivationStrategy || 'BIP44',
coin: opts.coin
});
walletClient.credentials.hwInfo = opts.hwInfo;
} catch (ex) {
@ -360,6 +364,7 @@ angular.module('copayApp.services')
passphrase: opts.passphrase,
language: lang,
account: 0,
coin: opts.coin
});
} catch (e) {
$log.info('Error creating recovery phrase: ' + e.message);
@ -369,6 +374,7 @@ angular.module('copayApp.services')
network: network,
passphrase: opts.passphrase,
account: 0,
coin: opts.coin
});
} else {
return cb(e);
@ -392,6 +398,7 @@ angular.module('copayApp.services')
network: opts.networkName,
singleAddress: opts.singleAddress,
walletPrivKey: opts.walletPrivKey,
coin: opts.coin
}, function(err, secret) {
if (err) return bwcError.cb(err, gettextCatalog.getString('Error creating wallet'), cb);
return cb(null, walletClient, secret);
@ -435,7 +442,7 @@ angular.module('copayApp.services')
seedWallet(opts, function(err, walletClient) {
if (err) return cb(err);
walletClient.joinWallet(opts.secret, opts.myName || 'me', {}, function(err) {
walletClient.joinWallet(opts.secret, opts.myName || 'me', { coin: opts.coin }, function(err) {
if (err) return bwcError.cb(err, gettextCatalog.getString('Could not join wallet'), cb);
addAndBindWalletClient(walletClient, {
bwsurl: opts.bwsurl
@ -623,6 +630,7 @@ angular.module('copayApp.services')
entropySourcePath: opts.entropySourcePath,
derivationStrategy: opts.derivationStrategy || 'BIP44',
account: opts.account || 0,
coin: opts.coin
}, function(err) {
if (err) {
if (err instanceof errors.NOT_AUTHORIZED)
@ -644,6 +652,7 @@ angular.module('copayApp.services')
walletClient.importFromExtendedPublicKey(opts.extendedPublicKey, opts.externalSource, opts.entropySource, {
account: opts.account || 0,
derivationStrategy: opts.derivationStrategy || 'BIP44',
coin: opts.coin
}, function(err) {
if (err) {
@ -684,6 +693,7 @@ angular.module('copayApp.services')
opts.m = 1;
opts.n = 1;
opts.networkName = 'livenet';
opts.coin = 'btc';
root.createWallet(opts, cb);
};
@ -749,6 +759,12 @@ angular.module('copayApp.services')
var ret = lodash.values(root.wallet);
if (opts.coin) {
ret = lodash.filter(ret, function(x) {
return (x.credentials.coin == opts.coin);
});
}
if (opts.network) {
ret = lodash.filter(ret, function(x) {
return (x.credentials.network == opts.network);
@ -861,7 +877,7 @@ angular.module('copayApp.services')
x.types = [x.type];
if (x.data && x.data.amount)
x.amountStr = txFormatService.formatAmountStr(x.data.amount);
x.amountStr = txFormatService.formatAmountStr(x.wallet.coin, x.data.amount);
x.action = function() {
// TODO?

View file

@ -25,9 +25,10 @@ var RateService = function(opts) {
self._isAvailable = false;
self._rates = {};
self._alternatives = [];
self._ratesBCH = {};
self._queued = [];
self._fetchCurrencies();
self.updateRates();
};
@ -39,14 +40,20 @@ RateService.singleton = function(opts) {
return _instance;
};
RateService.prototype._fetchCurrencies = function() {
RateService.prototype.updateRates = function() {
var self = this;
var backoffSeconds = 5;
var updateFrequencySeconds = 5 * 60;
var rateServiceUrl = 'https://bitpay.com/api/rates';
var bchRateServiceUrl = 'https://api.kraken.com/0/public/Ticker?pair=BCHUSD,BCHEUR';
function getBTC(cb, tries) {
tries = tries || 0;
if (!self.httprequest) return;
if (tries > 5) return cb('could not get BTC rates');
var retrieve = function() {
//log.info('Fetching exchange rates');
self.httprequest.get(rateServiceUrl).success(function(res) {
self.lodash.each(res, function(currency) {
@ -57,26 +64,63 @@ RateService.prototype._fetchCurrencies = function() {
rate: currency.rate
});
});
return cb();
}).error(function() {
//log.debug('Error fetching exchange rates', err);
setTimeout(function() {
backoffSeconds *= 1.5;
getBTC(cb, tries++);
}, backoffSeconds * 1000);
return;
})
}
function getBCH(cb, tries) {
tries = tries || 0;
if (!self.httprequest) return;
if (tries > 5) return cb('could not get BCH rates');
function retry(tries) {
//log.debug('Error fetching exchange rates', err);
setTimeout(function() {
backoffSeconds *= 1.5;
getBTC(cb, tries++);
}, backoffSeconds * 1000);
return;
}
self.httprequest.get(bchRateServiceUrl).success(function(res) {
self.lodash.each(res.result, function(data, paircode) {
var code = paircode.substr(3,3);
var rate =data.c[0];
self._ratesBCH[code] = rate;
})
return cb();
}).error(function() {
return retry(tries);
})
}
getBTC(function(err) {
if (err) return;
getBCH(function(err) {
if (err) return;
self._isAvailable = true;
self.lodash.each(self._queued, function(callback) {
setTimeout(callback, 1);
});
setTimeout(retrieve, updateFrequencySeconds * 1000);
}).error(function(err) {
//log.debug('Error fetching exchange rates', err);
setTimeout(function() {
backoffSeconds *= 1.5;
retrieve();
}, backoffSeconds * 1000);
return;
});
setTimeout( self.updateRates , updateFrequencySeconds * 1000);
})
})
};
retrieve();
};
RateService.prototype.getRate = function(code) {
RateService.prototype.getRate = function(code, chain) {
if (chain == 'bch')
return this._ratesBCH[code];
else
return this._rates[code];
};
@ -90,25 +134,25 @@ RateService.prototype.isAvailable = function() {
RateService.prototype.whenAvailable = function(callback) {
if (this.isAvailable()) {
setTimeout(callback, 1);
setTimeout(callback, 10);
} else {
this._queued.push(callback);
}
};
RateService.prototype.toFiat = function(satoshis, code) {
RateService.prototype.toFiat = function(satoshis, code, chain) {
if (!this.isAvailable()) {
return null;
}
return satoshis * this.SAT_TO_BTC * this.getRate(code);
return satoshis * this.SAT_TO_BTC * this.getRate(code, chain);
};
RateService.prototype.fromFiat = function(amount, code) {
RateService.prototype.fromFiat = function(amount, code, chain) {
if (!this.isAvailable()) {
return null;
}
return amount / this.getRate(code) * this.BTC_TO_SAT;
return amount / this.getRate(code, chain) * this.BTC_TO_SAT;
};
RateService.prototype.listAlternatives = function(sort) {

View file

@ -10,7 +10,7 @@ angular.module('copayApp.services').service('sendMaxService', function(feeServic
*
*/
this.getInfo = function(wallet, cb) {
feeService.getCurrentFeeRate(wallet.credentials.network, function(err, feePerKb) {
feeService.getCurrentFeeRate(wallet.coin, wallet.credentials.network, function(err, feePerKb) {
if (err) return cb(err);
var config = configService.getSync().wallet;

View file

@ -7,7 +7,7 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
root.formatAmount = function(satoshis, fullPrecision) {
var config = configService.getSync().wallet.settings;
var config = configService.getDefaults().wallet.settings;
if (config.unitCode == 'sat') return satoshis;
//TODO : now only works for english, specify opts to change thousand separator and decimal separator
@ -17,16 +17,15 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
return this.Utils.formatAmount(satoshis, config.unitCode, opts);
};
root.formatAmountStr = function(satoshis) {
root.formatAmountStr = function(coin, satoshis) {
if (isNaN(satoshis)) return;
var config = configService.getSync().wallet.settings;
return root.formatAmount(satoshis) + ' ' + config.unitName;
return root.formatAmount(satoshis) + ' ' + (coin).toUpperCase();
};
root.toFiat = function(satoshis, code, cb) {
root.toFiat = function(coin, satoshis, code, cb) {
if (isNaN(satoshis)) return;
var val = function() {
var v1 = rateService.toFiat(satoshis, code);
var v1 = rateService.toFiat(satoshis, code, coin);
if (!v1) return null;
return v1.toFixed(2);
@ -43,10 +42,10 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
};
};
root.formatToUSD = function(satoshis, cb) {
root.formatToUSD = function(coin, satoshis, cb) {
if (isNaN(satoshis)) return;
var val = function() {
var v1 = rateService.toFiat(satoshis, 'USD');
var v1 = rateService.toFiat(satoshis, 'USD', coin);
if (!v1) return null;
return v1.toFixed(2);
@ -63,12 +62,12 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
};
};
root.formatAlternativeStr = function(satoshis, cb) {
root.formatAlternativeStr = function(coin, satoshis, cb) {
if (isNaN(satoshis)) return;
var config = configService.getSync().wallet.settings;
var val = function() {
var v1 = parseFloat((rateService.toFiat(satoshis, config.alternativeIsoCode)).toFixed(2));
var v1 = parseFloat((rateService.toFiat(satoshis, config.alternativeIsoCode, coin)).toFixed(2));
v1 = $filter('formatFiatAmount')(v1);
if (!v1) return null;
@ -86,7 +85,7 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
};
};
root.processTx = function(tx) {
root.processTx = function(coin, tx) {
if (!tx || tx.action == 'invalid')
return tx;
@ -101,17 +100,17 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
tx.hasMultiplesOutputs = true;
}
tx.amount = lodash.reduce(tx.outputs, function(total, o) {
o.amountStr = root.formatAmountStr(o.amount);
o.alternativeAmountStr = root.formatAlternativeStr(o.amount);
o.amountStr = root.formatAmountStr(coin, o.amount);
o.alternativeAmountStr = root.formatAlternativeStr(coin, o.amount);
return total + o.amount;
}, 0);
}
tx.toAddress = tx.outputs[0].toAddress;
}
tx.amountStr = root.formatAmountStr(tx.amount);
tx.alternativeAmountStr = root.formatAlternativeStr(tx.amount);
tx.feeStr = root.formatAmountStr(tx.fee || tx.fees);
tx.amountStr = root.formatAmountStr(coin, tx.amount);
tx.alternativeAmountStr = root.formatAlternativeStr(coin, tx.amount);
tx.feeStr = root.formatAmountStr(coin, tx.fee || tx.fees);
if (tx.amountStr) {
tx.amountValueStr = tx.amountStr.split(' ')[0];
@ -145,8 +144,6 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
lodash.each(txps, function(tx) {
tx = txFormatService.processTx(tx);
// no future transactions...
if (tx.createdOn > now)
tx.createdOn = now;
@ -157,6 +154,8 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
return;
}
tx = txFormatService.processTx(tx.wallet.coin, tx);
var action = lodash.find(tx.actions, {
copayerId: tx.wallet.copayerId
});
@ -180,7 +179,7 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
return txps;
};
root.parseAmount = function(amount, currency) {
root.parseAmount = function(coin, amount, currency) {
var config = configService.getSync().wallet.settings;
var satToBtc = 1 / 100000000;
var unitToSatoshi = config.unitToSatoshi;
@ -189,21 +188,21 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
var alternativeIsoCode = config.alternativeIsoCode;
// If fiat currency
if (currency != 'bits' && currency != 'BTC' && currency != 'sat') {
if (currency != 'BCH' && currency != 'BTC' && currency != 'sat') {
amountUnitStr = $filter('formatFiatAmount')(amount) + ' ' + currency;
amountSat = rateService.fromFiat(amount, currency).toFixed(0);
amountSat = rateService.fromFiat(amount, currency, coin).toFixed(0);
} else if (currency == 'sat') {
amountSat = amount;
amountUnitStr = root.formatAmountStr(amountSat);
// convert sat to BTC
amountUnitStr = root.formatAmountStr(coin, amountSat);
// convert sat to BTC or BCH
amount = (amountSat * satToBtc).toFixed(8);
currency = 'BTC';
currency = (coin).toUpperCase();
} else {
amountSat = parseInt((amount * unitToSatoshi).toFixed(0));
amountUnitStr = root.formatAmountStr(amountSat);
// convert unit to BTC
amountUnitStr = root.formatAmountStr(coin, amountSat);
// convert unit to BTC or BCH
amount = (amountSat * satToBtc).toFixed(8);
currency = 'BTC';
currency = (coin).toUpperCase();
}
return {

View file

@ -130,7 +130,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
lodash.each(txps, function(tx) {
tx = txFormatService.processTx(tx);
tx = txFormatService.processTx(wallet.coin, tx);
// no future transactions...
if (tx.createdOn > now)
@ -213,14 +213,13 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
// Selected unit
cache.unitToSatoshi = config.settings.unitToSatoshi;
cache.satToUnit = 1 / cache.unitToSatoshi;
cache.unitName = config.settings.unitName;
//STR
cache.totalBalanceStr = txFormatService.formatAmount(cache.totalBalanceSat) + ' ' + cache.unitName;
cache.lockedBalanceStr = txFormatService.formatAmount(cache.lockedBalanceSat) + ' ' + cache.unitName;
cache.availableBalanceStr = txFormatService.formatAmount(cache.availableBalanceSat) + ' ' + cache.unitName;
cache.spendableBalanceStr = txFormatService.formatAmount(cache.spendableAmount) + ' ' + cache.unitName;
cache.pendingBalanceStr = txFormatService.formatAmount(cache.pendingAmount) + ' ' + cache.unitName;
cache.totalBalanceStr = txFormatService.formatAmountStr(wallet.coin, cache.totalBalanceSat);
cache.lockedBalanceStr = txFormatService.formatAmountStr(wallet.coin, cache.lockedBalanceSat);
cache.availableBalanceStr = txFormatService.formatAmountStr(wallet.coin, cache.availableBalanceSat);
cache.spendableBalanceStr = txFormatService.formatAmountStr(wallet.coin, cache.spendableAmount);
cache.pendingBalanceStr = txFormatService.formatAmountStr(wallet.coin, cache.pendingAmount);
cache.alternativeName = config.settings.alternativeName;
cache.alternativeIsoCode = config.settings.alternativeIsoCode;
@ -238,11 +237,11 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
rateService.whenAvailable(function() {
var totalBalanceAlternative = rateService.toFiat(cache.totalBalanceSat, cache.alternativeIsoCode);
var pendingBalanceAlternative = rateService.toFiat(cache.pendingAmount, cache.alternativeIsoCode);
var lockedBalanceAlternative = rateService.toFiat(cache.lockedBalanceSat, cache.alternativeIsoCode);
var spendableBalanceAlternative = rateService.toFiat(cache.spendableAmount, cache.alternativeIsoCode);
var alternativeConversionRate = rateService.toFiat(100000000, cache.alternativeIsoCode);
var totalBalanceAlternative = rateService.toFiat(cache.totalBalanceSat, cache.alternativeIsoCode, wallet.coin);
var pendingBalanceAlternative = rateService.toFiat(cache.pendingAmount, cache.alternativeIsoCode, wallet.coin);
var lockedBalanceAlternative = rateService.toFiat(cache.lockedBalanceSat, cache.alternativeIsoCode, wallet.coin);
var spendableBalanceAlternative = rateService.toFiat(cache.spendableAmount, cache.alternativeIsoCode, wallet.coin);
var alternativeConversionRate = rateService.toFiat(100000000, cache.alternativeIsoCode, wallet.coin);
cache.totalBalanceAlternative = $filter('formatFiatAmount')(totalBalanceAlternative);
cache.pendingBalanceAlternative = $filter('formatFiatAmount')(pendingBalanceAlternative);
@ -366,7 +365,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
wallet.hasUnsafeConfirmed = false;
lodash.each(txs, function(tx) {
tx = txFormatService.processTx(tx);
tx = txFormatService.processTx(wallet.coin, tx);
// no future transactions...
if (tx.time > now)
@ -400,7 +399,6 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
var LIMIT = 50;
var requestLimit = FIRST_LIMIT;
var walletId = wallet.credentials.walletId;
var config = configService.getSync().wallet.settings;
var opts = opts || {};
var progressFn = opts.progressFn || function() {};
@ -414,18 +412,16 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
var fixTxsUnit = function(txs) {
if (!txs || !txs[0] || !txs[0].amountStr) return;
var cacheUnit = txs[0].amountStr.split(' ')[1];
var cacheCoin = txs[0].amountStr.split(' ')[1];
if (cacheUnit == config.unitName)
return;
if (cacheCoin == 'bits') {
var name = ' ' + config.unitName;
$log.debug('Fixing Tx Cache Unit to:' + name)
$log.debug('Fixing Tx Cache Unit to: ' + wallet.coin)
lodash.each(txs, function(tx) {
tx.amountStr = txFormatService.formatAmount(tx.amount) + name;
tx.feeStr = txFormatService.formatAmount(tx.fees) + name;
tx.amountStr = txFormatService.formatAmountStr(wallet.coin, tx.amount);
tx.feeStr = txFormatService.formatAmountStr(wallet.coin, tx.fees);
});
}
};
getSavedTxs(walletId, function(err, txsFromLocal) {
@ -788,7 +784,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
//prefs.email (may come from arguments)
prefs.email = config.emailNotifications.email;
prefs.language = uxLanguage.getCurrentLanguage();
prefs.unit = walletSettings.unitCode;
// prefs.unit = walletSettings.unitCode; // TODO: remove, not used
updateRemotePreferencesFor(lodash.clone(clients), prefs, function(err) {
if (err) return cb(err);
@ -926,7 +922,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
root.getMinFee = function(wallet, feeLevels, nbOutputs) {
var lowLevelRate = (lodash.find(feeLevels[wallet.network], {
level: 'normal',
}).feePerKB / 1000).toFixed(0);
}).feePerKb / 1000).toFixed(0);
var size = root.getEstimatedTxSize(wallet, nbOutputs);
return size * lowLevelRate;
@ -943,7 +939,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
root.getLowUtxos = function(wallet, levels, cb) {
wallet.getUtxos({}, function(err, resp) {
wallet.getUtxos({coin: wallet.coin}, function(err, resp) {
if (err || !resp || !resp.length) return cb();
var minFee = root.getMinFee(wallet, levels, resp.length);

View file

@ -139,6 +139,19 @@
}
}
.amount {
.icon-toggle {
font-size: 1.2em;
width: auto;
margin: 0.8em auto;
border: 1px solid $v-subtle-gray;
color: $v-dark-gray;
border-radius: 3px;
padding: 0 10px;
cursor: pointer;
@media(max-height: 280px) {
margin: 0.1em auto;
}
}
&__editable {
&--minimize {
font-size: 22px;
@ -187,7 +200,7 @@
&__result {
color: $v-light-gray;
font-size: .9em;
margin-bottom: -.9em;
//margin-bottom: -.9em; TODO matias
line-height: 1;
@media(max-height: 480px) {
margin-bottom: 0;
@ -196,7 +209,6 @@
&__result-equiv {
color: $v-mid-gray;
font-size: 1.2em;
margin-top: 2rem;
@media(max-height: 480px) {
margin-top: 0;
font-size: 16px;

View file

@ -215,6 +215,11 @@
&__button-balance {
background-color: transparent;
border: 1px solid rgba(255,255,255,0.25);
margin-top: 10px;
i.icon {
margin-right: 7px;
vertical-align: middle;
}
}
&__error {

12
www/img/icon-bch.svg Normal file
View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
<g id="Fondo" transform="matrix(0.0814451,-0.0296277,0.0296277,0.0814451,-44.594,-27.3805)">
<g transform="matrix(10.8433,3.94452,-3.94452,10.8433,375.543,472.796)">
<use xlink:href="#_Image1" x="7.552" y="5.557" width="23.603px" height="28.885px" transform="matrix(0.983467,0,0,0.996049,0,0)"/>
</g>
</g>
<defs>
<image id="_Image1" width="24px" height="29px" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAdCAYAAACwuqxLAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACgUlEQVRIia2WzYuPURTHP88Y7zNEaWJKppnEUKRkM5shdlIipSSDSLazQFYkK/EXeMnChsWUkvK2mCJvWXgpZczGa6EmJn7Mx+K50zzu3OeZ35Tv6t5zzj3fc8859wUmAbVJbZjMmnqcZuo69ZT6XN31v5wuV+eE+XXH8FptrNfXP9tVZ6n7gD7gLrA6qO4BhnEHME1dpk6bbORz1duFaC8E0hXq24L8g/pJfa9eVddMhuSk/+KY+shqDKqb6nE+Q92hfpvAYQrP1QWxz0ydAiwAFgMHgJ6KGPqBH8AMoAvIIn17lmVv4qh71C8VkT1Rj6ob1Jawplk9H9kNq5tTaTlU4fyPurcknV3mxR7FV7UptmsErgNbw3YXAcsK+gZgeUm6BoH5hfltoJa0DHXAvMAxHqvtkf0ctS/scETtj23KiFrUOwmS3UG/VD2nDiXqdDOQ7hkNuIzkeILggflZeFdRr1HU1MtVBN2OPwcjCUfPzHt/MKH/re4vI5hufvxTeKGeUDeqbcF+ieNbVvWjOrOM5HBiwX21s8R+ZmIXI2pz2ePRD7yJZJ1Aa4l9E3nbFjEEtCYJsix7CtyKxM3k10MKs4G5kWwgy7JXVc/fvYSsW11YFKjzgHPAvKIYKO+ksLBNfZioxc6gX6+eVV8m8n9Jba4kCE5OJwgG1BuhS2L8VI9Y75OqbjHv6Sr8iebTiz4m+oJ8B4ZLdDXgM3AGGCjIe9X4nRgX+VTzCyzObS2KvCPY3yzIfxRTVNamNfLrNwN+AV+Ba0Av8KWwdlUYXwHeAxeBbYz9QCp3sTYUc3tB1mB+Y46iz/DbU1snTE09UHvN2/eguvK/OI0IZsedUoW/zudIHkrmZMIAAAAASUVORK5CYII="/>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

12
www/img/icon-btc.svg Normal file
View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
<g id="Fondo" transform="matrix(0.0814603,0.0295859,-0.0295859,0.0814603,0.874237,-57.7095)">
<g transform="matrix(10.8453,-3.93895,3.93895,10.8453,217.833,629.321)">
<use xlink:href="#_Image1" x="7.557" y="5.56" width="22.579px" height="28.881px" transform="matrix(0.981703,0,0,0.995881,0,0)"/>
</g>
</g>
<defs>
<image id="_Image1" width="23px" height="29px" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAdCAYAAABBsffGAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACiElEQVRIia3VPYhfRRQF8PM2myya1SxBcLUQP+JXYQpBkJUlGgu1EoRgIyxkUUQUEU0hKQ1io6K9YBRBC0Fj4UdhghYWURHBQtFI0oioWUVFs5vkZ/Hers/J/N9/F7zdO+/MuWfu3JmbbDAwg/PXw50YIzRVgfcmOYqnMY9mowaDObyE23AptmAT3vFvvIFpTOKadSfCgZ7IKbyI+7HUw+/puIs40SV+AJOD5cBr+NXoOI0bO/4HPfyPQfFekgX8PZDgczzZuV6N/esqD+7uHG4k1ppgsFuSzCXZVGBHkrw/gr+c5AVsH+f6ShytONuDi3ArnsJXFc4hbBsSv6+y6CNcUvB24kiFuzBUll0V7HDTND/0gaZpvkzySJIzBXe+Kq5tsdsL+M8kH48wMpvk9wK7YZTzuSRXFNjmJM/jGVzbmZjCTOd8puC/W3M9hTfHtNvPOIm38CPOFP//wo6a+G7n3sxf8MWYhP3Ei2hq1/SWJGUbvZ1kf5Lr057FniRX9/4vJTmU5HiSl5Mcb5pG6fpiHK64WSh4O/Eqzvbc7sOWitkEE7i3IvwZrqrwp/Fhj7eCJ0rS5TiG1/F1RfzZqpt27aMF91tc0Cc8NHA4Z8uS9NZN4r2Cv4z5Vc5EkukkJ5OcGmHwYW1v7+5EV5/ThSR3FNzNaQ81SbL27uKuJI8luSnJhTn3xfwpybHOhCQ3Jyln7HKS2aZplqo2tTPzt95WywsyKk7j8RG7XxM/UCx6TnsLVwaEV3BwnPA2/22vg9iqnf7f9/AT2sP+Bp9gL4YHj/ZduROvaKf8rg7fV5RnB7ZjdlBwRJIGl2Fr993fzXfWM903kOg6PIhPsfi/CFcSnTe2tr34BwJIUvoJiuf+AAAAAElFTkSuQmCC"/>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
<g id="flask" transform="matrix(1.27778,0,0,1.27778,7.86111,8)">
<path d="M13.358,7.26C13.563,7.465 13.78,7.69 14.009,7.937C14.237,8.183 14.571,8.552 15.011,9.044C15.45,9.536 15.854,10.034 16.224,10.538C16.593,11.042 16.959,11.58 17.322,12.151C17.686,12.722 17.973,13.295 18.184,13.869C18.395,14.443 18.5,14.962 18.5,15.425C18.5,16.134 18.248,16.74 17.744,17.244C17.24,17.748 16.634,18 15.925,18L3.075,18C2.366,18 1.76,17.748 1.256,17.244C0.752,16.74 0.5,16.134 0.5,15.425C0.5,14.962 0.605,14.443 0.816,13.869C1.027,13.295 1.314,12.722 1.678,12.151C2.041,11.58 2.407,11.042 2.776,10.538C3.146,10.034 3.55,9.536 3.989,9.044C4.429,8.552 4.763,8.183 4.991,7.937C5.22,7.69 5.437,7.465 5.642,7.26L5.642,1.925L4.675,1.925C4.587,1.925 4.512,1.894 4.451,1.833C4.389,1.771 4.358,1.696 4.358,1.608L4.358,0.316C4.358,0.229 4.389,0.154 4.451,0.092C4.512,0.031 4.587,0 4.675,0L14.325,0C14.413,0 14.488,0.031 14.549,0.092C14.611,0.154 14.642,0.229 14.642,0.316L14.642,1.608C14.642,1.696 14.611,1.771 14.549,1.833C14.488,1.894 14.413,1.925 14.325,1.925L13.358,1.925L13.358,7.26ZM5,1.283L14,1.283L14,0.642L5,0.642L5,1.283ZM12.717,1.925L6.283,1.925L6.283,4.14C6.705,4.011 7.105,3.926 7.483,3.885C7.861,3.844 8.168,3.838 8.406,3.867C8.643,3.896 8.863,3.948 9.065,4.021C9.267,4.094 9.408,4.156 9.487,4.206C9.566,4.255 9.632,4.304 9.685,4.351C9.737,4.392 9.806,4.437 9.891,4.487C9.976,4.537 10.124,4.601 10.335,4.68C10.546,4.759 10.763,4.811 10.985,4.834C11.208,4.857 11.478,4.835 11.794,4.768C12.11,4.701 12.418,4.576 12.717,4.395L12.717,1.925ZM15.925,17.358C16.458,17.358 16.914,17.169 17.292,16.792C17.669,16.414 17.858,15.958 17.858,15.425C17.858,14.897 17.688,14.273 17.349,13.553C17.009,12.832 16.615,12.161 16.167,11.54C15.718,10.919 15.228,10.295 14.694,9.668C14.161,9.041 13.747,8.574 13.451,8.266C13.155,7.958 12.942,7.746 12.813,7.629C12.749,7.564 12.717,7.485 12.717,7.392L12.717,5.124C12.242,5.353 11.753,5.467 11.249,5.467C10.903,5.467 10.566,5.413 10.238,5.304C9.91,5.196 9.679,5.101 9.544,5.019C9.409,4.937 9.321,4.875 9.28,4.834C9.233,4.799 9.192,4.77 9.157,4.746C9.122,4.723 9.012,4.679 8.828,4.614C8.643,4.55 8.45,4.51 8.248,4.496C8.045,4.481 7.767,4.496 7.413,4.54C7.058,4.583 6.682,4.673 6.283,4.808L6.283,7.392C6.283,7.485 6.251,7.564 6.187,7.629C6.058,7.746 5.845,7.958 5.549,8.266C5.253,8.574 4.839,9.041 4.306,9.668C3.772,10.295 3.282,10.919 2.833,11.54C2.385,12.161 1.991,12.832 1.651,13.553C1.312,14.273 1.142,14.897 1.142,15.425C1.142,15.958 1.331,16.414 1.708,16.792C2.086,17.169 2.542,17.358 3.075,17.358L15.925,17.358ZM9.825,6.425C10.358,6.425 10.812,6.614 11.187,6.992C11.563,7.37 11.75,7.825 11.75,8.358C11.75,8.892 11.563,9.346 11.187,9.721C10.812,10.096 10.358,10.283 9.825,10.283C9.292,10.283 8.836,10.096 8.458,9.721C8.081,9.346 7.892,8.892 7.892,8.358C7.892,7.825 8.081,7.37 8.458,6.992C8.836,6.614 9.292,6.425 9.825,6.425ZM9.825,9.642C10.177,9.642 10.479,9.517 10.73,9.268C10.982,9.019 11.108,8.716 11.108,8.358C11.108,8.001 10.982,7.696 10.73,7.444C10.479,7.192 10.177,7.066 9.825,7.066C9.468,7.066 9.163,7.192 8.911,7.444C8.659,7.696 8.533,8.001 8.533,8.358C8.533,8.716 8.659,9.019 8.911,9.268C9.163,9.517 9.468,9.642 9.825,9.642ZM7.892,10.925C8.249,10.925 8.552,11.051 8.801,11.303C9.05,11.555 9.175,11.859 9.175,12.217C9.175,12.568 9.05,12.87 8.801,13.122C8.552,13.374 8.249,13.5 7.892,13.5C7.534,13.5 7.231,13.374 6.982,13.122C6.733,12.87 6.608,12.568 6.608,12.217C6.608,11.859 6.733,11.555 6.982,11.303C7.231,11.051 7.534,10.925 7.892,10.925ZM7.892,12.858C8.073,12.858 8.226,12.795 8.349,12.669C8.472,12.543 8.533,12.393 8.533,12.217C8.533,12.035 8.472,11.881 8.349,11.755C8.226,11.629 8.073,11.566 7.892,11.566C7.716,11.566 7.565,11.629 7.439,11.755C7.313,11.881 7.25,12.035 7.25,12.217C7.25,12.393 7.313,12.543 7.439,12.669C7.565,12.795 7.716,12.858 7.892,12.858ZM10.783,13.5C11.053,13.5 11.281,13.594 11.469,13.781C11.656,13.969 11.75,14.197 11.75,14.467C11.75,14.73 11.656,14.956 11.469,15.144C11.281,15.331 11.053,15.425 10.783,15.425C10.52,15.425 10.294,15.331 10.106,15.144C9.919,14.956 9.825,14.73 9.825,14.467C9.825,14.197 9.919,13.969 10.106,13.781C10.294,13.594 10.52,13.5 10.783,13.5ZM10.783,14.783C10.871,14.783 10.947,14.752 11.012,14.691C11.076,14.629 11.108,14.555 11.108,14.467C11.108,14.373 11.076,14.295 11.012,14.234C10.947,14.172 10.871,14.142 10.783,14.142C10.695,14.142 10.621,14.172 10.559,14.234C10.498,14.295 10.467,14.373 10.467,14.467C10.467,14.555 10.498,14.629 10.559,14.691C10.621,14.752 10.695,14.783 10.783,14.783Z" style="fill:white;"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

View file

@ -7,6 +7,17 @@
<ion-content>
<div class="settings-list list">
<ion-toggle class="has-comment" ng-model="cashSupport.value" toggle-class="toggle-balanced" ng-change="cashSupportChange()">
<span class="toggle-label" translate>Support Bitcoin Cash</span>
</ion-toggle>
<div class="comment" translate>
Enable Bitcoin Cash wallet creation and operation within the App.
<a ng-click="learnMore()">Learn more</a>
</div>
<ion-toggle class="has-comment" ng-model="spendUnconfirmed.value" toggle-class="toggle-balanced" ng-change="spendUnconfirmedChange()">
<span class="toggle-label" translate>Use Unconfirmed Funds</span>
</ion-toggle>

View file

@ -48,16 +48,11 @@
<div class="amount">
<div class="amount__editable" ng-class="{'amount__editable--minimize': smallFont, 'amount__editable--standard': !smallFont, 'amount__editable--placeholder': !amount}">
<span class="amount__number">{{amount || "0.00" }}</span>
<a class="amount__currency-toggle" ng-click="toggleAlternative()" ng-show="showAlternativeAmount">{{alternativeIsoCode}}</a>
<a class="amount__currency-toggle" ng-click="toggleAlternative()" ng-show="!showAlternativeAmount">{{unitName}}</a>
<a class="amount__currency-toggle" ng-click="changeUnit()">{{unit}}</a>
</div>
<div ng-class="{'amount__results--minimize': smallFont, 'amount__results--standard': !smallFont, 'amount__results--placeholder': !amountResult}" ng-show="!showAlternativeAmount">
<div class="amount__result" ng-show="globalResult">{{globalResult}} {{unitName}}</div>
<div class="amount__result-equiv">&asymp; {{amountResult || '0.00'}} {{alternativeIsoCode}}</div>
</div>
<div ng-class="{'amount__results--minimize': smallFont, 'amount__results--standard': !smallFont, 'amount__results--placeholder': !amountResult}" ng-show="showAlternativeAmount">
<div class="amount__result" ng-show="globalResult">{{globalResult}} {{alternativeIsoCode}}</div>
<div class="amount__result-equiv">{{alternativeResult || '0.00'}} {{unitName}}</div>
<div ng-class="{'amount__results--minimize': smallFont, 'amount__results--standard': !smallFont, 'amount__results--placeholder': amountResult}" ng-click="changeAlternativeUnit()">
<div class="amount__result" ng-show="globalResult">{{globalResult}} {{unit}}</div>
<div class="amount__result-equiv">&asymp; {{alternativeAmount || '0.00'}} {{alternativeUnit}}</div>
</div>
</div>
</div>

View file

@ -29,7 +29,7 @@
<div class="label" translate>From</div>
<div class="wallet">
<i class="icon big-icon-svg">
<img src="img/icon-wallet.svg" ng-class="{'wallet-background-color-default': !wallet.color}" ng-style="{'background-color': wallet.color}" class="bg">
<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">
</i>
{{wallet ? wallet.name : '...'}}
</div>

View file

@ -38,7 +38,7 @@
<div class="label">Receive in</div>
<div class="wallet">
<i class="icon big-icon-svg">
<img src="img/icon-wallet.svg" ng-class="{'wallet-background-color-default': !wallet.color}" ng-style="{'background-color': wallet.color}" class="bg">
<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">
</i>
{{wallet ? wallet.name : '...'}}
</div>

View file

@ -30,7 +30,7 @@
<div class="label">Receive in</div>
<div class="wallet">
<i class="icon big-icon-svg">
<img src="img/icon-wallet.svg" ng-style="{'background-color': wallet.color}" class="bg">
<img ng-src="img/{{wallet.network == 'testnet' ? 'icon-wallet-testnet' : (wallet.coin == 'btc' ? 'icon-btc' : 'icon-bch')}}.svg" ng-style="{'background-color': wallet.color}" class="bg">
</i>
{{wallet ? wallet.name : '...'}}
</div>

View file

@ -28,7 +28,7 @@
<div class="label" translate>From</div>
<div class="wallet">
<i class="icon big-icon-svg">
<img src="img/icon-wallet.svg" ng-class="{'wallet-background-color-default': !wallet.color}" ng-style="{'background-color': wallet.color}" class="bg">
<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">
</i>
{{wallet ? wallet.name : '...'}}
</div>

View file

@ -65,7 +65,7 @@
<span class="label" translate>From</span>
<div class="wallet" ng-if="wallet">
<i class="icon big-icon-svg">
<img src="img/icon-wallet.svg" ng-class="{'wallet-background-color-default': !wallet.color}" ng-style="{'background-color': wallet.color}" class="bg"/>
<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"/>
</i>
<div>{{wallet.name}}</div>
</div>
@ -90,7 +90,7 @@
</span>
</span>
<i class="icon bp-arrow-right"></i>
<i ng-if="wallet.coin == 'btc'" class="icon bp-arrow-right"></i>
</div>
<a class="item item-icon-right" ng-if="wallet" ng-click="showDescriptionPopup(tx)">
<span class="label" translate>Add Memo</span>

View file

@ -21,7 +21,7 @@
<ion-content scroll="false">
<div class="address" ng-if="address && amountBtc">
<div class="qr-code" copy-to-clipboard="copyToClipboard()">
<qrcode size="220" data="bitcoin:{{address + '?amount=' + amountBtc}}" color="#334"></qrcode>
<qrcode size="220" data="bitcoin:{{address + '?amount=' + amountBtc + '&coin=' + coin}}" color="#334"></qrcode>
</div>
<div class="info">
<div class="item single-line" copy-to-clipboard="address">
@ -39,7 +39,7 @@
<div class="item single-line">
<div class="wallet">
<i class="icon big-icon-svg">
<img src="img/icon-wallet.svg" ng-class="{'wallet-background-color-default': !wallet.color}" ng-style="{'background-color': wallet.color}" class="bg">
<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">
</i>
{{wallet.name}}
</div>

View file

@ -0,0 +1,9 @@
<label class="item item-input item-select">
<div class="input-label" translate>
Coin
</div>
<select ng-model="formData.coin">
<option value="btc">BTC</option>
<option value="bch">BCH</option>
</select>
</label>

View file

@ -1,6 +1,6 @@
<div class="wallet-item">
<i class="icon big-icon-svg circle">
<img src="img/icon-wallet.svg" ng-class="{'wallet-background-color-default': !wallet.color}" ng-style="{'background-color': wallet.color}" class="bg"/>
<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"/>
</i>
<div class="name">
{{wallet.name || wallet.id}}

View file

@ -7,7 +7,7 @@
ng-click="selectWallet(w)"
>
<i class="icon big-icon-svg">
<img src="img/icon-wallet.svg" ng-class="{'wallet-background-color-default': !w.color}" ng-style="{'background-color': w.color}" class="bg">
<img ng-src="img/{{w.network == 'testnet' ? 'icon-wallet-testnet' : (w.coin == 'btc' ? 'icon-btc' : 'icon-bch')}}.svg" ng-class="{'wallet-background-color-default': !w.color}" ng-style="{'background-color': w.color}" class="bg">
</i>
<div class="wallet-inner">
<div class="wallet-details">

View file

@ -39,6 +39,9 @@
<qr-scanner class="qr-icon size-24" on-scan="onQrCodeScannedJoin(data)"></qr-scanner>
</div>
</div>
<div ng-include="'views/includes/cash.html'" ng-if="enableCash"></div>
<div class="item item-divider"></div>
<a class="item" ng-click="showAdvChange()">

View file

@ -74,7 +74,7 @@
<span class="label" translate>From</span>
<div class="wallet">
<i class="icon big-icon-svg">
<img src="img/icon-wallet.svg" ng-class="{'wallet-background-color-default': !wallet.color}" ng-style="{'background-color': wallet.color}" class="bg"/>
<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"/>
</i>
<div>{{wallet.name}}</div>
</div>

View file

@ -24,7 +24,7 @@
<div class="list card" ng-click="showWalletSelector()" ng-if="wallets[0]">
<a ng-if="wallet" class="item item-sub item-icon-left item-big-icon-left item-icon-right">
<i class="icon big-icon-svg">
<img src="img/icon-wallet.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"/>
</i>
<span>
{{wallet.name || wallet.id}}

View file

@ -1,14 +0,0 @@
<ion-view class="settings" show-tabs>
<ion-nav-bar class="bar-royal">
<ion-nav-title>
{{'Unit'|translate}}
</ion-nav-title>
<ion-nav-back-button>
</ion-nav-back-button>
</ion-nav-bar>
<ion-content>
<ion-radio ng-repeat="unit in unitList" ng-value="unit.code" ng-model="currentUnit"
ng-click="save(unit)">{{unit.shortName}}
</ion-radio>
</ion-content>
</ion-view>

View file

@ -29,7 +29,7 @@
<div class="label">From</div>
<div class="wallet">
<i class="icon big-icon-svg">
<img src="img/icon-wallet.svg" ng-class="{'wallet-background-color-default': !wallet.color}" ng-style="{'background-color': wallet.color}" class="bg">
<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">
</i>
{{wallet ? wallet.name : '...'}}
</div>

View file

@ -30,7 +30,7 @@
<div class="label">From</div>
<div class="wallet">
<i class="icon big-icon-svg">
<img src="img/icon-wallet.svg" ng-style="{'background-color': wallet.color}" class="bg">
<img ng-src="img/{{wallet.network == 'testnet' ? 'icon-wallet-testnet' : (wallet.coin == 'btc' ? 'icon-btc' : 'icon-bch')}}.svg" ng-style="{'background-color': wallet.color}" class="bg">
</i>
{{wallet ? wallet.name : '...'}}
</div>

View file

@ -19,6 +19,8 @@
required>
</label>
<div ng-include="'views/includes/cash.html'" ng-if="enableCash"></div>
<div class="item item-divider"></div>
<a class="item" ng-click="showAdvChange()">

View file

@ -29,6 +29,8 @@
ng-blur="formFocus(false)">
</label>
<div ng-include="'views/includes/cash.html'" ng-if="enableCash"></div>
<label class="item item-input item-select">
<div class="input-label" translate>
Total number of copayers

View file

@ -81,7 +81,7 @@
class="item item-sub item-icon-left item-big-icon-left item-icon-right wallet"
ng-click="openWallet(wallet)">
<i class="icon big-icon-svg">
<img src="img/icon-wallet.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"/>
</i>
<span>
{{wallet.name || wallet.id}}

View file

@ -21,6 +21,8 @@
ng-model="formData.password">
</label>
<div ng-include="'views/includes/cash.html'" ng-if="enableCash"></div>
<div class="item item-divider"></div>
<a class="item" ng-click="showAdvChange()">

View file

@ -26,6 +26,9 @@
<qr-scanner class="qr-icon size-24" on-scan="processWalletInfo(data)"></qr-scanner>
</div>
</div>
<div ng-include="'views/includes/cash.html'" ng-if="enableCash"></div>
<div class="item item-divider"></div>
<a class="item" ng-click="showAdvChange()">

View file

@ -63,7 +63,7 @@
<div class="wallet-selector" ng-click="showWalletSelector()" ng-if="wallets[0] && wallet">
<a ng-if="wallet" class="item item-sub item-icon-left item-big-icon-left item-icon-right">
<i class="icon big-icon-svg">
<img src="img/icon-wallet.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"/>
</i>
<span>
{{wallet.name || wallet.id}}

View file

@ -69,7 +69,7 @@
<div class="list">
<a class="item item-icon-left item-icon-right" ng-repeat="item in list" ng-if="hasWallets && item.recipientType == 'wallet'" ng-click="goToAmount(item)">
<i class="icon big-icon-svg" ng-if="item.recipientType == 'wallet'">
<img src="img/icon-wallet.svg" ng-class="{'wallet-background-color-default': !item.color}" ng-style="{'background-color': item.color}" class="bg"/>
<img ng-src="img/{{item.network == 'testnet' ? 'icon-wallet-testnet' : (item.coin == 'btc' ? 'icon-btc' : 'icon-bch')}}.svg" ng-class="{'wallet-background-color-default': !item.color}" ng-style="{'background-color': item.color}" class="bg"/>
</i>
{{item.name}}
<i class="icon bp-arrow-right"></i>

View file

@ -56,16 +56,6 @@
</span>
<i class="icon bp-arrow-right"></i>
</a>
<a class="item has-setting-value item-icon-left item-icon-right" ui-sref="tabs.unit">
<i class="icon big-icon-svg">
<img src="img/icon-unit.svg" class="bg"/>
</i>
<span class="setting-title">{{'Bitcoin Unit' | translate}}</span>
<span class="setting-value">
{{unitName}}
</span>
<i class="icon bp-arrow-right"></i>
</a>
<a class="item has-setting-value item-icon-left item-icon-right" ui-sref="tabs.altCurrency">
<i class="icon big-icon-svg">
@ -105,7 +95,7 @@
ui-sref="tabs.preferences({'walletId': item.id})"
ng-repeat="item in wallets track by $index">
<i class="icon big-icon-svg circle">
<img src="img/icon-wallet.svg" ng-class="{'wallet-background-color-default': !item.color}" ng-style="{'background-color': item.color}" class="bg"/>
<img ng-src="img/{{item.network == 'testnet' ? 'icon-wallet-testnet' : (item.coin == 'btc' ? 'icon-btc' : 'icon-bch')}}.svg" ng-class="{'wallet-background-color-default': !item.color}" ng-style="{'background-color': item.color}" class="bg"/>
</i>
<span>
{{item.name || item.id}}

View file

@ -31,10 +31,10 @@
<div class="info">
<div class="item item-icon-right" ng-click="showWalletSelector()">
<div class="label" translate>From</div>
<div class="label" translate>From {{wallet.coin}}</div>
<div class="wallet">
<i class="icon big-icon-svg">
<img src="img/icon-wallet.svg" ng-class="{'wallet-background-color-default': !wallet.color}" ng-style="{'background-color': wallet.color}" class="bg">
<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">
</i>
{{wallet ? wallet.name : '...'}}
</div>

View file

@ -53,7 +53,7 @@
<span class="label" ng-if="btx.action !== 'sent'" translate>To</span>
<div class="wallet">
<i class="icon big-icon-svg">
<img src="img/icon-wallet.svg" ng-class="{'wallet-background-color-default': !wallet.color}" ng-style="{'background-color': wallet.color}" class="bg"/>
<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"/>
</i>
<div>{{wallet.name}}</div>
</div>