bwc
This commit is contained in:
parent
04fb7ba032
commit
320de62f13
348 changed files with 7745 additions and 30874 deletions
|
|
@ -1,72 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('CopayersController',
|
||||
function($scope, $rootScope, $timeout, go, identityService, notification, isCordova) {
|
||||
var w = $rootScope.wallet;
|
||||
|
||||
|
||||
$scope.init = function() {
|
||||
$rootScope.title = 'Share this secret with your copayers';
|
||||
$scope.loading = false;
|
||||
$scope.secret = $rootScope.wallet.getSecret();
|
||||
$scope.isCordova = isCordova;
|
||||
|
||||
w.on('publicKeyRingUpdated', $scope.updateList);
|
||||
w.on('ready', $scope.updateList);
|
||||
|
||||
$scope.updateList();
|
||||
};
|
||||
|
||||
$scope.updateList = function() {
|
||||
var w = $rootScope.wallet;
|
||||
|
||||
$scope.copayers = $rootScope.wallet.getRegisteredPeerIds();
|
||||
if (w.isComplete()) {
|
||||
|
||||
w.removeListener('publicKeyRingUpdated', $scope.updateList);
|
||||
w.removeListener('ready', $scope.updateList);
|
||||
go.walletHome();
|
||||
}
|
||||
$timeout(function() {
|
||||
$rootScope.$digest();
|
||||
}, 1);
|
||||
};
|
||||
|
||||
$scope.deleteWallet = function() {
|
||||
$rootScope.starting = true;
|
||||
$timeout(function() {
|
||||
identityService.deleteWallet(w, function(err) {
|
||||
$rootScope.starting = false;
|
||||
if (err) {
|
||||
$scope.error = err.message || err;
|
||||
copay.logger.warn(err);
|
||||
$timeout(function () { $scope.$digest(); });
|
||||
} else {
|
||||
if ($rootScope.wallet) {
|
||||
go.walletHome();
|
||||
}
|
||||
$timeout(function() {
|
||||
notification.success('Success', 'The wallet "' + (w.name || w.id) + '" was deleted');
|
||||
});
|
||||
}
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
||||
$scope.copySecret = function(secret) {
|
||||
if (isCordova) {
|
||||
window.cordova.plugins.clipboard.copy(secret);
|
||||
window.plugins.toast.showShortCenter('Copied to clipboard');
|
||||
}
|
||||
};
|
||||
|
||||
$scope.shareSecret = function(secret) {
|
||||
if (isCordova) {
|
||||
if (isMobile.Android() || isMobile.Windows()) {
|
||||
window.ignoreMobilePause = true;
|
||||
}
|
||||
window.plugins.socialsharing.share(secret, null, null, null);
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('CreateController',
|
||||
function($scope, $rootScope, $location, $timeout, identityService, backupService, notification, defaults, isMobile, isCordova) {
|
||||
|
||||
$rootScope.fromSetup = true;
|
||||
$scope.loading = false;
|
||||
$scope.walletPassword = $rootScope.walletPassword;
|
||||
$scope.isMobile = isMobile.any();
|
||||
$scope.hideAdv = true;
|
||||
$scope.networkName = config.networkName;
|
||||
$rootScope.title = 'Create new wallet';
|
||||
$rootScope.hideWalletNavigation = true;
|
||||
$scope.isWindowsPhoneApp = isMobile.Windows() && isCordova;
|
||||
|
||||
// ng-repeat defined number of times instead of repeating over array?
|
||||
$scope.getNumber = function(num) {
|
||||
return new Array(num);
|
||||
}
|
||||
|
||||
$scope.totalCopayers = config.wallet.totalCopayers;
|
||||
$scope.TCValues = _.range(1, config.limits.totalCopayers + 1);
|
||||
|
||||
var updateRCSelect = function(n) {
|
||||
var maxReq = copay.Wallet.getMaxRequiredCopayers(n);
|
||||
$scope.RCValues = _.range(1, maxReq + 1);
|
||||
$scope.requiredCopayers = Math.min(parseInt(n / 2 + 1), maxReq);
|
||||
};
|
||||
|
||||
updateRCSelect($scope.totalCopayers);
|
||||
|
||||
$scope.$watch('totalCopayers', function(tc) {
|
||||
updateRCSelect(tc);
|
||||
});
|
||||
|
||||
$scope.$watch('networkName', function(tc) {
|
||||
$scope.networkUrl = config.network[$scope.networkName].url;
|
||||
});
|
||||
|
||||
$scope.showNetwork = function() {
|
||||
return $scope.networkUrl != defaults.network.livenet.url && $scope.networkUrl != defaults.network.testnet.url;
|
||||
};
|
||||
|
||||
|
||||
$scope.create = function(form) {
|
||||
if (form && form.$invalid) {
|
||||
$scope.error = 'Please enter the required fields';
|
||||
return;
|
||||
}
|
||||
var opts = {
|
||||
requiredCopayers: $scope.requiredCopayers,
|
||||
totalCopayers: $scope.totalCopayers,
|
||||
name: $scope.walletName,
|
||||
privateKeyHex: $scope.private,
|
||||
networkName: $scope.networkName,
|
||||
};
|
||||
$rootScope.starting = true;
|
||||
identityService.createWallet(opts, function(err, wallet){
|
||||
$rootScope.starting = false;
|
||||
if (err || !wallet) {
|
||||
copay.logger.debug(err);
|
||||
if (err.match('OVERQUOTA')){
|
||||
$scope.error = 'Could not create wallet: storage limits on remove server exceeded';
|
||||
} else {
|
||||
$scope.error = 'Could not create wallet: ' + err;
|
||||
}
|
||||
}
|
||||
|
||||
$timeout(function(){
|
||||
$rootScope.$digest();
|
||||
},1);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.$on("$destroy", function () {
|
||||
$rootScope.hideWalletNavigation = false;
|
||||
});
|
||||
});
|
||||
|
|
@ -1,202 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('CreateProfileController', function($scope, $rootScope, $location, $timeout, $window, notification, pluginManager, identityService, pinService, isMobile, isCordova, configService, go) {
|
||||
|
||||
var _credentials;
|
||||
|
||||
$scope.init = function() {
|
||||
|
||||
if ($rootScope.wallet)
|
||||
go.walletHome();
|
||||
|
||||
$scope.isMobile = isMobile.any();
|
||||
$scope.isWindowsPhoneApp = isMobile.Windows() && isCordova;
|
||||
$scope.hideForWP = 0;
|
||||
$scope.digits = [];
|
||||
$scope.defined = [];
|
||||
$scope.askForPin = 0;
|
||||
|
||||
$scope.createStep = 'storage';
|
||||
$scope.useLocalstorage = false;
|
||||
$scope.minPasswordStrength = _.isUndefined(config.minPasswordStrength) ?
|
||||
4 : config.minPasswordStrength;
|
||||
|
||||
};
|
||||
|
||||
$scope.clear = function() {
|
||||
pinService.clearPin($scope);
|
||||
};
|
||||
|
||||
$scope.press = function(digit) {
|
||||
pinService.pressPin($scope, digit, true);
|
||||
};
|
||||
|
||||
$scope.skip = function () {
|
||||
pinService.skipPin($scope, true);
|
||||
};
|
||||
|
||||
$scope.formFocus = function() {
|
||||
if (!$scope.isWindowsPhoneApp) return
|
||||
$scope.hideForWP = true;
|
||||
$timeout(function() {
|
||||
$scope.$digest();
|
||||
}, 1);
|
||||
};
|
||||
|
||||
$scope.createPin = function(pin) {
|
||||
preconditions.checkArgument(pin);
|
||||
preconditions.checkState($rootScope.iden);
|
||||
preconditions.checkState(_credentials && _credentials.email);
|
||||
$rootScope.starting = true;
|
||||
|
||||
$timeout(function() {
|
||||
pinService.save(pin, _credentials.email, _credentials.password, function(err) {
|
||||
_credentials.password = '';
|
||||
_credentials = null;
|
||||
$scope.askForPin = 0;
|
||||
$rootScope.hasPin = true;
|
||||
$scope.createDefaultWallet();
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
||||
|
||||
$scope.setStep = function(step) {
|
||||
$scope.error = null;
|
||||
$scope.createStep = step;
|
||||
$scope.hideForWP = false;
|
||||
$timeout(function() {
|
||||
$scope.$digest();
|
||||
}, 1);
|
||||
};
|
||||
|
||||
$scope.selectStorage = function(storage) {
|
||||
$scope.useLocalstorage = storage == 'local';
|
||||
$scope.hideForWP = false;
|
||||
$timeout(function() {
|
||||
$scope.$digest();
|
||||
}, 1);
|
||||
};
|
||||
|
||||
$scope.goToEmail = function() {
|
||||
$scope.createStep = 'email';
|
||||
$scope.useEmail = !$scope.useLocalstorage;
|
||||
};
|
||||
|
||||
$scope.setEmailOrUsername = function(form) {
|
||||
$scope.userOrEmail = $scope.useLocalstorage ? form.username.$modelValue : form.email.$modelValue;
|
||||
preconditions.checkState($scope.userOrEmail);
|
||||
|
||||
$scope.error = null;
|
||||
$scope.hideForWP = false;
|
||||
$scope.createStep = 'pass';
|
||||
$timeout(function() {
|
||||
$scope.$digest();
|
||||
}, 1);
|
||||
};
|
||||
|
||||
/* Last step. Will emit after creation so the UX gets updated */
|
||||
$scope.createDefaultWallet = function() {
|
||||
$rootScope.hideNavigation = false;
|
||||
$rootScope.starting = true;
|
||||
identityService.createDefaultWallet(function(err) {
|
||||
$scope.askForPin = 0;
|
||||
$rootScope.starting = null;
|
||||
|
||||
if (err) {
|
||||
var msg = err.toString();
|
||||
$scope.error = msg;
|
||||
} else {
|
||||
if (!$scope.useLocalstorage) {
|
||||
$rootScope.pleaseConfirmEmail = true;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
$scope._doCreateProfile = function(emailOrUsername, password, cb) {
|
||||
preconditions.checkArgument(_.isString(emailOrUsername));
|
||||
preconditions.checkArgument(_.isString(password));
|
||||
|
||||
$rootScope.hideNavigation = false;
|
||||
|
||||
identityService.create(emailOrUsername, password, function(err) {
|
||||
if (err) {
|
||||
var msg = err.toString();
|
||||
$scope.createStep = 'email';
|
||||
if (msg.indexOf('EEXIST') >= 0 || msg.indexOf('BADC') >= 0) {
|
||||
msg = 'This profile already exists'
|
||||
}
|
||||
if (msg.indexOf('EMAILERROR') >= 0) {
|
||||
msg = 'Could not send verification email. Please check your email address.';
|
||||
}
|
||||
return cb(msg);
|
||||
} else {
|
||||
// mobile
|
||||
if ($scope.isMobile) {
|
||||
$rootScope.starting = null;
|
||||
_credentials = {
|
||||
email: emailOrUsername,
|
||||
password: password,
|
||||
};
|
||||
$scope.askForPin = 1;
|
||||
$scope.hideForWP = 0;
|
||||
|
||||
$rootScope.hideNavigation = true;
|
||||
$timeout(function() {
|
||||
$rootScope.$digest();
|
||||
}, 1);
|
||||
return;
|
||||
} else {
|
||||
$scope.createDefaultWallet();
|
||||
}
|
||||
}
|
||||
return cb();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
$scope.saveSettings = function(cb) {
|
||||
var plugins = config.plugins;
|
||||
|
||||
plugins.EncryptedLocalStorage = false;
|
||||
plugins.EncryptedInsightStorage = false;
|
||||
|
||||
var pluginName = $scope.useLocalstorage ? 'EncryptedLocalStorage' : 'EncryptedInsightStorage';
|
||||
plugins[pluginName] = true;
|
||||
|
||||
configService.set({
|
||||
plugins: plugins
|
||||
}, cb);
|
||||
};
|
||||
|
||||
|
||||
$scope.createProfile = function(form) {
|
||||
if (form && form.$invalid) {
|
||||
$scope.error = 'Please enter the required fields';
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.saveSettings(function(err) {
|
||||
preconditions.checkState(!err, err);
|
||||
$rootScope.starting = true;
|
||||
|
||||
$scope._doCreateProfile($scope.userOrEmail, form.password.$modelValue, function(err) {
|
||||
if (err) {
|
||||
$scope.error = err;
|
||||
$scope.passwordStrength = null;
|
||||
$rootScope.starting = false;
|
||||
}
|
||||
form.password.$setViewValue('');
|
||||
form.password.$render();
|
||||
form.repeatpassword.$setViewValue('');
|
||||
form.repeatpassword.$render();
|
||||
form.$setPristine();
|
||||
$timeout(function() {
|
||||
$rootScope.$digest();
|
||||
}, 1);
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('DevLoginController', function($scope, $rootScope, $routeParams, identityService) {
|
||||
|
||||
var mail = $routeParams.mail;
|
||||
var password = $routeParams.password;
|
||||
|
||||
var form = {};
|
||||
form.email = {};
|
||||
form.password = {};
|
||||
form.email.$modelValue = mail;
|
||||
form.password.$modelValue = password;
|
||||
|
||||
identityService.open($scope, form);
|
||||
|
||||
});
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('EmailConfirmationController', function($scope, $rootScope, $location) {
|
||||
$rootScope.fromEmailConfirmation = true;
|
||||
$location.path('/');
|
||||
});
|
||||
|
|
@ -1,204 +0,0 @@
|
|||
'use strict';
|
||||
var bitcore = require('bitcore');
|
||||
|
||||
angular.module('copayApp.controllers').controller('HistoryController',
|
||||
function($scope, $rootScope, $filter, $timeout, $modal, rateService, notification, go) {
|
||||
var w = $rootScope.wallet;
|
||||
|
||||
$rootScope.title = 'History';
|
||||
$scope.loading = false;
|
||||
$scope.generating = false;
|
||||
$scope.lastShowed = false;
|
||||
|
||||
$scope.currentPage = 1;
|
||||
$scope.itemsPerPage = 10;
|
||||
$scope.nbPages = 0;
|
||||
$scope.totalItems = 0;
|
||||
$scope.blockchain_txs = [];
|
||||
$scope.alternativeCurrency = [];
|
||||
|
||||
$scope.selectPage = function(page) {
|
||||
$scope.paging = true;
|
||||
$scope.currentPage = page;
|
||||
$scope.update();
|
||||
};
|
||||
|
||||
$scope.downloadHistory = function() {
|
||||
var w = $rootScope.wallet;
|
||||
if (!w) return;
|
||||
|
||||
var filename = "copay_history.csv";
|
||||
var descriptor = {
|
||||
columns: [{
|
||||
label: 'Date',
|
||||
property: 'ts',
|
||||
type: 'date'
|
||||
}, {
|
||||
label: 'Amount (' + w.settings.unitName + ')',
|
||||
property: 'amount',
|
||||
type: 'number'
|
||||
}, {
|
||||
label: 'Amount (' + w.settings.alternativeIsoCode + ')',
|
||||
property: 'alternativeAmount'
|
||||
}, {
|
||||
label: 'Action',
|
||||
property: 'action'
|
||||
}, {
|
||||
label: 'AddressTo',
|
||||
property: 'addressTo'
|
||||
}, {
|
||||
label: 'Comment',
|
||||
property: 'comment'
|
||||
}, ],
|
||||
};
|
||||
if (w.isShared()) {
|
||||
descriptor.columns.push({
|
||||
label: 'Signers',
|
||||
property: function(obj) {
|
||||
if (!obj.actionList) return '';
|
||||
return _.map(obj.actionList, function(action) {
|
||||
return w.publicKeyRing.nicknameForCopayer(action.cId);
|
||||
}).join('|');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$scope.generating = true;
|
||||
|
||||
$scope._getTransactions(w, null, function(err, res) {
|
||||
if (err) {
|
||||
$scope.generating = false;
|
||||
logger.error(err);
|
||||
notification.error('Could not get transaction history');
|
||||
return;
|
||||
}
|
||||
$scope._addRates(w, res.items, function(err) {
|
||||
copay.csv.toCsv(res.items, descriptor, function(err, res) {
|
||||
if (err) {
|
||||
$scope.generating = false;
|
||||
logger.error(err);
|
||||
notification.error('Could not generate csv file');
|
||||
return;
|
||||
}
|
||||
var csvContent = "data:text/csv;charset=utf-8," + res;
|
||||
var encodedUri = encodeURI(csvContent);
|
||||
var link = document.createElement("a");
|
||||
link.setAttribute("href", encodedUri);
|
||||
link.setAttribute("download", filename);
|
||||
link.click();
|
||||
$scope.generating = false;
|
||||
$scope.$digest();
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
$scope.update = function() {
|
||||
$scope.getTransactions();
|
||||
};
|
||||
|
||||
$scope.show = function() {
|
||||
$scope.loading = true;
|
||||
setTimeout(function() {
|
||||
$scope.update();
|
||||
}, 1);
|
||||
};
|
||||
|
||||
$scope._getTransactions = function(w, opts, cb) {
|
||||
w.getTransactionHistory(opts, function(err, res) {
|
||||
if (err) return cb(err);
|
||||
if (!res) return cb();
|
||||
|
||||
var now = new Date();
|
||||
var items = res.items;
|
||||
_.each(items, function(tx) {
|
||||
tx.ts = tx.minedTs || tx.sentTs;
|
||||
tx.rateTs = Math.floor((tx.ts || now) / 1000);
|
||||
tx.amount = $filter('noFractionNumber')(tx.amount);
|
||||
});
|
||||
return cb(null, res);
|
||||
});
|
||||
};
|
||||
|
||||
$scope._addRates = function(w, txs, cb) {
|
||||
if (!txs || txs.length == 0) return cb();
|
||||
var index = _.groupBy(txs, 'rateTs');
|
||||
rateService.getHistoricRates(w.settings.alternativeIsoCode, _.keys(index), function(err, res) {
|
||||
if (err || !res) return cb(err);
|
||||
_.each(res, function(r) {
|
||||
_.each(index[r.ts], function (tx) {
|
||||
var alternativeAmount = (r.rate != null ? tx.amountSat * rateService.SAT_TO_BTC * r.rate : null);
|
||||
tx.alternativeAmount = alternativeAmount ? $filter('noFractionNumber')(alternativeAmount, 2) : null;
|
||||
});
|
||||
});
|
||||
return cb();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
$scope.openTxModal = function(btx) {
|
||||
var ModalInstanceCtrl = function($scope, $modalInstance) {
|
||||
$scope.btx = btx;
|
||||
|
||||
$scope.getShortNetworkName = function() {
|
||||
var w = $rootScope.wallet;
|
||||
return w.getNetworkName().substring(0, 4);
|
||||
};
|
||||
|
||||
$scope.cancel = function() {
|
||||
$modalInstance.dismiss('cancel');
|
||||
};
|
||||
};
|
||||
|
||||
$modal.open({
|
||||
templateUrl: 'views/modals/tx-details.html',
|
||||
windowClass: 'medium',
|
||||
controller: ModalInstanceCtrl,
|
||||
});
|
||||
};
|
||||
|
||||
$scope.getTransactions = function() {
|
||||
var w = $rootScope.wallet;
|
||||
if (!w) return;
|
||||
|
||||
$scope.blockchain_txs = w.cached_txs || [];
|
||||
$scope.loading = true;
|
||||
|
||||
$scope._getTransactions(w, {
|
||||
currentPage: $scope.currentPage,
|
||||
itemsPerPage: $scope.itemsPerPage,
|
||||
}, function(err, res) {
|
||||
if (err) throw err;
|
||||
|
||||
if (!res) {
|
||||
$scope.loading = false;
|
||||
$scope.lastShowed = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var items = res.items;
|
||||
$scope._addRates(w, items, function(err) {
|
||||
$timeout(function() {
|
||||
$scope.$digest();
|
||||
}, 1);
|
||||
})
|
||||
|
||||
$scope.blockchain_txs = w.cached_txs = items;
|
||||
$scope.nbPages = res.nbPages;
|
||||
$scope.totalItems = res.nbItems;
|
||||
|
||||
$scope.loading = false;
|
||||
$scope.paging = false;
|
||||
setTimeout(function() {
|
||||
$scope.$digest();
|
||||
}, 1);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
$scope.hasAction = function(actions, action) {
|
||||
return actions.hasOwnProperty('create');
|
||||
};
|
||||
|
||||
});
|
||||
|
|
@ -1,216 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('HomeController', function($scope, $rootScope, $timeout, $window, go, notification, identityService, Compatibility, pinService, applicationService, isMobile, isCordova, localstorageService) {
|
||||
|
||||
var KEY = 'CopayDisclaimer';
|
||||
var ls = localstorageService;
|
||||
var _credentials;
|
||||
|
||||
$scope.init = function() {
|
||||
$scope.isMobile = isMobile.any();
|
||||
$scope.isWindowsPhoneApp = isMobile.Windows() && isCordova;
|
||||
$scope.hideForWP = 0;
|
||||
$scope.attempt = 0;
|
||||
$scope.digits = [];
|
||||
$scope.defined = [];
|
||||
$scope.askForPin = 0;
|
||||
|
||||
// This is only for backwards compat, insight api should link to #!/confirmed directly
|
||||
if (getParam('confirmed')) {
|
||||
var hashIndex = window.location.href.indexOf('/?');
|
||||
window.location = window.location.href.substr(0, hashIndex) + '#!/confirmed';
|
||||
return;
|
||||
}
|
||||
|
||||
if ($rootScope.fromEmailConfirmation) {
|
||||
$scope.confirmedEmail = true;
|
||||
$rootScope.fromEmailConfirmation = false;
|
||||
}
|
||||
|
||||
if ($rootScope.wallet) {
|
||||
go.walletHome();
|
||||
}
|
||||
|
||||
Compatibility.check($scope);
|
||||
pinService.check(function(err, value) {
|
||||
$rootScope.hasPin = value;
|
||||
});
|
||||
$scope.usingLocalStorage = config.plugins.EncryptedLocalStorage;
|
||||
|
||||
if (isCordova) {
|
||||
ls.getItem(KEY, function(err, value) {
|
||||
$scope.showDisclaimer = value ? null : true;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.clear = function() {
|
||||
pinService.clearPin($scope);
|
||||
};
|
||||
|
||||
$scope.press = function(digit) {
|
||||
pinService.pressPin($scope, digit);
|
||||
};
|
||||
|
||||
$scope.skip = function () {
|
||||
pinService.skipPin($scope);
|
||||
};
|
||||
|
||||
$scope.agreeDisclaimer = function() {
|
||||
ls.setItem(KEY, true, function(err) {
|
||||
$scope.showDisclaimer = null;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.formFocus = function() {
|
||||
if ($scope.isWindowsPhoneApp) {
|
||||
$scope.hideForWP = true;
|
||||
$timeout(function() {
|
||||
$scope.$digest();
|
||||
}, 1);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.openWithPin = function(pin) {
|
||||
|
||||
if (!pin) {
|
||||
$scope.error = 'Please enter the required fields';
|
||||
return;
|
||||
}
|
||||
$rootScope.starting = true;
|
||||
|
||||
$timeout(function() {
|
||||
var credentials = pinService.get(pin, function(err, credentials) {
|
||||
if (err || !credentials) {
|
||||
$rootScope.starting = null;
|
||||
$scope.error = 'Wrong PIN';
|
||||
$scope.clear();
|
||||
$timeout(function() {
|
||||
$scope.error = null;
|
||||
}, 2000);
|
||||
return;
|
||||
}
|
||||
$scope.open(credentials.email, credentials.password);
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
||||
$scope.openWallets = function() {
|
||||
preconditions.checkState($rootScope.iden);
|
||||
var iden = $rootScope.iden;
|
||||
$rootScope.hideNavigation = false;
|
||||
$rootScope.starting = true;
|
||||
iden.openWallets();
|
||||
};
|
||||
|
||||
$scope.createPin = function(pin) {
|
||||
preconditions.checkArgument(pin);
|
||||
preconditions.checkState($rootScope.iden);
|
||||
preconditions.checkState(_credentials && _credentials.email);
|
||||
$rootScope.starting = true;
|
||||
|
||||
$timeout(function() {
|
||||
pinService.save(pin, _credentials.email, _credentials.password, function(err) {
|
||||
_credentials.password = '';
|
||||
_credentials = null;
|
||||
$scope.askForPin = 0;
|
||||
$rootScope.hasPin = true;
|
||||
$rootScope.starting = null;
|
||||
$scope.openWallets();
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
||||
$scope.openWithCredentials = function(form) {
|
||||
if (form && form.$invalid) {
|
||||
$scope.error = 'Please enter the required fields';
|
||||
return;
|
||||
}
|
||||
|
||||
$timeout(function() {
|
||||
$scope.open(form.email.$modelValue, form.password.$modelValue);
|
||||
}, 100);
|
||||
};
|
||||
|
||||
|
||||
$scope.pinLogout = function() {
|
||||
pinService.clear(function() {
|
||||
copay.logger.debug('PIN erased');
|
||||
delete $rootScope['hasPin'];
|
||||
applicationService.restart();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.open = function(email, password) {
|
||||
$rootScope.starting = true;
|
||||
identityService.open(email, password, function(err, iden) {
|
||||
if (err) {
|
||||
$rootScope.starting = false;
|
||||
copay.logger.warn(err);
|
||||
|
||||
var identifier = $scope.usingLocalStorage ? 'username' : 'email';
|
||||
if ((err.toString() || '').match('PNOTFOUND')) {
|
||||
$scope.error = 'Invalid ' + identifier + ' or password';
|
||||
|
||||
if ($scope.attempt++ > 1) {
|
||||
var storage = $scope.usingLocalStorage ? 'this device storage' : 'cloud storage';
|
||||
$scope.error = 'Invalid ' + identifier + ' or password. You are trying to sign in using ' + storage + '. Change it on settings if necessary.';
|
||||
};
|
||||
|
||||
$rootScope.hasPin = false;
|
||||
pinService.clear(function() {});
|
||||
|
||||
} else if ((err.toString() || '').match('Connection')) {
|
||||
$scope.error = 'Could not connect to Insight Server';
|
||||
} else if ((err.toString() || '').match('Unable')) {
|
||||
$scope.error = 'Unable to read data from the Insight Server';
|
||||
} else {
|
||||
$scope.error = 'Unknown error';
|
||||
}
|
||||
$timeout(function() {
|
||||
$rootScope.$digest();
|
||||
}, 1)
|
||||
return;
|
||||
}
|
||||
|
||||
// Open successfully?
|
||||
if (iden) {
|
||||
$scope.error = null;
|
||||
$scope.confirmedEmail = false;
|
||||
|
||||
// mobile
|
||||
if ($scope.isMobile && !$rootScope.hasPin) {
|
||||
_credentials = {
|
||||
email: email,
|
||||
password: password,
|
||||
};
|
||||
$scope.askForPin = 1;
|
||||
$rootScope.starting = false;
|
||||
$rootScope.hideNavigation = true;
|
||||
$timeout(function() {
|
||||
$rootScope.$digest();
|
||||
}, 1);
|
||||
return;
|
||||
}
|
||||
// no mobile
|
||||
else {
|
||||
$scope.openWallets();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function getParam(sname) {
|
||||
var params = location.search.substr(location.search.indexOf("?") + 1);
|
||||
var sval = "";
|
||||
params = params.split("&");
|
||||
// split param and value into individual pieces
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var temp = params[i].split("=");
|
||||
if ([temp[0]] == sname) {
|
||||
sval = temp[1];
|
||||
}
|
||||
}
|
||||
return sval;
|
||||
}
|
||||
});
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('HomeWalletController', function($scope, $rootScope, $timeout, $filter, $modal, rateService, notification, txStatus, identityService, isCordova) {
|
||||
|
||||
$scope.openTxModal = function(tx) {
|
||||
var ModalInstanceCtrl = function($scope, $modalInstance) {
|
||||
var w = $rootScope.wallet;
|
||||
$scope.error = null;
|
||||
$scope.tx = tx;
|
||||
$scope.registeredCopayerIds = w.getRegisteredCopayerIds();
|
||||
$scope.loading = null;
|
||||
|
||||
$scope.getShortNetworkName = function() {
|
||||
var w = $rootScope.wallet;
|
||||
return w.getNetworkName().substring(0, 4);
|
||||
};
|
||||
|
||||
$scope.sign = function(ntxid) {
|
||||
if (isCordova) {
|
||||
window.plugins.spinnerDialog.show(null, 'Signing transaction...', true);
|
||||
}
|
||||
$scope.loading = true;
|
||||
$scope.error = null;
|
||||
$timeout(function() {
|
||||
w.signAndSend(ntxid, function(err, id, status) {
|
||||
if (isCordova) {
|
||||
window.plugins.spinnerDialog.hide();
|
||||
}
|
||||
$scope.loading = false;
|
||||
if (err) {
|
||||
$scope.error = 'Transaction could not send. Please try again.';
|
||||
$scope.$digest();
|
||||
}
|
||||
else {
|
||||
$modalInstance.close(status);
|
||||
}
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
||||
$scope.reject = function(ntxid) {
|
||||
if (isCordova) {
|
||||
window.plugins.spinnerDialog.show(null, 'Rejecting transaction...', true);
|
||||
}
|
||||
$scope.loading = true;
|
||||
$scope.error = null;
|
||||
$timeout(function() {
|
||||
w.reject(ntxid, function(err, status) {
|
||||
if (isCordova) {
|
||||
window.plugins.spinnerDialog.hide();
|
||||
}
|
||||
$scope.loading = false;
|
||||
if (err) {
|
||||
$scope.error = err;
|
||||
$scope.$digest();
|
||||
}
|
||||
else {
|
||||
$modalInstance.close(status);
|
||||
}
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
||||
$scope.broadcast = function(ntxid) {
|
||||
if (isCordova) {
|
||||
window.plugins.spinnerDialog.show(null, 'Sending transaction...', true);
|
||||
}
|
||||
$scope.loading = true;
|
||||
$scope.error = null;
|
||||
$timeout(function() {
|
||||
w.issueTx(ntxid, function(err, txid, status) {
|
||||
if (isCordova) {
|
||||
window.plugins.spinnerDialog.hide();
|
||||
}
|
||||
$scope.loading = false;
|
||||
if (err) {
|
||||
$scope.error = 'Transaction could not send. Please try again.';
|
||||
$scope.$digest();
|
||||
}
|
||||
else {
|
||||
$modalInstance.close(status);
|
||||
}
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
||||
$scope.cancel = function() {
|
||||
$modalInstance.dismiss('cancel');
|
||||
};
|
||||
};
|
||||
|
||||
var modalInstance = $modal.open({
|
||||
templateUrl: 'views/modals/txp-details.html',
|
||||
windowClass: 'medium',
|
||||
controller: ModalInstanceCtrl,
|
||||
});
|
||||
|
||||
modalInstance.result.then(function(status) {
|
||||
txStatus.notify(status);
|
||||
});
|
||||
|
||||
};
|
||||
});
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('ImportController',
|
||||
function($scope, $rootScope, $location, $timeout, identityService, notification, isMobile, isCordova, Compatibility) {
|
||||
|
||||
$rootScope.title = 'Import wallet';
|
||||
$scope.importStatus = 'Importing wallet - Reading backup...';
|
||||
$scope.hideAdv = true;
|
||||
$scope.isSafari = isMobile.Safari();
|
||||
$scope.isCordova = isCordova;
|
||||
$scope.importOpts = {};
|
||||
$rootScope.hideWalletNavigation = true;
|
||||
|
||||
|
||||
window.ignoreMobilePause = true;
|
||||
$scope.$on('$destroy', function() {
|
||||
$timeout(function(){
|
||||
window.ignoreMobilePause = false;
|
||||
}, 100);
|
||||
});
|
||||
|
||||
Compatibility.check($scope);
|
||||
|
||||
var reader = new FileReader();
|
||||
|
||||
var updateStatus = function(status) {
|
||||
$scope.importStatus = status;
|
||||
}
|
||||
|
||||
|
||||
$scope.getFile = function() {
|
||||
// If we use onloadend, we need to check the readyState.
|
||||
reader.onloadend = function(evt) {
|
||||
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
|
||||
var encryptedObj = evt.target.result;
|
||||
updateStatus('Importing wallet - Procesing backup...');
|
||||
identityService.importWallet(encryptedObj, $scope.password, {}, function(err) {
|
||||
if (err) {
|
||||
$rootScope.starting = false;
|
||||
$scope.error = 'Could not read wallet. Please check your password';
|
||||
$timeout(function() {
|
||||
$rootScope.$digest();
|
||||
}, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.import = function(form) {
|
||||
|
||||
if (form.$invalid) {
|
||||
$scope.error = 'There is an error in the form';
|
||||
return;
|
||||
}
|
||||
|
||||
var backupFile = $scope.file;
|
||||
var backupText = form.backupText.$modelValue;
|
||||
var backupOldWallet = form.backupOldWallet.$modelValue;
|
||||
var password = form.password.$modelValue;
|
||||
|
||||
if (backupOldWallet) {
|
||||
backupText = backupOldWallet.value;
|
||||
}
|
||||
|
||||
if (!backupFile && !backupText) {
|
||||
$scope.error = 'Please, select your backup file';
|
||||
return;
|
||||
}
|
||||
|
||||
$rootScope.starting = true;
|
||||
|
||||
$timeout(function() {
|
||||
|
||||
$scope.importOpts = {};
|
||||
|
||||
var skipFields = [];
|
||||
|
||||
if ($scope.skipPublicKeyRing)
|
||||
skipFields.push('publicKeyRing');
|
||||
|
||||
if ($scope.skipTxProposals)
|
||||
skipFields.push('txProposals');
|
||||
|
||||
if (skipFields)
|
||||
$scope.importOpts.skipFields = skipFields;
|
||||
|
||||
if (backupFile) {
|
||||
reader.readAsBinaryString(backupFile);
|
||||
} else {
|
||||
updateStatus('Importing wallet - Procesing backup...');
|
||||
identityService.importWallet(backupText, $scope.password, $scope.importOpts, function(err) {
|
||||
if (err) {
|
||||
$rootScope.starting = false;
|
||||
$scope.error = 'Could not read wallet. Please check your password';
|
||||
$timeout(function() {
|
||||
$rootScope.$digest();
|
||||
}, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 100);
|
||||
};
|
||||
|
||||
|
||||
$scope.$on("$destroy", function () {
|
||||
$rootScope.hideWalletNavigation = false;
|
||||
});
|
||||
|
||||
});
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('ImportProfileController',
|
||||
function($scope, $rootScope, $location, $timeout, notification, isMobile, isCordova, identityService) {
|
||||
$scope.title = 'Import a backup';
|
||||
$scope.importStatus = 'Importing profile - Reading backup...';
|
||||
$scope.hideAdv = true;
|
||||
$scope.isSafari = isMobile.Safari();
|
||||
$scope.isCordova = isCordova;
|
||||
|
||||
window.ignoreMobilePause = true;
|
||||
$scope.$on('$destroy', function() {
|
||||
$timeout(function(){
|
||||
window.ignoreMobilePause = false;
|
||||
}, 100);
|
||||
});
|
||||
|
||||
var reader = new FileReader();
|
||||
|
||||
var updateStatus = function(status) {
|
||||
$scope.importStatus = status;
|
||||
}
|
||||
|
||||
var _importBackup = function(str) {
|
||||
var password = $scope.password;
|
||||
updateStatus('Importing profile - Setting things up...');
|
||||
|
||||
identityService.importProfile(str,password, function(err, iden) {
|
||||
if (err) {
|
||||
$rootScope.starting = false;
|
||||
copay.logger.warn(err);
|
||||
if ((err.toString() || '').match('BADSTR')) {
|
||||
$scope.error = 'Bad password or corrupt profile file';
|
||||
} else if ((err.toString() || '').match('EEXISTS')) {
|
||||
$scope.error = 'Profile already exists';
|
||||
} else {
|
||||
$scope.error = 'Unknown error';
|
||||
}
|
||||
$timeout(function() {
|
||||
$rootScope.$digest();
|
||||
}, 1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.getFile = function() {
|
||||
// If we use onloadend, we need to check the readyState.
|
||||
reader.onloadend = function(evt) {
|
||||
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
|
||||
var encryptedObj = evt.target.result;
|
||||
_importBackup(encryptedObj);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
$scope.import = function(form) {
|
||||
|
||||
if (form.$invalid) {
|
||||
$scope.error = 'Please enter the required fields';
|
||||
return;
|
||||
}
|
||||
var backupFile = $scope.file;
|
||||
var backupText = form.backupText.$modelValue;
|
||||
var password = form.password.$modelValue;
|
||||
|
||||
if (!backupFile && !backupText) {
|
||||
$scope.error = 'Please, select your backup file';
|
||||
return;
|
||||
}
|
||||
|
||||
$rootScope.starting = true;
|
||||
|
||||
$timeout(function() {
|
||||
|
||||
if (backupFile) {
|
||||
reader.readAsBinaryString(backupFile);
|
||||
} else {
|
||||
_importBackup(backupText);
|
||||
}
|
||||
}, 100);
|
||||
};
|
||||
});
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('IndexController', function($scope, $timeout, go, isCordova, identityService, notification) {
|
||||
$scope.init = function() {
|
||||
|
||||
};
|
||||
|
||||
$scope.resendVerificationEmail = function() {
|
||||
$scope.loading = true;
|
||||
identityService.resendVerificationEmail(function(err) {
|
||||
if (err) {
|
||||
notification.error('Could not send email', 'There was a problem sending the verification email.');
|
||||
}
|
||||
else {
|
||||
notification.success('Email sent', 'Check your inbox and confirms the email');
|
||||
$scope.hideReSendButton = true;
|
||||
}
|
||||
$scope.loading = null;
|
||||
$timeout(function() {
|
||||
$scope.$digest();
|
||||
}, 1);
|
||||
return;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.openMenu = function() {
|
||||
go.swipe(true);
|
||||
};
|
||||
|
||||
$scope.closeMenu = function() {
|
||||
go.swipe();
|
||||
};
|
||||
|
||||
});
|
||||
|
|
@ -1,160 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('JoinController',
|
||||
function($scope, $rootScope, $timeout, isMobile, notification, identityService) {
|
||||
$rootScope.fromSetup = false;
|
||||
$scope.loading = false;
|
||||
$scope.isMobile = isMobile.any();
|
||||
$rootScope.title = 'Join shared wallet';
|
||||
$rootScope.hideWalletNavigation = true;
|
||||
|
||||
|
||||
// QR code Scanner
|
||||
var cameraInput;
|
||||
var video;
|
||||
var canvas;
|
||||
var $video;
|
||||
var context;
|
||||
var localMediaStream;
|
||||
|
||||
$scope.hideAdv = true;
|
||||
|
||||
|
||||
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
|
||||
|
||||
if (!window.cordova && !navigator.getUserMedia)
|
||||
$scope.disableScanner = 1;
|
||||
|
||||
var _scan = function(evt) {
|
||||
if (localMediaStream) {
|
||||
context.drawImage(video, 0, 0, 300, 225);
|
||||
|
||||
try {
|
||||
qrcode.decode();
|
||||
} catch (e) {
|
||||
//qrcodeError(e);
|
||||
}
|
||||
}
|
||||
|
||||
$timeout(_scan, 500);
|
||||
};
|
||||
|
||||
var _successCallback = function(stream) {
|
||||
video.src = (window.URL && window.URL.createObjectURL(stream)) || stream;
|
||||
localMediaStream = stream;
|
||||
video.play();
|
||||
$timeout(_scan, 1000);
|
||||
};
|
||||
|
||||
var _scanStop = function() {
|
||||
$scope.showScanner = false;
|
||||
if (!$scope.isMobile) {
|
||||
if (localMediaStream && localMediaStream.stop) localMediaStream.stop();
|
||||
localMediaStream = null;
|
||||
video.src = '';
|
||||
}
|
||||
};
|
||||
|
||||
var _videoError = function(err) {
|
||||
_scanStop();
|
||||
};
|
||||
|
||||
qrcode.callback = function(data) {
|
||||
_scanStop();
|
||||
|
||||
$scope.$apply(function() {
|
||||
$scope.connectionId = data;
|
||||
$scope.joinForm.connectionId.$setViewValue(data);
|
||||
$scope.joinForm.connectionId.$render();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.cancelScanner = function() {
|
||||
_scanStop();
|
||||
};
|
||||
|
||||
$scope.openScanner = function() {
|
||||
if (window.cordova) return $scope.scannerIntent();
|
||||
|
||||
$scope.showScanner = true;
|
||||
|
||||
// Wait a moment until the canvas shows
|
||||
$timeout(function() {
|
||||
canvas = document.getElementById('qr-canvas');
|
||||
context = canvas.getContext('2d');
|
||||
|
||||
if ($scope.isMobile) {
|
||||
cameraInput = document.getElementById('qrcode-camera');
|
||||
cameraInput.addEventListener('change', _scan, false);
|
||||
} else {
|
||||
video = document.getElementById('qrcode-scanner-video');
|
||||
$video = angular.element(video);
|
||||
canvas.width = 300;
|
||||
canvas.height = 225;
|
||||
context.clearRect(0, 0, 300, 225);
|
||||
|
||||
navigator.getUserMedia({
|
||||
video: true
|
||||
}, _successCallback, _videoError);
|
||||
}
|
||||
}, 500);
|
||||
};
|
||||
|
||||
$scope.scannerIntent = function() {
|
||||
window.ignoreMobilePause = true;
|
||||
cordova.plugins.barcodeScanner.scan(
|
||||
function onSuccess(result) {
|
||||
$timeout(function(){
|
||||
window.ignoreMobilePause = false;
|
||||
}, 100);
|
||||
if (result.cancelled) return;
|
||||
|
||||
$scope.connectionId = result.text;
|
||||
$rootScope.$digest();
|
||||
},
|
||||
function onError(error) {
|
||||
$timeout(function(){
|
||||
window.ignoreMobilePause = false;
|
||||
}, 100);
|
||||
alert('Scanning error');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
$scope.join = function(form) {
|
||||
if (form && form.$invalid) {
|
||||
notification.error('Error', 'Please enter the required fields');
|
||||
return;
|
||||
}
|
||||
|
||||
$rootScope.starting = true;
|
||||
identityService.joinWallet({
|
||||
secret: $scope.connectionId,
|
||||
nickname: $scope.nickname,
|
||||
privateHex: $scope.private,
|
||||
}, function(err) {
|
||||
$rootScope.starting = false;
|
||||
if (err) {
|
||||
if (err === 'joinError')
|
||||
notification.error('Fatal error connecting to Insight server');
|
||||
else if (err === 'walletFull')
|
||||
notification.error('The wallet is full');
|
||||
else if (err === 'walletAlreadyExists')
|
||||
notification.error('Wallet already exists', 'Cannot join again from the same profile');
|
||||
else if (err === 'badNetwork')
|
||||
notification.error('Network Error', 'Wallet network configuration missmatch');
|
||||
else if (err === 'badSecret')
|
||||
notification.error('Bad secret', 'The secret string you entered is invalid');
|
||||
else {
|
||||
notification.error('Error', err.message || err);
|
||||
}
|
||||
}
|
||||
$timeout(function () { $scope.$digest(); }, 1);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
$scope.$on("$destroy", function () {
|
||||
$rootScope.hideWalletNavigation = false;
|
||||
});
|
||||
});
|
||||
|
|
@ -1,183 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('MoreController',
|
||||
function($scope, $rootScope, $location, $filter, $timeout, balanceService, notification, rateService, backupService, identityService, isMobile, isCordova, go, pendingTxsService) {
|
||||
var w = $rootScope.wallet;
|
||||
var max = $rootScope.quotaPerItem;
|
||||
$scope.isSafari = isMobile.Safari();
|
||||
$scope.isCordova = isCordova;
|
||||
$scope.wallet = w;
|
||||
$scope.error = null;
|
||||
$scope.success = null;
|
||||
|
||||
var bits = w.sizes().total;
|
||||
w.kb = $filter('noFractionNumber')(bits / 1000, 1);
|
||||
if (max) {
|
||||
w.usage = $filter('noFractionNumber')(bits / max * 100, 0);
|
||||
}
|
||||
|
||||
$rootScope.title = 'Settings';
|
||||
|
||||
$scope.unitOpts = [{
|
||||
name: 'Satoshis (100,000,000 satoshis = 1BTC)',
|
||||
shortName: 'SAT',
|
||||
value: 1,
|
||||
decimals: 0
|
||||
}, {
|
||||
name: 'bits (1,000,000 bits = 1BTC)',
|
||||
shortName: 'bits',
|
||||
value: 100,
|
||||
decimals: 2
|
||||
}, {
|
||||
name: 'mBTC (1,000 mBTC = 1BTC)',
|
||||
shortName: 'mBTC',
|
||||
value: 100000,
|
||||
decimals: 5
|
||||
}, {
|
||||
name: 'BTC',
|
||||
shortName: 'BTC',
|
||||
value: 100000000,
|
||||
decimals: 8
|
||||
}];
|
||||
|
||||
$scope.selectedAlternative = {
|
||||
name: w.settings.alternativeName,
|
||||
isoCode: w.settings.alternativeIsoCode
|
||||
};
|
||||
$scope.alternativeOpts = rateService.isAvailable() ?
|
||||
rateService.listAlternatives() : [$scope.selectedAlternative];
|
||||
|
||||
rateService.whenAvailable(function() {
|
||||
$scope.alternativeOpts = rateService.listAlternatives();
|
||||
for (var ii in $scope.alternativeOpts) {
|
||||
if (w.settings.alternativeIsoCode === $scope.alternativeOpts[ii].isoCode) {
|
||||
$scope.selectedAlternative = $scope.alternativeOpts[ii];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
for (var ii in $scope.unitOpts) {
|
||||
if (w.settings.unitName === $scope.unitOpts[ii].shortName) {
|
||||
$scope.selectedUnit = $scope.unitOpts[ii];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$scope.hideAdv = true;
|
||||
$scope.hidePriv = true;
|
||||
$scope.hideSecret = true;
|
||||
if (w) {
|
||||
$scope.priv = w.privateKey.toObj().extendedPrivateKeyString;
|
||||
$scope.secret = w.getSecret();
|
||||
}
|
||||
|
||||
setTimeout(function() {
|
||||
$scope.$digest();
|
||||
}, 1);
|
||||
|
||||
$scope.save = function() {
|
||||
var w = $rootScope.wallet;
|
||||
w.changeSettings({
|
||||
unitName: $scope.selectedUnit.shortName,
|
||||
unitToSatoshi: $scope.selectedUnit.value,
|
||||
unitDecimals: $scope.selectedUnit.decimals,
|
||||
alternativeName: $scope.selectedAlternative.name,
|
||||
alternativeIsoCode: $scope.selectedAlternative.isoCode,
|
||||
});
|
||||
notification.success('Success', $filter('translate')('settings successfully updated'));
|
||||
balanceService.update(w, function() {
|
||||
pendingTxsService.update();
|
||||
$rootScope.$digest();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.purge = function(deleteAll) {
|
||||
var removed = w.purgeTxProposals(deleteAll);
|
||||
if (removed) {
|
||||
balanceService.update(w, function() {
|
||||
$rootScope.$digest();
|
||||
}, true);
|
||||
}
|
||||
notification.info('Transactions Proposals Purged', removed + ' ' + $filter('translate')('transaction proposal purged'));
|
||||
};
|
||||
|
||||
$scope.updateIndexes = function() {
|
||||
var w = $rootScope.wallet;
|
||||
notification.info('Scaning for transactions', 'Using derived addresses from your wallet');
|
||||
w.updateIndexes(function(err) {
|
||||
notification.info('Scan Ended', 'Updating balance');
|
||||
if (err) {
|
||||
notification.error('Error', $filter('translate')('Error updating indexes: ') + err);
|
||||
}
|
||||
balanceService.update(w, function() {
|
||||
notification.info('Finished', 'The balance is updated using the derived addresses');
|
||||
w.sendIndexes();
|
||||
$rootScope.$digest();
|
||||
}, true);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.deleteWallet = function() {
|
||||
$scope.loading = true;
|
||||
$timeout(function() {
|
||||
identityService.deleteWallet(w, function(err) {
|
||||
$scope.loading = false;
|
||||
if (err) {
|
||||
$scope.error = err.message || err;
|
||||
copay.logger.warn(err);
|
||||
$timeout(function () { $scope.$digest(); });
|
||||
} else {
|
||||
if ($rootScope.wallet) {
|
||||
go.walletHome();
|
||||
}
|
||||
$timeout(function() {
|
||||
notification.success('Success', 'The wallet "' + (w.name || w.id) + '" was deleted');
|
||||
});
|
||||
}
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
||||
$scope.copyText = function(text) {
|
||||
if (isCordova) {
|
||||
window.cordova.plugins.clipboard.copy(text);
|
||||
window.plugins.toast.showShortCenter('Copied to clipboard');
|
||||
}
|
||||
};
|
||||
|
||||
$scope.downloadWalletBackup = function() {
|
||||
backupService.walletDownload(w);
|
||||
};
|
||||
|
||||
$scope.viewWalletBackup = function() {
|
||||
$scope.loading = true;
|
||||
$timeout(function() {
|
||||
$scope.backupWalletPlainText = backupService.walletEncrypted(w);
|
||||
}, 100);
|
||||
};
|
||||
|
||||
$scope.copyWalletBackup = function() {
|
||||
var ew = backupService.walletEncrypted(w);
|
||||
window.cordova.plugins.clipboard.copy(ew);
|
||||
window.plugins.toast.showShortCenter('Copied to clipboard');
|
||||
};
|
||||
|
||||
$scope.sendWalletBackup = function() {
|
||||
if (isMobile.Android() || isMobile.Windows()) {
|
||||
window.ignoreMobilePause = true;
|
||||
}
|
||||
window.plugins.toast.showShortCenter('Preparing backup...');
|
||||
var name = (w.name || w.id);
|
||||
var ew = backupService.walletEncrypted(w);
|
||||
var properties = {
|
||||
subject: 'Copay Wallet Backup: ' + name,
|
||||
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 {}',
|
||||
isHtml: false
|
||||
};
|
||||
window.plugin.email.open(properties);
|
||||
};
|
||||
|
||||
});
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
var bitcore = require('bitcore');
|
||||
|
||||
angular.module('copayApp.controllers').controller('paymentUriController', function($rootScope, $scope, $routeParams, $location, go) {
|
||||
|
||||
// Build bitcoinURI with querystring
|
||||
var query = [];
|
||||
angular.forEach($location.search(), function(value, key) {
|
||||
query.push(key + "=" + value);
|
||||
});
|
||||
var queryString = query ? query.join("&") : null;
|
||||
var bitcoinURI = $routeParams.data + ( queryString ? '?' + queryString : '');
|
||||
var uri = new bitcore.BIP21(bitcoinURI);
|
||||
|
||||
if (uri && uri.address && (_.isString(uri.address) || uri.address.isValid()) ) {
|
||||
copay.logger.debug('Payment Intent:', bitcoinURI);
|
||||
$rootScope.pendingPayment = bitcoinURI;
|
||||
}
|
||||
|
||||
go.home();
|
||||
});
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
'use strict';
|
||||
angular.module('copayApp.controllers').controller('ProfileController', function($scope, $rootScope, $location, $modal, $filter, $timeout, backupService, identityService, isMobile, isCordova, notification) {
|
||||
$scope.username = $rootScope.iden.getName();
|
||||
$scope.isSafari = isMobile.Safari();
|
||||
$scope.isCordova = isCordova;
|
||||
|
||||
$rootScope.title = 'Profile';
|
||||
$scope.hideAdv = true;
|
||||
|
||||
$scope.downloadProfileBackup = function() {
|
||||
backupService.profileDownload($rootScope.iden);
|
||||
};
|
||||
|
||||
$scope.viewProfileBackup = function() {
|
||||
$scope.loading = true;
|
||||
$timeout(function() {
|
||||
$scope.backupProfilePlainText = backupService.profileEncrypted($rootScope.iden);
|
||||
}, 100);
|
||||
};
|
||||
|
||||
$scope.copyProfileBackup = function() {
|
||||
var ep = backupService.profileEncrypted($rootScope.iden);
|
||||
window.cordova.plugins.clipboard.copy(ep);
|
||||
window.plugins.toast.showShortCenter('Copied to clipboard');
|
||||
};
|
||||
|
||||
$scope.sendProfileBackup = function() {
|
||||
if (isMobile.Android() || isMobile.Windows()) {
|
||||
window.ignoreMobilePause = true;
|
||||
}
|
||||
window.plugins.toast.showShortCenter('Preparing backup...');
|
||||
var name = $rootScope.iden.fullName;
|
||||
var ep = backupService.profileEncrypted($rootScope.iden);
|
||||
var properties = {
|
||||
subject: 'Copay Profile Backup: ' + name,
|
||||
body: 'Here is the encrypted backup of the profile '
|
||||
+ name + ': \n\n' + ep
|
||||
+ '\n\n To import this backup, copy all text between {...}, including the symbols {}',
|
||||
isHtml: false
|
||||
};
|
||||
window.plugin.email.open(properties);
|
||||
};
|
||||
|
||||
$scope.init = function() {
|
||||
if ($rootScope.quotaPerItem) {
|
||||
$scope.perItem = $filter('noFractionNumber')($rootScope.quotaPerItem / 1000, 1);
|
||||
$scope.nrWallets = parseInt($rootScope.quotaItems) - 1;
|
||||
}
|
||||
// no need to add event handlers here. Wallet deletion is handle by callback.
|
||||
};
|
||||
|
||||
$scope.deleteProfile = function() {
|
||||
$scope.loading = true;
|
||||
identityService.deleteProfile(function(err, res) {
|
||||
$scope.loading = false;
|
||||
if (err) {
|
||||
log.warn(err);
|
||||
notification.error('Error', 'Could not delete profile');
|
||||
$timeout(function () { $scope.$digest(); });
|
||||
}
|
||||
else {
|
||||
$location.path('/');
|
||||
$timeout(function() {
|
||||
notification.success('Success', 'Profile successfully deleted');
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('ReceiveController',
|
||||
function($scope, $rootScope, $timeout, $modal, isCordova, isMobile) {
|
||||
|
||||
$scope.newAddr = function() {
|
||||
var w = $rootScope.wallet;
|
||||
var lastAddr = w.generateAddress(null);
|
||||
$scope.setAddressList();
|
||||
$scope.addr = lastAddr;
|
||||
};
|
||||
|
||||
$scope.copyAddress = function(addr) {
|
||||
if (isCordova) {
|
||||
window.cordova.plugins.clipboard.copy('bitcoin:' + addr);
|
||||
window.plugins.toast.showShortCenter('Copied to clipboard');
|
||||
}
|
||||
};
|
||||
|
||||
$scope.shareAddress = function(addr) {
|
||||
if (isCordova) {
|
||||
if (isMobile.Android() || isMobile.Windows()) {
|
||||
window.ignoreMobilePause = true;
|
||||
}
|
||||
window.plugins.socialsharing.share('bitcoin:' + addr, null, null, null);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.init = function() {
|
||||
$rootScope.title = 'Receive';
|
||||
$scope.showAll = false;
|
||||
$scope.isCordova = isCordova;
|
||||
|
||||
var w = $rootScope.wallet;
|
||||
var lastAddr = _.first(w.getAddressesOrdered());
|
||||
var balance = w.balanceInfo.balanceByAddr;
|
||||
$scope.setAddressList();
|
||||
|
||||
while (balance && balance[lastAddr] > 0) {
|
||||
$scope.loading = true;
|
||||
lastAddr = w.generateAddress(null);
|
||||
};
|
||||
$scope.loading = false;
|
||||
$scope.addr = lastAddr;
|
||||
};
|
||||
|
||||
$scope.openAddressModal = function(address) {
|
||||
var scope = $scope;
|
||||
var ModalInstanceCtrl = function($scope, $modalInstance, address) {
|
||||
$scope.address = address;
|
||||
$scope.isCordova = isCordova;
|
||||
$scope.copyAddress = function(addr) {
|
||||
scope.copyAddress(addr);
|
||||
};
|
||||
|
||||
$scope.cancel = function() {
|
||||
$modalInstance.dismiss('cancel');
|
||||
};
|
||||
};
|
||||
|
||||
$modal.open({
|
||||
templateUrl: 'views/modals/qr-address.html',
|
||||
windowClass: 'small',
|
||||
controller: ModalInstanceCtrl,
|
||||
resolve: {
|
||||
address: function() {
|
||||
return address;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.toggleShowAll = function() {
|
||||
$scope.showAll = !$scope.showAll;
|
||||
$scope.setAddressList();
|
||||
};
|
||||
|
||||
$scope.setAddressList = function() {
|
||||
if ($scope.showAll) {
|
||||
var w = $rootScope.wallet;
|
||||
var balance = w.balanceInfo.balanceByAddr;
|
||||
|
||||
var addresses = w.getAddressesOrdered();
|
||||
if (addresses) {
|
||||
$scope.addrLength = addresses.length;
|
||||
|
||||
if (!$scope.showAll)
|
||||
addresses = addresses.slice(0, 3);
|
||||
|
||||
var list = [];
|
||||
_.each(addresses, function(address, index) {
|
||||
list.push({
|
||||
'index': index,
|
||||
'address': address,
|
||||
'balance': balance ? balance[address] : null,
|
||||
'isChange': w.addressIsChange(address),
|
||||
});
|
||||
});
|
||||
$scope.addresses = list;
|
||||
}
|
||||
} else {
|
||||
$scope.addresses = [];
|
||||
}
|
||||
};
|
||||
}
|
||||
);
|
||||
|
|
@ -1,602 +0,0 @@
|
|||
'use strict';
|
||||
var bitcore = require('bitcore');
|
||||
var preconditions = require('preconditions').singleton();
|
||||
|
||||
angular.module('copayApp.controllers').controller('SendController',
|
||||
function($scope, $rootScope, $window, $timeout, $modal, $filter, notification, isMobile, rateService, txStatus, isCordova) {
|
||||
|
||||
$scope.init = function() {
|
||||
var w = $rootScope.wallet;
|
||||
preconditions.checkState(w);
|
||||
|
||||
preconditions.checkState(w.settings.unitToSatoshi);
|
||||
|
||||
$scope.isMobile = isMobile.any();
|
||||
$scope.isWindowsPhoneApp = isMobile.Windows() && isCordova;
|
||||
$rootScope.wpInputFocused = false;
|
||||
|
||||
$scope.isShared = w.isShared();
|
||||
$scope.requiresMultipleSignatures = w.requiresMultipleSignatures();
|
||||
$rootScope.title = $scope.requiresMultipleSignatures ? 'Send Proposal' : 'Send';
|
||||
$scope.loading = false;
|
||||
$scope.error = $scope.success = null;
|
||||
|
||||
$scope.alternativeName = w.settings.alternativeName;
|
||||
$scope.alternativeIsoCode = w.settings.alternativeIsoCode;
|
||||
|
||||
$scope.isRateAvailable = false;
|
||||
$scope.rateService = rateService;
|
||||
$scope.showScanner = false;
|
||||
$scope.myId = w.getMyCopayerId();
|
||||
$scope.isMobile = isMobile.any();
|
||||
|
||||
if ($rootScope.pendingPayment) {
|
||||
$timeout(function() {
|
||||
$scope.setFromUri($rootScope.pendingPayment)
|
||||
$rootScope.pendingPayment = null;
|
||||
}, 100);
|
||||
}
|
||||
|
||||
$scope.setInputs();
|
||||
$scope.setScanner();
|
||||
|
||||
rateService.whenAvailable(function() {
|
||||
$scope.isRateAvailable = true;
|
||||
$scope.$digest();
|
||||
});
|
||||
};
|
||||
|
||||
if (isCordova) {
|
||||
var openScannerCordova = $rootScope.$on('dataScanned', function(event, data) {
|
||||
$scope.sendForm.address.$setViewValue(data);
|
||||
$scope.sendForm.address.$render();
|
||||
});
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
openScannerCordova();
|
||||
});
|
||||
}
|
||||
|
||||
$scope.formFocus = function(what) {
|
||||
if (!$scope.isWindowsPhoneApp) return
|
||||
|
||||
if (!what) {
|
||||
$rootScope.wpInputFocused = false;
|
||||
$scope.hideAddress = false;
|
||||
$scope.hideAmount = false;
|
||||
|
||||
} else {
|
||||
$rootScope.wpInputFocused = true;
|
||||
if (what == 'amount') {
|
||||
$scope.hideAddress = true;
|
||||
} else if (what == 'msg') {
|
||||
$scope.hideAddress = true;
|
||||
$scope.hideAmount = true;
|
||||
}
|
||||
|
||||
}
|
||||
$timeout(function() {
|
||||
$rootScope.$digest();
|
||||
}, 1);
|
||||
};
|
||||
|
||||
$scope.setInputs = function() {
|
||||
var w = $rootScope.wallet;
|
||||
var unitToSat = w.settings.unitToSatoshi;
|
||||
var satToUnit = 1 / unitToSat;
|
||||
/**
|
||||
* Setting the two related amounts as properties prevents an infinite
|
||||
* recursion for watches while preserving the original angular updates
|
||||
*
|
||||
*/
|
||||
Object.defineProperty($scope,
|
||||
"_alternative", {
|
||||
get: function() {
|
||||
return this.__alternative;
|
||||
},
|
||||
set: function(newValue) {
|
||||
this.__alternative = newValue;
|
||||
if (typeof(newValue) === 'number' && $scope.isRateAvailable) {
|
||||
this._amount = parseFloat(
|
||||
(rateService.fromFiat(newValue, $scope.alternativeIsoCode) * satToUnit).toFixed(w.settings.unitDecimals), 10);
|
||||
} else {
|
||||
this._amount = 0;
|
||||
}
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty($scope,
|
||||
"_amount", {
|
||||
get: function() {
|
||||
return this.__amount;
|
||||
},
|
||||
set: function(newValue) {
|
||||
this.__amount = newValue;
|
||||
if (typeof(newValue) === 'number' && $scope.isRateAvailable) {
|
||||
this.__alternative = parseFloat(
|
||||
(rateService.toFiat(newValue * unitToSat, $scope.alternativeIsoCode)).toFixed(2), 10);
|
||||
} else {
|
||||
this.__alternative = 0;
|
||||
}
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Object.defineProperty($scope,
|
||||
"_address", {
|
||||
get: function() {
|
||||
return this.__address;
|
||||
},
|
||||
set: function(newValue) {
|
||||
this.__address = $scope.onAddressChange(newValue);
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
};
|
||||
|
||||
$scope.setScanner = function() {
|
||||
navigator.getUserMedia = navigator.getUserMedia ||
|
||||
navigator.webkitGetUserMedia || navigator.mozGetUserMedia ||
|
||||
navigator.msGetUserMedia;
|
||||
window.URL = window.URL || window.webkitURL ||
|
||||
window.mozURL || window.msURL;
|
||||
|
||||
if (!window.cordova && !navigator.getUserMedia)
|
||||
$scope.disableScanner = 1;
|
||||
};
|
||||
|
||||
|
||||
$scope.setError = function(err) {
|
||||
var w = $rootScope.wallet;
|
||||
copay.logger.warn(err);
|
||||
|
||||
var msg = err.toString();
|
||||
if (msg.match('BIG'))
|
||||
msg = 'The transaction have too many inputs. Try creating many transactions for smaller amounts'
|
||||
|
||||
if (msg.match('totalNeededAmount') || msg.match('unspent not set'))
|
||||
msg = 'Insufficient funds'
|
||||
|
||||
if (msg.match('expired'))
|
||||
msg = 'The payment request has expired';
|
||||
|
||||
if (msg.match('XMLHttpRequest'))
|
||||
msg = 'Error when sending to the blockchain. Resend it from Home';
|
||||
|
||||
var message = 'The transaction' + ($scope.requiresMultipleSignatures ? ' proposal' : '') +
|
||||
' could not be created: ' + msg;
|
||||
|
||||
$scope.error = message;
|
||||
|
||||
$timeout(function() {
|
||||
$scope.$digest();
|
||||
}, 1);
|
||||
};
|
||||
|
||||
$scope.submitForm = function(form) {
|
||||
var w = $rootScope.wallet;
|
||||
var unitToSat = w.settings.unitToSatoshi;
|
||||
|
||||
if (form.$invalid) {
|
||||
$scope.error = 'Unable to send transaction proposal';
|
||||
return;
|
||||
}
|
||||
|
||||
if (isCordova) {
|
||||
window.plugins.spinnerDialog.show(null, 'Creating transaction...', true);
|
||||
}
|
||||
|
||||
$scope.loading = true;
|
||||
if ($scope.isWindowsPhoneApp)
|
||||
$rootScope.wpInputFocused = true;
|
||||
|
||||
$timeout(function () {
|
||||
var comment = form.comment.$modelValue;
|
||||
var merchantData = $scope._merchantData;
|
||||
var address, amount;
|
||||
if (!merchantData) {
|
||||
address = form.address.$modelValue;
|
||||
amount = parseInt((form.amount.$modelValue * unitToSat).toFixed(0));
|
||||
}
|
||||
|
||||
w.spend({
|
||||
merchantData: merchantData,
|
||||
toAddress: address,
|
||||
amountSat: amount,
|
||||
comment: comment,
|
||||
}, function (err, txid, status) {
|
||||
if (isCordova) {
|
||||
window.plugins.spinnerDialog.hide();
|
||||
}
|
||||
$scope.loading = false;
|
||||
if ($scope.isWindowsPhoneApp)
|
||||
$rootScope.wpInputFocused = false;
|
||||
|
||||
if (err) {
|
||||
$scope.setError(err);
|
||||
}
|
||||
else {
|
||||
txStatus.notify(status);
|
||||
$scope.resetForm();
|
||||
}
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
||||
// QR code Scanner
|
||||
var cameraInput;
|
||||
var video;
|
||||
var canvas;
|
||||
var $video;
|
||||
var context;
|
||||
var localMediaStream;
|
||||
|
||||
var _scan = function(evt) {
|
||||
if ($scope.isMobile) {
|
||||
$scope.scannerLoading = true;
|
||||
var files = evt.target.files;
|
||||
|
||||
if (files.length === 1 && files[0].type.indexOf('image/') === 0) {
|
||||
var file = files[0];
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.onload = (function(theFile) {
|
||||
return function(e) {
|
||||
var mpImg = new MegaPixImage(file);
|
||||
mpImg.render(canvas, {
|
||||
maxWidth: 200,
|
||||
maxHeight: 200,
|
||||
orientation: 6
|
||||
});
|
||||
|
||||
$timeout(function() {
|
||||
qrcode.width = canvas.width;
|
||||
qrcode.height = canvas.height;
|
||||
qrcode.imagedata = context.getImageData(0, 0, qrcode.width, qrcode.height);
|
||||
|
||||
try {
|
||||
qrcode.decode();
|
||||
} catch (e) {
|
||||
// error decoding QR
|
||||
}
|
||||
}, 1500);
|
||||
};
|
||||
})(file);
|
||||
|
||||
// Read in the file as a data URL
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
} else {
|
||||
if (localMediaStream) {
|
||||
context.drawImage(video, 0, 0, 300, 225);
|
||||
|
||||
try {
|
||||
qrcode.decode();
|
||||
} catch (e) {
|
||||
//qrcodeError(e);
|
||||
}
|
||||
}
|
||||
|
||||
$timeout(_scan, 500);
|
||||
}
|
||||
};
|
||||
|
||||
var _successCallback = function(stream) {
|
||||
video.src = (window.URL && window.URL.createObjectURL(stream)) || stream;
|
||||
localMediaStream = stream;
|
||||
video.play();
|
||||
$timeout(_scan, 1000);
|
||||
};
|
||||
|
||||
var _scanStop = function() {
|
||||
$scope.scannerLoading = false;
|
||||
$scope.showScanner = false;
|
||||
if (!$scope.isMobile) {
|
||||
if (localMediaStream && localMediaStream.stop) localMediaStream.stop();
|
||||
localMediaStream = null;
|
||||
video.src = '';
|
||||
}
|
||||
};
|
||||
|
||||
var _videoError = function(err) {
|
||||
_scanStop();
|
||||
};
|
||||
|
||||
qrcode.callback = function(data) {
|
||||
_scanStop();
|
||||
$scope.$apply(function() {
|
||||
$scope.sendForm.address.$setViewValue(data);
|
||||
$scope.sendForm.address.$render();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.cancelScanner = function() {
|
||||
_scanStop();
|
||||
};
|
||||
|
||||
$scope.openScanner = function() {
|
||||
$scope.showScanner = true;
|
||||
|
||||
// Wait a moment until the canvas shows
|
||||
$timeout(function() {
|
||||
canvas = document.getElementById('qr-canvas');
|
||||
context = canvas.getContext('2d');
|
||||
|
||||
if ($scope.isMobile) {
|
||||
cameraInput = document.getElementById('qrcode-camera');
|
||||
cameraInput.addEventListener('change', _scan, false);
|
||||
} else {
|
||||
video = document.getElementById('qrcode-scanner-video');
|
||||
$video = angular.element(video);
|
||||
canvas.width = 300;
|
||||
canvas.height = 225;
|
||||
context.clearRect(0, 0, 300, 225);
|
||||
|
||||
navigator.getUserMedia({
|
||||
video: true
|
||||
}, _successCallback, _videoError);
|
||||
}
|
||||
}, 500);
|
||||
};
|
||||
|
||||
$scope.setTopAmount = function() {
|
||||
var w = $rootScope.wallet;
|
||||
var form = $scope.sendForm;
|
||||
if (form) {
|
||||
form.amount.$setViewValue(w.balanceInfo.topAmount);
|
||||
form.amount.$render();
|
||||
form.amount.$isValid = true;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.setForm = function(to, amount, comment) {
|
||||
var form = $scope.sendForm;
|
||||
if (to) {
|
||||
form.address.$setViewValue(to);
|
||||
form.address.$isValid = true;
|
||||
form.address.$render();
|
||||
$scope.lockAddress = true;
|
||||
}
|
||||
|
||||
if (amount) {
|
||||
form.amount.$setViewValue("" + amount);
|
||||
form.amount.$isValid = true;
|
||||
form.amount.$render();
|
||||
$scope.lockAmount = true;
|
||||
}
|
||||
|
||||
if (comment) {
|
||||
form.comment.$setViewValue(comment);
|
||||
form.comment.$isValid = true;
|
||||
form.comment.$render();
|
||||
}
|
||||
};
|
||||
|
||||
$scope.resetForm = function() {
|
||||
var form = $scope.sendForm;
|
||||
|
||||
$scope.fetchingURL = null;
|
||||
$scope._merchantData = $scope._domain = null;
|
||||
|
||||
$scope.lockAddress = false;
|
||||
$scope.lockAmount = false;
|
||||
|
||||
$scope._amount = $scope._address = null;
|
||||
|
||||
form.amount.$pristine = true;
|
||||
form.amount.$setViewValue('');
|
||||
form.amount.$render();
|
||||
|
||||
form.comment.$setViewValue('');
|
||||
form.comment.$render();
|
||||
form.$setPristine();
|
||||
|
||||
if (form.address) {
|
||||
form.address.$pristine = true;
|
||||
form.address.$setViewValue('');
|
||||
form.address.$render();
|
||||
}
|
||||
$timeout(function() {
|
||||
$rootScope.$digest();
|
||||
}, 1);
|
||||
};
|
||||
|
||||
var $oscope = $scope;
|
||||
$scope.openPPModal = function(merchantData) {
|
||||
var ModalInstanceCtrl = function($scope, $modalInstance) {
|
||||
var w = $rootScope.wallet;
|
||||
var satToUnit = 1 / w.settings.unitToSatoshi;
|
||||
$scope.md = merchantData;
|
||||
$scope.alternative = $oscope._alternative;
|
||||
$scope.alternativeIsoCode = $oscope.alternativeIsoCode;
|
||||
$scope.isRateAvailable = $oscope.isRateAvailable;
|
||||
$scope.unitTotal = (merchantData.total * satToUnit).toFixed(w.settings.unitDecimals);
|
||||
|
||||
$scope.cancel = function() {
|
||||
$modalInstance.dismiss('cancel');
|
||||
};
|
||||
};
|
||||
$modal.open({
|
||||
templateUrl: 'views/modals/paypro.html',
|
||||
windowClass: 'medium',
|
||||
controller: ModalInstanceCtrl,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
$scope.setFromPayPro = function(uri) {
|
||||
|
||||
var isChromeApp = window.chrome && chrome.runtime && chrome.runtime.id;
|
||||
if (isChromeApp) {
|
||||
$scope.error = 'Payment Protocol not yet supported on ChromeApp';
|
||||
return;
|
||||
}
|
||||
|
||||
var w = $rootScope.wallet;
|
||||
var satToUnit = 1 / w.settings.unitToSatoshi;
|
||||
$scope.fetchingURL = uri;
|
||||
$scope.loading = true;
|
||||
|
||||
|
||||
// Payment Protocol URI (BIP-72)
|
||||
w.fetchPaymentRequest({
|
||||
url: uri
|
||||
}, function(err, merchantData) {
|
||||
$scope.loading = false;
|
||||
$scope.fetchingURL = null;
|
||||
|
||||
if (err) {
|
||||
copay.logger.warn(err);
|
||||
$scope.resetForm();
|
||||
var msg = err.toString();
|
||||
if (msg.match('HTTP')) {
|
||||
msg = 'Could not fetch payment information';
|
||||
}
|
||||
$scope.error = msg;
|
||||
} else {
|
||||
$scope._merchantData = merchantData;
|
||||
$scope._domain = merchantData.domain;
|
||||
$scope.setForm(null, (merchantData.total * satToUnit).toFixed(w.settings.unitDecimals));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.setFromUri = function(uri) {
|
||||
function sanitizeUri(uri) {
|
||||
// Fixes when a region uses comma to separate decimals
|
||||
var regex = /[\?\&]amount=(\d+([\,\.]\d+)?)/i;
|
||||
var match = regex.exec(uri);
|
||||
if (!match || match.length === 0) {
|
||||
return uri;
|
||||
}
|
||||
var value = match[0].replace(',', '.');
|
||||
var newUri = uri.replace(regex, value);
|
||||
return newUri;
|
||||
};
|
||||
|
||||
var w = $rootScope.wallet;
|
||||
var satToUnit = 1 / w.settings.unitToSatoshi;
|
||||
var form = $scope.sendForm;
|
||||
|
||||
uri = sanitizeUri(uri);
|
||||
|
||||
var parsed = new bitcore.BIP21(uri);
|
||||
if (!parsed.isValid() || !parsed.address.isValid()) {
|
||||
$scope.error = 'Invalid bitcoin URL';
|
||||
form.address.$isValid = false;
|
||||
return uri;
|
||||
};
|
||||
|
||||
var addr = parsed.address.toString();
|
||||
if (parsed.data.merchant)
|
||||
return $scope.setFromPayPro(parsed.data.merchant);
|
||||
|
||||
var amount = (parsed.data && parsed.data.amount) ?
|
||||
((parsed.data.amount * 100000000).toFixed(0) * satToUnit).toFixed(w.settings.unitDecimals) : 0;
|
||||
|
||||
$scope.setForm(addr, amount, parsed.data.message, true);
|
||||
return addr;
|
||||
};
|
||||
|
||||
$scope.onAddressChange = function(value) {
|
||||
$scope.error = $scope.success = null;
|
||||
if (!value) return '';
|
||||
|
||||
if (value.indexOf('bitcoin:') === 0) {
|
||||
return $scope.setFromUri(value);
|
||||
} else if (/^https?:\/\//.test(value)) {
|
||||
return $scope.setFromPayPro(value);
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
|
||||
$scope.openAddressBook = function() {
|
||||
var w = $rootScope.wallet;
|
||||
var modalInstance = $modal.open({
|
||||
templateUrl: 'views/modals/address-book.html',
|
||||
windowClass: 'large',
|
||||
controller: function($scope, $modalInstance) {
|
||||
|
||||
$scope.showForm = null;
|
||||
$scope.addressBook = w.addressBook;
|
||||
|
||||
$scope.hasEntry = function() {
|
||||
return _.keys($scope.addressBook).length > 0 ? true : false;
|
||||
};
|
||||
|
||||
$scope.toggleAddressBookEntry = function(key) {
|
||||
w.toggleAddressBookEntry(key);
|
||||
};
|
||||
|
||||
$scope.copyToSend = function(addr) {
|
||||
$modalInstance.close(addr);
|
||||
};
|
||||
|
||||
$scope.cancel = function(form) {
|
||||
$scope.error = $scope.success = $scope.newaddress = $scope.newlabel = null;
|
||||
clearForm(form);
|
||||
$scope.toggleForm();
|
||||
};
|
||||
|
||||
$scope.toggleForm = function() {
|
||||
$scope.showForm = !$scope.showForm;
|
||||
};
|
||||
|
||||
var clearForm = function(form) {
|
||||
form.newaddress.$pristine = true;
|
||||
form.newaddress.$setViewValue('');
|
||||
form.newaddress.$render();
|
||||
|
||||
form.newlabel.$pristine = true;
|
||||
form.newlabel.$setViewValue('');
|
||||
form.newlabel.$render();
|
||||
form.$setPristine();
|
||||
};
|
||||
|
||||
// TODO change to modal
|
||||
$scope.submitAddressBook = function(form) {
|
||||
if (form.$invalid) {
|
||||
return;
|
||||
}
|
||||
$scope.loading = true;
|
||||
$timeout(function() {
|
||||
var errorMsg;
|
||||
var entry = {
|
||||
"address": form.newaddress.$modelValue,
|
||||
"label": form.newlabel.$modelValue
|
||||
};
|
||||
try {
|
||||
w.setAddressBook(entry.address, entry.label);
|
||||
} catch (e) {
|
||||
copay.logger.warn(e);
|
||||
errorMsg = e.message;
|
||||
}
|
||||
|
||||
if (errorMsg) {
|
||||
$scope.error = errorMsg;
|
||||
} else {
|
||||
clearForm(form);
|
||||
$scope.toggleForm();
|
||||
notification.success('Entry created', 'New addressbook entry created')
|
||||
}
|
||||
$scope.loading = false;
|
||||
$rootScope.$digest();
|
||||
}, 100);
|
||||
return;
|
||||
};
|
||||
|
||||
$scope.close = function() {
|
||||
$modalInstance.dismiss('cancel');
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
modalInstance.result.then(function(addr) {
|
||||
$scope.setForm(addr);
|
||||
});
|
||||
};
|
||||
});
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('SettingsController', function($scope, $rootScope, $window, $route, $location, notification, configService) {
|
||||
$scope.title = 'Settings';
|
||||
$scope.insightLivenet = config.network.livenet.url;
|
||||
$scope.insightTestnet = config.network.testnet.url;
|
||||
$scope.defaultLogLevel = config.logLevel || 'log';
|
||||
|
||||
var logLevels = copay.logger.getLevels();
|
||||
|
||||
$scope.availableLogLevels = [];
|
||||
|
||||
for (var key in logLevels) {
|
||||
$scope.availableLogLevels.push({
|
||||
'name': key
|
||||
});
|
||||
}
|
||||
|
||||
$scope.availableStorages = [{
|
||||
name: 'In the cloud (Insight server)',
|
||||
pluginName: 'EncryptedInsightStorage',
|
||||
}, {
|
||||
name: 'On this device (localstorage)',
|
||||
pluginName: 'EncryptedLocalStorage',
|
||||
},
|
||||
// {
|
||||
// name: 'GoogleDrive',
|
||||
// pluginName: 'GoogleDrive',
|
||||
// }
|
||||
];
|
||||
|
||||
_.each($scope.availableStorages, function(v) {
|
||||
if (config.plugins[v.pluginName])
|
||||
$scope.selectedStorage = v;
|
||||
});
|
||||
|
||||
for (var ii in $scope.availableLogLevels) {
|
||||
if ($scope.defaultLogLevel === $scope.availableLogLevels[ii].name) {
|
||||
$scope.selectedLogLevel = $scope.availableLogLevels[ii];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$scope.save = function() {
|
||||
$scope.insightLivenet = copay.Insight.setCompleteUrl($scope.insightLivenet);
|
||||
$scope.insightTestnet = copay.Insight.setCompleteUrl($scope.insightTestnet);
|
||||
|
||||
var insightSettings = {
|
||||
livenet: {
|
||||
url: $scope.insightLivenet,
|
||||
transports: ['polling'],
|
||||
},
|
||||
testnet: {
|
||||
url: $scope.insightTestnet,
|
||||
transports: ['polling'],
|
||||
},
|
||||
}
|
||||
|
||||
var plugins = {};
|
||||
plugins[$scope.selectedStorage.pluginName] = true;
|
||||
|
||||
configService.set({
|
||||
network: insightSettings,
|
||||
plugins: plugins,
|
||||
logLevel: $scope.selectedLogLevel.name,
|
||||
EncryptedInsightStorage: _.extend(config.EncryptedInsightStorage, {
|
||||
url: insightSettings.livenet.url + '/api/email'
|
||||
}),
|
||||
rates: _.extend(config.rates, {
|
||||
url: insightSettings.livenet.url + '/api/rates'
|
||||
}),
|
||||
},
|
||||
function() {
|
||||
notification.success('Settings saved',"Settings were saved");
|
||||
$location.path('/');
|
||||
});
|
||||
};
|
||||
|
||||
$scope.reset = function() {
|
||||
configService.reset(function() {
|
||||
notification.success('Settings reseted',"Settings were reseted");
|
||||
$location.path('/');
|
||||
});
|
||||
};
|
||||
|
||||
});
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('SidebarController', function($scope, $rootScope, $location, $timeout, identityService, isMobile, isCordova, go) {
|
||||
|
||||
$scope.isMobile = isMobile.any();
|
||||
$scope.isCordova = isCordova;
|
||||
$scope.username = $rootScope.iden ? $rootScope.iden.getName() : '';
|
||||
|
||||
$scope.menu = [{
|
||||
'title': 'Home',
|
||||
'icon': 'icon-home',
|
||||
'link': 'homeWallet'
|
||||
}, {
|
||||
'title': 'Receive',
|
||||
'icon': 'icon-receive',
|
||||
'link': 'receive'
|
||||
}, {
|
||||
'title': 'Send',
|
||||
'icon': 'icon-paperplane',
|
||||
'link': 'send'
|
||||
}, {
|
||||
'title': 'History',
|
||||
'icon': 'icon-history',
|
||||
'link': 'history'
|
||||
}];
|
||||
|
||||
$scope.signout = function() {
|
||||
identityService.signout();
|
||||
};
|
||||
|
||||
$scope.isActive = function(item) {
|
||||
return item.link && item.link == $location.path().split('/')[1];
|
||||
};
|
||||
|
||||
$scope.switchWallet = function(wid) {
|
||||
$scope.walletSelection = false;
|
||||
identityService.setFocusedWallet(wid);
|
||||
go.walletHome();
|
||||
};
|
||||
|
||||
$scope.toggleWalletSelection = function() {
|
||||
$scope.walletSelection = !$scope.walletSelection;
|
||||
if (!$scope.walletSelection) return;
|
||||
$scope.setWallets();
|
||||
};
|
||||
|
||||
$scope.openScanner = function() {
|
||||
window.ignoreMobilePause = true;
|
||||
cordova.plugins.barcodeScanner.scan(
|
||||
function onSuccess(result) {
|
||||
$timeout(function() {
|
||||
window.ignoreMobilePause = false;
|
||||
}, 100);
|
||||
if (result.cancelled) return;
|
||||
|
||||
$timeout(function() {
|
||||
var data = result.text;
|
||||
$scope.$apply(function() {
|
||||
$rootScope.$emit('dataScanned', data);
|
||||
});
|
||||
}, 1000);
|
||||
},
|
||||
function onError(error) {
|
||||
$timeout(function() {
|
||||
window.ignoreMobilePause = false;
|
||||
}, 100);
|
||||
alert('Scanning error');
|
||||
}
|
||||
);
|
||||
go.send();
|
||||
};
|
||||
|
||||
$scope.init = function() {
|
||||
// This should be called only once.
|
||||
|
||||
// focused wallet change
|
||||
if ($rootScope.wallet) {
|
||||
$rootScope.$watch('wallet', function() {
|
||||
$scope.walletSelection = false;
|
||||
$scope.setWallets();
|
||||
});
|
||||
}
|
||||
|
||||
// wallet list change
|
||||
if ($rootScope.iden) {
|
||||
var iden = $rootScope.iden;
|
||||
iden.on('newWallet', function() {
|
||||
$scope.walletSelection = false;
|
||||
$scope.setWallets();
|
||||
});
|
||||
iden.on('walletDeleted', function(wid) {
|
||||
if (wid == $rootScope.wallet.id) {
|
||||
copay.logger.debug('Deleted focused wallet:', wid);
|
||||
|
||||
// new focus
|
||||
var newWid = $rootScope.iden.getLastFocusedWalletId();
|
||||
if (newWid && $rootScope.iden.getWalletById(newWid)) {
|
||||
identityService.setFocusedWallet(newWid);
|
||||
} else {
|
||||
copay.logger.debug('No wallets');
|
||||
identityService.noFocusedWallet(newWid);
|
||||
}
|
||||
}
|
||||
$scope.walletSelection = false;
|
||||
$scope.setWallets();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.setWallets = function() {
|
||||
if (!$rootScope.iden) return;
|
||||
var ret = _.filter($rootScope.iden.getWallets(), function(w) {
|
||||
return w;
|
||||
});
|
||||
$scope.wallets = _.sortBy(ret, 'name');
|
||||
};
|
||||
|
||||
$scope.openMenu = function() {
|
||||
go.swipe(true);
|
||||
};
|
||||
});
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
angular.module('copayApp.controllers').controller('signOutController', function(identityService) {
|
||||
|
||||
identityService.signout();
|
||||
|
||||
});
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('UnsupportedController',
|
||||
function($scope, $location) {
|
||||
if (localStorage && localStorage.length > 0) {
|
||||
$location.path('/');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('VersionController',
|
||||
function($scope, $rootScope, $http, $filter, notification) {
|
||||
|
||||
var w = $rootScope.wallet;
|
||||
|
||||
$scope.version = copay.version;
|
||||
$scope.commitHash = copay.commitHash;
|
||||
$scope.networkName = w ? w.getNetworkName() : '';
|
||||
if (_.isUndefined($rootScope.checkVersion))
|
||||
$rootScope.checkVersion = true;
|
||||
|
||||
if ($rootScope.checkVersion) {
|
||||
$rootScope.checkVersion = false;
|
||||
$http.get('https://api.github.com/repos/bitpay/copay/tags').success(function(data) {
|
||||
var toInt = function(s) {
|
||||
return parseInt(s);
|
||||
};
|
||||
var latestVersion = data[0].name.replace('v', '').split('.').map(toInt);
|
||||
var currentVersion = copay.version.split('.').map(toInt);
|
||||
var title = 'Copay ' + data[0].name + ' ' + $filter('translate')('available.');
|
||||
var content;
|
||||
if (currentVersion[0] < latestVersion[0]) {
|
||||
content = 'It\'s important that you update your wallet at https://copay.io';
|
||||
notification.version(title, content, true);
|
||||
} else if (currentVersion[0] == latestVersion[0] && currentVersion[1] < latestVersion[1]) {
|
||||
var content = 'Please update your wallet at https://copay.io';
|
||||
notification.version(title, content, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
var bitcore = require('bitcore');
|
||||
|
||||
angular.module('copayApp.controllers').controller('walletForPaymentController', function($rootScope, $scope, $modal, identityService, go) {
|
||||
|
||||
// INIT: (not it a function, since there is no associated html)
|
||||
|
||||
var ModalInstanceCtrl = function($scope, $modalInstance, identityService) {
|
||||
$scope.loading = true;
|
||||
preconditions.checkState($rootScope.iden);
|
||||
|
||||
var iden = $rootScope.iden;
|
||||
iden.on('newWallet', function() {
|
||||
$scope.setWallets();
|
||||
});
|
||||
|
||||
$scope.setWallets = function() {
|
||||
$scope.wallets = $rootScope.iden.getWallets();
|
||||
};
|
||||
|
||||
$scope.ok = function(w) {
|
||||
$modalInstance.close(w);
|
||||
};
|
||||
|
||||
$scope.cancel = function() {
|
||||
$rootScope.pendingPayment = null;
|
||||
$modalInstance.close();
|
||||
};
|
||||
};
|
||||
|
||||
var modalInstance = $modal.open({
|
||||
templateUrl: 'views/modals/walletSelection.html',
|
||||
windowClass: 'tiny',
|
||||
controller: ModalInstanceCtrl,
|
||||
});
|
||||
|
||||
modalInstance.result.then(function(w) {
|
||||
if (w) {
|
||||
identityService.setFocusedWallet(w);
|
||||
$rootScope.walletForPaymentSet = true;
|
||||
} else {
|
||||
$rootScope.pendingPayment = null;
|
||||
}
|
||||
go.walletHome();
|
||||
}, function() {
|
||||
$rootScope.pendingPayment = null;
|
||||
go.walletHome();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
'use strict';
|
||||
angular.module('copayApp.controllers').controller('WarningController', function($scope, $rootScope, $location, identityService) {
|
||||
|
||||
$scope.checkLock = function() {
|
||||
if (!$rootScope.tmp || !$rootScope.tmp.getLock()) {
|
||||
console.log('[warning.js.7] TODO LOCK'); //TODO
|
||||
}
|
||||
};
|
||||
|
||||
$scope.signout = function() {
|
||||
identityService.signout();
|
||||
};
|
||||
|
||||
$scope.ignoreLock = function() {
|
||||
var w = $rootScope.tmp;
|
||||
delete $rootScope['tmp'];
|
||||
|
||||
if (!w) {
|
||||
$location.path('/');
|
||||
} else {
|
||||
w.ignoreLock = 1;
|
||||
$scope.loading = true;
|
||||
//controllerUtils.startNetwork(w, $scope);
|
||||
// TODO
|
||||
}
|
||||
};
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue