Merge branch 'master' of https://github.com/bitpay/copay into feat/app-identity
This commit is contained in:
commit
9b3a3aab9d
213 changed files with 12663 additions and 7021 deletions
1
angular-bitcore-wallet-client/index.js
vendored
1
angular-bitcore-wallet-client/index.js
vendored
|
|
@ -36,6 +36,7 @@ bwcModule.provider("bwcService", function() {
|
|||
var bwc = new Client({
|
||||
baseUrl: opts.bwsurl || 'https://bws.bitpay.com/bws/api',
|
||||
verbose: opts.verbose,
|
||||
timeout: 100000,
|
||||
transports: ['polling'],
|
||||
});
|
||||
if (walletData)
|
||||
|
|
|
|||
|
|
@ -9,20 +9,20 @@
|
|||
"nameNoSpace": "bitpay",
|
||||
"nameCase": "BitPay",
|
||||
"nameCaseNoSpace": "BitPay",
|
||||
"gitHubRepoName": "bitpay-wallet",
|
||||
"gitHubRepoUrl": "git://github.com/bitpay/bitpay-wallet.git",
|
||||
"gitHubRepoBugs": "https://github.com/bitpay/bitpay-wallet/issues",
|
||||
"gitHubRepoName": "copay",
|
||||
"gitHubRepoUrl": "git://github.com/bitpay/copay.git",
|
||||
"gitHubRepoBugs": "https://github.com/bitpay/copay/issues",
|
||||
"disclaimerUrl": "",
|
||||
"url": "https://bitpay.com",
|
||||
"appDescription": "Secure Bitcoin Wallet",
|
||||
"winAppName": "BitPayWallet",
|
||||
"wpPublisherId": "{}",
|
||||
"wpProductId": "{}",
|
||||
"windowsAppId": "",
|
||||
"windowsAppId": "2d1002d7-ee34-4f60-bd29-0c871ba0c195",
|
||||
"pushSenderId": "1036948132229",
|
||||
"description": "Secure Bitcoin Wallet",
|
||||
"version": "1.0.1",
|
||||
"androidVersion": "1",
|
||||
"version": "1.2.1",
|
||||
"androidVersion": "12100",
|
||||
"_extraCSS": null,
|
||||
"_enabledExtensions": {
|
||||
"coinbase": true,
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@
|
|||
<variable name="SENDER_ID" value="*PUSHSENDERID*"/>
|
||||
</plugin>
|
||||
<plugin name="cordova-custom-config" spec="~3.0.5" />
|
||||
<plugin name="cordova-plugin-queries-schemes" spec="~0.1.5" />
|
||||
|
||||
<!-- Supported Platforms -->
|
||||
<engine name="ios" spec="~4.2.1" />
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@
|
|||
"bezier-easing": "^2.0.3",
|
||||
"bhttp": "^1.2.1",
|
||||
"bitauth": "^0.3.2",
|
||||
"bitcore-wallet-client": "4.3.2",
|
||||
"bitcore-wallet-client": "4.4.0",
|
||||
"bower": "^1.7.9",
|
||||
"chai": "^3.5.0",
|
||||
"cordova-android": "5.1.1",
|
||||
|
|
@ -87,6 +87,7 @@
|
|||
"start": "npm run build:www && ionic serve --nolivereload --nogulp -s",
|
||||
"start:ios": "npm run build:www && npm run build:ios && npm run open:ios",
|
||||
"start:android": "npm run build:www && npm run build:android && npm run run:android",
|
||||
"start:desktop": "npm start",
|
||||
"watch": "grunt watch",
|
||||
"build:www": "grunt",
|
||||
"build:www-release": "grunt prod",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#define MyAppVersion "*VERSION*"
|
||||
#define MyAppPublisher "BitPay"
|
||||
#define MyAppURL "*URL*"
|
||||
#define MyAppExeName "*PACKAGENAME*.exe"
|
||||
#define MyAppExeName "*USERVISIBLENAME*.exe"
|
||||
#define AppId "*WINDOWSAPPID*"
|
||||
|
||||
[Setup]
|
||||
|
|
@ -19,7 +19,7 @@ AppSupportURL={#MyAppURL}
|
|||
AppUpdatesURL={#MyAppURL}
|
||||
DefaultDirName={pf}\{#MyAppName}
|
||||
DefaultGroupName={#MyAppName}
|
||||
OutputBaseFilename=*PACKAGENAME*-win
|
||||
OutputBaseFilename=*USERVISIBLENAME*-win
|
||||
OutputDir=./
|
||||
Compression=lzma
|
||||
SolidCompression=yes
|
||||
|
|
@ -33,9 +33,9 @@ Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl"
|
|||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
|
||||
|
||||
[Files]
|
||||
Source: "*PACKAGENAME*\win64\*PACKAGENAME*.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "*PACKAGENAME*\win64\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
Source: "../www/img/icons/favicon.ico"; DestDir: "{app}"; DestName: "icon.ico"; Flags: ignoreversion
|
||||
Source: "*USERVISIBLENAME*\win64\*USERVISIBLENAME*.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "*USERVISIBLENAME*\win64\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
Source: "../www/img/app/favicon.ico"; DestDir: "{app}"; DestName: "icon.ico"; Flags: ignoreversion
|
||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||
|
||||
[Icons]
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ Copay is a Multisig HD Wallet. Copay app holds the extended private keys for the
|
|||
|
||||
### Wallet Recovery Scope
|
||||
* Basic Recovery: Wallet access is restored. It is possible to see wallet balance and past transactions. It is possible to send and receive payments.
|
||||
* Full Recovery: All the features of Partial Recovery + wallet name, copayer names are recovered, past payment proposal metadata (who signed, and notes) are recoved.
|
||||
* Full Recovery: All the features of Partial Recovery + wallet name, copayer names are recovered, past payment proposal metadata (who signed, and notes) are recovered.
|
||||
|
||||
## Wallet Restore Scenarios
|
||||
|
||||
|
|
|
|||
|
|
@ -40,10 +40,10 @@ var local_file3 = fs.createReadStream(local_file_name3)
|
|||
|
||||
// obtain the crowdin api key
|
||||
var crowdin_api_key = fs.readFileSync(path.join(__dirname, 'crowdin_api_key.txt'))
|
||||
//console.log('api key: ' + crowdin_api_key);
|
||||
//console.log('api key: ' + crowdin_api_key);
|
||||
|
||||
if (crowdin_api_key != '') {
|
||||
|
||||
|
||||
var payload = {
|
||||
'files[template.pot]': local_file1,
|
||||
'files[appstore/appstore_en.txt]': local_file2,
|
||||
|
|
@ -51,8 +51,9 @@ if (crowdin_api_key != '') {
|
|||
};
|
||||
|
||||
bhttp.post('https://api.crowdin.com/api/project/' + crowdin_identifier + '/update-file?key=' + crowdin_api_key, payload, {}, function(err, response) {
|
||||
console.log('\nResponse from update file call:\n', response.body.toString());
|
||||
|
||||
if (!err) console.log('\nResponse from update file call:\n', response.body.toString());
|
||||
else console.log('\nError from update file call:\n', err.toString());
|
||||
|
||||
// This call will tell the server to generate a new zip file for you based on most recent translations.
|
||||
https.get('https://api.crowdin.com/api/project/' + crowdin_identifier + '/export?key=' + crowdin_api_key, function(res) {
|
||||
console.log('Export Got response: ' + res.statusCode);
|
||||
|
|
|
|||
3308
i18n/po/es.po
3308
i18n/po/es.po
File diff suppressed because it is too large
Load diff
4956
i18n/po/fr.po
4956
i18n/po/fr.po
File diff suppressed because it is too large
Load diff
3182
i18n/po/template.pot
3182
i18n/po/template.pot
File diff suppressed because it is too large
Load diff
|
|
@ -26,7 +26,10 @@ angular.module('copayApp.controllers').controller('activityController',
|
|||
|
||||
$scope.openNotificationModal = function(n) {
|
||||
if (n.txid) {
|
||||
openTxModal(n);
|
||||
$state.transitionTo('tabs.wallet.tx-details', {
|
||||
txid: n.txid,
|
||||
walletId: n.walletId
|
||||
});
|
||||
} else {
|
||||
var txp = lodash.find($scope.txps, {
|
||||
id: n.txpId
|
||||
|
|
@ -46,35 +49,4 @@ angular.module('copayApp.controllers').controller('activityController',
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
var openTxModal = function(n) {
|
||||
var wallet = profileService.getWallet(n.walletId);
|
||||
|
||||
ongoingProcess.set('loadingTxInfo', true);
|
||||
walletService.getTx(wallet, n.txid, function(err, tx) {
|
||||
ongoingProcess.set('loadingTxInfo', false);
|
||||
|
||||
if (err) {
|
||||
$log.error(err);
|
||||
return popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||
}
|
||||
|
||||
if (!tx) {
|
||||
$log.warn('No tx found');
|
||||
return popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Transaction not found'));
|
||||
}
|
||||
|
||||
$scope.wallet = wallet;
|
||||
$scope.btx = lodash.cloneDeep(tx);
|
||||
$state.transitionTo('tabs.wallet.tx-details', {
|
||||
txid: $scope.btx.txid,
|
||||
walletId: $scope.walletId
|
||||
});
|
||||
|
||||
walletService.getTxNote(wallet, n.txid, function(err, note) {
|
||||
if (err) $log.warn('Could not fetch transaction note: ' + err);
|
||||
$scope.btx.note = note;
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('addressbookListController', function($scope, $log, $timeout, addressbookService, lodash, popupService) {
|
||||
angular.module('copayApp.controllers').controller('addressbookListController', function($scope, $log, $timeout, addressbookService, lodash, popupService, gettextCatalog) {
|
||||
|
||||
var contacts;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('addressbookAddController', function($scope, $state, $stateParams, $timeout, $ionicHistory, addressbookService, popupService) {
|
||||
angular.module('copayApp.controllers').controller('addressbookAddController', function($scope, $state, $stateParams, $timeout, $ionicHistory, gettextCatalog, addressbookService, popupService) {
|
||||
|
||||
$scope.fromSendTab = $stateParams.fromSendTab;
|
||||
|
||||
|
|
|
|||
199
src/js/controllers/addresses.js
Normal file
199
src/js/controllers/addresses.js
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('addressesController', function($scope, $stateParams, $state, $timeout, $ionicHistory, $ionicPopover, $ionicScrollDelegate, configService, popupService, gettextCatalog, ongoingProcess, lodash, profileService, walletService, platformInfo) {
|
||||
var UNUSED_ADDRESS_LIMIT = 5;
|
||||
var BALANCE_ADDRESS_LIMIT = 5;
|
||||
var MENU_ITEM_HEIGHT = 55;
|
||||
var config;
|
||||
var unitName;
|
||||
var unitToSatoshi;
|
||||
var satToUnit;
|
||||
var unitDecimals;
|
||||
var withBalance;
|
||||
$scope.showInfo = false;
|
||||
$scope.showMore = false;
|
||||
$scope.allAddressesView = false;
|
||||
$scope.isCordova = platformInfo.isCordova;
|
||||
$scope.wallet = profileService.getWallet($stateParams.walletId);
|
||||
|
||||
function init() {
|
||||
ongoingProcess.set('gettingAddresses', true);
|
||||
walletService.getMainAddresses($scope.wallet, {}, function(err, addresses) {
|
||||
if (err) {
|
||||
ongoingProcess.set('gettingAddresses', false);
|
||||
return popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||
}
|
||||
|
||||
var allAddresses = addresses;
|
||||
|
||||
walletService.getBalance($scope.wallet, {}, function(err, resp) {
|
||||
ongoingProcess.set('gettingAddresses', false);
|
||||
if (err) {
|
||||
return popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||
}
|
||||
|
||||
withBalance = resp.byAddress;
|
||||
var idx = lodash.indexBy(withBalance, 'address');
|
||||
$scope.noBalance = lodash.reject(allAddresses, function(x) {
|
||||
return idx[x.address];
|
||||
});
|
||||
|
||||
processPaths($scope.noBalance);
|
||||
processPaths(withBalance);
|
||||
|
||||
$scope.latestUnused = lodash.slice($scope.noBalance, 0, UNUSED_ADDRESS_LIMIT);
|
||||
$scope.latestWithBalance = lodash.slice(withBalance, 0, BALANCE_ADDRESS_LIMIT);
|
||||
|
||||
lodash.each(withBalance, function(a) {
|
||||
a.balanceStr = (a.amount * satToUnit).toFixed(unitDecimals) + ' ' + unitName;
|
||||
});
|
||||
|
||||
$scope.viewAll = {
|
||||
value: $scope.noBalance.length > UNUSED_ADDRESS_LIMIT || withBalance.length > BALANCE_ADDRESS_LIMIT
|
||||
};
|
||||
$scope.allAddresses = $scope.noBalance.concat(withBalance);
|
||||
$scope.$digest();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function processPaths(list) {
|
||||
lodash.each(list, function(n) {
|
||||
n.path = n.path.replace(/^m/g, 'xpub');
|
||||
});
|
||||
};
|
||||
|
||||
$scope.newAddress = function() {
|
||||
if ($scope.gapReached) return;
|
||||
|
||||
ongoingProcess.set('generatingNewAddress', true);
|
||||
walletService.getAddress($scope.wallet, true, function(err, addr) {
|
||||
if (err) {
|
||||
ongoingProcess.set('generatingNewAddress', false);
|
||||
$scope.gapReached = true;
|
||||
$timeout(function() {
|
||||
$scope.$digest();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
walletService.getMainAddresses($scope.wallet, {
|
||||
limit: 1
|
||||
}, function(err, _addr) {
|
||||
ongoingProcess.set('generatingNewAddress', false);
|
||||
if (err) return popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||
if (addr != _addr[0].address) return popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('New address could not be generated. Please try again.'));
|
||||
|
||||
$scope.noBalance = [_addr[0]].concat($scope.noBalance);
|
||||
$scope.latestUnused = lodash.slice($scope.noBalance, 0, UNUSED_ADDRESS_LIMIT);
|
||||
$scope.viewAll = {
|
||||
value: $scope.noBalance.length > UNUSED_ADDRESS_LIMIT
|
||||
};
|
||||
$scope.$digest();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$scope.viewAllAddresses = function() {
|
||||
$state.go('tabs.receive.allAddresses', {
|
||||
walletId: $scope.wallet.id
|
||||
});
|
||||
};
|
||||
|
||||
$scope.showInformation = function() {
|
||||
$timeout(function() {
|
||||
$scope.showInfo = !$scope.showInfo;
|
||||
$ionicScrollDelegate.resize();
|
||||
}, 10);
|
||||
};
|
||||
|
||||
$scope.readMore = function() {
|
||||
$timeout(function() {
|
||||
$scope.showMore = !$scope.showMore;
|
||||
$ionicScrollDelegate.resize();
|
||||
}, 10);
|
||||
};
|
||||
|
||||
$scope.showMenu = function(allAddresses, $event) {
|
||||
var scanObj = {
|
||||
text: gettextCatalog.getString('Scan addresses for funds'),
|
||||
action: scan,
|
||||
};
|
||||
|
||||
var sendAddressesObj = {
|
||||
text: gettextCatalog.getString('Send addresses by email'),
|
||||
action: sendByEmail,
|
||||
}
|
||||
|
||||
$scope.items = allAddresses ? [sendAddressesObj] : [scanObj];
|
||||
$scope.height = $scope.items.length * MENU_ITEM_HEIGHT;
|
||||
|
||||
$ionicPopover.fromTemplateUrl('views/includes/menu-popover.html', {
|
||||
scope: $scope
|
||||
}).then(function(popover) {
|
||||
$scope.menu = popover;
|
||||
$scope.menu.show($event);
|
||||
});
|
||||
};
|
||||
|
||||
var scan = function() {
|
||||
walletService.startScan($scope.wallet);
|
||||
$scope.menu.hide();
|
||||
$ionicHistory.clearHistory();
|
||||
$state.go('tabs.home');
|
||||
};
|
||||
|
||||
var sendByEmail = function() {
|
||||
function formatDate(ts) {
|
||||
var dateObj = new Date(ts * 1000);
|
||||
if (!dateObj) {
|
||||
$log.debug('Error formating a date');
|
||||
return 'DateError';
|
||||
}
|
||||
if (!dateObj.toJSON()) {
|
||||
return '';
|
||||
}
|
||||
return dateObj.toJSON();
|
||||
};
|
||||
|
||||
ongoingProcess.set('sendingByEmail', true);
|
||||
$timeout(function() {
|
||||
var body = 'Copay Wallet "' + $scope.walletName + '" Addresses\n Only Main Addresses are shown.\n\n';
|
||||
body += "\n";
|
||||
body += $scope.allAddresses.map(function(v) {
|
||||
return ('* ' + v.address + ' ' + 'xpub' + v.path.substring(1) + ' ' + formatDate(v.createdOn));
|
||||
}).join("\n");
|
||||
ongoingProcess.set('sendingByEmail', false);
|
||||
|
||||
window.plugins.socialsharing.shareViaEmail(
|
||||
body,
|
||||
'Copay Addresses',
|
||||
null, // TO: must be null or an array
|
||||
null, // CC: must be null or an array
|
||||
null, // BCC: must be null or an array
|
||||
null, // FILES: can be null, a string, or an array
|
||||
function() {},
|
||||
function() {}
|
||||
);
|
||||
|
||||
$scope.menu.hide();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||
$scope.allAddressesView = data.stateName == 'tabs.receive.allAddresses' ? true : false;
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
});
|
||||
});
|
||||
|
||||
$scope.$on("$ionicView.afterEnter", function(event, data) {
|
||||
config = configService.getSync().wallet.settings;
|
||||
unitToSatoshi = config.unitToSatoshi;
|
||||
satToUnit = 1 / unitToSatoshi;
|
||||
unitName = config.unitName;
|
||||
unitDecimals = config.unitDecimals;
|
||||
|
||||
if (!$scope.allAddresses || $scope.allAddresses.length < 0) init();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('advancedSettingsController', function($scope, $rootScope, $log, $window, lodash, configService, uxLanguage, platformInfo, pushNotificationsService, profileService, feeService) {
|
||||
angular.module('copayApp.controllers').controller('advancedSettingsController', function($scope, $rootScope, $log, $window, lodash, configService, uxLanguage, platformInfo, pushNotificationsService, profileService, feeService, storageService, $ionicHistory, $timeout, $ionicScrollDelegate) {
|
||||
|
||||
var updateConfig = function() {
|
||||
|
||||
|
|
@ -29,6 +29,50 @@ angular.module('copayApp.controllers').controller('advancedSettingsController',
|
|||
};
|
||||
};
|
||||
|
||||
$scope.global = $rootScope;
|
||||
if (!$scope.global.developmentUtilitiesEnabled) {
|
||||
$scope.global.developmentUtilitiesEnabled = {
|
||||
value: false
|
||||
};
|
||||
}
|
||||
|
||||
$scope.toggledDevelopmentUtils = function() {
|
||||
if ($scope.global.developmentUtilitiesEnabled.value) {
|
||||
$log.debug('User enabled development utilities.');
|
||||
$timeout(function() {
|
||||
$ionicScrollDelegate.resize();
|
||||
}, 10);
|
||||
} else {
|
||||
$log.debug('User disabled development utilities.');
|
||||
}
|
||||
}
|
||||
|
||||
$scope.activateFeedbackCard = function() {
|
||||
$scope.feedbackCardActivating = true;
|
||||
storageService.getFeedbackInfo(function(error, info) {
|
||||
var feedbackInfo = JSON.parse(info);
|
||||
// hardcoding so we can distinguish from normal operation
|
||||
feedbackInfo.time = 1231006505; // genesis block time
|
||||
feedbackInfo.version = window.version;
|
||||
feedbackInfo.sent = false;
|
||||
storageService.setFeedbackInfo(JSON.stringify(feedbackInfo), function() {
|
||||
$log.debug('Activated feedback card with: ' + JSON.stringify(feedbackInfo));
|
||||
$ionicHistory.clearCache();
|
||||
$timeout(function() {
|
||||
$scope.feedbackCardActivating = false;
|
||||
$scope.feedbackCardActivated = true;
|
||||
$timeout(function() {
|
||||
$scope.feedbackCardActivated = false;
|
||||
}, 10000);
|
||||
}, 500);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$scope.resetActivateFeedbackCard = function() {
|
||||
$scope.feedbackCardActivated = false;
|
||||
}
|
||||
|
||||
$scope.spendUnconfirmedChange = function() {
|
||||
var opts = {
|
||||
wallet: {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('amazonController',
|
||||
function($scope, $timeout, $ionicModal, $log, lodash, bwcError, amazonService, platformInfo, externalLinkService, popupService) {
|
||||
function($scope, $timeout, $ionicModal, $log, lodash, amazonService, platformInfo, externalLinkService, popupService, gettextCatalog) {
|
||||
|
||||
$scope.network = amazonService.getEnvironment();
|
||||
|
||||
$scope.openExternalLink = function(url, optIn, title, message, okText, cancelText) {
|
||||
externalLinkService.open(url, optIn, title, message, okText, cancelText);
|
||||
$scope.openExternalLink = function(url) {
|
||||
externalLinkService.open(url);
|
||||
};
|
||||
|
||||
var initAmazon = function() {
|
||||
|
|
@ -19,6 +19,16 @@ angular.module('copayApp.controllers').controller('amazonController',
|
|||
$timeout(function() {
|
||||
$scope.$digest();
|
||||
});
|
||||
if ($scope.cardClaimCode) {
|
||||
var card = lodash.find($scope.giftCards, {
|
||||
claimCode: $scope.cardClaimCode
|
||||
});
|
||||
if (lodash.isEmpty(card)) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Card not found'));
|
||||
return;
|
||||
}
|
||||
$scope.openCardModal(card);
|
||||
}
|
||||
});
|
||||
$scope.updatePendingGiftCards();
|
||||
};
|
||||
|
|
@ -26,12 +36,16 @@ angular.module('copayApp.controllers').controller('amazonController',
|
|||
$scope.updatePendingGiftCards = lodash.debounce(function() {
|
||||
|
||||
amazonService.getPendingGiftCards(function(err, gcds) {
|
||||
$timeout(function() {
|
||||
$scope.giftCards = gcds;
|
||||
$scope.$digest();
|
||||
});
|
||||
lodash.forEach(gcds, function(dataFromStorage) {
|
||||
if (dataFromStorage.status == 'PENDING') {
|
||||
$log.debug("creating gift card");
|
||||
amazonService.createGiftCard(dataFromStorage, function(err, giftCard) {
|
||||
if (err) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err));
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||
return;
|
||||
}
|
||||
if (giftCard.status != 'PENDING') {
|
||||
|
|
@ -84,6 +98,7 @@ angular.module('copayApp.controllers').controller('amazonController',
|
|||
};
|
||||
|
||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||
$scope.cardClaimCode = data.stateParams.cardClaimCode;
|
||||
initAmazon();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,34 +1,51 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('amountController', function($rootScope, $scope, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, platformInfo, lodash, configService, rateService, $stateParams, $window, $state, $log, txFormatService, ongoingProcess, bitpayCardService, popupService, bwcError, payproService) {
|
||||
|
||||
angular.module('copayApp.controllers').controller('amountController', function($scope, $filter, $timeout, $ionicScrollDelegate, $ionicHistory, $ionicPopover, gettextCatalog, platformInfo, lodash, configService, rateService, $stateParams, $window, $state, $log, txFormatService, ongoingProcess, bitpayCardService, popupService, bwcError, payproService, profileService, bitcore, amazonService, glideraService) {
|
||||
var unitToSatoshi;
|
||||
var satToUnit;
|
||||
var unitDecimals;
|
||||
var satToBtc;
|
||||
var self = $scope.self;
|
||||
var SMALL_FONT_SIZE_LIMIT = 10;
|
||||
var LENGTH_EXPRESSION_LIMIT = 19;
|
||||
var MENU_ITEM_HEIGHT = 55;
|
||||
|
||||
$scope.$on('$ionicView.leave', function() {
|
||||
angular.element($window).off('keydown');
|
||||
});
|
||||
|
||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||
$scope.isGiftCard = data.stateParams.isGiftCard;
|
||||
|
||||
// Glidera parameters
|
||||
$scope.isGlidera = data.stateParams.isGlidera;
|
||||
$scope.glideraAccessToken = data.stateParams.glideraAccessToken;
|
||||
|
||||
$scope.isWallet = data.stateParams.isWallet;
|
||||
$scope.cardId = data.stateParams.cardId;
|
||||
$scope.showMenu = $ionicHistory.backView().stateName == 'tabs.send';
|
||||
var isWallet = data.stateParams.isWallet || 'false';
|
||||
$scope.isWallet = (isWallet.toString().trim().toLowerCase() == 'true' ? true : false);
|
||||
$scope.toAddress = data.stateParams.toAddress;
|
||||
$scope.toName = data.stateParams.toName;
|
||||
$scope.toEmail = data.stateParams.toEmail;
|
||||
$scope.showAlternativeAmount = !!$scope.cardId;
|
||||
$scope.showAlternativeAmount = !!$scope.cardId || !!$scope.isGiftCard || !!$scope.isGlidera;
|
||||
$scope.toColor = data.stateParams.toColor;
|
||||
|
||||
if (!$scope.cardId && !$stateParams.toAddress) {
|
||||
$scope.customAmount = data.stateParams.customAmount;
|
||||
|
||||
if (!$scope.cardId && !$scope.isGiftCard && !$scope.isGlidera && !data.stateParams.toAddress) {
|
||||
$log.error('Bad params at amount')
|
||||
throw ('bad params');
|
||||
}
|
||||
|
||||
if ($scope.isGlidera) {
|
||||
glideraService.getLimits($scope.glideraAccessToken, function(err, limits) {
|
||||
$scope.limits = limits;
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var reNr = /^[1234567890\.]$/;
|
||||
var reOp = /^[\*\+\-\/]$/;
|
||||
|
||||
|
|
@ -49,8 +66,7 @@ angular.module('copayApp.controllers').controller('amountController', function($
|
|||
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
}, 10);
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
var config = configService.getSync().wallet.settings;
|
||||
|
|
@ -77,6 +93,35 @@ angular.module('copayApp.controllers').controller('amountController', function($
|
|||
}, 10);
|
||||
});
|
||||
|
||||
$scope.showSendMaxMenu = function($event) {
|
||||
var sendMaxObj = {
|
||||
text: gettextCatalog.getString('Send max amount'),
|
||||
action: setSendMax,
|
||||
};
|
||||
|
||||
$scope.items = [sendMaxObj];
|
||||
$scope.height = $scope.items.length * MENU_ITEM_HEIGHT;
|
||||
|
||||
$ionicPopover.fromTemplateUrl('views/includes/menu-popover.html', {
|
||||
scope: $scope
|
||||
}).then(function(popover) {
|
||||
$scope.menu = popover;
|
||||
$scope.menu.show($event);
|
||||
});
|
||||
};
|
||||
|
||||
function setSendMax() {
|
||||
$scope.menu.hide();
|
||||
$state.transitionTo('tabs.send.confirm', {
|
||||
isWallet: $scope.isWallet,
|
||||
toAmount: null,
|
||||
toAddress: $scope.toAddress,
|
||||
toName: $scope.toName,
|
||||
toEmail: $scope.toEmail,
|
||||
useSendMax: true,
|
||||
});
|
||||
};
|
||||
|
||||
$scope.toggleAlternative = function() {
|
||||
$scope.showAlternativeAmount = !$scope.showAlternativeAmount;
|
||||
|
||||
|
|
@ -121,7 +166,6 @@ angular.module('copayApp.controllers').controller('amountController', function($
|
|||
|
||||
function isExpression(val) {
|
||||
var regex = /^\.?\d+(\.?\d+)?([\/\-\+\*x]\d?\.?\d+)+$/;
|
||||
|
||||
return regex.test(val);
|
||||
};
|
||||
|
||||
|
|
@ -134,7 +178,6 @@ angular.module('copayApp.controllers').controller('amountController', function($
|
|||
$scope.resetAmount = function() {
|
||||
$scope.amount = $scope.alternativeResult = $scope.amountResult = $scope.globalResult = '';
|
||||
$scope.allowSend = false;
|
||||
|
||||
checkFontSize();
|
||||
};
|
||||
|
||||
|
|
@ -189,6 +232,20 @@ angular.module('copayApp.controllers').controller('amountController', function($
|
|||
return result.replace('x', '*');
|
||||
};
|
||||
|
||||
$scope.getRates = function() {
|
||||
bitpayCardService.getRates($scope.alternativeIsoCode, function(err, res) {
|
||||
if (err) {
|
||||
$log.warn(err);
|
||||
return;
|
||||
}
|
||||
if ($scope.unitName == 'bits') {
|
||||
$scope.exchangeRate = '1,000,000 bits ~ ' + res.rate + ' ' + $scope.alternativeIsoCode;
|
||||
} else {
|
||||
$scope.exchangeRate = '1 BTC ~ ' + res.rate + ' ' + $scope.alternativeIsoCode;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.finish = function() {
|
||||
var _amount = evaluate(format($scope.amount));
|
||||
|
||||
|
|
@ -199,6 +256,7 @@ angular.module('copayApp.controllers').controller('amountController', function($
|
|||
amount: amountUSD,
|
||||
currency: 'USD'
|
||||
};
|
||||
|
||||
ongoingProcess.set('Preparing transaction...', true);
|
||||
$timeout(function() {
|
||||
|
||||
|
|
@ -238,15 +296,87 @@ angular.module('copayApp.controllers').controller('amountController', function($
|
|||
});
|
||||
});
|
||||
|
||||
} else if ($scope.isGiftCard) {
|
||||
ongoingProcess.set('Preparing transaction...', true);
|
||||
// Get first wallet as UUID
|
||||
var uuid;
|
||||
try {
|
||||
uuid = profileService.getWallets({
|
||||
onlyComplete: true,
|
||||
network: 'livenet',
|
||||
})[0].id;
|
||||
} catch (err) {
|
||||
ongoingProcess.set('Preparing transaction...', false);
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('No wallet found!'));
|
||||
return;
|
||||
};
|
||||
var amountUSD = $scope.showAlternativeAmount ? _amount : $filter('formatFiatAmount')(toFiat(_amount));
|
||||
var dataSrc = {
|
||||
currency: 'USD',
|
||||
amount: amountUSD,
|
||||
uuid: uuid
|
||||
};
|
||||
|
||||
amazonService.createBitPayInvoice(dataSrc, function(err, dataInvoice) {
|
||||
if (err) {
|
||||
ongoingProcess.set('Preparing transaction...', false);
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err));
|
||||
return;
|
||||
}
|
||||
|
||||
amazonService.getBitPayInvoice(dataInvoice.invoiceId, function(err, invoice) {
|
||||
if (err) {
|
||||
ongoingProcess.set('Preparing transaction...', false);
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err));
|
||||
return;
|
||||
}
|
||||
|
||||
var payProUrl = invoice.paymentUrls.BIP73;
|
||||
|
||||
payproService.getPayProDetails(payProUrl, function(err, payProDetails) {
|
||||
ongoingProcess.set('Preparing transaction...', false);
|
||||
if (err) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err));
|
||||
return;
|
||||
}
|
||||
var stateParams = {
|
||||
giftCardAmountUSD: amountUSD,
|
||||
giftCardAccessKey: dataInvoice.accessKey,
|
||||
giftCardInvoiceTime: invoice.invoiceTime,
|
||||
giftCardUUID: dataSrc.uuid,
|
||||
toAmount: payProDetails.amount,
|
||||
toAddress: payProDetails.toAddress,
|
||||
description: payProDetails.memo,
|
||||
paypro: payProDetails
|
||||
};
|
||||
|
||||
$state.transitionTo('tabs.giftcards.amazon.confirm', stateParams);
|
||||
}, true);
|
||||
});
|
||||
});
|
||||
} else if ($scope.isGlidera) {
|
||||
var amount = $scope.showAlternativeAmount ? fromFiat(_amount) : _amount;
|
||||
$state.transitionTo('tabs.buyandsell.glidera.confirm', {
|
||||
toAmount: (amount * unitToSatoshi).toFixed(0),
|
||||
isGlidera: $scope.isGlidera,
|
||||
glideraAccessToken: $scope.glideraAccessToken
|
||||
});
|
||||
} else {
|
||||
var amount = $scope.showAlternativeAmount ? fromFiat(_amount) : _amount;
|
||||
$state.transitionTo('tabs.send.confirm', {
|
||||
isWallet: $scope.isWallet,
|
||||
toAmount: (amount * unitToSatoshi).toFixed(0),
|
||||
toAddress: $scope.toAddress,
|
||||
toName: $scope.toName,
|
||||
toEmail: $scope.toEmail
|
||||
});
|
||||
if ($scope.customAmount) {
|
||||
$state.transitionTo('tabs.receive.customAmount', {
|
||||
toAmount: (amount * unitToSatoshi).toFixed(0),
|
||||
toAddress: $scope.toAddress
|
||||
});
|
||||
} else {
|
||||
$state.transitionTo('tabs.send.confirm', {
|
||||
isWallet: $scope.isWallet,
|
||||
toAmount: (amount * unitToSatoshi).toFixed(0),
|
||||
toAddress: $scope.toAddress,
|
||||
toName: $scope.toName,
|
||||
toEmail: $scope.toEmail
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ angular.module('copayApp.controllers').controller('backupController',
|
|||
|
||||
var showBackupResult = function() {
|
||||
if ($scope.backupError) {
|
||||
var title = 'Uh oh...';
|
||||
var title = gettextCatalog.getString('Uh oh...');
|
||||
var message = gettextCatalog.getString("It's important that you write your backup phrase down correctly. If something happens to your wallet, you'll need this backup to recover your money. Please review your backup and try again.");
|
||||
popupService.showAlert(title, message, function() {
|
||||
$scope.setFlow(2);
|
||||
|
|
|
|||
|
|
@ -63,7 +63,9 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi
|
|||
|
||||
if (err) {
|
||||
$log.error(err);
|
||||
$scope.error = gettextCatalog.getString('Could not get transactions');
|
||||
self.bitpayCardTransactionHistory = null;
|
||||
self.bitpayCardCurrentBalance = null;
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Could not get transactions'));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ angular.module('copayApp.controllers').controller('bitpayCardIntroController', f
|
|||
popupService.showConfirm(title, msg, ok, cancel, function(res) {
|
||||
if (res) {
|
||||
// Set flag for nextStep
|
||||
storageService.setNextStep('BitpayCard', true, function(err) {});
|
||||
storageService.setNextStep('BitpayCard', 'true', function(err) {});
|
||||
// Save data
|
||||
bitpayCardService.setBitpayDebitCards(data, function(err) {
|
||||
if (err) return;
|
||||
|
|
|
|||
|
|
@ -1,224 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('buyAmazonController',
|
||||
function($scope, $log, $timeout, $state, lodash, profileService, bwcError, gettextCatalog, configService, walletService, amazonService, ongoingProcess, platformInfo, externalLinkService, popupService) {
|
||||
|
||||
var self = this;
|
||||
var network = amazonService.getEnvironment();
|
||||
var wallet;
|
||||
|
||||
$scope.$on('Wallet/Changed', function(event, w) {
|
||||
if (lodash.isEmpty(w)) {
|
||||
$log.debug('No wallet provided');
|
||||
return;
|
||||
}
|
||||
wallet = w;
|
||||
$log.debug('Wallet changed: ' + w.name);
|
||||
});
|
||||
|
||||
$scope.openExternalLink = function(url, optIn, title, message, okText, cancelText) {
|
||||
externalLinkService.open(url, optIn, title, message, okText, cancelText);
|
||||
};
|
||||
|
||||
this.confirm = function() {
|
||||
var message = gettextCatalog.getString('Amazon.com Gift Card purchase for ${{amount}} USD', {
|
||||
amount: $scope.formData.fiat
|
||||
});
|
||||
var ok = gettextCatalog.getString('Buy');
|
||||
popupService.showConfirm(null, message, ok, null, function(res) {
|
||||
if (res) self.createTx();
|
||||
});
|
||||
};
|
||||
|
||||
this.createTx = function() {
|
||||
self.errorInfo = null;
|
||||
|
||||
if (lodash.isEmpty(wallet)) return;
|
||||
|
||||
if (!wallet.canSign() && !wallet.isPrivKeyExternal()) {
|
||||
$log.info('No signing proposal: No private key');
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg('MISSING_PRIVATE_KEY'));
|
||||
return;
|
||||
}
|
||||
|
||||
var dataSrc = {
|
||||
currency: 'USD',
|
||||
amount: $scope.formData.fiat,
|
||||
uuid: wallet.id
|
||||
};
|
||||
var outputs = [];
|
||||
var config = configService.getSync();
|
||||
var configWallet = config.wallet;
|
||||
var walletSettings = configWallet.settings;
|
||||
|
||||
|
||||
ongoingProcess.set('Processing Transaction...', true);
|
||||
$timeout(function() {
|
||||
amazonService.createBitPayInvoice(dataSrc, function(err, dataInvoice) {
|
||||
if (err) {
|
||||
ongoingProcess.set('Processing Transaction...', false);
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err));
|
||||
return;
|
||||
}
|
||||
|
||||
amazonService.getBitPayInvoice(dataInvoice.invoiceId, function(err, invoice) {
|
||||
if (err) {
|
||||
ongoingProcess.set('Processing Transaction...', false);
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err));
|
||||
return;
|
||||
}
|
||||
|
||||
$log.debug('Fetch PayPro Request...', invoice.paymentUrls.BIP73);
|
||||
|
||||
wallet.fetchPayPro({
|
||||
payProUrl: invoice.paymentUrls.BIP73,
|
||||
}, function(err, paypro) {
|
||||
|
||||
if (err) {
|
||||
ongoingProcess.set('Processing Transaction...', false);
|
||||
$log.warn('Could not fetch payment request:', err);
|
||||
var msg = err.toString();
|
||||
if (msg.match('HTTP')) {
|
||||
msg = gettextCatalog.getString('Could not fetch payment information');
|
||||
}
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!paypro.verified) {
|
||||
ongoingProcess.set('Processing Transaction...', false);
|
||||
$log.warn('Failed to verify payment protocol signatures');
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Payment Protocol Invalid'));
|
||||
$timeout(function() {
|
||||
$scope.$digest();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var address, comment, amount, url;
|
||||
|
||||
address = paypro.toAddress;
|
||||
amount = paypro.amount;
|
||||
url = paypro.url;
|
||||
comment = 'Amazon.com Gift Card';
|
||||
|
||||
outputs.push({
|
||||
'toAddress': address,
|
||||
'amount': amount,
|
||||
'message': comment
|
||||
});
|
||||
|
||||
var txp = {
|
||||
toAddress: address,
|
||||
amount: amount,
|
||||
outputs: outputs,
|
||||
message: comment,
|
||||
payProUrl: url,
|
||||
excludeUnconfirmedUtxos: configWallet.spendUnconfirmed ? false : true,
|
||||
feeLevel: walletSettings.feeLevel || 'normal'
|
||||
};
|
||||
|
||||
walletService.createTx(wallet, txp, function(err, createdTxp) {
|
||||
ongoingProcess.set('Processing Transaction...', false);
|
||||
if (err) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err));
|
||||
return;
|
||||
}
|
||||
walletService.publishAndSign(wallet, createdTxp, function(err, tx) {
|
||||
if (err) {
|
||||
ongoingProcess.set('Processing Transaction...', false);
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err));
|
||||
walletService.removeTx(wallet, tx, function(err) {
|
||||
if (err) $log.debug(err);
|
||||
});
|
||||
$timeout(function() {
|
||||
$scope.$digest();
|
||||
});
|
||||
return;
|
||||
}
|
||||
var count = 0;
|
||||
ongoingProcess.set('Processing Transaction...', true);
|
||||
|
||||
dataSrc.accessKey = dataInvoice.accessKey;
|
||||
dataSrc.invoiceId = invoice.id;
|
||||
dataSrc.invoiceUrl = invoice.url;
|
||||
dataSrc.invoiceTime = invoice.invoiceTime;
|
||||
|
||||
self.debounceCreate(count, dataSrc);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
||||
self.debounceCreate = lodash.throttle(function(count, dataSrc) {
|
||||
self.debounceCreateGiftCard(count, dataSrc);
|
||||
}, 8000, {
|
||||
'leading': true
|
||||
});
|
||||
|
||||
self.debounceCreateGiftCard = function(count, dataSrc) {
|
||||
|
||||
amazonService.createGiftCard(dataSrc, function(err, giftCard) {
|
||||
$log.debug("creating gift card " + count);
|
||||
if (err) {
|
||||
giftCard = {};
|
||||
giftCard.status = 'FAILURE';
|
||||
ongoingProcess.set('Processing Transaction...', false);
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err));
|
||||
self.errorInfo = dataSrc;
|
||||
$timeout(function() {
|
||||
$scope.$digest();
|
||||
});
|
||||
}
|
||||
|
||||
if (giftCard.status == 'PENDING' && count < 3) {
|
||||
$log.debug("pending gift card not available yet");
|
||||
self.debounceCreate(count + 1, dataSrc, dataSrc);
|
||||
return;
|
||||
}
|
||||
|
||||
var now = moment().unix() * 1000;
|
||||
|
||||
var newData = giftCard;
|
||||
newData['invoiceId'] = dataSrc.invoiceId;
|
||||
newData['accessKey'] = dataSrc.accessKey;
|
||||
newData['invoiceUrl'] = dataSrc.invoiceUrl;
|
||||
newData['amount'] = dataSrc.amount;
|
||||
newData['date'] = dataSrc.invoiceTime || now;
|
||||
newData['uuid'] = dataSrc.uuid;
|
||||
|
||||
if (newData.status == 'expired') {
|
||||
amazonService.savePendingGiftCard(newData, {
|
||||
remove: true
|
||||
}, function(err) {
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
amazonService.savePendingGiftCard(newData, null, function(err) {
|
||||
ongoingProcess.set('Processing Transaction...', false);
|
||||
$log.debug("Saving new gift card with status: " + newData.status);
|
||||
|
||||
self.giftCard = newData;
|
||||
if (newData.status == 'PENDING') $state.transitionTo('tabs.giftcards.amazon');
|
||||
$timeout(function() {
|
||||
$scope.$digest();
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$scope.$on("$ionicView.enter", function(event, data) {
|
||||
$scope.formData = {
|
||||
fiat: null
|
||||
};
|
||||
$scope.wallets = profileService.getWallets({
|
||||
network: network,
|
||||
onlyComplete: true
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('buyGlideraController',
|
||||
function($scope, $timeout, $log, profileService, walletService, glideraService, bwcError, lodash, ongoingProcess, popupService, gettextCatalog) {
|
||||
|
||||
var wallet;
|
||||
var self = this;
|
||||
this.show2faCodeInput = null;
|
||||
this.success = null;
|
||||
$scope.network = glideraService.getEnvironment();
|
||||
|
||||
$scope.$on('Wallet/Changed', function(event, w) {
|
||||
if (lodash.isEmpty(w)) {
|
||||
$log.debug('No wallet provided');
|
||||
return;
|
||||
}
|
||||
wallet = w;
|
||||
$log.debug('Wallet changed: ' + w.name);
|
||||
});
|
||||
|
||||
$scope.update = function(opts) {
|
||||
if (!$scope.token || !$scope.permissions) return;
|
||||
$log.debug('Updating Glidera Account...');
|
||||
var accessToken = $scope.token;
|
||||
var permissions = $scope.permissions;
|
||||
|
||||
opts = opts || {};
|
||||
|
||||
glideraService.getStatus(accessToken, function(err, data) {
|
||||
$scope.status = data;
|
||||
});
|
||||
|
||||
glideraService.getLimits(accessToken, function(err, limits) {
|
||||
$scope.limits = limits;
|
||||
});
|
||||
|
||||
if (permissions.transaction_history) {
|
||||
glideraService.getTransactions(accessToken, function(err, data) {
|
||||
$scope.txs = data;
|
||||
});
|
||||
}
|
||||
|
||||
if (permissions.view_email_address && opts.fullUpdate) {
|
||||
glideraService.getEmail(accessToken, function(err, data) {
|
||||
$scope.email = data.email;
|
||||
});
|
||||
}
|
||||
if (permissions.personal_info && opts.fullUpdate) {
|
||||
glideraService.getPersonalInfo(accessToken, function(err, data) {
|
||||
$scope.personalInfo = data;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.getBuyPrice = function(token, price) {
|
||||
var self = this;
|
||||
if (!price || (price && !price.qty && !price.fiat)) {
|
||||
this.buyPrice = null;
|
||||
return;
|
||||
}
|
||||
this.gettingBuyPrice = true;
|
||||
glideraService.buyPrice(token, price, function(err, buyPrice) {
|
||||
self.gettingBuyPrice = false;
|
||||
if (err) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Could not get exchange information. Please, try again'));
|
||||
return;
|
||||
}
|
||||
self.buyPrice = buyPrice;
|
||||
});
|
||||
};
|
||||
|
||||
this.get2faCode = function(token) {
|
||||
var self = this;
|
||||
ongoingProcess.set('Sending 2FA code...', true);
|
||||
$timeout(function() {
|
||||
glideraService.get2faCode(token, function(err, sent) {
|
||||
ongoingProcess.set('Sending 2FA code...', false);
|
||||
if (err) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Could not send confirmation code to your phone'));
|
||||
return;
|
||||
}
|
||||
self.show2faCodeInput = sent;
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
||||
this.sendRequest = function(token, permissions, twoFaCode) {
|
||||
var self = this;
|
||||
ongoingProcess.set('Buying Bitcoin...', true);
|
||||
$timeout(function() {
|
||||
walletService.getAddress(wallet, false, function(err, walletAddr) {
|
||||
if (err) {
|
||||
ongoingProcess.set('Buying Bitcoin...', false);
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.cb(err, 'Could not create address'));
|
||||
return;
|
||||
}
|
||||
var data = {
|
||||
destinationAddress: walletAddr,
|
||||
qty: self.buyPrice.qty,
|
||||
priceUuid: self.buyPrice.priceUuid,
|
||||
useCurrentPrice: false,
|
||||
ip: null
|
||||
};
|
||||
glideraService.buy(token, twoFaCode, data, function(err, data) {
|
||||
ongoingProcess.set('Buying Bitcoin...', false);
|
||||
if (err) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||
return;
|
||||
}
|
||||
self.success = data;
|
||||
$timeout(function() {
|
||||
$scope.$digest();
|
||||
});
|
||||
});
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
||||
$scope.$on("$ionicView.enter", function(event, data){
|
||||
$scope.token = null;
|
||||
$scope.permissions = null;
|
||||
$scope.email = null;
|
||||
$scope.personalInfo = null;
|
||||
$scope.txs = null;
|
||||
$scope.status = null;
|
||||
$scope.limits = null;
|
||||
|
||||
ongoingProcess.set('connectingGlidera', true);
|
||||
glideraService.init($scope.token, function(err, glidera) {
|
||||
ongoingProcess.set('connectingGlidera');
|
||||
if (err || !glidera) {
|
||||
if (err) popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||
return;
|
||||
}
|
||||
$scope.token = glidera.token;
|
||||
$scope.permissions = glidera.permissions;
|
||||
$scope.update({fullUpdate: true});
|
||||
});
|
||||
|
||||
$scope.wallets = profileService.getWallets({
|
||||
network: $scope.network,
|
||||
onlyComplete: true
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
|
@ -1,103 +1,240 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $interval, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, walletService, platformInfo, lodash, configService, rateService, $stateParams, $window, $state, $log, profileService, bitcore, gettext, txFormatService, ongoingProcess, $ionicModal, popupService, $ionicHistory, $ionicConfig, payproService) {
|
||||
angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $interval, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, walletService, platformInfo, lodash, configService, rateService, $stateParams, $window, $state, $log, profileService, bitcore, txFormatService, ongoingProcess, $ionicModal, popupService, $ionicHistory, $ionicConfig, payproService, feeService, amazonService, glideraService, bwcError, bitpayCardService) {
|
||||
var cachedTxp = {};
|
||||
var toAmount;
|
||||
var isChromeApp = platformInfo.isChromeApp;
|
||||
var countDown = null;
|
||||
var giftCardAmountUSD;
|
||||
var giftCardAccessKey;
|
||||
var giftCardInvoiceTime;
|
||||
var giftCardUUID;
|
||||
var cachedSendMax = {};
|
||||
$scope.isCordova = platformInfo.isCordova;
|
||||
$ionicConfig.views.swipeBackEnabled(false);
|
||||
|
||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||
$scope.isWallet = data.stateParams.isWallet;
|
||||
// Amazon.com Gift Card parameters
|
||||
$scope.isGiftCard = data.stateParams.isGiftCard;
|
||||
giftCardAmountUSD = data.stateParams.giftCardAmountUSD;
|
||||
giftCardAccessKey = data.stateParams.giftCardAccessKey;
|
||||
giftCardInvoiceTime = data.stateParams.giftCardInvoiceTime;
|
||||
giftCardUUID = data.stateParams.giftCardUUID;
|
||||
|
||||
// Glidera parameters
|
||||
$scope.isGlidera = data.stateParams.isGlidera;
|
||||
$scope.glideraAccessToken = data.stateParams.glideraAccessToken;
|
||||
|
||||
toAmount = data.stateParams.toAmount;
|
||||
cachedSendMax = {};
|
||||
$scope.useSendMax = data.stateParams.useSendMax == 'true' ? true : false;
|
||||
var isWallet = data.stateParams.isWallet || 'false';
|
||||
$scope.isWallet = (isWallet.toString().trim().toLowerCase() == 'true' ? true : false);
|
||||
$scope.cardId = data.stateParams.cardId;
|
||||
$scope.toAmount = data.stateParams.toAmount;
|
||||
$scope.toAddress = data.stateParams.toAddress;
|
||||
$scope.toName = data.stateParams.toName;
|
||||
$scope.toEmail = data.stateParams.toEmail;
|
||||
$scope.description = data.stateParams.description;
|
||||
$scope.paypro = data.stateParams.paypro;
|
||||
$scope.insufficientFunds = false;
|
||||
$scope.noMatchingWallet = false;
|
||||
$scope.paymentExpired = {
|
||||
value: false
|
||||
};
|
||||
$scope.remainingTimeStr = {
|
||||
value: null
|
||||
};
|
||||
initConfirm();
|
||||
});
|
||||
|
||||
var initConfirm = function() {
|
||||
// TODO (URL , etc)
|
||||
if (!$scope.toAddress || !$scope.toAmount) {
|
||||
$log.error('Bad params at amount');
|
||||
throw ('bad params');
|
||||
}
|
||||
|
||||
var config = configService.getSync().wallet;
|
||||
$scope.feeLevel = config.settings && config.settings.feeLevel ? config.settings.feeLevel : 'normal';
|
||||
var feeLevel = config.settings && config.settings.feeLevel ? config.settings.feeLevel : 'normal';
|
||||
$scope.feeLevel = feeService.feeOpts[feeLevel];
|
||||
if ($scope.isGlidera) $scope.network = glideraService.getEnvironment();
|
||||
else $scope.network = (new bitcore.Address($scope.toAddress)).network.name;
|
||||
resetValues();
|
||||
setwallets();
|
||||
});
|
||||
|
||||
$scope.toAmount = parseInt($scope.toAmount);
|
||||
$scope.amountStr = txFormatService.formatAmountStr($scope.toAmount);
|
||||
$scope.displayAmount = getDisplayAmount($scope.amountStr);
|
||||
$scope.displayUnit = getDisplayUnit($scope.amountStr);
|
||||
|
||||
var networkName = (new bitcore.Address($scope.toAddress)).network.name;
|
||||
$scope.network = networkName;
|
||||
|
||||
$scope.insuffientFunds = false;
|
||||
$scope.noMatchingWallet = false;
|
||||
|
||||
var wallets = profileService.getWallets({
|
||||
function setwallets() {
|
||||
$scope.wallets = profileService.getWallets({
|
||||
onlyComplete: true,
|
||||
network: networkName,
|
||||
network: $scope.network
|
||||
});
|
||||
|
||||
if (!wallets || !wallets.length) {
|
||||
if (!$scope.wallets || !$scope.wallets.length) {
|
||||
$scope.noMatchingWallet = true;
|
||||
if ($scope.paypro) {
|
||||
displayValues();
|
||||
}
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if ($scope.isGlidera == 'buy') {
|
||||
initConfirm();
|
||||
return;
|
||||
}
|
||||
|
||||
var filteredWallets = [];
|
||||
var index = 0;
|
||||
var enoughFunds = false;
|
||||
|
||||
lodash.each(wallets, function(w) {
|
||||
lodash.each($scope.wallets, function(w) {
|
||||
walletService.getStatus(w, {}, function(err, status) {
|
||||
if (err || !status) {
|
||||
$log.error(err);
|
||||
} else {
|
||||
w.status = status;
|
||||
if (!status.availableBalanceSat) $log.debug('No balance available in: ' + w.name);
|
||||
if (status.availableBalanceSat > $scope.toAmount) {
|
||||
if (status.availableBalanceSat > toAmount) {
|
||||
filteredWallets.push(w);
|
||||
enoughFunds = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (++index == wallets.length) {
|
||||
if (++index == $scope.wallets.length) {
|
||||
if (!lodash.isEmpty(filteredWallets)) {
|
||||
$scope.wallets = lodash.clone(filteredWallets);
|
||||
setWallet($scope.wallets[0]);
|
||||
if ($scope.useSendMax) {
|
||||
if ($scope.wallets.length > 1)
|
||||
$scope.showWalletSelector();
|
||||
else {
|
||||
$scope.wallet = $scope.wallets[0];
|
||||
$scope.getSendMaxInfo();
|
||||
}
|
||||
} else initConfirm();
|
||||
} else {
|
||||
|
||||
if (!enoughFunds)
|
||||
$scope.insuffientFunds = true;
|
||||
|
||||
if (!enoughFunds) $scope.insufficientFunds = true;
|
||||
$log.warn('No wallet available to make the payment');
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
});
|
||||
}
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
txFormatService.formatAlternativeStr($scope.toAmount, function(v) {
|
||||
var initConfirm = function() {
|
||||
if ($scope.paypro) _paymentTimeControl($scope.paypro.expires);
|
||||
|
||||
displayValues();
|
||||
if ($scope.wallets.length > 1) $scope.showWalletSelector();
|
||||
else setWallet($scope.wallets[0]);
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
});
|
||||
};
|
||||
|
||||
function displayValues() {
|
||||
toAmount = parseInt(toAmount);
|
||||
$scope.amountStr = txFormatService.formatAmountStr(toAmount);
|
||||
$scope.displayAmount = getDisplayAmount($scope.amountStr);
|
||||
$scope.displayUnit = getDisplayUnit($scope.amountStr);
|
||||
txFormatService.formatAlternativeStr(toAmount, function(v) {
|
||||
$scope.alternativeAmountStr = v;
|
||||
});
|
||||
if ($scope.isGlidera == 'buy') $scope.getBuyPrice();
|
||||
if ($scope.isGlidera == 'sell') $scope.getSellPrice();
|
||||
};
|
||||
|
||||
if($scope.paypro) {
|
||||
_paymentTimeControl($scope.paypro.expires);
|
||||
}
|
||||
function resetValues() {
|
||||
$scope.displayAmount = $scope.displayUnit = $scope.fee = $scope.alternativeAmountStr = $scope.insufficientFunds = $scope.noMatchingWallet = null;
|
||||
};
|
||||
|
||||
$scope.getSendMaxInfo = function() {
|
||||
resetValues();
|
||||
|
||||
ongoingProcess.set('gettingFeeLevels', true);
|
||||
feeService.getCurrentFeeValue($scope.network, function(err, feePerKb) {
|
||||
ongoingProcess.set('gettingFeeLevels', false);
|
||||
if (err) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), err.message);
|
||||
return;
|
||||
}
|
||||
var config = configService.getSync().wallet;
|
||||
|
||||
ongoingProcess.set('retrievingInputs', true);
|
||||
walletService.getSendMaxInfo($scope.wallet, {
|
||||
feePerKb: feePerKb,
|
||||
excludeUnconfirmedUtxos: !config.spendUnconfirmed,
|
||||
returnInputs: true,
|
||||
}, function(err, resp) {
|
||||
ongoingProcess.set('retrievingInputs', false);
|
||||
if (err) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (resp.amount == 0) {
|
||||
$scope.insufficientFunds = true;
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Not enough funds for fee'));
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.sendMaxInfo = {
|
||||
sendMax: true,
|
||||
amount: resp.amount,
|
||||
inputs: resp.inputs,
|
||||
fee: resp.fee,
|
||||
feePerKb: feePerKb,
|
||||
};
|
||||
|
||||
cachedSendMax[$scope.wallet.id] = $scope.sendMaxInfo;
|
||||
|
||||
var msg = gettextCatalog.getString("{{fee}} will be deducted for bitcoin networking fees.", {
|
||||
fee: txFormatService.formatAmountStr(resp.fee)
|
||||
});
|
||||
var warningMsg = verifyExcludedUtxos();
|
||||
|
||||
if (!lodash.isEmpty(warningMsg))
|
||||
msg += '\n' + warningMsg;
|
||||
|
||||
popupService.showAlert(null, msg, function() {
|
||||
setSendMaxValues(resp);
|
||||
|
||||
createTx($scope.wallet, true, function(err, txp) {
|
||||
if (err) return;
|
||||
cachedTxp[$scope.wallet.id] = txp;
|
||||
apply(txp);
|
||||
});
|
||||
});
|
||||
|
||||
function verifyExcludedUtxos() {
|
||||
var warningMsg = [];
|
||||
if (resp.utxosBelowFee > 0) {
|
||||
warningMsg.push(gettextCatalog.getString("A total of {{amountBelowFeeStr}} were excluded. These funds come from UTXOs smaller than the network fee provided.", {
|
||||
amountBelowFeeStr: txFormatService.formatAmountStr(resp.amountBelowFee)
|
||||
}));
|
||||
}
|
||||
|
||||
if (resp.utxosAboveMaxSize > 0) {
|
||||
warningMsg.push(gettextCatalog.getString("A total of {{amountAboveMaxSizeStr}} were excluded. The maximum size allowed for a transaction was exceeded.", {
|
||||
amountAboveMaxSizeStr: txFormatService.formatAmountStr(resp.amountAboveMaxSize)
|
||||
}));
|
||||
}
|
||||
return warningMsg.join('\n');
|
||||
};
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function setSendMaxValues(data) {
|
||||
resetValues();
|
||||
var config = configService.getSync().wallet;
|
||||
var unitToSatoshi = config.settings.unitToSatoshi;
|
||||
var satToUnit = 1 / unitToSatoshi;
|
||||
var unitDecimals = config.settings.unitDecimals;
|
||||
|
||||
$scope.amountStr = txFormatService.formatAmountStr(data.amount, true);
|
||||
$scope.displayAmount = getDisplayAmount($scope.amountStr);
|
||||
$scope.displayUnit = getDisplayUnit($scope.amountStr);
|
||||
$scope.fee = txFormatService.formatAmountStr(data.fee);
|
||||
toAmount = parseFloat((data.amount * satToUnit).toFixed(unitDecimals));
|
||||
txFormatService.formatAlternativeStr(data.amount, function(v) {
|
||||
$scope.alternativeAmountStr = v;
|
||||
});
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
});
|
||||
|
|
@ -107,24 +244,25 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
|||
$scope.approve();
|
||||
});
|
||||
|
||||
$scope.$on('Wallet/Changed', function(event, wallet) {
|
||||
if (lodash.isEmpty(wallet)) {
|
||||
$log.debug('No wallet provided');
|
||||
return;
|
||||
}
|
||||
$log.debug('Wallet changed: ' + wallet.name);
|
||||
setWallet(wallet, true);
|
||||
});
|
||||
|
||||
$scope.showWalletSelector = function() {
|
||||
$scope.walletSelectorTitle = $scope.isGlidera == 'buy' ? 'Receive in' : $scope.isGlidera == 'sell' ? 'Sell From' : gettextCatalog.getString('Send from');
|
||||
if (!$scope.useSendMax && ($scope.insufficientFunds || $scope.noMatchingWallet)) return;
|
||||
$scope.showWallets = true;
|
||||
};
|
||||
|
||||
$scope.onWalletSelect = function(wallet) {
|
||||
setWallet(wallet);
|
||||
if ($scope.useSendMax) {
|
||||
$scope.wallet = wallet;
|
||||
if (cachedSendMax[wallet.id]) {
|
||||
$log.debug('Send max cached for wallet:', wallet.id);
|
||||
setSendMaxValues(cachedSendMax[wallet.id]);
|
||||
return;
|
||||
}
|
||||
$scope.getSendMaxInfo();
|
||||
} else
|
||||
setWallet(wallet);
|
||||
};
|
||||
|
||||
|
||||
$scope.showDescriptionPopup = function() {
|
||||
var message = gettextCatalog.getString('Add description');
|
||||
var opts = {
|
||||
|
|
@ -135,17 +273,17 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
|||
if (typeof res != 'undefined') $scope.description = res;
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
}, 100);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function getDisplayAmount(amountStr) {
|
||||
return amountStr.split(' ')[0];
|
||||
}
|
||||
return $scope.amountStr.split(' ')[0];
|
||||
};
|
||||
|
||||
function getDisplayUnit(amountStr) {
|
||||
return amountStr.split(' ')[1];
|
||||
}
|
||||
return $scope.amountStr.split(' ')[1];
|
||||
};
|
||||
|
||||
function _paymentTimeControl(expirationTime) {
|
||||
$scope.paymentExpired.value = false;
|
||||
|
|
@ -167,7 +305,7 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
|||
var m = Math.floor(totalSecs / 60);
|
||||
var s = totalSecs % 60;
|
||||
$scope.remainingTimeStr.value = ('0' + m).slice(-2) + ":" + ('0' + s).slice(-2);
|
||||
}
|
||||
};
|
||||
|
||||
function setExpiredValues() {
|
||||
$scope.paymentExpired.value = true;
|
||||
|
|
@ -176,19 +314,15 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
|||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
function setWallet(wallet, delayed) {
|
||||
var stop;
|
||||
$scope.wallet = wallet;
|
||||
$scope.fee = $scope.txp = null;
|
||||
|
||||
$timeout(function() {
|
||||
$ionicScrollDelegate.resize();
|
||||
$scope.$apply();
|
||||
}, 10);
|
||||
|
||||
if ($scope.isGlidera) return;
|
||||
if (stop) {
|
||||
$timeout.cancel(stop);
|
||||
stop = null;
|
||||
|
|
@ -205,67 +339,75 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
|||
});
|
||||
}, delayed ? 2000 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
$timeout(function() {
|
||||
$ionicScrollDelegate.resize();
|
||||
$scope.$apply();
|
||||
}, 10);
|
||||
};
|
||||
|
||||
var setSendError = function(msg) {
|
||||
$scope.sendStatus = '';
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
});
|
||||
popupService.showAlert(gettextCatalog.getString('Error at confirm:'), msg);
|
||||
popupService.showAlert(gettextCatalog.getString('Error at confirm'), bwcError.msg(msg));
|
||||
};
|
||||
|
||||
function apply(txp) {
|
||||
$scope.fee = txFormatService.formatAmountStr(txp.fee);
|
||||
$scope.txp = txp;
|
||||
$scope.$apply();
|
||||
}
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
});
|
||||
};
|
||||
|
||||
var createTx = function(wallet, dryRun, cb) {
|
||||
var config = configService.getSync().wallet;
|
||||
var currentSpendUnconfirmed = config.spendUnconfirmed;
|
||||
var outputs = [];
|
||||
|
||||
var paypro = $scope.paypro;
|
||||
var toAddress = $scope.toAddress;
|
||||
var toAmount = $scope.toAmount;
|
||||
var description = $scope.description;
|
||||
var unitToSatoshi = config.settings.unitToSatoshi;
|
||||
var unitDecimals = config.settings.unitDecimals;
|
||||
|
||||
// ToDo: use a credential's (or fc's) function for this
|
||||
if (description && !wallet.credentials.sharedEncryptingKey) {
|
||||
var msg = 'Could not add message to imported wallet without shared encrypting key';
|
||||
var msg = gettextCatalog.getString('Could not add message to imported wallet without shared encrypting key');
|
||||
$log.warn(msg);
|
||||
return setSendError(msg);
|
||||
}
|
||||
|
||||
if (toAmount > Number.MAX_SAFE_INTEGER) {
|
||||
var msg = 'Amount too big';
|
||||
var msg = gettextCatalog.getString('Amount too big');
|
||||
$log.warn(msg);
|
||||
return setSendError(msg);
|
||||
}
|
||||
|
||||
outputs.push({
|
||||
'toAddress': toAddress,
|
||||
'amount': toAmount,
|
||||
'message': description
|
||||
});
|
||||
|
||||
var txp = {};
|
||||
var amount;
|
||||
|
||||
// TODO
|
||||
if (!lodash.isEmpty($scope.sendMaxInfo)) {
|
||||
txp.sendMax = true;
|
||||
if ($scope.useSendMax) amount = parseFloat((toAmount * unitToSatoshi).toFixed(0));
|
||||
else amount = toAmount;
|
||||
|
||||
txp.outputs = [{
|
||||
'toAddress': toAddress,
|
||||
'amount': amount,
|
||||
'message': description
|
||||
}];
|
||||
|
||||
if ($scope.sendMaxInfo) {
|
||||
txp.inputs = $scope.sendMaxInfo.inputs;
|
||||
txp.fee = $scope.sendMaxInfo.fee;
|
||||
}
|
||||
} else
|
||||
txp.feeLevel = config.settings && config.settings.feeLevel ? config.settings.feeLevel : 'normal';
|
||||
|
||||
txp.outputs = outputs;
|
||||
txp.message = description;
|
||||
if(paypro) {
|
||||
|
||||
if (paypro) {
|
||||
txp.payProUrl = paypro.url;
|
||||
}
|
||||
txp.excludeUnconfirmedUtxos = config.spendUnconfirmed ? false : true;
|
||||
txp.feeLevel = config.settings && config.settings.feeLevel ? config.settings.feeLevel : 'normal';
|
||||
txp.excludeUnconfirmedUtxos = !currentSpendUnconfirmed;
|
||||
txp.dryRun = dryRun;
|
||||
|
||||
walletService.createTx(wallet, txp, function(err, ctxp) {
|
||||
|
|
@ -288,6 +430,11 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
|||
|
||||
$scope.approve = function(onSendStatusChange) {
|
||||
|
||||
var wallet = $scope.wallet;
|
||||
if (!wallet) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($scope.paypro && $scope.paymentExpired.value) {
|
||||
popupService.showAlert(null, gettextCatalog.getString('This bitcoin payment request has expired.'));
|
||||
$scope.sendStatus = '';
|
||||
|
|
@ -297,17 +444,45 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
|||
return;
|
||||
}
|
||||
|
||||
var wallet = $scope.wallet;
|
||||
if (!wallet) {
|
||||
return setSendError(gettextCatalog.getString('No wallet selected'));
|
||||
}
|
||||
|
||||
if (!wallet.canSign() && !wallet.isPrivKeyExternal()) {
|
||||
$log.info('No signing proposal: No private key');
|
||||
|
||||
return walletService.onlyPublish(wallet, txp, function(err, txp) {
|
||||
if (err) return setSendError(err);
|
||||
if ($scope.isGlidera) {
|
||||
$scope.get2faCode(function(err, sent) {
|
||||
if (err) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Could not send confirmation code to your phone'));
|
||||
return;
|
||||
}
|
||||
if (sent) {
|
||||
var title = gettextCatalog.getString("Please, enter the code below");
|
||||
var message = gettextCatalog.getString("A SMS containing a confirmation code was sent to your phone.");
|
||||
popupService.showPrompt(title, message, null, function(twoFaCode) {
|
||||
if (typeof twoFaCode == 'undefined') return;
|
||||
if ($scope.isGlidera == 'buy') {
|
||||
$scope.buyRequest(wallet, twoFaCode, function(err, data) {
|
||||
if (err) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||
return;
|
||||
}
|
||||
$scope.sendStatus = 'success';
|
||||
$timeout(function() {
|
||||
$scope.$digest();
|
||||
});
|
||||
})
|
||||
}
|
||||
if ($scope.isGlidera == 'sell') {
|
||||
$scope.sellRequest(wallet, twoFaCode, function(err, data) {
|
||||
if (err) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||
return;
|
||||
}
|
||||
$scope.sendStatus = 'success';
|
||||
$timeout(function() {
|
||||
$scope.$digest();
|
||||
});
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
ongoingProcess.set('creatingTx', true, onSendStatusChange);
|
||||
|
|
@ -356,13 +531,18 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
|||
|
||||
function statusChangeHandler(processName, showName, isOn) {
|
||||
$log.debug('statusChangeHandler: ', processName, showName, isOn);
|
||||
if ((processName === 'broadcastingTx' || ((processName === 'signingTx') && $scope.wallet.m > 1)) && !isOn) {
|
||||
if (
|
||||
(
|
||||
processName === 'broadcastingTx' ||
|
||||
((processName === 'signingTx') && $scope.wallet.m > 1) ||
|
||||
(processName == 'sendingTx' && !$scope.wallet.canSign() && !$scope.wallet.isPrivKeyExternal())
|
||||
) && !isOn) {
|
||||
$scope.sendStatus = 'success';
|
||||
$scope.$digest();
|
||||
} else if (showName) {
|
||||
$scope.sendStatus = showName;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.statusChangeHandler = statusChangeHandler;
|
||||
|
||||
|
|
@ -373,6 +553,8 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
|||
$scope.onSuccessConfirm = function() {
|
||||
var previousView = $ionicHistory.viewHistory().backView && $ionicHistory.viewHistory().backView.stateName;
|
||||
var fromBitPayCard = previousView.match(/tabs.bitpayCard/) ? true : false;
|
||||
var fromAmazon = previousView.match(/tabs.giftcards.amazon/) ? true : false;
|
||||
var fromGlidera = previousView.match(/tabs.buyandsell.glidera/) ? true : false;
|
||||
|
||||
$ionicHistory.nextViewOptions({
|
||||
disableAnimate: true
|
||||
|
|
@ -386,14 +568,288 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
|||
id: $stateParams.cardId
|
||||
});
|
||||
}, 100);
|
||||
} else if (fromAmazon) {
|
||||
$ionicHistory.nextViewOptions({
|
||||
disableAnimate: true,
|
||||
historyRoot: true
|
||||
});
|
||||
$ionicHistory.clearHistory();
|
||||
$state.go('tabs.home').then(function() {
|
||||
$state.transitionTo('tabs.giftcards.amazon', {
|
||||
cardClaimCode: $scope.amazonGiftCard ? $scope.amazonGiftCard.claimCode : null
|
||||
});
|
||||
});
|
||||
} else if (fromGlidera) {
|
||||
$ionicHistory.nextViewOptions({
|
||||
disableAnimate: true,
|
||||
historyRoot: true
|
||||
});
|
||||
$ionicHistory.clearHistory();
|
||||
$state.go('tabs.home').then(function() {
|
||||
$state.transitionTo('tabs.buyandsell.glidera');
|
||||
});
|
||||
} else {
|
||||
$state.go('tabs.send');
|
||||
$ionicHistory.nextViewOptions({
|
||||
disableAnimate: true,
|
||||
historyRoot: true
|
||||
});
|
||||
$ionicHistory.clearHistory();
|
||||
$state.go('tabs.send').then(function() {
|
||||
$state.transitionTo('tabs.home');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.get2faCode = function(cb) {
|
||||
ongoingProcess.set('sending2faCode', true);
|
||||
$timeout(function() {
|
||||
glideraService.get2faCode($scope.glideraAccessToken, function(err, sent) {
|
||||
ongoingProcess.set('sending2faCode', false);
|
||||
return cb(err, sent);
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
||||
$scope.buyRequest = function(wallet, twoFaCode, cb) {
|
||||
ongoingProcess.set('buyingBitcoin', true);
|
||||
$timeout(function() {
|
||||
walletService.getAddress(wallet, false, function(err, walletAddr) {
|
||||
if (err) {
|
||||
ongoingProcess.set('buyingBitcoin', false);
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.cb(err, 'Could not create address'));
|
||||
return;
|
||||
}
|
||||
var data = {
|
||||
destinationAddress: walletAddr,
|
||||
qty: $scope.buyPrice.qty,
|
||||
priceUuid: $scope.buyPrice.priceUuid,
|
||||
useCurrentPrice: false,
|
||||
ip: null
|
||||
};
|
||||
glideraService.buy($scope.glideraAccessToken, twoFaCode, data, function(err, data) {
|
||||
ongoingProcess.set('buyingBitcoin', false);
|
||||
return cb(err, data);
|
||||
});
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
||||
$scope.sellRequest = function(wallet, twoFaCode, cb) {
|
||||
var outputs = [];
|
||||
var config = configService.getSync();
|
||||
var configWallet = config.wallet;
|
||||
var walletSettings = configWallet.settings;
|
||||
|
||||
ongoingProcess.set('creatingTx', true);
|
||||
walletService.getAddress(wallet, null, function(err, refundAddress) {
|
||||
if (!refundAddress) {
|
||||
ongoingProcess.clear();
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err, 'Could not create address'));
|
||||
return;
|
||||
}
|
||||
glideraService.getSellAddress($scope.glideraAccessToken, function(err, sellAddress) {
|
||||
if (!sellAddress || err) {
|
||||
ongoingProcess.clear();
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Could not get the destination bitcoin address'));
|
||||
return;
|
||||
}
|
||||
var amount = parseInt(($scope.sellPrice.qty * 100000000).toFixed(0));
|
||||
var comment = 'Glidera transaction';
|
||||
|
||||
outputs.push({
|
||||
'toAddress': sellAddress,
|
||||
'amount': amount,
|
||||
'message': comment
|
||||
});
|
||||
|
||||
var txp = {
|
||||
toAddress: sellAddress,
|
||||
amount: amount,
|
||||
outputs: outputs,
|
||||
message: comment,
|
||||
payProUrl: null,
|
||||
excludeUnconfirmedUtxos: configWallet.spendUnconfirmed ? false : true,
|
||||
feeLevel: walletSettings.feeLevel || 'normal',
|
||||
customData: {
|
||||
'glideraToken': $scope.glideraAccessToken
|
||||
}
|
||||
};
|
||||
|
||||
walletService.createTx(wallet, txp, function(err, createdTxp) {
|
||||
ongoingProcess.clear();
|
||||
if (err) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), err.message || bwcError.msg(err));
|
||||
return;
|
||||
}
|
||||
walletService.prepare(wallet, function(err, password) {
|
||||
if (err) {
|
||||
ongoingProcess.clear();
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), err.message || bwcError.msg(err));
|
||||
return;
|
||||
}
|
||||
ongoingProcess.set('signingTx', true);
|
||||
walletService.publishTx(wallet, createdTxp, function(err, publishedTxp) {
|
||||
if (err) {
|
||||
ongoingProcess.clear();
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), err.message || bwcError.msg(err));
|
||||
return;
|
||||
}
|
||||
|
||||
walletService.signTx(wallet, publishedTxp, password, function(err, signedTxp) {
|
||||
if (err) {
|
||||
ongoingProcess.clear();
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), err.message || bwcError.msg(err));
|
||||
walletService.removeTx(wallet, signedTxp, function(err) {
|
||||
if (err) $log.debug(err);
|
||||
});
|
||||
return;
|
||||
}
|
||||
var rawTx = signedTxp.raw;
|
||||
var data = {
|
||||
refundAddress: refundAddress,
|
||||
signedTransaction: rawTx,
|
||||
priceUuid: $scope.sellPrice.priceUuid,
|
||||
useCurrentPrice: $scope.sellPrice.priceUuid ? false : true,
|
||||
ip: null
|
||||
};
|
||||
ongoingProcess.set('sellingBitcoin', true);
|
||||
glideraService.sell($scope.glideraAccessToken, twoFaCode, data, function(err, data) {
|
||||
ongoingProcess.clear();
|
||||
if (err) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), err.message || bwcError.msg(err));
|
||||
return;
|
||||
}
|
||||
return cb(err, data)
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$scope.getBuyPrice = function() {
|
||||
var satToBtc = 1 / 100000000;
|
||||
var price = {};
|
||||
price.qty = (toAmount * satToBtc).toFixed(8);
|
||||
glideraService.buyPrice($scope.glideraAccessToken, price, function(err, buyPrice) {
|
||||
if (err) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), 'Could not get exchange information. Please, try again');
|
||||
return;
|
||||
}
|
||||
$scope.buyPrice = buyPrice;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.getSellPrice = function() {
|
||||
var satToBtc = 1 / 100000000;
|
||||
var price = {};
|
||||
price.qty = (toAmount * satToBtc).toFixed(8);
|
||||
|
||||
glideraService.sellPrice($scope.glideraAccessToken, price, function(err, sellPrice) {
|
||||
if (err) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), 'Could not get exchange information. Please, try again');
|
||||
return;
|
||||
}
|
||||
$scope.sellPrice = sellPrice;
|
||||
});
|
||||
};
|
||||
|
||||
function publishAndSign(wallet, txp, onSendStatusChange) {
|
||||
|
||||
if (!wallet.canSign() && !wallet.isPrivKeyExternal()) {
|
||||
$log.info('No signing proposal: No private key');
|
||||
|
||||
return walletService.onlyPublish(wallet, txp, function(err) {
|
||||
if (err) setSendError(err);
|
||||
}, onSendStatusChange);
|
||||
}
|
||||
|
||||
walletService.publishAndSign(wallet, txp, function(err, txp) {
|
||||
if (err) return setSendError(err);
|
||||
|
||||
var previousView = $ionicHistory.viewHistory().backView && $ionicHistory.viewHistory().backView.stateName;
|
||||
var fromAmazon = previousView.match(/tabs.giftcards.amazon/) ? true : false;
|
||||
if (fromAmazon) {
|
||||
var count = 0;
|
||||
var invoiceId = JSON.parse($scope.paypro.merchant_data).invoiceId;
|
||||
var dataSrc = {
|
||||
currency: 'USD',
|
||||
amount: giftCardAmountUSD,
|
||||
uuid: giftCardUUID,
|
||||
accessKey: giftCardAccessKey,
|
||||
invoiceId: invoiceId,
|
||||
invoiceUrl: $scope.paypro.url,
|
||||
invoiceTime: giftCardInvoiceTime
|
||||
};
|
||||
debounceCreate(count, dataSrc, onSendStatusChange);
|
||||
}
|
||||
}, onSendStatusChange);
|
||||
}
|
||||
|
||||
var debounceCreate = lodash.throttle(function(count, dataSrc) {
|
||||
debounceCreateGiftCard(count, dataSrc);
|
||||
}, 8000, {
|
||||
'leading': true
|
||||
});
|
||||
|
||||
var debounceCreateGiftCard = function(count, dataSrc, onSendStatusChange) {
|
||||
|
||||
amazonService.createGiftCard(dataSrc, function(err, giftCard) {
|
||||
$log.debug("creating gift card " + count);
|
||||
if (err) {
|
||||
giftCard = {};
|
||||
giftCard.status = 'FAILURE';
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||
}
|
||||
|
||||
if (giftCard.status == 'PENDING' && count < 3) {
|
||||
$log.debug("pending gift card not available yet");
|
||||
debounceCreate(count + 1, dataSrc);
|
||||
return;
|
||||
}
|
||||
|
||||
var now = moment().unix() * 1000;
|
||||
|
||||
var newData = giftCard;
|
||||
newData['invoiceId'] = dataSrc.invoiceId;
|
||||
newData['accessKey'] = dataSrc.accessKey;
|
||||
newData['invoiceUrl'] = dataSrc.invoiceUrl;
|
||||
newData['amount'] = dataSrc.amount;
|
||||
newData['date'] = dataSrc.invoiceTime || now;
|
||||
newData['uuid'] = dataSrc.uuid;
|
||||
|
||||
if (newData.status == 'expired') {
|
||||
amazonService.savePendingGiftCard(newData, {
|
||||
remove: true
|
||||
}, function(err) {
|
||||
$log.error(err);
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
amazonService.savePendingGiftCard(newData, null, function(err) {
|
||||
$log.debug("Saving new gift card with status: " + newData.status);
|
||||
$scope.amazonGiftCard = newData;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$scope.getRates = function() {
|
||||
var config = configService.getSync().wallet.settings;
|
||||
var unitName = config.unitName;
|
||||
var alternativeIsoCode = config.alternativeIsoCode;
|
||||
bitpayCardService.getRates(alternativeIsoCode, function(err, res) {
|
||||
if (err) {
|
||||
$log.warn(err);
|
||||
return;
|
||||
}
|
||||
if (unitName == 'bits') {
|
||||
$scope.exchangeRate = '1,000,000 bits ~ ' + res.rate + ' ' + alternativeIsoCode;
|
||||
} else {
|
||||
$scope.exchangeRate = '1 BTC ~ ' + res.rate + ' ' + alternativeIsoCode;
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -79,8 +79,8 @@ angular.module('copayApp.controllers').controller('copayersController',
|
|||
};
|
||||
|
||||
$scope.goHome = function() {
|
||||
$ionicHistory.removeBackView();
|
||||
$state.go('tabs.home');
|
||||
$ionicHistory.clearHistory();
|
||||
};
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('createController',
|
||||
function($scope, $rootScope, $timeout, $log, lodash, $state, $ionicScrollDelegate, $ionicHistory, profileService, configService, gettext, gettextCatalog, ledger, trezor, platformInfo, derivationPathHelper, ongoingProcess, walletService, storageService, popupService) {
|
||||
function($scope, $rootScope, $timeout, $log, lodash, $state, $ionicScrollDelegate, $ionicHistory, profileService, configService, gettextCatalog, ledger, trezor, platformInfo, derivationPathHelper, ongoingProcess, walletService, storageService, popupService, $window) {
|
||||
|
||||
var isChromeApp = platformInfo.isChromeApp;
|
||||
var isCordova = platformInfo.isCordova;
|
||||
|
|
@ -33,7 +33,6 @@ angular.module('copayApp.controllers').controller('createController',
|
|||
$scope.formData.derivationPath = derivationPathHelper.default;
|
||||
$scope.setTotalCopayers(tc);
|
||||
updateRCSelect(tc);
|
||||
updateSeedSourceSelect(tc);
|
||||
};
|
||||
|
||||
$scope.showAdvChange = function() {
|
||||
|
|
@ -44,7 +43,7 @@ angular.module('copayApp.controllers').controller('createController',
|
|||
$scope.resizeView = function() {
|
||||
$timeout(function() {
|
||||
$ionicScrollDelegate.resize();
|
||||
});
|
||||
}, 10);
|
||||
checkPasswordFields();
|
||||
};
|
||||
|
||||
|
|
@ -67,26 +66,35 @@ angular.module('copayApp.controllers').controller('createController',
|
|||
function updateSeedSourceSelect(n) {
|
||||
var seedOptions = [{
|
||||
id: 'new',
|
||||
label: gettext('Random'),
|
||||
label: gettextCatalog.getString('Random'),
|
||||
}, {
|
||||
id: 'set',
|
||||
label: gettext('Specify Recovery Phrase...'),
|
||||
label: gettextCatalog.getString('Specify Recovery Phrase...'),
|
||||
}];
|
||||
|
||||
$scope.seedSource = seedOptions[0];
|
||||
|
||||
if (n > 1 && isChromeApp)
|
||||
seedOptions.push({
|
||||
id: 'ledger',
|
||||
label: 'Ledger Hardware Wallet',
|
||||
});
|
||||
/*
|
||||
|
||||
if (isChromeApp || isDevel) {
|
||||
seedOptions.push({
|
||||
id: 'trezor',
|
||||
label: 'Trezor Hardware Wallet',
|
||||
});
|
||||
Disable Hardware Wallets for BitPay distribution
|
||||
|
||||
*/
|
||||
|
||||
if ($window.appConfig.name == 'copay') {
|
||||
if (n > 1 && isChromeApp) {
|
||||
seedOptions.push({
|
||||
id: 'ledger',
|
||||
label: 'Ledger Hardware Wallet',
|
||||
});
|
||||
}
|
||||
if (isChromeApp || isDevel) {
|
||||
seedOptions.push({
|
||||
id: 'trezor',
|
||||
label: 'Trezor Hardware Wallet',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$scope.seedOptions = seedOptions;
|
||||
};
|
||||
|
||||
|
|
|
|||
27
src/js/controllers/customAmount.js
Normal file
27
src/js/controllers/customAmount.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('customAmountController', function($rootScope, $scope, $stateParams, $ionicHistory, txFormatService, platformInfo) {
|
||||
|
||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||
var satToBtc = 1 / 100000000;
|
||||
$scope.isCordova = platformInfo.isCordova;
|
||||
$scope.address = data.stateParams.toAddress;
|
||||
$scope.amount = parseInt(data.stateParams.toAmount);
|
||||
$scope.amountBtc = ($scope.amount * satToBtc).toFixed(8);
|
||||
$scope.amountStr = txFormatService.formatAmountStr($scope.amount);
|
||||
$scope.altAmountStr = txFormatService.formatAlternativeStr($scope.amount);
|
||||
});
|
||||
|
||||
$scope.shareAddress = function(uri) {
|
||||
window.plugins.socialsharing.share(uri, null, null, null);
|
||||
};
|
||||
|
||||
$scope.finish = function() {
|
||||
$ionicHistory.nextViewOptions({
|
||||
disableAnimate: false,
|
||||
historyRoot: true
|
||||
});
|
||||
$ionicHistory.goBack(-2);
|
||||
};
|
||||
|
||||
});
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('exportController',
|
||||
function($scope, $timeout, $log, $ionicHistory, $ionicScrollDelegate, backupService, walletService, storageService, profileService, platformInfo, gettextCatalog, $state, $stateParams, popupService) {
|
||||
function($scope, $timeout, $log, $ionicHistory, $ionicScrollDelegate, backupService, walletService, storageService, profileService, platformInfo, gettextCatalog, $state, $stateParams, popupService, $window) {
|
||||
var wallet = profileService.getWallet($stateParams.walletId);
|
||||
|
||||
$scope.showAdvChange = function() {
|
||||
|
|
@ -12,7 +12,7 @@ angular.module('copayApp.controllers').controller('exportController',
|
|||
$scope.resizeView = function() {
|
||||
$timeout(function() {
|
||||
$ionicScrollDelegate.resize();
|
||||
});
|
||||
}, 10);
|
||||
};
|
||||
|
||||
function getPassword(cb) {
|
||||
|
|
@ -191,7 +191,7 @@ angular.module('copayApp.controllers').controller('exportController',
|
|||
if ($scope.formData.noSignEnabled)
|
||||
name = name + '(No Private Key)';
|
||||
|
||||
var subject = 'Copay Wallet Backup: ' + name;
|
||||
var subject = $window.appConfig.nameCase + ' Wallet Backup: ' + name;
|
||||
var body = 'Here is the encrypted backup of the wallet ' + name + ': \n\n' + ew + '\n\n To import this backup, copy all text between {...}, including the symbols {}';
|
||||
window.plugins.socialsharing.shareViaEmail(
|
||||
body,
|
||||
|
|
|
|||
130
src/js/controllers/feedback/complete.js
Normal file
130
src/js/controllers/feedback/complete.js
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('completeController', function($scope, $stateParams, $timeout, $log, $ionicHistory, $state, $ionicNavBarDelegate, $ionicConfig, platformInfo, configService, storageService, lodash) {
|
||||
$scope.isCordova = platformInfo.isCordova;
|
||||
var defaults = configService.getDefaults();
|
||||
|
||||
function quickFeedback(cb) {
|
||||
window.plugins.spinnerDialog.show();
|
||||
$timeout(window.plugins.spinnerDialog.hide, 300);
|
||||
$timeout(cb, 20);
|
||||
}
|
||||
|
||||
$scope.shareFacebook = function() {
|
||||
quickFeedback(function() {
|
||||
window.plugins.socialsharing.shareVia($scope.shareFacebookVia, null, null, null, defaults.download.url);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.shareTwitter = function() {
|
||||
quickFeedback(function() {
|
||||
window.plugins.socialsharing.shareVia($scope.shareTwitterVia, null, null, null, defaults.download.url);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.shareGooglePlus = function() {
|
||||
quickFeedback(function() {
|
||||
window.plugins.socialsharing.shareVia($scope.shareGooglePlusVia, defaults.download.url);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.shareEmail = function() {
|
||||
quickFeedback(function() {
|
||||
window.plugins.socialsharing.shareViaEmail(defaults.download.url);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.shareWhatsapp = function() {
|
||||
quickFeedback(function() {
|
||||
window.plugins.socialsharing.shareViaWhatsApp(defaults.download.url);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.shareMessage = function() {
|
||||
quickFeedback(function() {
|
||||
window.plugins.socialsharing.shareViaSMS(defaults.download.url);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||
$scope.score = (data.stateParams && data.stateParams.score) ? parseInt(data.stateParams.score) : null;
|
||||
$scope.skipped = (data.stateParams && data.stateParams.skipped) ? true : false;
|
||||
$scope.rated = (data.stateParams && data.stateParams.rated) ? true : false;
|
||||
$scope.fromSettings = (data.stateParams && data.stateParams.fromSettings) ? true : false;
|
||||
|
||||
if (!$scope.fromSettings) {
|
||||
$ionicConfig.views.swipeBackEnabled(false);
|
||||
} else {
|
||||
$ionicNavBarDelegate.showBackButton(true);
|
||||
$ionicConfig.views.swipeBackEnabled(true);
|
||||
}
|
||||
|
||||
storageService.getFeedbackInfo(function(error, info) {
|
||||
var feedbackInfo = lodash.isString(info) ? JSON.parse(info) : null;
|
||||
feedbackInfo.sent = true;
|
||||
storageService.setFeedbackInfo(JSON.stringify(feedbackInfo), function() {});
|
||||
});
|
||||
|
||||
if (!$scope.isCordova) return;
|
||||
$scope.animate = true;
|
||||
|
||||
window.plugins.socialsharing.available(function(isAvailable) {
|
||||
// the boolean is only false on iOS < 6
|
||||
$scope.socialsharing = isAvailable;
|
||||
if (isAvailable) {
|
||||
window.plugins.socialsharing.canShareVia('com.apple.social.facebook', 'msg', null, null, null, function(e) {
|
||||
$scope.shareFacebookVia = 'com.apple.social.facebook';
|
||||
$scope.facebook = true;
|
||||
}, function(e) {
|
||||
window.plugins.socialsharing.canShareVia('com.facebook.katana', 'msg', null, null, null, function(e) {
|
||||
$scope.shareFacebookVia = 'com.facebook.katana';
|
||||
$scope.facebook = true;
|
||||
}, function(e) {
|
||||
$log.debug('facebook error: ' + e);
|
||||
$scope.facebook = false;
|
||||
});
|
||||
});
|
||||
window.plugins.socialsharing.canShareVia('com.apple.social.twitter', 'msg', null, null, null, function(e) {
|
||||
$scope.shareTwitterVia = 'com.apple.social.twitter';
|
||||
$scope.twitter = true;
|
||||
}, function(e) {
|
||||
window.plugins.socialsharing.canShareVia('com.twitter.android', 'msg', null, null, null, function(e) {
|
||||
$scope.shareTwitterVia = 'com.twitter.android';
|
||||
$scope.twitter = true;
|
||||
}, function(e) {
|
||||
$log.debug('twitter error: ' + e);
|
||||
$scope.twitter = false;
|
||||
});
|
||||
});
|
||||
window.plugins.socialsharing.canShareVia('com.google.android.apps.plus', 'msg', null, null, null, function(e) {
|
||||
$scope.shareGooglePlusVia = 'com.google.android.apps.plus';
|
||||
$scope.googleplus = true;
|
||||
}, function(e) {
|
||||
$log.debug('googlePlus error: ' + e);
|
||||
$scope.googleplus = false;
|
||||
});
|
||||
window.plugins.socialsharing.canShareViaEmail(function(e) {
|
||||
$scope.email = true;
|
||||
}, function(e) {
|
||||
$log.debug('email error: ' + e);
|
||||
$scope.email = false;
|
||||
});
|
||||
window.plugins.socialsharing.canShareVia('whatsapp', 'msg', null, null, null, function(e) {
|
||||
$scope.whatsapp = true;
|
||||
}, function(e) {
|
||||
$log.debug('whatsapp error: ' + e);
|
||||
$scope.whatsapp = false;
|
||||
});
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
|
||||
$scope.close = function() {
|
||||
$ionicHistory.nextViewOptions({
|
||||
disableAnimate: false,
|
||||
historyRoot: true
|
||||
});
|
||||
if ($scope.score == 5) $ionicHistory.goBack(-3);
|
||||
else $ionicHistory.goBack(-2);
|
||||
};
|
||||
});
|
||||
50
src/js/controllers/feedback/rateApp.js
Normal file
50
src/js/controllers/feedback/rateApp.js
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('rateAppController', function($scope, $state, $stateParams, $window, lodash, externalLinkService, configService, platformInfo, feedbackService, ongoingProcess, popupService) {
|
||||
$scope.score = parseInt($stateParams.score);
|
||||
var isAndroid = platformInfo.isAndroid;
|
||||
var isIOS = platformInfo.isIOS;
|
||||
var isWP = platformInfo.isWP;
|
||||
var config = configService.getSync();
|
||||
|
||||
$scope.skip = function() {
|
||||
var dataSrc = {
|
||||
"Email": lodash.values(config.emailFor)[0] || ' ',
|
||||
"Feedback": ' ',
|
||||
"Score": $stateParams.score,
|
||||
"AppVersion": $window.version,
|
||||
"Platform": ionic.Platform.platform(),
|
||||
"DeviceVersion": ionic.Platform.version()
|
||||
};
|
||||
feedbackService.send(dataSrc, function(err) {
|
||||
if (err) {
|
||||
// try to send, but not essential, since the user didn't add a message
|
||||
$log.warn('Could not send feedback.');
|
||||
}
|
||||
});
|
||||
$state.go('tabs.rate.complete', {
|
||||
score: $stateParams.score,
|
||||
skipped: true
|
||||
});
|
||||
};
|
||||
|
||||
$scope.sendFeedback = function() {
|
||||
$state.go('tabs.rate.send', {
|
||||
score: $scope.score
|
||||
});
|
||||
};
|
||||
|
||||
$scope.goAppStore = function() {
|
||||
var defaults = configService.getDefaults();
|
||||
var url;
|
||||
if (isAndroid) url = defaults.rateApp.android;
|
||||
if (isIOS) url = defaults.rateApp.ios;
|
||||
// if (isWP) url = defaults.rateApp.windows; // TODO
|
||||
externalLinkService.open(url);
|
||||
$state.go('tabs.rate.complete', {
|
||||
score: $stateParams.score,
|
||||
skipped: true,
|
||||
rated: true
|
||||
});
|
||||
};
|
||||
});
|
||||
59
src/js/controllers/feedback/rateCard.js
Normal file
59
src/js/controllers/feedback/rateCard.js
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('rateCardController', function($scope, $state, $timeout, $log, gettextCatalog, platformInfo, storageService) {
|
||||
|
||||
$scope.isCordova = platformInfo.isCordova;
|
||||
$scope.score = 0;
|
||||
|
||||
$scope.goFeedbackFlow = function() {
|
||||
$scope.hideCard();
|
||||
if ($scope.isCordova && $scope.score == 5) {
|
||||
$state.go('tabs.rate.rateApp', {
|
||||
score: $scope.score
|
||||
});
|
||||
} else {
|
||||
$state.go('tabs.rate.send', {
|
||||
score: $scope.score
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.setScore = function(score) {
|
||||
$scope.score = score;
|
||||
switch ($scope.score) {
|
||||
case 1:
|
||||
$scope.button_title = gettextCatalog.getString("I think this app is terrible.");
|
||||
break;
|
||||
case 2:
|
||||
$scope.button_title = gettextCatalog.getString("I don't like it");
|
||||
break;
|
||||
case 3:
|
||||
$scope.button_title = gettextCatalog.getString("Meh - it's alright");
|
||||
break;
|
||||
case 4:
|
||||
$scope.button_title = gettextCatalog.getString("I like the app");
|
||||
break;
|
||||
case 5:
|
||||
$scope.button_title = gettextCatalog.getString("This app is fantastic!");
|
||||
break;
|
||||
}
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.hideCard = function() {
|
||||
$log.debug('Feedback card dismissed.')
|
||||
storageService.getFeedbackInfo(function(error, info) {
|
||||
var feedbackInfo = JSON.parse(info);
|
||||
feedbackInfo.sent = true;
|
||||
storageService.setFeedbackInfo(JSON.stringify(feedbackInfo), function() {
|
||||
$scope.showRateCard.value = false;
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
}, 100);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
92
src/js/controllers/feedback/send.js
Normal file
92
src/js/controllers/feedback/send.js
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('sendController', function($scope, $state, $log, $timeout, $stateParams, $ionicNavBarDelegate, $ionicHistory, $ionicConfig, $window, gettextCatalog, popupService, configService, lodash, feedbackService, ongoingProcess) {
|
||||
|
||||
$scope.sendFeedback = function(feedback, goHome) {
|
||||
|
||||
var config = configService.getSync();
|
||||
|
||||
var dataSrc = {
|
||||
"Email": lodash.values(config.emailFor)[0] || ' ',
|
||||
"Feedback": goHome ? ' ' : feedback,
|
||||
"Score": $stateParams.score || ' ',
|
||||
"AppVersion": $window.version,
|
||||
"Platform": ionic.Platform.platform(),
|
||||
"DeviceVersion": ionic.Platform.version()
|
||||
};
|
||||
|
||||
if (!goHome) ongoingProcess.set('sendingFeedback', true);
|
||||
feedbackService.send(dataSrc, function(err) {
|
||||
if (goHome) return;
|
||||
ongoingProcess.set('sendingFeedback', false);
|
||||
if (err) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Feedback could not be submitted. Please try again later.'));
|
||||
return;
|
||||
}
|
||||
if (!$stateParams.score) {
|
||||
popupService.showAlert(gettextCatalog.getString('Thank you!'), gettextCatalog.getString('A member of the team will review your feedback as soon as possible.'), function() {
|
||||
$scope.feedback.value = '';
|
||||
$ionicHistory.nextViewOptions({
|
||||
disableAnimate: false,
|
||||
historyRoot: true
|
||||
});
|
||||
$ionicHistory.goBack();
|
||||
}, gettextCatalog.getString('Finish'));
|
||||
return;
|
||||
}
|
||||
$state.go('tabs.rate.complete', {
|
||||
score: $stateParams.score
|
||||
});
|
||||
});
|
||||
if (goHome) $state.go('tabs.home');
|
||||
};
|
||||
|
||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||
$scope.score = (data.stateParams && data.stateParams.score) ? parseInt(data.stateParams.score) : null;
|
||||
$scope.feedback = {};
|
||||
|
||||
if ($scope.score) {
|
||||
$ionicConfig.views.swipeBackEnabled(false);
|
||||
}
|
||||
|
||||
switch ($scope.score) {
|
||||
case 1:
|
||||
$scope.reaction = "Ouch!";
|
||||
$scope.comment = gettextCatalog.getString("There's obviously something we're doing wrong.") + ' ' + gettextCatalog.getString("How could we improve your experience?");
|
||||
break;
|
||||
case 2:
|
||||
$scope.reaction = gettextCatalog.getString("Oh no!");
|
||||
$scope.comment = gettextCatalog.getString("There's obviously something we're doing wrong.") + ' ' + gettextCatalog.getString("How could we improve your experience?");
|
||||
break;
|
||||
case 3:
|
||||
$scope.reaction = "Hmm...";
|
||||
$scope.comment = gettextCatalog.getString("We'd love to do better.") + ' ' + gettextCatalog.getString("How could we improve your experience?");
|
||||
break;
|
||||
case 4:
|
||||
$scope.reaction = gettextCatalog.getString("Thanks!");
|
||||
$scope.comment = gettextCatalog.getString("That's exciting to hear. We'd love to earn that fifth star from you – how could we improve your experience?");
|
||||
break;
|
||||
case 5:
|
||||
$scope.reaction = gettextCatalog.getString("Thank you!");
|
||||
$scope.comment = gettextCatalog.getString("We're always looking for ways to improve BitPay.") + ' ' + gettextCatalog.getString("Is there anything we could do better?");
|
||||
break;
|
||||
default:
|
||||
$scope.justFeedback = true;
|
||||
$scope.comment = gettextCatalog.getString("We're always looking for ways to improve BitPay. How could we improve your experience?");
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$on("$ionicView.afterEnter", function() {
|
||||
$scope.showForm = true;
|
||||
});
|
||||
|
||||
$scope.goBack = function() {
|
||||
$ionicHistory.nextViewOptions({
|
||||
disableAnimate: false,
|
||||
historyRoot: true
|
||||
});
|
||||
$ionicHistory.goBack();
|
||||
};
|
||||
|
||||
});
|
||||
|
|
@ -18,9 +18,11 @@ angular.module('copayApp.controllers').controller('glideraController',
|
|||
$scope.status = null;
|
||||
$scope.limits = null;
|
||||
|
||||
$scope.connectingGlidera = true;
|
||||
ongoingProcess.set('connectingGlidera', true);
|
||||
glideraService.init($scope.token, function(err, glidera) {
|
||||
ongoingProcess.set('connectingGlidera');
|
||||
$scope.connectingGlidera = false;
|
||||
if (err || !glidera) {
|
||||
if (err) popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||
return;
|
||||
|
|
@ -67,11 +69,11 @@ angular.module('copayApp.controllers').controller('glideraController',
|
|||
}
|
||||
};
|
||||
|
||||
this.getAuthenticateUrl = function() {
|
||||
$scope.getAuthenticateUrl = function() {
|
||||
return glideraService.getOauthCodeUrl();
|
||||
};
|
||||
|
||||
this.submitOauthCode = function(code) {
|
||||
$scope.submitOauthCode = function(code) {
|
||||
ongoingProcess.set('connectingGlidera', true);
|
||||
$timeout(function() {
|
||||
glideraService.getToken(code, function(err, data) {
|
||||
|
|
@ -90,10 +92,7 @@ angular.module('copayApp.controllers').controller('glideraController',
|
|||
}, 100);
|
||||
};
|
||||
|
||||
this.openTxModal = function(token, tx) {
|
||||
var self = this;
|
||||
|
||||
$scope.self = self;
|
||||
$scope.openTxModal = function(token, tx) {
|
||||
$scope.tx = tx;
|
||||
|
||||
glideraService.getTransaction(token, tx.transactionUuid, function(err, tx) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('headController',
|
||||
function($scope, $window, $log, glideraService) {
|
||||
function($scope, $window, $log) {
|
||||
$scope.appConfig = $window.appConfig;
|
||||
$log.info('Running head controller:' + $window.appConfig.nameCase)
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('importController',
|
||||
function($scope, $timeout, $log, $state, $stateParams, $ionicHistory, $ionicScrollDelegate, profileService, configService, sjcl, ledger, trezor, derivationPathHelper, platformInfo, bwcService, ongoingProcess, walletService, popupService, gettextCatalog) {
|
||||
function($scope, $timeout, $log, $state, $stateParams, $ionicHistory, $ionicScrollDelegate, profileService, configService, sjcl, ledger, trezor, derivationPathHelper, platformInfo, bwcService, ongoingProcess, walletService, popupService, gettextCatalog, $window) {
|
||||
|
||||
var isChromeApp = platformInfo.isChromeApp;
|
||||
var isDevel = platformInfo.isDevel;
|
||||
|
|
@ -17,6 +17,7 @@ angular.module('copayApp.controllers').controller('importController',
|
|||
$scope.formData.derivationPath = derivationPathHelper.default;
|
||||
$scope.formData.account = 1;
|
||||
$scope.importErr = false;
|
||||
$scope.showHardwareWallet = $window.appConfig.name == 'copay';
|
||||
|
||||
if ($stateParams.code)
|
||||
$scope.processWalletInfo($stateParams.code);
|
||||
|
|
@ -359,7 +360,11 @@ angular.module('copayApp.controllers').controller('importController',
|
|||
$scope.resizeView = function() {
|
||||
$timeout(function() {
|
||||
$ionicScrollDelegate.resize();
|
||||
});
|
||||
}, 10);
|
||||
};
|
||||
|
||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||
$scope.init();
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('joinController',
|
||||
function($scope, $rootScope, $timeout, $state, $ionicHistory, $ionicScrollDelegate, profileService, configService, storageService, applicationService, gettext, gettextCatalog, lodash, ledger, trezor, platformInfo, derivationPathHelper, ongoingProcess, walletService, $log, $stateParams, popupService) {
|
||||
function($scope, $rootScope, $timeout, $state, $ionicHistory, $ionicScrollDelegate, profileService, configService, storageService, applicationService, gettextCatalog, lodash, ledger, trezor, platformInfo, derivationPathHelper, ongoingProcess, walletService, $log, $stateParams, popupService, $window) {
|
||||
|
||||
var isChromeApp = platformInfo.isChromeApp;
|
||||
var isDevel = platformInfo.isDevel;
|
||||
|
|
@ -20,7 +20,7 @@ angular.module('copayApp.controllers').controller('joinController',
|
|||
$scope.resizeView = function() {
|
||||
$timeout(function() {
|
||||
$ionicScrollDelegate.resize();
|
||||
});
|
||||
}, 10);
|
||||
checkPasswordFields();
|
||||
};
|
||||
|
||||
|
|
@ -50,26 +50,33 @@ angular.module('copayApp.controllers').controller('joinController',
|
|||
var updateSeedSourceSelect = function() {
|
||||
self.seedOptions = [{
|
||||
id: 'new',
|
||||
label: gettext('Random'),
|
||||
label: gettextCatalog.getString('Random'),
|
||||
}, {
|
||||
id: 'set',
|
||||
label: gettext('Specify Recovery Phrase...'),
|
||||
label: gettextCatalog.getString('Specify Recovery Phrase...'),
|
||||
}];
|
||||
$scope.seedSource = self.seedOptions[0];
|
||||
|
||||
/*
|
||||
|
||||
if (isChromeApp) {
|
||||
self.seedOptions.push({
|
||||
id: 'ledger',
|
||||
label: 'Ledger Hardware Wallet',
|
||||
});
|
||||
}
|
||||
Disable Hardware Wallets
|
||||
|
||||
if (isChromeApp || isDevel) {
|
||||
self.seedOptions.push({
|
||||
id: 'trezor',
|
||||
label: 'Trezor Hardware Wallet',
|
||||
});
|
||||
*/
|
||||
|
||||
if ($window.appConfig.name == 'copay') {
|
||||
if (isChromeApp) {
|
||||
self.seedOptions.push({
|
||||
id: 'ledger',
|
||||
label: 'Ledger Hardware Wallet',
|
||||
});
|
||||
}
|
||||
|
||||
if (isChromeApp || isDevel) {
|
||||
self.seedOptions.push({
|
||||
id: 'trezor',
|
||||
label: 'Trezor Hardware Wallet',
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@ angular.module('copayApp.controllers').controller('amazonCardDetailsController',
|
|||
$scope.amazonCardDetailsModal.hide();
|
||||
};
|
||||
|
||||
$scope.openExternalLink = function(url, optIn, title, message, okText, cancelText) {
|
||||
externalLinkService.open(url, optIn, title, message, okText, cancelText);
|
||||
$scope.openExternalLink = function(url) {
|
||||
externalLinkService.open(url);
|
||||
};
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,79 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('customAmountController', function($scope, $timeout, $filter, platformInfo, rateService) {
|
||||
var self = $scope.self;
|
||||
|
||||
$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;
|
||||
$scope.isCordova = platformInfo.isCordova;
|
||||
|
||||
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);
|
||||
} else {
|
||||
$scope.customAmount = null;
|
||||
}
|
||||
},
|
||||
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 {
|
||||
$scope.customAlternative = null;
|
||||
}
|
||||
$scope.alternativeAmount = $scope.customAlternative;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
$scope.submitForm = function(form) {
|
||||
var satToBtc = 1 / 100000000;
|
||||
var amount = form.amount.$modelValue;
|
||||
var amountSat = parseInt((amount * $scope.unitToSatoshi).toFixed(0));
|
||||
$timeout(function() {
|
||||
$scope.customizedAmountUnit = amount + ' ' + $scope.unitName;
|
||||
$scope.customizedAlternativeUnit = $filter('formatFiatAmount')(form.alternative.$modelValue) + ' ' + $scope.alternativeIsoCode;
|
||||
if ($scope.unitName == 'bits') {
|
||||
amount = (amountSat * satToBtc).toFixed(8);
|
||||
}
|
||||
$scope.customizedAmountBtc = amount;
|
||||
}, 1);
|
||||
};
|
||||
|
||||
$scope.toggleAlternative = function() {
|
||||
$scope.showAlternative = !$scope.showAlternative;
|
||||
};
|
||||
|
||||
$scope.shareAddress = function(uri) {
|
||||
if (platformInfo.isCordova) {
|
||||
window.plugins.socialsharing.share(uri, null, null, null);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.cancel = function() {
|
||||
$scope.customAmountModal.hide();
|
||||
};
|
||||
});
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('searchController', function($scope, $rootScope, $interval, $timeout, $filter, $log, $ionicModal, $ionicPopover, $ionicNavBarDelegate, $state, $stateParams, $ionicScrollDelegate, bwcError, profileService, lodash, configService, gettext, gettextCatalog, platformInfo, walletService) {
|
||||
angular.module('copayApp.controllers').controller('searchController', function($scope, $rootScope, $interval, $timeout, $filter, $log, $ionicModal, $ionicPopover, $state, $stateParams, $ionicScrollDelegate, bwcError, profileService, lodash, configService, gettext, gettextCatalog, platformInfo, walletService) {
|
||||
|
||||
var HISTORY_SHOW_LIMIT = 10;
|
||||
var currentTxHistoryPage = 0;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('txpDetailsController', function($scope, $rootScope, $timeout, $interval, $ionicModal, $log, ongoingProcess, platformInfo, $ionicScrollDelegate, txFormatService, fingerprintService, bwcError, gettextCatalog, lodash, walletService, popupService, $state, $ionicHistory) {
|
||||
var self = $scope.self;
|
||||
var tx = $scope.tx;
|
||||
var copayers = $scope.copayers;
|
||||
angular.module('copayApp.controllers').controller('txpDetailsController', function($scope, $rootScope, $timeout, $interval, $log, ongoingProcess, platformInfo, $ionicScrollDelegate, txFormatService, bwcError, gettextCatalog, lodash, walletService, popupService, $ionicHistory) {
|
||||
var isGlidera = $scope.isGlidera;
|
||||
var GLIDERA_LOCK_TIME = 6 * 60 * 60;
|
||||
var now = Math.floor(Date.now() / 1000);
|
||||
|
|
@ -18,8 +15,8 @@ angular.module('copayApp.controllers').controller('txpDetailsController', functi
|
|||
$scope.color = $scope.wallet.color;
|
||||
$scope.data = {};
|
||||
$scope.hasClick = platformInfo.hasClick;
|
||||
$scope.displayAmount = getDisplayAmount(tx.amountStr);
|
||||
$scope.displayUnit = getDisplayUnit(tx.amountStr);
|
||||
$scope.displayAmount = getDisplayAmount($scope.tx.amountStr);
|
||||
$scope.displayUnit = getDisplayUnit($scope.tx.amountStr);
|
||||
initActionList();
|
||||
checkPaypro();
|
||||
}
|
||||
|
|
@ -46,12 +43,12 @@ angular.module('copayApp.controllers').controller('txpDetailsController', functi
|
|||
|
||||
$scope.actionList.push({
|
||||
type: 'created',
|
||||
time: tx.createdOn,
|
||||
time: $scope.tx.createdOn,
|
||||
description: actionDescriptions['created'],
|
||||
by: tx.creatorName
|
||||
by: $scope.tx.creatorName
|
||||
});
|
||||
|
||||
lodash.each(tx.actions, function(action) {
|
||||
lodash.each($scope.tx.actions, function(action) {
|
||||
$scope.actionList.push({
|
||||
type: action.type,
|
||||
time: action.createdOn,
|
||||
|
|
@ -61,103 +58,14 @@ angular.module('copayApp.controllers').controller('txpDetailsController', functi
|
|||
});
|
||||
};
|
||||
|
||||
$scope.$on('accepted', function(event) {
|
||||
$scope.sign();
|
||||
});
|
||||
|
||||
// ToDo: use tx.customData instead of tx.message
|
||||
if (tx.message === 'Glidera transaction' && isGlidera) {
|
||||
tx.isGlidera = true;
|
||||
if (tx.canBeRemoved) {
|
||||
tx.canBeRemoved = (Date.now() / 1000 - (tx.ts || tx.createdOn)) > GLIDERA_LOCK_TIME;
|
||||
}
|
||||
}
|
||||
|
||||
var setSendError = function(msg) {
|
||||
$scope.sendStatus = '';
|
||||
var error = msg || gettextCatalog.getString('Could not send payment');
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), error);
|
||||
}
|
||||
|
||||
$scope.sign = function(onSendStatusChange) {
|
||||
$scope.loading = true;
|
||||
walletService.publishAndSign($scope.wallet, $scope.tx, function(err, txp) {
|
||||
$scope.$emit('UpdateTx');
|
||||
if (err) return setSendError(err);
|
||||
success();
|
||||
}, onSendStatusChange);
|
||||
};
|
||||
|
||||
function setError(err, prefix) {
|
||||
$scope.loading = false;
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err, prefix));
|
||||
};
|
||||
|
||||
$scope.reject = function(txp) {
|
||||
var title = gettextCatalog.getString('Warning!');
|
||||
var msg = gettextCatalog.getString('Are you sure you want to reject this transaction?');
|
||||
popupService.showConfirm(title, msg, null, null, function(res) {
|
||||
if (res) {
|
||||
$scope.loading = true;
|
||||
|
||||
walletService.reject($scope.wallet, $scope.tx, function(err, txpr) {
|
||||
if (err)
|
||||
return setError(err, gettextCatalog.getString('Could not reject payment'));
|
||||
|
||||
$scope.close();
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.remove = function() {
|
||||
$scope.loading = true;
|
||||
|
||||
$timeout(function() {
|
||||
ongoingProcess.set('removeTx', true);
|
||||
walletService.removeTx($scope.wallet, $scope.tx, function(err) {
|
||||
ongoingProcess.set('removeTx', false);
|
||||
|
||||
// Hacky: request tries to parse an empty response
|
||||
if (err && !(err.message && err.message.match(/Unexpected/))) {
|
||||
$scope.$emit('UpdateTx');
|
||||
return setError(err, gettextCatalog.getString('Could not delete payment proposal'));
|
||||
}
|
||||
|
||||
$scope.close();
|
||||
});
|
||||
}, 10);
|
||||
};
|
||||
|
||||
$scope.broadcast = function(txp) {
|
||||
$scope.loading = true;
|
||||
|
||||
$timeout(function() {
|
||||
ongoingProcess.set('broadcastTx', true);
|
||||
walletService.broadcastTx($scope.wallet, $scope.tx, function(err, txpb) {
|
||||
ongoingProcess.set('broadcastTx', false);
|
||||
|
||||
if (err) {
|
||||
return setError(err, gettextCatalog.getString('Could not broadcast payment'));
|
||||
}
|
||||
|
||||
$scope.close();
|
||||
});
|
||||
}, 10);
|
||||
};
|
||||
|
||||
$scope.getShortNetworkName = function() {
|
||||
return $scope.wallet.credentials.networkName.substring(0, 4);
|
||||
};
|
||||
|
||||
function checkPaypro() {
|
||||
if (tx.payProUrl && !platformInfo.isChromeApp) {
|
||||
if ($scope.tx.payProUrl && !platformInfo.isChromeApp) {
|
||||
$scope.wallet.fetchPayPro({
|
||||
payProUrl: tx.payProUrl,
|
||||
payProUrl: $scope.tx.payProUrl,
|
||||
}, function(err, paypro) {
|
||||
if (err) return;
|
||||
tx.paypro = paypro;
|
||||
paymentTimeControl(tx.paypro.expires);
|
||||
$scope.tx.paypro = paypro;
|
||||
paymentTimeControl($scope.tx.paypro.expires);
|
||||
$timeout(function() {
|
||||
$ionicScrollDelegate.resize();
|
||||
}, 10);
|
||||
|
|
@ -187,32 +95,132 @@ angular.module('copayApp.controllers').controller('txpDetailsController', functi
|
|||
};
|
||||
};
|
||||
|
||||
lodash.each(['TxProposalRejectedBy', 'TxProposalAcceptedBy', 'transactionProposalRemoved', 'TxProposalRemoved', 'NewOutgoingTx', 'UpdateTx'], function(eventName) {
|
||||
$rootScope.$on(eventName, function() {
|
||||
$scope.wallet.getTx($scope.tx.id, function(err, tx) {
|
||||
if (err) {
|
||||
if (err.message && err.message == 'TX_NOT_FOUND' &&
|
||||
(eventName == 'transactionProposalRemoved' || eventName == 'TxProposalRemoved')) {
|
||||
$scope.tx.removed = true;
|
||||
$scope.tx.canBeRemoved = false;
|
||||
$scope.tx.pendingForUs = false;
|
||||
$scope.$apply();
|
||||
$scope.$on('accepted', function(event) {
|
||||
$scope.sign();
|
||||
});
|
||||
|
||||
// ToDo: use tx.customData instead of tx.message
|
||||
if ($scope.tx.message === 'Glidera transaction' && isGlidera) {
|
||||
$scope.tx.isGlidera = true;
|
||||
if ($scope.tx.canBeRemoved) {
|
||||
$scope.tx.canBeRemoved = (Date.now() / 1000 - ($scope.tx.ts || $scope.tx.createdOn)) > GLIDERA_LOCK_TIME;
|
||||
}
|
||||
}
|
||||
|
||||
var setError = function(err, prefix) {
|
||||
$scope.sendStatus = '';
|
||||
$scope.loading = false;
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err, prefix));
|
||||
};
|
||||
|
||||
$scope.sign = function(onSendStatusChange) {
|
||||
$scope.loading = true;
|
||||
walletService.publishAndSign($scope.wallet, $scope.tx, function(err, txp) {
|
||||
$scope.$emit('UpdateTx');
|
||||
if (err) return setError(err, gettextCatalog.getString('Could not send payment'));
|
||||
success();
|
||||
}, onSendStatusChange);
|
||||
};
|
||||
|
||||
$scope.reject = function(txp) {
|
||||
var title = gettextCatalog.getString('Warning!');
|
||||
var msg = gettextCatalog.getString('Are you sure you want to reject this transaction?');
|
||||
popupService.showConfirm(title, msg, null, null, function(res) {
|
||||
if (res) {
|
||||
$scope.loading = true;
|
||||
|
||||
walletService.reject($scope.wallet, $scope.tx, function(err, txpr) {
|
||||
if (err)
|
||||
return setError(err, gettextCatalog.getString('Could not reject payment'));
|
||||
|
||||
$scope.close();
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.remove = function() {
|
||||
var title = gettextCatalog.getString('Warning!');
|
||||
var msg = gettextCatalog.getString('Are you sure you want to remove this transaction?');
|
||||
popupService.showConfirm(title, msg, null, null, function(res) {
|
||||
if (res) {
|
||||
ongoingProcess.set('removeTx', true);
|
||||
walletService.removeTx($scope.wallet, $scope.tx, function(err) {
|
||||
ongoingProcess.set('removeTx', false);
|
||||
|
||||
// Hacky: request tries to parse an empty response
|
||||
if (err && !(err.message && err.message.match(/Unexpected/))) {
|
||||
$scope.$emit('UpdateTx');
|
||||
return setError(err, gettextCatalog.getString('Could not delete payment proposal'));
|
||||
}
|
||||
return;
|
||||
|
||||
$scope.close();
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.broadcast = function(txp) {
|
||||
$scope.loading = true;
|
||||
|
||||
$timeout(function() {
|
||||
ongoingProcess.set('broadcastingTx', true);
|
||||
walletService.broadcastTx($scope.wallet, $scope.tx, function(err, txpb) {
|
||||
ongoingProcess.set('broadcastingTx', false);
|
||||
|
||||
if (err) {
|
||||
return setError(err, gettextCatalog.getString('Could not broadcast payment'));
|
||||
}
|
||||
|
||||
var action = lodash.find(tx.actions, {
|
||||
copayerId: $scope.wallet.credentials.copayerId
|
||||
});
|
||||
|
||||
$scope.tx = txFormatService.processTx(tx);
|
||||
|
||||
if (!action && tx.status == 'pending')
|
||||
$scope.tx.pendingForUs = true;
|
||||
|
||||
$scope.updateCopayerList();
|
||||
$scope.$apply();
|
||||
$scope.close();
|
||||
});
|
||||
}, 10);
|
||||
};
|
||||
|
||||
$scope.getShortNetworkName = function() {
|
||||
return $scope.wallet.credentials.networkName.substring(0, 4);
|
||||
};
|
||||
|
||||
var updateTxInfo = function(eventName) {
|
||||
$scope.wallet.getTx($scope.tx.id, function(err, tx) {
|
||||
if (err) {
|
||||
if (err.message && err.message == 'Transaction proposal not found' &&
|
||||
(eventName == 'transactionProposalRemoved' || eventName == 'TxProposalRemoved')) {
|
||||
$scope.tx.removed = true;
|
||||
$scope.tx.canBeRemoved = false;
|
||||
$scope.tx.pendingForUs = false;
|
||||
$scope.$apply();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var action = lodash.find(tx.actions, {
|
||||
copayerId: $scope.wallet.credentials.copayerId
|
||||
});
|
||||
|
||||
$scope.tx = txFormatService.processTx(tx);
|
||||
|
||||
if (!action && tx.status == 'pending')
|
||||
$scope.tx.pendingForUs = true;
|
||||
|
||||
$scope.updateCopayerList();
|
||||
initActionList();
|
||||
$scope.$apply();
|
||||
});
|
||||
};
|
||||
|
||||
var bwsEvent = $rootScope.$on('bwsEvent', function(e, walletId, type, n) {
|
||||
lodash.each([
|
||||
'TxProposalRejectedBy',
|
||||
'TxProposalAcceptedBy',
|
||||
'transactionProposalRemoved',
|
||||
'TxProposalRemoved',
|
||||
'NewOutgoingTx',
|
||||
'UpdateTx'
|
||||
], function(eventName) {
|
||||
if (walletId == $scope.wallet.id && type == eventName) {
|
||||
updateTxInfo(eventName);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -252,6 +260,7 @@ angular.module('copayApp.controllers').controller('txpDetailsController', functi
|
|||
};
|
||||
|
||||
$scope.close = function() {
|
||||
bwsEvent();
|
||||
$scope.loading = null;
|
||||
$scope.txpDetailsModal.hide();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ angular.module('copayApp.controllers').controller('backupWarningController', fun
|
|||
$scope.openPopup = function() {
|
||||
$ionicModal.fromTemplateUrl('views/includes/screenshotWarningModal.html', {
|
||||
scope: $scope,
|
||||
backdropClickToClose: false,
|
||||
hardwareBackButtonClose: false
|
||||
backdropClickToClose: true,
|
||||
hardwareBackButtonClose: true
|
||||
}).then(function(modal) {
|
||||
$scope.warningModal = modal;
|
||||
$scope.warningModal.show();
|
||||
|
|
|
|||
|
|
@ -1,17 +1,18 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('disclaimerController', function($scope, $timeout, $state, $log, $ionicModal, profileService, uxLanguage, externalLinkService, storageService, $stateParams, startupService) {
|
||||
angular.module('copayApp.controllers').controller('disclaimerController', function($scope, $timeout, $state, $log, $ionicModal, profileService, uxLanguage, externalLinkService, storageService, $stateParams, startupService, $rootScope) {
|
||||
|
||||
$scope.$on("$ionicView.afterEnter", function() {
|
||||
startupService.ready();
|
||||
});
|
||||
|
||||
$scope.init = function() {
|
||||
$scope.lang = uxLanguage.currentLanguage;
|
||||
$scope.terms = {};
|
||||
$scope.accept1 = $scope.accept2 = $scope.accept3 = false;
|
||||
$scope.accepted = {};
|
||||
$scope.accepted.first = $scope.accepted.second = $scope.accepted.third = false;
|
||||
$scope.backedUp = $stateParams.backedUp;
|
||||
$scope.resume = $stateParams.resume;
|
||||
$scope.shrinkView = false;
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
}, 1);
|
||||
|
|
@ -32,14 +33,9 @@ angular.module('copayApp.controllers').controller('disclaimerController', functi
|
|||
externalLinkService.open(url, target);
|
||||
};
|
||||
|
||||
$scope.openTermsModal = function() {
|
||||
$ionicModal.fromTemplateUrl('views/modals/terms.html', {
|
||||
scope: $scope
|
||||
}).then(function(modal) {
|
||||
$scope.termsModal = modal;
|
||||
$scope.termsModal.show();
|
||||
});
|
||||
};
|
||||
$scope.openTerms = function() {
|
||||
$scope.shrinkView = !$scope.shrinkView;
|
||||
}
|
||||
|
||||
$scope.goBack = function() {
|
||||
$state.go('onboarding.backupRequest', {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('termsController', function($scope, $log, $state, $window, uxLanguage, profileService, externalLinkService) {
|
||||
angular.module('copayApp.controllers').controller('termsController', function($scope, $log, $state, $window, uxLanguage, profileService, externalLinkService, gettextCatalog) {
|
||||
$scope.lang = uxLanguage.currentLanguage;
|
||||
$scope.disclaimerUrl = $window.appConfig.disclaimerUrl;
|
||||
|
||||
$scope.confirm = function() {
|
||||
profileService.setDisclaimerAccepted(function(err) {
|
||||
|
|
@ -15,7 +14,13 @@ angular.module('copayApp.controllers').controller('termsController', function($s
|
|||
});
|
||||
};
|
||||
|
||||
$scope.openExternalLink = function(url, optIn, title, message, okText, cancelText) {
|
||||
$scope.openExternalLink = function() {
|
||||
var url = $window.appConfig.disclaimerUrl;
|
||||
var optIn = true;
|
||||
var title = gettextCatalog.getString('View Terms of Service');
|
||||
var message = gettextCatalog.getString('The official English Terms of Service are available on the BitPay website. Would you like to view them?');
|
||||
var okText = gettextCatalog.getString('Open Website');
|
||||
var cancelText = gettextCatalog.getString('Go Back');
|
||||
externalLinkService.open(url, optIn, title, message, okText, cancelText);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('welcomeController', function($scope, $state, $timeout, $ionicConfig, $log, profileService, startupService) {
|
||||
angular.module('copayApp.controllers').controller('welcomeController', function($scope, $state, $timeout, $ionicConfig, $log, profileService, startupService, storageService) {
|
||||
|
||||
$ionicConfig.views.swipeBackEnabled(false);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,24 +1,14 @@
|
|||
angular.module('copayApp.controllers').controller('paperWalletController',
|
||||
function($scope, $timeout, $log, $ionicModal, $ionicHistory, popupService, gettextCatalog, platformInfo, configService, profileService, $state, bitcore, ongoingProcess, txFormatService, $stateParams, walletService) {
|
||||
|
||||
$scope.onQrCodeScanned = function(data) {
|
||||
$scope.formData.inputData = data;
|
||||
$scope.onData(data);
|
||||
};
|
||||
|
||||
$scope.onData = function(data) {
|
||||
$scope.scannedKey = data;
|
||||
$scope.isPkEncrypted = (data.substring(0, 2) == '6P');
|
||||
};
|
||||
function($scope, $timeout, $log, $ionicModal, $ionicHistory, feeService, popupService, gettextCatalog, platformInfo, configService, profileService, $state, bitcore, ongoingProcess, txFormatService, $stateParams, walletService) {
|
||||
|
||||
function _scanFunds(cb) {
|
||||
function getPrivateKey(scannedKey, isPkEncrypted, passphrase, cb) {
|
||||
if (!isPkEncrypted) return cb(null, scannedKey);
|
||||
wallet.decryptBIP38PrivateKey(scannedKey, passphrase, null, cb);
|
||||
$scope.wallet.decryptBIP38PrivateKey(scannedKey, passphrase, null, cb);
|
||||
};
|
||||
|
||||
function getBalance(privateKey, cb) {
|
||||
wallet.getBalanceFromPrivateKey(privateKey, cb);
|
||||
$scope.wallet.getBalanceFromPrivateKey(privateKey, cb);
|
||||
};
|
||||
|
||||
function checkPrivateKey(privateKey) {
|
||||
|
|
@ -42,9 +32,6 @@ angular.module('copayApp.controllers').controller('paperWalletController',
|
|||
};
|
||||
|
||||
$scope.scanFunds = function() {
|
||||
$scope.privateKey = '';
|
||||
$scope.balanceSat = 0;
|
||||
|
||||
ongoingProcess.set('scanning', true);
|
||||
$timeout(function() {
|
||||
_scanFunds(function(err, privateKey, balance) {
|
||||
|
|
@ -52,32 +39,40 @@ angular.module('copayApp.controllers').controller('paperWalletController',
|
|||
if (err) {
|
||||
$log.error(err);
|
||||
popupService.showAlert(gettextCatalog.getString('Error scanning funds:'), err || err.toString());
|
||||
$state.go('tabs.home');
|
||||
} else {
|
||||
$scope.privateKey = privateKey;
|
||||
$scope.balanceSat = balance;
|
||||
if ($scope.balanceSat <= 0)
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Not funds found'));
|
||||
var config = configService.getSync().wallet.settings;
|
||||
$scope.balance = txFormatService.formatAmount(balance) + ' ' + config.unitName;
|
||||
$scope.scanned = true;
|
||||
}
|
||||
|
||||
$scope.$apply();
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
||||
function _sweepWallet(cb) {
|
||||
walletService.getAddress(wallet, true, function(err, destinationAddress) {
|
||||
walletService.getAddress($scope.wallet, true, function(err, destinationAddress) {
|
||||
if (err) return cb(err);
|
||||
|
||||
wallet.buildTxFromPrivateKey($scope.privateKey, destinationAddress, null, function(err, tx) {
|
||||
$scope.wallet.buildTxFromPrivateKey($scope.privateKey, destinationAddress, null, function(err, testTx) {
|
||||
if (err) return cb(err);
|
||||
|
||||
wallet.broadcastRawTx({
|
||||
rawTx: tx.serialize(),
|
||||
network: 'livenet'
|
||||
}, function(err, txid) {
|
||||
if (err) return cb(err);
|
||||
return cb(null, destinationAddress, txid);
|
||||
var rawTxLength = testTx.serialize().length;
|
||||
feeService.getCurrentFeeValue('livenet', function(err, feePerKB) {
|
||||
var opts = {};
|
||||
opts.fee = Math.round((feePerKB * rawTxLength) / 2000);
|
||||
$scope.wallet.buildTxFromPrivateKey($scope.privateKey, destinationAddress, opts, function(err, tx) {
|
||||
if (err) return cb(err);
|
||||
$scope.wallet.broadcastRawTx({
|
||||
rawTx: tx.serialize(),
|
||||
network: 'livenet'
|
||||
}, function(err, txid) {
|
||||
if (err) return cb(err);
|
||||
return cb(null, destinationAddress, txid);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -95,45 +90,61 @@ angular.module('copayApp.controllers').controller('paperWalletController',
|
|||
$log.error(err);
|
||||
popupService.showAlert(gettextCatalog.getString('Error sweeping wallet:'), err || err.toString());
|
||||
} else {
|
||||
$scope.openStatusModal('broadcasted', function() {
|
||||
$ionicHistory.removeBackView();
|
||||
$state.go('tabs.home');
|
||||
});
|
||||
$scope.sendStatus = 'success';
|
||||
}
|
||||
$scope.$apply();
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
||||
$scope.openStatusModal = function(type, cb) {
|
||||
$scope.tx = {};
|
||||
$scope.tx.amountStr = $scope.balance;
|
||||
$scope.type = type;
|
||||
$scope.color = wallet.backgroundColor;
|
||||
$scope.cb = cb;
|
||||
|
||||
$ionicModal.fromTemplateUrl('views/modals/tx-status.html', {
|
||||
scope: $scope
|
||||
}).then(function(modal) {
|
||||
$scope.txStatusModal = modal;
|
||||
$scope.txStatusModal.show();
|
||||
});
|
||||
$scope.onSuccessConfirm = function() {
|
||||
$state.go('tabs.home');
|
||||
};
|
||||
|
||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||
var wallet = profileService.getWallet($stateParams.walletId);
|
||||
$scope.$on('Wallet/Changed', function(event, wallet) {
|
||||
if (!wallet) {
|
||||
$log.debug('No wallet provided');
|
||||
return;
|
||||
}
|
||||
if (wallet == $scope.wallet) {
|
||||
$log.debug('No change in wallet');
|
||||
return;
|
||||
}
|
||||
$scope.wallet = wallet;
|
||||
$scope.needsBackup = wallet.needsBackup;
|
||||
$scope.walletAlias = wallet.name;
|
||||
$scope.walletName = wallet.credentials.walletName;
|
||||
$scope.formData = {};
|
||||
$scope.formData.inputData = null;
|
||||
$scope.scannedKey = null;
|
||||
$scope.balance = null;
|
||||
$scope.balanceSat = null;
|
||||
$scope.scanned = false;
|
||||
$log.debug('Wallet changed: ' + wallet.name);
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
}, 10);
|
||||
});
|
||||
});
|
||||
|
||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||
$scope.scannedKey = (data.stateParams && data.stateParams.privateKey) ? data.stateParams.privateKey : null;
|
||||
$scope.isPkEncrypted = $scope.scannedKey ? ($scope.scannedKey.substring(0, 2) == '6P') : null;
|
||||
$scope.sendStatus = null;
|
||||
$scope.error = false;
|
||||
|
||||
$scope.wallets = profileService.getWallets({
|
||||
onlyComplete: true,
|
||||
network: 'livenet',
|
||||
});
|
||||
|
||||
if (!$scope.wallets || !$scope.wallets.length) {
|
||||
$scope.noMatchingWallet = true;
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$on("$ionicView.enter", function(event, data) {
|
||||
$scope.wallet = $scope.wallets[0];
|
||||
if (!$scope.wallet) return;
|
||||
if (!$scope.isPkEncrypted) $scope.scanFunds();
|
||||
else {
|
||||
var message = gettextCatalog.getString('Private key encrypted. Enter password');
|
||||
popupService.showPrompt(null, message, null, function(res) {
|
||||
$scope.passphrase = res;
|
||||
$scope.scanFunds();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('preferencesController',
|
||||
function($scope, $rootScope, $timeout, $log, $stateParams, $ionicHistory, gettextCatalog, configService, profileService, fingerprintService, walletService) {
|
||||
function($scope, $rootScope, $timeout, $log, $stateParams, $ionicHistory, configService, profileService, fingerprintService, walletService) {
|
||||
var wallet = profileService.getWallet($stateParams.walletId);
|
||||
var walletId = wallet.credentials.walletId;
|
||||
$scope.wallet = wallet;
|
||||
|
|
@ -10,6 +10,16 @@ angular.module('copayApp.controllers').controller('preferencesController',
|
|||
value: walletService.isEncrypted(wallet)
|
||||
};
|
||||
|
||||
$scope.hiddenBalanceChange = function() {
|
||||
var opts = {
|
||||
balance: {
|
||||
enabled: $scope.hiddenBalance.value
|
||||
}
|
||||
};
|
||||
profileService.toggleHideBalanceFlag(walletId, function(err) {
|
||||
if (err) $log.error(err);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.encryptChange = function() {
|
||||
if (!wallet) return;
|
||||
|
|
@ -75,7 +85,9 @@ angular.module('copayApp.controllers').controller('preferencesController',
|
|||
|
||||
var config = configService.getSync();
|
||||
|
||||
|
||||
$scope.hiddenBalance = {
|
||||
value: $scope.wallet.balanceHidden
|
||||
};
|
||||
|
||||
if (wallet.isPrivKeyExternal)
|
||||
$scope.externalSource = wallet.getPrivKeyExternalSourceName() == 'ledger' ? 'Ledger' : 'Trezor';
|
||||
|
|
|
|||
|
|
@ -6,9 +6,14 @@ angular.module('copayApp.controllers').controller('preferencesAbout',
|
|||
$scope.title = gettextCatalog.getString('About') + ' ' + $window.appConfig.nameCase;
|
||||
$scope.version = $window.version;
|
||||
$scope.commitHash = $window.commitHash;
|
||||
$scope.name = $window.appConfig.gitHubRepoName;
|
||||
|
||||
$scope.openExternalLink = function(url, optIn, title, message, okText, cancelText) {
|
||||
$scope.openExternalLink = function() {
|
||||
var url = 'https://github.com/bitpay/' + $window.appConfig.gitHubRepoName + '/tree/' + $window.commitHash + '';
|
||||
var optIn = true;
|
||||
var title = gettextCatalog.getString('Open GitHub Project');
|
||||
var message = gettextCatalog.getString('You can see the latest developments and contribute to this open source app by visiting our project on GitHub.');
|
||||
var okText = gettextCatalog.getString('Open GitHub');
|
||||
var cancelText = gettextCatalog.getString('Go Back');
|
||||
externalLinkService.open(url, optIn, title, message, okText, cancelText);
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('preferencesAliasController',
|
||||
function($scope, $timeout, $stateParams, $ionicHistory, gettextCatalog, configService, profileService, walletService) {
|
||||
function($scope, $timeout, $stateParams, $ionicHistory, configService, profileService, walletService) {
|
||||
var wallet = profileService.getWallet($stateParams.walletId);
|
||||
var walletId = wallet.credentials.walletId;
|
||||
var config = configService.getSync();
|
||||
|
|
|
|||
|
|
@ -1,22 +1,35 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('preferencesAltCurrencyController',
|
||||
function($scope, $log, $timeout, $ionicHistory, gettextCatalog, configService, rateService, lodash, profileService, walletService) {
|
||||
function($scope, $log, $timeout, $ionicHistory, configService, rateService, lodash, profileService, walletService, storageService) {
|
||||
|
||||
var next = 10;
|
||||
var completeAlternativeList;
|
||||
|
||||
var config = configService.getSync();
|
||||
$scope.currentCurrency = config.wallet.settings.alternativeIsoCode;
|
||||
$scope.listComplete = false;
|
||||
function init() {
|
||||
var unusedCurrencyList = [{
|
||||
isoCode: 'LTL'
|
||||
}, {
|
||||
isoCode: 'BTC'
|
||||
}];
|
||||
rateService.whenAvailable(function() {
|
||||
|
||||
rateService.whenAvailable(function() {
|
||||
completeAlternativeList = rateService.listAlternatives();
|
||||
lodash.remove(completeAlternativeList, function(c) {
|
||||
return c.isoCode == 'BTC';
|
||||
$scope.listComplete = false;
|
||||
|
||||
var idx = lodash.indexBy(unusedCurrencyList, 'isoCode');
|
||||
var idx2 = lodash.indexBy($scope.lastUsedAltCurrencyList, 'isoCode');
|
||||
|
||||
completeAlternativeList = lodash.reject(rateService.listAlternatives(true), function(c) {
|
||||
return idx[c.isoCode] || idx2[c.isoCode];
|
||||
});
|
||||
|
||||
$scope.altCurrencyList = completeAlternativeList.slice(0, 10);
|
||||
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
});
|
||||
});
|
||||
$scope.altCurrencyList = completeAlternativeList.slice(0, next);
|
||||
});
|
||||
}
|
||||
|
||||
$scope.loadMore = function() {
|
||||
$timeout(function() {
|
||||
|
|
@ -27,6 +40,17 @@ angular.module('copayApp.controllers').controller('preferencesAltCurrencyControl
|
|||
}, 100);
|
||||
};
|
||||
|
||||
$scope.findCurrency = function(search) {
|
||||
if (!search) init();
|
||||
$scope.altCurrencyList = lodash.filter(completeAlternativeList, function(item) {
|
||||
var val = item.name;
|
||||
return lodash.includes(val.toLowerCase(), search.toLowerCase());
|
||||
});
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.save = function(newAltCurrency) {
|
||||
var opts = {
|
||||
wallet: {
|
||||
|
|
@ -41,9 +65,27 @@ angular.module('copayApp.controllers').controller('preferencesAltCurrencyControl
|
|||
if (err) $log.warn(err);
|
||||
|
||||
$ionicHistory.goBack();
|
||||
saveLastUsed(newAltCurrency);
|
||||
walletService.updateRemotePreferences(profileService.getWallets(), {}, function() {
|
||||
$log.debug('Remote preferences saved');
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function saveLastUsed(newAltCurrency) {
|
||||
$scope.lastUsedAltCurrencyList.unshift(newAltCurrency);
|
||||
$scope.lastUsedAltCurrencyList = lodash.uniq($scope.lastUsedAltCurrencyList, 'isoCode');
|
||||
$scope.lastUsedAltCurrencyList = $scope.lastUsedAltCurrencyList.slice(0, 3);
|
||||
storageService.setLastCurrencyUsed(JSON.stringify($scope.lastUsedAltCurrencyList), function() {});
|
||||
};
|
||||
|
||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||
var config = configService.getSync();
|
||||
$scope.currentCurrency = config.wallet.settings.alternativeIsoCode;
|
||||
|
||||
storageService.getLastCurrencyUsed(function(err, lastUsedAltCurrency) {
|
||||
$scope.lastUsedAltCurrencyList = lastUsedAltCurrency ? JSON.parse(lastUsedAltCurrency) : [];
|
||||
init();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -13,8 +13,11 @@ angular.module('copayApp.controllers').controller('preferencesBitpayCardControll
|
|||
};
|
||||
|
||||
var remove = function(card) {
|
||||
bitpayCardService.remove(card, function() {
|
||||
$ionicHistory.removeBackView();
|
||||
bitpayCardService.remove(card, function(err) {
|
||||
if (err) {
|
||||
return popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Could not remove card'));
|
||||
}
|
||||
$ionicHistory.clearHistory();
|
||||
$timeout(function() {
|
||||
$state.go('tabs.home');
|
||||
}, 100);
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('preferencesBwsUrlController',
|
||||
function($scope, $log, $stateParams, configService, applicationService, profileService, storageService) {
|
||||
function($scope, $log, $stateParams, configService, applicationService, profileService, storageService, $window) {
|
||||
$scope.success = null;
|
||||
|
||||
var wallet = profileService.getWallet($stateParams.walletId);
|
||||
var walletId = wallet.credentials.walletId;
|
||||
var defaults = configService.getDefaults();
|
||||
var config = configService.getSync();
|
||||
|
||||
$scope.appName = $window.appConfig.nameCase;
|
||||
$scope.bwsurl = {
|
||||
value: (config.bwsFor && config.bwsFor[walletId]) || defaults.bws.url
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('preferencesColorController', function($scope, $timeout, $log, $stateParams, $ionicHistory, gettextCatalog, configService, profileService) {
|
||||
angular.module('copayApp.controllers').controller('preferencesColorController', function($scope, $timeout, $log, $stateParams, $ionicHistory, configService, profileService) {
|
||||
var wallet = profileService.getWallet($stateParams.walletId);
|
||||
$scope.wallet = wallet;
|
||||
var walletId = wallet.credentials.walletId;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('preferencesFeeController', function($scope, $timeout, $ionicHistory, gettextCatalog, configService, feeService, ongoingProcess) {
|
||||
angular.module('copayApp.controllers').controller('preferencesFeeController', function($scope, $timeout, $ionicHistory, gettextCatalog, configService, feeService, ongoingProcess, popupService) {
|
||||
|
||||
ongoingProcess.set('gettingFeeLevels', true);
|
||||
feeService.getFeeLevels(function(levels) {
|
||||
feeService.getFeeLevels(function(err, levels) {
|
||||
ongoingProcess.set('gettingFeeLevels', false);
|
||||
if (err) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||
return;
|
||||
}
|
||||
$scope.feeLevels = levels;
|
||||
$scope.$apply();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('preferencesGlideraController',
|
||||
function($scope, $log, $timeout, $state, ongoingProcess, glideraService, popupService, gettextCatalog) {
|
||||
function($scope, $log, $timeout, $state, $ionicHistory, ongoingProcess, glideraService, popupService, gettextCatalog) {
|
||||
|
||||
$scope.update = function(opts) {
|
||||
if (!$scope.token || !$scope.permissions) return;
|
||||
|
|
@ -41,8 +41,9 @@ angular.module('copayApp.controllers').controller('preferencesGlideraController'
|
|||
popupService.showConfirm('Glidera', 'Are you sure you would like to log out of your Glidera account?', null, null, function(res) {
|
||||
if (res) {
|
||||
glideraService.removeToken(function() {
|
||||
$ionicHistory.clearHistory();
|
||||
$timeout(function() {
|
||||
$state.go('tabs.buyandsell.glidera');
|
||||
$state.go('tabs.home');
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
|
@ -52,14 +53,6 @@ angular.module('copayApp.controllers').controller('preferencesGlideraController'
|
|||
$scope.$on("$ionicView.enter", function(event, data){
|
||||
$scope.network = glideraService.getEnvironment();
|
||||
|
||||
$scope.token = null;
|
||||
$scope.permissions = null;
|
||||
$scope.email = null;
|
||||
$scope.personalInfo = null;
|
||||
$scope.txs = null;
|
||||
$scope.status = null;
|
||||
$scope.limits = null;
|
||||
|
||||
ongoingProcess.set('connectingGlidera', true);
|
||||
glideraService.init($scope.token, function(err, glidera) {
|
||||
ongoingProcess.set('connectingGlidera');
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('preferencesHistory',
|
||||
function($scope, $log, $stateParams, $timeout, $state, $ionicHistory, gettextCatalog, storageService, platformInfo, profileService, lodash) {
|
||||
function($scope, $log, $stateParams, $timeout, $state, $ionicHistory, storageService, platformInfo, profileService, lodash, $window) {
|
||||
$scope.wallet = profileService.getWallet($stateParams.walletId);
|
||||
$scope.csvReady = false;
|
||||
$scope.isCordova = platformInfo.isCordova;
|
||||
$scope.appName = $window.appConfig.nameCase;
|
||||
|
||||
$scope.csvHistory = function(cb) {
|
||||
var allTxs = [];
|
||||
|
|
@ -31,8 +32,7 @@ angular.module('copayApp.controllers').controller('preferencesHistory',
|
|||
if (err) {
|
||||
$log.warn('Failed to generate CSV:', err);
|
||||
$scope.err = err;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$log.warn('Failed to generate CSV: no transactions');
|
||||
$scope.err = 'no transactions';
|
||||
}
|
||||
|
|
@ -45,7 +45,7 @@ angular.module('copayApp.controllers').controller('preferencesHistory',
|
|||
var data = txs;
|
||||
var satToBtc = 1 / 100000000;
|
||||
$scope.csvContent = [];
|
||||
$scope.csvFilename = 'Copay-' + $scope.wallet.name + '.csv';
|
||||
$scope.csvFilename = $scope.appName + '-' + $scope.wallet.name + '.csv';
|
||||
$scope.csvHeader = ['Date', 'Destination', 'Description', 'Amount', 'Currency', 'Txid', 'Creator', 'Copayers', 'Comment'];
|
||||
|
||||
var _amount, _note, _copayers, _creator, _comment;
|
||||
|
|
|
|||
|
|
@ -1,62 +1,15 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('preferencesInformation',
|
||||
function($scope, $log, $timeout, $ionicHistory, $ionicScrollDelegate, platformInfo, gettextCatalog, lodash, profileService, configService, $stateParams, walletService, $state) {
|
||||
var base = 'xpub';
|
||||
function($scope, $log, $ionicHistory, platformInfo, lodash, profileService, configService, $stateParams, $state) {
|
||||
var wallet = profileService.getWallet($stateParams.walletId);
|
||||
var walletId = wallet.id;
|
||||
|
||||
var config = configService.getSync();
|
||||
var b = 1;
|
||||
var colorCounter = 1;
|
||||
var BLACK_WALLET_COLOR = '#202020';
|
||||
$scope.isCordova = platformInfo.isCordova;
|
||||
config.colorFor = config.colorFor || {};
|
||||
|
||||
$scope.sendAddrs = function() {
|
||||
function formatDate(ts) {
|
||||
var dateObj = new Date(ts * 1000);
|
||||
if (!dateObj) {
|
||||
$log.debug('Error formating a date');
|
||||
return 'DateError';
|
||||
}
|
||||
if (!dateObj.toJSON()) {
|
||||
return '';
|
||||
}
|
||||
return dateObj.toJSON();
|
||||
};
|
||||
|
||||
$timeout(function() {
|
||||
wallet.getMainAddresses({
|
||||
doNotVerify: true
|
||||
}, function(err, addrs) {
|
||||
if (err) {
|
||||
$log.warn(err);
|
||||
return;
|
||||
};
|
||||
|
||||
var body = 'Copay Wallet "' + $scope.walletName + '" Addresses\n Only Main Addresses are shown.\n\n';
|
||||
body += "\n";
|
||||
body += addrs.map(function(v) {
|
||||
return ('* ' + v.address + ' ' + base + v.path.substring(1) + ' ' + formatDate(v.createdOn));
|
||||
}).join("\n");
|
||||
|
||||
window.plugins.socialsharing.shareViaEmail(
|
||||
body,
|
||||
'Copay Addresses',
|
||||
null, // TO: must be null or an array
|
||||
null, // CC: must be null or an array
|
||||
null, // BCC: must be null or an array
|
||||
null, // FILES: can be null, a string, or an array
|
||||
function() {},
|
||||
function() {}
|
||||
);
|
||||
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
}, 1000);
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
||||
$scope.saveBlack = function() {
|
||||
function save(color) {
|
||||
var opts = {
|
||||
|
|
@ -71,14 +24,8 @@ angular.module('copayApp.controllers').controller('preferencesInformation',
|
|||
});
|
||||
};
|
||||
|
||||
if (b != 5) return b++;
|
||||
save('#202020');
|
||||
};
|
||||
|
||||
$scope.scan = function() {
|
||||
walletService.startScan(wallet);
|
||||
$ionicHistory.removeBackView();
|
||||
$state.go('tabs.home');
|
||||
if (colorCounter != 5) return colorCounter++;
|
||||
save(BLACK_WALLET_COLOR);
|
||||
};
|
||||
|
||||
$scope.$on("$ionicView.enter", function(event, data) {
|
||||
|
|
@ -95,29 +42,5 @@ angular.module('copayApp.controllers').controller('preferencesInformation',
|
|||
$scope.M = c.m;
|
||||
$scope.N = c.n;
|
||||
$scope.pubKeys = lodash.pluck(c.publicKeyRing, 'xPubKey');
|
||||
$scope.addrs = null;
|
||||
|
||||
wallet.getMainAddresses({
|
||||
doNotVerify: true
|
||||
}, function(err, addrs) {
|
||||
if (err) {
|
||||
$log.warn(err);
|
||||
return;
|
||||
};
|
||||
var last10 = [],
|
||||
i = 0,
|
||||
e = addrs.pop();
|
||||
while (i++ < 10 && e) {
|
||||
e.path = base + e.path.substring(1);
|
||||
last10.push(e);
|
||||
e = addrs.pop();
|
||||
}
|
||||
$scope.addrs = last10;
|
||||
$timeout(function() {
|
||||
$ionicScrollDelegate.resize();
|
||||
$scope.$apply();
|
||||
}, 10);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,12 +1,18 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('preferencesLanguageController',
|
||||
function($scope, $log, $ionicHistory, gettextCatalog, configService, profileService, uxLanguage, walletService, externalLinkService) {
|
||||
function($scope, $log, $ionicHistory, configService, profileService, uxLanguage, walletService, externalLinkService, gettextCatalog) {
|
||||
|
||||
$scope.availableLanguages = uxLanguage.getLanguages();
|
||||
|
||||
$scope.openExternalLink = function(url, target) {
|
||||
externalLinkService.open(url, target);
|
||||
$scope.openExternalLink = function() {
|
||||
var url = 'https://crowdin.com/project/copay';
|
||||
var optIn = true;
|
||||
var title = gettextCatalog.getString('Open Translation Community');
|
||||
var message = gettextCatalog.getString('You can make contributions by signing up on our Crowdin community translation website. We’re looking forward to hearing from you!');
|
||||
var okText = gettextCatalog.getString('Open Crowdin');
|
||||
var cancelText = gettextCatalog.getString('Go Back');
|
||||
externalLinkService.open(url, optIn, title, message, okText, cancelText);
|
||||
};
|
||||
|
||||
$scope.save = function(newLang) {
|
||||
|
|
@ -18,19 +24,18 @@ angular.module('copayApp.controllers').controller('preferencesLanguageController
|
|||
}
|
||||
};
|
||||
|
||||
uxLanguage._set(newLang);
|
||||
configService.set(opts, function(err) {
|
||||
if (err) $log.warn(err);
|
||||
|
||||
$ionicHistory.goBack();
|
||||
uxLanguage.init(function() {
|
||||
walletService.updateRemotePreferences(profileService.getWallets(), {}, function() {
|
||||
$log.debug('Remote preferences saved');
|
||||
});
|
||||
walletService.updateRemotePreferences(profileService.getWallets(), {}, function() {
|
||||
$log.debug('Remote preferences saved');
|
||||
});
|
||||
});
|
||||
|
||||
$ionicHistory.goBack();
|
||||
};
|
||||
|
||||
$scope.$on("$ionicView.enter", function(event, data){
|
||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||
$scope.currentLanguage = uxLanguage.getCurrentLanguage();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('preferencesLogs',
|
||||
function($scope, historicLog, gettextCatalog) {
|
||||
function($scope, historicLog) {
|
||||
|
||||
$scope.$on("$ionicView.enter", function(event, data) {
|
||||
$scope.logs = historicLog.get();
|
||||
|
|
|
|||
|
|
@ -1,24 +1,34 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('proposalsController',
|
||||
function($timeout, $scope, profileService, $log, txpModalService) {
|
||||
function($timeout, $scope, profileService, $log, txpModalService, addressbookService) {
|
||||
|
||||
$scope.fetchingProposals = true;
|
||||
|
||||
$scope.$on("$ionicView.enter", function(event, data){
|
||||
profileService.getTxps(50, function(err, txps) {
|
||||
$scope.fetchingProposals = false;
|
||||
if (err) {
|
||||
$log.error(err);
|
||||
return;
|
||||
}
|
||||
$scope.txps = txps;
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
}, 1);
|
||||
$scope.$on("$ionicView.enter", function(event, data) {
|
||||
addressbookService.list(function(err, ab) {
|
||||
if (err) $log.error(err);
|
||||
$scope.addressbook = ab || {};
|
||||
|
||||
profileService.getTxps(50, function(err, txps) {
|
||||
$scope.fetchingProposals = false;
|
||||
if (err) {
|
||||
$log.error(err);
|
||||
return;
|
||||
}
|
||||
$scope.txps = txps;
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$scope.openTxpModal = txpModalService.open;
|
||||
|
||||
$scope.createdWithinPastDay = function(time) {
|
||||
var now = new Date();
|
||||
var date = new Date(time * 1000);
|
||||
return (now.getTime() - date.getTime()) < (1000 * 60 * 60 * 24);
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,219 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('sellGlideraController',
|
||||
function($scope, $timeout, $log, profileService, glideraService, bwcError, lodash, walletService, configService, ongoingProcess, popupService, gettextCatalog) {
|
||||
|
||||
var self = this;
|
||||
this.data = {};
|
||||
this.show2faCodeInput = null;
|
||||
this.success = null;
|
||||
var wallet;
|
||||
$scope.network = glideraService.getEnvironment();
|
||||
|
||||
$scope.$on('Wallet/Changed', function(event, w) {
|
||||
if (lodash.isEmpty(w)) {
|
||||
$log.debug('No wallet provided');
|
||||
return;
|
||||
}
|
||||
wallet = w;
|
||||
$log.debug('Wallet changed: ' + w.name);
|
||||
});
|
||||
|
||||
$scope.update = function(opts) {
|
||||
if (!$scope.token || !$scope.permissions) return;
|
||||
$log.debug('Updating Glidera Account...');
|
||||
var accessToken = $scope.token;
|
||||
var permissions = $scope.permissions;
|
||||
|
||||
opts = opts || {};
|
||||
|
||||
glideraService.getStatus(accessToken, function(err, data) {
|
||||
$scope.status = data;
|
||||
});
|
||||
|
||||
glideraService.getLimits(accessToken, function(err, limits) {
|
||||
$scope.limits = limits;
|
||||
});
|
||||
|
||||
if (permissions.transaction_history) {
|
||||
glideraService.getTransactions(accessToken, function(err, data) {
|
||||
$scope.txs = data;
|
||||
});
|
||||
}
|
||||
|
||||
if (permissions.view_email_address && opts.fullUpdate) {
|
||||
glideraService.getEmail(accessToken, function(err, data) {
|
||||
$scope.email = data.email;
|
||||
});
|
||||
}
|
||||
if (permissions.personal_info && opts.fullUpdate) {
|
||||
glideraService.getPersonalInfo(accessToken, function(err, data) {
|
||||
$scope.personalInfo = data;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.getSellPrice = function(token, price) {
|
||||
var self = this;
|
||||
if (!price || (price && !price.qty && !price.fiat)) {
|
||||
self.sellPrice = null;
|
||||
return;
|
||||
}
|
||||
self.gettingSellPrice = true;
|
||||
glideraService.sellPrice(token, price, function(err, sellPrice) {
|
||||
self.gettingSellPrice = false;
|
||||
if (err) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Could not get exchange information. Please, try again'));
|
||||
return;
|
||||
}
|
||||
self.sellPrice = sellPrice;
|
||||
});
|
||||
};
|
||||
|
||||
this.get2faCode = function(token) {
|
||||
var self = this;
|
||||
ongoingProcess.set('Sending 2FA code...', true);
|
||||
$timeout(function() {
|
||||
glideraService.get2faCode(token, function(err, sent) {
|
||||
ongoingProcess.set('Sending 2FA code...', false);
|
||||
if (err) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Could not send confirmation code to your phone'));
|
||||
} else {
|
||||
self.show2faCodeInput = sent;
|
||||
}
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
||||
this.createTx = function(token, permissions, twoFaCode) {
|
||||
var self = this;
|
||||
var outputs = [];
|
||||
var config = configService.getSync();
|
||||
var configWallet = config.wallet;
|
||||
var walletSettings = configWallet.settings;
|
||||
|
||||
if (!wallet) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('No wallet selected'));
|
||||
return;
|
||||
}
|
||||
|
||||
ongoingProcess.set('creatingTx', true);
|
||||
walletService.getAddress(wallet, null, function(err, refundAddress) {
|
||||
if (!refundAddress) {
|
||||
ongoingProcess.clear();
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err, 'Could not create address'));
|
||||
return;
|
||||
}
|
||||
glideraService.getSellAddress(token, function(err, sellAddress) {
|
||||
if (!sellAddress || err) {
|
||||
ongoingProcess.clear();
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Could not get the destination bitcoin address'));
|
||||
return;
|
||||
}
|
||||
var amount = parseInt((self.sellPrice.qty * 100000000).toFixed(0));
|
||||
var comment = 'Glidera transaction';
|
||||
|
||||
outputs.push({
|
||||
'toAddress': sellAddress,
|
||||
'amount': amount,
|
||||
'message': comment
|
||||
});
|
||||
|
||||
var txp = {
|
||||
toAddress: sellAddress,
|
||||
amount: amount,
|
||||
outputs: outputs,
|
||||
message: comment,
|
||||
payProUrl: null,
|
||||
excludeUnconfirmedUtxos: configWallet.spendUnconfirmed ? false : true,
|
||||
feeLevel: walletSettings.feeLevel || 'normal',
|
||||
customData: {
|
||||
'glideraToken': token
|
||||
}
|
||||
};
|
||||
|
||||
walletService.createTx(wallet, txp, function(err, createdTxp) {
|
||||
ongoingProcess.clear();
|
||||
if (err) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), err.message || bwcError.msg(err));
|
||||
return;
|
||||
}
|
||||
walletService.prepare(wallet, function(err, password) {
|
||||
if (err) {
|
||||
ongoingProcess.clear();
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), err.message || bwcError.msg(err));
|
||||
return;
|
||||
}
|
||||
ongoingProcess.set('signingTx', true);
|
||||
walletService.publishTx(wallet, createdTxp, function(err, publishedTxp) {
|
||||
if (err) {
|
||||
ongoingProcess.clear();
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), err.message || bwcError.msg(err));
|
||||
return;
|
||||
}
|
||||
|
||||
walletService.signTx(wallet, publishedTxp, password, function(err, signedTxp) {
|
||||
if (err) {
|
||||
ongoingProcess.clear();
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), err.message || bwcError.msg(err));
|
||||
walletService.removeTx(wallet, signedTxp, function(err) {
|
||||
if (err) $log.debug(err);
|
||||
});
|
||||
return;
|
||||
}
|
||||
var rawTx = signedTxp.raw;
|
||||
var data = {
|
||||
refundAddress: refundAddress,
|
||||
signedTransaction: rawTx,
|
||||
priceUuid: self.sellPrice.priceUuid,
|
||||
useCurrentPrice: self.sellPrice.priceUuid ? false : true,
|
||||
ip: null
|
||||
};
|
||||
ongoingProcess.set('Selling Bitcoin', true);
|
||||
glideraService.sell(token, twoFaCode, data, function(err, data) {
|
||||
ongoingProcess.clear();
|
||||
if (err) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), err.message || bwcError.msg(err));
|
||||
return;
|
||||
}
|
||||
self.success = data;
|
||||
$timeout(function() {
|
||||
$scope.$digest();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$scope.$on("$ionicView.enter", function(event, data){
|
||||
$scope.token = null;
|
||||
$scope.permissions = null;
|
||||
$scope.email = null;
|
||||
$scope.personalInfo = null;
|
||||
$scope.txs = null;
|
||||
$scope.status = null;
|
||||
$scope.limits = null;
|
||||
|
||||
ongoingProcess.set('connectingGlidera', true);
|
||||
glideraService.init($scope.token, function(err, glidera) {
|
||||
ongoingProcess.set('connectingGlidera');
|
||||
if (err || !glidera) {
|
||||
if (err) popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||
return;
|
||||
}
|
||||
$scope.token = glidera.token;
|
||||
$scope.permissions = glidera.permissions;
|
||||
$scope.update({fullUpdate: true});
|
||||
});
|
||||
|
||||
$scope.wallets = profileService.getWallets({
|
||||
network: $scope.network,
|
||||
n: 1,
|
||||
onlyComplete: true
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('tabHomeController',
|
||||
function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, gettextCatalog, lodash, popupService, ongoingProcess, externalLinkService, latestReleaseService, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, $window, bitpayCardService, startupService, addressbookService) {
|
||||
function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, gettextCatalog, lodash, popupService, ongoingProcess, externalLinkService, latestReleaseService, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, $window, bitpayCardService, startupService, addressbookService, feedbackService) {
|
||||
var wallet;
|
||||
var listeners = [];
|
||||
var notifications = [];
|
||||
|
|
@ -13,29 +13,132 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
|||
$scope.isCordova = platformInfo.isCordova;
|
||||
$scope.isAndroid = platformInfo.isAndroid;
|
||||
$scope.isNW = platformInfo.isNW;
|
||||
$scope.showRateCard = {};
|
||||
|
||||
$scope.$on("$ionicView.afterEnter", function() {
|
||||
startupService.ready();
|
||||
});
|
||||
|
||||
if (!$scope.homeTip) {
|
||||
storageService.getHomeTipAccepted(function(error, value) {
|
||||
$scope.homeTip = (value == 'accepted') ? false : true;
|
||||
});
|
||||
}
|
||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||
if (!$scope.homeTip) {
|
||||
storageService.getHomeTipAccepted(function(error, value) {
|
||||
$scope.homeTip = (value == 'accepted') ? false : true;
|
||||
});
|
||||
}
|
||||
|
||||
if ($scope.isNW) {
|
||||
latestReleaseService.checkLatestRelease(function(err, newRelease) {
|
||||
if (err) {
|
||||
$log.warn(err);
|
||||
return;
|
||||
if ($scope.isNW) {
|
||||
latestReleaseService.checkLatestRelease(function(err, newRelease) {
|
||||
if (err) {
|
||||
$log.warn(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (newRelease) $scope.newRelease = true;
|
||||
});
|
||||
}
|
||||
|
||||
storageService.getFeedbackInfo(function(error, info) {
|
||||
if (!info) {
|
||||
initFeedBackInfo();
|
||||
} else {
|
||||
var feedbackInfo = JSON.parse(info);
|
||||
//Check if current version is greater than saved version
|
||||
var currentVersion = window.version;
|
||||
var savedVersion = feedbackInfo.version;
|
||||
var isVersionUpdated = feedbackService.isVersionUpdated(currentVersion, savedVersion);
|
||||
if (!isVersionUpdated) {
|
||||
initFeedBackInfo();
|
||||
return;
|
||||
}
|
||||
var now = moment().unix();
|
||||
var timeExceeded = (now - feedbackInfo.time) >= 24 * 7 * 60 * 60;
|
||||
$scope.showRateCard.value = timeExceeded && !feedbackInfo.sent;
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
});
|
||||
}
|
||||
|
||||
if (newRelease) $scope.newRelease = true;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.openExternalLink = function(url, optIn, title, message, okText, cancelText) {
|
||||
function initFeedBackInfo() {
|
||||
var feedbackInfo = {};
|
||||
feedbackInfo.time = moment().unix();
|
||||
feedbackInfo.version = window.version;
|
||||
feedbackInfo.sent = false;
|
||||
storageService.setFeedbackInfo(JSON.stringify(feedbackInfo), function() {
|
||||
$scope.showRateCard.value = false;
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
$scope.$on("$ionicView.enter", function(event, data) {
|
||||
updateAllWallets();
|
||||
|
||||
addressbookService.list(function(err, ab) {
|
||||
if (err) $log.error(err);
|
||||
$scope.addressbook = ab || {};
|
||||
});
|
||||
|
||||
listeners = [
|
||||
$rootScope.$on('bwsEvent', function(e, walletId, type, n) {
|
||||
var wallet = profileService.getWallet(walletId);
|
||||
updateWallet(wallet);
|
||||
if ($scope.recentTransactionsEnabled) getNotifications();
|
||||
}),
|
||||
$rootScope.$on('Local/TxAction', function(e, walletId) {
|
||||
$log.debug('Got action for wallet ' + walletId);
|
||||
var wallet = profileService.getWallet(walletId);
|
||||
updateWallet(wallet);
|
||||
if ($scope.recentTransactionsEnabled) getNotifications();
|
||||
})
|
||||
];
|
||||
|
||||
configService.whenAvailable(function() {
|
||||
nextStep(function() {
|
||||
var config = configService.getSync();
|
||||
var isWindowsPhoneApp = platformInfo.isWP && platformInfo.isCordova;
|
||||
|
||||
$scope.glideraEnabled = config.glidera.enabled && !isWindowsPhoneApp;
|
||||
$scope.coinbaseEnabled = config.coinbase.enabled && !isWindowsPhoneApp;
|
||||
$scope.amazonEnabled = config.amazon.enabled;
|
||||
$scope.bitpayCardEnabled = config.bitpayCard.enabled;
|
||||
|
||||
var buyAndSellEnabled = !$scope.externalServices.BuyAndSell && ($scope.glideraEnabled || $scope.coinbaseEnabled);
|
||||
var amazonEnabled = !$scope.externalServices.AmazonGiftCards && $scope.amazonEnabled;
|
||||
var bitpayCardEnabled = !$scope.externalServices.BitpayCard && $scope.bitpayCardEnabled;
|
||||
|
||||
$scope.nextStepEnabled = buyAndSellEnabled || amazonEnabled || bitpayCardEnabled;
|
||||
$scope.recentTransactionsEnabled = config.recentTransactions.enabled;
|
||||
|
||||
if ($scope.recentTransactionsEnabled) getNotifications();
|
||||
|
||||
if ($scope.bitpayCardEnabled) bitpayCardCache();
|
||||
$timeout(function() {
|
||||
$ionicScrollDelegate.resize();
|
||||
$scope.$apply();
|
||||
}, 10);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$scope.$on("$ionicView.leave", function(event, data) {
|
||||
lodash.each(listeners, function(x) {
|
||||
x();
|
||||
});
|
||||
});
|
||||
|
||||
$scope.createdWithinPastDay = function(time) {
|
||||
var now = new Date();
|
||||
var date = new Date(time * 1000);
|
||||
return (now.getTime() - date.getTime()) < (1000 * 60 * 60 * 24);
|
||||
};
|
||||
|
||||
$scope.openExternalLink = function() {
|
||||
var url = 'https://github.com/bitpay/copay/releases/latest';
|
||||
var optIn = true;
|
||||
var title = gettextCatalog.getString('Update Available');
|
||||
var message = gettextCatalog.getString('An update to this app is available. For your security, please update to the latest version.');
|
||||
var okText = gettextCatalog.getString('View Update');
|
||||
var cancelText = gettextCatalog.getString('Go Back');
|
||||
externalLinkService.open(url, optIn, title, message, okText, cancelText);
|
||||
};
|
||||
|
||||
|
|
@ -43,7 +146,10 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
|||
wallet = profileService.getWallet(n.walletId);
|
||||
|
||||
if (n.txid) {
|
||||
openTxModal(n);
|
||||
$state.transitionTo('tabs.wallet.tx-details', {
|
||||
txid: n.txid,
|
||||
walletId: n.walletId
|
||||
});
|
||||
} else {
|
||||
var txp = lodash.find($scope.txps, {
|
||||
id: n.txpId
|
||||
|
|
@ -65,37 +171,6 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
|||
}
|
||||
};
|
||||
|
||||
var openTxModal = function(n) {
|
||||
wallet = profileService.getWallet(n.walletId);
|
||||
|
||||
ongoingProcess.set('loadingTxInfo', true);
|
||||
walletService.getTx(wallet, n.txid, function(err, tx) {
|
||||
ongoingProcess.set('loadingTxInfo', false);
|
||||
|
||||
if (err) {
|
||||
$log.error(err);
|
||||
return popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||
}
|
||||
|
||||
if (!tx) {
|
||||
$log.warn('No tx found');
|
||||
return popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Transaction not found'));
|
||||
}
|
||||
|
||||
$scope.wallet = wallet;
|
||||
$scope.btx = lodash.cloneDeep(tx);
|
||||
$state.transitionTo('tabs.wallet.tx-details', {
|
||||
txid: $scope.btx.txid,
|
||||
walletId: $scope.walletId
|
||||
});
|
||||
|
||||
walletService.getTxNote(wallet, n.txid, function(err, note) {
|
||||
if (err) $log.warn('Could not fetch transaction note: ' + err);
|
||||
$scope.btx.note = note;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$scope.openWallet = function(wallet) {
|
||||
if (!wallet.isComplete()) {
|
||||
return $state.go('tabs.copayers', {
|
||||
|
|
@ -117,7 +192,8 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
|||
$scope.txpsN = n;
|
||||
$timeout(function() {
|
||||
$ionicScrollDelegate.resize();
|
||||
}, 100);
|
||||
$scope.$apply();
|
||||
}, 10);
|
||||
})
|
||||
};
|
||||
|
||||
|
|
@ -132,8 +208,11 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
|||
lodash.each($scope.wallets, function(wallet) {
|
||||
walletService.getStatus(wallet, {}, function(err, status) {
|
||||
if (err) {
|
||||
if (err === 'WALLET_NOT_REGISTERED') wallet.error = gettextCatalog.getString('Wallet not registered');
|
||||
else wallet.error = gettextCatalog.getString('Could not update');;
|
||||
$log.error(err);
|
||||
} else {
|
||||
wallet.error = null;
|
||||
wallet.status = status;
|
||||
}
|
||||
if (++j == i) {
|
||||
|
|
@ -141,25 +220,6 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (!$scope.recentTransactionsEnabled) return;
|
||||
$scope.fetchingNotifications = true;
|
||||
profileService.getNotifications({
|
||||
limit: 3
|
||||
}, function(err, n) {
|
||||
if (err) {
|
||||
$log.error(err);
|
||||
return;
|
||||
}
|
||||
$scope.fetchingNotifications = false;
|
||||
$scope.notifications = n;
|
||||
|
||||
$timeout(function() {
|
||||
$ionicScrollDelegate.resize();
|
||||
$scope.$apply();
|
||||
}, 100);
|
||||
|
||||
})
|
||||
};
|
||||
|
||||
var updateWallet = function(wallet) {
|
||||
|
|
@ -171,20 +231,22 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
|||
}
|
||||
wallet.status = status;
|
||||
updateTxps();
|
||||
});
|
||||
};
|
||||
|
||||
if (!$scope.recentTransactionsEnabled) return;
|
||||
|
||||
$scope.fetchingNotifications = true;
|
||||
profileService.getNotifications({
|
||||
limit: 3
|
||||
}, function(err, notifications) {
|
||||
$scope.fetchingNotifications = false;
|
||||
if (err) {
|
||||
$log.error(err);
|
||||
return;
|
||||
}
|
||||
$scope.notifications = notifications;
|
||||
});
|
||||
var getNotifications = function() {
|
||||
profileService.getNotifications({
|
||||
limit: 3
|
||||
}, function(err, n) {
|
||||
if (err) {
|
||||
$log.error(err);
|
||||
return;
|
||||
}
|
||||
$scope.notifications = n;
|
||||
$timeout(function() {
|
||||
$ionicScrollDelegate.resize();
|
||||
$scope.$apply();
|
||||
}, 10);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -202,7 +264,7 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
|||
var services = ['AmazonGiftCards', 'BitpayCard', 'BuyAndSell'];
|
||||
lodash.each(services, function(service) {
|
||||
storageService.getNextStep(service, function(err, value) {
|
||||
$scope.externalServices[service] = value ? true : false;
|
||||
$scope.externalServices[service] = value == 'true' ? true : false;
|
||||
if (++i == services.length) return cb();
|
||||
});
|
||||
});
|
||||
|
|
@ -213,7 +275,7 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
|||
$timeout(function() {
|
||||
$ionicScrollDelegate.resize();
|
||||
$scope.$apply();
|
||||
}, 100);
|
||||
}, 10);
|
||||
};
|
||||
|
||||
var bitpayCardCache = function() {
|
||||
|
|
@ -241,57 +303,4 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
|||
}, 300);
|
||||
updateAllWallets();
|
||||
};
|
||||
|
||||
$scope.$on("$ionicView.enter", function(event, data) {
|
||||
updateAllWallets();
|
||||
|
||||
addressbookService.list(function(err, ab) {
|
||||
if (err) $log.error(err);
|
||||
$scope.addressbook = ab || {};
|
||||
});
|
||||
|
||||
listeners = [
|
||||
$rootScope.$on('bwsEvent', function(e, walletId, type, n) {
|
||||
var wallet = profileService.getWallet(walletId);
|
||||
updateWallet(wallet);
|
||||
}),
|
||||
$rootScope.$on('Local/TxAction', function(e, walletId) {
|
||||
$log.debug('Got action for wallet ' + walletId);
|
||||
var wallet = profileService.getWallet(walletId);
|
||||
updateWallet(wallet);
|
||||
})
|
||||
];
|
||||
|
||||
configService.whenAvailable(function() {
|
||||
nextStep(function() {
|
||||
var config = configService.getSync();
|
||||
var isWindowsPhoneApp = platformInfo.isWP && platformInfo.isCordova;
|
||||
|
||||
$scope.glideraEnabled = config.glidera.enabled && !isWindowsPhoneApp;
|
||||
$scope.coinbaseEnabled = config.coinbase.enabled && !isWindowsPhoneApp;
|
||||
$scope.amazonEnabled = config.amazon.enabled;
|
||||
$scope.bitpayCardEnabled = config.bitpayCard.enabled;
|
||||
|
||||
var buyAndSellEnabled = !$scope.externalServices.BuyAndSell && ($scope.glideraEnabled || $scope.coinbaseEnabled);
|
||||
var amazonEnabled = !$scope.externalServices.AmazonGiftCards && $scope.amazonEnabled;
|
||||
var bitpayCardEnabled = !$scope.externalServices.BitpayCard && $scope.bitpayCardEnabled;
|
||||
|
||||
$scope.nextStepEnabled = buyAndSellEnabled || amazonEnabled || bitpayCardEnabled;
|
||||
$scope.recentTransactionsEnabled = config.recentTransactions.enabled;
|
||||
|
||||
if ($scope.bitpayCardEnabled) bitpayCardCache();
|
||||
$timeout(function() {
|
||||
$ionicScrollDelegate.resize();
|
||||
$scope.$apply();
|
||||
}, 10);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$scope.$on("$ionicView.leave", function(event, data) {
|
||||
lodash.each(listeners, function(x) {
|
||||
x();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('tabReceiveController', function($scope, $timeout, $log, $ionicModal, $state, $ionicHistory, storageService, platformInfo, walletService, profileService, configService, lodash, gettextCatalog, popupService) {
|
||||
angular.module('copayApp.controllers').controller('tabReceiveController', function($rootScope, $scope, $timeout, $log, $ionicModal, $state, $ionicHistory, $ionicPopover, storageService, platformInfo, walletService, profileService, configService, lodash, gettextCatalog, popupService, bwcError) {
|
||||
|
||||
var listeners = [];
|
||||
var MENU_ITEM_HEIGHT = 55;
|
||||
$scope.isCordova = platformInfo.isCordova;
|
||||
$scope.isNW = platformInfo.isNW;
|
||||
$scope.walletAddrs = {};
|
||||
|
||||
$scope.shareAddress = function(addr) {
|
||||
if ($scope.generatingAddress) return;
|
||||
|
|
@ -18,14 +21,21 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
|
|||
$scope.generatingAddress = true;
|
||||
walletService.getAddress($scope.wallet, forceNew, function(err, addr) {
|
||||
$scope.generatingAddress = false;
|
||||
if (err) popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||
if (err) popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err));
|
||||
$scope.addr = addr;
|
||||
if ($scope.walletAddrs[$scope.wallet.id]) $scope.walletAddrs[$scope.wallet.id] = addr;
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
}, 10);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.loadAddresses = function(wallet, index) {
|
||||
walletService.getAddress(wallet, false, function(err, addr) {
|
||||
$scope.walletAddrs[wallet.id] = addr;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.goCopayers = function() {
|
||||
$ionicHistory.removeBackView();
|
||||
$ionicHistory.nextViewOptions({
|
||||
|
|
@ -39,6 +49,12 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
|
|||
}, 100);
|
||||
};
|
||||
|
||||
$scope.showAddresses = function() {
|
||||
$state.transitionTo('tabs.receive.addresses', {
|
||||
walletId: $scope.wallet.credentials.walletId
|
||||
});
|
||||
};
|
||||
|
||||
$scope.openBackupNeededModal = function() {
|
||||
$ionicModal.fromTemplateUrl('views/includes/backupNeededPopup.html', {
|
||||
scope: $scope,
|
||||
|
|
@ -67,6 +83,24 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
|
|||
});
|
||||
};
|
||||
|
||||
$scope.setWallet = function(index) {
|
||||
$scope.wallet = $scope.wallets[index];
|
||||
$scope.walletIndex = index;
|
||||
if ($scope.walletAddrs[$scope.wallet.id].addr) $scope.addr = $scope.walletAddrs[$scope.walletIndex].addr;
|
||||
else $scope.setAddress(false);
|
||||
}
|
||||
|
||||
$scope.isActive = function(index) {
|
||||
return $scope.wallets[index] == $scope.wallet;
|
||||
}
|
||||
|
||||
$scope.walletPosition = function(index) {
|
||||
if (index == $scope.walletIndex) return 'current';
|
||||
if (index < $scope.walletIndex) return 'prev';
|
||||
if (index > $scope.walletIndex) return 'next';
|
||||
}
|
||||
|
||||
|
||||
$scope.$on('Wallet/Changed', function(event, wallet) {
|
||||
if (!wallet) {
|
||||
$log.debug('No wallet provided');
|
||||
|
|
@ -77,14 +111,82 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
|
|||
return;
|
||||
}
|
||||
$scope.wallet = wallet;
|
||||
$scope.generatingAddress = false;
|
||||
$log.debug('Wallet changed: ' + wallet.name);
|
||||
|
||||
$scope.walletIndex = lodash.findIndex($scope.wallets, function(wallet) {
|
||||
return wallet.id == $scope.wallet.id;
|
||||
});
|
||||
|
||||
if (!$scope.walletAddrs[wallet.id]) $scope.setAddress(false);
|
||||
else $scope.addr = $scope.walletAddrs[wallet.id];
|
||||
|
||||
$timeout(function() {
|
||||
$scope.setAddress(false);
|
||||
$scope.$apply();
|
||||
}, 100);
|
||||
|
||||
});
|
||||
|
||||
$scope.updateCurrentWallet = function() {
|
||||
walletService.getStatus($scope.wallet, {}, function(err, status) {
|
||||
if (err) {
|
||||
$log.error(err);
|
||||
}
|
||||
$timeout(function() {
|
||||
$scope.wallet = profileService.getWallet($scope.wallet.id);
|
||||
$scope.wallet.status = status;
|
||||
$scope.setAddress();
|
||||
$scope.$apply();
|
||||
}, 200);
|
||||
});
|
||||
};
|
||||
|
||||
var goRequestAmount = function() {
|
||||
$scope.menu.hide();
|
||||
$state.go('tabs.receive.amount', {
|
||||
customAmount: true,
|
||||
toAddress: $scope.addr
|
||||
});
|
||||
}
|
||||
|
||||
$scope.showMenu = function(allAddresses, $event) {
|
||||
var requestAmountObj = {
|
||||
text: gettextCatalog.getString('Request Specific amount'),
|
||||
action: goRequestAmount,
|
||||
};
|
||||
|
||||
$scope.items = [requestAmountObj];
|
||||
$scope.height = $scope.items.length * MENU_ITEM_HEIGHT;
|
||||
|
||||
$ionicPopover.fromTemplateUrl('views/includes/menu-popover.html', {
|
||||
scope: $scope
|
||||
}).then(function(popover) {
|
||||
$scope.menu = popover;
|
||||
$scope.menu.show($event);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||
$scope.wallets = profileService.getWallets();
|
||||
|
||||
lodash.each($scope.wallets, function(wallet, index) {
|
||||
$scope.loadAddresses(wallet);
|
||||
});
|
||||
|
||||
|
||||
listeners = [
|
||||
$rootScope.$on('bwsEvent', function(e, walletId, type, n) {
|
||||
// Update current address
|
||||
if ($scope.wallet && walletId == $scope.wallet.id) $scope.updateCurrentWallet();
|
||||
})
|
||||
];
|
||||
|
||||
// Update current wallet
|
||||
if ($scope.wallet) $scope.updateCurrentWallet();
|
||||
});
|
||||
|
||||
$scope.$on("$ionicView.leave", function(event, data) {
|
||||
lodash.each(listeners, function(x) {
|
||||
x();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('tabSendController', function($scope, $log, $timeout, $ionicScrollDelegate, addressbookService, profileService, lodash, $state, walletService, incomingData, popupService, $rootScope) {
|
||||
angular.module('copayApp.controllers').controller('tabSendController', function($scope, $rootScope, $log, $timeout, $ionicScrollDelegate, addressbookService, profileService, lodash, $state, walletService, incomingData, popupService) {
|
||||
|
||||
var originalList;
|
||||
var CONTACTS_SHOW_LIMIT;
|
||||
|
|
@ -55,7 +55,7 @@ angular.module('copayApp.controllers').controller('tabSendController', function(
|
|||
$timeout(function() {
|
||||
$ionicScrollDelegate.resize();
|
||||
$scope.$apply();
|
||||
});
|
||||
}, 10);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -128,10 +128,12 @@ angular.module('copayApp.controllers').controller('tabSendController', function(
|
|||
});
|
||||
}
|
||||
|
||||
$scope.checkingBalance = true;
|
||||
var index = 0;
|
||||
lodash.each(wallets, function(w) {
|
||||
walletService.getStatus(w, {}, function(err, status) {
|
||||
++index;
|
||||
if (index == wallets.length) $scope.checkingBalance = false;
|
||||
if (err || !status) {
|
||||
$log.error(err);
|
||||
return;
|
||||
|
|
@ -143,15 +145,15 @@ angular.module('copayApp.controllers').controller('tabSendController', function(
|
|||
}
|
||||
|
||||
if (index == wallets.length) {
|
||||
if ($scope.hasFunds != true) {
|
||||
$ionicScrollDelegate.freezeScroll(true);
|
||||
}
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
if ($scope.hasFunds != true) {
|
||||
$ionicScrollDelegate.freezeScroll(true);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||
|
|
|
|||
|
|
@ -1,30 +1,58 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('tabSettingsController', function($scope, $window, uxLanguage, platformInfo, profileService, feeService, configService, externalLinkService) {
|
||||
angular.module('copayApp.controllers').controller('tabSettingsController', function($scope, $window, $ionicModal, $log, lodash, uxLanguage, platformInfo, profileService, feeService, configService, externalLinkService, bitpayCardService, storageService, glideraService, gettextCatalog) {
|
||||
|
||||
var updateConfig = function() {
|
||||
|
||||
var config = configService.getSync();
|
||||
var isCordova = platformInfo.isCordova;
|
||||
var isWP = platformInfo.isWP;
|
||||
var isWindowsPhoneApp = platformInfo.isWP && isCordova;
|
||||
|
||||
$scope.usePushNotifications = isCordova && !isWP;
|
||||
$scope.isCordova = isCordova;
|
||||
|
||||
$scope.appName = $window.appConfig.nameCase;
|
||||
|
||||
$scope.unitName = config.wallet.settings.unitName;
|
||||
$scope.currentLanguageName = uxLanguage.getCurrentLanguageName();
|
||||
$scope.selectedAlternative = {
|
||||
name: config.wallet.settings.alternativeName,
|
||||
isoCode: config.wallet.settings.alternativeIsoCode
|
||||
};
|
||||
$scope.feeOpts = feeService.feeOpts;
|
||||
$scope.currentFeeLevel = feeService.getCurrentFeeLevel();
|
||||
|
||||
|
||||
$scope.wallets = profileService.getWallets();
|
||||
|
||||
configService.whenAvailable(function(config) {
|
||||
$scope.unitName = config.wallet.settings.unitName;
|
||||
$scope.selectedAlternative = {
|
||||
name: config.wallet.settings.alternativeName,
|
||||
isoCode: config.wallet.settings.alternativeIsoCode
|
||||
};
|
||||
|
||||
$scope.bitpayCardEnabled = config.bitpayCard.enabled;
|
||||
$scope.glideraEnabled = config.glidera.enabled && !isWindowsPhoneApp;
|
||||
|
||||
if ($scope.bitpayCardEnabled) {
|
||||
bitpayCardService.getBitpayDebitCards(function(err, data) {
|
||||
if (err) $log.error(err);
|
||||
if (!lodash.isEmpty(data)) {
|
||||
$scope.bitpayCards = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if ($scope.glideraEnabled) {
|
||||
storageService.getGlideraToken(glideraService.getEnvironment(), function(err, token) {
|
||||
if (err) $log.error(err);
|
||||
$scope.glideraToken = token;
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
$scope.openExternalLink = function(url, optIn, title, message, okText, cancelText) {
|
||||
$scope.openExternalLink = function() {
|
||||
var url = 'https://help.bitpay.com/bitpay-app';
|
||||
var optIn = true;
|
||||
var title = gettextCatalog.getString('BitPay Help Center');
|
||||
var message = gettextCatalog.getString('Help and support information is available at the BitPay Help Center website. Would you like to go there now?');
|
||||
var okText = gettextCatalog.getString('Open Help Center');
|
||||
var cancelText = gettextCatalog.getString('Go Back');
|
||||
externalLinkService.open(url, optIn, title, message, okText, cancelText);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('tabsController', function($rootScope, $log, $scope, $state, $stateParams, $timeout, incomingData, lodash, popupService) {
|
||||
angular.module('copayApp.controllers').controller('tabsController', function($rootScope, $log, $scope, $state, $stateParams, $timeout, incomingData, lodash, popupService, gettextCatalog) {
|
||||
|
||||
$scope.onScan = function(data) {
|
||||
if (!incomingData.redir(data)) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('termOfUseController',
|
||||
function($scope, $window, uxLanguage, gettextCatalog, externalLinkService) {
|
||||
function($scope, $window, uxLanguage, externalLinkService) {
|
||||
$scope.lang = uxLanguage.currentLanguage;
|
||||
$scope.disclaimerUrl = $window.appConfig.disclaimerUrl;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,14 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('translatorsController',
|
||||
function($scope, externalLinkService) {
|
||||
$scope.openExternalLink = function(url, target) {
|
||||
externalLinkService.open(url, target);
|
||||
function($scope, externalLinkService, gettextCatalog) {
|
||||
$scope.openExternalLink = function() {
|
||||
var url = 'https://crowdin.com/project/copay';
|
||||
var optIn = true;
|
||||
var title = gettextCatalog.getString('Open Translation Community');
|
||||
var message = gettextCatalog.getString('You can make contributions by signing up on our Crowdin community translation website. We’re looking forward to hearing from you!');
|
||||
var okText = gettextCatalog.getString('Open Crowdin');
|
||||
var cancelText = gettextCatalog.getString('Go Back');
|
||||
externalLinkService.open(url, optIn, title, message, okText, cancelText);
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,27 +1,23 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('txDetailsController', function($log, $timeout, $ionicHistory, $scope, $filter, $stateParams, ongoingProcess, walletService, lodash, gettextCatalog, profileService, configService, txFormatService, externalLinkService, popupService) {
|
||||
var config = configService.getSync();
|
||||
var configWallet = config.wallet;
|
||||
var walletSettings = configWallet.settings;
|
||||
var wallet = profileService.getWallet($stateParams.walletId);
|
||||
angular.module('copayApp.controllers').controller('txDetailsController', function($log, $ionicHistory, $scope, $timeout, walletService, lodash, gettextCatalog, profileService, configService, externalLinkService, popupService, ongoingProcess) {
|
||||
|
||||
$scope.wallet = wallet;
|
||||
$scope.title = gettextCatalog.getString('Transaction');
|
||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||
$scope.title = gettextCatalog.getString('Transaction');
|
||||
$scope.wallet = profileService.getWallet(data.stateParams.walletId);
|
||||
$scope.color = $scope.wallet.color;
|
||||
$scope.copayerId = $scope.wallet.credentials.copayerId;
|
||||
$scope.isShared = $scope.wallet.credentials.n > 1;
|
||||
|
||||
$scope.init = function() {
|
||||
$scope.alternativeIsoCode = walletSettings.alternativeIsoCode;
|
||||
$scope.color = wallet.color;
|
||||
$scope.copayerId = wallet.credentials.copayerId;
|
||||
$scope.isShared = wallet.credentials.n > 1;
|
||||
walletService.getTx(wallet, $stateParams.txid, function(err, tx) {
|
||||
ongoingProcess.set('loadingTxInfo', true);
|
||||
walletService.getTx($scope.wallet, data.stateParams.txid, function(err, tx) {
|
||||
ongoingProcess.set('loadingTxInfo', false);
|
||||
if (err) {
|
||||
$log.warn('Could not get tx');
|
||||
$ionicHistory.goBack();
|
||||
return;
|
||||
return popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Transaction not found'));
|
||||
}
|
||||
$scope.btx = tx;
|
||||
$scope.btx.feeLevel = walletSettings.feeLevel;
|
||||
if ($scope.btx.action != 'invalid') {
|
||||
if ($scope.btx.action == 'sent') $scope.title = gettextCatalog.getString('Sent Funds');
|
||||
if ($scope.btx.action == 'received') $scope.title = gettextCatalog.getString('Received Funds');
|
||||
|
|
@ -33,8 +29,11 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
|
|||
|
||||
updateMemo();
|
||||
initActionList();
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
function getDisplayAmount(amountStr) {
|
||||
return amountStr.split(' ')[0];
|
||||
|
|
@ -45,7 +44,7 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
|
|||
}
|
||||
|
||||
function updateMemo() {
|
||||
walletService.getTxNote(wallet, $scope.btx.txid, function(err, note) {
|
||||
walletService.getTxNote($scope.wallet, $scope.btx.txid, function(err, note) {
|
||||
if (err) {
|
||||
$log.warn('Could not fetch transaction note: ' + err);
|
||||
return;
|
||||
|
|
@ -53,18 +52,7 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
|
|||
if (!note) return;
|
||||
|
||||
$scope.btx.note = note;
|
||||
|
||||
walletService.getTx(wallet, $scope.btx.txid, function(err, tx) {
|
||||
if (err) {
|
||||
$log.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
tx.note = note;
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
});
|
||||
});
|
||||
$scope.$apply();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -109,9 +97,12 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
|
|||
}
|
||||
if ($scope.btx.note && $scope.btx.note.body) opts.defaultText = $scope.btx.note.body;
|
||||
|
||||
popupService.showPrompt(wallet.name, gettextCatalog.getString('Memo'), opts, function(text) {
|
||||
popupService.showPrompt($scope.wallet.name, gettextCatalog.getString('Memo'), opts, function(text) {
|
||||
if (typeof text == "undefined") return;
|
||||
|
||||
$scope.btx.note = {
|
||||
body: text
|
||||
};
|
||||
$log.debug('Saving memo');
|
||||
|
||||
var args = {
|
||||
|
|
@ -119,17 +110,10 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
|
|||
body: text
|
||||
};
|
||||
|
||||
walletService.editTxNote(wallet, args, function(err, res) {
|
||||
walletService.editTxNote($scope.wallet, args, function(err, res) {
|
||||
if (err) {
|
||||
$log.debug('Could not save tx comment ' + err);
|
||||
return;
|
||||
}
|
||||
// This is only to refresh the current screen data
|
||||
updateMemo();
|
||||
$scope.btx.searcheableString = null;
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
@ -137,23 +121,42 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
|
|||
$scope.viewOnBlockchain = function() {
|
||||
var btx = $scope.btx;
|
||||
var url = 'https://' + ($scope.getShortNetworkName() == 'test' ? 'test-' : '') + 'insight.bitpay.com/tx/' + btx.txid;
|
||||
var title = 'View Transaction on Insight';
|
||||
var message = 'Would you like to view this transaction on the Insight blockchain explorer?';
|
||||
$scope.openExternalLink(url, true, title, message, 'Open Insight', 'Go back');
|
||||
};
|
||||
|
||||
$scope.openExternalLink = function(url, optIn, title, message, okText, cancelText) {
|
||||
var optIn = true;
|
||||
var title = gettextCatalog.getString('View Transaction on Insight');
|
||||
var message = gettextCatalog.getString('Would you like to view this transaction on the Insight blockchain explorer?');
|
||||
var okText = gettextCatalog.getString('Open Insight');
|
||||
var cancelText = gettextCatalog.getString('Go Back');
|
||||
externalLinkService.open(url, optIn, title, message, okText, cancelText);
|
||||
};
|
||||
|
||||
$scope.getShortNetworkName = function() {
|
||||
var n = wallet.credentials.network;
|
||||
var n = $scope.wallet.credentials.network;
|
||||
return n.substring(0, 4);
|
||||
};
|
||||
|
||||
$scope.getFiatRate = function() {
|
||||
if ($scope.rateDate) return;
|
||||
var alternativeIsoCode = $scope.wallet.status.alternativeIsoCode;
|
||||
$scope.loadingRate = true;
|
||||
$scope.wallet.getFiatRate({
|
||||
code: alternativeIsoCode,
|
||||
ts: $scope.btx.time * 1000
|
||||
}, function(err, res) {
|
||||
$scope.loadingRate = false;
|
||||
if (err) {
|
||||
$log.debug('Could not get historic rate');
|
||||
return;
|
||||
}
|
||||
if (res && res.rate) {
|
||||
$scope.rateDate = res.fetchedOn;
|
||||
$scope.rateStr = res.rate + ' ' + alternativeIsoCode;
|
||||
$scope.$apply();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.cancel = function() {
|
||||
$scope.txDetailsModal.hide();
|
||||
};
|
||||
|
||||
$scope.init();
|
||||
});
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('walletDetailsController', function($scope, $rootScope, $interval, $timeout, $filter, $log, $ionicModal, $ionicPopover, $state, $stateParams, profileService, lodash, configService, gettextCatalog, platformInfo, walletService, txpModalService, externalLinkService, popupService, addressbookService) {
|
||||
angular.module('copayApp.controllers').controller('walletDetailsController', function($scope, $rootScope, $interval, $timeout, $filter, $log, $ionicModal, $ionicPopover, $state, $stateParams, $ionicHistory, profileService, lodash, configService, platformInfo, walletService, txpModalService, externalLinkService, popupService, addressbookService, storageService, $ionicScrollDelegate, $window, bwcError, gettextCatalog) {
|
||||
|
||||
var HISTORY_SHOW_LIMIT = 10;
|
||||
var currentTxHistoryPage = 0;
|
||||
|
|
@ -10,6 +10,9 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
|||
$scope.openTxpModal = txpModalService.open;
|
||||
$scope.isCordova = platformInfo.isCordova;
|
||||
$scope.isAndroid = platformInfo.isAndroid;
|
||||
$scope.isIOS = platformInfo.isIOS;
|
||||
|
||||
$scope.amountIsCollapsible = !$scope.isAndroid;
|
||||
|
||||
$scope.openExternalLink = function(url, target) {
|
||||
externalLinkService.open(url, target);
|
||||
|
|
@ -46,7 +49,7 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
|||
|
||||
var updateStatus = function(force) {
|
||||
$scope.updatingStatus = true;
|
||||
$scope.updateStatusError = false;
|
||||
$scope.updateStatusError = null;
|
||||
$scope.walletNotRegistered = false;
|
||||
|
||||
walletService.getStatus($scope.wallet, {
|
||||
|
|
@ -57,18 +60,17 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
|||
if (err === 'WALLET_NOT_REGISTERED') {
|
||||
$scope.walletNotRegistered = true;
|
||||
} else {
|
||||
$scope.updateStatusError = true;
|
||||
$scope.updateStatusError = bwcError.msg(err, gettextCatalog.getString('BWS Error'));
|
||||
}
|
||||
$scope.status = null;
|
||||
return;
|
||||
} else {
|
||||
setPendingTxps(status.pendingTxps);
|
||||
$scope.status = status;
|
||||
}
|
||||
|
||||
setPendingTxps(status.pendingTxps);
|
||||
|
||||
$scope.status = status;
|
||||
refreshAmountSection();
|
||||
$timeout(function() {
|
||||
$scope.$apply();
|
||||
}, 1);
|
||||
});
|
||||
|
||||
});
|
||||
};
|
||||
|
|
@ -87,6 +89,14 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
|||
$scope.close = function() {
|
||||
$scope.searchModal.hide();
|
||||
};
|
||||
|
||||
$scope.openTx = function(tx) {
|
||||
$ionicHistory.nextViewOptions({
|
||||
disableAnimate: true
|
||||
});
|
||||
$scope.searchModal.hide();
|
||||
$scope.openTxModal(tx);
|
||||
};
|
||||
};
|
||||
|
||||
$scope.openTxModal = function(btx) {
|
||||
|
|
@ -98,11 +108,25 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
|||
});
|
||||
};
|
||||
|
||||
$scope.openBalanceModal = function() {
|
||||
$ionicModal.fromTemplateUrl('views/modals/wallet-balance.html', {
|
||||
scope: $scope
|
||||
}).then(function(modal) {
|
||||
$scope.walletBalanceModal = modal;
|
||||
$scope.walletBalanceModal.show();
|
||||
});
|
||||
|
||||
$scope.close = function() {
|
||||
$scope.walletBalanceModal.hide();
|
||||
};
|
||||
};
|
||||
|
||||
$scope.recreate = function() {
|
||||
walletService.recreate($scope.wallet, function(err) {
|
||||
if (err) return;
|
||||
$timeout(function() {
|
||||
walletService.startScan($scope.wallet, function() {
|
||||
$scope.updateAll();
|
||||
$scope.$apply();
|
||||
});
|
||||
});
|
||||
|
|
@ -151,6 +175,52 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
|||
}
|
||||
};
|
||||
|
||||
$scope.getDate = function(txCreated) {
|
||||
var date = new Date(txCreated * 1000);
|
||||
return date;
|
||||
};
|
||||
|
||||
$scope.isFirstInGroup = function(index) {
|
||||
if (index === 0) {
|
||||
return true;
|
||||
}
|
||||
var curTx = $scope.txHistory[index];
|
||||
var prevTx = $scope.txHistory[index - 1];
|
||||
return !createdDuringSameMonth(curTx, prevTx);
|
||||
};
|
||||
|
||||
$scope.isLastInGroup = function(index) {
|
||||
if (index === $scope.txHistory.length - 1) {
|
||||
return true;
|
||||
}
|
||||
return $scope.isFirstInGroup(index + 1);
|
||||
};
|
||||
|
||||
function createdDuringSameMonth(tx1, tx2) {
|
||||
var date1 = new Date(tx1.time * 1000);
|
||||
var date2 = new Date(tx2.time * 1000);
|
||||
return getMonthYear(date1) === getMonthYear(date2);
|
||||
}
|
||||
|
||||
$scope.createdWithinPastDay = function(time) {
|
||||
var now = new Date();
|
||||
var date = new Date(time * 1000);
|
||||
return (now.getTime() - date.getTime()) < (1000 * 60 * 60 * 24);
|
||||
};
|
||||
|
||||
$scope.isDateInCurrentMonth = function(date) {
|
||||
var now = new Date();
|
||||
return getMonthYear(now) === getMonthYear(date);
|
||||
};
|
||||
|
||||
function getMonthYear(date) {
|
||||
return date.getMonth() + date.getFullYear();
|
||||
}
|
||||
|
||||
$scope.isUnconfirmed = function(tx) {
|
||||
return !tx.confirmations || tx.confirmations === 0;
|
||||
};
|
||||
|
||||
$scope.showMore = function() {
|
||||
$timeout(function() {
|
||||
currentTxHistoryPage++;
|
||||
|
|
@ -177,9 +247,99 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
|||
});
|
||||
};
|
||||
|
||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||
var prevPos;
|
||||
|
||||
$scope.wallet = profileService.getWallet(data.stateParams.walletId);
|
||||
function getScrollPosition() {
|
||||
var scrollPosition = $ionicScrollDelegate.getScrollPosition();
|
||||
if (!scrollPosition) {
|
||||
$window.requestAnimationFrame(function() {
|
||||
getScrollPosition();
|
||||
});
|
||||
return;
|
||||
}
|
||||
var pos = scrollPosition.top;
|
||||
if (pos === prevPos) {
|
||||
$window.requestAnimationFrame(function() {
|
||||
getScrollPosition();
|
||||
});
|
||||
return;
|
||||
}
|
||||
prevPos = pos;
|
||||
refreshAmountSection(pos);
|
||||
};
|
||||
|
||||
function refreshAmountSection(scrollPos) {
|
||||
$scope.showBalanceButton = false;
|
||||
if ($scope.wallet.status) {
|
||||
$scope.showBalanceButton = ($scope.wallet.status.totalBalanceSat != $scope.wallet.status.spendableAmount);
|
||||
}
|
||||
if (!$scope.amountIsCollapsible) {
|
||||
var t = ($scope.showBalanceButton ? 15 : 45);
|
||||
$scope.amountScale = 'translateY(' + t + 'px)';
|
||||
return;
|
||||
}
|
||||
|
||||
scrollPos = scrollPos || 0;
|
||||
var amountHeight = 210 - scrollPos;
|
||||
if (amountHeight < 80) {
|
||||
amountHeight = 80;
|
||||
}
|
||||
var contentMargin = amountHeight;
|
||||
if (contentMargin > 210) {
|
||||
contentMargin = 210;
|
||||
}
|
||||
|
||||
var amountScale = (amountHeight / 210);
|
||||
if (amountScale < 0.5) {
|
||||
amountScale = 0.5;
|
||||
}
|
||||
if (amountScale > 1.1) {
|
||||
amountScale = 1.1;
|
||||
}
|
||||
|
||||
var s = amountScale;
|
||||
|
||||
// Make space for the balance button when it needs to display.
|
||||
var TOP_NO_BALANCE_BUTTON = 115;
|
||||
var TOP_BALANCE_BUTTON = 30;
|
||||
var top = TOP_NO_BALANCE_BUTTON;
|
||||
if ($scope.showBalanceButton) {
|
||||
top = TOP_BALANCE_BUTTON;
|
||||
}
|
||||
|
||||
var amountTop = ((amountScale - 0.7) / 0.7) * top;
|
||||
if (amountTop < -10) {
|
||||
amountTop = -10;
|
||||
}
|
||||
if (amountTop > top) {
|
||||
amountTop = top;
|
||||
}
|
||||
|
||||
var t = amountTop;
|
||||
|
||||
$scope.altAmountOpacity = (amountHeight - 100) / 80;
|
||||
$window.requestAnimationFrame(function() {
|
||||
$scope.amountHeight = amountHeight + 'px';
|
||||
$scope.contentMargin = contentMargin + 'px';
|
||||
$scope.amountScale = 'scale3d(' + s + ',' + s + ',' + s + ') translateY(' + t + 'px)';
|
||||
$scope.$digest();
|
||||
getScrollPosition();
|
||||
});
|
||||
}
|
||||
|
||||
var scrollWatcherInitialized;
|
||||
|
||||
$scope.$on("$ionicView.enter", function(event, data) {
|
||||
if ($scope.isCordova && $scope.isAndroid) setAndroidStatusBarColor();
|
||||
if (scrollWatcherInitialized || !$scope.amountIsCollapsible) {
|
||||
return;
|
||||
}
|
||||
scrollWatcherInitialized = true;
|
||||
});
|
||||
|
||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||
$scope.walletId = data.stateParams.walletId;
|
||||
$scope.wallet = profileService.getWallet($scope.walletId);
|
||||
$scope.requiresMultipleSignatures = $scope.wallet.credentials.m > 1;
|
||||
|
||||
addressbookService.list(function(err, ab) {
|
||||
|
|
@ -188,6 +348,7 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
|||
});
|
||||
|
||||
$scope.updateAll();
|
||||
refreshAmountSection();
|
||||
|
||||
listeners = [
|
||||
$rootScope.$on('bwsEvent', function(e, walletId) {
|
||||
|
|
@ -201,9 +362,55 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
|||
];
|
||||
});
|
||||
|
||||
$scope.$on("$ionicView.beforeLeave", function(event, data) {
|
||||
if ($window.StatusBar) {
|
||||
$window.StatusBar.backgroundColorByHexString('#1e3186');
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$on("$ionicView.leave", function(event, data) {
|
||||
lodash.each(listeners, function(x) {
|
||||
x();
|
||||
});
|
||||
});
|
||||
|
||||
function setAndroidStatusBarColor() {
|
||||
var SUBTRACT_AMOUNT = 15;
|
||||
var rgb = hexToRgb($scope.wallet.color);
|
||||
var keys = Object.keys(rgb);
|
||||
keys.forEach(function(k) {
|
||||
if (rgb[k] - SUBTRACT_AMOUNT < 0) {
|
||||
rgb[k] = 0;
|
||||
} else {
|
||||
rgb[k] -= SUBTRACT_AMOUNT;
|
||||
}
|
||||
});
|
||||
var statusBarColorHexString = rgbToHex(rgb.r, rgb.g, rgb.b);
|
||||
if ($window.StatusBar)
|
||||
$window.StatusBar.backgroundColorByHexString(statusBarColorHexString);
|
||||
}
|
||||
|
||||
function hexToRgb(hex) {
|
||||
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
|
||||
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
|
||||
hex = hex.replace(shorthandRegex, function(m, r, g, b) {
|
||||
return r + r + g + g + b + b;
|
||||
});
|
||||
|
||||
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||
return result ? {
|
||||
r: parseInt(result[1], 16),
|
||||
g: parseInt(result[2], 16),
|
||||
b: parseInt(result[3], 16)
|
||||
} : null;
|
||||
}
|
||||
|
||||
function componentToHex(c) {
|
||||
var hex = c.toString(16);
|
||||
return hex.length == 1 ? "0" + hex : hex;
|
||||
}
|
||||
|
||||
function rgbToHex(r, g, b) {
|
||||
return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8,10 +8,11 @@ angular.module('copayApp.directives')
|
|||
transclude: true,
|
||||
scope: {
|
||||
sendStatus: '=clickSendStatus',
|
||||
wallet: '=hasWalletChosen'
|
||||
},
|
||||
link: function(scope, element, attrs) {
|
||||
scope.$watch('sendStatus', function() {
|
||||
if(scope.sendStatus !== 'success') {
|
||||
if (scope.sendStatus !== 'success') {
|
||||
scope.displaySendStatus = scope.sendStatus;
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -16,6 +16,6 @@ angular.module('copayApp.directives')
|
|||
scope.emailHash = md5.createHash(scope.email.toLowerCase() || '');
|
||||
}
|
||||
},
|
||||
template: '<img class="gravatar" alt="{{ name }}" height="{{ height }}" width="{{ width }}" src="https://secure.gravatar.com/avatar/{{ emailHash }}.jpg?s={{ width }}&d=mm">'
|
||||
}
|
||||
template: '<img class="gravatar" alt="{{ name }}" height="{{ height }}" width="{{ width }}" src="https://secure.gravatar.com/avatar/{{ emailHash }}.jpg?s={{ width }}&d=identicon">'
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ angular.module('copayApp.directives')
|
|||
scope.showMenu = true;
|
||||
scope.https = false;
|
||||
|
||||
if(scope.type === 'url') {
|
||||
if(scope.data.indexOf('https://') === 0) {
|
||||
if (scope.type === 'url') {
|
||||
if (scope.data.indexOf('https://') === 0) {
|
||||
scope.https = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -24,14 +24,16 @@ angular.module('copayApp.directives')
|
|||
scope.showMenu = false;
|
||||
$rootScope.$broadcast('incomingDataMenu.menuHidden');
|
||||
};
|
||||
scope.goToUrl = function(url){
|
||||
scope.goToUrl = function(url) {
|
||||
externalLinkService.open(url);
|
||||
};
|
||||
scope.sendPaymentToAddress = function(bitcoinAddress) {
|
||||
scope.showMenu = false;
|
||||
$state.go('tabs.send').then(function() {
|
||||
$timeout(function() {
|
||||
$state.transitionTo('tabs.send.amount', {toAddress: bitcoinAddress});
|
||||
$state.transitionTo('tabs.send.amount', {
|
||||
toAddress: bitcoinAddress
|
||||
});
|
||||
}, 50);
|
||||
});
|
||||
};
|
||||
|
|
@ -40,11 +42,23 @@ angular.module('copayApp.directives')
|
|||
$timeout(function() {
|
||||
$state.go('tabs.send').then(function() {
|
||||
$timeout(function() {
|
||||
$state.transitionTo('tabs.send.addressbook', {addressbookEntry: bitcoinAddress});
|
||||
$state.transitionTo('tabs.send.addressbook', {
|
||||
addressbookEntry: bitcoinAddress
|
||||
});
|
||||
});
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
scope.scanPaperWallet = function(privateKey) {
|
||||
scope.showMenu = false;
|
||||
$state.go('tabs.home').then(function() {
|
||||
$timeout(function() {
|
||||
$state.transitionTo('tabs.home.paperWallet', {
|
||||
privateKey: privateKey
|
||||
});
|
||||
}, 50);
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ angular.module('copayApp.directives')
|
|||
transclude: true,
|
||||
scope: {
|
||||
sendStatus: '=slideSendStatus',
|
||||
onConfirm: '&slideOnConfirm'
|
||||
onConfirm: '&slideOnConfirm',
|
||||
wallet: '=hasWalletChosen'
|
||||
},
|
||||
link: function(scope, element, attrs) {
|
||||
|
||||
|
|
@ -33,9 +34,9 @@ angular.module('copayApp.directives')
|
|||
scope.displaySendStatus = '';
|
||||
|
||||
scope.$watch('sendStatus', function() {
|
||||
if(!scope.sendStatus) {
|
||||
if (!scope.sendStatus) {
|
||||
reset();
|
||||
} else if(scope.sendStatus === 'success') {
|
||||
} else if (scope.sendStatus === 'success') {
|
||||
scope.displaySendStatus = '';
|
||||
$timeout(function() {
|
||||
reset();
|
||||
|
|
@ -51,19 +52,20 @@ angular.module('copayApp.directives')
|
|||
var startTime = currentEaseStartTime;
|
||||
var initialPct = fromPct;
|
||||
var distance = pct - fromPct;
|
||||
|
||||
function ease() {
|
||||
if(startTime !== currentEaseStartTime) {
|
||||
if (startTime !== currentEaseStartTime) {
|
||||
return;
|
||||
}
|
||||
$window.requestAnimationFrame(function() {
|
||||
var now = Date.now();
|
||||
var elapsed = now - startTime;
|
||||
var normalizedElapsedTime = elapsed/duration;
|
||||
var normalizedElapsedTime = elapsed / duration;
|
||||
var newVal = easeFx(normalizedElapsedTime);
|
||||
var newPct = newVal*distance + initialPct;
|
||||
var newPct = newVal * distance + initialPct;
|
||||
animateFx(newPct);
|
||||
scope.$digest();
|
||||
if(elapsed < duration) {
|
||||
if (elapsed < duration) {
|
||||
ease();
|
||||
} else {
|
||||
deferred.resolve();
|
||||
|
|
@ -93,31 +95,33 @@ angular.module('copayApp.directives')
|
|||
function setNewSliderStyle(pct) {
|
||||
var knobWidthPct = getKnobWidthPercentage();
|
||||
var translatePct = pct - knobWidthPct;
|
||||
if(isSliding) {
|
||||
translatePct += 0.35*pct;
|
||||
if (isSliding) {
|
||||
translatePct += 0.35 * pct;
|
||||
}
|
||||
scope.sliderStyle = getTransformStyle(translatePct);
|
||||
curSliderPct = pct;
|
||||
}
|
||||
|
||||
function setNewBitcoinStyle(pct) {
|
||||
var translatePct = -2.25*pct;
|
||||
var translatePct = -2.25 * pct;
|
||||
scope.bitcoinStyle = getTransformStyle(translatePct);
|
||||
curBitcoinPct = pct;
|
||||
}
|
||||
|
||||
function setNewTextStyle(pct) {
|
||||
var translatePct = -0.1*pct;
|
||||
var translatePct = -0.1 * pct;
|
||||
scope.textStyle = getTransformStyle(translatePct);
|
||||
curTextPct = pct;
|
||||
}
|
||||
|
||||
function getTransformStyle(translatePct) {
|
||||
return {'transform': 'translateX(' + translatePct + '%)'};
|
||||
return {
|
||||
'transform': 'translateX(' + translatePct + '%)'
|
||||
};
|
||||
}
|
||||
|
||||
function getKnobWidthPercentage() {
|
||||
var knobWidthPct = (KNOB_WIDTH/elm.clientWidth)*100;
|
||||
function getKnobWidthPercentage() {
|
||||
var knobWidthPct = (KNOB_WIDTH / elm.clientWidth) * 100;
|
||||
return knobWidthPct;
|
||||
}
|
||||
|
||||
|
|
@ -175,8 +179,8 @@ angular.module('copayApp.directives')
|
|||
|
||||
function getTouchXPosition($event) {
|
||||
var x;
|
||||
if($event.touches || $event.changedTouches) {
|
||||
if($event.touches.length) {
|
||||
if ($event.touches || $event.changedTouches) {
|
||||
if ($event.touches.length) {
|
||||
x = $event.touches[0].clientX;
|
||||
} else {
|
||||
x = $event.changedTouches[0].clientX;
|
||||
|
|
@ -190,18 +194,18 @@ angular.module('copayApp.directives')
|
|||
function getSlidPercentage($event) {
|
||||
var x = getTouchXPosition($event);
|
||||
var width = elm.clientWidth;
|
||||
var pct = (x/width)*100;
|
||||
if(x >= width) {
|
||||
var pct = (x / width) * 100;
|
||||
if (x >= width) {
|
||||
pct = 100;
|
||||
}
|
||||
return pct;
|
||||
}
|
||||
|
||||
scope.onTouchstart = function($event) {
|
||||
if(scope.isSlidFully) {
|
||||
if (scope.isSlidFully) {
|
||||
return;
|
||||
}
|
||||
if(!isSliding) {
|
||||
if (!isSliding) {
|
||||
var pct = getSlidPercentage($event);
|
||||
if (pct > MAX_SLIDE_START_PERCENTAGE) {
|
||||
jiggleSlider();
|
||||
|
|
@ -209,7 +213,7 @@ angular.module('copayApp.directives')
|
|||
} else {
|
||||
isSliding = true;
|
||||
var knobWidthPct = getKnobWidthPercentage();
|
||||
if(pct < knobWidthPct) {
|
||||
if (pct < knobWidthPct) {
|
||||
pct = knobWidthPct;
|
||||
}
|
||||
pct += PERCENTAGE_BUMP;
|
||||
|
|
@ -219,12 +223,12 @@ angular.module('copayApp.directives')
|
|||
};
|
||||
|
||||
scope.onTouchmove = function($event) {
|
||||
if(!isSliding || scope.isSlidFully) {
|
||||
if (!isSliding || scope.isSlidFully) {
|
||||
return;
|
||||
}
|
||||
var pct = getSlidPercentage($event);
|
||||
var knobWidthPct = getKnobWidthPercentage();
|
||||
if(pct < knobWidthPct) {
|
||||
if (pct < knobWidthPct) {
|
||||
pct = knobWidthPct;
|
||||
}
|
||||
pct += PERCENTAGE_BUMP;
|
||||
|
|
@ -233,11 +237,11 @@ angular.module('copayApp.directives')
|
|||
};
|
||||
|
||||
scope.onTouchend = function($event) {
|
||||
if(scope.isSlidFully) {
|
||||
if (scope.isSlidFully) {
|
||||
return;
|
||||
}
|
||||
var pct = getSlidPercentage($event);
|
||||
if(isSliding && pct > FULLY_SLID_PERCENTAGE) {
|
||||
if (isSliding && pct > FULLY_SLID_PERCENTAGE) {
|
||||
pct = 100;
|
||||
setSliderPosition(pct);
|
||||
alertSlidFully();
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ angular.module('copayApp.directives')
|
|||
templateUrl: 'views/includes/walletSelector.html',
|
||||
transclude: true,
|
||||
scope: {
|
||||
title: '=walletSelectorTitle',
|
||||
show: '=walletSelectorShow',
|
||||
wallets: '=walletSelectorWallets',
|
||||
selectedWallet: '=walletSelectorSelectedWallet',
|
||||
|
|
|
|||
235
src/js/routes.js
235
src/js/routes.js
|
|
@ -151,7 +151,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
|||
*/
|
||||
|
||||
.state('tabs.wallet', {
|
||||
url: '/wallet/{walletId}/{fromOnboarding}',
|
||||
url: '/wallet/:walletId/:fromOnboarding',
|
||||
views: {
|
||||
'tab-home@tabs': {
|
||||
controller: 'walletDetailsController',
|
||||
|
|
@ -182,7 +182,24 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
|||
views: {
|
||||
'tab-home@tabs': {
|
||||
controller: 'txDetailsController',
|
||||
templateUrl: 'views/modals/tx-details.html'
|
||||
templateUrl: 'views/tx-details.html'
|
||||
}
|
||||
}
|
||||
})
|
||||
.state('tabs.wallet.backupWarning', {
|
||||
url: '/backupWarning/:from/:walletId',
|
||||
views: {
|
||||
'tab-home@tabs': {
|
||||
templateUrl: 'views/backupWarning.html'
|
||||
}
|
||||
}
|
||||
})
|
||||
.state('tabs.wallet.backup', {
|
||||
url: '/backup/:walletId',
|
||||
views: {
|
||||
'tab-home@tabs': {
|
||||
templateUrl: 'views/backup.html',
|
||||
controller: 'backupController'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -269,7 +286,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
|||
}
|
||||
})
|
||||
.state('tabs.send.confirm', {
|
||||
url: '/confirm/:isWallet/:toAddress/:toName/:toAmount/:toEmail/:description',
|
||||
url: '/confirm/:isWallet/:toAddress/:toName/:toAmount/:toEmail/:description/:useSendMax',
|
||||
views: {
|
||||
'tab-send@tabs': {
|
||||
controller: 'confirmController',
|
||||
|
|
@ -538,15 +555,6 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
|||
}
|
||||
}
|
||||
})
|
||||
.state('tabs.preferences.paperWallet', {
|
||||
url: '/paperWallet',
|
||||
views: {
|
||||
'tab-settings@tabs': {
|
||||
controller: 'paperWalletController',
|
||||
templateUrl: 'views/paperWallet.html'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
/*
|
||||
*
|
||||
|
|
@ -601,7 +609,57 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
|||
|
||||
/*
|
||||
*
|
||||
* Back flow from receive
|
||||
* Addresses
|
||||
*
|
||||
*/
|
||||
|
||||
.state('tabs.receive.addresses', {
|
||||
url: '/addresses/:walletId',
|
||||
views: {
|
||||
'tab-receive@tabs': {
|
||||
controller: 'addressesController',
|
||||
templateUrl: 'views/addresses.html'
|
||||
}
|
||||
}
|
||||
})
|
||||
.state('tabs.receive.allAddresses', {
|
||||
url: '/allAddresses/:walletId',
|
||||
views: {
|
||||
'tab-receive@tabs': {
|
||||
controller: 'addressesController',
|
||||
templateUrl: 'views/allAddresses.html'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
/*
|
||||
*
|
||||
* Request Specific amount
|
||||
*
|
||||
*/
|
||||
|
||||
.state('tabs.receive.amount', {
|
||||
url: '/amount/:customAmount/:toAddress',
|
||||
views: {
|
||||
'tab-receive@tabs': {
|
||||
controller: 'amountController',
|
||||
templateUrl: 'views/amount.html'
|
||||
}
|
||||
}
|
||||
})
|
||||
.state('tabs.receive.customAmount', {
|
||||
url: '/customAmount/:toAmount/:toAddress',
|
||||
views: {
|
||||
'tab-receive@tabs': {
|
||||
controller: 'customAmountController',
|
||||
templateUrl: 'views/customAmount.html'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
/*
|
||||
*
|
||||
* Init backup flow
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -625,10 +683,25 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
|||
|
||||
/*
|
||||
*
|
||||
* Onboarding
|
||||
* Paper Wallet
|
||||
*
|
||||
*/
|
||||
|
||||
.state('tabs.home.paperWallet', {
|
||||
url: '/paperWallet/:privateKey',
|
||||
views: {
|
||||
'tab-home@tabs': {
|
||||
controller: 'paperWalletController',
|
||||
templateUrl: 'views/paperWallet.html'
|
||||
}
|
||||
}
|
||||
})
|
||||
/*
|
||||
*
|
||||
* Onboarding
|
||||
*
|
||||
*/
|
||||
|
||||
.state('onboarding', {
|
||||
url: '/onboarding',
|
||||
abstract: true,
|
||||
|
|
@ -695,7 +768,8 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
|||
url: '/disclaimer/:walletId/:backedUp/:resume',
|
||||
views: {
|
||||
'onboarding': {
|
||||
templateUrl: 'views/onboarding/disclaimer.html'
|
||||
templateUrl: 'views/onboarding/disclaimer.html',
|
||||
controller: 'disclaimerController'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -720,6 +794,67 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
|||
},
|
||||
})
|
||||
|
||||
/*
|
||||
*
|
||||
* Feedback
|
||||
*
|
||||
*/
|
||||
|
||||
.state('tabs.feedback', {
|
||||
url: '/feedback',
|
||||
views: {
|
||||
'tab-settings@tabs': {
|
||||
templateUrl: 'views/feedback/send.html',
|
||||
controller: 'sendController'
|
||||
}
|
||||
}
|
||||
})
|
||||
.state('tabs.shareApp', {
|
||||
url: '/shareApp/:score/:skipped/:fromSettings',
|
||||
views: {
|
||||
'tab-settings@tabs': {
|
||||
controller: 'completeController',
|
||||
templateUrl: 'views/feedback/complete.html'
|
||||
}
|
||||
}
|
||||
})
|
||||
.state('tabs.rate', {
|
||||
url: '/rate',
|
||||
abstract: true
|
||||
})
|
||||
.state('tabs.rate.send', {
|
||||
url: '/send/:score',
|
||||
views: {
|
||||
'tab-home@tabs': {
|
||||
templateUrl: 'views/feedback/send.html',
|
||||
controller: 'sendController'
|
||||
}
|
||||
}
|
||||
})
|
||||
.state('tabs.rate.complete', {
|
||||
url: '/complete/:score/:skipped',
|
||||
views: {
|
||||
'tab-home@tabs': {
|
||||
controller: 'completeController',
|
||||
templateUrl: 'views/feedback/complete.html'
|
||||
}
|
||||
},
|
||||
customConfig: {
|
||||
hideStatusBar: true
|
||||
}
|
||||
})
|
||||
.state('tabs.rate.rateApp', {
|
||||
url: '/rateApp/:score',
|
||||
views: {
|
||||
'tab-home@tabs': {
|
||||
controller: 'rateAppController',
|
||||
templateUrl: 'views/feedback/rateApp.html'
|
||||
}
|
||||
},
|
||||
customConfig: {
|
||||
hideStatusBar: true
|
||||
}
|
||||
})
|
||||
|
||||
/*
|
||||
*
|
||||
|
|
@ -753,30 +888,28 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
|||
}
|
||||
}
|
||||
})
|
||||
.state('tabs.buyandsell.glidera.buy', {
|
||||
url: '/buy',
|
||||
.state('tabs.buyandsell.glidera.amount', {
|
||||
url: '/amount/:isGlidera/:glideraAccessToken',
|
||||
views: {
|
||||
'tab-home@tabs': {
|
||||
controller: 'buyGlideraController',
|
||||
controllerAs: 'buy',
|
||||
templateUrl: 'views/buyGlidera.html'
|
||||
controller: 'amountController',
|
||||
templateUrl: 'views/amount.html'
|
||||
}
|
||||
}
|
||||
})
|
||||
.state('tabs.buyandsell.glidera.sell', {
|
||||
url: '/sell',
|
||||
.state('tabs.buyandsell.glidera.confirm', {
|
||||
url: '/confirm/:toAmount/:isGlidera/:glideraAccessToken',
|
||||
views: {
|
||||
'tab-home@tabs': {
|
||||
controller: 'sellGlideraController',
|
||||
controllerAs: 'sell',
|
||||
templateUrl: 'views/sellGlidera.html'
|
||||
controller: 'confirmController',
|
||||
templateUrl: 'views/confirm.html'
|
||||
}
|
||||
}
|
||||
})
|
||||
.state('tabs.buyandsell.glidera.preferences', {
|
||||
url: '/preferences',
|
||||
.state('tabs.preferences.glidera', {
|
||||
url: '/glidera',
|
||||
views: {
|
||||
'tab-home@tabs': {
|
||||
'tab-settings@tabs': {
|
||||
controller: 'preferencesGlideraController',
|
||||
templateUrl: 'views/preferencesGlidera.html'
|
||||
}
|
||||
|
|
@ -830,16 +963,36 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
|||
controller: 'amazonController',
|
||||
templateUrl: 'views/amazon.html'
|
||||
}
|
||||
},
|
||||
params: {
|
||||
cardClaimCode: null
|
||||
}
|
||||
})
|
||||
.state('tabs.giftcards.amazon.buy', {
|
||||
url: '/buy',
|
||||
.state('tabs.giftcards.amazon.amount', {
|
||||
url: '/amount',
|
||||
views: {
|
||||
'tab-home@tabs': {
|
||||
controller: 'buyAmazonController',
|
||||
controllerAs: 'buy',
|
||||
templateUrl: 'views/buyAmazon.html'
|
||||
controller: 'amountController',
|
||||
templateUrl: 'views/amount.html'
|
||||
}
|
||||
},
|
||||
params: {
|
||||
isGiftCard: true,
|
||||
toName: 'Amazon.com Gift Card'
|
||||
}
|
||||
})
|
||||
.state('tabs.giftcards.amazon.confirm', {
|
||||
url: '/confirm/:toAmount/:toAddress/:description/:giftCardAmountUSD/:giftCardAccessKey/:giftCardInvoiceTime/:giftCardUUID',
|
||||
views: {
|
||||
'tab-home@tabs': {
|
||||
controller: 'confirmController',
|
||||
templateUrl: 'views/confirm.html'
|
||||
}
|
||||
},
|
||||
params: {
|
||||
isGiftCard: true,
|
||||
toName: 'Amazon.com Gift Card',
|
||||
paypro: null
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -889,10 +1042,10 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
|||
paypro: null
|
||||
}
|
||||
})
|
||||
.state('tabs.bitpayCard.preferences', {
|
||||
url: '/preferences',
|
||||
.state('tabs.preferences.bitpayCard', {
|
||||
url: '/bitpay-card',
|
||||
views: {
|
||||
'tab-home@tabs': {
|
||||
'tab-settings@tabs': {
|
||||
controller: 'preferencesBitpayCardController',
|
||||
templateUrl: 'views/preferencesBitpayCard.html'
|
||||
}
|
||||
|
|
@ -1030,4 +1183,14 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
|||
$log.debug(' toParams:' + JSON.stringify(toParams || {}));
|
||||
$log.debug(' fromParams:' + JSON.stringify(fromParams || {}));
|
||||
});
|
||||
|
||||
$rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
|
||||
if ($window.StatusBar) {
|
||||
if (toState.customConfig && toState.customConfig.hideStatusBar) {
|
||||
$window.StatusBar.hide();
|
||||
} else {
|
||||
$window.StatusBar.show();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ angular.module('copayApp.services').factory('amazonService', function($http, $lo
|
|||
});
|
||||
|
||||
// Show pending task from the UI
|
||||
storageService.setNextStep('AmazonGiftCards', true, function(err) {});
|
||||
storageService.setNextStep('AmazonGiftCards', 'true', function(err) {});
|
||||
};
|
||||
|
||||
root.getPendingGiftCards = function(cb) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
angular.module('copayApp.services')
|
||||
.factory('backupService', function backupServiceFactory($log, $timeout, $stateParams, profileService, sjcl) {
|
||||
.factory('backupService', function backupServiceFactory($log, $timeout, $stateParams, profileService, sjcl, $window) {
|
||||
|
||||
var root = {};
|
||||
|
||||
|
|
@ -80,7 +80,7 @@ angular.module('copayApp.services')
|
|||
|
||||
var walletName = (wallet.alias || '') + (wallet.alias ? '-' : '') + wallet.credentials.walletName;
|
||||
if (opts.noSign) walletName = walletName + '-noSign'
|
||||
var filename = walletName + '-Copaybackup.aes.json';
|
||||
var filename = walletName + '-' + $window.appConfig.nameCase + 'backup.aes.json';
|
||||
_download(ew, filename, cb)
|
||||
};
|
||||
return root;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http,
|
|||
|
||||
var _setError = function(msg, e) {
|
||||
$log.error(msg);
|
||||
var error = e.data ? e.data.error : msg;
|
||||
var error = (e && e.data && e.data.error) ? e.data.error : msg;
|
||||
return error;
|
||||
};
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http,
|
|||
};
|
||||
|
||||
root.bitAuthPair = function(obj, cb) {
|
||||
var deviceName = 'Unknow device';
|
||||
var deviceName = 'Unknown device';
|
||||
if (platformInfo.isNW) {
|
||||
deviceName = require('os').platform();
|
||||
} else if (platformInfo.isCordova) {
|
||||
|
|
@ -143,7 +143,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http,
|
|||
root.getBitpayDebitCards(function(err, data) {
|
||||
if (err) return cb(err);
|
||||
var card = lodash.find(data, {id : cardId});
|
||||
if (!card) return cb(_setError('Not card found'));
|
||||
if (!card) return cb(_setError('Card not found'));
|
||||
// Get invoices
|
||||
$http(_post('/api/v2/' + card.token, json, appIdentity)).then(function(data) {
|
||||
$log.info('BitPay Get Invoices: SUCCESS');
|
||||
|
|
@ -180,7 +180,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http,
|
|||
root.getBitpayDebitCards(function(err, data) {
|
||||
if (err) return cb(err);
|
||||
var card = lodash.find(data, {id : cardId});
|
||||
if (!card) return cb(_setError('Not card found'));
|
||||
if (!card) return cb(_setError('Card not found'));
|
||||
$http(_post('/api/v2/' + card.token, json, appIdentity)).then(function(data) {
|
||||
$log.info('BitPay TopUp: SUCCESS');
|
||||
if(data.data.error) {
|
||||
|
|
@ -258,13 +258,30 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http,
|
|||
|
||||
root.remove = function(card, cb) {
|
||||
storageService.removeBitpayDebitCard(BITPAY_CARD_NETWORK, card, function(err) {
|
||||
if (err) {
|
||||
$log.error('Error removing BitPay debit card: ' + err);
|
||||
// Continue, try to remove/cleanup card history
|
||||
}
|
||||
storageService.removeBitpayDebitCardHistory(BITPAY_CARD_NETWORK, card, function(err) {
|
||||
$log.info('BitPay Debit Card(s) Removed: SUCCESS');
|
||||
if (err) {
|
||||
$log.error('Error removing BitPay debit card transaction history: ' + err);
|
||||
return cb(err);
|
||||
}
|
||||
$log.info('Successfully removed BitPay debit card');
|
||||
return cb();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
root.getRates = function(currency, cb) {
|
||||
$http(_get('/rates/' + currency)).then(function(data) {
|
||||
$log.info('BitPay Get Rates: SUCCESS');
|
||||
return cb(data.data.error, data.data.data);
|
||||
}, function(data) {
|
||||
return cb(_setError('BitPay Error: Get Rates', data));
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* CONSTANTS
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -15,6 +15,16 @@ angular.module('copayApp.services').factory('configService', function(storageSer
|
|||
url: 'https://bws.bitpay.com/bws/api',
|
||||
},
|
||||
|
||||
download: {
|
||||
url: 'https://bitpay.com/wallet',
|
||||
},
|
||||
|
||||
rateApp: {
|
||||
ios: 'http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=1149581638&pageNumber=0&sortOrdering=2&type=Purple+Software&mt=8',
|
||||
android: 'https://play.google.com/store/apps/details?id=com.bitpay.wallet',
|
||||
wp: ''
|
||||
},
|
||||
|
||||
// wallet default config
|
||||
wallet: {
|
||||
requiredCopayers: 2,
|
||||
|
|
|
|||
|
|
@ -21,14 +21,10 @@ angular.module('copayApp.services').service('externalLinkService', function(plat
|
|||
_restoreHandleOpenURL(old);
|
||||
} else {
|
||||
if (optIn) {
|
||||
var message = gettextCatalog.getString(message),
|
||||
title = gettextCatalog.getString(title),
|
||||
okText = gettextCatalog.getString(okText),
|
||||
cancelText = gettextCatalog.getString(cancelText),
|
||||
openBrowser = function(res) {
|
||||
if (res) window.open(url, '_system');
|
||||
_restoreHandleOpenURL(old);
|
||||
};
|
||||
var openBrowser = function(res) {
|
||||
if (res) window.open(url, '_system');
|
||||
_restoreHandleOpenURL(old);
|
||||
};
|
||||
popupService.showConfirm(title, message, okText, cancelText, openBrowser);
|
||||
} else {
|
||||
window.open(url, '_system');
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.services').factory('feeService', function($log, $stateParams, bwcService, walletService, configService, gettext, lodash, txFormatService) {
|
||||
angular.module('copayApp.services').factory('feeService', function($log, $stateParams, bwcService, walletService, configService, gettext, lodash, txFormatService, gettextCatalog) {
|
||||
var root = {};
|
||||
|
||||
// Constant fee options to translate
|
||||
|
|
@ -15,48 +15,48 @@ angular.module('copayApp.services').factory('feeService', function($log, $stateP
|
|||
return configService.getSync().wallet.settings.feeLevel || 'normal';
|
||||
};
|
||||
|
||||
root.getCurrentFeeValue = function(cb) {
|
||||
console.log('[feeService.js.18:getCurrentFeeValue:] TODO TODO TODO'); //TODO
|
||||
// TODO TODO TODO
|
||||
var wallet = profileService.getWallet($stateParams.walletId);
|
||||
root.getCurrentFeeValue = function(network, cb) {
|
||||
network = network || 'livenet';
|
||||
var feeLevel = root.getCurrentFeeLevel();
|
||||
|
||||
wallet.getFeeLevels(wallet.credentials.network, function(err, levels) {
|
||||
if (err)
|
||||
return cb({
|
||||
message: 'Could not get dynamic fee'
|
||||
});
|
||||
root.getFeeLevels(function(err, levels) {
|
||||
if (err) return cb(err);
|
||||
|
||||
var feeLevelValue = lodash.find(levels, {
|
||||
var feeLevelValue = lodash.find(levels[network], {
|
||||
level: feeLevel
|
||||
});
|
||||
if (!feeLevelValue || !feeLevelValue.feePerKB)
|
||||
|
||||
if (!feeLevelValue || !feeLevelValue.feePerKB) {
|
||||
return cb({
|
||||
message: 'Could not get dynamic fee for level: ' + feeLevel
|
||||
message: gettextCatalog.getString("Could not get dynamic fee for level: {{feeLevel}}", {
|
||||
feeLevel: feeLevel
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
var fee = feeLevelValue.feePerKB;
|
||||
$log.debug('Dynamic fee: ' + feeLevel + ' ' + fee + ' SAT');
|
||||
|
||||
return cb(null, fee);
|
||||
});
|
||||
};
|
||||
|
||||
root.getFeeLevels = function(cb) {
|
||||
var walletClient = bwcService.getClient();
|
||||
|
||||
var unitName = configService.getSync().wallet.settings.unitName;
|
||||
|
||||
walletClient.getFeeLevels('livenet', function(errLivenet, levelsLivenet) {
|
||||
walletClient.getFeeLevels('testnet', function(errTestnet, levelsTestnet) {
|
||||
if (errLivenet || errTestnet) $log.debug('Could not get dynamic fee');
|
||||
else {
|
||||
if (errLivenet || errTestnet) {
|
||||
return cb(gettextCatalog.getString('Could not get dynamic fee'));
|
||||
} else {
|
||||
for (var i = 0; i < 4; i++) {
|
||||
levelsLivenet[i]['feePerKBUnit'] = txFormatService.formatAmount(levelsLivenet[i].feePerKB) + ' ' + unitName;
|
||||
levelsTestnet[i]['feePerKBUnit'] = txFormatService.formatAmount(levelsTestnet[i].feePerKB) + ' ' + unitName;
|
||||
}
|
||||
}
|
||||
|
||||
return cb({
|
||||
return cb(null, {
|
||||
'livenet': levelsLivenet,
|
||||
'testnet': levelsTestnet
|
||||
});
|
||||
|
|
|
|||
58
src/js/services/feedbackService.js
Normal file
58
src/js/services/feedbackService.js
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
'use strict';
|
||||
angular.module('copayApp.services').factory('feedbackService', function($http, $log, $httpParamSerializer, configService) {
|
||||
var root = {};
|
||||
var URL = "https://script.google.com/macros/s/AKfycbybtvNSQKUfgzgXcj3jYLlvCKrcBoktjiJ1V8_cwd2yVkpUBGe3/exec";
|
||||
|
||||
root.send = function(dataSrc, cb) {
|
||||
$http(_post(dataSrc)).then(function() {
|
||||
$log.info("SUCCESS: Feedback sent");
|
||||
return cb();
|
||||
}, function(err) {
|
||||
$log.info("ERROR: Feedback sent anyway.");
|
||||
return cb(err);
|
||||
});
|
||||
};
|
||||
|
||||
var _post = function(dataSrc) {
|
||||
return {
|
||||
method: 'POST',
|
||||
url: URL,
|
||||
headers: {
|
||||
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8'
|
||||
},
|
||||
data: $httpParamSerializer(dataSrc)
|
||||
};
|
||||
};
|
||||
|
||||
root.isVersionUpdated = function(currentVersion, savedVersion) {
|
||||
|
||||
if (!verifyTagFormat(currentVersion))
|
||||
return 'Cannot verify the format of version tag: ' + currentVersion;
|
||||
if (!verifyTagFormat(savedVersion))
|
||||
return 'Cannot verify the format of the saved version tag: ' + savedVersion;
|
||||
|
||||
var current = formatTagNumber(currentVersion);
|
||||
var saved = formatTagNumber(savedVersion);
|
||||
if (saved.major > current.major || (saved.major == current.major && saved.minor > current.minor))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
function verifyTagFormat(tag) {
|
||||
var regex = /^v?\d+\.\d+\.\d+$/i;
|
||||
return regex.exec(tag);
|
||||
};
|
||||
|
||||
function formatTagNumber(tag) {
|
||||
var formattedNumber = tag.replace(/^v/i, '').split('.');
|
||||
return {
|
||||
major: +formattedNumber[0],
|
||||
minor: +formattedNumber[1],
|
||||
patch: +formattedNumber[2]
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
return root;
|
||||
});
|
||||
|
|
@ -81,7 +81,7 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l
|
|||
$http(req).then(function(data) {
|
||||
$log.info('Glidera Authorization Access Token: SUCCESS');
|
||||
// Show pending task from the UI
|
||||
storageService.setNextStep('BuyAndSell', true, function(err) {});
|
||||
storageService.setNextStep('BuyAndSell', 'true', function(err) {});
|
||||
return cb(null, data.data);
|
||||
}, function(data) {
|
||||
$log.error('Glidera Authorization Access Token: ERROR ' + data.statusText);
|
||||
|
|
@ -192,8 +192,13 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l
|
|||
};
|
||||
|
||||
root.get2faCode = function(token, cb) {
|
||||
if (!token) return cb('Invalid Token');
|
||||
if (!token) {
|
||||
$log.error('Glidera Sent 2FA code by SMS: ERROR Invalid Token');
|
||||
return cb('Invalid Token');
|
||||
}
|
||||
|
||||
$http(_get('/authentication/get2faCode', token)).then(function(data) {
|
||||
|
||||
$log.info('Glidera Sent 2FA code by SMS: SUCCESS');
|
||||
return cb(null, data.status == 200 ? true : false);
|
||||
}, function(data) {
|
||||
|
|
|
|||
|
|
@ -31,17 +31,31 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
|
|||
if (!url) return;
|
||||
name = name.replace(/[\[\]]/g, "\\$&");
|
||||
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
|
||||
results = regex.exec(url);
|
||||
results = regex.exec(url);
|
||||
if (!results) return null;
|
||||
if (!results[2]) return '';
|
||||
return decodeURIComponent(results[2].replace(/\+/g, " "));
|
||||
}
|
||||
|
||||
function checkPrivateKey(privateKey) {
|
||||
try {
|
||||
new bitcore.PrivateKey(privateKey, 'livenet');
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// data extensions for Payment Protocol with non-backwards-compatible request
|
||||
if ((/^bitcoin:\?r=[\w+]/).exec(data)) {
|
||||
data = decodeURIComponent(data.replace('bitcoin:?r=', ''));
|
||||
$state.go('tabs.send', {}, {'reload': true, 'notify': $state.current.name == 'tabs.send' ? false : true}).then(function() {
|
||||
$state.transitionTo('tabs.send.confirm', {paypro: data});
|
||||
$state.go('tabs.send', {}, {
|
||||
'reload': true,
|
||||
'notify': $state.current.name == 'tabs.send' ? false : true
|
||||
}).then(function() {
|
||||
$state.transitionTo('tabs.send.confirm', {
|
||||
paypro: data
|
||||
});
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
|
@ -55,31 +69,43 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
|
|||
var addr = parsed.address ? parsed.address.toString() : '';
|
||||
var message = parsed.message;
|
||||
|
||||
var amount = parsed.amount ? parsed.amount : '';
|
||||
var amount = parsed.amount ? parsed.amount : '';
|
||||
|
||||
if (parsed.r) {
|
||||
payproService.getPayProDetails(parsed.r, function(err, details) {
|
||||
handlePayPro(details);
|
||||
});
|
||||
} else {
|
||||
$state.go('tabs.send', {}, {'reload': true, 'notify': $state.current.name == 'tabs.send' ? false : true});
|
||||
$state.go('tabs.send', {}, {
|
||||
'reload': true,
|
||||
'notify': $state.current.name == 'tabs.send' ? false : true
|
||||
});
|
||||
// Timeout is required to enable the "Back" button
|
||||
$timeout(function() {
|
||||
if (amount) {
|
||||
$state.transitionTo('tabs.send.confirm', {toAmount: amount, toAddress: addr, description:message});
|
||||
$state.transitionTo('tabs.send.confirm', {
|
||||
toAmount: amount,
|
||||
toAddress: addr,
|
||||
description: message
|
||||
});
|
||||
} else {
|
||||
$state.transitionTo('tabs.send.amount', {toAddress: addr});
|
||||
$state.transitionTo('tabs.send.amount', {
|
||||
toAddress: addr
|
||||
});
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
return true;
|
||||
|
||||
// Plain URL
|
||||
// Plain URL
|
||||
} else if (/^https?:\/\//.test(data)) {
|
||||
|
||||
payproService.getPayProDetails(data, function(err, details) {
|
||||
if(err) {
|
||||
root.showMenu({data: data, type: 'url'});
|
||||
if (err) {
|
||||
root.showMenu({
|
||||
data: data,
|
||||
type: 'url'
|
||||
});
|
||||
return;
|
||||
}
|
||||
handlePayPro(details);
|
||||
|
|
@ -87,47 +113,75 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
|
|||
});
|
||||
// Plain Address
|
||||
} else if (bitcore.Address.isValid(data, 'livenet') || bitcore.Address.isValid(data, 'testnet')) {
|
||||
if($state.includes('tabs.scan')) {
|
||||
root.showMenu({data: data, type: 'bitcoinAddress'});
|
||||
if ($state.includes('tabs.scan')) {
|
||||
root.showMenu({
|
||||
data: data,
|
||||
type: 'bitcoinAddress'
|
||||
});
|
||||
} else {
|
||||
goToAmountPage(data);
|
||||
}
|
||||
} else if (data && data.indexOf($window.appConfig.name + '://glidera') === 0) {
|
||||
return $state.go('uriglidera', {url: data});
|
||||
return $state.go('uriglidera', {
|
||||
url: data
|
||||
});
|
||||
} else if (data && data.indexOf($window.appConfig.name + '://coinbase') === 0) {
|
||||
return $state.go('uricoinbase', {url: data});
|
||||
return $state.go('uricoinbase', {
|
||||
url: data
|
||||
});
|
||||
|
||||
// BitPayCard Authentication
|
||||
} else if (data && data.indexOf($window.appConfig.name + '://') === 0) {
|
||||
var secret = getParameterByName('secret', data);
|
||||
var email = getParameterByName('email', data);
|
||||
var otp = getParameterByName('otp', data);
|
||||
$state.go('tabs.home', {}, {'reload': true, 'notify': $state.current.name == 'tabs.home' ? false : true}).then(function() {
|
||||
$state.transitionTo('tabs.bitpayCardIntro', {
|
||||
secret: secret,
|
||||
email: email,
|
||||
otp: otp
|
||||
});
|
||||
var secret = getParameterByName('secret', data);
|
||||
var email = getParameterByName('email', data);
|
||||
var otp = getParameterByName('otp', data);
|
||||
$state.go('tabs.home', {}, {
|
||||
'reload': true,
|
||||
'notify': $state.current.name == 'tabs.home' ? false : true
|
||||
}).then(function() {
|
||||
$state.transitionTo('tabs.bitpayCardIntro', {
|
||||
secret: secret,
|
||||
email: email,
|
||||
otp: otp
|
||||
});
|
||||
return true;
|
||||
});
|
||||
return true;
|
||||
|
||||
// Join
|
||||
// Join
|
||||
} else if (data && data.match(/^copay:[0-9A-HJ-NP-Za-km-z]{70,80}$/)) {
|
||||
$state.go('tabs.home', {}, {'reload': true, 'notify': $state.current.name == 'tabs.home' ? false : true}).then(function() {
|
||||
$state.transitionTo('tabs.add.join', {url: data});
|
||||
$state.go('tabs.home', {}, {
|
||||
'reload': true,
|
||||
'notify': $state.current.name == 'tabs.home' ? false : true
|
||||
}).then(function() {
|
||||
$state.transitionTo('tabs.add.join', {
|
||||
url: data
|
||||
});
|
||||
});
|
||||
return true;
|
||||
|
||||
// Old join
|
||||
// Old join
|
||||
} else if (data && data.match(/^[0-9A-HJ-NP-Za-km-z]{70,80}$/)) {
|
||||
$state.go('tabs.home', {}, {'reload': true, 'notify': $state.current.name == 'tabs.home' ? false : true}).then(function() {
|
||||
$state.transitionTo('tabs.add.join', {url: data});
|
||||
$state.go('tabs.home', {}, {
|
||||
'reload': true,
|
||||
'notify': $state.current.name == 'tabs.home' ? false : true
|
||||
}).then(function() {
|
||||
$state.transitionTo('tabs.add.join', {
|
||||
url: data
|
||||
});
|
||||
});
|
||||
return true;
|
||||
} else if (data && (data.substring(0, 2) == '6P' || checkPrivateKey(data))) {
|
||||
root.showMenu({
|
||||
data: data,
|
||||
type: 'privateKey'
|
||||
});
|
||||
} else {
|
||||
|
||||
if($state.includes('tabs.scan')) {
|
||||
root.showMenu({data: data, type: 'text'});
|
||||
if ($state.includes('tabs.scan')) {
|
||||
root.showMenu({
|
||||
data: data,
|
||||
type: 'text'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -136,13 +190,18 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
|
|||
};
|
||||
|
||||
function goToAmountPage(toAddress) {
|
||||
$state.go('tabs.send', {}, {'reload': true, 'notify': $state.current.name == 'tabs.send' ? false : true});
|
||||
$state.go('tabs.send', {}, {
|
||||
'reload': true,
|
||||
'notify': $state.current.name == 'tabs.send' ? false : true
|
||||
});
|
||||
$timeout(function() {
|
||||
$state.transitionTo('tabs.send.amount', {toAddress: toAddress});
|
||||
$state.transitionTo('tabs.send.amount', {
|
||||
toAddress: toAddress
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function handlePayPro(payProDetails){
|
||||
function handlePayPro(payProDetails) {
|
||||
var stateParams = {
|
||||
toAmount: payProDetails.amount,
|
||||
toAddress: payProDetails.toAddress,
|
||||
|
|
@ -150,7 +209,10 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
|
|||
paypro: payProDetails
|
||||
};
|
||||
scannerService.pausePreview();
|
||||
$state.go('tabs.send', {}, {'reload': true, 'notify': $state.current.name == 'tabs.send' ? false : true}).then(function() {
|
||||
$state.go('tabs.send', {}, {
|
||||
'reload': true,
|
||||
'notify': $state.current.name == 'tabs.send' ? false : true
|
||||
}).then(function() {
|
||||
$timeout(function() {
|
||||
$state.transitionTo('tabs.send.confirm', stateParams);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.services')
|
||||
.factory('localStorageService', function(platformInfo, $timeout, $log) {
|
||||
.factory('localStorageService', function(platformInfo, $timeout, $log, lodash) {
|
||||
var isNW = platformInfo.isNW;
|
||||
var isChromeApp = platformInfo.isChromeApp;
|
||||
var root = {};
|
||||
|
|
@ -45,6 +45,14 @@ angular.module('copayApp.services')
|
|||
root.set = function(k, v, cb) {
|
||||
if (isChromeApp || isNW) {
|
||||
var obj = {};
|
||||
|
||||
if (lodash.isObject(v)) {
|
||||
v = JSON.stringify(v);
|
||||
}
|
||||
if (!lodash.isString(v)) {
|
||||
v = v.toString();
|
||||
}
|
||||
|
||||
obj[k] = v;
|
||||
|
||||
chrome.storage.local.set(obj, cb);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti
|
|||
'recreating': gettext('Recreating Wallet...'),
|
||||
'rejectTx': gettext('Rejecting payment proposal'),
|
||||
'removeTx': gettext('Deleting payment proposal'),
|
||||
'retrivingInputs': gettext('Retrieving inputs information'),
|
||||
'retrievingInputs': gettext('Retrieving inputs information'),
|
||||
'scanning': gettext('Scanning Wallet funds...'),
|
||||
'sendingTx': gettext('Sending transaction'),
|
||||
'signingTx': gettext('Signing transaction'),
|
||||
|
|
@ -33,6 +33,13 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti
|
|||
'validatingWallet': gettext('Validating wallet integrity...'),
|
||||
'validatingWords': gettext('Validating recovery phrase...'),
|
||||
'loadingTxInfo': gettext('Loading transaction info...'),
|
||||
'sendingFeedback': gettext('Sending feedback...'),
|
||||
'generatingNewAddress': gettext('Generating new address...'),
|
||||
'gettingAddresses': gettext('Getting addresses...'),
|
||||
'sendingByEmail': gettext('Preparing addresses...'),
|
||||
'sending2faCode': gettext('Sending 2FA code...'),
|
||||
'buyingBitcoin': gettext('Buying Bitcoin...'),
|
||||
'sellingBitcoin': gettext('Selling Bitcoin...')
|
||||
};
|
||||
|
||||
root.clear = function() {
|
||||
|
|
@ -64,7 +71,7 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti
|
|||
|
||||
var showName = $filter('translate')(processNames[name] || name);
|
||||
|
||||
if(customHandler) {
|
||||
if (customHandler) {
|
||||
customHandler(processName, showName, isOn);
|
||||
} else if (root.onGoingProcessName) {
|
||||
if (isCordova) {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ angular.module('copayApp.services').service('popupService', function($log, $ioni
|
|||
$ionicPopup.prompt({
|
||||
title: title,
|
||||
subTitle: message,
|
||||
inputType: opts.inputType,
|
||||
cssClass: opts.class,
|
||||
template: '<input ng-model="data.response" type="' + opts.inputType + '" autofocus>',
|
||||
inputPlaceholder: opts.inputPlaceholder,
|
||||
defaultText: opts.defaultText
|
||||
}).then(function(res) {
|
||||
|
|
@ -51,12 +52,12 @@ angular.module('copayApp.services').service('popupService', function($log, $ioni
|
|||
|
||||
var _cordovaConfirm = function(title, message, okText, cancelText, cb) {
|
||||
var onConfirm = function(buttonIndex) {
|
||||
if (buttonIndex == 1) return cb(true);
|
||||
if (buttonIndex == 2) return cb(true);
|
||||
else return cb(false);
|
||||
}
|
||||
okText = okText || gettextCatalog.getString('OK');
|
||||
cancelText = cancelText || gettextCatalog.getString('Cancel');
|
||||
navigator.notification.confirm(message, onConfirm, title, [okText, cancelText]);
|
||||
navigator.notification.confirm(message, onConfirm, title, [cancelText, okText]);
|
||||
};
|
||||
|
||||
var _cordovaPrompt = function(title, message, opts, cb) {
|
||||
|
|
@ -118,7 +119,7 @@ angular.module('copayApp.services').service('popupService', function($log, $ioni
|
|||
this.showPrompt = function(title, message, opts, cb) {
|
||||
$log.warn(title ? (title + ': ' + message) : message);
|
||||
|
||||
opts = opts || {};
|
||||
opts = opts || {};
|
||||
|
||||
if (isCordova && !opts.forceHTMLPrompt)
|
||||
_cordovaPrompt(title, message, opts, cb);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
angular.module('copayApp.services')
|
||||
.factory('profileService', function profileServiceFactory($rootScope, $timeout, $filter, $log, sjcl, lodash, storageService, bwcService, configService, pushNotificationsService, gettext, gettextCatalog, bwcError, uxLanguage, platformInfo, txFormatService, $state) {
|
||||
.factory('profileService', function profileServiceFactory($rootScope, $timeout, $filter, $log, sjcl, lodash, storageService, bwcService, configService, pushNotificationsService, gettextCatalog, bwcError, uxLanguage, platformInfo, txFormatService, $state) {
|
||||
|
||||
|
||||
var isChromeApp = platformInfo.isChromeApp;
|
||||
|
|
@ -361,14 +361,14 @@ angular.module('copayApp.services')
|
|||
|
||||
} catch (ex) {
|
||||
$log.info(ex);
|
||||
return cb(gettext('Could not create: Invalid wallet recovery phrase'));
|
||||
return cb(gettextCatalog.getString('Could not create: Invalid wallet recovery phrase'));
|
||||
}
|
||||
} else if (opts.extendedPrivateKey) {
|
||||
try {
|
||||
walletClient.seedFromExtendedPrivateKey(opts.extendedPrivateKey);
|
||||
} catch (ex) {
|
||||
$log.warn(ex);
|
||||
return cb(gettext('Could not create using the specified extended private key'));
|
||||
return cb(gettextCatalog.getString('Could not create using the specified extended private key'));
|
||||
}
|
||||
} else if (opts.extendedPublicKey) {
|
||||
try {
|
||||
|
|
@ -378,7 +378,7 @@ angular.module('copayApp.services')
|
|||
});
|
||||
} catch (ex) {
|
||||
$log.warn("Creating wallet from Extended Public Key Arg:", ex, opts);
|
||||
return cb(gettext('Could not create using the specified extended public key'));
|
||||
return cb(gettextCatalog.getString('Could not create using the specified extended public key'));
|
||||
}
|
||||
} else {
|
||||
var lang = uxLanguage.getCurrentLanguage();
|
||||
|
|
@ -421,7 +421,7 @@ angular.module('copayApp.services')
|
|||
singleAddress: opts.singleAddress,
|
||||
walletPrivKey: opts.walletPrivKey,
|
||||
}, function(err, secret) {
|
||||
if (err) return bwcError.cb(err, gettext('Error creating wallet'), cb);
|
||||
if (err) return bwcError.cb(err, gettextCatalog.getString('Error creating wallet'), cb);
|
||||
return cb(null, walletClient, secret);
|
||||
});
|
||||
});
|
||||
|
|
@ -451,11 +451,11 @@ angular.module('copayApp.services')
|
|||
if (lodash.find(root.profile.credentials, {
|
||||
'walletId': walletData.walletId
|
||||
})) {
|
||||
return cb(gettext('Cannot join the same wallet more that once'));
|
||||
return cb(gettextCatalog.getString('Cannot join the same wallet more that once'));
|
||||
}
|
||||
} catch (ex) {
|
||||
$log.debug(ex);
|
||||
return cb(gettext('Bad wallet invitation'));
|
||||
return cb(gettextCatalog.getString('Bad wallet invitation'));
|
||||
}
|
||||
opts.networkName = walletData.network;
|
||||
$log.debug('Joining Wallet:', opts);
|
||||
|
|
@ -464,7 +464,7 @@ angular.module('copayApp.services')
|
|||
if (err) return cb(err);
|
||||
|
||||
walletClient.joinWallet(opts.secret, opts.myName || 'me', {}, function(err) {
|
||||
if (err) return bwcError.cb(err, gettext('Could not join wallet'), cb);
|
||||
if (err) return bwcError.cb(err, gettextCatalog.getString('Could not join wallet'), cb);
|
||||
addAndBindWalletClient(walletClient, {
|
||||
bwsurl: opts.bwsurl
|
||||
}, cb);
|
||||
|
|
@ -521,12 +521,12 @@ angular.module('copayApp.services')
|
|||
// Adds and bind a new client to the profile
|
||||
var addAndBindWalletClient = function(client, opts, cb) {
|
||||
if (!client || !client.credentials)
|
||||
return cb(gettext('Could not access wallet'));
|
||||
return cb(gettextCatalog.getString('Could not access wallet'));
|
||||
|
||||
var walletId = client.credentials.walletId
|
||||
|
||||
if (!root.profile.addWallet(JSON.parse(client.export())))
|
||||
return cb(gettext('Wallet already in Copay'));
|
||||
return cb(gettextCatalog.getString('Wallet already in Copay'));
|
||||
|
||||
|
||||
var skipKeyValidation = root.profile.isChecked(platformInfo.ua, walletId);
|
||||
|
|
@ -595,15 +595,7 @@ angular.module('copayApp.services')
|
|||
password: opts.password
|
||||
});
|
||||
} catch (err) {
|
||||
return cb(gettext('Could not import. Check input file and spending password'));
|
||||
}
|
||||
|
||||
if (walletClient.hasPrivKeyEncrypted()) {
|
||||
try {
|
||||
walletClient.disablePrivateKeyEncryption();
|
||||
} catch (e) {
|
||||
$log.warn(e);
|
||||
}
|
||||
return cb(gettextCatalog.getString('Could not import. Check input file and spending password'));
|
||||
}
|
||||
|
||||
str = JSON.parse(str);
|
||||
|
|
@ -634,7 +626,7 @@ angular.module('copayApp.services')
|
|||
if (err instanceof errors.NOT_AUTHORIZED)
|
||||
return cb(err);
|
||||
|
||||
return bwcError.cb(err, gettext('Could not import'), cb);
|
||||
return bwcError.cb(err, gettextCatalog.getString('Could not import'), cb);
|
||||
}
|
||||
|
||||
addAndBindWalletClient(walletClient, {
|
||||
|
|
@ -665,7 +657,7 @@ angular.module('copayApp.services')
|
|||
if (err instanceof errors.NOT_AUTHORIZED)
|
||||
return cb(err);
|
||||
|
||||
return bwcError.cb(err, gettext('Could not import'), cb);
|
||||
return bwcError.cb(err, gettextCatalog.getString('Could not import'), cb);
|
||||
}
|
||||
|
||||
addAndBindWalletClient(walletClient, {
|
||||
|
|
@ -688,7 +680,7 @@ angular.module('copayApp.services')
|
|||
if (err instanceof errors.NOT_AUTHORIZED)
|
||||
err.name = 'WALLET_DOES_NOT_EXIST';
|
||||
|
||||
return bwcError.cb(err, gettext('Could not import'), cb);
|
||||
return bwcError.cb(err, gettextCatalog.getString('Could not import'), cb);
|
||||
}
|
||||
|
||||
addAndBindWalletClient(walletClient, {
|
||||
|
|
@ -773,6 +765,12 @@ angular.module('copayApp.services')
|
|||
});
|
||||
}
|
||||
|
||||
if (opts.m) {
|
||||
ret = lodash.filter(ret, function(w) {
|
||||
return (w.credentials.m == opts.m);
|
||||
});
|
||||
}
|
||||
|
||||
if (opts.onlyComplete) {
|
||||
ret = lodash.filter(ret, function(w) {
|
||||
return w.isComplete();
|
||||
|
|
@ -795,7 +793,7 @@ angular.module('copayApp.services')
|
|||
root.getNotifications = function(opts, cb) {
|
||||
opts = opts || {};
|
||||
|
||||
var TIME_STAMP = 60 * 60 * 24 * 7;
|
||||
var TIME_STAMP = 60 * 60 * 6;
|
||||
var MAX = 100;
|
||||
|
||||
var typeFilter = {
|
||||
|
|
@ -861,26 +859,25 @@ angular.module('copayApp.services')
|
|||
|
||||
var finale = shown; // GROUPING DISABLED!
|
||||
|
||||
// var finale = [],
|
||||
// prev;
|
||||
//
|
||||
//
|
||||
// // Item grouping... DISABLED.
|
||||
//
|
||||
// // REMOVE (if we want 1-to-1 notification) ????
|
||||
// lodash.each(shown, function(x) {
|
||||
// if (prev && prev.walletId === x.walletId && prev.txpId && prev.txpId === x.txpId && prev.creatorId && prev.creatorId === x.creatorId) {
|
||||
// prev.types.push(x.type);
|
||||
// prev.data = lodash.assign(prev.data, x.data);
|
||||
// prev.txid = prev.txid || x.txid;
|
||||
// prev.amountStr = prev.amountStr || x.amountStr;
|
||||
// prev.creatorName = prev.creatorName || x.creatorName;
|
||||
// } else {
|
||||
// finale.push(x);
|
||||
// prev = x;
|
||||
// }
|
||||
// });
|
||||
//
|
||||
var finale = [],
|
||||
prev;
|
||||
|
||||
|
||||
// Item grouping... DISABLED.
|
||||
|
||||
// REMOVE (if we want 1-to-1 notification) ????
|
||||
lodash.each(shown, function(x) {
|
||||
if (prev && prev.walletId === x.walletId && prev.txpId && prev.txpId === x.txpId && prev.creatorId && prev.creatorId === x.creatorId) {
|
||||
prev.types.push(x.type);
|
||||
prev.data = lodash.assign(prev.data, x.data);
|
||||
prev.txid = prev.txid || x.txid;
|
||||
prev.amountStr = prev.amountStr || x.amountStr;
|
||||
prev.creatorName = prev.creatorName || x.creatorName;
|
||||
} else {
|
||||
finale.push(x);
|
||||
prev = x;
|
||||
}
|
||||
});
|
||||
|
||||
var u = bwcService.getUtils();
|
||||
lodash.each(finale, function(x) {
|
||||
|
|
|
|||
|
|
@ -111,18 +111,24 @@ RateService.prototype.fromFiat = function(amount, code) {
|
|||
return amount / this.getRate(code) * this.BTC_TO_SAT;
|
||||
};
|
||||
|
||||
RateService.prototype.listAlternatives = function() {
|
||||
RateService.prototype.listAlternatives = function(sort) {
|
||||
var self = this;
|
||||
if (!this.isAvailable()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return self.lodash.map(this.getAlternatives(), function(item) {
|
||||
var alternatives = self.lodash.map(this.getAlternatives(), function(item) {
|
||||
return {
|
||||
name: item.name,
|
||||
isoCode: item.isoCode
|
||||
}
|
||||
});
|
||||
if (sort) {
|
||||
alternatives.sort(function(a, b) {
|
||||
return a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1;
|
||||
});
|
||||
}
|
||||
return self.lodash.uniq(alternatives, 'isoCode');
|
||||
};
|
||||
|
||||
angular.module('copayApp.services').factory('rateService', function($http, lodash) {
|
||||
|
|
|
|||
|
|
@ -77,23 +77,23 @@ angular.module('copayApp.services')
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// UPGRADING STORAGE
|
||||
//
|
||||
//
|
||||
// 1. Write a function to upgrade the desired storage key(s). The function should have the protocol:
|
||||
//
|
||||
//
|
||||
// _upgrade_x(key, network, cb), where:
|
||||
//
|
||||
//
|
||||
// `x` is the name of the storage key
|
||||
// `key` is the name of the storage key being upgraded
|
||||
// `key` is the name of the storage key being upgraded
|
||||
// `network` is one of 'livenet', 'testnet'
|
||||
//
|
||||
// 2. Add the storage key to `_upgraders` object using the name of the key as the `_upgrader` object key
|
||||
// with the value being the name of the upgrade function (e.g., _upgrade_x). In order to avoid conflicts
|
||||
// when a storage key is involved in multiple upgraders as well as predicte the order in which upgrades
|
||||
// occur the `_upgrader` object key should be prefixed with '##_' (e.g., '01_') to create a unique and
|
||||
// occur the `_upgrader` object key should be prefixed with '##_' (e.g., '01_') to create a unique and
|
||||
// sortable name. This format is interpreted by the _upgrade() function.
|
||||
//
|
||||
//
|
||||
// Upgraders are executed in numerical order per the '##_' object key prefix.
|
||||
//
|
||||
//
|
||||
var _upgraders = {
|
||||
'00_bitpayDebitCards' : _upgrade_bitpayDebitCards, // 2016-11: Upgrade bitpayDebitCards-x to bitpayAccounts-x
|
||||
'01_bitpayCardCredentials' : _upgrade_bitpayCardCredentials // 2016-11: Upgrade bitpayCardCredentials-x to appIdentity-x
|
||||
|
|
@ -244,6 +244,14 @@ angular.module('copayApp.services')
|
|||
storage.remove('profile', cb);
|
||||
};
|
||||
|
||||
root.setFeedbackInfo = function(feedbackValues, cb) {
|
||||
storage.set('feedback', feedbackValues, cb);
|
||||
};
|
||||
|
||||
root.getFeedbackInfo = function(cb) {
|
||||
storage.get('feedback', cb);
|
||||
};
|
||||
|
||||
root.storeFocusedWalletId = function(id, cb) {
|
||||
storage.set('focusedWalletId', id || '', cb);
|
||||
};
|
||||
|
|
@ -390,6 +398,14 @@ angular.module('copayApp.services')
|
|||
storage.remove('nextStep-' + service, cb);
|
||||
};
|
||||
|
||||
root.setLastCurrencyUsed = function(lastCurrencyUsed, cb) {
|
||||
storage.set('lastCurrencyUsed', lastCurrencyUsed, cb)
|
||||
};
|
||||
|
||||
root.getLastCurrencyUsed = function(cb) {
|
||||
storage.get('lastCurrencyUsed', cb)
|
||||
};
|
||||
|
||||
root.checkQuota = function() {
|
||||
var block = '';
|
||||
// 50MB
|
||||
|
|
@ -459,7 +475,10 @@ angular.module('copayApp.services')
|
|||
if (lodash.isEmpty(data) || !data.email) return cb('No card(s) to set');
|
||||
storage.get('bitpayAccounts-' + network, function(err, bitpayAccounts) {
|
||||
if (err) return cb(err);
|
||||
bitpayAccounts = JSON.parse(bitpayAccounts) || {};
|
||||
if (lodash.isString(bitpayAccounts)) {
|
||||
bitpayAccounts = JSON.parse(bitpayAccounts);
|
||||
}
|
||||
bitpayAccounts = bitpayAccounts || {};
|
||||
bitpayAccounts[data.email] = bitpayAccounts[data.email] || {};
|
||||
bitpayAccounts[data.email]['bitpayDebitCards-' + network] = data;
|
||||
storage.set('bitpayAccounts-' + network, JSON.stringify(bitpayAccounts), cb);
|
||||
|
|
@ -468,7 +487,10 @@ angular.module('copayApp.services')
|
|||
|
||||
root.getBitpayDebitCards = function(network, cb) {
|
||||
storage.get('bitpayAccounts-' + network, function(err, bitpayAccounts) {
|
||||
bitpayAccounts = JSON.parse(bitpayAccounts) || {};
|
||||
if (lodash.isString(bitpayAccounts)) {
|
||||
bitpayAccounts = JSON.parse(bitpayAccounts);
|
||||
}
|
||||
bitpayAccounts = bitpayAccounts || {};
|
||||
var cards = [];
|
||||
Object.keys(bitpayAccounts).forEach(function(email) {
|
||||
// For the UI, add the account email to the card object.
|
||||
|
|
@ -490,15 +512,20 @@ angular.module('copayApp.services')
|
|||
if (lodash.isEmpty(card) || !card.eid) return cb('No card to remove');
|
||||
storage.get('bitpayAccounts-' + network, function(err, bitpayAccounts) {
|
||||
if (err) cb(err);
|
||||
bitpayAccounts = JSON.parse(bitpayAccounts) || {};
|
||||
if (lodash.isString(bitpayAccounts)) {
|
||||
bitpayAccounts = JSON.parse(bitpayAccounts);
|
||||
}
|
||||
bitpayAccounts = bitpayAccounts || {};
|
||||
Object.keys(bitpayAccounts).forEach(function(userId) {
|
||||
var data = bitpayAccounts[userId]['bitpayDebitCards-' + network];
|
||||
var newCards = lodash.reject(data.cards, {'eid': card.eid});
|
||||
var newCards = lodash.reject(data.cards, {
|
||||
'eid': card.eid
|
||||
});
|
||||
data.cards = newCards;
|
||||
root.setBitpayDebitCards(network, data, function(err) {
|
||||
if (err) cb(err);
|
||||
// If there are no more cards in storage then re-enable the next step entry.
|
||||
root.getBitpayDebitCards(network, function(err, cards){
|
||||
root.getBitpayDebitCards(network, function(err, cards) {
|
||||
if (err) cb(err);
|
||||
if (cards.length == 0) {
|
||||
root.removeNextStep('BitpayCard', cb);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.services')
|
||||
.factory('trezor', function($log, $timeout, gettext, lodash, bitcore, hwWallet) {
|
||||
.factory('trezor', function($log, $timeout, lodash, bitcore, hwWallet) {
|
||||
var root = {};
|
||||
|
||||
var SETTLE_TIME = 3000;
|
||||
|
|
@ -82,7 +82,7 @@ angular.module('copayApp.services')
|
|||
if (txp.outputs.length > 1)
|
||||
return callback('Only single output TXPs are supported in TREZOR');
|
||||
} else {
|
||||
return callback('Unknown TXP at TREZOR');
|
||||
return callback('Unknown TXP at TREZOR');
|
||||
}
|
||||
|
||||
if (txp.outputs) {
|
||||
|
|
|
|||
|
|
@ -8,42 +8,39 @@ angular.module('copayApp.services')
|
|||
root.availableLanguages = [{
|
||||
name: 'English',
|
||||
isoCode: 'en',
|
||||
}, {
|
||||
name: 'Český',
|
||||
isoCode: 'cs',
|
||||
}, {
|
||||
name: 'Français',
|
||||
isoCode: 'fr',
|
||||
}, {
|
||||
name: 'Italiano',
|
||||
isoCode: 'it',
|
||||
}, {
|
||||
name: 'Deutsch',
|
||||
isoCode: 'de',
|
||||
}, {
|
||||
name: 'Español',
|
||||
isoCode: 'es',
|
||||
}, {
|
||||
name: '日本語',
|
||||
isoCode: 'ja',
|
||||
useIdeograms: true,
|
||||
}, {
|
||||
name: '中文(简体)',
|
||||
isoCode: 'zh',
|
||||
useIdeograms: true,
|
||||
}, {
|
||||
name: 'Polski',
|
||||
isoCode: 'pl',
|
||||
}, {
|
||||
name: 'Pусский',
|
||||
isoCode: 'ru',
|
||||
name: 'Français',
|
||||
isoCode: 'fr',
|
||||
// }, {
|
||||
// name: 'Český',
|
||||
// isoCode: 'cs',
|
||||
// }, {
|
||||
// name: 'Italiano',
|
||||
// isoCode: 'it',
|
||||
// }, {
|
||||
// name: 'Deutsch',
|
||||
// isoCode: 'de',
|
||||
// }, {
|
||||
// name: '日本語',
|
||||
// isoCode: 'ja',
|
||||
// useIdeograms: true,
|
||||
// }, {
|
||||
// name: '中文(简体)',
|
||||
// isoCode: 'zh',
|
||||
// useIdeograms: true,
|
||||
// }, {
|
||||
// name: 'Polski',
|
||||
// isoCode: 'pl',
|
||||
// }, {
|
||||
// name: 'Pусский',
|
||||
// isoCode: 'ru',
|
||||
}];
|
||||
|
||||
|
||||
root._detect = function(cb) {
|
||||
|
||||
return cb('en'); //disable auto detection for release;
|
||||
|
||||
var userLang, androidLang;
|
||||
if (navigator && navigator.globalization) {
|
||||
|
||||
|
|
|
|||
|
|
@ -29,16 +29,6 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
});
|
||||
};
|
||||
|
||||
// // RECEIVE
|
||||
// // Check address
|
||||
// root.isUsed(wallet.walletId, balance.byAddress, function(err, used) {
|
||||
// if (used) {
|
||||
// $log.debug('Address used. Creating new');
|
||||
// $rootScope.$emit('Local/AddressIsUsed');
|
||||
// }
|
||||
// });
|
||||
//
|
||||
|
||||
var _signWithLedger = function(wallet, txp, cb) {
|
||||
$log.info('Requesting Ledger Chrome app to sign the transaction');
|
||||
|
||||
|
|
@ -67,32 +57,6 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
});
|
||||
};
|
||||
|
||||
// TODO
|
||||
// This handles errors from BWS/index which normally
|
||||
// trigger from async events (like updates).
|
||||
// Debounce function avoids multiple popups
|
||||
var _handleError = function(err) {
|
||||
$log.warn('wallet ERROR: ', err);
|
||||
|
||||
$log.warn('TODO');
|
||||
return; // TODO!!!
|
||||
if (err instanceof errors.NOT_AUTHORIZED) {
|
||||
|
||||
console.log('[walletService.js.93] TODO NOT AUTH'); //TODO
|
||||
// TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO
|
||||
wallet.notAuthorized = true;
|
||||
$state.go('tabs.home');
|
||||
} else if (err instanceof errors.NOT_FOUND) {
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Could not access Wallet Service: Not found'));
|
||||
} else {
|
||||
var msg = ""
|
||||
$rootScope.$emit('Local/ClientError', (err.error ? err.error : err));
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err, gettextCatalog.getString('Error at Wallet Service')));
|
||||
}
|
||||
};
|
||||
root.handleError = lodash.debounce(_handleError, 1000);
|
||||
|
||||
|
||||
root.invalidateCache = function(wallet) {
|
||||
if (wallet.cachedStatus)
|
||||
wallet.cachedStatus.isValid = false;
|
||||
|
|
@ -180,8 +144,9 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
if (err instanceof errors.NOT_AUTHORIZED) {
|
||||
return cb('WALLET_NOT_REGISTERED');
|
||||
}
|
||||
return cb(bwcError.msg(err, gettext('Could not update Wallet')));
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
return cb(null, ret);
|
||||
});
|
||||
};
|
||||
|
|
@ -196,19 +161,22 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
// Address with Balance
|
||||
cache.balanceByAddress = balance.byAddress;
|
||||
|
||||
// Total wallet balance is same regardless of 'spend unconfirmed funds' setting.
|
||||
cache.totalBalanceSat = balance.totalAmount;
|
||||
|
||||
// Spend unconfirmed funds
|
||||
if (config.spendUnconfirmed) {
|
||||
cache.totalBalanceSat = balance.totalAmount;
|
||||
cache.lockedBalanceSat = balance.lockedAmount;
|
||||
cache.availableBalanceSat = balance.availableAmount;
|
||||
cache.totalBytesToSendMax = balance.totalBytesToSendMax;
|
||||
cache.pendingAmount = null;
|
||||
cache.pendingAmount = 0;
|
||||
cache.spendableAmount = balance.totalAmount - balance.lockedAmount;
|
||||
} else {
|
||||
cache.totalBalanceSat = balance.totalConfirmedAmount;
|
||||
cache.lockedBalanceSat = balance.lockedConfirmedAmount;
|
||||
cache.availableBalanceSat = balance.availableConfirmedAmount;
|
||||
cache.totalBytesToSendMax = balance.totalBytesToSendConfirmedMax;
|
||||
cache.pendingAmount = balance.totalAmount - balance.totalConfirmedAmount;
|
||||
cache.spendableAmount = balance.totalConfirmedAmount - balance.lockedAmount;
|
||||
}
|
||||
|
||||
// Selected unit
|
||||
|
|
@ -220,25 +188,35 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
cache.totalBalanceStr = txFormatService.formatAmount(cache.totalBalanceSat) + ' ' + cache.unitName;
|
||||
cache.lockedBalanceStr = txFormatService.formatAmount(cache.lockedBalanceSat) + ' ' + cache.unitName;
|
||||
cache.availableBalanceStr = txFormatService.formatAmount(cache.availableBalanceSat) + ' ' + cache.unitName;
|
||||
cache.pendingBalanceStr = txFormatService.formatAmount(cache.totalBalanceSat + (cache.pendingAmount === null? 0 : cache.pendingAmount)) + ' ' + cache.unitName;
|
||||
|
||||
if (cache.pendingAmount !== null && cache.pendingAmount !== 0) {
|
||||
cache.pendingAmountStr = txFormatService.formatAmount(cache.pendingAmount) + ' ' + cache.unitName;
|
||||
} else {
|
||||
cache.pendingAmountStr = null;
|
||||
}
|
||||
cache.spendableBalanceStr = txFormatService.formatAmount(cache.spendableAmount) + ' ' + cache.unitName;
|
||||
cache.pendingBalanceStr = txFormatService.formatAmount(cache.pendingAmount) + ' ' + cache.unitName;
|
||||
|
||||
cache.alternativeName = config.settings.alternativeName;
|
||||
cache.alternativeIsoCode = config.settings.alternativeIsoCode;
|
||||
|
||||
// Check address
|
||||
root.isAddressUsed(wallet, balance.byAddress, function(err, used) {
|
||||
if (used) {
|
||||
$log.debug('Address used. Creating new');
|
||||
// Force new address
|
||||
root.getAddress(wallet, true, function(err, addr) {
|
||||
$log.debug('New address: ', addr);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
rateService.whenAvailable(function() {
|
||||
|
||||
var totalBalanceAlternative = rateService.toFiat(cache.totalBalanceSat, cache.alternativeIsoCode);
|
||||
var pendingBalanceAlternative = rateService.toFiat(cache.pendingAmount, cache.alternativeIsoCode);
|
||||
var lockedBalanceAlternative = rateService.toFiat(cache.lockedBalanceSat, cache.alternativeIsoCode);
|
||||
var spendableBalanceAlternative = rateService.toFiat(cache.spendableAmount, cache.alternativeIsoCode);
|
||||
var alternativeConversionRate = rateService.toFiat(100000000, cache.alternativeIsoCode);
|
||||
|
||||
cache.totalBalanceAlternative = $filter('formatFiatAmount')(totalBalanceAlternative);
|
||||
cache.pendingBalanceAlternative = $filter('formatFiatAmount')(pendingBalanceAlternative);
|
||||
cache.lockedBalanceAlternative = $filter('formatFiatAmount')(lockedBalanceAlternative);
|
||||
cache.spendableBalanceAlternative = $filter('formatFiatAmount')(spendableBalanceAlternative);
|
||||
cache.alternativeConversionRate = $filter('formatFiatAmount')(alternativeConversionRate);
|
||||
|
||||
cache.alternativeBalanceAvailable = true;
|
||||
|
|
@ -337,7 +315,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
return tx.txid != endingTxid;
|
||||
});
|
||||
|
||||
return cb(null, res, res.length == limit);
|
||||
return cb(null, res, res.length >= limit);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -428,7 +406,16 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
|
||||
function getNewTxs(newTxs, skip, cb) {
|
||||
getTxsFromServer(wallet, skip, endingTxid, requestLimit, function(err, res, shouldContinue) {
|
||||
if (err) return cb(err);
|
||||
if (err) {
|
||||
$log.warn(bwcError.msg(err, 'BWS Error')); //TODO
|
||||
if (err instanceof errors.CONNECTION_ERROR || (err.message && err.message.match(/5../))) {
|
||||
log.info('Retrying history download in 5 secs...');
|
||||
return $timeout(function() {
|
||||
return getNewTxs(newTxs, skip, cb);
|
||||
}, 5000);
|
||||
};
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
newTxs = newTxs.concat(processNewTxs(wallet, lodash.compact(res)));
|
||||
|
||||
|
|
@ -587,20 +574,13 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
if (lodash.isEmpty(txp) || lodash.isEmpty(wallet))
|
||||
return cb('MISSING_PARAMETER');
|
||||
|
||||
if (txp.sendMax) {
|
||||
wallet.createTxProposal(txp, function(err, createdTxp) {
|
||||
if (err) return cb(err);
|
||||
else return cb(null, createdTxp);
|
||||
});
|
||||
} else {
|
||||
wallet.createTxProposal(txp, function(err, createdTxp) {
|
||||
if (err) return cb(err);
|
||||
else {
|
||||
$log.debug('Transaction created');
|
||||
return cb(null, createdTxp);
|
||||
}
|
||||
});
|
||||
}
|
||||
wallet.createTxProposal(txp, function(err, createdTxp) {
|
||||
if (err) return cb(err);
|
||||
else {
|
||||
$log.debug('Transaction created');
|
||||
return cb(null, createdTxp);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
root.publishTx = function(wallet, txp, cb) {
|
||||
|
|
@ -760,12 +740,13 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
});
|
||||
};
|
||||
|
||||
root.isUsed = function(wallet, byAddress, cb) {
|
||||
// Check address
|
||||
root.isAddressUsed = function(wallet, byAddress, cb) {
|
||||
storageService.getLastAddress(wallet.id, function(err, addr) {
|
||||
var used = lodash.find(byAddress, {
|
||||
address: addr
|
||||
});
|
||||
return cb(null, used);
|
||||
return cb(err, used);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -797,13 +778,30 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
});
|
||||
};
|
||||
|
||||
root.getAddress = function(wallet, forceNew, cb) {
|
||||
root.getMainAddresses = function(wallet, opts, cb) {
|
||||
opts = opts || {};
|
||||
opts.reverse = true;
|
||||
wallet.getMainAddresses(opts, function(err, addresses) {
|
||||
return cb(err, addresses);
|
||||
});
|
||||
};
|
||||
|
||||
root.getBalance = function(wallet, opts, cb) {
|
||||
opts = opts || {};
|
||||
wallet.getBalance(opts, function(err, resp) {
|
||||
return cb(err, resp);
|
||||
});
|
||||
};
|
||||
|
||||
root.getAddress = function(wallet, forceNew, cb) {
|
||||
storageService.getLastAddress(wallet.id, function(err, addr) {
|
||||
if (err) return cb(err);
|
||||
|
||||
if (!forceNew && addr) return cb(null, addr);
|
||||
|
||||
if (!wallet.isComplete())
|
||||
return cb('WALLET_NOT_COMPLETE');
|
||||
|
||||
createAddress(wallet, function(err, _addr) {
|
||||
if (err) return cb(err, addr);
|
||||
storageService.storeLastAddress(wallet.id, _addr, function() {
|
||||
|
|
@ -829,7 +827,8 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
var askPassword = function(name, title, cb) {
|
||||
var opts = {
|
||||
inputType: 'password',
|
||||
forceHTMLPrompt: true
|
||||
forceHTMLPrompt: true,
|
||||
class: 'text-warn'
|
||||
};
|
||||
popupService.showPrompt(title, name, opts, function(res) {
|
||||
if (!res) return cb();
|
||||
|
|
@ -839,9 +838,12 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
|
||||
|
||||
root.encrypt = function(wallet, cb) {
|
||||
askPassword(wallet.name, gettext('Enter new spending password'), function(password) {
|
||||
var title = gettextCatalog.getString('Enter new spending password');
|
||||
var warnMsg = gettextCatalog.getString('Your wallet key will be encrypted. The Spending Password cannot be recovered. Be sure to write it down.');
|
||||
askPassword(warnMsg, title, function(password) {
|
||||
if (!password) return cb('no password');
|
||||
askPassword(wallet.name, gettext('Confirm you new spending password'), function(password2) {
|
||||
title = gettextCatalog.getString('Confirm you new spending password');
|
||||
askPassword(warnMsg, gettextCatalog.getString('Confirm you new spending password'), function(password2) {
|
||||
if (!password2 || password != password2)
|
||||
return cb('password mismatch');
|
||||
|
||||
|
|
@ -854,7 +856,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
|
||||
root.decrypt = function(wallet, cb) {
|
||||
$log.debug('Disabling private key encryption for' + wallet.name);
|
||||
askPassword(wallet.name, gettext('Enter Spending Password'), function(password) {
|
||||
askPassword(null, gettextCatalog.getString('Enter Spending Password'), function(password) {
|
||||
if (!password) return cb('no password');
|
||||
|
||||
try {
|
||||
|
|
@ -869,7 +871,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
root.handleEncryptedWallet = function(wallet, cb) {
|
||||
if (!root.isEncrypted(wallet)) return cb();
|
||||
|
||||
askPassword(wallet.name, gettext('Enter Spending Password'), function(password) {
|
||||
askPassword(wallet.name, gettextCatalog.getString('Enter Spending Password'), function(password) {
|
||||
if (!password) return cb('No password');
|
||||
if (!wallet.checkPassword(password)) return cb('Wrong password');
|
||||
|
||||
|
|
@ -892,20 +894,14 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
};
|
||||
|
||||
|
||||
root.onlyPublish = function(wallet, txp, cb) {
|
||||
ongoingProcess.set('sendingTx', true);
|
||||
root.onlyPublish = function(wallet, txp, cb, customStatusHandler) {
|
||||
ongoingProcess.set('sendingTx', true, customStatusHandler);
|
||||
root.publishTx(wallet, txp, function(err, publishedTxp) {
|
||||
root.invalidateCache(wallet);
|
||||
|
||||
ongoingProcess.set('sendingTx', false);
|
||||
if (err) return cb(err);
|
||||
|
||||
var type = root.getViewStatus(wallet, createdTxp);
|
||||
root.openStatusModal(type, createdTxp, function() {
|
||||
$rootScope.$emit('Local/TxAction', wallet.id);
|
||||
return;
|
||||
});
|
||||
return cb(null, publishedTxp);
|
||||
ongoingProcess.set('sendingTx', false, customStatusHandler);
|
||||
if (err) return cb(bwcError.msg(err));
|
||||
$rootScope.$emit('Local/TxAction', wallet.id);
|
||||
return cb();
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -934,13 +930,13 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
}
|
||||
|
||||
root.prepare(wallet, function(err, password) {
|
||||
if (err) return cb('Prepare error: ' + err);
|
||||
if (err) return cb(bwcError.msg(err));
|
||||
|
||||
ongoingProcess.set('sendingTx', true, customStatusHandler);
|
||||
|
||||
publishFn(wallet, txp, function(err, publishedTxp) {
|
||||
ongoingProcess.set('sendingTx', false, customStatusHandler);
|
||||
if (err) return cb('Send Error: ' + err);
|
||||
if (err) return cb(bwcError.msg(err));
|
||||
|
||||
ongoingProcess.set('signingTx', true, customStatusHandler);
|
||||
root.signTx(wallet, publishedTxp, password, function(err, signedTxp) {
|
||||
|
|
@ -950,10 +946,9 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
|
||||
if (err) {
|
||||
$log.warn('sign error:' + err);
|
||||
// TODO?
|
||||
var msg = err.message ?
|
||||
var msg = err && err.message ?
|
||||
err.message :
|
||||
gettext('The payment was created but could not be completed. Please try again from home screen');
|
||||
gettextCatalog.getString('The payment was created but could not be completed. Please try again from home screen');
|
||||
|
||||
$rootScope.$emit('Local/TxAction', wallet.id);
|
||||
return cb(msg);
|
||||
|
|
@ -963,7 +958,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
ongoingProcess.set('broadcastingTx', true, customStatusHandler);
|
||||
root.broadcastTx(wallet, signedTxp, function(err, broadcastedTxp) {
|
||||
ongoingProcess.set('broadcastingTx', false, customStatusHandler);
|
||||
if (err) return cb('sign error' + err);
|
||||
if (err) return cb(bwcError.msg(err));
|
||||
|
||||
$rootScope.$emit('Local/TxAction', wallet.id);
|
||||
var type = root.getViewStatus(wallet, broadcastedTxp);
|
||||
|
|
@ -1090,6 +1085,12 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
return type;
|
||||
};
|
||||
|
||||
root.getSendMaxInfo = function(wallet, opts, cb) {
|
||||
opts = opts || {};
|
||||
wallet.getSendMaxInfo(opts, function(err, res) {
|
||||
return cb(err, res);
|
||||
});
|
||||
};
|
||||
|
||||
return root;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -19,8 +19,7 @@ $button-secondary-border: transparent;
|
|||
$button-secondary-active-bg: darken($subtle-gray, 5%);
|
||||
$button-secondary-active-border: transparent;
|
||||
|
||||
%button-standard,
|
||||
click-to-accept {
|
||||
%button-standard {
|
||||
width: 85%;
|
||||
max-width: 300px;
|
||||
margin-left: auto;
|
||||
|
|
|
|||
|
|
@ -6,9 +6,6 @@
|
|||
/* Ionic Overrides and Workarounds */
|
||||
// Please include a description of the problem solved by the workaround.
|
||||
|
||||
// class to dynamically hide the ion-nav-bar for v1 Amazon flow
|
||||
ion-nav-bar.hide { display: block !important; }
|
||||
|
||||
// the ion tabs element never needs it's own background (backgrounds are
|
||||
// rendered by the tabs), and the default background would cover the scanner
|
||||
ion-tabs.ion-tabs-transparent {
|
||||
|
|
@ -40,3 +37,20 @@ $placeholder-icon-padding: 10px;
|
|||
.card {
|
||||
margin: ($content-padding * 2) 14px;
|
||||
}
|
||||
|
||||
// A somewhat dirty solution to the nav-bar "flashing" during page transitions.
|
||||
// Since the old nav-bar is hidden before the new one is shown, this pseudo
|
||||
// element fills the space with the proper background color.
|
||||
ion-view.deflash-blue:before {
|
||||
content: " ";
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: $bar-height;
|
||||
background-color: $royal;
|
||||
}
|
||||
.platform-ios.platform-cordova:not(.fullscreen) ion-view.deflash-blue:before {
|
||||
height: $bar-height + $ios-statusbar-height;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,17 @@
|
|||
}
|
||||
}
|
||||
|
||||
.text-warn {
|
||||
.popup-sub-title {
|
||||
margin-top: 15px;
|
||||
color: #e42112 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.item-toggle, .item {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
max-width: none;
|
||||
width: inherit;
|
||||
|
|
@ -437,3 +448,7 @@ input[type=file] {
|
|||
.keyboard-open .has-tabs {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.white-space-initial {
|
||||
white-space: initial;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
}
|
||||
}
|
||||
#view-address-book {
|
||||
@extend .deflash-blue;
|
||||
.scroll {
|
||||
height:100%;
|
||||
}
|
||||
|
|
|
|||
89
src/sass/views/addresses.scss
Normal file
89
src/sass/views/addresses.scss
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#addresses {
|
||||
.addr {
|
||||
&-explanation, &-button-group {
|
||||
padding: 0 1rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
&-description {
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
color: $mid-gray;
|
||||
margin: 1rem 0;
|
||||
a {
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
cursor: hand;
|
||||
}
|
||||
}
|
||||
&-balance {
|
||||
margin-top: 4px;
|
||||
color: #5DD263;
|
||||
}
|
||||
&-path {
|
||||
margin-top: 4px;
|
||||
color: #B8B8B8;
|
||||
}
|
||||
}
|
||||
|
||||
.banner-icon {
|
||||
margin-top: 25px;
|
||||
i {
|
||||
box-shadow: $hovering-box-shadow;
|
||||
}
|
||||
}
|
||||
|
||||
.addr-list {
|
||||
.item {
|
||||
color: $dark-gray;
|
||||
padding-top: 1.3rem;
|
||||
padding-bottom: 1.3rem;
|
||||
&.has-addr-value {
|
||||
padding-top: .65rem;
|
||||
padding-bottom: .65rem;
|
||||
}
|
||||
&.item-divider {
|
||||
color: $mid-gray;
|
||||
padding-bottom: .5rem;
|
||||
font-size: .9rem;
|
||||
}
|
||||
&.view-all {
|
||||
margin: 20px 0px 20px 0px;
|
||||
cursor: pointer;
|
||||
cursor: hand;
|
||||
i {
|
||||
font-size: 35px;
|
||||
margin-right: 5px;
|
||||
color: #647ce8;
|
||||
}
|
||||
span {
|
||||
color: #647ce8;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
i {
|
||||
font-size: 35px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
}
|
||||
.box-error {
|
||||
padding: 25px;
|
||||
background-color: #E65555;
|
||||
color: #F4F4F4;
|
||||
h5 {
|
||||
margin: 5px;
|
||||
color: #F4F4F4;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
a {
|
||||
font-weight: bold;
|
||||
color: #F4F4F4;
|
||||
cursor: pointer;
|
||||
cursor: hand;
|
||||
}
|
||||
}
|
||||
.item-note {
|
||||
color: $light-gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
#view-amount {
|
||||
@extend .deflash-blue;
|
||||
.recipient-label {
|
||||
font-size: 14px;
|
||||
padding-bottom: 0;
|
||||
|
|
@ -10,6 +11,9 @@
|
|||
.icon-bitpay-card {
|
||||
background-image: url("../img/icon-bitpay.svg");
|
||||
}
|
||||
.icon-amazon {
|
||||
background-image: url("../img/icon-amazon.svg");
|
||||
}
|
||||
@media(max-width: 480px) {
|
||||
.bitcoin-address {
|
||||
.icon {
|
||||
|
|
@ -33,7 +37,7 @@
|
|||
position: absolute;
|
||||
top: 10px;
|
||||
}
|
||||
.amount-pane {
|
||||
.amount-pane-recipient {
|
||||
position: absolute;
|
||||
top: 95px;
|
||||
bottom: 0;
|
||||
|
|
@ -64,6 +68,42 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
.amount-pane-no-recipient {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
padding: 0 16px;
|
||||
|
||||
.amount-bar {
|
||||
padding: 24px 0;
|
||||
font-size: 18px;
|
||||
.title {
|
||||
float: left;
|
||||
padding-top: 10px;
|
||||
color: $dark-gray;
|
||||
font-weight: bold;
|
||||
.limits {
|
||||
margin-top: 10px;
|
||||
color: $light-gray;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.amount {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
flex-grow: 1;
|
||||
position: absolute;
|
||||
bottom: 254px;
|
||||
top: 66px;
|
||||
.light {
|
||||
color: $light-gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
.amount {
|
||||
&__editable {
|
||||
margin-bottom: 1rem;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#bitpayCard {
|
||||
background: white;
|
||||
.bar-header {
|
||||
border: 0;
|
||||
background: #1e3186;
|
||||
|
|
@ -9,15 +10,35 @@
|
|||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
.amount-wrapper {
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
|
||||
.amount-bg {
|
||||
content: '';
|
||||
top: -1000px;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
height: 1000px;
|
||||
width: 100%;
|
||||
background-color: #1e3186;
|
||||
}
|
||||
}
|
||||
.amount {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding: 2rem 1rem 1.5rem 1rem;
|
||||
height: 140px;
|
||||
height: 160px;
|
||||
border-color: #172565;
|
||||
background-color: #1e3186;
|
||||
background-image: linear-gradient(0deg, #172565, #172565 0%, transparent 0%);
|
||||
color: #fff;
|
||||
|
||||
&__balance {
|
||||
margin-bottom: 25px;
|
||||
font-weight: 600;
|
||||
font-size: 34px;
|
||||
}
|
||||
}
|
||||
.wallet-details-wallet-info {
|
||||
bottom: 5px;
|
||||
|
|
@ -37,4 +58,26 @@
|
|||
.item-select select {
|
||||
color: #667;
|
||||
}
|
||||
|
||||
.get-started {
|
||||
|
||||
margin-top: 20px;
|
||||
|
||||
&__arrow {
|
||||
font-size: 56px;
|
||||
opacity: .2;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 28px;
|
||||
color: #4A4A4A;
|
||||
}
|
||||
|
||||
&__text {
|
||||
font-weight: 300;
|
||||
color: #8e8e8e;
|
||||
max-width: 300px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,5 +11,12 @@
|
|||
color: $light-gray;
|
||||
font-size: 14px;
|
||||
}
|
||||
&.item-icon-right {
|
||||
.icon-hotspot {
|
||||
right: 0px;
|
||||
padding-left: 11px;
|
||||
padding-right: 11px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue