Merge pull request #18 from matiu/feat/client-filestorage

add FileStorage + refactor
This commit is contained in:
Ivan Socolsky 2015-02-15 14:11:03 -03:00
commit d96634f951
14 changed files with 167 additions and 184 deletions

View File

@ -2,7 +2,7 @@
var program = require('commander');
var Client = require('../lib/client');
var common = require('./common');
var utils = require('./cli-utils');
program
.version('0.0.1')
@ -11,14 +11,8 @@ program
.parse(process.argv);
var args = program.args;
var cli = new Client({
filename: program.config
});
cli.createAddress(function(err, x) {
common.die(err);
var client = utils.getClient(program);
client.createAddress(function(err, x) {
utils.die(err);
console.log('* New Address %s ', x.address);
if (program.verbose)
console.log('* Raw Server Response:\n', x); //TODO
});

View File

@ -2,7 +2,7 @@
var _ = require('lodash');
var program = require('commander');
var common = require('./common');
var utils = require('./cli-utils');
var Client = require('../lib/client');
program
@ -12,18 +12,12 @@ program
.parse(process.argv);
var args = program.args;
var cli = new Client({
filename: program.config
});
cli.getAddresses(function(err, x) {
common.die(err);
var client = utils.getClient(program);
client.getAddresses(function(err, x) {
utils.die(err);
console.log('* Addresses:');
_.each(x, function(a){
console.log(' ', a.address);
});
if (program.verbose)
console.log('* Raw Server Response:\n', x); //TODO
});

View File

@ -2,7 +2,7 @@
var program = require('commander');
var Client = require('../lib/client');
var common = require('./common');
var utils = require('./cli-utils');
program
.version('0.0.1')
@ -11,14 +11,9 @@ program
.parse(process.argv);
var args = program.args;
var cli = new Client({
filename: program.config
});
var client = utils.getClient(program);
cli.getBalance(function(err, x) {
common.die(err);
client.getBalance(function(err, x) {
utils.die(err);
console.log('* Wallet balance', x);
if (program.verbose)
console.log('* Raw Server Response:\n', x); //TODO
});

View File

@ -2,7 +2,7 @@
var program = require('commander');
var ClientLib = require('../lib/client');
var common = require('./common');
var utils = require('./cli-utils');
program
.version('0.0.1')
@ -19,13 +19,11 @@ var walletName = args[0];
var copayerName = args[2] || process.env.USER;
var network = program.network;
var mn = common.parseMN(args[1]);
var mn = utils.parseMN(args[1]);
var cli = new ClientLib({
filename: program.config
});
cli.createWallet(walletName, copayerName, mn[0], mn[1], network, function(err, secret) {
common.die(err);
var client = utils.getClient(program);
client.createWallet(walletName, copayerName, mn[0], mn[1], network, function(err, secret) {
utils.die(err);
console.log(' * Wallet Created.');
console.log(' - Secret to share:\n\t' + secret);
});

View File

@ -1,8 +1,8 @@
#!/usr/bin/env node
var program = require('commander');
var ClientLib = require('../lib/client');
var common = require('./common');
var Client = require('../lib/client');
var utils = require('./cli-utils');
program
.version('0.0.1')
@ -17,11 +17,8 @@ if (!args[0])
var secret = args[0];
var copayerName = args[1] || process.env.USER;
var cli = new ClientLib({
filename: program.config
});
var client = utils.getClient(program);
cli.joinWallet(secret, copayerName, function(err, xx) {
common.die(err);
utils.die(err);
console.log(' * Wallet Joined.', xx || '');
});

View File

@ -3,7 +3,7 @@
var _ = require('lodash');
var program = require('commander');
var Client = require('../lib/client');
var common = require('./common');
var utils = require('./cli-utils');
program
.version('0.0.1')
@ -17,25 +17,14 @@ if (!args[0])
program.help();
var txpid = args[0];
var reason = args[1] || '';
var client = utils.getClient(program);
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.rejectTxProposal(txp, reason, function(err, tx) {
common.die(err);
if (program.verbose)
console.log('* Raw Server Response:\n', tx); //TODO
client.getTxProposals({}, function(err, txps) {
utils.die(err);
var txp = utils.findOneTxProposal(txps, txpid);
client.rejectTxProposal(txp, reason, function(err, tx) {
utils.die(err);
console.log('Transaction rejected.');
});
});

View File

@ -2,32 +2,31 @@
var program = require('commander');
var Client = require('../lib/client');
var common = require('./common');
var utils = require('./cli-utils');
program
.version('0.0.1')
.option('-c, --config [file]', 'Wallet config filename')
.option('-v, --verbose', 'be verbose')
.usage('[options] <address> <amount> <message>')
.parse(process.argv);
.version('0.0.1')
.option('-c, --config [file]', 'Wallet config filename')
.option('-v, --verbose', 'be verbose')
.usage('[options] <address> <amount> <message>')
.parse(process.argv);
var args = program.args;
if (!args[0] || !args[1] || !args[2])
program.help();
var address = args[0];
var amount = args[1];
var message = args[2];
var address = args[0];
var amount = args[1];
var message = args[2];
var cli = new Client({
filename: program.config
var client = utils.getClient(program);
client.sendTxProposal({
toAddress: address,
amount: amount,
message: message
}, function(err, x) {
utils.die(err);
console.log(' * Tx created: ID %s [%s] RequiredSignatures:',
x.id, x.status, x.requiredSignatures);
});
cli.sendTxProposal({toAddress: address, amount: amount, message:message}, function(err, x) {
common.die(err);
console.log(' * Tx created: ID %s [%s] RequiredSignatures:',
x.id, x.status, x.requiredSignatures);
if (program.verbose)
console.log('* Raw Server Response:\n', x); //TODO
});

View File

@ -2,8 +2,7 @@
var _ = require('lodash');
var program = require('commander');
var ClientLib = require('../lib/client');
var common = require('./common');
var utils = require('./cli-utils');
program
.version('0.0.1')
@ -18,24 +17,13 @@ if (!args[0])
var txpid = args[0];
var cli = new ClientLib({
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.signTxProposal(txp, function(err, tx) {
common.die(err);
if (program.verbose)
console.log('* Raw Server Response:\n', tx); //TODO
var client = utils.getClient(program);
client.getTxProposals({}, function(err, txps) {
utils.die(err);
var txp = utils.findOneTxProposal(txps, txpid);
client.signTxProposal(txp, function(err, x) {
utils.die(err);
console.log('Transaction signed.');
});
});

View File

@ -2,9 +2,7 @@
var _ = require('lodash');
var program = require('commander');
var Client = require('../lib/client');
var common = require('./common');
var utils = require('./cli-utils');
program
.version('0.0.1')
@ -13,12 +11,10 @@ program
.parse(process.argv);
var args = program.args;
var cli = new Client({
filename: program.config
});
var client = utils.getClient(program);
cli.getStatus(function(err, res) {
common.die(err);
client.getStatus(function(err, res) {
utils.die(err);
var x = res.wallet;
console.log('* Wallet %s [%s]: %d-%d %s ', x.name, x.isTestnet ? 'testnet' : 'livenet', x.m, x.n, x.status);
@ -29,7 +25,7 @@ cli.getStatus(function(err, res) {
if (!_.isEmpty(res.pendingTxps)) {
console.log("* TX Proposals:")
_.each(res.pendingTxps, function(x) {
console.log("\t%s [%s by %s] %dSAT => %s", common.shortID(x.id), x.message, x.creatorName, x.amount, x.toAddress);
console.log("\t%s [%s by %s] %dSAT => %s", utils.shortID(x.id), x.message, x.creatorName, x.amount, x.toAddress);
if (!_.isEmpty(x.actions)) {
console.log('\t\t * Actions');

62
bit-wallet/cli-utils.js Normal file
View File

@ -0,0 +1,62 @@
var _ = require('lodash');
var Client = require('../lib/client');
var lib = function() {};
var die = lib.die = function(err) {
if (err) {
console.error(err);
process.exit(1);
}
};
lib.parseMN = function(MN) {
if (!MN)
die('No m-n parameter');
var mn = MN.split('-');
var m = parseInt(mn[0]);
var n = parseInt(mn[1]);
if (!m || ! n) {
die('Bad m-n parameter');
}
return [m, n];
};
lib.shortID = function(id) {
return id.substr(id.length - 4);
};
lib.getClient = function(args) {
var storage = new Client.FileStorage({
filename: args.config
});
return new Client({
storage: storage,
verbose: args.verbose
});
}
lib.findOneTxProposal = function(txps, id) {
var matches = _.filter(txps, function(tx) {
return _.endsWith(lib.shortID(tx.id), id);
});
if (!matches.length)
lib.die('Could not find TX Proposal:' + id);
if (matches.length > 1)
lib.die('More than one TX Proposals match:' + id + ' : ' + _.map(matches, function(tx) {
return tx.id;
}).join(' '));;
return matches[0];
};
module.exports = lib;

View File

@ -1,51 +0,0 @@
'use strict';
var _ = require('lodash');
var common = function() {};
var die = common.die = function(err) {
if (err) {
console.error(err);
process.exit(1);
}
};
common.parseMN = function(MN) {
if (!MN)
die('No m-n parameter');
var mn = MN.split('-');
var m = parseInt(mn[0]);
var n = parseInt(mn[1]);
if (!m || !n) {
die('Bad m-n parameter');
}
return [m, n];
};
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;

View File

@ -1,12 +1,11 @@
'use strict';
var _ = require('lodash');
var util = require('util');
var async = require('async');
var log = require('npmlog');
var request = require('request')
log.debug = log.verbose;
log.level = 'debug';
var fs = require('fs')
var Bitcore = require('bitcore')
var SignUtils = require('../signutils');
@ -48,24 +47,19 @@ function _createXPrivKey(network) {
};
function API(opts) {
if (!opts.filename) {
throw new Error('Please set the config filename');
if (!opts.storage) {
throw new Error('Must provide storage option');
}
this.storage = opts.storage;
this.verbose = !!opts.verbose;
if (this.verbose) {
log.level = 'debug';
}
this.filename = opts.filename;
};
API.prototype._save = function(data) {
fs.writeFileSync(this.filename, JSON.stringify(data));
};
API.prototype._load = function() {
try {
return JSON.parse(fs.readFileSync(this.filename));
} catch (ex) {}
};
API.prototype._loadAndCheck = function() {
var data = this._load();
var data = this.storage.load();
if (!data) {
log.error('Wallet file not found.');
process.exit(1);
@ -87,7 +81,7 @@ API.prototype._loadAndCheck = function() {
API.prototype._doRequest = function(method, url, args, data, cb) {
var reqSignature = _signRequest(method, url, args, data.signingPrivKey);
var absUrl = _getUrl(url);
request({
var args = {
headers: {
'x-identity': data.copayerId,
'x-signature': reqSignature,
@ -96,7 +90,11 @@ API.prototype._doRequest = function(method, url, args, data, cb) {
url: absUrl,
body: args,
json: true,
}, function(err, res, body) {
};
log.verbose('Request Args', util.inspect(args));
request(args, function(err, res, body) {
log.verbose('Response:', err, body);
if (err) return cb(err);
if (res.statusCode != 200) {
_parseError(body);
@ -123,7 +121,7 @@ API.prototype.createWallet = function(walletName, copayerName, m, n, network, cb
if (!_.contains(['testnet', 'livenet'], network))
return cb('Invalid network');
var data = this._load();
var data = this.storage.load();
if (data) return cb('File ' + this.filename + ' already contains a wallet');
// Generate wallet key pair to verify copayers
@ -152,7 +150,7 @@ API.prototype.createWallet = function(walletName, copayerName, m, n, network, cb
var secret = walletId + ':' + privKey.toString() + ':' + (network == 'testnet' ? 'T' : 'L');
data.secret = secret;
self._save(data);
self.storage.save(data);
self._joinWallet(data, secret, copayerName, function(err) {
if (err) return cb(err);
@ -192,7 +190,7 @@ API.prototype._joinWallet = function(data, secret, copayerName, cb) {
data.m = wallet.m;
data.n = wallet.n;
data.publicKeyRing = wallet.publicKeyRing;
self._save(data);
self.storage.save(data);
return cb();
});
@ -201,7 +199,7 @@ API.prototype._joinWallet = function(data, secret, copayerName, cb) {
API.prototype.joinWallet = function(secret, copayerName, cb) {
var self = this;
var data = this._load();
var data = this.storage.load();
if (data) return cb('File ' + this.filename + ' already contains a wallet');
self._joinWallet(data, secret, copayerName, cb);
@ -236,7 +234,7 @@ API.prototype.getStatus = function(cb) {
} else {
data.verified = 'ok';
}
self._save(data);
self.storage.save(data);
}
return cb(null, wallet);

24
lib/client/FileStorage.js Normal file
View File

@ -0,0 +1,24 @@
var fs = require('fs')
function FileStorage(opts) {
if (!opts.filename) {
throw new Error('Please set the config filename');
}
this.filename = opts.filename;
};
FileStorage.prototype.save = function(data) {
fs.writeFileSync(this.filename, JSON.stringify(data));
};
FileStorage.prototype.load = function() {
try {
return JSON.parse(fs.readFileSync(this.filename));
} catch (ex) {}
};
module.exports = FileStorage;

View File

@ -1,7 +1,7 @@
//var client = ;
module.exports = require('./API');
//client.verificator = require('./API');
var client = module.exports = require('./API');
client.FileStorage = require('./FileStorage');
// TODO