Compare commits

..

No commits in common. "master" and "wallet/task/590" have entirely different histories.

24 changed files with 1134 additions and 1340 deletions

14
.vscode/launch.json vendored
View file

@ -1,14 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceFolder}/www/index.html"
}
]
}

View file

@ -65,9 +65,6 @@ module.exports = function(grunt) {
run_android: { run_android: {
command: 'cordova run android --device', command: 'cordova run android --device',
}, },
run_android_emulator: {
command: 'cordova run android --emulator',
},
sign_android: { sign_android: {
// When the build log outputs "Built the following apk(s):", it seems to need the filename to start with "android-release". // When the build log outputs "Built the following apk(s):", it seems to need the filename to start with "android-release".
// It looks like it simply lists all apk files starting with "android-release" // It looks like it simply lists all apk files starting with "android-release"
@ -366,14 +363,13 @@ module.exports = function(grunt) {
grunt.registerTask('build-mobile-release', ['build-ios-release', 'build-android-release']); grunt.registerTask('build-mobile-release', ['build-ios-release', 'build-android-release']);
// Build ios // Build ios
grunt.registerTask('start-ios', ['default', 'exec:build_ios_debug', 'exec:xcode']); grunt.registerTask('start-ios', ['exec:build_ios_debug', 'exec:xcode']);
grunt.registerTask('build-ios-debug', ['default', 'exec:build_ios_debug']); grunt.registerTask('build-ios-debug', ['exec:build_ios_debug']);
grunt.registerTask('build-ios-release', ['prod', 'exec:build_ios_release']); grunt.registerTask('build-ios-release', ['prod', 'exec:build_ios_release']);
// Build android // Build android
grunt.registerTask('start-android', ['build-android-debug', 'exec:run_android']); grunt.registerTask('start-android', ['build-android-debug', 'exec:run_android']);
grunt.registerTask('build-android-debug', ['default', 'exec:build_android_debug']); grunt.registerTask('build-android-debug', ['exec:build_android_debug']);
grunt.registerTask('start-android-emulator', ['build-android-debug', 'exec:run_android_emulator']);
grunt.registerTask('build-android-release', ['prod', 'exec:build_android_release', 'sign-android']); grunt.registerTask('build-android-release', ['prod', 'exec:build_android_release', 'sign-android']);
grunt.registerTask('sign-android', ['exec:sign_android']); grunt.registerTask('sign-android', ['exec:sign_android']);

View file

@ -1,24 +1,3 @@
This is a fork of the Bitcoin.com wallet to add additional features.
Features included:
- Zero fee transactions (only works for Bitcoin Cash). You will be asked for, if you want to send a transaction as zero fee on the confirmation page.
## Zero fee transactions:
Because most network nodes on the Bitcoin Cash network don't relay zero fee txs, you will experience some strange issues, but don't worry: for me personally the Bitcoin.com pool has included all my zero fee transactions, but please beware that the receiver probably won't see your tx before it has been confirmed and please do also keep in mind, that the transactions coming after it won't confirm or be seen before the zero fee one has been confirmed.
If you do already have a Bitcoin.com wallet, you need to create a new one to use this feature or change the wallet URL to: https://bws.freepages.dk/bws/api
## Disclaimer
Please beware this is my personal experimental project. You are more than welcome to play with it, but I don't take any responsibility of loss of funds due to errors in the code, so please make sure you made a backup before running this software.
## Builds
You can build the software yourself using the instructions below or use prebuilt binaries which can be found here (currently Windows and Linux only): https://ipfs.io/ipfs/QmR1DaS3QsDS48SzAWKUWFfmtMfJc4tgMtkSk3JFmuzewe
##
The Bitcoin.com wallet is a fork of the Copay Wallet (https://github.com/bitpay/copay). The Bitcoin.com wallet is a fork of the Copay Wallet (https://github.com/bitpay/copay).
The Bitcoin.com wallet is a secure bitcoin wallet platform for both desktop and mobile devices. It uses [Bitcore Wallet Service](https://github.com/Bitcoin-com/bitcore-wallet-service) (our fork of the [Bitpay Bitcore Wallet Service](https://github.com/bitpay/bitcore-wallet-service)) (BWS) for peer synchronization and network interfacing. The Bitcoin.com wallet is a secure bitcoin wallet platform for both desktop and mobile devices. It uses [Bitcore Wallet Service](https://github.com/Bitcoin-com/bitcore-wallet-service) (our fork of the [Bitpay Bitcore Wallet Service](https://github.com/bitpay/bitcore-wallet-service)) (BWS) for peer synchronization and network interfacing.

View file

@ -24,9 +24,9 @@
"windowsAppId": "804636ee-b017-4cad-8719-e58ac97ffa5c", "windowsAppId": "804636ee-b017-4cad-8719-e58ac97ffa5c",
"pushSenderId": "1036948132229", "pushSenderId": "1036948132229",
"description": "A Secure Bitcoin Wallet", "description": "A Secure Bitcoin Wallet",
"version": "5.1.3", "version": "5.0.2",
"fullVersion": "5.1-rc2", "fullVersion": "5.0-rc3",
"androidVersion": "501003", "androidVersion": "500200",
"_extraCSS": "", "_extraCSS": "",
"_enabledExtensions": { "_enabledExtensions": {
"coinbase": false, "coinbase": false,

View file

@ -126,7 +126,6 @@
"start": "npm run build:www && ionic serve --nolivereload --nogulp -s --address 0.0.0.0", "start": "npm run build:www && ionic serve --nolivereload --nogulp -s --address 0.0.0.0",
"start:chrome": "npm run build:www && ionic serve --nolivereload --nogulp -s --address 0.0.0.0 --browser \"google chrome\"", "start:chrome": "npm run build:www && ionic serve --nolivereload --nogulp -s --address 0.0.0.0 --browser \"google chrome\"",
"start:android": "grunt start-android", "start:android": "grunt start-android",
"start:android-emulator": "grunt start-android",
"start:android-log": "grunt start-android && npm run log:android", "start:android-log": "grunt start-android && npm run log:android",
"start:ios": "grunt start-ios", "start:ios": "grunt start-ios",
"start:windows": "npm run build:www && npm run build:windows", "start:windows": "npm run build:www && npm run build:windows",

View file

@ -518,7 +518,6 @@ angular.module('copayApp.controllers').controller('confirmController', function(
msg += '\n' + warningMsg; msg += '\n' + warningMsg;
popupService.showAlert(null, msg, function() {}); popupService.showAlert(null, msg, function() {});
}; };
$scope.onWalletSelect = function(wallet) { $scope.onWalletSelect = function(wallet) {

View file

@ -1,7 +1,5 @@
'use strict'; 'use strict';
(function () {
angular angular
.module('copayApp.controllers') .module('copayApp.controllers')
.controller('reviewController', reviewController); .controller('reviewController', reviewController);
@ -398,12 +396,12 @@ angular
var balanceCryptoAmount = ''; var balanceCryptoAmount = '';
var balanceCryptoCurrencyCode = ''; var balanceCryptoCurrencyCode = '';
var balanceFiatAmount = ''; var balanceFiatAmount = '';
var balanceFiatCurrency = ''; var balanceFiatCurrency = ''
var displayAmount = ''; var displayAmount = '';
var displayCurrency = ''; var displayCurrency = '';
var walletStatus = null; var walletStatus = null;
if (wallet.status && wallet.status.isValid) { if (wallet.status.isValid) {
walletStatus = wallet.status; walletStatus = wallet.status;
} else if (wallet.cachedStatus.isValid) { } else if (wallet.cachedStatus.isValid) {
walletStatus = wallet.cachedStatus; walletStatus = wallet.cachedStatus;
@ -718,12 +716,6 @@ angular
if (tx.paypro) if (tx.paypro)
startExpirationTimer(tx.paypro.expires); startExpirationTimer(tx.paypro.expires);
popupService.showConfirm(null, 'Do you want this transaction to be sent without a fee?', 'Yes', 'No', function(ok) {
if(ok){
tx.feeRate = 0;
// tx.feeLevel = 'free';
usingCustomFee = true;
}
updateTx(tx, vm.originWallet, { updateTx(tx, vm.originWallet, {
dryRun: true dryRun: true
}, function(err) { }, function(err) {
@ -732,9 +724,6 @@ angular
}, 10); }, 10);
}); });
});
// setWalletSelector(tx.coin, tx.network, tx.amount, function(err) { // setWalletSelector(tx.coin, tx.network, tx.amount, function(err) {
// if (err) { // if (err) {
@ -787,7 +776,6 @@ angular
msg += '\n' + warningMsg; msg += '\n' + warningMsg;
popupService.showAlert(null, msg, function() {}); popupService.showAlert(null, msg, function() {});
//popupService.showConfirm(null, msg, null, null, function() {});
}; };
function statusChangeHandler(processName, showName, isOn) { function statusChangeHandler(processName, showName, isOn) {
@ -865,10 +853,6 @@ angular
} }
var msg; var msg;
// if (tx.feeLevel == 'free'){
// tx.feeRate = 0;
// }
// else
if (usingCustomFee) { if (usingCustomFee) {
msg = gettextCatalog.getString('Custom'); msg = gettextCatalog.getString('Custom');
tx.feeLevelName = msg; tx.feeLevelName = msg;
@ -879,10 +863,8 @@ angular
} else { } else {
tx.feeLevelName = feeService.feeOpts[tx.feeLevel]; tx.feeLevelName = feeService.feeOpts[tx.feeLevel];
tx.feeRate = feeRate; tx.feeRate = feeRate;
} }
getSendMaxInfo(lodash.clone(tx), wallet, function(err, sendMaxInfo) { getSendMaxInfo(lodash.clone(tx), wallet, function(err, sendMaxInfo) {
if (err) { if (err) {
ongoingProcess.set('calculatingFee', false); ongoingProcess.set('calculatingFee', false);
@ -970,5 +952,5 @@ angular
}); });
}); });
} }
} }
})();

