tiagosiebler / okx-api

Node.js SDK for the OKX APIs and WebSockets, with TypeScript & browser support, integration tests, beautification & more.
MIT License
74 stars 23 forks source link

Ws - buy, cancel and sell orders #19

Open korzh875 opened 1 year ago

korzh875 commented 1 year ago

Thanks for your work

I'm trying to find a library to work with okx api and now I'm trying to figure out how I can use not rest, but sockets to buy, cancel, sell orders. Does the library support it? but the example is not very clear

tiagosiebler commented 1 year ago

Hi, I guess you're the same person that asked this in the telegram group. Not yet, not without a code change.

Take a look at the websocket client. It manages connections and stores them in a key value store. Should be a way to make a connection dedicated for this use case and then maybe something like the sendAuthRequest method can be made to handle sending events on that dedicated connection

https://github.com/tiagosiebler/okx-api/blob/master/src/websocket-client.ts

Would like to add support for this in future but haven't had the bandwidth to explore this properly yet.

leosmartdev commented 1 year ago

Hi, @tiagosiebler This is Leo who just asked in telegram group about the same issue regarding order api issue from websocket client. and I want to contribute and try to implement it in the future, if you don't mind.

tiagosiebler commented 1 month ago

Hey @korzh875, @sezmars & @leosmartdev - tagging you since you've asked about the WS API before.

I will soon work to add WS API support to my existing SDKs. We've just released a new SDK for Gate.io, which has the first generation of a working WS API implementation. It's a different exchange, but I would appreciate if you could either take a look or even test the WS API implementation because this is a great chance to provide feedback before I add it to my existing SDKs as well.

The goal was for the WS API implementation to be as flexible as possible, while also being convenient for users that are more familiar with how the REST API works. Thus, for the first generation of this there are two possible ways of using the WS API.

Event-driven WebSocket API

The first way is probably what you would expect - event-driven.

Events are fire & forget - you call a function to send a WS API event (similar to how you would subscribe to a topic in the websocket client), for example (ignore the await in the link):

client.sendWSAPIRequest(
      'spotV4',
      'spot.order_place',
      {
        text: 't-my-custom-id',
        currency_pair: 'BTC_USDT',
        type: 'limit',
        account: 'spot',
        side: 'buy',
        amount: '0.001',
        price: '45000',
      },
    );

When the server sends a reply to your request, it will be emitted via the event emitter's 'response' event: https://github.com/tiagosiebler/gateio-api/blob/master/examples/ws-private-spot-wsapi.ts#L68-L75

// ws server reply { someJsonResponse: .... }
  client.on('response', (data) => {
    console.info(
      'ws server reply ',
      JSON.stringify(data, null, 2),
      '\n',
    );
  });

Promise-driven WebSocket API

The second way will feel very much like the REST API - promise-driven.

Each "request" includes a unique ID, which gives enough information to know which response is for which request. I've implemented a deferred-promise mechanism that tracks this within the Websocket Client. The end result is something I'm proud of - you can call the WS API and await the response:

    console.log(new Date(), 'Submitting spot order!');
    const newOrder = await client.sendWSAPIRequest(
      'spotV4',
      'spot.order_place',
      {
        text: 't-my-custom-id',
        currency_pair: 'BTC_USDT',
        type: 'limit',
        account: 'spot',
        side: 'buy',
        amount: '0.001',
        price: '45000',
      },
    );

    console.log(new Date(), 'Result:', newOrder);

With the WebSocket API there is always the risk that a connection is temporarily lost before you send a request. That would mean the request might not reach the server. The SDK will continue to use heartbeats to monitor connection health. If a connection seems to be lost, it will terminate and respawn the WS API connection (similar to existing websockets). In addition, any of these "deferred promises" will be rejected with a clear message, if they haven't received a reply yet - giving the caller a clear view of which requests may have never reached the server.

Rich Conditional Types

As an added bonus for typescript users, types are connected in such a way that typescript knows what the response type will be, depending on what channel the request went to. Requests, request parameters and response parameters have type checking in place (although some types are initially still missing).

With this design it's completely up to the user if they want event-driven or promise-driven WS API behaviour. I wanted to cater to both user types, while making it extremely easy for someone uncomfortable with websockets to benefit from intuitive calls to the WS API. I hope you have a chance to test it & that the implementation behaves as you expect it to. Would love to hear your feedback if you do manage to test it. Otherwise, a very similar implementation will be coming soon for my existing SDKs for exchanges that also support a Websocket API.