feat(): update basic spot/futures examples with initial types

This commit is contained in:
Tiago Siebler
2023-11-14 12:15:26 +00:00
parent b1b3ee926e
commit ea8fac777e
19 changed files with 499 additions and 63 deletions

View File

@@ -0,0 +1,8 @@
# Deprecated V1 REST API Examples
These examples are for Bitget's V1 APIs, the previous generation of their API offering.
If you're building new functionality, you should look at using the V2 APIs via the RestClientV2 class in this SDK. This covers all the newer functionality offered by Bitget's APIs - with significant upgrades on all aspects of their APIs:
https://www.bitget.com/api-doc/common/release-note
The V1 REST clients will remain function until Bitget formally deprecates their V1 API.

View File

@@ -0,0 +1,38 @@
import { FuturesClient, WebsocketClient } from '../../src/index';
// or
// import { SpotClient } from 'bitget-api';
// read from environmental variables
const API_KEY = process.env.API_KEY_COM;
const API_SECRET = process.env.API_SECRET_COM;
const API_PASS = process.env.API_PASS_COM;
const client = new FuturesClient({
apiKey: API_KEY,
apiSecret: API_SECRET,
apiPass: API_PASS,
// apiKey: 'apiKeyHere',
// apiSecret: 'apiSecretHere',
// apiPass: 'apiPassHere',
});
/** This is a simple script wrapped in a immediately invoked function expression, designed to check for any available BTC balance and immediately sell the full amount for USDT */
(async () => {
try {
const now = new Date();
const toTime = new Date(now.getTime() - 24 * 60 * 60 * 1000);
console.log(
await client.getAccountBill({
symbol: 'BTCUSDT_UMCBL',
marginCoin: 'USDT',
startTime: now.getTime() + '', // should be sent as a string
endTime: toTime.getTime() + '', // should be sent as a string
pageSize: 100,
}),
);
} catch (e) {
console.error('request failed: ', e);
}
})();

View File

@@ -0,0 +1,27 @@
import { SpotClient, WebsocketClient } from '../../src/index';
// or
// import { SpotClient } from 'bitget-api';
// read from environmental variables
const API_KEY = process.env.API_KEY_COM;
const API_SECRET = process.env.API_SECRET_COM;
const API_PASS = process.env.API_PASS_COM;
const client = new SpotClient({
apiKey: API_KEY,
apiSecret: API_SECRET,
apiPass: API_PASS,
// apiKey: 'apiKeyHere',
// apiSecret: 'apiSecretHere',
// apiPass: 'apiPassHere',
});
/** This is a simple script wrapped in a immediately invoked function expression, designed to check for any available BTC balance and immediately sell the full amount for USDT */
(async () => {
try {
console.log(await client.getApiKeyInfo());
} catch (e) {
console.error('request failed: ', e);
}
})();

View File

@@ -0,0 +1,30 @@
import { FuturesClient, WebsocketClient } from '../../src/index';
// or
// import { SpotClient } from 'bitget-api';
const futuresClient = new FuturesClient();
const symbol = 'BTCUSDT_UMCBL';
(async () => {
try {
// Fetch the last 1000 1min candles for a symbol
const timestampNow = Date.now();
const msPerCandle = 60 * 1000; // 60 seconds x 1000
const candlesToFetch = 1000;
const msFor1kCandles = candlesToFetch * msPerCandle;
const startTime = timestampNow - msFor1kCandles;
const response = await futuresClient.getCandles(
symbol,
'1m',
startTime.toString(),
timestampNow.toString(),
candlesToFetch.toString(),
);
console.log('getCandles returned ' + response.length + ' candles');
} catch (e) {
console.error('request failed: ', e);
}
})();

View File

@@ -0,0 +1,19 @@
import { SpotClient } from '../../src/index';
// or
// import { SpotClient } from 'bitget-api';
const spotClient = new SpotClient();
const symbol = 'BTCUSDT_SPBL';
(async () => {
try {
const response = await spotClient.getCandles(symbol, '1min', {
limit: '1000',
});
console.log('getCandles: ', response.data.length);
} catch (e) {
console.error('request failed: ', e);
}
})();

View File

