vucoin
Version:
Node.js module to access ucoin server through its HTTP API
580 lines (508 loc) • 19.9 kB
JavaScript
var fs = require('fs');
var nock = require('nock');
var should = require('should');
var async = require('async');
var _ = require('underscore');
var vucoin = require('./..');
var NO_MSIGNED = false, NO_SIGNATURE_EXTRACT = false;
var node;
nock('http://localhost:8888')
.get('/network/pubkey').reply(200, fs.readFileSync(__dirname + '/data/cat.pub'))
.get('/network/peering').reply(200, "No JSON data")
.get('/network/peering/peers').reply(200, "No JSON data")
.get('/network/peering/peers?leaves=true').reply(200, "No JSON data")
.get('/network/peering/peers?leaf=AAAA').reply(200, "No JSON data")
.post('/network/peering/peers').reply(200, "No JSON data")
.get('/network/peering/peers/upstream').reply(200, "No JSON data")
.get('/network/peering/peers/upstream/GFGEG').reply(200, "No JSON data")
.get('/network/peering/peers/downstream').reply(200, "No JSON data")
.get('/network/peering/peers/downstream/GFGEG').reply(200, "No JSON data")
.post('/network/peering/forward').reply(200, "No JSON data")
.post('/network/peering/status').reply(200, "No JSON data")
.get('/network/wallet').reply(200, "No JSON data")
.get('/network/wallet?leaves=true').reply(200, "No JSON data")
.get('/network/wallet?leaf=AAAA').reply(200, "No JSON data")
.post('/network/wallet').reply(200, "No JSON data")
.get('/network/wallet/ABCDE').reply(200, "No JSON data")
.get('/hdc/amendments/promoted').reply(200, "No JSON data")
.get('/hdc/amendments/promoted/1').reply(200, "No JSON data")
.get('/hdc/amendments/view/1-AM/self').reply(200, "No JSON data")
.get('/hdc/amendments/view/1-AM/signatures').reply(200, "No JSON data")
.get('/hdc/amendments/view/1-AM/signatures?leaves=true').reply(200, "No JSON data")
.get('/hdc/amendments/view/1-AM/signatures?leaf=AAAA').reply(200, "No JSON data")
.get('/hdc/amendments/votes').reply(200, "No JSON data")
.post('/hdc/amendments/votes').reply(200, "No JSON data")
.post('/hdc/transactions/process').reply(200, "No JSON data")
.get('/hdc/transactions/last/10').reply(200, "No JSON data")
.get('/hdc/transactions/sender/DEFG').reply(200, "No JSON data")
.get('/hdc/transactions/sender/DEFG?leaves=true').reply(200, "No JSON data")
.get('/hdc/transactions/sender/DEFG?leaf=AAAA').reply(200, "No JSON data")
.get('/hdc/transactions/sender/DEFG/view/0').reply(200, "No JSON data")
.get('/hdc/transactions/sender/DEFG/last/1').reply(200, "No JSON data")
.get('/hdc/transactions/sender/DEFG/last/1/2').reply(200, "No JSON data")
.get('/hdc/transactions/recipient/DEFG').reply(200, "No JSON data")
.get('/hdc/transactions/recipient/DEFG?leaves=true').reply(200, "No JSON data")
.get('/hdc/transactions/recipient/DEFG?leaf=AAAA').reply(200, "No JSON data")
.get('/hdc/transactions/refering/DEFG/4').reply(200, "No JSON data")
.get('/hdc/coins/list/HIJ').reply(200, "No JSON data")
.get('/hdc/coins/view/HIJ-0-1/owner').reply(200, "No JSON data")
.get('/hdc/coins/view/HIJ-0-1/history').reply(200, "No JSON data")
.get('/registry/parameters').reply(200, "No JSON data")
.get('/registry/community/members').reply(200, "No JSON data")
.get('/registry/community/members?leaves=true').reply(200, "No JSON data")
.get('/registry/community/members?leaf=AAAA').reply(200, "No JSON data")
.post('/registry/community/members').reply(200, "No JSON data")
.get('/registry/community/members/LMN/current').reply(200, "No JSON data")
.get('/registry/community/members/LMN/history').reply(200, "No JSON data")
.get('/registry/community/voters').reply(200, "No JSON data")
.get('/registry/community/voters?leaves=true').reply(200, "No JSON data")
.get('/registry/community/voters?leaf=AAAA').reply(200, "No JSON data")
.post('/registry/community/voters').reply(200, "No JSON data")
.get('/registry/community/voters/LMN/current').reply(200, "No JSON data")
.get('/registry/community/voters/LMN/history').reply(200, "No JSON data")
.get('/registry/amendment').reply(200, "No JSON data")
.get('/registry/amendment/4').reply(200, "No JSON data")
.get('/registry/amendment/4/AnyKey/vote').reply(200, "No JSON data")
;
before(function (done) {
vucoin('localhost', '8888', NO_MSIGNED, NO_SIGNATURE_EXTRACT, function (err, remoteNode) {
node = remoteNode;
done(err);
});
});
describe('/network', function () {
this.timeout(500);
it ('/pubkey should return a string', function (done) {
node.network.pubkey(noErrorResult(function(pubkey) {
pubkey.should.match(/^-----BEGIN PGP/);
}, done));
});
it ('/peering should return a peer', function (done) {
node.network.peering.get(noErrorResult(function(peer) {
isPeer(peer);
}, done));
});
testMerkle('/peering/peers', 'node.network.peering.peers.get', isPeer);
it ('/peering/peers POST should return a peer', function (done) {
node.network.peering.peers.post('blabla-----BEGIN', noErrorResult(function(p) {
isPeer(p);
}, done));
});
it ('/peering/peers/upstream POST should return a stream', function (done) {
node.network.peering.peers.upstream.get(noErrorResult(function(json) {
isStream(json);
}, done));
});
it ('/peering/peers/upstream/GFGEG POST should return a stream', function (done) {
node.network.peering.peers.upstream.of('GFGEG', noErrorResult(function(json) {
isStream(json);
}, done));
});
it ('/peering/peers/downstream POST should return a stream', function (done) {
node.network.peering.peers.downstream.get(noErrorResult(function(json) {
isStream(json);
}, done));
});
it ('/peering/peers/downstream/GFGEG POST should return a stream', function (done) {
node.network.peering.peers.downstream.of('GFGEG', noErrorResult(function(json) {
isStream(json);
}, done));
});
testMerkle('/network/wallet', 'node.network.wallet.get', isWallet);
it ('/network/wallet POST should return a wallet', function (done) {
node.network.wallet.post('blabla-----BEGIN', noErrorResult(function(json) {
isWallet(json);
}, done));
});
it ('/network/wallet/ABCDE should return a wallet', function (done) {
node.network.wallet.of('ABCDE', noErrorResult(function(json) {
isWallet(json);
}, done));
});
it ('/hdc/amendments/promoted should return an amendment', function (done) {
node.hdc.amendments.current(noErrorResult(function(json) {
isAmendment(json);
}, done));
});
it ('/hdc/amendments/promoted/1 should return an amendment', function (done) {
node.hdc.amendments.promoted(1, noErrorResult(function(json) {
isAmendment(json);
}, done));
});
it ('/hdc/amendments/view/1-AM/self should return an amendment', function (done) {
node.hdc.amendments.view.self(1, 'AM', noErrorResult(function(json) {
isAmendment(json);
}, done));
});
testMerkle('/hdc/amendments/view/1-AM/signatures', 'async.apply(node.hdc.amendments.view.signatures, 1, \'AM\')', isSignature);
it ('/hdc/amendments/votes should return an index of votes', function (done) {
node.hdc.amendments.votes.get(noErrorResult(function(json) {
isVoteIndex(json);
}, done));
});
it ('/hdc/amendments/votes POST should return a vote', function (done) {
node.hdc.amendments.votes.post('blabla-----BEGIN', noErrorResult(function(json) {
isVote(json);
}, done));
});
it ('/hdc/transactions/process should return a transaction', function (done) {
node.hdc.transactions.process('blabla-----BEGIN', noErrorResult(function(json) {
isTransaction(json);
}, done));
});
it ('/hdc/transactions/last/10 should return a transaction', function (done) {
node.hdc.transactions.lasts(10, noErrorResult(function(json) {
isTransactionList(json);
}, done));
});
it ('/hdc/transactions/sender/DEFG/view/0 should return a transaction', function (done) {
node.hdc.transactions.view('DEFG', 0, noErrorResult(function(json) {
isTransaction(json);
}, done));
});
it ('/hdc/transactions/sender/DEFG/last/1 should return a transaction', function (done) {
node.hdc.transactions.sender.lasts('DEFG', 1, null, noErrorResult(function(json) {
isTransactionList(json);
}, done));
});
it ('/hdc/transactions/sender/DEFG/last/1/2 should return a transaction', function (done) {
node.hdc.transactions.sender.lasts('DEFG', 1, 2, noErrorResult(function(json) {
isTransactionList(json);
}, done));
});
it ('/hdc/transactions/refering/DEFG/4 should return a transaction', function (done) {
node.hdc.transactions.refering('DEFG', 4, noErrorResult(function(json) {
isTransactionList(json);
}, done));
});
it ('/hdc/coins/list/HIJ should return a coin list', function (done) {
node.hdc.coins.list('HIJ', noErrorResult(function(json) {
isCoinList(json);
}, done));
});
it ('/hdc/coins/view/HIJ-0-1/owner should return a coin owning properties', function (done) {
node.hdc.coins.owner('HIJ', 0, 1, noErrorResult(function(json) {
isCoinOwning(json);
}, done));
});
it ('/hdc/coins/view/HIJ-0-1/history should return an history of property for a coin', function (done) {
node.hdc.coins.history('HIJ', 0, 1, noErrorResult(function(json) {
isCoinOwningHistory(json);
}, done));
});
it ('/registry/parameters should return parameters', function (done) {
node.registry.parameters(noErrorResult(function(json) {
isParameters(json);
}, done));
});
it ('/registry/community/members/LMN/current should return a membership', function (done) {
node.registry.community.members.current('LMN', noErrorResult(function(json) {
isMembership(json);
}, done));
});
it ('/registry/community/members/LMN/history should return an history of memberships', function (done) {
node.registry.community.members.history('LMN', noErrorResult(function(json) {
isMembershipHistory(json);
}, done));
});
it ('/registry/community/voters/LMN/current should return an voting request', function (done) {
node.registry.community.voters.current('LMN', noErrorResult(function(json) {
isVoting(json);
}, done));
});
it ('/registry/community/voters/LMN/history should return an history of voting requests', function (done) {
node.registry.community.voters.history('LMN', noErrorResult(function(json) {
isVotingHistory(json);
}, done));
});
it ('/registry/amendment/4 should return an amendment', function (done) {
node.registry.amendment.proposed(4, noErrorResult(function(json) {
isAmendment(json);
}, done));
});
it ('/registry/amendment/4/AnyKey/vote should return a vote', function (done) {
node.registry.amendment.vote(4, 'AnyKey', noErrorResult(function(json) {
isVote(json);
}, done));
});
it ('/registry/community/members POST should return a membership', function (done) {
node.registry.community.members.post('blabla-----BEGIN', noErrorResult(function(json) {
isMembership(json);
}, done));
});
it ('/registry/community/voters POST should return a voting request', function (done) {
node.registry.community.voters.post('blabla-----BEGIN', noErrorResult(function(json) {
isVoting(json);
}, done));
});
testMerkle('/hdc/transactions/sender/DEFG', 'async.apply(node.hdc.transactions.sender.get, \'DEFG\')', isTransaction);
testMerkle('/hdc/transactions/recipient/DEFG', 'async.apply(node.hdc.transactions.recipient, \'DEFG\')', isTransaction);
testMerkle('/registry/members', 'node.registry.community.members.get', isMembership);
testMerkle('/registry/voters', 'node.registry.community.voters.get', isVoting);
function testMerkle (url, methodName, leafTest) {
it (url + ' should return a simple merkle', function (done) {
var m = eval(methodName);
m({}, noErrorResult(function(merkle) {
isMerkleSimpleResult(merkle);
}, done));
});
it (url + '?leaves=true should return a merkle with leaves', function (done) {
var m = eval(methodName);
m({leaves: true}, noErrorResult(function(merkle) {
isMerkleLeavesResult(merkle);
}, done));
});
it (url + '?leaf=AAAA should return a merkle with leaf', function (done) {
var m = eval(methodName);
m({leaf: 'AAAA'}, noErrorResult(function(merkle) {
isMerkleLeafResult(merkle);
leafTest(merkle.leaf.value);
}, done));
});
}
});
function noErrorResult (f, done) {
return function (err, res) {
should.not.exist(err);
should.exist(res);
f(res);
done();
};
}
function isMerkleSimpleResult (json) {
isMerkleResult(json);
json.should.not.have.property('leaf');
json.should.not.have.property('leaves');
}
function isMerkleLeafResult (json) {
isMerkleResult(json);
json.should.have.property('leaf');
json.leaf.should.have.property('hash');
json.leaf.should.have.property('value');
json.should.not.have.property('leaves');
}
function isMerkleLeavesResult (json) {
isMerkleResult(json);
json.should.have.property('leaves');
json.should.not.have.property('leaf');
_(json.leaves).each(function (leaf) {
leaf.should.be.a.String;
});
}
function isMerkleResult (json) {
json.should.have.property('depth');
json.should.have.property('nodesCount');
json.should.have.property('leavesCount');
json.should.have.property('root');
}
function isPubKey (json) {
json.should.have.property('signature');
json.should.have.property('key');
json.key.should.have.property('email');
json.key.should.have.property('name');
json.key.should.have.property('fingerprint');
json.key.should.have.property('raw');
json.key.should.not.have.property('_id');
json.key.raw.should.not.match(/-----/g);
}
function isPeer (json) {
json.should.have.property('version');
json.should.have.property('currency');
json.should.have.property('fingerprint');
json.should.have.property('endpoints');
json.should.have.property('signature');
json.should.not.have.property('_id');
}
function isStream (json) {
json.should.have.property('peers');
json.peers.should.be.an.Array;
}
function isWallet (json) {
json.should.have.property('signature');
json.should.have.property('entry');
json.entry.should.have.property('version');
json.entry.should.have.property('currency');
json.entry.should.have.property('fingerprint');
json.entry.should.have.property('requiredTrusts');
json.entry.should.have.property('hosters');
json.entry.should.have.property('trusts');
json.entry.hosters.should.be.an.Array;
json.entry.trusts.should.be.an.Array;
}
function isMembership (json) {
json.should.have.property('signature');
json.should.have.property('membership');
json.membership.should.have.property('version');
json.membership.should.have.property('currency');
json.membership.should.have.property('issuer');
json.membership.should.have.property('membership');
json.membership.should.have.property('sigDate');
json.membership.should.have.property('raw');
json.membership.should.not.have.property('_id');
json.membership.raw.should.not.match(/-----/g);
}
function isMembershipHistory (json) {
json.should.have.property('memberships');
json.memberships.should.be.an.Array;
json.memberships.forEach(function(ms){
isMembership(ms);
});
}
function isVoting (json) {
json.should.have.property('signature');
json.should.have.property('voting');
json.voting.should.have.property('version');
json.voting.should.have.property('currency');
json.voting.should.have.property('issuer');
json.voting.should.have.property('sigDate');
json.voting.should.have.property('raw');
json.voting.should.not.have.property('_id');
json.voting.raw.should.not.match(/-----/g);
}
function isVotingHistory (json) {
json.should.have.property('votings');
json.votings.should.be.an.Array;
json.votings.forEach(function(voting){
isVoting(voting);
});
}
function isSignature (json) {
json.should.have.property('signature');
json.should.have.property('issuer');
}
function isVoteIndex (json) {
json.should.have.property('amendments');
}
function isVote (json) {
json.should.have.property('signature');
json.should.have.property('amendment');
isAmendment(json.amendment);
}
function isCoinList (json) {
json.should.have.property('coins');
json.coins.should.be.an.Array;
}
function isCoinOwning (json) {
json.should.have.property('coinid');
json.should.have.property('owner');
json.should.have.property('transaction');
json.transaction.should.be.a.String;
}
function isCoinOwningHistory (json) {
json.should.have.property('history');
json.history.should.be.an.Array;
json.history.forEach(function(coinOwning){
isCoinOwning(coinOwning);
});
}
function isParameters (json) {
json.should.have.property('AMStart');
json.should.have.property('AMFrequency');
json.should.have.property('UDFrequency');
json.should.have.property('UD0');
json.should.have.property('UDPercent');
json.should.have.property('CoinAlgo');
json.should.have.property('Consensus');
json.should.have.property('MSExpires');
json.should.have.property('VTExpires');
}
function isAmendment (json) {
var mandatories = [
"version",
"currency",
"generated",
"number",
"votersRoot",
"votersCount",
"votersChanges",
"membersRoot",
"membersCount",
"membersChanges",
"raw"
];
mandatories.forEach(function(prop){
json.should.have.property(prop);
});
if (json.number > 0) {
json.should.have.property('previousHash');
}
if (json.dividend > 0) {
json.should.have.property('coinBase');
json.should.have.property('coinList');
}
// Numbers
json.version.should.be.a.Number;
json.generated.should.be.a.Number;
json.number.should.be.a.Number;
if (json.dividend) {
should.exist(json.dividend);
should.exist(json.coinBase);
should.exist(json.coinList);
json.dividend.should.be.a.Number;
json.coinBase.should.be.a.Number;
json.coinList.should.be.an.Array;
}
json.membersCount.should.be.a.Number;
json.votersCount.should.be.a.Number;
// Strings
json.currency.should.be.a.String;
if (json.previousHash) {
json.previousHash.should.be.a.String;
}
if (json.membersCount > 0) {
json.membersRoot.should.be.a.String;
} else {
json.membersRoot.should.be.a.String;
}
if (json.votersCount > 0) {
json.votersRoot.should.be.a.String;
} else {
json.votersRoot.should.be.a.String;
}
json.membersChanges.should.be.an.Array;
json.membersChanges.forEach(function(change){
});
json.votersChanges.should.be.an.Array;
json.votersChanges.forEach(function(change){
});
}
function isTransactionList (json) {
json.should.have.property('transactions');
json.transactions.forEach(function(tx){
isTransaction(tx);
});
}
function isTransaction (json) {
json.should.have.property('raw');
json.should.have.property('transaction');
var mandatories = [
"version",
"currency",
"sender",
"number",
"recipient",
"coins",
"comment"
];
mandatories.forEach(function(prop){
json.transaction.should.have.property(prop);
});
if (json.transaction.number > 0) {
json.transaction.should.have.property('previousHash');
}
// Numbers
json.transaction.version.should.be.a.String;
json.transaction.number.should.be.a.Number;
json.transaction.number.should.not.be.below(0);
// Strings
json.transaction.currency.should.be.a.String;
should.not.exist(json.transaction.type);
should.not.exist(json.transaction.amounts);
if (json.transaction.previousHash) {
json.transaction.previousHash.should.be.a.String.and.match(/^[A-Z0-9]{40}$/);
}
json.transaction.coins.should.be.an.Array;
json.transaction.coins.forEach(function(amount){
amount.should.match(/^[A-Z\d]{40}-\d+-\d+(:[A-Z\d]{40}-\d+)?$/);
});
}