Skip to content

Commit d12a19f

Browse files
committed
feat: add orderdbook example using websocket
1 parent bdbab8c commit d12a19f

File tree

1 file changed

+252
-0
lines changed

1 file changed

+252
-0
lines changed
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
import { Network } from '../src/clients/constants';
2+
import { SocketClient } from '../src/clients/socket-client';
3+
4+
function test(): void {
5+
let orderBookBidList: [number, number, number][] = [];
6+
let orderBookAskList: [number, number, number][] = [];
7+
8+
const mySocket = new SocketClient(
9+
Network.mainnet().indexerConfig,
10+
() => {
11+
console.log('socket opened');
12+
13+
mySocket.subscribeToOrderbook('ETH-USD');
14+
},
15+
() => {
16+
console.log('socket closed');
17+
},
18+
(message) => {
19+
try {
20+
if (typeof message.data === "string") {
21+
const jsonString = message.data;
22+
const parsingData = JSON.parse(jsonString);
23+
const messageId = parsingData.message_id;
24+
const orderBookDataList = parsingData.contents;
25+
26+
if (orderBookDataList instanceof Array) {
27+
// common orderBook data;
28+
[orderBookBidList, orderBookAskList] = updateOrderBook(
29+
orderBookDataList,
30+
orderBookBidList,
31+
orderBookAskList,
32+
messageId,
33+
);
34+
35+
// sort
36+
orderBookBidList = sortByNthElementDesc(
37+
orderBookBidList,
38+
0,
39+
);
40+
orderBookAskList = sortByNthElementAsc(
41+
orderBookAskList,
42+
0,
43+
);
44+
45+
// resolving crossed orderBook
46+
if (
47+
orderBookBidList &&
48+
orderBookAskList &&
49+
orderBookBidList.length > 0 &&
50+
orderBookAskList.length > 0 &&
51+
orderBookBidList[0][0] >= orderBookAskList[0][0]
52+
) {
53+
[orderBookBidList, orderBookAskList] =
54+
resolveCrossedOrderBook(
55+
orderBookBidList,
56+
orderBookAskList,
57+
);
58+
}
59+
60+
printOrderBook(orderBookBidList, orderBookAskList);
61+
62+
if (orderBookBidList.length > 300) {
63+
orderBookBidList.splice(50);
64+
}
65+
66+
if (orderBookAskList.length > 300) {
67+
orderBookAskList.splice(50);
68+
}
69+
} else if (
70+
orderBookDataList !== null &&
71+
orderBookDataList !== undefined
72+
) {
73+
// initial OrderBook data
74+
setInitialOrderBook(
75+
orderBookDataList,
76+
orderBookBidList,
77+
orderBookAskList,
78+
messageId,
79+
);
80+
}
81+
}
82+
} catch (e) {
83+
console.error('Error parsing JSON message:', e);
84+
}
85+
},
86+
(event) => {
87+
console.error('Encountered error:', event.message);
88+
},
89+
);
90+
91+
mySocket.connect();
92+
}
93+
94+
const sortByNthElementAsc = (arr: [number, number, number][], n: number): [number, number, number][] => {
95+
return arr.sort((a, b) => {
96+
if (a[n] < b[n]) return -1;
97+
if (a[n] > b[n]) return 1;
98+
return 0;
99+
});
100+
};
101+
const sortByNthElementDesc = (arr: [number, number, number][], n: number): [number, number, number][] => {
102+
return arr.sort((a, b) => {
103+
if (a[n] > b[n]) return -1;
104+
if (a[n] < b[n]) return 1;
105+
return 0;
106+
});
107+
};
108+
109+
const printOrderBook = (
110+
orderBookBidList: [number, number, number][],
111+
orderBookAskList: [number, number, number][],
112+
): void => {
113+
// print
114+
console.log(`OrderBook for ETH-USD:`);
115+
console.log(`Price Qty`);
116+
for (let i = 4; i > -1; i--) {
117+
const priceStr = String(orderBookAskList[i][0]);
118+
const spaces = createSpaces(10 - priceStr.length);
119+
console.log(`${priceStr}${spaces}${orderBookAskList[i][1]}`);
120+
}
121+
console.log('---------------------');
122+
for (let i = 0; i < 5; i++) {
123+
const priceStr = String(orderBookBidList[i][0]);
124+
const spaces = createSpaces(10 - priceStr.length);
125+
console.log(`${priceStr}${spaces}${orderBookBidList[i][1]}`);
126+
}
127+
console.log('');
128+
};
129+
130+
function createSpaces(count: number): string {
131+
if(count <= 0 ){
132+
return "";
133+
}
134+
135+
let spaces = "";
136+
for (let i = 0; i < count; i++) {
137+
spaces += " ";
138+
}
139+
return spaces;
140+
}
141+
142+
const resolveCrossedOrderBook = (
143+
orderBookBidList: [number, number, number][],
144+
orderBookAskList: [number, number, number][],
145+
): [[number, number, number][], [number, number, number][]] => {
146+
while (orderBookBidList[0][0] >= orderBookAskList[0][0]) {
147+
if (orderBookBidList[0][2] < orderBookAskList[0][2]) {
148+
orderBookBidList.shift();
149+
} else if (orderBookBidList[0][2] > orderBookAskList[0][2]) {
150+
orderBookAskList.shift();
151+
} else {
152+
if (orderBookBidList[0][1] > orderBookAskList[0][1]) {
153+
orderBookBidList[0][1] -= orderBookAskList[0][1];
154+
orderBookAskList.shift();
155+
} else if (orderBookBidList[0][1] < orderBookAskList[0][1]) {
156+
orderBookAskList[0][1] -= orderBookBidList[0][1];
157+
orderBookBidList.shift();
158+
} else {
159+
orderBookAskList.shift();
160+
orderBookBidList.shift();
161+
}
162+
}
163+
}
164+
165+
return [orderBookBidList, orderBookAskList];
166+
};
167+
const setInitialOrderBook = (
168+
orderBookDataList: { bids: []; asks: [] },
169+
orderBookBidList: [number, number, number][],
170+
orderBookAskList: [number, number, number][],
171+
messageId: number,
172+
): void => {
173+
orderBookDataList.bids.forEach((item: { price: string; size: string }) => {
174+
orderBookBidList.push([Number(item.price), Number(item.size), messageId]);
175+
});
176+
177+
orderBookDataList.asks.forEach((item: { price: string; size: string }) => {
178+
orderBookAskList.push([Number(item.price), Number(item.size), messageId]);
179+
});
180+
};
181+
182+
const updateOrderBook = (
183+
orderBookDataList: { bids: [[]]; asks: [[]] }[],
184+
orderBookBidList: [number, number, number][],
185+
orderBookAskList: [number, number, number][],
186+
messageId: number,
187+
): [[number, number, number][], [number, number, number][]] => {
188+
orderBookDataList.forEach((entry: { bids: [[]]; asks: [[]] }) => {
189+
if (entry.bids !== null && entry.bids !== undefined) {
190+
const flattened = entry.bids.reduce((acc: any[], val: any[]) => acc.concat(val), []);
191+
const entryBidPrice = Number(flattened[0]);
192+
const entryBidSize = Number(flattened[1]);
193+
194+
// remove prices with zero Qty
195+
if (entryBidSize === 0) {
196+
for (let i = orderBookBidList.length - 1; i >= 0; i--) {
197+
if (orderBookBidList[i][0] === entryBidPrice) {
198+
orderBookBidList.splice(i, 1);
199+
}
200+
}
201+
} else {
202+
// The price that already exists in the order book is modified only Qty
203+
if (
204+
orderBookBidList.some((innerArray) => innerArray[0] === entryBidPrice)
205+
) {
206+
orderBookBidList.forEach((item, index) => {
207+
if (item[0] === entryBidPrice) {
208+
orderBookBidList[index][1] = entryBidSize;
209+
orderBookBidList[index][2] = messageId;
210+
}
211+
});
212+
} else {
213+
// Add new data to order book
214+
orderBookBidList.push([entryBidPrice, entryBidSize, messageId]);
215+
}
216+
}
217+
}
218+
if (entry.asks !== null && entry.asks !== undefined) {
219+
const flattened = entry.asks.reduce((acc: any[], val: any[]) => acc.concat(val), []);
220+
const entryAskPrice = Number(flattened[0]);
221+
const entryAskSize = Number(flattened[1]);
222+
223+
if (entryAskSize === 0) {
224+
// remove prices with zero Qty
225+
for (let i = orderBookAskList.length - 1; i >= 0; i--) {
226+
if (orderBookAskList[i][0] === entryAskPrice) {
227+
orderBookAskList.splice(i, 1);
228+
}
229+
}
230+
} else {
231+
// The price that already exists in the order book is modified only Qty
232+
if (
233+
orderBookAskList.some((innerArray) => innerArray[0] === entryAskPrice)
234+
) {
235+
orderBookAskList.forEach((item, index) => {
236+
if (item[0] === entryAskPrice) {
237+
orderBookAskList[index][1] = entryAskSize;
238+
orderBookAskList[index][2] = messageId;
239+
}
240+
});
241+
} else {
242+
// Add new data to order book
243+
orderBookAskList.push([entryAskPrice, entryAskSize, messageId]);
244+
}
245+
}
246+
}
247+
});
248+
249+
return [orderBookBidList, orderBookAskList];
250+
};
251+
252+
test();

0 commit comments

Comments
 (0)