ccxt 4.3.71 → 4.3.73

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/ccxt.js CHANGED
@@ -194,7 +194,7 @@ var xt$1 = require('./src/pro/xt.js');
194
194
 
195
195
  //-----------------------------------------------------------------------------
196
196
  // this is updated by vss.js when building
197
- const version = '4.3.71';
197
+ const version = '4.3.73';
198
198
  Exchange["default"].ccxtVersion = version;
199
199
  const exchanges = {
200
200
  'ace': ace,
@@ -12,7 +12,7 @@ var index = require('../../static_dependencies/scure-base/index.js');
12
12
 
13
13
  class Client {
14
14
  constructor(url, onMessageCallback, onErrorCallback, onCloseCallback, onConnectedCallback, config = {}) {
15
- this.useMessageQueue = true;
15
+ this.useMessageQueue = false;
16
16
  this.verbose = false;
17
17
  const defaults = {
18
18
  url,
@@ -27,7 +27,7 @@ class Client {
27
27
  subscriptions: {},
28
28
  rejections: {},
29
29
  messageQueue: {},
30
- useMessageQueue: true,
30
+ useMessageQueue: false,
31
31
  connected: undefined,
32
32
  error: undefined,
33
33
  connectionStarted: undefined,
@@ -126,7 +126,7 @@ class paradex extends paradex$1 {
126
126
  },
127
127
  'hostname': 'paradex.trade',
128
128
  'urls': {
129
- 'logo': 'https://github.com/user-attachments/assets/5dadc09a-74ba-466a-a8f2-3f55c7e4654a',
129
+ 'logo': 'https://github.com/user-attachments/assets/84628770-784e-4ec4-a759-ec2fbb2244ea',
130
130
  'api': {
131
131
  'v1': 'https://api.prod.{hostname}/v1',
132
132
  },
@@ -1182,11 +1182,15 @@ class binance extends binance$1 {
1182
1182
  * @method
1183
1183
  * @name binance#watchOHLCV
1184
1184
  * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1185
+ * @see https://binance-docs.github.io/apidocs/spot/en/#kline-candlestick-data
1186
+ * @see https://binance-docs.github.io/apidocs/futures/en/#kline-candlestick-data
1187
+ * @see https://binance-docs.github.io/apidocs/delivery/en/#kline-candlestick-data
1185
1188
  * @param {string} symbol unified symbol of the market to fetch OHLCV data for
1186
1189
  * @param {string} timeframe the length of time each candle represents
1187
1190
  * @param {int} [since] timestamp in ms of the earliest candle to fetch
1188
1191
  * @param {int} [limit] the maximum amount of candles to fetch
1189
1192
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1193
+ * @param {object} [params.timezone] if provided, kline intervals are interpreted in that timezone instead of UTC, example '+08:00'
1190
1194
  * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
1191
1195
  */
1192
1196
  params['callerMethodName'] = 'watchOHLCV';
@@ -1198,10 +1202,14 @@ class binance extends binance$1 {
1198
1202
  * @method
1199
1203
  * @name binance#watchOHLCVForSymbols
1200
1204
  * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1205
+ * @see https://binance-docs.github.io/apidocs/spot/en/#kline-candlestick-data
1206
+ * @see https://binance-docs.github.io/apidocs/futures/en/#kline-candlestick-data
1207
+ * @see https://binance-docs.github.io/apidocs/delivery/en/#kline-candlestick-data
1201
1208
  * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
1202
1209
  * @param {int} [since] timestamp in ms of the earliest candle to fetch
1203
1210
  * @param {int} [limit] the maximum amount of candles to fetch
1204
1211
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1212
+ * @param {object} [params.timezone] if provided, kline intervals are interpreted in that timezone instead of UTC, example '+08:00'
1205
1213
  * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
1206
1214
  */
1207
1215
  await this.loadMarkets();
@@ -1214,6 +1222,10 @@ class binance extends binance$1 {
1214
1222
  if (firstMarket['contract']) {
1215
1223
  type = firstMarket['linear'] ? 'future' : 'delivery';
1216
1224
  }
1225
+ const isSpot = (type === 'spot');
1226
+ let timezone = undefined;
1227
+ [timezone, params] = this.handleParamString(params, 'timezone', undefined);
1228
+ const isUtc8 = (timezone !== undefined) && ((timezone === '+08:00') || Precise["default"].stringEq(timezone, '8'));
1217
1229
  const rawHashes = [];
1218
1230
  const messageHashes = [];
1219
1231
  for (let i = 0; i < symbolsAndTimeframes.length; i++) {
@@ -1227,7 +1239,10 @@ class binance extends binance$1 {
1227
1239
  // weird behavior for index price kline we can't use the perp suffix
1228
1240
  marketId = marketId.replace('_perp', '');
1229
1241
  }
1230
- rawHashes.push(marketId + '@' + klineType + '_' + interval);
1242
+ const shouldUseUTC8 = (isUtc8 && isSpot);
1243
+ const suffix = '@+08:00';
1244
+ const utcSuffix = shouldUseUTC8 ? suffix : '';
1245
+ rawHashes.push(marketId + '@' + klineType + '_' + interval + utcSuffix);
1231
1246
  messageHashes.push('ohlcv::' + symbolString + '::' + timeframeString);
1232
1247
  }
1233
1248
  const url = this.urls['api']['ws'][type] + '/' + this.stream(type, 'multipleOHLCV');
@@ -1096,8 +1096,13 @@ class kucoin extends kucoin$1 {
1096
1096
  const type = this.safeString(trade, 'orderType');
1097
1097
  const side = this.safeString(trade, 'side');
1098
1098
  const tradeId = this.safeString(trade, 'tradeId');
1099
- const price = this.safeString(trade, 'matchPrice');
1100
- const amount = this.safeString(trade, 'matchSize');
1099
+ let price = this.safeString(trade, 'matchPrice');
1100
+ let amount = this.safeString(trade, 'matchSize');
1101
+ if (price === undefined) {
1102
+ // /spot/tradeFills
1103
+ price = this.safeString(trade, 'price');
1104
+ amount = this.safeString(trade, 'size');
1105
+ }
1101
1106
  const order = this.safeString(trade, 'orderId');
1102
1107
  const timestamp = this.safeIntegerProduct2(trade, 'ts', 'time', 0.000001);
1103
1108
  const feeCurrency = market['quote'];
@@ -85,32 +85,49 @@ class woo extends woo$1 {
85
85
  /**
86
86
  * @method
87
87
  * @name woo#watchOrderBook
88
+ * @see https://docs.woo.org/#orderbookupdate
88
89
  * @see https://docs.woo.org/#orderbook
89
90
  * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
90
91
  * @param {string} symbol unified symbol of the market to fetch the order book for
91
92
  * @param {int} [limit] the maximum amount of order book entries to return.
92
93
  * @param {object} [params] extra parameters specific to the exchange API endpoint
94
+ * @param {string} [params.method] either (default) 'orderbook' or 'orderbookupdate', default is 'orderbook'
93
95
  * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
94
96
  */
95
97
  await this.loadMarkets();
96
- const name = 'orderbook';
98
+ let method = undefined;
99
+ [method, params] = this.handleOptionAndParams(params, 'watchOrderBook', 'method', 'orderbook');
97
100
  const market = this.market(symbol);
98
- const topic = market['id'] + '@' + name;
101
+ const topic = market['id'] + '@' + method;
102
+ const urlUid = (this.uid) ? '/' + this.uid : '';
103
+ const url = this.urls['api']['ws']['public'] + urlUid;
104
+ const requestId = this.requestId(url);
99
105
  const request = {
100
106
  'event': 'subscribe',
101
107
  'topic': topic,
108
+ 'id': requestId,
102
109
  };
103
- const message = this.extend(request, params);
104
- const orderbook = await this.watchPublic(topic, message);
110
+ const subscription = {
111
+ 'id': requestId.toString(),
112
+ 'name': method,
113
+ 'symbol': symbol,
114
+ 'limit': limit,
115
+ 'params': params,
116
+ };
117
+ if (method === 'orderbookupdate') {
118
+ subscription['method'] = this.handleOrderBookSubscription;
119
+ }
120
+ const orderbook = await this.watch(url, topic, this.extend(request, params), topic, subscription);
105
121
  return orderbook.limit();
106
122
  }
107
123
  handleOrderBook(client, message) {
108
124
  //
109
125
  // {
110
- // "topic": "PERP_BTC_USDT@orderbook",
111
- // "ts": 1650121915308,
126
+ // "topic": "PERP_BTC_USDT@orderbookupdate",
127
+ // "ts": 1722500373999,
112
128
  // "data": {
113
129
  // "symbol": "PERP_BTC_USDT",
130
+ // "prevTs": 1722500373799,
114
131
  // "bids": [
115
132
  // [
116
133
  // 0.30891,
@@ -131,14 +148,106 @@ class woo extends woo$1 {
131
148
  const market = this.safeMarket(marketId);
132
149
  const symbol = market['symbol'];
133
150
  const topic = this.safeString(message, 'topic');
134
- if (!(symbol in this.orderbooks)) {
135
- this.orderbooks[symbol] = this.orderBook({});
151
+ const method = this.safeString(topic.split('@'), 1);
152
+ if (method === 'orderbookupdate') {
153
+ if (!(symbol in this.orderbooks)) {
154
+ return;
155
+ }
156
+ const orderbook = this.orderbooks[symbol];
157
+ const timestamp = this.safeInteger(orderbook, 'timestamp');
158
+ if (timestamp === undefined) {
159
+ orderbook.cache.push(message);
160
+ }
161
+ else {
162
+ try {
163
+ const ts = this.safeInteger(message, 'ts');
164
+ if (ts > timestamp) {
165
+ this.handleOrderBookMessage(client, message, orderbook);
166
+ client.resolve(orderbook, topic);
167
+ }
168
+ }
169
+ catch (e) {
170
+ delete this.orderbooks[symbol];
171
+ delete client.subscriptions[topic];
172
+ client.reject(e, topic);
173
+ }
174
+ }
175
+ }
176
+ else {
177
+ if (!(symbol in this.orderbooks)) {
178
+ const defaultLimit = this.safeInteger(this.options, 'watchOrderBookLimit', 1000);
179
+ const subscription = client.subscriptions[topic];
180
+ const limit = this.safeInteger(subscription, 'limit', defaultLimit);
181
+ this.orderbooks[symbol] = this.orderBook({}, limit);
182
+ }
183
+ const orderbook = this.orderbooks[symbol];
184
+ const timestamp = this.safeInteger(message, 'ts');
185
+ const snapshot = this.parseOrderBook(data, symbol, timestamp, 'bids', 'asks');
186
+ orderbook.reset(snapshot);
187
+ client.resolve(orderbook, topic);
188
+ }
189
+ }
190
+ handleOrderBookSubscription(client, message, subscription) {
191
+ const defaultLimit = this.safeInteger(this.options, 'watchOrderBookLimit', 1000);
192
+ const limit = this.safeInteger(subscription, 'limit', defaultLimit);
193
+ const symbol = this.safeString(subscription, 'symbol'); // watchOrderBook
194
+ if (symbol in this.orderbooks) {
195
+ delete this.orderbooks[symbol];
136
196
  }
137
- const orderbook = this.orderbooks[symbol];
197
+ this.orderbooks[symbol] = this.orderBook({}, limit);
198
+ this.spawn(this.fetchOrderBookSnapshot, client, message, subscription);
199
+ }
200
+ async fetchOrderBookSnapshot(client, message, subscription) {
201
+ const symbol = this.safeString(subscription, 'symbol');
202
+ const messageHash = this.safeString(message, 'topic');
203
+ try {
204
+ const defaultLimit = this.safeInteger(this.options, 'watchOrderBookLimit', 1000);
205
+ const limit = this.safeInteger(subscription, 'limit', defaultLimit);
206
+ const params = this.safeValue(subscription, 'params');
207
+ const snapshot = await this.fetchRestOrderBookSafe(symbol, limit, params);
208
+ if (this.safeValue(this.orderbooks, symbol) === undefined) {
209
+ // if the orderbook is dropped before the snapshot is received
210
+ return;
211
+ }
212
+ const orderbook = this.orderbooks[symbol];
213
+ orderbook.reset(snapshot);
214
+ const messages = orderbook.cache;
215
+ for (let i = 0; i < messages.length; i++) {
216
+ const messageItem = messages[i];
217
+ const ts = this.safeInteger(messageItem, 'ts');
218
+ if (ts < orderbook['timestamp']) {
219
+ continue;
220
+ }
221
+ else {
222
+ this.handleOrderBookMessage(client, messageItem, orderbook);
223
+ }
224
+ }
225
+ this.orderbooks[symbol] = orderbook;
226
+ client.resolve(orderbook, messageHash);
227
+ }
228
+ catch (e) {
229
+ delete client.subscriptions[messageHash];
230
+ client.reject(e, messageHash);
231
+ }
232
+ }
233
+ handleOrderBookMessage(client, message, orderbook) {
234
+ const data = this.safeDict(message, 'data');
235
+ this.handleDeltas(orderbook['asks'], this.safeValue(data, 'asks', []));
236
+ this.handleDeltas(orderbook['bids'], this.safeValue(data, 'bids', []));
138
237
  const timestamp = this.safeInteger(message, 'ts');
139
- const snapshot = this.parseOrderBook(data, symbol, timestamp, 'bids', 'asks');
140
- orderbook.reset(snapshot);
141
- client.resolve(orderbook, topic);
238
+ orderbook['timestamp'] = timestamp;
239
+ orderbook['datetime'] = this.iso8601(timestamp);
240
+ return orderbook;
241
+ }
242
+ handleDelta(bookside, delta) {
243
+ const price = this.safeFloat2(delta, 'price', 0);
244
+ const amount = this.safeFloat2(delta, 'quantity', 1);
245
+ bookside.store(price, amount);
246
+ }
247
+ handleDeltas(bookside, deltas) {
248
+ for (let i = 0; i < deltas.length; i++) {
249
+ this.handleDelta(bookside, deltas[i]);
250
+ }
142
251
  }
143
252
  async watchTicker(symbol, params = {}) {
144
253
  /**
@@ -1061,6 +1170,7 @@ class woo extends woo$1 {
1061
1170
  'pong': this.handlePong,
1062
1171
  'subscribe': this.handleSubscribe,
1063
1172
  'orderbook': this.handleOrderBook,
1173
+ 'orderbookupdate': this.handleOrderBook,
1064
1174
  'ticker': this.handleTicker,
1065
1175
  'tickers': this.handleTickers,
1066
1176
  'kline': this.handleOHLCV,
@@ -1126,6 +1236,13 @@ class woo extends woo$1 {
1126
1236
  // "ts": 1657117712212
1127
1237
  // }
1128
1238
  //
1239
+ const id = this.safeString(message, 'id');
1240
+ const subscriptionsById = this.indexBy(client.subscriptions, 'id');
1241
+ const subscription = this.safeValue(subscriptionsById, id, {});
1242
+ const method = this.safeValue(subscription, 'method');
1243
+ if (method !== undefined) {
1244
+ method.call(this, client, message, subscription);
1245
+ }
1129
1246
  return message;
1130
1247
  }
1131
1248
  handleAuth(client, message) {
@@ -374,10 +374,14 @@ async function run () {
374
374
  }
375
375
 
376
376
  if (debug) {
377
- const keys = Object.keys (httpsAgent.freeSockets)
378
- const firstKey = keys[0]
379
- let httpAgent = httpsAgent.freeSockets[firstKey];
380
- log (firstKey, httpAgent.length)
377
+ if (httpsAgent.freeSockets) {
378
+ const keys = Object.keys (httpsAgent.freeSockets)
379
+ if (keys.length) {
380
+ const firstKey = keys[0]
381
+ let httpAgent = httpsAgent.freeSockets[firstKey];
382
+ log (firstKey, httpAgent.length)
383
+ }
384
+ }
381
385
  }
382
386
 
383
387
  if (!poll && !isWsMethod){
package/js/ccxt.d.ts CHANGED
@@ -4,7 +4,7 @@ import * as functions from './src/base/functions.js';
4
4
  import * as errors from './src/base/errors.js';
5
5
  import type { Int, int, Str, Strings, Num, Bool, IndexType, OrderSide, OrderType, MarketType, SubType, Dict, NullableDict, List, NullableList, Fee, OHLCV, OHLCVC, implicitReturnType, Market, Currency, Dictionary, MinMax, FeeInterface, TradingFeeInterface, MarketInterface, Trade, Order, OrderBook, Ticker, Transaction, Tickers, CurrencyInterface, Balance, BalanceAccount, Account, PartialBalances, Balances, DepositAddress, WithdrawalResponse, DepositAddressResponse, FundingRate, FundingRates, Position, BorrowInterest, LeverageTier, LedgerEntry, DepositWithdrawFeeNetwork, DepositWithdrawFee, TransferEntry, CrossBorrowRate, IsolatedBorrowRate, FundingRateHistory, OpenInterest, Liquidation, OrderRequest, CancellationRequest, FundingHistory, MarginMode, Greeks, Conversion, Option, LastPrice, Leverage, MarginModification, Leverages, LastPrices, Currencies, TradingFees, MarginModes, OptionChain, IsolatedBorrowRates, CrossBorrowRates, LeverageTiers } from './src/base/types.js';
6
6
  import { BaseError, ExchangeError, AuthenticationError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, OperationRejected, NoChange, MarginModeAlreadySet, MarketClosed, InsufficientFunds, InvalidAddress, AddressPending, InvalidOrder, OrderNotFound, OrderNotCached, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, ContractUnavailable, NotSupported, InvalidProxySettings, ExchangeClosedByUser, OperationFailed, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, ChecksumError, RequestTimeout, BadResponse, NullResponse, CancelPending } from './src/base/errors.js';
7
- declare const version = "4.3.70";
7
+ declare const version = "4.3.72";
8
8
  import ace from './src/ace.js';
9
9
  import alpaca from './src/alpaca.js';
10
10
  import ascendex from './src/ascendex.js';
package/js/ccxt.js CHANGED
@@ -38,7 +38,7 @@ import * as errors from './src/base/errors.js';
38
38
  import { BaseError, ExchangeError, AuthenticationError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, OperationRejected, NoChange, MarginModeAlreadySet, MarketClosed, InsufficientFunds, InvalidAddress, AddressPending, InvalidOrder, OrderNotFound, OrderNotCached, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, ContractUnavailable, NotSupported, InvalidProxySettings, ExchangeClosedByUser, OperationFailed, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, ChecksumError, RequestTimeout, BadResponse, NullResponse, CancelPending } from './src/base/errors.js';
39
39
  //-----------------------------------------------------------------------------
40
40
  // this is updated by vss.js when building
41
- const version = '4.3.71';
41
+ const version = '4.3.73';
42
42
  Exchange.ccxtVersion = version;
43
43
  //-----------------------------------------------------------------------------
44
44
  import ace from './src/ace.js';
@@ -36,15 +36,15 @@ export interface TradingFeeInterface {
36
36
  }
37
37
  export declare type Fee = FeeInterface | undefined;
38
38
  export interface MarketInterface {
39
- id: string;
39
+ id: Str;
40
40
  numericId?: Num;
41
- uppercaseId?: string;
42
- lowercaseId?: string;
41
+ uppercaseId?: Str;
42
+ lowercaseId?: Str;
43
43
  symbol: string;
44
- base: string;
45
- quote: string;
46
- baseId: string;
47
- quoteId: string;
44
+ base: Str;
45
+ quote: Str;
46
+ baseId: Str;
47
+ quoteId: Str;
48
48
  active: Bool;
49
49
  type: MarketType;
50
50
  subType?: SubType;
@@ -66,9 +66,9 @@ export interface MarketInterface {
66
66
  optionType: Str;
67
67
  taker?: Num;
68
68
  maker?: Num;
69
- percentage?: boolean | undefined;
70
- tierBased?: boolean | undefined;
71
- feeSide?: string | undefined;
69
+ percentage?: Bool;
70
+ tierBased?: Bool;
71
+ feeSide?: Str;
72
72
  precision: {
73
73
  amount: Num;
74
74
  price: Num;
@@ -11,7 +11,7 @@ import { isNode, isJsonEncodedObject, deepExtend, milliseconds, } from '../../ba
11
11
  import { utf8 } from '../../static_dependencies/scure-base/index.js';
12
12
  export default class Client {
13
13
  constructor(url, onMessageCallback, onErrorCallback, onCloseCallback, onConnectedCallback, config = {}) {
14
- this.useMessageQueue = true;
14
+ this.useMessageQueue = false;
15
15
  this.verbose = false;
16
16
  const defaults = {
17
17
  url,
@@ -26,7 +26,7 @@ export default class Client {
26
26
  subscriptions: {},
27
27
  rejections: {},
28
28
  messageQueue: {},
29
- useMessageQueue: true,
29
+ useMessageQueue: false,
30
30
  connected: undefined,
31
31
  error: undefined,
32
32
  connectionStarted: undefined,
package/js/src/paradex.js CHANGED
@@ -128,7 +128,7 @@ export default class paradex extends Exchange {
128
128
  },
129
129
  'hostname': 'paradex.trade',
130
130
  'urls': {
131
- 'logo': 'https://github.com/user-attachments/assets/5dadc09a-74ba-466a-a8f2-3f55c7e4654a',
131
+ 'logo': 'https://github.com/user-attachments/assets/84628770-784e-4ec4-a759-ec2fbb2244ea',
132
132
  'api': {
133
133
  'v1': 'https://api.prod.{hostname}/v1',
134
134
  },
@@ -1185,11 +1185,15 @@ export default class binance extends binanceRest {
1185
1185
  * @method
1186
1186
  * @name binance#watchOHLCV
1187
1187
  * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1188
+ * @see https://binance-docs.github.io/apidocs/spot/en/#kline-candlestick-data
1189
+ * @see https://binance-docs.github.io/apidocs/futures/en/#kline-candlestick-data
1190
+ * @see https://binance-docs.github.io/apidocs/delivery/en/#kline-candlestick-data
1188
1191
  * @param {string} symbol unified symbol of the market to fetch OHLCV data for
1189
1192
  * @param {string} timeframe the length of time each candle represents
1190
1193
  * @param {int} [since] timestamp in ms of the earliest candle to fetch
1191
1194
  * @param {int} [limit] the maximum amount of candles to fetch
1192
1195
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1196
+ * @param {object} [params.timezone] if provided, kline intervals are interpreted in that timezone instead of UTC, example '+08:00'
1193
1197
  * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
1194
1198
  */
1195
1199
  params['callerMethodName'] = 'watchOHLCV';
@@ -1201,10 +1205,14 @@ export default class binance extends binanceRest {
1201
1205
  * @method
1202
1206
  * @name binance#watchOHLCVForSymbols
1203
1207
  * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1208
+ * @see https://binance-docs.github.io/apidocs/spot/en/#kline-candlestick-data
1209
+ * @see https://binance-docs.github.io/apidocs/futures/en/#kline-candlestick-data
1210
+ * @see https://binance-docs.github.io/apidocs/delivery/en/#kline-candlestick-data
1204
1211
  * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
1205
1212
  * @param {int} [since] timestamp in ms of the earliest candle to fetch
1206
1213
  * @param {int} [limit] the maximum amount of candles to fetch
1207
1214
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1215
+ * @param {object} [params.timezone] if provided, kline intervals are interpreted in that timezone instead of UTC, example '+08:00'
1208
1216
  * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
1209
1217
  */
1210
1218
  await this.loadMarkets();
@@ -1217,6 +1225,10 @@ export default class binance extends binanceRest {
1217
1225
  if (firstMarket['contract']) {
1218
1226
  type = firstMarket['linear'] ? 'future' : 'delivery';
1219
1227
  }
1228
+ const isSpot = (type === 'spot');
1229
+ let timezone = undefined;
1230
+ [timezone, params] = this.handleParamString(params, 'timezone', undefined);
1231
+ const isUtc8 = (timezone !== undefined) && ((timezone === '+08:00') || Precise.stringEq(timezone, '8'));
1220
1232
  const rawHashes = [];
1221
1233
  const messageHashes = [];
1222
1234
  for (let i = 0; i < symbolsAndTimeframes.length; i++) {
@@ -1230,7 +1242,10 @@ export default class binance extends binanceRest {
1230
1242
  // weird behavior for index price kline we can't use the perp suffix
1231
1243
  marketId = marketId.replace('_perp', '');
1232
1244
  }
1233
- rawHashes.push(marketId + '@' + klineType + '_' + interval);
1245
+ const shouldUseUTC8 = (isUtc8 && isSpot);
1246
+ const suffix = '@+08:00';
1247
+ const utcSuffix = shouldUseUTC8 ? suffix : '';
1248
+ rawHashes.push(marketId + '@' + klineType + '_' + interval + utcSuffix);
1234
1249
  messageHashes.push('ohlcv::' + symbolString + '::' + timeframeString);
1235
1250
  }
1236
1251
  const url = this.urls['api']['ws'][type] + '/' + this.stream(type, 'multipleOHLCV');
@@ -1099,8 +1099,13 @@ export default class kucoin extends kucoinRest {
1099
1099
  const type = this.safeString(trade, 'orderType');
1100
1100
  const side = this.safeString(trade, 'side');
1101
1101
  const tradeId = this.safeString(trade, 'tradeId');
1102
- const price = this.safeString(trade, 'matchPrice');
1103
- const amount = this.safeString(trade, 'matchSize');
1102
+ let price = this.safeString(trade, 'matchPrice');
1103
+ let amount = this.safeString(trade, 'matchSize');
1104
+ if (price === undefined) {
1105
+ // /spot/tradeFills
1106
+ price = this.safeString(trade, 'price');
1107
+ amount = this.safeString(trade, 'size');
1108
+ }
1104
1109
  const order = this.safeString(trade, 'orderId');
1105
1110
  const timestamp = this.safeIntegerProduct2(trade, 'ts', 'time', 0.000001);
1106
1111
  const feeCurrency = market['quote'];
@@ -7,6 +7,11 @@ export default class woo extends wooRest {
7
7
  watchPublic(messageHash: any, message: any): Promise<any>;
8
8
  watchOrderBook(symbol: string, limit?: Int, params?: {}): Promise<OrderBook>;
9
9
  handleOrderBook(client: Client, message: any): void;
10
+ handleOrderBookSubscription(client: Client, message: any, subscription: any): void;
11
+ fetchOrderBookSnapshot(client: any, message: any, subscription: any): Promise<void>;
12
+ handleOrderBookMessage(client: Client, message: any, orderbook: any): any;
13
+ handleDelta(bookside: any, delta: any): void;
14
+ handleDeltas(bookside: any, deltas: any): void;
10
15
  watchTicker(symbol: string, params?: {}): Promise<Ticker>;
11
16
  parseWsTicker(ticker: any, market?: any): Ticker;
12
17
  handleTicker(client: Client, message: any): any;