@@ -0,0 +1,175 @@
import {
FuturesClient,
isWsFuturesAccountSnapshotEvent,
isWsFuturesPositionsSnapshotEvent,
NewFuturesOrder,
WebsocketClient,
} from '../../src';
// or
// import {
// FuturesClient,
// isWsFuturesAccountSnapshotEvent,
// isWsFuturesPositionsSnapshotEvent,
// NewFuturesOrder,
// WebsocketClient,
// } from 'bitget-api';
// read from environmental variables
const API_KEY = process.env.API_KEY_COM;
const API_SECRET = process.env.API_SECRET_COM;
const API_PASS = process.env.API_PASS_COM;
const client = new FuturesClient({
apiKey: API_KEY,
apiSecret: API_SECRET,
apiPass: API_PASS,
// apiKey: 'apiKeyHere',
// apiSecret: 'apiSecretHere',
// apiPass: 'apiPassHere',
});
const wsClient = new WebsocketClient({
apiKey: API_KEY,
apiSecret: API_SECRET,
apiPass: API_PASS,
});
function logWSEvent(type, data) {
console.log(new Date(), `WS ${type} event: `, data);
}
// simple sleep function
function promiseSleep(milliseconds) {
return new Promise((resolve) => setTimeout(resolve, milliseconds));
}
// WARNING: for sensitive math you should be using a library such as decimal.js!
function roundDown(value, decimals) {
return Number(
Math.floor(parseFloat(value + 'e' + decimals)) + 'e-' + decimals,
);
}
/** WS event handler that uses type guards to narrow down event type */
async function handleWsUpdate(event) {
if (isWsFuturesAccountSnapshotEvent(event)) {
console.log(new Date(), 'ws update (account balance):', event);
return;
}
if (isWsFuturesPositionsSnapshotEvent(event)) {
console.log(new Date(), 'ws update (positions):', event);
return;
}
logWSEvent('update (unhandled)', event);
}
/**
* This is a simple script wrapped in a immediately invoked function expression (to execute the below workflow immediately).
*
* It is designed to:
* - open a private websocket channel to log account events
* - check for any available USDT balance in the futures account
* - immediately open a minimum sized long position on BTCUSDT
* - check active positions
* - immediately send closing orders for any active futures positions
* - check positions again
*
* The corresponding UI for this is at https://www.bitget.com/en/mix/usdt/BTCUSDT_UMCBL
*/
(async () => {
try {
// Add event listeners to log websocket events on account
wsClient.on('update', (data) => handleWsUpdate(data));
wsClient.on('open', (data) => logWSEvent('open', data));
wsClient.on('response', (data) => logWSEvent('response', data));
wsClient.on('reconnect', (data) => logWSEvent('reconnect', data));
wsClient.on('reconnected', (data) => logWSEvent('reconnected', data));
wsClient.on('authenticated', (data) => logWSEvent('authenticated', data));
wsClient.on('exception', (data) => logWSEvent('exception', data));
// Subscribe to private account topics
wsClient.subscribeTopic('UMCBL', 'account');
// : position updates
wsClient.subscribeTopic('UMCBL', 'positions');
// : order updates
wsClient.subscribeTopic('UMCBL', 'orders');
// wait briefly for ws to be ready (could also use the response or authenticated events, to make sure topics are subscribed to before starting)
await promiseSleep(2.5 * 1000);
const symbol = 'BTCUSDT_UMCBL';
const marginCoin = 'USDT';
const balanceResult = await client.getAccount(symbol, marginCoin);
const accountBalance = balanceResult.data;
// const balances = allBalances.filter((bal) => Number(bal.available) != 0);
const usdtAmount = accountBalance.available;
console.log('USDT balance: ', usdtAmount);
if (!usdtAmount) {
console.error('No USDT to trade');
return;
}
const symbolRulesResult = await client.getSymbols('umcbl');
const bitcoinUSDFuturesRule = symbolRulesResult.data.find(
(row) => row.symbol === symbol,
);
console.log('symbol rules: ', bitcoinUSDFuturesRule);
if (!bitcoinUSDFuturesRule) {
console.error('Failed to get trading rules for ' + symbol);
return;
}
const order: NewFuturesOrder = {
marginCoin,
orderType: 'market',
side: 'open_long',
size: bitcoinUSDFuturesRule.minTradeNum,
symbol,
} as const;
console.log('placing order: ', order);
const result = await client.submitOrder(order);
console.log('order result: ', result);
const positionsResult = await client.getPositions('umcbl');
const positionsToClose = positionsResult.data.filter(
(pos) => pos.total !== '0',
);
console.log('open positions to close: ', positionsToClose);
// Loop through any active positions and send a closing market order on each position
for (const position of positionsToClose) {
const closingSide =
position.holdSide === 'long' ? 'close_long' : 'close_short';
const closingOrder: NewFuturesOrder = {
marginCoin: position.marginCoin,
orderType: 'market',
side: closingSide,
size: position.available,
symbol: position.symbol,
};
console.log('closing position with market order: ', closingOrder);
const result = await client.submitOrder(closingOrder);
console.log('position closing order result: ', result);
}
console.log(
'positions after closing all: ',
await client.getPositions('umcbl'),
);
} catch (e) {
console.error('request failed: ', e);
}
})();

