From dba306045c15b731841ba1aba6c1d27f85a08bfb Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Thu, 5 Feb 2015 17:22:38 -0300 Subject: [PATCH] broadcastTx --- lib/model/txproposal.js | 9 +++- lib/model/wallet.js | 4 ++ lib/server.js | 95 +++++++++++++++++++++++------------------ 3 files changed, 65 insertions(+), 43 deletions(-) diff --git a/lib/model/txproposal.js b/lib/model/txproposal.js index fe95ff9..9f04307 100644 --- a/lib/model/txproposal.js +++ b/lib/model/txproposal.js @@ -64,7 +64,7 @@ TxProposal.prototype._updateStatus = function() { }; -TxProposal.prototype._getBitcoreTx = function(n) { +TxProposal.prototype._getBitcoreTx = function() { var self = this; var t = new Bitcore.Transaction(); @@ -80,6 +80,13 @@ TxProposal.prototype._getBitcoreTx = function(n) { }; +TxProposal.prototype.getRawTx = function() { + var t = this._getBitcoreTx(); + + return t.serialize(); +}; + + TxProposal.prototype.addAction = function(copayerId, type, signatures) { var action = new TxProposalAction({ copayerId: copayerId, diff --git a/lib/model/wallet.js b/lib/model/wallet.js index c0320f9..f65978d 100644 --- a/lib/model/wallet.js +++ b/lib/model/wallet.js @@ -96,6 +96,10 @@ Wallet.prototype.getCopayer = function(copayerId) { }; +Wallet.prototype.getNetworkName = function() { + return this.isTestnet ? 'testnet' : 'livenet'; +}; + Wallet.prototype._getBitcoreNetwork = function() { return this.isTestnet ? Bitcore.Networks.testnet : Bitcore.Networks.livenet; }; diff --git a/lib/server.js b/lib/server.js index a52793b..8e2914b 100644 --- a/lib/server.js +++ b/lib/server.js @@ -263,52 +263,62 @@ CopayServer.prototype._getBlockExplorer = function(provider, network) { } }; +/** + * _getUtxos + * + * @param opts.walletId + */ CopayServer.prototype._getUtxos = function(opts, cb) { var self = this; - // Get addresses for this wallet - self.storage.fetchAddresses(opts.walletId, function(err, addresses) { + + self.storage.fetchWallet(opts.walletId, function(err, wallet) { if (err) return cb(err); - if (addresses.length == 0) return cb(new ClientError('The wallet has no addresses')); - var addressStrs = _.pluck(addresses, 'address'); - var addressToPath = _.indexBy(addresses, 'address'); // TODO : check performance - - var bc = self._getBlockExplorer('insight', opts.network); - bc.getUnspentUtxos(addressStrs, function(err, utxos) { + // Get addresses for this wallet + self.storage.fetchAddresses(opts.walletId, function(err, addresses) { if (err) return cb(err); + if (addresses.length == 0) return cb(new ClientError('The wallet has no addresses')); - self.getPendingTxs({ - walletId: opts.walletId - }, function(err, txps) { + var addressStrs = _.pluck(addresses, 'address'); + var addressToPath = _.indexBy(addresses, 'address'); // TODO : check performance + + var bc = self._getBlockExplorer('insight', wallet.getNetworkName()); + bc.getUnspentUtxos(addressStrs, function(err, utxos) { if (err) return cb(err); - var inputs = _.chain(txps) - .pluck('inputs') - .flatten() - .map(function(utxo) { - return utxo.txid + '|' + utxo.vout - }) - .value(); + self.getPendingTxs({ + walletId: opts.walletId + }, function(err, txps) { + if (err) return cb(err); - var dictionary = _.reduce(utxos, function(memo, utxo) { - memo[utxo.txid + '|' + utxo.vout] = utxo; - return memo; - }, {}); + var inputs = _.chain(txps) + .pluck('inputs') + .flatten() + .map(function(utxo) { + return utxo.txid + '|' + utxo.vout + }) + .value(); - _.each(inputs, function(input) { - if (dictionary[input]) { - dictionary[input].locked = true; - } + var dictionary = _.reduce(utxos, function(memo, utxo) { + memo[utxo.txid + '|' + utxo.vout] = utxo; + return memo; + }, {}); + + _.each(inputs, function(input) { + if (dictionary[input]) { + dictionary[input].locked = true; + } + }); + + // Needed for the clients to sign UTXOs + _.each(utxos, function(utxo) { + utxo.path = addressToPath[utxo.address].path; + utxo.publicKeys = addressToPath[utxo.address].publicKeys; + }); + + return cb(null, utxos); }); - - // Needed for the clients to sign UTXOs - _.each(utxos, function(utxo) { - utxo.path = addressToPath[utxo.address].path; - utxo.publicKeys = addressToPath[utxo.address].publicKeys; - }); - - return cb(null, utxos); }); }); }); @@ -452,11 +462,12 @@ CopayServer.prototype.getTx = function(opts, cb) { }); }; -CopayServer.prototype._broadcastTx = function(rawTx, cb) { - // TODO: this should attempt to broadcast _all_ accepted and not-yet broadcasted (status=='accepted') txps? - cb = cb || function() {}; - - throw 'not implemented'; +CopayServer.prototype._broadcastTx = function(txp, networkName, cb) { + var raw = txp.getRawTx(); + var bc = self._getBlockExplorer('insight', networkName); + bc.broadcast(raw, function(err, txid) { + return cb(err, txid); + }) }; /** @@ -486,9 +497,9 @@ CopayServer.prototype.signTx = function(opts, cb) { var action = _.find(txp.actions, { copayerId: opts.copayerId }); - if (action) + if (action) return cb(new ClientError('CVOTED', 'Copayer already voted on this transaction proposal')); - if (txp.status != 'pending') + if (txp.status != 'pending') return cb(new ClientError('TXNOTPENDING', 'The transaction proposal is not pending')); var copayer = wallet.getCopayer(opts.copayerId); @@ -502,7 +513,7 @@ CopayServer.prototype.signTx = function(opts, cb) { if (err) return cb(err); if (txp.status == 'accepted') { - self._broadcastTx(txp.rawTx, function(err, txid) { + self._broadcastTx(txp, wallet.getNetworkName(), function(err, txid) { if (err) return cb(err); tx.setBroadcasted(txid);