mirror of https://github.com/BTCPrivate/copay.git
Add user comment to transaction propossal
This commit is contained in:
parent
fd7eaca46a
commit
bcbb6b54d1
|
@ -422,6 +422,14 @@ hr { margin: 2.25rem 0;}
|
|||
background: #C0392B;
|
||||
}
|
||||
|
||||
.box-note {
|
||||
text-align: center;
|
||||
clear: both;
|
||||
font-style: italic;
|
||||
color: gray;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.box-signin {
|
||||
padding: 20px 40px;
|
||||
border: 1px solid #eee;
|
||||
|
|
22
index.html
22
index.html
|
@ -189,7 +189,7 @@
|
|||
src="./img/satoshi.gif"
|
||||
/>
|
||||
<div class="size-12 text-center text-gray" stype="margin-top:4px">
|
||||
{{c.nick || 'NN'}}
|
||||
{{c.nick}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -455,6 +455,9 @@
|
|||
</div>
|
||||
|
||||
<div class="tx-copayers">
|
||||
<div class="box-note large-12" ng-show="tx.comment">
|
||||
"{{tx.comment}}" - {{$root.wallet.publicKeyRing.nicknameForCopayer(tx.creator)}}
|
||||
</div>
|
||||
|
||||
<div class="box-copayers" ng-repeat="(cId, actions) in tx.peerActions">
|
||||
<figure class="left">
|
||||
|
@ -664,6 +667,23 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="large-12 medium-6 columns">
|
||||
<div class="row collapse">
|
||||
<label for="comment">Note
|
||||
<small ng-hide="!sendForm.comment.$pristine">optional</small>
|
||||
<small class="is-valid" ng-show="!sendForm.comment.$invalid && !sendForm.comment.$pristine">valid!</small>
|
||||
<small class="has-error" ng-show="sendForm.comment.$invalid && !sendForm.comment.$pristine">too long!</small>
|
||||
</label>
|
||||
<div class="small-12 columns">
|
||||
<textarea id="comment" ng-disabled="loading"
|
||||
name="comment" placeholder="Leave a private message to your copayers" ng-model="comment" ng-maxlength="100"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="large-5 columns">
|
||||
<button type="submit" class="button secondary radius text-center" ng-disabled="sendForm.$invalid || loading" loading="Sending">
|
||||
|
|
|
@ -47,19 +47,18 @@ angular.module('copayApp.controllers').controller('SendController',
|
|||
|
||||
var address = form.address.$modelValue;
|
||||
var amount = (form.amount.$modelValue * 100000000).toFixed(); // satoshi to string
|
||||
var comment = form.comment.$modelValue;
|
||||
|
||||
var w = $rootScope.wallet;
|
||||
w.createTx(address, amount,function() {
|
||||
w.createTx(address, amount, comment, function() {
|
||||
$scope.loading = false;
|
||||
$rootScope.$flashMessage = { message: 'The transaction proposal has been created', type: 'success'};
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
// reset fields
|
||||
$scope.address = null;
|
||||
$scope.amount = null;
|
||||
form.address.$pristine = true;
|
||||
form.amount.$pristine = true;
|
||||
$scope.address = $scope.amount = $scope.comment = null;
|
||||
form.address.$pristine = form.amount.$pristine = form.comment.$pristine = true;
|
||||
};
|
||||
|
||||
// QR code Scanner
|
||||
|
|
|
@ -107,7 +107,7 @@ PublicKeyRing.prototype.nicknameForIndex = function(index) {
|
|||
};
|
||||
|
||||
PublicKeyRing.prototype.nicknameForCopayer = function(copayerId) {
|
||||
return this.nicknameFor[copayerId];
|
||||
return this.nicknameFor[copayerId] || 'NN';
|
||||
};
|
||||
|
||||
PublicKeyRing.prototype.addCopayer = function(newEpk, nickname) {
|
||||
|
|
|
@ -20,6 +20,7 @@ function TxProposal(opts) {
|
|||
this.sentTs = opts.sentTs || null;
|
||||
this.sentTxid = opts.sentTxid || null;
|
||||
this.inputChainPaths = opts.inputChainPaths || [];
|
||||
this.comment = opts.comment || null;
|
||||
}
|
||||
|
||||
TxProposal.prototype.toObj = function() {
|
||||
|
|
|
@ -620,7 +620,7 @@ Wallet.prototype.getUnspent = function(cb) {
|
|||
};
|
||||
|
||||
|
||||
Wallet.prototype.createTx = function(toAddress, amountSatStr, opts, cb) {
|
||||
Wallet.prototype.createTx = function(toAddress, amountSatStr, comment, opts, cb) {
|
||||
var self = this;
|
||||
if (typeof opts === 'function') {
|
||||
cb = opts;
|
||||
|
@ -633,7 +633,7 @@ Wallet.prototype.createTx = function(toAddress, amountSatStr, opts, cb) {
|
|||
}
|
||||
|
||||
this.getUnspent(function(err, safeUnspent) {
|
||||
var ntxid = self.createTxSync(toAddress, amountSatStr, safeUnspent, opts);
|
||||
var ntxid = self.createTxSync(toAddress, amountSatStr, comment, safeUnspent, opts);
|
||||
if (ntxid) {
|
||||
self.sendIndexes();
|
||||
self.sendTxProposals(null, ntxid);
|
||||
|
@ -644,7 +644,7 @@ Wallet.prototype.createTx = function(toAddress, amountSatStr, opts, cb) {
|
|||
});
|
||||
};
|
||||
|
||||
Wallet.prototype.createTxSync = function(toAddress, amountSatStr, utxos, opts) {
|
||||
Wallet.prototype.createTxSync = function(toAddress, amountSatStr, comment, utxos, opts) {
|
||||
var pkr = this.publicKeyRing;
|
||||
var priv = this.privateKey;
|
||||
opts = opts || {};
|
||||
|
@ -655,6 +655,10 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, utxos, opts) {
|
|||
throw new Error('publicKeyRing is not complete');
|
||||
}
|
||||
|
||||
if (comment && comment.length > 100) {
|
||||
throw new Error("comment can't be longer that 100 characters");
|
||||
}
|
||||
|
||||
if (!opts.remainderOut) {
|
||||
opts.remainderOut = {
|
||||
address: this._doGenerateAddress(true).toString()
|
||||
|
@ -695,6 +699,7 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, utxos, opts) {
|
|||
creator: myId,
|
||||
createdTs: now,
|
||||
builder: b,
|
||||
comment: comment
|
||||
};
|
||||
|
||||
var ntxid = this.txProposals.add(data);
|
||||
|
|
|
@ -140,6 +140,7 @@ describe('Wallet model', function() {
|
|||
var ntxid = w.createTxSync(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
'123456789',
|
||||
null,
|
||||
unspentTest
|
||||
);
|
||||
|
||||
|
@ -147,11 +148,54 @@ describe('Wallet model', function() {
|
|||
var txp = t.txps[ntxid];
|
||||
var tx = txp.builder.build();
|
||||
should.exist(tx);
|
||||
chai.expect(txp.comment).to.be.null;
|
||||
tx.isComplete().should.equal(false);
|
||||
Object.keys(txp.seenBy).length.should.equal(1);
|
||||
Object.keys(txp.signedBy).length.should.equal(1);
|
||||
});
|
||||
|
||||
it('#create with comment', function() {
|
||||
|
||||
var w = createW2();
|
||||
var comment = 'This is a comment';
|
||||
|
||||
unspentTest[0].address = w.publicKeyRing.getAddress(1, true).toString();
|
||||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true);
|
||||
|
||||
var ntxid = w.createTxSync(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
'123456789',
|
||||
comment,
|
||||
unspentTest
|
||||
);
|
||||
|
||||
var t = w.txProposals;
|
||||
var txp = t.txps[ntxid];
|
||||
var tx = txp.builder.build();
|
||||
should.exist(tx);
|
||||
txp.comment.should.equal(comment);
|
||||
});
|
||||
|
||||
it('#create throw exception on long comment', function() {
|
||||
|
||||
var w = createW2();
|
||||
var comment = 'Lorem ipsum dolor sit amet, suas euismod vis te, velit deleniti vix an. Pri ex suscipit similique, inermis per';
|
||||
|
||||
unspentTest[0].address = w.publicKeyRing.getAddress(1, true).toString();
|
||||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true);
|
||||
|
||||
var badCreate = function() {
|
||||
w.createTxSync(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
'123456789',
|
||||
comment,
|
||||
unspentTest
|
||||
);
|
||||
}
|
||||
|
||||
chai.expect(badCreate).to.throw(Error);
|
||||
});
|
||||
|
||||
it('#addressIsOwn', function() {
|
||||
var w = createW2();
|
||||
var l = w.getAddressesStr();
|
||||
|
@ -178,6 +222,7 @@ describe('Wallet model', function() {
|
|||
w.createTxSync(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
'123456789',
|
||||
null,
|
||||
unspentTest
|
||||
);
|
||||
var t = w.txProposals;
|
||||
|
@ -428,7 +473,7 @@ describe('Wallet model', function() {
|
|||
var w = createW2();
|
||||
var utxo = createUTXO(w);
|
||||
w.blockchain.fixUnspent(utxo);
|
||||
w.createTx(toAddress, amountSatStr, function(ntxid) {
|
||||
w.createTx(toAddress, amountSatStr, null, function(ntxid) {
|
||||
ntxid.length.should.equal(64);
|
||||
done();
|
||||
});
|
||||
|
@ -439,7 +484,7 @@ describe('Wallet model', function() {
|
|||
w.privateKey = null;
|
||||
var utxo = createUTXO(w);
|
||||
w.blockchain.fixUnspent(utxo);
|
||||
w.createTx(toAddress, amountSatStr, function(ntxid) {
|
||||
w.createTx(toAddress, amountSatStr, null, function(ntxid) {
|
||||
w.on('txProposalsUpdated', function() {
|
||||
w.getTxProposals()[0].signedByUs.should.equal(true);
|
||||
w.getTxProposals()[0].rejectedByUs.should.equal(false);
|
||||
|
@ -456,7 +501,7 @@ describe('Wallet model', function() {
|
|||
w.privateKey = null;
|
||||
var utxo = createUTXO(w);
|
||||
w.blockchain.fixUnspent(utxo);
|
||||
w.createTx(toAddress, amountSatStr, function(ntxid) {
|
||||
w.createTx(toAddress, amountSatStr, null, function(ntxid) {
|
||||
w.on('txProposalsUpdated', function() {
|
||||
w.getTxProposals()[0].signedByUs.should.equal(false);
|
||||
w.getTxProposals()[0].rejectedByUs.should.equal(true);
|
||||
|
@ -470,7 +515,7 @@ describe('Wallet model', function() {
|
|||
var w = createW2(null, 1);
|
||||
var utxo = createUTXO(w);
|
||||
w.blockchain.fixUnspent(utxo);
|
||||
w.createTx(toAddress, amountSatStr, function(ntxid) {
|
||||
w.createTx(toAddress, amountSatStr, null, function(ntxid) {
|
||||
w.sendTx(ntxid, function(txid) {
|
||||
txid.length.should.equal(64);
|
||||
done();
|
||||
|
|
|
@ -80,7 +80,7 @@ for (var n = 1; n <= N_LIMIT; n++) {
|
|||
'amount': 10.0,
|
||||
'confirmations': 2
|
||||
}];
|
||||
var ntxid = w.createTxSync(toAddress, amount, utxos);
|
||||
var ntxid = w.createTxSync(toAddress, amount, null, utxos);
|
||||
var txp = w.txProposals.txps[ntxid];
|
||||
|
||||
var signTx = function(pk, cb) {
|
||||
|
|
Loading…
Reference in New Issue