View File

@@ -0,0 +1,104 @@
import { SpotClient, WebsocketClient } from '../../src/index';
// or
// import { SpotClient } from 'bitget-api';
// read from environmental variables
const API_KEY = process.env.API_KEY_COM;
const API_SECRET = process.env.API_SECRET_COM;
const API_PASS = process.env.API_PASS_COM;
const client = new SpotClient({
apiKey: API_KEY,
apiSecret: API_SECRET,
apiPass: API_PASS,
// apiKey: 'apiKeyHere',
// apiSecret: 'apiSecretHere',
// apiPass: 'apiPassHere',
});
const wsClient = new WebsocketClient({
apiKey: API_KEY,
apiSecret: API_SECRET,
apiPass: API_PASS,
});
function logWSEvent(type, data) {
console.log(new Date(), `WS ${type} event: `, data);
}
// simple sleep function
function promiseSleep(milliseconds) {
return new Promise((resolve) => setTimeout(resolve, milliseconds));
}
// WARNING: for sensitive math you should be using a library such as decimal.js!
function roundDown(value, decimals) {
return Number(
Math.floor(parseFloat(value + 'e' + decimals)) + 'e-' + decimals,
);
}
/** This is a simple script wrapped in a immediately invoked function expression, designed to check for any available BTC balance and immediately sell the full amount for USDT */
(async () => {
try {
// Add event listeners to log websocket events on account
wsClient.on('update', (data) => logWSEvent('update', data));
wsClient.on('open', (data) => logWSEvent('open', data));
wsClient.on('response', (data) => logWSEvent('response', data));
wsClient.on('reconnect', (data) => logWSEvent('reconnect', data));
wsClient.on('reconnected', (data) => logWSEvent('reconnected', data));
wsClient.on('authenticated', (data) => logWSEvent('authenticated', data));
wsClient.on('exception', (data) => logWSEvent('exception', data));
// Subscribe to private account topics
wsClient.subscribeTopic('SPBL', 'account');
wsClient.subscribeTopic('SPBL', 'orders');
// wait briefly for ws to be ready (could also use the response or authenticated events, to make sure topics are subscribed to before starting)
await promiseSleep(2.5 * 1000);
const balanceResult = await client.getBalance();
const allBalances = balanceResult.data;
// const balances = allBalances.filter((bal) => Number(bal.available) != 0);
const balanceBTC = allBalances.find((bal) => bal.coinName === 'BTC');
const btcAmount = balanceBTC ? Number(balanceBTC.available) : 0;
// console.log('balance: ', JSON.stringify(balances, null, 2));
console.log('BTC balance result: ', balanceBTC);
if (!btcAmount) {
console.error('No BTC to trade');
return;
}
console.log(`BTC available: ${btcAmount}`);
const symbol = 'BTCUSDT_SPBL';
const symbolsResult = await client.getSymbols();
const btcRules = symbolsResult.data.find((rule) => rule.symbol === symbol);
console.log('btc trading rules: ', btcRules);
if (!btcRules) {
return console.log('no rules found for trading ' + symbol);
}
const quantityScale = Number(btcRules.quantityScale);
// const quantityRoundedDown = btcAmount - btcAmount % 0.01
const quantity = roundDown(btcAmount, quantityScale);
const order = {
symbol: symbol,
side: 'sell',
force: 'normal',
orderType: 'market',
quantity: String(quantity),
} as const;
console.log('submitting order: ', order);
const sellResult = await client.submitOrder(order);
console.log('sell result: ', sellResult);
} catch (e) {
console.error('request failed: ', e);
}
})();

View File

