diff --git a/README.md b/README.md index 6dd246f..6d8bfd3 100644 --- a/README.md +++ b/README.md @@ -88,4 +88,4 @@ stream.latestTradeDetail$.subscribe((v) => {}) - [x] Listen Key expired push - [x] Account balance and position update push - [x] Order update push - - [ ] Configuration updates such as leverage and margin mode + - [x] Configuration updates such as leverage and margin mode diff --git a/src/bingx-socket/bingx-account-socket-config-update.spec.ts b/src/bingx-socket/bingx-account-socket-config-update.spec.ts new file mode 100644 index 0000000..3ea79b5 --- /dev/null +++ b/src/bingx-socket/bingx-account-socket-config-update.spec.ts @@ -0,0 +1,86 @@ +import { Server, WebSocket } from 'ws'; +import { getPortFree } from 'bingx-api/get-port'; +import { ApiAccount } from 'bingx-api/bingx/account/api-account'; +import { BingxAccountSocketStream } from 'bingx-api/bingx-socket/bingx-account-socket-stream'; +import * as zlib from 'zlib'; +import { AccountWebsocketEventType } from 'bingx-api/bingx-socket/events'; + +describe('bingx account socket configuration update', () => { + let wss: Server; + let port: number; + let stream: BingxAccountSocketStream | undefined; + const sockets: WebSocket[] = []; + + const sendToSocket = (socket: WebSocket, msg: string) => { + zlib.gzip(msg, (err, result) => { + socket.send(result); + }); + }; + + beforeEach(async () => { + port = await getPortFree(); + wss = new Server({ port }); + await new Promise((resolve) => { + wss.on('listening', resolve); + wss.on('connection', (ws) => { + sockets[0] = ws; + ws.on('close', () => { + sockets.splice(0, 1); + }); + }); + }); + }); + + afterEach((done) => { + stream?.disconnect(); + wss.close(() => { + sockets.splice(0, sockets.length); + done(); + }); + }); + + it('emits account configuration update events', (done) => { + const requestExecutorMock = { + execute: jest.fn().mockResolvedValueOnce({ listenKey: '123' }), + }; + const account = new ApiAccount('xxx', 'xxx'); + + wss.once('connection', (socket) => { + setTimeout(() => { + sendToSocket( + socket, + JSON.stringify({ + e: AccountWebsocketEventType.ACCOUNT_CONFIG_UPDATE, + E: 1676603102163, + ac: { + s: 'BTC-USDT', + l: 12, + S: 9, + mt: 'cross', + }, + }), + ); + }, 10); + }); + + stream = new BingxAccountSocketStream(account, { + requestExecutor: requestExecutorMock, + url: new URL('', `ws://0.0.0.0:${port}`), + }); + + stream.accountConfigurationUpdate$.subscribe((event) => { + expect(event).toStrictEqual({ + e: AccountWebsocketEventType.ACCOUNT_CONFIG_UPDATE, + E: '1676603102163', + ac: { + s: 'BTC-USDT', + l: '12', + S: '9', + mt: 'cross', + }, + }); + expect(requestExecutorMock.execute).toHaveBeenCalledTimes(1); + done(); + }); + }); +}); diff --git a/src/bingx-socket/bingx-account-socket-stream.ts b/src/bingx-socket/bingx-account-socket-stream.ts index 9e85e9b..14969e6 100644 --- a/src/bingx-socket/bingx-account-socket-stream.ts +++ b/src/bingx-socket/bingx-account-socket-stream.ts @@ -12,6 +12,7 @@ import { BingxWebsocketSerializer } from 'bingx-api/bingx-socket/bingx-websocket import { HeartbeatInterface } from 'bingx-api/bingx-socket/interfaces/heartbeat.interface'; import { filterAndEmitToSubject } from 'bingx-api/bingx-socket/operators/filter-and-emit-to-subject'; import { + AccountConfigurationUpdateEvent, AccountBalanceAndPositionPushEvent, AccountOrderUpdatePushEvent, AccountWebSocketEvent, @@ -36,6 +37,8 @@ export class BingxAccountSocketStream { new Subject(); public readonly accountOrderUpdatePushEvent$ = new Subject(); + public readonly accountConfigurationUpdate$ = + new Subject(); constructor( private readonly account: AccountInterface, @@ -98,6 +101,11 @@ export class BingxAccountSocketStream { event.e === AccountWebsocketEventType.ORDER_TRADE_UPDATE, this.accountOrderUpdatePushEvent$, ), + filterAndEmitToSubject( + (event): event is AccountConfigurationUpdateEvent => + event.e === AccountWebsocketEventType.ACCOUNT_CONFIG_UPDATE, + this.accountConfigurationUpdate$, + ), ) .subscribe(); diff --git a/src/bingx-socket/events/account-websocket-events.ts b/src/bingx-socket/events/account-websocket-events.ts index b42b8ef..a3acec1 100644 --- a/src/bingx-socket/events/account-websocket-events.ts +++ b/src/bingx-socket/events/account-websocket-events.ts @@ -60,6 +60,7 @@ export type EntryPrice = number; export type UnrealizedProfitAndLossPosition = number; export type MarginMode = string; export type IsolatedPositionMargin = number; +export type AccountConfigLeverage = string | number; /** * Relates to order update events @@ -140,3 +141,16 @@ export interface AccountOrderUpdatePushEvent extends AccountWebSocketEvent { E: EventTimeInMilliseconds; o: AccountWebSocketOrder; } + +export interface AccountConfiguration { + s: TradingPair; + l: AccountConfigLeverage; + S: AccountConfigLeverage; + mt: MarginMode; +} + +export interface AccountConfigurationUpdateEvent extends AccountWebSocketEvent { + e: AccountWebsocketEventType.ACCOUNT_CONFIG_UPDATE; + E: EventTimeInMilliseconds; + ac: AccountConfiguration; +}