binance / binance-connector-node

A simple connector to Binance Public API
MIT License
567 stars 164 forks source link

Small Price floating point (scientific) notation throws 400 error from newOrder API #136

Closed BrandonDR closed 1 year ago

BrandonDR commented 1 year ago

Issue subject

When trying to sell RVN to BTC, I am getting a 400 error from the API.

Because the price is validated on the endpoint with this rule: "Illegal characters found in parameter 'price'; legal range is '^([0-9]{1,20})(\.[0-9]{1,20})?$'." The floating point / scientific notion of "8e-7" is not valid.

Expected behaviour

The price must not be shortened and remain in long form, price=0.0000008.

{
  method: 'POST',
  path: '/api/v3/order?price=0.0000008&quantity=200&timeInForce=GTC&symbol=RVNBTC&side=SELL&type=LIMIT&....(continues)'
}

Actual behaviour

This POST request is made instead, price=8e-7.

{
  method: 'POST',
  path: '/api/v3/order?price=8e-7&quantity=200&timeInForce=GTC&symbol=RVNBTC&side=SELL&type=LIMIT&....(continues)'
}

Steps to reproduce

Make a newOrder with a very small price.

const apiKey = process.env.BINANCE_API_KEY;
const apiSecret = process.env.BINANCE_API_SECRET;
const client = new Spot(apiKey, apiSecret)

// New Sell order with very small price decimal value,
await client.newOrder("RVNBTC", 'SELL', 'LIMIT', {
    price: 0.0000008,
    quantity: 200,
    timeInForce: 'GTC'
}).catch(err => {
    console.error(err);
    throw err;
});

Environment

(I wonder if v3 rc would not have this issue?)

BrandonDR commented 1 year ago

I found a work around, by converting it to a string myself

function convertDecimalToString(decimal) {
    // Convert the decimal value to a string with 20 decimal places
    let str = decimal.toFixed(20);

    // Remove trailing zeros
    str = str.replace(/0+$/, '');

    // Remove the decimal point if there are no decimal places remaining
    if (str.charAt(str.length - 1) === '.') {
        str = str.slice(0, -1);
    }

    return str;
}
await client.newOrder("RVNBTC", 'SELL', 'LIMIT', {
    price: convertDecimalToString(0.0000008),
    quantity: 200,
    timeInForce: 'GTC'
}).catch(err => {
    console.error(err);
    throw err;
});
2pd commented 1 year ago

Thanks for the feedback, for now it's recommended to provide the price as string:

await client.newOrder("RVNBTC", 'SELL', 'LIMIT', {
    price: '0.0000008',
    quantity: 200,
    timeInForce: 'GTC'
}).catch(err => {
    console.error(err);
    throw err;
});