@@ -1,14 +1,14 @@
import { FuturesClient, WebsocketClient } from '../src/index';
import { RestClientV2, WebsocketClient } from '../src/index';
// or
// import { SpotClient } from 'bitget-api';
// import { RestClientV2 } from 'bitget-api';
// read from environmental variables
const API_KEY = process.env.API_KEY_COM;
const API_SECRET = process.env.API_SECRET_COM;
const API_PASS = process.env.API_PASS_COM;
const client = new FuturesClient({
const client = new RestClientV2({
apiKey: API_KEY,
apiSecret: API_SECRET,
apiPass: API_PASS,
@@ -21,15 +21,14 @@ const client = new FuturesClient({
(async () => {
try {
const now = new Date();
const toTime = new Date(now.getTime() - 24 * 60 * 60 * 1000);
const fromTime = new Date(now.getTime() - 24 * 60 * 60 * 1000);
console.log(
await client.getAccountBill({
symbol: 'BTCUSDT_UMCBL',
marginCoin: 'USDT',
startTime: now.getTime() + '', // should be sent as a string
endTime: toTime.getTime() + '', // should be sent as a string
pageSize: 100,
await client.getFuturesAccountBills({
productType: 'USDT-FUTURES',
startTime: fromTime.getTime() + '', // should be sent as a string
endTime: now.getTime() + '', // should be sent as a string
limit: '100',
}),
);
} catch (e) {

View File

@@ -1,14 +1,14 @@
import { SpotClient, WebsocketClient } from '../src/index';
import { RestClientV2, WebsocketClient } from '../src/index';
// or
// import { SpotClient } from 'bitget-api';
// import { RestClientV2 } from 'bitget-api';
// read from environmental variables
const API_KEY = process.env.API_KEY_COM;
const API_SECRET = process.env.API_SECRET_COM;
const API_PASS = process.env.API_PASS_COM;
const client = new SpotClient({
const client = new RestClientV2({
apiKey: API_KEY,
apiSecret: API_SECRET,
apiPass: API_PASS,
@@ -20,7 +20,7 @@ const client = new SpotClient({
/** This is a simple script wrapped in a immediately invoked function expression, designed to check for any available BTC balance and immediately sell the full amount for USDT */
(async () => {
try {
console.log(await client.getApiKeyInfo());
console.log(await client.getSpotAccount());
} catch (e) {
console.error('request failed: ', e);
}

View File

@@ -1,11 +1,11 @@
import { FuturesClient, SpotClient } from '../src/index';
import { RestClientV2, SpotClient } from '../src/index';
// or
// import { SpotClient } from 'bitget-api';
const futuresClient = new FuturesClient();
const restClient = new RestClientV2();
const symbol = 'BTCUSDT_UMCBL';
const symbol = 'BTCUSDT';
(async () => {
try {
@@ -16,14 +16,18 @@ const symbol = 'BTCUSDT_UMCBL';
const msFor1kCandles = candlesToFetch * msPerCandle;
const startTime = timestampNow - msFor1kCandles;
const response = await futuresClient.getCandles(
const response = await restClient.getFuturesCandles({
symbol,
'1m',
startTime.toString(),
timestampNow.toString(),
candlesToFetch.toString(),
);
console.log('getCandles returned ' + response.length + ' candles');
productType: 'USDT-FUTURES',
granularity: '1m',
startTime: startTime.toString(),
endTime: timestampNow.toString(),
limit: candlesToFetch.toString(),
});
console.table(response.data);
console.log('getCandles returned ' + response.data.length + ' candles');
} catch (e) {
console.error('request failed: ', e);
}

View File

@@ -1,17 +1,19 @@
import { SpotClient } from '../src/index';
import { RestClientV2 } from '../src/index';
// or
// import { SpotClient } from 'bitget-api';
// import { RestClientV2 } from 'bitget-api';
const spotClient = new SpotClient();
const symbol = 'BTCUSDT_SPBL';
const restClient = new RestClientV2();
(async () => {
try {
const response = await spotClient.getCandles(symbol, '1min', {
const response = await restClient.getSpotCandles({
symbol: 'BTCUSDT',
granularity: '1min',
limit: '1000',
});
console.table(response.data);
console.log('getCandles: ', response.data.length);
} catch (e) {
console.error('request failed: ', e);

View File

@@ -1,3 +1,4 @@
export * from './rest-client-v2';
export * from './broker-client';
export * from './futures-client';
export * from './spot-client';

View File

@@ -1,27 +1,9 @@
import {
NewBatchSpotOrder,
NewSpotOrder,
NewWalletTransfer,
Pagination,
APIResponse,
CoinBalance,
SymbolRules,
NewSpotSubTransfer,
NewSpotWithdraw,
CancelSpotOrderV2,
BatchCancelSpotOrderV2,
SpotOrderResult,
NewSpotPlanOrder,
ModifySpotPlanOrder,
CancelSpotPlanOrderParams,
GetSpotPlanOrdersParams,
SpotPlanOrder,
GetHistoricPlanOrdersParams,
SpotMarketTrade,
GetHistoricTradesParams,
VIPFeeRate,
SpotKlineInterval,
MarginType,
FuturesAccountBillRequestV2,
FuturesCandlesRequestV2,
SpotCandlesRequestV2,
} from './types';
import { REST_CLIENT_TYPE_ENUM, assertMarginType } from './util';
import BaseRestClient from './util/BaseRestClient';
@@ -223,11 +205,11 @@ export class RestClientV2 extends BaseRestClient {
return this.getPrivate(`/api/v2/spot/market/orderbook`, params);
}
getSpotCandlestickData(params: object): Promise<APIResponse<any>> {
getSpotCandles(params: SpotCandlesRequestV2): Promise<APIResponse<any>> {
return this.getPrivate(`/api/v2/spot/market/candles`, params);
}
getSpotHistoricCandlestickData(params: object): Promise<APIResponse<any>> {
getSpotHistoricCandles(params: object): Promise<APIResponse<any>> {
return this.getPrivate(`/api/v2/spot/market/history-candles`, params);
}
@@ -394,21 +376,23 @@ export class RestClientV2 extends BaseRestClient {
return this.get(`/api/v2/mix/market/merge-depth`, params);
}
getFuturesCandlestickData(params: object): Promise<APIResponse<any>> {
getFuturesCandles(
params: FuturesCandlesRequestV2,
): Promise<APIResponse<any>> {
return this.get(`/api/v2/mix/market/candles`, params);
}
getFuturesHistoricCandlestickData(params: object): Promise<APIResponse<any>> {
getFuturesHistoricCandles(params: object): Promise<APIResponse<any>> {
return this.get(`/api/v2/mix/market/history-candles`, params);
}
getFuturesHistoricIndexPriceCandlestick(
getFuturesHistoricIndexPriceCandles(
params: object,
): Promise<APIResponse<any>> {
return this.get(`/api/v2/mix/market/history-index-candles`, params);
}
getFuturesHistoricMarkPriceCandlestick(
getFuturesHistoricMarkPriceCandles(
params: object,
): Promise<APIResponse<any>> {
return this.get(`/api/v2/mix/market/history-mark-candles`, params);
@@ -484,7 +468,9 @@ export class RestClientV2 extends BaseRestClient {
return this.postPrivate(`/api/v2/mix/account/set-position-mode`, params);
}
getFuturesAccountBills(params: object): Promise<APIResponse<any>> {
getFuturesAccountBills(
params: FuturesAccountBillRequestV2,
): Promise<APIResponse<any>> {
return this.getPrivate(`/api/v2/mix/account/bill`, params);
}

View File

@@ -1,4 +1,6 @@
export * from './broker';
export * from './futures';
export * from './v1/brokerV1';
export * from './v1/futuresV1';
export * from './v1/spotV1';
export * from './v2/futures';
export * from './v2/spot';
export * from './shared';
export * from './spot';

View File

@@ -1,4 +1,4 @@
import { OrderTimeInForce } from './shared';
import { OrderTimeInForce } from '../shared';
export type FuturesProductType =
| 'umcbl'

View File

@@ -1,4 +1,4 @@
import { OrderTimeInForce } from './shared';
import { OrderTimeInForce } from '../shared';
export type WalletType = 'spot' | 'mix_usdt' | 'mix_usd';

View File

@@ -0,0 +1,32 @@
import { FuturesKlineInterval } from '../v1/futuresV1';
export type FuturesProductTypeV2 =
| 'USDT-FUTURES'
| 'COIN-FUTURES'
| 'USDC-FUTURES'
| 'SUSDT-FUTURES'
| 'SCOIN-FUTURES'
| 'SUSDC-FUTURES';
export type FuturesKlineTypeV2 = 'MARKET' | 'MARK' | 'INDEX';
export interface FuturesAccountBillRequestV2 {
productType: FuturesProductTypeV2;
symbol?: string;
coin?: string;
businessType?: string;
idLessThan?: string;
startTime?: string;
endTime?: string;
limit?: string;
}
export interface FuturesCandlesRequestV2 {
symbol: string;
productType: FuturesProductTypeV2;
granularity: FuturesKlineInterval;
startTime?: string;
endTime?: string;
kLineType?: FuturesKlineTypeV2;
limit?: string;
}

View File

@@ -0,0 +1,9 @@
import { SpotKlineInterval } from '../v1/spotV1';
export interface SpotCandlesRequestV2 {
symbol: string;
granularity: SpotKlineInterval;
startTime?: string;
endTime?: string;
limit?: string;
}