commit
7177baf043
24
app.js
24
app.js
|
@ -44,6 +44,8 @@ var router = express.Router();
|
||||||
|
|
||||||
function returnError(err, res) {
|
function returnError(err, res) {
|
||||||
if (err instanceof CopayServer.ClientError) {
|
if (err instanceof CopayServer.ClientError) {
|
||||||
|
|
||||||
|
console.log('[app.js.47]'); //TODO
|
||||||
var status = (err.code == 'NOTAUTHORIZED') ? 401 : 400;
|
var status = (err.code == 'NOTAUTHORIZED') ? 401 : 400;
|
||||||
res.status(status).json({
|
res.status(status).json({
|
||||||
code: err.code,
|
code: err.code,
|
||||||
|
@ -78,7 +80,6 @@ function getServerWithAuth(req, res, cb) {
|
||||||
message: req.url + '|' + JSON.stringify(req.body),
|
message: req.url + '|' + JSON.stringify(req.body),
|
||||||
signature: credentials.signature,
|
signature: credentials.signature,
|
||||||
};
|
};
|
||||||
|
|
||||||
CopayServer.getInstanceWithAuth(auth, function(err, server) {
|
CopayServer.getInstanceWithAuth(auth, function(err, server) {
|
||||||
if (err) return returnError(err, res);
|
if (err) return returnError(err, res);
|
||||||
return cb(server);
|
return cb(server);
|
||||||
|
@ -87,26 +88,27 @@ function getServerWithAuth(req, res, cb) {
|
||||||
|
|
||||||
router.post('/v1/wallets/', function(req, res) {
|
router.post('/v1/wallets/', function(req, res) {
|
||||||
var server = CopayServer.getInstance();
|
var server = CopayServer.getInstance();
|
||||||
server.createWallet(req.body, function(err, wallet) {
|
server.createWallet(req.body, function(err, walletId) {
|
||||||
if (err) returnError(err, res);
|
if (err) return returnError(err, res);
|
||||||
|
|
||||||
res.json(wallet);
|
res.json({
|
||||||
|
walletId: walletId,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.post('/v1/wallets/:id/copayers/', function(req, res) {
|
router.post('/v1/wallets/:id/copayers/', function(req, res) {
|
||||||
req.body.walletId = req.params['id'];
|
req.body.walletId = req.params['id'];
|
||||||
var server = CopayServer.getInstance();
|
var server = CopayServer.getInstance();
|
||||||
server.joinWallet(req.body, function(err) {
|
server.joinWallet(req.body, function(err, result) {
|
||||||
if (err) returnError(err, res);
|
if (err) return returnError(err, res);
|
||||||
|
|
||||||
res.end();
|
res.json(result);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/v1/wallets/', function(req, res) {
|
router.get('/v1/wallets/', function(req, res) {
|
||||||
getServerWithAuth(req, res, function(server) {
|
getServerWithAuth(req, res, function(server) {
|
||||||
if (err) return returnError(err, res);
|
|
||||||
server.getWallet({}, function(err, wallet) {
|
server.getWallet({}, function(err, wallet) {
|
||||||
if (err) returnError(err, res);
|
if (err) returnError(err, res);
|
||||||
res.json(wallet);
|
res.json(wallet);
|
||||||
|
@ -117,7 +119,7 @@ router.get('/v1/wallets/', function(req, res) {
|
||||||
router.post('/v1/addresses/', function(req, res) {
|
router.post('/v1/addresses/', function(req, res) {
|
||||||
getServerWithAuth(req, res, function(server) {
|
getServerWithAuth(req, res, function(server) {
|
||||||
server.createAddress(req.body, function(err, address) {
|
server.createAddress(req.body, function(err, address) {
|
||||||
if (err) returnError(err, res);
|
if (err) return returnError(err, res);
|
||||||
res.json(address);
|
res.json(address);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -126,7 +128,7 @@ router.post('/v1/addresses/', function(req, res) {
|
||||||
router.get('/v1/addresses/', function(req, res) {
|
router.get('/v1/addresses/', function(req, res) {
|
||||||
getServerWithAuth(req, res, function(server) {
|
getServerWithAuth(req, res, function(server) {
|
||||||
server.getAddresses({}, function(err, addresses) {
|
server.getAddresses({}, function(err, addresses) {
|
||||||
if (err) returnError(err, res);
|
if (err) return returnError(err, res);
|
||||||
res.json(addresses);
|
res.json(addresses);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -135,7 +137,7 @@ router.get('/v1/addresses/', function(req, res) {
|
||||||
router.get('/v1/balance/', function(req, res) {
|
router.get('/v1/balance/', function(req, res) {
|
||||||
getServerWithAuth(req, res, function(server) {
|
getServerWithAuth(req, res, function(server) {
|
||||||
server.getBalance({}, function(err, balance) {
|
server.getBalance({}, function(err, balance) {
|
||||||
if (err) returnError(err, res);
|
if (err) return returnError(err, res);
|
||||||
res.json(balance);
|
res.json(balance);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
var program = require('commander');
|
||||||
|
var cli = require('../lib/clilib.js');
|
||||||
|
|
||||||
|
program
|
||||||
|
.version('0.0.1')
|
||||||
|
.command('create <walletName> <m-n> [username]', 'creates a wallet')
|
||||||
|
.command('join <secret> [username]', 'join a wallet')
|
||||||
|
.command('status', 'get wallet status')
|
||||||
|
.parse(process.argv);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
var program = require('commander');
|
||||||
|
var CliLib = require('../lib/clilib.js');
|
||||||
|
var common = require('./common');
|
||||||
|
|
||||||
|
program
|
||||||
|
.version('0.0.1')
|
||||||
|
.option('-c,--config [file]', 'Wallet config filename')
|
||||||
|
.option('-n,--network [networkname]', 'livenet|testnet', String, 'livenet')
|
||||||
|
.usage('[options] <walletName> <m-n> [copayerName]')
|
||||||
|
.parse(process.argv);
|
||||||
|
|
||||||
|
var args = program.args;
|
||||||
|
if (!args[0])
|
||||||
|
program.help();
|
||||||
|
|
||||||
|
var walletName = args[0];
|
||||||
|
var copayerName = args[2] || process.env.USER;
|
||||||
|
var network = program.network;
|
||||||
|
|
||||||
|
var mn = common.parseMN(args[1]);
|
||||||
|
|
||||||
|
var cli = new CliLib({
|
||||||
|
filename: program.config
|
||||||
|
});
|
||||||
|
cli.createWallet(walletName, copayerName, mn[0], mn[1], network, function(err, secret) {
|
||||||
|
common.die(err);
|
||||||
|
console.log(' * Wallet Created.');
|
||||||
|
console.log(' - Secret to share:\n\t' + secret);
|
||||||
|
});
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
var program = require('commander');
|
||||||
|
var cli = require('../lib/clilib.js');
|
||||||
|
|
||||||
|
program
|
||||||
|
.version('0.0.1')
|
||||||
|
.parse(process.argv);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
var program = require('commander');
|
||||||
|
var CliLib = require('../lib/clilib.js');
|
||||||
|
var common = require('./common');
|
||||||
|
|
||||||
|
program
|
||||||
|
.version('0.0.1')
|
||||||
|
.option('-c,--config [file]', 'Wallet config filename')
|
||||||
|
.usage('[options] <secret> [copayerName]')
|
||||||
|
.parse(process.argv);
|
||||||
|
|
||||||
|
var args = program.args;
|
||||||
|
if (!args[0])
|
||||||
|
program.help();
|
||||||
|
|
||||||
|
var secret = args[0];
|
||||||
|
var copayerName = args[1] || process.env.USER;
|
||||||
|
|
||||||
|
var cli = new CliLib({
|
||||||
|
filename: program.config
|
||||||
|
});
|
||||||
|
|
||||||
|
cli.joinWallet(secret, copayerName, function(err, xx) {
|
||||||
|
common.die(err);
|
||||||
|
console.log(' * Wallet Joined.', xx || '');
|
||||||
|
});
|
|
@ -0,0 +1,21 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
var program = require('commander');
|
||||||
|
var CliLib = require('../lib/clilib.js');
|
||||||
|
var common = require('./common');
|
||||||
|
|
||||||
|
program
|
||||||
|
.version('0.0.1')
|
||||||
|
.option('-c,--config [file]', 'Wallet config filename')
|
||||||
|
.parse(process.argv);
|
||||||
|
|
||||||
|
var args = program.args;
|
||||||
|
var cli = new CliLib({
|
||||||
|
filename: program.config
|
||||||
|
});
|
||||||
|
|
||||||
|
cli.status(function(err, xx) {
|
||||||
|
common.die(err);
|
||||||
|
console.log(' * Status:', xx);
|
||||||
|
});
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
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];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = common;
|
|
@ -0,0 +1,30 @@
|
||||||
|
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);
|
||||||
|
})
|
||||||
|
});
|
213
lib/clilib.js
213
lib/clilib.js
|
@ -4,7 +4,6 @@ var _ = require('lodash');
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
var log = require('npmlog');
|
var log = require('npmlog');
|
||||||
var request = require('request')
|
var request = require('request')
|
||||||
var commander = require('commander')
|
|
||||||
log.debug = log.verbose;
|
log.debug = log.verbose;
|
||||||
log.level = 'debug';
|
log.level = 'debug';
|
||||||
var fs = require('fs')
|
var fs = require('fs')
|
||||||
|
@ -14,132 +13,238 @@ var SignUtils = require('./signutils');
|
||||||
|
|
||||||
var BASE_URL = 'http://localhost:3001/copay/api/';
|
var BASE_URL = 'http://localhost:3001/copay/api/';
|
||||||
|
|
||||||
var cli = {};
|
|
||||||
|
|
||||||
|
|
||||||
function _getUrl(path) {
|
function _getUrl(path) {
|
||||||
return BASE_URL + path;
|
return BASE_URL + path;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function _parseError(body) {
|
||||||
function signRequest(url, args) {
|
if (_.isString(body)) {
|
||||||
|
body = JSON.parse(body);
|
||||||
|
}
|
||||||
|
var code = body.code || 'ERROR';
|
||||||
|
var message = body.error || 'There was an unknown error processing the request';
|
||||||
|
log.error(code, message);
|
||||||
};
|
};
|
||||||
|
|
||||||
function save(data) {
|
function _signRequest(url, args, privKey) {
|
||||||
fs.writeFileSync('./.bit', JSON.stringify(data));
|
var message = url + '|' + JSON.stringify(args);
|
||||||
|
return SignUtils.sign(message, privKey);
|
||||||
};
|
};
|
||||||
|
|
||||||
function load() {
|
function _createXPrivKey() {
|
||||||
|
return new Bitcore.HDPrivateKey().toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
function CliLib(opts) {
|
||||||
|
if (!opts.filename) {
|
||||||
|
throw new Error('Please set the config filename');
|
||||||
|
}
|
||||||
|
this.filename = opts.filename;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
CliLib.prototype._save = function(data) {
|
||||||
|
fs.writeFileSync(this.filename, JSON.stringify(data));
|
||||||
|
};
|
||||||
|
|
||||||
|
CliLib.prototype._load = function() {
|
||||||
try {
|
try {
|
||||||
return JSON.parse(fs.readFileSync('./.bit'));
|
return JSON.parse(fs.readFileSync(this.filename));
|
||||||
} catch (ex) {}
|
} catch (ex) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CliLib.prototype._loadAndCheck = function() {
|
||||||
|
var data = this._load();
|
||||||
clilib.createWallet = function(walletName, copayerName, m, n, cb) {
|
|
||||||
var data = load();
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
data = {};
|
log.error('Wallet file not found.');
|
||||||
data.xPrivKey = new Bitcore.HDPrivateKey().toString();
|
process.exit(1);
|
||||||
data.m = m;
|
|
||||||
}
|
}
|
||||||
|
if (data.verified == 'corrupt') {
|
||||||
|
log.error('The wallet is tagged as corrupt. Some of the copayers cannot be verified to have known the wallet secret.');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
if (data.n > 1) {
|
||||||
|
var pkrComplete = data.publicKeyRing && data.m && data.publicKeyRing.length === data.n;
|
||||||
|
if (!pkrComplete) {
|
||||||
|
log.warn('The file ' + this.filename + ' is incomplete. It will allow you to operate with the wallet but it should not be trusted as a backup. Please wait for all copayers to join the wallet and run the tool with -export flag.')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
CliLib.prototype.createWallet = function(walletName, copayerName, m, n, network, cb) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var data = this._load();
|
||||||
|
if (data) return cb('File ' + this.filename + ' already contains a wallet');
|
||||||
|
|
||||||
|
// Generate wallet key pair to verify copayers
|
||||||
var privKey = new Bitcore.PrivateKey();
|
var privKey = new Bitcore.PrivateKey();
|
||||||
var pubKey = privKey.toPublicKey();
|
var pubKey = privKey.toPublicKey();
|
||||||
|
|
||||||
|
data = {
|
||||||
|
xPrivKey: _createXPrivKey(),
|
||||||
|
m: m,
|
||||||
|
n: n,
|
||||||
|
walletPrivKey: privKey.toString(),
|
||||||
|
};
|
||||||
|
|
||||||
var args = {
|
var args = {
|
||||||
name: walletName,
|
name: walletName,
|
||||||
m: m,
|
m: m,
|
||||||
n: n,
|
n: n,
|
||||||
pubKey: pubKey.toString(),
|
pubKey: pubKey.toString(),
|
||||||
|
network: network || 'livenet',
|
||||||
};
|
};
|
||||||
|
|
||||||
request({
|
request({
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: _getUrl('v1/wallets'),
|
url: _getUrl('/v1/wallets/'),
|
||||||
body: args,
|
body: args,
|
||||||
json: true,
|
json: true,
|
||||||
}, function(err, res, body) {
|
}, function(err, res, body) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
var walletId = body;
|
if (res.statusCode != 200) {
|
||||||
var secret = walletId + '|' + privKey.toString();
|
_parseError(body);
|
||||||
|
return cb('Request error');
|
||||||
|
}
|
||||||
|
|
||||||
joinWallet(secret, copayerName, function(err) {
|
var walletId = body.walletId;
|
||||||
|
var secret = walletId + ':' + privKey.toString();
|
||||||
|
data.secret = secret;
|
||||||
|
|
||||||
|
self._save(data);
|
||||||
|
|
||||||
|
self._joinWallet(data, secret, copayerName, function(err) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
|
||||||
save(data);
|
return cb(null, data.secret);
|
||||||
return cb(null, secret);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
clilib.joinWallet = function(secret, copayerName, cb) {
|
CliLib.prototype._joinWallet = function(data, secret, copayerName, cb) {
|
||||||
var data = load();
|
var self = this;
|
||||||
if (!data) {
|
|
||||||
data = {};
|
var secretSplit = secret.split(':');
|
||||||
data.xPrivKey = new Bitcore.HDPrivateKey().toString();
|
|
||||||
}
|
|
||||||
var secretSplit = secret.split('|');
|
|
||||||
var walletId = secretSplit[0];
|
var walletId = secretSplit[0];
|
||||||
var privKey = Bitcore.PrivateKey.fromString(secretSplit[1]);
|
var privKey = Bitcore.PrivateKey.fromString(secretSplit[1]);
|
||||||
var pubKey = privKey.toPublicKey();
|
|
||||||
|
|
||||||
var xPubKey = new Bitcore.HDPublicKey(data.xPrivKey).toString();
|
var xPubKey = new Bitcore.HDPublicKey(data.xPrivKey);
|
||||||
var xPubKeySignature = SignUtils.sign(xPubKey, privKey);
|
var xPubKeySignature = SignUtils.sign(xPubKey.toString(), privKey);
|
||||||
|
|
||||||
|
var signingPrivKey = (new Bitcore.HDPrivateKey(data.xPrivKey)).derive('m/1/0').privateKey;
|
||||||
|
|
||||||
var args = {
|
var args = {
|
||||||
walletId: walletId,
|
walletId: walletId,
|
||||||
name: copayerName,
|
name: copayerName,
|
||||||
xPubKey: xPubKey,
|
xPubKey: xPubKey.toString(),
|
||||||
xPubKeySignature: xPubKeySignature,
|
xPubKeySignature: xPubKeySignature,
|
||||||
};
|
};
|
||||||
|
|
||||||
request({
|
request({
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: _getUrl('v1/wallets/' + walletId + '/copayers'),
|
url: _getUrl('/v1/wallets/' + walletId + '/copayers'),
|
||||||
body: args,
|
body: args,
|
||||||
json: true,
|
json: true,
|
||||||
}, function(err, res, body) {
|
}, function(err, res, body) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
if (res.statusCode != 200) {
|
||||||
|
_parseError(body);
|
||||||
|
return cb('Request error');
|
||||||
|
}
|
||||||
|
|
||||||
var copayerId = body;
|
var wallet = body.wallet;
|
||||||
data.copayerId = copayerId;
|
data.copayerId = body.copayerId;
|
||||||
save(data);
|
data.signingPrivKey = signingPrivKey.toString();
|
||||||
return status(cb);
|
data.m = wallet.m;
|
||||||
});
|
data.n = wallet.n;
|
||||||
};
|
data.publicKeyRing = wallet.publicKeyRing;
|
||||||
|
self._save(data);
|
||||||
|
|
||||||
clilib.status = function(cb) {
|
|
||||||
request({
|
|
||||||
method: 'get',
|
|
||||||
url: _getUrl('v1/dump/'),
|
|
||||||
}, function(err, res, body) {
|
|
||||||
if (err) return cb(err);
|
|
||||||
|
|
||||||
console.log(body);
|
|
||||||
return cb();
|
return cb();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
clilib.send = function(addressTo, amount, message, cb) {
|
CliLib.prototype.joinWallet = function(secret, copayerName, cb) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var data = this._load();
|
||||||
|
if (data) return cb('File ' + this.filename + ' already contains a wallet');
|
||||||
|
|
||||||
|
data = {
|
||||||
|
xPrivKey: _createXPrivKey(),
|
||||||
|
};
|
||||||
|
|
||||||
|
self._joinWallet(data, secret, copayerName, cb);
|
||||||
|
};
|
||||||
|
|
||||||
|
CliLib.prototype.status = function(cb) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var data = this._loadAndCheck();
|
||||||
|
console.log('[clilib.js.180:data:]', data); //TODO
|
||||||
|
|
||||||
|
var url = '/v1/wallets/';
|
||||||
|
var signature = _signRequest(url, {}, data.signingPrivKey);
|
||||||
|
|
||||||
|
request({
|
||||||
|
headers: {
|
||||||
|
'x-identity': data.copayerId,
|
||||||
|
'x-signature': signature,
|
||||||
|
},
|
||||||
|
method: 'get',
|
||||||
|
url: _getUrl(url),
|
||||||
|
json: true,
|
||||||
|
}, function(err, res, body) {
|
||||||
|
if (err) return cb(err);
|
||||||
|
if (res.statusCode != 200) {
|
||||||
|
_parseError(body);
|
||||||
|
return cb('Request error');
|
||||||
|
}
|
||||||
|
var wallet = body;
|
||||||
|
|
||||||
|
if (wallet.n > 0 && wallet.status === 'complete' && !data.verified) {
|
||||||
|
var pubKey = Bitcore.PrivateKey.fromString(data.walletPrivKey).toPublicKey().toString();
|
||||||
|
var fake = [];
|
||||||
|
_.each(wallet.copayers, function(copayer) {
|
||||||
|
if (!SignUtils.verify(copayer.xPubKey, copayer.xPubKeySignature, pubKey)) {
|
||||||
|
fake.push(copayer);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (fake.length > 0) {
|
||||||
|
log.error('Some copayers in the wallet could not be verified to have known the wallet secret');
|
||||||
|
data.verified = 'corrupt';
|
||||||
|
} else {
|
||||||
|
data.verified = 'ok';
|
||||||
|
}
|
||||||
|
self._save(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cb(null, wallet);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
CliLib.prototype.send = function(addressTo, amount, message, cb) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
clilib.sign = function(proposalId, cb) {
|
CliLib.prototype.sign = function(proposalId, cb) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
clilib.reject = function(proposalId, cb) {
|
CliLib.prototype.reject = function(proposalId, cb) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
clilib.address = function(cb) {
|
CliLib.prototype.address = function(cb) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
clilib.history = function(limit, cb) {
|
CliLib.prototype.history = function(limit, cb) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = clilib;
|
module.exports = CliLib;
|
||||||
|
|
|
@ -221,11 +221,17 @@ CopayServer.prototype.joinWallet = function(opts, cb) {
|
||||||
|
|
||||||
wallet.addCopayer(copayer);
|
wallet.addCopayer(copayer);
|
||||||
self.storage.storeWalletAndUpdateCopayersLookup(wallet, function(err) {
|
self.storage.storeWalletAndUpdateCopayersLookup(wallet, function(err) {
|
||||||
|
if (err) return cb(err);
|
||||||
|
|
||||||
self._notify('NewCopayer', {
|
self._notify('NewCopayer', {
|
||||||
walletId: opts.walletId,
|
walletId: opts.walletId,
|
||||||
copayerId: copayer.id,
|
copayerId: copayer.id,
|
||||||
|
copayerName: copayer.name,
|
||||||
|
});
|
||||||
|
return cb(null, {
|
||||||
|
copayerId: copayer.id,
|
||||||
|
wallet: wallet
|
||||||
});
|
});
|
||||||
return cb(err, copayer.id);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,6 +5,7 @@ var levelup = require('levelup');
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
var $ = require('preconditions').singleton();
|
var $ = require('preconditions').singleton();
|
||||||
var log = require('npmlog');
|
var log = require('npmlog');
|
||||||
|
var util = require('util');
|
||||||
log.debug = log.verbose;
|
log.debug = log.verbose;
|
||||||
|
|
||||||
var Wallet = require('./model/wallet');
|
var Wallet = require('./model/wallet');
|
||||||
|
@ -195,8 +196,8 @@ Storage.prototype.fetchNotifications = function(walletId, opts, cb) {
|
||||||
var txs = [];
|
var txs = [];
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
opts.limit = _.isNumber(opts.limit) ? parseInt(opts.limit) : -1;
|
opts.limit = _.isNumber(opts.limit) ? parseInt(opts.limit) : -1;
|
||||||
opts.minTs = _.isNumber(opts.minTs) ? zeroPad(opts.minTs,11) : 0;
|
opts.minTs = _.isNumber(opts.minTs) ? zeroPad(opts.minTs, 11) : 0;
|
||||||
opts.maxTs = _.isNumber(opts.maxTs) ? zeroPad(opts.maxTs,11) : MAX_TS;
|
opts.maxTs = _.isNumber(opts.maxTs) ? zeroPad(opts.maxTs, 11) : MAX_TS;
|
||||||
|
|
||||||
var key = KEY.NOTIFICATION(walletId, opts.minTs);
|
var key = KEY.NOTIFICATION(walletId, opts.minTs);
|
||||||
var endkey = KEY.NOTIFICATION(walletId, opts.maxTs);
|
var endkey = KEY.NOTIFICATION(walletId, opts.maxTs);
|
||||||
|
@ -380,7 +381,11 @@ Storage.prototype._dump = function(cb, fn) {
|
||||||
fn = fn || console.log;
|
fn = fn || console.log;
|
||||||
|
|
||||||
this.db.readStream()
|
this.db.readStream()
|
||||||
.on('data', fn)
|
.on('data', function(data) {
|
||||||
|
fn(util.inspect(data, {
|
||||||
|
depth: 10
|
||||||
|
}));
|
||||||
|
})
|
||||||
.on('end', function() {
|
.on('end', function() {
|
||||||
if (cb) return cb();
|
if (cb) return cb();
|
||||||
});
|
});
|
||||||
|
|
|
@ -57,8 +57,8 @@ helpers.createAndJoinWallet = function(m, n, cb) {
|
||||||
xPubKeySignature: TestData.copayers[i].xPubKeySignature,
|
xPubKeySignature: TestData.copayers[i].xPubKeySignature,
|
||||||
};
|
};
|
||||||
|
|
||||||
server.joinWallet(copayerOpts, function(err, copayerId) {
|
server.joinWallet(copayerOpts, function(err, result) {
|
||||||
copayerIds.push(copayerId);
|
copayerIds.push(result.copayerId);
|
||||||
return cb(err);
|
return cb(err);
|
||||||
});
|
});
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
|
@ -66,7 +66,7 @@ helpers.createAndJoinWallet = function(m, n, cb) {
|
||||||
|
|
||||||
helpers.getAuthServer(copayerIds[0], function(s) {
|
helpers.getAuthServer(copayerIds[0], function(s) {
|
||||||
s.getWallet({}, function(err, w) {
|
s.getWallet({}, function(err, w) {
|
||||||
cb(s, w, _.take(TestData.copayers, w.n), copayerIds);
|
cb(s, w);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -177,68 +177,70 @@ var db, storage;
|
||||||
|
|
||||||
|
|
||||||
describe('Copay server', function() {
|
describe('Copay server', function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
db = levelup(memdown, {
|
db = levelup(memdown, {
|
||||||
valueEncoding: 'json'
|
valueEncoding: 'json'
|
||||||
});
|
|
||||||
storage = new Storage({
|
|
||||||
db: db
|
|
||||||
});
|
|
||||||
CopayServer.initialize({
|
|
||||||
storage: storage
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
storage = new Storage({
|
||||||
|
db: db
|
||||||
|
});
|
||||||
|
CopayServer.initialize({
|
||||||
|
storage: storage
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('#getInstanceWithAuth', function() {
|
describe('#getInstanceWithAuth', function() {
|
||||||
beforeEach(function() {});
|
beforeEach(function() {});
|
||||||
|
|
||||||
it('should get server instance for existing copayer', function(done) {
|
it('should get server instance for existing copayer', function(done) {
|
||||||
helpers.createAndJoinWallet(1, 2, function(s, wallet, copayers, copayerIds) {
|
helpers.createAndJoinWallet(1, 2, function(s, wallet) {
|
||||||
var xpriv = copayers[0].xPrivKey;
|
var xpriv = TestData.copayers[0].xPrivKey;
|
||||||
var priv = Bitcore.HDPrivateKey
|
var priv = Bitcore.HDPrivateKey
|
||||||
.fromString(xpriv)
|
.fromString(xpriv)
|
||||||
.derive('m/1/0')
|
.derive('m/1/0')
|
||||||
.privateKey
|
.privateKey
|
||||||
.toString();
|
.toString();
|
||||||
|
|
||||||
var message = 'hola';
|
var message = 'hola';
|
||||||
var sig = SignUtils.sign(message, priv);
|
var sig = SignUtils.sign(message, priv);
|
||||||
|
|
||||||
CopayServer.getInstanceWithAuth({
|
|
||||||
copayerId: copayerIds[0],
|
|
||||||
message: message,
|
|
||||||
signature: sig,
|
|
||||||
}, function(err, server) {
|
|
||||||
should.not.exist(err);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fail when requesting for non-existent copayer', function(done) {
|
|
||||||
CopayServer.getInstanceWithAuth({
|
CopayServer.getInstanceWithAuth({
|
||||||
copayerId: 'ads',
|
copayerId: wallet.copayers[0].id,
|
||||||
message: 'dummy',
|
message: message,
|
||||||
signature: 'dummy',
|
signature: sig,
|
||||||
}, function(err, server) {
|
}, function(err, server) {
|
||||||
err.should.contain('Copayer not found');
|
should.not.exist(err);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should fail when message signature cannot be verified', function(done) {
|
it('should fail when requesting for non-existent copayer', function(done) {
|
||||||
helpers.createAndJoinWallet(1, 2, function(s, wallet, copayers, copayerIds) {
|
CopayServer.getInstanceWithAuth({
|
||||||
CopayServer.getInstanceWithAuth({
|
copayerId: 'ads',
|
||||||
copayerId: copayerIds[0],
|
message: TestData.message.text,
|
||||||
message: 'dummy',
|
signature: TestData.message.signature,
|
||||||
signature: 'dummy',
|
}, function(err, server) {
|
||||||
}, function(err, server) {
|
err.code.should.equal('NOTAUTHORIZED');
|
||||||
err.should.contain('Invalid signature');
|
err.message.should.contain('Copayer not found');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail when message signature cannot be verified', function(done) {
|
||||||
|
helpers.createAndJoinWallet(1, 2, function(s, wallet) {
|
||||||
|
CopayServer.getInstanceWithAuth({
|
||||||
|
copayerId: wallet.copayers[0].id,
|
||||||
|
message: 'dummy',
|
||||||
|
signature: 'dummy',
|
||||||
|
}, function(err, server) {
|
||||||
|
err.code.should.equal('NOTAUTHORIZED');
|
||||||
|
err.message.should.contain('Invalid signature');
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('#createWallet', function() {
|
describe('#createWallet', function() {
|
||||||
var server;
|
var server;
|
||||||
|
@ -343,8 +345,9 @@ describe('Copay server', function() {
|
||||||
xPubKey: TestData.copayers[0].xPubKey,
|
xPubKey: TestData.copayers[0].xPubKey,
|
||||||
xPubKeySignature: TestData.copayers[0].xPubKeySignature,
|
xPubKeySignature: TestData.copayers[0].xPubKeySignature,
|
||||||
};
|
};
|
||||||
server.joinWallet(copayerOpts, function(err, copayerId) {
|
server.joinWallet(copayerOpts, function(err, result) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
|
var copayerId = result.copayerId;
|
||||||
helpers.getAuthServer(copayerId, function(server) {
|
helpers.getAuthServer(copayerId, function(server) {
|
||||||
server.getWallet({}, function(err, wallet) {
|
server.getWallet({}, function(err, wallet) {
|
||||||
wallet.id.should.equal(walletId);
|
wallet.id.should.equal(walletId);
|
||||||
|
@ -365,8 +368,8 @@ describe('Copay server', function() {
|
||||||
xPubKey: TestData.copayers[0].xPubKey,
|
xPubKey: TestData.copayers[0].xPubKey,
|
||||||
xPubKeySignature: TestData.copayers[0].xPubKeySignature,
|
xPubKeySignature: TestData.copayers[0].xPubKeySignature,
|
||||||
};
|
};
|
||||||
server.joinWallet(copayerOpts, function(err, copayerId) {
|
server.joinWallet(copayerOpts, function(err, result) {
|
||||||
should.not.exist(copayerId);
|
should.not.exist(result);
|
||||||
err.should.exist;
|
err.should.exist;
|
||||||
err.message.should.contain('name');
|
err.message.should.contain('name');
|
||||||
done();
|
done();
|
||||||
|
@ -546,9 +549,9 @@ describe('Copay server', function() {
|
||||||
xPubKey: TestData.copayers[0].xPubKey,
|
xPubKey: TestData.copayers[0].xPubKey,
|
||||||
xPubKeySignature: TestData.copayers[0].xPubKeySignature,
|
xPubKeySignature: TestData.copayers[0].xPubKeySignature,
|
||||||
};
|
};
|
||||||
server.joinWallet(copayerOpts, function(err, copayerId) {
|
server.joinWallet(copayerOpts, function(err, result) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
helpers.getAuthServer(copayerId, function(server) {
|
helpers.getAuthServer(result.copayerId, function(server) {
|
||||||
server.createAddress({}, function(err, address) {
|
server.createAddress({}, function(err, address) {
|
||||||
should.not.exist(address);
|
should.not.exist(address);
|
||||||
err.should.exist;
|
err.should.exist;
|
||||||
|
@ -598,12 +601,11 @@ describe('Copay server', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#createTx', function() {
|
describe('#createTx', function() {
|
||||||
var server, wallet, copayerPriv;
|
var server, wallet;
|
||||||
beforeEach(function(done) {
|
beforeEach(function(done) {
|
||||||
helpers.createAndJoinWallet(2, 3, function(s, w, c) {
|
helpers.createAndJoinWallet(2, 3, function(s, w) {
|
||||||
server = s;
|
server = s;
|
||||||
wallet = w;
|
wallet = w;
|
||||||
copayerPriv = c;
|
|
||||||
server.createAddress({}, function(err, address) {
|
server.createAddress({}, function(err, address) {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -613,7 +615,7 @@ describe('Copay server', function() {
|
||||||
it('should create a tx', function(done) {
|
it('should create a tx', function(done) {
|
||||||
helpers.createUtxos(server, wallet, [100, 200], function(utxos) {
|
helpers.createUtxos(server, wallet, [100, 200], function(utxos) {
|
||||||
helpers.stubBlockExplorer(server, utxos);
|
helpers.stubBlockExplorer(server, utxos);
|
||||||
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 80, 'some message', copayerPriv[0].privKey);
|
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 80, 'some message', TestData.copayers[0].privKey);
|
||||||
server.createTx(txOpts, function(err, tx) {
|
server.createTx(txOpts, function(err, tx) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
tx.should.exist;
|
tx.should.exist;
|
||||||
|
@ -650,10 +652,10 @@ describe('Copay server', function() {
|
||||||
xPubKey: TestData.copayers[0].xPubKey,
|
xPubKey: TestData.copayers[0].xPubKey,
|
||||||
xPubKeySignature: TestData.copayers[0].xPubKeySignature,
|
xPubKeySignature: TestData.copayers[0].xPubKeySignature,
|
||||||
};
|
};
|
||||||
server.joinWallet(copayerOpts, function(err, copayerId) {
|
server.joinWallet(copayerOpts, function(err, result) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
helpers.getAuthServer(copayerId, function(server, wallet) {
|
helpers.getAuthServer(result.copayerId, function(server, wallet) {
|
||||||
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 80, null, copayerPriv[0].privKey);
|
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 80, null, TestData.copayers[0].privKey);
|
||||||
server.createTx(txOpts, function(err, tx) {
|
server.createTx(txOpts, function(err, tx) {
|
||||||
should.not.exist(tx);
|
should.not.exist(tx);
|
||||||
err.should.exist;
|
err.should.exist;
|
||||||
|
@ -668,7 +670,7 @@ describe('Copay server', function() {
|
||||||
it('should fail to create tx for address invalid address', function(done) {
|
it('should fail to create tx for address invalid address', function(done) {
|
||||||
helpers.createUtxos(server, wallet, [100, 200], function(utxos) {
|
helpers.createUtxos(server, wallet, [100, 200], function(utxos) {
|
||||||
helpers.stubBlockExplorer(server, utxos);
|
helpers.stubBlockExplorer(server, utxos);
|
||||||
var txOpts = helpers.createProposalOpts('invalid address', 80, null, copayerPriv[0].privKey);
|
var txOpts = helpers.createProposalOpts('invalid address', 80, null, TestData.copayers[0].privKey);
|
||||||
|
|
||||||
server.createTx(txOpts, function(err, tx) {
|
server.createTx(txOpts, function(err, tx) {
|
||||||
should.not.exist(tx);
|
should.not.exist(tx);
|
||||||
|
@ -683,7 +685,7 @@ describe('Copay server', function() {
|
||||||
it('should fail to create tx for address of different network', function(done) {
|
it('should fail to create tx for address of different network', function(done) {
|
||||||
helpers.createUtxos(server, wallet, [100, 200], function(utxos) {
|
helpers.createUtxos(server, wallet, [100, 200], function(utxos) {
|
||||||
helpers.stubBlockExplorer(server, utxos);
|
helpers.stubBlockExplorer(server, utxos);
|
||||||
var txOpts = helpers.createProposalOpts('myE38JHdxmQcTJGP1ZiX4BiGhDxMJDvLJD', 80, null, copayerPriv[0].privKey);
|
var txOpts = helpers.createProposalOpts('myE38JHdxmQcTJGP1ZiX4BiGhDxMJDvLJD', 80, null, TestData.copayers[0].privKey);
|
||||||
|
|
||||||
server.createTx(txOpts, function(err, tx) {
|
server.createTx(txOpts, function(err, tx) {
|
||||||
should.not.exist(tx);
|
should.not.exist(tx);
|
||||||
|
@ -698,7 +700,7 @@ describe('Copay server', function() {
|
||||||
it('should fail to create tx when insufficient funds', function(done) {
|
it('should fail to create tx when insufficient funds', function(done) {
|
||||||
helpers.createUtxos(server, wallet, [100], function(utxos) {
|
helpers.createUtxos(server, wallet, [100], function(utxos) {
|
||||||
helpers.stubBlockExplorer(server, utxos);
|
helpers.stubBlockExplorer(server, utxos);
|
||||||
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 120, null, copayerPriv[0].privKey);
|
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 120, null, TestData.copayers[0].privKey);
|
||||||
server.createTx(txOpts, function(err, tx) {
|
server.createTx(txOpts, function(err, tx) {
|
||||||
err.code.should.equal('INSUFFICIENTFUNDS');
|
err.code.should.equal('INSUFFICIENTFUNDS');
|
||||||
err.message.should.equal('Insufficient funds');
|
err.message.should.equal('Insufficient funds');
|
||||||
|
@ -723,11 +725,11 @@ describe('Copay server', function() {
|
||||||
it('should create tx when there is a pending tx and enough UTXOs', function(done) {
|
it('should create tx when there is a pending tx and enough UTXOs', function(done) {
|
||||||
helpers.createUtxos(server, wallet, [10.1, 10.2, 10.3], function(utxos) {
|
helpers.createUtxos(server, wallet, [10.1, 10.2, 10.3], function(utxos) {
|
||||||
helpers.stubBlockExplorer(server, utxos);
|
helpers.stubBlockExplorer(server, utxos);
|
||||||
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 12, null, copayerPriv[0].privKey);
|
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 12, null, TestData.copayers[0].privKey);
|
||||||
server.createTx(txOpts, function(err, tx) {
|
server.createTx(txOpts, function(err, tx) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
tx.should.exist;
|
tx.should.exist;
|
||||||
var txOpts2 = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 8, null, copayerPriv[0].privKey);
|
var txOpts2 = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 8, null, TestData.copayers[0].privKey);
|
||||||
server.createTx(txOpts2, function(err, tx) {
|
server.createTx(txOpts2, function(err, tx) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
tx.should.exist;
|
tx.should.exist;
|
||||||
|
@ -749,11 +751,11 @@ describe('Copay server', function() {
|
||||||
it('should fail to create tx when there is a pending tx and not enough UTXOs', function(done) {
|
it('should fail to create tx when there is a pending tx and not enough UTXOs', function(done) {
|
||||||
helpers.createUtxos(server, wallet, [10.1, 10.2, 10.3], function(utxos) {
|
helpers.createUtxos(server, wallet, [10.1, 10.2, 10.3], function(utxos) {
|
||||||
helpers.stubBlockExplorer(server, utxos);
|
helpers.stubBlockExplorer(server, utxos);
|
||||||
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 12, null, copayerPriv[0].privKey);
|
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 12, null, TestData.copayers[0].privKey);
|
||||||
server.createTx(txOpts, function(err, tx) {
|
server.createTx(txOpts, function(err, tx) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
tx.should.exist;
|
tx.should.exist;
|
||||||
var txOpts2 = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 24, null, copayerPriv[0].privKey);
|
var txOpts2 = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 24, null, TestData.copayers[0].privKey);
|
||||||
server.createTx(txOpts2, function(err, tx) {
|
server.createTx(txOpts2, function(err, tx) {
|
||||||
err.code.should.equal('INSUFFICIENTFUNDS');
|
err.code.should.equal('INSUFFICIENTFUNDS');
|
||||||
err.message.should.equal('Insufficient funds');
|
err.message.should.equal('Insufficient funds');
|
||||||
|
@ -783,7 +785,7 @@ describe('Copay server', function() {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
balance.totalAmount.should.equal(helpers.toSatoshi(N * 100));
|
balance.totalAmount.should.equal(helpers.toSatoshi(N * 100));
|
||||||
balance.lockedAmount.should.equal(helpers.toSatoshi(0));
|
balance.lockedAmount.should.equal(helpers.toSatoshi(0));
|
||||||
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 80, null, copayerPriv[0].privKey);
|
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 80, null, TestData.copayers[0].privKey);
|
||||||
async.map(_.range(N), function(i, cb) {
|
async.map(_.range(N), function(i, cb) {
|
||||||
server.createTx(txOpts, function(err, tx) {
|
server.createTx(txOpts, function(err, tx) {
|
||||||
cb(err, tx);
|
cb(err, tx);
|
||||||
|
@ -808,18 +810,16 @@ describe('Copay server', function() {
|
||||||
|
|
||||||
|
|
||||||
describe('#rejectTx', function() {
|
describe('#rejectTx', function() {
|
||||||
var server, wallet, copayerPriv, txid, copayerIds;
|
var server, wallet, txid;
|
||||||
|
|
||||||
beforeEach(function(done) {
|
beforeEach(function(done) {
|
||||||
helpers.createAndJoinWallet(2, 3, function(s, w, c, ids) {
|
helpers.createAndJoinWallet(2, 3, function(s, w) {
|
||||||
server = s;
|
server = s;
|
||||||
wallet = w;
|
wallet = w;
|
||||||
copayerPriv = c;
|
|
||||||
copayerIds = ids;
|
|
||||||
server.createAddress({}, function(err, address) {
|
server.createAddress({}, function(err, address) {
|
||||||
helpers.createUtxos(server, wallet, _.range(1, 9), function(utxos) {
|
helpers.createUtxos(server, wallet, _.range(1, 9), function(utxos) {
|
||||||
helpers.stubBlockExplorer(server, utxos);
|
helpers.stubBlockExplorer(server, utxos);
|
||||||
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 10, null, copayerPriv[0].privKey);
|
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 10, null, TestData.copayers[0].privKey);
|
||||||
server.createTx(txOpts, function(err, tx) {
|
server.createTx(txOpts, function(err, tx) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
tx.should.exist;
|
tx.should.exist;
|
||||||
|
@ -847,8 +847,8 @@ describe('Copay server', function() {
|
||||||
|
|
||||||
var actors = tx.getActors();
|
var actors = tx.getActors();
|
||||||
actors.length.should.equal(1);
|
actors.length.should.equal(1);
|
||||||
actors[0].should.equal(copayerIds[0]);
|
actors[0].should.equal(wallet.copayers[0].id);
|
||||||
tx.getActionBy(copayerIds[0]).type.should.equal('reject');
|
tx.getActionBy(wallet.copayers[0].id).type.should.equal('reject');
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -858,18 +858,16 @@ describe('Copay server', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#signTx', function() {
|
describe('#signTx', function() {
|
||||||
var server, wallet, copayerPriv, txid, copayerIds;
|
var server, wallet, txid;
|
||||||
|
|
||||||
beforeEach(function(done) {
|
beforeEach(function(done) {
|
||||||
helpers.createAndJoinWallet(2, 3, function(s, w, c, ids) {
|
helpers.createAndJoinWallet(2, 3, function(s, w) {
|
||||||
server = s;
|
server = s;
|
||||||
wallet = w;
|
wallet = w;
|
||||||
copayerPriv = c;
|
|
||||||
copayerIds = ids;
|
|
||||||
server.createAddress({}, function(err, address) {
|
server.createAddress({}, function(err, address) {
|
||||||
helpers.createUtxos(server, wallet, _.range(1, 9), function(utxos) {
|
helpers.createUtxos(server, wallet, _.range(1, 9), function(utxos) {
|
||||||
helpers.stubBlockExplorer(server, utxos);
|
helpers.stubBlockExplorer(server, utxos);
|
||||||
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 10, null, copayerPriv[0].privKey);
|
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 10, null, TestData.copayers[0].privKey);
|
||||||
server.createTx(txOpts, function(err, tx) {
|
server.createTx(txOpts, function(err, tx) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
tx.should.exist;
|
tx.should.exist;
|
||||||
|
@ -899,8 +897,8 @@ describe('Copay server', function() {
|
||||||
|
|
||||||
var actors = tx.getActors();
|
var actors = tx.getActors();
|
||||||
actors.length.should.equal(1);
|
actors.length.should.equal(1);
|
||||||
actors[0].should.equal(copayerIds[0]);
|
actors[0].should.equal(wallet.copayers[0].id);
|
||||||
tx.getActionBy(copayerIds[0]).type.should.equal('accept');
|
tx.getActionBy(wallet.copayers[0].id).type.should.equal('accept');
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -1002,12 +1000,11 @@ describe('Copay server', function() {
|
||||||
|
|
||||||
|
|
||||||
describe('#signTx and broadcast', function() {
|
describe('#signTx and broadcast', function() {
|
||||||
var server, wallet, copayerPriv, utxos;
|
var server, wallet, utxos;
|
||||||
beforeEach(function(done) {
|
beforeEach(function(done) {
|
||||||
helpers.createAndJoinWallet(1, 1, function(s, w, c) {
|
helpers.createAndJoinWallet(1, 1, function(s, w) {
|
||||||
server = s;
|
server = s;
|
||||||
wallet = w;
|
wallet = w;
|
||||||
copayerPriv = c;
|
|
||||||
server.createAddress({}, function(err, address) {
|
server.createAddress({}, function(err, address) {
|
||||||
helpers.createUtxos(server, wallet, _.range(1, 9), function(inutxos) {
|
helpers.createUtxos(server, wallet, _.range(1, 9), function(inutxos) {
|
||||||
utxos = inutxos;
|
utxos = inutxos;
|
||||||
|
@ -1019,7 +1016,7 @@ describe('Copay server', function() {
|
||||||
|
|
||||||
it('should sign and broadcast a tx', function(done) {
|
it('should sign and broadcast a tx', function(done) {
|
||||||
helpers.stubBlockExplorer(server, utxos, '1122334455');
|
helpers.stubBlockExplorer(server, utxos, '1122334455');
|
||||||
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 10, null, copayerPriv[0].privKey);
|
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 10, null, TestData.copayers[0].privKey);
|
||||||
server.createTx(txOpts, function(err, txp) {
|
server.createTx(txOpts, function(err, txp) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
txp.should.exist;
|
txp.should.exist;
|
||||||
|
@ -1045,7 +1042,7 @@ describe('Copay server', function() {
|
||||||
|
|
||||||
it('should keep tx as *accepted* if unable to broadcast it', function(done) {
|
it('should keep tx as *accepted* if unable to broadcast it', function(done) {
|
||||||
helpers.stubBlockExplorer(server, utxos);
|
helpers.stubBlockExplorer(server, utxos);
|
||||||
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 10, null, copayerPriv[0].privKey);
|
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 10, null, TestData.copayers[0].privKey);
|
||||||
server.createTx(txOpts, function(err, txp) {
|
server.createTx(txOpts, function(err, txp) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
txp.should.exist;
|
txp.should.exist;
|
||||||
|
@ -1076,12 +1073,11 @@ describe('Copay server', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Tx proposal workflow', function() {
|
describe('Tx proposal workflow', function() {
|
||||||
var server, wallet, copayerPriv, utxos;
|
var server, wallet, utxos;
|
||||||
beforeEach(function(done) {
|
beforeEach(function(done) {
|
||||||
helpers.createAndJoinWallet(2, 3, function(s, w, c) {
|
helpers.createAndJoinWallet(2, 3, function(s, w) {
|
||||||
server = s;
|
server = s;
|
||||||
wallet = w;
|
wallet = w;
|
||||||
copayerPriv = c;
|
|
||||||
server.createAddress({}, function(err, address) {
|
server.createAddress({}, function(err, address) {
|
||||||
helpers.createUtxos(server, wallet, _.range(1, 9), function(inutxos) {
|
helpers.createUtxos(server, wallet, _.range(1, 9), function(inutxos) {
|
||||||
utxos = inutxos;
|
utxos = inutxos;
|
||||||
|
@ -1093,7 +1089,7 @@ describe('Copay server', function() {
|
||||||
|
|
||||||
it('other copayers should see pending proposal created by one copayer', function(done) {
|
it('other copayers should see pending proposal created by one copayer', function(done) {
|
||||||
helpers.stubBlockExplorer(server, utxos);
|
helpers.stubBlockExplorer(server, utxos);
|
||||||
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 10, 'some message', copayerPriv[0].privKey);
|
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 10, 'some message', TestData.copayers[0].privKey);
|
||||||
server.createTx(txOpts, function(err, txp) {
|
server.createTx(txOpts, function(err, txp) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
should.exist.txp;
|
should.exist.txp;
|
||||||
|
@ -1119,21 +1115,20 @@ describe('Copay server', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#getTxs', function() {
|
describe('#getTxs', function() {
|
||||||
var server, wallet, copayerPriv, clock;
|
var server, wallet, clock;
|
||||||
|
|
||||||
beforeEach(function(done) {
|
beforeEach(function(done) {
|
||||||
if (server) return done();
|
if (server) return done();
|
||||||
this.timeout(5000);
|
this.timeout(5000);
|
||||||
console.log('\tCreating TXS...');
|
console.log('\tCreating TXS...');
|
||||||
clock = sinon.useFakeTimers();
|
clock = sinon.useFakeTimers();
|
||||||
helpers.createAndJoinWallet(1, 1, function(s, w, c) {
|
helpers.createAndJoinWallet(1, 1, function(s, w) {
|
||||||
server = s;
|
server = s;
|
||||||
wallet = w;
|
wallet = w;
|
||||||
copayerPriv = c;
|
|
||||||
server.createAddress({}, function(err, address) {
|
server.createAddress({}, function(err, address) {
|
||||||
helpers.createUtxos(server, wallet, _.range(10), function(utxos) {
|
helpers.createUtxos(server, wallet, _.range(10), function(utxos) {
|
||||||
helpers.stubBlockExplorer(server, utxos);
|
helpers.stubBlockExplorer(server, utxos);
|
||||||
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.1, null, copayerPriv[0].privKey);
|
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.1, null, TestData.copayers[0].privKey);
|
||||||
async.eachSeries(_.range(10), function(i, next) {
|
async.eachSeries(_.range(10), function(i, next) {
|
||||||
clock.tick(10000);
|
clock.tick(10000);
|
||||||
server.createTx(txOpts, function(err, tx) {
|
server.createTx(txOpts, function(err, tx) {
|
||||||
|
@ -1211,19 +1206,18 @@ describe('Copay server', function() {
|
||||||
|
|
||||||
|
|
||||||
describe('Notifications', function() {
|
describe('Notifications', function() {
|
||||||
var server, wallet, copayerPriv;
|
var server, wallet;
|
||||||
|
|
||||||
beforeEach(function(done) {
|
beforeEach(function(done) {
|
||||||
if (server) return done();
|
if (server) return done();
|
||||||
console.log('\tCreating TXS...');
|
console.log('\tCreating TXS...');
|
||||||
helpers.createAndJoinWallet(1, 1, function(s, w, c) {
|
helpers.createAndJoinWallet(1, 1, function(s, w) {
|
||||||
server = s;
|
server = s;
|
||||||
wallet = w;
|
wallet = w;
|
||||||
copayerPriv = c;
|
|
||||||
server.createAddress({}, function(err, address) {
|
server.createAddress({}, function(err, address) {
|
||||||
helpers.createUtxos(server, wallet, helpers.toSatoshi(_.range(4)), function(utxos) {
|
helpers.createUtxos(server, wallet, helpers.toSatoshi(_.range(4)), function(utxos) {
|
||||||
helpers.stubBlockExplorer(server, utxos);
|
helpers.stubBlockExplorer(server, utxos);
|
||||||
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.01, null, copayerPriv[0].privKey);
|
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.01, null, TestData.copayers[0].privKey);
|
||||||
async.eachSeries(_.range(3), function(i, next) {
|
async.eachSeries(_.range(3), function(i, next) {
|
||||||
server.createTx(txOpts, function(err, tx) {
|
server.createTx(txOpts, function(err, tx) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
|
@ -1253,8 +1247,8 @@ describe('Copay server', function() {
|
||||||
server.getNotifications({
|
server.getNotifications({
|
||||||
limit: 5,
|
limit: 5,
|
||||||
reverse: true,
|
reverse: true,
|
||||||
maxTs: Date.now()/1000,
|
maxTs: Date.now() / 1000,
|
||||||
minTs: Date.now()/1000-1000,
|
minTs: Date.now() / 1000 - 1000,
|
||||||
}, function(err, notifications) {
|
}, function(err, notifications) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
var types = _.pluck(notifications, 'type');
|
var types = _.pluck(notifications, 'type');
|
||||||
|
@ -1436,16 +1430,15 @@ describe('Copay server', function() {
|
||||||
|
|
||||||
|
|
||||||
describe('#removePendingTx', function() {
|
describe('#removePendingTx', function() {
|
||||||
var server, wallet, copayerPriv, txp;
|
var server, wallet, txp;
|
||||||
beforeEach(function(done) {
|
beforeEach(function(done) {
|
||||||
helpers.createAndJoinWallet(2, 3, function(s, w, c) {
|
helpers.createAndJoinWallet(2, 3, function(s, w) {
|
||||||
server = s;
|
server = s;
|
||||||
wallet = w;
|
wallet = w;
|
||||||
copayerPriv = c;
|
|
||||||
server.createAddress({}, function(err, address) {
|
server.createAddress({}, function(err, address) {
|
||||||
helpers.createUtxos(server, wallet, [100, 200], function(utxos) {
|
helpers.createUtxos(server, wallet, [100, 200], function(utxos) {
|
||||||
helpers.stubBlockExplorer(server, utxos);
|
helpers.stubBlockExplorer(server, utxos);
|
||||||
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 80, 'some message', copayerPriv[0].privKey);
|
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 80, 'some message', TestData.copayers[0].privKey);
|
||||||
server.createTx(txOpts, function(err, tx) {
|
server.createTx(txOpts, function(err, tx) {
|
||||||
server.getPendingTxs({}, function(err, txs) {
|
server.getPendingTxs({}, function(err, txs) {
|
||||||
txp = txs[0];
|
txp = txs[0];
|
||||||
|
|
Loading…
Reference in New Issue