Skip to content

Commit

Permalink
Merge pull request #21 from tiagosiebler/lintimports
Browse files Browse the repository at this point in the history
v1.0.10: fix() missing js extensions for some imports, add linter checks via eslint plugin, update ws client deferred types
  • Loading branch information
tiagosiebler authored Jul 27, 2024
2 parents 16bd852 + 3274301 commit f886341
Show file tree
Hide file tree
Showing 14 changed files with 75 additions and 44 deletions.
7 changes: 6 additions & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@ module.exports = {
tsconfigRootDir: __dirname,
sourceType: 'module',
},
plugins: ['@typescript-eslint/eslint-plugin', 'simple-import-sort'],
plugins: [
'@typescript-eslint/eslint-plugin',
'simple-import-sort',
'require-extensions',
],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
'plugin:require-extensions/recommended',
],
root: true,
env: {
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/e2etest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ jobs:
- name: Install
run: npm ci --ignore-scripts

- name: Build
- name: Check Lint
run: npx eslint src

- name: Check Build
run: npm run build

- name: Test
Expand Down
6 changes: 3 additions & 3 deletions examples/spot/submitMarketOrder.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { RestClient } from '../../src'; // For an easy demonstration, import from the src dir. Normally though, see below to import from the npm installed version instead.
import { RestClient } from '../../src/index.js'; // For an easy demonstration, import from the src dir. Normally though, see below to import from the npm installed version instead.
// import { RestClient } from 'gateio-api'; // Import the RestClient from the published version of this SDK, installed via NPM (npm install gateio-api)

// Define the account object with API key and secret
Expand All @@ -9,8 +9,8 @@ const account = {

// Initialize the RestClient with the API credentials
const gateRestClient = new RestClient({
apiKey: account.key,
apiSecret: account.secret,
apiKey: 'yourkeyhere',
apiSecret: 'yoursecrethere',
});

async function submitSpotOrder() {
Expand Down
17 changes: 15 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gateio-api",
"version": "1.0.9",
"version": "1.0.10",
"description": "Complete & robust Node.js SDK for Gate.io's REST APIs, WebSockets & WebSocket APIs, with TypeScript declarations.",
"scripts": {
"clean": "rm -rf dist/*",
Expand Down Expand Up @@ -39,6 +39,7 @@
"eslint": "^8.29.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-require-extensions": "^0.1.3",
"eslint-plugin-simple-import-sort": "^12.0.0",
"jest": "^29.7.0",
"ts-jest": "^29.1.2",
Expand Down
18 changes: 10 additions & 8 deletions src/WebsocketClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
WsMarket,
WsTopicRequest,
} from './lib/websocket/websocket-util.js';
import { DeferredPromise } from './lib/websocket/WsStore.types.js';
import { WSConnectedResult } from './lib/websocket/WsStore.types.js';
import {
WSAPIRequest,
WsOperation,
Expand All @@ -43,7 +43,7 @@ export class WebsocketClient extends BaseWebsocketClient<WsKey> {
*
* Returns array of promises that individually resolve when each connection is successfully opened.
*/
public connectAll(): (DeferredPromise['promise'] | undefined)[] {
public connectAll(): Promise<WSConnectedResult | undefined>[] {
return [
this.connect(WS_KEY_MAP.spotV4),
this.connect(WS_KEY_MAP.perpFuturesUSDTV4),
Expand Down Expand Up @@ -254,15 +254,11 @@ export class WebsocketClient extends BaseWebsocketClient<WsKey> {
wsKey,
});
if (!wsKey) {
throw new Error(
'Cannot send PONG due to no known websocket for this wsKey',
);
throw new Error('Cannot send PONG, no wsKey provided');
}
const wsState = this.getWsStore().get(wsKey);
if (!wsState || !wsState?.ws) {
throw new Error(
`${wsKey} socket not connected yet, call "connectAll()" first then try again when the "open" event arrives`,
);
throw new Error(`Cannot send pong, ${wsKey} socket not connected yet`);
}

// Send a protocol layer pong
Expand Down Expand Up @@ -422,6 +418,12 @@ export class WebsocketClient extends BaseWebsocketClient<WsKey> {
`!! Unhandled string event type "${eventAction}. Defaulting to "update" channel...`,
parsed,
);
} else {
// TODO: test meee
this.logger.error(
`!! Unhandled non-string event type "${eventAction}. Defaulting to "update" channel...`,
parsed,
);
}

results.push({
Expand Down
22 changes: 7 additions & 15 deletions src/lib/BaseWSClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
} from './websocket/websocket-util.js';
import { WsStore } from './websocket/WsStore.js';
import {
DeferredPromise,
WSConnectedResult,
WsConnectionStateEnum,
} from './websocket/WsStore.types.js';

Expand Down Expand Up @@ -169,7 +169,7 @@ export abstract class BaseWebsocketClient<
/**
* Request connection of all dependent (public & private) websockets, instead of waiting for automatic connection by library
*/
protected abstract connectAll(): (DeferredPromise['promise'] | undefined)[];
protected abstract connectAll(): Promise<WSConnectedResult | undefined>[];

protected isPrivateWsKey(wsKey: TWSKey): boolean {
return this.getPrivateWSKeys().includes(wsKey);
Expand Down Expand Up @@ -221,10 +221,8 @@ export abstract class BaseWebsocketClient<
WsConnectionStateEnum.CONNECTED,
);

// TODO: test this, spam loads of subscribe topic calls in intervals (and add a log line on this logic)
const isConnectionInProgress =
this.wsStore.isConnectionState(wsKey, WsConnectionStateEnum.CONNECTING) ||
this.wsStore.isConnectionState(wsKey, WsConnectionStateEnum.RECONNECTING);
this.wsStore.isConnectionAttemptInProgress(wsKey);

// start connection process if it hasn't yet begun. Topics are automatically subscribed to on-connect
if (!isConnected && !isConnectionInProgress) {
Expand Down Expand Up @@ -362,19 +360,17 @@ export abstract class BaseWebsocketClient<
*/
protected async connect(
wsKey: TWSKey,
): Promise<DeferredPromise['promise'] | undefined> {
): Promise<WSConnectedResult | undefined> {
try {
if (this.wsStore.isWsOpen(wsKey)) {
this.logger.error(
'Refused to connect to ws with existing active connection',
{ ...WS_LOGGER_CATEGORY, wsKey },
);
return this.wsStore.getConnectionInProgressPromise(wsKey);
return { wsKey };
}

if (
this.wsStore.isConnectionState(wsKey, WsConnectionStateEnum.CONNECTING)
) {
if (this.wsStore.isConnectionAttemptInProgress(wsKey)) {
this.logger.error(
'Refused to connect to ws, connection attempt already active',
{ ...WS_LOGGER_CATEGORY, wsKey },
Expand Down Expand Up @@ -459,7 +455,6 @@ export abstract class BaseWebsocketClient<
...WS_LOGGER_CATEGORY,
wsKey,
});
// TODO:!

const request = await this.getWsAuthRequestEvent(wsKey);

Expand All @@ -473,10 +468,7 @@ export abstract class BaseWebsocketClient<

private reconnectWithDelay(wsKey: TWSKey, connectionDelayMs: number) {
this.clearTimers(wsKey);
if (
this.wsStore.getConnectionState(wsKey) !==
WsConnectionStateEnum.CONNECTING
) {
if (!this.wsStore.isConnectionAttemptInProgress(wsKey)) {
this.setWsState(wsKey, WsConnectionStateEnum.RECONNECTING);
}

Expand Down
2 changes: 1 addition & 1 deletion src/lib/requestUtils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import WebSocket from 'isomorphic-ws';

import { GateBaseUrlKey } from '../types/shared';
import { GateBaseUrlKey } from '../types/shared.js';

export interface RestClientOptions {
/** Your API key */
Expand Down
18 changes: 16 additions & 2 deletions src/lib/websocket/WsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import WebSocket from 'isomorphic-ws';
import { DefaultLogger } from '../logger.js';
import {
DeferredPromise,
WSConnectedResult,
WsConnectionStateEnum,
WsStoredState,
} from './WsStore.types.js';
Expand Down Expand Up @@ -254,7 +255,7 @@ export class WsStore<
/** Get promise designed to track a connection attempt in progress. Resolves once connected. */
getConnectionInProgressPromise(
wsKey: WsKey,
): DeferredPromise<unknown> | undefined {
): DeferredPromise<WSConnectedResult> | undefined {
return this.getDeferredPromise(
wsKey,
DEFERRED_PROMISE_REF.CONNECTION_IN_PROGRESS,
Expand All @@ -269,7 +270,7 @@ export class WsStore<
createConnectionInProgressPromise(
wsKey: WsKey,
throwIfExists: boolean,
): DeferredPromise<unknown> {
): DeferredPromise<WSConnectedResult> {
return this.createDeferredPromise(
wsKey,
DEFERRED_PROMISE_REF.CONNECTION_IN_PROGRESS,
Expand Down Expand Up @@ -307,6 +308,19 @@ export class WsStore<
return this.getConnectionState(key) === state;
}

/**
* Check if we're currently in the process of opening a connection for any reason. Safer than only checking "CONNECTING" as the state
* @param key
* @returns
*/
isConnectionAttemptInProgress(key: WsKey): boolean {
const isConnectionInProgress =
this.isConnectionState(key, WsConnectionStateEnum.CONNECTING) ||
this.isConnectionState(key, WsConnectionStateEnum.RECONNECTING);

return isConnectionInProgress;
}

/* subscribed topics */

getTopics(key: WsKey): Set<TWSTopicSubscribeEventArgs> {
Expand Down
4 changes: 4 additions & 0 deletions src/lib/websocket/WsStore.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export interface DeferredPromise<TSuccess = any, TError = any> {
promise?: Promise<TSuccess>;
}

export interface WSConnectedResult {
wsKey: string;
}

export interface WsStoredState<TWSTopicSubscribeEvent extends string | object> {
/** The currently active websocket connection */
ws?: WebSocket;
Expand Down
4 changes: 2 additions & 2 deletions src/lib/websocket/websocket-util.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { WSAPIRequest } from '../../types/websockets/requests';
import { WSAPIRequest } from '../../types/websockets/requests.js';
import {
FuturesWSAPITopic,
SpotWSAPITopic,
} from '../../types/websockets/wsAPI';
} from '../../types/websockets/wsAPI.js';

/**
* Should be one WS key per unique URL. Some URLs may need a suffix.
Expand Down
3 changes: 0 additions & 3 deletions src/types/request/rebate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,3 @@ export interface PartnerTransactionReq {
limit?: number;
offset?: number;
}



4 changes: 2 additions & 2 deletions src/types/websockets/requests.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CHANNEL_ID } from '../../lib/requestUtils';
import { WSAPITopic } from './wsAPI';
import { CHANNEL_ID } from '../../lib/requestUtils.js';
import { WSAPITopic } from './wsAPI.js';

export type WsOperation = 'subscribe' | 'unsubscribe' | 'auth';

Expand Down
6 changes: 3 additions & 3 deletions src/types/websockets/wsAPI.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { WsKey } from '../../lib/websocket/websocket-util';
import { WsKey } from '../../lib/websocket/websocket-util.js';
import {
GetFuturesOrdersReq,
SubmitFuturesOrderReq,
UpdateFuturesOrderReq,
} from '../request/futures';
} from '../request/futures.js';
import {
CancelSpotBatchOrdersReq,
DeleteSpotOrderReq,
GetSpotOrderReq,
SubmitSpotOrderReq,
UpdateSpotOrderReq,
} from '../request/spot';
} from '../request/spot.js';

export type SpotWSAPITopic =
| 'spot.login'
Expand Down

0 comments on commit f886341

Please sign in to comment.