diff --git a/app.js b/app.js
index 7cd3ccb..99eba80 100644
--- a/app.js
+++ b/app.js
@@ -207,7 +207,17 @@ router.post('/v1/txproposals/:id/signatures/', function(req, res) {
router.post('/v1/txproposals/:id/rejections', function(req, res) {
getServerWithAuth(req, res, function(server) {
req.body.txProposalId = req.params['id'];
- server.signTx(req.body, function(err, txp) {
+ server.rejectTx(req.body, function(err, txp) {
+ if (err) return returnError(err, res, req);
+ res.end();
+ });
+ });
+});
+
+router.delete('/v1/txproposals/:id/', function(req, res) {
+ getServerWithAuth(req, res, function(server) {
+ req.body.txProposalId = req.params['id'];
+ server.removePendingTx(req.body, function(err) {
if (err) return returnError(err, res, req);
res.end();
});
diff --git a/bit-wallet/bit b/bit-wallet/bit
index 06930e3..cffe423 100755
--- a/bit-wallet/bit
+++ b/bit-wallet/bit
@@ -11,8 +11,9 @@ program
.command('addresses', 'list addresses')
.command('balance', 'wallet balance')
.command('send
', 'send bitcoins')
- .command('sign ', 'sign a Transaction Proposal')
- .command('reject ', 'reject a Transaction Proposal')
+ .command('sign ', 'sign a transaction proposal')
+ .command('reject [reason]', 'reject a transaction proposal')
+ .command('rm ', 'remove a transaction proposal')
.parse(process.argv);
diff --git a/bit-wallet/bit-reject b/bit-wallet/bit-reject
index b4bb33f..a2d7a9e 100644
--- a/bit-wallet/bit-reject
+++ b/bit-wallet/bit-reject
@@ -9,43 +9,32 @@ program
.version('0.0.1')
.option('-c,--config [file]', 'Wallet config filename')
.option('-v,--verbose', 'be verbose')
- .usage('[options] ')
+ .usage('[options] [reason]')
.parse(process.argv);
var args = program.args;
if (!args[0])
program.help();
-
var txpid = args[0];
+var reason = args[1] || '';
var cli = new Client({
filename: program.config
});
-cli.getTxProposals({}, function(err, x) {
+cli.getTxProposals({}, function(err, txps) {
common.die(err);
if (program.verbose)
- console.log('* Raw Server Response:\n', x); //TODO
+ console.log('* Raw Server Response:\n', txps); //TODO
- var txps = _.filter(x, function(x) {
- return _.endsWith(common.shortID(x.id), txpid);
- });
+ var txp = common.findOneTxProposal(txps, txpid);
- if (!txps.length)
- common.die('Could not find TX Proposal:' + txpid);
-
- if (txps.length > 1)
- common.die('More than one TX Proposals match:' + txpid + ' : ' + _.map(txps, function(x) {
- return x.id;
- }).join(' '));;
-
- var txp = txps[0];
- cli.rejectTxProposal(txp, function(err, x) {
+ cli.rejectTxProposal(txp, reason, function(err, tx) {
common.die(err);
if (program.verbose)
- console.log('* Raw Server Response:\n', x); //TODO
+ console.log('* Raw Server Response:\n', tx); //TODO
console.log('Transaction rejected.');
});
diff --git a/bit-wallet/bit-rm b/bit-wallet/bit-rm
new file mode 100644
index 0000000..45902eb
--- /dev/null
+++ b/bit-wallet/bit-rm
@@ -0,0 +1,38 @@
+#!/usr/bin/env node
+
+var _ = require('lodash');
+var program = require('commander');
+var Client = require('../lib/client');
+var common = require('./common');
+
+program
+ .version('0.0.1')
+ .option('-c,--config [file]', 'Wallet config filename')
+ .option('-v,--verbose', 'be verbose')
+ .usage('[options] ')
+ .parse(process.argv);
+
+var args = program.args;
+if (!args[0])
+ program.help();
+
+var txpid = args[0];
+
+var cli = new Client({
+ filename: program.config
+});
+
+cli.getTxProposals({}, function(err, txps) {
+ common.die(err);
+
+ if (program.verbose)
+ console.log('* Raw Server Response:\n', txps); //TODO
+
+ var txp = common.findOneTxProposal(txps, txpid);
+
+ cli.removeTxProposal(txp, function(err) {
+ common.die(err);
+
+ console.log('Transaction removed.');
+ });
+});
diff --git a/bit-wallet/bit-sign b/bit-wallet/bit-sign
index 68289a6..f4d8348 100755
--- a/bit-wallet/bit-sign
+++ b/bit-wallet/bit-sign
@@ -22,30 +22,19 @@ var cli = new ClientLib({
filename: program.config
});
-cli.getTxProposals({}, function(err, x) {
+cli.getTxProposals({}, function(err, txps) {
common.die(err);
if (program.verbose)
- console.log('* Raw Server Response:\n', x); //TODO
+ console.log('* Raw Server Response:\n', txps); //TODO
- var txps = _.filter(x, function(x) {
- return _.endsWith(common.shortID(x.id), txpid);
- });
+ var txp = common.findOneTxProposal(txps, txpid);
- if (!txps.length)
- common.die('Could not find TX Proposal:' + txpid);
-
- if (txps.length > 1)
- common.die('More than one TX Proposals match:' + txpid + ' : ' + _.map(txps, function(x) {
- return x.id;
- }).join(' '));;
-
- var txp = txps[0];
- cli.signTxProposal(txp, function(err, x) {
+ cli.signTxProposal(txp, function(err, tx) {
common.die(err);
if (program.verbose)
- console.log('* Raw Server Response:\n', x); //TODO
+ console.log('* Raw Server Response:\n', tx); //TODO
console.log('Transaction signed.');
});
diff --git a/bit-wallet/common.js b/bit-wallet/common.js
index 5fe7337..8671e0d 100644
--- a/bit-wallet/common.js
+++ b/bit-wallet/common.js
@@ -1,3 +1,7 @@
+'use strict';
+
+var _ = require('lodash');
+
var common = function() {};
@@ -9,14 +13,14 @@ var die = common.die = function(err) {
};
common.parseMN = function(MN) {
- if (!MN)
+ if (!MN)
die('No m-n parameter');
var mn = MN.split('-');
- var m = parseInt(mn[0]);
+ var m = parseInt(mn[0]);
var n = parseInt(mn[1]);
- if (!m || ! n) {
+ if (!m || !n) {
die('Bad m-n parameter');
}
@@ -28,4 +32,20 @@ common.shortID = function(id) {
return id.substr(id.length - 4);
};
+common.findOneTxProposal = function(txps, id) {
+ var matches = _.filter(txps, function(tx) {
+ return _.endsWith(common.shortID(tx.id), id);
+ });
+
+ if (!matches.length)
+ common.die('Could not find TX Proposal:' + id);
+
+ if (matches.length > 1)
+ common.die('More than one TX Proposals match:' + id + ' : ' + _.map(matches, function(tx) {
+ return tx.id;
+ }).join(' '));;
+
+ return matches[0];
+};
+
module.exports = common;
diff --git a/cli.js b/cli.js
deleted file mode 100644
index 3e1e0b3..0000000
--- a/cli.js
+++ /dev/null
@@ -1,30 +0,0 @@
-var _ = require('lodash');
-var async = require('async');
-var log = require('npmlog');
-var fs = require('fs');
-
-var CliLib = require('./lib/clilib');
-
-try {
- fs.unlinkSync('copay.dat');
-} catch (e) {}
-
-var cli = new CliLib({
- filename: 'copay.dat'
-});
-
-cli.createWallet('my wallet', 'me', 1, 1, 'testnet', function(err, secret) {
- if (err) {
- console.log(err);
- process.exit();
- }
-
- cli.status(function(err, status) {
- if (err) {
- console.log(err);
- process.exit();
- }
-
- console.log(status);
- })
-});
diff --git a/lib/client/API.js b/lib/client/API.js
index 615c58c..df263c2 100644
--- a/lib/client/API.js
+++ b/lib/client/API.js
@@ -84,7 +84,7 @@ API.prototype._loadAndCheck = function() {
return data;
};
-ClientLib.prototype._doRequest = function(method, url, args, data, cb) {
+API.prototype._doRequest = function(method, url, args, data, cb) {
var reqSignature = _signRequest(method, url, args, data.signingPrivKey);
var absUrl = _getUrl(url);
request({
@@ -359,4 +359,13 @@ API.prototype.rejectTxProposal = function(txp, reason, cb) {
this._doPostRequest(url, args, data, cb);
};
+API.prototype.removeTxProposal = function(txp, cb) {
+ var self = this;
+ var data = this._loadAndCheck();
+
+ var url = '/v1/txproposals/' + txp.id;
+
+ this._doRequest('delete', url, {}, data, cb);
+};
+
module.exports = API;
diff --git a/lib/server.js b/lib/server.js
index d186758..21b4d7f 100644
--- a/lib/server.js
+++ b/lib/server.js
@@ -547,19 +547,19 @@ CopayServer.prototype.removeWallet = function(opts, cb) {
* removePendingTx
*
* @param opts
- * @param {string} opts.id - The tx id.
+ * @param {string} opts.txProposalId - The tx id.
* @return {undefined}
*/
CopayServer.prototype.removePendingTx = function(opts, cb) {
var self = this;
- if (!Utils.checkRequired(opts, ['id']))
+ if (!Utils.checkRequired(opts, ['txProposalId']))
return cb(new ClientError('Required argument missing'));
Utils.runLocked(self.walletId, cb, function(cb) {
self.getTx({
- id: opts.id
+ id: opts.txProposalId,
}, function(err, txp) {
if (err) return cb(err);
@@ -576,7 +576,7 @@ CopayServer.prototype.removePendingTx = function(opts, cb) {
return cb(new ClientError('Cannot remove a proposal signed/rejected by other copayers'));
self._notify('transactionProposalRemoved');
- self.storage.removeTx(self.walletId, opts.id, cb);
+ self.storage.removeTx(self.walletId, txp.id, cb);
});
});
};
diff --git a/test/integration.js b/test/integration.js
index e80218c..1faf0c1 100644
--- a/test/integration.js
+++ b/test/integration.js
@@ -1499,7 +1499,7 @@ describe('Copay server', function() {
it('should allow creator to remove an unsigned TX', function(done) {
server.removePendingTx({
- id: txp.id
+ txProposalId: txp.id
}, function(err) {
should.not.exist(err);
server.getPendingTxs({}, function(err, txs) {
@@ -1516,7 +1516,7 @@ describe('Copay server', function() {
signatures: signatures,
}, function(err) {
server.removePendingTx({
- id: txp.id
+ txProposalId: txp.id
}, function(err) {
should.not.exist(err);
server.getPendingTxs({}, function(err, txs) {
@@ -1530,7 +1530,7 @@ describe('Copay server', function() {
it('should not allow non-creator copayer to remove an unsigned TX ', function(done) {
helpers.getAuthServer(wallet.copayers[1].id, function(server2) {
server2.removePendingTx({
- id: txp.id
+ txProposalId: txp.id
}, function(err) {
err.message.should.contain('creators');
server2.getPendingTxs({}, function(err, txs) {
@@ -1550,7 +1550,7 @@ describe('Copay server', function() {
}, function(err) {
should.not.exist(err);
server.removePendingTx({
- id: txp.id
+ txProposalId: txp.id
}, function(err) {
err.message.should.contain('other copayers');
done();