diff --git a/Gruntfile.js b/Gruntfile.js
index 7968f2510..4e06c69ab 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -57,7 +57,7 @@ module.exports = function(grunt) {
command: 'node ./util/buildExternalServices.js'
},
get_nwjs_for_pkg: {
- command: 'if [ ! -d ./cache/0.19.5-pkg/osx64/nwjs.app ]; then cd ./cache; curl https://dl.nwjs.io/v0.19.5-mas-beta/nwjs-mas-v0.19.5-osx-x64.zip --output nwjs.zip; unzip nwjs.zip; mkdir -p ./0.19.5-pkg/osx64; cp -R ./nwjs-mas-v0.19.5-osx-x64/nwjs.app ./0.19.5-pkg/osx64/; fi'
+ command: 'if [ ! -d ./cache/0.19.4/osx64/nwjs.app ]; then mkdir -p ./cache/0.19.4/osx64; curl https://dl.nwjs.io/v0.19.5-mas-beta/nwjs-mas-v0.19.5-osx-x64.zip --output ./cache/nwjs.zip; unzip ./cache/nwjs.zip -d ./cache; cp -R ./cache/nwjs-mas-v0.19.5-osx-x64/nwjs.app ./cache/0.19.4/osx64/; fi'
},
log_android: {
command: 'adb logcat | grep chromium',
@@ -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/bitcoincom/appConfig.json b/app-template/bitcoincom/appConfig.json
index 2eab6232d..d5a127f74 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.3",
- "fullVersion": "5.1-rc2",
- "androidVersion": "501003",
+ "version": "5.1.6",
+ "fullVersion": "5.1-rc5",
+ "androidVersion": "501600",
"_extraCSS": "",
"_enabledExtensions": {
"coinbase": false,
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 {
diff --git a/src/js/controllers/amount.controller.js b/src/js/controllers/amount.controller.js
index 07f31bb3e..219245e54 100644
--- a/src/js/controllers/amount.controller.js
+++ b/src/js/controllers/amount.controller.js
@@ -8,31 +8,7 @@ angular
function amountController(configService, $filter, gettextCatalog, $ionicHistory, $ionicModal, $ionicScrollDelegate, lodash, $log, nodeWebkitService, rateService, $scope, $state, $timeout, sendFlowService, shapeshiftService, txFormatService, platformInfo, ongoingProcess, popupService, profileService, walletService, $window) {
var vm = this;
-
- // Variables
- vm.allowSend = false;
- vm.altCurrencyList = [];
- vm.alternativeAmount = '';
- vm.alternativeUnit = '';
- vm.amount = '0';
- vm.availableFunds = '';
- vm.canSendAllAvailableFunds = true;
- vm.errorMessage = '';
- // Use insufficient for logic, as when the amount is invalid, funds being
- // either sufficent or insufficient doesn't make sense.
- vm.fundsAreInsufficient = false;
- vm.globalResult = '';
- vm.isRequestingSpecificAmount = false;
- vm.listComplete = false;
- vm.lastUsedPopularList = [];
- vm.maxAmount = 0;
- vm.minAmount = 0;
- vm.sendableFunds = '';
- vm.showSendMaxButton = false;
- vm.showSendLimitMaxButton = false;
- vm.thirdParty = false;
- vm.unit = '';
-
+
// Functions
vm.changeUnit = changeUnit;
vm.close = close;
@@ -46,7 +22,6 @@ function amountController(configService, $filter, gettextCatalog, $ionicHistory,
vm.removeDigit = removeDigit;
vm.save = save;
vm.sendMax = sendMax;
-
$scope.$on('$ionicView.beforeEnter', onBeforeEnter);
$scope.$on('$ionicView.leave', onLeave);
@@ -79,8 +54,55 @@ function amountController(configService, $filter, gettextCatalog, $ionicHistory,
satoshis: null
};
- function onLeave() {
- angular.element($window).off('keydown');
+ function initVariables() {
+ // Private variables
+ altCurrencyModal = null;
+ altUnitIndex = 0;
+ availableUnits = [];
+ canSendMax = true;
+ fiatCode;
+ isNW = platformInfo.isNW;
+ isAndroid = platformInfo.isAndroid;
+ isIos = platformInfo.isIOS;
+ lastUsedAltCurrencyList = [];
+ passthroughParams = {};
+ satToUnit;
+ transactionSendableAmount = {
+ crypto: '',
+ satoshis: null
+ };
+ unitDecimals;
+ unitIndex = 0;
+ unitToSatoshi;
+ useSendMax = false;
+ walletSpendableAmount = {
+ crypto: '',
+ satoshis: null
+ };
+
+ // Public variables
+ vm.allowSend = false;
+ vm.altCurrencyList = [];
+ vm.alternativeAmount = '';
+ vm.alternativeUnit = '';
+ vm.amount = '0';
+ vm.availableFunds = '';
+ vm.canSendAllAvailableFunds = true;
+ vm.errorMessage = '';
+ // Use insufficient for logic, as when the amount is invalid, funds being
+ // either sufficent or insufficient doesn't make sense.
+ vm.fundsAreInsufficient = false;
+ vm.globalResult = '';
+ vm.isRequestingSpecificAmount = false;
+ vm.listComplete = false;
+ vm.lastUsedPopularList = [];
+ vm.maxAmount = 0;
+ vm.minAmount = 0;
+ vm.sendableFunds = '';
+ vm.showSendMaxButton = false;
+ vm.showSendLimitMaxButton = false;
+ vm.thirdParty = null;
+ vm.unit = '';
}
function onBeforeEnter(event, data) {
@@ -88,11 +110,19 @@ function amountController(configService, $filter, gettextCatalog, $ionicHistory,
sendFlowService.state.pop();
}
+
+ // Init before entering on this screen
+ initVariables();
initCurrencies();
+ // Then start
passthroughParams = sendFlowService.state.getClone();
console.log('amount onBeforeEnter after back sendflow ', passthroughParams);
+
+ // Init thirdParty, should be done for all the variable
+ vm.thirdParty = null;
+
vm.fromWalletId = passthroughParams.fromWalletId;
vm.toWalletId = passthroughParams.toWalletId;
vm.minAmount = parseFloat(passthroughParams.minAmount);
@@ -218,6 +248,10 @@ function amountController(configService, $filter, gettextCatalog, $ionicHistory,
}
}
+ function onLeave() {
+ angular.element($window).off('keydown');
+ }
+
function goBack() {
sendFlowService.router.goBack();
}
diff --git a/src/js/controllers/review.controller.js b/src/js/controllers/review.controller.js
index 2311b2cb6..5352d609a 100644
--- a/src/js/controllers/review.controller.js
+++ b/src/js/controllers/review.controller.js
@@ -6,58 +6,9 @@ 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) {
+ function reviewController(addressbookService, externalLinkService, 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 = '';
@@ -76,23 +27,90 @@ angular
var unitFromSat = 0;
var FEE_TOO_HIGH_LIMIT_PERCENTAGE = 15;
+
+ // Functions
+ vm.goBack = goBack;
+ vm.onSuccessConfirm = onSuccessConfirm;
+ vm.onShareTransaction = onShareTransaction;
+
+ function initVariables() {
+ // Private variables
+ sendFlowData;
+ config = null;
+ coin = '';
+ countDown = null;
+ defaults = {};
+ usingCustomFee = false;
+ usingMerchantFee = false;
+ destinationWalletId = '';
+ lastTxId = '';
+ originWalletId = '';
+ priceDisplayIsFiat = true;
+ satoshis = null;
+ toAddress = '';
+ tx = {};
+ txPayproData = null;
+ unitFromSat = 0;
+
+ // Public variables
+ 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 = null;
+ vm.wallet = null;
+ vm.memoExpanded = false;
+ }
$scope.$on("$ionicView.beforeEnter", onBeforeEnter);
-
function onBeforeEnter(event, data) {
- console.log('review onBeforeEnter sendflow ', sendFlowService.state);
- // Reset from last time
- vm.memo = '';
+ $log.debug('reviewController onBeforeEnter sendflow ', sendFlowService.state);
+
+ // Init before entering on this screen
+ initVariables();
+ // Then start
defaults = configService.getDefaults();
sendFlowData = sendFlowService.state.getClone();
originWalletId = sendFlowData.fromWalletId;
- if (typeof sendFlowData.amount === 'string') {
- satoshis = parseInt(sendFlowData.amount, 10);
- } else {
- satoshis = sendFlowData.amount;
- }
+ satoshis = parseInt(sendFlowData.amount, 10);
toAddress = sendFlowData.toAddress;
destinationWalletId = sendFlowData.toWalletId;
@@ -105,11 +123,14 @@ angular
vm.thirdParty = sendFlowData.thirdParty;
switch (vm.thirdParty.id) {
case 'shapeshift':
- initShapeshift(function (err) {
+ initShapeshift(function onInitShapeshift(err) {
if (err) {
// Error stop here
ongoingProcess.set('connectingShapeshift', false);
- popupService.showAlert(gettextCatalog.getString('Shapeshift Error'), err.toString(), function () {
+ popupService.showConfirm(gettextCatalog.getString('Shapeshift Error'), err.toString(), gettextCatalog.getString('Open') + " Shapeshift", gettextCatalog.getString('Go Back'), function onConfirm(hasConfirm) {
+ if (hasConfirm) {
+ externalLinkService.open("https://shapeshift.io");
+ }
$ionicHistory.goBack();
});
} else {
@@ -135,7 +156,6 @@ angular
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();
@@ -152,18 +172,18 @@ angular
if (!tx || !vm.originWallet) return;
if (vm.paymentExpired) {
- popupService.showAlert(null, gettextCatalog.getString('This bitcoin payment request has expired.', function () {
+ popupService.showAlert(null, gettextCatalog.getString('This bitcoin payment request has expired.', function onAlert() {
$ionicHistory.goBack();
}));
vm.sendStatus = '';
- $timeout(function() {
+ $timeout(function onTimeout() {
$scope.$apply();
});
return;
}
ongoingProcess.set('creatingTx', true, statusChangeHandler);
- getTxp(lodash.clone(tx), vm.originWallet, false, function(err, txp) {
+ getTxp(lodash.clone(tx), vm.originWallet, false, function onGetTxp(err, txp) {
ongoingProcess.set('creatingTx', false, statusChangeHandler);
if (err) return;
@@ -180,12 +200,12 @@ angular
if (!vm.originWallet.canSign() && !vm.originWallet.isPrivKeyExternal()) {
$log.info('No signing proposal: No private key');
- return walletService.onlyPublish(vm.originWallet, txp, function(err) {
+ return walletService.onlyPublish(vm.originWallet, txp, function onOnlyPublish(err) {
if (err) setSendError(err);
}, statusChangeHandler);
}
- walletService.publishAndSign(vm.originWallet, txp, function(err, txp) {
+ walletService.publishAndSign(vm.originWallet, txp, function onPublishAndSign(err, txp) {
if (err) return setSendError(err);
if (config.confirmedTxsNotifications && config.confirmedTxsNotifications.enabled) {
txConfirmNotification.subscribe(vm.originWallet, {
@@ -199,7 +219,7 @@ angular
confirmTx(function(nok) {
if (nok) {
vm.sendStatus = '';
- $timeout(function() {
+ $timeout(function onTimeout() {
$scope.$apply();
});
return;
@@ -256,7 +276,6 @@ angular
};
function createVanityTransaction(data) {
- console.log('createVanityTransaction()');
var configFeeLevel = config.wallet.settings.feeLevel ? config.wallet.settings.feeLevel : 'normal';
// Grab stateParams
@@ -280,6 +299,9 @@ angular
txp: {},
};
+ if (vm.thirdParty && vm.thirdParty.id === "shapeshift") {
+ tx.toAddress = vm.thirdParty.toAddress;
+ }
if (data.stateParams.requiredFeeRate) {
vm.usingMerchantFee = true;
@@ -293,29 +315,35 @@ angular
var B = tx.coin === 'bch' ? bitcoreCash : bitcore;
var networkName;
try {
- if (vm.destination.kind === 'wallet') { // This is a wallet-to-wallet transfer
+ // Final destination is a wallet, but this transaction must go to an address for the first stage of the exchange.
+ if (sendFlowData.thirdParty && sendFlowData.thirdParty.id === 'shapeshift') {
+ networkName = (new B.Address(tx.toAddress)).network.name;
+ tx.network = networkName;
+ setupTx(tx);
+
+ } else 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);
+ if (err) {
+ $log.error('Error getting address for wallet.', err);
+ throw new Error(err.message);
+ }
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);
});
} 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);
+ $log.error('Error setting up tx', e);
var message = gettextCatalog.getString('Invalid address');
popupService.showAlert(null, message, function () {
$ionicHistory.nextViewOptions({
@@ -385,7 +413,7 @@ angular
}
txp.excludeUnconfirmedUtxos = !tx.spendUnconfirmed;
txp.dryRun = dryRun;
- walletService.createTx(wallet, txp, function(err, ctxp) {
+ walletService.createTx(wallet, txp, function onCreateTx(err, ctxp) {
if (err) {
setSendError(err);
return cb(err);
@@ -405,7 +433,7 @@ angular
var walletStatus = null;
if (wallet.status && wallet.status.isValid) {
walletStatus = wallet.status;
- } else if (wallet.cachedStatus.isValid) {
+ } else if (wallet.cachedStatus && wallet.cachedStatus.isValid) {
walletStatus = wallet.cachedStatus;
}
@@ -444,7 +472,7 @@ angular
}
// Check if the recipient is a contact
- addressbookService.get(originCoin + address, function(err, contact) {
+ addressbookService.get(originCoin + address, function onGetContact(err, contact) {
if (!err && contact) {
handleDestinationAsAddressOfContact(contact);
} else {
@@ -517,7 +545,6 @@ angular
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) {
@@ -535,9 +562,8 @@ angular
if (err) {
return cb(err);
} else {
- vm.destination.kind = 'shapeshift';
- vm.destination.address = toAddress;
- tx.toAddress = shapeshiftData.toAddress;
+ // Want it to appear like a wallet-to-wallet transfer, so don't set the main toAddress.
+ vm.thirdParty.toAddress = shapeshiftData.toAddress;
vm.memo = 'ShapeShift Order:\nhttps://www.shapeshift.io/#/status/' + shapeshiftData.orderId;
vm.memoExpanded = !!vm.memo;
ongoingProcess.set('connectingShapeshift', false);
@@ -572,7 +598,6 @@ angular
}, 1000);
function setExpirationTime() {
- console.log('setExpirationTime()');
var now = Math.floor(Date.now() / 1000);
if (now > expirationTime) {
@@ -690,7 +715,7 @@ angular
$timeout(function() {
$scope.$apply();
});
- popupService.showAlert(gettextCatalog.getString('Error at confirm'), bwcError.msg(msg), function () {
+ popupService.showAlert(gettextCatalog.getString('Error at confirm'), bwcError.msg(msg), function onAlert() {
$ionicHistory.goBack();
});
};
@@ -702,7 +727,7 @@ angular
tx.displayAddress = tx.toAddress;
}
- addressbookService.get(tx.coin+tx.toAddress, function(err, addr) { // Check if the recipient is a contact
+ addressbookService.get(tx.coin+tx.toAddress, function onGetContact(err, addr) { // Check if the recipient is a contact
if (!err && addr) {
tx.toName = addr.name;
tx.toEmail = addr.email;
@@ -721,23 +746,10 @@ angular
updateTx(tx, vm.originWallet, {
dryRun: true
}, function(err) {
- $timeout(function() {
+ $timeout(function onTimeout() {
$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) {
@@ -848,7 +860,7 @@ angular
// refresh();
var feeServiceLevel = usingMerchantFee && vm.originWallet.coin == 'btc' ? 'urgent' : tx.feeLevel;
- feeService.getFeeRate(vm.originWallet.coin, tx.network, feeServiceLevel, function(err, feeRate) {
+ feeService.getFeeRate(vm.originWallet.coin, tx.network, feeServiceLevel, function onGetFeeRate(err, feeRate) {
if (err) {
ongoingProcess.set('calculatingFee', false);
return cb(err);
@@ -867,7 +879,7 @@ angular
tx.feeRate = feeRate;
}
- getSendMaxInfo(lodash.clone(tx), wallet, function(err, sendMaxInfo) {
+ getSendMaxInfo(lodash.clone(tx), wallet, function onGetSendmaxInfo(err, sendMaxInfo) {
if (err) {
ongoingProcess.set('calculatingFee', false);
var msg = gettextCatalog.getString('Error getting SendMax information');
@@ -881,7 +893,7 @@ angular
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 () {
+ popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Not enough funds for fee'), function onAlert() {
$ionicHistory.goBack();
});
return cb('no_funds');
@@ -906,8 +918,7 @@ angular
return cb();
}
- console.log('calling getTxp() from getSendMaxInfo cb.');
- getTxp(lodash.clone(tx), wallet, opts.dryRun, function(err, txp) {
+ getTxp(lodash.clone(tx), wallet, opts.dryRun, function onGetTxp(err, txp) {
ongoingProcess.set('calculatingFee', false);
if (err) {
if (err.message == 'Insufficient funds') {
@@ -919,7 +930,7 @@ angular
}
txp.feeStr = txFormatService.formatAmountStr(wallet.coin, txp.fee);
- txFormatService.formatAlternativeStr(wallet.coin, txp.fee, function(v) {
+ txFormatService.formatAlternativeStr(wallet.coin, txp.fee, function onFormatAlternativeStr(v) {
// txp.alternativeFeeStr = v;
// if (txp.alternativeFeeStr.substring(0, 4) == '0.00')
// txp.alternativeFeeStr = '< ' + txp.alternativeFeeStr;
@@ -928,8 +939,6 @@ angular
if (v.substring(0, 1) === "<") {
vm.feeLessThanACent = true;
}
-
- console.log("fiat", vm.feeFiat);
});
@@ -939,14 +948,11 @@ angular
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 036727333..7a5cc2d87 100644
--- a/src/js/controllers/wallet-selector.controller.js
+++ b/src/js/controllers/wallet-selector.controller.js
@@ -12,6 +12,17 @@ angular
var unitDecimals = 0;
var unitsFromSatoshis = 0;
+ //
+ // Needs to migrate $scope to vm.
+ //
+ function initVariables() {
+ // Private variables
+ fromWalletId = '';
+ priceDisplayAsFiat = false;
+ unitDecimals = 0;
+ unitsFromSatoshis = 0;
+ }
+
$scope.$on("$ionicView.beforeEnter", onBeforeEnter);
$scope.$on("$ionicView.enter", onEnter);
@@ -20,6 +31,10 @@ angular
sendFlowService.state.pop();
}
+ // Init before entering on this screen
+ initVariables();
+ // Then start
+
$scope.params = sendFlowService.state.getClone();
console.log('walletSelector onBeforeEnter after back sendflow', $scope.params);
@@ -52,9 +67,6 @@ angular
$scope.specificAmount = $scope.specificAlternativeAmount = '';
$scope.isPaymentRequest = true;
}
- if ($scope.params.thirdParty) {
- $scope.thirdParty = $scope.params.thirdParty;
- }
};
function onEnter (event, data) {
@@ -62,7 +74,7 @@ angular
$scope.selectedPriceDisplay = config.wallet.settings.priceDisplay;
});
- if ($scope.thirdParty) {
+ if ($scope.params.thirdParty) {
// Third party services specific logic
handleThirdPartyIfShapeshift();
}
@@ -102,8 +114,8 @@ angular
}
function handleThirdPartyIfShapeshift() {
- console.log($scope.thirdParty, $scope.coin);
- if ($scope.thirdParty.id === 'shapeshift' && $scope.type === 'destination') { // Shapeshift wants to know the
+ console.log($scope.params.thirdParty, $scope.coin);
+ if ($scope.params.thirdParty.id === 'shapeshift' && $scope.type === 'destination') { // Shapeshift wants to know the
$scope.coin = profileService.getWallet(fromWalletId).coin;
if ($scope.coin === 'bch') {
$scope.coin = 'btc';
@@ -117,6 +129,8 @@ angular
var walletsAll = [];
var walletsSufficientFunds = [];
$scope.walletsInsufficientFunds = []; // For origin screen
+ $scope.walletsBtc = [];
+ $scope.walletsBch = [];
if ($scope.type === 'origin') {
$scope.headerTitle = gettextCatalog.getString('Choose a wallet to send from');
diff --git a/src/js/directives/incomingDataMenu.js b/src/js/directives/incomingDataMenu.js
index 78856e62f..e093cb5e3 100644
--- a/src/js/directives/incomingDataMenu.js
+++ b/src/js/directives/incomingDataMenu.js
@@ -16,8 +16,8 @@ angular.module('copayApp.directives')
scope.type = "url";
} else if (scope.data.parsed.publicAddress) {
scope.type = "bitcoinAddress";
- var prefix = scope.data.parsed.isTestnet ? 'bchtest:' : 'bitcoincash:';
- scope.data.toAddress = (prefix + scope.data.parsed.publicAddress.cashAddr) || scope.data.parsed.publicAddress.legacy || scope.data.parsed.publicAddress.bitpay;
+ var prefix = scope.data.coin === 'bch' ? (scope.data.parsed.isTestnet ? 'bchtest:' : 'bitcoincash:') : '';
+ scope.data.toAddress = (scope.data.parsed.publicAddress.cashAddr ? prefix + scope.data.parsed.publicAddress.cashAddr : false) || scope.data.parsed.publicAddress.legacy || scope.data.parsed.publicAddress.bitpay;
} else {
scope.type = "text";
}
diff --git a/src/js/services/bitcoin-uri.service.js b/src/js/services/bitcoin-uri.service.js
index 3da84f3da..669c14bf3 100644
--- a/src/js/services/bitcoin-uri.service.js
+++ b/src/js/services/bitcoin-uri.service.js
@@ -151,6 +151,7 @@
hasPassphrase: false,
type: 1,
},
+ isTestnet: false,
isValid: false,
label: '',
message: '',
@@ -170,7 +171,6 @@
"req-param0": '',
"req-param1": ''
},
- testnet: false,
url: '' // For BIP70
}
@@ -204,7 +204,13 @@
} else if (/^(?:bitcoincash)|(?:bitcoin-cash)$/.test(preColonLower)) {
parsed.coin = 'bch';
- parsed.test = false;
+ parsed.isTestnet = false;
+ addressAndParams = colonSplit[2].trim();
+ console.log('Is bch');
+
+ } else if (/^(?:bch)$/.test(preColonLower)) {
+ parsed.coin = 'bch';
+ parsed.isTestnet = false;
addressAndParams = colonSplit[2].trim();
console.log('Is bch');
diff --git a/src/js/services/bitcoin-uri.service.spec.js b/src/js/services/bitcoin-uri.service.spec.js
index 2ddbd0d2e..bf6c9ce9e 100644
--- a/src/js/services/bitcoin-uri.service.spec.js
+++ b/src/js/services/bitcoin-uri.service.spec.js
@@ -30,7 +30,7 @@ describe('bitcoinUriService', function() {
expect(parsed.isValid).toBe(true);
expect(parsed.coin).toBe('bch');
expect(parsed.publicAddress).toBeUndefined();
- expect(parsed.isTestnet).toBeUndefined();
+ expect(parsed.isTestnet).toBe(false);
expect(parsed.url).toBe('https://bitpay.com/i/SmHdie5dvBnG5kouZzEPzu');
});
@@ -171,6 +171,16 @@ describe('bitcoinUriService', function() {
expect(parsed.isTestnet).toBe(false);
});
+ it('legacy address with bch prefix', function() {
+
+ var parsed = bitcoinUriService.parse('bch:19yUdM2H7sADrabR6Afu9zTpmwqr6WYprX');
+
+ expect(parsed.isValid).toBe(true);
+ expect(parsed.coin).toBe('bch');
+ expect(parsed.publicAddress.legacy).toBe('19yUdM2H7sADrabR6Afu9zTpmwqr6WYprX');
+ expect(parsed.isTestnet).toBe(false);
+ });
+
it('cashAddr testnet with prefix', function() {
var parsed = bitcoinUriService.parse('bchtest:qpcz6pmurq9ctg5848trzz9zmuuygj4q5qam7ph3gt');
@@ -191,6 +201,16 @@ describe('bitcoinUriService', function() {
expect(parsed.isTestnet).toBe(false);
});
+ it('cashAddr with bch prefix', function() {
+
+ var parsed = bitcoinUriService.parse('bch:qpqzqtjqqc00nsxj0e3kevz65ujg4yt5z5w99jap5f');
+
+ expect(parsed.isValid).toBe(true);
+ expect(parsed.coin).toBe('bch');
+ expect(parsed.publicAddress.cashAddr).toBe('qpqzqtjqqc00nsxj0e3kevz65ujg4yt5z5w99jap5f');
+ expect(parsed.isTestnet).toBe(false);
+ });
+
it('cashAddr with dash', function() {
var parsed = bitcoinUriService.parse('bitcoin-cash:qpshfu3dk5s3e7zdcgdcun6xgxtra6uyxs7g580js0');
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';
}
diff --git a/src/js/services/servicesService.js b/src/js/services/servicesService.js
index ddd9db394..56d699e59 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',
- href: 'https://shapeshift.io/'
+ sref: 'tabs.shapeshift'
}];
root.register = function(serviceInfo) {
diff --git a/src/js/services/shapeShiftApiService.js b/src/js/services/shapeShiftApiService.js
index cc5fb0792..a90e587d4 100644
--- a/src/js/services/shapeShiftApiService.js
+++ b/src/js/services/shapeShiftApiService.js
@@ -24,7 +24,7 @@ var ShapeShift = (function() {
var parsedResponse = JP(xmlhttp.responseText);
cb.apply(null, [parsedResponse]);
} else {
- cb.apply(null, [new Error('Request Failed')])
+ cb.apply(null, [new Error('Request Failed')]);
}
}
};
diff --git a/src/js/services/shapeshift.service.js b/src/js/services/shapeshift.service.js
index 73410e478..8fdfe08b9 100644
--- a/src/js/services/shapeshift.service.js
+++ b/src/js/services/shapeshift.service.js
@@ -63,6 +63,7 @@ angular
} else if (amount > service.marketData.maxLimit) {
cb(new Error(gettextCatalog.getString('Amount is above the limit')));
} else {
+
// Init service data
service.withdrawalAddress = withdrawalAddress;
service.returnAddress = returnAddress;
@@ -72,7 +73,7 @@ angular
// Check the address
shapeshiftApiService
- .ValidateAddress(withdrawalAddress, coinOut)
+ .ValidateAddress(returnAddress, coinOut)
.then(function onSuccess(response) {
if (response && response.isvalid) {
// Prepare the transaction shapeshift side
diff --git a/src/js/services/wallet-history.service.js b/src/js/services/wallet-history.service.js
index 512a2d8b1..a9792c170 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);
@@ -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;
@@ -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) {
@@ -93,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);
@@ -147,7 +148,6 @@
* @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, []);
@@ -230,7 +230,6 @@
}
function updateLocalTxHistoryByPage(wallet, getLatest, flushCacheOnNew, cb) {
- console.log('txhistory updaetLocalTxHistoryByPage()');
if (flushCacheOnNew) {
fetchTxHistoryByPage(wallet, 0, function onFetchTxHistory(err, txs){
if (err) {