From 12a386094979eb71486e7b59e3f1780b9f6f9032 Mon Sep 17 00:00:00 2001 From: Codex Bounty Agent Date: Thu, 14 May 2026 09:36:22 +0800 Subject: [PATCH] feat: add listen key extend and delete endpoints --- README.md | 4 +- .../services/listen-key.service.spec.ts | 54 +++++++++++++++++++ .../services/listen-key.service.ts | 20 +++++++ .../bingx-delete-listen-key-endpoint.spec.ts | 22 ++++++++ .../bingx-delete-listen-key-endpoint.ts | 33 ++++++++++++ .../bingx-extend-listen-key-endpoint.spec.ts | 22 ++++++++ .../bingx-extend-listen-key-endpoint.ts | 12 ++--- src/bingx/endpoints/index.ts | 2 + src/bingx/interfaces/websocket-event.ts | 1 - 9 files changed, 160 insertions(+), 10 deletions(-) create mode 100644 src/bingx-client/services/listen-key.service.spec.ts create mode 100644 src/bingx/endpoints/bingx-delete-listen-key-endpoint.spec.ts create mode 100644 src/bingx/endpoints/bingx-delete-listen-key-endpoint.ts create mode 100644 src/bingx/endpoints/bingx-extend-listen-key-endpoint.spec.ts diff --git a/README.md b/README.md index 6dd246f..c4a52a7 100644 --- a/README.md +++ b/README.md @@ -77,8 +77,8 @@ stream.latestTradeDetail$.subscribe((v) => {}) - [ ] Query historical transaction orders * Listen Key - [x] Generate Listen Key - - [ ] Extend Listen Key Validity period - - [ ] Delete Listen Key + - [x] Extend Listen Key Validity period + - [x] Delete Listen Key * Socket API * Market Data - [ ] Subscribe Market Depth Data diff --git a/src/bingx-client/services/listen-key.service.spec.ts b/src/bingx-client/services/listen-key.service.spec.ts new file mode 100644 index 0000000..6c477e2 --- /dev/null +++ b/src/bingx-client/services/listen-key.service.spec.ts @@ -0,0 +1,54 @@ +import { ApiAccount } from 'bingx-api/bingx/account/api-account'; +import { BingxDeleteListenKeyEndpoint } from 'bingx-api/bingx/endpoints/bingx-delete-listen-key-endpoint'; +import { BingxExtendListenKeyEndpoint } from 'bingx-api/bingx/endpoints/bingx-extend-listen-key-endpoint'; +import { BingxGenerateListenKeyEndpoint } from 'bingx-api/bingx/endpoints/bingx-generate-listen-key-endpoint'; +import { ListenKeyService } from 'bingx-api/bingx-client/services/listen-key.service'; + +describe('ListenKeyService', () => { + const account = new ApiAccount('api-key', 'secret-key'); + + it('executes generate listen key endpoint', async () => { + const requestExecutorMock = { + execute: jest.fn().mockResolvedValue({ listenKey: 'listen-key-123' }), + }; + const service = new ListenKeyService(requestExecutorMock); + + await expect(service.generateListenKey(account)).resolves.toEqual({ + listenKey: 'listen-key-123', + }); + + expect(requestExecutorMock.execute).toHaveBeenCalledWith( + expect.any(BingxGenerateListenKeyEndpoint), + ); + }); + + it('executes extend listen key endpoint', async () => { + const requestExecutorMock = { + execute: jest.fn().mockResolvedValue(undefined), + }; + const service = new ListenKeyService(requestExecutorMock); + + await expect( + service.extendListenKey('listen-key-123', account), + ).resolves.toBeUndefined(); + + expect(requestExecutorMock.execute).toHaveBeenCalledWith( + expect.any(BingxExtendListenKeyEndpoint), + ); + }); + + it('executes delete listen key endpoint', async () => { + const requestExecutorMock = { + execute: jest.fn().mockResolvedValue(undefined), + }; + const service = new ListenKeyService(requestExecutorMock); + + await expect( + service.deleteListenKey('listen-key-123', account), + ).resolves.toBeUndefined(); + + expect(requestExecutorMock.execute).toHaveBeenCalledWith( + expect.any(BingxDeleteListenKeyEndpoint), + ); + }); +}); diff --git a/src/bingx-client/services/listen-key.service.ts b/src/bingx-client/services/listen-key.service.ts index 6535d93..656242e 100644 --- a/src/bingx-client/services/listen-key.service.ts +++ b/src/bingx-client/services/listen-key.service.ts @@ -1,4 +1,6 @@ import { AccountInterface } from 'bingx-api/bingx/account/account.interface'; +import { BingxDeleteListenKeyEndpoint } from 'bingx-api/bingx/endpoints/bingx-delete-listen-key-endpoint'; +import { BingxExtendListenKeyEndpoint } from 'bingx-api/bingx/endpoints/bingx-extend-listen-key-endpoint'; import { BingxGenerateListenKeyEndpoint } from 'bingx-api/bingx/endpoints/bingx-generate-listen-key-endpoint'; import { BingxGenerateListenKeyResponse } from 'bingx-api/bingx/endpoints/bingx-generate-listen-key-response'; import { RequestExecutorInterface } from 'bingx-api/bingx/request-executor/request-executor.interface'; @@ -13,4 +15,22 @@ export class ListenKeyService { new BingxGenerateListenKeyEndpoint(account), ); } + + async extendListenKey( + listenKey: string, + account: AccountInterface, + ): Promise { + return this.requestExecutor.execute( + new BingxExtendListenKeyEndpoint(listenKey, account), + ); + } + + async deleteListenKey( + listenKey: string, + account: AccountInterface, + ): Promise { + return this.requestExecutor.execute( + new BingxDeleteListenKeyEndpoint(listenKey, account), + ); + } } diff --git a/src/bingx/endpoints/bingx-delete-listen-key-endpoint.spec.ts b/src/bingx/endpoints/bingx-delete-listen-key-endpoint.spec.ts new file mode 100644 index 0000000..fa177dc --- /dev/null +++ b/src/bingx/endpoints/bingx-delete-listen-key-endpoint.spec.ts @@ -0,0 +1,22 @@ +import { ApiAccount } from 'bingx-api/bingx/account/api-account'; +import { BingxDeleteListenKeyEndpoint } from 'bingx-api/bingx/endpoints/bingx-delete-listen-key-endpoint'; + +describe('BingxDeleteListenKeyEndpoint', () => { + const endpoint = new BingxDeleteListenKeyEndpoint( + 'listen-key-123', + new ApiAccount('api-key', 'secret-key'), + ); + + it('describes the delete listen key endpoint', () => { + expect(endpoint.method()).toBe('delete'); + expect(endpoint.path()).toBe('/openApi/user/auth/userDataStream'); + }); + + it('passes listen key as a signed parameter', () => { + expect(endpoint.parameters().asRecord()).toEqual( + expect.objectContaining({ + listenKey: 'listen-key-123', + }), + ); + }); +}); diff --git a/src/bingx/endpoints/bingx-delete-listen-key-endpoint.ts b/src/bingx/endpoints/bingx-delete-listen-key-endpoint.ts new file mode 100644 index 0000000..82652c4 --- /dev/null +++ b/src/bingx/endpoints/bingx-delete-listen-key-endpoint.ts @@ -0,0 +1,33 @@ +import { AccountInterface } from 'bingx-api/bingx/account/account.interface'; +import { DefaultSignatureParameters } from 'bingx-api/bingx/account/default-signature-parameters'; +import { SignatureParametersInterface } from 'bingx-api/bingx/account/signature-parameters.interface'; +import { Endpoint } from 'bingx-api/bingx/endpoints/endpoint'; +import { EndpointInterface } from 'bingx-api/bingx/endpoints/endpoint.interface'; + +export class BingxDeleteListenKeyEndpoint + extends Endpoint + implements EndpointInterface +{ + constructor( + private readonly listenKey: string, + account: AccountInterface, + ) { + super(account); + } + + method(): 'get' | 'post' | 'put' | 'patch' | 'delete' { + return 'delete'; + } + + parameters(): SignatureParametersInterface { + return new DefaultSignatureParameters({ + listenKey: this.listenKey, + }); + } + + path(): string { + return '/openApi/user/auth/userDataStream'; + } + + readonly t!: R; +} diff --git a/src/bingx/endpoints/bingx-extend-listen-key-endpoint.spec.ts b/src/bingx/endpoints/bingx-extend-listen-key-endpoint.spec.ts new file mode 100644 index 0000000..62e1105 --- /dev/null +++ b/src/bingx/endpoints/bingx-extend-listen-key-endpoint.spec.ts @@ -0,0 +1,22 @@ +import { ApiAccount } from 'bingx-api/bingx/account/api-account'; +import { BingxExtendListenKeyEndpoint } from 'bingx-api/bingx/endpoints/bingx-extend-listen-key-endpoint'; + +describe('BingxExtendListenKeyEndpoint', () => { + const endpoint = new BingxExtendListenKeyEndpoint( + 'listen-key-123', + new ApiAccount('api-key', 'secret-key'), + ); + + it('describes the extend listen key endpoint', () => { + expect(endpoint.method()).toBe('put'); + expect(endpoint.path()).toBe('/openApi/user/auth/userDataStream'); + }); + + it('passes listen key as a signed parameter', () => { + expect(endpoint.parameters().asRecord()).toEqual( + expect.objectContaining({ + listenKey: 'listen-key-123', + }), + ); + }); +}); diff --git a/src/bingx/endpoints/bingx-extend-listen-key-endpoint.ts b/src/bingx/endpoints/bingx-extend-listen-key-endpoint.ts index a71c3b4..32a4ca4 100644 --- a/src/bingx/endpoints/bingx-extend-listen-key-endpoint.ts +++ b/src/bingx/endpoints/bingx-extend-listen-key-endpoint.ts @@ -1,10 +1,8 @@ -import { - AccountInterface, - DefaultSignatureParameters, - Endpoint, - EndpointInterface, - SignatureParametersInterface, -} from 'bingx-api/bingx'; +import { AccountInterface } from 'bingx-api/bingx/account/account.interface'; +import { DefaultSignatureParameters } from 'bingx-api/bingx/account/default-signature-parameters'; +import { SignatureParametersInterface } from 'bingx-api/bingx/account/signature-parameters.interface'; +import { Endpoint } from 'bingx-api/bingx/endpoints/endpoint'; +import { EndpointInterface } from 'bingx-api/bingx/endpoints/endpoint.interface'; export class BingxExtendListenKeyEndpoint extends Endpoint diff --git a/src/bingx/endpoints/index.ts b/src/bingx/endpoints/index.ts index 6866f8b..c82fc6a 100644 --- a/src/bingx/endpoints/index.ts +++ b/src/bingx/endpoints/index.ts @@ -2,6 +2,8 @@ export * from './bingx-cancel-all-orders-endpoint'; export * from './bingx-close-all-positions-endpoint'; export * from './bingx-generate-listen-key-endpoint'; export * from './bingx-generate-listen-key-response'; +export * from './bingx-extend-listen-key-endpoint'; +export * from './bingx-delete-listen-key-endpoint'; export * from './bingx-get-perpetual-swap-account-asset-endpoint'; export * from './bingx-get-server-time-endpoint'; export * from './bingx-perpetual-swap-positions-endpoint'; diff --git a/src/bingx/interfaces/websocket-event.ts b/src/bingx/interfaces/websocket-event.ts index a414299..3be37b3 100644 --- a/src/bingx/interfaces/websocket-event.ts +++ b/src/bingx/interfaces/websocket-event.ts @@ -1,4 +1,3 @@ -import { OrderTypeEnum } from 'bingx-api/bingx/enums/order-type.enum'; import { OrderSideEnum } from 'bingx-api/bingx/enums/order-side.enum'; import { OrderStatusEnum } from 'bingx-api/bingx/enums/order-status.enum'; import { OrderPositionSideEnum } from 'bingx-api/bingx/enums/order-position-side.enum';