feat(): add comprehensive tests for Bitget Private and Public REST API endpoints
- Introduced new test files for private read and write endpoints, covering account, trade, funding, and futures functionalities. - Added public API tests for server time, ticker, order book, and market trades - Enhanced error handling in tests with specific error codes and messages. - Updated response utility functions to improve error response structure. - Removed outdated broker tests to streamline the test suite.
This commit is contained in:
@@ -1,111 +0,0 @@
|
|||||||
import { API_ERROR_CODE, BrokerClient } from '../../src';
|
|
||||||
import { sucessEmptyResponseObject } from '../response.util';
|
|
||||||
|
|
||||||
describe('Private Broker REST API GET Endpoints', () => {
|
|
||||||
const API_KEY = process.env.API_KEY_COM;
|
|
||||||
const API_SECRET = process.env.API_SECRET_COM;
|
|
||||||
const API_PASS = process.env.API_PASS_COM;
|
|
||||||
|
|
||||||
it('should have api credentials to test with', () => {
|
|
||||||
expect(API_KEY).toStrictEqual(expect.any(String));
|
|
||||||
expect(API_SECRET).toStrictEqual(expect.any(String));
|
|
||||||
expect(API_PASS).toStrictEqual(expect.any(String));
|
|
||||||
});
|
|
||||||
|
|
||||||
const api = new BrokerClient({
|
|
||||||
apiKey: API_KEY,
|
|
||||||
apiSecret: API_SECRET,
|
|
||||||
apiPass: API_PASS,
|
|
||||||
});
|
|
||||||
|
|
||||||
const coin = 'BTC';
|
|
||||||
const subUid = '123456';
|
|
||||||
// const timestampOneHourAgo = new Date().getTime() - 1000 * 60 * 60;
|
|
||||||
// const from = timestampOneHourAgo.toFixed(0);
|
|
||||||
// const to = String(Number(from) + 1000 * 60 * 30); // 30 minutes
|
|
||||||
|
|
||||||
it('getBrokerInfo()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getBrokerInfo()).toMatchObject(
|
|
||||||
sucessEmptyResponseObject(),
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_BROKER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getSubAccounts()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getSubAccounts()).toMatchObject(
|
|
||||||
sucessEmptyResponseObject(),
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_BROKER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getSubEmail()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getSubEmail(subUid)).toMatchObject(
|
|
||||||
sucessEmptyResponseObject(),
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_BROKER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getSubSpotAssets()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getSubSpotAssets(subUid)).toMatchObject(
|
|
||||||
sucessEmptyResponseObject(),
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
// expect(e.body).toBeNull();
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_BROKER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getSubFutureAssets()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getSubFutureAssets(subUid, 'usdt')).toMatchObject(
|
|
||||||
sucessEmptyResponseObject(),
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_BROKER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getSubDepositAddress()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getSubDepositAddress(subUid, coin)).toMatchObject(
|
|
||||||
sucessEmptyResponseObject(),
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_BROKER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getSubAPIKeys()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getSubAPIKeys(subUid)).toMatchObject(
|
|
||||||
sucessEmptyResponseObject(),
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_BROKER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
import { API_ERROR_CODE, BrokerClient } from '../../src';
|
|
||||||
import { sucessEmptyResponseObject } from '../response.util';
|
|
||||||
|
|
||||||
describe('Private Broker REST API POST Endpoints', () => {
|
|
||||||
const API_KEY = process.env.API_KEY_COM;
|
|
||||||
const API_SECRET = process.env.API_SECRET_COM;
|
|
||||||
const API_PASS = process.env.API_PASS_COM;
|
|
||||||
|
|
||||||
it('should have api credentials to test with', () => {
|
|
||||||
expect(API_KEY).toStrictEqual(expect.any(String));
|
|
||||||
expect(API_SECRET).toStrictEqual(expect.any(String));
|
|
||||||
expect(API_PASS).toStrictEqual(expect.any(String));
|
|
||||||
});
|
|
||||||
|
|
||||||
const api = new BrokerClient({
|
|
||||||
apiKey: API_KEY,
|
|
||||||
apiSecret: API_SECRET,
|
|
||||||
apiPass: API_PASS,
|
|
||||||
});
|
|
||||||
|
|
||||||
// const coin = 'BTC';
|
|
||||||
const subUid = '123456';
|
|
||||||
// const timestampOneHourAgo = new Date().getTime() - 1000 * 60 * 60;
|
|
||||||
// const from = timestampOneHourAgo.toFixed(0);
|
|
||||||
// const to = String(Number(from) + 1000 * 60 * 30); // 30 minutes
|
|
||||||
|
|
||||||
it('createSubAccount()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.createSubAccount('test1')).toMatchObject(
|
|
||||||
sucessEmptyResponseObject(),
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_BROKER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('modifySubAccount()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.modifySubAccount('test1', 'spot_trade,transfer', 'normal'),
|
|
||||||
).toMatchObject(sucessEmptyResponseObject());
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_BROKER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('modifySubEmail()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.modifySubEmail('test1', 'ASDFASDF@LKMASDF.COM'),
|
|
||||||
).toMatchObject(sucessEmptyResponseObject());
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_BROKER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('subWithdrawal()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.subWithdrawal({
|
|
||||||
address: '123455',
|
|
||||||
amount: '12345',
|
|
||||||
chain: 'TRC20',
|
|
||||||
coin: 'USDT',
|
|
||||||
subUid,
|
|
||||||
}),
|
|
||||||
).toMatchObject(sucessEmptyResponseObject());
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_BROKER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('setSubDepositAutoTransfer()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.setSubDepositAutoTransfer(subUid, 'USDT', 'spot'),
|
|
||||||
).toMatchObject(sucessEmptyResponseObject());
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_BROKER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('createSubAPIKey()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.createSubAPIKey(
|
|
||||||
subUid,
|
|
||||||
'passphrase12345',
|
|
||||||
'remark',
|
|
||||||
'10.0.0.1',
|
|
||||||
),
|
|
||||||
).toMatchObject(sucessEmptyResponseObject());
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_BROKER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('modifySubAPIKey()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.modifySubAPIKey({
|
|
||||||
apikey: '12345',
|
|
||||||
subUid,
|
|
||||||
remark: 'test',
|
|
||||||
}),
|
|
||||||
).toMatchObject(sucessEmptyResponseObject());
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.PASSPHRASE_CANNOT_BE_EMPTY,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,398 +0,0 @@
|
|||||||
import { API_ERROR_CODE, FuturesClient } from '../../src';
|
|
||||||
import { sucessEmptyResponseObject } from '../response.util';
|
|
||||||
|
|
||||||
describe('Private Futures REST API GET Endpoints', () => {
|
|
||||||
const API_KEY = process.env.API_KEY_COM;
|
|
||||||
const API_SECRET = process.env.API_SECRET_COM;
|
|
||||||
const API_PASS = process.env.API_PASS_COM;
|
|
||||||
|
|
||||||
it('should have api credentials to test with', () => {
|
|
||||||
expect(API_KEY).toStrictEqual(expect.any(String));
|
|
||||||
expect(API_SECRET).toStrictEqual(expect.any(String));
|
|
||||||
expect(API_PASS).toStrictEqual(expect.any(String));
|
|
||||||
});
|
|
||||||
|
|
||||||
const api = new FuturesClient({
|
|
||||||
apiKey: API_KEY,
|
|
||||||
apiSecret: API_SECRET,
|
|
||||||
apiPass: API_PASS,
|
|
||||||
});
|
|
||||||
|
|
||||||
const symbol = 'BTCUSDT_UMCBL';
|
|
||||||
const marginCoin = 'USDT';
|
|
||||||
const timestampOneHourAgo = new Date().getTime() - 1000 * 60 * 60;
|
|
||||||
const from = timestampOneHourAgo.toFixed(0);
|
|
||||||
const to = String(Number(from) + 1000 * 60 * 30); // 30 minutes
|
|
||||||
|
|
||||||
it('getAccount()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getAccount(symbol, marginCoin)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {
|
|
||||||
available: expect.any(String),
|
|
||||||
btcEquity: expect.any(String),
|
|
||||||
equity: expect.any(String),
|
|
||||||
marginCoin: expect.any(String),
|
|
||||||
marginMode: expect.any(String),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getAccount: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getAccounts()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getAccounts('umcbl')).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getAccounts: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getOpenCount()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.getOpenCount(symbol, marginCoin, 20000, 1),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {
|
|
||||||
openCount: expect.any(Number),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getOpenCount: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getPosition()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getPosition(symbol, marginCoin)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getPosition: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getPositions()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getPositions('umcbl')).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getPosition: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getAccountBill()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.getAccountBill({
|
|
||||||
startTime: from,
|
|
||||||
endTime: to,
|
|
||||||
marginCoin,
|
|
||||||
symbol,
|
|
||||||
}),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {
|
|
||||||
lastEndId: null,
|
|
||||||
nextFlag: false,
|
|
||||||
preFlag: false,
|
|
||||||
result: expect.any(Array),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getAccountBill: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getBusinessBill()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.getBusinessBill({
|
|
||||||
startTime: from,
|
|
||||||
endTime: to,
|
|
||||||
productType: 'umcbl',
|
|
||||||
}),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {
|
|
||||||
lastEndId: null,
|
|
||||||
nextFlag: false,
|
|
||||||
preFlag: false,
|
|
||||||
result: expect.any(Array),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getBusinessBill: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getOpenSymbolOrders()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getOpenSymbolOrders(symbol)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getOpenSymbolOrders: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getOpenOrders()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getOpenOrders('umcbl', marginCoin)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getOpenOrders: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getOrderHistory()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getOrderHistory(symbol, from, to, '10')).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Object),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getOrderHistory: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getProductTypeOrderHistory()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.getProductTypeOrderHistory('umcbl', from, to, '10'),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Object),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getProductTypeOrderHistory: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getOrder() should throw FUTURES_ORDER_NOT_FOUND', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getOrder(symbol, '12345')).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Object),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.FUTURES_ORDER_GET_NOT_FOUND,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getOrderFills() should throw FUTURES_ORDER_NOT_FOUND', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getOrderFills(symbol, '12345')).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Object),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.FUTURES_ORDER_GET_NOT_FOUND,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getProductTypeOrderFills() ', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.getProductTypeOrderFills('umcbl', {
|
|
||||||
startTime: from,
|
|
||||||
endTime: to,
|
|
||||||
}),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Object),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getProductTypeOrderFills: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getPlanOrderTPSLs()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getPlanOrderTPSLs(symbol)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Object),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getPlanOrderTPSLs: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getHistoricPlanOrdersTPSL()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.getHistoricPlanOrdersTPSL({
|
|
||||||
startTime: from,
|
|
||||||
endTime: to,
|
|
||||||
symbol,
|
|
||||||
}),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Object),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getHistoricPlanOrdersTPSL: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it.skip('getCopyTraderOpenOrder()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.getCopyTraderOpenOrder(symbol, 'umcbl', 1, 0),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Object),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getCopyFollowersOpenOrder()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.getCopyFollowersOpenOrder(symbol, 'umcbl', 1, 0),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Object),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it.skip('getCopyTraderOrderHistory()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getCopyTraderOrderHistory(from, to, 1, 0)).toMatchObject(
|
|
||||||
{
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Object),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getCopyTraderProfitSummary()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getCopyTraderProfitSummary()).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Object),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getCopyTraderHistoricProfitSummary()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getCopyTraderHistoricProfitSummary()).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Object),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getCopyTraderHistoricProfitSummaryByDate()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.getCopyTraderHistoricProfitSummaryByDate(
|
|
||||||
marginCoin,
|
|
||||||
from,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Object),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getCopyTraderHistoricProfitDetail()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.getCopyTraderHistoricProfitDetail(marginCoin, from, 1, 1),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Object),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getCopyTraderProfitDetails()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getCopyTraderProfitDetails(1, 1)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Object),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getCopyTraderSymbols()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getCopyTraderSymbols()).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Object),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,352 +0,0 @@
|
|||||||
import { API_ERROR_CODE, FuturesClient } from '../../src';
|
|
||||||
import { sucessEmptyResponseObject } from '../response.util';
|
|
||||||
|
|
||||||
jest.setTimeout(10000);
|
|
||||||
|
|
||||||
describe('Private Futures REST API POST Endpoints', () => {
|
|
||||||
const API_KEY = process.env.API_KEY_COM;
|
|
||||||
const API_SECRET = process.env.API_SECRET_COM;
|
|
||||||
const API_PASS = process.env.API_PASS_COM;
|
|
||||||
|
|
||||||
it('should have api credentials to test with', () => {
|
|
||||||
expect(API_KEY).toStrictEqual(expect.any(String));
|
|
||||||
expect(API_SECRET).toStrictEqual(expect.any(String));
|
|
||||||
expect(API_PASS).toStrictEqual(expect.any(String));
|
|
||||||
});
|
|
||||||
|
|
||||||
const api = new FuturesClient({
|
|
||||||
apiKey: API_KEY,
|
|
||||||
apiSecret: API_SECRET,
|
|
||||||
apiPass: API_PASS,
|
|
||||||
});
|
|
||||||
|
|
||||||
const symbol = 'BTCUSDT_UMCBL';
|
|
||||||
const marginCoin = 'USDT';
|
|
||||||
// const timestampOneHourAgo = new Date().getTime() - 1000 * 60 * 60;
|
|
||||||
// const from = timestampOneHourAgo.toFixed(0);
|
|
||||||
// const to = String(Number(from) + 1000 * 60 * 30); // 30 minutes
|
|
||||||
|
|
||||||
it('setLeverage()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.setLeverage(symbol, marginCoin, '20')).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('setLeverage: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('setMargin()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.setMargin(symbol, marginCoin, '-10')).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
// expect(e).toBeNull();
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.PARAMETER_EXCEPTION,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('setMarginMode()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.setMarginMode(symbol, marginCoin, 'crossed'),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('setMarginMode: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('submitOrder()', async () => {
|
|
||||||
const symbol = 'BTCUSDT_UMCBL';
|
|
||||||
const marginCoin = 'USDT';
|
|
||||||
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.submitOrder({
|
|
||||||
marginCoin,
|
|
||||||
orderType: 'market',
|
|
||||||
symbol,
|
|
||||||
size: '1',
|
|
||||||
side: 'open_long',
|
|
||||||
}),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_KYC_REQUIRED,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('batchSubmitOrder()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.batchSubmitOrder(symbol, marginCoin, [
|
|
||||||
{
|
|
||||||
orderType: 'market',
|
|
||||||
size: '1',
|
|
||||||
side: 'open_long',
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_KYC_REQUIRED,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('cancelOrder()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.cancelOrder(symbol, marginCoin, '1234656'),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.FUTURES_ORDER_CANCEL_NOT_FOUND,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('batchCancelOrder()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.batchCancelOrder(symbol, marginCoin, ['1234656']),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('batchCancelOrder: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('cancelAllOrders()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.cancelAllOrders('umcbl', marginCoin)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.NO_ORDER_TO_CANCEL,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it.skip('submitPlanOrder()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.submitPlanOrder({
|
|
||||||
marginCoin,
|
|
||||||
orderType: 'market',
|
|
||||||
side: 'open_long',
|
|
||||||
size: '0.1',
|
|
||||||
symbol,
|
|
||||||
triggerPrice: '1000',
|
|
||||||
triggerType: 'market_price',
|
|
||||||
}),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
// {"code": "40889", "data": null, "msg": "The plan order of this contract has reached the upper limit"
|
|
||||||
// if the above error is seen, you need to cancel trigger orders on the test account (in futures)
|
|
||||||
console.error('submitPlanOrder: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it.skip('modifyPlanOrder()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.modifyPlanOrder({
|
|
||||||
orderId: '123456',
|
|
||||||
marginCoin,
|
|
||||||
orderType: 'market',
|
|
||||||
symbol,
|
|
||||||
triggerPrice: '100',
|
|
||||||
triggerType: 'market_price',
|
|
||||||
}),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.PLAN_ORDER_NOT_FOUND,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('modifyPlanOrderTPSL()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.modifyPlanOrderTPSL({
|
|
||||||
orderId: '123456',
|
|
||||||
marginCoin,
|
|
||||||
symbol,
|
|
||||||
presetTakeProfitPrice: '100',
|
|
||||||
}),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
// expect(e).toBeNull();
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.PLAN_ORDER_NOT_FOUND,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it.skip('submitStopOrder()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.submitStopOrder({
|
|
||||||
marginCoin,
|
|
||||||
symbol,
|
|
||||||
planType: 'profit_plan',
|
|
||||||
holdSide: 'long',
|
|
||||||
triggerPrice: '100',
|
|
||||||
}),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
// console.log(e.body);
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.FUTURES_INSUFFICIENT_POSITION_NO_TPSL,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('submitPositionTPSL()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.submitPositionTPSL({
|
|
||||||
marginCoin,
|
|
||||||
symbol,
|
|
||||||
holdSide: 'long',
|
|
||||||
planType: 'profit_plan',
|
|
||||||
triggerPrice: '50',
|
|
||||||
triggerType: 'market_price',
|
|
||||||
}),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.FUTURES_INSUFFICIENT_POSITION_NO_TPSL,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('modifyStopOrder()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.modifyStopOrder({
|
|
||||||
marginCoin,
|
|
||||||
symbol,
|
|
||||||
orderId: '123456',
|
|
||||||
planType: 'profit_plan',
|
|
||||||
}),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
// expect(e).toBeNull();
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.FUTURES_ORDER_TPSL_NOT_FOUND,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('cancelPlanOrderTPSL()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.cancelPlanOrderTPSL({
|
|
||||||
marginCoin,
|
|
||||||
symbol,
|
|
||||||
orderId: '123456',
|
|
||||||
planType: 'profit_plan',
|
|
||||||
}),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.FUTURES_ORDER_TPSL_NOT_FOUND,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it.skip('closeCopyTraderPosition()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.closeCopyTraderPosition(symbol, '123456')).toMatchObject(
|
|
||||||
{
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it.skip('modifyCopyTraderTPSL()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.modifyCopyTraderTPSL(symbol, '123456', {
|
|
||||||
stopLossPrice: 1234,
|
|
||||||
}),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it.skip('setCopyTraderSymbols()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.setCopyTraderSymbols(symbol, 'delete')).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_NOT_COPY_TRADER,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
import { FuturesClient } from '../../src';
|
|
||||||
import { sucessEmptyResponseObject } from '../response.util';
|
|
||||||
|
|
||||||
describe('Public Spot REST API Endpoints', () => {
|
|
||||||
const api = new FuturesClient();
|
|
||||||
|
|
||||||
const symbol = 'BTCUSDT_UMCBL';
|
|
||||||
const timestampOneHourAgo = new Date().getTime() - 1000 * 60 * 60;
|
|
||||||
const from = Number(timestampOneHourAgo.toFixed(0));
|
|
||||||
const to = from + 1000 * 60 * 30; // 30 minutes
|
|
||||||
|
|
||||||
// it('should throw for unauthenticated private calls', async () => {
|
|
||||||
// expect(() => api.getOpenOrders()).rejects.toMatchObject(
|
|
||||||
// notAuthenticatedError()
|
|
||||||
// );
|
|
||||||
// expect(() => api.getBalances()).rejects.toMatchObject(
|
|
||||||
// notAuthenticatedError()
|
|
||||||
// );
|
|
||||||
// });
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Market
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
it('getSymbols()', async () => {
|
|
||||||
expect(await api.getSymbols('umcbl')).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getDepth()', async () => {
|
|
||||||
expect(await api.getDepth(symbol)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {
|
|
||||||
bids: expect.any(Array),
|
|
||||||
asks: expect.any(Array),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getTicker()', async () => {
|
|
||||||
expect(await api.getTicker(symbol)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {
|
|
||||||
bestAsk: expect.any(String),
|
|
||||||
bestBid: expect.any(String),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getAllTickers()', async () => {
|
|
||||||
expect(await api.getAllTickers('umcbl')).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getMarketTrades()', async () => {
|
|
||||||
expect(await api.getMarketTrades(symbol)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getCandles()', async () => {
|
|
||||||
expect(
|
|
||||||
await api.getCandles(symbol, '1m', `${from}`, `${to}`),
|
|
||||||
).toMatchObject(expect.any(Array));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getIndexPrice()', async () => {
|
|
||||||
expect(await api.getIndexPrice(symbol)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {
|
|
||||||
index: expect.any(String),
|
|
||||||
symbol: expect.any(String),
|
|
||||||
timestamp: expect.any(String),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getNextFundingTime()', async () => {
|
|
||||||
expect(await api.getNextFundingTime(symbol)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {
|
|
||||||
fundingTime: expect.any(String),
|
|
||||||
symbol: expect.any(String),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getHistoricFundingRate()', async () => {
|
|
||||||
expect(await api.getHistoricFundingRate(symbol)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getCurrentFundingRate()', async () => {
|
|
||||||
expect(await api.getCurrentFundingRate(symbol)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {
|
|
||||||
fundingRate: expect.any(String),
|
|
||||||
symbol: expect.any(String),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getOpenInterest()', async () => {
|
|
||||||
expect(await api.getOpenInterest(symbol)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {
|
|
||||||
amount: expect.any(String),
|
|
||||||
symbol: expect.any(String),
|
|
||||||
timestamp: expect.any(String),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getMarkPrice()', async () => {
|
|
||||||
expect(await api.getMarkPrice(symbol)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {
|
|
||||||
markPrice: expect.any(String),
|
|
||||||
symbol: expect.any(String),
|
|
||||||
timestamp: expect.any(String),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getLeverageMinMax()', async () => {
|
|
||||||
expect(await api.getLeverageMinMax(symbol)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {
|
|
||||||
maxLeverage: expect.any(String),
|
|
||||||
minLeverage: expect.any(String),
|
|
||||||
symbol: expect.any(String),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
171
test/private.read.test.ts
Normal file
171
test/private.read.test.ts
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
import { RestClientV2 } from '../src/rest-client-v2';
|
||||||
|
import {
|
||||||
|
errorResponseObjectV3,
|
||||||
|
sucessEmptyResponseObject,
|
||||||
|
} from './response.util';
|
||||||
|
|
||||||
|
describe('Bitget Private REST API Read Endpoints', () => {
|
||||||
|
const API_KEY = process.env.API_KEY_COM;
|
||||||
|
const API_SECRET = process.env.API_SECRET_COM;
|
||||||
|
const API_PASSPHRASE = process.env.API_PASS_COM;
|
||||||
|
|
||||||
|
const api = new RestClientV2({
|
||||||
|
apiKey: API_KEY!,
|
||||||
|
apiSecret: API_SECRET!,
|
||||||
|
apiPass: API_PASSPHRASE!,
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have api credentials to use', () => {
|
||||||
|
expect(API_KEY).toStrictEqual(expect.any(String));
|
||||||
|
expect(API_SECRET).toStrictEqual(expect.any(String));
|
||||||
|
expect(API_PASSPHRASE).toStrictEqual(expect.any(String));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Account Endpoints', () => {
|
||||||
|
it('getSpotAccount()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.getSpotAccount();
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('40001'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getSpotAccountAssets()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.getSpotAccountAssets();
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('40001'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getSpotAccountBills()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.getSpotAccountBills();
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('40001'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Trade Endpoints', () => {
|
||||||
|
it('getSpotOrder()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.getSpotOrder({
|
||||||
|
orderId: '123456789',
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('40001'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getSpotOpenOrders()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.getSpotOpenOrders();
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('40001'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getSpotHistoricOrders()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.getSpotHistoricOrders();
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('40001'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getSpotFills()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.getSpotFills({
|
||||||
|
symbol: 'BTCUSDT',
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('40001'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Funding Endpoints', () => {
|
||||||
|
it('getSpotDepositHistory()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.getSpotDepositHistory({
|
||||||
|
startTime: '1715808000000',
|
||||||
|
endTime: '1715894400000',
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('40001'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getSpotWithdrawalHistory()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.getSpotWithdrawalHistory({
|
||||||
|
startTime: '1715808000000',
|
||||||
|
endTime: '1715894400000',
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('40001'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getSpotTransferHistory()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.getSpotTransferHistory({
|
||||||
|
coin: 'BTC',
|
||||||
|
fromType: 'spot',
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('40001'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Futures Endpoints', () => {
|
||||||
|
it('getFuturesAccountAsset()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.getFuturesAccountAsset({
|
||||||
|
symbol: 'BTCUSDT',
|
||||||
|
marginCoin: 'USDT',
|
||||||
|
productType: 'USDT-FUTURES',
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('40001'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getFuturesPositions()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.getFuturesPositions({
|
||||||
|
productType: 'USDT-FUTURES',
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('40001'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getFuturesOrder()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.getFuturesOrder({
|
||||||
|
symbol: 'BTCUSDT',
|
||||||
|
productType: 'USDT-FUTURES',
|
||||||
|
orderId: '123456789',
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('40109')); // The data of the order cannot be found, please confirm the order number
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
195
test/private.write.test.ts
Normal file
195
test/private.write.test.ts
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
import { RestClientV2 } from '../src/rest-client-v2';
|
||||||
|
import {
|
||||||
|
errorResponseObjectV3,
|
||||||
|
sucessEmptyResponseObject,
|
||||||
|
} from './response.util';
|
||||||
|
|
||||||
|
describe('Bitget Private REST API Write Endpoints', () => {
|
||||||
|
const API_KEY = process.env.API_KEY_COM;
|
||||||
|
const API_SECRET = process.env.API_SECRET_COM;
|
||||||
|
const API_PASSPHRASE = process.env.API_PASS_COM;
|
||||||
|
|
||||||
|
const api = new RestClientV2({
|
||||||
|
apiKey: API_KEY!,
|
||||||
|
apiSecret: API_SECRET!,
|
||||||
|
apiPass: API_PASSPHRASE!,
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have api credentials to use', () => {
|
||||||
|
expect(API_KEY).toStrictEqual(expect.any(String));
|
||||||
|
expect(API_SECRET).toStrictEqual(expect.any(String));
|
||||||
|
expect(API_PASSPHRASE).toStrictEqual(expect.any(String));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Trade Endpoints', () => {
|
||||||
|
it('spotSubmitOrder()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.spotSubmitOrder({
|
||||||
|
symbol: 'BTCUSDT',
|
||||||
|
side: 'buy',
|
||||||
|
orderType: 'limit',
|
||||||
|
price: '20000',
|
||||||
|
size: '0.001',
|
||||||
|
force: 'gtc',
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('43012')); // not enough balance
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('spotCancelOrder()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.spotCancelOrder({
|
||||||
|
symbol: 'BTCUSDT',
|
||||||
|
orderId: '123456789',
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('43001')); //The order does not exist
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('spotBatchSubmitOrders()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.spotBatchSubmitOrders({
|
||||||
|
symbol: 'BTCUSDT',
|
||||||
|
orderList: [
|
||||||
|
{
|
||||||
|
symbol: 'BTCUSDT',
|
||||||
|
side: 'buy',
|
||||||
|
orderType: 'limit',
|
||||||
|
price: '20000',
|
||||||
|
size: '0.001',
|
||||||
|
force: 'gtc',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('43001')); //The order does not exist
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('spotBatchCancelOrders()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.spotBatchCancelOrders({
|
||||||
|
symbol: 'BTCUSDT',
|
||||||
|
orderList: [
|
||||||
|
{
|
||||||
|
symbol: 'BTCUSDT',
|
||||||
|
orderId: '123456789',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('43001')); //The order does not exist
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Funding Endpoints', () => {
|
||||||
|
it('spotTransfer()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.spotTransfer({
|
||||||
|
fromType: 'spot',
|
||||||
|
toType: 'coin_futures',
|
||||||
|
amount: '0.001',
|
||||||
|
coin: 'BTC',
|
||||||
|
symbol: 'BTCUSDT',
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('43117')); // Exceeds the maximum amount that can be transferred
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('spotWithdraw()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.spotWithdraw({
|
||||||
|
coin: 'BTC',
|
||||||
|
address: 'test_address',
|
||||||
|
chain: 'BTC',
|
||||||
|
transferType: 'on_chain',
|
||||||
|
size: '0.001',
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('40014')); // Incorrect permissions
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Futures Endpoints', () => {
|
||||||
|
it('futuresSubmitOrder()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.futuresSubmitOrder({
|
||||||
|
symbol: 'BTCUSDT',
|
||||||
|
productType: 'USDT-FUTURES',
|
||||||
|
side: 'buy',
|
||||||
|
orderType: 'limit',
|
||||||
|
price: '20000',
|
||||||
|
size: '0.001',
|
||||||
|
marginMode: 'isolated',
|
||||||
|
marginCoin: 'USDT',
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('40774')); // The order type for unilateral position must also be the unilateral position type.
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('futuresCancelOrder()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.futuresCancelOrder({
|
||||||
|
symbol: 'BTCUSDT',
|
||||||
|
productType: 'USDT-FUTURES',
|
||||||
|
orderId: '123456789',
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('40768')); // The order does not exist
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('futuresBatchSubmitOrders()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.futuresBatchSubmitOrders({
|
||||||
|
symbol: 'BTCUSDT',
|
||||||
|
productType: 'USDT-FUTURES',
|
||||||
|
marginCoin: 'USDT',
|
||||||
|
marginMode: 'crossed',
|
||||||
|
orderList: [
|
||||||
|
{
|
||||||
|
side: 'buy',
|
||||||
|
orderType: 'limit',
|
||||||
|
price: '20000',
|
||||||
|
size: '0.001',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('43001'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('futuresBatchCancelOrders()', async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.futuresBatchCancelOrders({
|
||||||
|
symbol: 'BTCUSDT',
|
||||||
|
productType: 'USDT-FUTURES',
|
||||||
|
orderIdList: [
|
||||||
|
{
|
||||||
|
orderId: '123456789',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).toMatchObject(errorResponseObjectV3('43001'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
76
test/public.test.ts
Normal file
76
test/public.test.ts
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
import { RestClientV2 } from '../src/rest-client-v2';
|
||||||
|
import { sucessEmptyResponseObject } from './response.util';
|
||||||
|
|
||||||
|
describe('Bitget Public REST API Endpoints', () => {
|
||||||
|
const api = new RestClientV2();
|
||||||
|
|
||||||
|
describe('public endpoints', () => {
|
||||||
|
it('should succeed making a GET request without params', async () => {
|
||||||
|
const res = await api.getServerTime();
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should succeed making a GET request with params', async () => {
|
||||||
|
const res = await api.getSpotTicker({ symbol: 'BTCUSDT' });
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return orderbook data', async () => {
|
||||||
|
const res = await api.getSpotOrderBookDepth({
|
||||||
|
symbol: 'BTCUSDT',
|
||||||
|
type: 'step0',
|
||||||
|
limit: '20',
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return candles data', async () => {
|
||||||
|
const res = await api.getSpotCandles({
|
||||||
|
symbol: 'BTCUSDT',
|
||||||
|
granularity: '1min',
|
||||||
|
limit: '100',
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return recent trades', async () => {
|
||||||
|
const res = await api.getSpotRecentTrades({
|
||||||
|
symbol: 'BTCUSDT',
|
||||||
|
limit: '20',
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return historic trades', async () => {
|
||||||
|
const res = await api.getSpotHistoricTrades({
|
||||||
|
symbol: 'BTCUSDT',
|
||||||
|
limit: '20',
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return funding rate data', async () => {
|
||||||
|
const res = await api.getFuturesCurrentFundingRate({
|
||||||
|
symbol: 'BTCUSDT',
|
||||||
|
productType: 'USDT-FUTURES',
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return open interest data', async () => {
|
||||||
|
const res = await api.getFuturesOpenInterest({
|
||||||
|
symbol: 'BTCUSDT',
|
||||||
|
productType: 'USDT-FUTURES',
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return contract config', async () => {
|
||||||
|
const res = await api.getFuturesContractConfig({
|
||||||
|
symbol: 'BTCUSDT',
|
||||||
|
productType: 'USDT-FUTURES',
|
||||||
|
});
|
||||||
|
expect(res).toMatchObject(sucessEmptyResponseObject());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -28,13 +28,18 @@ export function errorResponseObject(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function errorResponseObjectV3(
|
export function errorResponseObjectV3(code: string, statusCode: number = 400) {
|
||||||
result: null | any = null,
|
|
||||||
retCode: number,
|
|
||||||
) {
|
|
||||||
return {
|
return {
|
||||||
result,
|
body: {
|
||||||
retCode: retCode,
|
code,
|
||||||
|
data: null,
|
||||||
|
msg: expect.any(String),
|
||||||
|
requestTime: expect.any(Number),
|
||||||
|
},
|
||||||
|
code: statusCode,
|
||||||
|
headers: expect.any(Object),
|
||||||
|
message: expect.any(String),
|
||||||
|
requestOptions: expect.any(Object),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,202 +0,0 @@
|
|||||||
import { SpotClient } from '../../src';
|
|
||||||
import { sucessEmptyResponseObject } from '../response.util';
|
|
||||||
|
|
||||||
describe('Private Spot REST API GET Endpoints', () => {
|
|
||||||
const API_KEY = process.env.API_KEY_COM;
|
|
||||||
const API_SECRET = process.env.API_SECRET_COM;
|
|
||||||
const API_PASS = process.env.API_PASS_COM;
|
|
||||||
|
|
||||||
it('should have api credentials to test with', () => {
|
|
||||||
expect(API_KEY).toStrictEqual(expect.any(String));
|
|
||||||
expect(API_SECRET).toStrictEqual(expect.any(String));
|
|
||||||
expect(API_PASS).toStrictEqual(expect.any(String));
|
|
||||||
});
|
|
||||||
|
|
||||||
const api = new SpotClient({
|
|
||||||
apiKey: API_KEY,
|
|
||||||
apiSecret: API_SECRET,
|
|
||||||
apiPass: API_PASS,
|
|
||||||
});
|
|
||||||
|
|
||||||
const symbol = 'BTCUSDT_SPBL';
|
|
||||||
const coin = 'BTC';
|
|
||||||
const timestampOneHourAgo = new Date().getTime() - 1000 * 60 * 60;
|
|
||||||
const from = timestampOneHourAgo.toFixed(0);
|
|
||||||
const to = String(Number(from) + 1000 * 60 * 30); // 30 minutes
|
|
||||||
|
|
||||||
// Seems to throw a permission error, probably because withdrawal permissions aren't set on this key (requires IP whitelist)
|
|
||||||
it.skip('getDepositAddress()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getDepositAddress(coin)).toStrictEqual('');
|
|
||||||
} catch (e) {
|
|
||||||
console.error('exception: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getWithdrawals()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getWithdrawals(coin, from, to)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getWithdrawals: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getDeposits()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getDeposits(coin, from, to)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getDeposits: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getApiKeyInfo()', async () => {
|
|
||||||
// No auth error == test pass
|
|
||||||
try {
|
|
||||||
expect(await api.getApiKeyInfo()).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {
|
|
||||||
user_id: expect.any(String),
|
|
||||||
authorities: expect.any(Array),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getApiKeyInfo: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getBalance()', async () => {
|
|
||||||
try {
|
|
||||||
// expect(await api.getWithdrawals(coin, from, to)).toStrictEqual('');
|
|
||||||
expect(await api.getBalance()).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getBalance: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getTransactionHistory()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getTransactionHistory()).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getTransactionHistory: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Sees exception now about requiring coinId. Question sent to bitget 7th feb.
|
|
||||||
it.skip('getTransferHistory()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getTransferHistory()).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getTransferHistory: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getOrder()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getOrder(symbol, '12345')).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getOrder: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getOpenOrders()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getOpenOrders()).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getOpenOrders: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getOrderHistory()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getOrderHistory(symbol)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getOrderHistory: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getOrderFills()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.getOrderFills(symbol, '12345')).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getOrderFills: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getCurrentPlanOrders()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.getCurrentPlanOrders({ symbol, pageSize: '20' }),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {
|
|
||||||
nextFlag: false,
|
|
||||||
orderList: expect.any(Array),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getCurrentPlanOrders: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getHistoricPlanOrders()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.getHistoricPlanOrders({
|
|
||||||
symbol,
|
|
||||||
pageSize: '20',
|
|
||||||
startTime: '1667889483000',
|
|
||||||
endTime: '1668134732000',
|
|
||||||
}),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {
|
|
||||||
endId: null,
|
|
||||||
nextFlag: false,
|
|
||||||
orderList: expect.any(Array),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error('getHistoricPlanOrders: ', e);
|
|
||||||
expect(e).toBeNull();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,302 +0,0 @@
|
|||||||
import { API_ERROR_CODE, SpotClient } from '../../src';
|
|
||||||
import { sucessEmptyResponseObject } from '../response.util';
|
|
||||||
|
|
||||||
describe('Private Spot REST API POST Endpoints', () => {
|
|
||||||
const API_KEY = process.env.API_KEY_COM;
|
|
||||||
const API_SECRET = process.env.API_SECRET_COM;
|
|
||||||
const API_PASS = process.env.API_PASS_COM;
|
|
||||||
|
|
||||||
it('should have api credentials to test with', () => {
|
|
||||||
expect(API_KEY).toStrictEqual(expect.any(String));
|
|
||||||
expect(API_SECRET).toStrictEqual(expect.any(String));
|
|
||||||
expect(API_PASS).toStrictEqual(expect.any(String));
|
|
||||||
});
|
|
||||||
|
|
||||||
const api = new SpotClient({
|
|
||||||
apiKey: API_KEY,
|
|
||||||
apiSecret: API_SECRET,
|
|
||||||
apiPass: API_PASS,
|
|
||||||
});
|
|
||||||
|
|
||||||
const symbol = 'BTCUSDT_SPBL';
|
|
||||||
const coin = 'USDT';
|
|
||||||
|
|
||||||
describe('transfers', () => {
|
|
||||||
it('transfer()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.transfer({
|
|
||||||
amount: '100',
|
|
||||||
coin,
|
|
||||||
fromType: 'spot',
|
|
||||||
toType: 'mix_usdt',
|
|
||||||
}),
|
|
||||||
).toStrictEqual('');
|
|
||||||
} catch (e) {
|
|
||||||
// console.error('transfer: ', e);
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
// not sure what this error means, probably no kyc. Seems to change?
|
|
||||||
code: expect.stringMatching(/42013|43117|40035/gim),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('transferV2()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.transferV2({
|
|
||||||
amount: '100',
|
|
||||||
coin,
|
|
||||||
fromType: 'spot',
|
|
||||||
toType: 'mix_usdt',
|
|
||||||
}),
|
|
||||||
).toStrictEqual('');
|
|
||||||
} catch (e) {
|
|
||||||
// console.error('transferV2: ', e);
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
// not sure what this error means, probably no kyc. Seems to change?
|
|
||||||
code: expect.stringMatching(/42013|43117|40035/gim),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('subTransfer()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.subTransfer({
|
|
||||||
fromUserId: '123',
|
|
||||||
toUserId: '456',
|
|
||||||
amount: '100',
|
|
||||||
clientOid: '123456',
|
|
||||||
coin,
|
|
||||||
fromType: 'spot',
|
|
||||||
toType: 'mix_usdt',
|
|
||||||
}),
|
|
||||||
).toStrictEqual('');
|
|
||||||
} catch (e) {
|
|
||||||
// console.error('transferV2: ', e);
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
// not sure what this error means, probably no balance. Seems to change?
|
|
||||||
code: expect.stringMatching(/42013|43117|40018/gim),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('withdraw()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.withdraw({
|
|
||||||
amount: '100',
|
|
||||||
coin,
|
|
||||||
chain: 'TRC20',
|
|
||||||
address: '123456',
|
|
||||||
}),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.INCORRECT_PERMISSIONS,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it.skip('withdrawV2()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.withdrawV2({
|
|
||||||
amount: '100',
|
|
||||||
coin,
|
|
||||||
chain: 'TRC20',
|
|
||||||
address: '123456',
|
|
||||||
}),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.log(
|
|
||||||
`"${expect.getState().currentTestName}"`,
|
|
||||||
JSON.stringify(e.body),
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.INCORRECT_PERMISSIONS,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('innerWithdraw()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.innerWithdraw(coin, '12345', '1')).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.INCORRECT_PERMISSIONS,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it.skip('innerWithdrawV2()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.innerWithdrawV2(coin, '12345', '1')).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.log(
|
|
||||||
`"${expect.getState().currentTestName}"`,
|
|
||||||
JSON.stringify(e.body),
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.INCORRECT_PERMISSIONS,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe('orders', () => {
|
|
||||||
it('submitOrder()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.submitOrder({
|
|
||||||
symbol,
|
|
||||||
side: 'buy',
|
|
||||||
orderType: 'market',
|
|
||||||
quantity: '1',
|
|
||||||
force: 'normal',
|
|
||||||
}),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_KYC_REQUIRED,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('batchSubmitOrder()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.batchSubmitOrder(symbol, [
|
|
||||||
{
|
|
||||||
side: 'buy',
|
|
||||||
orderType: 'market',
|
|
||||||
quantity: '1',
|
|
||||||
force: 'normal',
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {
|
|
||||||
resultList: expect.any(Array),
|
|
||||||
failure: [{ errorCode: API_ERROR_CODE }],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
// console.log(`fn() exception: `, e.body);
|
|
||||||
|
|
||||||
expect(e?.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_KYC_REQUIRED,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('cancelOrder()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.cancelOrder(symbol, '123456')).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: '123456', //expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.log('cancelorder err', e);
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ORDER_NOT_FOUND,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('batchCancelOrder()', async () => {
|
|
||||||
try {
|
|
||||||
expect(await api.batchCancelOrder(symbol, ['123456'])).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ORDER_NOT_FOUND,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('plan orders', () => {
|
|
||||||
let planOrderId: string;
|
|
||||||
|
|
||||||
it('submitPlanOrder()', async () => {
|
|
||||||
try {
|
|
||||||
const result = await api.submitPlanOrder({
|
|
||||||
symbol,
|
|
||||||
side: 'buy',
|
|
||||||
orderType: 'market',
|
|
||||||
size: 100,
|
|
||||||
triggerPrice: 100,
|
|
||||||
triggerType: 'fill_price',
|
|
||||||
});
|
|
||||||
|
|
||||||
planOrderId = result.data.orderId;
|
|
||||||
expect(result).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_KYC_REQUIRED,
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
// console.error('submitPlanOrder(): ', e);
|
|
||||||
expect(e?.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.ACCOUNT_KYC_REQUIRED,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('modifyPlanOrder()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.modifyPlanOrder({
|
|
||||||
orderType: 'market',
|
|
||||||
triggerPrice: 100,
|
|
||||||
orderId: '123456',
|
|
||||||
}),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.PLAN_ORDER_NOT_FOUND,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('cancelPlanOrder()', async () => {
|
|
||||||
try {
|
|
||||||
expect(
|
|
||||||
await api.cancelPlanOrder({
|
|
||||||
orderId: planOrderId || '123456',
|
|
||||||
}),
|
|
||||||
).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(String),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
// console.error('cancelPlanOrder(): ', e);
|
|
||||||
// expect(e).toBeNull();
|
|
||||||
expect(e.body).toMatchObject({
|
|
||||||
code: API_ERROR_CODE.PLAN_ORDER_NOT_FOUND,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
import { SpotClient } from '../../src';
|
|
||||||
import {
|
|
||||||
successResponseString,
|
|
||||||
sucessEmptyResponseObject,
|
|
||||||
} from '../response.util';
|
|
||||||
|
|
||||||
describe('Public Spot REST API Endpoints', () => {
|
|
||||||
const api = new SpotClient();
|
|
||||||
|
|
||||||
const symbol = 'BTCUSDT_SPBL';
|
|
||||||
|
|
||||||
// it('should throw for unauthenticated private calls', async () => {
|
|
||||||
// expect(() => api.getOpenOrders()).rejects.toMatchObject(
|
|
||||||
// notAuthenticatedError()
|
|
||||||
// );
|
|
||||||
// expect(() => api.getBalances()).rejects.toMatchObject(
|
|
||||||
// notAuthenticatedError()
|
|
||||||
// );
|
|
||||||
// });
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Public
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
it('getServerTime()', async () => {
|
|
||||||
// expect(await api.getServerTime()).toStrictEqual('');
|
|
||||||
expect(await api.getServerTime()).toMatchObject(successResponseString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('fetchServertime() returns number', async () => {
|
|
||||||
expect(await api.fetchServerTime()).toStrictEqual(expect.any(Number));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getCoins()', async () => {
|
|
||||||
expect(await api.getCoins()).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getSymbols()', async () => {
|
|
||||||
expect(await api.getSymbols()).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getSymbol()', async () => {
|
|
||||||
expect(await api.getSymbol(symbol)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {
|
|
||||||
baseCoin: expect.any(String),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Market
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
it('getTicker()', async () => {
|
|
||||||
expect(await api.getTicker(symbol)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {
|
|
||||||
askSz: expect.any(String),
|
|
||||||
baseVol: expect.any(String),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getAllTickers()', async () => {
|
|
||||||
expect(await api.getAllTickers()).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getMarketTrades()', async () => {
|
|
||||||
expect(await api.getMarketTrades(symbol)).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getCandles()', async () => {
|
|
||||||
expect(await api.getCandles(symbol, '1min')).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: expect.any(Array),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('getDepth()', async () => {
|
|
||||||
expect(await api.getDepth(symbol, 'step0')).toMatchObject({
|
|
||||||
...sucessEmptyResponseObject(),
|
|
||||||
data: {
|
|
||||||
bids: expect.any(Array),
|
|
||||||
asks: expect.any(Array),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user