ccxt 4.2.51 → 4.2.53

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.
Files changed (57) hide show
  1. package/CHANGELOG.md +76 -16
  2. package/README.md +5 -6
  3. package/dist/ccxt.browser.js +994 -1412
  4. package/dist/ccxt.browser.min.js +3 -3
  5. package/dist/cjs/ccxt.js +1 -4
  6. package/dist/cjs/src/base/Exchange.js +65 -26
  7. package/dist/cjs/src/binance.js +92 -3
  8. package/dist/cjs/src/bingx.js +32 -1
  9. package/dist/cjs/src/bitget.js +1 -0
  10. package/dist/cjs/src/bitvavo.js +1 -1
  11. package/dist/cjs/src/coinbase.js +186 -12
  12. package/dist/cjs/src/htx.js +10 -4
  13. package/dist/cjs/src/pro/binance.js +156 -1
  14. package/dist/cjs/src/pro/bitfinex2.js +3 -1
  15. package/dist/cjs/src/pro/bitvavo.js +1 -1
  16. package/dist/cjs/src/pro/blockchaincom.js +7 -25
  17. package/dist/cjs/src/pro/deribit.js +2 -2
  18. package/dist/cjs/src/pro/gate.js +2 -1
  19. package/dist/cjs/src/pro/gemini.js +1 -1
  20. package/dist/cjs/src/pro/okx.js +18 -4
  21. package/dist/cjs/src/woo.js +3 -1
  22. package/js/ccxt.d.ts +2 -5
  23. package/js/ccxt.js +2 -4
  24. package/js/src/abstract/coinbase.d.ts +1 -1
  25. package/js/src/base/Exchange.d.ts +65 -26
  26. package/js/src/base/Exchange.js +65 -26
  27. package/js/src/binance.d.ts +6 -0
  28. package/js/src/binance.js +92 -3
  29. package/js/src/bingx.d.ts +4 -0
  30. package/js/src/bingx.js +32 -1
  31. package/js/src/bitget.js +1 -0
  32. package/js/src/bitvavo.js +1 -1
  33. package/js/src/coinbase.d.ts +2 -0
  34. package/js/src/coinbase.js +186 -12
  35. package/js/src/deribit.js +1 -1
  36. package/js/src/htx.js +10 -4
  37. package/js/src/ndax.js +1 -1
  38. package/js/src/pro/binance.d.ts +3 -0
  39. package/js/src/pro/binance.js +156 -1
  40. package/js/src/pro/bingx.js +1 -1
  41. package/js/src/pro/bitfinex2.js +3 -1
  42. package/js/src/pro/bitvavo.js +1 -1
  43. package/js/src/pro/blockchaincom.d.ts +0 -1
  44. package/js/src/pro/blockchaincom.js +7 -25
  45. package/js/src/pro/deribit.js +2 -2
  46. package/js/src/pro/gate.js +2 -1
  47. package/js/src/pro/gemini.js +1 -1
  48. package/js/src/pro/okx.js +18 -4
  49. package/js/src/woo.js +4 -2
  50. package/package.json +2 -1
  51. package/skip-tests.json +29 -13
  52. package/dist/cjs/src/abstract/bitforex.js +0 -9
  53. package/dist/cjs/src/bitforex.js +0 -884
  54. package/js/src/abstract/bitforex.d.ts +0 -27
  55. package/js/src/abstract/bitforex.js +0 -11
  56. package/js/src/bitforex.d.ts +0 -39
  57. package/js/src/bitforex.js +0 -885
