From 8c62bc445acd6dd83f34fb3f6718ed4d05429478 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Wed, 5 Sep 2018 12:37:39 +1200 Subject: [PATCH 01/29] Shapeshift item on home tab now goes to the Shapeshift website. --- src/js/controllers/servicesController.js | 6 +++++- src/js/services/servicesService.js | 2 +- www/views/includes/services.html | 9 ++++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/js/controllers/servicesController.js b/src/js/controllers/servicesController.js index 62b13c041..0f9b6d4f8 100644 --- a/src/js/controllers/servicesController.js +++ b/src/js/controllers/servicesController.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('servicesController', function($scope, $ionicScrollDelegate, $timeout, servicesService, configService) { +angular.module('copayApp.controllers').controller('servicesController', function(externalLinkService, $scope, $ionicScrollDelegate, $timeout, servicesService, configService) { $scope.hide = false; configService.whenAvailable(function(config) { @@ -20,4 +20,8 @@ angular.module('copayApp.controllers').controller('servicesController', function }, 10); }; + $scope.open = function(url) { + externalLinkService.open(url, false); + } + }); diff --git a/src/js/services/servicesService.js b/src/js/services/servicesService.js index 316009957..ddd9db394 100644 --- a/src/js/services/servicesService.js +++ b/src/js/services/servicesService.js @@ -5,7 +5,7 @@ angular.module('copayApp.services').factory('servicesService', function(configSe name: 'shapeshift', title: 'Shapeshift', icon: 'icon-shapeshift', - sref: 'tabs.shapeshift', + href: 'https://shapeshift.io/' }]; root.register = function(serviceInfo) { diff --git a/www/views/includes/services.html b/www/views/includes/services.html index f57cd1004..05e6dcf2d 100644 --- a/www/views/includes/services.html +++ b/www/views/includes/services.html @@ -6,7 +6,14 @@
- + + +
+
+ {{service.title || service.name}} + +
+
From 00e4f8ac392c0219704331bd581c02f00bf90a67 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Wed, 5 Sep 2018 15:28:10 +1200 Subject: [PATCH 02/29] Hotfix 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 e4d6c8a84..9a155362b 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.0.3", + "fullVersion": "5.0-hotfix1", + "androidVersion": "500300", "_extraCSS": "", "_enabledExtensions": { "coinbase": false, From 51c35101a6c10215173ef4f3c46a0063c6e94562 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Dominguez Date: Fri, 7 Sep 2018 17:08:39 +0900 Subject: [PATCH 03/29] 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 04/29] 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 d55fc70e7d2d84a312bff06bc66d57af6ab10f71 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Wed, 12 Sep 2018 18:13:50 +1200 Subject: [PATCH 05/29] Remove Games link. --- src/js/services/bitcoincomService.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/js/services/bitcoincomService.js b/src/js/services/bitcoincomService.js index 68fd51a8a..20e326460 100644 --- a/src/js/services/bitcoincomService.js +++ b/src/js/services/bitcoincomService.js @@ -85,7 +85,9 @@ angular.module('copayApp.services').factory('bitcoincomService', function(gettex }; var register = function() { - nextStepsService.register(cashGamesItem); + if (!platformInfo.isAndroid) { + nextStepsService.register(cashGamesItem); + } nextStepsService.register(newsItem); nextStepsService.register(poolItem); nextStepsService.register(toolsItem); From 9438960e24b3cedf74a75d7235749e6006ef0ef7 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Wed, 12 Sep 2018 18:39:56 +1200 Subject: [PATCH 06/29] Hotfix 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 9a155362b..c65f67248 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.3", - "fullVersion": "5.0-hotfix1", - "androidVersion": "500300", + "version": "5.0.4", + "fullVersion": "5.0-hotfix2", + "androidVersion": "500400", "_extraCSS": "", "_enabledExtensions": { "coinbase": false, From e02368ea3cbae6f1cdf0c104d26477e31c74641c Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Sat, 15 Sep 2018 18:05:39 +1200 Subject: [PATCH 07/29] 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 d72a71d9205ef533dd0d941fb67902d3d5ac7a4d Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Fri, 21 Sep 2018 17:21:59 -0700 Subject: [PATCH 08/29] 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, From 0ba4db83e0f9ad5a06b6104a393d89ac0f8e0250 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Sat, 22 Sep 2018 11:03:26 -0700 Subject: [PATCH 09/29] Handling confirmation updates correctly for early transactions. --- src/js/services/wallet-history.service.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/js/services/wallet-history.service.js b/src/js/services/wallet-history.service.js index 512a2d8b1..798c92671 100644 --- a/src/js/services/wallet-history.service.js +++ b/src/js/services/wallet-history.service.js @@ -28,8 +28,8 @@ function addEarlyTransactions(walletId, cachedTxs, newTxs) { var cachedTxIndexFromId = {}; - cachedTxs.forEach(function forCachedTx(tx){ - cachedTxIndexFromId[tx.txid] = true; + cachedTxs.forEach(function forCachedTx(tx, txIndex){ + cachedTxIndexFromId[tx.txid] = txIndex; }); var confirmationsUpdated = false; @@ -147,7 +147,7 @@ * @param {function(error, txs)} cb - txs is always an array, may be empty */ function getCachedTxHistory(walletId, cb) { - console.log('txhistory updateLocalTxHistoryByPage()'); + console.log('txhistory getCachedTxHistory()'); storageService.getTxHistory(walletId, function onGetTxHistory(err, txHistoryString){ if (err) { return cb(err, []); @@ -230,7 +230,7 @@ } function updateLocalTxHistoryByPage(wallet, getLatest, flushCacheOnNew, cb) { - console.log('txhistory updaetLocalTxHistoryByPage()'); + console.log('txhistory updateLocalTxHistoryByPage()'); if (flushCacheOnNew) { fetchTxHistoryByPage(wallet, 0, function onFetchTxHistory(err, txs){ if (err) { From a5a1d3edb673f589e17110deb55194a76ab170ab Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Sat, 22 Sep 2018 11:07:24 -0700 Subject: [PATCH 10/29] Remove debug logging. --- src/js/services/wallet-history.service.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/js/services/wallet-history.service.js b/src/js/services/wallet-history.service.js index 798c92671..5cb08e6ee 100644 --- a/src/js/services/wallet-history.service.js +++ b/src/js/services/wallet-history.service.js @@ -147,7 +147,6 @@ * @param {function(error, txs)} cb - txs is always an array, may be empty */ function getCachedTxHistory(walletId, cb) { - console.log('txhistory getCachedTxHistory()'); storageService.getTxHistory(walletId, function onGetTxHistory(err, txHistoryString){ if (err) { return cb(err, []); @@ -230,7 +229,6 @@ } function updateLocalTxHistoryByPage(wallet, getLatest, flushCacheOnNew, cb) { - console.log('txhistory updateLocalTxHistoryByPage()'); if (flushCacheOnNew) { fetchTxHistoryByPage(wallet, 0, function onFetchTxHistory(err, txs){ if (err) { From c661798cd14128a2266acb36786bd285685a6506 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Sat, 22 Sep 2018 17:45:19 -0700 Subject: [PATCH 11/29] Android Debug and release builds work when Gradle 3.3 is in PATH. --- Gruntfile.js | 2 +- app-template/config-template.xml | 2 +- src/android/build-extras.gradle | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 7968f2510..4ac23e47a 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -71,7 +71,7 @@ module.exports = function(grunt) { sign_android: { // When the build log outputs "Built the following apk(s):", it seems to need the filename to start with "android-release". // It looks like it simply lists all apk files starting with "android-release" - command: 'rm -f platforms/android/build/outputs/apk/android-release-signed-*.apk; jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ../bitcoin-com-release-key.jks -signedjar platforms/android/build/outputs/apk/android-release-signed.apk platforms/android/build/outputs/apk/android-release-unsigned.apk bitcoin-com && zipalign -v 4 platforms/android/build/outputs/apk/android-release-signed.apk platforms/android/build/outputs/apk/bitcoin-com-wallet-<%= pkg.fullVersion %>-android-signed-aligned.apk', + command: 'rm -f platforms/android/build/outputs/apk/release/*-android-signed-aligned.apk; jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ../bitcoin-com-release-key.jks -signedjar platforms/android/build/outputs/apk/release/android-release-signed.apk platforms/android/build/outputs/apk/release/android-release-unsigned.apk bitcoin-com && zipalign -v 4 platforms/android/build/outputs/apk/release/android-release-signed.apk platforms/android/build/outputs/apk/release/bitcoin-com-wallet-<%= pkg.fullVersion %>-android-signed-aligned.apk', stdin: true, }, sign_desktop_dist: { diff --git a/app-template/config-template.xml b/app-template/config-template.xml index 8686b7b36..b24b86fae 100644 --- a/app-template/config-template.xml +++ b/app-template/config-template.xml @@ -77,7 +77,7 @@ - + diff --git a/src/android/build-extras.gradle b/src/android/build-extras.gradle index e7dd50572..c90145418 100644 --- a/src/android/build-extras.gradle +++ b/src/android/build-extras.gradle @@ -1,5 +1,6 @@ ext { ANDROID_SUPPORT_V4_VERSION = '26.1.0' + ANDROID_SUPPORT_ANNOTATIONS_VERSION = '26.1.0' } configurations.all { From 1b0541a7b5746c0ef2eae602695bc816cab1b0dc Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Sat, 22 Sep 2018 22:22:06 -0700 Subject: [PATCH 12/29] Return error from Shapeshift when pairs are unavailable. --- src/js/services/shapeShiftApiService.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/js/services/shapeShiftApiService.js b/src/js/services/shapeShiftApiService.js index cc5fb0792..92564464a 100644 --- a/src/js/services/shapeShiftApiService.js +++ b/src/js/services/shapeShiftApiService.js @@ -23,6 +23,13 @@ var ShapeShift = (function() { if (xmlhttp.status == 200) { var parsedResponse = JP(xmlhttp.responseText); cb.apply(null, [parsedResponse]); + } else if (xmlhttp.status === 500) { + var parsedResponse = JP(xmlhttp.responseText); + if (typeof parsedResponse.error === 'string') { + cb.apply(null, [parsedResponse]); + } else { + cb.apply(null, [new Error('Request Failed')]); + } } else { cb.apply(null, [new Error('Request Failed')]) } From 6452a0c7f4797a7321b58f4bff2ef72a54c01dda Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Sun, 23 Sep 2018 13:06:36 -0700 Subject: [PATCH 13/29] Handling JSON exception. --- src/js/services/shapeShiftApiService.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/js/services/shapeShiftApiService.js b/src/js/services/shapeShiftApiService.js index 92564464a..67e6f23de 100644 --- a/src/js/services/shapeShiftApiService.js +++ b/src/js/services/shapeShiftApiService.js @@ -23,15 +23,17 @@ var ShapeShift = (function() { if (xmlhttp.status == 200) { var parsedResponse = JP(xmlhttp.responseText); cb.apply(null, [parsedResponse]); - } else if (xmlhttp.status === 500) { - var parsedResponse = JP(xmlhttp.responseText); - if (typeof parsedResponse.error === 'string') { - cb.apply(null, [parsedResponse]); - } else { - cb.apply(null, [new Error('Request Failed')]); - } } else { - cb.apply(null, [new Error('Request Failed')]) + var cbResponse = new Error('Request Failed'); + if (xmlhttp.status === 500) { + try { + var errorResponse = JSON.parse(xmlhttp.responseText); + if (typeof errorResponse.error === 'string') { + cbResponse = errorResponse; + } + } catch (e) { /* nop */ } + } + cb.apply(null, [cbResponse]); } } }; From babdc8a13bb52474bd79d5433bc5a37f10293cd2 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Sun, 23 Sep 2018 20:14:42 -0700 Subject: [PATCH 14/29] Restored production setting for page size. --- src/js/services/wallet-history.service.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/js/services/wallet-history.service.js b/src/js/services/wallet-history.service.js index 5cb08e6ee..a0b36288d 100644 --- a/src/js/services/wallet-history.service.js +++ b/src/js/services/wallet-history.service.js @@ -7,8 +7,8 @@ .factory('walletHistoryService', walletHistoryService); function walletHistoryService(configService, storageService, lodash, $log, txFormatService) { - //var PAGE_SIZE = 50; - var PAGE_SIZE = 20; // For dev only + var PAGE_SIZE = 50; + //var PAGE_SIZE = 20; // For dev only // How much to overlap on each end of the page, for mitigating inconsistent sort order. var PAGE_OVERLAP_FRACTION = 0.2; var PAGE_OVERLAP = Math.floor(PAGE_SIZE * PAGE_OVERLAP_FRACTION); From 8f8027d573832c100e4293f9166bdd8a1cbb290a Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Sun, 23 Sep 2018 20:56:15 -0700 Subject: [PATCH 15/29] Reverse out bugfix. --- src/js/services/shapeShiftApiService.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/js/services/shapeShiftApiService.js b/src/js/services/shapeShiftApiService.js index 67e6f23de..a90e587d4 100644 --- a/src/js/services/shapeShiftApiService.js +++ b/src/js/services/shapeShiftApiService.js @@ -24,16 +24,7 @@ var ShapeShift = (function() { var parsedResponse = JP(xmlhttp.responseText); cb.apply(null, [parsedResponse]); } else { - var cbResponse = new Error('Request Failed'); - if (xmlhttp.status === 500) { - try { - var errorResponse = JSON.parse(xmlhttp.responseText); - if (typeof errorResponse.error === 'string') { - cbResponse = errorResponse; - } - } catch (e) { /* nop */ } - } - cb.apply(null, [cbResponse]); + cb.apply(null, [new Error('Request Failed')]); } } }; From d2178d670f2949f8c89164bdc7e94ed44ce31ecf Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Sun, 23 Sep 2018 21:05:26 -0700 Subject: [PATCH 16/29] Fix identification of BitPay. --- src/js/services/send-flow.service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/services/send-flow.service.js b/src/js/services/send-flow.service.js index e8be2e487..babf5096a 100644 --- a/src/js/services/send-flow.service.js +++ b/src/js/services/send-flow.service.js @@ -52,7 +52,7 @@ angular // Detect some merchant that we know if (payProData.memo.indexOf('eGifter') > -1) { name = 'eGifter' - } else if (paymentUrl.indexOf('https://bitpay.com') > -1) { + } else if (payProData.url.indexOf('https://bitpay.com') > -1) { name = 'BitPay'; } From 5401bf9a0998d8515d21b195656568674ec67d8a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Dominguez Date: Mon, 24 Sep 2018 16:54:40 +0200 Subject: [PATCH 17/29] Fix the case where the cache is empty --- src/js/services/wallet-history.service.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/js/services/wallet-history.service.js b/src/js/services/wallet-history.service.js index 5cb08e6ee..760f6994e 100644 --- a/src/js/services/wallet-history.service.js +++ b/src/js/services/wallet-history.service.js @@ -49,8 +49,9 @@ var overlappingTxFraction = overlappingTxsCount / Math.min(cachedTxs.length, PAGE_OVERLAP); console.log('overlappingTxFraction:', overlappingTxFraction); + console.log('overlappingTxsCount:', overlappingTxsCount); - if (overlappingTxFraction >= MIN_KNOWN_TX_OVERLAP_FRACTION) { // We are good + if (overlappingTxFraction >= MIN_KNOWN_TX_OVERLAP_FRACTION || (someTransactionsWereNew && overlappingTxsCount === 0)) { // We are good if (someTransactionsWereNew) { saveTxHistory(walletId, cachedTxs); } else if (confirmationsUpdated) { From fb41fca6015c7284657083139f8bc763437acfb6 Mon Sep 17 00:00:00 2001 From: Sebastiaan Pasma Date: Mon, 24 Sep 2018 17:13:28 +0200 Subject: [PATCH 18/29] Also apply fix to addLatestTransactions function --- src/js/services/wallet-history.service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/services/wallet-history.service.js b/src/js/services/wallet-history.service.js index 01e752465..a9792c170 100644 --- a/src/js/services/wallet-history.service.js +++ b/src/js/services/wallet-history.service.js @@ -94,7 +94,7 @@ var overlappingTxFraction = overlappingTxsCount / Math.min(cachedTxs.length, PAGE_OVERLAP); - if (overlappingTxFraction >= MIN_KNOWN_TX_OVERLAP_FRACTION) { // We are good + if (overlappingTxFraction >= MIN_KNOWN_TX_OVERLAP_FRACTION || (someTransactionsWereNew && overlappingTxsCount === 0)) { // We are good if (someTransactionsWereNew) { var allTxs = uniqueNewTxs.concat(cachedTxs); saveTxHistory(walletId, allTxs); From d68870f7435d3ed9b40b1ef91026325051ecfbb3 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Wed, 26 Sep 2018 18:03:14 +1200 Subject: [PATCH 19/29] Bugfix for getting wallet history when cache is empty, while still enforcing overlap in transactions when cache contains transactions, to ensure no transactions are missed. --- src/js/services/wallet-history.service.js | 33 ++++++++++++++++------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/src/js/services/wallet-history.service.js b/src/js/services/wallet-history.service.js index a9792c170..f114a396d 100644 --- a/src/js/services/wallet-history.service.js +++ b/src/js/services/wallet-history.service.js @@ -6,7 +6,7 @@ .module('bitcoincom.services') .factory('walletHistoryService', walletHistoryService); - function walletHistoryService(configService, storageService, lodash, $log, txFormatService) { + function walletHistoryService(storageService, lodash, $log, txFormatService) { var PAGE_SIZE = 50; //var PAGE_SIZE = 20; // For dev only // How much to overlap on each end of the page, for mitigating inconsistent sort order. @@ -47,11 +47,17 @@ } }); - var overlappingTxFraction = overlappingTxsCount / Math.min(cachedTxs.length, PAGE_OVERLAP); - console.log('overlappingTxFraction:', overlappingTxFraction); - console.log('overlappingTxsCount:', overlappingTxsCount); - - if (overlappingTxFraction >= MIN_KNOWN_TX_OVERLAP_FRACTION || (someTransactionsWereNew && overlappingTxsCount === 0)) { // We are good + var txsAreContinuous = false; + if (cachedTxs.length > 0) { + var overlappingTxFraction = overlappingTxsCount / Math.min(cachedTxs.length, PAGE_OVERLAP); + console.log('overlappingTxsCount:', overlappingTxsCount); + console.log('overlappingTxFraction:', overlappingTxFraction); + txsAreContinuous = overlappingTxFraction >= MIN_KNOWN_TX_OVERLAP_FRACTION; + } else { + txsAreContinuous = true; + } + + if (txsAreContinuous) { if (someTransactionsWereNew) { saveTxHistory(walletId, cachedTxs); } else if (confirmationsUpdated) { @@ -62,7 +68,7 @@ return cachedTxs; } else { // We might be missing some txs. - console.error('We might be missing some txs in the history.'); + $log.error('We might be missing some txs in the history.'); // Our history is wrong, so remove it - we could instead, try to fetch data that was not so early. storageService.removeTxHistory(walletId, function onRemoveTxHistory(){}); return []; @@ -92,9 +98,17 @@ } }); - var overlappingTxFraction = overlappingTxsCount / Math.min(cachedTxs.length, PAGE_OVERLAP); + var txsAreContinuous = false; + if (cachedTxs.length > 0) { + var overlappingTxFraction = overlappingTxsCount / Math.min(cachedTxs.length, PAGE_OVERLAP); + console.log('overlappingTxsCount:', overlappingTxsCount); + console.log('overlappingTxFraction:', overlappingTxFraction); + txsAreContinuous = overlappingTxFraction >= MIN_KNOWN_TX_OVERLAP_FRACTION; + } else { + txsAreContinuous = true; + } - if (overlappingTxFraction >= MIN_KNOWN_TX_OVERLAP_FRACTION || (someTransactionsWereNew && overlappingTxsCount === 0)) { // We are good + if (txsAreContinuous) { if (someTransactionsWereNew) { var allTxs = uniqueNewTxs.concat(cachedTxs); saveTxHistory(walletId, allTxs); @@ -107,6 +121,7 @@ } } else { // We might be missing some txs. + $log.error('We might be missing some txs in the history.'); // Our history is wrong, so just include the latest ones saveTxHistory(walletId, newTxs); return newTxs; From 2d0e5c5f79f1e29747fb559556b7c5f55a133659 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Wed, 26 Sep 2018 18:24:24 +1200 Subject: [PATCH 20/29] Started on unit tests for wallet history. --- .../services/wallet-history.service.spec.js | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 src/js/services/wallet-history.service.spec.js diff --git a/src/js/services/wallet-history.service.spec.js b/src/js/services/wallet-history.service.spec.js new file mode 100644 index 000000000..1a04833f8 --- /dev/null +++ b/src/js/services/wallet-history.service.spec.js @@ -0,0 +1,81 @@ +fdescribe('walletHistoryService', function(){ + var history = []; + var historyStringFull; + var storageServiceMock; + var txFormatServiceMock; + var walletHistoryService; + + + beforeEach(function(){ + module('ngLodash'); + module('bitcoincom.services'); + + storageServiceMock = jasmine.createSpyObj(['getTxHistory', 'removeTxHistory', 'setTxHistory']); + txFormatServiceMock = jasmine.createSpyObj(['processTx']); + txFormatServiceMock.processTx.and.callFake(function(coin, tx){ + return tx; + }) + + module(function($provide) { + $provide.value('storageService', storageServiceMock); + $provide.value('txFormatService', txFormatServiceMock); + }); + + inject(function($injector){ + walletHistoryService = $injector.get('walletHistoryService'); + }); + + for(var i = 0; i < 100; i++) { + history.push({ + confirmations: i, + time: (Date.now() / 1000) - i, + txid: 'id' + i.toString() + }); + } + historyStringFull = JSON.stringify(history); + }); + + it('getCachedHistory empty', function() { + var returnedErr; + var returnedHistory; + var walletIdForStorageGet = ''; + + storageServiceMock.getTxHistory.and.callFake(function(walletId, cb){ + walletIdForStorageGet = walletId; + + cb(null, "[]"); + }); + + walletHistoryService.getCachedTxHistory('wallet1234', function(err, txHistory){ + returnedErr = err; + returnedHistory = txHistory; + }); + + expect(walletIdForStorageGet).toBe('wallet1234'); + expect(returnedErr).toBeNull(); + expect(returnedHistory.length).toBe(0); + }); + + it('getCachedHistory page full', function() { + var returnedErr; + var returnedHistory; + var walletIdForStorageGet = ''; + + storageServiceMock.getTxHistory.and.callFake(function(walletId, cb){ + walletIdForStorageGet = walletId; + + cb(null, JSON.stringify(history.slice(0, 50))); + }); + + walletHistoryService.getCachedTxHistory('wallet1234', function(err, txHistory){ + returnedErr = err; + returnedHistory = txHistory; + }); + + expect(walletIdForStorageGet).toBe('wallet1234'); + expect(returnedErr).toBeNull(); + expect(returnedHistory.length).toBe(50); + }); + + +}); \ No newline at end of file From 5825ff26b8a599bee96583962917f33a3fdacdf1 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Wed, 26 Sep 2018 21:50:42 +1200 Subject: [PATCH 21/29] A few more test cases. --- .../services/wallet-history.service.spec.js | 215 +++++++++++++++++- 1 file changed, 214 insertions(+), 1 deletion(-) diff --git a/src/js/services/wallet-history.service.spec.js b/src/js/services/wallet-history.service.spec.js index 1a04833f8..1f55ca031 100644 --- a/src/js/services/wallet-history.service.spec.js +++ b/src/js/services/wallet-history.service.spec.js @@ -3,6 +3,7 @@ fdescribe('walletHistoryService', function(){ var historyStringFull; var storageServiceMock; var txFormatServiceMock; + var walletMock; var walletHistoryService; @@ -14,7 +15,8 @@ fdescribe('walletHistoryService', function(){ txFormatServiceMock = jasmine.createSpyObj(['processTx']); txFormatServiceMock.processTx.and.callFake(function(coin, tx){ return tx; - }) + }); + walletMock = jasmine.createSpyObj(['getTxHistory']); module(function($provide) { $provide.value('storageService', storageServiceMock); @@ -56,6 +58,27 @@ fdescribe('walletHistoryService', function(){ expect(returnedHistory.length).toBe(0); }); + it('getCachedHistory error from storage', function() { + var returnedErr; + var returnedHistory; + var walletIdForStorageGet = ''; + + storageServiceMock.getTxHistory.and.callFake(function(walletId, cb){ + walletIdForStorageGet = walletId; + + cb(new Error('Something went wrong.'), null); + }); + + walletHistoryService.getCachedTxHistory('wallet12345', function(err, txHistory){ + returnedErr = err; + returnedHistory = txHistory; + }); + + expect(walletIdForStorageGet).toBe('wallet12345'); + expect(returnedErr.message).toBe('Something went wrong.'); + expect(returnedHistory.length).toBe(0); + }); + it('getCachedHistory page full', function() { var returnedErr; var returnedHistory; @@ -77,5 +100,195 @@ fdescribe('walletHistoryService', function(){ expect(returnedHistory.length).toBe(50); }); + it('updateLocalTxHistoryByPage, getEarlier, keep cache, sufficient overlap so saved.', function(){ + var fetchLimit; + var fetchSkip; + var returnedHistory; + var savedTxs; + var walletIdForStorageGet; + var walletIdForStorageSet; + walletMock.id = 'wallet67890'; + + storageServiceMock.getTxHistory.and.callFake(function(walletId, cb){ + walletIdForStorageGet = walletId; + + cb(null, JSON.stringify(history.slice(0, 40))); + }); + + walletMock.getTxHistory.and.callFake(function(opts, cb){ + fetchSkip = opts.skip; + fetchLimit = opts.limit; + + cb(null, history.slice(fetchSkip, fetchSkip + fetchLimit)); + }); + + storageServiceMock.setTxHistory.and.callFake(function(txs, walletId, cb){ + savedTxs = txs; + walletIdForStorageSet = walletId; + cb(null); + }); + + walletHistoryService.updateLocalTxHistoryByPage(walletMock, false, false, function(err, txs){ + returnedErr = err; + returnedHistory = txs; + }); + + expect(walletIdForStorageGet).toBe('wallet67890'); + expect(walletIdForStorageSet).toBe('wallet67890'); + expect(fetchSkip).toBe(30); + expect(fetchLimit).toBe(50); + expect(savedTxs.length).toBe(80); + expect(returnedErr).toBeNull(); + expect(returnedHistory.length).toBe(80); + }); + + it('updateLocalTxHistoryByPage, cache empty, getLatest, do not flush cache, some new so saved.', function(){ + var fetchLimit; + var fetchSkip; + var returnedHistory; + var savedTxs; + var walletIdForStorageGet; + var walletIdForStorageSet; + walletMock.id = 'wallet789'; + + storageServiceMock.getTxHistory.and.callFake(function(walletId, cb){ + walletIdForStorageGet = walletId; + cb(null, "[]"); + }); + + walletMock.getTxHistory.and.callFake(function(opts, cb){ + fetchSkip = opts.skip; + fetchLimit = opts.limit; + + cb(null, history.slice(0, 10)); + }); + + storageServiceMock.setTxHistory.and.callFake(function(txs, walletId, cb){ + savedTxs = txs; + walletIdForStorageSet = walletId; + cb(null); + }); + + walletHistoryService.updateLocalTxHistoryByPage(walletMock, true, false, function(err, txs){ + returnedErr = err; + returnedHistory = txs; + }); + + expect(walletIdForStorageGet).toBe('wallet789'); + expect(fetchSkip).toBe(0); + expect(fetchLimit).toBe(50); + expect(savedTxs.length).toBe(10); + expect(returnedErr).toBeNull(); + expect(returnedHistory.length).toBe(10); + }); + + it('updateLocalTxHistoryByPage, some cachedTx, getLatest, do not flush cache, nothing new so nothing added.', function(){ + var fetchLimit; + var fetchSkip; + var returnedHistory; + var walletIdForStorageGet; + walletMock.id = 'wallet789'; + + storageServiceMock.getTxHistory.and.callFake(function(walletId, cb){ + walletIdForStorageGet = walletId; + cb(null, JSON.stringify(history.slice(0, 40))); + }); + + walletMock.getTxHistory.and.callFake(function(opts, cb){ + fetchSkip = opts.skip; + fetchLimit = opts.limit; + + cb(null, []); + }); + + walletHistoryService.updateLocalTxHistoryByPage(walletMock, true, false, function(err, txs){ + returnedErr = err; + returnedHistory = txs; + }); + + expect(walletIdForStorageGet).toBe('wallet789'); + expect(fetchSkip).toBe(0); + expect(fetchLimit).toBe(50); + expect(returnedErr).toBeNull(); + expect(returnedHistory.length).toBe(40); + expect(storageServiceMock.setTxHistory.calls.any()).toBe(false); + }); + + it('updateLocalTxHistoryByPage, some cachedTx, getLatest, do not flush cache, some new with sufficient overlap so all saved.', function(){ + var fetchLimit; + var fetchSkip; + var returnedHistory; + var savedTxs; + var walletIdForStorageGet; + var walletIdForStorageSet; + walletMock.id = 'wallet789'; + + storageServiceMock.getTxHistory.and.callFake(function(walletId, cb){ + walletIdForStorageGet = walletId; + cb(null, JSON.stringify(history.slice(42, 72))); + }); + + walletMock.getTxHistory.and.callFake(function(opts, cb){ + fetchSkip = opts.skip; + fetchLimit = opts.limit; + + cb(null, history.slice(fetchSkip, fetchSkip + fetchLimit)); + }); + + storageServiceMock.setTxHistory.and.callFake(function(txs, walletId, cb){ + savedTxs = txs; + walletIdForStorageSet = walletId; + cb(null); + }); + + walletHistoryService.updateLocalTxHistoryByPage(walletMock, true, false, function(err, txs){ + returnedErr = err; + returnedHistory = txs; + }); + + expect(walletIdForStorageGet).toBe('wallet789'); + expect(fetchSkip).toBe(0); + expect(fetchLimit).toBe(50); + expect(walletIdForStorageSet).toBe('wallet789'); + expect(savedTxs.length).toBe(72); + expect(returnedErr).toBeNull(); + expect(returnedHistory.length).toBe(72); + + }); + + it('updateLocalTxHistoryByPage, getLatest, flush cache, some new so saved.', function(){ + var fetchLimit; + var fetchSkip; + var returnedHistory; + var savedTxs; + var walletIdForStorageSet; + walletMock.id = 'wallet7890'; + + walletMock.getTxHistory.and.callFake(function(opts, cb){ + fetchSkip = opts.skip; + fetchLimit = opts.limit; + + cb(null, history.slice(0, fetchLimit)); + }); + + storageServiceMock.setTxHistory.and.callFake(function(txs, walletId, cb){ + savedTxs = txs; + walletIdForStorageSet = walletId; + cb(null); + }); + + walletHistoryService.updateLocalTxHistoryByPage(walletMock, true, true, function(err, txs){ + returnedErr = err; + returnedHistory = txs; + }); + + expect(walletIdForStorageSet).toBe('wallet7890'); + expect(fetchSkip).toBe(0); + expect(fetchLimit).toBe(50); + expect(savedTxs.length).toBe(50); + expect(returnedErr).toBeNull(); + expect(returnedHistory.length).toBe(50); + expect(storageServiceMock.getTxHistory.calls.any()).toBe(false); + }); }); \ No newline at end of file From 9cfc05deddc7a66688141cf92a4308e01ba1cf79 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Wed, 26 Sep 2018 22:05:31 +1200 Subject: [PATCH 22/29] Unit test cases to cover confirmations increasing, and insufficient overlap. --- .../services/wallet-history.service.spec.js | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/src/js/services/wallet-history.service.spec.js b/src/js/services/wallet-history.service.spec.js index 1f55ca031..113ab34b3 100644 --- a/src/js/services/wallet-history.service.spec.js +++ b/src/js/services/wallet-history.service.spec.js @@ -214,6 +214,100 @@ fdescribe('walletHistoryService', function(){ expect(storageServiceMock.setTxHistory.calls.any()).toBe(false); }); + it('updateLocalTxHistoryByPage, some cachedTx, getLatest, do not flush cache, confirmations increased, saved.', function(){ + var fetchLimit; + var fetchSkip; + var returnedHistory; + var savedTxs; + var walletIdForStorageGet; + var walletIdForStorageSet; + walletMock.id = 'wallet789'; + + storageServiceMock.getTxHistory.and.callFake(function(walletId, cb){ + walletIdForStorageGet = walletId; + cb(null, JSON.stringify(history.slice(2, 52))); + }); + + walletMock.getTxHistory.and.callFake(function(opts, cb){ + fetchSkip = opts.skip; + fetchLimit = opts.limit; + + var historyWithHigherConfirmations = []; + for (var i = 0; i < 50; i++) { + historyWithHigherConfirmations.push({ + confirmations: i >= 6 ? history[i].confirmations : history[i].confirmations + 1, + time: history[i].time, + txid: history[i].txid + }); + } + + cb(null, historyWithHigherConfirmations.slice(fetchSkip, fetchSkip + fetchLimit)); + }); + + storageServiceMock.setTxHistory.and.callFake(function(txs, walletId, cb){ + savedTxs = txs; + walletIdForStorageSet = walletId; + cb(null); + }); + + walletHistoryService.updateLocalTxHistoryByPage(walletMock, true, false, function(err, txs){ + returnedErr = err; + returnedHistory = txs; + }); + + expect(walletIdForStorageGet).toBe('wallet789'); + expect(fetchSkip).toBe(0); + expect(fetchLimit).toBe(50); + expect(walletIdForStorageSet).toBe('wallet789'); + expect(savedTxs.length).toBe(52); + expect(returnedErr).toBeNull(); + expect(returnedHistory.length).toBe(52); + expect(returnedHistory[2].confirmations).toBe(3); + + }); + + it('updateLocalTxHistoryByPage, some cachedTx, getLatest, do not flush cache, some new with insufficient overlap, so only new saved.', function(){ + var fetchLimit; + var fetchSkip; + var returnedHistory; + var savedTxs; + var walletIdForStorageGet; + var walletIdForStorageSet; + walletMock.id = 'wallet789'; + + storageServiceMock.getTxHistory.and.callFake(function(walletId, cb){ + walletIdForStorageGet = walletId; + cb(null, JSON.stringify(history.slice(48, 78))); + }); + + walletMock.getTxHistory.and.callFake(function(opts, cb){ + fetchSkip = opts.skip; + fetchLimit = opts.limit; + + cb(null, history.slice(fetchSkip, fetchSkip + fetchLimit)); + }); + + storageServiceMock.setTxHistory.and.callFake(function(txs, walletId, cb){ + savedTxs = txs; + walletIdForStorageSet = walletId; + cb(null); + }); + + walletHistoryService.updateLocalTxHistoryByPage(walletMock, true, false, function(err, txs){ + returnedErr = err; + returnedHistory = txs; + }); + + expect(walletIdForStorageGet).toBe('wallet789'); + expect(fetchSkip).toBe(0); + expect(fetchLimit).toBe(50); + expect(walletIdForStorageSet).toBe('wallet789'); + expect(savedTxs.length).toBe(50); + expect(returnedErr).toBeNull(); + expect(returnedHistory.length).toBe(50); + + }); + it('updateLocalTxHistoryByPage, some cachedTx, getLatest, do not flush cache, some new with sufficient overlap so all saved.', function(){ var fetchLimit; var fetchSkip; From 4692e0d91d944b825c421a6fbd0ee148f0c2dd82 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Wed, 26 Sep 2018 22:38:29 +1200 Subject: [PATCH 23/29] Unit test case for 2 items in cache and that being all of the transactions. --- .../services/wallet-history.service.spec.js | 85 ++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/src/js/services/wallet-history.service.spec.js b/src/js/services/wallet-history.service.spec.js index 113ab34b3..a6d9e12a7 100644 --- a/src/js/services/wallet-history.service.spec.js +++ b/src/js/services/wallet-history.service.spec.js @@ -100,10 +100,49 @@ fdescribe('walletHistoryService', function(){ expect(returnedHistory.length).toBe(50); }); + it('updateLocalTxHistoryByPage, 2 in cache, getEarlier, keep cache, same 2 returned, so all transactions received.', function(){ + var fetchLimit; + var fetchSkip; + var returnedAllFetched; + var returnedErr; + var returnedHistory; + var walletIdForStorageGet; + walletMock.id = 'wallet456'; + + storageServiceMock.getTxHistory.and.callFake(function(walletId, cb){ + walletIdForStorageGet = walletId; + + cb(null, JSON.stringify(history.slice(0, 2))); + }); + + walletMock.getTxHistory.and.callFake(function(opts, cb){ + fetchSkip = opts.skip; + fetchLimit = opts.limit; + + cb(null, history.slice(0, 2)); + }); + + walletHistoryService.updateLocalTxHistoryByPage(walletMock, false, false, function(err, txs, allFetched){ + returnedErr = err; + returnedHistory = txs; + returnedAllFetched = allFetched; + }); + + expect(walletIdForStorageGet).toBe('wallet456'); + expect(fetchSkip).toBe(0); + expect(fetchLimit).toBe(50); + expect(returnedErr).toBeNull(); + expect(returnedHistory.length).toBe(2); + expect(returnedAllFetched).toBe(true); + expect(storageServiceMock.setTxHistory.calls.any()).toBe(false); + }); + it('updateLocalTxHistoryByPage, getEarlier, keep cache, sufficient overlap so saved.', function(){ var fetchLimit; var fetchSkip; + var returnedErr; var returnedHistory; + var returnedAllFetched; var savedTxs; var walletIdForStorageGet; var walletIdForStorageSet; @@ -128,9 +167,10 @@ fdescribe('walletHistoryService', function(){ cb(null); }); - walletHistoryService.updateLocalTxHistoryByPage(walletMock, false, false, function(err, txs){ + walletHistoryService.updateLocalTxHistoryByPage(walletMock, false, false, function(err, txs, allFetched){ returnedErr = err; returnedHistory = txs; + returnedAllFetched = allFetched; }); expect(walletIdForStorageGet).toBe('wallet67890'); @@ -140,6 +180,48 @@ fdescribe('walletHistoryService', function(){ expect(savedTxs.length).toBe(80); expect(returnedErr).toBeNull(); expect(returnedHistory.length).toBe(80); + expect(returnedAllFetched).toBe(false); + }); + + it('updateLocalTxHistoryByPage, cache empty, getLatest, do not flush cache, one new so saved.', function(){ + var fetchLimit; + var fetchSkip; + var returnedHistory; + var savedTxs; + var walletIdForStorageGet; + var walletIdForStorageSet; + walletMock.id = 'wallet789'; + + storageServiceMock.getTxHistory.and.callFake(function(walletId, cb){ + walletIdForStorageGet = walletId; + cb(null, "[]"); + }); + + walletMock.getTxHistory.and.callFake(function(opts, cb){ + fetchSkip = opts.skip; + fetchLimit = opts.limit; + + cb(null, history.slice(0, 1)); + }); + + storageServiceMock.setTxHistory.and.callFake(function(txs, walletId, cb){ + savedTxs = txs; + walletIdForStorageSet = walletId; + cb(null); + }); + + walletHistoryService.updateLocalTxHistoryByPage(walletMock, true, false, function(err, txs){ + returnedErr = err; + returnedHistory = txs; + }); + + expect(walletIdForStorageGet).toBe('wallet789'); + expect(fetchSkip).toBe(0); + expect(fetchLimit).toBe(50); + expect(savedTxs.length).toBe(1); + expect(walletIdForStorageSet).toBe('wallet789'); + expect(returnedErr).toBeNull(); + expect(returnedHistory.length).toBe(1); }); it('updateLocalTxHistoryByPage, cache empty, getLatest, do not flush cache, some new so saved.', function(){ @@ -178,6 +260,7 @@ fdescribe('walletHistoryService', function(){ expect(fetchSkip).toBe(0); expect(fetchLimit).toBe(50); expect(savedTxs.length).toBe(10); + expect(walletIdForStorageSet).toBe('wallet789'); expect(returnedErr).toBeNull(); expect(returnedHistory.length).toBe(10); }); From 898b7d03fe938599c4f6e6a99e6d2b1bdfaef708 Mon Sep 17 00:00:00 2001 From: A R Hansen Date: Mon, 8 Oct 2018 01:55:55 +0200 Subject: [PATCH 24/29] 0 fee transaction feature added. --- .vscode/launch.json | 14 ++ src/js/controllers/confirm.js | 3 +- src/js/controllers/review.controller.js | 32 +++- src/js/services/feeService.js | 4 +- www/css/main.css | 209 +++++++++++++++--------- 5 files changed, 175 insertions(+), 87 deletions(-) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..29f920f4f --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "program": "${workspaceFolder}/www/index.html" + } + ] +} \ No newline at end of file diff --git a/src/js/controllers/confirm.js b/src/js/controllers/confirm.js index 76950df73..ae4bc7153 100644 --- a/src/js/controllers/confirm.js +++ b/src/js/controllers/confirm.js @@ -517,7 +517,8 @@ angular.module('copayApp.controllers').controller('confirmController', function( if (!lodash.isEmpty(warningMsg)) msg += '\n' + warningMsg; - popupService.showAlert(null, msg, function() {}); + popupService.showAlert(null, msg, function() {}); + }; $scope.onWalletSelect = function(wallet) { diff --git a/src/js/controllers/review.controller.js b/src/js/controllers/review.controller.js index 2311b2cb6..ae30382fb 100644 --- a/src/js/controllers/review.controller.js +++ b/src/js/controllers/review.controller.js @@ -718,14 +718,23 @@ angular if (tx.paypro) startExpirationTimer(tx.paypro.expires); - updateTx(tx, vm.originWallet, { - dryRun: true - }, function(err) { - $timeout(function() { - $scope.$apply(); - }, 10); + popupService.showConfirm(null, 'Do you want this transaction to be sent without a fee?', 'Yes', 'No', function(ok) { + if(ok){ + tx.feeRate = 0; + // tx.feeLevel = 'free'; + usingCustomFee = true; + } + updateTx(tx, vm.originWallet, { + dryRun: true + }, function(err) { + $timeout(function() { + $scope.$apply(); + }, 10); + + }); + }); + - }); // setWalletSelector(tx.coin, tx.network, tx.amount, function(err) { // if (err) { @@ -778,6 +787,7 @@ angular msg += '\n' + warningMsg; popupService.showAlert(null, msg, function() {}); + //popupService.showConfirm(null, msg, null, null, function() {}); }; function statusChangeHandler(processName, showName, isOn) { @@ -855,7 +865,11 @@ angular } var msg; - if (usingCustomFee) { + // if (tx.feeLevel == 'free'){ + // tx.feeRate = 0; + // } + // else + if (usingCustomFee) { msg = gettextCatalog.getString('Custom'); tx.feeLevelName = msg; } else if (usingMerchantFee) { @@ -865,7 +879,9 @@ angular } else { tx.feeLevelName = feeService.feeOpts[tx.feeLevel]; tx.feeRate = feeRate; + } + getSendMaxInfo(lodash.clone(tx), wallet, function(err, sendMaxInfo) { if (err) { diff --git a/src/js/services/feeService.js b/src/js/services/feeService.js index bba972b81..edb1800a4 100644 --- a/src/js/services/feeService.js +++ b/src/js/services/feeService.js @@ -12,6 +12,7 @@ angular.module('copayApp.services').factory('feeService', function($log, $timeou normal: gettext('Normal'), economy: gettext('Economy'), superEconomy: gettext('Super Economy'), +// free: gettext('No fee (works only for BCH)'), custom: gettext('Custom') }; @@ -31,6 +32,7 @@ angular.module('copayApp.services').factory('feeService', function($log, $timeou root.getFeeRate = function(coin, network, feeLevel, cb) { if (feeLevel == 'custom') return cb(); + if (feeLevel == 'free') return cb(null, 0); network = network || 'livenet'; @@ -48,9 +50,9 @@ angular.module('copayApp.services').factory('feeService', function($log, $timeou }) }); } - var feeRate = feeLevelRate.feePerKb; + if (!fromCache) $log.debug('Dynamic fee: ' + feeLevel + '/' + network + ' ' + (feeLevelRate.feePerKb / 1000).toFixed() + ' SAT/B'); return cb(null, feeRate); diff --git a/www/css/main.css b/www/css/main.css index 8602ba35d..83c50fe17 100644 --- a/www/css/main.css +++ b/www/css/main.css @@ -10083,7 +10083,7 @@ ion-view.deflash-blue:before, ion-view#view-amount:before, ion-view#view-confirm .onboarding .button.button-white.button-standard, .onboarding .button.button-green.button-standard, .onboarding .button.button-assertive.button-standard, #shapeshift .button-shapeshift { - width: 85%; + width: 90%; max-width: 300px; margin-left: auto; margin-right: auto; @@ -10195,6 +10195,7 @@ ion-view.deflash-blue:before, ion-view#view-amount:before, ion-view#view-confirm .button { border-radius: 6px; } .button.button-full { + border-radius: 0; display: block; } .button-green { border-color: #FFF; @@ -10263,8 +10264,8 @@ ion-view.deflash-blue:before, ion-view#view-amount:before, ion-view#view-confirm color: #FFFFFF; text-decoration: none; } .button-white-outline.active, .button-white-outline.activated { - border-color: #FFF; - background-color: #FAFAFA; } + border-color: #FFFFFF; + background-color: #FFFFFF; } .button-white-outline.button-outline { border-color: #FFFFFF; background: transparent; @@ -10632,7 +10633,7 @@ qrcode { #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long .primary-amount-display { font-size: 2em; } } #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .primary-amount-display { - font-size: 0.9em; } + font-size: 1.2em; } @media (min-width: 375px) { #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .primary-amount-display { font-size: 1.3em; } } @@ -10659,7 +10660,8 @@ qrcode { line-height: 1em; } #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .primary-amount-display { margin-right: 5px; - word-break: break-all; } + word-break: break-all; + width: 100%; } #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .alternative-amount { color: #6F6F70; } #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .switch-currencies { @@ -10680,30 +10682,33 @@ qrcode { justify-content: space-between; margin: 0 14px; } #view-amount .scroll-content .send-amount-extras .available-funds { - color: #6F6F70; } + color: #6F6F70; + text-align: left; } + #view-amount .scroll-content .send-amount-extras .change-currency { + text-align: right; } #view-amount .scroll-content .send-amount-extras .warning { color: #b7664d; } - #view-amount .scroll-content .send-amount-extras .extra, - #view-amount .scroll-content .send-amount-extras button.extra { - /*display: flex;*/ - flex: 0 1 auto; } - #view-amount .scroll-content .send-amount-extras button.extra { - background: none; - border: none; - color: #000; - font-family: 'ProximaNova'; - font-size: 14px; - line-height: normal; - min-height: auto; - min-width: auto; - padding: 0; } - #view-amount .scroll-content .send-amount-extras .button .icon:before { - font-size: 14px; + #view-amount .scroll-content .send-amount-extras .extra { + flex: 1; line-height: normal; } - #view-amount .scroll-content .send-amount-extras .button span { - display: flex; - align-items: center; - justify-content: center; } + #view-amount .scroll-content .send-amount-extras .extra .button { + background: none; + border: none; + border-radius: 0; + color: #000; + font-family: 'ProximaNova'; + font-size: 14px; + line-height: normal; + min-height: auto; + min-width: auto; + padding: 0; } + #view-amount .scroll-content .send-amount-extras .extra .button .icon:before { + font-size: 14px; + line-height: normal; } + #view-amount .scroll-content .send-amount-extras .extra .button span { + display: flex; + align-items: center; + justify-content: center; } #view-amount .scroll-content .button.no-margin { margin: 0; } #view-amount .scroll-content .notification-warning { @@ -10939,14 +10944,14 @@ qrcode { #tab-home .buttons .button { border: 2px solid; border-radius: 47px; - padding: 0 15px 0 15px; + padding: 8px 2px 8px 2px; text-align: center; width: 100%; max-width: 300px; font-size: 19px; font-weight: bolder; - min-height: auto; - line-height: 36px; } + min-height: 0; + line-height: 19px; } #tab-home .wallet-coin-logo { vertical-align: middle; @@ -11013,6 +11018,10 @@ qrcode { #tab-home .release .title { font-weight: 700; color: #444; } + #tab-home .release .release-notes { + white-space: pre; + white-space: pre-line; + text-align: left; } #tab-home .release .button { width: 100%; border: none; } @@ -11025,6 +11034,14 @@ qrcode { #tab-home .badge { top: 11px; } +.popup-update .popup-buttons { + display: block; } + +.popup-update .popup-buttons .button { + display: block; + min-width: 100% !important; + margin-top: 4px; } + #tab-receive .button-share { color: #fff; box-shadow: none; @@ -11101,6 +11118,8 @@ qrcode { #tab-receive .payment-received-container { margin: 0 20px; } + #tab-receive .payment-received-container svg { + max-height: 400px; } #tab-receive .payment-received-container .payment-received-amount { font-size: 1.8em; display: block; @@ -11207,7 +11226,7 @@ qrcode { margin: auto; margin-top: 18px; } #tab-send .send-wrapper .buttons .button { - height: 60px; + min-height: 65px; line-height: 16px; margin-right: 0px; width: 95%; @@ -11284,7 +11303,9 @@ qrcode { margin-top: 18px; } #tab-send .sendTip .buttons .button { font-weight: bold; - font-size: 19px; } + font-size: 19px; + line-height: 26px; + padding: 8px 6px; } #tab-send .sendTip .button-first-contact img { height: 19px; width: 19px; @@ -11920,6 +11941,13 @@ qrcode { #walletDetails .bp-content.status-bar { margin-top: 20px; margin-top: env(safe-area-inset-top); } + #walletDetails .bp-content.collapse ion-content { + margin-top: 40px; } + #walletDetails .bp-content.collapse .amount__scale, #walletDetails .bp-content.collapse .amount__error { + -webkit-transform: scale3d(0.5, 0.5, 0.5) translateY(0px); + transform: scale3d(0.5, 0.5, 0.5) translateY(0px); } + #walletDetails .bp-content.collapse .amount-alternative, #walletDetails .bp-content.collapse .send-receive-buttons, #walletDetails .bp-content.collapse .wallet-details-wallet-info { + opacity: 0; } #walletDetails .bar-header { border: 0; background: #eeb640; } @@ -11932,9 +11960,12 @@ qrcode { #walletDetails ion-content { padding-top: 0; top: 0; + transition: all 0.25s ease-in-out; + margin-top: 185px; margin-bottom: 16px; } - #walletDetails ion-content.collapsible { - margin-top: 230px; } + @media only screen and (max-height: 500px) { + #walletDetails ion-content { + margin-top: 165px; } } #walletDetails ion-content .scroll { background: #f8f8f9; min-height: 300px; } @@ -11965,38 +11996,45 @@ qrcode { justify-content: space-evenly; width: 100%; position: absolute; - bottom: 20px; } + bottom: 20px; + transition: all 0.25s ease-in-out; } #walletDetails .amount-wrapper .send-receive-buttons > .col { padding: 5px 10px; margin-bottom: 0; } #walletDetails .amount-wrapper .send-receive-buttons .button { border: 2px solid; border-radius: 47px; - padding: 0 15px 0 15px; + padding: 6px 2px 6px 2px; text-align: center; width: 100%; max-width: 300px; font-size: 19px; font-weight: bolder; - min-height: auto; - line-height: 36px; } + min-height: 0; + line-height: 19px; } #walletDetails .amount { - width: 100%; - text-align: center; - color: #fff; - height: 230px; - padding-top: 40px; - display: block; align-items: center; - justify-content: center; } + color: #fff; + display: block; + height: 230px; + justify-content: center; + padding-top: 40px; + text-align: center; + transition: all 0.25s ease-in-out; + width: 100%; } + @media only screen and (max-height: 500px) { + #walletDetails .amount { + height: 210px; } } #walletDetails .amount__balance { -webkit-transform: scale3d(1, 1, 1) translateY(45px); - transform: scale3d(1, 1, 1) translateY(45px); } + transform: scale3d(1, 1, 1) translateY(45px); + transition: all 0.25s ease-in-out; } #walletDetails .amount__updating { z-index: 999; margin-top: -2.1rem; } #walletDetails .amount-alternative { - line-height: 36px; } + line-height: 36px; + transition: all 0.25s ease-in-out; } #walletDetails .amount__button-balance { background-color: transparent; border: 1px solid rgba(255, 255, 255, 0.25); @@ -12006,7 +12044,8 @@ qrcode { vertical-align: middle; } #walletDetails .amount__error { font-size: 14px; - padding: 35px 20px; } + padding: 35px 20px; + opacity: 1; } #walletDetails .no-alternative { padding-top: 45px; } #walletDetails .item.item-footer { @@ -12071,7 +12110,9 @@ a.item { font-size: 0.9em; } .loading-wallet svg { - margin-top: 0; } + margin-top: 0; + width: 16px; + height: 16px; } #advanced-settings .list .item:before { display: block; @@ -12125,7 +12166,9 @@ a.item { margin-top: 18px; } #shapeshift .empty-case .buttons .button { font-weight: bold; - font-size: 19px; } + font-size: 19px; + line-height: 26px; + padding: 8px 6px; } #shapeshift .empty-case .button-first-contact img { height: 19px; width: 19px; @@ -13812,6 +13855,7 @@ click-to-accept { height: 92px; width: 100%; } click-to-accept .click-to-accept__button.button.button-primary.button-standard { + border-radius: 0; height: 100%; max-width: 9999px; width: 100%; } @@ -13918,6 +13962,8 @@ slide-to-accept { height: 92px; width: 100%; background: #494949; } + slide-to-accept .slide .button { + border-radius: 0; } slide-to-accept .slide__listener { height: 100%; width: 100%; @@ -15349,20 +15395,25 @@ log-options #check-bar .checkbox-icon { #cash-scan a { cursor: pointer; } -#view-review { - background-color: #494949; } - #view-review slide-to-accept, #view-review slide-to-accept-success { - margin-bottom: constant(safe-area-inset-bottom); - /* iOS 11.0 */ - margin-bottom: env(safe-area-inset-bottom); - /* iOS 11.2 */ } - #view-review .fee-summary { - position: absolute; - bottom: 92px; } - #view-review .shapeshift-banner, #view-review .bitpay-banner, #view-review .egifter-banner { - box-shadow: none; } - #view-review .warning { - color: #b7664d; } +#view-review slide-to-accept, #view-review slide-to-accept-success { + margin-bottom: constant(safe-area-inset-bottom); + /* iOS 11.0 */ + margin-bottom: env(safe-area-inset-bottom); + /* iOS 11.2 */ } + +#view-review .fee-summary { + bottom: 92px; + bottom: calc(92px + constant(safe-area-inset-bottom)); + /* iOS 11.0 */ + bottom: calc(92px + env(safe-area-inset-bottom)); + /* iOS 11.2 */ + position: absolute; } + +#view-review .shapeshift-banner, #view-review .bitpay-banner, #view-review .egifter-banner { + box-shadow: none; } + +#view-review .warning { + color: #b7664d; } .gravatar { border-radius: 3px; @@ -15395,6 +15446,7 @@ log-options #check-bar .checkbox-icon { left: 13px; top: 50%; padding: 0; + -webkit-transform: translate(0, -50%); transform: translate(0, -50%); } .item .item-content.item-content-compact { @@ -15463,8 +15515,8 @@ ion-content.padded-bottom-cta-with-summary { overflow: hidden; text-overflow: ellipsis; } .address-frame.expanded { - white-space: pre-wrap; - word-break: break-all; } + white-space: normal; + text-overflow: clip; } .address-frame .prefix { color: #000000; } .address-frame .mid { @@ -15507,13 +15559,13 @@ ion-content.padded-bottom-cta-with-summary { transform: scale(1, 1); } .fee-summary { - position: relative; + background-color: #F2F2F2; + box-sizing: border-box; display: flex; flex-direction: column; - width: 100%; padding: 5px 12px 15px; - box-sizing: border-box; - background-color: #F2F2F2; } + position: relative; + width: 100%; } .fee-summary:before { content: ''; position: absolute; @@ -15523,16 +15575,16 @@ ion-content.padded-bottom-cta-with-summary { height: 15px; background: linear-gradient(to bottom, rgba(242, 242, 242, 0) 0%, #f2f2f2 100%); } .fee-summary .amount { - display: flex; - flex-direction: row; - justify-content: space-between; width: 100%; } - .fee-summary .amount .fee-fiat.positive { - color: #70955F; } - .fee-summary .amount .fee-fiat.negative { - color: #C24633; } + .fee-summary .amount .fee-fiat { + display: inline; } + .fee-summary .amount .fee-fiat.positive { + color: #70955F; } + .fee-summary .amount .fee-fiat.negative { + color: #C24633; } .fee-summary .amount .fee-crypto { - color: #A7A7A7; } + color: #A7A7A7; + float: right; } .formatted-amount { display: inline-block; } @@ -15557,6 +15609,9 @@ ion-content.padded-bottom-cta-with-summary { margin-left: 5px; text-transform: uppercase; } +.wallet-balance-directive { + display: inline-block; } + /* This is for rules that don't yet have a home. * Our goal is to delete this file. Search the regex: /class=".*CLASS.*?"/ */ From d47393f16025571502a4bc418541799f1206e445 Mon Sep 17 00:00:00 2001 From: A R Hansen Date: Mon, 8 Oct 2018 02:00:36 +0200 Subject: [PATCH 25/29] .. From 4e524a7500abda0067c23132397870a771d22b64 Mon Sep 17 00:00:00 2001 From: A R Hansen Date: Mon, 8 Oct 2018 02:16:43 +0200 Subject: [PATCH 26/29] Not needed. --- src/js/services/feeService.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/services/feeService.js b/src/js/services/feeService.js index edb1800a4..5189527b2 100644 --- a/src/js/services/feeService.js +++ b/src/js/services/feeService.js @@ -32,7 +32,7 @@ angular.module('copayApp.services').factory('feeService', function($log, $timeou root.getFeeRate = function(coin, network, feeLevel, cb) { if (feeLevel == 'custom') return cb(); - if (feeLevel == 'free') return cb(null, 0); +// if (feeLevel == 'free') return cb(null, 0); network = network || 'livenet'; From f1d2b00b2baf6df56a293e2b6b452bc2f7ae93de Mon Sep 17 00:00:00 2001 From: A R Hansen Date: Fri, 12 Oct 2018 11:53:16 +0200 Subject: [PATCH 27/29] set up my own bitcore server and changed the url. for some reason Bitcoin.com's server won't accept 0 fee txs. --- src/js/services/configService.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/services/configService.js b/src/js/services/configService.js index 72cc4825f..6f2c0ec67 100644 --- a/src/js/services/configService.js +++ b/src/js/services/configService.js @@ -18,7 +18,7 @@ angular.module('copayApp.services').factory('configService', function(storageSer }, bwscash: { - url: 'https://bwscash.bitcoin.com/bws/api' + url: 'https://bws.freepages.dk/bws/api' }, download: { From 70f520ea43b99365d65083960720309a93675313 Mon Sep 17 00:00:00 2001 From: A R Hansen Date: Fri, 12 Oct 2018 12:46:09 +0200 Subject: [PATCH 28/29] adding instructions --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.md b/README.md index 75ced5808..9224c2b34 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,24 @@ +This is a fork of the Bitcoin.com wallet to add additional features. +Features included: + + - Zero fee transactions (only works for Bitcoin Cash). You will be asked for, if you want to send a transaction as zero fee on the confirmation page. + + ## Zero fee transactions: + Because most network nodes on the Bitcoin Cash network don't relay zero fee txs, you will experience some strange issues, but don't worry: for me personally the Bitcoin.com pool has included all my zero fee transactions, but please beware that the receiver probably won't see your tx before it has been confirmed and please do also keep in mind, that the transactions coming after it won't confirm or be seen before the zero fee one has been confirmed. + + If you do already have a Bitcoin.com wallet, you need to create a new one to use this feature or change the wallet URL to: https://bws.freepages.dk/bws/api + + ## Disclaimer + + Please beware this is my personal experimental project. You are more than welcome to play with it, but I don't take any responsibility of loss of funds due to errors in the code, so please make sure you made a backup before running this software. + + ## Builds + + You can build the software yourself using the instructions below or use prebuilt binaries which can be found here (currently Windows and Linux only): https://ipfs.io/ipfs/QmR1DaS3QsDS48SzAWKUWFfmtMfJc4tgMtkSk3JFmuzewe + + + + The Bitcoin.com wallet is a fork of the Copay Wallet (https://github.com/bitpay/copay). The Bitcoin.com wallet is a secure bitcoin wallet platform for both desktop and mobile devices. It uses [Bitcore Wallet Service](https://github.com/Bitcoin-com/bitcore-wallet-service) (our fork of the [Bitpay Bitcore Wallet Service](https://github.com/bitpay/bitcore-wallet-service)) (BWS) for peer synchronization and network interfacing. From 06f1f4df91b95133c2d8a9cf9c43a3285b84b59b Mon Sep 17 00:00:00 2001 From: A R Hansen Date: Fri, 12 Oct 2018 12:48:15 +0200 Subject: [PATCH 29/29] - ll - --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9224c2b34..ae2788217 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Features included: You can build the software yourself using the instructions below or use prebuilt binaries which can be found here (currently Windows and Linux only): https://ipfs.io/ipfs/QmR1DaS3QsDS48SzAWKUWFfmtMfJc4tgMtkSk3JFmuzewe - + ## The Bitcoin.com wallet is a fork of the Copay Wallet (https://github.com/bitpay/copay).