@dydxprotocol/v4-client-js 1.17.0 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
- # [1.17.0](https://github.com/dydxprotocol/v4-clients/compare/v4-client-js@1.16.3...v4-client-js@1.17.0) (2025-02-10)
1
+ # [1.18.0](https://github.com/dydxprotocol/v4-clients/compare/v4-client-js@1.17.0...v4-client-js@1.18.0) (2025-02-12)
2
2
 
3
3
 
4
4
  ### Features
5
5
 
6
- * compliance v2 endpoint ([#331](https://github.com/dydxprotocol/v4-clients/issues/331)) ([15a0905](https://github.com/dydxprotocol/v4-clients/commit/15a0905a5d2d97d31ea0f5b4849ebf79ef295816))
6
+ * add crossed orderbook resolving example using websocket ([#301](https://github.com/dydxprotocol/v4-clients/issues/301)) ([88aabad](https://github.com/dydxprotocol/v4-clients/commit/88aabadc23deb0401fa8a6fb9e08826cbba09197))
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,198 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const constants_1 = require("../src/clients/constants");
4
+ const socket_client_1 = require("../src/clients/socket-client");
5
+ function test() {
6
+ let orderBookBidList = [];
7
+ let orderBookAskList = [];
8
+ const mySocket = new socket_client_1.SocketClient(constants_1.Network.mainnet().indexerConfig, () => {
9
+ console.log('socket opened');
10
+ mySocket.subscribeToOrderbook('ETH-USD');
11
+ }, () => {
12
+ console.log('socket closed');
13
+ }, (message) => {
14
+ try {
15
+ if (typeof message.data === "string") {
16
+ const jsonString = message.data;
17
+ const parsingData = JSON.parse(jsonString);
18
+ const messageId = parsingData.message_id;
19
+ const orderBookDataList = parsingData.contents;
20
+ if (orderBookDataList instanceof Array) {
21
+ // common orderBook data;
22
+ [orderBookBidList, orderBookAskList] = updateOrderBook(orderBookDataList, orderBookBidList, orderBookAskList, messageId);
23
+ // sort
24
+ orderBookBidList = sortByNthElementDesc(orderBookBidList, 0);
25
+ orderBookAskList = sortByNthElementAsc(orderBookAskList, 0);
26
+ // resolving crossed orderBook
27
+ if (orderBookBidList &&
28
+ orderBookAskList &&
29
+ orderBookBidList.length > 0 &&
30
+ orderBookAskList.length > 0 &&
31
+ orderBookBidList[0][0] >= orderBookAskList[0][0]) {
32
+ [orderBookBidList, orderBookAskList] =
33
+ resolveCrossedOrderBook(orderBookBidList, orderBookAskList);
34
+ }
35
+ printOrderBook(orderBookBidList, orderBookAskList);
36
+ if (orderBookBidList.length > 300) {
37
+ orderBookBidList.splice(50);
38
+ }
39
+ if (orderBookAskList.length > 300) {
40
+ orderBookAskList.splice(50);
41
+ }
42
+ }
43
+ else if (orderBookDataList !== null &&
44
+ orderBookDataList !== undefined) {
45
+ // initial OrderBook data
46
+ setInitialOrderBook(orderBookDataList, orderBookBidList, orderBookAskList, messageId);
47
+ }
48
+ }
49
+ }
50
+ catch (e) {
51
+ console.error('Error parsing JSON message:', e);
52
+ }
53
+ }, (event) => {
54
+ console.error('Encountered error:', event.message);
55
+ });
56
+ mySocket.connect();
57
+ }
58
+ const sortByNthElementAsc = (arr, n) => {
59
+ return arr.sort((a, b) => {
60
+ if (a[n] < b[n])
61
+ return -1;
62
+ if (a[n] > b[n])
63
+ return 1;
64
+ return 0;
65
+ });
66
+ };
67
+ const sortByNthElementDesc = (arr, n) => {
68
+ return arr.sort((a, b) => {
69
+ if (a[n] > b[n])
70
+ return -1;
71
+ if (a[n] < b[n])
72
+ return 1;
73
+ return 0;
74
+ });
75
+ };
76
+ const printOrderBook = (orderBookBidList, orderBookAskList) => {
77
+ // print
78
+ console.log(`OrderBook for ETH-USD:`);
79
+ console.log(`Price Qty`);
80
+ for (let i = 4; i > -1; i--) {
81
+ const priceStr = String(orderBookAskList[i][0]);
82
+ const spaces = createSpaces(10 - priceStr.length);
83
+ console.log(`${priceStr}${spaces}${orderBookAskList[i][1]}`);
84
+ }
85
+ console.log('---------------------');
86
+ for (let i = 0; i < 5; i++) {
87
+ const priceStr = String(orderBookBidList[i][0]);
88
+ const spaces = createSpaces(10 - priceStr.length);
89
+ console.log(`${priceStr}${spaces}${orderBookBidList[i][1]}`);
90
+ }
91
+ console.log('');
92
+ };
93
+ function createSpaces(count) {
94
+ if (count <= 0) {
95
+ return "";
96
+ }
97
+ let spaces = "";
98
+ for (let i = 0; i < count; i++) {
99
+ spaces += " ";
100
+ }
101
+ return spaces;
102
+ }
103
+ const resolveCrossedOrderBook = (orderBookBidList, orderBookAskList) => {
104
+ while (orderBookBidList[0][0] >= orderBookAskList[0][0]) {
105
+ if (orderBookBidList[0][2] < orderBookAskList[0][2]) {
106
+ orderBookBidList.shift();
107
+ }
108
+ else if (orderBookBidList[0][2] > orderBookAskList[0][2]) {
109
+ orderBookAskList.shift();
110
+ }
111
+ else {
112
+ if (orderBookBidList[0][1] > orderBookAskList[0][1]) {
113
+ orderBookBidList[0][1] -= orderBookAskList[0][1];
114
+ orderBookAskList.shift();
115
+ }
116
+ else if (orderBookBidList[0][1] < orderBookAskList[0][1]) {
117
+ orderBookAskList[0][1] -= orderBookBidList[0][1];
118
+ orderBookBidList.shift();
119
+ }
120
+ else {
121
+ orderBookAskList.shift();
122
+ orderBookBidList.shift();
123
+ }
124
+ }
125
+ }
126
+ return [orderBookBidList, orderBookAskList];
127
+ };
128
+ const setInitialOrderBook = (orderBookDataList, orderBookBidList, orderBookAskList, messageId) => {
129
+ orderBookDataList.bids.forEach((item) => {
130
+ orderBookBidList.push([Number(item.price), Number(item.size), messageId]);
131
+ });
132
+ orderBookDataList.asks.forEach((item) => {
133
+ orderBookAskList.push([Number(item.price), Number(item.size), messageId]);
134
+ });
135
+ };
136
+ const updateOrderBook = (orderBookDataList, orderBookBidList, orderBookAskList, messageId) => {
137
+ orderBookDataList.forEach((entry) => {
138
+ if (entry.bids !== null && entry.bids !== undefined) {
139
+ const flattened = entry.bids.reduce((acc, val) => acc.concat(val), []);
140
+ const entryBidPrice = Number(flattened[0]);
141
+ const entryBidSize = Number(flattened[1]);
142
+ // remove prices with zero Qty
143
+ if (entryBidSize === 0) {
144
+ for (let i = orderBookBidList.length - 1; i >= 0; i--) {
145
+ if (orderBookBidList[i][0] === entryBidPrice) {
146
+ orderBookBidList.splice(i, 1);
147
+ }
148
+ }
149
+ }
150
+ else {
151
+ // The price that already exists in the order book is modified only Qty
152
+ if (orderBookBidList.some((innerArray) => innerArray[0] === entryBidPrice)) {
153
+ orderBookBidList.forEach((item, index) => {
154
+ if (item[0] === entryBidPrice) {
155
+ orderBookBidList[index][1] = entryBidSize;
156
+ orderBookBidList[index][2] = messageId;
157
+ }
158
+ });
159
+ }
160
+ else {
161
+ // Add new data to order book
162
+ orderBookBidList.push([entryBidPrice, entryBidSize, messageId]);
163
+ }
164
+ }
165
+ }
166
+ if (entry.asks !== null && entry.asks !== undefined) {
167
+ const flattened = entry.asks.reduce((acc, val) => acc.concat(val), []);
168
+ const entryAskPrice = Number(flattened[0]);
169
+ const entryAskSize = Number(flattened[1]);
170
+ if (entryAskSize === 0) {
171
+ // remove prices with zero Qty
172
+ for (let i = orderBookAskList.length - 1; i >= 0; i--) {
173
+ if (orderBookAskList[i][0] === entryAskPrice) {
174
+ orderBookAskList.splice(i, 1);
175
+ }
176
+ }
177
+ }
178
+ else {
179
+ // The price that already exists in the order book is modified only Qty
180
+ if (orderBookAskList.some((innerArray) => innerArray[0] === entryAskPrice)) {
181
+ orderBookAskList.forEach((item, index) => {
182
+ if (item[0] === entryAskPrice) {
183
+ orderBookAskList[index][1] = entryAskSize;
184
+ orderBookAskList[index][2] = messageId;
185
+ }
186
+ });
187
+ }
188
+ else {
189
+ // Add new data to order book
190
+ orderBookAskList.push([entryAskPrice, entryAskSize, messageId]);
191
+ }
192
+ }
193
+ }
194
+ });
195
+ return [orderBookBidList, orderBookAskList];
196
+ };
197
+ test();
198
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2Vic29ja2V0X29yZGVyYm9va19leGFtcGxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vZXhhbXBsZXMvd2Vic29ja2V0X29yZGVyYm9va19leGFtcGxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsd0RBQW1EO0FBQ25ELGdFQUE0RDtBQUU1RCxTQUFTLElBQUk7SUFDVCxJQUFJLGdCQUFnQixHQUErQixFQUFFLENBQUM7SUFDdEQsSUFBSSxnQkFBZ0IsR0FBK0IsRUFBRSxDQUFDO0lBRXRELE1BQU0sUUFBUSxHQUFHLElBQUksNEJBQVksQ0FDN0IsbUJBQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxhQUFhLEVBQy9CLEdBQUcsRUFBRTtRQUNELE9BQU8sQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLENBQUM7UUFFN0IsUUFBUSxDQUFDLG9CQUFvQixDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzdDLENBQUMsRUFDRCxHQUFHLEVBQUU7UUFDRCxPQUFPLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBQ2pDLENBQUMsRUFDRCxDQUFDLE9BQU8sRUFBRSxFQUFFO1FBQ1IsSUFBSTtZQUNBLElBQUksT0FBTyxPQUFPLENBQUMsSUFBSSxLQUFLLFFBQVEsRUFBRTtnQkFDbEMsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQztnQkFDaEMsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztnQkFDM0MsTUFBTSxTQUFTLEdBQUcsV0FBVyxDQUFDLFVBQVUsQ0FBQztnQkFDekMsTUFBTSxpQkFBaUIsR0FBRyxXQUFXLENBQUMsUUFBUSxDQUFDO2dCQUUvQyxJQUFJLGlCQUFpQixZQUFZLEtBQUssRUFBRTtvQkFDcEMseUJBQXlCO29CQUN6QixDQUFDLGdCQUFnQixFQUFFLGdCQUFnQixDQUFDLEdBQUcsZUFBZSxDQUNsRCxpQkFBaUIsRUFDakIsZ0JBQWdCLEVBQ2hCLGdC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