From 51c35101a6c10215173ef4f3c46a0063c6e94562 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Dominguez Date: Fri, 7 Sep 2018 17:08:39 +0900 Subject: [PATCH 01/23] appConfig beta release --- app-template/bitcoincom/appConfig.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app-template/bitcoincom/appConfig.json b/app-template/bitcoincom/appConfig.json index e4d6c8a84..f9ae8ab3f 100644 --- a/app-template/bitcoincom/appConfig.json +++ b/app-template/bitcoincom/appConfig.json @@ -24,9 +24,9 @@ "windowsAppId": "804636ee-b017-4cad-8719-e58ac97ffa5c", "pushSenderId": "1036948132229", "description": "A Secure Bitcoin Wallet", - "version": "5.0.2", - "fullVersion": "5.0-rc3", - "androidVersion": "500200", + "version": "5.1.0", + "fullVersion": "5.1-beta1", + "androidVersion": "501000", "_extraCSS": "", "_enabledExtensions": { "coinbase": false, From c1f6e56b56cfc538265b62b4ede6749ec4cf79b1 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Tue, 11 Sep 2018 15:37:47 +1200 Subject: [PATCH 02/23] Increment version. --- app-template/bitcoincom/appConfig.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app-template/bitcoincom/appConfig.json b/app-template/bitcoincom/appConfig.json index f9ae8ab3f..970432be2 100644 --- a/app-template/bitcoincom/appConfig.json +++ b/app-template/bitcoincom/appConfig.json @@ -24,9 +24,9 @@ "windowsAppId": "804636ee-b017-4cad-8719-e58ac97ffa5c", "pushSenderId": "1036948132229", "description": "A Secure Bitcoin Wallet", - "version": "5.1.0", - "fullVersion": "5.1-beta1", - "androidVersion": "501000", + "version": "5.1.1", + "fullVersion": "5.1-beta2", + "androidVersion": "501001", "_extraCSS": "", "_enabledExtensions": { "coinbase": false, From ad4aa76902325dc3a761dad47049742e77a29483 Mon Sep 17 00:00:00 2001 From: Sebastiaan Pasma Date: Tue, 11 Sep 2018 14:55:22 +0200 Subject: [PATCH 03/23] Empty origin wallet screen bug --- .../controllers/wallet-selector.controller.js | 42 +++++++++---------- www/views/walletSelector.html | 2 +- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/js/controllers/wallet-selector.controller.js b/src/js/controllers/wallet-selector.controller.js index 06e6179da..3fe10b931 100644 --- a/src/js/controllers/wallet-selector.controller.js +++ b/src/js/controllers/wallet-selector.controller.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('walletSelectorController', function($scope, $state, sendFlowService, configService, gettextCatalog, profileService, txFormatService) { +angular.module('copayApp.controllers').controller('walletSelectorController', function($scope, $state, sendFlowService, configService, gettextCatalog, ongoingProcess, profileService, walletService, txFormatService) { var fromWalletId = ''; var priceDisplayAsFiat = false; @@ -116,15 +116,27 @@ angular.module('copayApp.controllers').controller('walletSelectorController', fu if ($scope.type === 'origin') { $scope.headerTitle = gettextCatalog.getString('Choose a wallet to send from'); - if ($scope.params.amount) { + if ($scope.params.amount || $scope.coin) { walletsAll = profileService.getWallets({coin: $scope.coin}); - - walletsAll.forEach(function forWallet(wallet){ - if (wallet.status.availableBalanceSat > $scope.params.amount) { - walletsSufficientFunds.push(wallet); + ongoingProcess.set('scanning', true); + walletsAll.forEach(function forWallet(wallet) { + if (!wallet.status) { + walletService.getStatus(wallet, {}, function(err, status) { + if (status.availableBalanceSat > ($scope.params.amount ? $scope.params.amount : 0)) { + walletsSufficientFunds.push(wallet); + } else { + $scope.walletsInsufficientFunds.push(wallet); + } + ongoingProcess.set('scanning', false); + }); } else { - $scope.walletsInsufficientFunds.push(wallet); + if (wallet.status.availableBalanceSat > ($scope.params.amount ? $scope.params.amount : 0)) { + walletsSufficientFunds.push(wallet); + } else { + $scope.walletsInsufficientFunds.push(wallet); + } + ongoingProcess.set('scanning', false); } }); @@ -133,22 +145,6 @@ angular.module('copayApp.controllers').controller('walletSelectorController', fu } else { $scope.walletsBch = walletsSufficientFunds; } - - } else if ($scope.coin) { - walletsAll = profileService.getWallets({coin: $scope.coin}); - walletsAll.forEach(function forWallet(wallet){ - if (wallet.status.availableBalanceSat > 0) { - walletsSufficientFunds.push(wallet); - } else { - $scope.walletsInsufficientFunds.push(wallet); - } - }); - - if ($scope.coin === 'btc') { - $scope.walletsBtc = walletsSufficientFunds; - } else { - $scope.walletsBch = walletsSufficientFunds; - } } else { $scope.walletsBch = profileService.getWallets({coin: 'bch', hasFunds: true}); $scope.walletsBtc = profileService.getWallets({coin: 'btc', hasFunds: true}); diff --git a/www/views/walletSelector.html b/www/views/walletSelector.html index 2e4c4bc31..a9712adf9 100644 --- a/www/views/walletSelector.html +++ b/www/views/walletSelector.html @@ -13,7 +13,7 @@
{{requestAmountSecondary}} {{requestCurrencySecondary}}
-
+
{{headerTitle}}
From 6692812d55bbd69e261af164e18f9eb1983ed78b Mon Sep 17 00:00:00 2001 From: Sebastiaan Pasma Date: Wed, 12 Sep 2018 15:09:21 +0200 Subject: [PATCH 04/23] Websocket reconnect (and close old connection on leave) --- src/js/controllers/tab-receive.js | 95 ++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 32 deletions(-) diff --git a/src/js/controllers/tab-receive.js b/src/js/controllers/tab-receive.js index 320afe320..6642c2e1c 100644 --- a/src/js/controllers/tab-receive.js +++ b/src/js/controllers/tab-receive.js @@ -24,6 +24,52 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi }); }; + + function connectSocket() { + //close existing socket if not connected with current address + if (currentAddressSocket && typeof currentAddressSocket.close === 'function') { + currentAddressSocket.onclose = function(e) {}; // Overwrite onclose-function to prevent reconnecting old address socket. + currentAddressSocket.close(); + } + 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(e) { + console.log('Socket is closed. 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(); + }; + + $timeout(function() { + $scope.$apply(); + }, 10); + } + $scope.setAddress = function(newAddr, copyAddress) { $scope.addr = null; if (!$scope.wallet || $scope.generatingAddress || !$scope.wallet.isComplete()) return; @@ -36,28 +82,16 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi popupService.showAlert(err); } - //close existing socket - if (currentAddressSocket.close === 'function') { - currentAddressSocket.close(); - } - - if ($scope.wallet.coin == 'bch') { - bchAddresses = bitcoinCashJsService.translateAddresses(addr); - $scope.addr = bchAddresses[$scope.bchAddressType.type]; - $scope.addrBchLegacy = bchAddresses['legacy']; - - // listen to bch address - currentAddressSocket = new WebSocket("wss://ws.blockchain.info/bch/inv"); - paymentSubscriptionObj.addr = bchAddresses['legacy']; - + if ($scope.wallet.coin === 'bch') { + bchAddresses = bitcoinCashJsService.translateAddresses(addr); + $scope.addr = bchAddresses[$scope.bchAddressType.type]; + $scope.addrBchLegacy = bchAddresses['legacy']; } else { - $scope.addr = addr; - - // listen to btc address - currentAddressSocket = new WebSocket("wss://ws.blockchain.info/inv"); - paymentSubscriptionObj.addr = $scope.addr + $scope.addr = addr; } + connectSocket(); + if (copyAddress === true) { try { clipboardService.copyToClipboard($scope.wallet.coin == 'bch' && $scope.bchAddressType.type == 'cashaddr' ? 'bitcoincash:' + $scope.addr : $scope.addr); @@ -66,19 +100,6 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi $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() { $scope.$apply(); @@ -233,6 +254,16 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi } }; + $scope.$on("$ionicView.beforeLeave", function() { + // Close the old connection! + if (currentAddressSocket && typeof currentAddressSocket.close === 'function') { + console.log("Close open websocket address connection."); + currentAddressSocket.onclose = function(e) {}; // Overwrite onclose-function to prevent reconnecting old address socket. + currentAddressSocket.close(); + } + + }); + $scope.$on("$ionicView.beforeEnter", function(event, data) { $scope.wallets = profileService.getWallets(); $scope.singleWallet = $scope.wallets.length == 1; From 908dcbf9680a32ab1dcb8add6a3c085aca2b6451 Mon Sep 17 00:00:00 2001 From: Sebastiaan Pasma Date: Wed, 12 Sep 2018 16:50:26 +0200 Subject: [PATCH 05/23] Add the received wallet status to the wallet API object --- src/js/controllers/wallet-selector.controller.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/js/controllers/wallet-selector.controller.js b/src/js/controllers/wallet-selector.controller.js index 3fe10b931..c0210213f 100644 --- a/src/js/controllers/wallet-selector.controller.js +++ b/src/js/controllers/wallet-selector.controller.js @@ -123,6 +123,7 @@ angular.module('copayApp.controllers').controller('walletSelectorController', fu walletsAll.forEach(function forWallet(wallet) { if (!wallet.status) { walletService.getStatus(wallet, {}, function(err, status) { + wallet.status = status; if (status.availableBalanceSat > ($scope.params.amount ? $scope.params.amount : 0)) { walletsSufficientFunds.push(wallet); } else { From eb3067d369cbc0de58b16715c2c4d4fc97b69c10 Mon Sep 17 00:00:00 2001 From: Sebastiaan Pasma Date: Thu, 13 Sep 2018 09:47:45 +0200 Subject: [PATCH 06/23] Use cachedStatus when available and a fix for the review controller --- src/js/controllers/review.controller.js | 4 ++-- src/js/controllers/wallet-selector.controller.js | 11 +++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/js/controllers/review.controller.js b/src/js/controllers/review.controller.js index 15f982f2f..b8379b769 100644 --- a/src/js/controllers/review.controller.js +++ b/src/js/controllers/review.controller.js @@ -392,12 +392,12 @@ function reviewController(addressbookService, bitcoinCashJsService, bitcore, bit var balanceCryptoAmount = ''; var balanceCryptoCurrencyCode = ''; var balanceFiatAmount = ''; - var balanceFiatCurrency = '' + var balanceFiatCurrency = ''; var displayAmount = ''; var displayCurrency = ''; var walletStatus = null; - if (wallet.status.isValid) { + if (wallet.status && wallet.status.isValid) { walletStatus = wallet.status; } else if (wallet.cachedStatus.isValid) { walletStatus = wallet.cachedStatus; diff --git a/src/js/controllers/wallet-selector.controller.js b/src/js/controllers/wallet-selector.controller.js index c0210213f..62ac6a57a 100644 --- a/src/js/controllers/wallet-selector.controller.js +++ b/src/js/controllers/wallet-selector.controller.js @@ -121,7 +121,7 @@ angular.module('copayApp.controllers').controller('walletSelectorController', fu walletsAll = profileService.getWallets({coin: $scope.coin}); ongoingProcess.set('scanning', true); walletsAll.forEach(function forWallet(wallet) { - if (!wallet.status) { + if (!wallet.status && !wallet.cachedStatus) { walletService.getStatus(wallet, {}, function(err, status) { wallet.status = status; if (status.availableBalanceSat > ($scope.params.amount ? $scope.params.amount : 0)) { @@ -132,7 +132,14 @@ angular.module('copayApp.controllers').controller('walletSelectorController', fu ongoingProcess.set('scanning', false); }); } else { - if (wallet.status.availableBalanceSat > ($scope.params.amount ? $scope.params.amount : 0)) { + var walletStatus = null; + if (wallet.status && wallet.status.isValid) { + walletStatus = wallet.status; + } else if (wallet.cachedStatus) { + walletStatus = wallet.cachedStatus; + } + + if (walletStatus.availableBalanceSat > ($scope.params.amount ? $scope.params.amount : 0)) { walletsSufficientFunds.push(wallet); } else { $scope.walletsInsufficientFunds.push(wallet); From e6d8ddb360d64f7d6c23e8ef45dfbba0d29ed305 Mon Sep 17 00:00:00 2001 From: Sebastiaan Pasma Date: Thu, 13 Sep 2018 09:54:53 +0200 Subject: [PATCH 07/23] update wallets in the promise callback --- src/js/controllers/wallet-selector.controller.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/js/controllers/wallet-selector.controller.js b/src/js/controllers/wallet-selector.controller.js index 62ac6a57a..1a191870d 100644 --- a/src/js/controllers/wallet-selector.controller.js +++ b/src/js/controllers/wallet-selector.controller.js @@ -129,6 +129,11 @@ angular.module('copayApp.controllers').controller('walletSelectorController', fu } else { $scope.walletsInsufficientFunds.push(wallet); } + if ($scope.coin === 'btc') { // As this is a promise + $scope.walletsBtc = walletsSufficientFunds; + } else { + $scope.walletsBch = walletsSufficientFunds; + } ongoingProcess.set('scanning', false); }); } else { From 8bf31f97d8034e83d434ea181f51a6d3024de25f Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Sat, 15 Sep 2018 18:00:34 +1200 Subject: [PATCH 08/23] Updated translations from Crowdin. --- i18n/po/ca/template-ca.po | 87 ++++++++++++++++++++++++++- i18n/po/cs/template-cs.po | 93 ++++++++++++++++++++++++++-- i18n/po/de/template-de.po | 87 ++++++++++++++++++++++++++- i18n/po/es-ES/template-es-ES.po | 91 ++++++++++++++++++++++++++-- i18n/po/fa/template-fa.po | 89 +++++++++++++++++++++++++-- i18n/po/fr/template-fr.po | 91 ++++++++++++++++++++++++++-- i18n/po/it/template-it.po | 87 ++++++++++++++++++++++++++- i18n/po/ja/template-ja.po | 89 +++++++++++++++++++++++++-- i18n/po/ko/template-ko.po | 93 ++++++++++++++++++++++++++-- i18n/po/nl/template-nl.po | 91 ++++++++++++++++++++++++++-- i18n/po/pl/template-pl.po | 87 ++++++++++++++++++++++++++- i18n/po/pt-BR/template-pt-BR.po | 97 +++++++++++++++++++++++++++--- i18n/po/ru/template-ru.po | 87 ++++++++++++++++++++++++++- i18n/po/sv-SE/template-sv-SE.po | 87 ++++++++++++++++++++++++++- i18n/po/vi/template-vi.po | 103 ++++++++++++++++++++++++++++---- i18n/po/zh-CN/template-zh-CN.po | 89 +++++++++++++++++++++++++-- 16 files changed, 1372 insertions(+), 76 deletions(-) diff --git a/i18n/po/ca/template-ca.po b/i18n/po/ca/template-ca.po index 54c5202f2..0fa97d8ab 100644 --- a/i18n/po/ca/template-ca.po +++ b/i18n/po/ca/template-ca.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Catalan\n" "Language: ca\n" -"PO-Revision-Date: 2018-08-21 03:39\n" +"PO-Revision-Date: 2018-09-15 05:56\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -520,7 +520,7 @@ msgid "Cannot Create Wallet" msgstr "No es pot crear la cartera" #: src/js/services/profileService.js:442 -msgid "Cannot join the same wallet more that once" +msgid "Cannot join the same wallet more than once" msgstr "No us podeu unir a la mateixa cartera més d'un cop" #: www/views/includes/bitpayCardsCard.html:2 @@ -2925,10 +2925,15 @@ msgid "Sweep" msgstr "Escombratge" #: www/views/includes/incomingDataMenu.html:89 -#: www/views/paperWallet.html:3 +msgctxt "List item" msgid "Sweep paper wallet" msgstr "Escombra la cartera de paper" +#: www/views/paperWallet.html:3 +msgctxt "Page title" +msgid "Sweep Paper Wallet" +msgstr "Escombra la cartera de paper" + #: src/js/services/onGoingProcess.js:33 msgid "Sweeping Wallet..." msgstr "S'està escombrant la cartera..." @@ -3792,6 +3797,10 @@ msgstr "Explora Bitcoin.com" msgid "Bitcoin Cash Games" msgstr "Jocs de Bitcoin Cash" +#: www/views/includes/community.html:29 +msgid "Share the Wallet App" +msgstr "Comparteix l'aplicació de la cartera" + #: src/js/services/bitcoincomService.js:28 msgid "News" msgstr "Notícies" @@ -3860,3 +3869,75 @@ msgstr "Menys d'1 cèntim" msgid "This invoice is no longer accepting payments" msgstr "Aquesta factura ja no accepta pagaments" +#: www/views/amount.html.js:60 +msgid "Send Maximum Amount" +msgstr "Envia la quantitat màxima" + +#: src/js/controllers/amount.controller.js:239 +msgid "Unknown error." +msgstr "Error desconegut." + +#: www/views/paperWallet.html:48 +msgid "No Bitcoin Cash wallet to transfer funds to found." +msgstr "No hi ha cap cartera de Bitcoin Cash per transferir els fons trobats." + +#: www/views/paperWallet.html:54 +msgid "No Bitcoin Cash found." +msgstr "No s'ha trobat cap Bitcoin Cash." + +#: www/views/paperWallet.html:60 +msgid "Bitcoin Core found:" +msgstr "S'ha trobat Bitcoin Core:" + +#: www/views/paperWallet.html:98 +msgid "No Bitcoin Core wallet to transfer funds to found." +msgstr "No hi ha cap cartera de Bitcoin Core per transferir els fons trobats." + +#: www/views/paperWallet.html:104 +msgid "No Bitcoin Core found." +msgstr "No s'ha trobat cap Bitcoin Core." + +#: src/js/controllers/tab-scan.js:120 +msgid "Scan Failed" +msgstr "L'escaneig ha fallat" + +#: src/js/controllers/tab-scan.js:121 +msgid "Data not recognised." +msgstr "No s'han reconegut les dades." + +#: src/js/controllers/tab-scan.js:121 +msgid "Unsupported" +msgstr "No compatible" + +#: src/js/controllers/tab-scan.js:121 +msgid "Testnet is not supported." +msgstr "Testnet no és compatible." + +#: www/views/includes/incomingDataMenu.html:81 +msgid "URL" +msgstr "URL" + +#: www/views/includes/incomingDataMenu.html:90 +msgid "Open in web browser" +msgstr "Obre a l'explorador web" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid address" +msgstr "Adreça no vàlida" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is not defined" +msgstr "No s'ha definit l'import" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is below the minimun" +msgstr "L'import és inferior al mínim" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is above the limit" +msgstr "L'import supera el límit" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid response from Shapeshift" +msgstr "Resposta no vàlida de Shapeshift" + diff --git a/i18n/po/cs/template-cs.po b/i18n/po/cs/template-cs.po index 9627e2119..970b81daf 100644 --- a/i18n/po/cs/template-cs.po +++ b/i18n/po/cs/template-cs.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Czech\n" "Language: cs\n" -"PO-Revision-Date: 2018-08-21 03:39\n" +"PO-Revision-Date: 2018-09-15 05:56\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -520,8 +520,8 @@ msgid "Cannot Create Wallet" msgstr "Není možné vytvořit peněženku" #: src/js/services/profileService.js:442 -msgid "Cannot join the same wallet more that once" -msgstr "Není možné několikrát sloučit stejnou peněženku" +msgid "Cannot join the same wallet more than once" +msgstr "Nelze se připojit vícekrát ke stejné peněžence" #: www/views/includes/bitpayCardsCard.html:2 msgid "Cards" @@ -1297,7 +1297,7 @@ msgstr "Nastavení filtru" #: src/js/services/fingerprintService.js:43 #: src/js/services/fingerprintService.js:48 msgid "Finger Scan Failed" -msgstr "Scan otisku prstu se nezdařil" +msgstr "Sken otisku prstu se nezdařil" #: src/js/controllers/feedback/send.js:34 #: www/views/feedback/complete.html:7 @@ -1667,7 +1667,7 @@ msgstr "Neplatná odvozovací cesta" #: src/js/controllers/copayers.js:90 msgid "Invitation to share a {{appName}} Wallet" -msgstr "Pozvání ke sdílení {{appName}} peněženky" +msgstr "Pozvánka ke sdílení {{appName}} peněženky" #: www/views/mercadoLibreCards.html:20 #: www/views/modals/mercadolibre-card-details.html:48 @@ -2925,10 +2925,15 @@ msgid "Sweep" msgstr "Sweep" #: www/views/includes/incomingDataMenu.html:89 -#: www/views/paperWallet.html:3 +msgctxt "List item" msgid "Sweep paper wallet" msgstr "Sweep papírové peněženky" +#: www/views/paperWallet.html:3 +msgctxt "Page title" +msgid "Sweep Paper Wallet" +msgstr "Sweep papírové peněženky" + #: src/js/services/onGoingProcess.js:33 msgid "Sweeping Wallet..." msgstr "Probíhá sweep peněženky..." @@ -3792,6 +3797,10 @@ msgstr "Prohlédnout Bitcoin.com" msgid "Bitcoin Cash Games" msgstr "Bitcoin Cash hry" +#: www/views/includes/community.html:29 +msgid "Share the Wallet App" +msgstr "Sdílet aplikaci peněženky" + #: src/js/services/bitcoincomService.js:28 msgid "News" msgstr "Novinky" @@ -3860,3 +3869,75 @@ msgstr "Méně než 1 koruna" msgid "This invoice is no longer accepting payments" msgstr "Tato faktura již nepřijímá platby" +#: www/views/amount.html.js:60 +msgid "Send Maximum Amount" +msgstr "Odeslat maximální částku" + +#: src/js/controllers/amount.controller.js:239 +msgid "Unknown error." +msgstr "Neznámá chyba." + +#: www/views/paperWallet.html:48 +msgid "No Bitcoin Cash wallet to transfer funds to found." +msgstr "Žádná Bitcoin Cash peněženka pro transfer nalezených prostředků." + +#: www/views/paperWallet.html:54 +msgid "No Bitcoin Cash found." +msgstr "Žádný Bitcoin Cash nenalezen." + +#: www/views/paperWallet.html:60 +msgid "Bitcoin Core found:" +msgstr "Nalezen Bitcoin Core:" + +#: www/views/paperWallet.html:98 +msgid "No Bitcoin Core wallet to transfer funds to found." +msgstr "Žádná Bitcoin Core peněženka pro transfer nalezených prostředků." + +#: www/views/paperWallet.html:104 +msgid "No Bitcoin Core found." +msgstr "Žádný Bitcoin Core nenalezen." + +#: src/js/controllers/tab-scan.js:120 +msgid "Scan Failed" +msgstr "Sken selhal" + +#: src/js/controllers/tab-scan.js:121 +msgid "Data not recognised." +msgstr "Data nebyla rozpoznána." + +#: src/js/controllers/tab-scan.js:121 +msgid "Unsupported" +msgstr "Nepodporováno" + +#: src/js/controllers/tab-scan.js:121 +msgid "Testnet is not supported." +msgstr "Testnet není podporován." + +#: www/views/includes/incomingDataMenu.html:81 +msgid "URL" +msgstr "URL" + +#: www/views/includes/incomingDataMenu.html:90 +msgid "Open in web browser" +msgstr "Otevřít ve webovém prohlížeči" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid address" +msgstr "Neplatná adresa" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is not defined" +msgstr "Částka nedefinována" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is below the minimun" +msgstr "Nižší než minimální částka" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is above the limit" +msgstr "Nadlimitní částka" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid response from Shapeshift" +msgstr "Neplatná odpověď z Shapeshift" + diff --git a/i18n/po/de/template-de.po b/i18n/po/de/template-de.po index e15683a63..d2ea6cc62 100644 --- a/i18n/po/de/template-de.po +++ b/i18n/po/de/template-de.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: German\n" "Language: de\n" -"PO-Revision-Date: 2018-08-21 03:39\n" +"PO-Revision-Date: 2018-09-15 05:56\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -520,7 +520,7 @@ msgid "Cannot Create Wallet" msgstr "Wallet kann nicht erstellt werden" #: src/js/services/profileService.js:442 -msgid "Cannot join the same wallet more that once" +msgid "Cannot join the same wallet more than once" msgstr "An einem Wallet kann nicht mehrfach teilgenommen werden" #: www/views/includes/bitpayCardsCard.html:2 @@ -2925,10 +2925,15 @@ msgid "Sweep" msgstr "Leeren" #: www/views/includes/incomingDataMenu.html:89 -#: www/views/paperWallet.html:3 +msgctxt "List item" msgid "Sweep paper wallet" msgstr "Paperwallet löschen" +#: www/views/paperWallet.html:3 +msgctxt "Page title" +msgid "Sweep Paper Wallet" +msgstr "Paperwallet löschen" + #: src/js/services/onGoingProcess.js:33 msgid "Sweeping Wallet..." msgstr "Leere Wallet..." @@ -3792,6 +3797,10 @@ msgstr "Erkunden Sie Bitcoin.com" msgid "Bitcoin Cash Games" msgstr "Bitcoin Cash Spiele" +#: www/views/includes/community.html:29 +msgid "Share the Wallet App" +msgstr "Die Wallet-App teilen" + #: src/js/services/bitcoincomService.js:28 msgid "News" msgstr "Neuigkeiten" @@ -3860,3 +3869,75 @@ msgstr "Weniger als 1 Cent" msgid "This invoice is no longer accepting payments" msgstr "Diese Rechnung akzeptiert keine Zahlungen mehr" +#: www/views/amount.html.js:60 +msgid "Send Maximum Amount" +msgstr "Maximalen Betrag senden" + +#: src/js/controllers/amount.controller.js:239 +msgid "Unknown error." +msgstr "Unbekannter Fehler." + +#: www/views/paperWallet.html:48 +msgid "No Bitcoin Cash wallet to transfer funds to found." +msgstr "Keine Bitcoin Cash Wallet, zu welchem Geld verschickt werden kann, gefunden." + +#: www/views/paperWallet.html:54 +msgid "No Bitcoin Cash found." +msgstr "Kein Bitcoin Cash gefunden." + +#: www/views/paperWallet.html:60 +msgid "Bitcoin Core found:" +msgstr "Bitcoin Core gefunden:" + +#: www/views/paperWallet.html:98 +msgid "No Bitcoin Core wallet to transfer funds to found." +msgstr "Keine Bitcoin Core Wallet, zu welchem Geld verschickt werden kann, gefunden." + +#: www/views/paperWallet.html:104 +msgid "No Bitcoin Core found." +msgstr "Kein Bitcoin Core gefunden." + +#: src/js/controllers/tab-scan.js:120 +msgid "Scan Failed" +msgstr "Scan ist fehlgeschlagen" + +#: src/js/controllers/tab-scan.js:121 +msgid "Data not recognised." +msgstr "Daten nicht erkannt." + +#: src/js/controllers/tab-scan.js:121 +msgid "Unsupported" +msgstr "Nicht unterstützt" + +#: src/js/controllers/tab-scan.js:121 +msgid "Testnet is not supported." +msgstr "Testnet wird nicht unterstützt." + +#: www/views/includes/incomingDataMenu.html:81 +msgid "URL" +msgstr "URL" + +#: www/views/includes/incomingDataMenu.html:90 +msgid "Open in web browser" +msgstr "Im Webbrowser öffnen" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid address" +msgstr "Ungültige Adresse" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is not defined" +msgstr "Betrag ist nicht definiert" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is below the minimun" +msgstr "Menge liegt unter dem Minimum" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is above the limit" +msgstr "Betrag ist über dem Grenzwert" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid response from Shapeshift" +msgstr "Ungültige Antwort von Shapeshift" + diff --git a/i18n/po/es-ES/template-es-ES.po b/i18n/po/es-ES/template-es-ES.po index 76f004f41..2a22d3593 100644 --- a/i18n/po/es-ES/template-es-ES.po +++ b/i18n/po/es-ES/template-es-ES.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Spanish\n" "Language: es\n" -"PO-Revision-Date: 2018-08-21 03:40\n" +"PO-Revision-Date: 2018-09-15 05:56\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -520,7 +520,7 @@ msgid "Cannot Create Wallet" msgstr "No se pudo crear la billetera" #: src/js/services/profileService.js:442 -msgid "Cannot join the same wallet more that once" +msgid "Cannot join the same wallet more than once" msgstr "No puede unirse a la misma billetera más de una vez" #: www/views/includes/bitpayCardsCard.html:2 @@ -2674,7 +2674,7 @@ msgstr "Guardar las direcciones que usas frecuentemente y envía Bitcoin en un c #: www/views/tab-send.html:55 msgid "Add your first contact" -msgstr "Añadie tu primer contacto" +msgstr "Añade tu primer contacto" #: www/views/tab-send.html:65 msgid "Your Bitcoin wallet is empty" @@ -2925,9 +2925,14 @@ msgid "Sweep" msgstr "Importar" #: www/views/includes/incomingDataMenu.html:89 -#: www/views/paperWallet.html:3 +msgctxt "List item" msgid "Sweep paper wallet" -msgstr "Importar billetera en papel" +msgstr "Importar billetera de papel" + +#: www/views/paperWallet.html:3 +msgctxt "Page title" +msgid "Sweep Paper Wallet" +msgstr "Importar billetera de papel" #: src/js/services/onGoingProcess.js:33 msgid "Sweeping Wallet..." @@ -3792,6 +3797,10 @@ msgstr "Explora Bitcoin.com" msgid "Bitcoin Cash Games" msgstr "Juegos de Bitcoin Cash" +#: www/views/includes/community.html:29 +msgid "Share the Wallet App" +msgstr "Comparte esta app" + #: src/js/services/bitcoincomService.js:28 msgid "News" msgstr "Noticias" @@ -3860,3 +3869,75 @@ msgstr "Menos de 1 centavo" msgid "This invoice is no longer accepting payments" msgstr "Esta factura ya no está aceptando pagos" +#: www/views/amount.html.js:60 +msgid "Send Maximum Amount" +msgstr "Enviar cantidad máxima" + +#: src/js/controllers/amount.controller.js:239 +msgid "Unknown error." +msgstr "Error desconocido." + +#: www/views/paperWallet.html:48 +msgid "No Bitcoin Cash wallet to transfer funds to found." +msgstr "No se encontró billetera BCH para transferir estos fondos." + +#: www/views/paperWallet.html:54 +msgid "No Bitcoin Cash found." +msgstr "No se encontró Bitcoin Cash." + +#: www/views/paperWallet.html:60 +msgid "Bitcoin Core found:" +msgstr "Bitcoin Core encontrado:" + +#: www/views/paperWallet.html:98 +msgid "No Bitcoin Core wallet to transfer funds to found." +msgstr "No se encontró billetera BTC para transferir estos fondos." + +#: www/views/paperWallet.html:104 +msgid "No Bitcoin Core found." +msgstr "No se encontró Bitcoin Core." + +#: src/js/controllers/tab-scan.js:120 +msgid "Scan Failed" +msgstr "Falló el escaneado" + +#: src/js/controllers/tab-scan.js:121 +msgid "Data not recognised." +msgstr "Datos no reconocidos." + +#: src/js/controllers/tab-scan.js:121 +msgid "Unsupported" +msgstr "No compatible" + +#: src/js/controllers/tab-scan.js:121 +msgid "Testnet is not supported." +msgstr "Testnet no es compatible." + +#: www/views/includes/incomingDataMenu.html:81 +msgid "URL" +msgstr "URL" + +#: www/views/includes/incomingDataMenu.html:90 +msgid "Open in web browser" +msgstr "Abrir en navegador web" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid address" +msgstr "Dirección inválida" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is not defined" +msgstr "Cantidad no definida" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is below the minimun" +msgstr "Cantidad por debajo del mínimo" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is above the limit" +msgstr "Cantidad por encima del límite" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid response from Shapeshift" +msgstr "Respuesta inválida de Shapeshift" + diff --git a/i18n/po/fa/template-fa.po b/i18n/po/fa/template-fa.po index 4be7a1e8d..d2b460320 100644 --- a/i18n/po/fa/template-fa.po +++ b/i18n/po/fa/template-fa.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Persian\n" "Language: fa\n" -"PO-Revision-Date: 2018-08-21 03:39\n" +"PO-Revision-Date: 2018-09-15 05:56\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -520,7 +520,7 @@ msgid "Cannot Create Wallet" msgstr "قادر به ایجاد کیف پول نیست" #: src/js/services/profileService.js:442 -msgid "Cannot join the same wallet more that once" +msgid "Cannot join the same wallet more than once" msgstr "امکان بیش از یک بار پیوستن به یک کیف پول نیست" #: www/views/includes/bitpayCardsCard.html:2 @@ -2925,9 +2925,14 @@ msgid "Sweep" msgstr "وارد کردن و تغییر آدرس به جدید(sweep)" #: www/views/includes/incomingDataMenu.html:89 -#: www/views/paperWallet.html:3 +msgctxt "List item" msgid "Sweep paper wallet" -msgstr "وارد کردن والت کاغذی و تغییر آدرس به جدید(sweep)" +msgstr "جاروب کردن کیف پول کاغذی" + +#: www/views/paperWallet.html:3 +msgctxt "Page title" +msgid "Sweep Paper Wallet" +msgstr "جاروب کردن کیف پول کاغذی" #: src/js/services/onGoingProcess.js:33 msgid "Sweeping Wallet..." @@ -3792,6 +3797,10 @@ msgstr "کاوش Bitcoin.com" msgid "Bitcoin Cash Games" msgstr "Bitcoin Cash Games" +#: www/views/includes/community.html:29 +msgid "Share the Wallet App" +msgstr "اشتراک گذاری نرم افزار کیف پول" + #: src/js/services/bitcoincomService.js:28 msgid "News" msgstr "اخبار" @@ -3860,3 +3869,75 @@ msgstr "کمتر از 1 سنت" msgid "This invoice is no longer accepting payments" msgstr "این صورت حساب دیگر پرداخت ها را نمی پذیرد" +#: www/views/amount.html.js:60 +msgid "Send Maximum Amount" +msgstr "ارسال حداکثر مقدار" + +#: src/js/controllers/amount.controller.js:239 +msgid "Unknown error." +msgstr "خطای ناشناخته." + +#: www/views/paperWallet.html:48 +msgid "No Bitcoin Cash wallet to transfer funds to found." +msgstr "هیچ کیف پولی از نوع Bitcoin Cash برای انتقال وجه یافت نشد." + +#: www/views/paperWallet.html:54 +msgid "No Bitcoin Cash found." +msgstr "Bitcoin Cash یافت نشد." + +#: www/views/paperWallet.html:60 +msgid "Bitcoin Core found:" +msgstr "Bitcoin Core یافت شده:" + +#: www/views/paperWallet.html:98 +msgid "No Bitcoin Core wallet to transfer funds to found." +msgstr "هیچ کیف پولی از نوع Bitcoin Core برای انتقال وجه یافت نشد." + +#: www/views/paperWallet.html:104 +msgid "No Bitcoin Core found." +msgstr "Bitcoin Core یافت نشد." + +#: src/js/controllers/tab-scan.js:120 +msgid "Scan Failed" +msgstr "اسکن انجام نشد" + +#: src/js/controllers/tab-scan.js:121 +msgid "Data not recognised." +msgstr "داده ها شناسایی نشد." + +#: src/js/controllers/tab-scan.js:121 +msgid "Unsupported" +msgstr "پشتیبانی نشده" + +#: src/js/controllers/tab-scan.js:121 +msgid "Testnet is not supported." +msgstr "Testnet پشتیبانی نمی شود." + +#: www/views/includes/incomingDataMenu.html:81 +msgid "URL" +msgstr "آدرس" + +#: www/views/includes/incomingDataMenu.html:90 +msgid "Open in web browser" +msgstr "باز کردن در مرورگر" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid address" +msgstr "آدرس نامعتبر" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is not defined" +msgstr "مبلغ تعریف نشده است" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is below the minimun" +msgstr "مقدار زیر مقدار حداقل است" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is above the limit" +msgstr "مقدار بالاتر از حد است" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid response from Shapeshift" +msgstr "پاسخ نامعتبر از Shapeshift" + diff --git a/i18n/po/fr/template-fr.po b/i18n/po/fr/template-fr.po index aa22631e2..ba3d98244 100644 --- a/i18n/po/fr/template-fr.po +++ b/i18n/po/fr/template-fr.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: French\n" "Language: fr\n" -"PO-Revision-Date: 2018-08-21 03:39\n" +"PO-Revision-Date: 2018-09-15 05:56\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -520,8 +520,8 @@ msgid "Cannot Create Wallet" msgstr "Impossible de créer le portefeuille" #: src/js/services/profileService.js:442 -msgid "Cannot join the same wallet more that once" -msgstr "Impossible de rejoindre le même portefeuille plus d'une fois" +msgid "Cannot join the same wallet more than once" +msgstr "Impossible de joindre le même portefeuille plus d'une fois" #: www/views/includes/bitpayCardsCard.html:2 msgid "Cards" @@ -2925,9 +2925,14 @@ msgid "Sweep" msgstr "Balayer" #: www/views/includes/incomingDataMenu.html:89 -#: www/views/paperWallet.html:3 +msgctxt "List item" msgid "Sweep paper wallet" -msgstr "Balayer un portefeuille de papier" +msgstr "Balayer un portefeuille papier" + +#: www/views/paperWallet.html:3 +msgctxt "Page title" +msgid "Sweep Paper Wallet" +msgstr "Balayer un portefeuille papier" #: src/js/services/onGoingProcess.js:33 msgid "Sweeping Wallet..." @@ -3792,6 +3797,10 @@ msgstr "Explorez Bitcoin.com" msgid "Bitcoin Cash Games" msgstr "Jeux Bitcoin Cash" +#: www/views/includes/community.html:29 +msgid "Share the Wallet App" +msgstr "Partager l’application Wallet" + #: src/js/services/bitcoincomService.js:28 msgid "News" msgstr "Nouvelles" @@ -3860,3 +3869,75 @@ msgstr "Moins de 1 centime" msgid "This invoice is no longer accepting payments" msgstr "Cette facture n’accepte plus les paiements" +#: www/views/amount.html.js:60 +msgid "Send Maximum Amount" +msgstr "Envoi du montant maximal" + +#: src/js/controllers/amount.controller.js:239 +msgid "Unknown error." +msgstr "Erreur inconnue." + +#: www/views/paperWallet.html:48 +msgid "No Bitcoin Cash wallet to transfer funds to found." +msgstr "Aucun portefeuille Bitcoin Cash auquel transférer des fonds trouvé." + +#: www/views/paperWallet.html:54 +msgid "No Bitcoin Cash found." +msgstr "Pas de Bitcoin Cash trouvé." + +#: www/views/paperWallet.html:60 +msgid "Bitcoin Core found:" +msgstr "Bitcoin Core trouvé :" + +#: www/views/paperWallet.html:98 +msgid "No Bitcoin Core wallet to transfer funds to found." +msgstr "Aucun portefeuille Bitcoin Core auquel transférer des fonds trouvé." + +#: www/views/paperWallet.html:104 +msgid "No Bitcoin Core found." +msgstr "Pas de Bitcoin Core trouvé." + +#: src/js/controllers/tab-scan.js:120 +msgid "Scan Failed" +msgstr "Échec de l'analyse" + +#: src/js/controllers/tab-scan.js:121 +msgid "Data not recognised." +msgstr "Données non reconnues." + +#: src/js/controllers/tab-scan.js:121 +msgid "Unsupported" +msgstr "Non pris en charge" + +#: src/js/controllers/tab-scan.js:121 +msgid "Testnet is not supported." +msgstr "Testnet n’est pas pris en charge." + +#: www/views/includes/incomingDataMenu.html:81 +msgid "URL" +msgstr "URL" + +#: www/views/includes/incomingDataMenu.html:90 +msgid "Open in web browser" +msgstr "Ouvrir dans le navigateur web" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid address" +msgstr "Adresse invalide" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is not defined" +msgstr "Le montant n’est pas défini" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is below the minimun" +msgstr "Le montant est inférieur au minimum" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is above the limit" +msgstr "Le montant est supérieur à la limite" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid response from Shapeshift" +msgstr "Réponse de Shapeshift invalide" + diff --git a/i18n/po/it/template-it.po b/i18n/po/it/template-it.po index d0ac86478..0ea7daa0a 100644 --- a/i18n/po/it/template-it.po +++ b/i18n/po/it/template-it.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Italian\n" "Language: it\n" -"PO-Revision-Date: 2018-08-21 03:39\n" +"PO-Revision-Date: 2018-09-15 05:56\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -520,7 +520,7 @@ msgid "Cannot Create Wallet" msgstr "Impossibile creare portafoglio" #: src/js/services/profileService.js:442 -msgid "Cannot join the same wallet more that once" +msgid "Cannot join the same wallet more than once" msgstr "Non è possibile aggiungere un portafoglio più di una volta" #: www/views/includes/bitpayCardsCard.html:2 @@ -2925,10 +2925,15 @@ msgid "Sweep" msgstr "Spazzola" #: www/views/includes/incomingDataMenu.html:89 -#: www/views/paperWallet.html:3 +msgctxt "List item" msgid "Sweep paper wallet" msgstr "Spazzare il portafoglio di carta" +#: www/views/paperWallet.html:3 +msgctxt "Page title" +msgid "Sweep Paper Wallet" +msgstr "Spazzare il portafoglio di carta" + #: src/js/services/onGoingProcess.js:33 msgid "Sweeping Wallet..." msgstr "Spazzolamento Portafoglio..." @@ -3792,6 +3797,10 @@ msgstr "Esplora Bitcoin.com" msgid "Bitcoin Cash Games" msgstr "Giochi Bitcoin Cash" +#: www/views/includes/community.html:29 +msgid "Share the Wallet App" +msgstr "Condividere l'app Portafoglio" + #: src/js/services/bitcoincomService.js:28 msgid "News" msgstr "News" @@ -3860,3 +3869,75 @@ msgstr "Meno di 1 centesimo" msgid "This invoice is no longer accepting payments" msgstr "Questa fattura non accetta più pagamenti" +#: www/views/amount.html.js:60 +msgid "Send Maximum Amount" +msgstr "Inviare importo massimo" + +#: src/js/controllers/amount.controller.js:239 +msgid "Unknown error." +msgstr "Errore sconosciuto." + +#: www/views/paperWallet.html:48 +msgid "No Bitcoin Cash wallet to transfer funds to found." +msgstr "Nessun portafoglio Bitcoin Cash trovato per il trasferimento di fondi." + +#: www/views/paperWallet.html:54 +msgid "No Bitcoin Cash found." +msgstr "Nessun Bitcoin Cash trovato." + +#: www/views/paperWallet.html:60 +msgid "Bitcoin Core found:" +msgstr "Bitcoin Core trovato:" + +#: www/views/paperWallet.html:98 +msgid "No Bitcoin Core wallet to transfer funds to found." +msgstr "Nessun portafoglio Bitcoin Core trovato per il trasferimento di fondi." + +#: www/views/paperWallet.html:104 +msgid "No Bitcoin Core found." +msgstr "Nessun Bitcoin Core trovato." + +#: src/js/controllers/tab-scan.js:120 +msgid "Scan Failed" +msgstr "Scansione non riuscita" + +#: src/js/controllers/tab-scan.js:121 +msgid "Data not recognised." +msgstr "Dati non riconosciuti." + +#: src/js/controllers/tab-scan.js:121 +msgid "Unsupported" +msgstr "Non supportato" + +#: src/js/controllers/tab-scan.js:121 +msgid "Testnet is not supported." +msgstr "Testnet non supportato." + +#: www/views/includes/incomingDataMenu.html:81 +msgid "URL" +msgstr "URL" + +#: www/views/includes/incomingDataMenu.html:90 +msgid "Open in web browser" +msgstr "Aprire nel browser web" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid address" +msgstr "Indirizzo non valido" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is not defined" +msgstr "Importo non definito" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is below the minimun" +msgstr "Importo inferiore al minimo" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is above the limit" +msgstr "Importo sopra il limite" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid response from Shapeshift" +msgstr "Risposta non valida da Shapeshift" + diff --git a/i18n/po/ja/template-ja.po b/i18n/po/ja/template-ja.po index 7fb88de4f..896e8b06c 100644 --- a/i18n/po/ja/template-ja.po +++ b/i18n/po/ja/template-ja.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Japanese\n" "Language: ja\n" -"PO-Revision-Date: 2018-08-21 03:39\n" +"PO-Revision-Date: 2018-09-15 05:56\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -522,8 +522,8 @@ msgid "Cannot Create Wallet" msgstr "ウォレットを作成できません。" #: src/js/services/profileService.js:442 -msgid "Cannot join the same wallet more that once" -msgstr "同じ端末で同じウォレットに複数回参加することができません。" +msgid "Cannot join the same wallet more than once" +msgstr "同じ端末で同じウォレットに複数回参加することはできません。" #: www/views/includes/bitpayCardsCard.html:2 msgid "Cards" @@ -2929,10 +2929,15 @@ msgid "Sweep" msgstr "全残高インポート" #: www/views/includes/incomingDataMenu.html:89 -#: www/views/paperWallet.html:3 +msgctxt "List item" msgid "Sweep paper wallet" msgstr "ペーパーウォレットの全残高インポート" +#: www/views/paperWallet.html:3 +msgctxt "Page title" +msgid "Sweep Paper Wallet" +msgstr "ペーパーウォレットの全残高インポート" + #: src/js/services/onGoingProcess.js:33 msgid "Sweeping Wallet..." msgstr "ビットコイン回収中…" @@ -3798,6 +3803,10 @@ msgstr "Bitcoin.com を参照" msgid "Bitcoin Cash Games" msgstr "Bitcoin Cash ゲーム" +#: www/views/includes/community.html:29 +msgid "Share the Wallet App" +msgstr "ウォレットアプリを共有" + #: src/js/services/bitcoincomService.js:28 msgid "News" msgstr "ニュース" @@ -3866,3 +3875,75 @@ msgstr "1セント以下" msgid "This invoice is no longer accepting payments" msgstr "この請求書はもう支払を受け付けていません" +#: www/views/amount.html.js:60 +msgid "Send Maximum Amount" +msgstr "全残高を送金" + +#: src/js/controllers/amount.controller.js:239 +msgid "Unknown error." +msgstr "不明なエラーです。" + +#: www/views/paperWallet.html:48 +msgid "No Bitcoin Cash wallet to transfer funds to found." +msgstr "資金を送金できるビットコインキャッシュウォレットが見つかりません。" + +#: www/views/paperWallet.html:54 +msgid "No Bitcoin Cash found." +msgstr "ビットコインキャッシュが見つかりません。" + +#: www/views/paperWallet.html:60 +msgid "Bitcoin Core found:" +msgstr "ビットコインが見つかりました:" + +#: www/views/paperWallet.html:98 +msgid "No Bitcoin Core wallet to transfer funds to found." +msgstr "資金を送金できるビットコインウォレットが見つかりません。" + +#: www/views/paperWallet.html:104 +msgid "No Bitcoin Core found." +msgstr "ビットコインが見つかりません。" + +#: src/js/controllers/tab-scan.js:120 +msgid "Scan Failed" +msgstr "スキャンできませんでした" + +#: src/js/controllers/tab-scan.js:121 +msgid "Data not recognised." +msgstr "データが認識されていません。" + +#: src/js/controllers/tab-scan.js:121 +msgid "Unsupported" +msgstr "未対応" + +#: src/js/controllers/tab-scan.js:121 +msgid "Testnet is not supported." +msgstr "Testnet には対応していません。" + +#: www/views/includes/incomingDataMenu.html:81 +msgid "URL" +msgstr "URL" + +#: www/views/includes/incomingDataMenu.html:90 +msgid "Open in web browser" +msgstr "ウェブブラウザで開く" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid address" +msgstr "無効なアドレス" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is not defined" +msgstr "金額が定義されていません" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is below the minimun" +msgstr "金額が最少額を下回っています" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is above the limit" +msgstr "金額が上限を超えています" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid response from Shapeshift" +msgstr "Shapeshift から無効な応答がありました" + diff --git a/i18n/po/ko/template-ko.po b/i18n/po/ko/template-ko.po index 815608a50..490acef30 100644 --- a/i18n/po/ko/template-ko.po +++ b/i18n/po/ko/template-ko.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Korean\n" "Language: ko\n" -"PO-Revision-Date: 2018-08-21 03:39\n" +"PO-Revision-Date: 2018-09-15 05:56\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -233,12 +233,12 @@ msgstr "가격 표시" #: src/js/controllers/tab-settings.js:19 #: www/views/preferencesPriceDisplay.html:12 msgid "Fiat" -msgstr "고정비" +msgstr "법정 화폐" #: src/js/controllers/tab-settings.js:19 #: www/views/preferencesPriceDisplay.html:15 msgid "Cryptocurrency" -msgstr "가상화폐" +msgstr "가상 화폐" #: src/js/controllers/buyAmazon.js:98 msgid "Amazon.com is not available at this moment. Please try back later." @@ -520,7 +520,7 @@ msgid "Cannot Create Wallet" msgstr "지갑을 생성할 수 없습니다" #: src/js/services/profileService.js:442 -msgid "Cannot join the same wallet more that once" +msgid "Cannot join the same wallet more than once" msgstr "같은 지갑에 한 번 이상 접속할 수 없습니다" #: www/views/includes/bitpayCardsCard.html:2 @@ -2658,7 +2658,7 @@ msgstr "주소 붙여넣기" #: www/views/tab-send.html:27 msgid "Transfer between wallets" -msgstr "월릿 간 전송" +msgstr "지갑 간 전송" #: www/views/tab-send.html:35 msgid "Scan QR Code" @@ -2925,10 +2925,15 @@ msgid "Sweep" msgstr "스윕하기" #: www/views/includes/incomingDataMenu.html:89 -#: www/views/paperWallet.html:3 +msgctxt "List item" msgid "Sweep paper wallet" msgstr "종이 지갑 스윕하기" +#: www/views/paperWallet.html:3 +msgctxt "Page title" +msgid "Sweep Paper Wallet" +msgstr "종이 지갑 스윕하기" + #: src/js/services/onGoingProcess.js:33 msgid "Sweeping Wallet..." msgstr "지갑 스윕 중..." @@ -3792,6 +3797,10 @@ msgstr "Bitcoin.com 탐색" msgid "Bitcoin Cash Games" msgstr "BCH 게임" +#: www/views/includes/community.html:29 +msgid "Share the Wallet App" +msgstr "지갑 응용 프로그램 공유" + #: src/js/services/bitcoincomService.js:28 msgid "News" msgstr "소식" @@ -3860,3 +3869,75 @@ msgstr "1센트 미만" msgid "This invoice is no longer accepting payments" msgstr "이 청구서는 더 이상 결제를 수락하지 않습니다" +#: www/views/amount.html.js:60 +msgid "Send Maximum Amount" +msgstr "최대 수량 보내는 중" + +#: src/js/controllers/amount.controller.js:239 +msgid "Unknown error." +msgstr "알 수 없는 오류가 발생 했습니다." + +#: www/views/paperWallet.html:48 +msgid "No Bitcoin Cash wallet to transfer funds to found." +msgstr "자금 찾을 없습니다 Bitcoin Cash 현금 지갑." + +#: www/views/paperWallet.html:54 +msgid "No Bitcoin Cash found." +msgstr "찾을 수 없습니다 Bitcoin Cash 현금." + +#: www/views/paperWallet.html:60 +msgid "Bitcoin Core found:" +msgstr "Bitcoin Core 코어 발견:" + +#: www/views/paperWallet.html:98 +msgid "No Bitcoin Core wallet to transfer funds to found." +msgstr "자금 찾을 없습니다 Bitcoin Core 현금 지갑." + +#: www/views/paperWallet.html:104 +msgid "No Bitcoin Core found." +msgstr "찾을 수 없습니다 Bitcoin Core 현금." + +#: src/js/controllers/tab-scan.js:120 +msgid "Scan Failed" +msgstr "검색 실패" + +#: src/js/controllers/tab-scan.js:121 +msgid "Data not recognised." +msgstr "데이터 인식 되지입니다." + +#: src/js/controllers/tab-scan.js:121 +msgid "Unsupported" +msgstr "지원 되지 않는" + +#: src/js/controllers/tab-scan.js:121 +msgid "Testnet is not supported." +msgstr "Testnet는 지원 되지 않습니다." + +#: www/views/includes/incomingDataMenu.html:81 +msgid "URL" +msgstr "URL" + +#: www/views/includes/incomingDataMenu.html:90 +msgid "Open in web browser" +msgstr "웹 브라우저에서 열기" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid address" +msgstr "주소 오류" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is not defined" +msgstr "금액은 정의 되지 않은" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is below the minimun" +msgstr "Minimun 아래 금액은" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is above the limit" +msgstr "제한 위에 금액은" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid response from Shapeshift" +msgstr "변신에서 잘못 된 응답" + diff --git a/i18n/po/nl/template-nl.po b/i18n/po/nl/template-nl.po index 15e0cdde1..a42a1b370 100644 --- a/i18n/po/nl/template-nl.po +++ b/i18n/po/nl/template-nl.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Dutch\n" "Language: nl\n" -"PO-Revision-Date: 2018-08-21 03:39\n" +"PO-Revision-Date: 2018-09-15 05:56\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -520,8 +520,8 @@ msgid "Cannot Create Wallet" msgstr "Kan Portemonnee Niet Aanmaken" #: src/js/services/profileService.js:442 -msgid "Cannot join the same wallet more that once" -msgstr "Kan niet meerdere keren tegelijk deelnemen aan een portemonnee" +msgid "Cannot join the same wallet more than once" +msgstr "Je kan niet meerdere keren tegelijk aan een portemonnee deelnemen" #: www/views/includes/bitpayCardsCard.html:2 msgid "Cards" @@ -2925,9 +2925,14 @@ msgid "Sweep" msgstr "Saldo opnemen" #: www/views/includes/incomingDataMenu.html:89 -#: www/views/paperWallet.html:3 +msgctxt "List item" msgid "Sweep paper wallet" -msgstr "Saldo papieren portemonnee opnemen" +msgstr "Paper wallet leeghalen" + +#: www/views/paperWallet.html:3 +msgctxt "Page title" +msgid "Sweep Paper Wallet" +msgstr "Paper wallet leeghalen" #: src/js/services/onGoingProcess.js:33 msgid "Sweeping Wallet..." @@ -3792,6 +3797,10 @@ msgstr "Bitcoin.com verkennen" msgid "Bitcoin Cash Games" msgstr "Bitcoin Cash spellen" +#: www/views/includes/community.html:29 +msgid "Share the Wallet App" +msgstr "Wallet app delen" + #: src/js/services/bitcoincomService.js:28 msgid "News" msgstr "Nieuws" @@ -3860,3 +3869,75 @@ msgstr "Minder dan 1 cent" msgid "This invoice is no longer accepting payments" msgstr "Deze factuur accepteert geen betalingen meer" +#: www/views/amount.html.js:60 +msgid "Send Maximum Amount" +msgstr "Alles versturen" + +#: src/js/controllers/amount.controller.js:239 +msgid "Unknown error." +msgstr "Onbekende fout." + +#: www/views/paperWallet.html:48 +msgid "No Bitcoin Cash wallet to transfer funds to found." +msgstr "Geen Bitcoin Cash portemonnee gevonden om bedrag naartoe over te maken." + +#: www/views/paperWallet.html:54 +msgid "No Bitcoin Cash found." +msgstr "Geen Bitcoin Cash gevonden." + +#: www/views/paperWallet.html:60 +msgid "Bitcoin Core found:" +msgstr "Bitcoin Core gevonden:" + +#: www/views/paperWallet.html:98 +msgid "No Bitcoin Core wallet to transfer funds to found." +msgstr "Geen Bitcoin Core portemonnee gevonden om waarde naartoe te versturen." + +#: www/views/paperWallet.html:104 +msgid "No Bitcoin Core found." +msgstr "Geen Bitcoin Core gevonden." + +#: src/js/controllers/tab-scan.js:120 +msgid "Scan Failed" +msgstr "Scannen mislukt" + +#: src/js/controllers/tab-scan.js:121 +msgid "Data not recognised." +msgstr "Gegevens niet herkend." + +#: src/js/controllers/tab-scan.js:121 +msgid "Unsupported" +msgstr "Niet ondersteund" + +#: src/js/controllers/tab-scan.js:121 +msgid "Testnet is not supported." +msgstr "Testnet wordt niet ondersteund." + +#: www/views/includes/incomingDataMenu.html:81 +msgid "URL" +msgstr "URL" + +#: www/views/includes/incomingDataMenu.html:90 +msgid "Open in web browser" +msgstr "Open in webbrowser" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid address" +msgstr "Ongeldig adres" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is not defined" +msgstr "Bedrag is niet gespecificeerd" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is below the minimun" +msgstr "Bedrag lager is dan het minimum" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is above the limit" +msgstr "Bedrag is boven het limiet" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid response from Shapeshift" +msgstr "Ongeldig respons van Shapeshift" + diff --git a/i18n/po/pl/template-pl.po b/i18n/po/pl/template-pl.po index 584984472..63e8e47ee 100644 --- a/i18n/po/pl/template-pl.po +++ b/i18n/po/pl/template-pl.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Polish\n" "Language: pl\n" -"PO-Revision-Date: 2018-08-21 03:40\n" +"PO-Revision-Date: 2018-09-15 05:56\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -520,7 +520,7 @@ msgid "Cannot Create Wallet" msgstr "Nie można utworzyć portfela" #: src/js/services/profileService.js:442 -msgid "Cannot join the same wallet more that once" +msgid "Cannot join the same wallet more than once" msgstr "Nie można dołączyć tego samego portfela więcej niż raz" #: www/views/includes/bitpayCardsCard.html:2 @@ -2925,10 +2925,15 @@ msgid "Sweep" msgstr "Opróżnij" #: www/views/includes/incomingDataMenu.html:89 -#: www/views/paperWallet.html:3 +msgctxt "List item" msgid "Sweep paper wallet" msgstr "Wyczyść papierowy portfel" +#: www/views/paperWallet.html:3 +msgctxt "Page title" +msgid "Sweep Paper Wallet" +msgstr "Wyczyść papierowy portfel" + #: src/js/services/onGoingProcess.js:33 msgid "Sweeping Wallet..." msgstr "Sczytywanie portfela..." @@ -3792,6 +3797,10 @@ msgstr "Poznaj Bitcoin.com" msgid "Bitcoin Cash Games" msgstr "Gry Bitcoin Cash" +#: www/views/includes/community.html:29 +msgid "Share the Wallet App" +msgstr "Udostępnij aplikację Portfel" + #: src/js/services/bitcoincomService.js:28 msgid "News" msgstr "Aktualności" @@ -3860,3 +3869,75 @@ msgstr "Mniej niż 1 cent" msgid "This invoice is no longer accepting payments" msgstr "Nie można już opłacić tej faktury" +#: www/views/amount.html.js:60 +msgid "Send Maximum Amount" +msgstr "Wyślij maksymalną kwotę" + +#: src/js/controllers/amount.controller.js:239 +msgid "Unknown error." +msgstr "Nieznany błąd." + +#: www/views/paperWallet.html:48 +msgid "No Bitcoin Cash wallet to transfer funds to found." +msgstr "Nie znaleziono portfela Bitcoin Cash do przekazania środków." + +#: www/views/paperWallet.html:54 +msgid "No Bitcoin Cash found." +msgstr "Nie znaleziono Bitcoin Cash." + +#: www/views/paperWallet.html:60 +msgid "Bitcoin Core found:" +msgstr "Znaleziono Bitcoin Core:" + +#: www/views/paperWallet.html:98 +msgid "No Bitcoin Core wallet to transfer funds to found." +msgstr "Nie znaleziono portfela Bitcoin Core do przekazania środków." + +#: www/views/paperWallet.html:104 +msgid "No Bitcoin Core found." +msgstr "Nie znaleziono Bitcoin Core." + +#: src/js/controllers/tab-scan.js:120 +msgid "Scan Failed" +msgstr "Skanowanie nie powiodło się" + +#: src/js/controllers/tab-scan.js:121 +msgid "Data not recognised." +msgstr "Nie rozpoznano danych." + +#: src/js/controllers/tab-scan.js:121 +msgid "Unsupported" +msgstr "Nieobsługiwane" + +#: src/js/controllers/tab-scan.js:121 +msgid "Testnet is not supported." +msgstr "Sieć testowa nie jest obsługiwana." + +#: www/views/includes/incomingDataMenu.html:81 +msgid "URL" +msgstr "Adres URL" + +#: www/views/includes/incomingDataMenu.html:90 +msgid "Open in web browser" +msgstr "Otwórz w przeglądarce internetowej" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid address" +msgstr "Nieprawidłowy adres" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is not defined" +msgstr "Kwota nie jest określona" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is below the minimun" +msgstr "Kwota niższa od minimalnej" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is above the limit" +msgstr "Kwota przekracza limit" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid response from Shapeshift" +msgstr "Nieprawidłowa odpowiedź z Shapeshift" + diff --git a/i18n/po/pt-BR/template-pt-BR.po b/i18n/po/pt-BR/template-pt-BR.po index 4dec70b33..7d15602e7 100644 --- a/i18n/po/pt-BR/template-pt-BR.po +++ b/i18n/po/pt-BR/template-pt-BR.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Portuguese, Brazilian\n" "Language: pt\n" -"PO-Revision-Date: 2018-08-21 03:40\n" +"PO-Revision-Date: 2018-09-15 05:56\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -520,8 +520,8 @@ msgid "Cannot Create Wallet" msgstr "Não é possível criar a carteira" #: src/js/services/profileService.js:442 -msgid "Cannot join the same wallet more that once" -msgstr "Não pode juntar-se a mesma carteira mais que uma vez" +msgid "Cannot join the same wallet more than once" +msgstr "Não pode juntar-se à mesma carteira mais que uma vez" #: www/views/includes/bitpayCardsCard.html:2 msgid "Cards" @@ -1623,7 +1623,7 @@ msgstr "Endereço de rede incorreto" #: src/js/controllers/confirm.js:306 #: src/js/services/bwcError.js:44 msgid "Insufficient confirmed funds" -msgstr "Insuficiência de fundos confirmados" +msgstr "Insuficiência de fundos confirmada" #: src/js/controllers/topup.js:165 #: src/js/controllers/topup.js:177 @@ -2090,7 +2090,7 @@ msgstr "Abrir Projeto no GitHub" #: src/js/controllers/bitpayCard.js:123 #: src/js/controllers/tx-details.js:192 msgid "Open Explorer" -msgstr "Abra o Explorer" +msgstr "Abrir o Explorer" #: www/views/tab-scan.html:22 msgid "Open Settings" @@ -2222,7 +2222,7 @@ msgstr "Detalhes do pagamento" #: www/views/modals/paypro.html:6 msgid "Payment Request" -msgstr "Pedido de pagamento" +msgstr "Solicitação de pagamento" #: www/views/mercadoLibreCards.html:22 #: www/views/modals/mercadolibre-card-details.html:39 @@ -2696,7 +2696,7 @@ msgstr "Para começar, você precisa criar uma carteira de bitcoins e obter algu #: www/views/tab-send.html:74 msgid "Buy Bitcoin now" -msgstr "Compre Bitcoin agora" +msgstr "Comprar Bitcoin agora" #: www/views/tab-send.html:76 msgid "Show my address" @@ -2925,10 +2925,15 @@ msgid "Sweep" msgstr "Limpar" #: www/views/includes/incomingDataMenu.html:89 -#: www/views/paperWallet.html:3 +msgctxt "List item" msgid "Sweep paper wallet" msgstr "Varrer a carteira de papel" +#: www/views/paperWallet.html:3 +msgctxt "Page title" +msgid "Sweep Paper Wallet" +msgstr "Varrer a carteira de papel" + #: src/js/services/onGoingProcess.js:33 msgid "Sweeping Wallet..." msgstr "Carteira de varredura..." @@ -3792,6 +3797,10 @@ msgstr "Explore Bitcoin.com" msgid "Bitcoin Cash Games" msgstr "Jogos Bitcoin Cash" +#: www/views/includes/community.html:29 +msgid "Share the Wallet App" +msgstr "Compartilhar o app de carteira" + #: src/js/services/bitcoincomService.js:28 msgid "News" msgstr "Notícias" @@ -3860,3 +3869,75 @@ msgstr "Menos de 1 centavo" msgid "This invoice is no longer accepting payments" msgstr "Essa fatura não aceita mais pagamentos" +#: www/views/amount.html.js:60 +msgid "Send Maximum Amount" +msgstr "Enviar montante máximo" + +#: src/js/controllers/amount.controller.js:239 +msgid "Unknown error." +msgstr "Erro desconhecido." + +#: www/views/paperWallet.html:48 +msgid "No Bitcoin Cash wallet to transfer funds to found." +msgstr "Nenhuma carteira de Bitcoin Cash para transferir fundos encontrada." + +#: www/views/paperWallet.html:54 +msgid "No Bitcoin Cash found." +msgstr "Bitcoin Cash não encontrado." + +#: www/views/paperWallet.html:60 +msgid "Bitcoin Core found:" +msgstr "Bitcoin Core encontrado:" + +#: www/views/paperWallet.html:98 +msgid "No Bitcoin Core wallet to transfer funds to found." +msgstr "Nenhuma carteira de Bitcoin Core para transferir fundos encontrada." + +#: www/views/paperWallet.html:104 +msgid "No Bitcoin Core found." +msgstr "Nenhum Bitcoin Core encontrado." + +#: src/js/controllers/tab-scan.js:120 +msgid "Scan Failed" +msgstr "Falha de verificação" + +#: src/js/controllers/tab-scan.js:121 +msgid "Data not recognised." +msgstr "Dados não reconhecidos." + +#: src/js/controllers/tab-scan.js:121 +msgid "Unsupported" +msgstr "Não suportado" + +#: src/js/controllers/tab-scan.js:121 +msgid "Testnet is not supported." +msgstr "Testnet não suportado." + +#: www/views/includes/incomingDataMenu.html:81 +msgid "URL" +msgstr "URL" + +#: www/views/includes/incomingDataMenu.html:90 +msgid "Open in web browser" +msgstr "Abrir no navegador da Web" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid address" +msgstr "Endereço inválido" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is not defined" +msgstr "Montante não definido" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is below the minimun" +msgstr "Montante abaixo do mínimo" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is above the limit" +msgstr "Montante acima do limite" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid response from Shapeshift" +msgstr "Resposta inválida do Shapeshift" + diff --git a/i18n/po/ru/template-ru.po b/i18n/po/ru/template-ru.po index ffdc6c0df..cb4ec3a36 100644 --- a/i18n/po/ru/template-ru.po +++ b/i18n/po/ru/template-ru.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Russian\n" "Language: ru\n" -"PO-Revision-Date: 2018-08-21 03:40\n" +"PO-Revision-Date: 2018-09-15 05:56\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -520,7 +520,7 @@ msgid "Cannot Create Wallet" msgstr "Не удаётся создать кошелёк" #: src/js/services/profileService.js:442 -msgid "Cannot join the same wallet more that once" +msgid "Cannot join the same wallet more than once" msgstr "Нельзя присоединиться к одному и тому же кошельку более одного раза" #: www/views/includes/bitpayCardsCard.html:2 @@ -2925,10 +2925,15 @@ msgid "Sweep" msgstr "Считать" #: www/views/includes/incomingDataMenu.html:89 -#: www/views/paperWallet.html:3 +msgctxt "List item" msgid "Sweep paper wallet" msgstr "Пополнить с бумажного кошелька" +#: www/views/paperWallet.html:3 +msgctxt "Page title" +msgid "Sweep Paper Wallet" +msgstr "Пополнить с бумажного кошелька" + #: src/js/services/onGoingProcess.js:33 msgid "Sweeping Wallet..." msgstr "Считывание кошелька..." @@ -3792,6 +3797,10 @@ msgstr "Обзор Bitcoin.com" msgid "Bitcoin Cash Games" msgstr "Игры Bitcoin Cash" +#: www/views/includes/community.html:29 +msgid "Share the Wallet App" +msgstr "Поделиться программой «Кошелёк»" + #: src/js/services/bitcoincomService.js:28 msgid "News" msgstr "Новости" @@ -3860,3 +3869,75 @@ msgstr "менее 1 копейки" msgid "This invoice is no longer accepting payments" msgstr "По этому инвойсу платежи больше не принимаются" +#: www/views/amount.html.js:60 +msgid "Send Maximum Amount" +msgstr "Отправить максимальную сумму" + +#: src/js/controllers/amount.controller.js:239 +msgid "Unknown error." +msgstr "Неизвестная ошибка." + +#: www/views/paperWallet.html:48 +msgid "No Bitcoin Cash wallet to transfer funds to found." +msgstr "Не найден кошелек Bitcoin Cash для перевода средств." + +#: www/views/paperWallet.html:54 +msgid "No Bitcoin Cash found." +msgstr "Не найден Bitcoin Cash." + +#: www/views/paperWallet.html:60 +msgid "Bitcoin Core found:" +msgstr "Найден Bitcoin Core:" + +#: www/views/paperWallet.html:98 +msgid "No Bitcoin Core wallet to transfer funds to found." +msgstr "Не найден кошелек Bitcoin Core для перевода средств." + +#: www/views/paperWallet.html:104 +msgid "No Bitcoin Core found." +msgstr "Не найден Bitcoin Core." + +#: src/js/controllers/tab-scan.js:120 +msgid "Scan Failed" +msgstr "Ошибка сканирования" + +#: src/js/controllers/tab-scan.js:121 +msgid "Data not recognised." +msgstr "Данные не распознаны." + +#: src/js/controllers/tab-scan.js:121 +msgid "Unsupported" +msgstr "Не поддерживается" + +#: src/js/controllers/tab-scan.js:121 +msgid "Testnet is not supported." +msgstr "Testnet не поддерживается." + +#: www/views/includes/incomingDataMenu.html:81 +msgid "URL" +msgstr "URL-адрес" + +#: www/views/includes/incomingDataMenu.html:90 +msgid "Open in web browser" +msgstr "Открыть в веб-браузере" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid address" +msgstr "Неверный адрес" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is not defined" +msgstr "Сумма не задана" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is below the minimun" +msgstr "Сумма ниже минимума" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is above the limit" +msgstr "Сумма больше ограничения" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid response from Shapeshift" +msgstr "Неправильный ответ от Shapeshift" + diff --git a/i18n/po/sv-SE/template-sv-SE.po b/i18n/po/sv-SE/template-sv-SE.po index a4eeaada7..b80fca04b 100644 --- a/i18n/po/sv-SE/template-sv-SE.po +++ b/i18n/po/sv-SE/template-sv-SE.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Swedish\n" "Language: sv\n" -"PO-Revision-Date: 2018-08-21 03:40\n" +"PO-Revision-Date: 2018-09-06 16:45\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -520,7 +520,7 @@ msgid "Cannot Create Wallet" msgstr "Kan inte skapa plånbok" #: src/js/services/profileService.js:442 -msgid "Cannot join the same wallet more that once" +msgid "Cannot join the same wallet more than once" msgstr "" #: www/views/includes/bitpayCardsCard.html:2 @@ -2925,10 +2925,15 @@ msgid "Sweep" msgstr "" #: www/views/includes/incomingDataMenu.html:89 -#: www/views/paperWallet.html:3 +msgctxt "List item" msgid "Sweep paper wallet" msgstr "" +#: www/views/paperWallet.html:3 +msgctxt "Page title" +msgid "Sweep Paper Wallet" +msgstr "" + #: src/js/services/onGoingProcess.js:33 msgid "Sweeping Wallet..." msgstr "" @@ -3792,6 +3797,10 @@ msgstr "" msgid "Bitcoin Cash Games" msgstr "" +#: www/views/includes/community.html:29 +msgid "Share the Wallet App" +msgstr "" + #: src/js/services/bitcoincomService.js:28 msgid "News" msgstr "" @@ -3860,3 +3869,75 @@ msgstr "" msgid "This invoice is no longer accepting payments" msgstr "" +#: www/views/amount.html.js:60 +msgid "Send Maximum Amount" +msgstr "" + +#: src/js/controllers/amount.controller.js:239 +msgid "Unknown error." +msgstr "" + +#: www/views/paperWallet.html:48 +msgid "No Bitcoin Cash wallet to transfer funds to found." +msgstr "" + +#: www/views/paperWallet.html:54 +msgid "No Bitcoin Cash found." +msgstr "" + +#: www/views/paperWallet.html:60 +msgid "Bitcoin Core found:" +msgstr "" + +#: www/views/paperWallet.html:98 +msgid "No Bitcoin Core wallet to transfer funds to found." +msgstr "" + +#: www/views/paperWallet.html:104 +msgid "No Bitcoin Core found." +msgstr "" + +#: src/js/controllers/tab-scan.js:120 +msgid "Scan Failed" +msgstr "" + +#: src/js/controllers/tab-scan.js:121 +msgid "Data not recognised." +msgstr "" + +#: src/js/controllers/tab-scan.js:121 +msgid "Unsupported" +msgstr "" + +#: src/js/controllers/tab-scan.js:121 +msgid "Testnet is not supported." +msgstr "" + +#: www/views/includes/incomingDataMenu.html:81 +msgid "URL" +msgstr "" + +#: www/views/includes/incomingDataMenu.html:90 +msgid "Open in web browser" +msgstr "" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid address" +msgstr "" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is not defined" +msgstr "" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is below the minimun" +msgstr "" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is above the limit" +msgstr "" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid response from Shapeshift" +msgstr "" + diff --git a/i18n/po/vi/template-vi.po b/i18n/po/vi/template-vi.po index 3bdc71b26..29e62e498 100644 --- a/i18n/po/vi/template-vi.po +++ b/i18n/po/vi/template-vi.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Vietnamese\n" "Language: vi\n" -"PO-Revision-Date: 2018-08-21 03:40\n" +"PO-Revision-Date: 2018-09-15 05:56\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -36,7 +36,7 @@ msgstr "{{tx.feeRateStr}} của giao dịch" #: www/views/feedback/rateApp.html:7 msgid "5-star ratings help us get {{appName}} into more hands, and more users means more resources can be committed to the app!" -msgstr "5-star ratings help us get {{appName}} into more hands, and more users means more resources can be committed to the app!" +msgstr "{{appName}} 5-star ratings help us get {{appName}} into more hands, and more users means more resources can be committed to the app!" #: www/views/mercadoLibre.html:18 #: www/views/mercadoLibre.html:40 @@ -56,8 +56,8 @@ msgstr "A total of {{amountAboveMaxSizeStr}} were excluded. The maximum size all #: src/js/controllers/confirm.js:395 msgid "A total of {{amountBelowFeeStr}} were excluded. These funds come from UTXOs smaller than the network fee provided." -msgstr "Tổng cộng {{amountBelowFeeStr}} đã bị loại trừ. Số tiền này đến từ UTXOs nhỏ hơn chi phí mạng cung cấp.#\n" -"1" +msgstr "{{amountBelowFeeStr}} Tổng cộng {{amountBelowFeeStr}} đã bị loại trừ. Số tiền này đến từ UTXOs nhỏ hơn chi phí mạng cung cấp.#\n" +"1." #: src/js/controllers/preferencesAbout.js:6 #: www/views/tab-settings.html:156 @@ -67,7 +67,7 @@ msgstr "About" #: src/js/controllers/modals/txpDetails.js:62 #: src/js/controllers/tx-details.js:79 msgid "Accepted" -msgstr "Accepted" +msgstr "Chấp nhận" #: www/views/preferencesInformation.html:72 msgid "Account" @@ -78,7 +78,7 @@ msgstr "Account" #: www/views/tab-create-shared.html:74 #: www/views/tab-import-hardware.html:19 msgid "Account Number" -msgstr "Account Number" +msgstr "Account Number0941162662" #: www/views/tab-home.html:61 msgid "Instant transactions with low fees" @@ -241,7 +241,7 @@ msgstr "Fiat" #: src/js/controllers/tab-settings.js:19 #: www/views/preferencesPriceDisplay.html:15 msgid "Cryptocurrency" -msgstr "Cryptocurrency" +msgstr "Cryptocurrencyg" #: src/js/controllers/buyAmazon.js:98 msgid "Amazon.com is not available at this moment. Please try back later." @@ -523,8 +523,8 @@ msgid "Cannot Create Wallet" msgstr "Cannot Create Wallet" #: src/js/services/profileService.js:442 -msgid "Cannot join the same wallet more that once" -msgstr "Cannot join the same wallet more that once" +msgid "Cannot join the same wallet more than once" +msgstr "" #: www/views/includes/bitpayCardsCard.html:2 msgid "Cards" @@ -2928,9 +2928,14 @@ msgid "Sweep" msgstr "Sweep" #: www/views/includes/incomingDataMenu.html:89 -#: www/views/paperWallet.html:3 +msgctxt "List item" msgid "Sweep paper wallet" -msgstr "Sweep paper wallet" +msgstr "" + +#: www/views/paperWallet.html:3 +msgctxt "Page title" +msgid "Sweep Paper Wallet" +msgstr "Sweep Paper Wallet" #: src/js/services/onGoingProcess.js:33 msgid "Sweeping Wallet..." @@ -3795,6 +3800,10 @@ msgstr "Explore Bitcoin.com" msgid "Bitcoin Cash Games" msgstr "Bitcoin Cash Games" +#: www/views/includes/community.html:29 +msgid "Share the Wallet App" +msgstr "" + #: src/js/services/bitcoincomService.js:28 msgid "News" msgstr "News" @@ -3863,3 +3872,75 @@ msgstr "Less than 1 cent" msgid "This invoice is no longer accepting payments" msgstr "This invoice is no longer accepting payments" +#: www/views/amount.html.js:60 +msgid "Send Maximum Amount" +msgstr "" + +#: src/js/controllers/amount.controller.js:239 +msgid "Unknown error." +msgstr "" + +#: www/views/paperWallet.html:48 +msgid "No Bitcoin Cash wallet to transfer funds to found." +msgstr "" + +#: www/views/paperWallet.html:54 +msgid "No Bitcoin Cash found." +msgstr "" + +#: www/views/paperWallet.html:60 +msgid "Bitcoin Core found:" +msgstr "" + +#: www/views/paperWallet.html:98 +msgid "No Bitcoin Core wallet to transfer funds to found." +msgstr "" + +#: www/views/paperWallet.html:104 +msgid "No Bitcoin Core found." +msgstr "" + +#: src/js/controllers/tab-scan.js:120 +msgid "Scan Failed" +msgstr "" + +#: src/js/controllers/tab-scan.js:121 +msgid "Data not recognised." +msgstr "" + +#: src/js/controllers/tab-scan.js:121 +msgid "Unsupported" +msgstr "" + +#: src/js/controllers/tab-scan.js:121 +msgid "Testnet is not supported." +msgstr "" + +#: www/views/includes/incomingDataMenu.html:81 +msgid "URL" +msgstr "" + +#: www/views/includes/incomingDataMenu.html:90 +msgid "Open in web browser" +msgstr "" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid address" +msgstr "" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is not defined" +msgstr "" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is below the minimun" +msgstr "" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is above the limit" +msgstr "" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid response from Shapeshift" +msgstr "" + diff --git a/i18n/po/zh-CN/template-zh-CN.po b/i18n/po/zh-CN/template-zh-CN.po index cd2681041..f648a8cd6 100644 --- a/i18n/po/zh-CN/template-zh-CN.po +++ b/i18n/po/zh-CN/template-zh-CN.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Chinese Simplified\n" "Language: zh\n" -"PO-Revision-Date: 2018-08-21 03:39\n" +"PO-Revision-Date: 2018-09-15 05:56\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -520,7 +520,7 @@ msgid "Cannot Create Wallet" msgstr "不能创建钱包" #: src/js/services/profileService.js:442 -msgid "Cannot join the same wallet more that once" +msgid "Cannot join the same wallet more than once" msgstr "无法重复加入同一个钱包" #: www/views/includes/bitpayCardsCard.html:2 @@ -2925,9 +2925,14 @@ msgid "Sweep" msgstr "扫描" #: www/views/includes/incomingDataMenu.html:89 -#: www/views/paperWallet.html:3 +msgctxt "List item" msgid "Sweep paper wallet" -msgstr "Sweep 纸钱包" +msgstr "清空纸钱包" + +#: www/views/paperWallet.html:3 +msgctxt "Page title" +msgid "Sweep Paper Wallet" +msgstr "清空纸钱包" #: src/js/services/onGoingProcess.js:33 msgid "Sweeping Wallet..." @@ -3792,6 +3797,10 @@ msgstr "探索 Bitcoin.com" msgid "Bitcoin Cash Games" msgstr "Bitcoin Cash 游戏" +#: www/views/includes/community.html:29 +msgid "Share the Wallet App" +msgstr "分享钱包应用" + #: src/js/services/bitcoincomService.js:28 msgid "News" msgstr "新闻" @@ -3860,3 +3869,75 @@ msgstr "少于 1 美分" msgid "This invoice is no longer accepting payments" msgstr "此发票不再接受付款" +#: www/views/amount.html.js:60 +msgid "Send Maximum Amount" +msgstr "发送最大金额" + +#: src/js/controllers/amount.controller.js:239 +msgid "Unknown error." +msgstr "未知错误。" + +#: www/views/paperWallet.html:48 +msgid "No Bitcoin Cash wallet to transfer funds to found." +msgstr "未找到可以转入资金的 Bitcoin Cash 钱包。" + +#: www/views/paperWallet.html:54 +msgid "No Bitcoin Cash found." +msgstr "未找到 Bitcoin Cash。" + +#: www/views/paperWallet.html:60 +msgid "Bitcoin Core found:" +msgstr "已找到 Bitcoin Core:" + +#: www/views/paperWallet.html:98 +msgid "No Bitcoin Core wallet to transfer funds to found." +msgstr "未找到可以转入资金的 Bitcoin Core 钱包。" + +#: www/views/paperWallet.html:104 +msgid "No Bitcoin Core found." +msgstr "未找到 Bitcoin Core。" + +#: src/js/controllers/tab-scan.js:120 +msgid "Scan Failed" +msgstr "扫描失败" + +#: src/js/controllers/tab-scan.js:121 +msgid "Data not recognised." +msgstr "数据未被识别。" + +#: src/js/controllers/tab-scan.js:121 +msgid "Unsupported" +msgstr "不受支持" + +#: src/js/controllers/tab-scan.js:121 +msgid "Testnet is not supported." +msgstr "不支持测试网。" + +#: www/views/includes/incomingDataMenu.html:81 +msgid "URL" +msgstr "网址" + +#: www/views/includes/incomingDataMenu.html:90 +msgid "Open in web browser" +msgstr "在网络浏览器中打开" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid address" +msgstr "地址无效" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is not defined" +msgstr "未定义金额" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is below the minimun" +msgstr "金额低于最低金额" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Amount is above the limit" +msgstr "金额高于限额" + +#: src/js/services/shapeshift.service.js.html:90 +msgid "Invalid response from Shapeshift" +msgstr "Shapeshift 的响应无效" + From e02368ea3cbae6f1cdf0c104d26477e31c74641c Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Sat, 15 Sep 2018 18:05:39 +1200 Subject: [PATCH 09/23] Incremented version for release candidate. --- app-template/bitcoincom/appConfig.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app-template/bitcoincom/appConfig.json b/app-template/bitcoincom/appConfig.json index 970432be2..a73fae33f 100644 --- a/app-template/bitcoincom/appConfig.json +++ b/app-template/bitcoincom/appConfig.json @@ -24,9 +24,9 @@ "windowsAppId": "804636ee-b017-4cad-8719-e58ac97ffa5c", "pushSenderId": "1036948132229", "description": "A Secure Bitcoin Wallet", - "version": "5.1.1", - "fullVersion": "5.1-beta2", - "androidVersion": "501001", + "version": "5.1.2", + "fullVersion": "5.1-rc1", + "androidVersion": "501002", "_extraCSS": "", "_enabledExtensions": { "coinbase": false, From 7b6efaa1db8b2675435db2d180e284f6116e16b0 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Mon, 17 Sep 2018 21:26:21 -0700 Subject: [PATCH 10/23] Clear memo before entering Review screen. --- src/js/controllers/review.controller.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/js/controllers/review.controller.js b/src/js/controllers/review.controller.js index 15f982f2f..58ae2c2f7 100644 --- a/src/js/controllers/review.controller.js +++ b/src/js/controllers/review.controller.js @@ -26,6 +26,7 @@ function reviewController(addressbookService, bitcoinCashJsService, bitcore, bit vm.feeIsHigh = false; vm.feeLessThanACent = false; vm.isCordova = platformInfo.isCordova; + vm.memo = ''; vm.notReadyMessage = ''; vm.origin = { balanceAmount: '', @@ -76,9 +77,12 @@ function reviewController(addressbookService, bitcoinCashJsService, bitcore, bit $scope.$on("$ionicView.beforeEnter", onBeforeEnter); - + function onBeforeEnter(event, data) { console.log('review onBeforeEnter sendflow ', sendFlowService.state); + // Reset from last time + vm.memo = ''; + defaults = configService.getDefaults(); sendFlowData = sendFlowService.state.getClone(); originWalletId = sendFlowData.fromWalletId; @@ -94,7 +98,7 @@ function reviewController(addressbookService, bitcoinCashJsService, bitcore, bit vm.originWallet = profileService.getWallet(originWalletId); vm.origin.currency = vm.originWallet.coin.toUpperCase(); coin = vm.originWallet.coin; - + if (sendFlowData.thirdParty) { vm.thirdParty = sendFlowData.thirdParty; switch (vm.thirdParty.id) { From 4d6aeb4f910f105544f189955ac2b68e45a49a90 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Tue, 18 Sep 2018 15:26:30 -0700 Subject: [PATCH 11/23] Renamed directive and replaced old variable references with new ones. --- ...rective.js => wallet-balance.directive.js} | 27 +++++++++++++------ www/views/tab-send.html | 5 ++-- 2 files changed, 21 insertions(+), 11 deletions(-) rename src/js/directives/{walletBalanceDirective.js => wallet-balance.directive.js} (81%) diff --git a/src/js/directives/walletBalanceDirective.js b/src/js/directives/wallet-balance.directive.js similarity index 81% rename from src/js/directives/walletBalanceDirective.js rename to src/js/directives/wallet-balance.directive.js index 1fea59203..4d8ca2875 100644 --- a/src/js/directives/walletBalanceDirective.js +++ b/src/js/directives/wallet-balance.directive.js @@ -12,6 +12,7 @@ totalBalanceSat: '@', // The Wallet object is sometimes not stringify()-able, so not interpolatable, // so can't be passed to a directive. + walletCoin: '@', walletStatus: '@', walletCachedBalance: '@', walletCachedBalanceUpdatedOn: '@', @@ -31,7 +32,6 @@ }); function displayCryptoBalance(walletStatus, walletCachedBalance, walletCachedBalanceUpdatedOn, walletCachedStatus) { - console.log('displayCryptoBalance()'); if (walletStatus && walletStatus.isValid && walletStatus.totalBalanceStr) { setDisplay(walletStatus.totalBalanceStr, ''); @@ -52,7 +52,7 @@ setDisplay('', ''); } - function displayFiatBalance(walletStatus, walletCachedStatus) { + function displayFiatBalance(walletStatus, walletCachedStatus, walletCoin) { var displayAmount = ''; if (walletStatus && walletStatus.isValid && walletStatus.alternativeBalanceAvailable) { displayAmount = walletStatus.totalBalanceAlternative + ' ' + walletStatus.alternativeIsoCode; @@ -66,7 +66,7 @@ return; } - getFiatBalance(wallet); + getFiatBalance(walletStatus, walletCachedStatus, walletCoin); } function formatBalance() { @@ -94,19 +94,30 @@ } if (displayAsFiat) { - displayFiatBalance(walletStatusObj, walletCachedStatusObj); + displayFiatBalance(walletStatusObj, walletCachedStatusObj, $scope.walletCoin); } } - function getFiatBalance(wallet) { - if (!(wallet.status && wallet.status.isValid)) { - $log.warn('Abandoning call to get fiat balance, because no valid wallet status.'); + function getFiatBalance(walletStatus, walletCachedStatus, walletCoin) { + var totalBalanceSat = null; + + 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; } - txFormatService.formatAlternativeStr(wallet.coin, wallet.status.totalBalanceSat, function onFormatAlernativeStr(formatted) { + txFormatService.formatAlternativeStr(walletCoin, totalBalanceSat, function onFormatAlernativeStr(formatted) { if (formatted) { setDisplay(formatted, ''); + } else { + $log.error('Failed to format fiat balance of wallet.'); } }); } diff --git a/www/views/tab-send.html b/www/views/tab-send.html index 0b62fe0a5..b8c2b7884 100644 --- a/www/views/tab-send.html +++ b/www/views/tab-send.html @@ -17,14 +17,13 @@

{{fromWallet.name}}

- -
From 3cad7d7ad86f4f723b73f0033e67d377391c9d6f Mon Sep 17 00:00:00 2001 From: Sebastiaan Pasma Date: Thu, 20 Sep 2018 15:58:42 +0200 Subject: [PATCH 12/23] Update confirmations on cached transactions --- src/js/services/wallet-history.service.js | 24 +++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/js/services/wallet-history.service.js b/src/js/services/wallet-history.service.js index 7a6f18a13..0738d4348 100644 --- a/src/js/services/wallet-history.service.js +++ b/src/js/services/wallet-history.service.js @@ -66,16 +66,21 @@ function addLatestTransactions(walletId, cachedTxs, newTxs) { var cachedTxIds = {}; - cachedTxs.forEach(function forCachedTx(tx){ - cachedTxIds[tx.txid] = true; + cachedTxs.forEach(function forCachedTx(tx, txIndex){ + cachedTxIds[tx.txid] = txIndex; }); var someTransactionsWereNew = false; + var confirmationsUpdated = false; var overlappingTxsCount = 0; var uniqueNewTxs = []; newTxs.forEach(function forNewTx(tx){ - if (cachedTxIds[tx.txid]) { + if (typeof cachedTxIds[tx.txid] !== "undefined") { + if (cachedTxs[cachedTxIds[tx.txid]].confirmations < SAFE_CONFIRMATIONS && tx.confirmations >= SAFE_CONFIRMATIONS) { + cachedTxs[cachedTxIds[tx.txid]].confirmations = tx.confirmations; + confirmationsUpdated = true; + } overlappingTxsCount++; } else { someTransactionsWereNew = true; @@ -91,6 +96,9 @@ saveTxHistory(walletId, allTxs); return allTxs; } else { + if (confirmationsUpdated) { + saveTxHistory(walletId, cachedTxs); + } return cachedTxs; } } else { @@ -104,6 +112,8 @@ // 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 */ function fetchTxHistoryByPage(wallet, start, cb) { @@ -187,7 +197,7 @@ }); return processedTxs; - }; + } function saveTxHistory(walletId, processedTxs) { storageService.setTxHistory(processedTxs, walletId, function onSetTxHistory(error){ @@ -197,7 +207,6 @@ }); } - function updateLocalTxHistoryByPage(wallet, getLatest, flushCacheOnNew, cb) { if (flushCacheOnNew) { @@ -240,10 +249,5 @@ }); } } - - - } - - })(); \ No newline at end of file From 5cb3d7521df0fbb42f44ebf01c641d6565441abb Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Dominguez Date: Fri, 21 Sep 2018 10:23:02 +0200 Subject: [PATCH 13/23] Fix modal --- src/js/services/onGoingProcess.js | 10 ++++++---- src/js/services/shapeshift.service.js | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/js/services/onGoingProcess.js b/src/js/services/onGoingProcess.js index 9c25c3c26..422be070f 100644 --- a/src/js/services/onGoingProcess.js +++ b/src/js/services/onGoingProcess.js @@ -74,10 +74,8 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti root.onGoingProcessName = name; var showName = $filter('translate')(processNames[name] || name); - - if (customHandler) { - customHandler(processName, showName, isOn); - } else if (root.onGoingProcessName) { + + if (root.onGoingProcessName) { var tmpl; if (isWindowsPhoneApp) tmpl = '
' + showName + '
'; else tmpl = '
' + showName + '
'; @@ -87,6 +85,10 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti } else { $ionicLoading.hide(); } + + if (customHandler) { + customHandler(processName, showName, isOn); + } }; return root; diff --git a/src/js/services/shapeshift.service.js b/src/js/services/shapeshift.service.js index 77f0de297..73410e478 100644 --- a/src/js/services/shapeshift.service.js +++ b/src/js/services/shapeshift.service.js @@ -57,7 +57,7 @@ angular function shiftIt(coinIn, coinOut, withdrawalAddress, returnAddress, amount, cb) { // Test if the amount is correct depending on the min and max if (!amount || typeof amount !== 'number') { - cb(new Error(gettextCatalog.getString('Amount is not defined')))); + cb(new Error(gettextCatalog.getString('Amount is not defined'))); } else if (amount < service.marketData.minimum) { cb(new Error(gettextCatalog.getString('Amount is below the minimun'))); } else if (amount > service.marketData.maxLimit) { From a3614566e3cf9a2128d24f508917e1c8e4faee08 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Fri, 21 Sep 2018 02:27:34 -0700 Subject: [PATCH 14/23] Reconnecting socket based on CloseEvent.code. --- src/js/controllers/tab-receive.js | 54 +++++++++++++------------------ 1 file changed, 22 insertions(+), 32 deletions(-) diff --git a/src/js/controllers/tab-receive.js b/src/js/controllers/tab-receive.js index 6642c2e1c..645e46739 100644 --- a/src/js/controllers/tab-receive.js +++ b/src/js/controllers/tab-receive.js @@ -2,6 +2,7 @@ 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 = []; $scope.bchAddressType = { type: 'cashaddr' }; var bchAddresses = {}; @@ -10,12 +11,11 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi $scope.isCordova = platformInfo.isCordova; $scope.isNW = platformInfo.isNW; - var currentAddressSocket = {}; - var paymentSubscriptionObj = { op:"addr_sub" } - - var config; + var currentAddressSocket = null; + var paymentSubscriptionObj = { op:'addr_sub' }; $scope.displayBalanceAsFiat = true; + $scope.$on('$ionicView.beforeLeave', onBeforeLeave); $scope.requestSpecificAmount = function() { sendFlowService.start({ @@ -26,18 +26,18 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi function connectSocket() { - //close existing socket if not connected with current address - if (currentAddressSocket && typeof currentAddressSocket.close === 'function') { - currentAddressSocket.onclose = function(e) {}; // Overwrite onclose-function to prevent reconnecting old address socket. - currentAddressSocket.close(); + // 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"); + 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"); + currentAddressSocket = new WebSocket('wss://ws.blockchain.info/inv'); paymentSubscriptionObj.addr = $scope.addr; } @@ -53,21 +53,19 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi receivedPayment(event.data); }; - currentAddressSocket.onclose = function(e) { - console.log('Socket is closed. Reconnect will be attempted in 1 second.'); - $timeout(function() { - connectSocket(); - }, 1000); + 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(); }; - - $timeout(function() { - $scope.$apply(); - }, 10); } $scope.setAddress = function(newAddr, copyAddress) { @@ -96,7 +94,7 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi try { clipboardService.copyToClipboard($scope.wallet.coin == 'bch' && $scope.bchAddressType.type == 'cashaddr' ? 'bitcoincash:' + $scope.addr : $scope.addr); } catch (error) { - $log.debug("Error copying to clipboard:"); + $log.debug('Error copying to clipboard:'); $log.debug(error); } } @@ -185,7 +183,6 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi // Notify new tx $scope.$emit('bwsEvent', $scope.wallet.id); - $scope.$apply(function () { $scope.showingPaymentReceived = true; }); @@ -254,16 +251,10 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi } }; - $scope.$on("$ionicView.beforeLeave", function() { - // Close the old connection! - if (currentAddressSocket && typeof currentAddressSocket.close === 'function') { - console.log("Close open websocket address connection."); - currentAddressSocket.onclose = function(e) {}; // Overwrite onclose-function to prevent reconnecting old address socket. - currentAddressSocket.close(); - } - - }); - + function onBeforeLeave() { + currentAddressSocket.close([CLOSE_NORMAL]); + } + $scope.$on("$ionicView.beforeEnter", function(event, data) { $scope.wallets = profileService.getWallets(); $scope.singleWallet = $scope.wallets.length == 1; @@ -289,7 +280,6 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi configService.whenAvailable(function(_config) { $scope.displayBalanceAsFiat = _config.wallet.settings.priceDisplay === 'fiat'; - config = _config; }); }); From 4250a98718c9bad3d3f0de9eb8e21253ad082f8d Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Dominguez Date: Fri, 21 Sep 2018 11:31:27 +0200 Subject: [PATCH 15/23] walletStatus worst case, IIFE for both controllers. --- src/js/controllers/review.controller.js | 1752 +++++++++-------- .../controllers/wallet-selector.controller.js | 348 ++-- 2 files changed, 1054 insertions(+), 1046 deletions(-) diff --git a/src/js/controllers/review.controller.js b/src/js/controllers/review.controller.js index b8379b769..53bae167e 100644 --- a/src/js/controllers/review.controller.js +++ b/src/js/controllers/review.controller.js @@ -1,952 +1,954 @@ 'use strict'; +(function () { + angular .module('copayApp.controllers') .controller('reviewController', reviewController); -function reviewController(addressbookService, bitcoinCashJsService, bitcore, bitcoreCash, bwcError, clipboardService, configService, feeService, gettextCatalog, $interval, $ionicHistory, $ionicModal, ionicToast, lodash, $log, ongoingProcess, platformInfo, popupService, profileService, $scope, sendFlowService, shapeshiftService, soundService, $state, $timeout, txConfirmNotification, txFormatService, walletService) { - var vm = this; + function reviewController(addressbookService, bitcoinCashJsService, bitcore, bitcoreCash, bwcError, clipboardService, configService, feeService, gettextCatalog, $interval, $ionicHistory, $ionicModal, ionicToast, lodash, $log, ongoingProcess, platformInfo, popupService, profileService, $scope, sendFlowService, shapeshiftService, soundService, $state, $timeout, txConfirmNotification, txFormatService, walletService) { + var vm = this; - vm.buttonText = ''; - vm.destination = { - address: '', - balanceAmount: '', - balanceCurrency: '', - coin: '', - color: '', - currency: '', - currencyColor: '', - kind: '', // 'address', 'contact', 'wallet' - name: '' - }; - vm.displayAddress = ''; - vm.feeCrypto = ''; - vm.feeFiat = ''; - vm.fiatCurrency = ''; - vm.feeIsHigh = false; - vm.feeLessThanACent = false; - vm.isCordova = platformInfo.isCordova; - vm.notReadyMessage = ''; - vm.origin = { - balanceAmount: '', - balanceCurrency: '', - currency: '', - currencyColor: '', - }; - vm.originWallet = null; - vm.paymentExpired = false; - vm.personalNotePlaceholder = gettextCatalog.getString('Enter text here'); - vm.primaryAmount = ''; - vm.primaryCurrency = ''; - vm.usingMerchantFee = false; - vm.readyToSend = false; - vm.remainingTimeStr = ''; - vm.secondaryAmount = ''; - vm.secondaryCurrency = ''; - vm.sendingTitle = gettextCatalog.getString('You are sending'); - vm.sendStatus = ''; - vm.showAddress = true; - vm.thirdParty = false; - vm.wallet = null; - vm.memoExpanded = false; + vm.buttonText = ''; + vm.destination = { + address: '', + balanceAmount: '', + balanceCurrency: '', + coin: '', + color: '', + currency: '', + currencyColor: '', + kind: '', // 'address', 'contact', 'wallet' + name: '' + }; + vm.displayAddress = ''; + vm.feeCrypto = ''; + vm.feeFiat = ''; + vm.fiatCurrency = ''; + vm.feeIsHigh = false; + vm.feeLessThanACent = false; + vm.isCordova = platformInfo.isCordova; + vm.notReadyMessage = ''; + vm.origin = { + balanceAmount: '', + balanceCurrency: '', + currency: '', + currencyColor: '', + }; + vm.originWallet = null; + vm.paymentExpired = false; + vm.personalNotePlaceholder = gettextCatalog.getString('Enter text here'); + vm.primaryAmount = ''; + vm.primaryCurrency = ''; + vm.usingMerchantFee = false; + vm.readyToSend = false; + vm.remainingTimeStr = ''; + vm.secondaryAmount = ''; + vm.secondaryCurrency = ''; + vm.sendingTitle = gettextCatalog.getString('You are sending'); + vm.sendStatus = ''; + vm.showAddress = true; + vm.thirdParty = false; + vm.wallet = null; + vm.memoExpanded = false; - // Functions - vm.goBack = goBack; - vm.onSuccessConfirm = onSuccessConfirm; - vm.onShareTransaction = onShareTransaction; + // Functions + vm.goBack = goBack; + vm.onSuccessConfirm = onSuccessConfirm; + vm.onShareTransaction = onShareTransaction; - var sendFlowData; - var config = null; - var coin = ''; - var countDown = null; - var defaults = {}; - var usingCustomFee = false; - var usingMerchantFee = false; - var destinationWalletId = ''; - var lastTxId = ''; - var originWalletId = ''; - var priceDisplayIsFiat = true; - var satoshis = null; - var toAddress = ''; - var tx = {}; - var txPayproData = null; - var unitFromSat = 0; + var sendFlowData; + var config = null; + var coin = ''; + var countDown = null; + var defaults = {}; + var usingCustomFee = false; + var usingMerchantFee = false; + var destinationWalletId = ''; + var lastTxId = ''; + var originWalletId = ''; + var priceDisplayIsFiat = true; + var satoshis = null; + var toAddress = ''; + var tx = {}; + var txPayproData = null; + var unitFromSat = 0; - var FEE_TOO_HIGH_LIMIT_PERCENTAGE = 15; + var FEE_TOO_HIGH_LIMIT_PERCENTAGE = 15; - $scope.$on("$ionicView.beforeEnter", onBeforeEnter); + $scope.$on("$ionicView.beforeEnter", onBeforeEnter); - function onBeforeEnter(event, data) { - console.log('review onBeforeEnter sendflow ', sendFlowService.state); - defaults = configService.getDefaults(); - sendFlowData = sendFlowService.state.getClone(); - originWalletId = sendFlowData.fromWalletId; - if (typeof sendFlowData.amount === 'string') { - satoshis = parseInt(sendFlowData.amount, 10); - } else { - satoshis = sendFlowData.amount; - } - toAddress = sendFlowData.toAddress; - destinationWalletId = sendFlowData.toWalletId; - - vm.displayAddress = sendFlowData.displayAddress; - vm.originWallet = profileService.getWallet(originWalletId); - vm.origin.currency = vm.originWallet.coin.toUpperCase(); - coin = vm.originWallet.coin; - - if (sendFlowData.thirdParty) { - vm.thirdParty = sendFlowData.thirdParty; - switch (vm.thirdParty.id) { - case 'shapeshift': - initShapeshift(function (err) { - if (err) { - // Error stop here - ongoingProcess.set('connectingShapeshift', false); - popupService.showAlert(gettextCatalog.getString('Shapeshift Error'), err.toString(), function () { - $ionicHistory.goBack(); - }); - } else { - _next(data); - } - }); - break; - case 'bip70': - initBip70(); - default: - _next(data); - break; + function onBeforeEnter(event, data) { + console.log('review onBeforeEnter sendflow ', sendFlowService.state); + defaults = configService.getDefaults(); + sendFlowData = sendFlowService.state.getClone(); + originWalletId = sendFlowData.fromWalletId; + if (typeof sendFlowData.amount === 'string') { + satoshis = parseInt(sendFlowData.amount, 10); + } else { + satoshis = sendFlowData.amount; } - } else { - _next(data); - } + toAddress = sendFlowData.toAddress; + destinationWalletId = sendFlowData.toWalletId; - function _next() { - configService.get(function onConfig(err, configCache) { - if (err) { - $log.err('Error getting config.', err); - } else { - config = configCache; - priceDisplayIsFiat = config.wallet.settings.priceDisplay === 'fiat'; - vm.origin.currencyColor = (vm.originWallet.coin === 'btc' ? defaults.bitcoinWalletColor : defaults.bitcoinCashWalletColor); - console.log("coin", vm.originWallet.coin, vm.origin.currencyColor, config.bitcoinWalletColor, vm.originWallet.coin === 'btc'); - unitFromSat = 1 / config.wallet.settings.unitToSatoshi; - } - updateSendAmounts(); - getOriginWalletBalance(vm.originWallet); - handleDestinationAsAddress(toAddress, coin); - handleDestinationAsWallet(sendFlowData.toWalletId); - createVanityTransaction(data); - }); - } - } + vm.displayAddress = sendFlowData.displayAddress; + vm.originWallet = profileService.getWallet(originWalletId); + vm.origin.currency = vm.originWallet.coin.toUpperCase(); + coin = vm.originWallet.coin; - vm.approve = function() { - - if (!tx || !vm.originWallet) return; - - if (vm.paymentExpired) { - popupService.showAlert(null, gettextCatalog.getString('This bitcoin payment request has expired.', function () { - $ionicHistory.goBack(); - })); - vm.sendStatus = ''; - $timeout(function() { - $scope.$apply(); - }); - return; - } - - ongoingProcess.set('creatingTx', true, statusChangeHandler); - getTxp(lodash.clone(tx), vm.originWallet, false, function(err, txp) { - ongoingProcess.set('creatingTx', false, statusChangeHandler); - if (err) return; - - // confirm txs for more that 20usd, if not spending/touchid is enabled - function confirmTx(cb) { - if (walletService.isEncrypted(vm.originWallet)) - return cb(); - - var amountUsd = parseFloat(txFormatService.formatToUSD(vm.originWallet.coin, txp.amount)); - return cb(); - }; - - function publishAndSign() { - if (!vm.originWallet.canSign() && !vm.originWallet.isPrivKeyExternal()) { - $log.info('No signing proposal: No private key'); - - return walletService.onlyPublish(vm.originWallet, txp, function(err) { - if (err) setSendError(err); - }, statusChangeHandler); - } - - walletService.publishAndSign(vm.originWallet, txp, function(err, txp) { - if (err) return setSendError(err); - if (config.confirmedTxsNotifications && config.confirmedTxsNotifications.enabled) { - txConfirmNotification.subscribe(vm.originWallet, { - txid: txp.txid + if (sendFlowData.thirdParty) { + vm.thirdParty = sendFlowData.thirdParty; + switch (vm.thirdParty.id) { + case 'shapeshift': + initShapeshift(function (err) { + if (err) { + // Error stop here + ongoingProcess.set('connectingShapeshift', false); + popupService.showAlert(gettextCatalog.getString('Shapeshift Error'), err.toString(), function () { + $ionicHistory.goBack(); + }); + } else { + _next(data); + } }); - lastTxId = txp.txid; + break; + case 'bip70': + initBip70(); + default: + _next(data); + break; + } + } else { + _next(data); + } + + function _next() { + configService.get(function onConfig(err, configCache) { + if (err) { + $log.err('Error getting config.', err); + } else { + config = configCache; + priceDisplayIsFiat = config.wallet.settings.priceDisplay === 'fiat'; + vm.origin.currencyColor = (vm.originWallet.coin === 'btc' ? defaults.bitcoinWalletColor : defaults.bitcoinCashWalletColor); + console.log("coin", vm.originWallet.coin, vm.origin.currencyColor, config.bitcoinWalletColor, vm.originWallet.coin === 'btc'); + unitFromSat = 1 / config.wallet.settings.unitToSatoshi; } - }, statusChangeHandler); + updateSendAmounts(); + getOriginWalletBalance(vm.originWallet); + handleDestinationAsAddress(toAddress, coin); + handleDestinationAsWallet(sendFlowData.toWalletId); + createVanityTransaction(data); + }); + } + } + + vm.approve = function() { + + if (!tx || !vm.originWallet) return; + + if (vm.paymentExpired) { + popupService.showAlert(null, gettextCatalog.getString('This bitcoin payment request has expired.', function () { + $ionicHistory.goBack(); + })); + vm.sendStatus = ''; + $timeout(function() { + $scope.$apply(); + }); + return; + } + + ongoingProcess.set('creatingTx', true, statusChangeHandler); + getTxp(lodash.clone(tx), vm.originWallet, false, function(err, txp) { + ongoingProcess.set('creatingTx', false, statusChangeHandler); + if (err) return; + + // confirm txs for more that 20usd, if not spending/touchid is enabled + function confirmTx(cb) { + if (walletService.isEncrypted(vm.originWallet)) + return cb(); + + var amountUsd = parseFloat(txFormatService.formatToUSD(vm.originWallet.coin, txp.amount)); + return cb(); + }; + + function publishAndSign() { + if (!vm.originWallet.canSign() && !vm.originWallet.isPrivKeyExternal()) { + $log.info('No signing proposal: No private key'); + + return walletService.onlyPublish(vm.originWallet, txp, function(err) { + if (err) setSendError(err); + }, statusChangeHandler); + } + + walletService.publishAndSign(vm.originWallet, txp, function(err, txp) { + if (err) return setSendError(err); + if (config.confirmedTxsNotifications && config.confirmedTxsNotifications.enabled) { + txConfirmNotification.subscribe(vm.originWallet, { + txid: txp.txid + }); + lastTxId = txp.txid; + } + }, statusChangeHandler); + }; + + confirmTx(function(nok) { + if (nok) { + vm.sendStatus = ''; + $timeout(function() { + $scope.$apply(); + }); + return; + } + publishAndSign(); + }); + }); + }; + + vm.chooseFeeLevel = function(tx, wallet) { + + if (wallet.coin == 'bch') return; + if (usingMerchantFee) return; + + var scope = $rootScope.$new(true); + scope.network = tx.network; + scope.feeLevel = tx.feeLevel; + scope.noSave = true; + scope.coin = vm.originWallet.coin; + + if (usingCustomFee) { + scope.customFeePerKB = tx.feeRate; + scope.feePerSatByte = tx.feeRate / 1000; + } + + $ionicModal.fromTemplateUrl('views/modals/chooseFeeLevel.html', { + scope: scope, + backdropClickToClose: false, + hardwareBackButtonClose: false + }).then(function(modal) { + scope.chooseFeeLevelModal = modal; + scope.openModal(); + }); + scope.openModal = function() { + scope.chooseFeeLevelModal.show(); }; - confirmTx(function(nok) { - if (nok) { - vm.sendStatus = ''; - $timeout(function() { - $scope.$apply(); + scope.hideModal = function(newFeeLevel, customFeePerKB) { + scope.chooseFeeLevelModal.hide(); + $log.debug('New fee level choosen:' + newFeeLevel + ' was:' + tx.feeLevel); + + usingCustomFee = newFeeLevel == 'custom' ? true : false; + + if (tx.feeLevel == newFeeLevel && !usingCustomFee) return; + + tx.feeLevel = newFeeLevel; + if (usingCustomFee) tx.feeRate = parseInt(customFeePerKB); + + updateTx(tx, vm.originWallet, { + clearCache: true, + dryRun: true + }, function() {}); + }; + }; + + function createVanityTransaction(data) { + console.log('createVanityTransaction()'); + var configFeeLevel = config.wallet.settings.feeLevel ? config.wallet.settings.feeLevel : 'normal'; + + // Grab stateParams + tx = { + amount: parseInt(sendFlowData.amount), + sendMax: sendFlowData.sendMax, + fromWalletId: sendFlowData.fromWalletId, + toAddress: sendFlowData.toAddress, + paypro: txPayproData, + + feeLevel: configFeeLevel, + spendUnconfirmed: config.wallet.spendUnconfirmed, + + // Vanity tx info (not in the real tx) + recipientType: vm.destination.kind || null, + toName: vm.destination.name || null, + toEmail: vm.destination.email || null, + toColor: vm.destination.color || null, + network: false, + coin: vm.originWallet.coin, + txp: {}, + }; + + + if (data.stateParams.requiredFeeRate) { + vm.usingMerchantFee = true; + tx.feeRate = parseInt(data.stateParams.requiredFeeRate); + } + + if (tx.coin && tx.coin === 'bch') { + tx.feeLevel = 'normal'; + } + + var B = tx.coin === 'bch' ? bitcoreCash : bitcore; + var networkName; + try { + if (vm.destination.kind === 'wallet') { // This is a wallet-to-wallet transfer + ongoingProcess.set('generatingNewAddress', true); + var toWallet = profileService.getWallet(destinationWalletId); + + // We need an address to send to, so we ask the walletService to create a new address for the toWallet. + console.log('Getting address for wallet...'); + walletService.getAddress(toWallet, true, function onWalletAddress(err, addr) { + console.log('getAddress cb called', err); + ongoingProcess.set('generatingNewAddress', false); + tx.toAddress = addr; + networkName = (new B.Address(tx.toAddress)).network.name; + tx.network = networkName; + console.log('calling setupTx() for wallet.'); + setupTx(tx); }); - return; - } - publishAndSign(); - }); - }); - }; - - vm.chooseFeeLevel = function(tx, wallet) { - - if (wallet.coin == 'bch') return; - if (usingMerchantFee) return; - - var scope = $rootScope.$new(true); - scope.network = tx.network; - scope.feeLevel = tx.feeLevel; - scope.noSave = true; - scope.coin = vm.originWallet.coin; - - if (usingCustomFee) { - scope.customFeePerKB = tx.feeRate; - scope.feePerSatByte = tx.feeRate / 1000; - } - - $ionicModal.fromTemplateUrl('views/modals/chooseFeeLevel.html', { - scope: scope, - backdropClickToClose: false, - hardwareBackButtonClose: false - }).then(function(modal) { - scope.chooseFeeLevelModal = modal; - scope.openModal(); - }); - scope.openModal = function() { - scope.chooseFeeLevelModal.show(); - }; - - scope.hideModal = function(newFeeLevel, customFeePerKB) { - scope.chooseFeeLevelModal.hide(); - $log.debug('New fee level choosen:' + newFeeLevel + ' was:' + tx.feeLevel); - - usingCustomFee = newFeeLevel == 'custom' ? true : false; - - if (tx.feeLevel == newFeeLevel && !usingCustomFee) return; - - tx.feeLevel = newFeeLevel; - if (usingCustomFee) tx.feeRate = parseInt(customFeePerKB); - - updateTx(tx, vm.originWallet, { - clearCache: true, - dryRun: true - }, function() {}); - }; - }; - - function createVanityTransaction(data) { - console.log('createVanityTransaction()'); - var configFeeLevel = config.wallet.settings.feeLevel ? config.wallet.settings.feeLevel : 'normal'; - - // Grab stateParams - tx = { - amount: parseInt(sendFlowData.amount), - sendMax: sendFlowData.sendMax, - fromWalletId: sendFlowData.fromWalletId, - toAddress: sendFlowData.toAddress, - paypro: txPayproData, - - feeLevel: configFeeLevel, - spendUnconfirmed: config.wallet.spendUnconfirmed, - - // Vanity tx info (not in the real tx) - recipientType: vm.destination.kind || null, - toName: vm.destination.name || null, - toEmail: vm.destination.email || null, - toColor: vm.destination.color || null, - network: false, - coin: vm.originWallet.coin, - txp: {}, - }; - - - if (data.stateParams.requiredFeeRate) { - vm.usingMerchantFee = true; - tx.feeRate = parseInt(data.stateParams.requiredFeeRate); - } - - if (tx.coin && tx.coin === 'bch') { - tx.feeLevel = 'normal'; - } - - var B = tx.coin === 'bch' ? bitcoreCash : bitcore; - var networkName; - try { - if (vm.destination.kind === 'wallet') { // This is a wallet-to-wallet transfer - ongoingProcess.set('generatingNewAddress', true); - var toWallet = profileService.getWallet(destinationWalletId); - - // We need an address to send to, so we ask the walletService to create a new address for the toWallet. - console.log('Getting address for wallet...'); - walletService.getAddress(toWallet, true, function onWalletAddress(err, addr) { - console.log('getAddress cb called', err); - ongoingProcess.set('generatingNewAddress', false); - tx.toAddress = addr; + } else { // This is a Wallet-to-address transfer networkName = (new B.Address(tx.toAddress)).network.name; tx.network = networkName; - console.log('calling setupTx() for wallet.'); + console.log('calling setupTx() for address.'); setupTx(tx); - }); - } else { // This is a Wallet-to-address transfer - networkName = (new B.Address(tx.toAddress)).network.name; - tx.network = networkName; - console.log('calling setupTx() for address.'); - setupTx(tx); - } - } catch (e) { - console.error('Error setting up tx', e); - var message = gettextCatalog.getString('Invalid address'); - popupService.showAlert(null, message, function () { - $ionicHistory.nextViewOptions({ - disableAnimate: true, - historyRoot: true - }); - $state.go('tabs.send').then(function () { - $ionicHistory.clearHistory(); - }); - }); - return; - } - } - function getOriginWalletBalance(originWallet) { - var balanceText = getWalletBalanceDisplayText(vm.originWallet); - vm.origin.balanceAmount = balanceText.amount; - vm.origin.balanceCurrency = balanceText.currency; - } - - function getSendMaxInfo(tx, wallet, cb) { - if (!tx.sendMax) return cb(); - - //ongoingProcess.set('retrievingInputs', true); - walletService.getSendMaxInfo(wallet, { - feePerKb: tx.feeRate, - excludeUnconfirmedUtxos: !tx.spendUnconfirmed, - returnInputs: true, - }, cb); - }; - - function getTxp(tx, wallet, dryRun, cb) { - - // ToDo: use a credential's (or fc's) function for this - if (tx.description && !wallet.credentials.sharedEncryptingKey) { - var msg = gettextCatalog.getString('Could not add message to imported wallet without shared encrypting key'); - $log.warn(msg); - return setSendError(msg); - } - - if (tx.amount > Number.MAX_SAFE_INTEGER) { - var msg = gettextCatalog.getString('Amount too big'); - $log.warn(msg); - return setSendError(msg); - } - - var txp = {}; - - txp.outputs = [{ - 'toAddress': tx.toAddress, - 'amount': tx.amount, - 'message': vm.memo - }]; - - if (tx.sendMaxInfo) { - txp.inputs = tx.sendMaxInfo.inputs; - txp.fee = tx.sendMaxInfo.fee; - } else { - if (usingCustomFee || usingMerchantFee) { - txp.feePerKb = tx.feeRate; - } else txp.feeLevel = tx.feeLevel; - } - - txp.message = vm.memo; - - if (tx.paypro) { - txp.payProUrl = tx.paypro.url; - } - txp.excludeUnconfirmedUtxos = !tx.spendUnconfirmed; - txp.dryRun = dryRun; - walletService.createTx(wallet, txp, function(err, ctxp) { - if (err) { - setSendError(err); - return cb(err); - } - return cb(null, ctxp); - }); - }; - - function getWalletBalanceDisplayText(wallet) { - var balanceCryptoAmount = ''; - var balanceCryptoCurrencyCode = ''; - var balanceFiatAmount = ''; - var balanceFiatCurrency = ''; - var displayAmount = ''; - var displayCurrency = ''; - - var walletStatus = null; - if (wallet.status && wallet.status.isValid) { - walletStatus = wallet.status; - } else if (wallet.cachedStatus.isValid) { - walletStatus = wallet.cachedStatus; - } - - if (walletStatus) { - var cryptoBalanceParts = walletStatus.spendableBalanceStr.split(' '); - balanceCryptoAmount = cryptoBalanceParts[0]; - balanceCryptoCurrencyCode = cryptoBalanceParts.length > 1 ? cryptoBalanceParts[1] : ''; - - if (walletStatus.alternativeBalanceAvailable) { - balanceFiatAmount = walletStatus.spendableBalanceAlternative; - balanceFiatCurrency = walletStatus.alternativeIsoCode; - } - } - - if (priceDisplayIsFiat) { - displayAmount = balanceFiatAmount ? balanceFiatAmount : balanceCryptoAmount; - displayCurrency = balanceFiatAmount ? balanceFiatCurrency : balanceCryptoCurrencyCode; - } else { - displayAmount = balanceCryptoAmount; - displayCurrency = balanceCryptoCurrencyCode; - } - - return { - amount: displayAmount, - currency: displayCurrency - }; - } - - function goBack() { - sendFlowService.router.goBack(); - } - - function handleDestinationAsAddress(address, originCoin) { - if (!address) { - return; - } - - // Check if the recipient is a contact - addressbookService.get(originCoin + address, function(err, contact) { - if (!err && contact) { - handleDestinationAsAddressOfContact(contact); - } else { - if (originCoin === 'bch') { - vm.destination.address = bitcoinCashJsService.readAddress(address).cashaddr; - } else { - vm.destination.address = address; } - vm.destination.kind = 'address'; + } catch (e) { + console.error('Error setting up tx', e); + var message = gettextCatalog.getString('Invalid address'); + popupService.showAlert(null, message, function () { + $ionicHistory.nextViewOptions({ + disableAnimate: true, + historyRoot: true + }); + $state.go('tabs.send').then(function () { + $ionicHistory.clearHistory(); + }); + }); + return; } - }); - - } - - function handleDestinationAsAddressOfContact(contact) { - vm.destination.kind = 'contact'; - vm.destination.name = contact.name; - vm.destination.email = contact.email; - vm.destination.color = contact.coin === 'btc' ? defaults.bitcoinWalletColor : defaults.bitcoinCashWalletColor; - vm.destination.currency = contact.coin.toUpperCase(); - vm.destination.currencyColor = vm.destination.color; - } - - function handleDestinationAsWallet(walletId) { - destinationWalletId = walletId; - if (!destinationWalletId) { - return; + } + function getOriginWalletBalance(originWallet) { + var balanceText = getWalletBalanceDisplayText(vm.originWallet); + vm.origin.balanceAmount = balanceText.amount; + vm.origin.balanceCurrency = balanceText.currency; } - var destinationWallet = profileService.getWallet(destinationWalletId); - vm.destination.coin = destinationWallet.coin; - vm.destination.color = destinationWallet.color; - vm.destination.currency = destinationWallet.coin.toUpperCase(); - vm.destination.kind = 'wallet'; - vm.destination.name = destinationWallet.name; + function getSendMaxInfo(tx, wallet, cb) { + if (!tx.sendMax) return cb(); - if (defaults) { - vm.destination.currencyColor = vm.destination.coin === 'btc' ? defaults.bitcoinWalletColor : defaults.bitcoinCashWalletColor; - } - - var balanceText = getWalletBalanceDisplayText(destinationWallet); - vm.destination.balanceAmount = balanceText.amount; - vm.destination.balanceCurrency = balanceText.currency; - } - - function initBip70() { - vm.sendingTitle = gettextCatalog.getString('You are paying'); - vm.memo = vm.thirdParty.memo; - vm.memoExpanded = !!vm.memo; - vm.destination.name = vm.thirdParty.name; - - txPayproData = { - caTrusted: vm.thirdParty.caTrusted, - domain: vm.thirdParty.domain, - expires: vm.thirdParty.expires, - toAddress: toAddress, - url: vm.thirdParty.url, - verified: vm.thirdParty.verified, + //ongoingProcess.set('retrievingInputs', true); + walletService.getSendMaxInfo(wallet, { + feePerKb: tx.feeRate, + excludeUnconfirmedUtxos: !tx.spendUnconfirmed, + returnInputs: true, + }, cb); }; - } - function initShapeshift(cb) { - vm.sendingTitle = gettextCatalog.getString('You are shifting'); - if (!vm.thirdParty.data) { - vm.thirdParty.data = {}; + function getTxp(tx, wallet, dryRun, cb) { + + // ToDo: use a credential's (or fc's) function for this + if (tx.description && !wallet.credentials.sharedEncryptingKey) { + var msg = gettextCatalog.getString('Could not add message to imported wallet without shared encrypting key'); + $log.warn(msg); + return setSendError(msg); + } + + if (tx.amount > Number.MAX_SAFE_INTEGER) { + var msg = gettextCatalog.getString('Amount too big'); + $log.warn(msg); + return setSendError(msg); + } + + var txp = {}; + + txp.outputs = [{ + 'toAddress': tx.toAddress, + 'amount': tx.amount, + 'message': vm.memo + }]; + + if (tx.sendMaxInfo) { + txp.inputs = tx.sendMaxInfo.inputs; + txp.fee = tx.sendMaxInfo.fee; + } else { + if (usingCustomFee || usingMerchantFee) { + txp.feePerKb = tx.feeRate; + } else txp.feeLevel = tx.feeLevel; + } + + txp.message = vm.memo; + + if (tx.paypro) { + txp.payProUrl = tx.paypro.url; + } + txp.excludeUnconfirmedUtxos = !tx.spendUnconfirmed; + txp.dryRun = dryRun; + walletService.createTx(wallet, txp, function(err, ctxp) { + if (err) { + setSendError(err); + return cb(err); + } + return cb(null, ctxp); + }); + }; + + function getWalletBalanceDisplayText(wallet) { + var balanceCryptoAmount = ''; + var balanceCryptoCurrencyCode = ''; + var balanceFiatAmount = ''; + var balanceFiatCurrency = ''; + var displayAmount = ''; + var displayCurrency = ''; + + var walletStatus = null; + if (wallet.status && wallet.status.isValid) { + walletStatus = wallet.status; + } else if (wallet.cachedStatus.isValid) { + walletStatus = wallet.cachedStatus; + } + + if (walletStatus) { + var cryptoBalanceParts = walletStatus.spendableBalanceStr.split(' '); + balanceCryptoAmount = cryptoBalanceParts[0]; + balanceCryptoCurrencyCode = cryptoBalanceParts.length > 1 ? cryptoBalanceParts[1] : ''; + + if (walletStatus.alternativeBalanceAvailable) { + balanceFiatAmount = walletStatus.spendableBalanceAlternative; + balanceFiatCurrency = walletStatus.alternativeIsoCode; + } + } + + if (priceDisplayIsFiat) { + displayAmount = balanceFiatAmount ? balanceFiatAmount : balanceCryptoAmount; + displayCurrency = balanceFiatAmount ? balanceFiatCurrency : balanceCryptoCurrencyCode; + } else { + displayAmount = balanceCryptoAmount; + displayCurrency = balanceCryptoCurrencyCode; + } + + return { + amount: displayAmount, + currency: displayCurrency + }; } - var toWallet = profileService.getWallet(destinationWalletId); - vm.destination.name = toWallet.name; - vm.destination.color = toWallet.color; - vm.destination.currency = toWallet.coin.toUpperCase(); + function goBack() { + sendFlowService.router.goBack(); + } + + function handleDestinationAsAddress(address, originCoin) { + if (!address) { + return; + } + + // Check if the recipient is a contact + addressbookService.get(originCoin + address, function(err, contact) { + if (!err && contact) { + handleDestinationAsAddressOfContact(contact); + } else { + if (originCoin === 'bch') { + vm.destination.address = bitcoinCashJsService.readAddress(address).cashaddr; + } else { + vm.destination.address = address; + } + vm.destination.kind = 'address'; + } + }); + + } + + function handleDestinationAsAddressOfContact(contact) { + vm.destination.kind = 'contact'; + vm.destination.name = contact.name; + vm.destination.email = contact.email; + vm.destination.color = contact.coin === 'btc' ? defaults.bitcoinWalletColor : defaults.bitcoinCashWalletColor; + vm.destination.currency = contact.coin.toUpperCase(); + vm.destination.currencyColor = vm.destination.color; + } + + function handleDestinationAsWallet(walletId) { + destinationWalletId = walletId; + if (!destinationWalletId) { + return; + } + + var destinationWallet = profileService.getWallet(destinationWalletId); + vm.destination.coin = destinationWallet.coin; + vm.destination.color = destinationWallet.color; + vm.destination.currency = destinationWallet.coin.toUpperCase(); + vm.destination.kind = 'wallet'; + vm.destination.name = destinationWallet.name; + + if (defaults) { + vm.destination.currencyColor = vm.destination.coin === 'btc' ? defaults.bitcoinWalletColor : defaults.bitcoinCashWalletColor; + } + + var balanceText = getWalletBalanceDisplayText(destinationWallet); + vm.destination.balanceAmount = balanceText.amount; + vm.destination.balanceCurrency = balanceText.currency; + } + + function initBip70() { + vm.sendingTitle = gettextCatalog.getString('You are paying'); + vm.memo = vm.thirdParty.memo; + vm.memoExpanded = !!vm.memo; + vm.destination.name = vm.thirdParty.name; + + txPayproData = { + caTrusted: vm.thirdParty.caTrusted, + domain: vm.thirdParty.domain, + expires: vm.thirdParty.expires, + toAddress: toAddress, + url: vm.thirdParty.url, + verified: vm.thirdParty.verified, + }; + } + + function initShapeshift(cb) { + vm.sendingTitle = gettextCatalog.getString('You are shifting'); + if (!vm.thirdParty.data) { + vm.thirdParty.data = {}; + } + + var toWallet = profileService.getWallet(destinationWalletId); + vm.destination.name = toWallet.name; + vm.destination.color = toWallet.color; + vm.destination.currency = toWallet.coin.toUpperCase(); - ongoingProcess.set('connectingShapeshift', true); - walletService.getAddress(vm.originWallet, false, function onReturnWalletAddress(err, returnAddr) { - if (err) { - return cb(err); - } - walletService.getAddress(toWallet, false, function onWithdrawalWalletAddress(err, withdrawalAddr) { + ongoingProcess.set('connectingShapeshift', true); + walletService.getAddress(vm.originWallet, false, function onReturnWalletAddress(err, returnAddr) { if (err) { return cb(err); } - - // Need to use the correct service to do it. - var amount = parseFloat(satoshis / 100000000); - - shapeshiftService.shiftIt(vm.originWallet.coin, toWallet.coin, withdrawalAddr, returnAddr, amount, function onShiftIt(err, shapeshiftData) { + walletService.getAddress(toWallet, false, function onWithdrawalWalletAddress(err, withdrawalAddr) { if (err) { return cb(err); - } else { - vm.destination.kind = 'shapeshift'; - vm.destination.address = toAddress; - tx.toAddress = shapeshiftData.toAddress; - vm.memo = 'ShapeShift Order:\nhttps://www.shapeshift.io/#/status/' + shapeshiftData.orderId; - vm.memoExpanded = !!vm.memo; - ongoingProcess.set('connectingShapeshift', false); - cb(); - } + } + + // Need to use the correct service to do it. + var amount = parseFloat(satoshis / 100000000); + + shapeshiftService.shiftIt(vm.originWallet.coin, toWallet.coin, withdrawalAddr, returnAddr, amount, function onShiftIt(err, shapeshiftData) { + if (err) { + return cb(err); + } else { + vm.destination.kind = 'shapeshift'; + vm.destination.address = toAddress; + tx.toAddress = shapeshiftData.toAddress; + vm.memo = 'ShapeShift Order:\nhttps://www.shapeshift.io/#/status/' + shapeshiftData.orderId; + vm.memoExpanded = !!vm.memo; + ongoingProcess.set('connectingShapeshift', false); + cb(); + } + }); }); }); - }); - } - - function onShareTransaction() { - var explorerTxUrl = 'https://explorer.bitcoin.com/' + tx.coin + '/tx/' + lastTxId; - if (platformInfo.isCordova) { - var text = gettextCatalog.getString('Take a look at this Bitcoin Cash transaction here: ') + explorerTxUrl; - if (coin === 'btc') { - text = gettextCatalog.getString('Take a look at this Bitcoin transaction here: ') + explorerTxUrl; - } - window.plugins.socialsharing.share(text, null, null, null); - } else { - ionicToast.show(gettextCatalog.getString('Copied to clipboard'), 'bottom', false, 3000); - clipboardService.copyToClipboard(explorerTxUrl); } - - } - function startExpirationTimer(expirationTime) { - vm.paymentExpired = false; - setExpirationTime(); + function onShareTransaction() { + var explorerTxUrl = 'https://explorer.bitcoin.com/' + tx.coin + '/tx/' + lastTxId; + if (platformInfo.isCordova) { + var text = gettextCatalog.getString('Take a look at this Bitcoin Cash transaction here: ') + explorerTxUrl; + if (coin === 'btc') { + text = gettextCatalog.getString('Take a look at this Bitcoin transaction here: ') + explorerTxUrl; + } + window.plugins.socialsharing.share(text, null, null, null); + } else { + ionicToast.show(gettextCatalog.getString('Copied to clipboard'), 'bottom', false, 3000); + clipboardService.copyToClipboard(explorerTxUrl); + } + + } - countDown = $interval(function() { + function startExpirationTimer(expirationTime) { + vm.paymentExpired = false; setExpirationTime(); - }, 1000); - function setExpirationTime() { - console.log('setExpirationTime()'); - var now = Math.floor(Date.now() / 1000); + countDown = $interval(function() { + setExpirationTime(); + }, 1000); - if (now > expirationTime) { - setExpiredValues(); + function setExpirationTime() { + console.log('setExpirationTime()'); + var now = Math.floor(Date.now() / 1000); + + if (now > expirationTime) { + setExpiredValues(); + return; + } + + var totalSecs = expirationTime - now; + var m = Math.floor(totalSecs / 60); + var s = totalSecs % 60; + vm.remainingTimeStr = m + ":" + ('0' + s).slice(-2); + }; + + function setExpiredValues() { + vm.paymentExpired = true; + vm.remainingTimeStr = gettextCatalog.getString('Expired'); + vm.readyToSend = false; + if (countDown) $interval.cancel(countDown); + $timeout(function() { + $scope.$apply(); + }); + }; + }; + + function updateSendAmounts() { + if (typeof satoshis !== 'number') { return; } - var totalSecs = expirationTime - now; - var m = Math.floor(totalSecs / 60); - var s = totalSecs % 60; - vm.remainingTimeStr = m + ":" + ('0' + s).slice(-2); + var cryptoAmount = ''; + var cryptoCurrencyCode = ''; + var amountStr = txFormatService.formatAmountStr(coin, satoshis); + if (amountStr) { + var amountParts = amountStr.split(' '); + cryptoAmount = amountParts[0]; + cryptoCurrencyCode = amountParts.length > 1 ? amountParts[1] : ''; + } + // Want to avoid flashing of amount strings so do all formatting after this has returned. + txFormatService.formatAlternativeStr(coin, satoshis, function(v) { + if (!v) { + vm.primaryAmount = cryptoAmount; + vm.primaryCurrency = cryptoCurrencyCode; + vm.secondaryAmount = ''; + vm.secondaryCurrency = ''; + return; + } + vm.secondaryAmount = vm.primaryAmount; + vm.secondaryCurrency = vm.primaryCurrency; + + var fiatParts = v.split(' '); + var fiatAmount = fiatParts[0]; + var fiatCurrency = fiatParts.length > 1 ? fiatParts[1] : ''; + + if (priceDisplayIsFiat) { + vm.primaryAmount = fiatAmount; + vm.primaryCurrency = fiatCurrency; + vm.secondaryAmount = cryptoAmount; + vm.secondaryCurrency = cryptoCurrencyCode; + } else { + vm.primaryAmount = cryptoAmount; + vm.primaryCurrency = cryptoCurrencyCode; + vm.secondaryAmount = fiatAmount; + vm.secondaryCurrency = fiatCurrency; + } + }); + } + + function onSuccessConfirm() { + vm.sendStatus = ''; + $ionicHistory.nextViewOptions({ + disableAnimate: true, + historyRoot: true + }); + $state.go('tabs.send').then(function() { + $ionicHistory.clearHistory(); + $state.transitionTo('tabs.home'); + }); }; - function setExpiredValues() { - vm.paymentExpired = true; - vm.remainingTimeStr = gettextCatalog.getString('Expired'); + function setButtonText(isMultisig, isPayPro) { + if (isPayPro) { + if (vm.isCordova) { + vm.buttonText = gettextCatalog.getString('Slide to pay'); + } else { + vm.buttonText = gettextCatalog.getString('Click to pay'); + } + } else if (isMultisig) { + if (vm.isCordova) { + vm.buttonText = gettextCatalog.getString('Slide to accept'); + } else { + vm.buttonText = gettextCatalog.getString('Click to accept'); + } + } else { + if (vm.isCordova) { + vm.buttonText = gettextCatalog.getString('Slide to send'); + } else { + vm.buttonText = gettextCatalog.getString('Click to send'); + } + } + } + + function setNotReady(msg, criticalError) { + vn.readyToSend = false; + vm.notReadyMessage = msg; + $scope.criticalError = criticalError; + $log.warn('Not ready to make the payment:' + msg); + $timeout(function() { + $scope.$apply(); + }); + }; + + function setSendError(msg) { + $scope.sendStatus = ''; vm.readyToSend = false; - if (countDown) $interval.cancel(countDown); $timeout(function() { $scope.$apply(); }); - }; - }; - - function updateSendAmounts() { - if (typeof satoshis !== 'number') { - return; - } - - var cryptoAmount = ''; - var cryptoCurrencyCode = ''; - var amountStr = txFormatService.formatAmountStr(coin, satoshis); - if (amountStr) { - var amountParts = amountStr.split(' '); - cryptoAmount = amountParts[0]; - cryptoCurrencyCode = amountParts.length > 1 ? amountParts[1] : ''; - } - // Want to avoid flashing of amount strings so do all formatting after this has returned. - txFormatService.formatAlternativeStr(coin, satoshis, function(v) { - if (!v) { - vm.primaryAmount = cryptoAmount; - vm.primaryCurrency = cryptoCurrencyCode; - vm.secondaryAmount = ''; - vm.secondaryCurrency = ''; - return; - } - vm.secondaryAmount = vm.primaryAmount; - vm.secondaryCurrency = vm.primaryCurrency; - - var fiatParts = v.split(' '); - var fiatAmount = fiatParts[0]; - var fiatCurrency = fiatParts.length > 1 ? fiatParts[1] : ''; - - if (priceDisplayIsFiat) { - vm.primaryAmount = fiatAmount; - vm.primaryCurrency = fiatCurrency; - vm.secondaryAmount = cryptoAmount; - vm.secondaryCurrency = cryptoCurrencyCode; - } else { - vm.primaryAmount = cryptoAmount; - vm.primaryCurrency = cryptoCurrencyCode; - vm.secondaryAmount = fiatAmount; - vm.secondaryCurrency = fiatCurrency; - } - }); - } - - function onSuccessConfirm() { - vm.sendStatus = ''; - $ionicHistory.nextViewOptions({ - disableAnimate: true, - historyRoot: true - }); - $state.go('tabs.send').then(function() { - $ionicHistory.clearHistory(); - $state.transitionTo('tabs.home'); - }); - }; - - function setButtonText(isMultisig, isPayPro) { - if (isPayPro) { - if (vm.isCordova) { - vm.buttonText = gettextCatalog.getString('Slide to pay'); - } else { - vm.buttonText = gettextCatalog.getString('Click to pay'); - } - } else if (isMultisig) { - if (vm.isCordova) { - vm.buttonText = gettextCatalog.getString('Slide to accept'); - } else { - vm.buttonText = gettextCatalog.getString('Click to accept'); - } - } else { - if (vm.isCordova) { - vm.buttonText = gettextCatalog.getString('Slide to send'); - } else { - vm.buttonText = gettextCatalog.getString('Click to send'); - } - } - } - - function setNotReady(msg, criticalError) { - vn.readyToSend = false; - vm.notReadyMessage = msg; - $scope.criticalError = criticalError; - $log.warn('Not ready to make the payment:' + msg); - $timeout(function() { - $scope.$apply(); - }); - }; - - function setSendError(msg) { - $scope.sendStatus = ''; - vm.readyToSend = false; - $timeout(function() { - $scope.$apply(); - }); - popupService.showAlert(gettextCatalog.getString('Error at confirm'), bwcError.msg(msg), function () { - $ionicHistory.goBack(); - }); - }; - - function setupTx(tx) { - if (tx.coin === 'bch') { - tx.displayAddress = bitcoinCashJsService.readAddress(tx.toAddress).cashaddr; - } else { - tx.displayAddress = tx.toAddress; - } - - addressbookService.get(tx.coin+tx.toAddress, function(err, addr) { // Check if the recipient is a contact - if (!err && addr) { - tx.toName = addr.name; - tx.toEmail = addr.email; - tx.recipientType = 'contact'; - } - }); - - vm.showAddress = false; - - - setButtonText(vm.originWallet.credentials.m > 1, !!tx.paypro); - - if (tx.paypro) - startExpirationTimer(tx.paypro.expires); - - updateTx(tx, vm.originWallet, { - dryRun: true - }, function(err) { - $timeout(function() { - $scope.$apply(); - }, 10); - - }); - - // setWalletSelector(tx.coin, tx.network, tx.amount, function(err) { - // if (err) { - // return exitWithError('Could not update wallets'); - // } - // - // if (vm.wallets.length > 1) { - // vm.showWalletSelector(); - // } else if (vm.wallets.length) { - // setWallet(vm.wallets[0], tx); - // } - // }); - } - - function showSendMaxWarning(wallet, sendMaxInfo) { - var feeAlternative = '', - msg = ''; - - function verifyExcludedUtxos() { - var warningMsg = []; - if (sendMaxInfo.utxosBelowFee > 0) { - warningMsg.push(gettextCatalog.getString("A total of {{amountBelowFeeStr}} were excluded. These funds come from UTXOs smaller than the network fee provided.", { - amountBelowFeeStr: txFormatService.formatAmountStr(wallet.coin, sendMaxInfo.amountBelowFee) - })); - } - - if (sendMaxInfo.utxosAboveMaxSize > 0) { - warningMsg.push(gettextCatalog.getString("A total of {{amountAboveMaxSizeStr}} were excluded. The maximum size allowed for a transaction was exceeded.", { - amountAboveMaxSizeStr: txFormatService.formatAmountStr(vm.originWallet.coin, sendMaxInfo.amountAboveMaxSize) - })); - } - return warningMsg.join('\n'); + popupService.showAlert(gettextCatalog.getString('Error at confirm'), bwcError.msg(msg), function () { + $ionicHistory.goBack(); + }); }; - feeAlternative = txFormatService.formatAlternativeStr(vm.originWallet.coin, sendMaxInfo.fee); - if (feeAlternative) { - msg = gettextCatalog.getString("{{feeAlternative}} will be deducted for bitcoin networking fees ({{fee}}).", { - fee: txFormatService.formatAmountStr(vm.originWallet.coin, sendMaxInfo.fee), - feeAlternative: feeAlternative - }); - } else { - msg = gettextCatalog.getString("{{fee}} will be deducted for bitcoin networking fees).", { - fee: txFormatService.formatAmountStr(vm.originWallet.coin, sendMaxInfo.fee) - }); - } - - var warningMsg = verifyExcludedUtxos(); - - if (!lodash.isEmpty(warningMsg)) - msg += '\n' + warningMsg; - - popupService.showAlert(null, msg, function() {}); - }; - - function statusChangeHandler(processName, showName, isOn) { - $log.debug('statusChangeHandler: ', processName, showName, isOn); - if ( - ( - processName === 'broadcastingTx' || - ((processName === 'signingTx') && vm.originWallet.m > 1) || - (processName == 'sendingTx' && !vm.originWallet.canSign() && !vm.originWallet.isPrivKeyExternal()) - ) && !isOn) { - // Show the popup - vm.sendStatus = 'success'; - - // Clear the send flow service state - sendFlowService.state.clear(); - - if ($state.current.name === "tabs.send.review") { // XX SP: Otherwise all open wallets on other devices play this sound if you have been in a send flow before on that device. - soundService.play('misc/payment_sent.mp3'); - } - - var channel = "firebase"; - if (platformInfo.isNW) { - channel = "ga"; - } - // When displaying Fiat, if the formatting fails, the crypto will be the primary amount. - var amount = unitFromSat * satoshis; - var log = new window.BitAnalytics.LogEvent("transfer_success", [{ - "coin": vm.originWallet.coin, - "type": "outgoing", - "amount": amount, - "fees": vm.feeCrypto - }], [channel, "adjust"]); - window.BitAnalytics.LogEventHandlers.postEvent(log); - - $timeout(function() { - $scope.$digest(); - }, 100); - } else if (showName) { - vm.sendStatus = showName; - } - }; - - function updateTx(tx, wallet, opts, cb) { - ongoingProcess.set('calculatingFee', true); - - if (opts.clearCache) { - tx.txp = {}; - } - - // $scope.tx = tx; - - // function updateAmount() { - // if (!tx.amount) return; - // - // // Amount - // tx.amountStr = txFormatService.formatAmountStr(originWallet.coin, tx.amount); - // tx.amountValueStr = tx.amountStr.split(' ')[0]; - // tx.amountUnitStr = tx.amountStr.split(' ')[1]; - // txFormatService.formatAlternativeStr(wallet.coin, tx.amount, function(v) { - // var parts = v.split(' '); - // tx.alternativeAmountStr = v; - // tx.alternativeAmountValueStr = parts[0]; - // tx.alternativeAmountUnitStr = (parts.length > 0) ? parts[1] : ''; - // }); - // } - // - // updateAmount(); - // refresh(); - - var feeServiceLevel = usingMerchantFee && vm.originWallet.coin == 'btc' ? 'urgent' : tx.feeLevel; - feeService.getFeeRate(vm.originWallet.coin, tx.network, feeServiceLevel, function(err, feeRate) { - if (err) { - ongoingProcess.set('calculatingFee', false); - return cb(err); - } - - var msg; - if (usingCustomFee) { - msg = gettextCatalog.getString('Custom'); - tx.feeLevelName = msg; - } else if (usingMerchantFee) { - $log.info('Using Merchant Fee:' + tx.feeRate + ' vs. Urgent level:' + feeRate); - msg = gettextCatalog.getString('Suggested by Merchant'); - tx.feeLevelName = msg; + function setupTx(tx) { + if (tx.coin === 'bch') { + tx.displayAddress = bitcoinCashJsService.readAddress(tx.toAddress).cashaddr; } else { - tx.feeLevelName = feeService.feeOpts[tx.feeLevel]; - tx.feeRate = feeRate; + tx.displayAddress = tx.toAddress; } - getSendMaxInfo(lodash.clone(tx), wallet, function(err, sendMaxInfo) { + addressbookService.get(tx.coin+tx.toAddress, function(err, addr) { // Check if the recipient is a contact + if (!err && addr) { + tx.toName = addr.name; + tx.toEmail = addr.email; + tx.recipientType = 'contact'; + } + }); + + vm.showAddress = false; + + + setButtonText(vm.originWallet.credentials.m > 1, !!tx.paypro); + + if (tx.paypro) + startExpirationTimer(tx.paypro.expires); + + updateTx(tx, vm.originWallet, { + dryRun: true + }, function(err) { + $timeout(function() { + $scope.$apply(); + }, 10); + + }); + + // setWalletSelector(tx.coin, tx.network, tx.amount, function(err) { + // if (err) { + // return exitWithError('Could not update wallets'); + // } + // + // if (vm.wallets.length > 1) { + // vm.showWalletSelector(); + // } else if (vm.wallets.length) { + // setWallet(vm.wallets[0], tx); + // } + // }); + } + + function showSendMaxWarning(wallet, sendMaxInfo) { + var feeAlternative = '', + msg = ''; + + function verifyExcludedUtxos() { + var warningMsg = []; + if (sendMaxInfo.utxosBelowFee > 0) { + warningMsg.push(gettextCatalog.getString("A total of {{amountBelowFeeStr}} were excluded. These funds come from UTXOs smaller than the network fee provided.", { + amountBelowFeeStr: txFormatService.formatAmountStr(wallet.coin, sendMaxInfo.amountBelowFee) + })); + } + + if (sendMaxInfo.utxosAboveMaxSize > 0) { + warningMsg.push(gettextCatalog.getString("A total of {{amountAboveMaxSizeStr}} were excluded. The maximum size allowed for a transaction was exceeded.", { + amountAboveMaxSizeStr: txFormatService.formatAmountStr(vm.originWallet.coin, sendMaxInfo.amountAboveMaxSize) + })); + } + return warningMsg.join('\n'); + }; + + feeAlternative = txFormatService.formatAlternativeStr(vm.originWallet.coin, sendMaxInfo.fee); + if (feeAlternative) { + msg = gettextCatalog.getString("{{feeAlternative}} will be deducted for bitcoin networking fees ({{fee}}).", { + fee: txFormatService.formatAmountStr(vm.originWallet.coin, sendMaxInfo.fee), + feeAlternative: feeAlternative + }); + } else { + msg = gettextCatalog.getString("{{fee}} will be deducted for bitcoin networking fees).", { + fee: txFormatService.formatAmountStr(vm.originWallet.coin, sendMaxInfo.fee) + }); + } + + var warningMsg = verifyExcludedUtxos(); + + if (!lodash.isEmpty(warningMsg)) + msg += '\n' + warningMsg; + + popupService.showAlert(null, msg, function() {}); + }; + + function statusChangeHandler(processName, showName, isOn) { + $log.debug('statusChangeHandler: ', processName, showName, isOn); + if ( + ( + processName === 'broadcastingTx' || + ((processName === 'signingTx') && vm.originWallet.m > 1) || + (processName == 'sendingTx' && !vm.originWallet.canSign() && !vm.originWallet.isPrivKeyExternal()) + ) && !isOn) { + // Show the popup + vm.sendStatus = 'success'; + + // Clear the send flow service state + sendFlowService.state.clear(); + + if ($state.current.name === "tabs.send.review") { // XX SP: Otherwise all open wallets on other devices play this sound if you have been in a send flow before on that device. + soundService.play('misc/payment_sent.mp3'); + } + + var channel = "firebase"; + if (platformInfo.isNW) { + channel = "ga"; + } + // When displaying Fiat, if the formatting fails, the crypto will be the primary amount. + var amount = unitFromSat * satoshis; + var log = new window.BitAnalytics.LogEvent("transfer_success", [{ + "coin": vm.originWallet.coin, + "type": "outgoing", + "amount": amount, + "fees": vm.feeCrypto + }], [channel, "adjust"]); + window.BitAnalytics.LogEventHandlers.postEvent(log); + + $timeout(function() { + $scope.$digest(); + }, 100); + } else if (showName) { + vm.sendStatus = showName; + } + }; + + function updateTx(tx, wallet, opts, cb) { + ongoingProcess.set('calculatingFee', true); + + if (opts.clearCache) { + tx.txp = {}; + } + + // $scope.tx = tx; + + // function updateAmount() { + // if (!tx.amount) return; + // + // // Amount + // tx.amountStr = txFormatService.formatAmountStr(originWallet.coin, tx.amount); + // tx.amountValueStr = tx.amountStr.split(' ')[0]; + // tx.amountUnitStr = tx.amountStr.split(' ')[1]; + // txFormatService.formatAlternativeStr(wallet.coin, tx.amount, function(v) { + // var parts = v.split(' '); + // tx.alternativeAmountStr = v; + // tx.alternativeAmountValueStr = parts[0]; + // tx.alternativeAmountUnitStr = (parts.length > 0) ? parts[1] : ''; + // }); + // } + // + // updateAmount(); + // refresh(); + + var feeServiceLevel = usingMerchantFee && vm.originWallet.coin == 'btc' ? 'urgent' : tx.feeLevel; + feeService.getFeeRate(vm.originWallet.coin, tx.network, feeServiceLevel, function(err, feeRate) { if (err) { ongoingProcess.set('calculatingFee', false); - var msg = gettextCatalog.getString('Error getting SendMax information'); - return setSendError(msg); + return cb(err); } - if (sendMaxInfo) { - - $log.debug('Send max info', sendMaxInfo); - - if (tx.sendMax && sendMaxInfo.amount == 0) { - ongoingProcess.set('calculatingFee', false); - setNotReady(gettextCatalog.getString('Insufficient confirmed funds')); - popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Not enough funds for fee'), function () { - $ionicHistory.goBack(); - }); - return cb('no_funds'); - } - - tx.sendMaxInfo = sendMaxInfo; - tx.amount = tx.sendMaxInfo.amount; - satoshis = tx.amount; - updateSendAmounts(); - ongoingProcess.set('calculatingFee', false); - $timeout(function() { - showSendMaxWarning(wallet, sendMaxInfo); - }, 200); + var msg; + if (usingCustomFee) { + msg = gettextCatalog.getString('Custom'); + tx.feeLevelName = msg; + } else if (usingMerchantFee) { + $log.info('Using Merchant Fee:' + tx.feeRate + ' vs. Urgent level:' + feeRate); + msg = gettextCatalog.getString('Suggested by Merchant'); + tx.feeLevelName = msg; + } else { + tx.feeLevelName = feeService.feeOpts[tx.feeLevel]; + tx.feeRate = feeRate; } - // txp already generated for this wallet? - if (tx.txp[wallet.id]) { - ongoingProcess.set('calculatingFee', false); - vm.readyToSend = true; - updateSendAmounts(); - $scope.$apply(); - return cb(); - } - - console.log('calling getTxp() from getSendMaxInfo cb.'); - getTxp(lodash.clone(tx), wallet, opts.dryRun, function(err, txp) { - ongoingProcess.set('calculatingFee', false); + getSendMaxInfo(lodash.clone(tx), wallet, function(err, sendMaxInfo) { if (err) { - if (err.message == 'Insufficient funds') { - setNotReady(gettextCatalog.getString('Insufficient funds')); - popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Not enough funds for fee')); - return cb('no_funds'); - } else - return cb(err); + ongoingProcess.set('calculatingFee', false); + var msg = gettextCatalog.getString('Error getting SendMax information'); + return setSendError(msg); } - txp.feeStr = txFormatService.formatAmountStr(wallet.coin, txp.fee); - txFormatService.formatAlternativeStr(wallet.coin, txp.fee, function(v) { - // txp.alternativeFeeStr = v; - // if (txp.alternativeFeeStr.substring(0, 4) == '0.00') - // txp.alternativeFeeStr = '< ' + txp.alternativeFeeStr; - vm.feeFiat = v; - vm.fiatCurrency = config.wallet.settings.alternativeIsoCode; - if (v.substring(0, 1) === "<") { - vm.feeLessThanACent = true; + if (sendMaxInfo) { + + $log.debug('Send max info', sendMaxInfo); + + if (tx.sendMax && sendMaxInfo.amount == 0) { + ongoingProcess.set('calculatingFee', false); + setNotReady(gettextCatalog.getString('Insufficient confirmed funds')); + popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Not enough funds for fee'), function () { + $ionicHistory.goBack(); + }); + return cb('no_funds'); } - - console.log("fiat", vm.feeFiat); + tx.sendMaxInfo = sendMaxInfo; + tx.amount = tx.sendMaxInfo.amount; + satoshis = tx.amount; + updateSendAmounts(); + ongoingProcess.set('calculatingFee', false); + $timeout(function() { + showSendMaxWarning(wallet, sendMaxInfo); + }, 200); + } + + // txp already generated for this wallet? + if (tx.txp[wallet.id]) { + ongoingProcess.set('calculatingFee', false); + vm.readyToSend = true; + updateSendAmounts(); + $scope.$apply(); + return cb(); + } + + console.log('calling getTxp() from getSendMaxInfo cb.'); + getTxp(lodash.clone(tx), wallet, opts.dryRun, function(err, txp) { + ongoingProcess.set('calculatingFee', false); + if (err) { + if (err.message == 'Insufficient funds') { + setNotReady(gettextCatalog.getString('Insufficient funds')); + popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Not enough funds for fee')); + return cb('no_funds'); + } else + return cb(err); + } + + txp.feeStr = txFormatService.formatAmountStr(wallet.coin, txp.fee); + txFormatService.formatAlternativeStr(wallet.coin, txp.fee, function(v) { + // txp.alternativeFeeStr = v; + // if (txp.alternativeFeeStr.substring(0, 4) == '0.00') + // txp.alternativeFeeStr = '< ' + txp.alternativeFeeStr; + vm.feeFiat = v; + vm.fiatCurrency = config.wallet.settings.alternativeIsoCode; + if (v.substring(0, 1) === "<") { + vm.feeLessThanACent = true; + } + + console.log("fiat", vm.feeFiat); + + }); + + var per = (txp.fee / (txp.amount + txp.fee) * 100); + var perString = per.toFixed(2); + txp.feeRatePerStr = (perString == '0.00' ? '< ' : '') + perString + '%'; + txp.feeToHigh = per > FEE_TOO_HIGH_LIMIT_PERCENTAGE; + vm.feeCrypto = (unitFromSat * txp.fee).toFixed(8); + vm.feeIsHigh = txp.feeToHigh; + console.log("crypto", vm.feeCrypto); + + + tx.txp[wallet.id] = txp; + $log.debug('Confirm. TX Fully Updated for wallet:' + wallet.id, tx); + vm.readyToSend = true; + updateSendAmounts(); + console.log('readyToSend:', vm.readyToSend); + $scope.$apply(); + + return cb(); }); - - var per = (txp.fee / (txp.amount + txp.fee) * 100); - var perString = per.toFixed(2); - txp.feeRatePerStr = (perString == '0.00' ? '< ' : '') + perString + '%'; - txp.feeToHigh = per > FEE_TOO_HIGH_LIMIT_PERCENTAGE; - vm.feeCrypto = (unitFromSat * txp.fee).toFixed(8); - vm.feeIsHigh = txp.feeToHigh; - console.log("crypto", vm.feeCrypto); - - - tx.txp[wallet.id] = txp; - $log.debug('Confirm. TX Fully Updated for wallet:' + wallet.id, tx); - vm.readyToSend = true; - updateSendAmounts(); - console.log('readyToSend:', vm.readyToSend); - $scope.$apply(); - - return cb(); }); }); - }); + } } - -} +})(); diff --git a/src/js/controllers/wallet-selector.controller.js b/src/js/controllers/wallet-selector.controller.js index 1a191870d..694852f0f 100644 --- a/src/js/controllers/wallet-selector.controller.js +++ b/src/js/controllers/wallet-selector.controller.js @@ -1,198 +1,204 @@ 'use strict'; -angular.module('copayApp.controllers').controller('walletSelectorController', function($scope, $state, sendFlowService, configService, gettextCatalog, ongoingProcess, profileService, walletService, txFormatService) { +(function () { - var fromWalletId = ''; - var priceDisplayAsFiat = false; - var unitDecimals = 0; - var unitsFromSatoshis = 0; +angular + .module('copayApp.controllers') + .controller('walletSelectorController', walletSelectorController); - $scope.$on("$ionicView.beforeEnter", onBeforeEnter); - $scope.$on("$ionicView.enter", onEnter); - - function onBeforeEnter(event, data) { - if (data.direction == "back") { - sendFlowService.state.pop(); - } + function walletSelectorController ($scope, $state, sendFlowService, configService, gettextCatalog, ongoingProcess, profileService, walletService, txFormatService) { + var fromWalletId = ''; + var priceDisplayAsFiat = false; + var unitDecimals = 0; + var unitsFromSatoshis = 0; - $scope.params = sendFlowService.state.getClone(); - - console.log('walletSelector onBeforeEnter after back sendflow', $scope.params); - - var config = configService.getSync().wallet.settings; - priceDisplayAsFiat = config.priceDisplay === 'fiat'; - unitDecimals = config.unitDecimals; - unitsFromSatoshis = 1 / config.unitToSatoshi; - - if ($scope.params.isWalletTransfer) { - $scope.sendFlowTitle = gettextCatalog.getString('Transfer between wallets'); - } else if (!$scope.params.thirdParty) { - $scope.sendFlowTitle = gettextCatalog.getString('Send'); - } - - $scope.coin = false; // Wallets to show (for destination screen or contacts) - $scope.type = $scope.params['fromWalletId'] ? 'destination' : 'origin'; // origin || destination - fromWalletId = $scope.params['fromWalletId']; - - if ($scope.type === 'destination' && $scope.params.toAddress) { - $state.transitionTo(getNextStep($scope.params)); - } - - if ($scope.params.coin) { - $scope.coin = $scope.params.coin; // Contacts have a coin embedded - } - - if ($scope.params.amount) { // There is an amount, so presume that it is a payment request - $scope.sendFlowTitle = gettextCatalog.getString('Payment Request'); - $scope.specificAmount = $scope.specificAlternativeAmount = ''; - $scope.isPaymentRequest = true; - } - if ($scope.params.thirdParty) { - $scope.thirdParty = $scope.params.thirdParty; - } - }; - - function onEnter (event, data) { - configService.whenAvailable(function(config) { - $scope.selectedPriceDisplay = config.wallet.settings.priceDisplay; - }); - - if ($scope.thirdParty) { - // Third party services specific logic - handleThirdPartyIfShapeshift(); - } - - prepareWalletLists(); - formatRequestedAmount(); - }; - - function formatRequestedAmount() { - if ($scope.params.amount) { - var cryptoAmount = (unitsFromSatoshis * $scope.params.amount).toFixed(unitDecimals); - var cryptoCoin = $scope.coin.toUpperCase(); - - txFormatService.formatAlternativeStr($scope.coin, $scope.params.amount, function onFormatAlternativeStr(formatted){ - if (formatted) { - var fiatParts = formatted.split(' '); - var fiatAmount = fiatParts[0]; - var fiatCurrrency = fiatParts.length > 1 ? fiatParts[1] : ''; - - if (priceDisplayAsFiat) { - $scope.requestAmount = fiatAmount; - $scope.requestCurrency = fiatCurrrency; - - $scope.requestAmountSecondary = cryptoAmount; - $scope.requestCurrencySecondary = cryptoCoin; - } else { - $scope.requestAmount = cryptoAmount; - $scope.requestCurrency = cryptoCoin; - - $scope.requestAmountSecondary = fiatAmount; - $scope.requestCurrencySecondary = fiatCurrrency; - } - $scope.$apply(); - } - }); - } - } - - function handleThirdPartyIfShapeshift() { - console.log($scope.thirdParty, $scope.coin); - if ($scope.thirdParty.id === 'shapeshift' && $scope.type === 'destination') { // Shapeshift wants to know the - $scope.coin = profileService.getWallet(fromWalletId).coin; - if ($scope.coin === 'bch') { - $scope.coin = 'btc'; - } else { - $scope.coin = 'bch'; + $scope.$on("$ionicView.beforeEnter", onBeforeEnter); + $scope.$on("$ionicView.enter", onEnter); + + function onBeforeEnter(event, data) { + if (data.direction == "back") { + sendFlowService.state.pop(); } - } - } - function prepareWalletLists() { - var walletsAll = []; - var walletsSufficientFunds = []; - $scope.walletsInsufficientFunds = []; // For origin screen + $scope.params = sendFlowService.state.getClone(); - if ($scope.type === 'origin') { - $scope.headerTitle = gettextCatalog.getString('Choose a wallet to send from'); + console.log('walletSelector onBeforeEnter after back sendflow', $scope.params); - if ($scope.params.amount || $scope.coin) { + var config = configService.getSync().wallet.settings; + priceDisplayAsFiat = config.priceDisplay === 'fiat'; + unitDecimals = config.unitDecimals; + unitsFromSatoshis = 1 / config.unitToSatoshi; - walletsAll = profileService.getWallets({coin: $scope.coin}); - ongoingProcess.set('scanning', true); - walletsAll.forEach(function forWallet(wallet) { - if (!wallet.status && !wallet.cachedStatus) { - walletService.getStatus(wallet, {}, function(err, status) { - wallet.status = status; - if (status.availableBalanceSat > ($scope.params.amount ? $scope.params.amount : 0)) { + if ($scope.params.isWalletTransfer) { + $scope.sendFlowTitle = gettextCatalog.getString('Transfer between wallets'); + } else if (!$scope.params.thirdParty) { + $scope.sendFlowTitle = gettextCatalog.getString('Send'); + } + + $scope.coin = false; // Wallets to show (for destination screen or contacts) + $scope.type = $scope.params['fromWalletId'] ? 'destination' : 'origin'; // origin || destination + fromWalletId = $scope.params['fromWalletId']; + + if ($scope.type === 'destination' && $scope.params.toAddress) { + $state.transitionTo(getNextStep($scope.params)); + } + + if ($scope.params.coin) { + $scope.coin = $scope.params.coin; // Contacts have a coin embedded + } + + if ($scope.params.amount) { // There is an amount, so presume that it is a payment request + $scope.sendFlowTitle = gettextCatalog.getString('Payment Request'); + $scope.specificAmount = $scope.specificAlternativeAmount = ''; + $scope.isPaymentRequest = true; + } + if ($scope.params.thirdParty) { + $scope.thirdParty = $scope.params.thirdParty; + } + }; + + function onEnter (event, data) { + configService.whenAvailable(function(config) { + $scope.selectedPriceDisplay = config.wallet.settings.priceDisplay; + }); + + if ($scope.thirdParty) { + // Third party services specific logic + handleThirdPartyIfShapeshift(); + } + + prepareWalletLists(); + formatRequestedAmount(); + }; + + function formatRequestedAmount() { + if ($scope.params.amount) { + var cryptoAmount = (unitsFromSatoshis * $scope.params.amount).toFixed(unitDecimals); + var cryptoCoin = $scope.coin.toUpperCase(); + + txFormatService.formatAlternativeStr($scope.coin, $scope.params.amount, function onFormatAlternativeStr(formatted){ + if (formatted) { + var fiatParts = formatted.split(' '); + var fiatAmount = fiatParts[0]; + var fiatCurrrency = fiatParts.length > 1 ? fiatParts[1] : ''; + + if (priceDisplayAsFiat) { + $scope.requestAmount = fiatAmount; + $scope.requestCurrency = fiatCurrrency; + + $scope.requestAmountSecondary = cryptoAmount; + $scope.requestCurrencySecondary = cryptoCoin; + } else { + $scope.requestAmount = cryptoAmount; + $scope.requestCurrency = cryptoCoin; + + $scope.requestAmountSecondary = fiatAmount; + $scope.requestCurrencySecondary = fiatCurrrency; + } + $scope.$apply(); + } + }); + } + } + + function handleThirdPartyIfShapeshift() { + console.log($scope.thirdParty, $scope.coin); + if ($scope.thirdParty.id === 'shapeshift' && $scope.type === 'destination') { // Shapeshift wants to know the + $scope.coin = profileService.getWallet(fromWalletId).coin; + if ($scope.coin === 'bch') { + $scope.coin = 'btc'; + } else { + $scope.coin = 'bch'; + } + } + } + + function prepareWalletLists() { + var walletsAll = []; + var walletsSufficientFunds = []; + $scope.walletsInsufficientFunds = []; // For origin screen + + if ($scope.type === 'origin') { + $scope.headerTitle = gettextCatalog.getString('Choose a wallet to send from'); + + if ($scope.params.amount || $scope.coin) { + + walletsAll = profileService.getWallets({coin: $scope.coin}); + ongoingProcess.set('scanning', true); + walletsAll.forEach(function forWallet(wallet) { + if (!wallet.status && !wallet.cachedStatus) { + walletService.getStatus(wallet, {}, function(err, status) { + wallet.status = status; + if (status.availableBalanceSat > ($scope.params.amount ? $scope.params.amount : 0)) { + walletsSufficientFunds.push(wallet); + } else { + $scope.walletsInsufficientFunds.push(wallet); + } + if ($scope.coin === 'btc') { // As this is a promise + $scope.walletsBtc = walletsSufficientFunds; + } else { + $scope.walletsBch = walletsSufficientFunds; + } + ongoingProcess.set('scanning', false); + }); + } else { + var walletStatus = null; + if (wallet.status && wallet.status.isValid) { + walletStatus = wallet.status; + } else if (wallet.cachedStatus) { + walletStatus = wallet.cachedStatus; + } + + if (walletStatus && walletStatus.availableBalanceSat > ($scope.params.amount ? $scope.params.amount : 0)) { walletsSufficientFunds.push(wallet); } else { $scope.walletsInsufficientFunds.push(wallet); } - if ($scope.coin === 'btc') { // As this is a promise - $scope.walletsBtc = walletsSufficientFunds; - } else { - $scope.walletsBch = walletsSufficientFunds; - } ongoingProcess.set('scanning', false); - }); + } + }); + + if ($scope.coin === 'btc') { + $scope.walletsBtc = walletsSufficientFunds; } else { - var walletStatus = null; - if (wallet.status && wallet.status.isValid) { - walletStatus = wallet.status; - } else if (wallet.cachedStatus) { - walletStatus = wallet.cachedStatus; - } - - if (walletStatus.availableBalanceSat > ($scope.params.amount ? $scope.params.amount : 0)) { - walletsSufficientFunds.push(wallet); - } else { - $scope.walletsInsufficientFunds.push(wallet); - } - ongoingProcess.set('scanning', false); + $scope.walletsBch = walletsSufficientFunds; } - }); - - if ($scope.coin === 'btc') { - $scope.walletsBtc = walletsSufficientFunds; } else { - $scope.walletsBch = walletsSufficientFunds; + $scope.walletsBch = profileService.getWallets({coin: 'bch', hasFunds: true}); + $scope.walletsBtc = profileService.getWallets({coin: 'btc', hasFunds: true}); + $scope.walletsInsufficientFunds = profileService.getWallets({coin: $scope.coin, hasNoFunds: true}); } - } else { - $scope.walletsBch = profileService.getWallets({coin: 'bch', hasFunds: true}); - $scope.walletsBtc = profileService.getWallets({coin: 'btc', hasFunds: true}); - $scope.walletsInsufficientFunds = profileService.getWallets({coin: $scope.coin, hasNoFunds: true}); - } - - } else if ($scope.type === 'destination') { - if (!$scope.coin) { // Allow for the coin to be set by a third party - $scope.fromWallet = profileService.getWallet(fromWalletId); - $scope.coin = $scope.fromWallet.coin; // Only show wallets with the select origin wallet coin - } - $scope.headerTitle = gettextCatalog.getString('Choose a wallet to send to'); + + } else if ($scope.type === 'destination') { + if (!$scope.coin) { // Allow for the coin to be set by a third party + $scope.fromWallet = profileService.getWallet(fromWalletId); + $scope.coin = $scope.fromWallet.coin; // Only show wallets with the select origin wallet coin + } + $scope.headerTitle = gettextCatalog.getString('Choose a wallet to send to'); - if ($scope.coin === 'btc') { // if no specific coin is set or coin is set btc - $scope.walletsBtc = profileService.getWallets({coin: $scope.coin}); - } else { - $scope.walletsBch = profileService.getWallets({coin: $scope.coin}); + if ($scope.coin === 'btc') { // if no specific coin is set or coin is set btc + $scope.walletsBtc = profileService.getWallets({coin: $scope.coin}); + } else { + $scope.walletsBch = profileService.getWallets({coin: $scope.coin}); + } } } - } - + - $scope.useWallet = function(wallet) { - var params = sendFlowService.state.getClone(); - if ($scope.type === 'origin') { // we're on the origin screen, set wallet to send from - params.fromWalletId = wallet.id; - } else { // we're on the destination screen, set wallet to send to - params.toWalletId = wallet.id; + $scope.useWallet = function(wallet) { + var params = sendFlowService.state.getClone(); + if ($scope.type === 'origin') { // we're on the origin screen, set wallet to send from + params.fromWalletId = wallet.id; + } else { // we're on the destination screen, set wallet to send to + params.toWalletId = wallet.id; + } + sendFlowService.goNext(params); + }; + + $scope.goBack = function() { + sendFlowService.router.goBack(); } - sendFlowService.goNext(params); - }; - $scope.goBack = function() { - sendFlowService.router.goBack(); } - -}); \ No newline at end of file +})(); \ No newline at end of file From a8e5c212f08abc13cff85b5484166714ba5773f2 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Dominguez Date: Fri, 21 Sep 2018 11:41:20 +0200 Subject: [PATCH 16/23] Fix : Check if the status could be set before checking the balance. --- src/js/controllers/shapeshift.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/controllers/shapeshift.js b/src/js/controllers/shapeshift.js index 0dac21a11..652f54c34 100644 --- a/src/js/controllers/shapeshift.js +++ b/src/js/controllers/shapeshift.js @@ -10,7 +10,7 @@ angular.module('copayApp.controllers').controller('shapeshiftController', functi walletsBtc = profileService.getWallets({coin: 'btc'}); walletsBch = profileService.getWallets({coin: 'bch'}); $scope.fromWallets = lodash.filter(walletsBtc.concat(walletsBch), function(w) { - return w.status.balance.availableAmount > 0; + return (w.status && w.status.balance && w.status.balance.availableAmount > 0); }); $scope.singleFromWallet = $scope.fromWallets.length === 1; From 0c8d145f73cd6a861fcaed5e8d349d0e381f39f7 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Fri, 21 Sep 2018 02:54:06 -0700 Subject: [PATCH 17/23] Check validity of cachedStatus. --- src/js/controllers/wallet-selector.controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/controllers/wallet-selector.controller.js b/src/js/controllers/wallet-selector.controller.js index 694852f0f..036727333 100644 --- a/src/js/controllers/wallet-selector.controller.js +++ b/src/js/controllers/wallet-selector.controller.js @@ -145,7 +145,7 @@ angular var walletStatus = null; if (wallet.status && wallet.status.isValid) { walletStatus = wallet.status; - } else if (wallet.cachedStatus) { + } else if (wallet.cachedStatus && wallet.status.isValid) { walletStatus = wallet.cachedStatus; } From ea51e035abd3fe8066669c1e13faed876b04404b Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Fri, 21 Sep 2018 03:56:51 -0700 Subject: [PATCH 18/23] Fixed updating of confirmations of cached transactions. Cache now properly cleared on first fetch from Wallet Details screen. --- .../controllers/wallet-details.controller.js | 4 +- src/js/services/wallet-history.service.js | 50 +++++++++++++------ 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/js/controllers/wallet-details.controller.js b/src/js/controllers/wallet-details.controller.js index f3109db8b..cef57925e 100644 --- a/src/js/controllers/wallet-details.controller.js +++ b/src/js/controllers/wallet-details.controller.js @@ -400,8 +400,8 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun var refreshInterval; - $scope.$on("$ionicView.afterEnter", function(event, data) { - $scope.updateAll(); + $scope.$on("$ionicView.afterEnter", function onAfterEnter(event, data) { + $scope.updateAll(true, true); // refreshAmountSection(); refreshInterval = $interval($scope.onRefresh, 10 * 1000); $timeout(function() { diff --git a/src/js/services/wallet-history.service.js b/src/js/services/wallet-history.service.js index 0738d4348..13fc8d636 100644 --- a/src/js/services/wallet-history.service.js +++ b/src/js/services/wallet-history.service.js @@ -27,20 +27,23 @@ function addEarlyTransactions(walletId, cachedTxs, newTxs) { - var cachedTxIds = {}; + var cachedTxIndexFromId = {}; cachedTxs.forEach(function forCachedTx(tx){ - cachedTxIds[tx.txid] = true; + cachedTxIndexFromId[tx.txid] = true; }); + var confirmationsUpdated = false; var someTransactionsWereNew = false; var overlappingTxsCount = 0; newTxs.forEach(function forNewTx(tx){ - if (cachedTxIds[tx.txid]) { - overlappingTxsCount++; - } else { + if (typeof cachedTxIndexFromId[tx.txid] === "undefined") { someTransactionsWereNew = true; cachedTxs.push(tx); + } else { + var txUpdated = updateCachedTx(cachedTxs, cachedTxIndexFromId, tx); + confirmationsUpdated = confirmationsUpdated || txUpdated; + overlappingTxsCount++; } }); @@ -50,6 +53,8 @@ if (overlappingTxFraction >= MIN_KNOWN_TX_OVERLAP_FRACTION) { // We are good if (someTransactionsWereNew) { saveTxHistory(walletId, cachedTxs); + } else if (confirmationsUpdated) { + saveTxHistory(walletId, cachedTxs); } else if (overlappingTxsCount === newTxs.length) { allTransactionsFetched = true; } @@ -65,9 +70,9 @@ } function addLatestTransactions(walletId, cachedTxs, newTxs) { - var cachedTxIds = {}; + var cachedTxIndexFromId = {}; cachedTxs.forEach(function forCachedTx(tx, txIndex){ - cachedTxIds[tx.txid] = txIndex; + cachedTxIndexFromId[tx.txid] = txIndex; }); var someTransactionsWereNew = false; @@ -76,15 +81,13 @@ var uniqueNewTxs = []; newTxs.forEach(function forNewTx(tx){ - if (typeof cachedTxIds[tx.txid] !== "undefined") { - if (cachedTxs[cachedTxIds[tx.txid]].confirmations < SAFE_CONFIRMATIONS && tx.confirmations >= SAFE_CONFIRMATIONS) { - cachedTxs[cachedTxIds[tx.txid]].confirmations = tx.confirmations; - confirmationsUpdated = true; - } - overlappingTxsCount++; - } else { + if (typeof cachedTxIndexFromId[tx.txid] === "undefined") { someTransactionsWereNew = true; uniqueNewTxs.push(tx); + } else { + var txUpdated = updateCachedTx(cachedTxs, cachedTxIndexFromId, tx); + confirmationsUpdated = confirmationsUpdated || txUpdated; + overlappingTxsCount++; } }); @@ -207,8 +210,25 @@ }); } - function updateLocalTxHistoryByPage(wallet, getLatest, flushCacheOnNew, cb) { + /** + * 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) { if (flushCacheOnNew) { fetchTxHistoryByPage(wallet, 0, function onFetchTxHistory(err, txs){ if (err) { From c0912c5f1768d9b093985d6f3204d2e5290a2645 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Fri, 21 Sep 2018 12:31:55 -0700 Subject: [PATCH 19/23] IIFE for reviewController to make merging easier. --- src/js/controllers/review.controller.js | 1764 ++++++++++++----------- 1 file changed, 883 insertions(+), 881 deletions(-) diff --git a/src/js/controllers/review.controller.js b/src/js/controllers/review.controller.js index 58ae2c2f7..fcaa80455 100644 --- a/src/js/controllers/review.controller.js +++ b/src/js/controllers/review.controller.js @@ -1,956 +1,958 @@ 'use strict'; +(function () { + angular .module('copayApp.controllers') .controller('reviewController', reviewController); -function reviewController(addressbookService, bitcoinCashJsService, bitcore, bitcoreCash, bwcError, clipboardService, configService, feeService, gettextCatalog, $interval, $ionicHistory, $ionicModal, ionicToast, lodash, $log, ongoingProcess, platformInfo, popupService, profileService, $scope, sendFlowService, shapeshiftService, soundService, $state, $timeout, txConfirmNotification, txFormatService, walletService) { - var vm = this; + function reviewController(addressbookService, bitcoinCashJsService, bitcore, bitcoreCash, bwcError, clipboardService, configService, feeService, gettextCatalog, $interval, $ionicHistory, $ionicModal, ionicToast, lodash, $log, ongoingProcess, platformInfo, popupService, profileService, $scope, sendFlowService, shapeshiftService, soundService, $state, $timeout, txConfirmNotification, txFormatService, walletService) { + var vm = this; - vm.buttonText = ''; - vm.destination = { - address: '', - balanceAmount: '', - balanceCurrency: '', - coin: '', - color: '', - currency: '', - currencyColor: '', - kind: '', // 'address', 'contact', 'wallet' - name: '' - }; - vm.displayAddress = ''; - vm.feeCrypto = ''; - vm.feeFiat = ''; - vm.fiatCurrency = ''; - vm.feeIsHigh = false; - vm.feeLessThanACent = false; - vm.isCordova = platformInfo.isCordova; - vm.memo = ''; - vm.notReadyMessage = ''; - vm.origin = { - balanceAmount: '', - balanceCurrency: '', - currency: '', - currencyColor: '', - }; - vm.originWallet = null; - vm.paymentExpired = false; - vm.personalNotePlaceholder = gettextCatalog.getString('Enter text here'); - vm.primaryAmount = ''; - vm.primaryCurrency = ''; - vm.usingMerchantFee = false; - vm.readyToSend = false; - vm.remainingTimeStr = ''; - vm.secondaryAmount = ''; - vm.secondaryCurrency = ''; - vm.sendingTitle = gettextCatalog.getString('You are sending'); - vm.sendStatus = ''; - vm.showAddress = true; - vm.thirdParty = false; - vm.wallet = null; - vm.memoExpanded = false; - - // Functions - vm.goBack = goBack; - vm.onSuccessConfirm = onSuccessConfirm; - vm.onShareTransaction = onShareTransaction; - - var sendFlowData; - var config = null; - var coin = ''; - var countDown = null; - var defaults = {}; - var usingCustomFee = false; - var usingMerchantFee = false; - var destinationWalletId = ''; - var lastTxId = ''; - var originWalletId = ''; - var priceDisplayIsFiat = true; - var satoshis = null; - var toAddress = ''; - var tx = {}; - var txPayproData = null; - var unitFromSat = 0; - - var FEE_TOO_HIGH_LIMIT_PERCENTAGE = 15; - - $scope.$on("$ionicView.beforeEnter", onBeforeEnter); - - - function onBeforeEnter(event, data) { - console.log('review onBeforeEnter sendflow ', sendFlowService.state); - // Reset from last time + vm.buttonText = ''; + vm.destination = { + address: '', + balanceAmount: '', + balanceCurrency: '', + coin: '', + color: '', + currency: '', + currencyColor: '', + kind: '', // 'address', 'contact', 'wallet' + name: '' + }; + vm.displayAddress = ''; + vm.feeCrypto = ''; + vm.feeFiat = ''; + vm.fiatCurrency = ''; + vm.feeIsHigh = false; + vm.feeLessThanACent = false; + vm.isCordova = platformInfo.isCordova; vm.memo = ''; + vm.notReadyMessage = ''; + vm.origin = { + balanceAmount: '', + balanceCurrency: '', + currency: '', + currencyColor: '', + }; + vm.originWallet = null; + vm.paymentExpired = false; + vm.personalNotePlaceholder = gettextCatalog.getString('Enter text here'); + vm.primaryAmount = ''; + vm.primaryCurrency = ''; + vm.usingMerchantFee = false; + vm.readyToSend = false; + vm.remainingTimeStr = ''; + vm.secondaryAmount = ''; + vm.secondaryCurrency = ''; + vm.sendingTitle = gettextCatalog.getString('You are sending'); + vm.sendStatus = ''; + vm.showAddress = true; + vm.thirdParty = false; + vm.wallet = null; + vm.memoExpanded = false; - defaults = configService.getDefaults(); - sendFlowData = sendFlowService.state.getClone(); - originWalletId = sendFlowData.fromWalletId; - if (typeof sendFlowData.amount === 'string') { - satoshis = parseInt(sendFlowData.amount, 10); - } else { - satoshis = sendFlowData.amount; - } - toAddress = sendFlowData.toAddress; - destinationWalletId = sendFlowData.toWalletId; + // Functions + vm.goBack = goBack; + vm.onSuccessConfirm = onSuccessConfirm; + vm.onShareTransaction = onShareTransaction; + + var sendFlowData; + var config = null; + var coin = ''; + var countDown = null; + var defaults = {}; + var usingCustomFee = false; + var usingMerchantFee = false; + var destinationWalletId = ''; + var lastTxId = ''; + var originWalletId = ''; + var priceDisplayIsFiat = true; + var satoshis = null; + var toAddress = ''; + var tx = {}; + var txPayproData = null; + var unitFromSat = 0; + + var FEE_TOO_HIGH_LIMIT_PERCENTAGE = 15; + + $scope.$on("$ionicView.beforeEnter", onBeforeEnter); - vm.displayAddress = sendFlowData.displayAddress; - vm.originWallet = profileService.getWallet(originWalletId); - vm.origin.currency = vm.originWallet.coin.toUpperCase(); - coin = vm.originWallet.coin; - if (sendFlowData.thirdParty) { - vm.thirdParty = sendFlowData.thirdParty; - switch (vm.thirdParty.id) { - case 'shapeshift': - initShapeshift(function (err) { - if (err) { - // Error stop here - ongoingProcess.set('connectingShapeshift', false); - popupService.showAlert(gettextCatalog.getString('Shapeshift Error'), err.toString(), function () { - $ionicHistory.goBack(); - }); - } else { - _next(data); - } - }); - break; - case 'bip70': - initBip70(); - default: - _next(data); - break; + function onBeforeEnter(event, data) { + console.log('review onBeforeEnter sendflow ', sendFlowService.state); + // Reset from last time + vm.memo = ''; + + defaults = configService.getDefaults(); + sendFlowData = sendFlowService.state.getClone(); + originWalletId = sendFlowData.fromWalletId; + if (typeof sendFlowData.amount === 'string') { + satoshis = parseInt(sendFlowData.amount, 10); + } else { + satoshis = sendFlowData.amount; } - } else { - _next(data); - } + toAddress = sendFlowData.toAddress; + destinationWalletId = sendFlowData.toWalletId; - function _next() { - configService.get(function onConfig(err, configCache) { - if (err) { - $log.err('Error getting config.', err); - } else { - config = configCache; - priceDisplayIsFiat = config.wallet.settings.priceDisplay === 'fiat'; - vm.origin.currencyColor = (vm.originWallet.coin === 'btc' ? defaults.bitcoinWalletColor : defaults.bitcoinCashWalletColor); - console.log("coin", vm.originWallet.coin, vm.origin.currencyColor, config.bitcoinWalletColor, vm.originWallet.coin === 'btc'); - unitFromSat = 1 / config.wallet.settings.unitToSatoshi; - } - updateSendAmounts(); - getOriginWalletBalance(vm.originWallet); - handleDestinationAsAddress(toAddress, coin); - handleDestinationAsWallet(sendFlowData.toWalletId); - createVanityTransaction(data); - }); - } - } - - vm.approve = function() { + vm.displayAddress = sendFlowData.displayAddress; + vm.originWallet = profileService.getWallet(originWalletId); + vm.origin.currency = vm.originWallet.coin.toUpperCase(); + coin = vm.originWallet.coin; - if (!tx || !vm.originWallet) return; - - if (vm.paymentExpired) { - popupService.showAlert(null, gettextCatalog.getString('This bitcoin payment request has expired.', function () { - $ionicHistory.goBack(); - })); - vm.sendStatus = ''; - $timeout(function() { - $scope.$apply(); - }); - return; - } - - ongoingProcess.set('creatingTx', true, statusChangeHandler); - getTxp(lodash.clone(tx), vm.originWallet, false, function(err, txp) { - ongoingProcess.set('creatingTx', false, statusChangeHandler); - if (err) return; - - // confirm txs for more that 20usd, if not spending/touchid is enabled - function confirmTx(cb) { - if (walletService.isEncrypted(vm.originWallet)) - return cb(); - - var amountUsd = parseFloat(txFormatService.formatToUSD(vm.originWallet.coin, txp.amount)); - return cb(); - }; - - function publishAndSign() { - if (!vm.originWallet.canSign() && !vm.originWallet.isPrivKeyExternal()) { - $log.info('No signing proposal: No private key'); - - return walletService.onlyPublish(vm.originWallet, txp, function(err) { - if (err) setSendError(err); - }, statusChangeHandler); - } - - walletService.publishAndSign(vm.originWallet, txp, function(err, txp) { - if (err) return setSendError(err); - if (config.confirmedTxsNotifications && config.confirmedTxsNotifications.enabled) { - txConfirmNotification.subscribe(vm.originWallet, { - txid: txp.txid + if (sendFlowData.thirdParty) { + vm.thirdParty = sendFlowData.thirdParty; + switch (vm.thirdParty.id) { + case 'shapeshift': + initShapeshift(function (err) { + if (err) { + // Error stop here + ongoingProcess.set('connectingShapeshift', false); + popupService.showAlert(gettextCatalog.getString('Shapeshift Error'), err.toString(), function () { + $ionicHistory.goBack(); + }); + } else { + _next(data); + } }); - lastTxId = txp.txid; + break; + case 'bip70': + initBip70(); + default: + _next(data); + break; + } + } else { + _next(data); + } + + function _next() { + configService.get(function onConfig(err, configCache) { + if (err) { + $log.err('Error getting config.', err); + } else { + config = configCache; + priceDisplayIsFiat = config.wallet.settings.priceDisplay === 'fiat'; + vm.origin.currencyColor = (vm.originWallet.coin === 'btc' ? defaults.bitcoinWalletColor : defaults.bitcoinCashWalletColor); + console.log("coin", vm.originWallet.coin, vm.origin.currencyColor, config.bitcoinWalletColor, vm.originWallet.coin === 'btc'); + unitFromSat = 1 / config.wallet.settings.unitToSatoshi; } - }, statusChangeHandler); + updateSendAmounts(); + getOriginWalletBalance(vm.originWallet); + handleDestinationAsAddress(toAddress, coin); + handleDestinationAsWallet(sendFlowData.toWalletId); + createVanityTransaction(data); + }); + } + } + + vm.approve = function() { + + if (!tx || !vm.originWallet) return; + + if (vm.paymentExpired) { + popupService.showAlert(null, gettextCatalog.getString('This bitcoin payment request has expired.', function () { + $ionicHistory.goBack(); + })); + vm.sendStatus = ''; + $timeout(function() { + $scope.$apply(); + }); + return; + } + + ongoingProcess.set('creatingTx', true, statusChangeHandler); + getTxp(lodash.clone(tx), vm.originWallet, false, function(err, txp) { + ongoingProcess.set('creatingTx', false, statusChangeHandler); + if (err) return; + + // confirm txs for more that 20usd, if not spending/touchid is enabled + function confirmTx(cb) { + if (walletService.isEncrypted(vm.originWallet)) + return cb(); + + var amountUsd = parseFloat(txFormatService.formatToUSD(vm.originWallet.coin, txp.amount)); + return cb(); + }; + + function publishAndSign() { + if (!vm.originWallet.canSign() && !vm.originWallet.isPrivKeyExternal()) { + $log.info('No signing proposal: No private key'); + + return walletService.onlyPublish(vm.originWallet, txp, function(err) { + if (err) setSendError(err); + }, statusChangeHandler); + } + + walletService.publishAndSign(vm.originWallet, txp, function(err, txp) { + if (err) return setSendError(err); + if (config.confirmedTxsNotifications && config.confirmedTxsNotifications.enabled) { + txConfirmNotification.subscribe(vm.originWallet, { + txid: txp.txid + }); + lastTxId = txp.txid; + } + }, statusChangeHandler); + }; + + confirmTx(function(nok) { + if (nok) { + vm.sendStatus = ''; + $timeout(function() { + $scope.$apply(); + }); + return; + } + publishAndSign(); + }); + }); + }; + + vm.chooseFeeLevel = function(tx, wallet) { + + if (wallet.coin == 'bch') return; + if (usingMerchantFee) return; + + var scope = $rootScope.$new(true); + scope.network = tx.network; + scope.feeLevel = tx.feeLevel; + scope.noSave = true; + scope.coin = vm.originWallet.coin; + + if (usingCustomFee) { + scope.customFeePerKB = tx.feeRate; + scope.feePerSatByte = tx.feeRate / 1000; + } + + $ionicModal.fromTemplateUrl('views/modals/chooseFeeLevel.html', { + scope: scope, + backdropClickToClose: false, + hardwareBackButtonClose: false + }).then(function(modal) { + scope.chooseFeeLevelModal = modal; + scope.openModal(); + }); + scope.openModal = function() { + scope.chooseFeeLevelModal.show(); }; - confirmTx(function(nok) { - if (nok) { - vm.sendStatus = ''; - $timeout(function() { - $scope.$apply(); + scope.hideModal = function(newFeeLevel, customFeePerKB) { + scope.chooseFeeLevelModal.hide(); + $log.debug('New fee level choosen:' + newFeeLevel + ' was:' + tx.feeLevel); + + usingCustomFee = newFeeLevel == 'custom' ? true : false; + + if (tx.feeLevel == newFeeLevel && !usingCustomFee) return; + + tx.feeLevel = newFeeLevel; + if (usingCustomFee) tx.feeRate = parseInt(customFeePerKB); + + updateTx(tx, vm.originWallet, { + clearCache: true, + dryRun: true + }, function() {}); + }; + }; + + function createVanityTransaction(data) { + console.log('createVanityTransaction()'); + var configFeeLevel = config.wallet.settings.feeLevel ? config.wallet.settings.feeLevel : 'normal'; + + // Grab stateParams + tx = { + amount: parseInt(sendFlowData.amount), + sendMax: sendFlowData.sendMax, + fromWalletId: sendFlowData.fromWalletId, + toAddress: sendFlowData.toAddress, + paypro: txPayproData, + + feeLevel: configFeeLevel, + spendUnconfirmed: config.wallet.spendUnconfirmed, + + // Vanity tx info (not in the real tx) + recipientType: vm.destination.kind || null, + toName: vm.destination.name || null, + toEmail: vm.destination.email || null, + toColor: vm.destination.color || null, + network: false, + coin: vm.originWallet.coin, + txp: {}, + }; + + + if (data.stateParams.requiredFeeRate) { + vm.usingMerchantFee = true; + tx.feeRate = parseInt(data.stateParams.requiredFeeRate); + } + + if (tx.coin && tx.coin === 'bch') { + tx.feeLevel = 'normal'; + } + + var B = tx.coin === 'bch' ? bitcoreCash : bitcore; + var networkName; + try { + if (vm.destination.kind === 'wallet') { // This is a wallet-to-wallet transfer + ongoingProcess.set('generatingNewAddress', true); + var toWallet = profileService.getWallet(destinationWalletId); + + // We need an address to send to, so we ask the walletService to create a new address for the toWallet. + console.log('Getting address for wallet...'); + walletService.getAddress(toWallet, true, function onWalletAddress(err, addr) { + console.log('getAddress cb called', err); + ongoingProcess.set('generatingNewAddress', false); + tx.toAddress = addr; + networkName = (new B.Address(tx.toAddress)).network.name; + tx.network = networkName; + console.log('calling setupTx() for wallet.'); + setupTx(tx); }); - return; - } - publishAndSign(); - }); - }); - }; - - vm.chooseFeeLevel = function(tx, wallet) { - - if (wallet.coin == 'bch') return; - if (usingMerchantFee) return; - - var scope = $rootScope.$new(true); - scope.network = tx.network; - scope.feeLevel = tx.feeLevel; - scope.noSave = true; - scope.coin = vm.originWallet.coin; - - if (usingCustomFee) { - scope.customFeePerKB = tx.feeRate; - scope.feePerSatByte = tx.feeRate / 1000; - } - - $ionicModal.fromTemplateUrl('views/modals/chooseFeeLevel.html', { - scope: scope, - backdropClickToClose: false, - hardwareBackButtonClose: false - }).then(function(modal) { - scope.chooseFeeLevelModal = modal; - scope.openModal(); - }); - scope.openModal = function() { - scope.chooseFeeLevelModal.show(); - }; - - scope.hideModal = function(newFeeLevel, customFeePerKB) { - scope.chooseFeeLevelModal.hide(); - $log.debug('New fee level choosen:' + newFeeLevel + ' was:' + tx.feeLevel); - - usingCustomFee = newFeeLevel == 'custom' ? true : false; - - if (tx.feeLevel == newFeeLevel && !usingCustomFee) return; - - tx.feeLevel = newFeeLevel; - if (usingCustomFee) tx.feeRate = parseInt(customFeePerKB); - - updateTx(tx, vm.originWallet, { - clearCache: true, - dryRun: true - }, function() {}); - }; - }; - - function createVanityTransaction(data) { - console.log('createVanityTransaction()'); - var configFeeLevel = config.wallet.settings.feeLevel ? config.wallet.settings.feeLevel : 'normal'; - - // Grab stateParams - tx = { - amount: parseInt(sendFlowData.amount), - sendMax: sendFlowData.sendMax, - fromWalletId: sendFlowData.fromWalletId, - toAddress: sendFlowData.toAddress, - paypro: txPayproData, - - feeLevel: configFeeLevel, - spendUnconfirmed: config.wallet.spendUnconfirmed, - - // Vanity tx info (not in the real tx) - recipientType: vm.destination.kind || null, - toName: vm.destination.name || null, - toEmail: vm.destination.email || null, - toColor: vm.destination.color || null, - network: false, - coin: vm.originWallet.coin, - txp: {}, - }; - - - if (data.stateParams.requiredFeeRate) { - vm.usingMerchantFee = true; - tx.feeRate = parseInt(data.stateParams.requiredFeeRate); - } - - if (tx.coin && tx.coin === 'bch') { - tx.feeLevel = 'normal'; - } - - var B = tx.coin === 'bch' ? bitcoreCash : bitcore; - var networkName; - try { - if (vm.destination.kind === 'wallet') { // This is a wallet-to-wallet transfer - ongoingProcess.set('generatingNewAddress', true); - var toWallet = profileService.getWallet(destinationWalletId); - - // We need an address to send to, so we ask the walletService to create a new address for the toWallet. - console.log('Getting address for wallet...'); - walletService.getAddress(toWallet, true, function onWalletAddress(err, addr) { - console.log('getAddress cb called', err); - ongoingProcess.set('generatingNewAddress', false); - tx.toAddress = addr; + } else { // This is a Wallet-to-address transfer networkName = (new B.Address(tx.toAddress)).network.name; tx.network = networkName; - console.log('calling setupTx() for wallet.'); + console.log('calling setupTx() for address.'); setupTx(tx); - }); - } else { // This is a Wallet-to-address transfer - networkName = (new B.Address(tx.toAddress)).network.name; - tx.network = networkName; - console.log('calling setupTx() for address.'); - setupTx(tx); - } - } catch (e) { - console.error('Error setting up tx', e); - var message = gettextCatalog.getString('Invalid address'); - popupService.showAlert(null, message, function () { - $ionicHistory.nextViewOptions({ - disableAnimate: true, - historyRoot: true - }); - $state.go('tabs.send').then(function () { - $ionicHistory.clearHistory(); - }); - }); - return; - } - } - function getOriginWalletBalance(originWallet) { - var balanceText = getWalletBalanceDisplayText(vm.originWallet); - vm.origin.balanceAmount = balanceText.amount; - vm.origin.balanceCurrency = balanceText.currency; - } - - function getSendMaxInfo(tx, wallet, cb) { - if (!tx.sendMax) return cb(); - - //ongoingProcess.set('retrievingInputs', true); - walletService.getSendMaxInfo(wallet, { - feePerKb: tx.feeRate, - excludeUnconfirmedUtxos: !tx.spendUnconfirmed, - returnInputs: true, - }, cb); - }; - - function getTxp(tx, wallet, dryRun, cb) { - - // ToDo: use a credential's (or fc's) function for this - if (tx.description && !wallet.credentials.sharedEncryptingKey) { - var msg = gettextCatalog.getString('Could not add message to imported wallet without shared encrypting key'); - $log.warn(msg); - return setSendError(msg); - } - - if (tx.amount > Number.MAX_SAFE_INTEGER) { - var msg = gettextCatalog.getString('Amount too big'); - $log.warn(msg); - return setSendError(msg); - } - - var txp = {}; - - txp.outputs = [{ - 'toAddress': tx.toAddress, - 'amount': tx.amount, - 'message': vm.memo - }]; - - if (tx.sendMaxInfo) { - txp.inputs = tx.sendMaxInfo.inputs; - txp.fee = tx.sendMaxInfo.fee; - } else { - if (usingCustomFee || usingMerchantFee) { - txp.feePerKb = tx.feeRate; - } else txp.feeLevel = tx.feeLevel; - } - - txp.message = vm.memo; - - if (tx.paypro) { - txp.payProUrl = tx.paypro.url; - } - txp.excludeUnconfirmedUtxos = !tx.spendUnconfirmed; - txp.dryRun = dryRun; - walletService.createTx(wallet, txp, function(err, ctxp) { - if (err) { - setSendError(err); - return cb(err); - } - return cb(null, ctxp); - }); - }; - - function getWalletBalanceDisplayText(wallet) { - var balanceCryptoAmount = ''; - var balanceCryptoCurrencyCode = ''; - var balanceFiatAmount = ''; - var balanceFiatCurrency = '' - var displayAmount = ''; - var displayCurrency = ''; - - var walletStatus = null; - if (wallet.status.isValid) { - walletStatus = wallet.status; - } else if (wallet.cachedStatus.isValid) { - walletStatus = wallet.cachedStatus; - } - - if (walletStatus) { - var cryptoBalanceParts = walletStatus.spendableBalanceStr.split(' '); - balanceCryptoAmount = cryptoBalanceParts[0]; - balanceCryptoCurrencyCode = cryptoBalanceParts.length > 1 ? cryptoBalanceParts[1] : ''; - - if (walletStatus.alternativeBalanceAvailable) { - balanceFiatAmount = walletStatus.spendableBalanceAlternative; - balanceFiatCurrency = walletStatus.alternativeIsoCode; - } - } - - if (priceDisplayIsFiat) { - displayAmount = balanceFiatAmount ? balanceFiatAmount : balanceCryptoAmount; - displayCurrency = balanceFiatAmount ? balanceFiatCurrency : balanceCryptoCurrencyCode; - } else { - displayAmount = balanceCryptoAmount; - displayCurrency = balanceCryptoCurrencyCode; - } - - return { - amount: displayAmount, - currency: displayCurrency - }; - } - - function goBack() { - sendFlowService.router.goBack(); - } - - function handleDestinationAsAddress(address, originCoin) { - if (!address) { - return; - } - - // Check if the recipient is a contact - addressbookService.get(originCoin + address, function(err, contact) { - if (!err && contact) { - handleDestinationAsAddressOfContact(contact); - } else { - if (originCoin === 'bch') { - vm.destination.address = bitcoinCashJsService.readAddress(address).cashaddr; - } else { - vm.destination.address = address; } - vm.destination.kind = 'address'; + } catch (e) { + console.error('Error setting up tx', e); + var message = gettextCatalog.getString('Invalid address'); + popupService.showAlert(null, message, function () { + $ionicHistory.nextViewOptions({ + disableAnimate: true, + historyRoot: true + }); + $state.go('tabs.send').then(function () { + $ionicHistory.clearHistory(); + }); + }); + return; } - }); - - } - - function handleDestinationAsAddressOfContact(contact) { - vm.destination.kind = 'contact'; - vm.destination.name = contact.name; - vm.destination.email = contact.email; - vm.destination.color = contact.coin === 'btc' ? defaults.bitcoinWalletColor : defaults.bitcoinCashWalletColor; - vm.destination.currency = contact.coin.toUpperCase(); - vm.destination.currencyColor = vm.destination.color; - } - - function handleDestinationAsWallet(walletId) { - destinationWalletId = walletId; - if (!destinationWalletId) { - return; + } + function getOriginWalletBalance(originWallet) { + var balanceText = getWalletBalanceDisplayText(vm.originWallet); + vm.origin.balanceAmount = balanceText.amount; + vm.origin.balanceCurrency = balanceText.currency; } - var destinationWallet = profileService.getWallet(destinationWalletId); - vm.destination.coin = destinationWallet.coin; - vm.destination.color = destinationWallet.color; - vm.destination.currency = destinationWallet.coin.toUpperCase(); - vm.destination.kind = 'wallet'; - vm.destination.name = destinationWallet.name; + function getSendMaxInfo(tx, wallet, cb) { + if (!tx.sendMax) return cb(); - if (defaults) { - vm.destination.currencyColor = vm.destination.coin === 'btc' ? defaults.bitcoinWalletColor : defaults.bitcoinCashWalletColor; - } - - var balanceText = getWalletBalanceDisplayText(destinationWallet); - vm.destination.balanceAmount = balanceText.amount; - vm.destination.balanceCurrency = balanceText.currency; - } - - function initBip70() { - vm.sendingTitle = gettextCatalog.getString('You are paying'); - vm.memo = vm.thirdParty.memo; - vm.memoExpanded = !!vm.memo; - vm.destination.name = vm.thirdParty.name; - - txPayproData = { - caTrusted: vm.thirdParty.caTrusted, - domain: vm.thirdParty.domain, - expires: vm.thirdParty.expires, - toAddress: toAddress, - url: vm.thirdParty.url, - verified: vm.thirdParty.verified, + //ongoingProcess.set('retrievingInputs', true); + walletService.getSendMaxInfo(wallet, { + feePerKb: tx.feeRate, + excludeUnconfirmedUtxos: !tx.spendUnconfirmed, + returnInputs: true, + }, cb); }; - } - function initShapeshift(cb) { - vm.sendingTitle = gettextCatalog.getString('You are shifting'); - if (!vm.thirdParty.data) { - vm.thirdParty.data = {}; + function getTxp(tx, wallet, dryRun, cb) { + + // ToDo: use a credential's (or fc's) function for this + if (tx.description && !wallet.credentials.sharedEncryptingKey) { + var msg = gettextCatalog.getString('Could not add message to imported wallet without shared encrypting key'); + $log.warn(msg); + return setSendError(msg); + } + + if (tx.amount > Number.MAX_SAFE_INTEGER) { + var msg = gettextCatalog.getString('Amount too big'); + $log.warn(msg); + return setSendError(msg); + } + + var txp = {}; + + txp.outputs = [{ + 'toAddress': tx.toAddress, + 'amount': tx.amount, + 'message': vm.memo + }]; + + if (tx.sendMaxInfo) { + txp.inputs = tx.sendMaxInfo.inputs; + txp.fee = tx.sendMaxInfo.fee; + } else { + if (usingCustomFee || usingMerchantFee) { + txp.feePerKb = tx.feeRate; + } else txp.feeLevel = tx.feeLevel; + } + + txp.message = vm.memo; + + if (tx.paypro) { + txp.payProUrl = tx.paypro.url; + } + txp.excludeUnconfirmedUtxos = !tx.spendUnconfirmed; + txp.dryRun = dryRun; + walletService.createTx(wallet, txp, function(err, ctxp) { + if (err) { + setSendError(err); + return cb(err); + } + return cb(null, ctxp); + }); + }; + + function getWalletBalanceDisplayText(wallet) { + var balanceCryptoAmount = ''; + var balanceCryptoCurrencyCode = ''; + var balanceFiatAmount = ''; + var balanceFiatCurrency = '' + var displayAmount = ''; + var displayCurrency = ''; + + var walletStatus = null; + if (wallet.status.isValid) { + walletStatus = wallet.status; + } else if (wallet.cachedStatus.isValid) { + walletStatus = wallet.cachedStatus; + } + + if (walletStatus) { + var cryptoBalanceParts = walletStatus.spendableBalanceStr.split(' '); + balanceCryptoAmount = cryptoBalanceParts[0]; + balanceCryptoCurrencyCode = cryptoBalanceParts.length > 1 ? cryptoBalanceParts[1] : ''; + + if (walletStatus.alternativeBalanceAvailable) { + balanceFiatAmount = walletStatus.spendableBalanceAlternative; + balanceFiatCurrency = walletStatus.alternativeIsoCode; + } + } + + if (priceDisplayIsFiat) { + displayAmount = balanceFiatAmount ? balanceFiatAmount : balanceCryptoAmount; + displayCurrency = balanceFiatAmount ? balanceFiatCurrency : balanceCryptoCurrencyCode; + } else { + displayAmount = balanceCryptoAmount; + displayCurrency = balanceCryptoCurrencyCode; + } + + return { + amount: displayAmount, + currency: displayCurrency + }; } - var toWallet = profileService.getWallet(destinationWalletId); - vm.destination.name = toWallet.name; - vm.destination.color = toWallet.color; - vm.destination.currency = toWallet.coin.toUpperCase(); + function goBack() { + sendFlowService.router.goBack(); + } + + function handleDestinationAsAddress(address, originCoin) { + if (!address) { + return; + } + + // Check if the recipient is a contact + addressbookService.get(originCoin + address, function(err, contact) { + if (!err && contact) { + handleDestinationAsAddressOfContact(contact); + } else { + if (originCoin === 'bch') { + vm.destination.address = bitcoinCashJsService.readAddress(address).cashaddr; + } else { + vm.destination.address = address; + } + vm.destination.kind = 'address'; + } + }); + + } + + function handleDestinationAsAddressOfContact(contact) { + vm.destination.kind = 'contact'; + vm.destination.name = contact.name; + vm.destination.email = contact.email; + vm.destination.color = contact.coin === 'btc' ? defaults.bitcoinWalletColor : defaults.bitcoinCashWalletColor; + vm.destination.currency = contact.coin.toUpperCase(); + vm.destination.currencyColor = vm.destination.color; + } + + function handleDestinationAsWallet(walletId) { + destinationWalletId = walletId; + if (!destinationWalletId) { + return; + } + + var destinationWallet = profileService.getWallet(destinationWalletId); + vm.destination.coin = destinationWallet.coin; + vm.destination.color = destinationWallet.color; + vm.destination.currency = destinationWallet.coin.toUpperCase(); + vm.destination.kind = 'wallet'; + vm.destination.name = destinationWallet.name; + + if (defaults) { + vm.destination.currencyColor = vm.destination.coin === 'btc' ? defaults.bitcoinWalletColor : defaults.bitcoinCashWalletColor; + } + + var balanceText = getWalletBalanceDisplayText(destinationWallet); + vm.destination.balanceAmount = balanceText.amount; + vm.destination.balanceCurrency = balanceText.currency; + } + + function initBip70() { + vm.sendingTitle = gettextCatalog.getString('You are paying'); + vm.memo = vm.thirdParty.memo; + vm.memoExpanded = !!vm.memo; + vm.destination.name = vm.thirdParty.name; + + txPayproData = { + caTrusted: vm.thirdParty.caTrusted, + domain: vm.thirdParty.domain, + expires: vm.thirdParty.expires, + toAddress: toAddress, + url: vm.thirdParty.url, + verified: vm.thirdParty.verified, + }; + } + + function initShapeshift(cb) { + vm.sendingTitle = gettextCatalog.getString('You are shifting'); + if (!vm.thirdParty.data) { + vm.thirdParty.data = {}; + } + + var toWallet = profileService.getWallet(destinationWalletId); + vm.destination.name = toWallet.name; + vm.destination.color = toWallet.color; + vm.destination.currency = toWallet.coin.toUpperCase(); - ongoingProcess.set('connectingShapeshift', true); - walletService.getAddress(vm.originWallet, false, function onReturnWalletAddress(err, returnAddr) { - if (err) { - return cb(err); - } - walletService.getAddress(toWallet, false, function onWithdrawalWalletAddress(err, withdrawalAddr) { + ongoingProcess.set('connectingShapeshift', true); + walletService.getAddress(vm.originWallet, false, function onReturnWalletAddress(err, returnAddr) { if (err) { return cb(err); } - - // Need to use the correct service to do it. - var amount = parseFloat(satoshis / 100000000); - - shapeshiftService.shiftIt(vm.originWallet.coin, toWallet.coin, withdrawalAddr, returnAddr, amount, function onShiftIt(err, shapeshiftData) { + walletService.getAddress(toWallet, false, function onWithdrawalWalletAddress(err, withdrawalAddr) { if (err) { return cb(err); - } else { - vm.destination.kind = 'shapeshift'; - vm.destination.address = toAddress; - tx.toAddress = shapeshiftData.toAddress; - vm.memo = 'ShapeShift Order:\nhttps://www.shapeshift.io/#/status/' + shapeshiftData.orderId; - vm.memoExpanded = !!vm.memo; - ongoingProcess.set('connectingShapeshift', false); - cb(); - } + } + + // Need to use the correct service to do it. + var amount = parseFloat(satoshis / 100000000); + + shapeshiftService.shiftIt(vm.originWallet.coin, toWallet.coin, withdrawalAddr, returnAddr, amount, function onShiftIt(err, shapeshiftData) { + if (err) { + return cb(err); + } else { + vm.destination.kind = 'shapeshift'; + vm.destination.address = toAddress; + tx.toAddress = shapeshiftData.toAddress; + vm.memo = 'ShapeShift Order:\nhttps://www.shapeshift.io/#/status/' + shapeshiftData.orderId; + vm.memoExpanded = !!vm.memo; + ongoingProcess.set('connectingShapeshift', false); + cb(); + } + }); }); }); - }); - } - - function onShareTransaction() { - var explorerTxUrl = 'https://explorer.bitcoin.com/' + tx.coin + '/tx/' + lastTxId; - if (platformInfo.isCordova) { - var text = gettextCatalog.getString('Take a look at this Bitcoin Cash transaction here: ') + explorerTxUrl; - if (coin === 'btc') { - text = gettextCatalog.getString('Take a look at this Bitcoin transaction here: ') + explorerTxUrl; - } - window.plugins.socialsharing.share(text, null, null, null); - } else { - ionicToast.show(gettextCatalog.getString('Copied to clipboard'), 'bottom', false, 3000); - clipboardService.copyToClipboard(explorerTxUrl); } - - } - function startExpirationTimer(expirationTime) { - vm.paymentExpired = false; - setExpirationTime(); + function onShareTransaction() { + var explorerTxUrl = 'https://explorer.bitcoin.com/' + tx.coin + '/tx/' + lastTxId; + if (platformInfo.isCordova) { + var text = gettextCatalog.getString('Take a look at this Bitcoin Cash transaction here: ') + explorerTxUrl; + if (coin === 'btc') { + text = gettextCatalog.getString('Take a look at this Bitcoin transaction here: ') + explorerTxUrl; + } + window.plugins.socialsharing.share(text, null, null, null); + } else { + ionicToast.show(gettextCatalog.getString('Copied to clipboard'), 'bottom', false, 3000); + clipboardService.copyToClipboard(explorerTxUrl); + } + + } - countDown = $interval(function() { + function startExpirationTimer(expirationTime) { + vm.paymentExpired = false; setExpirationTime(); - }, 1000); - function setExpirationTime() { - console.log('setExpirationTime()'); - var now = Math.floor(Date.now() / 1000); + countDown = $interval(function() { + setExpirationTime(); + }, 1000); - if (now > expirationTime) { - setExpiredValues(); + function setExpirationTime() { + console.log('setExpirationTime()'); + var now = Math.floor(Date.now() / 1000); + + if (now > expirationTime) { + setExpiredValues(); + return; + } + + var totalSecs = expirationTime - now; + var m = Math.floor(totalSecs / 60); + var s = totalSecs % 60; + vm.remainingTimeStr = m + ":" + ('0' + s).slice(-2); + }; + + function setExpiredValues() { + vm.paymentExpired = true; + vm.remainingTimeStr = gettextCatalog.getString('Expired'); + vm.readyToSend = false; + if (countDown) $interval.cancel(countDown); + $timeout(function() { + $scope.$apply(); + }); + }; + }; + + function updateSendAmounts() { + if (typeof satoshis !== 'number') { return; } - var totalSecs = expirationTime - now; - var m = Math.floor(totalSecs / 60); - var s = totalSecs % 60; - vm.remainingTimeStr = m + ":" + ('0' + s).slice(-2); + var cryptoAmount = ''; + var cryptoCurrencyCode = ''; + var amountStr = txFormatService.formatAmountStr(coin, satoshis); + if (amountStr) { + var amountParts = amountStr.split(' '); + cryptoAmount = amountParts[0]; + cryptoCurrencyCode = amountParts.length > 1 ? amountParts[1] : ''; + } + // Want to avoid flashing of amount strings so do all formatting after this has returned. + txFormatService.formatAlternativeStr(coin, satoshis, function(v) { + if (!v) { + vm.primaryAmount = cryptoAmount; + vm.primaryCurrency = cryptoCurrencyCode; + vm.secondaryAmount = ''; + vm.secondaryCurrency = ''; + return; + } + vm.secondaryAmount = vm.primaryAmount; + vm.secondaryCurrency = vm.primaryCurrency; + + var fiatParts = v.split(' '); + var fiatAmount = fiatParts[0]; + var fiatCurrency = fiatParts.length > 1 ? fiatParts[1] : ''; + + if (priceDisplayIsFiat) { + vm.primaryAmount = fiatAmount; + vm.primaryCurrency = fiatCurrency; + vm.secondaryAmount = cryptoAmount; + vm.secondaryCurrency = cryptoCurrencyCode; + } else { + vm.primaryAmount = cryptoAmount; + vm.primaryCurrency = cryptoCurrencyCode; + vm.secondaryAmount = fiatAmount; + vm.secondaryCurrency = fiatCurrency; + } + }); + } + + function onSuccessConfirm() { + vm.sendStatus = ''; + $ionicHistory.nextViewOptions({ + disableAnimate: true, + historyRoot: true + }); + $state.go('tabs.send').then(function() { + $ionicHistory.clearHistory(); + $state.transitionTo('tabs.home'); + }); }; - function setExpiredValues() { - vm.paymentExpired = true; - vm.remainingTimeStr = gettextCatalog.getString('Expired'); + function setButtonText(isMultisig, isPayPro) { + if (isPayPro) { + if (vm.isCordova) { + vm.buttonText = gettextCatalog.getString('Slide to pay'); + } else { + vm.buttonText = gettextCatalog.getString('Click to pay'); + } + } else if (isMultisig) { + if (vm.isCordova) { + vm.buttonText = gettextCatalog.getString('Slide to accept'); + } else { + vm.buttonText = gettextCatalog.getString('Click to accept'); + } + } else { + if (vm.isCordova) { + vm.buttonText = gettextCatalog.getString('Slide to send'); + } else { + vm.buttonText = gettextCatalog.getString('Click to send'); + } + } + } + + function setNotReady(msg, criticalError) { + vn.readyToSend = false; + vm.notReadyMessage = msg; + $scope.criticalError = criticalError; + $log.warn('Not ready to make the payment:' + msg); + $timeout(function() { + $scope.$apply(); + }); + }; + + function setSendError(msg) { + $scope.sendStatus = ''; vm.readyToSend = false; - if (countDown) $interval.cancel(countDown); $timeout(function() { $scope.$apply(); }); - }; - }; - - function updateSendAmounts() { - if (typeof satoshis !== 'number') { - return; - } - - var cryptoAmount = ''; - var cryptoCurrencyCode = ''; - var amountStr = txFormatService.formatAmountStr(coin, satoshis); - if (amountStr) { - var amountParts = amountStr.split(' '); - cryptoAmount = amountParts[0]; - cryptoCurrencyCode = amountParts.length > 1 ? amountParts[1] : ''; - } - // Want to avoid flashing of amount strings so do all formatting after this has returned. - txFormatService.formatAlternativeStr(coin, satoshis, function(v) { - if (!v) { - vm.primaryAmount = cryptoAmount; - vm.primaryCurrency = cryptoCurrencyCode; - vm.secondaryAmount = ''; - vm.secondaryCurrency = ''; - return; - } - vm.secondaryAmount = vm.primaryAmount; - vm.secondaryCurrency = vm.primaryCurrency; - - var fiatParts = v.split(' '); - var fiatAmount = fiatParts[0]; - var fiatCurrency = fiatParts.length > 1 ? fiatParts[1] : ''; - - if (priceDisplayIsFiat) { - vm.primaryAmount = fiatAmount; - vm.primaryCurrency = fiatCurrency; - vm.secondaryAmount = cryptoAmount; - vm.secondaryCurrency = cryptoCurrencyCode; - } else { - vm.primaryAmount = cryptoAmount; - vm.primaryCurrency = cryptoCurrencyCode; - vm.secondaryAmount = fiatAmount; - vm.secondaryCurrency = fiatCurrency; - } - }); - } - - function onSuccessConfirm() { - vm.sendStatus = ''; - $ionicHistory.nextViewOptions({ - disableAnimate: true, - historyRoot: true - }); - $state.go('tabs.send').then(function() { - $ionicHistory.clearHistory(); - $state.transitionTo('tabs.home'); - }); - }; - - function setButtonText(isMultisig, isPayPro) { - if (isPayPro) { - if (vm.isCordova) { - vm.buttonText = gettextCatalog.getString('Slide to pay'); - } else { - vm.buttonText = gettextCatalog.getString('Click to pay'); - } - } else if (isMultisig) { - if (vm.isCordova) { - vm.buttonText = gettextCatalog.getString('Slide to accept'); - } else { - vm.buttonText = gettextCatalog.getString('Click to accept'); - } - } else { - if (vm.isCordova) { - vm.buttonText = gettextCatalog.getString('Slide to send'); - } else { - vm.buttonText = gettextCatalog.getString('Click to send'); - } - } - } - - function setNotReady(msg, criticalError) { - vn.readyToSend = false; - vm.notReadyMessage = msg; - $scope.criticalError = criticalError; - $log.warn('Not ready to make the payment:' + msg); - $timeout(function() { - $scope.$apply(); - }); - }; - - function setSendError(msg) { - $scope.sendStatus = ''; - vm.readyToSend = false; - $timeout(function() { - $scope.$apply(); - }); - popupService.showAlert(gettextCatalog.getString('Error at confirm'), bwcError.msg(msg), function () { - $ionicHistory.goBack(); - }); - }; - - function setupTx(tx) { - if (tx.coin === 'bch') { - tx.displayAddress = bitcoinCashJsService.readAddress(tx.toAddress).cashaddr; - } else { - tx.displayAddress = tx.toAddress; - } - - addressbookService.get(tx.coin+tx.toAddress, function(err, addr) { // Check if the recipient is a contact - if (!err && addr) { - tx.toName = addr.name; - tx.toEmail = addr.email; - tx.recipientType = 'contact'; - } - }); - - vm.showAddress = false; - - - setButtonText(vm.originWallet.credentials.m > 1, !!tx.paypro); - - if (tx.paypro) - startExpirationTimer(tx.paypro.expires); - - updateTx(tx, vm.originWallet, { - dryRun: true - }, function(err) { - $timeout(function() { - $scope.$apply(); - }, 10); - - }); - - // setWalletSelector(tx.coin, tx.network, tx.amount, function(err) { - // if (err) { - // return exitWithError('Could not update wallets'); - // } - // - // if (vm.wallets.length > 1) { - // vm.showWalletSelector(); - // } else if (vm.wallets.length) { - // setWallet(vm.wallets[0], tx); - // } - // }); - } - - function showSendMaxWarning(wallet, sendMaxInfo) { - var feeAlternative = '', - msg = ''; - - function verifyExcludedUtxos() { - var warningMsg = []; - if (sendMaxInfo.utxosBelowFee > 0) { - warningMsg.push(gettextCatalog.getString("A total of {{amountBelowFeeStr}} were excluded. These funds come from UTXOs smaller than the network fee provided.", { - amountBelowFeeStr: txFormatService.formatAmountStr(wallet.coin, sendMaxInfo.amountBelowFee) - })); - } - - if (sendMaxInfo.utxosAboveMaxSize > 0) { - warningMsg.push(gettextCatalog.getString("A total of {{amountAboveMaxSizeStr}} were excluded. The maximum size allowed for a transaction was exceeded.", { - amountAboveMaxSizeStr: txFormatService.formatAmountStr(vm.originWallet.coin, sendMaxInfo.amountAboveMaxSize) - })); - } - return warningMsg.join('\n'); + popupService.showAlert(gettextCatalog.getString('Error at confirm'), bwcError.msg(msg), function () { + $ionicHistory.goBack(); + }); }; - feeAlternative = txFormatService.formatAlternativeStr(vm.originWallet.coin, sendMaxInfo.fee); - if (feeAlternative) { - msg = gettextCatalog.getString("{{feeAlternative}} will be deducted for bitcoin networking fees ({{fee}}).", { - fee: txFormatService.formatAmountStr(vm.originWallet.coin, sendMaxInfo.fee), - feeAlternative: feeAlternative - }); - } else { - msg = gettextCatalog.getString("{{fee}} will be deducted for bitcoin networking fees).", { - fee: txFormatService.formatAmountStr(vm.originWallet.coin, sendMaxInfo.fee) - }); - } - - var warningMsg = verifyExcludedUtxos(); - - if (!lodash.isEmpty(warningMsg)) - msg += '\n' + warningMsg; - - popupService.showAlert(null, msg, function() {}); - }; - - function statusChangeHandler(processName, showName, isOn) { - $log.debug('statusChangeHandler: ', processName, showName, isOn); - if ( - ( - processName === 'broadcastingTx' || - ((processName === 'signingTx') && vm.originWallet.m > 1) || - (processName == 'sendingTx' && !vm.originWallet.canSign() && !vm.originWallet.isPrivKeyExternal()) - ) && !isOn) { - // Show the popup - vm.sendStatus = 'success'; - - // Clear the send flow service state - sendFlowService.state.clear(); - - if ($state.current.name === "tabs.send.review") { // XX SP: Otherwise all open wallets on other devices play this sound if you have been in a send flow before on that device. - soundService.play('misc/payment_sent.mp3'); - } - - var channel = "firebase"; - if (platformInfo.isNW) { - channel = "ga"; - } - // When displaying Fiat, if the formatting fails, the crypto will be the primary amount. - var amount = unitFromSat * satoshis; - var log = new window.BitAnalytics.LogEvent("transfer_success", [{ - "coin": vm.originWallet.coin, - "type": "outgoing", - "amount": amount, - "fees": vm.feeCrypto - }], [channel, "adjust"]); - window.BitAnalytics.LogEventHandlers.postEvent(log); - - $timeout(function() { - $scope.$digest(); - }, 100); - } else if (showName) { - vm.sendStatus = showName; - } - }; - - function updateTx(tx, wallet, opts, cb) { - ongoingProcess.set('calculatingFee', true); - - if (opts.clearCache) { - tx.txp = {}; - } - - // $scope.tx = tx; - - // function updateAmount() { - // if (!tx.amount) return; - // - // // Amount - // tx.amountStr = txFormatService.formatAmountStr(originWallet.coin, tx.amount); - // tx.amountValueStr = tx.amountStr.split(' ')[0]; - // tx.amountUnitStr = tx.amountStr.split(' ')[1]; - // txFormatService.formatAlternativeStr(wallet.coin, tx.amount, function(v) { - // var parts = v.split(' '); - // tx.alternativeAmountStr = v; - // tx.alternativeAmountValueStr = parts[0]; - // tx.alternativeAmountUnitStr = (parts.length > 0) ? parts[1] : ''; - // }); - // } - // - // updateAmount(); - // refresh(); - - var feeServiceLevel = usingMerchantFee && vm.originWallet.coin == 'btc' ? 'urgent' : tx.feeLevel; - feeService.getFeeRate(vm.originWallet.coin, tx.network, feeServiceLevel, function(err, feeRate) { - if (err) { - ongoingProcess.set('calculatingFee', false); - return cb(err); - } - - var msg; - if (usingCustomFee) { - msg = gettextCatalog.getString('Custom'); - tx.feeLevelName = msg; - } else if (usingMerchantFee) { - $log.info('Using Merchant Fee:' + tx.feeRate + ' vs. Urgent level:' + feeRate); - msg = gettextCatalog.getString('Suggested by Merchant'); - tx.feeLevelName = msg; + function setupTx(tx) { + if (tx.coin === 'bch') { + tx.displayAddress = bitcoinCashJsService.readAddress(tx.toAddress).cashaddr; } else { - tx.feeLevelName = feeService.feeOpts[tx.feeLevel]; - tx.feeRate = feeRate; + tx.displayAddress = tx.toAddress; } - getSendMaxInfo(lodash.clone(tx), wallet, function(err, sendMaxInfo) { + addressbookService.get(tx.coin+tx.toAddress, function(err, addr) { // Check if the recipient is a contact + if (!err && addr) { + tx.toName = addr.name; + tx.toEmail = addr.email; + tx.recipientType = 'contact'; + } + }); + + vm.showAddress = false; + + + setButtonText(vm.originWallet.credentials.m > 1, !!tx.paypro); + + if (tx.paypro) + startExpirationTimer(tx.paypro.expires); + + updateTx(tx, vm.originWallet, { + dryRun: true + }, function(err) { + $timeout(function() { + $scope.$apply(); + }, 10); + + }); + + // setWalletSelector(tx.coin, tx.network, tx.amount, function(err) { + // if (err) { + // return exitWithError('Could not update wallets'); + // } + // + // if (vm.wallets.length > 1) { + // vm.showWalletSelector(); + // } else if (vm.wallets.length) { + // setWallet(vm.wallets[0], tx); + // } + // }); + } + + function showSendMaxWarning(wallet, sendMaxInfo) { + var feeAlternative = '', + msg = ''; + + function verifyExcludedUtxos() { + var warningMsg = []; + if (sendMaxInfo.utxosBelowFee > 0) { + warningMsg.push(gettextCatalog.getString("A total of {{amountBelowFeeStr}} were excluded. These funds come from UTXOs smaller than the network fee provided.", { + amountBelowFeeStr: txFormatService.formatAmountStr(wallet.coin, sendMaxInfo.amountBelowFee) + })); + } + + if (sendMaxInfo.utxosAboveMaxSize > 0) { + warningMsg.push(gettextCatalog.getString("A total of {{amountAboveMaxSizeStr}} were excluded. The maximum size allowed for a transaction was exceeded.", { + amountAboveMaxSizeStr: txFormatService.formatAmountStr(vm.originWallet.coin, sendMaxInfo.amountAboveMaxSize) + })); + } + return warningMsg.join('\n'); + }; + + feeAlternative = txFormatService.formatAlternativeStr(vm.originWallet.coin, sendMaxInfo.fee); + if (feeAlternative) { + msg = gettextCatalog.getString("{{feeAlternative}} will be deducted for bitcoin networking fees ({{fee}}).", { + fee: txFormatService.formatAmountStr(vm.originWallet.coin, sendMaxInfo.fee), + feeAlternative: feeAlternative + }); + } else { + msg = gettextCatalog.getString("{{fee}} will be deducted for bitcoin networking fees).", { + fee: txFormatService.formatAmountStr(vm.originWallet.coin, sendMaxInfo.fee) + }); + } + + var warningMsg = verifyExcludedUtxos(); + + if (!lodash.isEmpty(warningMsg)) + msg += '\n' + warningMsg; + + popupService.showAlert(null, msg, function() {}); + }; + + function statusChangeHandler(processName, showName, isOn) { + $log.debug('statusChangeHandler: ', processName, showName, isOn); + if ( + ( + processName === 'broadcastingTx' || + ((processName === 'signingTx') && vm.originWallet.m > 1) || + (processName == 'sendingTx' && !vm.originWallet.canSign() && !vm.originWallet.isPrivKeyExternal()) + ) && !isOn) { + // Show the popup + vm.sendStatus = 'success'; + + // Clear the send flow service state + sendFlowService.state.clear(); + + if ($state.current.name === "tabs.send.review") { // XX SP: Otherwise all open wallets on other devices play this sound if you have been in a send flow before on that device. + soundService.play('misc/payment_sent.mp3'); + } + + var channel = "firebase"; + if (platformInfo.isNW) { + channel = "ga"; + } + // When displaying Fiat, if the formatting fails, the crypto will be the primary amount. + var amount = unitFromSat * satoshis; + var log = new window.BitAnalytics.LogEvent("transfer_success", [{ + "coin": vm.originWallet.coin, + "type": "outgoing", + "amount": amount, + "fees": vm.feeCrypto + }], [channel, "adjust"]); + window.BitAnalytics.LogEventHandlers.postEvent(log); + + $timeout(function() { + $scope.$digest(); + }, 100); + } else if (showName) { + vm.sendStatus = showName; + } + }; + + function updateTx(tx, wallet, opts, cb) { + ongoingProcess.set('calculatingFee', true); + + if (opts.clearCache) { + tx.txp = {}; + } + + // $scope.tx = tx; + + // function updateAmount() { + // if (!tx.amount) return; + // + // // Amount + // tx.amountStr = txFormatService.formatAmountStr(originWallet.coin, tx.amount); + // tx.amountValueStr = tx.amountStr.split(' ')[0]; + // tx.amountUnitStr = tx.amountStr.split(' ')[1]; + // txFormatService.formatAlternativeStr(wallet.coin, tx.amount, function(v) { + // var parts = v.split(' '); + // tx.alternativeAmountStr = v; + // tx.alternativeAmountValueStr = parts[0]; + // tx.alternativeAmountUnitStr = (parts.length > 0) ? parts[1] : ''; + // }); + // } + // + // updateAmount(); + // refresh(); + + var feeServiceLevel = usingMerchantFee && vm.originWallet.coin == 'btc' ? 'urgent' : tx.feeLevel; + feeService.getFeeRate(vm.originWallet.coin, tx.network, feeServiceLevel, function(err, feeRate) { if (err) { ongoingProcess.set('calculatingFee', false); - var msg = gettextCatalog.getString('Error getting SendMax information'); - return setSendError(msg); + return cb(err); } - if (sendMaxInfo) { - - $log.debug('Send max info', sendMaxInfo); - - if (tx.sendMax && sendMaxInfo.amount == 0) { - ongoingProcess.set('calculatingFee', false); - setNotReady(gettextCatalog.getString('Insufficient confirmed funds')); - popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Not enough funds for fee'), function () { - $ionicHistory.goBack(); - }); - return cb('no_funds'); - } - - tx.sendMaxInfo = sendMaxInfo; - tx.amount = tx.sendMaxInfo.amount; - satoshis = tx.amount; - updateSendAmounts(); - ongoingProcess.set('calculatingFee', false); - $timeout(function() { - showSendMaxWarning(wallet, sendMaxInfo); - }, 200); + var msg; + if (usingCustomFee) { + msg = gettextCatalog.getString('Custom'); + tx.feeLevelName = msg; + } else if (usingMerchantFee) { + $log.info('Using Merchant Fee:' + tx.feeRate + ' vs. Urgent level:' + feeRate); + msg = gettextCatalog.getString('Suggested by Merchant'); + tx.feeLevelName = msg; + } else { + tx.feeLevelName = feeService.feeOpts[tx.feeLevel]; + tx.feeRate = feeRate; } - // txp already generated for this wallet? - if (tx.txp[wallet.id]) { - ongoingProcess.set('calculatingFee', false); - vm.readyToSend = true; - updateSendAmounts(); - $scope.$apply(); - return cb(); - } - - console.log('calling getTxp() from getSendMaxInfo cb.'); - getTxp(lodash.clone(tx), wallet, opts.dryRun, function(err, txp) { - ongoingProcess.set('calculatingFee', false); + getSendMaxInfo(lodash.clone(tx), wallet, function(err, sendMaxInfo) { if (err) { - if (err.message == 'Insufficient funds') { - setNotReady(gettextCatalog.getString('Insufficient funds')); - popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Not enough funds for fee')); - return cb('no_funds'); - } else - return cb(err); + ongoingProcess.set('calculatingFee', false); + var msg = gettextCatalog.getString('Error getting SendMax information'); + return setSendError(msg); } - txp.feeStr = txFormatService.formatAmountStr(wallet.coin, txp.fee); - txFormatService.formatAlternativeStr(wallet.coin, txp.fee, function(v) { - // txp.alternativeFeeStr = v; - // if (txp.alternativeFeeStr.substring(0, 4) == '0.00') - // txp.alternativeFeeStr = '< ' + txp.alternativeFeeStr; - vm.feeFiat = v; - vm.fiatCurrency = config.wallet.settings.alternativeIsoCode; - if (v.substring(0, 1) === "<") { - vm.feeLessThanACent = true; + if (sendMaxInfo) { + + $log.debug('Send max info', sendMaxInfo); + + if (tx.sendMax && sendMaxInfo.amount == 0) { + ongoingProcess.set('calculatingFee', false); + setNotReady(gettextCatalog.getString('Insufficient confirmed funds')); + popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Not enough funds for fee'), function () { + $ionicHistory.goBack(); + }); + return cb('no_funds'); } - - console.log("fiat", vm.feeFiat); + tx.sendMaxInfo = sendMaxInfo; + tx.amount = tx.sendMaxInfo.amount; + satoshis = tx.amount; + updateSendAmounts(); + ongoingProcess.set('calculatingFee', false); + $timeout(function() { + showSendMaxWarning(wallet, sendMaxInfo); + }, 200); + } + + // txp already generated for this wallet? + if (tx.txp[wallet.id]) { + ongoingProcess.set('calculatingFee', false); + vm.readyToSend = true; + updateSendAmounts(); + $scope.$apply(); + return cb(); + } + + console.log('calling getTxp() from getSendMaxInfo cb.'); + getTxp(lodash.clone(tx), wallet, opts.dryRun, function(err, txp) { + ongoingProcess.set('calculatingFee', false); + if (err) { + if (err.message == 'Insufficient funds') { + setNotReady(gettextCatalog.getString('Insufficient funds')); + popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Not enough funds for fee')); + return cb('no_funds'); + } else + return cb(err); + } + + txp.feeStr = txFormatService.formatAmountStr(wallet.coin, txp.fee); + txFormatService.formatAlternativeStr(wallet.coin, txp.fee, function(v) { + // txp.alternativeFeeStr = v; + // if (txp.alternativeFeeStr.substring(0, 4) == '0.00') + // txp.alternativeFeeStr = '< ' + txp.alternativeFeeStr; + vm.feeFiat = v; + vm.fiatCurrency = config.wallet.settings.alternativeIsoCode; + if (v.substring(0, 1) === "<") { + vm.feeLessThanACent = true; + } + + console.log("fiat", vm.feeFiat); + + }); + + var per = (txp.fee / (txp.amount + txp.fee) * 100); + var perString = per.toFixed(2); + txp.feeRatePerStr = (perString == '0.00' ? '< ' : '') + perString + '%'; + txp.feeToHigh = per > FEE_TOO_HIGH_LIMIT_PERCENTAGE; + vm.feeCrypto = (unitFromSat * txp.fee).toFixed(8); + vm.feeIsHigh = txp.feeToHigh; + console.log("crypto", vm.feeCrypto); + + + tx.txp[wallet.id] = txp; + $log.debug('Confirm. TX Fully Updated for wallet:' + wallet.id, tx); + vm.readyToSend = true; + updateSendAmounts(); + console.log('readyToSend:', vm.readyToSend); + $scope.$apply(); + + return cb(); }); - - var per = (txp.fee / (txp.amount + txp.fee) * 100); - var perString = per.toFixed(2); - txp.feeRatePerStr = (perString == '0.00' ? '< ' : '') + perString + '%'; - txp.feeToHigh = per > FEE_TOO_HIGH_LIMIT_PERCENTAGE; - vm.feeCrypto = (unitFromSat * txp.fee).toFixed(8); - vm.feeIsHigh = txp.feeToHigh; - console.log("crypto", vm.feeCrypto); - - - tx.txp[wallet.id] = txp; - $log.debug('Confirm. TX Fully Updated for wallet:' + wallet.id, tx); - vm.readyToSend = true; - updateSendAmounts(); - console.log('readyToSend:', vm.readyToSend); - $scope.$apply(); - - return cb(); }); }); - }); + } } - -} +})(); From a17c3518c3fd7be6f3039fd7b0e494b5ab4f2ad5 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Fri, 21 Sep 2018 14:38:28 -0700 Subject: [PATCH 20/23] Manual merge from Sprint 22 for 575. --- src/js/controllers/review.controller.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/js/controllers/review.controller.js b/src/js/controllers/review.controller.js index fcaa80455..2311b2cb6 100644 --- a/src/js/controllers/review.controller.js +++ b/src/js/controllers/review.controller.js @@ -79,7 +79,7 @@ angular $scope.$on("$ionicView.beforeEnter", onBeforeEnter); - + function onBeforeEnter(event, data) { console.log('review onBeforeEnter sendflow ', sendFlowService.state); // Reset from last time @@ -100,7 +100,7 @@ angular vm.originWallet = profileService.getWallet(originWalletId); vm.origin.currency = vm.originWallet.coin.toUpperCase(); coin = vm.originWallet.coin; - + if (sendFlowData.thirdParty) { vm.thirdParty = sendFlowData.thirdParty; switch (vm.thirdParty.id) { @@ -398,12 +398,12 @@ angular var balanceCryptoAmount = ''; var balanceCryptoCurrencyCode = ''; var balanceFiatAmount = ''; - var balanceFiatCurrency = '' + var balanceFiatCurrency = ''; var displayAmount = ''; var displayCurrency = ''; var walletStatus = null; - if (wallet.status.isValid) { + if (wallet.status && wallet.status.isValid) { walletStatus = wallet.status; } else if (wallet.cachedStatus.isValid) { walletStatus = wallet.cachedStatus; From 2e1cc9fa872a33a10ce36e4c22820828a2708ef9 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Fri, 21 Sep 2018 16:43:27 -0700 Subject: [PATCH 21/23] Showing cached history first when entering Wallet Details screen. --- src/js/controllers/wallet-details.controller.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/js/controllers/wallet-details.controller.js b/src/js/controllers/wallet-details.controller.js index cef57925e..429420741 100644 --- a/src/js/controllers/wallet-details.controller.js +++ b/src/js/controllers/wallet-details.controller.js @@ -203,6 +203,7 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun function updateTxHistoryFromCachedData() { + $scope.vm.gettingCachedHistory = true; walletHistoryService.getCachedTxHistory($scope.wallet.id, function onGetCachedTxHistory(err, txHistory){ $scope.vm.gettingCachedHistory = false; if (err) { @@ -401,6 +402,7 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun var refreshInterval; $scope.$on("$ionicView.afterEnter", function onAfterEnter(event, data) { + updateTxHistoryFromCachedData(); $scope.updateAll(true, true); // refreshAmountSection(); refreshInterval = $interval($scope.onRefresh, 10 * 1000); From ff40317d87ea74405bc0a52afd5b43e021783c65 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Fri, 21 Sep 2018 16:45:46 -0700 Subject: [PATCH 22/23] Merged fix for wallet transaction history. --- src/js/services/wallet-history.service.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/js/services/wallet-history.service.js b/src/js/services/wallet-history.service.js index 13fc8d636..512a2d8b1 100644 --- a/src/js/services/wallet-history.service.js +++ b/src/js/services/wallet-history.service.js @@ -147,6 +147,7 @@ * @param {function(error, txs)} cb - txs is always an array, may be empty */ function getCachedTxHistory(walletId, cb) { + console.log('txhistory updateLocalTxHistoryByPage()'); storageService.getTxHistory(walletId, function onGetTxHistory(err, txHistoryString){ if (err) { return cb(err, []); @@ -229,6 +230,7 @@ } function updateLocalTxHistoryByPage(wallet, getLatest, flushCacheOnNew, cb) { + console.log('txhistory updaetLocalTxHistoryByPage()'); if (flushCacheOnNew) { fetchTxHistoryByPage(wallet, 0, function onFetchTxHistory(err, txs){ if (err) { From d72a71d9205ef533dd0d941fb67902d3d5ac7a4d Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Fri, 21 Sep 2018 17:21:59 -0700 Subject: [PATCH 23/23] RC version. --- app-template/bitcoincom/appConfig.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app-template/bitcoincom/appConfig.json b/app-template/bitcoincom/appConfig.json index a73fae33f..2eab6232d 100644 --- a/app-template/bitcoincom/appConfig.json +++ b/app-template/bitcoincom/appConfig.json @@ -24,9 +24,9 @@ "windowsAppId": "804636ee-b017-4cad-8719-e58ac97ffa5c", "pushSenderId": "1036948132229", "description": "A Secure Bitcoin Wallet", - "version": "5.1.2", - "fullVersion": "5.1-rc1", - "androidVersion": "501002", + "version": "5.1.3", + "fullVersion": "5.1-rc2", + "androidVersion": "501003", "_extraCSS": "", "_enabledExtensions": { "coinbase": false,