diff --git a/lib/expressapp.js b/lib/expressapp.js index 5944b5e..55a838a 100644 --- a/lib/expressapp.js +++ b/lib/expressapp.js @@ -288,6 +288,16 @@ ExpressApp.prototype.start = function(opts, cb) { }); }); + router.post('/v1/broadcast_raw/', function(req, res) { + getServerWithAuth(req, res, function(server) { + server.broadcastRawTx(req.body, function(err, txid) { + if (err) return returnError(err, res, req); + res.json(txid); + res.end(); + }); + }); + }); + router.post('/v1/txproposals/:id/signatures/', function(req, res) { getServerWithAuth(req, res, function(server) { req.body.txProposalId = req.params['id']; diff --git a/lib/server.js b/lib/server.js index d12a04b..9ad1b96 100644 --- a/lib/server.js +++ b/lib/server.js @@ -1181,21 +1181,34 @@ WalletService.prototype.removePendingTx = function(opts, cb) { }); }; - -WalletService.prototype._broadcastTx = function(txp, cb) { - var raw; - try { - raw = txp.getRawTx(); - } catch (ex) { - return cb(ex); - } - var bc = this._getBlockchainExplorer(txp.getNetworkName()); +WalletService.prototype._broadcastRawTx = function(network, raw, cb) { + var bc = this._getBlockchainExplorer(network); bc.broadcast(raw, function(err, txid) { if (err) return cb(err); return cb(null, txid); }) }; +/** + * Broadcast a raw transaction. + * @param {Object} opts + * @param {string} [opts.network = 'livenet'] - The Bitcoin network for this transaction. + * @param {string} opts.rawTx - Raw tx data. + */ +WalletService.prototype.broadcastRawTx = function(opts, cb) { + var self = this; + + if (!Utils.checkRequired(opts, ['network', 'rawTx'])) + return cb(new ClientError('Required argument missing')); + + var network = opts.network || 'livenet'; + if (network != 'livenet' && network != 'testnet') + return cb(new ClientError('Invalid network')); + + self._broadcastRawTx(network, opts.rawTx, cb); +}; + + WalletService.prototype._checkTxInBlockchain = function(txp, cb) { var tx = txp.getBitcoreTx(); var bc = this._getBlockchainExplorer(txp.getNetworkName()); @@ -1308,7 +1321,13 @@ WalletService.prototype.broadcastTx = function(opts, cb) { if (txp.status == 'broadcasted') return cb(Errors.TX_ALREADY_BROADCASTED); if (txp.status != 'accepted') return cb(Errors.TX_NOT_ACCEPTED); - self._broadcastTx(txp, function(err, txid) { + var raw; + try { + raw = txp.getRawTx(); + } catch (ex) { + return cb(ex); + } + self._broadcastRawTx(txp.getNetworkName(), raw, function(err, txid) { if (err) { var broadcastErr = err; // Check if tx already in blockchain diff --git a/package.json b/package.json index fa1209c..aa40182 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "bitcore-wallet-service", "description": "A service for Mutisig HD Bitcoin Wallets", "author": "BitPay Inc", - "version": "0.1.4", + "version": "0.1.5", "keywords": [ "bitcoin", "copay", diff --git a/test/integration/server.js b/test/integration/server.js index 0dceb24..fd3086f 100644 --- a/test/integration/server.js +++ b/test/integration/server.js @@ -2571,7 +2571,7 @@ describe('Wallet service', function() { }); }); - describe('#broadcastTx', function() { + describe('#broadcastTx & #braodcastRawTx', function() { var server, wallet, txpid; beforeEach(function(done) { helpers.createAndJoinWallet(1, 1, function(s, w) { @@ -2619,6 +2619,18 @@ describe('Wallet service', function() { }); }); + it('should broadcast a raw tx', function(done) { + helpers.stubBroadcast('999'); + server.broadcastRawTx({ + network: 'testnet', + rawTx: 'raw tx', + }, function(err, txid) { + should.not.exist(err); + txid.should.equal('999'); + done(); + }); + }); + it('should fail to brodcast a tx already marked as broadcasted', function(done) { helpers.stubBroadcast('999'); server.broadcastTx({