ccxt 4.5.46 → 4.5.47

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 (63) hide show
  1. package/README.md +5 -6
  2. package/dist/ccxt.browser.min.js +3 -3
  3. package/dist/cjs/ccxt.js +1 -6
  4. package/dist/cjs/src/aftermath.js +1 -1
  5. package/dist/cjs/src/backpack.js +1 -1
  6. package/dist/cjs/src/base/Exchange.js +24 -0
  7. package/dist/cjs/src/binance.js +12 -15
  8. package/dist/cjs/src/bitfinex.js +6 -11
  9. package/dist/cjs/src/bitget.js +6 -3
  10. package/dist/cjs/src/bitmex.js +46 -0
  11. package/dist/cjs/src/bitstamp.js +14 -1
  12. package/dist/cjs/src/bittrade.js +1 -1
  13. package/dist/cjs/src/blofin.js +137 -29
  14. package/dist/cjs/src/hollaex.js +1 -1
  15. package/dist/cjs/src/kraken.js +39 -31
  16. package/dist/cjs/src/kucoin.js +2158 -461
  17. package/dist/cjs/src/lighter.js +2 -2
  18. package/dist/cjs/src/okx.js +0 -1
  19. package/dist/cjs/src/pro/bittrade.js +4 -0
  20. package/dist/cjs/src/pro/grvt.js +1 -1
  21. package/dist/cjs/src/pro/lighter.js +1 -1
  22. package/dist/cjs/src/whitebit.js +21 -2
  23. package/js/ccxt.d.ts +2 -8
  24. package/js/ccxt.js +2 -6
  25. package/js/src/abstract/blofin.d.ts +28 -12
  26. package/js/src/abstract/kraken.d.ts +36 -30
  27. package/js/src/abstract/kucoin.d.ts +1 -0
  28. package/js/src/abstract/kucoinfutures.d.ts +1 -0
  29. package/js/src/aftermath.js +1 -1
  30. package/js/src/backpack.js +1 -1
  31. package/js/src/base/Exchange.d.ts +1 -0
  32. package/js/src/base/Exchange.js +24 -0
  33. package/js/src/binance.js +12 -15
  34. package/js/src/bitfinex.js +6 -11
  35. package/js/src/bitget.d.ts +1 -1
  36. package/js/src/bitget.js +6 -3
  37. package/js/src/bitmex.d.ts +12 -0
  38. package/js/src/bitmex.js +46 -0
  39. package/js/src/bitstamp.js +14 -1
  40. package/js/src/bittrade.js +1 -1
  41. package/js/src/blofin.d.ts +2 -0
  42. package/js/src/blofin.js +137 -29
  43. package/js/src/hollaex.js +1 -1
  44. package/js/src/kraken.js +39 -31
  45. package/js/src/kucoin.d.ts +249 -8
  46. package/js/src/kucoin.js +2158 -461
  47. package/js/src/lighter.js +2 -2
  48. package/js/src/okx.js +0 -1
  49. package/js/src/pro/bittrade.js +4 -0
  50. package/js/src/pro/grvt.js +1 -1
  51. package/js/src/pro/lighter.js +1 -1
  52. package/js/src/whitebit.d.ts +1 -1
  53. package/js/src/whitebit.js +21 -2
  54. package/package.json +1 -1
  55. package/dist/cjs/src/abstract/coincatch.js +0 -11
  56. package/dist/cjs/src/coincatch.js +0 -5495
  57. package/dist/cjs/src/pro/coincatch.js +0 -1563
  58. package/js/src/abstract/coincatch.d.ts +0 -97
  59. package/js/src/abstract/coincatch.js +0 -5
  60. package/js/src/coincatch.d.ts +0 -788
  61. package/js/src/coincatch.js +0 -5488
  62. package/js/src/pro/coincatch.d.ts +0 -207
  63. package/js/src/pro/coincatch.js +0 -1556
package/dist/cjs/ccxt.js CHANGED
@@ -51,7 +51,6 @@ var coinbase = require('./src/coinbase.js');
51
51
  var coinbaseadvanced = require('./src/coinbaseadvanced.js');
52
52
  var coinbaseexchange = require('./src/coinbaseexchange.js');
