Merge pull request #5070 from JDonadio/feat/address-view
Feat/address view
This commit is contained in:
commit
3b6926e463
15 changed files with 470 additions and 118 deletions
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();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.readMore = function() {
|
||||||
|
$timeout(function() {
|
||||||
|
$scope.showMore = !$scope.showMore;
|
||||||
|
$ionicScrollDelegate.resize();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$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,62 +1,15 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('preferencesInformation',
|
angular.module('copayApp.controllers').controller('preferencesInformation',
|
||||||
function($scope, $log, $timeout, $ionicHistory, $ionicScrollDelegate, platformInfo, gettextCatalog, lodash, profileService, configService, $stateParams, walletService, $state) {
|
function($scope, $log, $ionicHistory, platformInfo, lodash, profileService, configService, $stateParams, $state) {
|
||||||
var base = 'xpub';
|
|
||||||
var wallet = profileService.getWallet($stateParams.walletId);
|
var wallet = profileService.getWallet($stateParams.walletId);
|
||||||
var walletId = wallet.id;
|
var walletId = wallet.id;
|
||||||
|
|
||||||
var config = configService.getSync();
|
var config = configService.getSync();
|
||||||
var b = 1;
|
var colorCounter = 1;
|
||||||
|
var BLACK_WALLET_COLOR = '#202020';
|
||||||
$scope.isCordova = platformInfo.isCordova;
|
$scope.isCordova = platformInfo.isCordova;
|
||||||
config.colorFor = config.colorFor || {};
|
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() {
|
$scope.saveBlack = function() {
|
||||||
function save(color) {
|
function save(color) {
|
||||||
var opts = {
|
var opts = {
|
||||||
|
|
@ -71,14 +24,8 @@ angular.module('copayApp.controllers').controller('preferencesInformation',
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (b != 5) return b++;
|
if (colorCounter != 5) return colorCounter++;
|
||||||
save('#202020');
|
save(BLACK_WALLET_COLOR);
|
||||||
};
|
|
||||||
|
|
||||||
$scope.scan = function() {
|
|
||||||
walletService.startScan(wallet);
|
|
||||||
$ionicHistory.removeBackView();
|
|
||||||
$state.go('tabs.home');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.$on("$ionicView.enter", function(event, data) {
|
$scope.$on("$ionicView.enter", function(event, data) {
|
||||||
|
|
@ -95,29 +42,5 @@ angular.module('copayApp.controllers').controller('preferencesInformation',
|
||||||
$scope.M = c.m;
|
$scope.M = c.m;
|
||||||
$scope.N = c.n;
|
$scope.N = c.n;
|
||||||
$scope.pubKeys = lodash.pluck(c.publicKeyRing, 'xPubKey');
|
$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);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,12 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
|
||||||
}, 100);
|
}, 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.showAddresses = function() {
|
||||||
|
$state.transitionTo('tabs.receive.addresses', {
|
||||||
|
walletId: $scope.wallet.credentials.walletId
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
$scope.openBackupNeededModal = function() {
|
$scope.openBackupNeededModal = function() {
|
||||||
$ionicModal.fromTemplateUrl('views/includes/backupNeededPopup.html', {
|
$ionicModal.fromTemplateUrl('views/includes/backupNeededPopup.html', {
|
||||||
scope: $scope,
|
scope: $scope,
|
||||||
|
|
|
||||||
|
|
@ -616,6 +616,31 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* 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'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Init backup flow
|
* Init backup flow
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,9 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti
|
||||||
'validatingWords': gettext('Validating recovery phrase...'),
|
'validatingWords': gettext('Validating recovery phrase...'),
|
||||||
'loadingTxInfo': gettext('Loading transaction info...'),
|
'loadingTxInfo': gettext('Loading transaction info...'),
|
||||||
'sendingFeedback': gettext('Sending feedback...'),
|
'sendingFeedback': gettext('Sending feedback...'),
|
||||||
|
'generatingNewAddress': gettext('Generating new address...'),
|
||||||
|
'gettingAddresses': gettext('Getting addresses...'),
|
||||||
|
'sendingByEmail': gettext('Preparing addresses...'),
|
||||||
};
|
};
|
||||||
|
|
||||||
root.clear = function() {
|
root.clear = function() {
|
||||||
|
|
|
||||||
|
|
@ -773,6 +773,21 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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) {
|
root.getAddress = function(wallet, forceNew, cb) {
|
||||||
storageService.getLastAddress(wallet.id, function(err, addr) {
|
storageService.getLastAddress(wallet.id, function(err, addr) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/sass/views/includes/menu-popover.scss
Normal file
12
src/sass/views/includes/menu-popover.scss
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#menu-popover {
|
||||||
|
border-radius: 5px;
|
||||||
|
.list {
|
||||||
|
.item {
|
||||||
|
cursor: pointer;
|
||||||
|
cursor: hand;
|
||||||
|
&:hover {
|
||||||
|
background-color: #E4E2E2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -89,6 +89,8 @@
|
||||||
.bit-address {
|
.bit-address {
|
||||||
font-size: .8rem;
|
font-size: .8rem;
|
||||||
// left:10%;
|
// left:10%;
|
||||||
|
cursor: pointer;
|
||||||
|
cursor: hand;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
transition: all .15s ease;
|
transition: all .15s ease;
|
||||||
width:100%;
|
width:100%;
|
||||||
|
|
@ -117,7 +119,6 @@
|
||||||
.item {
|
.item {
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
display: inline-block;
|
|
||||||
font-size: .7rem;
|
font-size: .7rem;
|
||||||
@media(min-width:350px) {
|
@media(min-width:350px) {
|
||||||
font-size:.9rem;
|
font-size:.9rem;
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
@import "bitpayCardIntro";
|
@import "bitpayCardIntro";
|
||||||
@import "bitpayCardPreferences";
|
@import "bitpayCardPreferences";
|
||||||
@import "address-book";
|
@import "address-book";
|
||||||
|
@import "addresses";
|
||||||
@import "wallet-backup-phrase";
|
@import "wallet-backup-phrase";
|
||||||
@import "zero-state";
|
@import "zero-state";
|
||||||
@import "onboarding/onboarding";
|
@import "onboarding/onboarding";
|
||||||
|
|
@ -26,6 +27,7 @@
|
||||||
@import "export";
|
@import "export";
|
||||||
@import "import";
|
@import "import";
|
||||||
@import "join";
|
@import "join";
|
||||||
|
@import "includes/menu-popover";
|
||||||
@import "includes/walletActivity";
|
@import "includes/walletActivity";
|
||||||
@import "includes/wallets";
|
@import "includes/wallets";
|
||||||
@import "includes/modals/modals";
|
@import "includes/modals/modals";
|
||||||
|
|
|
||||||
72
www/views/addresses.html
Normal file
72
www/views/addresses.html
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
<ion-view hide-tabs id="addresses" class="addr">
|
||||||
|
<ion-nav-bar class="bar-royal">
|
||||||
|
<ion-nav-title>{{'Wallet Addresses' | translate}}</ion-nav-title>
|
||||||
|
<ion-nav-back-button>
|
||||||
|
</ion-nav-back-button>
|
||||||
|
<ion-nav-buttons side="secondary">
|
||||||
|
<button class="button back-button" ng-click="showMenu(false, $event)">
|
||||||
|
<i class="icon ion-ios-more"></i>
|
||||||
|
</button>
|
||||||
|
</ion-nav-buttons>
|
||||||
|
</ion-nav-bar>
|
||||||
|
|
||||||
|
<ion-content>
|
||||||
|
<div class="text-center banner-icon">
|
||||||
|
<i class="icon zero-state-icon">
|
||||||
|
<img src="img/tab-icons/ico-receive-selected.svg"/>
|
||||||
|
</i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="addr-list">
|
||||||
|
<div class="addr-explanation">
|
||||||
|
<div class="addr-description" translate>
|
||||||
|
Each bitcoin wallet can generate billions of addresses from your 12-word backup. A new address is automatically generated and shown each time your recive a payment. <a ng-click="showInformation()" ng-if="!showInfo" translate>Why?</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="addr-explanation" ng-if="showInfo">
|
||||||
|
<div class="addr-description" translate>
|
||||||
|
It's a good idea to avoid reusing addresses-this both protects your privacy and keeps your bitcoins secure against hypothetical attacks by quantum computers. <a ng-click="showInformation()" translate>Hide</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="list">
|
||||||
|
<div class="item item-divider item-icon-right" ng-click="newAddress()" translate>
|
||||||
|
Unused Addresses
|
||||||
|
<i class="icon ion-ios-plus-empty"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-if="latestUnused[0]">
|
||||||
|
<div class="box-error" ng-if="gapReached">
|
||||||
|
<h5 translate>Unused Addresses Limit</h5>
|
||||||
|
<p translate>The maximum number of consecutive unused addresses (20) has been reached. When one of your unused addresses receives a payment, a new address will be generated and shown in your Receive tab. <a ng-click="readMore()" ng-if="!showMore" translate>Read more</a></p>
|
||||||
|
<p ng-if="showMore" translate>The restore process will stop when 20 addresses are generated in a row which contain no funds. To safely generate more addresses, make a payment to one of the unused addresses which has already been generated. <a ng-click="readMore()" translate>Read less</a></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="item" ng-repeat="u in latestUnused track by $index" copy-to-clipboard="u.address">
|
||||||
|
{{u.address}}
|
||||||
|
<div class="addr-path">
|
||||||
|
{{u.path}} {{u.createdOn * 1000 | amDateFormat:'MMMM Do YYYY, hh:mm a'}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-if="latestWithBalance[0]">
|
||||||
|
<div class="item item-divider" translate>
|
||||||
|
Addresses With Balance
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="item" ng-repeat="w in latestWithBalance track by $index" copy-to-clipboard="w.address">
|
||||||
|
{{w.address}}
|
||||||
|
<div class="addr-balance">{{w.balanceStr}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="item item-icon-right view-all" ng-show="viewAll.value" ng-click="viewAllAddresses()">
|
||||||
|
<span translate>View All Addresses</span>
|
||||||
|
<i class="icon ion-ios-arrow-thin-right"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ion-content>
|
||||||
|
</ion-view>
|
||||||
28
www/views/allAddresses.html
Normal file
28
www/views/allAddresses.html
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
<ion-view hide-tabs id="addresses" class="addr">
|
||||||
|
<ion-nav-bar class="bar-royal">
|
||||||
|
<ion-nav-title>{{'All Addresses' | translate}}</ion-nav-title>
|
||||||
|
<ion-nav-back-button>
|
||||||
|
</ion-nav-back-button>
|
||||||
|
<ion-nav-buttons side="secondary">
|
||||||
|
<button class="button back-button" ng-click="showMenu(true, $event)" ng-hide="!isCordova && allAddressesView">
|
||||||
|
<i class="icon ion-ios-more"></i>
|
||||||
|
</button>
|
||||||
|
</ion-nav-buttons>
|
||||||
|
</ion-nav-bar>
|
||||||
|
|
||||||
|
<ion-content>
|
||||||
|
<div class="addr-list list">
|
||||||
|
<div class="item item-divider"></div>
|
||||||
|
|
||||||
|
<div class="item" ng-repeat="a in allAddresses track by $index" copy-to-clipboard="a.address">
|
||||||
|
{{a.address}}
|
||||||
|
<div class="addr-path" ng-if="!a.balanceStr">
|
||||||
|
{{a.path}} {{a.createdOn * 1000 | amDateFormat:'MMMM Do YYYY, hh:mm a'}}
|
||||||
|
</div>
|
||||||
|
<div class="addr-balance" ng-if="a.balanceStr">{{a.balanceStr}}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="item item-divider"></div>
|
||||||
|
</div>
|
||||||
|
</ion-content>
|
||||||
|
</ion-view>
|
||||||
9
www/views/includes/menu-popover.html
Normal file
9
www/views/includes/menu-popover.html
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<ion-popover-view ng-style="{'height': height + 'px'}" id="menu-popover">
|
||||||
|
<ion-content>
|
||||||
|
<div class="list">
|
||||||
|
<div class="item" ng-repeat="i in items track by $index" ng-click="i.action()">
|
||||||
|
{{i.text}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ion-content>
|
||||||
|
</ion-popover-view>
|
||||||
|
|
@ -80,38 +80,11 @@
|
||||||
<div class="item" ng-repeat="pk in pubKeys" copy-to-clipboard="pk">
|
<div class="item" ng-repeat="pk in pubKeys" copy-to-clipboard="pk">
|
||||||
<span translate>Copayer {{$index}}</span>
|
<span translate>Copayer {{$index}}</span>
|
||||||
<span class="item-note">
|
<span class="item-note">
|
||||||
<span>Copayer {{$index}}</span>
|
|
||||||
<span>{{pk}}</span>
|
<span>{{pk}}</span>
|
||||||
<span ng-if="$index == 0">({{basePath}})</span>
|
<span ng-if="$index == 0">({{basePath}})</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ng-show="addrs">
|
|
||||||
<div class="item item-divider" translate>
|
|
||||||
Latest Wallet Addresses
|
|
||||||
</div>
|
|
||||||
<div class="settings-explanation">
|
|
||||||
<div class="settings-description" translate>
|
|
||||||
Only “main” addresses are shown below. This excludes “change” address.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="item" ng-repeat="a in addrs" class="oh" copy-to-clipboard="a.address">
|
|
||||||
<span>{{a.address}}</span>
|
|
||||||
<span class="item-note">{{a.path}} · {{a.createdOn *1000 | amDateFormat:'MMMM Do YYYY, h:mm a' }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="settings-explanation">
|
|
||||||
<div class="settings-description" translate>
|
|
||||||
Please note: due to resource constraints, this list of addresses is not verified locally. A compromised BWS node could return addresses which are not controlled by this wallet.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button class="button button-standard button-primary" ng-click="scan()" translate>
|
|
||||||
Scan addresses for funds
|
|
||||||
</button>
|
|
||||||
<button class="button button-standard button-primary" ng-show="isCordova" ng-click="sendAddrs()" translate>
|
|
||||||
Send addresses by email
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div ng-show="wallet.balanceByAddress[0]">
|
<div ng-show="wallet.balanceByAddress[0]">
|
||||||
<div class="item item-divider" translate>
|
<div class="item item-divider" translate>
|
||||||
Balance By Address
|
Balance By Address
|
||||||
|
|
|
||||||
|
|
@ -64,19 +64,14 @@
|
||||||
<i class="icon ion-ios-upload-outline"></i>
|
<i class="icon ion-ios-upload-outline"></i>
|
||||||
<span translate>Share</span>
|
<span translate>Share</span>
|
||||||
</div>
|
</div>
|
||||||
<div ng-class="{'center-block': !isCordova || !addr}">
|
|
||||||
<div class="item item-icon-left" ng-click="setAddress(true)">
|
|
||||||
<i class="icon ion-ios-loop"></i>
|
|
||||||
<span translate>Next Address</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div id="bit-address" class="row border-top">
|
<div id="bit-address" class="row border-top" ng-click="showAddresses()">
|
||||||
<div class="center-block bit-address text-center" ng-repeat="wallet in wallets track by $index" ng-class="walletPosition($index)">
|
<div class="center-block bit-address text-center" ng-repeat="wallet in wallets track by $index" ng-class="walletPosition($index)">
|
||||||
<div class="item item-icon-left item-icon-right">
|
<div class="item item-icon-left item-icon-right">
|
||||||
<i class="icon icon-svg receive-tab-bitcoin-icon"><img src="img/icon-bitcoin-symbol.svg"></i>
|
<i class="icon icon-svg receive-tab-bitcoin-icon"><img src="img/icon-bitcoin-symbol.svg"></i>
|
||||||
<span class="bit-address-gen-address" ng-if="generatingAddress">...</span>
|
<span class="bit-address-gen-address" ng-if="generatingAddress">...</span>
|
||||||
<span class="bit-address-gen-address" ng-if="!generatingAddress" copy-to-clipboard="walletAddrs[wallet.id]">{{walletAddrs[wallet.id]}}</span>
|
<span class="bit-address-gen-address" ng-if="!generatingAddress" class="ellipsis">{{walletAddrs[wallet.id]}}</span>
|
||||||
|
<i class="icon ion-ios-arrow-right"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue