ccxt 4.1.24 → 4.1.25

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 (54) hide show
  1. package/README.md +3 -3
  2. package/dist/ccxt.browser.js +1172 -200
  3. package/dist/ccxt.browser.min.js +4 -4
  4. package/dist/cjs/ccxt.js +1 -1
  5. package/dist/cjs/src/ace.js +1 -1
  6. package/dist/cjs/src/base/Exchange.js +7 -3
  7. package/dist/cjs/src/base/functions/crypto.js +11 -2
  8. package/dist/cjs/src/base/functions/generic.js +5 -3
  9. package/dist/cjs/src/base/functions.js +1 -0
  10. package/dist/cjs/src/binance.js +108 -5
  11. package/dist/cjs/src/bitget.js +289 -21
  12. package/dist/cjs/src/bybit.js +132 -15
  13. package/dist/cjs/src/cryptocom.js +262 -15
  14. package/dist/cjs/src/gate.js +191 -88
  15. package/dist/cjs/src/krakenfutures.js +86 -20
  16. package/dist/cjs/src/oceanex.js +0 -12
  17. package/dist/cjs/src/okx.js +60 -1
  18. package/dist/cjs/src/pro/bybit.js +1 -1
  19. package/dist/cjs/src/static_dependencies/noble-curves/abstract/edwards.js +8 -6
  20. package/dist/cjs/src/wavesexchange.js +6 -6
  21. package/js/ccxt.d.ts +1 -1
  22. package/js/ccxt.js +1 -1
  23. package/js/src/abstract/gate.d.ts +2 -7
  24. package/js/src/abstract/gateio.d.ts +2 -7
  25. package/js/src/ace.js +1 -1
  26. package/js/src/base/Exchange.d.ts +4 -2
  27. package/js/src/base/Exchange.js +7 -3
  28. package/js/src/base/functions/crypto.d.ts +3 -2
  29. package/js/src/base/functions/crypto.js +11 -3
  30. package/js/src/base/functions/generic.d.ts +1 -1
  31. package/js/src/base/functions/generic.js +5 -3
  32. package/js/src/base/types.d.ts +8 -0
  33. package/js/src/binance.d.ts +2 -1
  34. package/js/src/binance.js +108 -5
  35. package/js/src/bitget.d.ts +15 -1
  36. package/js/src/bitget.js +289 -21
  37. package/js/src/bybit.d.ts +4 -2
  38. package/js/src/bybit.js +132 -15
  39. package/js/src/cryptocom.d.ts +4 -1
  40. package/js/src/cryptocom.js +262 -15
  41. package/js/src/gate.d.ts +3 -1
  42. package/js/src/gate.js +191 -88
  43. package/js/src/krakenfutures.d.ts +3 -1
  44. package/js/src/krakenfutures.js +86 -20
  45. package/js/src/oceanex.d.ts +0 -1
  46. package/js/src/oceanex.js +0 -12
  47. package/js/src/okx.d.ts +2 -1
  48. package/js/src/okx.js +60 -1
  49. package/js/src/pro/bybit.js +1 -1
  50. package/js/src/static_dependencies/noble-curves/abstract/edwards.d.ts +1 -0
  51. package/js/src/static_dependencies/noble-curves/abstract/edwards.js +5 -3
  52. package/js/src/wavesexchange.js +7 -7
  53. package/package.json +1 -1
  54. package/skip-tests.json +2 -3
