ws server works

This commit is contained in:
Nour Alharithi
2023-10-24 15:20:35 -07:00
parent 22203fd20a
commit 568ab5a239
6 changed files with 260 additions and 31 deletions

1
.gitignore vendored
View File

@@ -140,3 +140,4 @@ src/**.js.map
.env
lib
src/playground.ts

View File

@@ -22,6 +22,8 @@
"express-rate-limit": "^6.7.0",
"morgan": "^1.10.0",
"response-time": "^2.3.2",
"socket.io": "^4.7.2",
"socket.io-client": "^4.7.2",
"typescript": "4.5.4",
"winston": "^3.8.1"
},
@@ -50,6 +52,7 @@
"prettify": "prettier --check './src/**/*.ts'",
"prettify:fix": "prettier --write './src/**/*.ts'",
"lint": "eslint . --ext ts --quiet",
"lint:fix": "eslint . --ext ts --fix"
"lint:fix": "eslint . --ext ts --fix",
"playground": "ts-node src/playground.ts"
}
}

View File

@@ -0,0 +1,56 @@
import {
BN,
DLOBSubscriber,
DLOBSubscriptionConfig,
L2OrderBookGenerator,
MarketType,
groupL2,
} from '@drift-labs/sdk';
import { l2WithBNToStrings } from '../utils';
import { Server } from 'socket.io';
import { getIOServer } from '..';
type wsMarketL2Args = {
marketIndex: number;
marketType: MarketType;
marketName: string;
depth: number;
includeVamm: boolean;
grouping?: number;
fallbackL2Generators?: L2OrderBookGenerator[];
};
export class DLOBSubscriberIO extends DLOBSubscriber {
public marketL2Args: wsMarketL2Args[] = [];
io: Server;
constructor(config: DLOBSubscriptionConfig) {
super(config);
}
override async updateDLOB(): Promise<void> {
this.io = getIOServer();
await super.updateDLOB();
for (const l2Args of this.marketL2Args) {
this.getL2AndSendMsg(l2Args);
}
}
getL2AndSendMsg(l2Args: wsMarketL2Args): void {
console.time('getL2AndSendMsg');
const grouping = l2Args.grouping;
const l2 = this.getL2(l2Args);
let l2Formatted: any;
if (grouping) {
const groupingBN = new BN(grouping);
l2Formatted = l2WithBNToStrings(groupL2(l2, groupingBN, l2Args.depth));
} else {
l2Formatted = l2WithBNToStrings(l2);
}
l2Formatted['marketName'] = l2Args.marketName;
l2Formatted['marketType'] = l2Args.marketType;
l2Formatted['marketIndex'] = l2Args.marketIndex;
this.io.emit('l2Update', l2Formatted);
console.timeEnd('getL2AndSendMsg');
}
}

View File

