Merge pull request #3795 from cmgustavo/feat/send-confirmation-popup
Send confirmation popup
This commit is contained in:
commit
bcde97727e
14 changed files with 237 additions and 84 deletions
|
|
@ -40,7 +40,7 @@
|
||||||
"url": "https://github.com/bitpay/copay/issues"
|
"url": "https://github.com/bitpay/copay/issues"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bitcore-wallet-client": "1.5.0",
|
"bitcore-wallet-client": "2.1.0",
|
||||||
"express": "^4.11.2",
|
"express": "^4.11.2",
|
||||||
"fs": "0.0.2",
|
"fs": "0.0.2",
|
||||||
"grunt": "^0.4.5",
|
"grunt": "^0.4.5",
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
<div notifications="right top"></div>
|
<div notifications="right top"></div>
|
||||||
<div ng-include="'views/includes/password.html'" ng-if="index.askPassword"></div>
|
<div ng-include="'views/includes/password.html'" ng-if="index.askPassword"></div>
|
||||||
<div ng-include="'views/includes/alert.html'" ng-if="index.showAlert"></div>
|
<div ng-include="'views/includes/alert.html'" ng-if="index.showAlert"></div>
|
||||||
|
<div ng-include="'views/includes/confirm-tx.html'" ng-if="index.confirmTx"></div>
|
||||||
<div id="sectionContainer">
|
<div id="sectionContainer">
|
||||||
<div id="mainSection">
|
<div id="mainSection">
|
||||||
<section ui-view="main"
|
<section ui-view="main"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<div class="passModalMask">
|
<div class="modalMask">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="alertModal">
|
<div class="alertModal">
|
||||||
|
|
|
||||||
40
public/views/includes/confirm-tx.html
Normal file
40
public/views/includes/confirm-tx.html
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
<div class="modalMask"></div>
|
||||||
|
|
||||||
|
<div class="confirmTxModal" ng-controller="confirmTxController as confirm" ng-init="tx = index.confirmTx.txp">
|
||||||
|
|
||||||
|
<div class="confirmHead" ng-style="{'background-color':index.backgroundColor}">
|
||||||
|
<h1 class="m0 text-center text-white size-18" translate>Confirm transaction</h1>
|
||||||
|
</div>
|
||||||
|
<div class="p10">
|
||||||
|
<div class="size-36">{{tx.amountStr}}</div>
|
||||||
|
<div class="size-14 text-light" ng-show="tx.alternativeAmountStr">{{tx.alternativeAmountStr}}</div>
|
||||||
|
<i class="db fi-arrow-down size-24 m10v"></i>
|
||||||
|
<div class="payment-proposal-to" ng-click="copyAddress(tx.toAddress)">
|
||||||
|
<i class="fi-bitcoin left m10l"></i>
|
||||||
|
<contact ng-if="!tx.hasMultiplesOutputs" class="dib enable_text_select ellipsis m5t m5b m15l size-14" address="{{tx.toAddress}}"></contact>
|
||||||
|
<span ng-if="tx.hasMultiplesOutputs" translate>
|
||||||
|
Multiple recipients
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="text-bold m10t size-12">
|
||||||
|
<span translate>Fee</span>: {{tx.feeStr}}
|
||||||
|
</div>
|
||||||
|
<div class="row m20t">
|
||||||
|
<div class="large-6 medium-6 small-6 columns">
|
||||||
|
<button
|
||||||
|
ng-click="confirm.close(index.confirmTx.callback)"
|
||||||
|
class="small m10b round outline dark-gray expand" translate>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="large-6 medium-6 small-6 columns">
|
||||||
|
<button
|
||||||
|
ng-click="confirm.accept(index.confirmTx.callback)"
|
||||||
|
class="small m10b round expand"
|
||||||
|
ng-style="{'background-color':index.backgroundColor}" translate>
|
||||||
|
Accept
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
<div class="passModalMask">
|
<div class="modalMask">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ng-controller="passwordController as pass" class="passModal"
|
<div ng-controller="passwordController as pass" class="passModal"
|
||||||
|
|
|
||||||
|
|
@ -31,17 +31,19 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="oh">
|
<div class="oh">
|
||||||
<div class="box-notification m20t" ng-show="error">
|
<div class="box-notification" ng-show="error">
|
||||||
<span class="text-warning size-14">
|
<span class="text-warning size-14">
|
||||||
{{error|translate}}
|
{{error|translate}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row column m20t text-center text-warning size-12" ng-if="tx.removed" translate>
|
<div class="row" ng-if="tx.removed">
|
||||||
The payment was removed by creator
|
<div class="column m20t text-center text-warning size-12" translate>
|
||||||
|
The payment was removed by creator
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="oh p20t white" ng-if="tx.pendingForUs">
|
<div class="row p20t white" ng-if="tx.pendingForUs">
|
||||||
<div class="large-6 medium-6 small-6 columns" ng-show="isShared">
|
<div class="large-6 medium-6 small-6 columns" ng-show="isShared">
|
||||||
<button class="button outline round dark-gray expand" ng-click="reject(tx);"
|
<button class="button outline round dark-gray expand" ng-click="reject(tx);"
|
||||||
ng-disabled="loading">
|
ng-disabled="loading">
|
||||||
|
|
|
||||||
|
|
@ -1374,9 +1374,30 @@ input.ng-invalid-match, input.ng-invalid-match:focus {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Confirmation popup */
|
||||||
|
|
||||||
|
.confirmTxModal {
|
||||||
|
background: white;
|
||||||
|
border-radius: 5px;
|
||||||
|
position: absolute;
|
||||||
|
width: 90%;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
margin: 15% auto;
|
||||||
|
z-index: 1100;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirmHead {
|
||||||
|
padding: 10px;
|
||||||
|
border-top-left-radius: 5px;
|
||||||
|
border-top-right-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************/
|
||||||
|
|
||||||
.alertModal {
|
.alertModal {
|
||||||
background: #FFFFFF;
|
background: #FFFFFF;
|
||||||
box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.50);
|
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 90%;
|
width: 90%;
|
||||||
|
|
@ -1387,7 +1408,6 @@ input.ng-invalid-match, input.ng-invalid-match:focus {
|
||||||
|
|
||||||
.passModal {
|
.passModal {
|
||||||
background: #FFFFFF;
|
background: #FFFFFF;
|
||||||
box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.50);
|
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 90%;
|
width: 90%;
|
||||||
|
|
@ -1396,12 +1416,12 @@ input.ng-invalid-match, input.ng-invalid-match:focus {
|
||||||
z-index: 1100;
|
z-index: 1100;
|
||||||
}
|
}
|
||||||
|
|
||||||
.passModalMask {
|
.modalMask {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
z-index: 1099;
|
z-index: 1099;
|
||||||
opacity:0.3;
|
opacity:0.8;
|
||||||
background: black;
|
background: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
13
src/js/controllers/confirmTx.js
Normal file
13
src/js/controllers/confirmTx.js
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('copayApp.controllers').controller('confirmTxController', function() {
|
||||||
|
|
||||||
|
this.close = function(cb) {
|
||||||
|
return cb();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.accept = function(cb) {
|
||||||
|
return cb(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -391,7 +391,6 @@ angular.module('copayApp.controllers').controller('indexController', function($r
|
||||||
|
|
||||||
self.setFeeAndSendMax = function(cb) {
|
self.setFeeAndSendMax = function(cb) {
|
||||||
|
|
||||||
self.feeToSendMaxStr = null;
|
|
||||||
self.availableMaxBalance = null;
|
self.availableMaxBalance = null;
|
||||||
self.currentFeePerKb = null;
|
self.currentFeePerKb = null;
|
||||||
|
|
||||||
|
|
@ -518,7 +517,6 @@ angular.module('copayApp.controllers').controller('indexController', function($r
|
||||||
message: 'test multi-output',
|
message: 'test multi-output',
|
||||||
fee: 1000,
|
fee: 1000,
|
||||||
createdOn: new Date() / 1000,
|
createdOn: new Date() / 1000,
|
||||||
type: 'multiple_output',
|
|
||||||
outputs: []
|
outputs: []
|
||||||
};
|
};
|
||||||
function addOutput(n) {
|
function addOutput(n) {
|
||||||
|
|
@ -1460,6 +1458,19 @@ angular.module('copayApp.controllers').controller('indexController', function($r
|
||||||
self.setTab(tab, reset);
|
self.setTab(tab, reset);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$rootScope.$on('Local/NeedsConfirmation', function(event, txp, cb) {
|
||||||
|
self.confirmTx = {
|
||||||
|
txp : txFormatService.processTx(txp),
|
||||||
|
callback: function(accept) {
|
||||||
|
self.confirmTx = null;
|
||||||
|
return cb(accept);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
$timeout(function() {
|
||||||
|
$rootScope.$apply();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
$rootScope.$on('Local/NeedsPassword', function(event, isSetup, cb) {
|
$rootScope.$on('Local/NeedsPassword', function(event, isSetup, cb) {
|
||||||
self.askPassword = {
|
self.askPassword = {
|
||||||
isSetup: isSetup,
|
isSetup: isSetup,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('preferencesController',
|
angular.module('copayApp.controllers').controller('preferencesController',
|
||||||
function($scope, $rootScope, $timeout, $log, configService, profileService, txSignService) {
|
function($scope, $rootScope, $timeout, $log, configService, profileService, txService) {
|
||||||
|
|
||||||
var fc = profileService.focusedClient;
|
var fc = profileService.focusedClient;
|
||||||
$scope.deleted = false;
|
$scope.deleted = false;
|
||||||
|
|
@ -75,7 +75,7 @@ angular.module('copayApp.controllers').controller('preferencesController',
|
||||||
};
|
};
|
||||||
opts.touchIdFor[walletId] = newVal;
|
opts.touchIdFor[walletId] = newVal;
|
||||||
|
|
||||||
txSignService.setTouchId(function(err) {
|
txService.setTouchId(function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
$log.debug(err);
|
$log.debug(err);
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('sellGlideraController',
|
angular.module('copayApp.controllers').controller('sellGlideraController',
|
||||||
function($scope, $timeout, $log, $modal, configService, profileService, addressService, feeService, glideraService, bwsError, lodash, isChromeApp, animationService, txSignService) {
|
function($scope, $timeout, $log, $modal, configService, profileService, addressService, feeService, glideraService, bwsError, lodash, isChromeApp, animationService, txService) {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
var config = configService.getSync();
|
var config = configService.getSync();
|
||||||
|
|
@ -130,7 +130,7 @@ angular.module('copayApp.controllers').controller('sellGlideraController',
|
||||||
self.error = null;
|
self.error = null;
|
||||||
|
|
||||||
|
|
||||||
txSignService.prepare(function(err) {
|
txService.prepare(function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
self.error = err;
|
self.error = err;
|
||||||
return;
|
return;
|
||||||
|
|
@ -174,7 +174,7 @@ angular.module('copayApp.controllers').controller('sellGlideraController',
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
txSignService.sign(txp, function(err, txp) {
|
txService.sign(txp, function(err, txp) {
|
||||||
if (err) {
|
if (err) {
|
||||||
self.loading = null;
|
self.loading = null;
|
||||||
self.error = err;
|
self.error = err;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('walletHomeController', function($scope, $rootScope, $timeout, $filter, $modal, $log, notification, txStatus, isCordova, isMobile, profileService, lodash, configService, rateService, storageService, bitcore, isChromeApp, gettext, gettextCatalog, nodeWebkit, addressService, ledger, bwsError, confirmDialog, txFormatService, animationService, addressbookService, go, feeService, txSignService) {
|
angular.module('copayApp.controllers').controller('walletHomeController', function($scope, $rootScope, $timeout, $filter, $modal, $log, notification, txStatus, isCordova, isMobile, profileService, lodash, configService, rateService, storageService, bitcore, isChromeApp, gettext, gettextCatalog, nodeWebkit, addressService, ledger, bwsError, confirmDialog, txFormatService, animationService, addressbookService, go, feeService, txService) {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
window.ignoreMobilePause = false;
|
window.ignoreMobilePause = false;
|
||||||
|
|
@ -324,7 +324,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
|
||||||
$scope.error = null;
|
$scope.error = null;
|
||||||
$scope.loading = true;
|
$scope.loading = true;
|
||||||
|
|
||||||
txSignService.prepareAndSignAndBroadcast(txp, {
|
txService.prepareAndSignAndBroadcast(txp, {
|
||||||
reporterFn: self.setOngoingProcess.bind(self)
|
reporterFn: self.setOngoingProcess.bind(self)
|
||||||
}, function(err, txp) {
|
}, function(err, txp) {
|
||||||
$scope.loading = false;
|
$scope.loading = false;
|
||||||
|
|
@ -771,6 +771,8 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
|
||||||
var currentSpendUnconfirmed = configWallet.spendUnconfirmed;
|
var currentSpendUnconfirmed = configWallet.spendUnconfirmed;
|
||||||
var currentFeeLevel = walletSettings.feeLevel || 'normal';
|
var currentFeeLevel = walletSettings.feeLevel || 'normal';
|
||||||
|
|
||||||
|
var outputs = [];
|
||||||
|
|
||||||
this.resetError();
|
this.resetError();
|
||||||
|
|
||||||
if (isCordova && this.isWindowsPhoneApp) {
|
if (isCordova && this.isWindowsPhoneApp) {
|
||||||
|
|
@ -793,14 +795,6 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
|
||||||
return self.setSendError(gettext(msg));
|
return self.setSendError(gettext(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
var getFee = function(cb) {
|
|
||||||
if (self.lockedCurrentFeePerKb) {
|
|
||||||
cb(null, self.lockedCurrentFeePerKb);
|
|
||||||
} else {
|
|
||||||
feeService.getCurrentFeeValue(currentFeeLevel, cb);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
var paypro = self._paypro;
|
var paypro = self._paypro;
|
||||||
var address, amount;
|
var address, amount;
|
||||||
|
|
@ -808,59 +802,88 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
|
||||||
address = form.address.$modelValue;
|
address = form.address.$modelValue;
|
||||||
amount = parseInt((form.amount.$modelValue * unitToSat).toFixed(0));
|
amount = parseInt((form.amount.$modelValue * unitToSat).toFixed(0));
|
||||||
|
|
||||||
txSignService.prepare(function(err) {
|
outputs.push({
|
||||||
|
'toAddress' : address,
|
||||||
|
'amount': amount,
|
||||||
|
'message': comment
|
||||||
|
});
|
||||||
|
|
||||||
|
var opts = {
|
||||||
|
toAddress: address,
|
||||||
|
amount: amount,
|
||||||
|
outputs: outputs,
|
||||||
|
message: comment,
|
||||||
|
payProUrl: paypro ? paypro.url : null,
|
||||||
|
lockedCurrentFeePerKb: self.lockedCurrentFeePerKb
|
||||||
|
};
|
||||||
|
|
||||||
|
self.setOngoingProcess(gettextCatalog.getString('Creating transaction'));
|
||||||
|
txService.createTx(opts, function(err, txp) {
|
||||||
|
self.setOngoingProcess();
|
||||||
if (err) {
|
if (err) {
|
||||||
return self.setSendError(err);
|
return self.setSendError(err);
|
||||||
}
|
}
|
||||||
self.setOngoingProcess(gettextCatalog.getString('Creating transaction'));
|
|
||||||
getFee(function(err, feePerKb) {
|
|
||||||
if (err) $log.debug(err);
|
|
||||||
fc.sendTxProposal({
|
|
||||||
toAddress: address,
|
|
||||||
amount: amount,
|
|
||||||
message: comment,
|
|
||||||
payProUrl: paypro ? paypro.url : null,
|
|
||||||
feePerKb: feePerKb,
|
|
||||||
excludeUnconfirmedUtxos: currentSpendUnconfirmed ? false : true
|
|
||||||
}, function(err, txp) {
|
|
||||||
if (err) {
|
|
||||||
self.setOngoingProcess();
|
|
||||||
return self.setSendError(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fc.canSign() && !fc.isPrivKeyExternal()) {
|
if (!fc.canSign() && !fc.isPrivKeyExternal()) {
|
||||||
self.setOngoingProcess();
|
self.setOngoingProcess();
|
||||||
$log.info('No signing proposal: No private key')
|
$log.info('No signing proposal: No private key');
|
||||||
self.resetForm();
|
self.resetForm();
|
||||||
txStatus.notify(txp, function() {
|
txStatus.notify(txp, function() {
|
||||||
return $scope.$emit('Local/TxProposalAction');
|
return $scope.$emit('Local/TxProposalAction');
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
txSignService.signAndBroadcast(txp, {
|
|
||||||
reporterFn: self.setOngoingProcess.bind(self)
|
|
||||||
}, function(err, txp) {
|
|
||||||
self.resetForm();
|
|
||||||
if (err) {
|
|
||||||
self.error = err.message ? err.message : gettext('The payment was created but could not be completed. Please try again from home screen');
|
|
||||||
$scope.$emit('Local/TxProposalAction');
|
|
||||||
$timeout(function() {
|
|
||||||
$scope.$digest();
|
|
||||||
}, 1);
|
|
||||||
} else {
|
|
||||||
go.walletHome();
|
|
||||||
txStatus.notify(txp, function() {
|
|
||||||
$scope.$emit('Local/TxProposalAction', txp.status == 'broadcasted');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
return;
|
||||||
|
} else {
|
||||||
|
$rootScope.$emit('Local/NeedsConfirmation', txp, function(accept) {
|
||||||
|
if (accept) self.acceptTx(txp);
|
||||||
|
else self.resetForm();
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}, 100);
|
}, 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.acceptTx = function(txp) {
|
||||||
|
var self = this;
|
||||||
|
txService.prepare(function(err) {
|
||||||
|
if (err) {
|
||||||
|
return self.setSendError(err);
|
||||||
|
}
|
||||||
|
self.setOngoingProcess(gettextCatalog.getString('Sending transaction'));
|
||||||
|
txService.publishTx(txp, function(err, txpPublished) {
|
||||||
|
if (err) {
|
||||||
|
self.setOngoingProcess();
|
||||||
|
self.setSendError(err);
|
||||||
|
} else {
|
||||||
|
self.prepareSignAndBroadcastTx(txpPublished);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.prepareSignAndBroadcastTx = function(txp) {
|
||||||
|
var fc = profileService.focusedClient;
|
||||||
|
var self = this;
|
||||||
|
txService.prepareAndSignAndBroadcast(txp, {
|
||||||
|
reporterFn: self.setOngoingProcess.bind(self)
|
||||||
|
}, function(err, txp) {
|
||||||
|
self.resetForm();
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
self.error = err.message ? err.message : gettext('The payment was created but could not be completed. Please try again from home screen');
|
||||||
|
$scope.$emit('Local/TxProposalAction');
|
||||||
|
$timeout(function() {
|
||||||
|
$scope.$digest();
|
||||||
|
}, 1);
|
||||||
|
} else {
|
||||||
|
go.walletHome();
|
||||||
|
txStatus.notify(txp, function() {
|
||||||
|
$scope.$emit('Local/TxProposalAction', txp.status == 'broadcasted');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
this.setForm = function(to, amount, comment) {
|
this.setForm = function(to, amount, comment) {
|
||||||
var form = $scope.sendForm;
|
var form = $scope.sendForm;
|
||||||
if (to) {
|
if (to) {
|
||||||
|
|
|
||||||
|
|
@ -24,17 +24,23 @@ angular.module('copayApp.services').factory('txFormatService', function(profileS
|
||||||
root.processTx = function(tx) {
|
root.processTx = function(tx) {
|
||||||
if (!tx) return;
|
if (!tx) return;
|
||||||
|
|
||||||
var outputs = lodash.isArray(tx.outputs) ? tx.outputs.length : 0;
|
// New transaction output format
|
||||||
if (outputs && tx.action != 'received') {
|
if (tx.outputs) {
|
||||||
if ((tx.type && tx.type == 'multiple_output') || (tx.proposalType && tx.proposalType == 'multiple_output')) {
|
|
||||||
tx.hasMultiplesOutputs = true;
|
var outputsNr = tx.outputs.length;
|
||||||
tx.recipientCount = outputs;
|
|
||||||
|
if (tx.action != 'received') {
|
||||||
|
if (outputsNr > 1) {
|
||||||
|
tx.recipientCount = outputsNr;
|
||||||
|
tx.hasMultiplesOutputs = true;
|
||||||
|
}
|
||||||
|
tx.amount = lodash.reduce(tx.outputs, function(total, o) {
|
||||||
|
o.amountStr = formatAmountStr(o.amount);
|
||||||
|
o.alternativeAmountStr = formatAlternativeStr(o.amount);
|
||||||
|
return total + o.amount;
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
tx.amount = lodash.reduce(tx.outputs, function(total, o) {
|
tx.toAddress = tx.outputs[0].toAddress;
|
||||||
o.amountStr = formatAmountStr(o.amount);
|
|
||||||
o.alternativeAmountStr = formatAlternativeStr(o.amount);
|
|
||||||
return total + o.amount;
|
|
||||||
}, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.amountStr = formatAmountStr(tx.amount);
|
tx.amountStr = formatAmountStr(tx.amount);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.services').factory('txSignService', function($rootScope, profileService, gettextCatalog, lodash, trezor, ledger, configService, bwsError, $log) {
|
angular.module('copayApp.services').factory('txService', function($rootScope, profileService, gettextCatalog, lodash, trezor, ledger, configService, bwsError, $log, feeService) {
|
||||||
var root = {};
|
var root = {};
|
||||||
|
|
||||||
var reportSigningStatus = function(opts) {
|
var reportSigningStatus = function(opts) {
|
||||||
|
|
@ -85,10 +85,47 @@ angular.module('copayApp.services').factory('txSignService', function($rootScope
|
||||||
};
|
};
|
||||||
|
|
||||||
return cb();
|
return cb();
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
root.createTx = function(opts, cb) {
|
||||||
|
var fc = profileService.focusedClient;
|
||||||
|
var config = configService.getSync();
|
||||||
|
var configWallet = config.wallet;
|
||||||
|
var walletSettings = configWallet.settings;
|
||||||
|
|
||||||
|
var currentSpendUnconfirmed = configWallet.spendUnconfirmed;
|
||||||
|
var currentFeeLevel = walletSettings.feeLevel || 'normal';
|
||||||
|
|
||||||
|
var getFee = function(cb) {
|
||||||
|
if (opts.lockedCurrentFeePerKb) {
|
||||||
|
cb(null, opts.lockedCurrentFeePerKb);
|
||||||
|
} else {
|
||||||
|
feeService.getCurrentFeeValue(currentFeeLevel, cb);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
getFee(function(err, feePerKb) {
|
||||||
|
if (err) $log.debug(err);
|
||||||
|
opts.feePerKb = feePerKb;
|
||||||
|
opts.excludeUnconfirmedUtxos = currentSpendUnconfirmed ? false : true;
|
||||||
|
fc.createTxProposal(opts, function(err, txp) {
|
||||||
|
if (err) return cb(err);
|
||||||
|
else return cb(null, txp);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
root.publishTx = function(txp, cb) {
|
||||||
|
var fc = profileService.focusedClient;
|
||||||
|
fc.publishTxProposal({txp: txp}, function(err, txp) {
|
||||||
|
if (err) return cb(err);
|
||||||
|
else return cb(null, txp);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
var _signWithLedger = function(txp, cb) {
|
var _signWithLedger = function(txp, cb) {
|
||||||
var fc = profileService.focusedClient;
|
var fc = profileService.focusedClient;
|
||||||
$log.info('Requesting Ledger Chrome app to sign the transaction');
|
$log.info('Requesting Ledger Chrome app to sign the transaction');
|
||||||
Loading…
Add table
Add a link
Reference in a new issue