diff --git a/bit-wallet/bit-export b/bit-wallet/bit-export index 7db22e9..a4604b3 100755 --- a/bit-wallet/bit-export +++ b/bit-wallet/bit-export @@ -22,6 +22,7 @@ client.export(function(err, x) { var filename = program.config + '.svg'; var qr_svg = qr.image(x, { type: 'svg' }); qr_svg.pipe(require('fs').createWriteStream(filename)); + console.log('Wallet Critical Data: exported to ' + filename); } else { console.log('Wallet Critical Data:\n', x); } diff --git a/lib/client/api.js b/lib/client/api.js index b8dd5c9..950f159 100644 --- a/lib/client/api.js +++ b/lib/client/api.js @@ -15,6 +15,8 @@ var ServerCompromisedError = require('./servercompromisederror') var BASE_URL = 'http://localhost:3001/copay/api'; +var WALLET_CRITICAL_DATA = ['copayerId', 'xPrivKey', 'm', 'walletPrivKey', 'publicKeyRing']; + function _createProposalOpts(opts, signingKey) { var msg = opts.toAddress + '|' + opts.amount + '|' + opts.message; opts.proposalSignature = WalletUtils.signMessage(msg, signingKey); @@ -104,7 +106,12 @@ API.prototype._loadAndCheck = function(cb) { }; API.prototype._doRequest = function(method, url, args, data, cb) { - var reqSignature = _signRequest(method, url, args, data.signingPrivKey); + var reqSignature; + data = data || {}; + + if (data.signingPrivKey) + reqSignature = _signRequest(method, url, args, data.signingPrivKey); + var absUrl = _getUrl(url); var args = { headers: { @@ -142,8 +149,6 @@ API.prototype._doGetRequest = function(url, data, cb) { return this._doRequest('get', url, {}, data, cb); }; - - API.prototype.createWallet = function(walletName, copayerName, m, n, network, cb) { var self = this; network = network || 'livenet'; @@ -154,62 +159,46 @@ API.prototype.createWallet = function(walletName, copayerName, m, n, network, cb if (data) return cb('Storage already contains a wallet'); - // Generate wallet key pair to verify copayers - var privKey = new Bitcore.PrivateKey(null, network); - var pubKey = privKey.toPublicKey(); - - data = { - m: m, - n: n, - walletPrivKey: privKey.toWIF(), - network: network, - }; - + var walletPrivKey = new Bitcore.PrivateKey(); var args = { name: walletName, m: m, n: n, - pubKey: pubKey.toString(), + pubKey: walletPrivKey.toPublicKey().toString(), network: network, }; var url = '/v1/wallets/'; - - self._doPostRequest(url, args, data, function(err, body) { + self._doPostRequest(url, args, {}, function(err, body) { if (err) return cb(err); var walletId = body.walletId; - var secret = walletId + ':' + privKey.toString() + ':' + (network == 'testnet' ? 'T' : 'L'); + var secret = walletId + ':' + walletPrivKey.toWIF() + ':' + (network == 'testnet' ? 'T' : 'L'); var ret; if (n > 1) - ret = data.secret = secret; - - self.storage.save(data, function(err) { - if (err) return cb(err); - self._joinWallet(data, secret, copayerName, function(err) { - return cb(err, ret); - }); + ret = secret; + self._joinWallet(secret, copayerName, function(err) { + return cb(err, ret); }); }); }); }; -API.prototype._joinWallet = function(data, secret, copayerName, cb) { +API.prototype._joinWallet = function(secret, copayerName, cb) { var self = this; - data = data || {}; var secretSplit = secret.split(':'); var walletId = secretSplit[0]; var walletPrivKey = Bitcore.PrivateKey.fromString(secretSplit[1]); var network = secretSplit[2] == 'T' ? 'testnet' : 'livenet'; - data.xPrivKey = _createXPrivKey(network); + var xPrivKey = _createXPrivKey(network); - var xPubKey = new Bitcore.HDPublicKey(data.xPrivKey); + var xPubKey = new Bitcore.HDPublicKey(xPrivKey); var xPubKeySignature = WalletUtils.signMessage(xPubKey.toString(), walletPrivKey); - var signingPrivKey = (new Bitcore.HDPrivateKey(data.xPrivKey)).derive('m/1/0').privateKey; + var signingPrivKey = (new Bitcore.HDPrivateKey(xPrivKey)).derive('m/1/0').privateKey; var args = { walletId: walletId, name: copayerName, @@ -218,15 +207,17 @@ API.prototype._joinWallet = function(data, secret, copayerName, cb) { }; var url = '/v1/wallets/' + walletId + '/copayers'; - this._doPostRequest(url, args, data, function(err, body) { + this._doPostRequest(url, args, {}, function(err, body) { var wallet = body.wallet; - data.copayerId = body.copayerId; - data.walletPrivKey = walletPrivKey.toWIF(); - data.signingPrivKey = signingPrivKey.toWIF(); - data.m = wallet.m; - data.n = wallet.n; - data.publicKeyRing = wallet.publicKeyRing; - data.network = wallet.network, + var data = { + copayerId: body.copayerId, + walletPrivKey: walletPrivKey.toWIF(), + signingPrivKey: signingPrivKey.toWIF(), + m: wallet.m, + n: wallet.n, + publicKeyRing: wallet.publicKeyRing, + network: wallet.network, + }; self.storage.save(data, cb); }); }; @@ -238,7 +229,7 @@ API.prototype.joinWallet = function(secret, copayerName, cb) { if (data) return cb('Storage already contains a wallet'); - self._joinWallet(data, secret, copayerName, cb); + self._joinWallet(secret, copayerName, cb); }); }; @@ -313,11 +304,27 @@ API.prototype.export = function(cb) { this._loadAndCheck(function(err, data) { if (err) return cb(err); - var x = _.pick(data, ['publicKeyRing', 'xPrivKey', 'copayerId', 'm']) - return cb(null, JSON.stringify(x)); + var x = _.pick(data, WALLET_CRITICAL_DATA) + return cb(null, JSON.stringify(_.values(x))); }); } + +API.prototype.import = function(str, cb) { + var self = this; + + var inData = JSON.parse(str); + var data = {}, + i = 0; + + _.each(WALLET_CRITICAL_DATA, function(k) { + data[k] = inData[i++]; + }); + + if (err) return cb(err); +} + + API.prototype.getTxProposals = function(opts, cb) { var self = this;