@@ -22,7 +22,6 @@ import {
DLOBOrdersCoder,
SpotMarkets,
PerpMarkets,
DLOBSubscriber,
MarketType,
SpotMarketConfig,
PhoenixSubscriber,
@@ -31,7 +30,6 @@ import {
isVariant,
BN,
groupL2,
L2OrderBook,
Wallet,
UserStatsMap,
} from '@drift-labs/sdk';
@@ -48,6 +46,10 @@ import {
View,
} from '@opentelemetry/sdk-metrics-base';
import { ObservableResult } from '@opentelemetry/api';
import * as http from 'http';
import { Server } from 'socket.io';
import { l2WithBNToStrings, sleep } from './utils';
import { DLOBSubscriberIO } from './dlob-subscriber/DLOBSubscriberIO';
require('dotenv').config();
const driftEnv = (process.env.ENV || 'devnet') as DriftEnv;
@@ -57,6 +59,12 @@ const sdkConfig = initialize({ env: process.env.ENV });
const stateCommitment: Commitment = 'processed';
const serverPort = process.env.PORT || 6969;
const maxPerpMarketIndex = Math.max(
...sdkConfig.PERP_MARKETS.map((m) => m.marketIndex)
);
const maxSpotMarketIndex = Math.max(
...sdkConfig.SPOT_MARKETS.map((m) => m.marketIndex)
);
const bulkAccountLoaderPollingInterval = process.env
.BULK_ACCOUNT_LOADER_POLLING_INTERVAL
@@ -89,6 +97,13 @@ app.use(compression());
app.set('trust proxy', 1);
app.use(logHttp);
const server = http.createServer(app);
const io = new Server(server);
export function getIOServer(): Server {
return io;
}
const handleResponseTime = responseTime(
(req: Request, res: Response, time: number) => {
const endpoint = req.path;
@@ -147,10 +162,6 @@ logger.info(`WS endpoint: ${wsEndpoint}`);
logger.info(`DriftEnv: ${driftEnv}`);
logger.info(`Commit: ${commitHash}`);
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
/**
* Creates {count} buckets of size {increment} starting from {start}. Each bucket stores the count of values within its "size".
* @param start
@@ -398,7 +409,7 @@ const main = async () => {
);
await userStatsMap.subscribe();
const dlobSubscriber = new DLOBSubscriber({
const dlobSubscriber = new DLOBSubscriberIO({
driftClient,
dlobSource: userMap,
slotSource: slotSubscriber,
@@ -903,24 +914,6 @@ const main = async () => {
}
});
const l2WithBNToStrings = (l2: L2OrderBook): any => {
for (const key of Object.keys(l2)) {
for (const idx in l2[key]) {
const level = l2[key][idx];
const sources = level['sources'];
for (const sourceKey of Object.keys(sources)) {
sources[sourceKey] = sources[sourceKey].toString();
}
l2[key][idx] = {
price: level.price.toString(),
size: level.size.toString(),
sources,
};
}
}
return l2;
};
const getOracleForMarket = (
marketType: MarketType,
marketIndex: number
@@ -1249,9 +1242,48 @@ const main = async () => {
});
app.use(errorHandler);
app.listen(serverPort, () => {
server.listen(serverPort, () => {
logger.info(`DLOB server listening on port http://localhost:${serverPort}`);
});
/**
* Handle websocket logic here
*/
io.on('connection', (socket) => {
console.log('a user connected');
socket.on('disconnect', () => {
console.log('user disconnected');
});
socket.on('message', (msg: any) => {
const parsed = JSON.parse(msg);
if (parsed['type'] == 'subscribe') {
console.log('here');
dlobSubscriber.marketL2Args.push({
marketIndex: parseInt(parsed['marketIndex']),
marketType: isVariant(parsed['marketType'].toLowerCase(), 'spot')
? MarketType.SPOT
: MarketType.PERP,
marketName: parsed['marketName'],
depth: parseInt(parsed['depth']),
includeVamm: parsed['includeVamm'] === 'true',
grouping: parsed['grouping']
? parseInt(parsed['grouping'])
: undefined,
fallbackL2Generators: isVariant(parsed['marketType'], 'spot')
? [
`${parsed['includePhoenix']}`.toLowerCase() === 'true' &&
MARKET_SUBSCRIBERS[parseInt(parsed['marketIndex'])].phoenix,
`${parsed['includeSerum']}`.toLowerCase() === 'true' &&
MARKET_SUBSCRIBERS[parseInt(parsed['marketIndex'])].serum,
].filter((a) => !!a)
: [],
});
}
});
});
};
async function recursiveTryCatch(f: () => void) {

23
src/utils.ts Normal file
View File

@@ -0,0 +1,23 @@
import { L2OrderBook } from '@drift-labs/sdk';
export const l2WithBNToStrings = (l2: L2OrderBook): any => {
for (const key of Object.keys(l2)) {
for (const idx in l2[key]) {
const level = l2[key][idx];
const sources = level['sources'];
for (const sourceKey of Object.keys(sources)) {
sources[sourceKey] = sources[sourceKey].toString();
}
l2[key][idx] = {
price: level.price.toString(),
size: level.size.toString(),
sources,
};
}
}
return l2;
};
export function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}

122
yarn.lock
View File

@@ -901,6 +901,11 @@
resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df"
integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
"@socket.io/component-emitter@~3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553"
integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==
"@solana/buffer-layout-utils@^0.2.0":
version "0.2.0"
resolved "https://registry.yarnpkg.com/@solana/buffer-layout-utils/-/buffer-layout-utils-0.2.0.tgz#b45a6cab3293a2eb7597cceb474f229889d875ca"
@@ -1090,6 +1095,11 @@
resolved "https://registry.yarnpkg.com/@types/content-disposition/-/content-disposition-0.5.5.tgz#650820e95de346e1f84e30667d168c8fd25aa6e3"
integrity sha512-v6LCdKfK6BwcqMo+wYW05rLS12S0ZO0Fl4w1h4aaZMD7bqT3gVUns6FvLJKGZHQmYn3SX55JWGpziwJRwVgutA==
"@types/cookie@^0.4.1":
version "0.4.1"
resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d"
integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==
"@types/cookies@*":
version "0.7.7"
resolved "https://registry.yarnpkg.com/@types/cookies/-/cookies-0.7.7.tgz#7a92453d1d16389c05a5301eef566f34946cfd81"
@@ -1100,6 +1110,13 @@
"@types/keygrip" "*"
"@types/node" "*"
"@types/cors@^2.8.12":
version "2.8.15"
resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.15.tgz#eb143aa2f8807ddd78e83cbff141bbedd91b60ee"
integrity sha512-n91JxbNLD8eQIuXDIChAN1tCKNWCEgpceU9b7ZMbFA+P+Q4yIeh80jizFLEvolRPc1ES0VdwFlGv+kJTSirogw==
dependencies:
"@types/node" "*"
"@types/express-serve-static-core@^4.17.18":
version "4.17.31"
resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz#a1139efeab4e7323834bb0226e62ac019f474b2f"
@@ -1280,6 +1297,13 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.9.tgz#02d013de7058cea16d36168ef2fc653464cfbad4"
integrity sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==
"@types/node@>=10.0.0":
version "20.8.8"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.8.8.tgz#adee050b422061ad5255fc38ff71b2bb96ea2a0e"
integrity sha512-YRsdVxq6OaLfmR9Hy816IMp33xOBjfyOgUd77ehqg96CFywxAPbDbXvAsuN2KVg2HOT8Eh6uAfU+l4WffwPVrQ==
dependencies:
undici-types "~5.25.1"
"@types/node@^12.12.54":
version "12.20.55"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240"
@@ -1438,7 +1462,7 @@ abstract-logging@^2.0.0:
resolved "https://registry.yarnpkg.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839"
integrity sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==
accepts@~1.3.5, accepts@~1.3.8:
accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8:
version "1.3.8"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
@@ -1620,6 +1644,11 @@ base64-js@^1.3.1, base64-js@^1.5.1:
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
base64id@2.0.0, base64id@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6"
integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==
basic-auth@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a"
@@ -1910,7 +1939,12 @@ cookie@0.5.0, cookie@^0.5.0:
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
cors@^2.8.5:
cookie@~0.4.1:
version "0.4.2"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432"
integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==
cors@^2.8.5, cors@~2.8.5:
version "2.8.5"
resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==
@@ -1951,7 +1985,7 @@ debug@2.6.9:
dependencies:
ms "2.0.0"
debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3, debug@^4.3.4:
debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
@@ -2065,6 +2099,38 @@ end-of-stream@^1.4.1:
dependencies:
once "^1.4.0"
engine.io-client@~6.5.2:
version "6.5.2"
resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.5.2.tgz#8709e22c291d4297ae80318d3c8baeae71f0e002"
integrity sha512-CQZqbrpEYnrpGqC07a9dJDz4gePZUgTPMU3NKJPSeQOyw27Tst4Pl3FemKoFGAlHzgZmKjoRmiJvbWfhCXUlIg==
dependencies:
"@socket.io/component-emitter" "~3.1.0"
debug "~4.3.1"
engine.io-parser "~5.2.1"
ws "~8.11.0"
xmlhttprequest-ssl "~2.0.0"
engine.io-parser@~5.2.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.1.tgz#9f213c77512ff1a6cc0c7a86108a7ffceb16fcfb"
integrity sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==
engine.io@~6.5.2:
version "6.5.3"
resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.5.3.tgz#80b0692912cef3a417e1b7433301d6397bf0374b"
integrity sha512-IML/R4eG/pUS5w7OfcDE0jKrljWS9nwnEfsxWCIJF5eO6AHo6+Hlv+lQbdlAYsiJPHzUthLm1RUjnBzWOs45cw==
dependencies:
"@types/cookie" "^0.4.1"
"@types/cors" "^2.8.12"
"@types/node" ">=10.0.0"
accepts "~1.3.4"
base64id "2.0.0"
cookie "~0.4.1"
cors "~2.8.5"
debug "~4.3.1"
engine.io-parser "~5.2.1"
ws "~8.11.0"
enquirer@^2.3.5:
version "2.3.6"
resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d"
@@ -3575,6 +3641,44 @@ snake-case@^3.0.4:
dot-case "^3.0.4"
tslib "^2.0.3"
socket.io-adapter@~2.5.2:
version "2.5.2"
resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz#5de9477c9182fdc171cd8c8364b9a8894ec75d12"
integrity sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==
dependencies:
ws "~8.11.0"
socket.io-client@^4.7.2:
version "4.7.2"
resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.7.2.tgz#f2f13f68058bd4e40f94f2a1541f275157ff2c08"
integrity sha512-vtA0uD4ibrYD793SOIAwlo8cj6haOeMHrGvwPxJsxH7CeIksqJ+3Zc06RvWTIFgiSqx4A3sOnTXpfAEE2Zyz6w==
dependencies:
"@socket.io/component-emitter" "~3.1.0"
debug "~4.3.2"
engine.io-client "~6.5.2"
socket.io-parser "~4.2.4"
socket.io-parser@~4.2.4:
version "4.2.4"
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.4.tgz#c806966cf7270601e47469ddeec30fbdfda44c83"
integrity sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==
dependencies:
"@socket.io/component-emitter" "~3.1.0"
debug "~4.3.1"
socket.io@^4.7.2:
version "4.7.2"
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.7.2.tgz#22557d76c3f3ca48f82e73d68b7add36a22df002"
integrity sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==
dependencies:
accepts "~1.3.4"
base64id "~2.0.0"
cors "~2.8.5"
debug "~4.3.2"
engine.io "~6.5.2"
socket.io-adapter "~2.5.2"
socket.io-parser "~4.2.4"
sonic-boom@^1.0.2:
version "1.4.1"
resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-1.4.1.tgz#d35d6a74076624f12e6f917ade7b9d75e918f53e"
@@ -3826,6 +3930,11 @@ typescript@4.5.4:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.4.tgz#a17d3a0263bf5c8723b9c52f43c5084edf13c2e8"
integrity sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==
undici-types@~5.25.1:
version "5.25.3"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.25.3.tgz#e044115914c85f0bcbb229f346ab739f064998c3"
integrity sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==
unpipe@1.0.0, unpipe@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
@@ -3959,11 +4068,16 @@ ws@^7.4.5:
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591"
integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==
ws@^8.5.0:
ws@^8.5.0, ws@~8.11.0:
version "8.11.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143"
integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==
xmlhttprequest-ssl@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz#91360c86b914e67f44dce769180027c0da618c67"
integrity sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==
xtend@^4.0.0:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"