Skip to content
This repository was archived by the owner on Sep 9, 2023. It is now read-only.

Commit 0cf93ec

Browse files
committed
ledgerx: update to new API endpoint
Now connects to api.ledgerx.com instead of trade.ledgerx.com per https://docs.ledgerx.com/reference#connecting
1 parent 959d117 commit 0cf93ec

File tree

1 file changed

+105
-10
lines changed

1 file changed

+105
-10
lines changed

Diff for: src/exchanges/ledgerx-client.js

+105-10
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ const Level3Update = require("../level3-update");
66
const Level3Snapshot = require("../level3-snapshot");
77

88
/**
9-
* LedgerX is defined in https://docs.ledgerx.com/reference#market-data-feed
9+
* LedgerX is defined in https://docs.ledgerx.com/reference#connecting
1010
* This socket uses a unified stream for ALL market data. So we will leverage
1111
* subscription filtering to only reply with values that of are of interest.
1212
*/
1313
class LedgerXClient extends BasicClient {
14-
constructor({ wssPath = "wss://trade.ledgerx.com/api/ws?token=", apiKey, watcherMs } = {}) {
14+
constructor({ wssPath = "wss://api.ledgerx.com/ws?token=", apiKey, watcherMs } = {}) {
1515
super(wssPath + apiKey, "LedgerX", undefined, watcherMs);
1616

1717
this.hasTrades = true;
@@ -31,6 +31,8 @@ class LedgerXClient extends BasicClient {
3131
_sendUnSubLevel3Updates() {}
3232

3333
_onMessage(msg) {
34+
this.emit("raw", msg);
35+
3436
const json = JSON.parse(msg);
3537

3638
if (json.type === "auth_success") {
@@ -41,15 +43,15 @@ class LedgerXClient extends BasicClient {
4143
return;
4244
}
4345

44-
if (json.type === "exposure_reports") {
46+
if (json.positions !== undefined) {
4547
return;
4648
}
4749

48-
if (json.type === "open_positions_update") {
50+
if (json.collateral !== undefined) {
4951
return;
5052
}
5153

52-
if (json.type === "collateral_balance_update") {
54+
if (json.type === "exposure_reports") {
5355
return;
5456
}
5557

@@ -76,7 +78,7 @@ class LedgerXClient extends BasicClient {
7678
return;
7779
}
7880

79-
// trade event
81+
// trade event, filled either partial or fully
8082
if (json.status_type === 201) {
8183
// check for trade subscription
8284
let market =
@@ -110,6 +112,18 @@ class LedgerXClient extends BasicClient {
110112
this.emit("l3update", update, market, json);
111113
return;
112114
}
115+
116+
// cancelled and replaced event
117+
if (json.status_type === 204) {
118+
const market =
119+
this._level3UpdateSubs.get(json.contract_id) ||
120+
this._level3UpdateSubs.get(json.contract_id.toString());
121+
if (!market) return;
122+
123+
const update = this._constructL3Replace(json, market);
124+
this.emit("l3update", update, market, json);
125+
return;
126+
}
113127
}
114128
}
115129

@@ -125,7 +139,7 @@ class LedgerXClient extends BasicClient {
125139
let bids = [];
126140
for (let row of data.book_states) {
127141
let orderId = row.mid;
128-
let price = (row.price / 100).toFixed(2);
142+
let price = row.price.toFixed(2);
129143
let size = row.size.toFixed();
130144
let point = new Level3Point(orderId, price, size);
131145
if (row.is_ask) asks.push(point);
@@ -212,10 +226,13 @@ class LedgerXClient extends BasicClient {
212226
amount: msg.filled_size.toFixed(8),
213227
buyOrderId,
214228
sellOrderId,
229+
open_interest: msg.open_interest,
215230
});
216231
}
217232

218233
/**
234+
* 200 - A resting limit order of size inserted_size @ price
235+
* inserted_price was inserted into book depth.
219236
{
220237
inserted_time: 1597176131501325800,
221238
timestamp: 1597176131501343700,
@@ -242,7 +259,7 @@ class LedgerXClient extends BasicClient {
242259
}
243260
*/
244261
_constructL3Insert(msg, market) {
245-
let price = (msg.price / 100).toFixed(8);
262+
let price = msg.price.toFixed(8);
246263
let size = msg.inserted_size.toFixed(8);
247264
let point = new Level3Point(msg.mid, price, size, {
248265
order_type: msg.order_type,
@@ -283,6 +300,8 @@ class LedgerXClient extends BasicClient {
283300
}
284301

285302
/**
303+
* 201 - A cross of size filled_size @ price filled_price occurred.
304+
* Subtract filled_size from the resting size for this order.
286305
{
287306
mid: '885be81549974faf88e4430f6046513d',
288307
filled_size: 5,
@@ -309,7 +328,7 @@ class LedgerXClient extends BasicClient {
309328
}
310329
*/
311330
_constructL3Trade(msg, market) {
312-
let price = (msg.original_price / 100).toFixed(8);
331+
let price = msg.original_price.toFixed(8);
313332
let size = (msg.original_size - msg.filled_size).toFixed(8);
314333
let point = new Level3Point(msg.mid, price, size, {
315334
order_type: msg.order_type,
@@ -329,6 +348,7 @@ class LedgerXClient extends BasicClient {
329348
price: msg.price,
330349
size: msg.size,
331350
vwap: msg.vwap,
351+
open_interest: msg.open_interest,
332352
});
333353

334354
let asks = [];
@@ -350,6 +370,7 @@ class LedgerXClient extends BasicClient {
350370
}
351371

352372
/**
373+
* 203 - An order was cancelled. Remove this order from book depth.
353374
{
354375
inserted_time: 1597176853952381700,
355376
timestamp: 1597176857137740800,
@@ -376,7 +397,7 @@ class LedgerXClient extends BasicClient {
376397
}
377398
*/
378399
_constructL3Cancel(msg, market) {
379-
let price = (msg.original_price / 100).toFixed(8);
400+
let price = msg.original_price.toFixed(8);
380401
let size = (0).toFixed(8);
381402
let point = new Level3Point(msg.mid, price, size, {
382403
order_type: msg.order_type,
@@ -396,6 +417,80 @@ class LedgerXClient extends BasicClient {
396417
price: msg.price,
397418
size: msg.size,
398419
vwap: msg.vwap,
420+
open_interest: msg.open_interest,
421+
});
422+
423+
let asks = [];
424+
let bids = [];
425+
426+
if (msg.is_ask) asks.push(point);
427+
else bids.push(point);
428+
429+
return new Level3Update({
430+
exchange: this._name,
431+
base: market.base,
432+
quote: market.quote,
433+
sequenceId: msg.clock,
434+
timestampMs: Math.floor(msg.inserted_time / 1e6),
435+
runId: this.runId,
436+
asks,
437+
bids,
438+
});
439+
}
440+
441+
/**
442+
* 204 - An order was cancelled and replaced. The new order retains the
443+
* existing mid, and can only reflect an update in size and not price.
444+
* Overwrite the resting order size with inserted_size.
445+
*
446+
{
447+
"status_type": 204,
448+
"inserted_size": 12,
449+
"original_price": 59000,
450+
"open_interest": 121,
451+
"filled_size": 0,
452+
"updated_time": 1623074768372895949,
453+
"clock": 40011,
454+
"size": 12,
455+
"timestamp": 1623074768372897897,
456+
"status_reason": 0,
457+
"vwap": 0,
458+
"inserted_time": 1623074764668677182,
459+
"price": 59000,
460+
"type": "action_report",
461+
"is_ask": true,
462+
"original_size": 12,
463+
"order_type": "customer_limit_order",
464+
"is_volatile": true,
465+
"ticks": 25980094140252686,
466+
"filled_price": 0,
467+
"mid": "c071baaa458a411db184cb6874e86d69",
468+
"inserted_price": 59000,
469+
"contract_id": 22216779
470+
}
471+
*/
472+
_constructL3Replace(msg, market) {
473+
let price = msg.original_price.toFixed(8);
474+
let size = msg.inserted_size.toFixed(8);
475+
let point = new Level3Point(msg.mid, price, size, {
476+
order_type: msg.order_type,
477+
status_type: msg.status_type,
478+
status_reason: msg.status_reason,
479+
is_volatile: msg.is_volatile,
480+
timestamp: msg.timestamp,
481+
ticks: msg.ticks,
482+
inserted_time: msg.inserted_time,
483+
updated_time: msg.updated_time,
484+
original_price: msg.original_price,
485+
original_size: msg.original_size,
486+
inserted_price: msg.inserted_price,
487+
inserted_size: msg.inserted_size,
488+
filled_price: msg.filled_price,
489+
filled_size: msg.filled_size,
490+
price: msg.price,
491+
size: msg.size,
492+
vwap: msg.vwap,
493+
open_interest: msg.open_interest,
399494
});
400495

401496
let asks = [];

0 commit comments

Comments
 (0)