Skip to content

Commit

Permalink
Merge pull request #306 from tiagosiebler/nextstuff
Browse files Browse the repository at this point in the history
Safer WS timer cleanup & teardown, add proxy/rate limits example, docs...
  • Loading branch information
tiagosiebler authored Jan 3, 2024
2 parents a2cc9f5 + c54d86c commit 1ac1aa5
Show file tree
Hide file tree
Showing 24 changed files with 259 additions and 78 deletions.
129 changes: 75 additions & 54 deletions README.md

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions examples/deprecated/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Deprecated Examples

The examples in this folder use old/deprecated/obsolete APIs. They should all have a modern alternative.

As of December 2023, use the V5 APIs & WebSockets.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ContractClient } from '../src/index';
import { ContractClient } from '../../src/index';

// or
// import { ContractClient } from 'bybit-api';
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/

// For testing with the repo directly, import from the src folder
import { ContractClient } from '../src';
import { ContractClient } from '../../src';

// or, use the version installed with npm
// import { ContractClient } from 'bybit-api';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CopyTradingClient } from '../src/index';
import { CopyTradingClient } from '../../src/index';

// or
// import { CopyTradingClient } from 'bybit-api';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { LinearClient } from '../src/index';
import { LinearClient } from '../../src/index';

// or
// import { LinearClient } from 'bybit-api';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ContractClient } from '../src/index';
import { ContractClient } from '../../src/index';

// or
// import { ContractClient } from 'bybit-api';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SpotClientV3 } from '../src/index';
import { SpotClientV3 } from '../../src/index';

// or
// import { SpotClientV3 } from 'bybit-api';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SpotClientV3 } from '../src/index';
import { SpotClientV3 } from '../../src/index';

// or
// import { SpotClientV3 } from 'bybit-api';
Expand All @@ -25,15 +25,15 @@ const client = new SpotClientV3({
symbol,
orderId,
ordersPerPage,
0
0,
);
console.log('normal orders:', normalOrders);

const tpSlOrders = await client.getOpenOrders(
symbol,
orderId,
ordersPerPage,
1
1,
);
console.log('tpSlOrders:', tpSlOrders);
} catch (e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { UnifiedMarginClient } from '../src/index';
import { UnifiedMarginClient } from '../../src/index';

// or
// import { UnifiedMarginClient } from 'bybit-api';
Expand Down Expand Up @@ -36,7 +36,7 @@ const client = new UnifiedMarginClient({
});
console.log(
'both to compare:',
JSON.stringify(historicOrdersBoth, null, 2)
JSON.stringify(historicOrdersBoth, null, 2),
);
} catch (e) {
console.error('request failed: ', e);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { UnifiedMarginClient } from '../src/index';
import { UnifiedMarginClient } from '../../src/index';

// or
// import { UnifiedMarginClient } from 'bybit-api';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/no-empty-function */
import { DefaultLogger, WS_KEY_MAP, WebsocketClient } from '../src';
import { DefaultLogger, WS_KEY_MAP, WebsocketClient } from '../../src';

// or
// import { DefaultLogger, WS_KEY_MAP, WebsocketClient } from 'bybit-api';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/no-empty-function */
import { DefaultLogger, WS_KEY_MAP, WebsocketClient } from '../src';
import { DefaultLogger, WS_KEY_MAP, WebsocketClient } from '../../src';

// or
// import { DefaultLogger, WS_KEY_MAP, WebsocketClient } from 'bybit-api';
Expand Down
4 changes: 2 additions & 2 deletions examples/ws-public.ts → examples/deprecated/ws-public.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DefaultLogger, WS_KEY_MAP, WebsocketClient } from '../src';
import { DefaultLogger, WS_KEY_MAP, WebsocketClient } from '../../src';

// or
// import { DefaultLogger, WS_KEY_MAP, WebsocketClient } from 'bybit-api';
Expand All @@ -22,7 +22,7 @@ const wsClient = new WebsocketClient(
// market: 'unifiedOption',
market: 'contractUSDT',
},
logger
logger,
);

