mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-12-02 10:05:49 +00:00
http server example
allows to use both positional and named parameters
This commit is contained in:
38
npm-shrinkwrap.json
generated
38
npm-shrinkwrap.json
generated
@@ -91,6 +91,44 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"jayson": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/jayson/-/jayson-1.2.2.tgz",
|
||||
"dependencies": {
|
||||
"JSONStream": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.0.3.tgz",
|
||||
"dependencies": {
|
||||
"jsonparse": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.0.0.tgz"
|
||||
},
|
||||
"through": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-1.3.2.tgz",
|
||||
"dependencies": {
|
||||
"keypress": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"eyes": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz"
|
||||
},
|
||||
"lodash": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.6.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "3.10.1",
|
||||
"from": "lodash@>=3.1.0 <4.0.0",
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"babel-runtime": "^5.5.4",
|
||||
"bignumber.js": "^2.0.3",
|
||||
"https-proxy-agent": "^1.0.0",
|
||||
"jayson": "^1.2.2",
|
||||
"lodash": "^3.1.0",
|
||||
"ripple-address-codec": "^2.0.1",
|
||||
"ripple-binary-codec": "^0.1.0",
|
||||
@@ -65,7 +66,8 @@
|
||||
"test": "istanbul test _mocha",
|
||||
"coveralls": "cat ./coverage/lcov.info | coveralls",
|
||||
"lint": "if ! [ -f eslintrc ]; then curl -o eslintrc 'https://raw.githubusercontent.com/ripple/javascript-style-guide/es6/eslintrc'; echo 'parser: babel-eslint' >> eslintrc; fi; eslint -c eslintrc src/",
|
||||
"perf": "./scripts/perf_test.sh"
|
||||
"perf": "./scripts/perf_test.sh",
|
||||
"start": "babel-node scripts/http.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -34,6 +34,7 @@ unittest() {
|
||||
|
||||
integrationtest() {
|
||||
mocha test/integration/integration-test.js
|
||||
mocha test/integration/http-integration-test.js
|
||||
}
|
||||
|
||||
doctest() {
|
||||
|
||||
16
scripts/http.js
Normal file
16
scripts/http.js
Normal file
@@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
const createHTTPServer = require('../src/index').createHTTPServer;
|
||||
const port = 5990;
|
||||
const serverUrl = 'wss://s1.ripple.com';
|
||||
|
||||
|
||||
function main() {
|
||||
const server = createHTTPServer({server: serverUrl}, port);
|
||||
server.start().then(() => {
|
||||
console.log('Server started on port ' + String(port));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
main();
|
||||
85
src/http.js
Normal file
85
src/http.js
Normal file
@@ -0,0 +1,85 @@
|
||||
/* eslint-disable new-cap */
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert-diff');
|
||||
const _ = require('lodash');
|
||||
const jayson = require('jayson');
|
||||
|
||||
const RippleAPI = require('./api').RippleAPI;
|
||||
|
||||
|
||||
function createHTTPServer(options, httpPort) {
|
||||
const rippleAPI = new RippleAPI(options);
|
||||
|
||||
const methodNames = _.filter(_.keys(RippleAPI.prototype), k => {
|
||||
return typeof RippleAPI.prototype[k] === 'function'
|
||||
&& k !== 'connect'
|
||||
&& k !== 'disconnect'
|
||||
&& k !== 'constructor'
|
||||
&& k !== 'RippleAPI';
|
||||
});
|
||||
|
||||
function applyPromiseWithCallback(fnName, callback, args_) {
|
||||
try {
|
||||
let args = args_;
|
||||
if (!_.isArray(args_)) {
|
||||
const fnParameters = jayson.Utils.getParameterNames(rippleAPI[fnName]);
|
||||
args = fnParameters.map(name => args_[name]);
|
||||
const defaultArgs = _.omit(args_, fnParameters);
|
||||
assert(_.size(defaultArgs) <= 1,
|
||||
'Function must have no more than one default argument');
|
||||
if (_.size(defaultArgs) > 0) {
|
||||
args.push(defaultArgs[_.keys(defaultArgs)[0]]);
|
||||
}
|
||||
}
|
||||
Promise.resolve(rippleAPI[fnName].apply(rippleAPI, args))
|
||||
.then(res => callback(null, res))
|
||||
.catch(err => {
|
||||
callback({code: 99, message: err.message, data: {name: err.name}});
|
||||
});
|
||||
} catch (err) {
|
||||
callback({code: 99, message: err.message, data: {name: err.name}});
|
||||
}
|
||||
}
|
||||
|
||||
const methods = {};
|
||||
_.forEach(methodNames, fn => {
|
||||
methods[fn] = jayson.Method((args, cb) => {
|
||||
applyPromiseWithCallback(fn, cb, args);
|
||||
}, {collect: true});
|
||||
});
|
||||
|
||||
const server = jayson.server(methods);
|
||||
let httpServer = null;
|
||||
|
||||
return {
|
||||
server: server,
|
||||
start: function() {
|
||||
if (httpServer !== null) {
|
||||
return Promise.reject('Already started');
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
rippleAPI.connect().then(() => {
|
||||
httpServer = server.http();
|
||||
httpServer.listen(httpPort, resolve);
|
||||
});
|
||||
});
|
||||
},
|
||||
stop: function() {
|
||||
if (httpServer === null) {
|
||||
return Promise.reject('Not started');
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
rippleAPI.disconnect();
|
||||
httpServer.close(() => {
|
||||
httpServer = null;
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createHTTPServer
|
||||
};
|
||||
@@ -2,5 +2,8 @@
|
||||
|
||||
module.exports = {
|
||||
RippleAPI: require('./api').RippleAPI,
|
||||
RippleAPIBroadcast: require('./broadcast').RippleAPIBroadcast
|
||||
// Broadcast api is experimental
|
||||
RippleAPIBroadcast: require('./broadcast').RippleAPIBroadcast,
|
||||
// HTTP server is experimental
|
||||
createHTTPServer: require('./http').createHTTPServer
|
||||
};
|
||||
|
||||
74
test/integration/fixtures/get-transaction.json
Normal file
74
test/integration/fixtures/get-transaction.json
Normal file
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": "2",
|
||||
"result": {
|
||||
"type": "order",
|
||||
"address": "rK5j9n8baXfL4gzUoZsfxBvvsv97P5swaV",
|
||||
"sequence": 7973823,
|
||||
"id": "4EB6B76237DEEE99F1EA16FAACED2D1E69C5F9CB54F727A4ECA51A08AD3AF466",
|
||||
"specification": {
|
||||
"direction": "buy",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"value": "0.000709756467",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "JPY",
|
||||
"value": "0.086630181788",
|
||||
"counterparty": "r94s8px6kSw1uZ1MV98dhSRTvc6VMPoPcN"
|
||||
}
|
||||
},
|
||||
"outcome": {
|
||||
"result": "tesSUCCESS",
|
||||
"timestamp": "2015-12-03T00:53:21.000Z",
|
||||
"fee": "0.010001",
|
||||
"balanceChanges": {
|
||||
"rK5j9n8baXfL4gzUoZsfxBvvsv97P5swaV": [
|
||||
{
|
||||
"currency": "XRP",
|
||||
"value": "-0.010001"
|
||||
}
|
||||
]
|
||||
},
|
||||
"orderbookChanges": {
|
||||
"rK5j9n8baXfL4gzUoZsfxBvvsv97P5swaV": [
|
||||
{
|
||||
"direction": "buy",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
|
||||
"value": "0.000709260645"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "JPY",
|
||||
"counterparty": "r94s8px6kSw1uZ1MV98dhSRTvc6VMPoPcN",
|
||||
"value": "0.086665436143"
|
||||
},
|
||||
"sequence": 7973725,
|
||||
"status": "cancelled",
|
||||
"makerExchangeRate": "0.008183892870852266"
|
||||
},
|
||||
{
|
||||
"direction": "buy",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
|
||||
"value": "0.000709756467"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "JPY",
|
||||
"counterparty": "r94s8px6kSw1uZ1MV98dhSRTvc6VMPoPcN",
|
||||
"value": "0.086630181788"
|
||||
},
|
||||
"sequence": 7973823,
|
||||
"status": "created",
|
||||
"makerExchangeRate": "0.008192946757712049"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ledgerVersion": 17445469,
|
||||
"indexInLedger": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
72
test/integration/fixtures/get-transactions.json
Normal file
72
test/integration/fixtures/get-transactions.json
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": "3",
|
||||
"result": [
|
||||
{
|
||||
"type": "order",
|
||||
"address": "rpP2JgiMyTF5jR5hLG3xHCPi1knBb1v9cM",
|
||||
"sequence": 3372206,
|
||||
"id": "848397FA686BD4A59F91EC1F4DE717360470EE8BD67CAA01D5FD333EDA8D97B3",
|
||||
"specification": {
|
||||
"direction": "buy",
|
||||
"quantity": {
|
||||
"currency": "JPY",
|
||||
"value": "27865.90216965619",
|
||||
"counterparty": "rJRi8WW24gt9X85PHAxfWNPCizMMhqUQwg"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "XRP",
|
||||
"value": "40000"
|
||||
}
|
||||
},
|
||||
"outcome": {
|
||||
"result": "tesSUCCESS",
|
||||
"fee": "0.011",
|
||||
"balanceChanges": {
|
||||
"rpP2JgiMyTF5jR5hLG3xHCPi1knBb1v9cM": [
|
||||
{
|
||||
"currency": "XRP",
|
||||
"value": "-0.011"
|
||||
}
|
||||
]
|
||||
},
|
||||
"orderbookChanges": {
|
||||
"rpP2JgiMyTF5jR5hLG3xHCPi1knBb1v9cM": [
|
||||
{
|
||||
"direction": "buy",
|
||||
"quantity": {
|
||||
"currency": "JPY",
|
||||
"counterparty": "rJRi8WW24gt9X85PHAxfWNPCizMMhqUQwg",
|
||||
"value": "27880.6855384734"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "XRP",
|
||||
"value": "40000"
|
||||
},
|
||||
"sequence": 3372204,
|
||||
"status": "cancelled",
|
||||
"makerExchangeRate": "0.697017138461835"
|
||||
},
|
||||
{
|
||||
"direction": "buy",
|
||||
"quantity": {
|
||||
"currency": "JPY",
|
||||
"counterparty": "rJRi8WW24gt9X85PHAxfWNPCizMMhqUQwg",
|
||||
"value": "27865.90216965619"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "XRP",
|
||||
"value": "40000"
|
||||
},
|
||||
"sequence": 3372206,
|
||||
"status": "created",
|
||||
"makerExchangeRate": "0.6966475542414048"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ledgerVersion": 17533547,
|
||||
"indexInLedger": 12
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
6
test/integration/fixtures/index.js
Normal file
6
test/integration/fixtures/index.js
Normal file
@@ -0,0 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
getTransaction: require('./get-transaction'),
|
||||
getTransactions: require('./get-transactions')
|
||||
};
|
||||
157
test/integration/http-integration-test.js
Normal file
157
test/integration/http-integration-test.js
Normal file
@@ -0,0 +1,157 @@
|
||||
/* eslint-disable max-nested-callbacks */
|
||||
'use strict';
|
||||
const assert = require('assert-diff');
|
||||
const _ = require('lodash');
|
||||
const jayson = require('jayson');
|
||||
|
||||
const createHTTPServer = require('../../src/index').createHTTPServer;
|
||||
|
||||
const apiFixtures = require('../fixtures');
|
||||
const apiRequests = apiFixtures.requests;
|
||||
const apiResponses = apiFixtures.responses;
|
||||
|
||||
const fixtures = require('./fixtures');
|
||||
|
||||
const TIMEOUT = 20000; // how long before each test case times out
|
||||
|
||||
const apiOptions = {
|
||||
server: 'wss://s1.ripple.com'
|
||||
};
|
||||
|
||||
const httpPort = 3000;
|
||||
|
||||
function createClient() {
|
||||
return jayson.client.http({port: httpPort, hostname: 'localhost'});
|
||||
}
|
||||
|
||||
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
|
||||
|
||||
function makePositionalParams(params) {
|
||||
return params.map(value => value[_.keys(value)[0]]);
|
||||
}
|
||||
|
||||
function makeNamedParams(params) {
|
||||
return _.reduce(params, _.assign, {});
|
||||
}
|
||||
|
||||
function random() {
|
||||
return _.fill(Array(16), 0);
|
||||
}
|
||||
|
||||
describe('http server integration tests', function() {
|
||||
this.timeout(TIMEOUT);
|
||||
|
||||
let server = null;
|
||||
let client = null;
|
||||
|
||||
function createTestInternal(testName, methodName, params, testFunc, id) {
|
||||
it(testName, function() {
|
||||
return new Promise((resolve, reject) => {
|
||||
client.request(methodName, params, id,
|
||||
(err, result) => err ? reject(err) : resolve(testFunc(result)));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function createTest(name, params, testFunc, id) {
|
||||
createTestInternal(name + ' - positional params', name,
|
||||
makePositionalParams(params), testFunc, id);
|
||||
createTestInternal(name + ' - named params', name,
|
||||
makeNamedParams(params), testFunc, id);
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
server = createHTTPServer(apiOptions, httpPort);
|
||||
return server.start().then(() => {
|
||||
this.client = createClient();
|
||||
client = this.client;
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
return server.stop();
|
||||
});
|
||||
|
||||
|
||||
createTest(
|
||||
'getLedgerVersion',
|
||||
[],
|
||||
result => assert(_.isNumber(result.result))
|
||||
);
|
||||
|
||||
createTest(
|
||||
'getServerInfo',
|
||||
[],
|
||||
result => assert(_.isNumber(result.result.validatedLedger.ledgerVersion))
|
||||
);
|
||||
|
||||
createTest(
|
||||
'getTransaction',
|
||||
[{id: '4EB6B76237DEEE99F1EA16FAACED2D1E69C5F9CB54F727A4ECA51A08AD3AF466'}],
|
||||
result => assert.deepEqual(result, fixtures.getTransaction),
|
||||
'2'
|
||||
);
|
||||
|
||||
createTest(
|
||||
'getTransactions',
|
||||
[{address: 'rpP2JgiMyTF5jR5hLG3xHCPi1knBb1v9cM'}, {
|
||||
options: {
|
||||
binary: true,
|
||||
limit: 1,
|
||||
start:
|
||||
'FBAAC31D6BAEEFA9E501266FD62DA7A7982662BC19BC42F49BB41405C2F820DB'
|
||||
}
|
||||
}],
|
||||
result => assert.deepEqual(result, fixtures.getTransactions),
|
||||
'3'
|
||||
);
|
||||
|
||||
createTest(
|
||||
'prepareSettings',
|
||||
[
|
||||
{address},
|
||||
{settings: apiRequests.prepareSettings},
|
||||
{instructions: {
|
||||
maxFee: '0.000012',
|
||||
sequence: 23,
|
||||
maxLedgerVersion: 8820051
|
||||
}}
|
||||
],
|
||||
result => {
|
||||
const got = JSON.parse(result.result.txJSON);
|
||||
const expected = JSON.parse(apiResponses.prepareSettings.flags.txJSON);
|
||||
assert.deepEqual(got, expected);
|
||||
}
|
||||
);
|
||||
|
||||
createTest(
|
||||
'sign',
|
||||
[{txJSON: apiRequests.sign.normal.txJSON},
|
||||
{secret: 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'}],
|
||||
result => assert.deepEqual(result.result, apiResponses.sign.normal)
|
||||
);
|
||||
|
||||
createTest(
|
||||
'generateAddress',
|
||||
[{options: {entropy: random()}}],
|
||||
result => assert.deepEqual(result.result, apiResponses.generateAddress)
|
||||
);
|
||||
|
||||
createTest(
|
||||
'computeLedgerHash',
|
||||
[{ledger: _.assign({}, apiResponses.getLedger.full,
|
||||
{parentCloseTime: apiResponses.getLedger.full.closeTime})
|
||||
}],
|
||||
result => {
|
||||
assert.strictEqual(result.result,
|
||||
'E6DB7365949BF9814D76BCC730B01818EB9136A89DB224F3F9F5AAE4569D758E');
|
||||
}
|
||||
);
|
||||
|
||||
createTest(
|
||||
'isConnected',
|
||||
[],
|
||||
result => assert(result.result)
|
||||
);
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user