mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-20 12:15:51 +00:00
Convert getOrderBook and add unit test
This commit is contained in:
@@ -11,7 +11,7 @@ const getTrustlines = require('./ledger/trustlines');
|
||||
const getBalances = require('./ledger/balances');
|
||||
// const getPathFind = require('./ledger/pathfind');
|
||||
const getOrders = require('./ledger/orders');
|
||||
// const getOrderBook = require('./ledger/orderbook');
|
||||
const getOrderBook = require('./ledger/orderbook');
|
||||
const getSettings = require('./ledger/settings');
|
||||
const preparePayment = require('./transaction/payment');
|
||||
const prepareTrustline = require('./transaction/trustline');
|
||||
@@ -39,7 +39,7 @@ RippleAPI.prototype = {
|
||||
getBalances,
|
||||
// getPathFind,
|
||||
getOrders,
|
||||
// getOrderBook,
|
||||
getOrderBook,
|
||||
getSettings,
|
||||
|
||||
preparePayment,
|
||||
|
||||
@@ -40,4 +40,4 @@ function getBalances(account, options, callback) {
|
||||
], composeAsync(formatBalances, callback));
|
||||
}
|
||||
|
||||
module.exports = getBalances;
|
||||
module.exports = utils.wrapCatch(getBalances);
|
||||
|
||||
@@ -1,171 +1,54 @@
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const async = require('async');
|
||||
const utils = require('./utils');
|
||||
const ripple = utils.common.core;
|
||||
const parseOrderbookOrder = require('./parse/orderbook-order');
|
||||
const validate = utils.common.validate;
|
||||
const bignum = require('bignumber.js');
|
||||
const composeAsync = utils.common.composeAsync;
|
||||
|
||||
// account is to specify a "perspective", which affects which unfunded offers
|
||||
// are returned
|
||||
function getBookOffers(remote, account, ledgerVersion, limit,
|
||||
takerGets, takerPays, callback) {
|
||||
remote.requestBookOffers({
|
||||
taker_gets: takerGets,
|
||||
taker_pays: takerPays,
|
||||
ledger: ledgerVersion || 'validated',
|
||||
limit: limit,
|
||||
taker: account
|
||||
}, composeAsync((data) => data.offers.map(parseOrderbookOrder), callback));
|
||||
}
|
||||
|
||||
function isSameIssue(a, b) {
|
||||
return a.currency === b.currency && a.counterparty === b.counterparty;
|
||||
}
|
||||
|
||||
function orderFilter(issue, direction, order) {
|
||||
return isSameIssue(issue, order.specification.quantity)
|
||||
&& order.specification.direction === direction;
|
||||
}
|
||||
|
||||
function formatBidsAndAsks(orderbook, orders) {
|
||||
// the "base" currency is the currency that you are buying or selling
|
||||
// the "counter" is the currency that the "base" is priced in
|
||||
// a "bid"/"ask" is an order to buy/sell the base, respectively
|
||||
const bids = orders.filter(_.partial(orderFilter, orderbook.base, 'buy'));
|
||||
const asks = orders.filter(_.partial(orderFilter, orderbook.base, 'sell'));
|
||||
return {bids, asks};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the most recent spapshot of the order book for a currency pair
|
||||
*
|
||||
* @url
|
||||
* @param {RippleAddress} request.params.account
|
||||
* - The ripple address to use as point-of-view
|
||||
* (returns unfunded orders for this account)
|
||||
* @param {String ISO 4217 Currency Code + RippleAddress} request.params.base
|
||||
* - Base currency as currency+issuer
|
||||
* @param {String ISO 4217 Currency Code + RippleAddress}
|
||||
* request.params.counter - Counter currency as currency+issuer
|
||||
*
|
||||
* @query
|
||||
* @param {String} [request.query.limit]
|
||||
* - Set a limit to the number of results returned
|
||||
*
|
||||
* @param {Express.js Request} request
|
||||
*/
|
||||
function getOrderBook(account, orderbook, options, callback) {
|
||||
const self = this;
|
||||
validate.address(account);
|
||||
validate.orderbook(orderbook);
|
||||
validate.options(options);
|
||||
|
||||
const params = _.assign({}, orderbook, options, {
|
||||
validated: true,
|
||||
order_book: orderbook.base + '/' + orderbook.counter
|
||||
});
|
||||
|
||||
function getLastValidatedLedger(parameters) {
|
||||
const promise = new Promise(function(resolve, reject) {
|
||||
const ledgerRequest = self.remote.requestLedger('validated');
|
||||
|
||||
ledgerRequest.once('success', function(res) {
|
||||
parameters.ledger = res.ledger.ledger_index;
|
||||
resolve(parameters);
|
||||
});
|
||||
|
||||
ledgerRequest.once('error', reject);
|
||||
ledgerRequest.request();
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
function getBookOffers(taker_gets, taker_pays, parameters) {
|
||||
const promise = new Promise(function(resolve, reject) {
|
||||
const bookOffersRequest = self.remote.requestBookOffers({
|
||||
taker_gets: {currency: taker_gets.currency,
|
||||
issuer: taker_gets.counterparty},
|
||||
taker_pays: {currency: taker_pays.currency,
|
||||
issuer: taker_pays.counterparty},
|
||||
ledger: parameters.ledger,
|
||||
limit: parameters.limit,
|
||||
taker: account
|
||||
});
|
||||
|
||||
bookOffersRequest.once('success', resolve);
|
||||
bookOffersRequest.once('error', reject);
|
||||
bookOffersRequest.request();
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
function getBids(parameters) {
|
||||
const taker_gets = parameters.counter;
|
||||
const taker_pays = parameters.base;
|
||||
|
||||
return getBookOffers(taker_gets, taker_pays, parameters);
|
||||
}
|
||||
|
||||
function getAsks(parameters) {
|
||||
const taker_gets = parameters.base;
|
||||
const taker_pays = parameters.counter;
|
||||
|
||||
return getBookOffers(taker_gets, taker_pays, parameters);
|
||||
}
|
||||
|
||||
function getBidsAndAsks(parameters) {
|
||||
return Promise.join(
|
||||
getBids(parameters),
|
||||
getAsks(parameters),
|
||||
function(bids, asks) {
|
||||
return [bids, asks, parameters];
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function getParsedBookOffers(offers, isAsk) {
|
||||
return offers.reduce(function(orderBook, off) {
|
||||
let price;
|
||||
const order_maker = off.Account;
|
||||
const sequence = off.Sequence;
|
||||
|
||||
// Transaction Flags
|
||||
const passive = (off.Flags & ripple.Remote.flags.offer.Passive) !== 0;
|
||||
const sell = (off.Flags & ripple.Remote.flags.offer.Sell) !== 0;
|
||||
|
||||
const taker_gets_total = utils.parseCurrencyAmount(off.TakerGets);
|
||||
const taker_gets_funded = off.taker_gets_funded ?
|
||||
utils.parseCurrencyAmount(off.taker_gets_funded) : taker_gets_total;
|
||||
|
||||
const taker_pays_total = utils.parseCurrencyAmount(off.TakerPays);
|
||||
const taker_pays_funded = off.taker_pays_funded ?
|
||||
utils.parseCurrencyAmount(off.taker_pays_funded) : taker_pays_total;
|
||||
|
||||
if (isAsk) {
|
||||
price = {
|
||||
currency: taker_pays_total.currency,
|
||||
counterparty: taker_pays_total.counterparty,
|
||||
value: bignum(taker_pays_total.value).div(
|
||||
bignum(taker_gets_total.value))
|
||||
};
|
||||
} else {
|
||||
price = {
|
||||
currency: taker_gets_total.currency,
|
||||
counterparty: taker_gets_total.counterparty,
|
||||
value: bignum(taker_gets_total.value).div(
|
||||
bignum(taker_pays_total.value))
|
||||
};
|
||||
}
|
||||
|
||||
price.value = price.value.toString();
|
||||
|
||||
orderBook.push({
|
||||
price: price,
|
||||
taker_gets_funded: taker_gets_funded,
|
||||
taker_gets_total: taker_gets_total,
|
||||
taker_pays_funded: taker_pays_funded,
|
||||
taker_pays_total: taker_pays_total,
|
||||
order_maker: order_maker,
|
||||
sequence: sequence,
|
||||
passive: passive,
|
||||
sell: sell
|
||||
});
|
||||
|
||||
return orderBook;
|
||||
}, []);
|
||||
}
|
||||
|
||||
function respondWithOrderBook(bids, asks, parameters) {
|
||||
const promise = new Promise(function(resolve) {
|
||||
const orderBook = {
|
||||
order_book: parameters.order_book,
|
||||
ledger: parameters.ledger,
|
||||
validated: parameters.validated,
|
||||
bids: getParsedBookOffers(bids.offers),
|
||||
asks: getParsedBookOffers(asks.offers, true)
|
||||
};
|
||||
|
||||
resolve(callback(null, orderBook));
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
getLastValidatedLedger(params)
|
||||
.then(getBidsAndAsks)
|
||||
.spread(respondWithOrderBook)
|
||||
.catch(callback);
|
||||
const getter = _.partial(getBookOffers, this.remote, account,
|
||||
options.ledgerVersion, options.limit);
|
||||
const getOrders = _.partial(getter, orderbook.base, orderbook.counter);
|
||||
const getReverseOrders = _.partial(getter, orderbook.counter, orderbook.base);
|
||||
async.parallel([getOrders, getReverseOrders],
|
||||
composeAsync((data) => formatBidsAndAsks(orderbook, _.flatten(data)),
|
||||
callback));
|
||||
}
|
||||
|
||||
module.exports = getOrderBook;
|
||||
module.exports = utils.wrapCatch(getOrderBook);
|
||||
|
||||
@@ -30,8 +30,8 @@ function getAccountOrders(account, options, callback) {
|
||||
const getter = _.partial(requestAccountOffers, this.remote, account,
|
||||
ledgerVersion, options);
|
||||
utils.getRecursive(getter, limit,
|
||||
composeAsync((orders) => _.sortBy(orders, (order) => order.state.sequence),
|
||||
callback));
|
||||
composeAsync((orders) => _.sortBy(orders,
|
||||
(order) => order.properties.sequence), callback));
|
||||
}
|
||||
|
||||
module.exports = getAccountOrders;
|
||||
module.exports = utils.wrapCatch(getAccountOrders);
|
||||
|
||||
@@ -1,14 +1,27 @@
|
||||
'use strict';
|
||||
const parseOrderBase = require('./order-base');
|
||||
const utils = require('./utils');
|
||||
const flags = utils.core.Remote.flags.offer;
|
||||
const parseAmount = require('./amount');
|
||||
|
||||
// rippled 'account_offers' returns a different format for orders than 'tx'
|
||||
function parseAccountOrder(order) {
|
||||
const specification = parseOrderBase(
|
||||
order.taker_gets, order.taker_pays, order.flags);
|
||||
const state = {
|
||||
// the flags are also different
|
||||
function parseAccountOrder(order: Object): Object {
|
||||
const direction = (order.flags & flags.Sell) === 0 ? 'buy' : 'sell';
|
||||
const takerGetsAmount = parseAmount(order.taker_gets);
|
||||
const takerPaysAmount = parseAmount(order.taker_pays);
|
||||
const quantity = (direction === 'buy') ? takerPaysAmount : takerGetsAmount;
|
||||
const totalPrice = (direction === 'buy') ? takerGetsAmount : takerPaysAmount;
|
||||
|
||||
const specification = utils.removeUndefined({
|
||||
direction: direction,
|
||||
quantity: quantity,
|
||||
totalPrice: totalPrice,
|
||||
passive: ((order.flags & flags.Passive) !== 0) || undefined
|
||||
});
|
||||
const properties = {
|
||||
sequence: order.seq
|
||||
};
|
||||
return {specification, state};
|
||||
return {specification, properties};
|
||||
}
|
||||
|
||||
module.exports = parseAccountOrder;
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const utils = require('./utils');
|
||||
const parseAmount = require('./amount');
|
||||
const orderFlags = utils.core.Transaction.flags.OfferCreate;
|
||||
|
||||
/*:: type Amount = string | {currency: string, issuer: string, value: string} */
|
||||
function parseOrder(takerGets: Amount, takerPays: Amount, flags: number):
|
||||
Object {
|
||||
const direction = (flags & orderFlags.Sell) === 0 ? 'buy' : 'sell';
|
||||
const takerGetsAmount = parseAmount(takerGets);
|
||||
const takerPaysAmount = parseAmount(takerPays);
|
||||
const quantity = (direction === 'buy') ? takerPaysAmount : takerGetsAmount;
|
||||
const totalPrice = (direction === 'buy') ? takerGetsAmount : takerPaysAmount;
|
||||
|
||||
return utils.removeUndefined({
|
||||
direction: direction,
|
||||
quantity: quantity,
|
||||
totalPrice: totalPrice,
|
||||
passive: ((flags & orderFlags.Passive) !== 0) || undefined,
|
||||
immediateOrCancel: ((flags & orderFlags.ImmediateOrCancel) !== 0)
|
||||
|| undefined,
|
||||
fillOrKill: ((flags & orderFlags.FillOrKill) !== 0) || undefined
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = parseOrder;
|
||||
@@ -1,11 +1,28 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
const assert = require('assert');
|
||||
const parseOrderBase = require('./order-base');
|
||||
const utils = require('./utils');
|
||||
const parseAmount = require('./amount');
|
||||
const flags = utils.core.Transaction.flags.OfferCreate;
|
||||
|
||||
function parseOrder(tx: Object): Object {
|
||||
assert(tx.TransactionType === 'OfferCreate');
|
||||
return parseOrderBase(tx.TakerGets, tx.TakerPays, tx.Flags);
|
||||
|
||||
const direction = (tx.Flags & flags.Sell) === 0 ? 'buy' : 'sell';
|
||||
const takerGetsAmount = parseAmount(tx.TakerGets);
|
||||
const takerPaysAmount = parseAmount(tx.TakerPays);
|
||||
const quantity = (direction === 'buy') ? takerPaysAmount : takerGetsAmount;
|
||||
const totalPrice = (direction === 'buy') ? takerGetsAmount : takerPaysAmount;
|
||||
|
||||
return utils.removeUndefined({
|
||||
direction: direction,
|
||||
quantity: quantity,
|
||||
totalPrice: totalPrice,
|
||||
passive: ((tx.Flags & flags.Passive) !== 0) || undefined,
|
||||
immediateOrCancel: ((tx.Flags & flags.ImmediateOrCancel) !== 0)
|
||||
|| undefined,
|
||||
fillOrKill: ((tx.Flags & flags.FillOrKill) !== 0) || undefined
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = parseOrder;
|
||||
|
||||
40
src/api/ledger/parse/orderbook-order.js
Normal file
40
src/api/ledger/parse/orderbook-order.js
Normal file
@@ -0,0 +1,40 @@
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const utils = require('./utils');
|
||||
const flags = utils.core.Remote.flags.offer;
|
||||
const parseAmount = require('./amount');
|
||||
|
||||
function parseOrderbookOrder(order: Object): Object {
|
||||
const direction = (order.Flags & flags.Sell) === 0 ? 'buy' : 'sell';
|
||||
const takerGetsAmount = parseAmount(order.TakerGets);
|
||||
const takerPaysAmount = parseAmount(order.TakerPays);
|
||||
const quantity = (direction === 'buy') ? takerPaysAmount : takerGetsAmount;
|
||||
const totalPrice = (direction === 'buy') ? takerGetsAmount : takerPaysAmount;
|
||||
|
||||
const specification = utils.removeUndefined({
|
||||
direction: direction,
|
||||
quantity: quantity,
|
||||
totalPrice: totalPrice,
|
||||
passive: ((order.Flags & flags.Passive) !== 0) || undefined
|
||||
});
|
||||
// "quality" is omitted intentionally as it corresponds to
|
||||
// either price or inverse price, and it is better to avoid
|
||||
// inverting floats where precision issues can arise
|
||||
const properties = {
|
||||
maker: order.Account,
|
||||
sequence: order.Sequence
|
||||
};
|
||||
const takerGetsFunded = order.taker_gets_funded ?
|
||||
parseAmount(order.taker_gets_funded) : undefined;
|
||||
const takerPaysFunded = order.taker_pays_funded ?
|
||||
parseAmount(order.taker_pays_funded) : undefined;
|
||||
const available = utils.removeUndefined({
|
||||
availableQuantity: direction === 'buy' ? takerPaysFunded : takerGetsFunded,
|
||||
priceOfAvailableQuantity: direction === 'buy' ?
|
||||
takerGetsFunded : takerPaysFunded
|
||||
});
|
||||
const state = _.isEmpty(available) ? undefined : available;
|
||||
return utils.removeUndefined({specification, properties, state});
|
||||
}
|
||||
|
||||
module.exports = parseOrderbookOrder;
|
||||
@@ -144,4 +144,4 @@ function getPathFind(pathfind, callback) {
|
||||
async.waterfall(steps, callback);
|
||||
}
|
||||
|
||||
module.exports = getPathFind;
|
||||
module.exports = utils.wrapCatch(getPathFind);
|
||||
|
||||
@@ -41,4 +41,4 @@ function getSettings(account, callback) {
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = getSettings;
|
||||
module.exports = utils.wrapCatch(getSettings);
|
||||
|
||||
@@ -45,4 +45,4 @@ function getTrustlines(account: string, options: Options,
|
||||
utils.getRecursive(getter, limit, callback);
|
||||
}
|
||||
|
||||
module.exports = getTrustlines;
|
||||
module.exports = utils.wrapCatch(getTrustlines);
|
||||
|
||||
@@ -1610,7 +1610,7 @@ Remote.prototype.requestBookOffers = function(options_, callback_) {
|
||||
const request = new Request(this, 'book_offers');
|
||||
|
||||
request.message.taker_gets = {
|
||||
currency: Currency.json_rewrite(gets.currency, {force_hex: true})
|
||||
currency: Currency.json_rewrite(gets.currency)
|
||||
};
|
||||
|
||||
if (!Currency.from_json(request.message.taker_gets.currency).is_native()) {
|
||||
@@ -1618,7 +1618,7 @@ Remote.prototype.requestBookOffers = function(options_, callback_) {
|
||||
}
|
||||
|
||||
request.message.taker_pays = {
|
||||
currency: Currency.json_rewrite(pays.currency, {force_hex: true})
|
||||
currency: Currency.json_rewrite(pays.currency)
|
||||
};
|
||||
|
||||
if (!Currency.from_json(request.message.taker_pays.currency).is_native()) {
|
||||
|
||||
@@ -28,12 +28,14 @@ const trustlinesResponse = require('./fixtures/trustlines-response');
|
||||
const walletResponse = require('./fixtures/wallet.json');
|
||||
const getSettingsResponse = require('./fixtures/get-settings-response');
|
||||
const getOrdersResponse = require('./fixtures/get-orders-response');
|
||||
const getOrderBookResponse = require('./fixtures/get-orderbook-response');
|
||||
|
||||
function checkResult(expected, done, error, response) {
|
||||
if (error) {
|
||||
done(error);
|
||||
return;
|
||||
}
|
||||
// console.log(JSON.stringify(response, null, 2));
|
||||
assert.deepEqual(response, expected);
|
||||
done();
|
||||
}
|
||||
@@ -137,4 +139,18 @@ describe('RippleAPI', function() {
|
||||
_.partial(checkResult, getOrdersResponse, done));
|
||||
});
|
||||
|
||||
it('getOrderBook', function(done) {
|
||||
const orderbook = {
|
||||
base: {
|
||||
currency: 'USD',
|
||||
counterparty: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
|
||||
},
|
||||
counter: {
|
||||
currency: 'BTC',
|
||||
counterparty: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
|
||||
}
|
||||
};
|
||||
this.api.getOrderBook(address, orderbook, {},
|
||||
_.partial(checkResult, getOrderBookResponse, done));
|
||||
});
|
||||
});
|
||||
|
||||
1183
test/fixtures/book-offers-response.js
vendored
Normal file
1183
test/fixtures/book-offers-response.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
370
test/fixtures/get-orderbook-response.json
vendored
Normal file
370
test/fixtures/get-orderbook-response.json
vendored
Normal file
@@ -0,0 +1,370 @@
|
||||
{
|
||||
"bids": [
|
||||
{
|
||||
"specification": {
|
||||
"direction": "buy",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"value": "10",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "BTC",
|
||||
"value": "3205.1",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"maker": "r49y2xKuKVG2dPkNHgWQAV61cjxk8gryjQ",
|
||||
"sequence": 434
|
||||
}
|
||||
},
|
||||
{
|
||||
"specification": {
|
||||
"direction": "buy",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"value": "4.99707396683212",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "BTC",
|
||||
"value": "1599.063669386278",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"maker": "rDYCRhpahKEhCFV25xScg67Bwf4W9sTYAm",
|
||||
"sequence": 233
|
||||
}
|
||||
},
|
||||
{
|
||||
"specification": {
|
||||
"direction": "buy",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"value": "0.4499999999999999",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "BTC",
|
||||
"value": "143.1050962074379",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"maker": "raudnGKfTK23YKfnS7ixejHrqGERTYNFXk",
|
||||
"sequence": 110104
|
||||
},
|
||||
"state": {
|
||||
"availableQuantity": {
|
||||
"currency": "USD",
|
||||
"value": "0",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"priceOfAvailableQuantity": {
|
||||
"currency": "BTC",
|
||||
"value": "0",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"specification": {
|
||||
"direction": "buy",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"value": "0.8",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "BTC",
|
||||
"value": "254.329207354604",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"maker": "rDVBvAQScXrGRGnzrxRrcJPeNLeLeUTAqE",
|
||||
"sequence": 35625
|
||||
},
|
||||
"state": {
|
||||
"availableQuantity": {
|
||||
"currency": "USD",
|
||||
"value": "0",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"priceOfAvailableQuantity": {
|
||||
"currency": "BTC",
|
||||
"value": "0",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"specification": {
|
||||
"direction": "buy",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"value": "1.23231134568807",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "BTC",
|
||||
"value": "390.4979",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"maker": "rwBYyfufTzk77zUSKEu4MvixfarC35av1J",
|
||||
"sequence": 387756
|
||||
}
|
||||
},
|
||||
{
|
||||
"specification": {
|
||||
"direction": "buy",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"value": "0.003160328237957649",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "BTC",
|
||||
"value": "1",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"maker": "rwjsRktX1eguUr1pHTffyHnC4uyrvX58V1",
|
||||
"sequence": 208927
|
||||
}
|
||||
},
|
||||
{
|
||||
"specification": {
|
||||
"direction": "buy",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"value": "15",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "BTC",
|
||||
"value": "4725",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"maker": "r49y2xKuKVG2dPkNHgWQAV61cjxk8gryjQ",
|
||||
"sequence": 429
|
||||
}
|
||||
},
|
||||
{
|
||||
"specification": {
|
||||
"direction": "buy",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"value": "1.6",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "BTC",
|
||||
"value": "496.5429474010489",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"maker": "rDVBvAQScXrGRGnzrxRrcJPeNLeLeUTAqE",
|
||||
"sequence": 35627
|
||||
},
|
||||
"state": {
|
||||
"availableQuantity": {
|
||||
"currency": "USD",
|
||||
"value": "0",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"priceOfAvailableQuantity": {
|
||||
"currency": "BTC",
|
||||
"value": "0",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"specification": {
|
||||
"direction": "buy",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"value": "10",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "BTC",
|
||||
"value": "3103",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"maker": "r49y2xKuKVG2dPkNHgWQAV61cjxk8gryjQ",
|
||||
"sequence": 431
|
||||
}
|
||||
}
|
||||
],
|
||||
"asks": [
|
||||
{
|
||||
"specification": {
|
||||
"direction": "sell",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"value": "0.3",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "BTC",
|
||||
"value": "99.34014894048333",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"maker": "raudnGKfTK23YKfnS7ixejHrqGERTYNFXk",
|
||||
"sequence": 110103
|
||||
}
|
||||
},
|
||||
{
|
||||
"specification": {
|
||||
"direction": "sell",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"value": "0.8095",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "BTC",
|
||||
"value": "268.754",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"maker": "rPyYxUGK8L4dgEvjPs3aRc1B1jEiLr3Hx5",
|
||||
"sequence": 392
|
||||
},
|
||||
"state": {
|
||||
"availableQuantity": {
|
||||
"currency": "USD",
|
||||
"value": "0.8078974385735969",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"priceOfAvailableQuantity": {
|
||||
"currency": "BTC",
|
||||
"value": "268.2219496064341",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"specification": {
|
||||
"direction": "sell",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"value": "0.4499999999999999",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "BTC",
|
||||
"value": "152.0098333185607",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"maker": "raudnGKfTK23YKfnS7ixejHrqGERTYNFXk",
|
||||
"sequence": 110105
|
||||
}
|
||||
},
|
||||
{
|
||||
"specification": {
|
||||
"direction": "sell",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"value": "0.003768001830745216",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "BTC",
|
||||
"value": "1.308365894430151",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"maker": "rDbsCJr5m8gHDCNEHCZtFxcXHsD4S9jH83",
|
||||
"sequence": 110061
|
||||
}
|
||||
},
|
||||
{
|
||||
"specification": {
|
||||
"direction": "sell",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"value": "0.5",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "BTC",
|
||||
"value": "176.3546101589987",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"maker": "rDVBvAQScXrGRGnzrxRrcJPeNLeLeUTAqE",
|
||||
"sequence": 35788
|
||||
}
|
||||
},
|
||||
{
|
||||
"specification": {
|
||||
"direction": "sell",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"value": "0.5",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "BTC",
|
||||
"value": "179.48",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"maker": "rN6jbxx4H6NxcnmkzBxQnbCWLECNKrgSSf",
|
||||
"sequence": 491
|
||||
},
|
||||
"state": {
|
||||
"availableQuantity": {
|
||||
"currency": "USD",
|
||||
"value": "0.499001996007984",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"priceOfAvailableQuantity": {
|
||||
"currency": "BTC",
|
||||
"value": "179.1217564870259",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"specification": {
|
||||
"direction": "sell",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"value": "0.8",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "BTC",
|
||||
"value": "288.7710263794967",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"maker": "rDVBvAQScXrGRGnzrxRrcJPeNLeLeUTAqE",
|
||||
"sequence": 35789
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
47
test/fixtures/get-orders-response.json
vendored
47
test/fixtures/get-orders-response.json
vendored
@@ -1,20 +1,19 @@
|
||||
[
|
||||
{
|
||||
"specification": {
|
||||
"direction": "buy",
|
||||
"direction": "sell",
|
||||
"quantity": {
|
||||
"currency": "USD",
|
||||
"value": "1122.990930900328",
|
||||
"counterparty": "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q"
|
||||
},
|
||||
"totalPrice": {
|
||||
"currency": "EUR",
|
||||
"value": "17.70155237781915",
|
||||
"counterparty": "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q"
|
||||
},
|
||||
"immediateOrCancel": true
|
||||
"totalPrice": {
|
||||
"currency": "USD",
|
||||
"value": "1122.990930900328",
|
||||
"counterparty": "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
"properties": {
|
||||
"sequence": 719930
|
||||
}
|
||||
},
|
||||
@@ -32,7 +31,7 @@
|
||||
"counterparty": "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
"properties": {
|
||||
"sequence": 756999
|
||||
}
|
||||
},
|
||||
@@ -50,7 +49,7 @@
|
||||
"counterparty": "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
"properties": {
|
||||
"sequence": 757002
|
||||
}
|
||||
},
|
||||
@@ -68,7 +67,7 @@
|
||||
"counterparty": "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
"properties": {
|
||||
"sequence": 757003
|
||||
}
|
||||
},
|
||||
@@ -86,7 +85,7 @@
|
||||
"counterparty": "rsP3mgGb2tcYUrxiLFiHJiQXhsziegtwBc"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
"properties": {
|
||||
"sequence": 782148
|
||||
}
|
||||
},
|
||||
@@ -104,7 +103,7 @@
|
||||
"counterparty": "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
"properties": {
|
||||
"sequence": 787368
|
||||
}
|
||||
},
|
||||
@@ -122,7 +121,7 @@
|
||||
"counterparty": "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
"properties": {
|
||||
"sequence": 787408
|
||||
}
|
||||
},
|
||||
@@ -140,7 +139,7 @@
|
||||
"counterparty": "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
"properties": {
|
||||
"sequence": 803438
|
||||
}
|
||||
},
|
||||
@@ -158,7 +157,7 @@
|
||||
"counterparty": "r9Dr5xwkeLegBeXq6ujinjSBLQzQ1zQGjH"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
"properties": {
|
||||
"sequence": 807858
|
||||
}
|
||||
},
|
||||
@@ -176,7 +175,7 @@
|
||||
"counterparty": "r9Dr5xwkeLegBeXq6ujinjSBLQzQ1zQGjH"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
"properties": {
|
||||
"sequence": 807896
|
||||
}
|
||||
},
|
||||
@@ -193,7 +192,7 @@
|
||||
"counterparty": "rsP3mgGb2tcYUrxiLFiHJiQXhsziegtwBc"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
"properties": {
|
||||
"sequence": 814018
|
||||
}
|
||||
},
|
||||
@@ -211,7 +210,7 @@
|
||||
"counterparty": "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
"properties": {
|
||||
"sequence": 827522
|
||||
}
|
||||
},
|
||||
@@ -229,7 +228,7 @@
|
||||
"counterparty": "r9Dr5xwkeLegBeXq6ujinjSBLQzQ1zQGjH"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
"properties": {
|
||||
"sequence": 833591
|
||||
}
|
||||
},
|
||||
@@ -247,7 +246,7 @@
|
||||
"counterparty": "r9Dr5xwkeLegBeXq6ujinjSBLQzQ1zQGjH"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
"properties": {
|
||||
"sequence": 833592
|
||||
}
|
||||
},
|
||||
@@ -265,7 +264,7 @@
|
||||
"counterparty": "r9Dr5xwkeLegBeXq6ujinjSBLQzQ1zQGjH"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
"properties": {
|
||||
"sequence": 838954
|
||||
}
|
||||
},
|
||||
@@ -282,7 +281,7 @@
|
||||
"value": "2229.229447"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
"properties": {
|
||||
"sequence": 843730
|
||||
}
|
||||
},
|
||||
@@ -300,7 +299,7 @@
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
"properties": {
|
||||
"sequence": 844068
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ const fixtures = require('./fixtures/mock');
|
||||
const addresses = require('./fixtures/addresses');
|
||||
const hashes = require('./fixtures/hashes');
|
||||
const accountOffersResponse = require('./fixtures/acct-offers-response');
|
||||
const bookOffers = require('./fixtures/book-offers-response');
|
||||
|
||||
module.exports = function(port) {
|
||||
const mock = new WebSocketServer({port: port});
|
||||
@@ -129,5 +130,17 @@ module.exports = function(port) {
|
||||
}
|
||||
});
|
||||
|
||||
mock.on('request_book_offers', function(request, conn) {
|
||||
if (request.taker_gets.currency === 'BTC'
|
||||
&& request.taker_pays.currency === 'USD') {
|
||||
conn.send(bookOffers.requestBookOffersBidsResponse(request));
|
||||
} else if (request.taker_gets.currency === 'USD'
|
||||
&& request.taker_pays.currency === 'BTC') {
|
||||
conn.send(bookOffers.requestBookOffersAsksResponse(request));
|
||||
} else {
|
||||
assert(false, 'Unrecognized order book: ' + JSON.stringify(request));
|
||||
}
|
||||
});
|
||||
|
||||
return mock;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user