wsClient.on('update', (data) => {
Expand Down
66 changes: 66 additions & 0 deletions examples/rest-v5-proxies.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { RestClientV5 } from '../src/index';

// or
// import { RestClientV5 } from 'bybit-api';

const key = process.env.API_KEY_COM;
const secret = process.env.API_SECRET_COM;

const client = new RestClientV5(
{
key: key,
secret: secret,
parseAPIRateLimits: true,
testnet: true,
// Sometimes using a proxy introduces recv timestamp errors (due to the extra latency)
// If that happens, you can try increasing the recv window (which is 5000ms by default)
// recv_window: 10000,
},
{
proxy: {
host: 'proxyhost',
port: Number('proxyport'),
auth: {
username: 'proxyuserifneeded',
password: 'proxypassifneeded',
},
},
},
);

(async () => {
try {
const res = await client.getWalletBalance({ accountType: 'UNIFIED' });

console.log('response: ', JSON.stringify(res, null, 2));

// const orders = await client.batchSubmitOrders('linear', [
// {
// symbol: 'ETHUSDT',
// orderType: 'Limit',
// side: 'Buy',
// qty: '1',
// orderIv: '6',
// timeInForce: 'GTC',
// orderLinkId: 'option-test-001',
// mmp: false,
// reduceOnly: false,
// },
// {
// symbol: 'ETHUSDT',
// orderType: 'Limit',
// side: 'Sell',
// qty: '2',
// price: '700',
// timeInForce: 'GTC',
// orderLinkId: 'option-test-001',
// mmp: false,
// reduceOnly: false,
// },
// ]);

// console.log('orders: ', JSON.stringify(orders, null, 2));
} catch (e) {
console.error('request failed: ', e);
}
})();
61 changes: 61 additions & 0 deletions examples/rest-v5-public.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { RestClientV5 } from '../src/index';

// or
// import { RestClientV5 } from 'bybit-api';

/**
* If you don't plan on making any private api calls,
* you can instance the REST client without any parameters
*/
const client = new RestClientV5();

(async () => {
try {
// const klineResult = await client.getKline({
// category: 'linear',
// interval: '15',
// symbol: 'BTCUSDT',
// });
// console.log('klineResult: ', klineResult);

// const markPriceKlineResult = await client.getMarkPriceKline({
// category: 'linear',
// interval: '15',
// symbol: 'BTCUSDT',
// });
// console.log('markPriceKlineResult: ', markPriceKlineResult);

// const indexPriceKline = await client.getIndexPriceKline({
// category: 'linear',
// interval: '15',
// symbol: 'BTCUSDT',
// });
// console.log('indexPriceKline: ', indexPriceKline);

// const openInterest = await client.getOpenInterest({
// category: 'linear',
// symbol: 'BTCUSDT',
// intervalTime: '5min',
// });

const tickers = await client.getTickers({ category: 'linear' });
// console.log(
// JSON.stringify(
// tickers.result.list.map((ticker) => ticker.symbol),
// null,
// 2,
// ),
// );

console.log('response', tickers);
// openInterest.result.list.forEach((row) => {
// console.log('int: ', {
// timestamp: row.timestamp,
// value: row.openInterest,
// });
// });
// console.log('openInterest: ', openInterest.result.list);
} catch (e) {
console.error('request failed: ', e);
}
})();
4 changes: 2 additions & 2 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "bybit-api",
"version": "3.7.8",
"version": "3.8.0",
"description": "Complete & robust Node.js SDK for Bybit's REST APIs and WebSockets, with TypeScript & strong end to end tests.",
"main": "lib/index.js",
"types": "lib/index.d.ts",
Expand Down
8 changes: 8 additions & 0 deletions src/types/request/v5-asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,15 @@ export interface WithdrawParamsV5 {

export interface CreateSubMemberParamsV5 {
username: string;
password?: string;
/**
* 1: normal, 6: custodial
*/
memberType: 1 | 6;
/**
* 0: quick login disabled (default), 1: quick login enabled
*/
switch?: 0 | 1;
isUta?: boolean;
note?: string;
}
14 changes: 14 additions & 0 deletions src/util/websocket-util.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import WebSocket from 'isomorphic-ws';

import { APIMarket, CategoryV5, WsKey } from '../types';
import { DefaultLogger } from './logger';

Expand Down Expand Up @@ -548,3 +550,15 @@ export const WS_ERROR_ENUM = {
export function neverGuard(x: never, msg: string): Error {
return new Error(`Unhandled value exception "x", ${msg}`);
}

/**
* #305: ws.terminate() is undefined in browsers.
* This only works in node.js, not in browsers.
* Does nothing if `ws` is undefined.
*/
export function safeTerminateWs(ws?: WebSocket | unknown) {
// #305: ws.terminate() undefined in browsers
if (ws && typeof ws['terminate'] === 'function') {
ws.terminate();
}
}
12 changes: 9 additions & 3 deletions src/websocket-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
isTopicSubscriptionSuccess,
isWsPong,
neverGuard,
safeTerminateWs,
serializeParams,
} from './util';
import { RestClientV5 } from './rest-client-v5';
Expand Down Expand Up @@ -462,7 +463,7 @@ export class WebsocketClient extends EventEmitter {
const ws = this.getWs(wsKey);
ws?.close();
if (force) {
ws?.terminate();
safeTerminateWs(ws);
}
}

Expand Down Expand Up @@ -808,11 +809,16 @@ export class WebsocketClient extends EventEmitter {

const wasOpen = this.wsStore.isWsOpen(wsKey);

this.getWs(wsKey)?.terminate();
delete this.wsStore.get(wsKey, true).activePongTimer;
this.clearPingTimer(wsKey);
this.clearPongTimer(wsKey);

const ws = this.getWs(wsKey);

if (ws) {
ws.close();
safeTerminateWs(ws);
}

if (!wasOpen) {
this.logger.info(
`${reason} - socket already closed - trigger immediate reconnect`,
Expand Down
2 changes: 1 addition & 1 deletion test/account-asset/private.read.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ describe('Private Account Asset REST API GET Endpoints', () => {
});
});

it('getUniversalTransfers()', async () => {
it.skip('getUniversalTransfers()', async () => {
expect(await api.getInternalTransfers()).toMatchObject(
successResponseObject(),
);
Expand Down
2 changes: 1 addition & 1 deletion test/account-asset/private.v3.read.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ describe('Private Account Asset V3 REST API Endpoints', () => {
});
});

it('getUniversalTransfers()', async () => {
it.skip('getUniversalTransfers()', async () => {
expect(await api.getUniversalTransfers({ coin: coin })).toMatchObject({
...successResponseObjectV3(),
retCode: API_ERROR_CODE.INCORRECT_API_KEY_PERMISSIONS,
Expand Down

0 comments on commit 1ac1aa5

Please sign in to comment.