diff --git a/README.md b/README.md index 6dd246f..53e50a0 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ stream.latestTradeDetail$.subscribe((v) => {}) * Listen Key - [x] Generate Listen Key - [ ] Extend Listen Key Validity period - - [ ] Delete Listen Key + - [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..055d28d --- /dev/null +++ b/src/bingx-client/services/listen-key.service.spec.ts @@ -0,0 +1,40 @@ +import { ApiAccount } from 'bingx-api/bingx/account/api-account'; +import { BingxDeleteListenKeyEndpoint } from 'bingx-api/bingx/endpoints/bingx-delete-listen-key-endpoint'; +import { BingxGenerateListenKeyEndpoint } from 'bingx-api/bingx/endpoints/bingx-generate-listen-key-endpoint'; +import { RequestExecutorInterface } from 'bingx-api/bingx/request-executor/request-executor.interface'; +import { ListenKeyService } from 'bingx-api/bingx-client/services/listen-key.service'; + +describe('listen key service', () => { + const account = new ApiAccount('api-key', 'secret-key'); + let requestExecutor: jest.Mocked; + let service: ListenKeyService; + + beforeEach(() => { + requestExecutor = { + execute: jest.fn(), + }; + service = new ListenKeyService(requestExecutor); + }); + + it('must generate listen key', async () => { + requestExecutor.execute.mockResolvedValueOnce({ listenKey: 'listen-key' }); + + await expect(service.generateListenKey(account)).resolves.toStrictEqual({ + listenKey: 'listen-key', + }); + expect(requestExecutor.execute).toHaveBeenCalledWith( + expect.any(BingxGenerateListenKeyEndpoint), + ); + }); + + it('must delete listen key', async () => { + requestExecutor.execute.mockResolvedValueOnce(undefined); + + await expect( + service.deleteListenKey('listen-key', account), + ).resolves.toBeUndefined(); + expect(requestExecutor.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..5d04890 100644 --- a/src/bingx-client/services/listen-key.service.ts +++ b/src/bingx-client/services/listen-key.service.ts @@ -1,4 +1,5 @@ import { AccountInterface } from 'bingx-api/bingx/account/account.interface'; +import { BingxDeleteListenKeyEndpoint } from 'bingx-api/bingx/endpoints/bingx-delete-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 +14,13 @@ export class ListenKeyService { new BingxGenerateListenKeyEndpoint(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..000da66 --- /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('bingx delete listen key endpoint', () => { + const account = new ApiAccount('api-key', 'secret-key'); + const endpoint = new BingxDeleteListenKeyEndpoint('listen-key', account); + + it('must describe delete listen key request', () => { + expect(endpoint.method()).toBe('delete'); + expect(endpoint.path()).toBe('/openApi/user/auth/userDataStream'); + expect(endpoint.parameters().asRecord()).toMatchObject({ + listenKey: 'listen-key', + }); + }); + + it('must include signed endpoint details', () => { + expect(endpoint.apiKey().asHeader()).toStrictEqual({ + 'X-BX-APIKEY': 'api-key', + }); + expect(endpoint.signature().toString()).toEqual(expect.any(String)); + }); +}); 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/index.ts b/src/bingx/endpoints/index.ts index 6866f8b..eab3777 100644 --- a/src/bingx/endpoints/index.ts +++ b/src/bingx/endpoints/index.ts @@ -1,5 +1,6 @@ export * from './bingx-cancel-all-orders-endpoint'; export * from './bingx-close-all-positions-endpoint'; +export * from './bingx-delete-listen-key-endpoint'; export * from './bingx-generate-listen-key-endpoint'; export * from './bingx-generate-listen-key-response'; export * from './bingx-get-perpetual-swap-account-asset-endpoint';