53
53
  var coinbaseinternational = require('./src/coinbaseinternational.js');
54
- var coincatch = require('./src/coincatch.js');
55
54
  var coincheck = require('./src/coincheck.js');
56
55
  var coinex = require('./src/coinex.js');
57
56
  var coinmate = require('./src/coinmate.js');
@@ -151,7 +150,6 @@ var coinbase$1 = require('./src/pro/coinbase.js');
151
150
  var coinbaseadvanced$1 = require('./src/pro/coinbaseadvanced.js');
152
151
  var coinbaseexchange$1 = require('./src/pro/coinbaseexchange.js');
153
152
  var coinbaseinternational$1 = require('./src/pro/coinbaseinternational.js');
154
- var coincatch$1 = require('./src/pro/coincatch.js');
155
153
  var coincheck$1 = require('./src/pro/coincheck.js');
156
154
  var coinex$1 = require('./src/pro/coinex.js');
157
155
  var coinone$1 = require('./src/pro/coinone.js');
@@ -200,7 +198,7 @@ var xt$1 = require('./src/pro/xt.js');
200
198
 
201
199
  //-----------------------------------------------------------------------------
202
200
  // this is updated by vss.js when building
203
- const version = '4.5.46';
201
+ const version = '4.5.47';
204
202
  Exchange["default"].ccxtVersion = version;
