From 9f59422be2ec175d5f63d0ff67a4af60e35f8b4f Mon Sep 17 00:00:00 2001 From: carlosmiei <43336371+carlosmiei@users.noreply.github.com> Date: Sat, 6 Sep 2025 17:52:43 +0100 Subject: [PATCH 1/2] feat(client): add spotCloseDataStream --- src/node-binance-api.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/node-binance-api.ts b/src/node-binance-api.ts index 33b37db8..213d9ec2 100644 --- a/src/node-binance-api.ts +++ b/src/node-binance-api.ts @@ -4139,6 +4139,12 @@ export default class Binance { return await this.privateFuturesRequest('v1/listenKey', params, 'DELETE'); } + async spotCloseDataStream(listenKey: string | undefined = undefined, params: Dict = {}) { + listenKey = listenKey || this.Options.listenKey; + if (!listenKey) throw new Error('A listenKey is required, either as an argument or in this.Options.listenKey'); + return await this.privateSpotRequest('v3/userDataStream', { listenKey, ...params }, 'DELETE'); + } + /** * Get the account position risk (v3) * @see https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/rest-api/Position-Information-V3 From 4ab113687907de8f7d3c4f3bc4c126a031b250bf Mon Sep 17 00:00:00 2001 From: carlosmiei <43336371+carlosmiei@users.noreply.github.com> Date: Sat, 6 Sep 2025 18:15:51 +0100 Subject: [PATCH 2/2] fix signedRequest --- src/node-binance-api.ts | 46 +++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/node-binance-api.ts b/src/node-binance-api.ts index 213d9ec2..4dfd7f67 100644 --- a/src/node-binance-api.ts +++ b/src/node-binance-api.ts @@ -656,14 +656,19 @@ export default class Binance { */ async signedRequest(url: string, data: Dict = {}, method: HttpMethod = 'GET', noDataInSignature = false) { this.requireApiSecret('signedRequest'); + const isListenKeyEndpoint = url.includes('v3/userDataStream'); - data.timestamp = new Date().getTime(); - if (this.timeOffset) data.timestamp += this.timeOffset; - - if (!data.recvWindow) data.recvWindow = this.Options.recvWindow; const query = method === 'POST' && noDataInSignature ? '' : this.makeQueryString(data); - const signature = this.generateSignature(query); + let signature = undefined; + if (!noDataInSignature && !isListenKeyEndpoint) { + data.timestamp = new Date().getTime(); + + if (this.timeOffset) data.timestamp += this.timeOffset; + + if (!data.recvWindow) data.recvWindow = this.Options.recvWindow; + signature = this.generateSignature(query); + } if (method === 'POST') { const opt = this.reqObjPOST( @@ -672,12 +677,17 @@ export default class Binance { method, this.APIKEY ); - opt.form.signature = signature; + if (signature) { + opt.form.signature = signature; + } const reqPost = await this.proxyRequest(opt); return reqPost; } else { + let encodedUrl = url; + if (query) encodedUrl += '?' + query; + if (signature) encodedUrl += '&signature=' + signature; const opt = this.reqObj( - url + '?' + query + '&signature=' + signature, + encodedUrl, data, method, this.APIKEY @@ -3917,6 +3927,22 @@ export default class Binance { return res; } + async spotGetDataStream(params: Dict = {}) { + return await this.privateSpotRequest('v3/userDataStream', params, 'POST', true); + } + + async spotKeepDataStream(listenKey: string | undefined = undefined, params: Dict = {}) { + listenKey = listenKey || this.Options.listenKey; + if (!listenKey) throw new Error('A listenKey is required, either as an argument or in this.Options.listenKey'); + return await this.privateSpotRequest('v3/userDataStream', { listenKey, ...params }, 'PUT'); + } + + async spotCloseDataStream(listenKey: string | undefined = undefined, params: Dict = {}) { + listenKey = listenKey || this.Options.listenKey; + if (!listenKey) throw new Error('A listenKey is required, either as an argument or in this.Options.listenKey'); + return await this.privateSpotRequest('v3/userDataStream', { listenKey, ...params }, 'DELETE'); + } + // /** // * Queries the public api // * @param {string} url - the public api endpoint @@ -4139,12 +4165,6 @@ export default class Binance { return await this.privateFuturesRequest('v1/listenKey', params, 'DELETE'); } - async spotCloseDataStream(listenKey: string | undefined = undefined, params: Dict = {}) { - listenKey = listenKey || this.Options.listenKey; - if (!listenKey) throw new Error('A listenKey is required, either as an argument or in this.Options.listenKey'); - return await this.privateSpotRequest('v3/userDataStream', { listenKey, ...params }, 'DELETE'); - } - /** * Get the account position risk (v3) * @see https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/rest-api/Position-Information-V3