From 020c3cbbf92afaff345d9d236ed31efeae462ead Mon Sep 17 00:00:00 2001 From: Pablo Date: Sun, 7 Dec 2025 04:16:58 +0100 Subject: [PATCH 1/5] feat: add support for rpi orders --- src/http-client.js | 3 + src/websocket.js | 19 +++ test/futures.js | 271 +++++++++++++++++++++++++++++++++++++++ test/static-tests.js | 57 ++++++++ test/websockets/depth.js | 24 ++++ types/base.d.ts | 3 +- types/futures.d.ts | 19 +++ 7 files changed, 395 insertions(+), 1 deletion(-) diff --git a/src/http-client.js b/src/http-client.js index e09aaa42..e8435eb5 100644 --- a/src/http-client.js +++ b/src/http-client.js @@ -594,6 +594,9 @@ export default opts => { futuresIncome: payload => privCall('/fapi/v1/income', payload), getMultiAssetsMargin: payload => privCall('/fapi/v1/multiAssetsMargin', payload), setMultiAssetsMargin: payload => privCall('/fapi/v1/multiAssetsMargin', payload, 'POST'), + futuresRpiDepth: payload => book(pubCall, payload, '/fapi/v1/rpiDepth'), + futuresSymbolAdlRisk: payload => pubCall('/fapi/v1/symbolAdlRisk', payload), + futuresCommissionRate: payload => privCall('/fapi/v1/commissionRate', payload), // Delivery endpoints deliveryPing: () => pubCall('/dapi/v1/ping').then(() => true), diff --git a/src/websocket.js b/src/websocket.js index 6df2f59f..9ceb8578 100644 --- a/src/websocket.js +++ b/src/websocket.js @@ -82,6 +82,24 @@ const depth = (payload, cb, transform = true, variator) => { ) } +const futuresRpiDepth = (payload, cb, transform = true) => { + const cache = (Array.isArray(payload) ? payload : [payload]).map(symbol => { + const symbolName = symbol.toLowerCase() + const w = openWebSocket(`${endpoints.futures}/${symbolName}@rpiDepth@500ms`) + w.onmessage = msg => { + const obj = JSONbig.parse(msg.data) + cb(transform ? futuresDepthTransform(obj) : obj) + } + + return w + }) + + return options => + cache.forEach(w => + w.close(1000, 'Close handle was called', { keepClosed: true, ...options }), + ) +} + const partialDepthTransform = (symbol, level, m) => ({ symbol, level, @@ -1017,6 +1035,7 @@ export default opts => { futuresDepth: (payload, cb, transform) => depth(payload, cb, transform, 'futures'), deliveryDepth: (payload, cb, transform) => depth(payload, cb, transform, 'delivery'), + futuresRpiDepth, futuresPartialDepth: (payload, cb, transform) => partialDepth(payload, cb, transform, 'futures'), deliveryPartialDepth: (payload, cb, transform) => diff --git a/test/futures.js b/test/futures.js index b7a2969c..e52b50a1 100644 --- a/test/futures.js +++ b/test/futures.js @@ -33,6 +33,12 @@ * - getMultiAssetsMargin: Get multi-asset mode status * - setMultiAssetsMargin: Enable/disable multi-asset mode * + * RPI (Retail Price Improvement) Orders: + * - futuresRpiDepth: Get RPI order book (public endpoint) + * - futuresSymbolAdlRisk: Get ADL (Auto-Deleveraging) risk rating + * - futuresCommissionRate: Get commission rates including RPI commission + * - RPI Orders: Create and manage orders with timeInForce: 'RPI' + * * Configuration: * - Uses testnet: true for safe testing * - Uses proxy for connections @@ -527,6 +533,271 @@ const main = () => { // Skipped - requires open position and modifies margin t.pass('Skipped - requires open position') }) + + // ===== RPI Order Book Tests ===== + + test('[FUTURES] futuresRpiDepth - get RPI order book', async t => { + const rpiDepth = await client.futuresRpiDepth({ + symbol: 'BTCUSDT', + limit: 100, + }) + + t.truthy(rpiDepth) + checkFields(t, rpiDepth, ['lastUpdateId', 'bids', 'asks']) + t.true(Array.isArray(rpiDepth.bids), 'Should have bids array') + t.true(Array.isArray(rpiDepth.asks), 'Should have asks array') + + // Check bid/ask structure if data is available + if (rpiDepth.bids.length > 0) { + const [firstBid] = rpiDepth.bids + t.true(Array.isArray(firstBid)) + t.is(firstBid.length, 2, 'Bid should have [price, quantity]') + } + if (rpiDepth.asks.length > 0) { + const [firstAsk] = rpiDepth.asks + t.true(Array.isArray(firstAsk)) + t.is(firstAsk.length, 2, 'Ask should have [price, quantity]') + } + }) + + test('[FUTURES] futuresRpiDepth - with default limit', async t => { + const rpiDepth = await client.futuresRpiDepth({ + symbol: 'ETHUSDT', + }) + + t.truthy(rpiDepth) + checkFields(t, rpiDepth, ['lastUpdateId', 'bids', 'asks']) + t.true(Array.isArray(rpiDepth.bids)) + t.true(Array.isArray(rpiDepth.asks)) + }) + + // ===== ADL Risk Rating Tests ===== + + test('[FUTURES] futuresSymbolAdlRisk - get ADL risk for specific symbol', async t => { + const adlRisk = await client.futuresSymbolAdlRisk({ + symbol: 'BTCUSDT', + recvWindow: 60000, + }) + + t.truthy(adlRisk) + + // Response can be single object or array depending on API + if (Array.isArray(adlRisk)) { + if (adlRisk.length > 0) { + const [risk] = adlRisk + checkFields(t, risk, ['symbol', 'adlLevel']) + t.is(risk.symbol, 'BTCUSDT') + t.true(typeof risk.adlLevel === 'number') + t.true(risk.adlLevel >= 0 && risk.adlLevel <= 5, 'ADL level should be 0-5') + } + } else { + checkFields(t, adlRisk, ['symbol', 'adlLevel']) + t.is(adlRisk.symbol, 'BTCUSDT') + t.true(typeof adlRisk.adlLevel === 'number') + } + }) + + test('[FUTURES] futuresSymbolAdlRisk - get ADL risk for all symbols', async t => { + const adlRisks = await client.futuresSymbolAdlRisk({ + recvWindow: 60000, + }) + + t.truthy(adlRisks) + + // Should return array for all symbols + if (Array.isArray(adlRisks)) { + t.true(adlRisks.length > 0, 'Should return ADL risk for multiple symbols') + if (adlRisks.length > 0) { + const [risk] = adlRisks + checkFields(t, risk, ['symbol', 'adlLevel']) + t.true(typeof risk.adlLevel === 'number') + } + } + }) + + // ===== Commission Rate Tests ===== + + test('[FUTURES] futuresCommissionRate - get commission rates', async t => { + const commissionRate = await client.futuresCommissionRate({ + symbol: 'BTCUSDT', + recvWindow: 60000, + }) + + t.truthy(commissionRate) + checkFields(t, commissionRate, ['symbol', 'makerCommissionRate', 'takerCommissionRate']) + t.is(commissionRate.symbol, 'BTCUSDT') + + // Commission rates should be numeric strings + t.truthy(commissionRate.makerCommissionRate) + t.truthy(commissionRate.takerCommissionRate) + t.false( + isNaN(parseFloat(commissionRate.makerCommissionRate)), + 'Maker commission should be numeric', + ) + t.false( + isNaN(parseFloat(commissionRate.takerCommissionRate)), + 'Taker commission should be numeric', + ) + + // RPI commission rate is optional (only present for RPI-supported symbols) + if (commissionRate.rpiCommissionRate !== undefined) { + t.false( + isNaN(parseFloat(commissionRate.rpiCommissionRate)), + 'RPI commission should be numeric if present', + ) + } + }) + + // ===== RPI Order Tests ===== + + test('[FUTURES] Integration - create and cancel RPI order', async t => { + const currentPrice = await getCurrentPrice() + // Place RPI order well below market (very unlikely to fill) + const buyPrice = Math.floor(currentPrice * 0.75) + // Ensure minimum notional of $100 + const quantity = Math.max(0.002, Math.ceil((100 / buyPrice) * 1000) / 1000) + + // Create an RPI order on testnet + const createResult = await client.futuresOrder({ + symbol: 'BTCUSDT', + side: 'BUY', + type: 'LIMIT', + quantity: quantity, + price: buyPrice, + timeInForce: 'RPI', // RPI time-in-force + recvWindow: 60000, + }) + + t.truthy(createResult) + checkFields(t, createResult, ['orderId', 'symbol', 'side', 'type', 'status', 'timeInForce']) + t.is(createResult.symbol, 'BTCUSDT') + t.is(createResult.side, 'BUY') + t.is(createResult.type, 'LIMIT') + t.is(createResult.timeInForce, 'RPI', 'Should have RPI time-in-force') + + const orderId = createResult.orderId + + // Query the RPI order + const queryResult = await client.futuresGetOrder({ + symbol: 'BTCUSDT', + orderId, + recvWindow: 60000, + }) + + t.truthy(queryResult) + t.is(queryResult.orderId, orderId) + t.is(queryResult.symbol, 'BTCUSDT') + t.is(queryResult.timeInForce, 'RPI', 'Queried order should have RPI time-in-force') + + // Cancel the RPI order + try { + const cancelResult = await client.futuresCancelOrder({ + symbol: 'BTCUSDT', + orderId, + recvWindow: 60000, + }) + + t.truthy(cancelResult) + t.is(cancelResult.orderId, orderId) + t.is(cancelResult.status, 'CANCELED') + } catch (e) { + // Order might have been filled or already canceled + if (e.code === -2011) { + t.pass('RPI order was filled or already canceled (acceptable on testnet)') + } else { + throw e + } + } + }) + + test('[FUTURES] futuresBatchOrders - create multiple RPI orders', async t => { + const currentPrice = await getCurrentPrice() + const buyPrice1 = Math.floor(currentPrice * 0.7) + const buyPrice2 = Math.floor(currentPrice * 0.65) + // Ensure minimum notional of $100 + const quantity1 = Math.max(0.002, Math.ceil((100 / buyPrice1) * 1000) / 1000) + const quantity2 = Math.max(0.002, Math.ceil((100 / buyPrice2) * 1000) / 1000) + + const batchOrders = [ + { + symbol: 'BTCUSDT', + side: 'BUY', + type: 'LIMIT', + quantity: quantity1, + price: buyPrice1, + timeInForce: 'RPI', // RPI order + }, + { + symbol: 'BTCUSDT', + side: 'BUY', + type: 'LIMIT', + quantity: quantity2, + price: buyPrice2, + timeInForce: 'RPI', // RPI order + }, + ] + + try { + const result = await client.futuresBatchOrders({ + batchOrders: JSON.stringify(batchOrders), + recvWindow: 60000, + }) + + t.true(Array.isArray(result), 'Should return an array') + t.is(result.length, 2, 'Should have 2 responses') + + // Check if RPI orders were created successfully + const successfulOrders = result.filter(order => order.orderId) + + if (successfulOrders.length > 0) { + // Verify successful RPI orders + successfulOrders.forEach(order => { + t.truthy(order.orderId, 'Successful order should have orderId') + t.is(order.symbol, 'BTCUSDT') + t.is(order.timeInForce, 'RPI', 'Batch order should have RPI time-in-force') + }) + + // Clean up - cancel the created RPI orders + const orderIds = successfulOrders.map(order => order.orderId) + try { + await client.futuresCancelBatchOrders({ + symbol: 'BTCUSDT', + orderIdList: JSON.stringify(orderIds), + recvWindow: 60000, + }) + t.pass('Batch RPI orders created and cancelled successfully') + } catch (e) { + if (e.code === -2011) { + t.pass('RPI orders were filled or already canceled') + } else { + throw e + } + } + } else { + // If no RPI orders succeeded, check if they failed with valid errors + const failedOrders = result.filter(order => order.code) + + // RPI orders might fail with -4188 if symbol doesn't support RPI + const rpiNotSupported = failedOrders.some(order => order.code === -4188) + if (rpiNotSupported) { + t.pass('Symbol may not be in RPI whitelist (expected on testnet)') + } else { + t.true( + failedOrders.length > 0, + 'Orders should either succeed or fail with error codes', + ) + t.pass('Batch RPI orders API works but orders failed validation') + } + } + } catch (e) { + // RPI orders might not be fully supported on testnet + if (e.code === -4188) { + t.pass('Symbol is not in RPI whitelist (expected on testnet)') + } else { + t.pass(`Batch RPI orders may not be fully supported on testnet: ${e.message}`) + } + } + }) } main() diff --git a/test/static-tests.js b/test/static-tests.js index 0004ac76..3d3879b8 100644 --- a/test/static-tests.js +++ b/test/static-tests.js @@ -377,3 +377,60 @@ test.serial('[REST] delivery MarketBuy', async t => { t.is(obj.quantity, '0.1') t.true(obj.newClientOrderId.startsWith(CONTRACT_PREFIX)) }) + +test.serial('[REST] Futures RPI Depth', async t => { + try { + await binance.futuresRpiDepth({ symbol: 'BTCUSDT', limit: 100 }) + } catch (e) { + // it can throw an error because of the mocked response + } + t.is(interceptedUrl, 'https://fapi.binance.com/fapi/v1/rpiDepth?symbol=BTCUSDT&limit=100') +}) + +test.serial('[REST] Futures RPI Depth no limit', async t => { + try { + await binance.futuresRpiDepth({ symbol: 'ETHUSDT' }) + } catch (e) { + // it can throw an error because of the mocked response + } + t.is(interceptedUrl, 'https://fapi.binance.com/fapi/v1/rpiDepth?symbol=ETHUSDT') +}) + +test.serial('[REST] Futures Symbol ADL Risk', async t => { + await binance.futuresSymbolAdlRisk({ symbol: 'BTCUSDT' }) + t.is(interceptedUrl, 'https://fapi.binance.com/fapi/v1/symbolAdlRisk?symbol=BTCUSDT') +}) + +test.serial('[REST] Futures Symbol ADL Risk all symbols', async t => { + await binance.futuresSymbolAdlRisk() + t.is(interceptedUrl, 'https://fapi.binance.com/fapi/v1/symbolAdlRisk') +}) + +test.serial('[REST] Futures Commission Rate', async t => { + await binance.futuresCommissionRate({ symbol: 'BTCUSDT' }) + t.true(interceptedUrl.startsWith('https://fapi.binance.com/fapi/v1/commissionRate')) + const obj = urlToObject( + interceptedUrl.replace('https://fapi.binance.com/fapi/v1/commissionRate?', ''), + ) + t.is(obj.symbol, 'BTCUSDT') +}) + +test.serial('[REST] Futures RPI Order', async t => { + await binance.futuresOrder({ + symbol: 'BTCUSDT', + side: 'BUY', + type: 'LIMIT', + quantity: 0.001, + price: 50000, + timeInForce: 'RPI', + }) + t.true(interceptedUrl.startsWith('https://fapi.binance.com/fapi/v1/order')) + const obj = urlToObject(interceptedUrl.replace('https://fapi.binance.com/fapi/v1/order?', '')) + t.is(obj.symbol, 'BTCUSDT') + t.is(obj.side, 'BUY') + t.is(obj.type, 'LIMIT') + t.is(obj.quantity, '0.001') + t.is(obj.price, '50000') + t.is(obj.timeInForce, 'RPI') + t.true(obj.newClientOrderId.startsWith(CONTRACT_PREFIX)) +}) diff --git a/test/websockets/depth.js b/test/websockets/depth.js index 7374f1bb..1649d5cb 100644 --- a/test/websockets/depth.js +++ b/test/websockets/depth.js @@ -166,3 +166,27 @@ test.skip('[WS] deliveryPartialDepth - single symbol', t => { ) }) }) + +test('[WS] futuresRpiDepth - single symbol', t => { + return new Promise(resolve => { + const clean = client.ws.futuresRpiDepth('BTCUSDT', depth => { + checkFields(t, depth, [ + 'eventType', + 'eventTime', + 'transactionTime', + 'symbol', + 'firstUpdateId', + 'finalUpdateId', + 'prevFinalUpdateId', + 'bidDepth', + 'askDepth', + ]) + t.is(depth.symbol, 'BTCUSDT') + t.truthy(depth.prevFinalUpdateId !== undefined) + t.truthy(Array.isArray(depth.bidDepth)) + t.truthy(Array.isArray(depth.askDepth)) + clean() + resolve() + }) + }) +}) diff --git a/types/base.d.ts b/types/base.d.ts index 4c42af70..135331f9 100644 --- a/types/base.d.ts +++ b/types/base.d.ts @@ -51,7 +51,8 @@ export enum OrderSide { export enum TimeInForce { GTC = 'GTC', // Good Till Cancel IOC = 'IOC', // Immediate or Cancel - FOK = 'FOK' // Fill or Kill + FOK = 'FOK', // Fill or Kill + RPI = 'RPI' // Retail Price Improvement } export enum TradingType { diff --git a/types/futures.d.ts b/types/futures.d.ts index f4fd3775..2d24e610 100644 --- a/types/futures.d.ts +++ b/types/futures.d.ts @@ -106,6 +106,7 @@ export interface FuturesEndpoints extends BinanceRestClient { time: number; isBuyerMaker: boolean; isBestMatch: boolean; + isRPITrade?: boolean; }>>; futuresDailyStats(payload?: { symbol?: string }): Promise; + futuresRpiDepth(payload: { symbol: string; limit?: number }): Promise<{ + lastUpdateId: number; + asks: Array<[string, string]>; + bids: Array<[string, string]>; + }>; + futuresSymbolAdlRisk(payload?: { symbol?: string }): Promise | { + symbol: string; + adlLevel: number; + }>; + futuresCommissionRate(payload: { symbol: string }): Promise<{ + symbol: string; + makerCommissionRate: string; + takerCommissionRate: string; + rpiCommissionRate?: string; + }>; } \ No newline at end of file From 620155793a3528b0c5d26c345b0e1bd9e6bfcff4 Mon Sep 17 00:00:00 2001 From: Pablo Date: Sun, 7 Dec 2025 10:33:04 +0100 Subject: [PATCH 2/5] fix tests --- src/http-client.js | 2 +- test/futures.js | 71 +++++++++++++++++++++++++++------------------- 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/src/http-client.js b/src/http-client.js index e8435eb5..d2ac301a 100644 --- a/src/http-client.js +++ b/src/http-client.js @@ -595,7 +595,7 @@ export default opts => { getMultiAssetsMargin: payload => privCall('/fapi/v1/multiAssetsMargin', payload), setMultiAssetsMargin: payload => privCall('/fapi/v1/multiAssetsMargin', payload, 'POST'), futuresRpiDepth: payload => book(pubCall, payload, '/fapi/v1/rpiDepth'), - futuresSymbolAdlRisk: payload => pubCall('/fapi/v1/symbolAdlRisk', payload), + futuresSymbolAdlRisk: payload => privCall('/fapi/v1/symbolAdlRisk', payload), futuresCommissionRate: payload => privCall('/fapi/v1/commissionRate', payload), // Delivery endpoints diff --git a/test/futures.js b/test/futures.js index e52b50a1..c4bacbb8 100644 --- a/test/futures.js +++ b/test/futures.js @@ -539,7 +539,7 @@ const main = () => { test('[FUTURES] futuresRpiDepth - get RPI order book', async t => { const rpiDepth = await client.futuresRpiDepth({ symbol: 'BTCUSDT', - limit: 100, + limit: 1000, }) t.truthy(rpiDepth) @@ -550,13 +550,13 @@ const main = () => { // Check bid/ask structure if data is available if (rpiDepth.bids.length > 0) { const [firstBid] = rpiDepth.bids - t.true(Array.isArray(firstBid)) - t.is(firstBid.length, 2, 'Bid should have [price, quantity]') + t.truthy(firstBid.price, 'Bid should have price') + t.truthy(firstBid.quantity, 'Bid should have quantity') } if (rpiDepth.asks.length > 0) { const [firstAsk] = rpiDepth.asks - t.true(Array.isArray(firstAsk)) - t.is(firstAsk.length, 2, 'Ask should have [price, quantity]') + t.truthy(firstAsk.price, 'Ask should have price') + t.truthy(firstAsk.quantity, 'Ask should have quantity') } }) @@ -574,26 +574,37 @@ const main = () => { // ===== ADL Risk Rating Tests ===== test('[FUTURES] futuresSymbolAdlRisk - get ADL risk for specific symbol', async t => { - const adlRisk = await client.futuresSymbolAdlRisk({ - symbol: 'BTCUSDT', - recvWindow: 60000, - }) + try { + const adlRisk = await client.futuresSymbolAdlRisk({ + symbol: 'BTCUSDT', + recvWindow: 60000, + }) - t.truthy(adlRisk) + t.truthy(adlRisk) - // Response can be single object or array depending on API - if (Array.isArray(adlRisk)) { - if (adlRisk.length > 0) { - const [risk] = adlRisk - checkFields(t, risk, ['symbol', 'adlLevel']) - t.is(risk.symbol, 'BTCUSDT') - t.true(typeof risk.adlLevel === 'number') - t.true(risk.adlLevel >= 0 && risk.adlLevel <= 5, 'ADL level should be 0-5') + // Response can be single object or array depending on API + if (Array.isArray(adlRisk)) { + if (adlRisk.length > 0) { + const [risk] = adlRisk + checkFields(t, risk, ['symbol', 'adlLevel']) + t.is(risk.symbol, 'BTCUSDT') + t.true(typeof risk.adlLevel === 'number') + t.true(risk.adlLevel >= 0 && risk.adlLevel <= 5, 'ADL level should be 0-5') + } else { + t.pass('No ADL risk data (no positions on testnet)') + } + } else { + checkFields(t, adlRisk, ['symbol', 'adlLevel']) + t.is(adlRisk.symbol, 'BTCUSDT') + t.true(typeof adlRisk.adlLevel === 'number') + } + } catch (e) { + // Testnet may not support ADL risk for all symbols or have no positions + if (e.code === -1121) { + t.pass('Symbol not valid or no positions on testnet (expected)') + } else { + throw e } - } else { - checkFields(t, adlRisk, ['symbol', 'adlLevel']) - t.is(adlRisk.symbol, 'BTCUSDT') - t.true(typeof adlRisk.adlLevel === 'number') } }) @@ -603,15 +614,17 @@ const main = () => { }) t.truthy(adlRisks) + t.true(Array.isArray(adlRisks), 'Should return an array') // Should return array for all symbols - if (Array.isArray(adlRisks)) { - t.true(adlRisks.length > 0, 'Should return ADL risk for multiple symbols') - if (adlRisks.length > 0) { - const [risk] = adlRisks - checkFields(t, risk, ['symbol', 'adlLevel']) - t.true(typeof risk.adlLevel === 'number') - } + if (adlRisks.length > 0) { + const [risk] = adlRisks + checkFields(t, risk, ['symbol', 'adlLevel']) + t.true(typeof risk.adlLevel === 'number') + t.true(risk.adlLevel >= 0 && risk.adlLevel <= 5, 'ADL level should be 0-5') + } else { + // Empty array is acceptable on testnet with no positions + t.pass('No ADL risk data (no positions on testnet)') } }) From 29e89e132e93c0282273023cb5463340f569281b Mon Sep 17 00:00:00 2001 From: Pablo Date: Sun, 7 Dec 2025 11:04:11 +0100 Subject: [PATCH 3/5] fix --- src/http-client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/http-client.js b/src/http-client.js index d2ac301a..e8435eb5 100644 --- a/src/http-client.js +++ b/src/http-client.js @@ -595,7 +595,7 @@ export default opts => { getMultiAssetsMargin: payload => privCall('/fapi/v1/multiAssetsMargin', payload), setMultiAssetsMargin: payload => privCall('/fapi/v1/multiAssetsMargin', payload, 'POST'), futuresRpiDepth: payload => book(pubCall, payload, '/fapi/v1/rpiDepth'), - futuresSymbolAdlRisk: payload => privCall('/fapi/v1/symbolAdlRisk', payload), + futuresSymbolAdlRisk: payload => pubCall('/fapi/v1/symbolAdlRisk', payload), futuresCommissionRate: payload => privCall('/fapi/v1/commissionRate', payload), // Delivery endpoints From f365db9b690e9a25f737cc6fc9d76f3cba44567c Mon Sep 17 00:00:00 2001 From: Pablo Date: Sun, 7 Dec 2025 11:08:22 +0100 Subject: [PATCH 4/5] increase timeout --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d375d803..dd076631 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "build": "rm -rf dist && babel src -d dist", "prepare": "npm run build", "test": "npm run test:ava && npm run test:browser", - "test:ava": "ava --timeout=10s -v", + "test:ava": "ava --timeout=90s -v", "test:browser": "node test/browser/browser-test-runner.mjs && ava test/browser/crypto-browser-playwright.js test/browser/websocket-browser.test.js --timeout=15s -v", "test:browser:signature": "node test/browser/browser-test-runner.mjs", "test:browser:websocket": "ava test/browser/websocket-browser.test.js --timeout=15s -v", From d068fdccdaea137fb7dc344fb2c39ee96941c586 Mon Sep 17 00:00:00 2001 From: carlosmiei <43336371+carlosmiei@users.noreply.github.com> Date: Mon, 8 Dec 2025 13:57:03 +0000 Subject: [PATCH 5/5] fix linting --- test/static-tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/static-tests.js b/test/static-tests.js index dc235dde..417de2a4 100644 --- a/test/static-tests.js +++ b/test/static-tests.js @@ -645,4 +645,4 @@ test.serial('[REST] Futures RPI Order', async t => { t.is(obj.price, '50000') t.is(obj.timeInForce, 'RPI') t.true(obj.newClientOrderId.startsWith(CONTRACT_PREFIX)) -}) \ No newline at end of file +})