@@ -51,6 +51,7 @@ class coinbase extends coinbase$1 {
51
51
  'createStopLimitOrder': true,
52
52
  'createStopMarketOrder': false,
53
53
  'createStopOrder': true,
54
+ 'deposit': true,
54
55
  'editOrder': true,
55
56
  'fetchAccounts': true,
56
57
  'fetchBalance': true,
@@ -62,6 +63,7 @@ class coinbase extends coinbase$1 {
62
63
  'fetchCrossBorrowRate': false,
63
64
  'fetchCrossBorrowRates': false,
64
65
  'fetchCurrencies': true,
66
+ 'fetchDeposit': true,
65
67
  'fetchDepositAddress': 'emulated',
66
68
  'fetchDepositAddresses': false,
67
69
  'fetchDepositAddressesByNetwork': true,
@@ -190,6 +192,11 @@ class coinbase extends coinbase$1 {
190
192
  },
191
193
  },
192
194
  'v3': {
195
+ 'public': {
196
+ 'get': [
197
+ 'brokerage/time',
198
+ ],
199
+ },
193
200
  'private': {
194
201
  'get': [
195
202
  'brokerage/accounts',
@@ -207,7 +214,6 @@ class coinbase extends coinbase$1 {
207
214
  'brokerage/product_book',
208
215
  'brokerage/best_bid_ask',
209
216
  'brokerage/convert/trade/{trade_id}',
210
- 'brokerage/time',
211
217
  'brokerage/cfm/balance_summary',
212
218
  'brokerage/cfm/positions',
213
219
  'brokerage/cfm/positions/{product_id}',
@@ -338,6 +344,7 @@ class coinbase extends coinbase$1 {
338
344
  'fetchTickers': 'fetchTickersV3',
339
345
  'fetchAccounts': 'fetchAccountsV3',
340
346
  'fetchBalance': 'v2PrivateGetAccounts',
347
+ 'fetchTime': 'v2PublicGetTime',
341
348
  'user_native_currency': 'USD', // needed to get fees for v3
342
349
  },
343
350
  });
@@ -349,19 +356,36 @@ class coinbase extends coinbase$1 {
349
356
  * @description fetches the current integer timestamp in milliseconds from the exchange server
350
357
  * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-time#http-request
351
358
  * @param {object} [params] extra parameters specific to the exchange API endpoint
359
+ * @param {string} [params.method] 'v2PublicGetTime' or 'v3PublicGetBrokerageTime' default is 'v2PublicGetTime'
352
360
  * @returns {int} the current integer timestamp in milliseconds from the exchange server
353
361
  */
354
- const response = await this.v2PublicGetTime(params);
355
- //
356
- // {
357
- // "data": {
358
- // "epoch": 1589295679,
359
- // "iso": "2020-05-12T15:01:19Z"
360
- // }
361
- // }
362
- //
363
- const data = this.safeValue(response, 'data', {});
364
- return this.safeTimestamp(data, 'epoch');
362
+ const defaultMethod = this.safeString(this.options, 'fetchTime', 'v2PublicGetTime');
363
+ const method = this.safeString(params, 'method', defaultMethod);
364
+ params = this.omit(params, 'method');
365
+ let response = undefined;
366
+ if (method === 'v2PublicGetTime') {
367
+ response = await this.v2PublicGetTime(params);
368
+ //
369
+ // {
370
+ // "data": {
371
+ // "epoch": 1589295679,
372
+ // "iso": "2020-05-12T15:01:19Z"
373
+ // }
374
+ // }
375
+ //
376
+ response = this.safeValue(response, 'data', {});
377
+ }
378
+ else {
379
+ response = await this.v3PublicGetBrokerageTime(params);
380
+ //
381
+ // {
382
+ // "iso": "2024-02-27T03:37:14Z",
383
+ // "epochSeconds": "1709005034",
384
+ // "epochMillis": "1709005034333"
385
+ // }
386
+ //
387
+ }
388
+ return this.safeTimestamp2(response, 'epoch', 'epochSeconds');
365
389
  }
366
390
  async fetchAccounts(params = {}) {
367
391
  /**
@@ -1757,6 +1781,7 @@ class coinbase extends coinbase$1 {
1757
1781
  response = await this.v3PrivateGetBrokerageAccounts(this.extend(request, params));
1758
1782
  }
1759
1783
  else {
1784
+ request['limit'] = 100;
1760
1785
  response = await this.v2PrivateGetAccounts(this.extend(request, params));
1761
1786
  }
1762
1787
  //
@@ -3536,6 +3561,145 @@ class coinbase extends coinbase$1 {
3536
3561
  'network': this.networkIdToCode(networkId, code),
3537
3562
  };
3538
3563
  }
3564
+ async deposit(code, amount, id, params = {}) {
3565
+ /**
3566
+ * @method
3567
+ * @name coinbase#deposit
3568
+ * @description make a deposit
3569
+ * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-deposits#deposit-funds
3570
+ * @param {string} code unified currency code
3571
+ * @param {float} amount the amount to deposit
3572
+ * @param {string} id the payment method id to be used for the deposit, can be retrieved from v2PrivateGetPaymentMethods
3573
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3574
+ * @param {string} [params.accountId] the id of the account to deposit into
3575
+ * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
3576
+ */
3577
+ await this.loadMarkets();
3578
+ let accountId = this.safeString2(params, 'account_id', 'accountId');
3579
+ params = this.omit(params, ['account_id', 'accountId']);
3580
+ if (accountId === undefined) {
3581
+ if (code === undefined) {
3582
+ throw new errors.ArgumentsRequired(this.id + ' deposit() requires an account_id (or accountId) parameter OR a currency code argument');
3583
+ }
3584
+ accountId = await this.findAccountId(code);
3585
+ if (accountId === undefined) {
3586
+ throw new errors.ExchangeError(this.id + ' deposit() could not find account id for ' + code);
3587
+ }
3588
+ }
3589
+ const request = {
3590
+ 'account_id': accountId,
3591
+ 'amount': this.numberToString(amount),
3592
+ 'currency': code.toUpperCase(),
3593
+ 'payment_method': id,
3594
+ };
3595
+ const response = await this.v2PrivatePostAccountsAccountIdDeposits(this.extend(request, params));
3596
+ //
3597
+ // {
3598
+ // "data": {
3599
+ // "id": "67e0eaec-07d7-54c4-a72c-2e92826897df",
3600
+ // "status": "created",
3601
+ // "payment_method": {
3602
+ // "id": "83562370-3e5c-51db-87da-752af5ab9559",
3603
+ // "resource": "payment_method",
3604
+ // "resource_path": "/v2/payment-methods/83562370-3e5c-51db-87da-752af5ab9559"
3605
+ // },
3606
+ // "transaction": {
3607
+ // "id": "441b9494-b3f0-5b98-b9b0-4d82c21c252a",
3608
+ // "resource": "transaction",
3609
+ // "resource_path": "/v2/accounts/2bbf394c-193b-5b2a-9155-3b4732659ede/transactions/441b9494-b3f0-5b98-b9b0-4d82c21c252a"
3610
+ // },
3611
+ // "amount": {
3612
+ // "amount": "10.00",
3613
+ // "currency": "USD"
3614
+ // },
3615
+ // "subtotal": {
3616
+ // "amount": "10.00",
3617
+ // "currency": "USD"
3618
+ // },
3619
+ // "created_at": "2015-01-31T20:49:02Z",
3620
+ // "updated_at": "2015-02-11T16:54:02-08:00",
3621
+ // "resource": "deposit",
3622
+ // "resource_path": "/v2/accounts/2bbf394c-193b-5b2a-9155-3b4732659ede/deposits/67e0eaec-07d7-54c4-a72c-2e92826897df",
3623
+ // "committed": true,
3624
+ // "fee": {
3625
+ // "amount": "0.00",
3626
+ // "currency": "USD"
3627
+ // },
3628
+ // "payout_at": "2015-02-18T16:54:00-08:00"
3629
+ // }
3630
+ // }
3631
+ //
3632
+ const data = this.safeDict(response, 'data', {});
3633
+ return this.parseTransaction(data);
3634
+ }
3635
+ async fetchDeposit(id, code = undefined, params = {}) {
3636
+ /**
3637
+ * @method
3638
+ * @name coinbase#fetchDeposit
3639
+ * @description fetch information on a deposit, fiat only, for crypto transactions use fetchLedger
3640
+ * @see https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-deposits#show-deposit
3641
+ * @param {string} id deposit id
3642
+ * @param {string} [code] unified currency code
3643
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3644
+ * @param {string} [params.accountId] the id of the account that the funds were deposited into
3645
+ * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
3646
+ */
3647
+ await this.loadMarkets();
3648
+ let accountId = this.safeString2(params, 'account_id', 'accountId');
3649
+ params = this.omit(params, ['account_id', 'accountId']);
3650
+ if (accountId === undefined) {
3651
+ if (code === undefined) {
3652
+ throw new errors.ArgumentsRequired(this.id + ' fetchDeposit() requires an account_id (or accountId) parameter OR a currency code argument');
3653
+ }
3654
+ accountId = await this.findAccountId(code);
3655
+ if (accountId === undefined) {
3656
+ throw new errors.ExchangeError(this.id + ' fetchDeposit() could not find account id for ' + code);
3657
+ }
3658
+ }
3659
+ const request = {
3660
+ 'account_id': accountId,
3661
+ 'deposit_id': id,
3662
+ };
3663
+ const response = await this.v2PrivateGetAccountsAccountIdDepositsDepositId(this.extend(request, params));
3664
+ //
3665
+ // {
3666
+ // "data": {
3667
+ // "id": "67e0eaec-07d7-54c4-a72c-2e92826897df",
3668
+ // "status": "completed",
3669
+ // "payment_method": {
3670
+ // "id": "83562370-3e5c-51db-87da-752af5ab9559",
3671
+ // "resource": "payment_method",
3672
+ // "resource_path": "/v2/payment-methods/83562370-3e5c-51db-87da-752af5ab9559"
3673
+ // },
3674
+ // "transaction": {
3675
+ // "id": "441b9494-b3f0-5b98-b9b0-4d82c21c252a",
3676
+ // "resource": "transaction",
3677
+ // "resource_path": "/v2/accounts/2bbf394c-193b-5b2a-9155-3b4732659ede/transactions/441b9494-b3f0-5b98-b9b0-4d82c21c252a"
3678
+ // },
3679
+ // "amount": {
3680
+ // "amount": "10.00",
3681
+ // "currency": "USD"
3682
+ // },
3683
+ // "subtotal": {
3684
+ // "amount": "10.00",
3685
+ // "currency": "USD"
3686
+ // },
3687
+ // "created_at": "2015-01-31T20:49:02Z",
3688
+ // "updated_at": "2015-02-11T16:54:02-08:00",
3689
+ // "resource": "deposit",
3690
+ // "resource_path": "/v2/accounts/2bbf394c-193b-5b2a-9155-3b4732659ede/deposits/67e0eaec-07d7-54c4-a72c-2e92826897df",
3691
+ // "committed": true,
3692
+ // "fee": {
3693
+ // "amount": "0.00",
3694
+ // "currency": "USD"
3695
+ // },
3696
+ // "payout_at": "2015-02-18T16:54:00-08:00"
3697
+ // }
3698
+ // }
3699
+ //
3700
+ const data = this.safeValue(response, 'data', {});
3701
+ return this.parseTransaction(data);
3702
+ }
3539
3703
  sign(path, api = [], method = 'GET', params = {}, headers = undefined, body = undefined) {
3540
3704
  const version = api[0];
3541
3705
  const signed = api[1] === 'private';
@@ -3556,6 +3720,11 @@ class coinbase extends coinbase$1 {
3556
3720
  'Authorization': authorization,
3557
3721
  'Content-Type': 'application/json',
3558
3722
  };
3723
+ if (method !== 'GET') {
3724
+ if (Object.keys(query).length) {
3725
+ body = this.json(query);
3726
+ }
3727
+ }
3559
3728
  }
3560
3729
  else if (this.token && !this.checkRequiredCredentials(false)) {
3561
3730
  headers = {
@@ -3578,6 +3747,11 @@ class coinbase extends coinbase$1 {
3578
3747
  payload = body;
3579
3748
  }
3580
3749
  }
3750
+ else {
3751
+ if (Object.keys(query).length) {
3752
+ payload += '?' + this.urlencode(query);
3753
+ }
3754
+ }
3581
3755
  const auth = nonce + method + savedPath + payload;
3582
3756
  const signature = this.hmac(this.encode(auth), this.encode(this.secret), sha256.sha256);
3583
3757
  headers = {
@@ -1231,9 +1231,10 @@ class htx extends htx$1 {
1231
1231
  async fetchStatus(params = {}) {
1232
1232
  await this.loadMarkets();
1233
1233
  let marketType = undefined;
1234
- [marketType, params] = this.handleMarketTypeAndParams('fetchMyTrades', undefined, params);
1234
+ [marketType, params] = this.handleMarketTypeAndParams('fetchStatus', undefined, params);
1235
+ const enabledForContracts = this.handleOption('fetchStatus', 'enableForContracts', false); // temp fix for: https://status-linear-swap.huobigroup.com/api/v2/summary.json
1235
1236
  let response = undefined;
1236
- if (marketType !== 'spot') {
1237
+ if (marketType !== 'spot' && enabledForContracts) {
1237
1238
  const subType = this.safeString(params, 'subType', this.options['defaultSubType']);
1238
1239
  if (marketType === 'swap') {
1239
1240
  if (subType === 'linear') {
@@ -1255,7 +1256,7 @@ class htx extends htx$1 {
1255
1256
  response = await this.contractPublicGetHeartbeat();
1256
1257
  }
1257
1258
  }
1258
- else {
1259
+ else if (marketType === 'spot') {
1259
1260
  response = await this.statusPublicSpotGetApiV2SummaryJson();
1260
1261
  }
1261
1262
  //
@@ -1424,7 +1425,12 @@ class htx extends htx$1 {
1424
1425
  let url = undefined;
1425
1426
  if (marketType === 'contract') {
1426
1427
  const statusRaw = this.safeString(response, 'status');
1427
- status = (statusRaw === 'ok') ? 'ok' : 'maintenance'; // 'ok', 'error'
1428
+ if (statusRaw === undefined) {
1429
+ status = undefined;
1430
+ }
1431
+ else {
1432
+ status = (statusRaw === 'ok') ? 'ok' : 'maintenance'; // 'ok', 'error'
1433
+ }
1428
1434
  updated = this.safeString(response, 'ts');
1429
1435
  }
1430
1436
  else {
@@ -38,9 +38,11 @@ class binance extends binance$1 {
38
38
  'fetchDepositsWs': false,
39
39
  'fetchMarketsWs': false,
40
40
  'fetchMyTradesWs': true,
41
+ 'fetchOHLCVWs': true,
41
42
  'fetchOpenOrdersWs': true,
42
43
  'fetchOrderWs': true,
43
44
  'fetchOrdersWs': true,
45
+ 'fetchTradesWs': true,
44
46
  'fetchTradingFeesWs': false,
45
47
  'fetchWithdrawalsWs': false,
46
48
  },
@@ -837,6 +839,94 @@ class binance extends binance$1 {
837
839
  stored.append(parsed);
838
840
  client.resolve(stored, messageHash);
839
841
  }
842
+ async fetchOHLCVWs(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
843
+ /**
844
+ * @method
845
+ * @name binance#fetchOHLCVWs
846
+ * @see https://binance-docs.github.io/apidocs/websocket_api/en/#klines
847
+ * @description query historical candlestick data containing the open, high, low, and close price, and the volume of a market
848
+ * @param {string} symbol unified symbol of the market to query OHLCV data for
849
+ * @param {string} timeframe the length of time each candle represents
850
+ * @param {int} since timestamp in ms of the earliest candle to fetch
851
+ * @param {int} limit the maximum amount of candles to fetch
852
+ * @param {object} params extra parameters specific to the exchange API endpoint
853
+ * @param {int} params.until timestamp in ms of the earliest candle to fetch
854
+ *
855
+ * EXCHANGE SPECIFIC PARAMETERS
856
+ * @param {string} params.timeZone default=0 (UTC)
857
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
858
+ */
859
+ await this.loadMarkets();
860
+ this.checkIsSpot('fetchOHLCVWs', symbol, params);
861
+ const url = this.urls['api']['ws']['ws'];
862
+ const requestId = this.requestId(url);
863
+ const messageHash = requestId.toString();
864
+ let returnRateLimits = false;
865
+ [returnRateLimits, params] = this.handleOptionAndParams(params, 'fetchOHLCVWs', 'returnRateLimits', false);
866
+ const payload = {
867
+ 'symbol': this.marketId(symbol),
868
+ 'returnRateLimits': returnRateLimits,
869
+ 'interval': this.timeframes[timeframe],
870
+ };
871
+ const until = this.safeInteger(params, 'until');
872
+ params = this.omit(params, 'until');
873
+ if (since !== undefined) {
874
+ payload['startTime'] = since;
875
+ }
876
+ if (limit !== undefined) {
877
+ payload['limit'] = limit;
878
+ }
879
+ if (until !== undefined) {
880
+ payload['endTime'] = until;
881
+ }
882
+ const message = {
883
+ 'id': messageHash,
884
+ 'method': 'klines',
885
+ 'params': this.extend(payload, params),
886
+ };
887
+ const subscription = {
888
+ 'method': this.handleFetchOHLCV,
889
+ };
890
+ return await this.watch(url, messageHash, message, messageHash, subscription);
891
+ }
892
+ handleFetchOHLCV(client, message) {
893
+ //
894
+ // {
895
+ // "id": "1dbbeb56-8eea-466a-8f6e-86bdcfa2fc0b",
896
+ // "status": 200,
897
+ // "result": [
898
+ // [
899
+ // 1655971200000, // Kline open time
900
+ // "0.01086000", // Open price
901
+ // "0.01086600", // High price
902
+ // "0.01083600", // Low price
903
+ // "0.01083800", // Close price
904
+ // "2290.53800000", // Volume
905
+ // 1655974799999, // Kline close time
906
+ // "24.85074442", // Quote asset volume
907
+ // 2283, // Number of trades
908
+ // "1171.64000000", // Taker buy base asset volume
909
+ // "12.71225884", // Taker buy quote asset volume
910
+ // "0" // Unused field, ignore
911
+ // ]
912
+ // ],
913
+ // "rateLimits": [
914
+ // {
915
+ // "rateLimitType": "REQUEST_WEIGHT",
916
+ // "interval": "MINUTE",
917
+ // "intervalNum": 1,
918
+ // "limit": 6000,
919
+ // "count": 2
920
+ // }
921
+ // ]
922
+ // }
923
+ //
924
+ const result = this.safeList(message, 'result');
925
+ const parsed = this.parseOHLCVs(result);
926
+ // use a reverse lookup in a static map instead
927
+ const messageHash = this.safeString(message, 'id');
928
+ client.resolve(parsed, messageHash);
929
+ }
840
930
  async watchTicker(symbol, params = {}) {
841
931
  /**
842
932
  * @method
@@ -2538,12 +2628,58 @@ class binance extends binance$1 {
2538
2628
  const trades = await this.watch(url, messageHash, message, messageHash, subscription);
2539
2629
  return this.filterBySymbolSinceLimit(trades, symbol, since, limit);
2540
2630
  }
2631
+ async fetchTradesWs(symbol = undefined, since = undefined, limit = undefined, params = {}) {
2632
+ /**
2633
+ * @method
2634
+ * @name binance#fetchTradesWs
2635
+ * @see https://binance-docs.github.io/apidocs/websocket_api/en/#recent-trades
2636
+ * @description fetch all trades made by the user
2637
+ * @param {string} symbol unified market symbol
2638
+ * @param {int} [since] the earliest time in ms to fetch trades for
2639
+ * @param {int} [limit] the maximum number of trades structures to retrieve, default=500, max=1000
2640
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2641
+ *
2642
+ * EXCHANGE SPECIFIC PARAMETERS
2643
+ * @param {int} [params.fromId] trade ID to begin at
2644
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
2645
+ */
2646
+ await this.loadMarkets();
2647
+ if (symbol === undefined) {
2648
+ throw new errors.BadRequest(this.id + ' fetchTradesWs () requires a symbol argument');
2649
+ }
2650
+ this.checkIsSpot('fetchTradesWs', symbol, params);
2651
+ const url = this.urls['api']['ws']['ws'];
2652
+ const requestId = this.requestId(url);
2653
+ const messageHash = requestId.toString();
2654
+ let returnRateLimits = false;
2655
+ [returnRateLimits, params] = this.handleOptionAndParams(params, 'fetchTradesWs', 'returnRateLimits', false);
2656
+ const payload = {
2657
+ 'symbol': this.marketId(symbol),
2658
+ 'returnRateLimits': returnRateLimits,
2659
+ };
2660
+ if (limit !== undefined) {
2661
+ payload['limit'] = limit;
2662
+ }
2663
+ const message = {
2664
+ 'id': messageHash,
2665
+ 'method': 'trades.historical',
2666
+ 'params': this.extend(payload, params),
2667
+ };
2668
+ const subscription = {
2669
+ 'method': this.handleTradesWs,
2670
+ };
2671
+ const trades = await this.watch(url, messageHash, message, messageHash, subscription);
2672
+ return this.filterBySinceLimit(trades, since, limit);
2673
+ }
2541
2674
  handleTradesWs(client, message) {
2675
+ //
2676
+ // fetchMyTradesWs
2542
2677
  //
2543
2678
  // {
2544
2679
  // "id": "f4ce6a53-a29d-4f70-823b-4ab59391d6e8",
2545
2680
  // "status": 200,
2546
- // "result": [{
2681
+ // "result": [
2682
+ // {
2547
2683
  // "symbol": "BTCUSDT",
2548
2684
  // "id": 1650422481,
2549
2685
  // "orderId": 12569099453,
@@ -2562,6 +2698,25 @@ class binance extends binance$1 {
2562
2698
  // ],
2563
2699
  // }
2564
2700
  //
2701
+ // fetchTradesWs
2702
+ //
2703
+ // {
2704
+ // "id": "f4ce6a53-a29d-4f70-823b-4ab59391d6e8",
2705
+ // "status": 200,
2706
+ // "result": [
2707
+ // {
2708
+ // "id": 0,
2709
+ // "price": "0.00005000",
2710
+ // "qty": "40.00000000",
2711
+ // "quoteQty": "0.00200000",
2712
+ // "time": 1500004800376,
2713
+ // "isBuyerMaker": true,
2714
+ // "isBestMatch": true
2715
+ // }
2716
+ // ...
2717
+ // ],
2718
+ // }
2719
+ //
2565
2720
  const messageHash = this.safeString(message, 'id');
2566
2721
  const result = this.safeValue(message, 'result', []);
2567
2722
  const trades = this.parseTrades(result);
@@ -320,7 +320,9 @@ class bitfinex2 extends bitfinex2$1 {
320
320
  const messageLength = message.length;
321
321
  if (messageLength === 2) {
322
322
  // initial snapshot
323
- const trades = this.safeValue(message, 1, []);
323
+ let trades = this.safeList(message, 1, []);
324
+ // needs to be reversed to make chronological order
325
+ trades = trades.reverse();
324
326
  for (let i = 0; i < trades.length; i++) {
325
327
  const parsed = this.parseWsTrade(trades[i], market);
326
328
  stored.append(parsed);
@@ -102,7 +102,7 @@ class bitvavo extends bitvavo$1 {
102
102
  // "volume": "3587.05020246",
103
103
  // "volumeQuote": "708030.17",
104
104
  // "bid": "199.56",
105
- // "bidSize": "4.14730803",
105
+ // "bidSize": "4.14730802",
106
106
  // "ask": "199.57",
107
107
  // "askSize": "6.13642074",
108
108
  // "timestamp": 1590770885217
@@ -34,7 +34,6 @@ class blockchaincom extends blockchaincom$1 {
34
34
  },
35
35
  'noOriginHeader': false,
36
36
  },
37
- 'sequenceNumbers': {},
38
37
  },
39
38
  'streaming': {},
40
39
  'exceptions': {},
@@ -678,21 +677,20 @@ class blockchaincom extends blockchaincom$1 {
678
677
  // }
679
678
  //
680
679
  const event = this.safeString(message, 'event');
680
+ if (event === 'subscribed') {
681
+ return;
682
+ }
681
683
  const type = this.safeString(message, 'channel');
682
684
  const marketId = this.safeString(message, 'symbol');
683
685
  const symbol = this.safeSymbol(marketId);
684
686
  const messageHash = 'orderbook:' + symbol + ':' + type;
685
687
  const datetime = this.safeString(message, 'timestamp');
686
688
  const timestamp = this.parse8601(datetime);
687
- let orderbook = this.safeValue(this.orderbooks, symbol);
688
- if (orderbook === undefined) {
689
- orderbook = this.countedOrderBook({});
690
- this.orderbooks[symbol] = orderbook;
691
- }
692
- if (event === 'subscribed') {
693
- return;
689
+ if (this.safeValue(this.orderbooks, symbol) === undefined) {
690
+ this.orderbooks[symbol] = this.countedOrderBook();
694
691
  }
695
- else if (event === 'snapshot') {
692
+ const orderbook = this.orderbooks[symbol];
693
+ if (event === 'snapshot') {
696
694
  const snapshot = this.parseOrderBook(message, symbol, timestamp, 'bids', 'asks', 'px', 'qty', 'num');
697
695
  orderbook.reset(snapshot);
698
696
  }
@@ -718,23 +716,7 @@ class blockchaincom extends blockchaincom$1 {
718
716
  this.handleDelta(bookside, deltas[i]);
719
717
  }
720
718
  }
721
- checkSequenceNumber(client, message) {
722
- const seqnum = this.safeInteger(message, 'seqnum', 0);
723
- const channel = this.safeString(message, 'channel', '');
724
- const sequenceNumbersByChannel = this.safeValue(this.options, 'sequenceNumbers', {});
725
- const lastSeqnum = this.safeInteger(sequenceNumbersByChannel, channel);
726
- if (lastSeqnum === undefined) {
727
- this.options['sequenceNumbers'][channel] = seqnum;
728
- }
729
- else {
730
- if (seqnum !== lastSeqnum + 1) {
731
- throw new errors.ExchangeError(this.id + ' ' + channel + ' seqnum ' + seqnum + ' is not the expected ' + (lastSeqnum + 1));
732
- }
733
- this.options['sequenceNumbers'][channel] = seqnum;
734
- }
735
- }
736
719
  handleMessage(client, message) {
737
- this.checkSequenceNumber(client, message);
738
720
  const channel = this.safeString(message, 'channel');
739
721
  const handlers = {
740
722
  'ticker': this.handleTicker,
@@ -177,7 +177,7 @@ class deribit extends deribit$1 {
177
177
  // "params": {
178
178
  // "channel": "ticker.BTC_USDC-PERPETUAL.raw",
179
179
  // "data": {
180
- // "timestamp": 1655393725041,
180
+ // "timestamp": 1655393725040,
181
181
  // "stats": [Object],
182
182
  // "state": "open",
183
183
  // "settlement_price": 21729.5891,
@@ -658,7 +658,7 @@ class deribit extends deribit$1 {
658
658
  const symbol = this.safeSymbol(marketId);
659
659
  const ohlcv = this.safeValue(params, 'data', {});
660
660
  const parsed = [
661
- this.safeNumber(ohlcv, 'tick'),
661
+ this.safeInteger(ohlcv, 'tick'),
662
662
  this.safeNumber(ohlcv, 'open'),
663
663
  this.safeNumber(ohlcv, 'high'),
664
664
  this.safeNumber(ohlcv, 'low'),
@@ -383,8 +383,9 @@ class gate extends gate$1 {
383
383
  const parts = channel.split('.');
384
384
  const rawMarketType = this.safeString(parts, 0);
385
385
  const marketType = (rawMarketType === 'futures') ? 'contract' : 'spot';
386
+ const result = this.safeValue(message, 'result');
386
387
  let results = [];
387
- if (marketType === 'contract') {
388
+ if (Array.isArray(result)) {
388
389
  results = this.safeList(message, 'result', []);
389
390
  }
390
391
  else {
@@ -203,7 +203,7 @@ class gemini extends gemini$1 {
203
203
  // "time_ms": 1655323185000,
204
204
  // "result": "failure",
205
205
  // "highest_bid_price": "21661.90",
206
- // "lowest_ask_price": "21663.79",
206
+ // "lowest_ask_price": "21663.78",
207
207
  // "collar_price": "21662.845"
208
208
  // },
209
209
  // ]
@@ -907,9 +907,6 @@ class okx extends okx$1 {
907
907
  * @param {object} params extra parameters specific to the exchange API endpoint
908
908
  * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
909
909
  */
910
- if (this.isEmpty(symbols)) {
911
- throw new errors.ArgumentsRequired(this.id + ' watchPositions requires a list of symbols');
912
- }
913
910
  await this.loadMarkets();
914
911
  await this.authenticate(params);
915
912
  symbols = this.marketSymbols(symbols);
@@ -917,7 +914,23 @@ class okx extends okx$1 {
917
914
  'instType': 'ANY',
918
915
  };
919
916
  const channel = 'positions';
920
- const newPositions = await this.subscribeMultiple('private', channel, symbols, this.extend(request, params));
917
+ let newPositions = undefined;
918
+ if (symbols === undefined) {
919
+ const arg = {
920
+ 'channel': 'positions',
921
+ 'instType': 'ANY',
922
+ };
923
+ const args = [arg];
924
+ const nonSymbolRequest = {
925
+ 'op': 'subscribe',
926
+ 'args': args,
927
+ };
928
+ const url = this.getUrl(channel, 'private');
929
+ newPositions = await this.watch(url, channel, nonSymbolRequest, channel);
930
+ }
931
+ else {
932
+ newPositions = await this.subscribeMultiple('private', channel, symbols, this.extend(request, params));
933
+ }
921
934
  if (this.newUpdates) {
922
935
  return newPositions;
923
936
  }
@@ -1015,6 +1028,7 @@ class okx extends okx$1 {
1015
1028
  client.resolve(positions, messageHash);
1016
1029
  }
1017
1030
  }
1031
+ client.resolve(newPositions, channel);
1018
1032
  }
1019
1033
  async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1020
1034
  /**