refactor tx proposal events
This commit is contained in:
parent
4841c2dc05
commit
6ce2667274
11 changed files with 201 additions and 248 deletions
|
|
@ -2,119 +2,55 @@
|
|||
|
||||
angular.module('copayApp.controllers').controller('HomeWalletController', function($scope, $rootScope, $timeout, $filter, $modal, rateService, notification, txStatus, identityService) {
|
||||
$scope.initHome = function() {
|
||||
var w = $rootScope.wallet;
|
||||
|
||||
$rootScope.title = 'Home';
|
||||
$scope.rateService = rateService;
|
||||
$scope.isRateAvailable = false;
|
||||
|
||||
var w = $rootScope.wallet;
|
||||
if (w.isShared())
|
||||
$scope.copayers = w.getRegisteredPeerIds();
|
||||
|
||||
w.on('txProposalEvent', _updateTxs);
|
||||
_updateTxs();
|
||||
|
||||
rateService.whenAvailable(function() {
|
||||
$scope.isRateAvailable = true;
|
||||
$scope.$digest();
|
||||
});
|
||||
};
|
||||
|
||||
// This is necessary, since wallet can change in homeWallet,
|
||||
// without running init() again.
|
||||
|
||||
var removeWatch;
|
||||
removeWatch = $rootScope.$watch('wallet.id', function(newWallet, oldWallet) {
|
||||
if ($rootScope.wallet && $rootScope.wallet.isComplete() && newWallet !== oldWallet) {
|
||||
|
||||
if (removeWatch)
|
||||
removeWatch();
|
||||
|
||||
if (oldWallet) {
|
||||
var oldw = $rootScope.iden.getWalletById(oldWallet);
|
||||
if (oldw)
|
||||
oldw.removeListener('txProposalEvent', _updateTxs);
|
||||
}
|
||||
|
||||
|
||||
var w = $rootScope.wallet;
|
||||
$rootScope.pendingTxCount = 0;
|
||||
w.on('txProposalEvent', _updateTxs);
|
||||
_updateTxs();
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$on("$destroy", function() {
|
||||
var w = $rootScope.wallet;
|
||||
if (w) {
|
||||
removeWatch();
|
||||
w.removeListener('txProposalEvent', _updateTxs);
|
||||
};
|
||||
});
|
||||
|
||||
$scope.setAlternativeAmount = function(w, tx, cb) {
|
||||
rateService.whenAvailable(function() {
|
||||
_.each(tx.outs, function(out) {
|
||||
var valueSat = out.valueSat * w.settings.unitToSatoshi;
|
||||
out.alternativeAmount = $filter('noFractionNumber')(rateService.toFiat(valueSat, $scope.alternativeIsoCode), 2);
|
||||
out.alternativeIsoCode = $scope.alternativeIsoCode;
|
||||
});
|
||||
if (cb) return cb(tx);
|
||||
});
|
||||
};
|
||||
|
||||
var _updateTxs = _.throttle(function() {
|
||||
var w = $rootScope.wallet;
|
||||
if (!w) return;
|
||||
|
||||
$scope.alternativeIsoCode = w.settings.alternativeIsoCode;
|
||||
$scope.myId = w.getMyCopayerId();
|
||||
|
||||
var res = w.getPendingTxProposals();
|
||||
_.each(res.txs, function(tx) {
|
||||
$scope.setAlternativeAmount(w, tx);
|
||||
if (tx.merchant) {
|
||||
var url = tx.merchant.request_url;
|
||||
var domain = /^(?:https?)?:\/\/([^\/:]+).*$/.exec(url)[1];
|
||||
tx.merchant.domain = domain;
|
||||
}
|
||||
if (tx.outs) {
|
||||
_.each(tx.outs, function(out) {
|
||||
out.valueSat = out.value;
|
||||
out.value = $filter('noFractionNumber')(out.value);
|
||||
});
|
||||
}
|
||||
});
|
||||
$scope.txps = res.txs;
|
||||
$timeout(function(){
|
||||
$scope.$digest();
|
||||
},1)
|
||||
}, 100);
|
||||
|
||||
$scope.sign = function(ntxid) {
|
||||
var w = $rootScope.wallet;
|
||||
$scope.loading = true;
|
||||
$scope.error = $scope.success = null;
|
||||
w.signAndSend(ntxid, function(err, id, status) {
|
||||
$scope.loading = false;
|
||||
if (!txStatus.notify(status))
|
||||
$scope.error = status;
|
||||
_updateTxs();
|
||||
|
||||
if (err)
|
||||
$scope.error = err;
|
||||
else
|
||||
txStatus.notify(status);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.reject = function(ntxid) {
|
||||
var w = $rootScope.wallet;
|
||||
w.reject(ntxid);
|
||||
txStatus.notify('txRejected');
|
||||
_updateTxs();
|
||||
w.reject(ntxid, function(err, status) {
|
||||
if (err)
|
||||
$scope.error = err;
|
||||
else
|
||||
txStatus.notify(status);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
$scope.broadcast = function(ntxid) {
|
||||
var w = $rootScope.wallet;
|
||||
$scope.error = $scope.success = null;
|
||||
$scope.loading = true;
|
||||
w.issueTx(ntxid, function(err, txid, status) {
|
||||
$scope.loading = false;
|
||||
|
||||
if (err)
|
||||
$scope.error = err;
|
||||
|
||||
txStatus.notify(status);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
$scope.openTxModal = function(tx) {
|
||||
var ModalInstanceCtrl = function($scope, $modalInstance) {
|
||||
$scope.tx = tx;
|
||||
|
||||
$scope.getShortNetworkName = function() {
|
||||
var w = $rootScope.wallet;
|
||||
return w.getNetworkName().substring(0, 4);
|
||||
|
|
@ -131,7 +67,4 @@ angular.module('copayApp.controllers').controller('HomeWalletController', functi
|
|||
controller: ModalInstanceCtrl,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -160,11 +160,10 @@ angular.module('copayApp.controllers').controller('SendController',
|
|||
comment: comment,
|
||||
}, function(err, txid, status) {
|
||||
$scope.loading = false;
|
||||
|
||||
if (err)
|
||||
return $scope.setError(err);
|
||||
|
||||
$scope.resetForm(status);
|
||||
txStatus.notify(status);
|
||||
$scope.resetForm();
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -313,37 +312,6 @@ angular.module('copayApp.controllers').controller('SendController',
|
|||
}
|
||||
};
|
||||
|
||||
$scope.notifyStatus = function(status) {
|
||||
var msg;
|
||||
|
||||
if (status == copay.Wallet.TX_BROADCASTED)
|
||||
msg = 'Transaction broadcasted!';
|
||||
else if (status == copay.Wallet.TX_PROPOSAL_SENT)
|
||||
msg = 'Transaction proposal created';
|
||||
else if (status == copay.Wallet.TX_SIGNED)
|
||||
msg = 'Transaction proposal was signed';
|
||||
else if (status == copay.Wallet.TX_SIGNED_AND_BROADCASTED)
|
||||
msg = 'Transaction signed and broadcasted!';
|
||||
|
||||
if (msg)
|
||||
$scope.openTxStatusModal(msg);
|
||||
else
|
||||
$scope.error = status;
|
||||
};
|
||||
|
||||
|
||||
$scope.send = function(ntxid, cb) {
|
||||
var w = $rootScope.wallet;
|
||||
$scope.error = $scope.success = null;
|
||||
$scope.loading = true;
|
||||
$rootScope.txAlertCount = 0;
|
||||
w.issueTx(ntxid, function(err, txid, status) {
|
||||
$scope.loading = false;
|
||||
$scope.resetForm(status);
|
||||
if (cb) return cb();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.setForm = function(to, amount, comment) {
|
||||
var form = $scope.sendForm;
|
||||
if (to) {
|
||||
|
|
@ -367,7 +335,7 @@ angular.module('copayApp.controllers').controller('SendController',
|
|||
}
|
||||
};
|
||||
|
||||
$scope.resetForm = function(status) {
|
||||
$scope.resetForm = function() {
|
||||
var form = $scope.sendForm;
|
||||
|
||||
$scope.fetchingURL = null;
|
||||
|
|
@ -391,10 +359,6 @@ angular.module('copayApp.controllers').controller('SendController',
|
|||
form.address.$setViewValue('');
|
||||
form.address.$render();
|
||||
}
|
||||
|
||||
if (!txStatus.notify(status))
|
||||
$scope.error = status;
|
||||
|
||||
$timeout(function() {
|
||||
$rootScope.$digest();
|
||||
}, 1);
|
||||
|
|
@ -434,11 +398,8 @@ angular.module('copayApp.controllers').controller('SendController',
|
|||
|
||||
if (err) {
|
||||
copay.logger.warn(err);
|
||||
if (err.toString().match('TIMEOUT')) {
|
||||
$scope.resetForm('Payment server timed out');
|
||||
} else {
|
||||
$scope.resetForm(err.toString());
|
||||
}
|
||||
$scope.resetForm();
|
||||
$scope.error = err.toString();
|
||||
} else {
|
||||
$scope._merchantData = merchantData;
|
||||
$scope._domain = merchantData.domain;
|
||||
|
|
|
|||
|
|
@ -118,6 +118,10 @@ function Wallet(opts) {
|
|||
inherits(Wallet, events.EventEmitter);
|
||||
|
||||
|
||||
Wallet.TX_NEW = 'txNew';
|
||||
Wallet.TX_PURGED = 'txPurged';
|
||||
Wallet.TX_ALL_PURGED = 'txAllPurged';
|
||||
Wallet.TX_REJECTED = 'txRejected';
|
||||
Wallet.TX_BROADCASTED = 'txBroadcasted';
|
||||
Wallet.TX_PROPOSAL_SENT = 'txProposalSent';
|
||||
Wallet.TX_SIGNED = 'txSigned';
|
||||
|
|
@ -433,7 +437,6 @@ Wallet.prototype._updateTxProposalSent = function(txp, cb) {
|
|||
|
||||
if (txid) {
|
||||
txp.setSent(txid);
|
||||
self.emitAndKeepAlive('txProposalsUpdated');
|
||||
}
|
||||
if (cb)
|
||||
return cb(null, txid, txid ? Wallet.TX_BROADCASTED : null);
|
||||
|
|
@ -508,7 +511,7 @@ Wallet.prototype._txProposalFromUntrustedObj = function(data, opts) {
|
|||
* @param {string} senderId - the id of the sender
|
||||
* @param {Object} data - the data received
|
||||
* @param {Object} data.txProposal - first parameter for {@link TxProposals#merge}
|
||||
* @emits txProposalsUpdated
|
||||
* @emits txProposalEvent
|
||||
*/
|
||||
Wallet.prototype._onTxProposal = function(senderId, data) {
|
||||
preconditions.checkArgument(data.txProposal);
|
||||
|
|
@ -539,7 +542,7 @@ Wallet.prototype._onTxProposal = function(senderId, data) {
|
|||
|
||||
self.txProposals.add(incomingTx);
|
||||
self.emitAndKeepAlive('txProposalEvent', {
|
||||
type: 'new',
|
||||
type: Wallet.TX_NEW,
|
||||
cId: senderId,
|
||||
});
|
||||
});
|
||||
|
|
@ -555,12 +558,11 @@ Wallet.prototype._onSignature = function(senderId, data) {
|
|||
return;
|
||||
};
|
||||
localTx.addSignature(senderId, data.signatures);
|
||||
self.issueTxIfComplete(data.ntxid, function(err, txid) {
|
||||
self.emitAndKeepAlive('txProposalEvent', {
|
||||
type: txid ? 'signedAndBroadcasted' : 'signed',
|
||||
cId: senderId,
|
||||
});
|
||||
self.emitAndKeepAlive('txProposalEvent', {
|
||||
type: Wallet.TX_SIGNED,
|
||||
cId: senderId,
|
||||
});
|
||||
self.issueTxIfComplete(data.ntxid, function(err, txid) {});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -570,7 +572,6 @@ Wallet.prototype._onSignature = function(senderId, data) {
|
|||
* @param {string} senderId
|
||||
* @param {Object} data
|
||||
* @param {string} data.ntxid
|
||||
* @emits txProposalsUpdated
|
||||
* @emits txProposalEvent
|
||||
*/
|
||||
Wallet.prototype._onReject = function(senderId, data) {
|
||||
|
|
@ -589,7 +590,7 @@ Wallet.prototype._onReject = function(senderId, data) {
|
|||
|
||||
txp.setRejected(senderId);
|
||||
this.emitAndKeepAlive('txProposalEvent', {
|
||||
type: 'rejected',
|
||||
type: Wallet.TX_REJECTED,
|
||||
cId: senderId,
|
||||
txId: data.ntxid
|
||||
});
|
||||
|
|
@ -603,7 +604,6 @@ Wallet.prototype._onReject = function(senderId, data) {
|
|||
* @param {string} senderId
|
||||
* @param {Object} data
|
||||
* @param {string} data.ntxid
|
||||
* @emits txProposalsUpdated
|
||||
* @emits txProposalEvent
|
||||
*/
|
||||
Wallet.prototype._onSeen = function(senderId, data) {
|
||||
|
|
@ -614,7 +614,7 @@ Wallet.prototype._onSeen = function(senderId, data) {
|
|||
if (txp) {
|
||||
txp.setSeen(senderId);
|
||||
this.emitAndKeepAlive('txProposalEvent', {
|
||||
type: 'seen',
|
||||
type: Wallet.TX_SEEN,
|
||||
cId: senderId,
|
||||
txId: data.ntxid
|
||||
});
|
||||
|
|
@ -808,7 +808,11 @@ Wallet.prototype.getCopayerId = function(index) {
|
|||
* @return {string} hex-encoded pubkey
|
||||
*/
|
||||
Wallet.prototype.getMyCopayerId = function() {
|
||||
return this.getCopayerId(0); //copayer id is hex of a public key
|
||||
|
||||
if (!this._myId)
|
||||
this._myId = this.getCopayerId(0);
|
||||
|
||||
return this._myId; //copayer id is hex of a public key
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -923,7 +927,6 @@ Wallet.prototype._setupNetworkHandlers = function() {
|
|||
* @emits data
|
||||
*
|
||||
* @emits ready
|
||||
* @emits txProposalsUpdated
|
||||
*
|
||||
*/
|
||||
Wallet.prototype.netStart = function() {
|
||||
|
|
@ -1429,7 +1432,6 @@ Wallet.prototype.getPendingTxProposalsCount = function() {
|
|||
Wallet.prototype.getPendingTxProposals = function() {
|
||||
var self = this;
|
||||
var ret = [];
|
||||
ret.txs = [];
|
||||
var txps = this.txProposals.txps;
|
||||
var maxRejectCount = this.maxRejectCount();
|
||||
var satToUnit = 1 / this.settings.unitToSatoshi;
|
||||
|
|
@ -1458,7 +1460,7 @@ Wallet.prototype.getPendingTxProposals = function() {
|
|||
txp.fee = txp.builder.feeSat * satToUnit;
|
||||
txp.missingSignatures = txp.builder.build().countInputMissingSignatures(0);
|
||||
txp.actionList = self._getActionList(txp);
|
||||
ret.txs.push(txp);
|
||||
ret.push(txp);
|
||||
});
|
||||
|
||||
return ret;
|
||||
|
|
@ -1472,7 +1474,10 @@ Wallet.prototype.getPendingTxProposals = function() {
|
|||
Wallet.prototype.purgeTxProposals = function(deleteAll) {
|
||||
var deleted = this.txProposals.purge(deleteAll, this.maxRejectCount());
|
||||
if (deleted) {
|
||||
this.emitAndKeepAlive('txProposalsUpdated');
|
||||
this.emitAndKeepAlive('txProposalEvent', {
|
||||
type: deleteAll ? Wallet.TX_PURGED : Wallet.TX_ALL_PURGED,
|
||||
cId: this.getMyCopayerId(),
|
||||
});
|
||||
}
|
||||
return deleted;
|
||||
};
|
||||
|
|
@ -1480,35 +1485,36 @@ Wallet.prototype.purgeTxProposals = function(deleteAll) {
|
|||
/**
|
||||
* @desc Reject a proposal
|
||||
* @param {string} ntxid the id of the transaction proposal to reject
|
||||
* @emits txProposalsUpdated
|
||||
* @emits txProposalsEvent
|
||||
*/
|
||||
Wallet.prototype.reject = function(ntxid) {
|
||||
Wallet.prototype.reject = function(ntxid, cb) {
|
||||
var txp = this.txProposals.get(ntxid);
|
||||
txp.setRejected(this.getMyCopayerId());
|
||||
this.sendReject(ntxid);
|
||||
this.emitAndKeepAlive('txProposalsUpdated');
|
||||
|
||||
this.emitAndKeepAlive('txProposalEvent', {
|
||||
type: Wallet.TX_REJECTED,
|
||||
cId: this.getMyCopayerId(),
|
||||
});
|
||||
|
||||
// TODO this callback should be triggered by sendRejected, which is trully async
|
||||
return cb(null, Wallet.TX_REJECTED);
|
||||
};
|
||||
|
||||
/**
|
||||
* @callback signCallback
|
||||
* @param {Error} error if any
|
||||
* @param {number} Transaction ID or Transaction Proposal ID
|
||||
* @param {status} Wallet.TX_* Status:
|
||||
*
|
||||
* TX_BROADCASTED
|
||||
* TX_SIGNED
|
||||
* TX_PROPOSAL_SENT
|
||||
* @param {status} Wallet.TX_* Status
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @desc Signs a transaction proposal
|
||||
* @param {string} ntxid the id of the transaction proposal to sign
|
||||
* @emits txProposalsUpdated
|
||||
* @throws {Error} Could not sign proposal
|
||||
* @throws {Error} Bad payment request
|
||||
* @return {boolean} true if signing actually incremented the number of signatures
|
||||
* @emits txProposalsUpdated
|
||||
*/
|
||||
Wallet.prototype.sign = function(ntxid) {
|
||||
preconditions.checkState(!_.isUndefined(this.getMyCopayerId()));
|
||||
|
|
@ -1520,7 +1526,6 @@ Wallet.prototype.sign = function(ntxid) {
|
|||
if (!signaturesAdded)
|
||||
return false;
|
||||
|
||||
this.emitAndKeepAlive('txProposalsUpdated');
|
||||
return true;
|
||||
};
|
||||
|
||||
|
|
@ -1545,15 +1550,25 @@ Wallet.prototype.issueTxIfComplete = function(ntxid, cb) {
|
|||
* @param ntxid Transaction Proposal Id
|
||||
* @param {signCallback} cb
|
||||
* @throws {Error} Could not sign proposal
|
||||
* @emits txProposalEvent
|
||||
*/
|
||||
Wallet.prototype.signAndSend = function(ntxid, cb) {
|
||||
var self = this;
|
||||
|
||||
if (this.sign(ntxid)) {
|
||||
|
||||
this.sendSignature(ntxid);
|
||||
this.issueTxIfComplete(ntxid, function(err, txid, status) {
|
||||
if (!txid)
|
||||
return cb(null, ntxid, Wallet.TX_SIGNED);
|
||||
else
|
||||
return cb(null, ntxid, Wallet.TX_SIGNED_AND_BROADCASTED);
|
||||
|
||||
// We did not broadcast the TX, only signed it.
|
||||
if (!txid) {
|
||||
self.emitAndKeepAlive('txProposalEvent', {
|
||||
type: Wallet.TX_SIGNED,
|
||||
cId: self.getMyCopayerId(),
|
||||
});
|
||||
}
|
||||
|
||||
return cb(err, txid, status ? status : Wallet.TX_SIGNED);
|
||||
});
|
||||
} else {
|
||||
return cb(new Error('Could not sign the proposal'));
|
||||
|
|
@ -1615,7 +1630,10 @@ Wallet.prototype.issueTx = function(ntxid, cb) {
|
|||
|
||||
var txp = self.txProposals.get(ntxid);
|
||||
txp.setSent(txid);
|
||||
|
||||
self.emitAndKeepAlive('txProposalEvent', {
|
||||
type: Wallet.TX_BROADCASTED,
|
||||
cId: self.getMyCopayerId(),
|
||||
});
|
||||
|
||||
// PAYPRO: Payment message is optional, only if payment_url is set
|
||||
// This is async. and will notify and update txp async.
|
||||
|
|
@ -1626,7 +1644,6 @@ Wallet.prototype.issueTx = function(ntxid, cb) {
|
|||
self.onPayProPaymentAck(ntxid, data);
|
||||
});
|
||||
}
|
||||
self.emitAndKeepAlive('txProposalsUpdated');
|
||||
return cb(null, txid, Wallet.TX_BROADCASTED);
|
||||
});
|
||||
};
|
||||
|
|
@ -2210,6 +2227,8 @@ Wallet.prototype.spend = function(opts, cb) {
|
|||
preconditions.checkArgument(amountSat, 'no amount');
|
||||
preconditions.checkArgument(toAddress, 'no address');
|
||||
|
||||
// TODO no bajar los unspends de vuelta...
|
||||
//
|
||||
this.getUnspent(function(err, safeUnspent) {
|
||||
if (err) {
|
||||
log.info(err);
|
||||
|
|
@ -2237,14 +2256,17 @@ Wallet.prototype.spend = function(opts, cb) {
|
|||
log.debug('TXP Added: ', ntxid);
|
||||
|
||||
self.sendIndexes();
|
||||
|
||||
// Needs only one signature? Broadcast it!
|
||||
if (!self.requiresMultipleSignatures()) {
|
||||
self.issueTx(ntxid, cb);
|
||||
} else {
|
||||
self.sendTxProposal(ntxid);
|
||||
self.emitAndKeepAlive('txProposalsUpdated');
|
||||
return cb(null, ntxid, Wallet.TX_PROPOSAL_SENT);
|
||||
}
|
||||
if (!self.requiresMultipleSignatures())
|
||||
return self.issueTx(ntxid, cb);
|
||||
|
||||
self.sendTxProposal(ntxid);
|
||||
self.emitAndKeepAlive('txProposalEvent', {
|
||||
type: Wallet.TX_PROPOSAL_SENT,
|
||||
cId: self.getMyCopayerId(),
|
||||
});
|
||||
return cb(null, ntxid, Wallet.TX_PROPOSAL_SENT);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -110,7 +110,6 @@ angular.module('copayApp.services')
|
|||
};
|
||||
|
||||
root.setupGlobalVariables = function(iden) {
|
||||
$rootScope.pendingTxCount = 0;
|
||||
$rootScope.reconnecting = false;
|
||||
$rootScope.iden = iden;
|
||||
};
|
||||
|
|
@ -140,6 +139,32 @@ angular.module('copayApp.services')
|
|||
})
|
||||
};
|
||||
|
||||
root.notifyTxProposalEvent = function(w, e) {
|
||||
if (e.cId == w.getMyCopayerId())
|
||||
return;
|
||||
|
||||
var user = w.publicKeyRing.nicknameForCopayer(e.cId);
|
||||
var name = w.getName();
|
||||
switch (e.type) {
|
||||
case copay.Wallet.TX_NEW:
|
||||
notification.info('[' + name + '] New Transaction',
|
||||
$filter('translate')('You received a transaction proposal from') + ' ' + user);
|
||||
break;
|
||||
case copay.Wallet.TX_SIGNED:
|
||||
notification.success('[' + name + '] Transaction Signed',
|
||||
$filter('translate')('A transaction was signed by') + ' ' + user);
|
||||
break;
|
||||
case copay.Wallet.TX_BROADCASTED:
|
||||
notification.success('[' + name + '] Transaction Approved',
|
||||
$filter('translate')('A transaction was broadcasted by') + ' ' + user);
|
||||
break;
|
||||
case copay.Wallet.TX_REJECTED:
|
||||
notification.warning('[' + name + '] Transaction Rejected',
|
||||
$filter('translate')('A transaction was rejected by') + ' ' + user);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
root.installWalletHandlers = function(w) {
|
||||
var wid = w.getId();
|
||||
w.on('connectionError', function() {
|
||||
|
|
@ -150,9 +175,7 @@ angular.module('copayApp.services')
|
|||
});
|
||||
|
||||
w.on('corrupt', function(peerId) {
|
||||
if (root.isFocused(wid)) {
|
||||
notification.error('Error', $filter('translate')('Received corrupt message from ') + peerId);
|
||||
}
|
||||
copay.logger.warn('Received corrupt message from ' + peerId);
|
||||
});
|
||||
|
||||
w.on('publicKeyRingUpdated', function() {
|
||||
|
|
@ -200,52 +223,29 @@ angular.module('copayApp.services')
|
|||
// Nothing yet
|
||||
});
|
||||
|
||||
w.on('txProposalsUpdated', function() {
|
||||
if (root.isFocused(wid)) {
|
||||
pendingTxsService.update();
|
||||
}
|
||||
});
|
||||
// Disabled for now, does not seens to have much value for the user
|
||||
// w.on('paymentACK', function(memo) {
|
||||
// notification.success('Payment Acknowledged', memo);
|
||||
// });
|
||||
|
||||
w.on('txProposalEvent', function(ev) {
|
||||
|
||||
w.on('paymentACK', function(memo) {
|
||||
notification.success('Payment Acknowledged', memo);
|
||||
});
|
||||
|
||||
w.on('txProposalEvent', function(e) {
|
||||
if (root.isFocused(wid)) {
|
||||
pendingTxsService.update();
|
||||
}
|
||||
|
||||
// TODO aqui lo unico que cambia son los locked
|
||||
// se puede optimizar
|
||||
balanceService.update(w, function() {
|
||||
$rootScope.$digest();
|
||||
}, root.isFocused(wid));
|
||||
|
||||
// TODO: add wallet name notification
|
||||
var user = w.publicKeyRing.nicknameForCopayer(e.cId);
|
||||
var name = w.getName();
|
||||
switch (e.type) {
|
||||
case 'new':
|
||||
notification.info('[' + name + '] New Transaction',
|
||||
$filter('translate')('You received a transaction proposal from') + ' ' + user);
|
||||
break;
|
||||
case 'signed':
|
||||
notification.success('[' + name + '] Transaction Signed',
|
||||
$filter('translate')('A transaction was signed by') + ' ' + user);
|
||||
break;
|
||||
case 'signedAndBroadcasted':
|
||||
notification.success('[' + name + '] Transaction Approved',
|
||||
$filter('translate')('A transaction was signed and broadcasted by') + ' ' + user);
|
||||
break;
|
||||
case 'rejected':
|
||||
notification.warning('[' + name + '] Transaction Rejected',
|
||||
$filter('translate')('A transaction was rejected by') + ' ' + user);
|
||||
break;
|
||||
case 'corrupt':
|
||||
notification.error('[' + name + '] Transaction Error',
|
||||
$filter('translate')('Received corrupt transaction from') + ' ' + user);
|
||||
break;
|
||||
}
|
||||
$rootScope.$digest();
|
||||
root.notifyTxProposalEvent(w, ev);
|
||||
$timeout(function(){
|
||||
$rootScope.$digest();
|
||||
});
|
||||
});
|
||||
|
||||
w.on('addressBookUpdated', function(dontDigest) {
|
||||
if (root.isFocused(wid)) {
|
||||
if (!dontDigest) {
|
||||
|
|
@ -282,7 +282,7 @@ angular.module('copayApp.services')
|
|||
});
|
||||
|
||||
iden.on('noWallets', function() {
|
||||
notification.warning('No Wallets','Your profile has no wallets. Create one here');
|
||||
notification.warning('No Wallets', 'Your profile has no wallets. Create one here');
|
||||
$rootScope.starting = false;
|
||||
$location.path('/create');
|
||||
$timeout(function() {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,51 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
angular.module('copayApp.services')
|
||||
.factory('pendingTxsService', function($rootScope) {
|
||||
.factory('pendingTxsService', function($rootScope, $filter, rateService) {
|
||||
var root = {};
|
||||
|
||||
root.setAlternativeAmount = function(w, tx, cb) {
|
||||
var alternativeIsoCode = w.settings.alternativeIsoCode;
|
||||
rateService.whenAvailable(function() {
|
||||
_.each(tx.outs, function(out) {
|
||||
var valueSat = out.valueSat * w.settings.unitToSatoshi;
|
||||
out.alternativeAmount = $filter('noFractionNumber')(
|
||||
rateService.toFiat(valueSat, alternativeIsoCode), 2);
|
||||
out.alternativeIsoCode = alternativeIsoCode;
|
||||
});
|
||||
if (cb) return cb(tx);
|
||||
});
|
||||
};
|
||||
|
||||
root.getDecoratedTxProposals = function(w) {
|
||||
var txps = w.getPendingTxProposals();
|
||||
|
||||
_.each(txps, function(tx) {
|
||||
root.setAlternativeAmount(w, tx);
|
||||
if (tx.outs) {
|
||||
_.each(tx.outs, function(out) {
|
||||
out.valueSat = out.value;
|
||||
out.value = $filter('noFractionNumber')(out.value);
|
||||
});
|
||||
}
|
||||
});
|
||||
return txps;
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc adds 2 fields to wallet: pendingTxProposalsCountForUs, pendingTxProposals.
|
||||
*
|
||||
* @param w wallet
|
||||
*/
|
||||
root.update = function(w) {
|
||||
var w = $rootScope.wallet;
|
||||
if (!w) return;
|
||||
|
||||
//pendingTxCount
|
||||
var ret = w.getPendingTxProposalsCount();
|
||||
$rootScope.pendingTxCount = ret.pendingForUs;
|
||||
w.pendingTxProposalsCountForUs = ret.pendingForUs;
|
||||
w.pendingTxProposals = root.getDecoratedTxProposals(w);
|
||||
};
|
||||
|
||||
return root;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,19 +6,16 @@ angular.module('copayApp.services').factory('txStatus', function($modal) {
|
|||
root.notify = function(status) {
|
||||
var msg;
|
||||
if (status == copay.Wallet.TX_BROADCASTED)
|
||||
msg = 'Transaction broadcasted!';
|
||||
msg = 'Transaction broadcasted';
|
||||
else if (status == copay.Wallet.TX_PROPOSAL_SENT)
|
||||
msg = 'Transaction proposal created';
|
||||
else if (status == copay.Wallet.TX_SIGNED)
|
||||
msg = 'Transaction proposal was signed';
|
||||
else if (status == copay.Wallet.TX_SIGNED_AND_BROADCASTED)
|
||||
msg = 'Transaction signed and broadcasted!';
|
||||
else if (status == 'txRejected')
|
||||
msg = 'Transaction was rejected!';
|
||||
msg = 'Transaction proposal signed';
|
||||
else if (status == copay.Wallet.TX_REJECTED)
|
||||
msg = 'Transaction was rejected';
|
||||
|
||||
if (msg)
|
||||
root.openModal(msg);
|
||||
return msg ? true : false;
|
||||
};
|
||||
|
||||
root.openModal = function(statusStr) {
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ describe("Unit: Controllers", function() {
|
|||
beforeEach(inject(function($controller, $rootScope) {
|
||||
scope = $rootScope.$new();
|
||||
$rootScope.safeUnspentCount = 1;
|
||||
$rootScope.pendingTxCount = 0;
|
||||
|
||||
//
|
||||
// TODO Use the REAL wallet, and stub only networking and DB components!
|
||||
|
|
@ -86,10 +85,9 @@ describe("Unit: Controllers", function() {
|
|||
w.requiresMultipleSignatures = sinon.stub().returns(true);
|
||||
w.getTxProposals = sinon.stub().returns([1, 2, 3]);
|
||||
w.getPendingTxProposals = sinon.stub().returns({
|
||||
txs: [{
|
||||
[{
|
||||
isPending: true
|
||||
}],
|
||||
pendingForUs: 1
|
||||
}]
|
||||
});
|
||||
w.getId = sinon.stub().returns(1234);
|
||||
w.on = sinon.stub().yields({
|
||||
|
|
|
|||
|
|
@ -20,14 +20,14 @@
|
|||
<span class="size-21">
|
||||
<strong>
|
||||
<span ng-if="!$root.updatingBalance">{{$root.wallet.balanceInfo.totalBalance || 0}}</span>
|
||||
<span ng-if="$root.updatingBalance"><i class="fi-bitcoin-circle icon-rotate spinner"></i></span>
|
||||
{{$root.wallet.settings.unitName}}
|
||||
</strong>
|
||||
<span ng-if="$root.updatingBalance"><i class="fi-bitcoin-circle icon-rotate spinner"></i></span>
|
||||
{{$root.wallet.settings.unitName}}
|
||||
</strong>
|
||||
</span>
|
||||
<span class="size-14 db m5t text-gray">
|
||||
<span ng-if="!$root.wallet.balanceInfo.updatingBalance && $root.wallet.balanceInfo.alternativeBalanceAvailable">{{$root.wallet.balanceInfo.totalBalanceAlternative}} {{$root.wallet.balanceInfo.alternativeIsoCode}}</span>
|
||||
<span ng-if="!$root.wallet.balanceInfo.updatingBalance && !$root.wallet.balanceInfo.alternativeBalanceAvailable">N/A</span>
|
||||
<span ng-if="$root.wallet.balanceInfo.updatingBalance"><i class="fi-bitcoin-circle icon-rotate spinner"></i></span>
|
||||
<span ng-if="!$root.wallet.balanceInfo.updatingBalance && !$root.wallet.balanceInfo.alternativeBalanceAvailable">N/A</span>
|
||||
<span ng-if="$root.wallet.balanceInfo.updatingBalance"><i class="fi-bitcoin-circle icon-rotate spinner"></i></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -47,13 +47,18 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-show="$root.wallet.isShared() && txps.length != 0">
|
||||
|
||||
<div ng-show="$root.wallet.isShared()">
|
||||
<div class="row">
|
||||
<div class="large-12 columns">
|
||||
<h2 translate>Pending Transactions Proposals</h2>
|
||||
<div class="panel last-transactions pr"
|
||||
ng-repeat="tx in txps | paged"
|
||||
ng-include="'views/includes/transaction.html'"></div>
|
||||
<div class="panel oh">
|
||||
<h2 class="line-b" translate>Spend proposals</h2>
|
||||
<div class="last-transactions pr" ng-repeat="tx in $root.wallet.pendingTxProposals | paged" ng-include="'views/includes/transaction.html'" ng-if="$root.wallet.pendingTxProposals[0]">
|
||||
</div>
|
||||
<div class="pr" ng-if="!$root.wallet.pendingTxProposals[0]">
|
||||
<p> No pending spend proposals at the moment.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<i class="size-36 {{item.icon}} db"></i>
|
||||
<div class="size-10 tu">
|
||||
{{item.title}}
|
||||
<span class="label alert round" ng-if="item.link=='homeWallet' && $root.pendingTxCount > 0">{{$root.pendingTxCount}}</span>
|
||||
<span class="label alert round" ng-if="item.link=='homeWallet' && $root.wallet.pendingTxProposalsCountForUs > 0">{{$root.wallet.pendingTxProposalsCountForUs}}</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -86,8 +86,8 @@
|
|||
<a href="#!/{{item.link}}" ng-click="toggleCollapse()" class="db p20h">
|
||||
<i class="size-21 m20r {{item.icon}}"></i> {{item.title|translate}}
|
||||
<span class="right">
|
||||
<span class="label alert" ng-if="item.link=='homeWallet' && $root.pendingTxCount > 0">
|
||||
{{$root.pendingTxCount}}
|
||||
<span class="label alert" ng-if="item.link=='homeWallet' && $root.wallet.pendingTxProposalsCountForUs > 0">
|
||||
{{$root.wallet.pendingTxProposalsCountForUs}}
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
</div>
|
||||
|
||||
|
||||
<div class="last-transactions-footer">
|
||||
<div class="last-transactions-footer" ng-init="myId = $root.wallet.getMyCopayerId()">
|
||||
<div class="row collapse">
|
||||
<div class="small-12 columns" ng-show="!tx.sentTs">
|
||||
<div ng-show="tx.signedBy[myId]">
|
||||
|
|
@ -60,8 +60,9 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-show="!tx.missingSignatures && !tx.sentTs">
|
||||
<button class="primary tiny m0" ng-click="send(tx.ntxid)" ng-disabled="loading"> <i class="fi-upload-cloud"></i>
|
||||
<button class="primary tiny m0" ng-click="broadcast(tx.ntxid)" ng-disabled="loading"> <i class="fi-upload-cloud"></i>
|
||||
<span translate>Broadcast Transaction</span>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue