kucoin-api 2.1.19 → 2.1.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/llms.txt CHANGED
@@ -1681,6 +1681,8 @@ export async function signMessage(
1681
1681
  method: SignEncodeMethod,
1682
1682
  algorithm: SignAlgorithm,
1683
1683
  ): Promise<string>
1684
+ ⋮----
1685
+ export function checkWebCryptoAPISupported()
1684
1686
 
1685
1687
  ================
1686
1688
  File: src/types/request/spot-margin-trading.ts
@@ -3457,919 +3459,1105 @@ File: tsconfig.json
3457
3459
  }
3458
3460
 
3459
3461
  ================
3460
- File: src/types/request/spot-account.ts
3462
+ File: src/lib/BaseWSClient.ts
3461
3463
  ================
3462
- export interface GetBalancesRequest {
3463
- currency?: string;
3464
- type?: 'main' | 'trade';
3465
- }
3464
+ import EventEmitter from 'events';
3465
+ import WebSocket from 'isomorphic-ws';
3466
3466
  ⋮----
3467
- export interface GetSpotTransactionsRequest {
3468
- currency?: string;
3469
- direction?: 'in' | 'out';
3470
- bizType?:
3471
- | 'DEPOSIT'
3472
- | 'WITHDRAW'
3473
- | 'TRANSFER'
3474
- | 'SUB_TRANSFER'
3475
- | 'TRADE_EXCHANGE'
3476
- | 'MARGIN_EXCHANGE'
3477
- | 'KUCOIN_BONUS'
3478
- | 'BROKER_TRANSFER'
3479
- | 'REBATE';
3480
- startAt?: number;
3481
- endAt?: number;
3482
- currentPage?: number;
3483
- pageSize?: number;
3484
- }
3467
+ import {
3468
+ WebsocketClientOptions,
3469
+ WSClientConfigurableOptions,
3470
+ } from '../types/websockets/client.js';
3471
+ import { WsOperation } from '../types/websockets/requests.js';
3472
+ import { WS_LOGGER_CATEGORY } from '../WebsocketClient.js';
3473
+ import { checkWebCryptoAPISupported } from './webCryptoAPI.js';
3474
+ import { DefaultLogger } from './websocket/logger.js';
3475
+ import {
3476
+ isMessageEvent,
3477
+ MessageEventLike,
3478
+ safeTerminateWs,
3479
+ WsTopicRequest,
3480
+ WsTopicRequestOrStringTopic,
3481
+ } from './websocket/websocket-util.js';
3482
+ import { WsStore } from './websocket/WsStore.js';
3483
+ import {
3484
+ WSConnectedResult,
3485
+ WsConnectionStateEnum,
3486
+ } from './websocket/WsStore.types.js';
3485
3487
  ⋮----
3486
- export interface AccountHFTransactionsRequest {
3487
- currency?: string;
3488
- direction?: 'in' | 'out';
3489
- bizType?:
3490
- | 'TRANSFER'
3491
- | 'TRADE_EXCHANGE'
3492
- | 'RETURNED_FEES'
3493
- | 'DEDUCTION_FEES'
3494
- | 'OTHER';
3495
- lastId?: number;
3496
- limit?: number;
3497
- startAt?: number;
3498
- endAt?: number;
3488
+ interface WSClientEventMap<WsKey extends string> {
3489
+ /** Connection opened. If this connection was previously opened and reconnected, expect the reconnected event instead */
3490
+ open: (evt: { wsKey: WsKey; event: any }) => void;
3491
+ /** Reconnecting a dropped connection */
3492
+ reconnect: (evt: { wsKey: WsKey; event: any }) => void;
3493
+ /** Successfully reconnected a connection that dropped */
3494
+ reconnected: (evt: { wsKey: WsKey; event: any }) => void;
3495
+ /** Connection closed */
3496
+ close: (evt: { wsKey: WsKey; event: any }) => void;
3497
+ /** Received reply to websocket command (e.g. after subscribing to topics) */
3498
+ response: (response: any & { wsKey: WsKey }) => void;
3499
+ /** Received data for topic */
3500
+ update: (response: any & { wsKey: WsKey }) => void;
3501
+ /** Exception from ws client OR custom listeners (e.g. if you throw inside your event handler) */
3502
+ exception: (response: any & { wsKey: WsKey }) => void;
3503
+ error: (response: any & { wsKey: WsKey }) => void;
3504
+ /** Confirmation that a connection successfully authenticated */
3505
+ authenticated: (event: { wsKey: WsKey; event: any }) => void;
3499
3506
  }
3500
3507
  ⋮----
3501
- export interface AccountHFMarginTransactionsRequest {
3502
- currency?: string;
3503
- direction?: 'in' | 'out';
3504
- bizType?:
3505
- | 'TRANSFER'
3506
- | 'MARGIN_EXCHANGE'
3507
- | 'ISOLATED_EXCHANGE'
3508
- | 'LIQUIDATION'
3509
- | 'ASSERT_RETURN';
3510
- lastId?: number;
3511
- limit?: number;
3512
- startAt?: number;
3513
- endAt?: number;
3514
- }
3508
+ /** Connection opened. If this connection was previously opened and reconnected, expect the reconnected event instead */
3515
3509
  ⋮----
3516
- export interface CreateSubAccountRequest {
3517
- password: string;
3518
- remarks?: string;
3519
- subName: string;
3520
- access: string;
3521
- }
3510
+ /** Reconnecting a dropped connection */
3522
3511
  ⋮----
3523
- export interface CreateSubAccountAPIRequest {
3524
- subName: string;
3525
- passphrase: string;
3526
- remark: string;
3527
- permission?: string;
3528
- ipWhitelist?: string;
3529
- expire?: string;
3530
- }
3512
+ /** Successfully reconnected a connection that dropped */
3531
3513
  ⋮----
3532
- export interface UpdateSubAccountAPIRequest {
3533
- subName: string;
3534
- apiKey: string;
3535
- passphrase: string;
3536
- permission?: string;
3537
- ipWhitelist?: string;
3538
- expire?: string;
3539
- }
3514
+ /** Connection closed */
3540
3515
  ⋮----
3541
- export interface DeleteSubAccountAPIRequest {
3542
- apiKey: string;
3543
- passphrase: string;
3544
- subName: string;
3545
- }
3546
-
3547
- ================
3548
- File: src/types/response/spot-account.ts
3549
- ================
3550
- export interface SpotAccountSummary {
3551
- level: number;
3552
- subQuantity: number;
3553
- spotSubQuantity: number;
3554
- marginSubQuantity: number;
3555
- futuresSubQuantity: number;
3556
- optionSubQuantity: number;
3557
- maxSubQuantity: number;
3558
- maxDefaultSubQuantity: number;
3559
- maxSpotSubQuantity: number;
3560
- maxMarginSubQuantity: number;
3561
- maxFuturesSubQuantity: number;
3562
- maxOptionSubQuantity: number;
3563
- }
3516
+ /** Received reply to websocket command (e.g. after subscribing to topics) */
3564
3517
  ⋮----
3565
- export interface Balances {
3566
- id: string;
3567
- currency: string;
3568
- type: 'main' | 'trade';
3569
- balance: string;
3570
- available: string;
3571
- holds: string;
3572
- }
3518
+ /** Received data for topic */
3573
3519
  ⋮----
3574
- export interface Account {
3575
- currency: string;
3576
- balance: string;
3577
- available: string;
3578
- holds: string;
3579
- }
3520
+ /** Exception from ws client OR custom listeners (e.g. if you throw inside your event handler) */
3580
3521
  ⋮----
3581
- export interface SpotAccountTransaction {
3582
- id: string;
3583
- currency: string;
3584
- amount: string;
3585
- fee: string;
3586
- tax: string;
3587
- balance: string;
3588
- accountType: string; // 'TRADE_HF'
3589
- bizType: string;
3590
- direction: 'out' | 'in';
3591
- createdAt: string;
3592
- context: string;
3522
+ /** Confirmation that a connection successfully authenticated */
3523
+ ⋮----
3524
+ export interface EmittableEvent<TEvent = any> {
3525
+ eventType:
3526
+ | 'response'
3527
+ | 'update'
3528
+ | 'exception'
3529
+ | 'authenticated'
3530
+ | 'connectionReady'; // tied to "requireConnectionReadyConfirmation"
3531
+ event: TEvent;
3593
3532
  }
3594
3533
  ⋮----
3595
- accountType: string; // 'TRADE_HF'
3534
+ | 'connectionReady'; // tied to "requireConnectionReadyConfirmation"
3596
3535
  ⋮----
3597
- export interface SpotAccountTransactions {
3598
- currentPage: number;
3599
- pageSize: number;
3600
- totalNum: number;
3601
- totalPage: number;
3602
- items: SpotAccountTransaction[];
3536
+ // Type safety for on and emit handlers: https://stackoverflow.com/a/61609010/880837
3537
+ export interface BaseWebsocketClient<TWSKey extends string> {
3538
+ on<U extends keyof WSClientEventMap<TWSKey>>(
3539
+ event: U,
3540
+ listener: WSClientEventMap<TWSKey>[U],
3541
+ ): this;
3542
+
3543
+ emit<U extends keyof WSClientEventMap<TWSKey>>(
3544
+ event: U,
3545
+ ...args: Parameters<WSClientEventMap<TWSKey>[U]>
3546
+ ): boolean;
3603
3547
  }
3604
3548
  ⋮----
3605
- export interface AccountHFMarginTransactions {
3606
- id: string;
3607
- currency: string;
3608
- amount: string;
3609
- fee: string;
3610
- balance: string;
3611
- accountType: 'MARGIN_V2' | 'ISOLATED_V2';
3612
- bizType:
3613
- | 'TRANSFER'
3614
- | 'MARGIN_EXCHANGE'
3615
- | 'ISOLATED_EXCHANGE'
3616
- | 'LIQUIDATION'
3617
- | 'ASSERT_RETURN';
3618
- direction: 'out' | 'in';
3619
- createdAt: string;
3620
- tax: string;
3621
- context: string;
3622
- }
3549
+ on<U extends keyof WSClientEventMap<TWSKey>>(
3550
+ event: U,
3551
+ listener: WSClientEventMap<TWSKey>[U],
3552
+ ): this;
3553
+ ⋮----
3554
+ emit<U extends keyof WSClientEventMap<TWSKey>>(
3555
+ event: U,
3556
+ ...args: Parameters<WSClientEventMap<TWSKey>[U]>
3557
+ ): boolean;
3623
3558
  ⋮----
3624
3559
  /**
3560
+ * Users can conveniently pass topics as strings or objects (object has topic name + optional params).
3625
3561
  *
3626
- * Sub-Account
3627
- *
3562
+ * This method normalises topics into objects (object has topic name + optional params).
3628
3563
  */
3564
+ function getNormalisedTopicRequests(
3565
+ wsTopicRequests: WsTopicRequestOrStringTopic<string>[],
3566
+ ): WsTopicRequest<string>[]
3629
3567
  ⋮----
3630
- export interface SubAccountInfo {
3631
- userId: string;
3632
- uid: number;
3633
- subName: string;
3634
- status: number;
3635
- type: number;
3636
- access: string;
3637
- createdAt: number;
3638
- remarks: string;
3639
- tradeTypes: string[];
3640
- openedTradeTypes: string[];
3641
- hostedStatus: null | string;
3642
- }
3568
+ // passed as string, convert to object
3643
3569
  ⋮----
3644
- export interface SubAccountsV2 {
3645
- currentPage: number;
3646
- pageSize: number;
3647
- totalNum: number;
3648
- totalPage: number;
3649
- items: SubAccountInfo[];
3650
- }
3570
+ // already a normalised object, thanks to user
3651
3571
  ⋮----
3652
- export interface SubAccountItem {
3653
- userId: string;
3654
- uid: number;
3655
- subName: string;
3656
- status: number;
3657
- type: number;
3658
- access: string;
3659
- createdAt: number;
3660
- remarks: string;
3661
- tradeTypes: string[];
3662
- openedTradeTypes: string[];
3663
- hostedStatus: null | string;
3664
- }
3572
+ type WSTopic = string;
3665
3573
  ⋮----
3666
- export interface CreateSubAccount {
3667
- currentPage: number;
3668
- pageSize: number;
3669
- totalNum: number;
3670
- totalPage: number;
3671
- items: SubAccountItem[];
3672
- }
3574
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
3575
+ export abstract class BaseWebsocketClient<
3576
+ TWSKey extends string,
3673
3577
  ⋮----
3674
- export interface SubAccountBalance {
3675
- currency: string;
3676
- balance: string;
3677
- available: string;
3678
- holds: string;
3679
- baseCurrency: string;
3680
- baseCurrencyPrice: string;
3681
- baseAmount: string;
3682
- }
3578
+ constructor(
3579
+ options?: WSClientConfigurableOptions,
3580
+ logger?: typeof DefaultLogger,
3581
+ )
3683
3582
  ⋮----
3684
- // deprecated
3685
- export interface SubAccountBalances {
3686
- subUserId: string;
3687
- subName: string;
3688
- mainAccounts: SubAccountBalance[];
3689
- tradeAccounts: SubAccountBalance[];
3690
- marginAccounts: SubAccountBalance[];
3691
- }
3583
+ // Requires a confirmation "response" from the ws connection before assuming it is ready
3692
3584
  ⋮----
3693
- export interface SubAccountBalancesV2 {
3694
- currentPage: number;
3695
- pageSize: number;
3696
- totalNum: number;
3697
- totalPage: number;
3698
- items: {
3699
- subUserId: string;
3700
- subName: string;
3701
- mainAccounts: SubAccountBalance[];
3702
- }[];
3703
- }
3704
- export interface SubAccountV2Details {
3705
- currency?: string;
3706
- balance?: string;
3707
- available?: string;
3708
- holds?: string;
3709
- baseCurrency?: string;
3710
- baseCurrencyPrice?: string;
3711
- baseAmount?: string;
3712
- tag?: string;
3713
- }
3585
+ // Automatically auth after opening a connection?
3714
3586
  ⋮----
3715
- export interface SubAccountBalanceItemV2 {
3716
- subUserId: string;
3717
- subName: string;
3718
- mainAccounts: SubAccountV2Details[]; // Funding Account
3719
- tradeAccounts: SubAccountV2Details[]; // Spot Account
3720
- marginAccounts: SubAccountV2Details[]; // Margin Account
3721
- tradeHFAccounts: string[]; // Deprecated, only for old users
3722
- }
3587
+ // Automatically include auth/sign with every WS request
3723
3588
  ⋮----
3724
- mainAccounts: SubAccountV2Details[]; // Funding Account
3725
- tradeAccounts: SubAccountV2Details[]; // Spot Account
3726
- marginAccounts: SubAccountV2Details[]; // Margin Account
3727
- tradeHFAccounts: string[]; // Deprecated, only for old users
3589
+ // Automatically re-auth WS API, if we were auth'd before and get reconnected
3728
3590
  ⋮----
3729
- /**
3730
- *
3731
- * Sub-Account API
3732
- *
3733
- *
3734
- */
3591
+ // Check Web Crypto API support when credentials are provided and no custom sign function is used
3735
3592
  ⋮----
3736
- export interface SubAccountAPIInfo {
3737
- subName: string;
3738
- remark: string;
3739
- apiKey: string;
3740
- apiVersion: number;
3741
- permission: string;
3742
- ipWhitelist: string;
3743
- createdAt: number;
3744
- uid: number;
3745
- isMaster: boolean;
3746
- }
3593
+ protected abstract sendPingEvent(wsKey: TWSKey, ws: WebSocket): void;
3747
3594
  ⋮----
3748
- export interface CreateSubAPI {
3749
- subName: string;
3750
- remark: string;
3751
- apiKey: string;
3752
- apiSecret: string;
3753
- apiVersion: number;
3754
- passphrase: string;
3755
- permission: string;
3756
- createdAt: number;
3757
- }
3595
+ protected abstract sendPongEvent(wsKey: TWSKey, ws: WebSocket): void;
3758
3596
  ⋮----
3759
- export interface UpdateSubAPI {
3760
- apiKey: string;
3761
- ipWhitelist: string;
3762
- permission: string;
3763
- subName: string;
3764
- }
3597
+ protected abstract isWsPong(data: any): boolean;
3765
3598
  ⋮----
3766
- export interface DeleteSubAccountAPI {
3767
- subName: string;
3768
- apiKey: string;
3769
- }
3770
-
3771
- ================
3772
- File: src/BrokerClient.ts
3773
- ================
3774
- import { BaseRestClient } from './lib/BaseRestClient.js';
3775
- import { REST_CLIENT_TYPE_ENUM, RestClientType } from './lib/requestUtils.js';
3776
- import {
3777
- BrokerTransferRequest,
3778
- CreateBrokerSubAccountApiRequest,
3779
- DeleteBrokerSubAccountApiRequest,
3780
- GetBrokerDepositListRequest,
3781
- GetBrokerInfoRequest,
3782
- GetBrokerSubAccountApisRequest,
3783
- GetBrokerSubAccountsRequest,
3784
- UpdateBrokerSubAccountApiRequest,
3785
- } from './types/request/broker.types.js';
3786
- import {
3787
- BrokerDepositRecord,
3788
- BrokerInfo,
3789
- BrokerSubAccountApi,
3790
- BrokerTransferHistory,
3791
- BrokerWithdrawalRecord,
3792
- CreateBrokerSubAccountApiResponse,
3793
- CreateBrokerSubAccountResponse,
3794
- GetBrokerSubAccountsResponse,
3795
- } from './types/response/broker.types.js';
3796
- import { APISuccessResponse } from './types/response/shared.types.js';
3599
+ protected abstract isWsPing(data: any): boolean;
3797
3600
  ⋮----
3798
- /**
3799
- *
3800
- */
3801
- export class BrokerClient extends BaseRestClient
3601
+ protected abstract getWsAuthRequestEvent(wsKey: TWSKey): Promise<object>;
3802
3602
  ⋮----
3803
- getClientType(): RestClientType
3603
+ protected abstract isPrivateTopicRequest(
3604
+ request: WsTopicRequest<WSTopic>,
3605
+ wsKey: TWSKey,
3606
+ ): boolean;
3804
3607
  ⋮----
3805
3608
  /**
3806
- * Get Broker Info
3807
- *
3808
- * This endpoint supports querying the basic information of the current Broker
3609
+ * Returns a list of string events that can be individually sent upstream to complete subscribing/unsubscribing/etc to these topics
3809
3610
  */
3810
- getBrokerInfo(
3811
- params: GetBrokerInfoRequest,
3812
- ): Promise<APISuccessResponse<BrokerInfo>>
3611
+ protected abstract getWsOperationEventsForTopics(
3612
+ topics: WsTopicRequest<WSTopic>[],
3613
+ wsKey: TWSKey,
3614
+ operation: WsOperation,
3615
+ ): Promise<string[]>;
3616
+ ⋮----
3617
+ protected abstract getPrivateWSKeys(): TWSKey[];
3618
+ ⋮----
3619
+ protected abstract getWsUrl(wsKey: TWSKey): Promise<string>;
3620
+ ⋮----
3621
+ protected abstract getMaxTopicsPerSubscribeEvent(
3622
+ wsKey: TWSKey,
3623
+ ): number | null;
3813
3624
  ⋮----
3814
3625
  /**
3815
- * Add SubAccount
3816
- *
3817
- * This endpoint supports Broker users to create sub-accounts.
3818
- * Note that the account name is unique across the exchange.
3819
- * It is recommended to add a special identifier to prevent name duplication.
3626
+ * Abstraction called to sort ws events into emittable event types (response to a request, data update, etc)
3820
3627
  */
3821
- createSubAccount(params: {
3822
- accountName: string;
3823
- }): Promise<APISuccessResponse<CreateBrokerSubAccountResponse>>
3628
+ protected abstract resolveEmittableEvents(
3629
+ wsKey: TWSKey,
3630
+ event: MessageEventLike,
3631
+ ): EmittableEvent[];
3824
3632
  ⋮----
3825
3633
  /**
3826
- * Get SubAccount
3827
- *
3828
- * This interface supports querying sub-accounts created by Broker.
3829
- * Returns paginated results with default page size of 20 (max 100).
3634
+ * Request connection of all dependent (public & private) websockets, instead of waiting for automatic connection by library
3830
3635
  */
3831
- getSubAccounts(
3832
- params: GetBrokerSubAccountsRequest,
3833
- ): Promise<APISuccessResponse<GetBrokerSubAccountsResponse>>
3636
+ protected abstract connectAll(): Promise<(WSConnectedResult | undefined)[]>;
3637
+ ⋮----
3638
+ protected isPrivateWsKey(wsKey: TWSKey): boolean
3639
+ ⋮----
3640
+ /** Returns auto-incrementing request ID, used to track promise references for async requests */
3641
+ protected getNewRequestId(): string
3642
+ ⋮----
3643
+ protected abstract sendWSAPIRequest(
3644
+ wsKey: TWSKey,
3645
+ channel: WSTopic,
3646
+ params?: any,
3647
+ ): Promise<unknown>;
3648
+ ⋮----
3649
+ protected abstract sendWSAPIRequest(
3650
+ wsKey: TWSKey,
3651
+ channel: WSTopic,
3652
+ params: any,
3653
+ ): Promise<unknown>;
3834
3654
  ⋮----
3835
3655
  /**
3836
- * Add SubAccount API
3656
+ * Subscribe to one or more topics on a WS connection (identified by WS Key).
3837
3657
  *
3838
- * This interface supports the creation of Broker sub-account APIKEY.
3839
- * Supports up to 20 IPs in the whitelist.
3840
- * Only General, Spot, and Futures permissions can be set.
3841
- * Label must be between 4 and 32 characters.
3658
+ * - Topics are automatically cached
3659
+ * - Connections are automatically opened, if not yet connected
3660
+ * - Authentication is automatically handled
3661
+ * - Topics are automatically resubscribed to, if something happens to the connection, unless you call unsubsribeTopicsForWsKey(topics, key).
3662
+ *
3663
+ * @param wsTopicRequests array of topics to subscribe to
3664
+ * @param wsKey ws key referring to the ws connection these topics should be subscribed on
3842
3665
  */
3843
- createSubAccountApi(
3844
- params: CreateBrokerSubAccountApiRequest,
3845
- ): Promise<APISuccessResponse<CreateBrokerSubAccountApiResponse>>
3666
+ public subscribeTopicsForWsKey(
3667
+ wsTopicRequests: WsTopicRequestOrStringTopic<WSTopic>[],
3668
+ wsKey: TWSKey,
3669
+ )
3670
+ ⋮----
3671
+ // Store topics, so future automation (post-auth, post-reconnect) has everything needed to resubscribe automatically
3672
+ ⋮----
3673
+ // start connection process if it hasn't yet begun. Topics are automatically subscribed to on-connect
3674
+ ⋮----
3675
+ // Subscribe should happen automatically once connected, nothing to do here after topics are added to wsStore.
3846
3676
  ⋮----
3847
3677
  /**
3848
- * Get SubAccount API
3849
- *
3850
- * This interface supports querying the Broker's sub-account APIKEYs.
3851
- * Can optionally filter by specific apiKey.
3852
- */
3853
- getSubAccountApis(
3854
- params: GetBrokerSubAccountApisRequest,
3855
- ): Promise<APISuccessResponse<BrokerSubAccountApi[]>>
3678
+ * Are we in the process of connection? Nothing to send yet.
3679
+ */
3680
+ ⋮----
3681
+ // We're connected. Check if auth is needed and if already authenticated
3856
3682
  ⋮----
3857
3683
  /**
3858
- * Modify SubAccount API
3859
- *
3860
- * This interface supports modifying the Broker's sub-account APIKEY.
3861
- * Supports up to 20 IPs in the whitelist.
3862
- * Only General, Spot, and Futures permissions can be set.
3863
- * Label must be between 4 and 32 characters.
3864
- */
3865
- updateSubAccountApi(
3866
- params: UpdateBrokerSubAccountApiRequest,
3867
- ): Promise<APISuccessResponse<BrokerSubAccountApi>>
3684
+ * If not authenticated yet and auth is required, don't request topics yet.
3685
+ *
3686
+ * Auth should already automatically be in progress, so no action needed from here. Topics will automatically subscribe post-auth success.
3687
+ */
3688
+ ⋮----
3689
+ // Finally, request subscription to topics if the connection is healthy and ready
3690
+ ⋮----
3691
+ protected unsubscribeTopicsForWsKey(
3692
+ wsTopicRequests: WsTopicRequestOrStringTopic<string>[],
3693
+ wsKey: TWSKey,
3694
+ )
3695
+ ⋮----
3696
+ // Store topics, so future automation (post-auth, post-reconnect) has everything needed to resubscribe automatically
3697
+ ⋮----
3698
+ // If not connected, don't need to do anything.
3699
+ // Removing the topic from the store is enough to stop it from being resubscribed to on reconnect.
3700
+ ⋮----
3701
+ // We're connected. Check if auth is needed and if already authenticated
3868
3702
  ⋮----
3869
3703
  /**
3870
- * Delete SubAccount API
3871
- *
3872
- * This interface supports deleting Broker's sub-account APIKEY.
3873
- */
3874
- deleteSubAccountApi(
3875
- params: DeleteBrokerSubAccountApiRequest,
3876
- ): Promise<APISuccessResponse<boolean>>
3704
+ * If not authenticated yet and auth is required, don't need to do anything.
3705
+ * We don't subscribe to topics until auth is complete anyway.
3706
+ */
3707
+ ⋮----
3708
+ // Finally, request subscription to topics if the connection is healthy and ready
3877
3709
  ⋮----
3878
3710
  /**
3879
- * Transfer
3880
- *
3881
- * This endpoint supports fund transfer between Broker account and Broker sub-accounts.
3882
- * Please be aware that withdrawal from sub-account is not directly supported.
3883
- * Broker has to transfer funds from broker sub-account to broker account to initiate the withdrawals.
3884
- *
3885
- * Direction:
3886
- * - OUT: Broker account is transferred to Broker sub-account
3887
- * - IN: Broker sub-account is transferred to Broker account
3888
- *
3889
- * Account Types:
3890
- * - MAIN: Funding account
3891
- * - TRADE: Spot trading account
3711
+ * Splits topic requests into two groups, public & private topic requests
3892
3712
  */
3893
- submitTransfer(params: BrokerTransferRequest): Promise<
3894
- APISuccessResponse<{
3895
- orderId: string;
3896
- }>
3897
- > {
3898
- return this.postPrivate('api/v1/broker/nd/transfer', params);
3713
+ private sortTopicRequestsIntoPublicPrivate(
3714
+ wsTopicRequests: WsTopicRequest<string>[],
3715
+ wsKey: TWSKey,
3716
+ ):
3717
+ ⋮----
3718
+ /** Get the WsStore that tracks websockets & topics */
3719
+ public getWsStore(): WsStore<TWSKey, WsTopicRequest<string>>
3720
+ ⋮----
3721
+ public close(wsKey: TWSKey, force?: boolean)
3722
+ ⋮----
3723
+ public closeAll(force?: boolean)
3724
+ ⋮----
3725
+ public isConnected(wsKey: TWSKey): boolean
3899
3726
  ⋮----
3900
3727
  /**
3901
- * Get Transfer History
3902
- *
3903
- * This endpoint supports querying transfer records of the broker itself and its created sub-accounts.
3904
- *
3905
- * Account Types:
3906
- * - MAIN: Funding account
3907
- * - TRADE: Spot trading account
3908
- * - CONTRACT: Contract account
3909
- * - MARGIN: Margin account
3910
- * - ISOLATED: Isolated margin account
3911
- *
3912
- * Status:
3913
- * - PROCESSING: Processing
3914
- * - SUCCESS: Successful
3915
- * - FAILURE: Failed
3728
+ * Request connection to a specific websocket, instead of waiting for automatic connection.
3916
3729
  */
3917
- getTransferHistory(params: {
3918
- orderId: string;
3919
- }): Promise<APISuccessResponse<BrokerTransferHistory>>
3730
+ public async connect(wsKey: TWSKey): Promise<WSConnectedResult | undefined>
3731
+ ⋮----
3732
+ private connectToWsUrl(url: string, wsKey: TWSKey): WebSocket
3733
+ ⋮----
3734
+ private parseWsError(context: string, error: any, wsKey: TWSKey)
3735
+ ⋮----
3736
+ /** Get a signature, build the auth request and send it */
3737
+ private async sendAuthRequest(wsKey: TWSKey): Promise<void>
3738
+ ⋮----
3739
+ private reconnectWithDelay(wsKey: TWSKey, connectionDelayMs: number)
3740
+ ⋮----
3741
+ private ping(wsKey: TWSKey)
3742
+ ⋮----
3743
+ private clearTimers(wsKey: TWSKey)
3744
+ ⋮----
3745
+ // Send a ping at intervals
3746
+ private clearPingTimer(wsKey: TWSKey)
3747
+ ⋮----
3748
+ // Expect a pong within a time limit
3749
+ private clearPongTimer(wsKey: TWSKey)
3750
+ ⋮----
3751
+ // this.logger.trace(`Cleared pong timeout for "${wsKey}"`);
3752
+ ⋮----
3753
+ // this.logger.trace(`No active pong timer for "${wsKey}"`);
3920
3754
  ⋮----
3921
3755
  /**
3922
- * Get Deposit List
3923
- *
3924
- * This endpoint can obtain the deposit records of each sub-account under the ND Broker.
3925
- * Default limit is 1000 records (max 1000).
3926
- * Results are sorted in descending order by default.
3756
+ * Simply builds and sends subscribe events for a list of topics for a ws key
3927
3757
  *
3928
- * Status:
3929
- * - PROCESSING: Processing
3930
- * - SUCCESS: Successful
3931
- * - FAILURE: Failed
3758
+ * @private Use the `subscribe(topics)` or `subscribeTopicsForWsKey(topics, wsKey)` method to subscribe to topics. Send WS message to subscribe to topics.
3932
3759
  */
3933
- getDeposits(
3934
- params?: GetBrokerDepositListRequest,
3935
- ): Promise<APISuccessResponse<BrokerDepositRecord[]>>
3760
+ private async requestSubscribeTopics(
3761
+ wsKey: TWSKey,
3762
+ topics: WsTopicRequest<string>[],
3763
+ )
3764
+ ⋮----
3765
+ // Automatically splits requests into smaller batches, if needed
3766
+ ⋮----
3767
+ `Subscribing to ${topics.length} "${wsKey}" topics in ${subscribeWsMessages.length} batches.`, // Events: "${JSON.stringify(topics)}"
3768
+ ⋮----
3769
+ // this.logger.trace(`Sending batch via message: "${wsMessage}"`);
3936
3770
  ⋮----
3937
3771
  /**
3938
- * Get Deposit Detail
3939
- *
3940
- * This endpoint supports querying the deposit record of sub-accounts created by a Broker
3941
- * (excluding main account of nd broker).
3772
+ * Simply builds and sends unsubscribe events for a list of topics for a ws key
3942
3773
  *
3943
- * Status:
3944
- * - PROCESSING: Processing
3945
- * - SUCCESS: Successful
3946
- * - FAILURE: Failed
3774
+ * @private Use the `unsubscribe(topics)` method to unsubscribe from topics. Send WS message to unsubscribe from topics.
3947
3775
  */
3948
- getDeposit(params: {
3949
- currency: string;
3950
- hash: string;
3951
- }): Promise<APISuccessResponse<BrokerDepositRecord>>
3776
+ private async requestUnsubscribeTopics(
3777
+ wsKey: TWSKey,
3778
+ wsTopicRequests: WsTopicRequest<string>[],
3779
+ )
3952
3780
  ⋮----
3953
3781
  /**
3954
- * Get Withdrawal Detail
3955
- *
3956
- * This endpoint supports querying the withdrawal records of sub-accounts created by a Broker
3957
- * (excluding main account of nd broker).
3958
- *
3959
- * Status:
3960
- * - PROCESSING: Processing
3961
- * - WALLET_PROCESSING: Wallet Processing
3962
- * - REVIEW: Under Review
3963
- * - SUCCESS: Successful
3964
- * - FAILURE: Failed
3782
+ * Try sending a string event on a WS connection (identified by the WS Key)
3965
3783
  */
3966
- getWithdrawal(params: {
3967
- withdrawalId: string;
3968
- }): Promise<APISuccessResponse<BrokerWithdrawalRecord>>
3784
+ public tryWsSend(wsKey: TWSKey, wsMessage: string)
3785
+ ⋮----
3786
+ private async onWsOpen(event: any, wsKey: TWSKey)
3969
3787
  ⋮----
3970
3788
  /**
3971
- * Get Broker Rebate
3789
+ * Called automatically once a connection is ready.
3790
+ * - Some exchanges are ready immediately after the connections open.
3791
+ * - Some exchanges send an event to confirm the connection is ready for us.
3972
3792
  *
3973
- * This interface supports downloading Broker rebate orders.
3974
- * Returns a URL to download a CSV file containing the rebate data.
3975
- * The URL is valid for 1 day.
3976
- * Maximum interval between begin and end dates is 6 months.
3793
+ * This method is called to act when the connection is ready. Use `requireConnectionReadyConfirmation` to control how this is called.
3977
3794
  */
3978
- getBrokerRebate(params: {
3979
- begin: string;
3980
- end: string;
3981
- tradeType: '1' | '2';
3982
- }): Promise<
3983
- APISuccessResponse<{
3984
- url: string;
3985
- }>
3986
- > {
3987
- return this.getPrivate('api/v1/broker/nd/rebase/download', params);
3988
-
3989
- ================
3990
- File: .eslintrc.cjs
3991
- ================
3992
- // 'no-unused-vars': ['warn'],
3993
-
3994
- ================
3995
- File: src/lib/BaseWSClient.ts
3996
- ================
3997
- import EventEmitter from 'events';
3998
- import WebSocket from 'isomorphic-ws';
3999
- ⋮----
4000
- import {
4001
- WebsocketClientOptions,
4002
- WSClientConfigurableOptions,
4003
- } from '../types/websockets/client.js';
4004
- import { WsOperation } from '../types/websockets/requests.js';
4005
- import { WS_LOGGER_CATEGORY } from '../WebsocketClient.js';
4006
- import { DefaultLogger } from './websocket/logger.js';
4007
- import {
4008
- isMessageEvent,
4009
- MessageEventLike,
4010
- safeTerminateWs,
4011
- WsTopicRequest,
4012
- WsTopicRequestOrStringTopic,
4013
- } from './websocket/websocket-util.js';
4014
- import { WsStore } from './websocket/WsStore.js';
4015
- import {
4016
- WSConnectedResult,
4017
- WsConnectionStateEnum,
4018
- } from './websocket/WsStore.types.js';
3795
+ private async onWsReadyForEvents(wsKey: TWSKey)
4019
3796
  ⋮----
4020
- interface WSClientEventMap<WsKey extends string> {
4021
- /** Connection opened. If this connection was previously opened and reconnected, expect the reconnected event instead */
4022
- open: (evt: { wsKey: WsKey; event: any }) => void;
4023
- /** Reconnecting a dropped connection */
4024
- reconnect: (evt: { wsKey: WsKey; event: any }) => void;
4025
- /** Successfully reconnected a connection that dropped */
4026
- reconnected: (evt: { wsKey: WsKey; event: any }) => void;
4027
- /** Connection closed */
4028
- close: (evt: { wsKey: WsKey; event: any }) => void;
4029
- /** Received reply to websocket command (e.g. after subscribing to topics) */
4030
- response: (response: any & { wsKey: WsKey }) => void;
4031
- /** Received data for topic */
4032
- update: (response: any & { wsKey: WsKey }) => void;
4033
- /** Exception from ws client OR custom listeners (e.g. if you throw inside your event handler) */
4034
- exception: (response: any & { wsKey: WsKey }) => void;
4035
- error: (response: any & { wsKey: WsKey }) => void;
4036
- /** Confirmation that a connection successfully authenticated */
4037
- authenticated: (event: { wsKey: WsKey; event: any }) => void;
4038
- }
3797
+ // Resolve & cleanup deferred "connection attempt in progress" promise
4039
3798
  ⋮----
4040
- /** Connection opened. If this connection was previously opened and reconnected, expect the reconnected event instead */
3799
+ // Remove before resolving, in case there's more requests queued
4041
3800
  ⋮----
4042
- /** Reconnecting a dropped connection */
3801
+ // Some websockets require an auth packet to be sent after opening the connection
4043
3802
  ⋮----
4044
- /** Successfully reconnected a connection that dropped */
3803
+ // Reconnect to topics known before it connected
4045
3804
  ⋮----
4046
- /** Connection closed */
3805
+ // Request sub to public topics, if any
4047
3806
  ⋮----
4048
- /** Received reply to websocket command (e.g. after subscribing to topics) */
3807
+ // Request sub to private topics, if auth on connect isn't needed
4049
3808
  ⋮----
4050
- /** Received data for topic */
3809
+ /**
3810
+ * Handle subscription to private topics _after_ authentication successfully completes asynchronously.
3811
+ *
3812
+ * Only used for exchanges that require auth before sending private topic subscription requests
3813
+ */
3814
+ private onWsAuthenticated(
3815
+ wsKey: TWSKey,
3816
+ event: { isWSAPI?: boolean; WSAPIAuthChannel?: string },
3817
+ )
4051
3818
  ⋮----
4052
- /** Exception from ws client OR custom listeners (e.g. if you throw inside your event handler) */
3819
+ private onWsMessage(event: unknown, wsKey: TWSKey, ws: WebSocket)
4053
3820
  ⋮----
4054
- /** Confirmation that a connection successfully authenticated */
3821
+ // any message can clear the pong timer - wouldn't get a message if the ws wasn't working
4055
3822
  ⋮----
4056
- export interface EmittableEvent<TEvent = any> {
4057
- eventType:
4058
- | 'response'
4059
- | 'update'
4060
- | 'exception'
4061
- | 'authenticated'
4062
- | 'connectionReady'; // tied to "requireConnectionReadyConfirmation"
4063
- event: TEvent;
4064
- }
3823
+ // console.log(`raw event: `, { data, dataType, emittableEvents });
4065
3824
  ⋮----
4066
- | 'connectionReady'; // tied to "requireConnectionReadyConfirmation"
3825
+ private onWsClose(event: unknown, wsKey: TWSKey)
4067
3826
  ⋮----
4068
- // Type safety for on and emit handlers: https://stackoverflow.com/a/61609010/880837
4069
- export interface BaseWebsocketClient<TWSKey extends string> {
4070
- on<U extends keyof WSClientEventMap<TWSKey>>(
4071
- event: U,
4072
- listener: WSClientEventMap<TWSKey>[U],
4073
- ): this;
4074
-
4075
- emit<U extends keyof WSClientEventMap<TWSKey>>(
4076
- event: U,
4077
- ...args: Parameters<WSClientEventMap<TWSKey>[U]>
4078
- ): boolean;
4079
- }
3827
+ // clean up any pending promises for this connection
4080
3828
  ⋮----
4081
- on<U extends keyof WSClientEventMap<TWSKey>>(
4082
- event: U,
4083
- listener: WSClientEventMap<TWSKey>[U],
4084
- ): this;
3829
+ // clean up any pending promises for this connection
4085
3830
  ⋮----
4086
- emit<U extends keyof WSClientEventMap<TWSKey>>(
4087
- event: U,
4088
- ...args: Parameters<WSClientEventMap<TWSKey>[U]>
4089
- ): boolean;
3831
+ private getWs(wsKey: TWSKey)
4090
3832
  ⋮----
4091
- /**
4092
- * Users can conveniently pass topics as strings or objects (object has topic name + optional params).
4093
- *
4094
- * This method normalises topics into objects (object has topic name + optional params).
4095
- */
4096
- function getNormalisedTopicRequests(
4097
- wsTopicRequests: WsTopicRequestOrStringTopic<string>[],
4098
- ): WsTopicRequest<string>[]
3833
+ private setWsState(wsKey: TWSKey, state: WsConnectionStateEnum)
4099
3834
  ⋮----
4100
- // passed as string, convert to object
3835
+ /**
3836
+ * Promise-driven method to assert that a ws has successfully connected (will await until connection is open)
3837
+ */
3838
+ protected async assertIsConnected(wsKey: TWSKey): Promise<unknown>
4101
3839
  ⋮----
4102
- // already a normalised object, thanks to user
3840
+ // Already in progress? Await shared promise and retry
4103
3841
  ⋮----
4104
- type WSTopic = string;
3842
+ // Start connection, it should automatically store/return a promise.
3843
+
3844
+ ================
3845
+ File: src/types/request/spot-account.ts
3846
+ ================
3847
+ export interface GetBalancesRequest {
3848
+ currency?: string;
3849
+ type?: 'main' | 'trade';
3850
+ }
4105
3851
  ⋮----
4106
- // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
4107
- export abstract class BaseWebsocketClient<
4108
- TWSKey extends string,
3852
+ export interface GetSpotTransactionsRequest {
3853
+ currency?: string;
3854
+ direction?: 'in' | 'out';
3855
+ bizType?:
3856
+ | 'DEPOSIT'
3857
+ | 'WITHDRAW'
3858
+ | 'TRANSFER'
3859
+ | 'SUB_TRANSFER'
3860
+ | 'TRADE_EXCHANGE'
3861
+ | 'MARGIN_EXCHANGE'
3862
+ | 'KUCOIN_BONUS'
3863
+ | 'BROKER_TRANSFER'
3864
+ | 'REBATE';
3865
+ startAt?: number;
3866
+ endAt?: number;
3867
+ currentPage?: number;
3868
+ pageSize?: number;
3869
+ }
4109
3870
  ⋮----
4110
- constructor(
4111
- options?: WSClientConfigurableOptions,
4112
- logger?: typeof DefaultLogger,
4113
- )
3871
+ export interface AccountHFTransactionsRequest {
3872
+ currency?: string;
3873
+ direction?: 'in' | 'out';
3874
+ bizType?:
3875
+ | 'TRANSFER'
3876
+ | 'TRADE_EXCHANGE'
3877
+ | 'RETURNED_FEES'
3878
+ | 'DEDUCTION_FEES'
3879
+ | 'OTHER';
3880
+ lastId?: number;
3881
+ limit?: number;
3882
+ startAt?: number;
3883
+ endAt?: number;
3884
+ }
4114
3885
  ⋮----
4115
- // Requires a confirmation "response" from the ws connection before assuming it is ready
3886
+ export interface AccountHFMarginTransactionsRequest {
3887
+ currency?: string;
3888
+ direction?: 'in' | 'out';
3889
+ bizType?:
3890
+ | 'TRANSFER'
3891
+ | 'MARGIN_EXCHANGE'
3892
+ | 'ISOLATED_EXCHANGE'
3893
+ | 'LIQUIDATION'
3894
+ | 'ASSERT_RETURN';
3895
+ lastId?: number;
3896
+ limit?: number;
3897
+ startAt?: number;
3898
+ endAt?: number;
3899
+ }
4116
3900
  ⋮----
4117
- // Automatically auth after opening a connection?
3901
+ export interface CreateSubAccountRequest {
3902
+ password: string;
3903
+ remarks?: string;
3904
+ subName: string;
3905
+ access: string;
3906
+ }
4118
3907
  ⋮----
4119
- // Automatically include auth/sign with every WS request
3908
+ export interface CreateSubAccountAPIRequest {
3909
+ subName: string;
3910
+ passphrase: string;
3911
+ remark: string;
3912
+ permission?: string;
3913
+ ipWhitelist?: string;
3914
+ expire?: string;
3915
+ }
4120
3916
  ⋮----
4121
- // Automatically re-auth WS API, if we were auth'd before and get reconnected
3917
+ export interface UpdateSubAccountAPIRequest {
3918
+ subName: string;
3919
+ apiKey: string;
3920
+ passphrase: string;
3921
+ permission?: string;
3922
+ ipWhitelist?: string;
3923
+ expire?: string;
3924
+ }
4122
3925
  ⋮----
4123
- protected abstract sendPingEvent(wsKey: TWSKey, ws: WebSocket): void;
3926
+ export interface DeleteSubAccountAPIRequest {
3927
+ apiKey: string;
3928
+ passphrase: string;
3929
+ subName: string;
3930
+ }
3931
+
3932
+ ================
3933
+ File: src/types/request/spot-funding.ts
3934
+ ================
3935
+ /**
3936
+ *
3937
+ ***********
3938
+ * Funding
3939
+ ***********
3940
+ *
3941
+ */
4124
3942
  ⋮----
4125
- protected abstract sendPongEvent(wsKey: TWSKey, ws: WebSocket): void;
3943
+ export interface CreateDepositAddressV3Request {
3944
+ currency: string;
3945
+ chain?: string;
3946
+ to?: 'main' | 'trade';
3947
+ amount?: string;
3948
+ }
4126
3949
  ⋮----
4127
- protected abstract isWsPong(data: any): boolean;
3950
+ export interface GetMarginBalanceRequest {
3951
+ quoteCurrency?: string;
3952
+ queryType?: 'MARGIN' | 'MARGIN_V2' | 'ALL';
3953
+ }
4128
3954
  ⋮----
4129
- protected abstract isWsPing(data: any): boolean;
3955
+ export interface GetIsolatedMarginBalanceRequest {
3956
+ symbol?: string;
3957
+ quoteCurrency?: string;
3958
+ queryType?: 'ISOLATED' | 'ISOLATED_V2' | 'ALL';
3959
+ }
4130
3960
  ⋮----
4131
- protected abstract getWsAuthRequestEvent(wsKey: TWSKey): Promise<object>;
3961
+ /**
3962
+ *
3963
+ * Deposit
3964
+ *
3965
+ */
4132
3966
  ⋮----
4133
- protected abstract isPrivateTopicRequest(
4134
- request: WsTopicRequest<WSTopic>,
4135
- wsKey: TWSKey,
4136
- ): boolean;
3967
+ export interface GetDepositsRequest {
3968
+ currency?: string;
3969
+ startAt?: number;
3970
+ endAt?: number;
3971
+ status?: 'PROCESSING' | 'SUCCESS' | 'FAILURE';
3972
+ currentPage?: number;
3973
+ pageSize?: number;
3974
+ }
4137
3975
  ⋮----
4138
3976
  /**
4139
- * Returns a list of string events that can be individually sent upstream to complete subscribing/unsubscribing/etc to these topics
4140
- */
4141
- protected abstract getWsOperationEventsForTopics(
4142
- topics: WsTopicRequest<WSTopic>[],
4143
- wsKey: TWSKey,
4144
- operation: WsOperation,
4145
- ): Promise<string[]>;
3977
+ *
3978
+ * Withdrawals
3979
+ *
3980
+ */
4146
3981
  ⋮----
4147
- protected abstract getPrivateWSKeys(): TWSKey[];
3982
+ export interface GetWithdrawalsRequest {
3983
+ currency?: string;
3984
+ status?: 'PROCESSING' | 'WALLET_PROCESSING' | 'SUCCESS' | 'FAILURE';
3985
+ startAt?: number;
3986
+ endAt?: number;
3987
+ currentPage?: number;
3988
+ pageSize?: number;
3989
+ }
4148
3990
  ⋮----
4149
- protected abstract getWsUrl(wsKey: TWSKey): Promise<string>;
3991
+ export interface ApplyWithdrawRequest {
3992
+ currency: string;
3993
+ address: string;
3994
+ amount: number;
3995
+ memo?: string;
3996
+ isInner?: boolean;
3997
+ remark?: string;
3998
+ chain?: string;
3999
+ feeDeductType?: 'INTERNAL' | 'EXTERNAL';
4000
+ }
4150
4001
  ⋮----
4151
- protected abstract getMaxTopicsPerSubscribeEvent(
4152
- wsKey: TWSKey,
4153
- ): number | null;
4002
+ export interface SubmitWithdrawV3Request {
4003
+ currency: string;
4004
+ toAddress: string;
4005
+ amount: number;
4006
+ memo?: string;
4007
+ isInner?: boolean;
4008
+ remark?: string;
4009
+ chain?: string;
4010
+ feeDeductType?: 'INTERNAL' | 'EXTERNAL';
4011
+ withdrawType: 'ADDRESS' | 'UID' | 'MAIL' | 'PHONE';
4012
+ }
4154
4013
  ⋮----
4155
4014
  /**
4156
- * Abstraction called to sort ws events into emittable event types (response to a request, data update, etc)
4157
- */
4158
- protected abstract resolveEmittableEvents(
4159
- wsKey: TWSKey,
4160
- event: MessageEventLike,
4161
- ): EmittableEvent[];
4015
+ *
4016
+ * Transfer
4017
+ *
4018
+ */
4162
4019
  ⋮----
4163
- /**
4164
- * Request connection of all dependent (public & private) websockets, instead of waiting for automatic connection by library
4165
- */
4166
- protected abstract connectAll(): Promise<(WSConnectedResult | undefined)[]>;
4020
+ export interface GetTransferableRequest {
4021
+ currency: string;
4022
+ type:
4023
+ | 'MAIN'
4024
+ | 'TRADE'
4025
+ | 'TRADE_HF'
4026
+ | 'MARGIN'
4027
+ | 'ISOLATED'
4028
+ | 'OPTION'
4029
+ | 'MARGIN_V2'
4030
+ | 'ISOLATED_V2';
4031
+ tag?: string;
4032
+ }
4167
4033
  ⋮----
4168
- protected isPrivateWsKey(wsKey: TWSKey): boolean
4034
+ export interface FlexTransferRequest {
4035
+ clientOid: string;
4036
+ currency?: string;
4037
+ amount: string;
4038
+ fromUserId?: string;
4039
+ fromAccountType:
4040
+ | 'MAIN'
4041
+ | 'TRADE'
4042
+ | 'CONTRACT'
4043
+ | 'MARGIN'
4044
+ | 'ISOLATED'
4045
+ | 'TRADE_HF'
4046
+ | 'MARGIN_V2'
4047
+ | 'ISOLATED_V2'
4048
+ | 'OPTION';
4049
+ fromAccountTag?: string;
4050
+ type: 'INTERNAL' | 'PARENT_TO_SUB' | 'SUB_TO_PARENT';
4051
+ toUserId?: string;
4052
+ toAccountType:
4053
+ | 'MAIN'
4054
+ | 'TRADE'
4055
+ | 'CONTRACT'
4056
+ | 'MARGIN'
4057
+ | 'ISOLATED'
4058
+ | 'TRADE_HF'
4059
+ | 'MARGIN_V2'
4060
+ | 'ISOLATED_V2'
4061
+ | 'OPTION';
4062
+ toAccountTag?: string;
4063
+ }
4169
4064
  ⋮----
4170
- /** Returns auto-incrementing request ID, used to track promise references for async requests */
4171
- protected getNewRequestId(): string
4065
+ export interface submitTransferMasterSubRequest {
4066
+ clientOid: string;
4067
+ currency: string;
4068
+ amount: string;
4069
+ direction: 'OUT' | 'IN';
4070
+ accountType?:
4071
+ | 'MAIN'
4072
+ | 'TRADE'
4073
+ | 'TRADE_HF'
4074
+ | 'MARGIN'
4075
+ | 'CONTRACT'
4076
+ | 'OPTION';
4077
+ subAccountType?:
4078
+ | 'MAIN'
4079
+ | 'TRADE'
4080
+ | 'TRADE_HF'
4081
+ | 'MARGIN'
4082
+ | 'CONTRACT'
4083
+ | 'OPTION';
4084
+ subUserId: string;
4085
+ }
4172
4086
  ⋮----
4173
- protected abstract sendWSAPIRequest(
4174
- wsKey: TWSKey,
4175
- channel: WSTopic,
4176
- params?: any,
4177
- ): Promise<unknown>;
4087
+ export interface InnerTransferRequest {
4088
+ clientOid: string;
4089
+ currency: string;
4090
+ from:
4091
+ | 'main'
4092
+ | 'trade'
4093
+ | 'trade_hf'
4094
+ | 'margin'
4095
+ | 'isolated'
4096
+ | 'margin_v2'
4097
+ | 'isolated_v2'
4098
+ | 'contract'
4099
+ | 'option';
4100
+ to:
4101
+ | 'main'
4102
+ | 'trade'
4103
+ | 'trade_hf'
4104
+ | 'margin'
4105
+ | 'isolated'
4106
+ | 'margin_v2'
4107
+ | 'isolated_v2'
4108
+ | 'contract'
4109
+ | 'option';
4110
+ amount: string;
4111
+ fromTag?: string;
4112
+ toTag?: string;
4113
+ }
4114
+
4115
+ ================
4116
+ File: src/types/response/spot-account.ts
4117
+ ================
4118
+ export interface SpotAccountSummary {
4119
+ level: number;
4120
+ subQuantity: number;
4121
+ spotSubQuantity: number;
4122
+ marginSubQuantity: number;
4123
+ futuresSubQuantity: number;
4124
+ optionSubQuantity: number;
4125
+ maxSubQuantity: number;
4126
+ maxDefaultSubQuantity: number;
4127
+ maxSpotSubQuantity: number;
4128
+ maxMarginSubQuantity: number;
4129
+ maxFuturesSubQuantity: number;
4130
+ maxOptionSubQuantity: number;
4131
+ }
4178
4132
  ⋮----
4179
- protected abstract sendWSAPIRequest(
4180
- wsKey: TWSKey,
4181
- channel: WSTopic,
4182
- params: any,
4183
- ): Promise<unknown>;
4133
+ export interface Balances {
4134
+ id: string;
4135
+ currency: string;
4136
+ type: 'main' | 'trade';
4137
+ balance: string;
4138
+ available: string;
4139
+ holds: string;
4140
+ }
4184
4141
  ⋮----
4185
- /**
4186
- * Subscribe to one or more topics on a WS connection (identified by WS Key).
4187
- *
4188
- * - Topics are automatically cached
4189
- * - Connections are automatically opened, if not yet connected
4190
- * - Authentication is automatically handled
4191
- * - Topics are automatically resubscribed to, if something happens to the connection, unless you call unsubsribeTopicsForWsKey(topics, key).
4192
- *
4193
- * @param wsTopicRequests array of topics to subscribe to
4194
- * @param wsKey ws key referring to the ws connection these topics should be subscribed on
4195
- */
4196
- public subscribeTopicsForWsKey(
4197
- wsTopicRequests: WsTopicRequestOrStringTopic<WSTopic>[],
4198
- wsKey: TWSKey,
4199
- )
4142
+ export interface Account {
4143
+ currency: string;
4144
+ balance: string;
4145
+ available: string;
4146
+ holds: string;
4147
+ }
4200
4148
  ⋮----
4201
- // Store topics, so future automation (post-auth, post-reconnect) has everything needed to resubscribe automatically
4149
+ export interface SpotAccountTransaction {
4150
+ id: string;
4151
+ currency: string;
4152
+ amount: string;
4153
+ fee: string;
4154
+ tax: string;
4155
+ balance: string;
4156
+ accountType: string; // 'TRADE_HF'
4157
+ bizType: string;
4158
+ direction: 'out' | 'in';
4159
+ createdAt: string;
4160
+ context: string;
4161
+ }
4202
4162
  ⋮----
4203
- // start connection process if it hasn't yet begun. Topics are automatically subscribed to on-connect
4163
+ accountType: string; // 'TRADE_HF'
4204
4164
  ⋮----
4205
- // Subscribe should happen automatically once connected, nothing to do here after topics are added to wsStore.
4165
+ export interface SpotAccountTransactions {
4166
+ currentPage: number;
4167
+ pageSize: number;
4168
+ totalNum: number;
4169
+ totalPage: number;
4170
+ items: SpotAccountTransaction[];
4171
+ }
4172
+ ⋮----
4173
+ export interface AccountHFMarginTransactions {
4174
+ id: string;
4175
+ currency: string;
4176
+ amount: string;
4177
+ fee: string;
4178
+ balance: string;
4179
+ accountType: 'MARGIN_V2' | 'ISOLATED_V2';
4180
+ bizType:
4181
+ | 'TRANSFER'
4182
+ | 'MARGIN_EXCHANGE'
4183
+ | 'ISOLATED_EXCHANGE'
4184
+ | 'LIQUIDATION'
4185
+ | 'ASSERT_RETURN';
4186
+ direction: 'out' | 'in';
4187
+ createdAt: string;
4188
+ tax: string;
4189
+ context: string;
4190
+ }
4206
4191
  ⋮----
4207
4192
  /**
4208
- * Are we in the process of connection? Nothing to send yet.
4209
- */
4193
+ *
4194
+ * Sub-Account
4195
+ *
4196
+ */
4210
4197
  ⋮----
4211
- // We're connected. Check if auth is needed and if already authenticated
4198
+ export interface SubAccountInfo {
4199
+ userId: string;
4200
+ uid: number;
4201
+ subName: string;
4202
+ status: number;
4203
+ type: number;
4204
+ access: string;
4205
+ createdAt: number;
4206
+ remarks: string;
4207
+ tradeTypes: string[];
4208
+ openedTradeTypes: string[];
4209
+ hostedStatus: null | string;
4210
+ }
4212
4211
  ⋮----
4213
- /**
4214
- * If not authenticated yet and auth is required, don't request topics yet.
4215
- *
4216
- * Auth should already automatically be in progress, so no action needed from here. Topics will automatically subscribe post-auth success.
4217
- */
4212
+ export interface SubAccountsV2 {
4213
+ currentPage: number;
4214
+ pageSize: number;
4215
+ totalNum: number;
4216
+ totalPage: number;
4217
+ items: SubAccountInfo[];
4218
+ }
4218
4219
  ⋮----
4219
- // Finally, request subscription to topics if the connection is healthy and ready
4220
+ export interface SubAccountItem {
4221
+ userId: string;
4222
+ uid: number;
4223
+ subName: string;
4224
+ status: number;
4225
+ type: number;
4226
+ access: string;
4227
+ createdAt: number;
4228
+ remarks: string;
4229
+ tradeTypes: string[];
4230
+ openedTradeTypes: string[];
4231
+ hostedStatus: null | string;
4232
+ }
4220
4233
  ⋮----
4221
- protected unsubscribeTopicsForWsKey(
4222
- wsTopicRequests: WsTopicRequestOrStringTopic<string>[],
4223
- wsKey: TWSKey,
4224
- )
4234
+ export interface CreateSubAccount {
4235
+ currentPage: number;
4236
+ pageSize: number;
4237
+ totalNum: number;
4238
+ totalPage: number;
4239
+ items: SubAccountItem[];
4240
+ }
4225
4241
  ⋮----
4226
- // Store topics, so future automation (post-auth, post-reconnect) has everything needed to resubscribe automatically
4242
+ export interface SubAccountBalance {
4243
+ currency: string;
4244
+ balance: string;
4245
+ available: string;
4246
+ holds: string;
4247
+ baseCurrency: string;
4248
+ baseCurrencyPrice: string;
4249
+ baseAmount: string;
4250
+ }
4227
4251
  ⋮----
4228
- // If not connected, don't need to do anything.
4229
- // Removing the topic from the store is enough to stop it from being resubscribed to on reconnect.
4252
+ // deprecated
4253
+ export interface SubAccountBalances {
4254
+ subUserId: string;
4255
+ subName: string;
4256
+ mainAccounts: SubAccountBalance[];
4257
+ tradeAccounts: SubAccountBalance[];
4258
+ marginAccounts: SubAccountBalance[];
4259
+ }
4230
4260
  ⋮----
4231
- // We're connected. Check if auth is needed and if already authenticated
4261
+ export interface SubAccountBalancesV2 {
4262
+ currentPage: number;
4263
+ pageSize: number;
4264
+ totalNum: number;
4265
+ totalPage: number;
4266
+ items: {
4267
+ subUserId: string;
4268
+ subName: string;
4269
+ mainAccounts: SubAccountBalance[];
4270
+ }[];
4271
+ }
4272
+ export interface SubAccountV2Details {
4273
+ currency?: string;
4274
+ balance?: string;
4275
+ available?: string;
4276
+ holds?: string;
4277
+ baseCurrency?: string;
4278
+ baseCurrencyPrice?: string;
4279
+ baseAmount?: string;
4280
+ tag?: string;
4281
+ }
4232
4282
  ⋮----
4233
- /**
4234
- * If not authenticated yet and auth is required, don't need to do anything.
4235
- * We don't subscribe to topics until auth is complete anyway.
4236
- */
4283
+ export interface SubAccountBalanceItemV2 {
4284
+ subUserId: string;
4285
+ subName: string;
4286
+ mainAccounts: SubAccountV2Details[]; // Funding Account
4287
+ tradeAccounts: SubAccountV2Details[]; // Spot Account
4288
+ marginAccounts: SubAccountV2Details[]; // Margin Account
4289
+ tradeHFAccounts: string[]; // Deprecated, only for old users
4290
+ }
4237
4291
  ⋮----
4238
- // Finally, request subscription to topics if the connection is healthy and ready
4292
+ mainAccounts: SubAccountV2Details[]; // Funding Account
4293
+ tradeAccounts: SubAccountV2Details[]; // Spot Account
4294
+ marginAccounts: SubAccountV2Details[]; // Margin Account
4295
+ tradeHFAccounts: string[]; // Deprecated, only for old users
4239
4296
  ⋮----
4240
4297
  /**
4241
- * Splits topic requests into two groups, public & private topic requests
4242
- */
4243
- private sortTopicRequestsIntoPublicPrivate(
4244
- wsTopicRequests: WsTopicRequest<string>[],
4245
- wsKey: TWSKey,
4246
- ):
4298
+ *
4299
+ * Sub-Account API
4300
+ *
4301
+ *
4302
+ */
4247
4303
  ⋮----
4248
- /** Get the WsStore that tracks websockets & topics */
4249
- public getWsStore(): WsStore<TWSKey, WsTopicRequest<string>>
4304
+ export interface SubAccountAPIInfo {
4305
+ subName: string;
4306
+ remark: string;
4307
+ apiKey: string;
4308
+ apiVersion: number;
4309
+ permission: string;
4310
+ ipWhitelist: string;
4311
+ createdAt: number;
4312
+ uid: number;
4313
+ isMaster: boolean;
4314
+ }
4250
4315
  ⋮----
4251
- public close(wsKey: TWSKey, force?: boolean)
4316
+ export interface CreateSubAPI {
4317
+ subName: string;
4318
+ remark: string;
4319
+ apiKey: string;
4320
+ apiSecret: string;
4321
+ apiVersion: number;
4322
+ passphrase: string;
4323
+ permission: string;
4324
+ createdAt: number;
4325
+ }
4252
4326
  ⋮----
4253
- public closeAll(force?: boolean)
4327
+ export interface UpdateSubAPI {
4328
+ apiKey: string;
4329
+ ipWhitelist: string;
4330
+ permission: string;
4331
+ subName: string;
4332
+ }
4254
4333
  ⋮----
4255
- public isConnected(wsKey: TWSKey): boolean
4334
+ export interface DeleteSubAccountAPI {
4335
+ subName: string;
4336
+ apiKey: string;
4337
+ }
4338
+
4339
+ ================
4340
+ File: src/BrokerClient.ts
4341
+ ================
4342
+ import { BaseRestClient } from './lib/BaseRestClient.js';
4343
+ import { REST_CLIENT_TYPE_ENUM, RestClientType } from './lib/requestUtils.js';
4344
+ import {
4345
+ BrokerTransferRequest,
4346
+ CreateBrokerSubAccountApiRequest,
4347
+ DeleteBrokerSubAccountApiRequest,
4348
+ GetBrokerDepositListRequest,
4349
+ GetBrokerInfoRequest,
4350
+ GetBrokerSubAccountApisRequest,
4351
+ GetBrokerSubAccountsRequest,
4352
+ UpdateBrokerSubAccountApiRequest,
4353
+ } from './types/request/broker.types.js';
4354
+ import {
4355
+ BrokerDepositRecord,
4356
+ BrokerInfo,
4357
+ BrokerSubAccountApi,
4358
+ BrokerTransferHistory,
4359
+ BrokerWithdrawalRecord,
4360
+ CreateBrokerSubAccountApiResponse,
4361
+ CreateBrokerSubAccountResponse,
4362
+ GetBrokerSubAccountsResponse,
4363
+ } from './types/response/broker.types.js';
4364
+ import { APISuccessResponse } from './types/response/shared.types.js';
4256
4365
  ⋮----
4257
4366
  /**
4258
- * Request connection to a specific websocket, instead of waiting for automatic connection.
4259
- */
4260
- public async connect(wsKey: TWSKey): Promise<WSConnectedResult | undefined>
4261
- ⋮----
4262
- private connectToWsUrl(url: string, wsKey: TWSKey): WebSocket
4263
- ⋮----
4264
- private parseWsError(context: string, error: any, wsKey: TWSKey)
4367
+ *
4368
+ */
4369
+ export class BrokerClient extends BaseRestClient
4265
4370
  ⋮----
4266
- /** Get a signature, build the auth request and send it */
4267
- private async sendAuthRequest(wsKey: TWSKey): Promise<void>
4371
+ getClientType(): RestClientType
4268
4372
  ⋮----
4269
- private reconnectWithDelay(wsKey: TWSKey, connectionDelayMs: number)
4373
+ /**
4374
+ * Get Broker Info
4375
+ *
4376
+ * This endpoint supports querying the basic information of the current Broker
4377
+ */
4378
+ getBrokerInfo(
4379
+ params: GetBrokerInfoRequest,
4380
+ ): Promise<APISuccessResponse<BrokerInfo>>
4270
4381
  ⋮----
4271
- private ping(wsKey: TWSKey)
4382
+ /**
4383
+ * Add SubAccount
4384
+ *
4385
+ * This endpoint supports Broker users to create sub-accounts.
4386
+ * Note that the account name is unique across the exchange.
4387
+ * It is recommended to add a special identifier to prevent name duplication.
4388
+ */
4389
+ createSubAccount(params: {
4390
+ accountName: string;
4391
+ }): Promise<APISuccessResponse<CreateBrokerSubAccountResponse>>
4272
4392
  ⋮----
4273
- private clearTimers(wsKey: TWSKey)
4393
+ /**
4394
+ * Get SubAccount
4395
+ *
4396
+ * This interface supports querying sub-accounts created by Broker.
4397
+ * Returns paginated results with default page size of 20 (max 100).
4398
+ */
4399
+ getSubAccounts(
4400
+ params: GetBrokerSubAccountsRequest,
4401
+ ): Promise<APISuccessResponse<GetBrokerSubAccountsResponse>>
4274
4402
  ⋮----
4275
- // Send a ping at intervals
4276
- private clearPingTimer(wsKey: TWSKey)
4403
+ /**
4404
+ * Add SubAccount API
4405
+ *
4406
+ * This interface supports the creation of Broker sub-account APIKEY.
4407
+ * Supports up to 20 IPs in the whitelist.
4408
+ * Only General, Spot, and Futures permissions can be set.
4409
+ * Label must be between 4 and 32 characters.
4410
+ */
4411
+ createSubAccountApi(
4412
+ params: CreateBrokerSubAccountApiRequest,
4413
+ ): Promise<APISuccessResponse<CreateBrokerSubAccountApiResponse>>
4277
4414
  ⋮----
4278
- // Expect a pong within a time limit
4279
- private clearPongTimer(wsKey: TWSKey)
4415
+ /**
4416
+ * Get SubAccount API
4417
+ *
4418
+ * This interface supports querying the Broker's sub-account APIKEYs.
4419
+ * Can optionally filter by specific apiKey.
4420
+ */
4421
+ getSubAccountApis(
4422
+ params: GetBrokerSubAccountApisRequest,
4423
+ ): Promise<APISuccessResponse<BrokerSubAccountApi[]>>
4280
4424
  ⋮----
4281
- // this.logger.trace(`Cleared pong timeout for "${wsKey}"`);
4425
+ /**
4426
+ * Modify SubAccount API
4427
+ *
4428
+ * This interface supports modifying the Broker's sub-account APIKEY.
4429
+ * Supports up to 20 IPs in the whitelist.
4430
+ * Only General, Spot, and Futures permissions can be set.
4431
+ * Label must be between 4 and 32 characters.
4432
+ */
4433
+ updateSubAccountApi(
4434
+ params: UpdateBrokerSubAccountApiRequest,
4435
+ ): Promise<APISuccessResponse<BrokerSubAccountApi>>
4282
4436
  ⋮----
4283
- // this.logger.trace(`No active pong timer for "${wsKey}"`);
4437
+ /**
4438
+ * Delete SubAccount API
4439
+ *
4440
+ * This interface supports deleting Broker's sub-account APIKEY.
4441
+ */
4442
+ deleteSubAccountApi(
4443
+ params: DeleteBrokerSubAccountApiRequest,
4444
+ ): Promise<APISuccessResponse<boolean>>
4284
4445
  ⋮----
4285
4446
  /**
4286
- * Simply builds and sends subscribe events for a list of topics for a ws key
4447
+ * Transfer
4448
+ *
4449
+ * This endpoint supports fund transfer between Broker account and Broker sub-accounts.
4450
+ * Please be aware that withdrawal from sub-account is not directly supported.
4451
+ * Broker has to transfer funds from broker sub-account to broker account to initiate the withdrawals.
4287
4452
  *
4288
- * @private Use the `subscribe(topics)` or `subscribeTopicsForWsKey(topics, wsKey)` method to subscribe to topics. Send WS message to subscribe to topics.
4453
+ * Direction:
4454
+ * - OUT: Broker account is transferred to Broker sub-account
4455
+ * - IN: Broker sub-account is transferred to Broker account
4456
+ *
4457
+ * Account Types:
4458
+ * - MAIN: Funding account
4459
+ * - TRADE: Spot trading account
4289
4460
  */
4290
- private async requestSubscribeTopics(
4291
- wsKey: TWSKey,
4292
- topics: WsTopicRequest<string>[],
4293
- )
4294
- ⋮----
4295
- // Automatically splits requests into smaller batches, if needed
4296
- ⋮----
4297
- `Subscribing to ${topics.length} "${wsKey}" topics in ${subscribeWsMessages.length} batches.`, // Events: "${JSON.stringify(topics)}"
4298
- ⋮----
4299
- // this.logger.trace(`Sending batch via message: "${wsMessage}"`);
4461
+ submitTransfer(params: BrokerTransferRequest): Promise<
4462
+ APISuccessResponse<{
4463
+ orderId: string;
4464
+ }>
4465
+ > {
4466
+ return this.postPrivate('api/v1/broker/nd/transfer', params);
4300
4467
  ⋮----
4301
4468
  /**
4302
- * Simply builds and sends unsubscribe events for a list of topics for a ws key
4469
+ * Get Transfer History
4303
4470
  *
4304
- * @private Use the `unsubscribe(topics)` method to unsubscribe from topics. Send WS message to unsubscribe from topics.
4471
+ * This endpoint supports querying transfer records of the broker itself and its created sub-accounts.
4472
+ *
4473
+ * Account Types:
4474
+ * - MAIN: Funding account
4475
+ * - TRADE: Spot trading account
4476
+ * - CONTRACT: Contract account
4477
+ * - MARGIN: Margin account
4478
+ * - ISOLATED: Isolated margin account
4479
+ *
4480
+ * Status:
4481
+ * - PROCESSING: Processing
4482
+ * - SUCCESS: Successful
4483
+ * - FAILURE: Failed
4305
4484
  */
4306
- private async requestUnsubscribeTopics(
4307
- wsKey: TWSKey,
4308
- wsTopicRequests: WsTopicRequest<string>[],
4309
- )
4485
+ getTransferHistory(params: {
4486
+ orderId: string;
4487
+ }): Promise<APISuccessResponse<BrokerTransferHistory>>
4310
4488
  ⋮----
4311
4489
  /**
4312
- * Try sending a string event on a WS connection (identified by the WS Key)
4490
+ * Get Deposit List
4491
+ *
4492
+ * This endpoint can obtain the deposit records of each sub-account under the ND Broker.
4493
+ * Default limit is 1000 records (max 1000).
4494
+ * Results are sorted in descending order by default.
4495
+ *
4496
+ * Status:
4497
+ * - PROCESSING: Processing
4498
+ * - SUCCESS: Successful
4499
+ * - FAILURE: Failed
4313
4500
  */
4314
- public tryWsSend(wsKey: TWSKey, wsMessage: string)
4315
- ⋮----
4316
- private async onWsOpen(event: any, wsKey: TWSKey)
4501
+ getDeposits(
4502
+ params?: GetBrokerDepositListRequest,
4503
+ ): Promise<APISuccessResponse<BrokerDepositRecord[]>>
4317
4504
  ⋮----
4318
4505
  /**
4319
- * Called automatically once a connection is ready.
4320
- * - Some exchanges are ready immediately after the connections open.
4321
- * - Some exchanges send an event to confirm the connection is ready for us.
4506
+ * Get Deposit Detail
4322
4507
  *
4323
- * This method is called to act when the connection is ready. Use `requireConnectionReadyConfirmation` to control how this is called.
4508
+ * This endpoint supports querying the deposit record of sub-accounts created by a Broker
4509
+ * (excluding main account of nd broker).
4510
+ *
4511
+ * Status:
4512
+ * - PROCESSING: Processing
4513
+ * - SUCCESS: Successful
4514
+ * - FAILURE: Failed
4324
4515
  */
4325
- private async onWsReadyForEvents(wsKey: TWSKey)
4326
- ⋮----
4327
- // Resolve & cleanup deferred "connection attempt in progress" promise
4328
- ⋮----
4329
- // Remove before resolving, in case there's more requests queued
4330
- ⋮----
4331
- // Some websockets require an auth packet to be sent after opening the connection
4332
- ⋮----
4333
- // Reconnect to topics known before it connected
4334
- ⋮----
4335
- // Request sub to public topics, if any
4336
- ⋮----
4337
- // Request sub to private topics, if auth on connect isn't needed
4516
+ getDeposit(params: {
4517
+ currency: string;
4518
+ hash: string;
4519
+ }): Promise<APISuccessResponse<BrokerDepositRecord>>
4338
4520
  ⋮----
4339
4521
  /**
4340
- * Handle subscription to private topics _after_ authentication successfully completes asynchronously.
4522
+ * Get Withdrawal Detail
4341
4523
  *
4342
- * Only used for exchanges that require auth before sending private topic subscription requests
4524
+ * This endpoint supports querying the withdrawal records of sub-accounts created by a Broker
4525
+ * (excluding main account of nd broker).
4526
+ *
4527
+ * Status:
4528
+ * - PROCESSING: Processing
4529
+ * - WALLET_PROCESSING: Wallet Processing
4530
+ * - REVIEW: Under Review
4531
+ * - SUCCESS: Successful
4532
+ * - FAILURE: Failed
4343
4533
  */
4344
- private onWsAuthenticated(
4345
- wsKey: TWSKey,
4346
- event: { isWSAPI?: boolean; WSAPIAuthChannel?: string },
4347
- )
4348
- ⋮----
4349
- private onWsMessage(event: unknown, wsKey: TWSKey, ws: WebSocket)
4350
- ⋮----
4351
- // any message can clear the pong timer - wouldn't get a message if the ws wasn't working
4352
- ⋮----
4353
- // console.log(`raw event: `, { data, dataType, emittableEvents });
4354
- ⋮----
4355
- private onWsClose(event: unknown, wsKey: TWSKey)
4356
- ⋮----
4357
- // clean up any pending promises for this connection
4358
- ⋮----
4359
- // clean up any pending promises for this connection
4360
- ⋮----
4361
- private getWs(wsKey: TWSKey)
4362
- ⋮----
4363
- private setWsState(wsKey: TWSKey, state: WsConnectionStateEnum)
4534
+ getWithdrawal(params: {
4535
+ withdrawalId: string;
4536
+ }): Promise<APISuccessResponse<BrokerWithdrawalRecord>>
4364
4537
  ⋮----
4365
4538
  /**
4366
- * Promise-driven method to assert that a ws has successfully connected (will await until connection is open)
4539
+ * Get Broker Rebate
4540
+ *
4541
+ * This interface supports downloading Broker rebate orders.
4542
+ * Returns a URL to download a CSV file containing the rebate data.
4543
+ * The URL is valid for 1 day.
4544
+ * Maximum interval between begin and end dates is 6 months.
4367
4545
  */
4368
- protected async assertIsConnected(wsKey: TWSKey): Promise<unknown>
4369
- ⋮----
4370
- // Already in progress? Await shared promise and retry
4371
- ⋮----
4372
- // Start connection, it should automatically store/return a promise.
4546
+ getBrokerRebate(params: {
4547
+ begin: string;
4548
+ end: string;
4549
+ tradeType: '1' | '2';
4550
+ }): Promise<
4551
+ APISuccessResponse<{
4552
+ url: string;
4553
+ }>
4554
+ > {
4555
+ return this.getPrivate('api/v1/broker/nd/rebase/download', params);
4556
+
4557
+ ================
4558
+ File: .eslintrc.cjs
4559
+ ================
4560
+ // 'no-unused-vars': ['warn'],
4373
4561
 
4374
4562
  ================
4375
4563
  File: src/lib/requestUtils.ts
@@ -4470,187 +4658,299 @@ export function getRestBaseUrl(
4470
4658
  ): string
4471
4659
 
4472
4660
  ================
4473
- File: src/types/request/spot-funding.ts
4661
+ File: src/types/request/futures.types.ts
4474
4662
  ================
4663
+ /**
4664
+ * REST - ACCOUNT - BASIC INFO
4665
+ * Get Account Ledgers - Futures
4666
+ */
4667
+ ⋮----
4668
+ export interface GetTransactionsRequest {
4669
+ startAt?: number;
4670
+ endAt?: number;
4671
+ type?:
4672
+ | 'RealisedPNL'
4673
+ | 'Deposit'
4674
+ | 'Withdrawal'
4675
+ | 'Transferin'
4676
+ | 'TransferOut';
4677
+ offset?: number;
4678
+ maxCount?: number;
4679
+ currency?: string;
4680
+ forward?: boolean;
4681
+ }
4682
+ ⋮----
4683
+ /**
4684
+ * REST - ACCOUNT - SUBACCOUNT API
4685
+ */
4686
+ ⋮----
4687
+ export interface GetSubAPIsRequest {
4688
+ apiKey?: string;
4689
+ subName: string;
4690
+ }
4691
+ ⋮----
4692
+ export interface CreateSubAPIRequest {
4693
+ subName: string;
4694
+ passphrase: string;
4695
+ remark: string;
4696
+ permission?: string;
4697
+ ipWhitelist?: string;
4698
+ expire?: string;
4699
+ }
4700
+ ⋮----
4701
+ export interface UpdateSubAPIRequest {
4702
+ subName: string;
4703
+ apiKey: string;
4704
+ passphrase: string;
4705
+ permission?: string;
4706
+ ipWhitelist?: string;
4707
+ expire?: string;
4708
+ }
4709
+ ⋮----
4710
+ export interface DeleteSubAPIRequest {
4711
+ apiKey: string;
4712
+ passphrase: string;
4713
+ subName: string;
4714
+ }
4715
+ ⋮----
4716
+ /**
4717
+ * REST - FUNDING - FUNDING OVERVIEW
4718
+ */
4719
+ ⋮----
4720
+ /**
4721
+ * REST - FUNDING - TRANSFER
4722
+ */
4723
+ ⋮----
4724
+ export interface SubmitTransfer {
4725
+ amount: number;
4726
+ currency: string;
4727
+ recAccountType: 'MAIN' | 'TRADE';
4728
+ }
4729
+ ⋮----
4730
+ export interface GetTransfersRequest {
4731
+ startAt?: number;
4732
+ endAt?: number;
4733
+ status?: 'PROCESSING' | 'SUCCESS' | 'FAILURE';
4734
+ queryStatus?: 'PROCESSING' | 'SUCCESS' | 'FAILURE'[];
4735
+ currency?: string;
4736
+ currentPage?: number;
4737
+ pageSize?: number;
4738
+ }
4739
+ ⋮----
4740
+ /**
4741
+ *
4742
+ * Futures Market Data
4743
+ *
4744
+ */
4745
+ ⋮----
4746
+ export interface GetKlinesRequest {
4747
+ symbol: string;
4748
+ granularity: number;
4749
+ from?: number;
4750
+ to?: number;
4751
+ }
4752
+ ⋮----
4753
+ export interface GetInterestRatesRequest {
4754
+ symbol: string;
4755
+ startAt?: number;
4756
+ endAt?: number;
4757
+ reverse?: boolean;
4758
+ offset?: number;
4759
+ forward?: boolean;
4760
+ maxCount?: number;
4761
+ }
4762
+ ⋮----
4475
4763
  /**
4476
4764
  *
4477
4765
  ***********
4478
- * Funding
4766
+ * Account
4479
4767
  ***********
4480
4768
  *
4481
4769
  */
4482
4770
  ⋮----
4483
- export interface CreateDepositAddressV3Request {
4484
- currency: string;
4485
- chain?: string;
4486
- to?: 'main' | 'trade';
4487
- amount?: string;
4488
- }
4771
+ /**
4772
+ *
4773
+ * Orders
4774
+ *
4775
+ */
4489
4776
  ⋮----
4490
- export interface GetMarginBalanceRequest {
4491
- quoteCurrency?: string;
4492
- queryType?: 'MARGIN' | 'MARGIN_V2' | 'ALL';
4777
+ export interface Order {
4778
+ clientOid: string;
4779
+ side: 'buy' | 'sell';
4780
+ symbol: string;
4781
+ leverage?: number;
4782
+ type?: 'limit' | 'market';
4783
+ remark?: string;
4784
+ stop?: 'down' | 'up';
4785
+ stopPriceType?: 'TP' | 'MP' | 'IP';
4786
+ stopPrice?: string;
4787
+ reduceOnly?: boolean;
4788
+ closeOrder?: boolean;
4789
+ forceHold?: boolean;
4790
+ stp?: 'CN' | 'CO' | 'CB';
4791
+ marginMode?: 'ISOLATED' | 'CROSS';
4792
+ price?: string;
4793
+ size?: number;
4794
+ qty?: string;
4795
+ valueQty?: string;
4796
+ timeInForce?: 'GTC' | 'IOC';
4797
+ postOnly?: boolean;
4798
+ hidden?: boolean;
4799
+ iceberg?: boolean;
4800
+ visibleSize?: string;
4493
4801
  }
4494
4802
  ⋮----
4495
- export interface GetIsolatedMarginBalanceRequest {
4803
+ export interface SLTPOrder {
4804
+ clientOid: string;
4805
+ side: 'buy' | 'sell';
4806
+ symbol: string;
4807
+ leverage?: number;
4808
+ type: 'limit' | 'market';
4809
+ remark?: string;
4810
+ triggerStopUpPrice?: string;
4811
+ stopPriceType?: 'TP' | 'MP' | 'IP';
4812
+ triggerStopDownPrice?: string;
4813
+ reduceOnly?: boolean;
4814
+ closeOrder?: boolean;
4815
+ forceHold?: boolean;
4816
+ stp?: 'CN' | 'CO' | 'CB';
4817
+ marginMode?: 'ISOLATED' | 'CROSS';
4818
+ price?: string;
4819
+ size?: number;
4820
+ qty?: string;
4821
+ valueQty?: string;
4822
+ timeInForce?: 'GTC' | 'IOC';
4823
+ postOnly?: boolean;
4824
+ hidden?: boolean;
4825
+ iceberg?: boolean;
4826
+ visibleSize?: string;
4827
+ }
4828
+ export interface GetOrdersRequest {
4829
+ status: 'active' | 'done';
4496
4830
  symbol?: string;
4497
- quoteCurrency?: string;
4498
- queryType?: 'ISOLATED' | 'ISOLATED_V2' | 'ALL';
4831
+ side: 'buy' | 'sell';
4832
+ type: 'limit' | 'market' | 'limit_stop' | 'market_stop';
4833
+ startAt?: number;
4834
+ endAt?: number;
4835
+ currentPage?: number;
4836
+ pageSize?: number;
4499
4837
  }
4500
4838
  ⋮----
4501
- /**
4502
- *
4503
- * Deposit
4504
- *
4505
- */
4506
- ⋮----
4507
- export interface GetDepositsRequest {
4508
- currency?: string;
4839
+ export interface GetStopOrdersRequest {
4840
+ symbol?: string;
4841
+ side?: 'buy' | 'sell';
4842
+ type?: 'limit' | 'market';
4509
4843
  startAt?: number;
4510
4844
  endAt?: number;
4511
- status?: 'PROCESSING' | 'SUCCESS' | 'FAILURE';
4512
4845
  currentPage?: number;
4513
4846
  pageSize?: number;
4514
4847
  }
4515
4848
  ⋮----
4849
+ // Note: Either orderIdsList or clientOidsList must be provided, but not both.
4850
+ // When both are provided, orderIdsList takes precedence.
4851
+ export interface BatchCancelOrdersRequest {
4852
+ orderIdsList?: string[];
4853
+ clientOidsList?: {
4854
+ symbol: string;
4855
+ clientOid: string;
4856
+ }[];
4857
+ }
4858
+ ⋮----
4516
4859
  /**
4517
4860
  *
4518
- * Withdrawals
4861
+ * Futures Fills
4519
4862
  *
4520
4863
  */
4521
4864
  ⋮----
4522
- export interface GetWithdrawalsRequest {
4523
- currency?: string;
4524
- status?: 'PROCESSING' | 'WALLET_PROCESSING' | 'SUCCESS' | 'FAILURE';
4865
+ export interface AccountFillsRequest {
4866
+ orderId?: string;
4867
+ symbol?: string;
4868
+ side?: 'buy' | 'sell';
4869
+ type?: 'limit' | 'market' | 'limit_stop' | 'market_stop';
4525
4870
  startAt?: number;
4526
4871
  endAt?: number;
4527
4872
  currentPage?: number;
4528
4873
  pageSize?: number;
4874
+ tradeTypes?: string;
4529
4875
  }
4530
4876
  ⋮----
4531
- export interface ApplyWithdrawRequest {
4532
- currency: string;
4533
- address: string;
4534
- amount: number;
4535
- memo?: string;
4536
- isInner?: boolean;
4537
- remark?: string;
4538
- chain?: string;
4539
- feeDeductType?: 'INTERNAL' | 'EXTERNAL';
4540
- }
4877
+ /**
4878
+ *
4879
+ * Futures Positions
4880
+ *
4881
+ */
4541
4882
  ⋮----
4542
- export interface SubmitWithdrawV3Request {
4543
- currency: string;
4544
- toAddress: string;
4545
- amount: number;
4546
- memo?: string;
4547
- isInner?: boolean;
4548
- remark?: string;
4549
- chain?: string;
4550
- feeDeductType?: 'INTERNAL' | 'EXTERNAL';
4551
- withdrawType: 'ADDRESS' | 'UID' | 'MAIL' | 'PHONE';
4883
+ export interface MaxOpenSizeRequest {
4884
+ symbol: string;
4885
+ price: string;
4886
+ leverage: number;
4552
4887
  }
4553
4888
  ⋮----
4554
4889
  /**
4555
4890
  *
4556
- * Transfer
4891
+ * Futures risk limit
4557
4892
  *
4558
4893
  */
4559
4894
  ⋮----
4560
- export interface GetTransferableRequest {
4561
- currency: string;
4562
- type:
4563
- | 'MAIN'
4564
- | 'TRADE'
4565
- | 'TRADE_HF'
4566
- | 'MARGIN'
4567
- | 'ISOLATED'
4568
- | 'OPTION'
4569
- | 'MARGIN_V2'
4570
- | 'ISOLATED_V2';
4571
- tag?: string;
4572
- }
4895
+ /**
4896
+ *
4897
+ * Futures funding fees
4898
+ *
4899
+ */
4573
4900
  ⋮----
4574
- export interface FlexTransferRequest {
4575
- clientOid: string;
4576
- currency?: string;
4577
- amount: string;
4578
- fromUserId?: string;
4579
- fromAccountType:
4580
- | 'MAIN'
4581
- | 'TRADE'
4582
- | 'CONTRACT'
4583
- | 'MARGIN'
4584
- | 'ISOLATED'
4585
- | 'TRADE_HF'
4586
- | 'MARGIN_V2'
4587
- | 'ISOLATED_V2'
4588
- | 'OPTION';
4589
- fromAccountTag?: string;
4590
- type: 'INTERNAL' | 'PARENT_TO_SUB' | 'SUB_TO_PARENT';
4591
- toUserId?: string;
4592
- toAccountType:
4593
- | 'MAIN'
4594
- | 'TRADE'
4595
- | 'CONTRACT'
4596
- | 'MARGIN'
4597
- | 'ISOLATED'
4598
- | 'TRADE_HF'
4599
- | 'MARGIN_V2'
4600
- | 'ISOLATED_V2'
4601
- | 'OPTION';
4602
- toAccountTag?: string;
4901
+ export interface GetFundingRatesRequest {
4902
+ symbol: string;
4903
+ from: number;
4904
+ to: number;
4603
4905
  }
4604
4906
  ⋮----
4605
- export interface submitTransferMasterSubRequest {
4606
- clientOid: string;
4607
- currency: string;
4608
- amount: string;
4609
- direction: 'OUT' | 'IN';
4610
- accountType?:
4611
- | 'MAIN'
4612
- | 'TRADE'
4613
- | 'TRADE_HF'
4614
- | 'MARGIN'
4615
- | 'CONTRACT'
4616
- | 'OPTION';
4617
- subAccountType?:
4618
- | 'MAIN'
4619
- | 'TRADE'
4620
- | 'TRADE_HF'
4621
- | 'MARGIN'
4622
- | 'CONTRACT'
4623
- | 'OPTION';
4624
- subUserId: string;
4907
+ export interface GetFundingHistoryRequest {
4908
+ symbol: string;
4909
+ from?: number;
4910
+ to?: number;
4911
+ reverse?: boolean;
4912
+ offset?: number;
4913
+ forward?: boolean;
4914
+ maxCount?: number;
4625
4915
  }
4626
4916
  ⋮----
4627
- export interface InnerTransferRequest {
4917
+ /**
4918
+ *
4919
+ * Futures Copy Trading
4920
+ *
4921
+ */
4922
+ ⋮----
4923
+ export interface CopyTradeOrderRequest {
4628
4924
  clientOid: string;
4629
- currency: string;
4630
- from:
4631
- | 'main'
4632
- | 'trade'
4633
- | 'trade_hf'
4634
- | 'margin'
4635
- | 'isolated'
4636
- | 'margin_v2'
4637
- | 'isolated_v2'
4638
- | 'contract'
4639
- | 'option';
4640
- to:
4641
- | 'main'
4642
- | 'trade'
4643
- | 'trade_hf'
4644
- | 'margin'
4645
- | 'isolated'
4646
- | 'margin_v2'
4647
- | 'isolated_v2'
4648
- | 'contract'
4649
- | 'option';
4650
- amount: string;
4651
- fromTag?: string;
4652
- toTag?: string;
4925
+ side: 'buy' | 'sell';
4926
+ symbol: string;
4927
+ type: 'limit' | 'market';
4928
+ leverage?: number;
4929
+ remark?: string;
4930
+ stop?: 'up' | 'down';
4931
+ stopPriceType?: 'TP' | 'MP' | 'IP';
4932
+ stopPrice?: string;
4933
+ reduceOnly?: boolean;
4934
+ closeOrder?: boolean;
4935
+ forceHold?: boolean;
4936
+ marginMode?: 'ISOLATED' | 'CROSS';
4937
+ price?: string;
4938
+ size: number;
4939
+ timeInForce?: 'GTC' | 'IOC';
4940
+ postOnly?: boolean;
4941
+ hidden?: boolean;
4942
+ iceberg?: boolean;
4943
+ visibleSize?: string;
4944
+ }
4945
+ ⋮----
4946
+ export interface CopyTradeSLTPOrderRequest extends CopyTradeOrderRequest {
4947
+ triggerStopUpPrice?: string; // Take profit price
4948
+ triggerStopDownPrice?: string; // Stop loss price
4949
+ stopPriceType?: 'TP' | 'MP' | 'IP';
4653
4950
  }
4951
+ ⋮----
4952
+ triggerStopUpPrice?: string; // Take profit price
4953
+ triggerStopDownPrice?: string; // Stop loss price
4654
4954
 
4655
4955
  ================
4656
4956
  File: src/types/request/spot-trading.ts
@@ -5371,6 +5671,106 @@ export interface LendingRedemption {
5371
5671
  items: LendingOrder[];
5372
5672
  }
5373
5673
 
5674
+ ================
5675
+ File: src/types/websockets/client.ts
5676
+ ================
5677
+ import { AxiosRequestConfig } from 'axios';
5678
+ ⋮----
5679
+ import { RestClientOptions } from '../../lib/requestUtils.js';
5680
+ ⋮----
5681
+ /** General configuration for the WebsocketClient */
5682
+ export interface WSClientConfigurableOptions {
5683
+ /** Your API key */
5684
+ apiKey?: string;
5685
+
5686
+ /** Your API secret */
5687
+ apiSecret?: string;
5688
+
5689
+ /** Your API passphrase (can be anything) that you included when creating this API key */
5690
+ apiPassphrase?: string;
5691
+
5692
+ /** Define a recv window when preparing a private websocket signature. This is in milliseconds, so 5000 == 5 seconds */
5693
+ recvWindow?: number;
5694
+
5695
+ /** How often to check if the connection is alive */
5696
+ pingInterval?: number;
5697
+
5698
+ /** How long to wait for a pong (heartbeat reply) before assuming the connection is dead */
5699
+ pongTimeout?: number;
5700
+
5701
+ /** Delay in milliseconds before respawning the connection */
5702
+ reconnectTimeout?: number;
5703
+
5704
+ restOptions?: RestClientOptions;
5705
+ requestOptions?: AxiosRequestConfig;
5706
+
5707
+ wsOptions?: {
5708
+ protocols?: string[];
5709
+ agent?: any;
5710
+ };
5711
+
5712
+ wsUrl?: string;
5713
+ /**
5714
+ * Allows you to provide a custom "signMessage" function, e.g. to use node's much faster createHmac method
5715
+ *
5716
+ * Look in the examples folder for a demonstration on using node's createHmac instead.
5717
+ */
5718
+ customSignMessageFn?: (message: string, secret: string) => Promise<string>;
5719
+
5720
+ /**
5721
+ * If you authenticated the WS API before, automatically try to re-authenticate the WS API if you're disconnected/reconnected for any reason.
5722
+ */
5723
+ reauthWSAPIOnReconnect?: boolean;
5724
+ }
5725
+ ⋮----
5726
+ /** Your API key */
5727
+ ⋮----
5728
+ /** Your API secret */
5729
+ ⋮----
5730
+ /** Your API passphrase (can be anything) that you included when creating this API key */
5731
+ ⋮----
5732
+ /** Define a recv window when preparing a private websocket signature. This is in milliseconds, so 5000 == 5 seconds */
5733
+ ⋮----
5734
+ /** How often to check if the connection is alive */
5735
+ ⋮----
5736
+ /** How long to wait for a pong (heartbeat reply) before assuming the connection is dead */
5737
+ ⋮----
5738
+ /** Delay in milliseconds before respawning the connection */
5739
+ ⋮----
5740
+ /**
5741
+ * Allows you to provide a custom "signMessage" function, e.g. to use node's much faster createHmac method
5742
+ *
5743
+ * Look in the examples folder for a demonstration on using node's createHmac instead.
5744
+ */
5745
+ ⋮----
5746
+ /**
5747
+ * If you authenticated the WS API before, automatically try to re-authenticate the WS API if you're disconnected/reconnected for any reason.
5748
+ */
5749
+ ⋮----
5750
+ /**
5751
+ * WS configuration that's always defined, regardless of user configuration
5752
+ * (usually comes from defaults if there's no user-provided values)
5753
+ */
5754
+ export interface WebsocketClientOptions extends WSClientConfigurableOptions {
5755
+ pingInterval: number;
5756
+ pongTimeout: number;
5757
+ reconnectTimeout: number;
5758
+ recvWindow: number;
5759
+ /**
5760
+ * If true, require a "receipt" that the connection is ready for use (e.g. a specific event type)
5761
+ */
5762
+ requireConnectionReadyConfirmation: boolean;
5763
+ authPrivateConnectionsOnConnect: boolean;
5764
+ authPrivateRequests: boolean;
5765
+ reauthWSAPIOnReconnect: boolean;
5766
+ }
5767
+ ⋮----
5768
+ /**
5769
+ * If true, require a "receipt" that the connection is ready for use (e.g. a specific event type)
5770
+ */
5771
+ ⋮----
5772
+ export type WsMarket = 'spot' | 'futures';
5773
+
5374
5774
  ================
5375
5775
  File: src/lib/BaseRestClient.ts
5376
5776
  ================
@@ -5389,7 +5789,7 @@ import {
5389
5789
  RestClientType,
5390
5790
  serializeParams,
5391
5791
  } from './requestUtils.js';
5392
- import { signMessage } from './webCryptoAPI.js';
5792
+ import { checkWebCryptoAPISupported, signMessage } from './webCryptoAPI.js';
5393
5793
  ⋮----
5394
5794
  interface SignedRequest<T extends object | undefined = {}> {
5395
5795
  originalParams: T;
@@ -5443,6 +5843,8 @@ constructor(
5443
5843
  // For more advanced configuration, raise an issue on GitHub or use the "networkOptions"
5444
5844
  // parameter to define a custom httpsAgent with the desired properties
5445
5845
  ⋮----
5846
+ // Check Web Crypto API support when credentials are provided
5847
+ ⋮----
5446
5848
  // Throw if one of the 3 values is missing, but at least one of them is set
5447
5849
  ⋮----
5448
5850
  /**
@@ -6032,175 +6434,75 @@ export interface StopOrderItem {
6032
6434
  stopTriggerTime?: number | null;
6033
6435
  stopPrice?: string;
6034
6436
  orderTime?: number;
6035
- }
6036
- ⋮----
6037
- export interface StopOrders {
6038
- currentPage: number;
6039
- pageSize: number;
6040
- totalNum: number;
6041
- totalPage: number;
6042
- items: StopOrderItem[];
6043
- }
6044
- ⋮----
6045
- /**
6046
- *
6047
- * OCO order
6048
- *
6049
- */
6050
- export interface OCOOrderSubOrder {
6051
- id: string; // Sub-order ID
6052
- symbol: string; // Symbol of the sub-order
6053
- side: 'buy' | 'sell'; // Side of the sub-order
6054
- price: string; // Price of the sub-order
6055
- stopPrice: string; // Stop price of the sub-order
6056
- size: string; // Size of the sub-order
6057
- status: 'NEW' | 'DONE' | 'TRIGGERED' | 'CANCELLED'; // Status of the sub-order
6058
- }
6059
- ⋮----
6060
- id: string; // Sub-order ID
6061
- symbol: string; // Symbol of the sub-order
6062
- side: 'buy' | 'sell'; // Side of the sub-order
6063
- price: string; // Price of the sub-order
6064
- stopPrice: string; // Stop price of the sub-order
6065
- size: string; // Size of the sub-order
6066
- status: 'NEW' | 'DONE' | 'TRIGGERED' | 'CANCELLED'; // Status of the sub-order
6067
- ⋮----
6068
- export interface OCOOrderDetails {
6069
- orderId: string; // order id, Unique order id created by users to identify their orders
6070
- symbol: string; // symbol, such as, ETH-BTC
6071
- clientOid: string; // client order id
6072
- orderTime: number; // Order Submitment time, milliseconds
6073
- status: 'NEW' | 'DONE' | 'TRIGGERED' | 'CANCELLED'; // Order status
6074
- orders: OCOOrderSubOrder[];
6075
- }
6076
- ⋮----
6077
- orderId: string; // order id, Unique order id created by users to identify their orders
6078
- symbol: string; // symbol, such as, ETH-BTC
6079
- clientOid: string; // client order id
6080
- orderTime: number; // Order Submitment time, milliseconds
6081
- status: 'NEW' | 'DONE' | 'TRIGGERED' | 'CANCELLED'; // Order status
6082
- ⋮----
6083
- export interface OCOOrderListItem {
6084
- orderId: string; // order id, Unique order id created by users to identify their orders
6085
- symbol: string; // symbol, such as, ETH-BTC
6086
- clientOid: string; // client order id
6087
- orderTime: number; // Order Submitment time, milliseconds
6088
- status: 'NEW' | 'DONE' | 'TRIGGERED' | 'CANCELLED'; // Order status
6089
- }
6090
- ⋮----
6091
- orderId: string; // order id, Unique order id created by users to identify their orders
6092
- symbol: string; // symbol, such as, ETH-BTC
6093
- clientOid: string; // client order id
6094
- orderTime: number; // Order Submitment time, milliseconds
6095
- status: 'NEW' | 'DONE' | 'TRIGGERED' | 'CANCELLED'; // Order status
6096
- ⋮----
6097
- export interface OCOOrders {
6098
- currentPage: number;
6099
- pageSize: number;
6100
- totalNum: number;
6101
- totalPage: number;
6102
- items: OCOOrderListItem[];
6103
- }
6104
-
6105
- ================
6106
- File: src/types/websockets/client.ts
6107
- ================
6108
- import { AxiosRequestConfig } from 'axios';
6109
- ⋮----
6110
- import { RestClientOptions } from '../../lib/requestUtils.js';
6111
- ⋮----
6112
- /** General configuration for the WebsocketClient */
6113
- export interface WSClientConfigurableOptions {
6114
- /** Your API key */
6115
- apiKey?: string;
6116
-
6117
- /** Your API secret */
6118
- apiSecret?: string;
6119
-
6120
- /** Your API passphrase (can be anything) that you included when creating this API key */
6121
- apiPassphrase?: string;
6122
-
6123
- /** Define a recv window when preparing a private websocket signature. This is in milliseconds, so 5000 == 5 seconds */
6124
- recvWindow?: number;
6125
-
6126
- /** How often to check if the connection is alive */
6127
- pingInterval?: number;
6128
-
6129
- /** How long to wait for a pong (heartbeat reply) before assuming the connection is dead */
6130
- pongTimeout?: number;
6131
-
6132
- /** Delay in milliseconds before respawning the connection */
6133
- reconnectTimeout?: number;
6134
-
6135
- restOptions?: RestClientOptions;
6136
- requestOptions?: AxiosRequestConfig;
6137
-
6138
- wsOptions?: {
6139
- protocols?: string[];
6140
- agent?: any;
6141
- };
6142
-
6143
- wsUrl?: string;
6144
- /**
6145
- * Allows you to provide a custom "signMessage" function, e.g. to use node's much faster createHmac method
6146
- *
6147
- * Look in the examples folder for a demonstration on using node's createHmac instead.
6148
- */
6149
- customSignMessageFn?: (message: string, secret: string) => Promise<string>;
6150
-
6151
- /**
6152
- * If you authenticated the WS API before, automatically try to re-authenticate the WS API if you're disconnected/reconnected for any reason.
6153
- */
6154
- reauthWSAPIOnReconnect?: boolean;
6155
- }
6156
- ⋮----
6157
- /** Your API key */
6158
- ⋮----
6159
- /** Your API secret */
6160
- ⋮----
6161
- /** Your API passphrase (can be anything) that you included when creating this API key */
6162
- ⋮----
6163
- /** Define a recv window when preparing a private websocket signature. This is in milliseconds, so 5000 == 5 seconds */
6437
+ }
6164
6438
  ⋮----
6165
- /** How often to check if the connection is alive */
6439
+ export interface StopOrders {
6440
+ currentPage: number;
6441
+ pageSize: number;
6442
+ totalNum: number;
6443
+ totalPage: number;
6444
+ items: StopOrderItem[];
6445
+ }
6166
6446
  ⋮----
6167
- /** How long to wait for a pong (heartbeat reply) before assuming the connection is dead */
6447
+ /**
6448
+ *
6449
+ * OCO order
6450
+ *
6451
+ */
6452
+ export interface OCOOrderSubOrder {
6453
+ id: string; // Sub-order ID
6454
+ symbol: string; // Symbol of the sub-order
6455
+ side: 'buy' | 'sell'; // Side of the sub-order
6456
+ price: string; // Price of the sub-order
6457
+ stopPrice: string; // Stop price of the sub-order
6458
+ size: string; // Size of the sub-order
6459
+ status: 'NEW' | 'DONE' | 'TRIGGERED' | 'CANCELLED'; // Status of the sub-order
6460
+ }
6168
6461
  ⋮----
6169
- /** Delay in milliseconds before respawning the connection */
6462
+ id: string; // Sub-order ID
6463
+ symbol: string; // Symbol of the sub-order
6464
+ side: 'buy' | 'sell'; // Side of the sub-order
6465
+ price: string; // Price of the sub-order
6466
+ stopPrice: string; // Stop price of the sub-order
6467
+ size: string; // Size of the sub-order
6468
+ status: 'NEW' | 'DONE' | 'TRIGGERED' | 'CANCELLED'; // Status of the sub-order
6170
6469
  ⋮----
6171
- /**
6172
- * Allows you to provide a custom "signMessage" function, e.g. to use node's much faster createHmac method
6173
- *
6174
- * Look in the examples folder for a demonstration on using node's createHmac instead.
6175
- */
6470
+ export interface OCOOrderDetails {
6471
+ orderId: string; // order id, Unique order id created by users to identify their orders
6472
+ symbol: string; // symbol, such as, ETH-BTC
6473
+ clientOid: string; // client order id
6474
+ orderTime: number; // Order Submitment time, milliseconds
6475
+ status: 'NEW' | 'DONE' | 'TRIGGERED' | 'CANCELLED'; // Order status
6476
+ orders: OCOOrderSubOrder[];
6477
+ }
6176
6478
  ⋮----
6177
- /**
6178
- * If you authenticated the WS API before, automatically try to re-authenticate the WS API if you're disconnected/reconnected for any reason.
6179
- */
6479
+ orderId: string; // order id, Unique order id created by users to identify their orders
6480
+ symbol: string; // symbol, such as, ETH-BTC
6481
+ clientOid: string; // client order id
6482
+ orderTime: number; // Order Submitment time, milliseconds
6483
+ status: 'NEW' | 'DONE' | 'TRIGGERED' | 'CANCELLED'; // Order status
6180
6484
  ⋮----
6181
- /**
6182
- * WS configuration that's always defined, regardless of user configuration
6183
- * (usually comes from defaults if there's no user-provided values)
6184
- */
6185
- export interface WebsocketClientOptions extends WSClientConfigurableOptions {
6186
- pingInterval: number;
6187
- pongTimeout: number;
6188
- reconnectTimeout: number;
6189
- recvWindow: number;
6190
- /**
6191
- * If true, require a "receipt" that the connection is ready for use (e.g. a specific event type)
6192
- */
6193
- requireConnectionReadyConfirmation: boolean;
6194
- authPrivateConnectionsOnConnect: boolean;
6195
- authPrivateRequests: boolean;
6196
- reauthWSAPIOnReconnect: boolean;
6485
+ export interface OCOOrderListItem {
6486
+ orderId: string; // order id, Unique order id created by users to identify their orders
6487
+ symbol: string; // symbol, such as, ETH-BTC
6488
+ clientOid: string; // client order id
6489
+ orderTime: number; // Order Submitment time, milliseconds
6490
+ status: 'NEW' | 'DONE' | 'TRIGGERED' | 'CANCELLED'; // Order status
6197
6491
  }
6198
6492
  ⋮----
6199
- /**
6200
- * If true, require a "receipt" that the connection is ready for use (e.g. a specific event type)
6201
- */
6493
+ orderId: string; // order id, Unique order id created by users to identify their orders
6494
+ symbol: string; // symbol, such as, ETH-BTC
6495
+ clientOid: string; // client order id
6496
+ orderTime: number; // Order Submitment time, milliseconds
6497
+ status: 'NEW' | 'DONE' | 'TRIGGERED' | 'CANCELLED'; // Order status
6202
6498
  ⋮----
6203
- export type WsMarket = 'spot' | 'futures';
6499
+ export interface OCOOrders {
6500
+ currentPage: number;
6501
+ pageSize: number;
6502
+ totalNum: number;
6503
+ totalPage: number;
6504
+ items: OCOOrderListItem[];
6505
+ }
6204
6506
 
6205
6507
  ================
6206
6508
  File: src/index.ts
@@ -6308,386 +6610,91 @@ async sendWSAPIRequest<
6308
6610
  | object = WsAPITopicResponseMap[TWSChannel],
6309
6611
  >(
6310
6612
  wsKey: TWSKey,
6311
- channel: TWSChannel,
6312
- ...params: TWSParams extends undefined ? [] : [TWSParams]
6313
- ): Promise<TWSAPIResponse>;
6314
- ⋮----
6315
- async sendWSAPIRequest<
6316
- TWSKey extends keyof WsAPIWsKeyTopicMap = keyof WsAPIWsKeyTopicMap,
6317
- TWSChannel extends WsAPIWsKeyTopicMap[TWSKey] = WsAPIWsKeyTopicMap[TWSKey],
6318
- TWSParams extends
6319
- WsAPITopicRequestParamMap[TWSChannel] = WsAPITopicRequestParamMap[TWSChannel],
6320
- >(
6321
- wsKey: TWSKey,
6322
- channel: TWSChannel,
6323
- params?: TWSParams,
6324
- ): Promise<undefined>
6325
- ⋮----
6326
- /**
6327
- *
6328
- * Internal methods
6329
- *
6330
- */
6331
- ⋮----
6332
- /**
6333
- * Whatever url this method returns, it's connected to as-is!
6334
- *
6335
- * If a token or anything else is needed in the URL, this is a good place to add it.
6336
- */
6337
- protected async getWsUrl(wsKey: WsKey): Promise<string>
6338
- ⋮----
6339
- protected sendPingEvent(wsKey: WsKey)
6340
- ⋮----
6341
- protected sendPongEvent(wsKey: WsKey)
6342
- ⋮----
6343
- // Send a protocol layer pong
6344
- ⋮----
6345
- // Not really used for kucoin - they don't send pings
6346
- protected isWsPing(msg: any): boolean
6347
- ⋮----
6348
- protected isWsPong(msg: any): boolean
6349
- ⋮----
6350
- // this.logger.info(`Not a pong: `, msg);
6351
- ⋮----
6352
- protected resolveEmittableEvents(
6353
- wsKey: WsKey,
6354
- event: MessageEventLike,
6355
- ): EmittableEvent[]
6356
- ⋮----
6357
- // These are request/reply pattern events (e.g. after subscribing to topics or authenticating)
6358
- ⋮----
6359
- // Request/reply pattern for authentication success
6360
- ⋮----
6361
- /**
6362
- * Determines if a topic is for a private channel, using a hardcoded list of strings
6363
- */
6364
- protected isPrivateTopicRequest(
6365
- request: WsTopicRequest<string>,
6366
- wsKey: WsKey,
6367
- ): boolean
6368
- ⋮----
6369
- protected getWsKeyForMarket(market: WsMarket, isPrivate: boolean): WsKey
6370
- ⋮----
6371
- protected getWsMarketForWsKey(key: WsKey): WsMarket
6372
- ⋮----
6373
- protected getPrivateWSKeys(): WsKey[]
6374
- ⋮----
6375
- /** Force subscription requests to be sent in smaller batches, if a number is returned */
6376
- protected getMaxTopicsPerSubscribeEvent(wsKey: WsKey): number | null
6377
- ⋮----
6378
- // Return a number if there's a limit on the number of sub topics per rq
6379
- // Always 1 at a time for this exchange
6380
- ⋮----
6381
- /**
6382
- * Map one or more topics into fully prepared "subscribe request" events (already stringified and ready to send)
6383
- */
6384
- protected async getWsOperationEventsForTopics(
6385
- topicRequests: WsTopicRequest<string>[],
6386
- wsKey: WsKey,
6387
- operation: WsOperation,
6388
- ): Promise<string[]>
6389
- ⋮----
6390
- // Operations structured in a way that this exchange understands
6391
- ⋮----
6392
- // Events that are ready to send (usually stringified JSON)
6393
- ⋮----
6394
- // Not used for kucoin - auth is part of the WS URL
6395
- protected async getWsAuthRequestEvent(wsKey: WsKey): Promise<object>
6396
-
6397
- ================
6398
- File: src/types/request/futures.types.ts
6399
- ================
6400
- /**
6401
- * REST - ACCOUNT - BASIC INFO
6402
- * Get Account Ledgers - Futures
6403
- */
6404
- ⋮----
6405
- export interface GetTransactionsRequest {
6406
- startAt?: number;
6407
- endAt?: number;
6408
- type?:
6409
- | 'RealisedPNL'
6410
- | 'Deposit'
6411
- | 'Withdrawal'
6412
- | 'Transferin'
6413
- | 'TransferOut';
6414
- offset?: number;
6415
- maxCount?: number;
6416
- currency?: string;
6417
- forward?: boolean;
6418
- }
6419
- ⋮----
6420
- /**
6421
- * REST - ACCOUNT - SUBACCOUNT API
6422
- */
6423
- ⋮----
6424
- export interface GetSubAPIsRequest {
6425
- apiKey?: string;
6426
- subName: string;
6427
- }
6428
- ⋮----
6429
- export interface CreateSubAPIRequest {
6430
- subName: string;
6431
- passphrase: string;
6432
- remark: string;
6433
- permission?: string;
6434
- ipWhitelist?: string;
6435
- expire?: string;
6436
- }
6437
- ⋮----
6438
- export interface UpdateSubAPIRequest {
6439
- subName: string;
6440
- apiKey: string;
6441
- passphrase: string;
6442
- permission?: string;
6443
- ipWhitelist?: string;
6444
- expire?: string;
6445
- }
6446
- ⋮----
6447
- export interface DeleteSubAPIRequest {
6448
- apiKey: string;
6449
- passphrase: string;
6450
- subName: string;
6451
- }
6452
- ⋮----
6453
- /**
6454
- * REST - FUNDING - FUNDING OVERVIEW
6455
- */
6456
- ⋮----
6457
- /**
6458
- * REST - FUNDING - TRANSFER
6459
- */
6460
- ⋮----
6461
- export interface SubmitTransfer {
6462
- amount: number;
6463
- currency: string;
6464
- recAccountType: 'MAIN' | 'TRADE';
6465
- }
6466
- ⋮----
6467
- export interface GetTransfersRequest {
6468
- startAt?: number;
6469
- endAt?: number;
6470
- status?: 'PROCESSING' | 'SUCCESS' | 'FAILURE';
6471
- queryStatus?: 'PROCESSING' | 'SUCCESS' | 'FAILURE'[];
6472
- currency?: string;
6473
- currentPage?: number;
6474
- pageSize?: number;
6475
- }
6613
+ channel: TWSChannel,
6614
+ ...params: TWSParams extends undefined ? [] : [TWSParams]
6615
+ ): Promise<TWSAPIResponse>;
6616
+ ⋮----
6617
+ async sendWSAPIRequest<
6618
+ TWSKey extends keyof WsAPIWsKeyTopicMap = keyof WsAPIWsKeyTopicMap,
6619
+ TWSChannel extends WsAPIWsKeyTopicMap[TWSKey] = WsAPIWsKeyTopicMap[TWSKey],
6620
+ TWSParams extends
6621
+ WsAPITopicRequestParamMap[TWSChannel] = WsAPITopicRequestParamMap[TWSChannel],
6622
+ >(
6623
+ wsKey: TWSKey,
6624
+ channel: TWSChannel,
6625
+ params?: TWSParams,
6626
+ ): Promise<undefined>
6476
6627
  ⋮----
6477
6628
  /**
6478
- *
6479
- * Futures Market Data
6480
- *
6481
- */
6629
+ *
6630
+ * Internal methods
6631
+ *
6632
+ */
6482
6633
  ⋮----
6483
- export interface GetKlinesRequest {
6484
- symbol: string;
6485
- granularity: number;
6486
- from?: number;
6487
- to?: number;
6488
- }
6634
+ /**
6635
+ * Whatever url this method returns, it's connected to as-is!
6636
+ *
6637
+ * If a token or anything else is needed in the URL, this is a good place to add it.
6638
+ */
6639
+ protected async getWsUrl(wsKey: WsKey): Promise<string>
6489
6640
  ⋮----
6490
- export interface GetInterestRatesRequest {
6491
- symbol: string;
6492
- startAt?: number;
6493
- endAt?: number;
6494
- reverse?: boolean;
6495
- offset?: number;
6496
- forward?: boolean;
6497
- maxCount?: number;
6498
- }
6641
+ protected sendPingEvent(wsKey: WsKey)
6499
6642
  ⋮----
6500
- /**
6501
- *
6502
- ***********
6503
- * Account
6504
- ***********
6505
- *
6506
- */
6643
+ protected sendPongEvent(wsKey: WsKey)
6507
6644
  ⋮----
6508
- /**
6509
- *
6510
- * Orders
6511
- *
6512
- */
6645
+ // Send a protocol layer pong
6513
6646
  ⋮----
6514
- export interface Order {
6515
- clientOid: string;
6516
- side: 'buy' | 'sell';
6517
- symbol: string;
6518
- leverage?: number;
6519
- type?: 'limit' | 'market';
6520
- remark?: string;
6521
- stop?: 'down' | 'up';
6522
- stopPriceType?: 'TP' | 'MP' | 'IP';
6523
- stopPrice?: string;
6524
- reduceOnly?: boolean;
6525
- closeOrder?: boolean;
6526
- forceHold?: boolean;
6527
- stp?: 'CN' | 'CO' | 'CB';
6528
- marginMode?: 'ISOLATED' | 'CROSS';
6529
- price?: string;
6530
- size?: number;
6531
- qty?: string;
6532
- valueQty?: string;
6533
- timeInForce?: 'GTC' | 'IOC';
6534
- postOnly?: boolean;
6535
- hidden?: boolean;
6536
- iceberg?: boolean;
6537
- visibleSize?: string;
6538
- }
6647
+ // Not really used for kucoin - they don't send pings
6648
+ protected isWsPing(msg: any): boolean
6539
6649
  ⋮----
6540
- export interface SLTPOrder {
6541
- clientOid: string;
6542
- side: 'buy' | 'sell';
6543
- symbol: string;
6544
- leverage?: number;
6545
- type: 'limit' | 'market';
6546
- remark?: string;
6547
- triggerStopUpPrice?: string;
6548
- stopPriceType?: 'TP' | 'MP' | 'IP';
6549
- triggerStopDownPrice?: string;
6550
- reduceOnly?: boolean;
6551
- closeOrder?: boolean;
6552
- forceHold?: boolean;
6553
- stp?: 'CN' | 'CO' | 'CB';
6554
- marginMode?: 'ISOLATED' | 'CROSS';
6555
- price?: string;
6556
- size?: number;
6557
- qty?: string;
6558
- valueQty?: string;
6559
- timeInForce?: 'GTC' | 'IOC';
6560
- postOnly?: boolean;
6561
- hidden?: boolean;
6562
- iceberg?: boolean;
6563
- visibleSize?: string;
6564
- }
6565
- export interface GetOrdersRequest {
6566
- status: 'active' | 'done';
6567
- symbol?: string;
6568
- side: 'buy' | 'sell';
6569
- type: 'limit' | 'market' | 'limit_stop' | 'market_stop';
6570
- startAt?: number;
6571
- endAt?: number;
6572
- currentPage?: number;
6573
- pageSize?: number;
6574
- }
6650
+ protected isWsPong(msg: any): boolean
6575
6651
  ⋮----
6576
- export interface GetStopOrdersRequest {
6577
- symbol?: string;
6578
- side?: 'buy' | 'sell';
6579
- type?: 'limit' | 'market';
6580
- startAt?: number;
6581
- endAt?: number;
6582
- currentPage?: number;
6583
- pageSize?: number;
6584
- }
6652
+ // this.logger.info(`Not a pong: `, msg);
6585
6653
  ⋮----
6586
- // Note: Either orderIdsList or clientOidsList must be provided, but not both.
6587
- // When both are provided, orderIdsList takes precedence.
6588
- export interface BatchCancelOrdersRequest {
6589
- orderIdsList?: string[];
6590
- clientOidsList?: {
6591
- symbol: string;
6592
- clientOid: string;
6593
- }[];
6594
- }
6654
+ protected resolveEmittableEvents(
6655
+ wsKey: WsKey,
6656
+ event: MessageEventLike,
6657
+ ): EmittableEvent[]
6595
6658
  ⋮----
6596
- /**
6597
- *
6598
- * Futures Fills
6599
- *
6600
- */
6659
+ // These are request/reply pattern events (e.g. after subscribing to topics or authenticating)
6601
6660
  ⋮----
6602
- export interface AccountFillsRequest {
6603
- orderId?: string;
6604
- symbol?: string;
6605
- side?: 'buy' | 'sell';
6606
- type?: 'limit' | 'market' | 'limit_stop' | 'market_stop';
6607
- startAt?: number;
6608
- endAt?: number;
6609
- currentPage?: number;
6610
- pageSize?: number;
6611
- tradeTypes?: string;
6612
- }
6661
+ // Request/reply pattern for authentication success
6613
6662
  ⋮----
6614
6663
  /**
6615
- *
6616
- * Futures Positions
6617
- *
6618
- */
6664
+ * Determines if a topic is for a private channel, using a hardcoded list of strings
6665
+ */
6666
+ protected isPrivateTopicRequest(
6667
+ request: WsTopicRequest<string>,
6668
+ wsKey: WsKey,
6669
+ ): boolean
6619
6670
  ⋮----
6620
- export interface MaxOpenSizeRequest {
6621
- symbol: string;
6622
- price: string;
6623
- leverage: number;
6624
- }
6671
+ protected getWsKeyForMarket(market: WsMarket, isPrivate: boolean): WsKey
6625
6672
  ⋮----
6626
- /**
6627
- *
6628
- * Futures risk limit
6629
- *
6630
- */
6673
+ protected getWsMarketForWsKey(key: WsKey): WsMarket
6631
6674
  ⋮----
6632
- /**
6633
- *
6634
- * Futures funding fees
6635
- *
6636
- */
6675
+ protected getPrivateWSKeys(): WsKey[]
6637
6676
  ⋮----
6638
- export interface GetFundingRatesRequest {
6639
- symbol: string;
6640
- from: number;
6641
- to: number;
6642
- }
6677
+ /** Force subscription requests to be sent in smaller batches, if a number is returned */
6678
+ protected getMaxTopicsPerSubscribeEvent(wsKey: WsKey): number | null
6643
6679
  ⋮----
6644
- export interface GetFundingHistoryRequest {
6645
- symbol: string;
6646
- from?: number;
6647
- to?: number;
6648
- reverse?: boolean;
6649
- offset?: number;
6650
- forward?: boolean;
6651
- maxCount?: number;
6652
- }
6680
+ // Return a number if there's a limit on the number of sub topics per rq
6681
+ // Always 1 at a time for this exchange
6653
6682
  ⋮----
6654
6683
  /**
6655
- *
6656
- * Futures Copy Trading
6657
- *
6658
- */
6684
+ * Map one or more topics into fully prepared "subscribe request" events (already stringified and ready to send)
6685
+ */
6686
+ protected async getWsOperationEventsForTopics(
6687
+ topicRequests: WsTopicRequest<string>[],
6688
+ wsKey: WsKey,
6689
+ operation: WsOperation,
6690
+ ): Promise<string[]>
6659
6691
  ⋮----
6660
- export interface CopyTradeOrderRequest {
6661
- clientOid: string;
6662
- side: 'buy' | 'sell';
6663
- symbol: string;
6664
- type: 'limit' | 'market';
6665
- leverage?: number;
6666
- remark?: string;
6667
- stop?: 'up' | 'down';
6668
- stopPriceType?: 'TP' | 'MP' | 'IP';
6669
- stopPrice?: string;
6670
- reduceOnly?: boolean;
6671
- closeOrder?: boolean;
6672
- forceHold?: boolean;
6673
- marginMode?: 'ISOLATED' | 'CROSS';
6674
- price?: string;
6675
- size: number;
6676
- timeInForce?: 'GTC' | 'IOC';
6677
- postOnly?: boolean;
6678
- hidden?: boolean;
6679
- iceberg?: boolean;
6680
- visibleSize?: string;
6681
- }
6692
+ // Operations structured in a way that this exchange understands
6682
6693
  ⋮----
6683
- export interface CopyTradeSLTPOrderRequest extends CopyTradeOrderRequest {
6684
- triggerStopUpPrice?: string; // Take profit price
6685
- triggerStopDownPrice?: string; // Stop loss price
6686
- stopPriceType?: 'TP' | 'MP' | 'IP';
6687
- }
6694
+ // Events that are ready to send (usually stringified JSON)
6688
6695
  ⋮----
6689
- triggerStopUpPrice?: string; // Take profit price
6690
- triggerStopDownPrice?: string; // Stop loss price
6696
+ // Not used for kucoin - auth is part of the WS URL
6697
+ protected async getWsAuthRequestEvent(wsKey: WsKey): Promise<object>
6691
6698
 
6692
6699
  ================
6693
6700
  File: src/types/response/spot-funding.ts
@@ -6999,6 +7006,7 @@ Updated & performant JavaScript & Node.js SDK for the Kucoin REST APIs and WebSo
6999
7006
  - [Private WebSocket Streams](#private-websocket-streams)
7000
7007
  - [Customise Logging](#customise-logging)
7001
7008
  - [LLMs & AI](#use-with-llms--ai)
7009
+ - [Used By](#used-by)
7002
7010
  - [Contributions & Thanks](#contributions--thanks)
7003
7011
 
7004
7012
  ## Installation
@@ -7271,6 +7279,12 @@ This file contains AI optimised structure of all the functions in this package,
7271
7279
 
7272
7280
  ---
7273
7281
 
7282
+ ## Used By
7283
+
7284
+ [![Repository Users Preview Image](https://dependents.info/tiagosiebler/kucoin-api/image)](https://github.com/tiagosiebler/kucoin-api/network/dependents)
7285
+
7286
+ ---
7287
+
7274
7288
  <!-- template_contributions -->
7275
7289
 
7276
7290
  ### Contributions & Thanks
@@ -11259,7 +11273,7 @@ File: package.json
11259
11273
  ================
11260
11274
  {
11261
11275
  "name": "kucoin-api",
11262
- "version": "2.1.19",
11276
+ "version": "2.1.20",
11263
11277
  "description": "Complete & robust Node.js SDK for Kucoin's REST APIs and WebSockets, with TypeScript & strong end to end tests.",
11264
11278
  "scripts": {
11265
11279
  "clean": "rm -rf dist",
@@ -11287,9 +11301,9 @@ File: package.json
11287
11301
  "Jerko J (https://github.com/JJ-Cro)"
11288
11302
  ],
11289
11303
  "dependencies": {
11290
- "axios": "^1.7.4",
11304
+ "axios": "^1.10.0",
11291
11305
  "isomorphic-ws": "^4.0.1",
11292
- "nanoid": "^3.3.7",
11306
+ "nanoid": "^3.3.11",
11293
11307
  "ws": "^7.4.0"
11294
11308
  },
11295
11309
  "devDependencies": {