Added wallet regtest.
This commit is contained in:
parent
2140c0ce4d
commit
5dfadf9d2b
@ -397,10 +397,9 @@ WalletService.prototype._loadAllBalances = function(callback) {
|
|||||||
WalletService.prototype._endpointUTXOs = function() {
|
WalletService.prototype._endpointUTXOs = function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
return function(req, res) {
|
return function(req, res) {
|
||||||
req.setTimeout(600000);
|
|
||||||
var walletId = req.params.walletId;
|
var walletId = req.params.walletId;
|
||||||
var queryMempool = req.query.queryMempool !== false;
|
var queryMempool = req.query.queryMempool !== false;
|
||||||
var height = null;
|
var height = self.node.services.db.tip.__height;
|
||||||
var options = {
|
var options = {
|
||||||
queryMempool: queryMempool
|
queryMempool: queryMempool
|
||||||
};
|
};
|
||||||
@ -435,7 +434,11 @@ WalletService.prototype._endpointGetBalance= function() {
|
|||||||
if(err) {
|
if(err) {
|
||||||
return utils.sendError(err, res);
|
return utils.sendError(err, res);
|
||||||
}
|
}
|
||||||
res.status(200).jsonp(result);
|
res.status(200).jsonp({
|
||||||
|
satoshis: result,
|
||||||
|
height: self.node.services.db.tip.__height,
|
||||||
|
hash: self.node.services.db.tip.hash
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -699,13 +702,12 @@ WalletService.prototype._getUtxos = function(walletId, options, callback) {
|
|||||||
stream.on('data', function(data) {
|
stream.on('data', function(data) {
|
||||||
var key = self._encoding.decodeWalletUtxoKey(data.key);
|
var key = self._encoding.decodeWalletUtxoKey(data.key);
|
||||||
var value = self._encoding.decodeWalletUtxoValue(data.value);
|
var value = self._encoding.decodeWalletUtxoValue(data.value);
|
||||||
|
|
||||||
utxos.push({
|
utxos.push({
|
||||||
txid: key.txid,
|
txid: key.txid,
|
||||||
vout: key.outputIndex,
|
vout: key.outputIndex,
|
||||||
height: value.height,
|
height: value.height,
|
||||||
satoshis: value.satoshis,
|
satoshis: value.satoshis,
|
||||||
scriptPubKey: value.script._scriptBuffer
|
scriptPubKey: value.script.toString('hex')
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -727,7 +729,6 @@ WalletService.prototype._getBalance = function(walletId, options, callback) {
|
|||||||
if(err) {
|
if(err) {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(null, self._encoding.decodeWalletBalanceValue(buffer));
|
callback(null, self._encoding.decodeWalletBalanceValue(buffer));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -17,6 +17,7 @@ var fs = require('fs');
|
|||||||
var http = require('http');
|
var http = require('http');
|
||||||
var crypto = require('crypto');
|
var crypto = require('crypto');
|
||||||
|
|
||||||
|
var debug = false;
|
||||||
var bitcoreDataDir = '/tmp/bitcore';
|
var bitcoreDataDir = '/tmp/bitcore';
|
||||||
var bitcoinDataDir = '/tmp/bitcoin';
|
var bitcoinDataDir = '/tmp/bitcoin';
|
||||||
|
|
||||||
@ -93,12 +94,15 @@ var bitcore = {
|
|||||||
var rpc = new BitcoinRPC(rpcConfig);
|
var rpc = new BitcoinRPC(rpcConfig);
|
||||||
var walletPassphrase = 'test';
|
var walletPassphrase = 'test';
|
||||||
|
|
||||||
var numberOfStartingTxs = 50;
|
var numberOfStartingTxs = 49; //this should be an even number of txs
|
||||||
|
var txCount = 0;
|
||||||
|
var blockHeight = 0;
|
||||||
|
|
||||||
var walletPrivKeys = [];
|
var walletPrivKeys = [];
|
||||||
var initialTxs = [];
|
var initialTxs = [];
|
||||||
var fee = 100000;
|
var fee = 100000;
|
||||||
var walletId = crypto.createHash('sha256').update('test').digest('hex');
|
var walletId = crypto.createHash('sha256').update('test').digest('hex');
|
||||||
|
var satoshisReceived = 0;
|
||||||
|
|
||||||
describe('Wallet Operations', function() {
|
describe('Wallet Operations', function() {
|
||||||
|
|
||||||
@ -123,11 +127,7 @@ describe('Wallet Operations', function() {
|
|||||||
|
|
||||||
it('should register wallet', function(done) {
|
it('should register wallet', function(done) {
|
||||||
|
|
||||||
var httpOpts = Object.assign({
|
var httpOpts = getHttpOpts({ path: '/wallet-api/wallets/' + walletId, method: 'POST' });
|
||||||
path: '/wallet-api/wallets/' + walletId,
|
|
||||||
method: 'POST'
|
|
||||||
}, bitcore.httpOpts);
|
|
||||||
|
|
||||||
queryBitcoreNode(httpOpts, function(err, res) {
|
queryBitcoreNode(httpOpts, function(err, res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
@ -143,15 +143,12 @@ describe('Wallet Operations', function() {
|
|||||||
var addresses = JSON.stringify(walletPrivKeys.map(function(privKey) {
|
var addresses = JSON.stringify(walletPrivKeys.map(function(privKey) {
|
||||||
return privKey.toAddress().toString();
|
return privKey.toAddress().toString();
|
||||||
}));
|
}));
|
||||||
var httpOpts = Object.assign({
|
var httpOpts = getHttpOpts({
|
||||||
path: '/wallet-api/wallets/' + walletId + '/addresses',
|
path: '/wallet-api/wallets/' + walletId + '/addresses',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: addresses,
|
body: addresses,
|
||||||
headers: {
|
length: addresses.length
|
||||||
'Content-Type': 'application/json',
|
});
|
||||||
'Content-Length': addresses.length
|
|
||||||
}
|
|
||||||
}, bitcore.httpOpts);
|
|
||||||
async.waterfall([ queryBitcoreNode.bind(this, httpOpts) ], function(err, res) {
|
async.waterfall([ queryBitcoreNode.bind(this, httpOpts) ], function(err, res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
@ -160,10 +157,7 @@ describe('Wallet Operations', function() {
|
|||||||
|
|
||||||
Object.keys(job).should.deep.equal(['jobId']);
|
Object.keys(job).should.deep.equal(['jobId']);
|
||||||
|
|
||||||
var httpOpts = Object.assign({
|
var httpOpts = getHttpOpts({ path: '/wallet-api/jobs/' + job.jobId });
|
||||||
path: '/wallet-api/jobs/' + job.jobId,
|
|
||||||
method: 'GET'
|
|
||||||
}, bitcore.httpOpts);
|
|
||||||
|
|
||||||
async.retry({ times: 10, interval: 1000 }, function(next) {
|
async.retry({ times: 10, interval: 1000 }, function(next) {
|
||||||
queryBitcoreNode(httpOpts, function(err, res) {
|
queryBitcoreNode(httpOpts, function(err, res) {
|
||||||
@ -187,27 +181,89 @@ describe('Wallet Operations', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should get a list of transactions', function(done) {
|
it('should get a list of transactions', function(done) {
|
||||||
var httpOpts = Object.assign({
|
var httpOpts = getHttpOpts({ path: '/wallet-api/wallets/' + walletId + '/transactions' });
|
||||||
path: '/wallet-api/wallets/' + walletId + '/transactions',
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
}
|
|
||||||
}, bitcore.httpOpts);
|
|
||||||
queryBitcoreNode(httpOpts, function(err, res) {
|
queryBitcoreNode(httpOpts, function(err, res) {
|
||||||
if(err) {
|
if(err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
var results = res.split('\n').slice(0, -1);
|
//jsonl is returned, so there will be a newline at the end
|
||||||
results.length.should.equal(numberOfStartingTxs);
|
var results = res.split('\n').filter(function(result) {
|
||||||
|
return result.length > 0;
|
||||||
|
});
|
||||||
var map = initialTxs.map(function(tx) {
|
var map = initialTxs.map(function(tx) {
|
||||||
return tx.serialize();
|
return tx.serialize();
|
||||||
});
|
});
|
||||||
for(var i = 0; i < results.length; i++) {
|
for(var i = 0; i < results.length; i++) {
|
||||||
var result = results[i];
|
var result = results[i];
|
||||||
var tx = new Transaction(JSON.parse(result));
|
var tx = new Transaction(JSON.parse(result));
|
||||||
tx.uncheckedSerialize().should.equal(initialTxs[i].serialize());
|
map.splice(map.indexOf(tx.uncheckedSerialize()), 1);
|
||||||
}
|
}
|
||||||
|
map.length.should.equal(0);
|
||||||
|
results.length.should.equal(numberOfStartingTxs);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get the balance of a wallet', function(done) {
|
||||||
|
var httpOpts = getHttpOpts({ path: '/wallet-api/wallets/' + walletId + '/balance' });
|
||||||
|
queryBitcoreNode(httpOpts, function(err, res) {
|
||||||
|
if(err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
var results = JSON.parse(res);
|
||||||
|
results.satoshis.should.equal(satoshisReceived);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get the set of utxos for the wallet', function(done) {
|
||||||
|
var httpOpts = getHttpOpts({ path: '/wallet-api/wallets/' + walletId + '/utxos' });
|
||||||
|
queryBitcoreNode(httpOpts, function(err, res) {
|
||||||
|
if(err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
var results = JSON.parse(res);
|
||||||
|
// all starting txs were spending to our wallet
|
||||||
|
results.utxos.length.should.equal(numberOfStartingTxs);
|
||||||
|
var map = initialTxs.map(function(tx) {
|
||||||
|
return tx.txid;
|
||||||
|
});
|
||||||
|
var balance = 0;
|
||||||
|
for(var i = 0; i < results.utxos.length; i++) {
|
||||||
|
var result = results.utxos[i];
|
||||||
|
balance += result.satoshis;
|
||||||
|
map.splice(map.indexOf(result.txid), 1);
|
||||||
|
}
|
||||||
|
map.length.should.equal(0);
|
||||||
|
results.height.should.equal(blockHeight);
|
||||||
|
balance.should.equal(satoshisReceived);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get the list of jobs', function(done) {
|
||||||
|
var httpOpts = getHttpOpts({ path: '/wallet-api/jobs' });
|
||||||
|
queryBitcoreNode(httpOpts, function(err, res) {
|
||||||
|
if(err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
var results = JSON.parse(res);
|
||||||
|
results.jobCount.should.equal(1);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should remove all wallets', function(done) {
|
||||||
|
var httpOpts = getHttpOpts({ path: '/wallet-api/wallets', method: 'DELETE' });
|
||||||
|
queryBitcoreNode(httpOpts, function(err, res) {
|
||||||
|
if(err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
//walletTransactionKey = 1, walletUtxoKey = 1, walletUtxoSatoshis = 1 <-- multiples of numberOfStartingTxs
|
||||||
|
//walletAddresses = 1, walletBalance = 1 <-- one record per index
|
||||||
|
var results = JSON.parse(res);
|
||||||
|
results.numberRemoved.should.equal((numberOfStartingTxs * 3) + 2);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -273,7 +329,9 @@ function queryBitcoreNode(httpOpts, next) {
|
|||||||
|
|
||||||
function waitForBitcoreNode(next) {
|
function waitForBitcoreNode(next) {
|
||||||
bitcore.process.stdout.on('data', function(data) {
|
bitcore.process.stdout.on('data', function(data) {
|
||||||
console.log(data.toString());
|
if (debug) {
|
||||||
|
console.log(data.toString());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
bitcore.process.stderr.on('data', function(data) {
|
bitcore.process.stderr.on('data', function(data) {
|
||||||
console.log(data.toString());
|
console.log(data.toString());
|
||||||
@ -284,11 +342,7 @@ function waitForBitcoreNode(next) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var httpOpts = Object.assign({
|
var httpOpts = getHttpOpts({ path: '/wallet-api/issynced', errorFilter: errorFilter });
|
||||||
path: '/wallet-api/issynced',
|
|
||||||
errorFilter: errorFilter,
|
|
||||||
method: 'GET'
|
|
||||||
}, bitcore.httpOpts);
|
|
||||||
|
|
||||||
waitForService(queryBitcoreNode.bind(this, httpOpts), next);
|
waitForService(queryBitcoreNode.bind(this, httpOpts), next);
|
||||||
}
|
}
|
||||||
@ -299,6 +353,7 @@ function waitForBitcoinReady(next) {
|
|||||||
if (err || (res && res.error)) {
|
if (err || (res && res.error)) {
|
||||||
return next('keep trying');
|
return next('keep trying');
|
||||||
}
|
}
|
||||||
|
blockHeight += 150;
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
@ -372,7 +427,7 @@ function getPrivateKeyWithABalance(next) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function generateSpendingTx(privKey, utxo) {
|
function generateSpendingTx(privKey, utxo) {
|
||||||
|
txCount++;
|
||||||
var toPrivKey = new PrivateKey('testnet'); //external addresses
|
var toPrivKey = new PrivateKey('testnet'); //external addresses
|
||||||
var changePrivKey = new PrivateKey('testnet'); //our wallet keys
|
var changePrivKey = new PrivateKey('testnet'); //our wallet keys
|
||||||
var utxoSatoshis = Unit.fromBTC(utxo.amount).satoshis;
|
var utxoSatoshis = Unit.fromBTC(utxo.amount).satoshis;
|
||||||
@ -386,6 +441,7 @@ function generateSpendingTx(privKey, utxo) {
|
|||||||
tx.sign(privKey);
|
tx.sign(privKey);
|
||||||
|
|
||||||
walletPrivKeys.push(changePrivKey);
|
walletPrivKeys.push(changePrivKey);
|
||||||
|
satoshisReceived += Unit.fromBTC(utxo.amount).toSatoshis() - (satsToPrivKey + fee);
|
||||||
return tx;
|
return tx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,7 +462,13 @@ function setupInitialTx(index, next) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setupInitialTxs(next) {
|
function setupInitialTxs(next) {
|
||||||
async.timesSeries(numberOfStartingTxs, setupInitialTx, next);
|
async.timesSeries(numberOfStartingTxs, setupInitialTx, function(err) {
|
||||||
|
if(err) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
blockHeight++;
|
||||||
|
rpc.generate(1, next);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendTx(tx, generateBlocks, next) {
|
function sendTx(tx, generateBlocks, next) {
|
||||||
@ -415,6 +477,7 @@ function sendTx(tx, generateBlocks, next) {
|
|||||||
return next(err);
|
return next(err);
|
||||||
}
|
}
|
||||||
if (generateBlocks) {
|
if (generateBlocks) {
|
||||||
|
blockHeight += generateBlocks;
|
||||||
rpc.generate(generateBlocks, function(err) {
|
rpc.generate(generateBlocks, function(err) {
|
||||||
if(err) {
|
if(err) {
|
||||||
return next(err);
|
return next(err);
|
||||||
@ -426,3 +489,16 @@ function sendTx(tx, generateBlocks, next) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getHttpOpts(opts) {
|
||||||
|
return Object.assign({
|
||||||
|
path: opts.path,
|
||||||
|
method: opts.method || 'GET',
|
||||||
|
body: opts.body,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Content-Length': opts.length || 0
|
||||||
|
},
|
||||||
|
errorFilter: opts.errorFilter
|
||||||
|
}, bitcore.httpOpts);
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user