Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion src/node-binance-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,9 @@ export default class Binance {
* @param {string} quantity - The quantity to buy or sell
* @param {string} price - The price per unit to transact each unit at
* @param {object} params - additional order settings
* @param {number} [params.quoteOrderQty] - The quote order quantity, used for MARKET orders
* @param {number} [params.stopPrice] - The stop price, used for STOP_LOSS, STOP_LOSS_LIMIT, TAKE_PROFIT, TAKE_PROFIT_LIMIT orders
* @param {number} [params.trailingDelta] - Delta price
* @return {undefined}
*/
async order(type: OrderType, side: OrderSide, symbol: string, quantity: number, price?: number, params: Dict = {}): Promise<Order> {
Expand Down Expand Up @@ -778,6 +781,15 @@ export default class Binance {
request.newClientOrderId = this.SPOT_PREFIX + this.uuid22();
}

const allowedTypesForStopAndTrailing = ['STOP_LOSS', 'STOP_LOSS_LIMIT', 'TAKE_PROFIT', 'TAKE_PROFIT_LIMIT'];
if (params.trailingDelta) {
request.trailingDelta = params.trailingDelta;

if (!allowedTypesForStopAndTrailing.includes(request.type)) {
throw Error('trailingDelta: Must set "type" to one of the following: STOP_LOSS, STOP_LOSS_LIMIT, TAKE_PROFIT, TAKE_PROFIT_LIMIT');
}
}

/*
* STOP_LOSS
* STOP_LOSS_LIMIT
Expand All @@ -788,7 +800,9 @@ export default class Binance {
// if (typeof params.icebergQty !== 'undefined') request.icebergQty = params.icebergQty;
if (params.stopPrice) {
request.stopPrice = params.stopPrice;
if (request.type === 'LIMIT') throw Error('stopPrice: Must set "type" to one of the following: STOP_LOSS, STOP_LOSS_LIMIT, TAKE_PROFIT, TAKE_PROFIT_LIMIT');
if (!allowedTypesForStopAndTrailing.includes(request.type)) {
throw Error('stopPrice: Must set "type" to one of the following: STOP_LOSS, STOP_LOSS_LIMIT, TAKE_PROFIT, TAKE_PROFIT_LIMIT');
}
}
const response = await this.privateSpotRequest(endpoint, this.extend(request, params), 'POST');
// to do error handling
Expand Down
46 changes: 35 additions & 11 deletions tests/binance-class-live.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,10 @@ describe('Limit buy Order', function () {
assert(res['orderId'] !== undefined)
spotOrderId = res['orderId'];
} catch (e) {
assert(e.toString().includes('{"code":-2010,"msg":"Account has insufficient balance for requested action."}'));
const exceptionA = '{"code":-2010,"msg":"Account has insufficient balance for requested action."}';
const exceptionB = '{"code":-2019,"msg":"Margin is insufficient."}'
const eStr = e.toString();
assert(eStr.includes(exceptionA) || eStr.includes(exceptionB));
}
}

Expand All @@ -287,7 +290,10 @@ describe('MarketSell', function () {
const res = await binance.marketSell('LTCUSDT', quantity)
assert(res['orderId'] !== undefined)
} catch (e) {
assert(e.toString().includes('{"code":-2010,"msg":"Account has insufficient balance for requested action."}'));
const exceptionA = '{"code":-2010,"msg":"Account has insufficient balance for requested action."}';
const exceptionB = '{"code":-2019,"msg":"Margin is insufficient."}'
const eStr = e.toString();
assert(eStr.includes(exceptionA) || eStr.includes(exceptionB));
}

}).timeout(TIMEOUT);
Expand All @@ -301,28 +307,46 @@ describe('Futures MarketBuy', function () {
assert(res['orderId'] !== undefined)
futuresOrderId = res['orderId'];
} catch (e) {
assert(e.toString().includes('{"code":-2010,"msg":"Account has insufficient balance for requested action."}'));
const exceptionA = '{"code":-2010,"msg":"Account has insufficient balance for requested action."}';
const exceptionB = '{"code":-2019,"msg":"Margin is insufficient."}'
const eStr = e.toString();
assert(eStr.includes(exceptionA) || eStr.includes(exceptionB));
}

}).timeout(TIMEOUT);
});

describe('Futures Limit buy Order', function () {
it('Attempt to buy ETH', async function () {
if (ethusdtPrice !== 0) {
let quantity = 0.1;
const res = await futuresBinance.futuresOrder('LIMIT', 'BUY', 'ETHUSDT', quantity, Math.round(ethusdtPrice * 0.8))
assert(res['orderId'] !== undefined)
futuresOrderId = res['orderId'];
try {
if (ethusdtPrice !== 0) {
let quantity = 0.1;
const res = await futuresBinance.futuresOrder('LIMIT', 'BUY', 'ETHUSDT', quantity, Math.round(ethusdtPrice * 0.8))
assert(res['orderId'] !== undefined)
futuresOrderId = res['orderId'];
}
} catch (e) {
const exceptionA = '{"code":-2010,"msg":"Account has insufficient balance for requested action."}';
const exceptionB = '{"code":-2019,"msg":"Margin is insufficient."}'
const eStr = e.toString();
assert(eStr.includes(exceptionA) || eStr.includes(exceptionB));
}

}).timeout(TIMEOUT);
});

describe('Futures MarketSell', function () {
it('futures Attempt to buy ETH at market price', async function () {
let quantity = 0.1;
const res = await futuresBinance.futuresMarketSell('ETHUSDT', quantity)
assert(res['orderId'] !== undefined)
try {
let quantity = 0.1;
const res = await futuresBinance.futuresMarketSell('ETHUSDT', quantity)
assert(res['orderId'] !== undefined)
} catch (e) {
const exceptionA = '{"code":-2010,"msg":"Account has insufficient balance for requested action."}';
const exceptionB = '{"code":-2019,"msg":"Margin is insufficient."}'
const eStr = e.toString();
assert(eStr.includes(exceptionA) || eStr.includes(exceptionB));
}

}).timeout(TIMEOUT);
});
Expand Down