Skip to content

Commit b6ed945

Browse files
authored
Merge pull request #78 from JJ-Cro/V3ExamplesTests
feat(): V3 examples, v3 readme
2 parents 2494740 + bb9b19e commit b6ed945

File tree

6 files changed

+430
-20
lines changed

6 files changed

+430
-20
lines changed

README.md

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,30 @@ import { RestClientV3 } from 'bitget-api';
125125
// or if you prefer require:
126126
// const { RestClientV3 } = require('bitget-api');
127127

128-
// TODO: REST V3 example here, similar to V2
128+
// note the single quotes, preventing special characters such as $ from being incorrectly passed
129+
const client = new RestClientV3({
130+
apiKey: process.env.API_KEY_COM || 'insert_api_key_here',
131+
apiSecret: process.env.API_SECRET_COM || 'insert_api_secret_here',
132+
apiPass: process.env.API_PASS_COM || 'insert_api_pass_here',
133+
});
134+
135+
(async () => {
136+
try {
137+
console.log(await client.getBalances());
138+
139+
const newOrder = await client.submitNewOrder({
140+
category: 'USDT-FUTURES',
141+
orderType: 'market',
142+
side: 'buy',
143+
qty: '0.001',
144+
symbol: 'BTCUSDT',
145+
});
146+
147+
console.log('Order submitted: ', newOrder);
148+
} catch (e) {
149+
console.error('request failed: ', e);
150+
}
151+
})();
129152
```
130153

131154
#### V2 REST APIs
@@ -143,13 +166,11 @@ const API_KEY = 'xxx';
143166
const API_SECRET = 'yyy';
144167
const API_PASS = 'zzz';
145168

146-
const client = new RestClientV2(
147-
{
148-
apiKey: API_KEY,
149-
apiSecret: API_SECRET,
150-
apiPass: API_PASS,
151-
},
152-
);
169+
const client = new RestClientV2({
170+
apiKey: API_KEY,
171+
apiSecret: API_SECRET,
172+
apiPass: API_PASS,
173+
});
153174

154175
// For public-only API calls, simply don't provide a key & secret or set them to undefined
155176
// const client = new RestClientV2();
@@ -182,6 +203,7 @@ client
182203
All WebSocket functionality is supported via the WebsocketClient. Since there are currently 3 generations of Bitget's API, there are 3 WebsocketClient classes in this Node.js, JavaScript & TypeScript SDK for Bitget.
183204

184205
Use the following guidance to decide which one to use:
206+
185207
- Unified Trading Account / V3 (latest generation):
186208
- For receiving data, use the [WebsocketClientV3](./src/websocket-client-v3.ts).
187209
- For sending orders via WebSockets, use the [WebsocketAPIClient](./src/websocket-api-client.ts).
@@ -206,21 +228,19 @@ This integration looks & feels like a REST API client, but uses WebSockets, via
206228
A simple example is below, but for a more thorough example, check the example here: [./examples/V3/ws-api-client-trade.ts](./examples/V3/ws-api-client-trade.ts)
207229

208230
```typescript
209-
import { WebsocketAPIClient } from "bitget-api";
231+
import { WebsocketAPIClient } from 'bitget-api';
210232
// or if you prefer require:
211233
// const { WebsocketAPIClient } = require("bitget-api");
212234

213235
// Make an instance of the WS API Client class with your API keys
214-
const wsClient = new WebsocketAPIClient(
215-
{
216-
apiKey: API_KEY,
217-
apiSecret: API_SECRET,
218-
apiPass: API_PASS,
236+
const wsClient = new WebsocketAPIClient({
237+
apiKey: API_KEY,
238+
apiSecret: API_SECRET,
239+
apiPass: API_PASS,
219240

220-
// Whether to use the demo trading wss connection
221-
// demoTrading: true,
222-
}
223-
);
241+
// Whether to use the demo trading wss connection
242+
// demoTrading: true,
243+
});
224244

225245
async function start() {
226246
// Start using it like a REST API. All actions are sent via a persisted WebSocket connection.
@@ -245,7 +265,7 @@ async function start() {
245265
}
246266
}
247267

248-
start().catch(e => console.error("Exception in example: ". e));
268+
start().catch((e) => console.error('Exception in example: '.e));
249269
```
250270

251271
###### Receiving realtime data
@@ -385,7 +405,6 @@ wsClient.subscribe(
385405
);
386406
```
387407

388-
389408
For more examples, including how to use websockets with Bitget, check the [examples](./examples/) and [test](./test/) folders.
390409

391410
---

