Skip to content

Commit 01e6921

Browse files
committed
fix: use query params for private listenKey URL per new Binance spec
The new /private/ endpoint requires ?listenKey=<key> format instead of the legacy path-based /<key> format.
1 parent 570d886 commit 01e6921

2 files changed

Lines changed: 26 additions & 3 deletions

File tree

src/node-binance-api.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1802,6 +1802,10 @@ export default class Binance {
18021802
let ws: any = undefined;
18031803
const category = this.classifyFuturesStream(endpoint);
18041804
const baseUrl = this.getFStreamSingleUrl(category);
1805+
// Private streams use query params: ?listenKey=<key> instead of path: /<key>
1806+
const wsUrl = category === 'private'
1807+
? baseUrl.replace(/\/$/, '') + '?listenKey=' + endpoint
1808+
: baseUrl + endpoint;
18051809

18061810
if (socksproxy) {
18071811
socksproxy = this.proxyReplacewithIp(socksproxy);
@@ -1811,14 +1815,14 @@ export default class Binance {
18111815
host: this.parseProxy(socksproxy)[1],
18121816
port: this.parseProxy(socksproxy)[2]
18131817
});
1814-
ws = new WebSocket(baseUrl + endpoint, { agent });
1818+
ws = new WebSocket(wsUrl, { agent });
18151819
} else if (httpsproxy) {
18161820
const config = url.parse(httpsproxy);
18171821
const agent = new HttpsProxyAgent(config);
18181822
if (this.Options.verbose) this.Options.log(`futuresSubscribeSingle: using proxy server: ${agent}`);
1819-
ws = new WebSocket(baseUrl + endpoint, { agent });
1823+
ws = new WebSocket(wsUrl, { agent });
18201824
} else {
1821-
ws = new WebSocket(baseUrl + endpoint);
1825+
ws = new WebSocket(wsUrl);
18221826
}
18231827

18241828
if (this.Options.verbose) this.Options.log('futuresSubscribeSingle: Subscribed to ' + endpoint);

tests/ws-endpoints-migration.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,25 @@ describe('Demo mode uses category-based URLs', function () {
133133
});
134134
});
135135

136+
describe('Private stream URL uses query params for listenKey', function () {
137+
it('constructs ?listenKey= URL instead of path-based', function () {
138+
const listenKey = 'pqia91ma19a5s61cv6a81va65sdf19v8a65a1a5s61cv6a81va65sdf19v8a1a65a1a5s61cv6a81va65sd';
139+
const category = binance.classifyFuturesStream(listenKey);
140+
const baseUrl = binance.getFStreamSingleUrl(category);
141+
const wsUrl = baseUrl.replace(/\/$/, '') + '?listenKey=' + listenKey;
142+
assert.equal(category, 'private');
143+
assert.equal(wsUrl, `wss://fstream.binance.com/private/ws?listenKey=${listenKey}`);
144+
});
145+
146+
it('constructs query-param URL for demo too', function () {
147+
const listenKey = 'pqia91ma19a5s61cv6a81va65sdf19v8a65a1a5s61cv6a81va65sdf19v8a1a65a1a5s61cv6a81va65sd';
148+
const category = demoBinance.classifyFuturesStream(listenKey);
149+
const baseUrl = demoBinance.getFStreamSingleUrl(category);
150+
const wsUrl = baseUrl.replace(/\/$/, '') + '?listenKey=' + listenKey;
151+
assert.equal(wsUrl, `wss://fstream.binancefuture.com/private/ws?listenKey=${listenKey}`);
152+
});
153+
});
154+
136155
describe('Live: production market stream (aggTrade via /market/)', function () {
137156
let trade;
138157
let cnt = 0;

0 commit comments

Comments
 (0)