205
203
  const exchanges = {
206
204
  'aftermath': aftermath["default"],
@@ -246,7 +244,6 @@ const exchanges = {
246
244
  'coinbaseadvanced': coinbaseadvanced["default"],
247
245
  'coinbaseexchange': coinbaseexchange["default"],
248
246
  'coinbaseinternational': coinbaseinternational["default"],
249
- 'coincatch': coincatch["default"],
250
247
  'coincheck': coincheck["default"],
251
248
  'coinex': coinex["default"],
252
249
  'coinmate': coinmate["default"],
@@ -348,7 +345,6 @@ const pro = {
348
345
  'coinbaseadvanced': coinbaseadvanced$1["default"],
349
346
  'coinbaseexchange': coinbaseexchange$1["default"],
350
347
  'coinbaseinternational': coinbaseinternational$1["default"],
351
- 'coincatch': coincatch$1["default"],
352
348
  'coincheck': coincheck$1["default"],
353
349
  'coinex': coinex$1["default"],
354
350
  'coinone': coinone$1["default"],
@@ -489,7 +485,6 @@ exports.coinbase = coinbase["default"];
489
485
  exports.coinbaseadvanced = coinbaseadvanced["default"];
490
486
  exports.coinbaseexchange = coinbaseexchange["default"];
491
487
  exports.coinbaseinternational = coinbaseinternational["default"];
492
- exports.coincatch = coincatch["default"];
493
488
  exports.coincheck = coincheck["default"];
494
489
  exports.coinex = coinex["default"];
495
490
  exports.coinmate = coinmate["default"];
@@ -655,7 +655,7 @@ class aftermath extends aftermath$1["default"] {
655
655
  //
656
656
  // [
657
657
  // {
658
- // "id": "0x21c5e3d2f5bcfd4351a62cd70874878b7923b56d79d04225ed96370a7ac844c4",
658
+ // "id": "0x22c5e3d2f5bcfd4351a62cd70874878b7923b56d79d04225ed96370a7ac844c4",
659
659
  // "type": "primary",
660
660
  // "code": "USDC",
661
661
  // "accountNumber": 14822
@@ -469,7 +469,7 @@ class backpack extends backpack$1["default"] {
469
469
  'INSUFFICIENT_SUPPLY': errors.InsufficientFunds,
470
470
  'INVALID_ASSET': errors.BadRequest,
471
471
  'INVALID_MARKET': errors.BadSymbol,
472
- 'INVALID_PRICE': errors.BadRequest,
472
+ 'INVALID_PRICE': errors.InvalidOrder,
473
473
  'INVALID_POSITION_ID': errors.BadRequest,
474
474
  'INVALID_QUANTITY': errors.BadRequest,
475
475
  'INVALID_RANGE': errors.BadRequest,
@@ -5023,6 +5023,30 @@ class Exchange {
5023
5023
  }
5024
5024
  return results;
5025
5025
  }
5026
+ filterOutByArray(objects, key, values = undefined, indexed = true) {
5027
+ objects = this.toArray(objects);
5028
+ // return all of them if no values were passed
5029
+ if (values === undefined || !values) {
5030
+ // return indexed ? this.indexBy (objects, key) : objects;
5031
+ if (indexed) {
5032
+ return this.indexBy(objects, key);
5033
+ }
5034
+ else {
5035
+ return objects;
5036
+ }
5037
+ }
5038
+ const results = [];
5039
+ for (let i = 0; i < objects.length; i++) {
5040
+ if (!this.inArray(objects[i][key], values)) {
5041
+ results.push(objects[i]);
5042
+ }
5043
+ }
5044
+ // return indexed ? this.indexBy (results, key) : results;
5045
+ if (indexed) {
5046
+ return this.indexBy(results, key);
5047
+ }
5048
+ return results;
5049
+ }
5026
5050
  async fetch2(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined, config = {}) {
5027
5051
  if (this.enableRateLimit) {
5028
5052
  const cost = this.calculateRateLimiterCost(api, method, path, params, config);
@@ -3076,7 +3076,7 @@ class binance extends binance$1["default"] {
3076
3076
  for (let j = 0; j < networkList.length; j++) {
3077
3077
  const networkItem = networkList[j];
3078
3078
  const network = this.safeString(networkItem, 'network');
3079
- const networkCode = this.networkIdToCode(network);
3079
+ const networkCode = this.networkIdToCode(network, code);
3080
3080
  const isETF = (network === 'ETF'); // e.g. BTCUP, ETHDOWN
3081
3081
  // const name = this.safeString (networkItem, 'name');
3082
3082
  const withdrawFee = this.safeNumber(networkItem, 'withdrawFee');
@@ -9400,12 +9400,10 @@ class binance extends binance$1["default"] {
9400
9400
  'coin': currency['id'],
9401
9401
  // 'network': 'ETH', // 'BSC', 'XMR', you can get network and isDefault in networkList in the response of sapiGetCapitalConfigDetail
9402
9402
  };
9403
- const networks = this.safeDict(this.options, 'networks', {});
9404
- let network = this.safeStringUpper(params, 'network'); // this line allows the user to specify either ERC20 or ETH
9405
- network = this.safeString(networks, network, network); // handle ERC20>ETH alias
9406
- if (network !== undefined) {
9407
- request['network'] = network;
9408
- params = this.omit(params, 'network');
9403
+ let networkCode = undefined;
9404
+ [networkCode, params] = this.handleNetworkCodeAndParams(params);
9405
+ if (networkCode !== undefined) {
9406
+ request['network'] = this.networkCodeToId(networkCode, currency['code']);
9409
9407
  }
9410
9408
  // has support for the 'network' parameter
9411
9409
  const response = await this.sapiGetCapitalDepositAddress(this.extend(request, params));
@@ -9665,12 +9663,13 @@ class binance extends binance$1["default"] {
9665
9663
  // ]
9666
9664
  // }
9667
9665
  //
9666
+ const code = this.safeString(currency, 'code');
9668
9667
  const networkList = this.safeList(fee, 'networkList', []);
9669
9668
  const result = this.depositWithdrawFee(fee);
9670
9669
  for (let j = 0; j < networkList.length; j++) {
9671
9670
  const networkEntry = networkList[j];
9672
9671
  const networkId = this.safeString(networkEntry, 'network');
9673
- const networkCode = this.networkIdToCode(networkId);
9672
+ const networkCode = this.networkIdToCode(networkId, code);
9674
9673
  const withdrawFee = this.safeNumber(networkEntry, 'withdrawFee');
9675
9674
  const isDefault = this.safeBool(networkEntry, 'isDefault');
9676
9675
  if (isDefault === true) {
@@ -9718,14 +9717,12 @@ class binance extends binance$1["default"] {
9718
9717
  if (tag !== undefined) {
9719
9718
  request['addressTag'] = tag;
9720
9719
  }
9721
- const networks = this.safeDict(this.options, 'networks', {});
9722
- let network = this.safeStringUpper(params, 'network'); // this line allows the user to specify either ERC20 or ETH
9723
- network = this.safeString(networks, network, network); // handle ERC20>ETH alias
9724
- if (network !== undefined) {
9725
- request['network'] = network;
9726
- params = this.omit(params, 'network');
9720
+ let networkCode = undefined;
9721
+ [networkCode, params] = this.handleNetworkCodeAndParams(params);
9722
+ if (networkCode !== undefined) {
9723
+ request['network'] = this.networkCodeToId(networkCode, currency['code']);
9727
9724
  }
9728
- request['amount'] = this.currencyToPrecision(code, amount, network);
9725
+ request['amount'] = this.currencyToPrecision(currency['code'], amount, networkCode);
9729
9726
  const response = await this.sapiPostCapitalWithdrawApply(this.extend(request, params));
9730
9727
  // { id: '9a67628b16ba4988ae20d329333f16bc' }
9731
9728
  return this.parseTransaction(response, currency);
@@ -870,30 +870,25 @@ class bitfinex extends bitfinex$1["default"] {
870
870
  const pool = this.safeList(indexed['pool'], id, []);
871
871
  const rawType = this.safeString(pool, 1);
872
872
  const isCryptoCoin = (rawType !== undefined) || (id in indexed['explorer']); // "hacky" solution
873
- let type = undefined;
874
- if (isCryptoCoin) {
875
- type = 'crypto';
876
- }
873
+ const type = isCryptoCoin ? 'crypto' : undefined;
877
874
  const feeValues = this.safeList(indexed['fees'], id, []);
878
875
  const fees = this.safeList(feeValues, 1, []);
879
876
  const fee = this.safeNumber(fees, 1);
880
877
  const undl = this.safeList(indexed['undl'], id, []);
881
878
  const precision = '8'; // default precision, todo: fix "magic constants"
882
- const dwStatuses = this.safeList(indexed['statuses'], id, []);
883
- const depositEnabled = this.safeInteger(dwStatuses, 1) === 1;
884
- const withdrawEnabled = this.safeInteger(dwStatuses, 2) === 1;
885
879
  const networks = {};
886
880
  const netwokIds = this.safeList(indexedNetworks, id, []);
887
881
  for (let j = 0; j < netwokIds.length; j++) {
888
882
  const networkId = netwokIds[j];
889
883
  const network = this.networkIdToCode(networkId);
884
+ const dwStatuses = this.safeList(indexed['statuses'], networkId, []);
890
885
  networks[network] = {
891
886
  'info': networkId,
892
887
  'id': networkId.toLowerCase(),
893
888
  'network': networkId,
894
889
  'active': undefined,
895
- 'deposit': undefined,
896
- 'withdraw': undefined,
890
+ 'deposit': this.safeInteger(dwStatuses, 1) === 1,
891
+ 'withdraw': this.safeInteger(dwStatuses, 2) === 1,
897
892
  'fee': undefined,
898
893
  'precision': undefined,
899
894
  'limits': {
@@ -911,8 +906,8 @@ class bitfinex extends bitfinex$1["default"] {
911
906
  'type': type,
912
907
  'name': name,
913
908
  'active': true,
914
- 'deposit': depositEnabled,
915
- 'withdraw': withdrawEnabled,
909
+ 'deposit': undefined,
910
+ 'withdraw': undefined,
916
911
  'fee': fee,
917
912
  'precision': parseInt(precision),
918
913
  'limits': {
@@ -5109,7 +5109,7 @@ class bitget extends bitget$1["default"] {
5109
5109
  * @param {string} type 'market' or 'limit'
5110
5110
  * @param {string} side 'buy' or 'sell'
5111
5111
  * @param {float} amount how much you want to trade in units of the base currency
5112
- * @param {float} [price] the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
5112
+ * @param {float} [price] the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders, and used as the execution price for contract stop-loss / take-profit orders
5113
5113
  * @param {object} [params] extra parameters specific to the exchange API endpoint
5114
5114
  * @param {float} [params.cost] *spot only* how much you want to trade in units of the quote currency, for market buy orders only
5115
5115
  * @param {float} [params.triggerPrice] *swap only* The price at which a trigger order is triggered at
@@ -5440,8 +5440,11 @@ class bitget extends bitget$1["default"] {
5440
5440
  }
5441
5441
  }
5442
5442
  else if (isStopLossOrTakeProfitTrigger) {
5443
- if (!isMarketOrder) {
5444
- throw new errors.ExchangeError(this.id + ' createOrder() bitget stopLoss or takeProfit orders must be market orders');
5443
+ if (price !== undefined) {
5444
+ request['executePrice'] = this.priceToPrecision(symbol, price);
5445
+ if ('price' in request) {
5446
+ delete request['price'];
5447
+ }
5445
5448
  }
5446
5449
  if (hedged) {
5447
5450
  request['holdSide'] = (side === 'sell') ? 'long' : 'short';
@@ -3479,6 +3479,52 @@ class bitmex extends bitmex$1["default"] {
3479
3479
  'datetime': datetime,
3480
3480
  };
3481
3481
  }
3482
+ /**
3483
+ * @method
3484
+ * @name bitmex#closePosition
3485
+ * @description closes open positions for a market
3486
+ * @see https://docs.bitmex.com/api-explorer/order-new
3487
+ * @see https://docs.bitmex.com/api-explorer/order-close-position
3488
+ * @param {string} symbol Unified CCXT market symbol
3489
+ * @param {string} side the buy or sell side of the closing order, if the position is long set the side to sell, reduceOnly is implied
3490
+ * @param {object} [params] extra parameters specific to the bingx api endpoint
3491
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/?id=order-structure}
3492
+ */
3493
+ async closePosition(symbol, side = undefined, params = {}) {
3494
+ await this.loadMarkets();
3495
+ const market = this.market(symbol);
3496
+ const request = {
3497
+ 'symbol': market['id'],
3498
+ 'side': this.capitalize(side),
3499
+ 'execInst': 'Close',
3500
+ };
3501
+ const response = await this.privatePostOrder(this.extend(request, params));
3502
+ //
3503
+ // {
3504
+ // "account": 395724,
3505
+ // "avgPx": 66358.8,
3506
+ // "cumQty": 200,
3507
+ // "currency": "USDT",
3508
+ // "execInst": "Close",
3509
+ // "leavesQty": 0,
3510
+ // "ordStatus": "Filled",
3511
+ // "ordType": "Market",
3512
+ // "orderID": "4e1ef998-33c1-4736-b58b-9d8b4d085c49",
3513
+ // "orderQty": 200,
3514
+ // "pool": "Primary",
3515
+ // "settlCurrency": "USDt",
3516
+ // "side": "Sell",
3517
+ // "strategy": "OneWay",
3518
+ // "symbol": "XBTUSDT",
3519
+ // "text": "Submitted via API.",
3520
+ // "timeInForce": "ImmediateOrCancel",
3521
+ // "timestamp": "2026-04-02T05:20:26.607Z",
3522
+ // "transactTime": "2026-04-02T05:20:26.606Z",
3523
+ // "workingIndicator": false
3524
+ // }
3525
+ //
3526
+ return this.parseOrder(response, market);
3527
+ }
3482
3528
  handleErrors(code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
3483
3529
  if (response === undefined) {
3484
3530
  return undefined;
@@ -524,7 +524,6 @@ class bitstamp extends bitstamp$1["default"] {
524
524
  'Your account is frozen': errors.PermissionDenied,
525
525
  'Please update your profile with your FATCA information, before using API.': errors.PermissionDenied,
526
526
  'Order not found.': errors.OrderNotFound,
527
- 'Price is more than 20% below market price.': errors.InvalidOrder,
528
527
  "Bitstamp.net is under scheduled maintenance. We'll be back soon.": errors.OnMaintenance,
529
528
  'Order could not be placed.': errors.ExchangeNotAvailable,
530
529
  'Invalid offset.': errors.BadRequest,
@@ -532,6 +531,7 @@ class bitstamp extends bitstamp$1["default"] {
532
531
  },
533
532
  'broad': {
534
533
  'Minimum order size is': errors.InvalidOrder,
534
+ 'Price is more than': errors.InvalidOrder,
535
535
  'Check your account balance for details.': errors.InsufficientFunds,
536
536
  'Ensure this value has at least': errors.InvalidAddress,
537
537
  'Ensure that there are no more than': errors.InvalidOrder, // {"status": "error", "reason": {"amount": ["Ensure that there are no more than 0 decimal places."], "__all__": [""]}}
@@ -1137,6 +1137,19 @@ class bitstamp extends bitstamp$1["default"] {
1137
1137
  priceString = this.safeString(trade, priceId, priceString);
1138
1138
  amountString = this.safeString(trade, market['baseId'], amountString);
1139
1139
  costString = this.safeString(trade, market['quoteId'], costString);
1140
+ // this endpoint is not aligned with "markets" endpoint
1141
+ const baseIdLower = market['baseId'].toLowerCase();
1142
+ const quoteIdLower = market['quoteId'].toLowerCase();
1143
+ const dashedIdLower = baseIdLower + '_' + quoteIdLower;
1144
+ if (priceString === undefined) {
1145
+ priceString = this.safeString(trade, dashedIdLower);
1146
+ }
1147
+ if (amountString === undefined) {
1148
+ amountString = this.safeString(trade, baseIdLower);
1149
+ }
1150
+ if (costString === undefined) {
1151
+ costString = this.safeString(trade, quoteIdLower);
1152
+ }
1140
1153
  symbol = market['symbol'];
1141
1154
  const datetimeString = this.safeString2(trade, 'date', 'datetime');
1142
1155
  let timestamp = undefined;
@@ -1217,7 +1217,7 @@ class bittrade extends bittrade$1["default"] {
1217
1217
  const response = await this[method](this.extend(request, params));
1218
1218
  //
1219
1219
  // { "status": "ok",
1220
- // "data": [ { id: 13997833014,
1220
+ // "data": [ { id: 13997833015,
1221
1221
  // "symbol": "ethbtc",
1222
1222
  // "account-id": 3398321,
1223
1223
  // "amount": "0.045000000000000000",
@@ -180,35 +180,52 @@ class blofin extends blofin$1["default"] {
180
180
  'market/tickers': 1,
181
181
  'market/books': 1,
182
182
  'market/trades': 1,
183
- 'market/candles': 1,
184
183
  'market/mark-price': 1,
185
184
  'market/funding-rate': 1,
186
185
  'market/funding-rate-history': 1,
186
+ 'market/candles': 1,
187
+ 'market/index-candles': 1,
188
+ 'market/mark-price-candles': 1,
189
+ 'market/position-tiers': 1,
187
190
  },
188
191
  },
189
192
  'private': {
190
193
  'get': {
194
+ // account
191
195
  'asset/balances': 1,
192
- 'trade/orders-pending': 1,
193
- 'trade/fills-history': 1,
194
- 'asset/deposit-history': 1,
195
- 'asset/withdrawal-history': 1,
196
196
  'asset/bills': 1,
197
+ 'asset/withdrawal-history': 1,
198
+ 'asset/deposit-history': 1,
199
+ 'account/config': 1,
200
+ 'asset/currencies': 1,
201
+ // trading
197
202
  'account/balance': 1,
198
203
  'account/positions': 1,
199
- 'account/leverage-info': 1,
204
+ 'account/positions-history': 1,
200
205
  'account/margin-mode': 1,
201
206
  'account/position-mode': 1,
207
+ 'account/leverage-info': 1,
202
208
  'account/batch-leverage-info': 1,
209
+ 'trade/orders-pending': 1,
210
+ 'trade/order-detail': 1,
203
211
  'trade/orders-tpsl-pending': 1,
212
+ 'trade/order-tpsl-detail': 1,
204
213
  'trade/orders-algo-pending': 1,
205
214
  'trade/orders-history': 1,
206
215
  'trade/orders-tpsl-history': 1,
207
216
  'trade/orders-algo-history': 1,
217
+ 'trade/fills-history': 1,
208
218
  'trade/order/price-range': 1,
209
- 'user/query-apikey': 1,
219
+ // affiliate
210
220
  'affiliate/basic': 1,
221
+ 'affiliate/referral-code': 1,
222
+ 'affiliate/invitees': 1,
223
+ 'affiliate/sub-invitees': 1,
224
+ 'affiliate/sub-affiliates': 1,
225
+ 'affiliate/invitees/daily/info': 1,
226
+ // copy trading
211
227
  'copytrading/instruments': 1,
228
+ 'copytrading/config': 1,
212
229
  'copytrading/account/balance': 1,
213
230
  'copytrading/account/positions-by-order': 1,
214
231
  'copytrading/account/positions-details-by-order': 1,
@@ -220,21 +237,29 @@ class blofin extends blofin$1["default"] {
220
237
  'copytrading/trade/position-history-by-order': 1,
221
238
  'copytrading/trade/orders-history': 1,
222
239
  'copytrading/trade/pending-tpsl-by-order': 1,
240
+ // user
241
+ 'user/query-apikey': 1,
242
+ // tax
243
+ 'spot/trade/fills-history': 1,
223
244
  },
224
245
  'post': {
246
+ // account
247
+ 'asset/transfer': 1,
248
+ 'asset/demo-apply-money': 1,
249
+ // trading
225
250
  'account/set-margin-mode': 1,
226
251
  'account/set-position-mode': 1,
227
- 'trade/order': 1,
228
- 'trade/order-algo': 1,
229
- 'trade/cancel-order': 1,
230
- 'trade/cancel-algo': 1,
231
252
  'account/set-leverage': 1,
253
+ 'trade/order': 1,
232
254
  'trade/batch-orders': 1,
233
255
  'trade/order-tpsl': 1,
256
+ 'trade/order-algo': 1,
257
+ 'trade/cancel-order': 1,
234
258
  'trade/cancel-batch-orders': 1,
235
259
  'trade/cancel-tpsl': 1,
260
+ 'trade/cancel-algo': 1,
236
261
  'trade/close-position': 1,
237
- 'asset/transfer': 1,
262
+ // copy trading
238
263
  'copytrading/account/set-position-mode': 1,
239
264
  'copytrading/account/set-leverage': 1,
240
265
  'copytrading/trade/place-order': 1,
@@ -766,6 +791,21 @@ class blofin extends blofin$1["default"] {
766
791
  // "brokerId": ""
767
792
  // }
768
793
  //
794
+ // fetchMyTrades spot
795
+ // {
796
+ // "instId": "DOGE-USDT",
797
+ // "tradeId": "6000001623870",
798
+ // "orderId": "6000011777113",
799
+ // "fillPrice": "0.091480000000000000",
800
+ // "fillSize": "30.000000000000000000",
801
+ // "fillPnl": null,
802
+ // "side": "buy",
803
+ // "fee": "0.030000000000000000",
804
+ // "ts": "1775213753407",
805
+ // "brokerId": null,
806
+ // "feeCurrency": "base_currency"
807
+ // }
808
+ //
769
809
  const id = this.safeString(trade, 'tradeId');
770
810
  const marketId = this.safeString(trade, 'instId');
771
811
  market = this.safeMarket(marketId, market, '-');
@@ -777,27 +817,63 @@ class blofin extends blofin$1["default"] {
777
817
  const orderId = this.safeString(trade, 'orderId');
778
818
  const feeCost = this.safeString(trade, 'fee');
779
819
  let fee = undefined;
820
+ let feeCurrency = this.safeString(trade, 'feeCurrency');
821
+ const isSpot = feeCurrency !== undefined;
822
+ if (feeCurrency === undefined) {
823
+ feeCurrency = market['settle'];
824
+ }
825
+ else if (feeCurrency === 'base_currency') {
826
+ feeCurrency = market['base'];
827
+ }
828
+ else if (feeCurrency === 'quote_currency') {
829
+ feeCurrency = market['quote'];
830
+ }
780
831
  if (feeCost !== undefined) {
781
832
  fee = {
782
833
  'cost': feeCost,
783
- 'currency': market['settle'],
834
+ 'currency': feeCurrency,
784
835
  };
785
836
  }
786
- return this.safeTrade({
787
- 'info': trade,
788
- 'timestamp': timestamp,
789
- 'datetime': this.iso8601(timestamp),
790
- 'symbol': symbol,
791
- 'id': id,
792
- 'order': orderId,
793
- 'type': undefined,
794
- 'takerOrMaker': undefined,
795
- 'side': side,
796
- 'price': price,
797
- 'amount': amount,
798
- 'cost': undefined,
799
- 'fee': fee,
800
- }, market);
837
+ if (isSpot) {
838
+ const spotSymbol = market['base'] + '/' + market['quote'];
839
+ const cost = this.parseNumber(Precise["default"].stringMul(price, amount));
840
+ const result = {
841
+ 'info': trade,
842
+ 'timestamp': timestamp,
843
+ 'datetime': this.iso8601(timestamp),
844
+ 'symbol': spotSymbol,
845
+ 'id': id,
846
+ 'order': orderId,
847
+ 'type': undefined,
848
+ 'takerOrMaker': undefined,
849
+ 'side': side,
850
+ 'price': this.parseNumber(price),
851
+ 'amount': this.parseNumber(amount),
852
+ 'cost': cost,
853
+ 'fee': {
854
+ 'cost': this.parseNumber(feeCost),
855
+ 'currency': feeCurrency,
856
+ },
857
+ };
858
+ return result;
859
+ }
860
+ else {
861
+ return this.safeTrade({
862
+ 'info': trade,
863
+ 'timestamp': timestamp,
864
+ 'datetime': this.iso8601(timestamp),
865
+ 'symbol': symbol,
866
+ 'id': id,
867
+ 'order': orderId,
868
+ 'type': undefined,
869
+ 'takerOrMaker': undefined,
870
+ 'side': side,
871
+ 'price': price,
872
+ 'amount': amount,
873
+ 'cost': undefined,
874
+ 'fee': fee,
875
+ }, market);
876
+ }
801
877
  }
802
878
  /**
803
879
  * @method
@@ -1608,6 +1684,8 @@ class blofin extends blofin$1["default"] {
1608
1684
  * @param {int} [limit] the maximum number of trades structures to retrieve
1609
1685
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1610
1686
  * @param {int} [params.until] Timestamp in ms of the latest time to retrieve trades for
1687
+ * @param {string} [params.type] 'swap' or 'spot' (defaults to 'swap'), required to fetch spot trade history
1688
+ * @param {string} [params.instId] *spot markets only* the market id of the spot market to fetch the trade history for (e.g. 'BTC-USDT')
1611
1689
  * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
1612
1690
  * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=trade-structure}
1613
1691
  */
@@ -1628,7 +1706,37 @@ class blofin extends blofin$1["default"] {
1628
1706
  if (limit !== undefined) {
1629
1707
  request['limit'] = limit; // default 100, max 100
1630
1708
  }
1631
- const response = await this.privateGetTradeFillsHistory(this.extend(request, params));
1709
+ let type = 'swap';
1710
+ [type, params] = this.handleMarketTypeAndParams('fetchMyTrades', market, params, type);
1711
+ let response = undefined;
1712
+ if (type === 'spot') {
1713
+ request['instType'] = 'SPOT';
1714
+ //
1715
+ // {
1716
+ // "code": "0",
1717
+ // "msg": "success",
1718
+ // "data": [
1719
+ // {
1720
+ // "instId": "DOGE-USDT",
1721
+ // "tradeId": "6000001623870",
1722
+ // "orderId": "6000011777113",
1723
+ // "fillPrice": "0.091480000000000000",
1724
+ // "fillSize": "30.000000000000000000",
1725
+ // "fillPnl": null,
1726
+ // "side": "buy",
1727
+ // "fee": "0.030000000000000000",
1728
+ // "ts": "1775213753407",
1729
+ // "brokerId": null,
1730
+ // "feeCurrency": "base_currency"
1731
+ // }
1732
+ // ]
1733
+ // }
1734
+ //
1735
+ response = await this.privateGetSpotTradeFillsHistory(this.extend(request, params));
1736
+ }
1737
+ else {
1738
+ response = await this.privateGetTradeFillsHistory(this.extend(request, params));
1739
+ }
1632
1740
  const data = this.safeList(response, 'data', []);
1633
1741
  return this.parseTrades(data, market, since, limit);
1634
1742
  }
@@ -640,7 +640,7 @@ class hollaex extends hollaex$1["default"] {
640
640
  // "low": 8607,
641
641
  // "last": 8841.05,
642
642
  // "volume": 20.2802,
643
- // "timestamp": "2020-03-03T03:11:18.964Z"
643
+ // "timestamp": "2020-03-03T03:11:18.965Z"
644
644
  // }
645
645
  //
646
646
  return this.parseTicker(response, market);