View file

@ -1,6 +1,6 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('servicesController', function(externalLinkService, $scope, $ionicScrollDelegate, $timeout, servicesService, configService) { angular.module('copayApp.controllers').controller('servicesController', function($scope, $ionicScrollDelegate, $timeout, servicesService, configService) {
$scope.hide = false; $scope.hide = false;
configService.whenAvailable(function(config) { configService.whenAvailable(function(config) {
@ -20,8 +20,4 @@ angular.module('copayApp.controllers').controller('servicesController', function
}, 10); }, 10);
}; };
$scope.open = function(url) {
externalLinkService.open(url, false);
}
}); });

View file

@ -10,7 +10,7 @@ angular.module('copayApp.controllers').controller('shapeshiftController', functi
walletsBtc = profileService.getWallets({coin: 'btc'}); walletsBtc = profileService.getWallets({coin: 'btc'});
walletsBch = profileService.getWallets({coin: 'bch'}); walletsBch = profileService.getWallets({coin: 'bch'});
$scope.fromWallets = lodash.filter(walletsBtc.concat(walletsBch), function(w) { $scope.fromWallets = lodash.filter(walletsBtc.concat(walletsBch), function(w) {
return (w.status && w.status.balance && w.status.balance.availableAmount > 0); return w.status.balance.availableAmount > 0;
}); });
$scope.singleFromWallet = $scope.fromWallets.length === 1; $scope.singleFromWallet = $scope.fromWallets.length === 1;

View file

@ -2,7 +2,6 @@
angular.module('copayApp.controllers').controller('tabReceiveController', function($rootScope, $scope, $timeout, $log, $ionicModal, $state, $ionicHistory, $ionicPopover, storageService, platformInfo, walletService, profileService, configService, lodash, gettextCatalog, popupService, bwcError, bitcoinCashJsService, $ionicNavBarDelegate, sendFlowService, txFormatService, soundService, clipboardService) { angular.module('copayApp.controllers').controller('tabReceiveController', function($rootScope, $scope, $timeout, $log, $ionicModal, $state, $ionicHistory, $ionicPopover, storageService, platformInfo, walletService, profileService, configService, lodash, gettextCatalog, popupService, bwcError, bitcoinCashJsService, $ionicNavBarDelegate, sendFlowService, txFormatService, soundService, clipboardService) {
var CLOSE_NORMAL = 1000;
var listeners = []; var listeners = [];
$scope.bchAddressType = { type: 'cashaddr' }; $scope.bchAddressType = { type: 'cashaddr' };
var bchAddresses = {}; var bchAddresses = {};
@ -11,11 +10,12 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
$scope.isCordova = platformInfo.isCordova; $scope.isCordova = platformInfo.isCordova;
$scope.isNW = platformInfo.isNW; $scope.isNW = platformInfo.isNW;
var currentAddressSocket = null; var currentAddressSocket = {};
var paymentSubscriptionObj = { op:'addr_sub' }; var paymentSubscriptionObj = { op:"addr_sub" }
var config;
$scope.displayBalanceAsFiat = true; $scope.displayBalanceAsFiat = true;
$scope.$on('$ionicView.beforeLeave', onBeforeLeave);
$scope.requestSpecificAmount = function() { $scope.requestSpecificAmount = function() {
sendFlowService.start({ sendFlowService.start({
@ -24,50 +24,6 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
}); });
}; };
function connectSocket() {
// Close existing socket if not connected with current address
if (currentAddressSocket) {
currentAddressSocket.close([CLOSE_NORMAL]);
}
if ($scope.wallet.coin === 'bch') {
// listen to bch address
currentAddressSocket = new WebSocket('wss://ws.blockchain.info/bch/inv');
paymentSubscriptionObj.addr = $scope.addrBchLegacy;
} else {
// listen to btc address
currentAddressSocket = new WebSocket('wss://ws.blockchain.info/inv');
paymentSubscriptionObj.addr = $scope.addr;
}
// create subscription to address
var msg = JSON.stringify(paymentSubscriptionObj);
currentAddressSocket.onopen = function (event) {
currentAddressSocket.send(msg);
};
// listen for response
currentAddressSocket.onmessage = function (event) {
//console.log("message received:" + event.data);
receivedPayment(event.data);
};
currentAddressSocket.onclose = function(event) {
if (event.code !== CLOSE_NORMAL) {
$log.debug('Socket was closed abnormally. Reconnect will be attempted in 1 second.');
$timeout(function() {
connectSocket();
}, 1000);
}
};
currentAddressSocket.onerror = function(err) {
console.error('Socket encountered error: ', err, 'Closing socket');
currentAddressSocket.close();
};
}
$scope.setAddress = function(newAddr, copyAddress) { $scope.setAddress = function(newAddr, copyAddress) {
$scope.addr = null; $scope.addr = null;
if (!$scope.wallet || $scope.generatingAddress || !$scope.wallet.isComplete()) return; if (!$scope.wallet || $scope.generatingAddress || !$scope.wallet.isComplete()) return;
@ -80,24 +36,49 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
popupService.showAlert(err); popupService.showAlert(err);
} }
if ($scope.wallet.coin === 'bch') { //close existing socket
if (currentAddressSocket.close === 'function') {
currentAddressSocket.close();
}
if ($scope.wallet.coin == 'bch') {
bchAddresses = bitcoinCashJsService.translateAddresses(addr); bchAddresses = bitcoinCashJsService.translateAddresses(addr);
$scope.addr = bchAddresses[$scope.bchAddressType.type]; $scope.addr = bchAddresses[$scope.bchAddressType.type];
$scope.addrBchLegacy = bchAddresses['legacy']; $scope.addrBchLegacy = bchAddresses['legacy'];
// listen to bch address
currentAddressSocket = new WebSocket("wss://ws.blockchain.info/bch/inv");
paymentSubscriptionObj.addr = bchAddresses['legacy'];
} else { } else {
$scope.addr = addr; $scope.addr = addr;
}
connectSocket(); // listen to btc address
currentAddressSocket = new WebSocket("wss://ws.blockchain.info/inv");
paymentSubscriptionObj.addr = $scope.addr
}
if (copyAddress === true) { if (copyAddress === true) {
try { try {
clipboardService.copyToClipboard($scope.wallet.coin == 'bch' && $scope.bchAddressType.type == 'cashaddr' ? 'bitcoincash:' + $scope.addr : $scope.addr); clipboardService.copyToClipboard($scope.wallet.coin == 'bch' && $scope.bchAddressType.type == 'cashaddr' ? 'bitcoincash:' + $scope.addr : $scope.addr);
} catch (error) { } catch (error) {
$log.debug('Error copying to clipboard:'); $log.debug("Error copying to clipboard:");
$log.debug(error); $log.debug(error);
} }
} }
// create subscription
var msg = JSON.stringify(paymentSubscriptionObj);
currentAddressSocket.onopen = function (event) {
//console.log("message sent: " + msg);
currentAddressSocket.send(msg);
}
// listen for response
currentAddressSocket.onmessage = function (event) {
//console.log("message received:" + event.data);
receivedPayment(event.data);
}
$timeout(function() { $timeout(function() {
$scope.$apply(); $scope.$apply();
@ -183,6 +164,7 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
// Notify new tx // Notify new tx
$scope.$emit('bwsEvent', $scope.wallet.id); $scope.$emit('bwsEvent', $scope.wallet.id);
$scope.$apply(function () { $scope.$apply(function () {
$scope.showingPaymentReceived = true; $scope.showingPaymentReceived = true;
}); });
@ -251,10 +233,6 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
} }
}; };
function onBeforeLeave() {
currentAddressSocket.close([CLOSE_NORMAL]);
}
$scope.$on("$ionicView.beforeEnter", function(event, data) { $scope.$on("$ionicView.beforeEnter", function(event, data) {
$scope.wallets = profileService.getWallets(); $scope.wallets = profileService.getWallets();
$scope.singleWallet = $scope.wallets.length == 1; $scope.singleWallet = $scope.wallets.length == 1;
@ -280,6 +258,7 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
configService.whenAvailable(function(_config) { configService.whenAvailable(function(_config) {
$scope.displayBalanceAsFiat = _config.wallet.settings.priceDisplay === 'fiat'; $scope.displayBalanceAsFiat = _config.wallet.settings.priceDisplay === 'fiat';
config = _config;
}); });
}); });

View file

@ -203,7 +203,6 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
function updateTxHistoryFromCachedData() { function updateTxHistoryFromCachedData() {
$scope.vm.gettingCachedHistory = true;
walletHistoryService.getCachedTxHistory($scope.wallet.id, function onGetCachedTxHistory(err, txHistory){ walletHistoryService.getCachedTxHistory($scope.wallet.id, function onGetCachedTxHistory(err, txHistory){
$scope.vm.gettingCachedHistory = false; $scope.vm.gettingCachedHistory = false;
if (err) { if (err) {
@ -401,9 +400,8 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
var refreshInterval; var refreshInterval;
$scope.$on("$ionicView.afterEnter", function onAfterEnter(event, data) { $scope.$on("$ionicView.afterEnter", function(event, data) {
updateTxHistoryFromCachedData(); $scope.updateAll();
$scope.updateAll(true, true);
// refreshAmountSection(); // refreshAmountSection();
refreshInterval = $interval($scope.onRefresh, 10 * 1000); refreshInterval = $interval($scope.onRefresh, 10 * 1000);
$timeout(function() { $timeout(function() {

View file

@ -1,12 +1,7 @@
'use strict'; 'use strict';
(function () { angular.module('copayApp.controllers').controller('walletSelectorController', function($scope, $state, sendFlowService, configService, gettextCatalog, profileService, txFormatService) {
angular
.module('copayApp.controllers')
.controller('walletSelectorController', walletSelectorController);
function walletSelectorController ($scope, $state, sendFlowService, configService, gettextCatalog, ongoingProcess, profileService, walletService, txFormatService) {
var fromWalletId = ''; var fromWalletId = '';
var priceDisplayAsFiat = false; var priceDisplayAsFiat = false;
var unitDecimals = 0; var unitDecimals = 0;
@ -121,41 +116,32 @@ angular
if ($scope.type === 'origin') { if ($scope.type === 'origin') {
$scope.headerTitle = gettextCatalog.getString('Choose a wallet to send from'); $scope.headerTitle = gettextCatalog.getString('Choose a wallet to send from');
if ($scope.params.amount || $scope.coin) { if ($scope.params.amount) {
walletsAll = profileService.getWallets({coin: $scope.coin}); walletsAll = profileService.getWallets({coin: $scope.coin});
ongoingProcess.set('scanning', true);
walletsAll.forEach(function forWallet(wallet){ walletsAll.forEach(function forWallet(wallet){
if (!wallet.status && !wallet.cachedStatus) { if (wallet.status.availableBalanceSat > $scope.params.amount) {
walletService.getStatus(wallet, {}, function(err, status) {
wallet.status = status;
if (status.availableBalanceSat > ($scope.params.amount ? $scope.params.amount : 0)) {
walletsSufficientFunds.push(wallet); walletsSufficientFunds.push(wallet);
} else { } else {
$scope.walletsInsufficientFunds.push(wallet); $scope.walletsInsufficientFunds.push(wallet);
} }
if ($scope.coin === 'btc') { // As this is a promise });
if ($scope.coin === 'btc') {
$scope.walletsBtc = walletsSufficientFunds; $scope.walletsBtc = walletsSufficientFunds;
} else { } else {
$scope.walletsBch = walletsSufficientFunds; $scope.walletsBch = walletsSufficientFunds;
} }
ongoingProcess.set('scanning', false);
});
} else {
var walletStatus = null;
if (wallet.status && wallet.status.isValid) {
walletStatus = wallet.status;
} else if (wallet.cachedStatus && wallet.status.isValid) {
walletStatus = wallet.cachedStatus;
}
if (walletStatus && walletStatus.availableBalanceSat > ($scope.params.amount ? $scope.params.amount : 0)) { } else if ($scope.coin) {
walletsAll = profileService.getWallets({coin: $scope.coin});
walletsAll.forEach(function forWallet(wallet){
if (wallet.status.availableBalanceSat > 0) {
walletsSufficientFunds.push(wallet); walletsSufficientFunds.push(wallet);
} else { } else {
$scope.walletsInsufficientFunds.push(wallet); $scope.walletsInsufficientFunds.push(wallet);
} }
ongoingProcess.set('scanning', false);
}
}); });
if ($scope.coin === 'btc') { if ($scope.coin === 'btc') {
@ -200,5 +186,4 @@ angular
sendFlowService.router.goBack(); sendFlowService.router.goBack();
} }
} });
})();

View file

@ -12,7 +12,6 @@
totalBalanceSat: '@', totalBalanceSat: '@',
// The Wallet object is sometimes not stringify()-able, so not interpolatable, // The Wallet object is sometimes not stringify()-able, so not interpolatable,
// so can't be passed to a directive. // so can't be passed to a directive.
walletCoin: '@',
walletStatus: '@', walletStatus: '@',
walletCachedBalance: '@', walletCachedBalance: '@',
walletCachedBalanceUpdatedOn: '@', walletCachedBalanceUpdatedOn: '@',
@ -32,6 +31,7 @@
}); });
function displayCryptoBalance(walletStatus, walletCachedBalance, walletCachedBalanceUpdatedOn, walletCachedStatus) { function displayCryptoBalance(walletStatus, walletCachedBalance, walletCachedBalanceUpdatedOn, walletCachedStatus) {
console.log('displayCryptoBalance()');
if (walletStatus && walletStatus.isValid && walletStatus.totalBalanceStr) { if (walletStatus && walletStatus.isValid && walletStatus.totalBalanceStr) {
setDisplay(walletStatus.totalBalanceStr, ''); setDisplay(walletStatus.totalBalanceStr, '');
@ -52,7 +52,7 @@
setDisplay('', ''); setDisplay('', '');
} }
function displayFiatBalance(walletStatus, walletCachedStatus, walletCoin) { function displayFiatBalance(walletStatus, walletCachedStatus) {
var displayAmount = ''; var displayAmount = '';
if (walletStatus && walletStatus.isValid && walletStatus.alternativeBalanceAvailable) { if (walletStatus && walletStatus.isValid && walletStatus.alternativeBalanceAvailable) {
displayAmount = walletStatus.totalBalanceAlternative + ' ' + walletStatus.alternativeIsoCode; displayAmount = walletStatus.totalBalanceAlternative + ' ' + walletStatus.alternativeIsoCode;
@ -66,7 +66,7 @@
return; return;
} }
getFiatBalance(walletStatus, walletCachedStatus, walletCoin); getFiatBalance(wallet);
} }
function formatBalance() { function formatBalance() {
@ -94,30 +94,19 @@
} }
if (displayAsFiat) { if (displayAsFiat) {
displayFiatBalance(walletStatusObj, walletCachedStatusObj, $scope.walletCoin); displayFiatBalance(walletStatusObj, walletCachedStatusObj);
} }
} }
function getFiatBalance(walletStatus, walletCachedStatus, walletCoin) { function getFiatBalance(wallet) {
var totalBalanceSat = null; if (!(wallet.status && wallet.status.isValid)) {
$log.warn('Abandoning call to get fiat balance, because no valid wallet status.');
if (walletStatus && walletStatus.isValid) {
totalBalanceSat = walletStatus.totalBalanceSat
} else if (walletCachedStatus && walletCachedStatus.isValid) {
totalBalanceSat = walletCachedStatus.totalBalanceSat
}
// 0 is valid
if (totalBalanceSat === null) {
$log.warn('Abandoning call to get fiat balance, because no valid wallet status (cached or otherwise).');
return; return;
} }
txFormatService.formatAlternativeStr(walletCoin, totalBalanceSat, function onFormatAlernativeStr(formatted) { txFormatService.formatAlternativeStr(wallet.coin, wallet.status.totalBalanceSat, function onFormatAlernativeStr(formatted) {
if (formatted) { if (formatted) {
setDisplay(formatted, ''); setDisplay(formatted, '');
} else {
$log.error('Failed to format fiat balance of wallet.');
} }
}); });
} }

View file

@ -85,9 +85,7 @@ angular.module('copayApp.services').factory('bitcoincomService', function(gettex
}; };
var register = function() { var register = function() {
if (!platformInfo.isAndroid) { // To comply with Google Play policies
nextStepsService.register(cashGamesItem); nextStepsService.register(cashGamesItem);
}
nextStepsService.register(newsItem); nextStepsService.register(newsItem);
nextStepsService.register(poolItem); nextStepsService.register(poolItem);
nextStepsService.register(toolsItem); nextStepsService.register(toolsItem);

View file

@ -18,7 +18,7 @@ angular.module('copayApp.services').factory('configService', function(storageSer
}, },
bwscash: { bwscash: {
url: 'https://bws.freepages.dk/bws/api' url: 'https://bwscash.bitcoin.com/bws/api'
}, },
download: { download: {

View file

@ -12,7 +12,6 @@ angular.module('copayApp.services').factory('feeService', function($log, $timeou
normal: gettext('Normal'), normal: gettext('Normal'),
economy: gettext('Economy'), economy: gettext('Economy'),
superEconomy: gettext('Super Economy'), superEconomy: gettext('Super Economy'),
// free: gettext('No fee (works only for BCH)'),
custom: gettext('Custom') custom: gettext('Custom')
}; };
@ -32,7 +31,6 @@ angular.module('copayApp.services').factory('feeService', function($log, $timeou
root.getFeeRate = function(coin, network, feeLevel, cb) { root.getFeeRate = function(coin, network, feeLevel, cb) {
if (feeLevel == 'custom') return cb(); if (feeLevel == 'custom') return cb();
// if (feeLevel == 'free') return cb(null, 0);
network = network || 'livenet'; network = network || 'livenet';
@ -50,8 +48,8 @@ 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');

View file

@ -75,7 +75,9 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti
var showName = $filter('translate')(processNames[name] || name); var showName = $filter('translate')(processNames[name] || name);
if (root.onGoingProcessName) { if (customHandler) {
customHandler(processName, showName, isOn);
} else if (root.onGoingProcessName) {
var tmpl; var tmpl;
if (isWindowsPhoneApp) tmpl = '<div>' + showName + '</div>'; if (isWindowsPhoneApp) tmpl = '<div>' + showName + '</div>';
else tmpl = '<div class="item-icon-left">' + showName + '<ion-spinner class="spinner-stable" icon="lines"></ion-spinner></div>'; else tmpl = '<div class="item-icon-left">' + showName + '<ion-spinner class="spinner-stable" icon="lines"></ion-spinner></div>';
@ -85,10 +87,6 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti
} else { } else {
$ionicLoading.hide(); $ionicLoading.hide();
} }
if (customHandler) {
customHandler(processName, showName, isOn);
}
}; };
return root; return root;

View file

@ -5,7 +5,7 @@ angular.module('copayApp.services').factory('servicesService', function(configSe
name: 'shapeshift', name: 'shapeshift',
title: 'Shapeshift', title: 'Shapeshift',
icon: 'icon-shapeshift', icon: 'icon-shapeshift',
href: 'https://shapeshift.io/' sref: 'tabs.shapeshift',
}]; }];
root.register = function(serviceInfo) { root.register = function(serviceInfo) {

View file

@ -10,7 +10,7 @@ angular.module('copayApp.services')
isoCode: 'en', isoCode: 'en',
rateCode: 'USD' rateCode: 'USD'
}, { }, {
name: 'Català', name: 'català',
isoCode: 'ca', isoCode: 'ca',
rateCode: 'EUR' rateCode: 'EUR'
},{ },{
@ -59,6 +59,10 @@ angular.module('copayApp.services')
name: 'Português', name: 'Português',
isoCode: 'pt', isoCode: 'pt',
rateCode: 'EUR' rateCode: 'EUR'
}, {
name: 'русский язык',
isoCode: 'ru',
rateCode: 'RUB'
}, { }, {
name: '한국어', name: '한국어',
isoCode: 'ko', isoCode: 'ko',

View file

@ -12,9 +12,9 @@
// How much to overlap on each end of the page, for mitigating inconsistent sort order. // How much to overlap on each end of the page, for mitigating inconsistent sort order.
var PAGE_OVERLAP_FRACTION = 0.2; var PAGE_OVERLAP_FRACTION = 0.2;
var PAGE_OVERLAP = Math.floor(PAGE_SIZE * PAGE_OVERLAP_FRACTION); var PAGE_OVERLAP = Math.floor(PAGE_SIZE * PAGE_OVERLAP_FRACTION);
// The fraction of transactions in the new overlapping resultset that we already know about. // The amount of transactions in the new overlapping resultset that we already know about.
// If we know about at least this many, then there are probably no gaps. // If we know about at least this many, then there are probably no gaps.
var MIN_KNOWN_TX_OVERLAP_FRACTION = 0.5; var MIN_KNOWN_TX_OVERLAP = Math.floor(PAGE_OVERLAP * 0.5);
var SAFE_CONFIRMATIONS = 6; var SAFE_CONFIRMATIONS = 6;
@ -27,34 +27,26 @@
function addEarlyTransactions(walletId, cachedTxs, newTxs) { function addEarlyTransactions(walletId, cachedTxs, newTxs) {
var cachedTxIndexFromId = {}; var cachedTxIds = {};
cachedTxs.forEach(function forCachedTx(tx){ cachedTxs.forEach(function forCachedTx(tx){
cachedTxIndexFromId[tx.txid] = true; cachedTxIds[tx.txid] = true;
}); });
var confirmationsUpdated = false;
var someTransactionsWereNew = false; var someTransactionsWereNew = false;
var overlappingTxsCount = 0; var overlappingTxsCount = 0;
newTxs.forEach(function forNewTx(tx){ newTxs.forEach(function forNewTx(tx){
if (typeof cachedTxIndexFromId[tx.txid] === "undefined") { if (cachedTxIds[tx.txid]) {
overlappingTxsCount++;
} else {
someTransactionsWereNew = true; someTransactionsWereNew = true;
cachedTxs.push(tx); cachedTxs.push(tx);
} else {
var txUpdated = updateCachedTx(cachedTxs, cachedTxIndexFromId, tx);
confirmationsUpdated = confirmationsUpdated || txUpdated;
overlappingTxsCount++;
} }
}); });
var overlappingTxFraction = overlappingTxsCount / Math.min(cachedTxs.length, PAGE_OVERLAP); if (overlappingTxsCount >= MIN_KNOWN_TX_OVERLAP) { // We are good
console.log('overlappingTxFraction:', overlappingTxFraction);
if (overlappingTxFraction >= MIN_KNOWN_TX_OVERLAP_FRACTION) { // We are good
if (someTransactionsWereNew) { if (someTransactionsWereNew) {
saveTxHistory(walletId, cachedTxs); saveTxHistory(walletId, cachedTxs);
} else if (confirmationsUpdated) {
saveTxHistory(walletId, cachedTxs);
} else if (overlappingTxsCount === newTxs.length) { } else if (overlappingTxsCount === newTxs.length) {
allTransactionsFetched = true; allTransactionsFetched = true;
} }
@ -70,38 +62,30 @@
} }
function addLatestTransactions(walletId, cachedTxs, newTxs) { function addLatestTransactions(walletId, cachedTxs, newTxs) {
var cachedTxIndexFromId = {}; var cachedTxIds = {};
cachedTxs.forEach(function forCachedTx(tx, txIndex){ cachedTxs.forEach(function forCachedTx(tx){
cachedTxIndexFromId[tx.txid] = txIndex; cachedTxIds[tx.txid] = true;
}); });
var someTransactionsWereNew = false; var someTransactionsWereNew = false;
var confirmationsUpdated = false;
var overlappingTxsCount = 0; var overlappingTxsCount = 0;
var uniqueNewTxs = []; var uniqueNewTxs = [];
newTxs.forEach(function forNewTx(tx){ newTxs.forEach(function forNewTx(tx){
if (typeof cachedTxIndexFromId[tx.txid] === "undefined") { if (cachedTxIds[tx.txid]) {
overlappingTxsCount++;
} else {
someTransactionsWereNew = true; someTransactionsWereNew = true;
uniqueNewTxs.push(tx); uniqueNewTxs.push(tx);
} else {
var txUpdated = updateCachedTx(cachedTxs, cachedTxIndexFromId, tx);
confirmationsUpdated = confirmationsUpdated || txUpdated;
overlappingTxsCount++;
} }
}); });
var overlappingTxFraction = overlappingTxsCount / Math.min(cachedTxs.length, PAGE_OVERLAP); if (overlappingTxsCount >= MIN_KNOWN_TX_OVERLAP) { // We are good
if (overlappingTxFraction >= MIN_KNOWN_TX_OVERLAP_FRACTION) { // We are good
if (someTransactionsWereNew) { if (someTransactionsWereNew) {
var allTxs = uniqueNewTxs.concat(cachedTxs); var allTxs = uniqueNewTxs.concat(cachedTxs);
saveTxHistory(walletId, allTxs); saveTxHistory(walletId, allTxs);
return allTxs; return allTxs;
} else { } else {
if (confirmationsUpdated) {
saveTxHistory(walletId, cachedTxs);
}
return cachedTxs; return cachedTxs;
} }
} else { } else {
@ -115,8 +99,6 @@
// Only clear the cache once we have received new transactions from the server. // Only clear the cache once we have received new transactions from the server.
/** /**
* @param wallet
* @param start
* @param {function(err, txs)} cb - transactions is always an array, may be empty * @param {function(err, txs)} cb - transactions is always an array, may be empty
*/ */
function fetchTxHistoryByPage(wallet, start, cb) { function fetchTxHistoryByPage(wallet, start, cb) {
@ -147,7 +129,6 @@
* @param {function(error, txs)} cb - txs is always an array, may be empty * @param {function(error, txs)} cb - txs is always an array, may be empty
*/ */
function getCachedTxHistory(walletId, cb) { function getCachedTxHistory(walletId, cb) {
console.log('txhistory updateLocalTxHistoryByPage()');
storageService.getTxHistory(walletId, function onGetTxHistory(err, txHistoryString){ storageService.getTxHistory(walletId, function onGetTxHistory(err, txHistoryString){
if (err) { if (err) {
return cb(err, []); return cb(err, []);
@ -201,7 +182,7 @@
}); });
return processedTxs; return processedTxs;
} };
function saveTxHistory(walletId, processedTxs) { function saveTxHistory(walletId, processedTxs) {
storageService.setTxHistory(processedTxs, walletId, function onSetTxHistory(error){ storageService.setTxHistory(processedTxs, walletId, function onSetTxHistory(error){
@ -211,26 +192,9 @@
}); });
} }
/**
* Returns true if the cached tx was updated
* @param {*} cachedTxs
* @param {*} cachedTxIndexFromId - Indices for cachedTxs, based on txid
* @param {*} tx - The most recent tx info
*/
function updateCachedTx(cachedTxs, cachedTxIndexFromId, tx) {
var updated = false;
var txIndex = cachedTxIndexFromId[tx.txid];
var cachedTx = cachedTxs[txIndex];
if (cachedTx.confirmations < SAFE_CONFIRMATIONS && tx.confirmations > cachedTx.confirmations) {
cachedTxs[txIndex].confirmations = tx.confirmations;
updated = true;
}
return updated;
}
function updateLocalTxHistoryByPage(wallet, getLatest, flushCacheOnNew, cb) { function updateLocalTxHistoryByPage(wallet, getLatest, flushCacheOnNew, cb) {
console.log('txhistory updaetLocalTxHistoryByPage()');
if (flushCacheOnNew) { if (flushCacheOnNew) {
fetchTxHistoryByPage(wallet, 0, function onFetchTxHistory(err, txs){ fetchTxHistoryByPage(wallet, 0, function onFetchTxHistory(err, txs){
if (err) { if (err) {
@ -271,5 +235,10 @@
}); });
} }
} }
} }
})(); })();

View file

@ -10083,7 +10083,7 @@ ion-view.deflash-blue:before, ion-view#view-amount:before, ion-view#view-confirm
.onboarding .button.button-white.button-standard, .onboarding .button.button-white.button-standard,
.onboarding .button.button-green.button-standard, .onboarding .button.button-green.button-standard,
.onboarding .button.button-assertive.button-standard, #shapeshift .button-shapeshift { .onboarding .button.button-assertive.button-standard, #shapeshift .button-shapeshift {
width: 90%; width: 85%;
max-width: 300px; max-width: 300px;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
@ -10195,7 +10195,6 @@ ion-view.deflash-blue:before, ion-view#view-amount:before, ion-view#view-confirm
.button { .button {
border-radius: 6px; } border-radius: 6px; }
.button.button-full { .button.button-full {
border-radius: 0;
display: block; } display: block; }
.button-green { .button-green {
border-color: #FFF; border-color: #FFF;
@ -10264,8 +10263,8 @@ ion-view.deflash-blue:before, ion-view#view-amount:before, ion-view#view-confirm
color: #FFFFFF; color: #FFFFFF;
text-decoration: none; } text-decoration: none; }
.button-white-outline.active, .button-white-outline.activated { .button-white-outline.active, .button-white-outline.activated {
border-color: #FFFFFF; border-color: #FFF;
background-color: #FFFFFF; } background-color: #FAFAFA; }
.button-white-outline.button-outline { .button-white-outline.button-outline {
border-color: #FFFFFF; border-color: #FFFFFF;
background: transparent; background: transparent;
@ -10633,7 +10632,7 @@ qrcode {
#view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long .primary-amount-display { #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long .primary-amount-display {
font-size: 2em; } } font-size: 2em; } }
#view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .primary-amount-display { #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .primary-amount-display {
font-size: 1.2em; } font-size: 0.9em; }
@media (min-width: 375px) { @media (min-width: 375px) {
#view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .primary-amount-display { #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .primary-amount-display {
font-size: 1.3em; } } font-size: 1.3em; } }
@ -10660,8 +10659,7 @@ qrcode {
line-height: 1em; } line-height: 1em; }
#view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .primary-amount-display { #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .primary-amount-display {
margin-right: 5px; margin-right: 5px;
word-break: break-all; word-break: break-all; }
width: 100%; }
#view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .alternative-amount { #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .alternative-amount {
color: #6F6F70; } color: #6F6F70; }
#view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .switch-currencies { #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .switch-currencies {
@ -10682,19 +10680,16 @@ qrcode {
justify-content: space-between; justify-content: space-between;
margin: 0 14px; } margin: 0 14px; }
#view-amount .scroll-content .send-amount-extras .available-funds { #view-amount .scroll-content .send-amount-extras .available-funds {
color: #6F6F70; color: #6F6F70; }
text-align: left; }
#view-amount .scroll-content .send-amount-extras .change-currency {
text-align: right; }
#view-amount .scroll-content .send-amount-extras .warning { #view-amount .scroll-content .send-amount-extras .warning {
color: #b7664d; } color: #b7664d; }
#view-amount .scroll-content .send-amount-extras .extra { #view-amount .scroll-content .send-amount-extras .extra,
flex: 1; #view-amount .scroll-content .send-amount-extras button.extra {
line-height: normal; } /*display: flex;*/
#view-amount .scroll-content .send-amount-extras .extra .button { flex: 0 1 auto; }
#view-amount .scroll-content .send-amount-extras button.extra {
background: none; background: none;
border: none; border: none;
border-radius: 0;
color: #000; color: #000;
font-family: 'ProximaNova'; font-family: 'ProximaNova';
font-size: 14px; font-size: 14px;
@ -10702,10 +10697,10 @@ qrcode {
min-height: auto; min-height: auto;
min-width: auto; min-width: auto;
padding: 0; } padding: 0; }
#view-amount .scroll-content .send-amount-extras .extra .button .icon:before { #view-amount .scroll-content .send-amount-extras .button .icon:before {
font-size: 14px; font-size: 14px;
line-height: normal; } line-height: normal; }
#view-amount .scroll-content .send-amount-extras .extra .button span { #view-amount .scroll-content .send-amount-extras .button span {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; } justify-content: center; }
@ -10944,14 +10939,14 @@ qrcode {
#tab-home .buttons .button { #tab-home .buttons .button {
border: 2px solid; border: 2px solid;
border-radius: 47px; border-radius: 47px;
padding: 8px 2px 8px 2px; padding: 0 15px 0 15px;
text-align: center; text-align: center;
width: 100%; width: 100%;
max-width: 300px; max-width: 300px;
font-size: 19px; font-size: 19px;
font-weight: bolder; font-weight: bolder;
min-height: 0; min-height: auto;
line-height: 19px; } line-height: 36px; }
#tab-home .wallet-coin-logo { #tab-home .wallet-coin-logo {
vertical-align: middle; vertical-align: middle;
@ -11018,10 +11013,6 @@ qrcode {
#tab-home .release .title { #tab-home .release .title {
font-weight: 700; font-weight: 700;
color: #444; } color: #444; }
#tab-home .release .release-notes {
white-space: pre;
white-space: pre-line;
text-align: left; }
#tab-home .release .button { #tab-home .release .button {
width: 100%; width: 100%;
border: none; } border: none; }
@ -11034,14 +11025,6 @@ qrcode {
#tab-home .badge { #tab-home .badge {
top: 11px; } top: 11px; }
.popup-update .popup-buttons {
display: block; }
.popup-update .popup-buttons .button {
display: block;
min-width: 100% !important;
margin-top: 4px; }
#tab-receive .button-share { #tab-receive .button-share {
color: #fff; color: #fff;
box-shadow: none; box-shadow: none;
@ -11118,8 +11101,6 @@ qrcode {
#tab-receive .payment-received-container { #tab-receive .payment-received-container {
margin: 0 20px; } margin: 0 20px; }
#tab-receive .payment-received-container svg {
max-height: 400px; }
#tab-receive .payment-received-container .payment-received-amount { #tab-receive .payment-received-container .payment-received-amount {
font-size: 1.8em; font-size: 1.8em;
display: block; display: block;
@ -11226,7 +11207,7 @@ qrcode {
margin: auto; margin: auto;
margin-top: 18px; } margin-top: 18px; }
#tab-send .send-wrapper .buttons .button { #tab-send .send-wrapper .buttons .button {
min-height: 65px; height: 60px;
line-height: 16px; line-height: 16px;
margin-right: 0px; margin-right: 0px;
width: 95%; width: 95%;
@ -11303,9 +11284,7 @@ qrcode {
margin-top: 18px; } margin-top: 18px; }
#tab-send .sendTip .buttons .button { #tab-send .sendTip .buttons .button {
font-weight: bold; font-weight: bold;
font-size: 19px; font-size: 19px; }
line-height: 26px;
padding: 8px 6px; }
#tab-send .sendTip .button-first-contact img { #tab-send .sendTip .button-first-contact img {
height: 19px; height: 19px;
width: 19px; width: 19px;
@ -11941,13 +11920,6 @@ qrcode {
#walletDetails .bp-content.status-bar { #walletDetails .bp-content.status-bar {
margin-top: 20px; margin-top: 20px;
margin-top: env(safe-area-inset-top); } margin-top: env(safe-area-inset-top); }
#walletDetails .bp-content.collapse ion-content {
margin-top: 40px; }
#walletDetails .bp-content.collapse .amount__scale, #walletDetails .bp-content.collapse .amount__error {
-webkit-transform: scale3d(0.5, 0.5, 0.5) translateY(0px);
transform: scale3d(0.5, 0.5, 0.5) translateY(0px); }
#walletDetails .bp-content.collapse .amount-alternative, #walletDetails .bp-content.collapse .send-receive-buttons, #walletDetails .bp-content.collapse .wallet-details-wallet-info {
opacity: 0; }
#walletDetails .bar-header { #walletDetails .bar-header {
border: 0; border: 0;
background: #eeb640; } background: #eeb640; }
@ -11960,12 +11932,9 @@ qrcode {
#walletDetails ion-content { #walletDetails ion-content {
padding-top: 0; padding-top: 0;
top: 0; top: 0;
transition: all 0.25s ease-in-out;
margin-top: 185px;
margin-bottom: 16px; } margin-bottom: 16px; }
@media only screen and (max-height: 500px) { #walletDetails ion-content.collapsible {
#walletDetails ion-content { margin-top: 230px; }
margin-top: 165px; } }
#walletDetails ion-content .scroll { #walletDetails ion-content .scroll {
background: #f8f8f9; background: #f8f8f9;
min-height: 300px; } min-height: 300px; }
@ -11996,45 +11965,38 @@ qrcode {
justify-content: space-evenly; justify-content: space-evenly;
width: 100%; width: 100%;
position: absolute; position: absolute;
bottom: 20px; bottom: 20px; }
transition: all 0.25s ease-in-out; }
#walletDetails .amount-wrapper .send-receive-buttons > .col { #walletDetails .amount-wrapper .send-receive-buttons > .col {
padding: 5px 10px; padding: 5px 10px;
margin-bottom: 0; } margin-bottom: 0; }
#walletDetails .amount-wrapper .send-receive-buttons .button { #walletDetails .amount-wrapper .send-receive-buttons .button {
border: 2px solid; border: 2px solid;
border-radius: 47px; border-radius: 47px;
padding: 6px 2px 6px 2px; padding: 0 15px 0 15px;
text-align: center; text-align: center;
width: 100%; width: 100%;
max-width: 300px; max-width: 300px;
font-size: 19px; font-size: 19px;
font-weight: bolder; font-weight: bolder;
min-height: 0; min-height: auto;
line-height: 19px; } line-height: 36px; }
#walletDetails .amount { #walletDetails .amount {
align-items: center; width: 100%;
color: #fff;
display: block;
height: 230px;
justify-content: center;
padding-top: 40px;
text-align: center; text-align: center;
transition: all 0.25s ease-in-out; color: #fff;
width: 100%; } height: 230px;
@media only screen and (max-height: 500px) { padding-top: 40px;
#walletDetails .amount { display: block;
height: 210px; } } align-items: center;
justify-content: center; }
#walletDetails .amount__balance { #walletDetails .amount__balance {
-webkit-transform: scale3d(1, 1, 1) translateY(45px); -webkit-transform: scale3d(1, 1, 1) translateY(45px);
transform: scale3d(1, 1, 1) translateY(45px); transform: scale3d(1, 1, 1) translateY(45px); }
transition: all 0.25s ease-in-out; }
#walletDetails .amount__updating { #walletDetails .amount__updating {
z-index: 999; z-index: 999;
margin-top: -2.1rem; } margin-top: -2.1rem; }
#walletDetails .amount-alternative { #walletDetails .amount-alternative {
line-height: 36px; line-height: 36px; }
transition: all 0.25s ease-in-out; }
#walletDetails .amount__button-balance { #walletDetails .amount__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);
@ -12044,8 +12006,7 @@ qrcode {
vertical-align: middle; } vertical-align: middle; }
#walletDetails .amount__error { #walletDetails .amount__error {
font-size: 14px; font-size: 14px;
padding: 35px 20px; padding: 35px 20px; }
opacity: 1; }
#walletDetails .no-alternative { #walletDetails .no-alternative {
padding-top: 45px; } padding-top: 45px; }
#walletDetails .item.item-footer { #walletDetails .item.item-footer {
@ -12110,9 +12071,7 @@ a.item {
font-size: 0.9em; } font-size: 0.9em; }
.loading-wallet svg { .loading-wallet svg {
margin-top: 0; margin-top: 0; }
width: 16px;
height: 16px; }
#advanced-settings .list .item:before { #advanced-settings .list .item:before {
display: block; display: block;
@ -12166,9 +12125,7 @@ a.item {
margin-top: 18px; } margin-top: 18px; }
#shapeshift .empty-case .buttons .button { #shapeshift .empty-case .buttons .button {
font-weight: bold; font-weight: bold;
font-size: 19px; font-size: 19px; }
line-height: 26px;
padding: 8px 6px; }
#shapeshift .empty-case .button-first-contact img { #shapeshift .empty-case .button-first-contact img {
height: 19px; height: 19px;
width: 19px; width: 19px;
@ -13855,7 +13812,6 @@ click-to-accept {
height: 92px; height: 92px;
width: 100%; } width: 100%; }
click-to-accept .click-to-accept__button.button.button-primary.button-standard { click-to-accept .click-to-accept__button.button.button-primary.button-standard {
border-radius: 0;
height: 100%; height: 100%;
max-width: 9999px; max-width: 9999px;
width: 100%; } width: 100%; }
@ -13962,8 +13918,6 @@ slide-to-accept {
height: 92px; height: 92px;
width: 100%; width: 100%;
background: #494949; } background: #494949; }
slide-to-accept .slide .button {
border-radius: 0; }
slide-to-accept .slide__listener { slide-to-accept .slide__listener {
height: 100%; height: 100%;
width: 100%; width: 100%;
@ -15395,23 +15349,18 @@ log-options #check-bar .checkbox-icon {
#cash-scan a { #cash-scan a {
cursor: pointer; } cursor: pointer; }
#view-review {
background-color: #494949; }
#view-review slide-to-accept, #view-review slide-to-accept-success { #view-review slide-to-accept, #view-review slide-to-accept-success {
margin-bottom: constant(safe-area-inset-bottom); margin-bottom: constant(safe-area-inset-bottom);
/* iOS 11.0 */ /* iOS 11.0 */
margin-bottom: env(safe-area-inset-bottom); margin-bottom: env(safe-area-inset-bottom);
/* iOS 11.2 */ } /* iOS 11.2 */ }
#view-review .fee-summary { #view-review .fee-summary {
bottom: 92px; position: absolute;
bottom: calc(92px + constant(safe-area-inset-bottom)); bottom: 92px; }
/* iOS 11.0 */
bottom: calc(92px + env(safe-area-inset-bottom));
/* iOS 11.2 */
position: absolute; }
#view-review .shapeshift-banner, #view-review .bitpay-banner, #view-review .egifter-banner { #view-review .shapeshift-banner, #view-review .bitpay-banner, #view-review .egifter-banner {
box-shadow: none; } box-shadow: none; }
#view-review .warning { #view-review .warning {
color: #b7664d; } color: #b7664d; }
@ -15446,7 +15395,6 @@ log-options #check-bar .checkbox-icon {
left: 13px; left: 13px;
top: 50%; top: 50%;
padding: 0; padding: 0;
-webkit-transform: translate(0, -50%);
transform: translate(0, -50%); } transform: translate(0, -50%); }
.item .item-content.item-content-compact { .item .item-content.item-content-compact {
@ -15515,8 +15463,8 @@ ion-content.padded-bottom-cta-with-summary {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; } text-overflow: ellipsis; }
.address-frame.expanded { .address-frame.expanded {
white-space: normal; white-space: pre-wrap;
text-overflow: clip; } word-break: break-all; }
.address-frame .prefix { .address-frame .prefix {
color: #000000; } color: #000000; }
.address-frame .mid { .address-frame .mid {
@ -15559,13 +15507,13 @@ ion-content.padded-bottom-cta-with-summary {
transform: scale(1, 1); } transform: scale(1, 1); }
.fee-summary { .fee-summary {
background-color: #F2F2F2; position: relative;
box-sizing: border-box;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 100%;
padding: 5px 12px 15px; padding: 5px 12px 15px;
position: relative; box-sizing: border-box;
width: 100%; } background-color: #F2F2F2; }
.fee-summary:before { .fee-summary:before {
content: ''; content: '';
position: absolute; position: absolute;
@ -15575,16 +15523,16 @@ ion-content.padded-bottom-cta-with-summary {
height: 15px; height: 15px;
background: linear-gradient(to bottom, rgba(242, 242, 242, 0) 0%, #f2f2f2 100%); } background: linear-gradient(to bottom, rgba(242, 242, 242, 0) 0%, #f2f2f2 100%); }
.fee-summary .amount { .fee-summary .amount {
display: flex;
flex-direction: row;
justify-content: space-between;
width: 100%; } width: 100%; }
.fee-summary .amount .fee-fiat {
display: inline; }
.fee-summary .amount .fee-fiat.positive { .fee-summary .amount .fee-fiat.positive {
color: #70955F; } color: #70955F; }
.fee-summary .amount .fee-fiat.negative { .fee-summary .amount .fee-fiat.negative {
color: #C24633; } color: #C24633; }
.fee-summary .amount .fee-crypto { .fee-summary .amount .fee-crypto {
color: #A7A7A7; color: #A7A7A7; }
float: right; }
.formatted-amount { .formatted-amount {
display: inline-block; } display: inline-block; }
@ -15609,9 +15557,6 @@ ion-content.padded-bottom-cta-with-summary {
margin-left: 5px; margin-left: 5px;
text-transform: uppercase; } text-transform: uppercase; }
.wallet-balance-directive {
display: inline-block; }
/* This is for rules that don't yet have a home. /* This is for rules that don't yet have a home.
* Our goal is to delete this file. Search the regex: /class=".*CLASS.*?"/ * Our goal is to delete this file. Search the regex: /class=".*CLASS.*?"/
*/ */

View file

@ -6,14 +6,7 @@
</div> </div>
<div ng-show="!hide"> <div ng-show="!hide">
<div ng-repeat="service in services track by $index"> <div ng-repeat="service in services track by $index">
<a ng-if="service.sref" ui-sref="{{service.sref}}" id="home_{{service.name}}" title="{{service.title || service.name}}" class="track_link_click_out item item-sub item-icon-left item-big-icon-left item-icon-right next-step"> <a ui-sref="{{service.sref}}" id="home_{{service.name}}" title="{{service.title || service.name}}" class="track_link_click_out item item-sub item-icon-left item-big-icon-left item-icon-right next-step">
<i class="icon big-icon-svg theme-circle theme-circle-services">
<div class="bg {{service.icon}}"></div>
</i>
<span>{{service.title || service.name}}</span>
<i class="icon bp-arrow-right"></i>
</a>
<a ng-if="!service.sref" ng-click="open('{{service.href}}')" id="home_{{service.name}}" title="{{service.title || service.name}}" class="track_link_click_out item item-sub item-icon-left item-big-icon-left item-icon-right next-step">
<i class="icon big-icon-svg theme-circle theme-circle-services"> <i class="icon big-icon-svg theme-circle theme-circle-services">
<div class="bg {{service.icon}}"></div> <div class="bg {{service.icon}}"></div>
</i> </i>

View file

@ -18,12 +18,13 @@
<h2>{{fromWallet.name}}</h2> <h2>{{fromWallet.name}}</h2>
<wallet-balance <wallet-balance
display-as-fiat="{{displayBalanceAsFiat}}" display-as-fiat="{{displayBalanceAsFiat}}"
wallet-coin="{{fromWallet.coin}}"
wallet-status="{{fromWallet.status}}" wallet-status="{{fromWallet.status}}"
wallet-cached-balance="{{fromWallet.cachedBalance}}" wallet-cached-balance="{{fromWallet.cachedBalance}}"
wallet-cached-balance-updated-on="{{fromWallet.cachedBalanceUpdatedOn}}" wallet-cached-balance-updated-on="{{fromWallet.cachedBalanceUpdatedOn}}"
wallet-cached-status="{{fromWallet.cachedStatus}}" wallet-cached-status="{{fromWallet.cachedStatus}}"
total-balance-sat="{{fromWallet.status.totalBalanceSat}}"></wallet-balance> total-balance-sat="{{fromWallet.status.totalBalanceSat}}"></wallet-balance>
<!--<p ng-show="vm.origin.balanceAmount">{{vm.origin.balanceAmount}} {{vm.origin.balanceCurrency}}</p>-->
<!--<formatted-amount value="{{fromWallet.status.totalBalanceStr ? fromWallet.status.totalBalanceStr : ( fromWallet.cachedBalance ? fromWallet.cachedBalance + (fromWallet.cachedBalanceUpdatedOn ? ' &middot; ' + ( fromWallet.cachedBalanceUpdatedOn * 1000 | amTimeAgo) : '') : '' ) }}"></formatted-amount>-->
</div> </div>
</div> </div>
</div> </div>

View file

@ -13,7 +13,7 @@
<div class="header--request__amount-alt" ng-show="requestAmountSecondary" translate>{{requestAmountSecondary}} {{requestCurrencySecondary}}</div> <div class="header--request__amount-alt" ng-show="requestAmountSecondary" translate>{{requestAmountSecondary}} {{requestCurrencySecondary}}</div>
</div> </div>
<div class="wallets-header"> <div class="wallets-header">
<div class="title" ng-if="walletsBch.length > 0 || walletsBtc.length > 0 || walletsInsufficientFunds.length > 0"> <div class="title">
{{headerTitle}} {{headerTitle}}
</div> </div>
</div> </div>