examples/V3/rest-private.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { RestClientV3 } from '../../src/index';
2+
3+
// or
4+
// import { RestClientV3 } from 'bitget-api';
5+
6+
// read from environmental variables
7+
const API_KEY = process.env.API_KEY_COM;
8+
const API_SECRET = process.env.API_SECRET_COM;
9+
const API_PASS = process.env.API_PASS_COM;
10+
11+
// If running from CLI in unix, you can pass env vars as such:
12+
// API_KEY_COM='lkm12n3-2ba3-1mxf-fn13-lkm12n3a' API_SECRET_COM='035B2B9637E1BDFFEE2646BFBDDB8CE4' API_PASSPHRASE_COM='ComplexPa$$!23$5^' ts-node examples/V3/rest-private-futures.ts
13+
14+
// note the single quotes, preventing special characters such as $ from being incorrectly passed
15+
16+
const client = new RestClientV3({
17+
apiKey: API_KEY,
18+
apiSecret: API_SECRET,
19+
apiPass: API_PASS,
20+
// apiKey: 'apiKeyHere',
21+
// apiSecret: 'apiSecretHere',
22+
// apiPass: 'apiPassHere',
23+
});
24+
25+
/** This is a simple script wrapped in a immediately invoked function expression, designed to check account assets for futures trading */
26+
(async () => {
27+
try {
28+
console.log(await client.getBalances());
29+
} catch (e) {
30+
console.error('request failed: ', e);
31+
}
32+
})();
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { RestClientV3 } from '../../src/index';
2+
3+
// or
4+
// import { RestClientV3 } from 'bitget-api';
5+
6+
const restClient = new RestClientV3();
7+
8+
const symbol = 'BTCUSDT';
9+
10+
(async () => {
11+
try {
12+
const response = await restClient.getCandles({
13+
symbol,
14+
category: 'USDT-FUTURES',
15+
interval: '1m',
16+
});
17+
18+
console.table(response.data);
19+
20+
console.log('getCandles returned ' + response.data.length + ' candles');
21+
} catch (e) {
22+
console.error('request failed: ', e);
23+
}
24+
})();
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { RestClientV3 } from '../../src/index';
2+
3+
// or
4+
// import { RestClientV3 } from 'bitget-api';
5+
6+
const restClient = new RestClientV3();
7+
8+
(async () => {
9+
try {
10+
const response = await restClient.getCandles({
11+
symbol: 'BTCUSDT',
12+
category: 'SPOT',
13+
interval: '1m',
14+
});
15+
16+
console.table(response.data);
17+
console.log('getCandles: ', response.data.length);
18+
} catch (e) {
19+
console.error('request failed: ', e);
20+
}
21+
})();
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/* eslint-disable @typescript-eslint/no-unused-vars */
2+
import {
3+
PlaceOrderRequestV3,
4+
RestClientV3,
5+
WebsocketClientV3,
6+
} from '../../src';
7+
8+
// or
9+
// import { PlaceOrderRequestV3, RestClientV3, WebsocketClientV3 } from '../src';
10+
11+
// read from environmental variables
12+
const API_KEY = process.env.API_KEY_COM;
13+
const API_SECRET = process.env.API_SECRET_COM;
14+
const API_PASS = process.env.API_PASS_COM;
15+
16+
// If running from CLI in unix, you can pass env vars as such:
17+
// API_KEY_COM='lkm12n3-2ba3-1mxf-fn13-lkm12n3a' API_SECRET_COM='035B2B9637E1BDFFEE2646BFBDDB8CE4' API_PASSPHRASE_COM='ComplexPa$$!23$5^' ts-node examples/V3/rest-trade-futures.ts
18+
19+
// note the single quotes, preventing special characters such as $ from being incorrectly passed
20+
21+
const client = new RestClientV3({
22+
apiKey: API_KEY,
23+
apiSecret: API_SECRET,
24+
apiPass: API_PASS,
25+
// apiKey: 'apiKeyHere',
26+
// apiSecret: 'apiSecretHere',
27+
// apiPass: 'apiPassHere',
28+
});
29+
30+
const wsClient = new WebsocketClientV3({
31+
apiKey: API_KEY,
32+
apiSecret: API_SECRET,
33+
apiPass: API_PASS,
34+
});
35+
36+
function logWSEvent(type, data) {
37+
console.log(new Date(), `WS ${type} event: `, data);
38+
}
39+
40+
// simple sleep function
41+
function promiseSleep(milliseconds) {
42+
return new Promise((resolve) => setTimeout(resolve, milliseconds));
43+
}
44+
45+
/**
46+
* This is a simple script wrapped in a immediately invoked function expression (to execute the below workflow immediately).
47+
*
48+
* It is designed to:
49+
* - open a private websocket channel to log account events
50+
* - check for any available USDT balance in the account
51+
* - immediately open a minimum sized long position on BTCUSDT
52+
* - check active positions
53+
* - immediately send closing orders for any active futures positions
54+
* - check positions again
55+
*
56+
*/
57+
(async () => {
58+
try {
59+
// Add event listeners to log websocket events on account
60+
wsClient.on('update', (data) => logWSEvent('update', data));
61+
62+
wsClient.on('open', (data) => logWSEvent('open', data));
63+
wsClient.on('response', (data) => logWSEvent('response', data));
64+
wsClient.on('reconnect', (data) => logWSEvent('reconnect', data));
65+
wsClient.on('reconnected', (data) => logWSEvent('reconnected', data));
66+
wsClient.on('authenticated', (data) => logWSEvent('authenticated', data));
67+
wsClient.on('exception', (data) => logWSEvent('exception', data));
68+
69+
// Subscribe to private topics for UTA account
70+
wsClient.subscribe(
71+
{
72+
topic: 'account',
73+
payload: {
74+
instType: 'UTA',
75+
},
76+
},
77+
'v3Private',
78+
);
79+
80+
// Subscribe to position updates
81+
wsClient.subscribe(
82+
{
83+
topic: 'position',
84+
payload: {
85+
instType: 'UTA',
86+
},
87+
},
88+
'v3Private',
89+
);
90+
91+
// Subscribe to order updates
92+
wsClient.subscribe(
93+
{
94+
topic: 'order',
95+
payload: {
96+
instType: 'UTA',
97+
},
98+
},
99+
'v3Private',
100+
);
101+
102+
// wait briefly for ws to be ready (could also use the response or authenticated events, to make sure topics are subscribed to before starting)
103+
await promiseSleep(2.5 * 1000);
104+
105+
const symbol = 'BTCUSDT';
106+
107+
const balanceResult = await client.getBalances();
108+
const accountBalance = balanceResult.data;
109+
110+
const usdtAsset = accountBalance.assets?.find(
111+
(asset) => asset.coin === 'USDT',
112+
);
113+
const usdtAmount = usdtAsset ? Number(usdtAsset.available) : 0;
114+
115+
console.log('USDT balance: ', usdtAmount);
116+
117+
if (!usdtAmount) {
118+
console.error('No USDT to trade');
119+
return;
120+
}
121+
122+
const symbolRulesResult = await client.getInstruments({
123+
category: 'USDT-FUTURES',
124+
symbol: symbol,
125+
});
126+
const bitcoinUSDFuturesRule = symbolRulesResult.data.find(
127+
(row) => row.symbol === symbol,
128+
);
129+
130+
console.log('symbol rules: ', bitcoinUSDFuturesRule);
131+
if (!bitcoinUSDFuturesRule) {
132+
console.error('Failed to get trading rules for ' + symbol);
133+
return;
134+
}
135+
136+
const order: PlaceOrderRequestV3 = {
137+
category: 'USDT-FUTURES',
138+
orderType: 'market',
139+
side: 'buy',
140+
qty: bitcoinUSDFuturesRule.minOrderQty,
141+
symbol: symbol,
142+
} as const;
143+
144+
console.log('placing order: ', order);
145+
146+
const result = await client.submitNewOrder(order);
147+
148+
console.log('order result: ', result);
149+
150+
const positionsResult = await client.getCurrentPosition({
151+
category: 'USDT-FUTURES',
152+
});
153+
const positionsToClose = positionsResult.data.list.filter(
154+
(pos) => pos.total !== '0',
155+
);
156+
157+
console.log('open positions to close: ', positionsToClose);
158+
159+
// Loop through any active positions and send a closing market order on each position
160+
for (const position of positionsToClose) {
161+
const closingSide = position.posSide === 'long' ? 'sell' : 'buy';
162+
const closingOrder: PlaceOrderRequestV3 = {
163+
category: 'USDT-FUTURES',
164+
orderType: 'market',
165+
side: closingSide,
166+
qty: position.total,
167+
symbol: position.symbol,
168+
};
169+
170+
console.log('closing position with market order: ', closingOrder);
171+
172+
const result = await client.submitNewOrder(closingOrder);
173+
console.log('position closing order result: ', result);
174+
}
175+
176+
console.log(
177+
'positions after closing all: ',
178+
await client.getCurrentPosition({
179+
category: 'USDT-FUTURES',
180+
}),
181+
);
182+
} catch (e) {
183+
console.error('request failed: ', e);
184+
}
185+
})();

0 commit comments

Comments
 (0)