diff --git a/README.md b/README.md index 6dd246f..e816816 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ stream.latestTradeDetail$.subscribe((v) => {}) - [ ] Cancel a Batch of Orders - [ ] Cancel All Orders - [ ] Query all current pending orders - - [ ] Query Order + - [x] Query Order - [ ] Query Margin Mode - [ ] Switch Margin Mode - [ ] Query Leverage diff --git a/src/bingx-client/services/trade.service.spec.ts b/src/bingx-client/services/trade.service.spec.ts new file mode 100644 index 0000000..b137c63 --- /dev/null +++ b/src/bingx-client/services/trade.service.spec.ts @@ -0,0 +1,68 @@ +import { AccountInterface } from 'bingx-api/bingx/account/account.interface'; +import { EndpointInterface } from 'bingx-api/bingx/endpoints/endpoint.interface'; +import { BingxQueryOrderEndpoint } from 'bingx-api/bingx/endpoints/bingx-query-order-endpoint'; +import { RequestExecutorInterface } from 'bingx-api/bingx/request-executor/request-executor.interface'; +import { TradeService } from 'bingx-api/bingx-client/services/trade.service'; + +class TestRequestExecutor implements RequestExecutorInterface { + public endpoint?: EndpointInterface; + + execute(endpoint: EndpointInterface): Promise { + this.endpoint = endpoint; + return Promise.resolve({} as T); + } +} + +const account: AccountInterface = { + getApiKey: () => 'api-key', + sign: () => ({ + toString: () => 'signature', + secretKey: () => 'secret-key', + }), +}; + +describe('TradeService', () => { + describe('queryOrder', () => { + it('dispatches the query order endpoint', async () => { + const executor = new TestRequestExecutor(); + const service = new TradeService(executor); + + await service.queryOrder( + { + symbol: 'OP-USDT', + orderId: '1736012449498123456', + recvWindow: '5000', + }, + account, + ); + + const endpoint = executor.endpoint as BingxQueryOrderEndpoint; + const parameters = endpoint.parameters().asRecord(); + + expect(endpoint).toBeInstanceOf(BingxQueryOrderEndpoint); + expect(endpoint.method()).toBe('get'); + expect(endpoint.path()).toBe('/openApi/swap/v2/trade/order'); + expect(parameters).toMatchObject({ + symbol: 'OP-USDT', + orderId: '1736012449498123456', + recvWindow: '5000', + }); + expect(parameters.timestamp).toBeDefined(); + }); + + it('supports querying by client order id', async () => { + const endpoint = new BingxQueryOrderEndpoint( + { + symbol: 'BTC-USDT', + clientOrderId: 'client-order-id', + }, + account, + ); + + expect(endpoint.parameters().asRecord()).toMatchObject({ + symbol: 'BTC-USDT', + clientOrderId: 'client-order-id', + }); + }); + }); +}); diff --git a/src/bingx-client/services/trade.service.ts b/src/bingx-client/services/trade.service.ts index 65fa5bd..7f40ef0 100644 --- a/src/bingx-client/services/trade.service.ts +++ b/src/bingx-client/services/trade.service.ts @@ -12,6 +12,8 @@ import { BingxSwitchLeverageEndpoint } from 'bingx-api/bingx/endpoints/bingx-swi import { OrderPositionSideEnum } from 'bingx-api/bingx'; import { BingxUserHistoryOrdersEndpoint } from 'bingx-api/bingx/endpoints/bingx-user-history-orders-endpoint'; import { BingxCancelOrderEndpoint } from 'bingx-api/bingx/endpoints/bingx-cancel-order-endpoint'; +import { QueryOrderInterface } from 'bingx-api/bingx/interfaces/query-order.interface'; +import { BingxQueryOrderEndpoint } from 'bingx-api/bingx/endpoints/bingx-query-order-endpoint'; export class TradeService { constructor(private readonly requestExecutor: RequestExecutorInterface) {} @@ -44,6 +46,15 @@ export class TradeService { ); } + public async queryOrder( + order: QueryOrderInterface, + account: AccountInterface, + ) { + return this.requestExecutor.execute( + new BingxQueryOrderEndpoint(order, account), + ); + } + public async getUserHistoryOrders( symbol: string, limit: number, diff --git a/src/bingx/endpoints/bingx-query-order-endpoint.ts b/src/bingx/endpoints/bingx-query-order-endpoint.ts new file mode 100644 index 0000000..76759bb --- /dev/null +++ b/src/bingx/endpoints/bingx-query-order-endpoint.ts @@ -0,0 +1,55 @@ +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 { BingxResponse } from 'bingx-api/bingx/interfaces/bingx-response'; +import { BingxOrderInterface } from 'bingx-api/bingx/interfaces/bingx-order.interface'; +import { QueryOrderInterface } from 'bingx-api/bingx/interfaces/query-order.interface'; +import { Endpoint } from 'bingx-api/bingx/endpoints/endpoint'; +import { EndpointInterface } from 'bingx-api/bingx/endpoints/endpoint.interface'; + +export interface BingxQueryOrderResponseInterface { + order: BingxOrderInterface & { + clientOrderId?: string; + workingType?: string; + closePosition?: string; + stopGuaranteed?: boolean; + triggerOrderId?: number; + }; +} + +export class BingxQueryOrderEndpoint + extends Endpoint + implements EndpointInterface> +{ + constructor( + private readonly order: QueryOrderInterface, + account: AccountInterface, + ) { + super(account); + } + + readonly t!: BingxResponse; + + method(): 'get' | 'post' | 'put' | 'patch' | 'delete' { + return 'get'; + } + + parameters(): SignatureParametersInterface { + return new DefaultSignatureParameters({ + symbol: this.order.symbol, + ...(this.order.orderId === undefined + ? {} + : { orderId: this.order.orderId }), + ...(this.order.clientOrderId === undefined + ? {} + : { clientOrderId: this.order.clientOrderId }), + ...(this.order.recvWindow === undefined + ? {} + : { recvWindow: this.order.recvWindow }), + }); + } + + path(): string { + return '/openApi/swap/v2/trade/order'; + } +} diff --git a/src/bingx/endpoints/index.ts b/src/bingx/endpoints/index.ts index 6866f8b..3b59c09 100644 --- a/src/bingx/endpoints/index.ts +++ b/src/bingx/endpoints/index.ts @@ -7,6 +7,7 @@ export * from './bingx-get-server-time-endpoint'; export * from './bingx-perpetual-swap-positions-endpoint'; export * from './bingx-request.interface'; export * from './bingx-response.interface'; +export * from './bingx-query-order-endpoint'; export * from './bingx-trade-order-endpoint'; export * from './endpoint.interface'; export * from './endpoint'; diff --git a/src/bingx/interfaces/query-order.interface.ts b/src/bingx/interfaces/query-order.interface.ts index 4ea90dd..c5380d8 100644 --- a/src/bingx/interfaces/query-order.interface.ts +++ b/src/bingx/interfaces/query-order.interface.ts @@ -1,4 +1,6 @@ export interface QueryOrderInterface { symbol: string; - orderId: string; + orderId?: string; + clientOrderId?: string; + recvWindow?: string; } 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';