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", "bezier-easing": "^2.0.3",
"bhttp": "1.2.1", "bhttp": "1.2.1",
"bitauth": "^0.2.1", "bitauth": "^0.2.1",
"bitcore-wallet-client": "5.3.0", "bitcore-wallet-client": "6.0.0",
"bower": "^1.7.9", "bower": "^1.7.9",
"cordova-android": "5.1.1", "cordova-android": "5.1.1",
"cordova-custom-config": "^3.0.5", "cordova-custom-config": "^3.0.5",

View file

@ -1,13 +1,8 @@
'use strict'; '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 UNUSED_ADDRESS_LIMIT = 5;
var BALANCE_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; var withBalance, cachedWallet;
$scope.isCordova = platformInfo.isCordova; $scope.isCordova = platformInfo.isCordova;
@ -55,7 +50,7 @@ angular.module('copayApp.controllers').controller('addressesController', functio
$scope.latestWithBalance = lodash.slice(withBalance, 0, BALANCE_ADDRESS_LIMIT); $scope.latestWithBalance = lodash.slice(withBalance, 0, BALANCE_ADDRESS_LIMIT);
lodash.each(withBalance, function(a) { lodash.each(withBalance, function(a) {
a.balanceStr = txFormatService.formatAmount(a.amount); a.balanceStr = txFormatService.formatAmountStr($scope.wallet.coin, a.amount);
}); });
$scope.viewAll = { $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) { walletService.getLowUtxos($scope.wallet, levels, function(err, resp) {
if (err) return; if (err) return;
if (resp.allUtxos && resp.allUtxos.length) { if (resp && resp.allUtxos && resp.allUtxos.length) {
var allSum = lodash.sum(resp.allUtxos || 0, 'satoshis'); var allSum = lodash.sum(resp.allUtxos || 0, 'satoshis');
@ -88,9 +83,9 @@ angular.module('copayApp.controllers').controller('addressesController', functio
$scope.lowWarning = resp.warning; $scope.lowWarning = resp.warning;
$scope.lowUtxosNb = resp.lowUtxos.length; $scope.lowUtxosNb = resp.lowUtxos.length;
$scope.allUtxosNb = resp.allUtxos.length; $scope.allUtxosNb = resp.allUtxos.length;
$scope.lowUtxosSum = txFormatService.formatAmountStr(lodash.sum(resp.lowUtxos || 0, 'satoshis')); $scope.lowUtxosSum = txFormatService.formatAmountStr($scope.wallet.coin, lodash.sum(resp.lowUtxos || 0, 'satoshis'));
$scope.allUtxosSum = txFormatService.formatAmountStr(allSum); $scope.allUtxosSum = txFormatService.formatAmountStr($scope.wallet.coin, allSum);
$scope.minFee = txFormatService.formatAmountStr(resp.minFee || 0); $scope.minFee = txFormatService.formatAmountStr($scope.wallet.coin, resp.minFee || 0);
$scope.minFeePer = per.toFixed(2) + '%'; $scope.minFeePer = per.toFixed(2) + '%';

View file

@ -1,6 +1,6 @@
'use strict'; '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 updateConfig = function() {
var config = configService.getSync(); var config = configService.getSync();
@ -14,6 +14,10 @@ angular.module('copayApp.controllers').controller('advancedSettingsController',
$scope.hideNextSteps = { $scope.hideNextSteps = {
value: config.hideNextSteps.enabled value: config.hideNextSteps.enabled
}; };
$scope.cashSupport = {
value: config.cashSupport.enabled
};
}; };
$scope.spendUnconfirmedChange = function() { $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() { $scope.nextStepsChange = function() {
var opts = { var opts = {
hideNextSteps: { 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.$on("$ionicView.beforeEnter", function(event, data) {
$scope.isWindowsPhoneApp = platformInfo.isCordova && platformInfo.isWP; $scope.isWindowsPhoneApp = platformInfo.isCordova && platformInfo.isWP;
updateConfig(); updateConfig();

View file

@ -9,6 +9,14 @@ angular.module('copayApp.controllers').controller('amountController', function($
var SMALL_FONT_SIZE_LIMIT = 10; var SMALL_FONT_SIZE_LIMIT = 10;
var LENGTH_EXPRESSION_LIMIT = 19; var LENGTH_EXPRESSION_LIMIT = 19;
var isNW = platformInfo.isNW; var isNW = platformInfo.isNW;
var unitIndex = 0;
var altUnitIndex = 0;
var availableUnits = [];
var fiatCode;
var fixedUnit;
$scope.isChromeApp = platformInfo.isChromeApp; $scope.isChromeApp = platformInfo.isChromeApp;
$scope.$on('$ionicView.leave', function() { $scope.$on('$ionicView.leave', function() {
@ -16,11 +24,82 @@ angular.module('copayApp.controllers').controller('amountController', function($
}); });
$scope.$on("$ionicView.beforeEnter", function(event, data) { $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... // Go to...
_id = data.stateParams.id; // Optional (BitPay Card ID or Wallet ID) _id = data.stateParams.id; // Optional (BitPay Card ID or Wallet ID)
$scope.nextStep = data.stateParams.nextStep; $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' || $scope.showMenu = $ionicHistory.backView() && ($ionicHistory.backView().stateName == 'tabs.send' ||
$ionicHistory.backView().stateName == 'tabs.bitpayCard'); $ionicHistory.backView().stateName == 'tabs.bitpayCard');
@ -28,7 +107,6 @@ angular.module('copayApp.controllers').controller('amountController', function($
$scope.toAddress = data.stateParams.toAddress; $scope.toAddress = data.stateParams.toAddress;
$scope.toName = data.stateParams.toName; $scope.toName = data.stateParams.toName;
$scope.toEmail = data.stateParams.toEmail; $scope.toEmail = data.stateParams.toEmail;
$scope.showAlternativeAmount = !!$scope.nextStep;
$scope.toColor = data.stateParams.toColor; $scope.toColor = data.stateParams.toColor;
$scope.showSendMax = false; $scope.showSendMax = false;
@ -61,14 +139,6 @@ angular.module('copayApp.controllers').controller('amountController', function($
$scope.$apply(); $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.specificAmount = $scope.specificAlternativeAmount = '';
$scope.isCordova = platformInfo.isCordova; $scope.isCordova = platformInfo.isCordova;
unitToSatoshi = config.unitToSatoshi; unitToSatoshi = config.unitToSatoshi;
@ -114,16 +184,59 @@ angular.module('copayApp.controllers').controller('amountController', function($
$scope.finish(); $scope.finish();
}; };
$scope.toggleAlternative = function() {
if ($scope.forceCurrency) return;
$scope.showAlternativeAmount = !$scope.showAlternativeAmount;
$scope.toggleAlternative = function() {
if ($scope.amount && isExpression($scope.amount)) { if ($scope.amount && isExpression($scope.amount)) {
var amount = evaluate(format($scope.amount)); var amount = evaluate(format($scope.amount));
$scope.globalResult = '= ' + processResult(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() { function checkFontSize() {
if ($scope.amount && $scope.amount.length >= SMALL_FONT_SIZE_LIMIT) $scope.smallFont = true; if ($scope.amount && $scope.amount.length >= SMALL_FONT_SIZE_LIMIT) $scope.smallFont = true;
else $scope.smallFont = false; else $scope.smallFont = false;
@ -132,7 +245,7 @@ angular.module('copayApp.controllers').controller('amountController', function($
$scope.pushDigit = function(digit) { $scope.pushDigit = function(digit) {
if ($scope.amount && $scope.amount.length >= LENGTH_EXPRESSION_LIMIT) return; if ($scope.amount && $scope.amount.length >= LENGTH_EXPRESSION_LIMIT) return;
if ($scope.amount.indexOf('.') > -1 && digit == '.') 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('..', '.'); $scope.amount = ($scope.amount + digit).replace('..', '.');
checkFontSize(); checkFontSize();
@ -169,7 +282,7 @@ angular.module('copayApp.controllers').controller('amountController', function($
}; };
$scope.resetAmount = function() { $scope.resetAmount = function() {
$scope.amount = $scope.alternativeResult = $scope.amountResult = $scope.globalResult = ''; $scope.amount = $scope.alternativeAmount = $scope.globalResult = '';
$scope.allowSend = false; $scope.allowSend = false;
checkFontSize(); checkFontSize();
}; };
@ -180,24 +293,28 @@ angular.module('copayApp.controllers').controller('amountController', function($
$scope.allowSend = lodash.isNumber(result) && +result > 0; $scope.allowSend = lodash.isNumber(result) && +result > 0;
if (lodash.isNumber(result)) { if (lodash.isNumber(result)) {
$scope.globalResult = isExpression($scope.amount) ? '= ' + processResult(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) { function processResult(val) {
if ($scope.showAlternativeAmount) if (availableUnits[unitIndex].isFiat)
return $filter('formatFiatAmount')(val); return $filter('formatFiatAmount')(val);
else else
return txFormatService.formatAmount(val.toFixed(unitDecimals) * unitToSatoshi, true); return txFormatService.formatAmount(val.toFixed(unitDecimals) * unitToSatoshi, true);
}; };
function fromFiat(val) { 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) { 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) { function evaluate(val) {
@ -212,6 +329,8 @@ angular.module('copayApp.controllers').controller('amountController', function($
}; };
function format(val) { function format(val) {
if (!val) return;
var result = val.toString(); var result = val.toString();
if (isOperator(lodash.last(val))) if (isOperator(lodash.last(val)))
@ -221,24 +340,42 @@ angular.module('copayApp.controllers').controller('amountController', function($
}; };
$scope.finish = function() { $scope.finish = function() {
var unit = availableUnits[unitIndex];
var _amount = evaluate(format($scope.amount)); var _amount = evaluate(format($scope.amount));
if ($scope.nextStep) { if ($scope.nextStep) {
var coin = unit.id;
if (unit.isFiat) {
coin = availableUnits[altUnitIndex].id;
}
$state.transitionTo($scope.nextStep, { $state.transitionTo($scope.nextStep, {
id: _id, id: _id,
amount: $scope.useSendMax ? null : _amount, amount: $scope.useSendMax ? null : _amount,
currency: $scope.showAlternativeAmount ? $scope.alternativeIsoCode : $scope.unitName, currency: unit.id.toUpperCase(),
coin: coin,
useSendMax: $scope.useSendMax useSendMax: $scope.useSendMax
}); });
} else { } 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', { $state.transitionTo('tabs.send.confirm', {
recipientType: $scope.recipientType, recipientType: $scope.recipientType,
toAmount: $scope.useSendMax ? null : (amount * unitToSatoshi).toFixed(0), toAmount: amount,
toAddress: $scope.toAddress, toAddress: $scope.toAddress,
toName: $scope.toName, toName: $scope.toName,
toEmail: $scope.toEmail, toEmail: $scope.toEmail,
toColor: $scope.toColor, toColor: $scope.toColor,
coin: unit.id,
useSendMax: $scope.useSendMax 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) { 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 amount;
var currency; var currency;
var createdTx; var createdTx;
@ -64,7 +65,7 @@ angular.module('copayApp.controllers').controller('buyAmazonController', functio
}; };
var satToFiat = function(sat, cb) { var satToFiat = function(sat, cb) {
txFormatService.toFiat(sat, $scope.currencyIsoCode, function(value) { txFormatService.toFiat(coin, sat, $scope.currencyIsoCode, function(value) {
return cb(value); return cb(value);
}); });
}; };
@ -216,7 +217,7 @@ angular.module('copayApp.controllers').controller('buyAmazonController', functio
}); });
var initialize = function(wallet) { var initialize = function(wallet) {
var parsedAmount = txFormatService.parseAmount(amount, currency); var parsedAmount = txFormatService.parseAmount(coin, amount, currency);
$scope.currencyIsoCode = parsedAmount.currency; $scope.currencyIsoCode = parsedAmount.currency;
$scope.amountUnitStr = parsedAmount.amountUnitStr; $scope.amountUnitStr = parsedAmount.amountUnitStr;
var dataSrc = { var dataSrc = {
@ -260,7 +261,7 @@ angular.module('copayApp.controllers').controller('buyAmazonController', functio
invoiceUrl: invoice.url, invoiceUrl: invoice.url,
invoiceTime: invoice.invoiceTime invoiceTime: invoice.invoiceTime
}; };
$scope.totalAmountStr = txFormatService.formatAmountStr(ctxp.amount); $scope.totalAmountStr = txFormatService.formatAmountStr(coin, ctxp.amount);
setTotalAmount(parsedAmount.amountSat, invoiceFeeSat, ctxp.fee); setTotalAmount(parsedAmount.amountSat, invoiceFeeSat, ctxp.fee);
}); });
}); });
@ -292,7 +293,8 @@ angular.module('copayApp.controllers').controller('buyAmazonController', functio
$scope.wallets = profileService.getWallets({ $scope.wallets = profileService.getWallets({
onlyComplete: true, onlyComplete: true,
network: $scope.network, network: $scope.network,
hasFunds: true hasFunds: true,
coin: coin
}); });
if (lodash.isEmpty($scope.wallets)) { if (lodash.isEmpty($scope.wallets)) {
showErrorAndBack(null, gettextCatalog.getString('No wallets available')); 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) { 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 amount;
var currency; var currency;
@ -33,46 +34,7 @@ angular.module('copayApp.controllers').controller('buyCoinbaseController', funct
} }
}; };
$scope.$on("$ionicView.beforeLeave", function(event, data) { var processPaymentInfo = function() {
$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
ongoingProcess.set('connectingCoinbase', true); ongoingProcess.set('connectingCoinbase', true);
coinbaseService.init(function(err, res) { coinbaseService.init(function(err, res) {
if (err) { if (err) {
@ -116,7 +78,33 @@ angular.module('copayApp.controllers').controller('buyCoinbaseController', funct
$scope.buyRequest(); $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() { $scope.buyRequest = function() {
@ -248,6 +236,25 @@ angular.module('copayApp.controllers').controller('buyCoinbaseController', funct
$scope.onWalletSelect = function(wallet) { $scope.onWalletSelect = function(wallet) {
$scope.wallet = 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() { $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) { 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 amount;
var currency; var currency;
@ -35,36 +36,7 @@ angular.module('copayApp.controllers').controller('buyGlideraController', functi
} }
}; };
$scope.$on("$ionicView.beforeLeave", function(event, data) { var processPaymentInfo = function() {
$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
ongoingProcess.set('connectingGlidera', true); ongoingProcess.set('connectingGlidera', true);
glideraService.init(function(err, data) { glideraService.init(function(err, data) {
if (err) { if (err) {
@ -88,6 +60,33 @@ angular.module('copayApp.controllers').controller('buyGlideraController', functi
$scope.buyInfo = buy; $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) { var ask2FaCode = function(mode, cb) {
@ -162,6 +161,15 @@ angular.module('copayApp.controllers').controller('buyGlideraController', functi
$scope.onWalletSelect = function(wallet) { $scope.onWalletSelect = function(wallet) {
$scope.wallet = 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() { $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) { 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 amount;
var currency; var currency;
var createdTx; var createdTx;
@ -64,7 +65,7 @@ angular.module('copayApp.controllers').controller('buyMercadoLibreController', f
}; };
var satToFiat = function(sat, cb) { var satToFiat = function(sat, cb) {
txFormatService.toFiat(sat, $scope.currencyIsoCode, function(value) { txFormatService.toFiat(coin, sat, $scope.currencyIsoCode, function(value) {
return cb(value); return cb(value);
}); });
}; };
@ -214,7 +215,7 @@ angular.module('copayApp.controllers').controller('buyMercadoLibreController', f
}); });
var initialize = function(wallet) { var initialize = function(wallet) {
var parsedAmount = txFormatService.parseAmount(amount, currency); var parsedAmount = txFormatService.parseAmount(coin, amount, currency);
$scope.currencyIsoCode = parsedAmount.currency; $scope.currencyIsoCode = parsedAmount.currency;
$scope.amountUnitStr = parsedAmount.amountUnitStr; $scope.amountUnitStr = parsedAmount.amountUnitStr;
var dataSrc = { var dataSrc = {
@ -258,7 +259,7 @@ angular.module('copayApp.controllers').controller('buyMercadoLibreController', f
invoiceUrl: invoice.url, invoiceUrl: invoice.url,
invoiceTime: invoice.invoiceTime invoiceTime: invoice.invoiceTime
}; };
$scope.totalAmountStr = txFormatService.formatAmountStr(ctxp.amount); $scope.totalAmountStr = txFormatService.formatAmountStr(coin, ctxp.amount);
setTotalAmount(parsedAmount.amountSat, invoiceFeeSat, ctxp.fee); setTotalAmount(parsedAmount.amountSat, invoiceFeeSat, ctxp.fee);
}); });
}); });
@ -284,7 +285,8 @@ angular.module('copayApp.controllers').controller('buyMercadoLibreController', f
$scope.network = mercadoLibreService.getNetwork(); $scope.network = mercadoLibreService.getNetwork();
$scope.wallets = profileService.getWallets({ $scope.wallets = profileService.getWallets({
onlyComplete: true, onlyComplete: true,
network: $scope.network network: $scope.network,
coin: coin
}); });
if (lodash.isEmpty($scope.wallets)) { if (lodash.isEmpty($scope.wallets)) {
showErrorAndBack(null, gettextCatalog.getString('No wallets available')); showErrorAndBack(null, gettextCatalog.getString('No wallets available'));

View file

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

View file

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

View file

@ -28,7 +28,9 @@ angular.module('copayApp.controllers').controller('customAmountController', func
$scope.address = addr; $scope.address = addr;
$scope.coin = data.stateParams.coin;
var parsedAmount = txFormatService.parseAmount( var parsedAmount = txFormatService.parseAmount(
$scope.wallet.coin,
data.stateParams.amount, data.stateParams.amount,
data.stateParams.currency); data.stateParams.currency);
@ -37,17 +39,17 @@ angular.module('copayApp.controllers').controller('customAmountController', func
var currency = parsedAmount.currency; var currency = parsedAmount.currency;
$scope.amountUnitStr = parsedAmount.amountUnitStr; $scope.amountUnitStr = parsedAmount.amountUnitStr;
if (currency != 'BTC') { if (currency != 'BTC' && currency != 'BCH') {
// Convert to BTC // Convert to BTC or BCH
var config = configService.getSync().wallet.settings; var config = configService.getSync().wallet.settings;
var amountUnit = txFormatService.satToUnit(parsedAmount.amountSat); 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.amountBtc = btcParsedAmount.amount;
$scope.altAmountStr = btcParsedAmount.amountUnitStr; $scope.altAmountStr = btcParsedAmount.amountUnitStr;
} else { } else {
$scope.amountBtc = amount; // BTC $scope.amountBtc = amount; // BTC or BCH
$scope.altAmountStr = txFormatService.formatAlternativeStr(parsedAmount.amountSat); $scope.altAmountStr = txFormatService.formatAlternativeStr($scope.wallet.coin, parsedAmount.amountSat);
} }
}); });
}); });
@ -61,12 +63,12 @@ angular.module('copayApp.controllers').controller('customAmountController', func
$scope.shareAddress = function() { $scope.shareAddress = function() {
if (!platformInfo.isCordova) return; 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); window.plugins.socialsharing.share(data, null, null, null);
} }
$scope.copyToClipboard = function() { $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 reader = new FileReader();
var defaults = configService.getDefaults(); var defaults = configService.getDefaults();
var config = configService.getSync();
var errors = bwcService.getErrors(); var errors = bwcService.getErrors();
$scope.init = function() { $scope.init = function() {
@ -15,10 +16,13 @@ angular.module('copayApp.controllers').controller('importController',
$scope.formData.bwsurl = defaults.bws.url; $scope.formData.bwsurl = defaults.bws.url;
$scope.formData.derivationPath = derivationPathHelper.default; $scope.formData.derivationPath = derivationPathHelper.default;
$scope.formData.account = 1; $scope.formData.account = 1;
$scope.formData.coin = 'btc';
$scope.importErr = false; $scope.importErr = false;
$scope.isCopay = appConfigService.name == 'copay'; $scope.isCopay = appConfigService.name == 'copay';
$scope.fromHardwareWallet = { value: false }; $scope.fromHardwareWallet = { value: false };
if (config.cashSupport.enabled) $scope.enableCash = true;
if ($stateParams.code) if ($stateParams.code)
$scope.processWalletInfo($stateParams.code); $scope.processWalletInfo($stateParams.code);
@ -203,6 +207,7 @@ angular.module('copayApp.controllers').controller('importController',
if (evt.target.readyState == FileReader.DONE) { // DONE == 2 if (evt.target.readyState == FileReader.DONE) { // DONE == 2
var opts = {}; var opts = {};
opts.bwsurl = $scope.formData.bwsurl; opts.bwsurl = $scope.formData.bwsurl;
opts.coin = $scope.formData.coin;
_importBlob(evt.target.result, opts); _importBlob(evt.target.result, opts);
} }
} }
@ -228,6 +233,7 @@ angular.module('copayApp.controllers').controller('importController',
} else { } else {
var opts = {}; var opts = {};
opts.bwsurl = $scope.formData.bwsurl; opts.bwsurl = $scope.formData.bwsurl;
opts.coin = $scope.formData.coin;
_importBlob(backupText, opts); _importBlob(backupText, opts);
} }
}; };
@ -273,6 +279,7 @@ angular.module('copayApp.controllers').controller('importController',
} }
opts.passphrase = $scope.formData.passphrase || null; opts.passphrase = $scope.formData.passphrase || null;
opts.coin = $scope.formData.coin;
if ($scope.fromHardwareWallet.value) { if ($scope.fromHardwareWallet.value) {
$log.debug('Importing seed from hardware wallet'); $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) { $scope.$on("$ionicView.beforeEnter", function(event, data) {
var defaults = configService.getDefaults(); var defaults = configService.getDefaults();
var config = configService.getSync();
$scope.formData = {}; $scope.formData = {};
$scope.formData.bwsurl = defaults.bws.url; $scope.formData.bwsurl = defaults.bws.url;
$scope.formData.derivationPath = derivationPathHelper.default; $scope.formData.derivationPath = derivationPathHelper.default;
$scope.formData.account = 1; $scope.formData.account = 1;
$scope.formData.secret = null; $scope.formData.secret = null;
$scope.formData.coin = 'btc';
if (config.cashSupport.enabled) $scope.enableCash = true;
resetPasswordFields(); resetPasswordFields();
updateSeedSourceSelect(); updateSeedSourceSelect();
}); });
@ -103,7 +106,8 @@ angular.module('copayApp.controllers').controller('joinController',
var opts = { var opts = {
secret: $scope.formData.secret, secret: $scope.formData.secret,
myName: $scope.formData.myName, myName: $scope.formData.myName,
bwsurl: $scope.formData.bwsurl bwsurl: $scope.formData.bwsurl,
coin: $scope.formData.coin
} }
var setSeed = $scope.formData.seedSource.id == 'set'; 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], { var value = lodash.find($scope.feeLevels[$scope.network], {
level: 'superEconomy' level: 'superEconomy'
}); });
return parseInt((value.feePerKB / 1000).toFixed()); return parseInt((value.feePerKb / 1000).toFixed());
}; };
var getMaxRecommended = function() { var getMaxRecommended = function() {
var value = lodash.find($scope.feeLevels[$scope.network], { var value = lodash.find($scope.feeLevels[$scope.network], {
level: 'urgent' level: 'urgent'
}); });
return parseInt((value.feePerKB / 1000).toFixed()); return parseInt((value.feePerKb / 1000).toFixed());
}; };
$scope.ok = function() { $scope.ok = function() {
@ -61,7 +61,7 @@ angular.module('copayApp.controllers').controller('feeLevelsController', functio
// If no custom fee // If no custom fee
if (value) { if (value) {
$scope.customFeePerKB = null; $scope.customFeePerKB = null;
$scope.feePerSatByte = (value.feePerKB / 1000).toFixed(); $scope.feePerSatByte = (value.feePerKb / 1000).toFixed();
$scope.avgConfirmationTime = value.nbBlocks * 10; $scope.avgConfirmationTime = value.nbBlocks * 10;
} else { } else {
$scope.avgConfirmationTime = null; $scope.avgConfirmationTime = null;
@ -102,7 +102,7 @@ angular.module('copayApp.controllers').controller('feeLevelsController', functio
$scope.feeOpts = feeService.feeOpts; $scope.feeOpts = feeService.feeOpts;
$scope.loadingFee = true; $scope.loadingFee = true;
feeService.getFeeLevels(function(err, levels) { feeService.getFeeLevels($scope.coin, function(err, levels) {
$scope.loadingFee = false; $scope.loadingFee = false;
if (err || lodash.isEmpty(levels)) { if (err || lodash.isEmpty(levels)) {
showErrorAndClose(null, err); showErrorAndClose(null, err);

View file

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

View file

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

View file

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

View file

@ -32,11 +32,12 @@ angular.module('copayApp.controllers').controller('preferencesFeeController', fu
}); });
$scope.init = function() { $scope.init = function() {
var coin = 'btc'; // TODO: only BTC in preferences
$scope.network = $scope.network || 'livenet'; $scope.network = $scope.network || 'livenet';
$scope.feeOpts = feeService.feeOpts; $scope.feeOpts = feeService.feeOpts;
$scope.currentFeeLevel = $scope.feeLevel || feeService.getCurrentFeeLevel(); $scope.currentFeeLevel = $scope.feeLevel || feeService.getCurrentFeeLevel();
$scope.loadingFee = true; $scope.loadingFee = true;
feeService.getFeeLevels(function(err, levels) { feeService.getFeeLevels(coin, function(err, levels) {
$scope.loadingFee = false; $scope.loadingFee = false;
if (err) { if (err) {
//Error is already formatted //Error is already formatted
@ -66,7 +67,7 @@ angular.module('copayApp.controllers').controller('preferencesFeeController', fu
return; return;
} }
$scope.feePerSatByte = (value.feePerKB / 1000).toFixed(); $scope.feePerSatByte = (value.feePerKb / 1000).toFixed();
$scope.avgConfirmationTime = value.nbBlocks * 10; $scope.avgConfirmationTime = value.nbBlocks * 10;
$scope.invalidCustomFeeEntered = false; $scope.invalidCustomFeeEntered = false;
setMinWarning(); setMinWarning();
@ -97,7 +98,7 @@ angular.module('copayApp.controllers').controller('preferencesFeeController', fu
var value = lodash.find($scope.feeLevels[$scope.network], { var value = lodash.find($scope.feeLevels[$scope.network], {
level: 'superEconomy' level: 'superEconomy'
}); });
return parseInt((value.feePerKB / 1000).toFixed()); return parseInt((value.feePerKb / 1000).toFixed());
}; };
var setMinWarning = function() { 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) { 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 amount;
var currency; var currency;
@ -34,6 +35,51 @@ angular.module('copayApp.controllers').controller('sellCoinbaseController', func
}, onSendStatusChange); }, 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) { var checkTransaction = lodash.throttle(function(count, txp) {
$log.warn('Check if transaction has been received by Coinbase. Try ' + count + '/5'); $log.warn('Check if transaction has been received by Coinbase. Try ' + count + '/5');
// TX amount in BTC // TX amount in BTC
@ -125,14 +171,9 @@ angular.module('copayApp.controllers').controller('sellCoinbaseController', func
}); });
$scope.$on("$ionicView.beforeEnter", function(event, data) { $scope.$on("$ionicView.beforeEnter", function(event, data) {
$scope.isFiat = data.stateParams.currency != 'bits' && data.stateParams.currency != 'BTC' ? true : false; $scope.isFiat = data.stateParams.currency != 'BTC' ? true : false;
var parsedAmount = txFormatService.parseAmount( amount = data.stateParams.amount;
data.stateParams.amount, currency = data.stateParams.currency;
data.stateParams.currency);
amount = parsedAmount.amount;
currency = parsedAmount.currency;
$scope.amountUnitStr = parsedAmount.amountUnitStr;
$scope.priceSensitivity = coinbaseService.priceSensitivity; $scope.priceSensitivity = coinbaseService.priceSensitivity;
$scope.selectedPriceSensitivity = { data: coinbaseService.selectedPriceSensitivity }; $scope.selectedPriceSensitivity = { data: coinbaseService.selectedPriceSensitivity };
@ -143,57 +184,14 @@ angular.module('copayApp.controllers').controller('sellCoinbaseController', func
onlyComplete: true, onlyComplete: true,
network: $scope.network, network: $scope.network,
hasFunds: true, hasFunds: true,
minAmount: parsedAmount.amountSat coin: coin
}); });
if (lodash.isEmpty($scope.wallets)) { if (lodash.isEmpty($scope.wallets)) {
showErrorAndBack('Insufficient funds'); showErrorAndBack('Insufficient funds');
return; return;
} }
$scope.wallet = $scope.wallets[0]; // Default first wallet $scope.onWalletSelect($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.sellRequest = function() { $scope.sellRequest = function() {
@ -306,6 +304,15 @@ angular.module('copayApp.controllers').controller('sellCoinbaseController', func
$scope.onWalletSelect = function(wallet) { $scope.onWalletSelect = function(wallet) {
$scope.wallet = 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() { $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) { 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 amount;
var currency; var currency;
@ -35,39 +36,7 @@ angular.module('copayApp.controllers').controller('sellGlideraController', funct
} }
}; };
$scope.$on("$ionicView.beforeLeave", function(event, data) { var processPaymentInfo = function() {
$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
ongoingProcess.set('connectingGlidera', true); ongoingProcess.set('connectingGlidera', true);
glideraService.init(function(err, data) { glideraService.init(function(err, data) {
if (err) { if (err) {
@ -91,6 +60,35 @@ angular.module('copayApp.controllers').controller('sellGlideraController', funct
$scope.sellInfo = sell; $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) { var ask2FaCode = function(mode, cb) {
@ -231,6 +229,15 @@ angular.module('copayApp.controllers').controller('sellGlideraController', funct
$scope.onWalletSelect = function(wallet) { $scope.onWalletSelect = function(wallet) {
$scope.wallet = 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() { $scope.goBackHome = function() {

View file

@ -8,7 +8,8 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
$scope.requestSpecificAmount = function() { $scope.requestSpecificAmount = function() {
$state.go('tabs.paymentRequest.amount', { $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, color: v.color,
name: v.name, name: v.name,
recipientType: 'wallet', recipientType: 'wallet',
coin: v.coin,
getAddress: function(cb) { getAddress: function(cb) {
walletService.getAddress(v, false, cb); walletService.getAddress(v, false, cb);
}, },
@ -186,7 +187,8 @@ angular.module('copayApp.controllers').controller('tabSendController', function(
toAddress: addr, toAddress: addr,
toName: item.name, toName: item.name,
toEmail: item.email, 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(); $scope.buyAndSellServices = buyAndSellService.getLinked();
configService.whenAvailable(function(config) { configService.whenAvailable(function(config) {
$scope.unitName = config.wallet.settings.unitName;
$scope.selectedAlternative = { $scope.selectedAlternative = {
name: config.wallet.settings.alternativeName, name: config.wallet.settings.alternativeName,
isoCode: config.wallet.settings.alternativeIsoCode 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) { 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; $scope.isCordova = platformInfo.isCordova;
var coin = 'btc';
var cardId; var cardId;
var useSendMax; var useSendMax;
var amount; var amount;
@ -36,7 +37,7 @@ angular.module('copayApp.controllers').controller('topUpController', function($s
}; };
var satToFiat = function(sat, cb) { var satToFiat = function(sat, cb) {
txFormatService.toFiat(sat, $scope.currencyIsoCode, function(value) { txFormatService.toFiat(coin, sat, $scope.currencyIsoCode, function(value) {
return cb(value); return cb(value);
}); });
}; };
@ -218,7 +219,7 @@ angular.module('copayApp.controllers').controller('topUpController', function($s
// Save TX in memory // Save TX in memory
createdTx = ctxp; createdTx = ctxp;
$scope.totalAmountStr = txFormatService.formatAmountStr(ctxp.amount); $scope.totalAmountStr = txFormatService.formatAmountStr(coin, ctxp.amount);
setTotalAmount(parsedAmount.amountSat, invoiceFeeSat, ctxp.fee); setTotalAmount(parsedAmount.amountSat, invoiceFeeSat, ctxp.fee);
@ -256,7 +257,8 @@ angular.module('copayApp.controllers').controller('topUpController', function($s
$scope.wallets = profileService.getWallets({ $scope.wallets = profileService.getWallets({
onlyComplete: true, onlyComplete: true,
network: bitpayService.getEnvironment().network, network: bitpayService.getEnvironment().network,
hasFunds: true hasFunds: true,
coin: coin
}); });
if (lodash.isEmpty($scope.wallets)) { if (lodash.isEmpty($scope.wallets)) {
@ -319,7 +321,7 @@ angular.module('copayApp.controllers').controller('topUpController', function($s
}); });
return; return;
} }
var parsedAmount = txFormatService.parseAmount(a, c); var parsedAmount = txFormatService.parseAmount(coin, a, c);
initializeTopUp(wallet, parsedAmount); initializeTopUp(wallet, parsedAmount);
}); });
}; };

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -61,7 +61,10 @@ angular.module('copayApp.services').factory('configService', function(storageSer
bannedUntil: null, bannedUntil: null,
}, },
// External services cashSupport: {
enabled: false,
},
recentTransactions: { recentTransactions: {
enabled: true, enabled: true,
}, },
@ -133,6 +136,11 @@ angular.module('copayApp.services').factory('configService', function(storageSer
configCache.hideNextSteps = defaultConfig.hideNextSteps; configCache.hideNextSteps = defaultConfig.hideNextSteps;
} }
if (!configCache.cashSupport) {
configCache.cashSupport = defaultConfig.cashSupport;
}
if (!configCache.recentTransactions) { if (!configCache.recentTransactions) {
configCache.recentTransactions = defaultConfig.recentTransactions; configCache.recentTransactions = defaultConfig.recentTransactions;
} }
@ -143,6 +151,14 @@ angular.module('copayApp.services').factory('configService', function(storageSer
configCache.bitpayAccount = defaultConfig.bitpayAccount; 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 { } else {
configCache = lodash.clone(defaultConfig); 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(); if (feeLevel == 'custom') return cb();
network = network || 'livenet'; network = network || 'livenet';
root.getFeeLevels(function(err, levels, fromCache) { root.getFeeLevels(coin, function(err, levels, fromCache) {
if (err) return cb(err); if (err) return cb(err);
var feeLevelRate = lodash.find(levels[network], { var feeLevelRate = lodash.find(levels[network], {
level: feeLevel level: feeLevel
}); });
if (!feeLevelRate || !feeLevelRate.feePerKB) { if (!feeLevelRate || !feeLevelRate.feePerKb) {
return cb({ return cb({
message: gettextCatalog.getString("Could not get dynamic fee for level: {{feeLevel}}", { message: gettextCatalog.getString("Could not get dynamic fee for level: {{feeLevel}}", {
feeLevel: 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); return cb(null, feeRate);
}); });
}; };
root.getCurrentFeeRate = function(network, cb) { root.getCurrentFeeRate = function(coin, network, cb) {
return root.getFeeRate(network, root.getCurrentFeeLevel(), 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) { if (cache.updateTs > Date.now() - CACHE_TIME_TS * 1000) {
return cb(null, cache.data, true); return cb(null, cache.data, true);
} }
var walletClient = bwcService.getClient(); var walletClient = bwcService.getClient();
var unitName = configService.getSync().wallet.settings.unitName;
walletClient.getFeeLevels('livenet', function(errLivenet, levelsLivenet) { walletClient.getFeeLevels(coin, 'livenet', function(errLivenet, levelsLivenet) {
walletClient.getFeeLevels('testnet', function(errTestnet, levelsTestnet) { walletClient.getFeeLevels('btc', 'testnet', function(errTestnet, levelsTestnet) {
if (errLivenet || errTestnet) { if (errLivenet || errTestnet) {
return cb(gettextCatalog.getString('Could not get dynamic fee')); 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; return true;
} }
function goSend(addr, amount, message) { function goSend(addr, amount, message, coin) {
$state.go('tabs.send', {}, { $state.go('tabs.send', {}, {
'reload': true, 'reload': true,
'notify': $state.current.name == 'tabs.send' ? false : 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', { $state.transitionTo('tabs.send.confirm', {
toAmount: amount, toAmount: amount,
toAddress: addr, toAddress: addr,
description: message description: message,
coin: coin
}); });
} else { } else {
$state.transitionTo('tabs.send.amount', { $state.transitionTo('tabs.send.amount', {
toAddress: addr toAddress: addr,
coin: coin
}); });
} }
}, 100); }, 100);
@ -90,16 +92,17 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
var message = parsed.message; var message = parsed.message;
var amount = parsed.amount ? parsed.amount : ''; var amount = parsed.amount ? parsed.amount : '';
var coin = parsed.extras && parsed.extras.coin ? parsed.extras.coin : '';
if (parsed.r) { if (parsed.r) {
payproService.getPayProDetails(parsed.r, function(err, details) { payproService.getPayProDetails(parsed.r, function(err, details) {
if (err) { 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 popupService.showAlert(gettextCatalog.getString('Error'), err);
} else handlePayPro(details); } else handlePayPro(details);
}); });
} else { } else {
goSend(addr, amount, message); goSend(addr, amount, message, coin);
} }
return true; return true;

View file

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

View file

@ -25,9 +25,10 @@ var RateService = function(opts) {
self._isAvailable = false; self._isAvailable = false;
self._rates = {}; self._rates = {};
self._alternatives = []; self._alternatives = [];
self._ratesBCH = {};
self._queued = []; self._queued = [];
self._fetchCurrencies(); self.updateRates();
}; };
@ -39,14 +40,20 @@ RateService.singleton = function(opts) {
return _instance; return _instance;
}; };
RateService.prototype._fetchCurrencies = function() { RateService.prototype.updateRates = function() {
var self = this; var self = this;
var backoffSeconds = 5; var backoffSeconds = 5;
var updateFrequencySeconds = 5 * 60; var updateFrequencySeconds = 5 * 60;
var rateServiceUrl = 'https://bitpay.com/api/rates'; 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'); //log.info('Fetching exchange rates');
self.httprequest.get(rateServiceUrl).success(function(res) { self.httprequest.get(rateServiceUrl).success(function(res) {
self.lodash.each(res, function(currency) { self.lodash.each(res, function(currency) {
@ -57,26 +64,63 @@ RateService.prototype._fetchCurrencies = function() {
rate: currency.rate 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._isAvailable = true;
self.lodash.each(self._queued, function(callback) { self.lodash.each(self._queued, function(callback) {
setTimeout(callback, 1); setTimeout(callback, 1);
}); });
setTimeout(retrieve, updateFrequencySeconds * 1000); setTimeout( self.updateRates , updateFrequencySeconds * 1000);
}).error(function(err) { })
//log.debug('Error fetching exchange rates', err); })
setTimeout(function() {
backoffSeconds *= 1.5;
retrieve();
}, backoffSeconds * 1000);
return;
});
}; };
retrieve(); RateService.prototype.getRate = function(code, chain) {
}; if (chain == 'bch')
return this._ratesBCH[code];
RateService.prototype.getRate = function(code) { else
return this._rates[code]; return this._rates[code];
}; };
@ -90,25 +134,25 @@ RateService.prototype.isAvailable = function() {
RateService.prototype.whenAvailable = function(callback) { RateService.prototype.whenAvailable = function(callback) {
if (this.isAvailable()) { if (this.isAvailable()) {
setTimeout(callback, 1); setTimeout(callback, 10);
} else { } else {
this._queued.push(callback); this._queued.push(callback);
} }
}; };
RateService.prototype.toFiat = function(satoshis, code) { RateService.prototype.toFiat = function(satoshis, code, chain) {
if (!this.isAvailable()) { if (!this.isAvailable()) {
return null; 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()) { if (!this.isAvailable()) {
return null; 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) { RateService.prototype.listAlternatives = function(sort) {

View file

@ -10,7 +10,7 @@ angular.module('copayApp.services').service('sendMaxService', function(feeServic
* *
*/ */
this.getInfo = function(wallet, cb) { 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); if (err) return cb(err);
var config = configService.getSync().wallet; var config = configService.getSync().wallet;

View file

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

View file

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

View file

@ -139,6 +139,19 @@
} }
} }
.amount { .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 { &__editable {
&--minimize { &--minimize {
font-size: 22px; font-size: 22px;
@ -187,7 +200,7 @@
&__result { &__result {
color: $v-light-gray; color: $v-light-gray;
font-size: .9em; font-size: .9em;
margin-bottom: -.9em; //margin-bottom: -.9em; TODO matias
line-height: 1; line-height: 1;
@media(max-height: 480px) { @media(max-height: 480px) {
margin-bottom: 0; margin-bottom: 0;
@ -196,7 +209,6 @@
&__result-equiv { &__result-equiv {
color: $v-mid-gray; color: $v-mid-gray;
font-size: 1.2em; font-size: 1.2em;
margin-top: 2rem;
@media(max-height: 480px) { @media(max-height: 480px) {
margin-top: 0; margin-top: 0;
font-size: 16px; font-size: 16px;

View file

@ -215,6 +215,11 @@
&__button-balance { &__button-balance {
background-color: transparent; background-color: transparent;
border: 1px solid rgba(255,255,255,0.25); border: 1px solid rgba(255,255,255,0.25);
margin-top: 10px;
i.icon {
margin-right: 7px;
vertical-align: middle;
}
} }
&__error { &__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> <ion-content>
<div class="settings-list list"> <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()"> <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> <span class="toggle-label" translate>Use Unconfirmed Funds</span>
</ion-toggle> </ion-toggle>

View file

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

View file

@ -29,7 +29,7 @@
<div class="label" translate>From</div> <div class="label" translate>From</div>
<div class="wallet"> <div class="wallet">
<i class="icon big-icon-svg"> <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> </i>
{{wallet ? wallet.name : '...'}} {{wallet ? wallet.name : '...'}}
</div> </div>

View file

@ -38,7 +38,7 @@
<div class="label">Receive in</div> <div class="label">Receive in</div>
<div class="wallet"> <div class="wallet">
<i class="icon big-icon-svg"> <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> </i>
{{wallet ? wallet.name : '...'}} {{wallet ? wallet.name : '...'}}
</div> </div>

View file

@ -30,7 +30,7 @@
<div class="label">Receive in</div> <div class="label">Receive in</div>
<div class="wallet"> <div class="wallet">
<i class="icon big-icon-svg"> <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> </i>
{{wallet ? wallet.name : '...'}} {{wallet ? wallet.name : '...'}}
</div> </div>

View file

@ -28,7 +28,7 @@
<div class="label" translate>From</div> <div class="label" translate>From</div>
<div class="wallet"> <div class="wallet">
<i class="icon big-icon-svg"> <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> </i>
{{wallet ? wallet.name : '...'}} {{wallet ? wallet.name : '...'}}
</div> </div>

View file

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

View file

@ -21,7 +21,7 @@
<ion-content scroll="false"> <ion-content scroll="false">
<div class="address" ng-if="address && amountBtc"> <div class="address" ng-if="address && amountBtc">
<div class="qr-code" copy-to-clipboard="copyToClipboard()"> <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>
<div class="info"> <div class="info">
<div class="item single-line" copy-to-clipboard="address"> <div class="item single-line" copy-to-clipboard="address">
@ -39,7 +39,7 @@
<div class="item single-line"> <div class="item single-line">
<div class="wallet"> <div class="wallet">
<i class="icon big-icon-svg"> <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> </i>
{{wallet.name}} {{wallet.name}}
</div> </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"> <div class="wallet-item">
<i class="icon big-icon-svg circle"> <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> </i>
<div class="name"> <div class="name">
{{wallet.name || wallet.id}} {{wallet.name || wallet.id}}

View file

@ -7,7 +7,7 @@
ng-click="selectWallet(w)" ng-click="selectWallet(w)"
> >
<i class="icon big-icon-svg"> <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> </i>
<div class="wallet-inner"> <div class="wallet-inner">
<div class="wallet-details"> <div class="wallet-details">

View file

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

View file

@ -74,7 +74,7 @@
<span class="label" translate>From</span> <span class="label" translate>From</span>
<div class="wallet"> <div class="wallet">
<i class="icon big-icon-svg"> <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> </i>
<div>{{wallet.name}}</div> <div>{{wallet.name}}</div>
</div> </div>

View file

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

View file

@ -30,7 +30,7 @@
<div class="label">From</div> <div class="label">From</div>
<div class="wallet"> <div class="wallet">
<i class="icon big-icon-svg"> <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> </i>
{{wallet ? wallet.name : '...'}} {{wallet ? wallet.name : '...'}}
</div> </div>

View file

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

View file

@ -29,6 +29,8 @@
ng-blur="formFocus(false)"> ng-blur="formFocus(false)">
</label> </label>
<div ng-include="'views/includes/cash.html'" ng-if="enableCash"></div>
<label class="item item-input item-select"> <label class="item item-input item-select">
<div class="input-label" translate> <div class="input-label" translate>
Total number of copayers 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" class="item item-sub item-icon-left item-big-icon-left item-icon-right wallet"
ng-click="openWallet(wallet)"> ng-click="openWallet(wallet)">
<i class="icon big-icon-svg"> <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> </i>
<span> <span>
{{wallet.name || wallet.id}} {{wallet.name || wallet.id}}

View file

@ -21,6 +21,8 @@
ng-model="formData.password"> ng-model="formData.password">
</label> </label>
<div ng-include="'views/includes/cash.html'" ng-if="enableCash"></div>
<div class="item item-divider"></div> <div class="item item-divider"></div>
<a class="item" ng-click="showAdvChange()"> <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> <qr-scanner class="qr-icon size-24" on-scan="processWalletInfo(data)"></qr-scanner>
</div> </div>
</div> </div>
<div ng-include="'views/includes/cash.html'" ng-if="enableCash"></div>
<div class="item item-divider"></div> <div class="item item-divider"></div>
<a class="item" ng-click="showAdvChange()"> <a class="item" ng-click="showAdvChange()">

View file

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

View file

@ -69,7 +69,7 @@
<div class="list"> <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)"> <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'"> <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> </i>
{{item.name}} {{item.name}}
<i class="icon bp-arrow-right"></i> <i class="icon bp-arrow-right"></i>

View file

@ -56,16 +56,6 @@
</span> </span>
<i class="icon bp-arrow-right"></i> <i class="icon bp-arrow-right"></i>
</a> </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"> <a class="item has-setting-value item-icon-left item-icon-right" ui-sref="tabs.altCurrency">
<i class="icon big-icon-svg"> <i class="icon big-icon-svg">
@ -105,7 +95,7 @@
ui-sref="tabs.preferences({'walletId': item.id})" ui-sref="tabs.preferences({'walletId': item.id})"
ng-repeat="item in wallets track by $index"> ng-repeat="item in wallets track by $index">
<i class="icon big-icon-svg circle"> <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> </i>
<span> <span>
{{item.name || item.id}} {{item.name || item.id}}

View file

@ -31,10 +31,10 @@
<div class="info"> <div class="info">
<div class="item item-icon-right" ng-click="showWalletSelector()"> <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"> <div class="wallet">
<i class="icon big-icon-svg"> <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> </i>
{{wallet ? wallet.name : '...'}} {{wallet ? wallet.name : '...'}}
</div> </div>

View file

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