@@ -36,6 +36,7 @@ export default class cryptocom extends Exchange {
36
36
  'cancelAllOrders': true,
37
37
  'cancelOrder': true,
38
38
  'createOrder': true,
39
+ 'createOrders': true,
39
40
  'fetchAccounts': true,
40
41
  'fetchBalance': true,
41
42
  'fetchBidsAsks': false,
@@ -1170,6 +1171,210 @@ export default class cryptocom extends Exchange {
1170
1171
  const result = this.safeValue(response, 'result', {});
1171
1172
  return this.parseOrder(result, market);
1172
1173
  }
1174
+ async createOrders(orders, params = {}) {
1175
+ /**
1176
+ * @method
1177
+ * @name cryptocom#createOrders
1178
+ * @description create a list of trade orders
1179
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-create-order-list-list
1180
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-create-order-list-oco
1181
+ * @param {array} orders list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
1182
+ * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
1183
+ */
1184
+ await this.loadMarkets();
1185
+ const ordersRequests = [];
1186
+ for (let i = 0; i < orders.length; i++) {
1187
+ const rawOrder = orders[i];
1188
+ const marketId = this.safeString(rawOrder, 'symbol');
1189
+ const type = this.safeString(rawOrder, 'type');
1190
+ const side = this.safeString(rawOrder, 'side');
1191
+ const amount = this.safeValue(rawOrder, 'amount');
1192
+ const price = this.safeValue(rawOrder, 'price');
1193
+ const orderParams = this.safeValue(rawOrder, 'params', {});
1194
+ const orderRequest = this.createAdvancedOrderRequest(marketId, type, side, amount, price, orderParams);
1195
+ ordersRequests.push(orderRequest);
1196
+ }
1197
+ const contigency = this.safeString(params, 'contingency_type', 'LIST');
1198
+ const request = {
1199
+ 'contingency_type': contigency,
1200
+ 'order_list': ordersRequests,
1201
+ };
1202
+ const response = await this.v1PrivatePostPrivateCreateOrderList(this.extend(request, params));
1203
+ //
1204
+ // {
1205
+ // "id": 12,
1206
+ // "method": "private/create-order-list",
1207
+ // "code": 10001,
1208
+ // "result": {
1209
+ // "result_list": [
1210
+ // {
1211
+ // "index": 0,
1212
+ // "code": 0,
1213
+ // "order_id": "2015106383706015873",
1214
+ // "client_oid": "my_order_0001"
1215
+ // },
1216
+ // {
1217
+ // "index": 1,
1218
+ // "code": 20007,
1219
+ // "message": "INVALID_REQUEST",
1220
+ // "client_oid": "my_order_0002"
1221
+ // }
1222
+ // ]
1223
+ // }
1224
+ // }
1225
+ //
1226
+ // {
1227
+ // "id" : 1698068111133,
1228
+ // "method" : "private/create-order-list",
1229
+ // "code" : 0,
1230
+ // "result" : [ {
1231
+ // "code" : 0,
1232
+ // "index" : 0,
1233
+ // "client_oid" : "1698068111133_0",
1234
+ // "order_id" : "6142909896519488206"
1235
+ // }, {
1236
+ // "code" : 306,
1237
+ // "index" : 1,
1238
+ // "client_oid" : "1698068111133_1",
1239
+ // "message" : "INSUFFICIENT_AVAILABLE_BALANCE",
1240
+ // "order_id" : "6142909896519488207"
1241
+ // } ]
1242
+ // }
1243
+ //
1244
+ const result = this.safeValue(response, 'result', []);
1245
+ const listId = this.safeString(result, 'list_id');
1246
+ if (listId !== undefined) {
1247
+ const ocoOrders = [{ 'order_id': listId }];
1248
+ return this.parseOrders(ocoOrders);
1249
+ }
1250
+ return this.parseOrders(result);
1251
+ }
1252
+ createAdvancedOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
1253
+ // differs slightly from createOrderRequest
1254
+ // since the advanced order endpoint requires a different set of parameters
1255
+ // namely here we don't support ref_price or spot_margin
1256
+ // and market-buy orders need to send notional instead of quantity
1257
+ const market = this.market(symbol);
1258
+ const uppercaseType = type.toUpperCase();
1259
+ const request = {
1260
+ 'instrument_name': market['id'],
1261
+ 'side': side.toUpperCase(),
1262
+ };
1263
+ if ((uppercaseType === 'LIMIT') || (uppercaseType === 'STOP_LIMIT') || (uppercaseType === 'TAKE_PROFIT_LIMIT')) {
1264
+ request['price'] = this.priceToPrecision(symbol, price);
1265
+ }
1266
+ const broker = this.safeString(this.options, 'broker', 'CCXT');
1267
+ request['broker_id'] = broker;
1268
+ const timeInForce = this.safeStringUpper2(params, 'timeInForce', 'time_in_force');
1269
+ if (timeInForce !== undefined) {
1270
+ if (timeInForce === 'GTC') {
1271
+ request['time_in_force'] = 'GOOD_TILL_CANCEL';
1272
+ }
1273
+ else if (timeInForce === 'IOC') {
1274
+ request['time_in_force'] = 'IMMEDIATE_OR_CANCEL';
1275
+ }
1276
+ else if (timeInForce === 'FOK') {
1277
+ request['time_in_force'] = 'FILL_OR_KILL';
1278
+ }
1279
+ else {
1280
+ request['time_in_force'] = timeInForce;
1281
+ }
1282
+ }
1283
+ const postOnly = this.safeValue(params, 'postOnly', false);
1284
+ if ((postOnly) || (timeInForce === 'PO')) {
1285
+ request['exec_inst'] = ['POST_ONLY'];
1286
+ request['time_in_force'] = 'GOOD_TILL_CANCEL';
1287
+ }
1288
+ const triggerPrice = this.safeStringN(params, ['stopPrice', 'triggerPrice', 'ref_price']);
1289
+ const stopLossPrice = this.safeNumber(params, 'stopLossPrice');
1290
+ const takeProfitPrice = this.safeNumber(params, 'takeProfitPrice');
1291
+ const isTrigger = (triggerPrice !== undefined);
1292
+ const isStopLossTrigger = (stopLossPrice !== undefined);
1293
+ const isTakeProfitTrigger = (takeProfitPrice !== undefined);
1294
+ if (isTrigger) {
1295
+ price = price.toString();
1296
+ if ((uppercaseType === 'LIMIT') || (uppercaseType === 'STOP_LIMIT') || (uppercaseType === 'TAKE_PROFIT_LIMIT')) {
1297
+ if (side === 'buy') {
1298
+ if (Precise.stringLt(price, triggerPrice)) {
1299
+ request['type'] = 'TAKE_PROFIT_LIMIT';
1300
+ }
1301
+ else {
1302
+ request['type'] = 'STOP_LIMIT';
1303
+ }
1304
+ }
1305
+ else {
1306
+ if (Precise.stringLt(price, triggerPrice)) {
1307
+ request['type'] = 'STOP_LIMIT';
1308
+ }
1309
+ else {
1310
+ request['type'] = 'TAKE_PROFIT_LIMIT';
1311
+ }
1312
+ }
1313
+ }
1314
+ else {
1315
+ if (side === 'buy') {
1316
+ if (Precise.stringLt(price, triggerPrice)) {
1317
+ request['type'] = 'TAKE_PROFIT';
1318
+ }
1319
+ else {
1320
+ request['type'] = 'STOP_LOSS';
1321
+ }
1322
+ }
1323
+ else {
1324
+ if (Precise.stringLt(price, triggerPrice)) {
1325
+ request['type'] = 'STOP_LOSS';
1326
+ }
1327
+ else {
1328
+ request['type'] = 'TAKE_PROFIT';
1329
+ }
1330
+ }
1331
+ }
1332
+ }
1333
+ else if (isStopLossTrigger) {
1334
+ if ((uppercaseType === 'LIMIT') || (uppercaseType === 'STOP_LIMIT')) {
1335
+ request['type'] = 'STOP_LIMIT';
1336
+ }
1337
+ else {
1338
+ request['type'] = 'STOP_LOSS';
1339
+ }
1340
+ }
1341
+ else if (isTakeProfitTrigger) {
1342
+ if ((uppercaseType === 'LIMIT') || (uppercaseType === 'TAKE_PROFIT_LIMIT')) {
1343
+ request['type'] = 'TAKE_PROFIT_LIMIT';
1344
+ }
1345
+ else {
1346
+ request['type'] = 'TAKE_PROFIT';
1347
+ }
1348
+ }
1349
+ else {
1350
+ request['type'] = uppercaseType;
1351
+ }
1352
+ if ((side === 'buy') && ((uppercaseType === 'MARKET') || (uppercaseType === 'STOP_LOSS') || (uppercaseType === 'TAKE_PROFIT'))) {
1353
+ // use createmarketBuy logic here
1354
+ if (this.options['createMarketBuyOrderRequiresPrice']) {
1355
+ const cost = this.safeNumber2(params, 'cost', 'notional');
1356
+ params = this.omit(params, 'cost');
1357
+ if (price === undefined && cost === undefined) {
1358
+ throw new InvalidOrder(this.id + ' createOrder() requires the price argument with market buy orders to calculate total order cost (amount to spend), where cost = amount * price. Supply a price argument to createOrder() call if you want the cost to be calculated for you from price and amount, or, alternatively, add .options["createMarketBuyOrderRequiresPrice"] = false to supply the cost in the amount argument (the exchange-specific behaviour)');
1359
+ }
1360
+ else {
1361
+ const amountString = this.numberToString(amount);
1362
+ const priceString = this.numberToString(price);
1363
+ const quoteAmount = Precise.stringMul(amountString, priceString);
1364
+ amount = (cost !== undefined) ? cost : this.parseNumber(quoteAmount);
1365
+ request['notional'] = this.costToPrecision(symbol, amount);
1366
+ }
1367
+ }
1368
+ else {
1369
+ request['notional'] = this.costToPrecision(symbol, amount);
1370
+ }
1371
+ }
1372
+ else {
1373
+ request['quantity'] = this.amountToPrecision(symbol, amount);
1374
+ }
1375
+ params = this.omit(params, ['postOnly', 'clientOrderId', 'timeInForce', 'stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice']);
1376
+ return this.extend(request, params);
1377
+ }
1173
1378
  async cancelAllOrders(symbol = undefined, params = {}) {
1174
1379
  /**
1175
1380
  * @method
@@ -2010,12 +2215,31 @@ export default class cryptocom extends Exchange {
2010
2215
  // "update_time": 1686806053993
2011
2216
  // }
2012
2217
  //
2218
+ // createOrders
2219
+ // {
2220
+ // "code" : 306,
2221
+ // "index" : 1,
2222
+ // "client_oid" : "1698068111133_1",
2223
+ // "message" : "INSUFFICIENT_AVAILABLE_BALANCE",
2224
+ // "order_id" : "6142909896519488207"
2225
+ // }
2226
+ //
2227
+ const code = this.safeInteger(order, 'code');
2228
+ if ((code !== undefined) && (code !== 0)) {
2229
+ return this.safeOrder({
2230
+ 'id': this.safeString(order, 'order_id'),
2231
+ 'clientOrderId': this.safeString(order, 'client_oid'),
2232
+ 'info': order,
2233
+ 'status': 'rejected',
2234
+ });
2235
+ }
2013
2236
  const created = this.safeInteger(order, 'create_time');
2014
2237
  const marketId = this.safeString(order, 'instrument_name');
2015
2238
  const symbol = this.safeSymbol(marketId, market);
2016
2239
  const execInst = this.safeValue(order, 'exec_inst');
2017
- let postOnly = false;
2240
+ let postOnly = undefined;
2018
2241
  if (execInst !== undefined) {
2242
+ postOnly = false;
2019
2243
  for (let i = 0; i < execInst.length; i++) {
2020
2244
  const inst = execInst[i];
2021
2245
  if (inst === 'POST_ONLY') {
@@ -2937,6 +3161,41 @@ export default class cryptocom extends Exchange {
2937
3161
  nonce() {
2938
3162
  return this.milliseconds();
2939
3163
  }
3164
+ paramsToString(object, level) {
3165
+ const maxLevel = 3;
3166
+ if (level >= maxLevel) {
3167
+ return object.toString();
3168
+ }
3169
+ if (typeof object === 'string') {
3170
+ return object;
3171
+ }
3172
+ let returnString = '';
3173
+ let paramsKeys = undefined;
3174
+ if (Array.isArray(object)) {
3175
+ paramsKeys = object;
3176
+ }
3177
+ else {
3178
+ const sorted = this.keysort(object);
3179
+ paramsKeys = Object.keys(sorted);
3180
+ }
3181
+ for (let i = 0; i < paramsKeys.length; i++) {
3182
+ const key = paramsKeys[i];
3183
+ returnString += key;
3184
+ const value = object[key];
3185
+ if (value === 'undefined') {
3186
+ returnString += 'null';
3187
+ }
3188
+ else if (Array.isArray(value)) {
3189
+ for (let j = 0; j < value.length; j++) {
3190
+ returnString += this.paramsToString(value[j], level + 1);
3191
+ }
3192
+ }
3193
+ else {
3194
+ returnString += value.toString();
3195
+ }
3196
+ }
3197
+ return returnString;
3198
+ }
2940
3199
  sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
2941
3200
  const type = this.safeString(api, 0);
2942
3201
  const access = this.safeString(api, 1);
@@ -2951,20 +3210,8 @@ export default class cryptocom extends Exchange {
2951
3210
  this.checkRequiredCredentials();
2952
3211
  const nonce = this.nonce().toString();
2953
3212
  const requestParams = this.extend({}, params);
2954
- const keysorted = this.keysort(requestParams);
2955
- const paramsKeys = Object.keys(keysorted);
2956
- let strSortKey = '';
2957
- for (let i = 0; i < paramsKeys.length; i++) {
2958
- const key = paramsKeys[i].toString();
2959
- let value = requestParams[paramsKeys[i]];
2960
- if (Array.isArray(value)) {
2961
- value = value.join(',');
2962
- }
2963
- else {
2964
- value = value.toString();
2965
- }
2966
- strSortKey = strSortKey + key + value;
2967
- }
3213
+ const paramsKeys = Object.keys(requestParams);
3214
+ const strSortKey = this.paramsToString(requestParams, 0);
2968
3215
  const payload = path + nonce + this.apiKey + strSortKey + nonce;
2969
3216
  const signature = this.hmac(this.encode(payload), this.encode(this.secret), sha256);
2970
3217
  const paramsKeysLength = paramsKeys.length;
package/js/src/gate.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import Exchange from './abstract/gate.js';
2
- import { Int, OrderSide, OrderType, OHLCV, Trade, FundingRateHistory, OpenInterest, Order, Balances } from './base/types.js';
2
+ import { Int, OrderSide, OrderType, OHLCV, Trade, FundingRateHistory, OpenInterest, Order, Balances, OrderRequest } from './base/types.js';
3
3
  /**
4
4
  * @class gate
5
5
  * @extends Exchange
@@ -268,6 +268,8 @@ export default class gate extends Exchange {
268
268
  };
269
269
  };
270
270
  createOrder(symbol: string, type: OrderType, side: OrderSide, amount: any, price?: any, params?: {}): Promise<Order>;
271
+ createOrders(orders: OrderRequest[], params?: {}): Promise<Order[]>;
272
+ createOrderRequest(symbol: string, type: OrderType, side: OrderSide, amount: any, price?: any, params?: {}): any;
271
273
  editOrder(id: string, symbol: any, type: any, side: any, amount?: any, price?: any, params?: {}): Promise<Order>;
272
274
  parseOrderStatus(status: any): string;
273
275
  parseOrder(order: any, market?: any): Order;