2015-03-06 07:00:10 -08:00
|
|
|
'use strict';
|
|
|
|
|
2016-02-18 12:16:07 -08:00
|
|
|
angular.module('copayApp.controllers').controller('walletHomeController', function($scope, $rootScope, $interval, $timeout, $filter, $modal, $log, notification, txStatus, isCordova, isMobile, profileService, lodash, configService, rateService, storageService, bitcore, isChromeApp, gettext, gettextCatalog, nodeWebkit, addressService, ledger, bwsError, confirmDialog, txFormatService, animationService, addressbookService, go, feeService, txService){
|
2015-03-06 07:00:10 -08:00
|
|
|
|
2015-04-23 08:27:43 -07:00
|
|
|
var self = this;
|
2016-01-11 11:46:50 -08:00
|
|
|
window.ignoreMobilePause = false;
|
2016-02-03 08:35:52 -08:00
|
|
|
$rootScope.shouldHideMenuBar = false;
|
2015-04-23 08:27:43 -07:00
|
|
|
$rootScope.wpInputFocused = false;
|
2015-10-07 12:17:19 -07:00
|
|
|
var config = configService.getSync();
|
|
|
|
var configWallet = config.wallet;
|
|
|
|
var walletSettings = configWallet.settings;
|
2016-02-18 12:16:07 -08:00
|
|
|
var ret = {};
|
|
|
|
|
|
|
|
// INIT. Global value
|
|
|
|
ret.unitToSatoshi = walletSettings.unitToSatoshi;
|
|
|
|
ret.satToUnit = 1 / ret.unitToSatoshi;
|
|
|
|
ret.unitName = walletSettings.unitName;
|
|
|
|
ret.alternativeIsoCode = walletSettings.alternativeIsoCode;
|
|
|
|
ret.alternativeName = walletSettings.alternativeName;
|
|
|
|
ret.alternativeAmount = 0;
|
|
|
|
ret.unitDecimals = walletSettings.unitDecimals;
|
|
|
|
ret.isCordova = isCordova;
|
|
|
|
ret.addresses = [];
|
|
|
|
ret.isMobile = isMobile.any();
|
|
|
|
ret.isWindowsPhoneApp = isMobile.Windows() && isCordova;
|
|
|
|
var vanillaScope = ret;
|
|
|
|
|
2015-04-23 08:27:43 -07:00
|
|
|
|
2016-02-18 11:54:13 -08:00
|
|
|
|
2015-04-23 08:27:43 -07:00
|
|
|
var disableScannerListener = $rootScope.$on('dataScanned', function(event, data) {
|
|
|
|
self.setForm(data);
|
2015-04-28 14:11:06 -07:00
|
|
|
$rootScope.$emit('Local/SetTab', 'send');
|
2015-07-15 12:15:05 -07:00
|
|
|
|
|
|
|
var form = $scope.sendForm;
|
2015-09-18 11:29:55 -07:00
|
|
|
if (form.address.$invalid && !self.blockUx) {
|
2015-07-15 12:15:05 -07:00
|
|
|
self.resetForm();
|
|
|
|
self.error = gettext('Could not recognize a valid Bitcoin QR Code');
|
|
|
|
}
|
2015-04-23 08:27:43 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
var disablePaymentUriListener = $rootScope.$on('paymentUri', function(event, uri) {
|
2015-12-09 11:55:56 -08:00
|
|
|
$rootScope.$emit('Local/SetTab', 'send');
|
2015-04-23 08:27:43 -07:00
|
|
|
$timeout(function() {
|
|
|
|
self.setForm(uri);
|
|
|
|
}, 100);
|
|
|
|
});
|
|
|
|
|
2016-02-18 12:16:07 -08:00
|
|
|
var disableAddrListener = $rootScope.$on('Local/AddressIsUsed', function() {
|
2015-06-27 09:22:56 -07:00
|
|
|
self.setAddress(true);
|
2015-04-23 08:27:43 -07:00
|
|
|
});
|
|
|
|
|
2015-04-23 22:42:10 -07:00
|
|
|
var disableFocusListener = $rootScope.$on('Local/NewFocusedWallet', function() {
|
2016-02-18 12:16:07 -08:00
|
|
|
self.addr = null;
|
2015-04-23 22:42:10 -07:00
|
|
|
self.resetForm();
|
2016-02-18 12:16:07 -08:00
|
|
|
|
|
|
|
$log.debug('Cleaning WalletHome Instance');
|
|
|
|
lodash.each(self, function(v, k) {
|
|
|
|
if (lodash.isFunction(v)) return;
|
|
|
|
if (vanillaScope[k]) return;
|
|
|
|
|
|
|
|
delete self[k];
|
|
|
|
});
|
2015-04-23 22:42:10 -07:00
|
|
|
});
|
2015-04-23 11:19:30 -07:00
|
|
|
|
2015-04-28 14:00:49 -07:00
|
|
|
var disableResumeListener = $rootScope.$on('Local/Resume', function() {
|
2015-04-28 15:26:22 -07:00
|
|
|
// This is needed then the apps go to sleep
|
2015-05-04 09:27:12 -07:00
|
|
|
self.bindTouchDown();
|
2015-04-28 14:00:49 -07:00
|
|
|
});
|
|
|
|
|
2015-04-23 22:42:10 -07:00
|
|
|
var disableTabListener = $rootScope.$on('Local/TabChanged', function(e, tab) {
|
2015-04-28 12:58:40 -07:00
|
|
|
// This will slow down switch, do not add things here!
|
2015-04-23 22:42:10 -07:00
|
|
|
switch (tab) {
|
2015-04-23 11:19:30 -07:00
|
|
|
case 'receive':
|
2015-04-28 12:58:40 -07:00
|
|
|
// just to be sure we have an address
|
|
|
|
self.setAddress();
|
2015-04-23 11:19:30 -07:00
|
|
|
break;
|
2015-04-28 12:58:40 -07:00
|
|
|
case 'send':
|
|
|
|
self.resetError();
|
2015-04-23 11:19:30 -07:00
|
|
|
};
|
|
|
|
});
|
|
|
|
|
2015-07-16 09:08:27 -07:00
|
|
|
var disableOngoingProcessListener = $rootScope.$on('Addon/OngoingProcess', function(e, name) {
|
|
|
|
self.setOngoingProcess(name);
|
|
|
|
});
|
|
|
|
|
2015-04-23 08:27:43 -07:00
|
|
|
$scope.$on('$destroy', function() {
|
|
|
|
disableAddrListener();
|
|
|
|
disableScannerListener();
|
|
|
|
disablePaymentUriListener();
|
2015-04-23 11:19:30 -07:00
|
|
|
disableTabListener();
|
2015-04-23 22:42:10 -07:00
|
|
|
disableFocusListener();
|
2015-04-28 14:00:49 -07:00
|
|
|
disableResumeListener();
|
2015-07-16 09:08:27 -07:00
|
|
|
disableOngoingProcessListener();
|
2016-02-03 08:35:52 -08:00
|
|
|
$rootScope.shouldHideMenuBar = false;
|
2015-04-23 08:27:43 -07:00
|
|
|
});
|
|
|
|
|
2016-02-18 11:54:13 -08:00
|
|
|
|
|
|
|
|
2015-12-01 12:16:39 -08:00
|
|
|
this.onQrCodeScanned = function(data) {
|
2015-12-08 07:14:44 -08:00
|
|
|
if (data) go.send();
|
2015-12-01 12:16:39 -08:00
|
|
|
$rootScope.$emit('dataScanned', data);
|
|
|
|
};
|
|
|
|
|
2015-04-23 08:27:43 -07:00
|
|
|
rateService.whenAvailable(function() {
|
|
|
|
self.isRateAvailable = true;
|
|
|
|
$rootScope.$digest();
|
|
|
|
});
|
|
|
|
|
2016-02-08 13:36:30 -08:00
|
|
|
var getClipboard = function(cb) {
|
|
|
|
if (!isCordova || isMobile.Windows()) return cb();
|
|
|
|
|
|
|
|
window.cordova.plugins.clipboard.paste(function(value) {
|
|
|
|
var fc = profileService.focusedClient;
|
|
|
|
var Address = bitcore.Address;
|
|
|
|
var networkName = fc.credentials.network;
|
|
|
|
if (Address.isValid(value, networkName) && !$scope.newAddress) {
|
|
|
|
return cb(value);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2015-07-29 08:37:51 -07:00
|
|
|
var accept_msg = gettextCatalog.getString('Accept');
|
|
|
|
var cancel_msg = gettextCatalog.getString('Cancel');
|
|
|
|
var confirm_msg = gettextCatalog.getString('Confirm');
|
|
|
|
|
2015-12-02 07:21:26 -08:00
|
|
|
this.openDestinationAddressModal = function(wallets, address) {
|
2015-09-30 10:14:15 -07:00
|
|
|
$rootScope.modalOpened = true;
|
2015-10-22 14:43:32 -07:00
|
|
|
var fc = profileService.focusedClient;
|
2015-12-02 07:21:26 -08:00
|
|
|
self.lockAddress = false;
|
|
|
|
self._address = null;
|
2015-06-19 18:01:38 -07:00
|
|
|
|
|
|
|
var ModalInstanceCtrl = function($scope, $modalInstance) {
|
2015-09-25 09:10:05 -07:00
|
|
|
$scope.wallets = wallets;
|
2015-10-22 14:43:32 -07:00
|
|
|
$scope.editAddressbook = false;
|
|
|
|
$scope.addAddressbookEntry = false;
|
|
|
|
$scope.selectedAddressbook = {};
|
2015-10-23 07:12:23 -07:00
|
|
|
$scope.newAddress = address;
|
2015-12-01 12:33:53 -08:00
|
|
|
$scope.walletName = fc.credentials.walletName;
|
2015-12-02 13:20:22 -08:00
|
|
|
$scope.color = fc.backgroundColor;
|
2015-09-25 09:10:05 -07:00
|
|
|
$scope.addressbook = {
|
|
|
|
'address': ($scope.newAddress || ''),
|
|
|
|
'label': ''
|
|
|
|
};
|
2015-10-22 14:43:32 -07:00
|
|
|
|
2016-02-02 12:07:39 -08:00
|
|
|
$scope.checkClipboard = function() {
|
2016-02-08 13:36:30 -08:00
|
|
|
getClipboard(function(value) {
|
|
|
|
$scope.newAddress = value;
|
2016-02-02 12:07:39 -08:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2015-10-23 07:12:23 -07:00
|
|
|
$scope.beforeQrCodeScann = function() {
|
|
|
|
$scope.error = null;
|
|
|
|
$scope.addAddressbookEntry = true;
|
|
|
|
$scope.editAddressbook = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
$scope.onQrCodeScanned = function(data, addressbookForm) {
|
|
|
|
$timeout(function() {
|
|
|
|
var form = addressbookForm;
|
|
|
|
if (data && form) {
|
|
|
|
data = data.replace('bitcoin:', '');
|
|
|
|
form.address.$setViewValue(data);
|
|
|
|
form.address.$isValid = true;
|
|
|
|
form.address.$render();
|
|
|
|
}
|
|
|
|
$scope.$digest();
|
|
|
|
}, 100);
|
|
|
|
};
|
|
|
|
|
2015-10-22 14:43:32 -07:00
|
|
|
$scope.selectAddressbook = function(addr) {
|
|
|
|
$modalInstance.close(addr);
|
|
|
|
};
|
|
|
|
|
|
|
|
$scope.toggleEditAddressbook = function() {
|
|
|
|
$scope.editAddressbook = !$scope.editAddressbook;
|
|
|
|
$scope.selectedAddressbook = {};
|
|
|
|
$scope.addAddressbookEntry = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
$scope.toggleSelectAddressbook = function(addr) {
|
|
|
|
$scope.selectedAddressbook[addr] = $scope.selectedAddressbook[addr] ? false : true;
|
|
|
|
};
|
|
|
|
|
|
|
|
$scope.toggleAddAddressbookEntry = function() {
|
2015-10-23 07:12:23 -07:00
|
|
|
$scope.error = null;
|
2015-09-25 09:10:05 -07:00
|
|
|
$scope.addressbook = {
|
|
|
|
'address': ($scope.newAddress || ''),
|
|
|
|
'label': ''
|
|
|
|
};
|
2015-10-22 14:43:32 -07:00
|
|
|
$scope.addAddressbookEntry = !$scope.addAddressbookEntry;
|
|
|
|
};
|
|
|
|
|
|
|
|
$scope.list = function() {
|
|
|
|
$scope.error = null;
|
|
|
|
addressbookService.list(function(err, ab) {
|
2015-09-25 09:10:05 -07:00
|
|
|
if (err) {
|
2015-10-22 14:43:32 -07:00
|
|
|
$scope.error = err;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
$scope.list = ab;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
$scope.add = function(addressbook) {
|
|
|
|
$scope.error = null;
|
2015-10-22 15:06:23 -07:00
|
|
|
$timeout(function() {
|
|
|
|
addressbookService.add(addressbook, function(err, ab) {
|
2015-09-25 09:10:05 -07:00
|
|
|
if (err) {
|
2015-10-22 15:06:23 -07:00
|
|
|
$scope.error = err;
|
|
|
|
return;
|
|
|
|
}
|
2015-11-02 07:04:18 -08:00
|
|
|
$rootScope.$emit('Local/AddressbookUpdated', ab);
|
2015-10-22 15:06:23 -07:00
|
|
|
$scope.list = ab;
|
|
|
|
$scope.editAddressbook = true;
|
|
|
|
$scope.toggleEditAddressbook();
|
|
|
|
$scope.$digest();
|
|
|
|
});
|
|
|
|
}, 100);
|
2015-10-22 14:43:32 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
$scope.remove = function(addr) {
|
|
|
|
$scope.error = null;
|
2015-10-22 15:06:23 -07:00
|
|
|
$timeout(function() {
|
|
|
|
addressbookService.remove(addr, function(err, ab) {
|
2015-09-25 09:10:05 -07:00
|
|
|
if (err) {
|
2015-10-22 15:06:23 -07:00
|
|
|
$scope.error = err;
|
|
|
|
return;
|
|
|
|
}
|
2015-11-02 07:04:18 -08:00
|
|
|
$rootScope.$emit('Local/AddressbookUpdated', ab);
|
2015-10-22 15:06:23 -07:00
|
|
|
$scope.list = ab;
|
|
|
|
$scope.$digest();
|
|
|
|
});
|
|
|
|
}, 100);
|
2015-10-22 14:43:32 -07:00
|
|
|
};
|
2015-09-30 10:14:15 -07:00
|
|
|
|
2015-06-19 18:01:38 -07:00
|
|
|
$scope.cancel = function() {
|
|
|
|
$modalInstance.dismiss('cancel');
|
|
|
|
};
|
2015-06-27 09:48:25 -07:00
|
|
|
|
|
|
|
$scope.selectWallet = function(walletId, walletName) {
|
2015-06-28 07:03:28 -07:00
|
|
|
$scope.gettingAddress = true;
|
|
|
|
$scope.selectedWalletName = walletName;
|
|
|
|
$timeout(function() {
|
2015-06-27 09:48:25 -07:00
|
|
|
$scope.$apply();
|
|
|
|
});
|
2015-06-28 07:03:28 -07:00
|
|
|
addressService.getAddress(walletId, false, function(err, addr) {
|
|
|
|
$scope.gettingAddress = false;
|
2015-08-12 07:08:33 -07:00
|
|
|
|
|
|
|
if (err) {
|
2015-06-27 09:48:25 -07:00
|
|
|
self.error = err;
|
|
|
|
$modalInstance.dismiss('cancel');
|
2015-08-12 07:08:33 -07:00
|
|
|
return;
|
2015-06-27 09:48:25 -07:00
|
|
|
}
|
2015-08-12 07:08:33 -07:00
|
|
|
|
|
|
|
$modalInstance.close(addr);
|
2015-06-27 09:48:25 -07:00
|
|
|
});
|
|
|
|
};
|
2015-06-19 18:01:38 -07:00
|
|
|
};
|
2015-06-27 09:48:25 -07:00
|
|
|
|
2015-06-19 18:01:38 -07:00
|
|
|
var modalInstance = $modal.open({
|
2015-10-22 14:43:32 -07:00
|
|
|
templateUrl: 'views/modals/destination-address.html',
|
2015-09-30 22:13:33 -07:00
|
|
|
windowClass: animationService.modalAnimated.slideUp,
|
2015-06-19 18:01:38 -07:00
|
|
|
controller: ModalInstanceCtrl,
|
|
|
|
});
|
|
|
|
|
2015-09-30 10:14:15 -07:00
|
|
|
var disableCloseModal = $rootScope.$on('closeModal', function() {
|
|
|
|
modalInstance.dismiss('cancel');
|
|
|
|
});
|
|
|
|
|
2015-06-19 18:01:38 -07:00
|
|
|
modalInstance.result.finally(function() {
|
2015-09-30 10:14:15 -07:00
|
|
|
$rootScope.modalOpened = false;
|
|
|
|
disableCloseModal();
|
2015-06-19 18:01:38 -07:00
|
|
|
var m = angular.element(document.getElementsByClassName('reveal-modal'));
|
2015-09-30 22:13:33 -07:00
|
|
|
m.addClass(animationService.modalAnimated.slideOutDown);
|
2015-06-19 18:01:38 -07:00
|
|
|
});
|
2015-06-27 09:48:25 -07:00
|
|
|
|
|
|
|
modalInstance.result.then(function(addr) {
|
|
|
|
if (addr) {
|
|
|
|
self.setForm(addr);
|
|
|
|
}
|
2016-02-02 12:07:39 -08:00
|
|
|
}, function() {
|
|
|
|
// onRejected
|
|
|
|
self.resetForm();
|
2015-06-27 09:48:25 -07:00
|
|
|
});
|
2015-06-19 18:01:38 -07:00
|
|
|
};
|
|
|
|
|
2015-09-14 05:46:45 -07:00
|
|
|
var GLIDERA_LOCK_TIME = 6 * 60 * 60;
|
2016-01-16 15:04:01 -08:00
|
|
|
// isGlidera flag is a security measure so glidera status is not
|
2015-09-08 18:39:33 -07:00
|
|
|
// only determined by the tx.message
|
|
|
|
this.openTxpModal = function(tx, copayers, isGlidera) {
|
2015-09-30 10:14:15 -07:00
|
|
|
$rootScope.modalOpened = true;
|
2015-03-06 07:00:10 -08:00
|
|
|
var fc = profileService.focusedClient;
|
2015-12-02 06:57:13 -08:00
|
|
|
var currentSpendUnconfirmed = configWallet.spendUnconfirmed;
|
2015-03-06 07:00:10 -08:00
|
|
|
var ModalInstanceCtrl = function($scope, $modalInstance) {
|
2016-02-19 08:29:41 -08:00
|
|
|
$scope.paymentExpired = null;
|
2016-02-05 12:36:25 -08:00
|
|
|
checkPaypro();
|
2015-03-06 07:00:10 -08:00
|
|
|
$scope.error = null;
|
|
|
|
$scope.copayers = copayers
|
2015-05-13 06:56:08 -07:00
|
|
|
$scope.copayerId = fc.credentials.copayerId;
|
2015-09-04 06:17:59 -07:00
|
|
|
$scope.canSign = fc.canSign() || fc.isPrivKeyExternal();
|
2015-03-06 07:00:10 -08:00
|
|
|
$scope.loading = null;
|
|
|
|
$scope.color = fc.backgroundColor;
|
2015-11-14 13:08:04 -08:00
|
|
|
$scope.isShared = fc.credentials.n > 1;
|
2016-02-19 08:29:41 -08:00
|
|
|
var now = Math.floor(Date.now() / 1000);
|
2015-09-08 17:11:13 -07:00
|
|
|
|
2015-09-08 18:39:33 -07:00
|
|
|
// ToDo: use tx.customData instead of tx.message
|
|
|
|
if (tx.message === 'Glidera transaction' && isGlidera) {
|
|
|
|
tx.isGlidera = true;
|
|
|
|
if (tx.canBeRemoved) {
|
2015-09-14 05:46:45 -07:00
|
|
|
tx.canBeRemoved = (Date.now() / 1000 - (tx.ts || tx.createdOn)) > GLIDERA_LOCK_TIME;
|
2015-09-08 18:39:33 -07:00
|
|
|
}
|
2015-09-08 17:11:13 -07:00
|
|
|
}
|
2015-09-08 18:39:33 -07:00
|
|
|
$scope.tx = tx;
|
2015-08-11 13:59:41 -07:00
|
|
|
$scope.currentSpendUnconfirmed = currentSpendUnconfirmed;
|
2015-03-06 07:00:10 -08:00
|
|
|
|
|
|
|
$scope.getShortNetworkName = function() {
|
|
|
|
return fc.credentials.networkName.substring(0, 4);
|
|
|
|
};
|
2016-02-05 12:36:25 -08:00
|
|
|
|
|
|
|
function checkPaypro() {
|
2016-02-19 08:29:41 -08:00
|
|
|
if (tx.payProUrl && !isChromeApp) {
|
2016-02-05 12:36:25 -08:00
|
|
|
fc.fetchPayPro({
|
|
|
|
payProUrl: tx.payProUrl,
|
|
|
|
}, function(err, paypro) {
|
2016-02-10 08:04:00 -08:00
|
|
|
if (err) return;
|
2016-02-05 12:36:25 -08:00
|
|
|
tx.paypro = paypro;
|
2016-02-19 08:29:41 -08:00
|
|
|
$scope.paymentExpired = tx.paypro.expires <= now;
|
|
|
|
if (!$scope.paymentExpired)
|
|
|
|
paymentTimeControl(tx.paypro.expires);
|
2016-02-05 12:36:25 -08:00
|
|
|
$scope.$apply();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-02-19 08:29:41 -08:00
|
|
|
function paymentTimeControl(timeToExpire) {
|
|
|
|
$scope.expires = timeToExpire;
|
|
|
|
var countDown = $interval(function() {
|
|
|
|
if ($scope.expires <= now) {
|
|
|
|
$scope.paymentExpired = true;
|
|
|
|
$interval.cancel(countDown);
|
|
|
|
}
|
|
|
|
$scope.expires --;
|
|
|
|
}, 1000);
|
|
|
|
};
|
|
|
|
|
2015-09-03 14:14:38 -07:00
|
|
|
lodash.each(['TxProposalRejectedBy', 'TxProposalAcceptedBy', 'transactionProposalRemoved', 'TxProposalRemoved', 'NewOutgoingTx', 'UpdateTx'], function(eventName) {
|
2015-03-06 07:00:10 -08:00
|
|
|
$rootScope.$on(eventName, function() {
|
|
|
|
fc.getTx($scope.tx.id, function(err, tx) {
|
|
|
|
if (err) {
|
2016-01-22 13:16:50 -08:00
|
|
|
if (err.message && err.message == 'TX_NOT_FOUND' &&
|
2015-03-06 07:00:10 -08:00
|
|
|
(eventName == 'transactionProposalRemoved' || eventName == 'TxProposalRemoved')) {
|
|
|
|
$scope.tx.removed = true;
|
2015-06-18 07:17:35 -07:00
|
|
|
$scope.tx.canBeRemoved = false;
|
2015-03-06 07:00:10 -08:00
|
|
|
$scope.tx.pendingForUs = false;
|
|
|
|
$scope.$apply();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var action = lodash.find(tx.actions, {
|
|
|
|
copayerId: fc.credentials.copayerId
|
|
|
|
});
|
2016-02-05 12:36:25 -08:00
|
|
|
|
2015-09-09 12:17:08 -07:00
|
|
|
$scope.tx = txFormatService.processTx(tx);
|
2016-02-05 12:36:25 -08:00
|
|
|
|
2015-03-06 07:00:10 -08:00
|
|
|
if (!action && tx.status == 'pending')
|
|
|
|
$scope.tx.pendingForUs = true;
|
2016-02-05 12:36:25 -08:00
|
|
|
|
2015-03-06 07:00:10 -08:00
|
|
|
$scope.updateCopayerList();
|
|
|
|
$scope.$apply();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
$scope.updateCopayerList = function() {
|
|
|
|
lodash.map($scope.copayers, function(cp) {
|
|
|
|
lodash.each($scope.tx.actions, function(ac) {
|
|
|
|
if (cp.id == ac.copayerId) {
|
|
|
|
cp.action = ac.type;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
$scope.sign = function(txp) {
|
2015-09-25 09:10:05 -07:00
|
|
|
var fc = profileService.focusedClient;
|
2016-01-20 10:25:54 -08:00
|
|
|
$scope.error = null;
|
2015-03-06 07:00:10 -08:00
|
|
|
$scope.loading = true;
|
2016-01-20 10:25:54 -08:00
|
|
|
|
2016-02-11 11:06:30 -08:00
|
|
|
txService.prepareAndSignAndBroadcast(txp, {
|
2016-01-21 09:52:58 -08:00
|
|
|
reporterFn: self.setOngoingProcess.bind(self)
|
|
|
|
}, function(err, txp) {
|
|
|
|
$scope.loading = false;
|
|
|
|
$scope.$emit('UpdateTx');
|
2015-10-07 12:17:19 -07:00
|
|
|
|
2016-01-21 09:52:58 -08:00
|
|
|
if (err) {
|
|
|
|
$scope.error = err;
|
|
|
|
$timeout(function() {
|
|
|
|
$scope.$digest();
|
2015-10-07 12:17:19 -07:00
|
|
|
});
|
2016-01-21 09:52:58 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
$modalInstance.close(txp);
|
|
|
|
return;
|
|
|
|
});
|
2015-03-06 07:00:10 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
$scope.reject = function(txp) {
|
2016-01-06 12:19:31 -08:00
|
|
|
self.setOngoingProcess(gettextCatalog.getString('Rejecting payment'));
|
2015-03-06 07:00:10 -08:00
|
|
|
$scope.loading = true;
|
|
|
|
$scope.error = null;
|
|
|
|
$timeout(function() {
|
|
|
|
fc.rejectTxProposal(txp, null, function(err, txpr) {
|
2015-04-24 11:02:14 -07:00
|
|
|
self.setOngoingProcess();
|
2015-03-06 07:00:10 -08:00
|
|
|
$scope.loading = false;
|
|
|
|
if (err) {
|
2015-09-03 14:14:38 -07:00
|
|
|
$scope.$emit('UpdateTx');
|
2015-08-13 12:47:10 -07:00
|
|
|
$scope.error = bwsError.msg(err, gettextCatalog.getString('Could not reject payment'));
|
2015-03-06 07:00:10 -08:00
|
|
|
$scope.$digest();
|
|
|
|
} else {
|
|
|
|
$modalInstance.close(txpr);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}, 100);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
$scope.remove = function(txp) {
|
2016-01-06 12:19:31 -08:00
|
|
|
self.setOngoingProcess(gettextCatalog.getString('Deleting payment'));
|
2015-03-06 07:00:10 -08:00
|
|
|
$scope.loading = true;
|
|
|
|
$scope.error = null;
|
|
|
|
$timeout(function() {
|
|
|
|
fc.removeTxProposal(txp, function(err, txpb) {
|
2015-04-24 11:02:14 -07:00
|
|
|
self.setOngoingProcess();
|
2015-03-06 07:00:10 -08:00
|
|
|
$scope.loading = false;
|
|
|
|
|
|
|
|
// Hacky: request tries to parse an empty response
|
2015-04-21 09:06:44 -07:00
|
|
|
if (err && !(err.message && err.message.match(/Unexpected/))) {
|
2015-09-03 14:14:38 -07:00
|
|
|
$scope.$emit('UpdateTx');
|
2015-08-13 12:47:10 -07:00
|
|
|
$scope.error = bwsError.msg(err, gettextCatalog.getString('Could not delete payment proposal'));
|
2015-03-06 07:00:10 -08:00
|
|
|
$scope.$digest();
|
|
|
|
return;
|
2015-04-21 09:06:44 -07:00
|
|
|
}
|
2015-03-06 07:00:10 -08:00
|
|
|
$modalInstance.close();
|
|
|
|
});
|
|
|
|
}, 100);
|
|
|
|
};
|
|
|
|
|
|
|
|
$scope.broadcast = function(txp) {
|
2016-01-06 12:19:31 -08:00
|
|
|
self.setOngoingProcess(gettextCatalog.getString('Broadcasting Payment'));
|
2015-03-06 07:00:10 -08:00
|
|
|
$scope.loading = true;
|
|
|
|
$scope.error = null;
|
|
|
|
$timeout(function() {
|
2015-05-22 13:16:55 -07:00
|
|
|
fc.broadcastTxProposal(txp, function(err, txpb, memo) {
|
2015-04-24 11:02:14 -07:00
|
|
|
self.setOngoingProcess();
|
2015-03-06 07:00:10 -08:00
|
|
|
$scope.loading = false;
|
|
|
|
if (err) {
|
2015-08-13 12:47:10 -07:00
|
|
|
$scope.error = bwsError.msg(err, gettextCatalog.getString('Could not broadcast payment'));
|
2015-03-06 07:00:10 -08:00
|
|
|
$scope.$digest();
|
|
|
|
} else {
|
2015-05-22 13:16:55 -07:00
|
|
|
|
|
|
|
if (memo)
|
|
|
|
$log.info(memo);
|
2015-05-29 08:39:17 -07:00
|
|
|
|
|
|
|
$modalInstance.close(txpb);
|
2015-03-06 07:00:10 -08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}, 100);
|
|
|
|
};
|
|
|
|
|
2016-02-16 11:13:50 -08:00
|
|
|
$scope.copyToClipboard = function(addr) {
|
2015-04-26 22:31:07 -07:00
|
|
|
if (!addr) return;
|
2016-02-16 11:13:50 -08:00
|
|
|
self.copyToClipboard(addr);
|
2015-04-26 22:31:07 -07:00
|
|
|
};
|
|
|
|
|
2015-12-04 12:04:13 -08:00
|
|
|
$scope.cancel = lodash.debounce(function() {
|
2015-04-21 22:48:00 -07:00
|
|
|
$modalInstance.dismiss('cancel');
|
2015-12-04 12:04:13 -08:00
|
|
|
}, 0, 1000);
|
2015-03-06 07:00:10 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
var modalInstance = $modal.open({
|
|
|
|
templateUrl: 'views/modals/txp-details.html',
|
2015-09-30 22:13:33 -07:00
|
|
|
windowClass: animationService.modalAnimated.slideRight,
|
2015-03-06 07:00:10 -08:00
|
|
|
controller: ModalInstanceCtrl,
|
|
|
|
});
|
|
|
|
|
2015-09-30 10:14:15 -07:00
|
|
|
var disableCloseModal = $rootScope.$on('closeModal', function() {
|
|
|
|
modalInstance.dismiss('cancel');
|
|
|
|
});
|
|
|
|
|
2015-05-07 15:02:38 -07:00
|
|
|
modalInstance.result.finally(function() {
|
2015-09-30 10:14:15 -07:00
|
|
|
$rootScope.modalOpened = false;
|
|
|
|
disableCloseModal();
|
2015-05-07 15:02:38 -07:00
|
|
|
var m = angular.element(document.getElementsByClassName('reveal-modal'));
|
2015-09-30 22:13:33 -07:00
|
|
|
m.addClass(animationService.modalAnimated.slideOutRight);
|
2015-05-07 15:02:38 -07:00
|
|
|
});
|
|
|
|
|
2015-05-29 08:39:17 -07:00
|
|
|
modalInstance.result.then(function(txp) {
|
2015-05-12 06:59:10 -07:00
|
|
|
self.setOngoingProcess();
|
2015-03-06 07:00:10 -08:00
|
|
|
if (txp) {
|
2015-05-08 07:38:34 -07:00
|
|
|
txStatus.notify(txp, function() {
|
2016-01-22 07:39:44 -08:00
|
|
|
$scope.$emit('Local/TxProposalAction', txp.status == 'broadcasted');
|
2015-05-08 07:38:34 -07:00
|
|
|
});
|
2015-05-12 06:59:10 -07:00
|
|
|
} else {
|
|
|
|
$timeout(function() {
|
2016-01-22 07:39:44 -08:00
|
|
|
$scope.$emit('Local/TxProposalAction');
|
2015-05-12 06:59:10 -07:00
|
|
|
}, 100);
|
2015-03-06 07:00:10 -08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2015-06-27 09:22:56 -07:00
|
|
|
this.setAddress = function(forceNew) {
|
2015-05-29 07:46:33 -07:00
|
|
|
self.addrError = null;
|
2015-04-23 08:27:43 -07:00
|
|
|
var fc = profileService.focusedClient;
|
2015-05-13 08:41:05 -07:00
|
|
|
if (!fc)
|
|
|
|
return;
|
|
|
|
|
2015-06-27 09:22:56 -07:00
|
|
|
// Address already set?
|
2016-02-18 12:16:07 -08:00
|
|
|
if (!forceNew && self.addr) {
|
2015-05-30 19:15:43 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-06-27 09:22:56 -07:00
|
|
|
self.generatingAddress = true;
|
2015-04-23 08:27:43 -07:00
|
|
|
$timeout(function() {
|
2015-06-28 07:03:28 -07:00
|
|
|
addressService.getAddress(fc.credentials.walletId, forceNew, function(err, addr) {
|
2015-06-27 09:22:56 -07:00
|
|
|
self.generatingAddress = false;
|
|
|
|
|
2015-08-12 07:49:13 -07:00
|
|
|
if (err) {
|
2015-08-12 07:08:33 -07:00
|
|
|
self.addrError = err;
|
2015-08-12 07:49:13 -07:00
|
|
|
} else {
|
2015-08-12 07:08:33 -07:00
|
|
|
if (addr)
|
2016-02-18 12:16:07 -08:00
|
|
|
self.addr = addr;
|
2015-04-23 08:27:43 -07:00
|
|
|
}
|
2015-06-27 09:22:56 -07:00
|
|
|
|
|
|
|
$scope.$digest();
|
2015-04-23 08:27:43 -07:00
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2016-02-16 11:13:50 -08:00
|
|
|
this.copyToClipboard = function(addr) {
|
2015-04-23 08:27:43 -07:00
|
|
|
if (isCordova) {
|
2015-06-08 07:15:30 -07:00
|
|
|
window.cordova.plugins.clipboard.copy(addr);
|
2015-07-29 08:42:05 -07:00
|
|
|
window.plugins.toast.showShortCenter(gettextCatalog.getString('Copied to clipboard'));
|
2015-05-28 06:52:33 -07:00
|
|
|
} else if (nodeWebkit.isDefined()) {
|
|
|
|
nodeWebkit.writeToClipboard(addr);
|
2015-04-23 08:27:43 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
this.shareAddress = function(addr) {
|
|
|
|
if (isCordova) {
|
|
|
|
if (isMobile.Android() || isMobile.Windows()) {
|
|
|
|
window.ignoreMobilePause = true;
|
|
|
|
}
|
|
|
|
window.plugins.socialsharing.share('bitcoin:' + addr, null, null, null);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-24 13:55:08 -07:00
|
|
|
this.openCustomizedAmountModal = function(addr) {
|
2015-09-30 10:14:15 -07:00
|
|
|
$rootScope.modalOpened = true;
|
2015-06-24 13:55:08 -07:00
|
|
|
var self = this;
|
|
|
|
var fc = profileService.focusedClient;
|
|
|
|
var ModalInstanceCtrl = function($scope, $modalInstance) {
|
|
|
|
$scope.addr = addr;
|
|
|
|
$scope.color = fc.backgroundColor;
|
|
|
|
$scope.unitName = self.unitName;
|
|
|
|
$scope.alternativeAmount = self.alternativeAmount;
|
|
|
|
$scope.alternativeName = self.alternativeName;
|
|
|
|
$scope.alternativeIsoCode = self.alternativeIsoCode;
|
|
|
|
$scope.isRateAvailable = self.isRateAvailable;
|
|
|
|
$scope.unitToSatoshi = self.unitToSatoshi;
|
|
|
|
$scope.unitDecimals = self.unitDecimals;
|
|
|
|
var satToUnit = 1 / self.unitToSatoshi;
|
|
|
|
$scope.showAlternative = false;
|
2015-09-11 10:44:52 -07:00
|
|
|
$scope.isCordova = isCordova;
|
2015-06-24 13:55:08 -07:00
|
|
|
|
|
|
|
Object.defineProperty($scope,
|
|
|
|
"_customAlternative", {
|
|
|
|
get: function() {
|
|
|
|
return $scope.customAlternative;
|
|
|
|
},
|
|
|
|
set: function(newValue) {
|
|
|
|
$scope.customAlternative = newValue;
|
|
|
|
if (typeof(newValue) === 'number' && $scope.isRateAvailable) {
|
|
|
|
$scope.customAmount = parseFloat((rateService.fromFiat(newValue, $scope.alternativeIsoCode) * satToUnit).toFixed($scope.unitDecimals), 10);
|
2015-08-07 13:21:22 -07:00
|
|
|
} else {
|
|
|
|
$scope.customAmount = null;
|
2015-06-24 13:55:08 -07:00
|
|
|
}
|
|
|
|
},
|
|
|
|
enumerable: true,
|
|
|
|
configurable: true
|
|
|
|
});
|
|
|
|
|
|
|
|
Object.defineProperty($scope,
|
|
|
|
"_customAmount", {
|
|
|
|
get: function() {
|
|
|
|
return $scope.customAmount;
|
|
|
|
},
|
|
|
|
set: function(newValue) {
|
|
|
|
$scope.customAmount = newValue;
|
|
|
|
if (typeof(newValue) === 'number' && $scope.isRateAvailable) {
|
|
|
|
$scope.customAlternative = parseFloat((rateService.toFiat(newValue * $scope.unitToSatoshi, $scope.alternativeIsoCode)).toFixed(2), 10);
|
|
|
|
} else {
|
2015-08-07 13:21:22 -07:00
|
|
|
$scope.customAlternative = null;
|
2015-06-24 13:55:08 -07:00
|
|
|
}
|
|
|
|
$scope.alternativeAmount = $scope.customAlternative;
|
|
|
|
},
|
|
|
|
enumerable: true,
|
|
|
|
configurable: true
|
|
|
|
});
|
|
|
|
|
|
|
|
$scope.submitForm = function(form) {
|
|
|
|
var satToBtc = 1 / 100000000;
|
|
|
|
var amount = form.amount.$modelValue;
|
2015-06-26 10:25:53 -07:00
|
|
|
var amountSat = parseInt((amount * $scope.unitToSatoshi).toFixed(0));
|
|
|
|
$timeout(function() {
|
|
|
|
$scope.customizedAmountUnit = amount + ' ' + $scope.unitName;
|
|
|
|
$scope.customizedAlternativeUnit = $filter('noFractionNumber')(form.alternative.$modelValue, 2) + ' ' + $scope.alternativeIsoCode;
|
|
|
|
if ($scope.unitName == 'bits') {
|
2015-06-26 11:08:59 -07:00
|
|
|
amount = (amountSat * satToBtc).toFixed(8);
|
2015-06-26 10:25:53 -07:00
|
|
|
}
|
|
|
|
$scope.customizedAmountBtc = amount;
|
|
|
|
}, 1);
|
2015-06-24 13:55:08 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
$scope.toggleAlternative = function() {
|
|
|
|
$scope.showAlternative = !$scope.showAlternative;
|
|
|
|
};
|
|
|
|
|
2015-09-11 10:44:52 -07:00
|
|
|
$scope.shareAddress = function(uri) {
|
|
|
|
if (isCordova) {
|
|
|
|
if (isMobile.Android() || isMobile.Windows()) {
|
|
|
|
window.ignoreMobilePause = true;
|
|
|
|
}
|
|
|
|
window.plugins.socialsharing.share(uri, null, null, null);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-24 13:55:08 -07:00
|
|
|
$scope.cancel = function() {
|
|
|
|
$modalInstance.dismiss('cancel');
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
var modalInstance = $modal.open({
|
|
|
|
templateUrl: 'views/modals/customized-amount.html',
|
2015-09-30 22:13:33 -07:00
|
|
|
windowClass: animationService.modalAnimated.slideUp,
|
2015-06-24 13:55:08 -07:00
|
|
|
controller: ModalInstanceCtrl,
|
|
|
|
});
|
|
|
|
|
2015-09-30 10:14:15 -07:00
|
|
|
var disableCloseModal = $rootScope.$on('closeModal', function() {
|
|
|
|
modalInstance.dismiss('cancel');
|
|
|
|
});
|
|
|
|
|
2015-06-24 13:55:08 -07:00
|
|
|
modalInstance.result.finally(function() {
|
2015-09-30 10:14:15 -07:00
|
|
|
$rootScope.modalOpened = false;
|
|
|
|
disableCloseModal();
|
2015-06-24 13:55:08 -07:00
|
|
|
var m = angular.element(document.getElementsByClassName('reveal-modal'));
|
2015-09-30 22:13:33 -07:00
|
|
|
m.addClass(animationService.modalAnimated.slideOutDown);
|
2015-06-24 13:55:08 -07:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2016-02-04 05:33:41 -08:00
|
|
|
// Send
|
2015-04-28 08:06:04 -07:00
|
|
|
|
|
|
|
this.canShowAlternative = function() {
|
|
|
|
return $scope.showAlternative;
|
|
|
|
};
|
|
|
|
|
|
|
|
this.showAlternative = function() {
|
|
|
|
$scope.showAlternative = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
this.hideAlternative = function() {
|
|
|
|
$scope.showAlternative = false;
|
|
|
|
};
|
|
|
|
|
2015-04-23 08:27:43 -07:00
|
|
|
this.resetError = function() {
|
2015-05-29 08:39:17 -07:00
|
|
|
this.error = this.success = null;
|
2015-04-23 08:27:43 -07:00
|
|
|
};
|
|
|
|
|
2015-04-28 12:08:43 -07:00
|
|
|
this.bindTouchDown = function(tries) {
|
|
|
|
var self = this;
|
|
|
|
tries = tries || 0;
|
|
|
|
if (tries > 5) return;
|
|
|
|
var e = document.getElementById('menu-walletHome');
|
2015-04-28 16:13:28 -07:00
|
|
|
if (!e) return $timeout(function() {
|
2015-04-28 12:08:43 -07:00
|
|
|
self.bindTouchDown(++tries);
|
|
|
|
}, 500);
|
|
|
|
|
|
|
|
// on touchdown elements
|
|
|
|
$log.debug('Binding touchstart elements...');
|
2015-12-02 13:20:22 -08:00
|
|
|
['hamburger', 'menu-walletHome', 'menu-send', 'menu-receive'].forEach(function(id) {
|
2015-04-28 12:08:43 -07:00
|
|
|
var e = document.getElementById(id);
|
|
|
|
if (e) e.addEventListener('touchstart', function() {
|
2015-05-04 09:27:12 -07:00
|
|
|
try {
|
|
|
|
event.preventDefault();
|
|
|
|
} catch (e) {};
|
2015-04-28 12:08:43 -07:00
|
|
|
angular.element(e).triggerHandler('click');
|
2015-05-04 09:27:12 -07:00
|
|
|
}, true);
|
2015-04-28 12:08:43 -07:00
|
|
|
});
|
|
|
|
}
|
2015-04-23 08:27:43 -07:00
|
|
|
|
2015-04-28 12:08:43 -07:00
|
|
|
this.hideMenuBar = lodash.debounce(function(hide) {
|
2015-04-23 08:27:43 -07:00
|
|
|
if (hide) {
|
2016-02-03 08:35:52 -08:00
|
|
|
$rootScope.shouldHideMenuBar = true;
|
2015-04-28 12:08:43 -07:00
|
|
|
this.bindTouchDown();
|
2015-04-23 08:27:43 -07:00
|
|
|
} else {
|
2016-02-03 08:35:52 -08:00
|
|
|
$rootScope.shouldHideMenuBar = false;
|
2015-04-23 08:27:43 -07:00
|
|
|
}
|
|
|
|
$rootScope.$digest();
|
|
|
|
}, 100);
|
|
|
|
|
|
|
|
|
|
|
|
this.formFocus = function(what) {
|
2015-04-24 13:34:18 -07:00
|
|
|
if (isCordova && !this.isWindowsPhoneApp) {
|
2015-04-28 12:08:43 -07:00
|
|
|
this.hideMenuBar(what);
|
2015-04-23 08:27:43 -07:00
|
|
|
}
|
2016-02-04 05:33:41 -08:00
|
|
|
|
2016-02-08 13:36:30 -08:00
|
|
|
var self = this;
|
|
|
|
if (isCordova && !this.isWindowsPhoneApp && what == 'address') {
|
|
|
|
getClipboard(function(value) {
|
|
|
|
if (value) {
|
|
|
|
document.getElementById("amount").focus();
|
|
|
|
$timeout(function() {
|
|
|
|
window.plugins.toast.showShortCenter(gettextCatalog.getString('Pasted from clipboard'));
|
|
|
|
self.setForm(value);
|
|
|
|
}, 100);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-04-23 08:27:43 -07:00
|
|
|
if (!this.isWindowsPhoneApp) return
|
|
|
|
|
|
|
|
if (!what) {
|
|
|
|
this.hideAddress = false;
|
|
|
|
this.hideAmount = false;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
if (what == 'amount') {
|
|
|
|
this.hideAddress = true;
|
|
|
|
} else if (what == 'msg') {
|
|
|
|
this.hideAddress = true;
|
|
|
|
this.hideAmount = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$timeout(function() {
|
|
|
|
$rootScope.$digest();
|
|
|
|
}, 1);
|
|
|
|
};
|
|
|
|
|
2015-04-28 12:58:40 -07:00
|
|
|
this.setSendFormInputs = function() {
|
2015-04-23 08:27:43 -07:00
|
|
|
var unitToSat = this.unitToSatoshi;
|
|
|
|
var satToUnit = 1 / unitToSat;
|
|
|
|
/**
|
|
|
|
* Setting the two related amounts as properties prevents an infinite
|
|
|
|
* recursion for watches while preserving the original angular updates
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
Object.defineProperty($scope,
|
|
|
|
"_alternative", {
|
|
|
|
get: function() {
|
|
|
|
return $scope.__alternative;
|
|
|
|
},
|
|
|
|
set: function(newValue) {
|
|
|
|
$scope.__alternative = newValue;
|
|
|
|
if (typeof(newValue) === 'number' && self.isRateAvailable) {
|
|
|
|
$scope._amount = parseFloat((rateService.fromFiat(newValue, self.alternativeIsoCode) * satToUnit).toFixed(self.unitDecimals), 10);
|
2015-08-07 13:21:22 -07:00
|
|
|
} else {
|
|
|
|
$scope.__amount = null;
|
2015-04-23 08:27:43 -07:00
|
|
|
}
|
|
|
|
},
|
|
|
|
enumerable: true,
|
|
|
|
configurable: true
|
|
|
|
});
|
|
|
|
Object.defineProperty($scope,
|
|
|
|
"_amount", {
|
|
|
|
get: function() {
|
|
|
|
return $scope.__amount;
|
|
|
|
},
|
|
|
|
set: function(newValue) {
|
|
|
|
$scope.__amount = newValue;
|
|
|
|
if (typeof(newValue) === 'number' && self.isRateAvailable) {
|
|
|
|
$scope.__alternative = parseFloat((rateService.toFiat(newValue * self.unitToSatoshi, self.alternativeIsoCode)).toFixed(2), 10);
|
|
|
|
} else {
|
2015-08-07 13:21:22 -07:00
|
|
|
$scope.__alternative = null;
|
2015-04-23 08:27:43 -07:00
|
|
|
}
|
|
|
|
self.alternativeAmount = $scope.__alternative;
|
|
|
|
self.resetError();
|
|
|
|
},
|
|
|
|
enumerable: true,
|
|
|
|
configurable: true
|
|
|
|
});
|
|
|
|
|
|
|
|
Object.defineProperty($scope,
|
|
|
|
"_address", {
|
|
|
|
get: function() {
|
|
|
|
return $scope.__address;
|
|
|
|
},
|
|
|
|
set: function(newValue) {
|
|
|
|
$scope.__address = self.onAddressChange(newValue);
|
2015-10-22 14:43:32 -07:00
|
|
|
if ($scope.sendForm && $scope.sendForm.address.$valid) {
|
|
|
|
self.lockAddress = true;
|
|
|
|
}
|
2015-04-23 08:27:43 -07:00
|
|
|
},
|
|
|
|
enumerable: true,
|
|
|
|
configurable: true
|
|
|
|
});
|
2015-09-14 08:19:52 -07:00
|
|
|
|
|
|
|
var fc = profileService.focusedClient;
|
|
|
|
// ToDo: use a credential's (or fc's) function for this
|
|
|
|
this.hideNote = !fc.credentials.sharedEncryptingKey;
|
2015-04-23 08:27:43 -07:00
|
|
|
};
|
|
|
|
|
2015-05-12 06:48:00 -07:00
|
|
|
this.setSendError = function(err) {
|
2015-04-23 11:23:21 -07:00
|
|
|
var fc = profileService.focusedClient;
|
2015-08-12 07:08:33 -07:00
|
|
|
var prefix =
|
2015-08-13 12:47:10 -07:00
|
|
|
fc.credentials.m > 1 ? gettextCatalog.getString('Could not create payment proposal') : gettextCatalog.getString('Could not send payment');
|
2015-04-23 08:27:43 -07:00
|
|
|
|
2015-08-12 07:49:13 -07:00
|
|
|
this.error = bwsError.msg(err, prefix);
|
2016-02-01 11:18:44 -08:00
|
|
|
|
2015-04-23 08:27:43 -07:00
|
|
|
$timeout(function() {
|
|
|
|
$scope.$digest();
|
|
|
|
}, 1);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
this.setOngoingProcess = function(name) {
|
|
|
|
var self = this;
|
2015-04-23 22:42:10 -07:00
|
|
|
self.blockUx = !!name;
|
|
|
|
|
|
|
|
if (isCordova) {
|
|
|
|
if (name) {
|
2015-04-28 13:49:09 -07:00
|
|
|
window.plugins.spinnerDialog.hide();
|
2015-04-23 22:42:10 -07:00
|
|
|
window.plugins.spinnerDialog.show(null, name + '...', true);
|
|
|
|
} else {
|
|
|
|
window.plugins.spinnerDialog.hide();
|
|
|
|
}
|
|
|
|
} else {
|
2015-04-28 13:19:22 -07:00
|
|
|
self.onGoingProcess = name;
|
2015-04-28 13:28:49 -07:00
|
|
|
$timeout(function() {
|
|
|
|
$rootScope.$apply();
|
|
|
|
});
|
2015-04-28 13:19:22 -07:00
|
|
|
};
|
2015-04-23 08:27:43 -07:00
|
|
|
};
|
|
|
|
|
2015-12-23 13:05:22 -08:00
|
|
|
this.submitForm = function() {
|
2015-04-23 11:23:21 -07:00
|
|
|
var fc = profileService.focusedClient;
|
2015-04-23 08:27:43 -07:00
|
|
|
var unitToSat = this.unitToSatoshi;
|
2015-12-02 06:57:13 -08:00
|
|
|
var currentSpendUnconfirmed = configWallet.spendUnconfirmed;
|
2015-12-24 06:08:49 -08:00
|
|
|
var currentFeeLevel = walletSettings.feeLevel || 'normal';
|
2015-08-12 07:49:13 -07:00
|
|
|
|
2016-01-27 11:41:12 -08:00
|
|
|
var outputs = [];
|
|
|
|
|
2016-01-20 10:25:54 -08:00
|
|
|
this.resetError();
|
|
|
|
|
2015-07-02 10:42:53 -07:00
|
|
|
if (isCordova && this.isWindowsPhoneApp) {
|
|
|
|
this.hideAddress = false;
|
|
|
|
this.hideAmount = false;
|
|
|
|
}
|
2015-04-23 08:27:43 -07:00
|
|
|
|
2015-04-23 22:42:10 -07:00
|
|
|
var form = $scope.sendForm;
|
2015-04-23 08:27:43 -07:00
|
|
|
if (form.$invalid) {
|
2015-04-29 15:19:10 -07:00
|
|
|
this.error = gettext('Unable to send transaction proposal');
|
2015-04-23 08:27:43 -07:00
|
|
|
return;
|
2016-01-21 09:52:58 -08:00
|
|
|
}
|
2015-04-23 08:27:43 -07:00
|
|
|
|
2015-09-14 08:12:24 -07:00
|
|
|
var comment = form.comment.$modelValue;
|
|
|
|
|
|
|
|
// ToDo: use a credential's (or fc's) function for this
|
|
|
|
if (comment && !fc.credentials.sharedEncryptingKey) {
|
|
|
|
var msg = 'Could not add message to imported wallet without shared encrypting key';
|
|
|
|
$log.warn(msg);
|
|
|
|
return self.setSendError(gettext(msg));
|
|
|
|
}
|
|
|
|
|
2015-04-23 08:27:43 -07:00
|
|
|
$timeout(function() {
|
|
|
|
var paypro = self._paypro;
|
|
|
|
var address, amount;
|
|
|
|
|
|
|
|
address = form.address.$modelValue;
|
|
|
|
amount = parseInt((form.amount.$modelValue * unitToSat).toFixed(0));
|
|
|
|
|
2016-01-27 11:41:12 -08:00
|
|
|
outputs.push({
|
2016-02-18 12:16:07 -08:00
|
|
|
'toAddress': address,
|
2016-01-27 11:41:12 -08:00
|
|
|
'amount': amount,
|
|
|
|
'message': comment
|
|
|
|
});
|
|
|
|
|
2016-01-29 11:39:32 -08:00
|
|
|
var opts = {
|
|
|
|
toAddress: address,
|
|
|
|
amount: amount,
|
|
|
|
outputs: outputs,
|
|
|
|
message: comment,
|
|
|
|
payProUrl: paypro ? paypro.url : null,
|
|
|
|
lockedCurrentFeePerKb: self.lockedCurrentFeePerKb
|
|
|
|
};
|
|
|
|
|
|
|
|
self.setOngoingProcess(gettextCatalog.getString('Creating transaction'));
|
2016-02-11 11:06:30 -08:00
|
|
|
txService.createTx(opts, function(err, txp) {
|
2016-01-29 11:39:32 -08:00
|
|
|
self.setOngoingProcess();
|
2015-10-07 12:17:19 -07:00
|
|
|
if (err) {
|
2016-01-21 09:52:58 -08:00
|
|
|
return self.setSendError(err);
|
2015-10-07 12:17:19 -07:00
|
|
|
}
|
2015-07-24 08:11:07 -07:00
|
|
|
|
2016-01-29 11:39:32 -08:00
|
|
|
if (!fc.canSign() && !fc.isPrivKeyExternal()) {
|
2016-01-27 11:41:12 -08:00
|
|
|
self.setOngoingProcess();
|
2016-01-29 11:39:32 -08:00
|
|
|
$log.info('No signing proposal: No private key');
|
|
|
|
self.resetForm();
|
|
|
|
txStatus.notify(txp, function() {
|
|
|
|
return $scope.$emit('Local/TxProposalAction');
|
2015-07-24 08:11:07 -07:00
|
|
|
});
|
2016-01-29 11:39:32 -08:00
|
|
|
return;
|
|
|
|
} else {
|
2016-02-18 12:16:07 -08:00
|
|
|
$rootScope.$emit('Local/NeedsConfirmation', txp, function(accept) {
|
2016-01-29 11:39:32 -08:00
|
|
|
if (accept) self.acceptTx(txp);
|
|
|
|
else self.resetForm();
|
|
|
|
});
|
|
|
|
}
|
2015-04-23 08:27:43 -07:00
|
|
|
});
|
2016-01-29 11:39:32 -08:00
|
|
|
|
2015-04-23 08:27:43 -07:00
|
|
|
}, 100);
|
2016-02-04 05:33:41 -08:00
|
|
|
};
|
2016-01-27 11:41:12 -08:00
|
|
|
|
|
|
|
this.acceptTx = function(txp) {
|
|
|
|
var self = this;
|
2016-02-11 11:06:30 -08:00
|
|
|
txService.prepare(function(err) {
|
2016-01-27 11:41:12 -08:00
|
|
|
if (err) {
|
2016-01-29 11:39:32 -08:00
|
|
|
return self.setSendError(err);
|
2016-01-27 11:41:12 -08:00
|
|
|
}
|
2016-01-29 11:39:32 -08:00
|
|
|
self.setOngoingProcess(gettextCatalog.getString('Sending transaction'));
|
2016-02-11 11:06:30 -08:00
|
|
|
txService.publishTx(txp, function(err, txpPublished) {
|
2016-01-29 11:39:32 -08:00
|
|
|
if (err) {
|
|
|
|
self.setOngoingProcess();
|
|
|
|
self.setSendError(err);
|
|
|
|
} else {
|
|
|
|
self.prepareSignAndBroadcastTx(txpPublished);
|
|
|
|
}
|
|
|
|
});
|
2016-01-27 11:41:12 -08:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2016-01-29 11:39:32 -08:00
|
|
|
this.prepareSignAndBroadcastTx = function(txp) {
|
|
|
|
var fc = profileService.focusedClient;
|
2016-01-27 11:41:12 -08:00
|
|
|
var self = this;
|
2016-02-11 11:06:30 -08:00
|
|
|
txService.prepareAndSignAndBroadcast(txp, {
|
2016-01-27 11:41:12 -08:00
|
|
|
reporterFn: self.setOngoingProcess.bind(self)
|
|
|
|
}, function(err, txp) {
|
|
|
|
self.resetForm();
|
2016-01-29 11:39:32 -08:00
|
|
|
|
2016-01-27 11:41:12 -08:00
|
|
|
if (err) {
|
|
|
|
self.error = err.message ? err.message : gettext('The payment was created but could not be completed. Please try again from home screen');
|
|
|
|
$scope.$emit('Local/TxProposalAction');
|
|
|
|
$timeout(function() {
|
|
|
|
$scope.$digest();
|
|
|
|
}, 1);
|
|
|
|
} else {
|
|
|
|
go.walletHome();
|
|
|
|
txStatus.notify(txp, function() {
|
|
|
|
$scope.$emit('Local/TxProposalAction', txp.status == 'broadcasted');
|
|
|
|
});
|
2016-01-29 11:39:32 -08:00
|
|
|
}
|
2016-01-27 11:41:12 -08:00
|
|
|
});
|
2015-04-23 08:27:43 -07:00
|
|
|
};
|
|
|
|
|
2015-12-02 07:21:26 -08:00
|
|
|
this.setForm = function(to, amount, comment) {
|
2015-04-23 08:27:43 -07:00
|
|
|
var form = $scope.sendForm;
|
|
|
|
if (to) {
|
|
|
|
form.address.$setViewValue(to);
|
|
|
|
form.address.$isValid = true;
|
|
|
|
form.address.$render();
|
|
|
|
this.lockAddress = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (amount) {
|
|
|
|
form.amount.$setViewValue("" + amount);
|
|
|
|
form.amount.$isValid = true;
|
|
|
|
form.amount.$render();
|
|
|
|
this.lockAmount = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (comment) {
|
|
|
|
form.comment.$setViewValue(comment);
|
|
|
|
form.comment.$isValid = true;
|
|
|
|
form.comment.$render();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-04-23 22:42:10 -07:00
|
|
|
this.resetForm = function() {
|
2015-04-23 08:27:43 -07:00
|
|
|
this.resetError();
|
2016-02-19 08:29:41 -08:00
|
|
|
this.paymentExpired = false;
|
2015-04-23 08:27:43 -07:00
|
|
|
this._paypro = null;
|
2015-12-23 13:05:22 -08:00
|
|
|
this.lockedCurrentFeePerKb = null;
|
2015-04-23 08:27:43 -07:00
|
|
|
|
|
|
|
this.lockAddress = false;
|
|
|
|
this.lockAmount = false;
|
|
|
|
|
|
|
|
this._amount = this._address = null;
|
|
|
|
|
2015-04-23 22:42:10 -07:00
|
|
|
var form = $scope.sendForm;
|
2015-08-13 10:54:53 -07:00
|
|
|
|
2015-04-23 08:27:43 -07:00
|
|
|
if (form && form.amount) {
|
|
|
|
form.amount.$pristine = true;
|
|
|
|
form.amount.$setViewValue('');
|
|
|
|
form.amount.$render();
|
|
|
|
|
|
|
|
form.comment.$setViewValue('');
|
|
|
|
form.comment.$render();
|
|
|
|
form.$setPristine();
|
|
|
|
|
|
|
|
if (form.address) {
|
|
|
|
form.address.$pristine = true;
|
|
|
|
form.address.$setViewValue('');
|
|
|
|
form.address.$render();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$timeout(function() {
|
|
|
|
$rootScope.$digest();
|
|
|
|
}, 1);
|
2016-02-04 05:33:41 -08:00
|
|
|
};
|
2015-04-23 08:27:43 -07:00
|
|
|
|
|
|
|
this.openPPModal = function(paypro) {
|
2015-09-30 10:14:15 -07:00
|
|
|
$rootScope.modalOpened = true;
|
2015-04-23 08:27:43 -07:00
|
|
|
var ModalInstanceCtrl = function($scope, $modalInstance) {
|
2015-04-23 11:23:21 -07:00
|
|
|
var fc = profileService.focusedClient;
|
2015-04-23 08:27:43 -07:00
|
|
|
var satToUnit = 1 / self.unitToSatoshi;
|
|
|
|
$scope.paypro = paypro;
|
|
|
|
$scope.alternative = self.alternativeAmount;
|
|
|
|
$scope.alternativeIsoCode = self.alternativeIsoCode;
|
|
|
|
$scope.isRateAvailable = self.isRateAvailable;
|
|
|
|
$scope.unitTotal = (paypro.amount * satToUnit).toFixed(self.unitDecimals);
|
|
|
|
$scope.unitName = self.unitName;
|
|
|
|
$scope.color = fc.backgroundColor;
|
|
|
|
|
|
|
|
$scope.cancel = function() {
|
|
|
|
$modalInstance.dismiss('cancel');
|
|
|
|
};
|
|
|
|
};
|
2015-05-07 15:02:38 -07:00
|
|
|
var modalInstance = $modal.open({
|
2015-04-23 08:27:43 -07:00
|
|
|
templateUrl: 'views/modals/paypro.html',
|
2015-09-30 22:13:33 -07:00
|
|
|
windowClass: animationService.modalAnimated.slideUp,
|
2015-04-23 08:27:43 -07:00
|
|
|
controller: ModalInstanceCtrl,
|
|
|
|
});
|
2015-05-07 15:02:38 -07:00
|
|
|
|
2015-09-30 10:14:15 -07:00
|
|
|
var disableCloseModal = $rootScope.$on('closeModal', function() {
|
|
|
|
modalInstance.dismiss('cancel');
|
|
|
|
});
|
|
|
|
|
2015-05-07 15:02:38 -07:00
|
|
|
modalInstance.result.finally(function() {
|
2015-09-30 10:14:15 -07:00
|
|
|
$rootScope.modalOpened = false;
|
|
|
|
disableCloseModal();
|
2015-05-07 15:02:38 -07:00
|
|
|
var m = angular.element(document.getElementsByClassName('reveal-modal'));
|
2015-09-30 22:13:33 -07:00
|
|
|
m.addClass(animationService.modalAnimated.slideOutDown);
|
2015-05-07 15:02:38 -07:00
|
|
|
});
|
2015-04-23 08:27:43 -07:00
|
|
|
};
|
|
|
|
|
2015-09-16 08:32:22 -07:00
|
|
|
this.setFromPayPro = function(uri, cb) {
|
|
|
|
if (!cb) cb = function() {};
|
|
|
|
|
2015-04-23 11:23:21 -07:00
|
|
|
var fc = profileService.focusedClient;
|
2015-04-23 08:27:43 -07:00
|
|
|
if (isChromeApp) {
|
2015-04-29 15:19:10 -07:00
|
|
|
this.error = gettext('Payment Protocol not supported on Chrome App');
|
2015-09-16 08:32:22 -07:00
|
|
|
return cb(true);
|
2015-04-23 08:27:43 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
var satToUnit = 1 / this.unitToSatoshi;
|
|
|
|
var self = this;
|
2015-04-30 09:03:30 -07:00
|
|
|
/// Get information of payment if using Payment Protocol
|
2016-01-06 12:19:31 -08:00
|
|
|
self.setOngoingProcess(gettextCatalog.getString('Fetching Payment Information'));
|
2015-04-23 08:27:43 -07:00
|
|
|
|
|
|
|
$log.debug('Fetch PayPro Request...', uri);
|
|
|
|
$timeout(function() {
|
|
|
|
fc.fetchPayPro({
|
|
|
|
payProUrl: uri,
|
|
|
|
}, function(err, paypro) {
|
2015-04-23 22:42:10 -07:00
|
|
|
self.setOngoingProcess();
|
2015-04-23 08:27:43 -07:00
|
|
|
|
|
|
|
if (err) {
|
2015-09-16 08:32:22 -07:00
|
|
|
$log.warn('Could not fetch payment request:', err);
|
2015-04-23 22:42:10 -07:00
|
|
|
self.resetForm();
|
2015-04-23 08:27:43 -07:00
|
|
|
var msg = err.toString();
|
|
|
|
if (msg.match('HTTP')) {
|
2015-04-29 15:19:10 -07:00
|
|
|
msg = gettext('Could not fetch payment information');
|
2015-04-23 08:27:43 -07:00
|
|
|
}
|
|
|
|
self.error = msg;
|
2015-09-18 08:07:51 -07:00
|
|
|
$timeout(function() {
|
|
|
|
$rootScope.$digest();
|
|
|
|
}, 1);
|
|
|
|
return cb(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!paypro.verified) {
|
|
|
|
self.resetForm();
|
2016-01-16 15:04:01 -08:00
|
|
|
$log.warn('Failed to verify payment protocol signatures');
|
2015-09-18 08:07:51 -07:00
|
|
|
self.error = gettext('Payment Protocol Invalid');
|
|
|
|
$timeout(function() {
|
|
|
|
$rootScope.$digest();
|
|
|
|
}, 1);
|
2015-09-16 08:32:22 -07:00
|
|
|
return cb(true);
|
2015-04-23 08:27:43 -07:00
|
|
|
}
|
2015-09-16 08:32:22 -07:00
|
|
|
|
|
|
|
self._paypro = paypro;
|
|
|
|
self.setForm(paypro.toAddress, (paypro.amount * satToUnit).toFixed(self.unitDecimals), paypro.memo);
|
2016-02-10 13:26:30 -08:00
|
|
|
_paymentTimeControl(paypro.expires);
|
2015-09-16 08:32:22 -07:00
|
|
|
return cb();
|
2015-04-23 08:27:43 -07:00
|
|
|
});
|
|
|
|
}, 1);
|
|
|
|
};
|
|
|
|
|
2016-02-10 13:26:30 -08:00
|
|
|
function _paymentTimeControl(timeToExpire) {
|
|
|
|
var now = Math.floor(Date.now() / 1000);
|
|
|
|
|
|
|
|
if (timeToExpire <= now) {
|
|
|
|
setExpiredPaymentValues();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.timeToExpire = timeToExpire;
|
2016-02-10 10:32:29 -08:00
|
|
|
var countDown = $interval(function() {
|
2016-02-10 13:26:30 -08:00
|
|
|
if (self.timeToExpire <= now) {
|
|
|
|
setExpiredPaymentValues();
|
2016-02-04 05:33:41 -08:00
|
|
|
$interval.cancel(countDown);
|
|
|
|
}
|
2016-02-10 13:26:30 -08:00
|
|
|
self.timeToExpire --;
|
2016-02-04 05:33:41 -08:00
|
|
|
}, 1000);
|
2016-02-10 13:26:30 -08:00
|
|
|
|
|
|
|
function setExpiredPaymentValues() {
|
|
|
|
self.paymentExpired = true;
|
|
|
|
self.timeToExpire = null;
|
|
|
|
self._paypro = null;
|
|
|
|
self.error = gettext('Cannot sign: The payment request has expired');
|
|
|
|
};
|
2016-02-04 05:33:41 -08:00
|
|
|
};
|
|
|
|
|
2015-04-23 08:27:43 -07:00
|
|
|
this.setFromUri = function(uri) {
|
2015-09-16 08:32:22 -07:00
|
|
|
var self = this;
|
2015-09-25 09:10:05 -07:00
|
|
|
|
2015-04-23 08:27:43 -07:00
|
|
|
function sanitizeUri(uri) {
|
|
|
|
// Fixes when a region uses comma to separate decimals
|
|
|
|
var regex = /[\?\&]amount=(\d+([\,\.]\d+)?)/i;
|
|
|
|
var match = regex.exec(uri);
|
|
|
|
if (!match || match.length === 0) {
|
|
|
|
return uri;
|
|
|
|
}
|
|
|
|
var value = match[0].replace(',', '.');
|
|
|
|
var newUri = uri.replace(regex, value);
|
|
|
|
return newUri;
|
|
|
|
};
|
|
|
|
|
|
|
|
var satToUnit = 1 / this.unitToSatoshi;
|
|
|
|
|
2015-09-29 08:51:08 -07:00
|
|
|
// URI extensions for Payment Protocol with non-backwards-compatible request
|
|
|
|
if ((/^bitcoin:\?r=[\w+]/).exec(uri)) {
|
|
|
|
uri = decodeURIComponent(uri.replace('bitcoin:?r=', ''));
|
|
|
|
this.setFromPayPro(uri, function(err) {
|
2015-09-29 08:27:14 -07:00
|
|
|
if (err) {
|
|
|
|
return err;
|
|
|
|
}
|
2015-09-25 09:10:05 -07:00
|
|
|
});
|
2015-09-29 08:27:14 -07:00
|
|
|
} else {
|
|
|
|
uri = sanitizeUri(uri);
|
2015-04-23 08:27:43 -07:00
|
|
|
|
2015-09-29 08:27:14 -07:00
|
|
|
if (!bitcore.URI.isValid(uri)) {
|
|
|
|
return uri;
|
|
|
|
}
|
|
|
|
var parsed = new bitcore.URI(uri);
|
2015-09-16 08:32:22 -07:00
|
|
|
|
2015-09-29 08:27:14 -07:00
|
|
|
var addr = parsed.address ? parsed.address.toString() : '';
|
|
|
|
var message = parsed.message;
|
2015-04-23 08:27:43 -07:00
|
|
|
|
2015-09-29 08:27:14 -07:00
|
|
|
var amount = parsed.amount ?
|
|
|
|
(parsed.amount.toFixed(0) * satToUnit).toFixed(this.unitDecimals) : 0;
|
2015-04-23 08:27:43 -07:00
|
|
|
|
2015-09-16 08:32:22 -07:00
|
|
|
|
2015-09-29 08:27:14 -07:00
|
|
|
if (parsed.r) {
|
|
|
|
this.setFromPayPro(parsed.r, function(err) {
|
|
|
|
if (err && addr && amount) {
|
|
|
|
self.setForm(addr, amount, message);
|
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
this.setForm(addr, amount, message);
|
|
|
|
return addr;
|
|
|
|
}
|
2015-09-16 08:32:22 -07:00
|
|
|
}
|
|
|
|
|
2015-04-23 08:27:43 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
this.onAddressChange = function(value) {
|
|
|
|
this.resetError();
|
|
|
|
if (!value) return '';
|
|
|
|
|
|
|
|
if (this._paypro)
|
|
|
|
return value;
|
|
|
|
|
|
|
|
if (value.indexOf('bitcoin:') === 0) {
|
|
|
|
return this.setFromUri(value);
|
|
|
|
} else if (/^https?:\/\//.test(value)) {
|
|
|
|
return this.setFromPayPro(value);
|
|
|
|
} else {
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-02-04 05:33:41 -08:00
|
|
|
// History
|
2015-04-23 08:27:43 -07:00
|
|
|
|
|
|
|
function strip(number) {
|
|
|
|
return (parseFloat(number.toPrecision(12)));
|
|
|
|
}
|
|
|
|
|
|
|
|
this.getUnitName = function() {
|
|
|
|
return this.unitName;
|
|
|
|
};
|
|
|
|
|
|
|
|
this.getAlternativeIsoCode = function() {
|
|
|
|
return this.alternativeIsoCode;
|
|
|
|
};
|
|
|
|
|
2016-02-10 12:35:26 -08:00
|
|
|
this.openTxModal = function(tx) {
|
2016-02-09 13:48:53 -08:00
|
|
|
$rootScope.$emit('Local/TxModal', tx);
|
|
|
|
};
|
|
|
|
|
2015-04-23 08:27:43 -07:00
|
|
|
this.hasAction = function(actions, action) {
|
|
|
|
return actions.hasOwnProperty('create');
|
|
|
|
};
|
|
|
|
|
2015-12-02 07:21:26 -08:00
|
|
|
this._doSendAll = function(amount) {
|
|
|
|
this.setForm(null, amount, null);
|
2015-06-19 11:00:27 -07:00
|
|
|
};
|
|
|
|
|
2015-12-23 13:05:22 -08:00
|
|
|
this.sendAll = function() {
|
2015-06-28 07:03:28 -07:00
|
|
|
var self = this;
|
2015-12-24 06:08:49 -08:00
|
|
|
self.error = null;
|
2016-01-06 12:19:31 -08:00
|
|
|
self.setOngoingProcess(gettextCatalog.getString('Calculating fee'));
|
2015-12-23 13:05:22 -08:00
|
|
|
$rootScope.$emit('Local/SetFeeSendMax', function(currentFeePerKb, availableMaxBalance, feeToSendMaxStr) {
|
2015-12-24 06:08:49 -08:00
|
|
|
self.setOngoingProcess();
|
|
|
|
if (lodash.isNull(currentFeePerKb)) {
|
|
|
|
self.error = gettext('Could not calculate fee');
|
|
|
|
$scope.$apply();
|
|
|
|
return;
|
|
|
|
}
|
2015-12-23 13:05:22 -08:00
|
|
|
self.lockedCurrentFeePerKb = currentFeePerKb;
|
|
|
|
var msg = gettextCatalog.getString("{{fee}} will be deducted for bitcoin networking fees", {
|
|
|
|
fee: feeToSendMaxStr
|
|
|
|
});
|
2015-06-28 07:03:28 -07:00
|
|
|
|
2015-12-24 06:08:49 -08:00
|
|
|
$scope.$apply();
|
2015-12-23 13:05:22 -08:00
|
|
|
confirmDialog.show(msg, function(confirmed) {
|
|
|
|
if (confirmed) {
|
|
|
|
self._doSendAll(availableMaxBalance);
|
2015-12-24 06:08:49 -08:00
|
|
|
} else {
|
|
|
|
self.resetForm();
|
|
|
|
}
|
2015-12-23 13:05:22 -08:00
|
|
|
});
|
2015-09-25 09:39:41 -07:00
|
|
|
});
|
2015-08-12 07:49:13 -07:00
|
|
|
};
|
2015-06-19 11:00:27 -07:00
|
|
|
|
2015-06-27 09:22:56 -07:00
|
|
|
/* Start setup */
|
2016-02-18 12:16:07 -08:00
|
|
|
lodash.assign(self, vanillaScope);
|
2015-06-19 11:00:27 -07:00
|
|
|
|
2015-05-11 11:25:42 -07:00
|
|
|
this.bindTouchDown();
|
2015-09-14 11:01:49 -07:00
|
|
|
if (profileService.focusedClient) {
|
|
|
|
this.setAddress();
|
|
|
|
this.setSendFormInputs();
|
|
|
|
}
|
2016-02-18 12:16:07 -08:00
|
|
|
|
2015-03-06 07:00:10 -08:00
|
|
|
});
|