Skip to content

Commit 81d9dc5

Browse files
authored
Merge pull request #57 from tiagosiebler/wsapiclient
feat(): add REST-like WS API Client class
2 parents 415bc6e + f6de8e7 commit 81d9dc5

36 files changed

+1866
-269
lines changed

.nvmrc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
v20.11.0
2-
1+
v22.17.0

README.md

Lines changed: 93 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Node.js & JavaScript SDK for Gate.io REST APIs, WebSockets & WebSocket API
1+
# Node.js & JavaScript SDK for Gate.com (Gate.io) REST APIs, WebSockets & WebSocket API
22

33
<p align="center">
44
<a href="https://www.npmjs.com/package/gateio-api">
@@ -18,27 +18,27 @@
1818

1919
[1]: https://www.npmjs.com/package/gateio-api
2020

21-
Updated & performant JavaScript & Node.js SDK for the Gate.io REST APIs and WebSockets:
21+
Updated & performant JavaScript & Node.js SDK for the Gate.com (gate.io) REST APIs and WebSockets:
2222

23-
- Extensive integration with Gate.io REST APIs and WebSockets.
23+
- Extensive integration with Gate.com (Gate.io) REST APIs and WebSockets.
2424
- TypeScript support (with type declarations for most API requests & responses).
25-
- Gate.io REST APIs for Gate.io Spot, Margin, Perpetual Futures, Delivery Futures, Options & Announcements APIs.
25+
- Gate.com REST APIs for Gate.com Spot, Margin, Perpetual Futures, Delivery Futures, Options & Announcements APIs.
2626
- Strongly typed on most requests and responses.
27-
- Extremely robust & performant JavaScript/Node.js Gate.io SDK.
27+
- Extremely robust & performant JavaScript/Node.js Gate.com SDK.
2828
- Actively maintained with a modern, promise-driven interface.
29-
- Support for seamless API authentication for private Gate.io REST API and WebSocket calls.
30-
- Gate.io Spot, Margin, Perpetual Futures, Delivery Futures & Options.
29+
- Support for seamless API authentication for private Gate.com REST API and WebSocket calls.
30+
- Gate.com Spot, Margin, Perpetual Futures, Delivery Futures & Options.
3131
- Event driven messaging.
3232
- Smart websocket persistence
3333
- Automatically handle silent websocket disconnections through timed heartbeats, including the scheduled 24hr disconnect.
3434
- Automatically handle listenKey persistence and expiration/refresh.
3535
- Emit `reconnected` event when dropped connection is restored.
36-
- Websocket API for Gate.io Spot, Margin, Perpetual Futures & Delivery Futures.
36+
- Websocket API for Gate.com Spot, Margin, Perpetual Futures & Delivery Futures.
3737
- Automatic connectivity via existing WebsocketClient, just call sendWSAPIRequest to trigger a request.
3838
- Automatic authentication, just call sendWSAPIRequest with channel & parameters.
3939
- Choose between two interfaces for WS API communication:
4040
- Event-driven interface, fire & forget via sendWSAPIRequest and receive async replies via wsClient's event emitter.
41-
- Promise-driven interface, simply call and await sendWSAPIRequest for a REST-API-like behaviour with the WS API.
41+
- Promise-driven interface, simply use the WebsocketAPIClient for a REST-like experience. Use the WebSocket API like a REST API! See [examples/ws-api-client.ts](./examples/ws-api-client.ts) for a demonstration.
4242
- Proxy support via axios integration.
4343
- Active community support & collaboration in telegram: [Node.js Algo Traders](https://t.me/nodetraders).
4444

@@ -78,7 +78,7 @@ Check out my related JavaScript/TypeScript/Node.js projects:
7878

7979
Most methods accept JS objects. These can be populated using parameters specified by gateio's API documentation.
8080

81-
- [Gate.io API Documentation](https://www.gate.io/docs/developers/apiv4/en/)
81+
- [Gate.com/gate.io API Documentation](https://www.gate.com/docs/developers/apiv4/en/)
8282
- [REST Endpoint Function List](./docs/endpointFunctionList.md)
8383
- [TSDoc Documentation (autogenerated using typedoc)](https://tsdocs.dev/docs/gateio-api)
8484

@@ -95,11 +95,11 @@ This project uses typescript. Resources are stored in 2 key structures:
9595

9696
Create API credentials
9797

98-
- [Gate.io API Key Management](https://www.gate.io/myaccount/api_key_manage)
98+
- [Gate.com API Key Management](https://www.gate.com/myaccount/api_key_manage)
9999

100100
### REST API
101101

102-
To use any of Gate.io's REST APIs in JavaScript/TypeScript/Node.js, import (or require) the `RestClient`:
102+
To use any of Gate.com's REST APIs in JavaScript/TypeScript/Node.js, import (or require) the `RestClient`:
103103

104104
```javascript
105105
const { RestClient } = require('gateio-api');
@@ -252,107 +252,114 @@ See [WebsocketClient](./src/WebsocketClient.ts) for further information and make
252252

253253
### Websocket API
254254

255-
The [WebsocketClient](./src/WebsocketClient.ts) supports this exchange's Websocket API. There are two ways to use the WS API, depending on individual preference:
255+
Gate.com supports sending requests (commands) over an active WebSocket connection. This is called the WebSocket API.
256+
257+
The WebSocket API is available through two approaches, depending on individual preference:
258+
259+
#### Event Driven API
260+
261+
The WebSocket API is available in the [WebsocketClient](./src/WebsocketClient.ts) via the `sendWSAPIRequest(wsKey, channel, params)` method.
262+
263+
Each call to this method is wrapped in a promise, which you can async await for a response, or handle it in a raw event-driven design.
256264

257265
- event-driven:
258-
- send requests via `client.sendWSAPIRequest(wsKey, channel, params)`, fire and forget, don't use await
266+
- send requests via `client.sendWSAPIRequest(wsKey, channel, params).catch(e => console.error('WS API exception for channel', channel, e))`, fire and forget, don't use await
259267
- handle async replies via event handlers on `client.on('exception', cb)` and `client.on('response', cb)`
260268
- promise-driven:
261269
- send requests via `const result = await client.sendWSAPIRequest(wsKey, channel, params)`, which returns a promise
262270
- await each call
263271
- use try/catch blocks to handle promise rejections
264272

265-
The below example demonstrates the promise-driven approach, which behaves similar to a REST API. For more detailed examples, refer to the [examples](./examples/) folder (e.g the [ws-private-spot-wsapi.ts](./examples/ws-private-spot-wsapi.ts) example).
273+
#### REST-like API
274+
275+
The WebSocket API is also available in a promise-wrapped REST-like format. Either, as above, await any calls to `sendWSAPIRequest(...)`, or directly use the convenient WebsocketAPIClient. This class is very similar to existing REST API classes (such as the RestClient).
276+
277+
It provides one function per endpoint, feels like a REST API and will automatically route your request via an automatically persisted, authenticated and health-checked WebSocket API connection.
278+
279+
Below is an example showing how easy it is to use the WebSocket API without any concern for the complexity of managing WebSockets.
266280

267281
```javascript
268-
const { WebsocketClient } = require('gateio-api');
282+
const { WebsocketAPIClient } = require('gateio-api');
269283

270284
const API_KEY = 'xxx';
271-
const PRIVATE_KEY = 'yyy';
285+
const API_SECRET = 'yyy';
272286

273287
async function start() {
274-
const client = new WebsocketClient({
288+
// Make an instance of the WS API Client
289+
const wsClient = new WebsocketAPIClient({
275290
apiKey: API_KEY,
276-
apiSecret: PRIVATE_KEY,
291+
apiSecret: API_SECRET,
277292
// Automatically re-auth WS API, if we were auth'd before and get reconnected
278293
reauthWSAPIOnReconnect: true,
279294
});
280295

281-
/**
282-
* Setup basic event handlers for core connectivity events.
283-
* Note for this approach, the `response` and `update` events are not needed (but you can use them too/instead if you prefer).
284-
**/
285-
286-
// Successfully connected
287-
client.on('open', (data) => {
288-
console.log(new Date(), 'ws connected ', data?.wsKey);
289-
});
290-
291-
// Something happened, attempting to reconnect
292-
client.on('reconnect', (data) => {
293-
console.log(new Date(), 'ws reconnect: ', data);
294-
});
295-
296-
// Reconnect successful
297-
client.on('reconnected', (data) => {
298-
console.log(new Date(), 'ws reconnected: ', data);
299-
});
300-
301-
// Connection closed. If unexpected, expect reconnect -> reconnected.
302-
client.on('close', (data) => {
303-
console.error(new Date(), 'ws close: ', data);
304-
});
305-
306-
client.on('exception', (data) => {
307-
console.error(new Date(), 'ws exception: ', data);
308-
});
309-
310-
client.on('authenticated', (data) => {
311-
console.error(new Date(), 'ws authenticated: ', data);
312-
});
313-
314296
try {
315-
/**
316-
* All WebSocket API (WS API) messaging should be done via the sendWSAPIRequest method.
317-
*/
318-
319-
// The WSKey identifies which connection this request is for.
320-
// (e.g. "spotV4" | "perpFuturesUSDTV4" | "perpFuturesBTCV4" | "deliveryFuturesUSDTV4" | "deliveryFuturesBTCV4" | "optionsV4")
321-
const wsKey = 'spotV4';
322-
323-
/**
324-
* To authenticate, send an empty request to "spot.login". The SDK will handle all the parameters.
325-
*
326-
* By default (reauthWSAPIOnReconnect: true), if we get reconnected later on (e.g. connection temporarily lost), we will try to re-authenticate the WS API automatically when the connection is restored.
327-
*/
328-
console.log(new Date(), 'try authenticate');
329-
const loginResult = await client.sendWSAPIRequest(wsKey, 'spot.login');
330-
console.log(new Date(), 'authenticated!', loginResult);
331-
332-
/**
333-
* For other channels, you should include any parameters for the request (the payload) in your call.
334-
*
335-
* Note that internal parameters such as "signature" etc are all handled automatically by the SDK. Only the core request parameters are needed.
336-
*/
337-
console.log(new Date(), 'try get order status');
338-
const orderStatus = await client.sendWSAPIRequest(
339-
wsKey,
340-
'spot.order_status',
341-
{
342-
order_id: '600995435390',
343-
currency_pair: 'BTC_USDT',
344-
},
345-
);
346-
347-
console.log(new Date(), 'orderStatus result!', orderStatus);
297+
// Connection will authenticate automatically before first request
298+
// Make WebSocket API calls, very similar to a REST API:
299+
300+
/* ============ SPOT TRADING EXAMPLES ============ */
301+
302+
// Submit a new spot order
303+
const newOrder = await wsClient.submitNewSpotOrder({
304+
text: 't-my-custom-id',
305+
currency_pair: 'BTC_USDT',
306+
type: 'limit',
307+
account: 'spot',
308+
side: 'buy',
309+
amount: '1',
310+
price: '10000',
311+
});
312+
console.log('Order result:', newOrder.data);
313+
314+
// Cancel a spot order
315+
const cancelOrder = await wsClient.cancelSpotOrder({
316+
order_id: '1700664330',
317+
currency_pair: 'BTC_USDT',
318+
account: 'spot',
319+
});
320+
console.log('Cancel result:', cancelOrder.data);
321+
322+
// Get spot order status
323+
const orderStatus = await wsClient.getSpotOrderStatus({
324+
order_id: '1700664330',
325+
currency_pair: 'BTC_USDT',
326+
account: 'spot',
327+
});
328+
console.log('Order status:', orderStatus.data);
329+
330+
/* ============ FUTURES TRADING EXAMPLES ============ */
331+
332+
// Submit a new futures order
333+
const newFuturesOrder = await wsClient.submitNewFuturesOrder({
334+
contract: 'BTC_USDT',
335+
size: 10,
336+
price: '31503.28',
337+
tif: 'gtc',
338+
text: 't-my-custom-id',
339+
});
340+
console.log('Futures order result:', newFuturesOrder.data);
341+
342+
// Cancel a futures order
343+
const cancelFuturesOrder = await wsClient.cancelFuturesOrder({
344+
order_id: '74046514',
345+
});
346+
console.log('Cancel futures order result:', cancelFuturesOrder.data);
347+
348+
// Get futures order status
349+
const futuresOrderStatus = await wsClient.getFuturesOrderStatus({
350+
order_id: '74046543',
351+
});
352+
console.log('Futures order status:', futuresOrderStatus.data);
348353
} catch (e) {
349-
console.error(`WS API Error: `, e);
354+
console.error('WS API Error:', e);
350355
}
351356
}
352357

353358
start();
354359
```
355360

361+
For more detailed examples using any approach, refer to the [examples](./examples/) folder (e.g. [ws-api-client.ts](./examples/ws-api-client.ts)).
362+
356363
---
357364

358365
## Customise Logging

docs/endpointFunctionList.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ All REST clients are in the [src](/src) folder. For usage examples, make sure to
2020

2121
List of clients:
2222
- [RestClient](#RestClientts)
23+
- [WebsocketAPIClient](#WebsocketAPIClientts)
2324

2425

2526
If anything is missing or wrong, please open an issue or let us know in our [Node.js Traders](https://t.me/nodetraders) telegram group!
@@ -333,4 +334,28 @@ This table includes all endpoints from the official Exchange API docs and corres
333334
| [getPartnerSubordinateList()](https://github.com/tiagosiebler/gateio-api/blob/master/src/RestClient.ts#L4472) | :closed_lock_with_key: | GET | `/rebate/partner/sub_list` |
334335
| [getBrokerCommissionHistory()](https://github.com/tiagosiebler/gateio-api/blob/master/src/RestClient.ts#L4486) | :closed_lock_with_key: | GET | `/rebate/broker/commission_history` |
335336
| [getBrokerTransactionHistory()](https://github.com/tiagosiebler/gateio-api/blob/master/src/RestClient.ts#L4499) | :closed_lock_with_key: | GET | `/rebate/broker/transaction_history` |
336-
| [getUserRebateInfo()](https://github.com/tiagosiebler/gateio-api/blob/master/src/RestClient.ts#L4508) | :closed_lock_with_key: | GET | `/rebate/user/info` |
337+
| [getUserRebateInfo()](https://github.com/tiagosiebler/gateio-api/blob/master/src/RestClient.ts#L4508) | :closed_lock_with_key: | GET | `/rebate/user/info` |
338+
339+
# WebsocketAPIClient.ts
340+
341+
This table includes all endpoints from the official Exchange API docs and corresponding SDK functions for each endpoint that are found in [WebsocketAPIClient.ts](/src/WebsocketAPIClient.ts).
342+
343+
This client provides WebSocket API endpoints which allow for faster interactions with the Gate.io API via a WebSocket connection.
344+
345+
| Function | AUTH | HTTP Method | Endpoint |
346+
| -------- | :------: | :------: | -------- |
347+
| [submitNewSpotOrder()](https://github.com/tiagosiebler/gateio-api/blob/master/src/WebsocketAPIClient.ts#L97) | :closed_lock_with_key: | WS | `spot.order_place` |
348+
| [cancelSpotOrder()](https://github.com/tiagosiebler/gateio-api/blob/master/src/WebsocketAPIClient.ts#L111) | :closed_lock_with_key: | WS | `spot.order_cancel` |
349+
| [cancelSpotOrderById()](https://github.com/tiagosiebler/gateio-api/blob/master/src/WebsocketAPIClient.ts#L125) | :closed_lock_with_key: | WS | `spot.order_cancel_ids` |
350+
| [cancelSpotOrderForSymbol()](https://github.com/tiagosiebler/gateio-api/blob/master/src/WebsocketAPIClient.ts#L139) | :closed_lock_with_key: | WS | `spot.order_cancel_cp` |
351+
| [updateSpotOrder()](https://github.com/tiagosiebler/gateio-api/blob/master/src/WebsocketAPIClient.ts#L153) | :closed_lock_with_key: | WS | `spot.order_amend` |
352+
| [getSpotOrderStatus()](https://github.com/tiagosiebler/gateio-api/blob/master/src/WebsocketAPIClient.ts#L167) | :closed_lock_with_key: | WS | `spot.order_status` |
353+
| [getSpotOrders()](https://github.com/tiagosiebler/gateio-api/blob/master/src/WebsocketAPIClient.ts#L181) | :closed_lock_with_key: | WS | `spot.order_list` |
354+
| [submitNewFuturesOrder()](https://github.com/tiagosiebler/gateio-api/blob/master/src/WebsocketAPIClient.ts#L201) | :closed_lock_with_key: | WS | `futures.order_place` |
355+
| [submitNewFuturesBatchOrder()](https://github.com/tiagosiebler/gateio-api/blob/master/src/WebsocketAPIClient.ts#L215) | :closed_lock_with_key: | WS | `futures.order_batch_place` |
356+
| [cancelFuturesOrder()](https://github.com/tiagosiebler/gateio-api/blob/master/src/WebsocketAPIClient.ts#L229) | :closed_lock_with_key: | WS | `futures.order_cancel` |
357+
| [cancelFuturesOrderById()](https://github.com/tiagosiebler/gateio-api/blob/master/src/WebsocketAPIClient.ts#L243) | :closed_lock_with_key: | WS | `futures.order_cancel_ids` |
358+
| [cancelFuturesAllOpenOrders()](https://github.com/tiagosiebler/gateio-api/blob/master/src/WebsocketAPIClient.ts#L257) | :closed_lock_with_key: | WS | `futures.order_cancel_cp` |
359+
| [updateFuturesOrder()](https://github.com/tiagosiebler/gateio-api/blob/master/src/WebsocketAPIClient.ts#L271) | :closed_lock_with_key: | WS | `futures.order_amend` |
360+
| [getFuturesOrders()](https://github.com/tiagosiebler/gateio-api/blob/master/src/WebsocketAPIClient.ts#L285) | :closed_lock_with_key: | WS | `futures.order_list` |
361+
| [getFuturesOrderStatus()](https://github.com/tiagosiebler/gateio-api/blob/master/src/WebsocketAPIClient.ts#L299) | :closed_lock_with_key: | WS | `futures.order_status` |
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const { WebsocketAPIClient } = require('gateio-api');
2+
3+
// This example shows how to call this Gate.io WebSocket API endpoint with either node.js, javascript (js) or typescript (ts) with the npm module "gateio-api" for Gate.io exchange
4+
// This Gate.io API SDK is available on npm via "npm install gateio-api"
5+
// WS API ENDPOINT: futures.order_cancel_cp
6+
// METHOD: WebSocket API
7+
// PUBLIC: NO
8+
9+
// Create a WebSocket API client instance
10+
const client = new WebsocketAPIClient({
11+
apiKey: 'insert_api_key_here',
12+
apiSecret: 'insert_api_secret_here',
13+
});
14+
15+
// The WebSocket connection is established automatically when needed
16+
// You can use the client to make requests immediately
17+
18+
// Example use of the cancelFuturesAllOpenOrders method
19+
client.cancelFuturesAllOpenOrders(params)
20+
.then((response) => {
21+
console.log(response);
22+
})
23+
.catch((error) => {
24+
console.error(error);
25+
});
26+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const { WebsocketAPIClient } = require('gateio-api');
2+
3+
// This example shows how to call this Gate.io WebSocket API endpoint with either node.js, javascript (js) or typescript (ts) with the npm module "gateio-api" for Gate.io exchange
4+
// This Gate.io API SDK is available on npm via "npm install gateio-api"
5+
// WS API ENDPOINT: futures.order_cancel
6+
// METHOD: WebSocket API
7+
// PUBLIC: NO
8+
9+
// Create a WebSocket API client instance
10+
const client = new WebsocketAPIClient({
11+
apiKey: 'insert_api_key_here',
12+
apiSecret: 'insert_api_secret_here',
13+
});
14+
15+
// The WebSocket connection is established automatically when needed
16+
// You can use the client to make requests immediately
17+
18+
// Example use of the cancelFuturesOrder method
19+
client.cancelFuturesOrder(params)
20+
.then((response) => {
21+
console.log(response);
22+
})
23+
.catch((error) => {
24+
console.error(error);
25+
});
26+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const { WebsocketAPIClient } = require('gateio-api');
2+
3+
// This example shows how to call this Gate.io WebSocket API endpoint with either node.js, javascript (js) or typescript (ts) with the npm module "gateio-api" for Gate.io exchange
4+
// This Gate.io API SDK is available on npm via "npm install gateio-api"
5+
// WS API ENDPOINT: futures.order_cancel_ids
6+
// METHOD: WebSocket API
7+
// PUBLIC: NO
8+
9+
// Create a WebSocket API client instance
10+
const client = new WebsocketAPIClient({
11+
apiKey: 'insert_api_key_here',
12+
apiSecret: 'insert_api_secret_here',
13+
});
14+
15+
// The WebSocket connection is established automatically when needed
16+
// You can use the client to make requests immediately
17+
18+
// Example use of the cancelFuturesOrderById method
19+
client.cancelFuturesOrderById(params)
20+
.then((response) => {
21+
console.log(response);
22+
})
23+
.catch((error) => {
24+
console.error(error);
25+
});
26+

0 commit comments

Comments
 (0)