ccxt 4.0.97 → 4.0.99

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
@@ -180,7 +180,7 @@ var woo$1 = require('./src/pro/woo.js');
180
180
 
181
181
  //-----------------------------------------------------------------------------
182
182
  // this is updated by vss.js when building
183
- const version = '4.0.97';
183
+ const version = '4.0.99';
184
184
  Exchange["default"].ccxtVersion = version;
185
185
  const exchanges = {
186
186
  'ace': ace,
@@ -31,6 +31,7 @@ class bigone extends bigone$1 {
31
31
  'cancelAllOrders': true,
32
32
  'cancelOrder': true,
33
33
  'createOrder': true,
34
+ 'createPostOnlyOrder': true,
34
35
  'createStopLimitOrder': true,
35
36
  'createStopMarketOrder': true,
36
37
  'createStopOrder': true,
@@ -132,6 +133,7 @@ class bigone extends bigone$1 {
132
133
  },
133
134
  },
134
135
  'options': {
136
+ 'createMarketBuyOrderRequiresPrice': true,
135
137
  'accountsByType': {
136
138
  'spot': 'SPOT',
137
139
  'fund': 'FUND',
@@ -1088,30 +1090,39 @@ class bigone extends bigone$1 {
1088
1090
  //
1089
1091
  return this.parseBalance(response);
1090
1092
  }
1093
+ parseType(type) {
1094
+ const types = {
1095
+ 'STOP_LIMIT': 'limit',
1096
+ 'STOP_MARKET': 'market',
1097
+ 'LIMIT': 'limit',
1098
+ 'MARKET': 'market',
1099
+ };
1100
+ return this.safeString(types, type, type);
1101
+ }
1091
1102
  parseOrder(order, market = undefined) {
1092
1103
  //
1093
1104
  // {
1094
- // "id": 10,
1095
- // "asset_pair_name": "EOS-BTC",
1096
- // "price": "10.00",
1097
- // "amount": "10.00",
1098
- // "filled_amount": "9.0",
1099
- // "avg_deal_price": "12.0",
1100
- // "side": "ASK",
1101
- // "state": "FILLED",
1102
- // "created_at":"2019-01-29T06:05:56Z",
1103
- // "updated_at":"2019-01-29T06:05:56Z",
1105
+ // "id": '42154072251',
1106
+ // "asset_pair_name": 'SOL-USDT',
1107
+ // "price": '20',
1108
+ // "amount": '0.5',
1109
+ // "filled_amount": '0',
1110
+ // "avg_deal_price": '0',
1111
+ // "side": 'ASK',
1112
+ // "state": 'PENDING',
1113
+ // "created_at": '2023-09-13T03:42:00Z',
1114
+ // "updated_at": '2023-09-13T03:42:00Z',
1115
+ // "type": 'LIMIT',
1116
+ // "stop_price": '0',
1117
+ // "immediate_or_cancel": false,
1118
+ // "post_only": false,
1119
+ // "client_order_id": ''
1104
1120
  // }
1105
1121
  //
1106
1122
  const id = this.safeString(order, 'id');
1107
1123
  const marketId = this.safeString(order, 'asset_pair_name');
1108
1124
  const symbol = this.safeSymbol(marketId, market, '-');
1109
1125
  const timestamp = this.parse8601(this.safeString(order, 'created_at'));
1110
- const price = this.safeString(order, 'price');
1111
- const amount = this.safeString(order, 'amount');
1112
- const average = this.safeString(order, 'avg_deal_price');
1113
- const filled = this.safeString(order, 'filled_amount');
1114
- const status = this.parseOrderStatus(this.safeString(order, 'state'));
1115
1126
  let side = this.safeString(order, 'side');
1116
1127
  if (side === 'BID') {
1117
1128
  side = 'buy';
@@ -1119,28 +1130,48 @@ class bigone extends bigone$1 {
1119
1130
  else {
1120
1131
  side = 'sell';
1121
1132
  }
1122
- const lastTradeTimestamp = this.parse8601(this.safeString(order, 'updated_at'));
1133
+ let triggerPrice = this.safeString(order, 'stop_price');
1134
+ if (Precise["default"].stringEq(triggerPrice, '0')) {
1135
+ triggerPrice = undefined;
1136
+ }
1137
+ const immediateOrCancel = this.safeValue(order, 'immediate_or_cancel');
1138
+ let timeInForce = undefined;
1139
+ if (immediateOrCancel) {
1140
+ timeInForce = 'IOC';
1141
+ }
1142
+ const type = this.parseType(this.safeString(order, 'type'));
1143
+ const price = this.safeString(order, 'price');
1144
+ let amount = undefined;
1145
+ let filled = undefined;
1146
+ let cost = undefined;
1147
+ if (type === 'market' && side === 'buy') {
1148
+ cost = this.safeString(order, 'filled_amount');
1149
+ }
1150
+ else {
1151
+ amount = this.safeString(order, 'amount');
1152
+ filled = this.safeString(order, 'filled_amount');
1153
+ }
1123
1154
  return this.safeOrder({
1124
1155
  'info': order,
1125
1156
  'id': id,
1126
- 'clientOrderId': undefined,
1157
+ 'clientOrderId': this.safeString(order, 'client_order_id'),
1127
1158
  'timestamp': timestamp,
1128
1159
  'datetime': this.iso8601(timestamp),
1129
- 'lastTradeTimestamp': lastTradeTimestamp,
1160
+ 'lastTradeTimestamp': this.parse8601(this.safeString(order, 'updated_at')),
1130
1161
  'symbol': symbol,
1131
- 'type': undefined,
1132
- 'timeInForce': undefined,
1133
- 'postOnly': undefined,
1162
+ 'type': type,
1163
+ 'timeInForce': timeInForce,
1164
+ 'postOnly': this.safeValue(order, 'post_only'),
1134
1165
  'side': side,
1135
1166
  'price': price,
1136
- 'stopPrice': undefined,
1137
- 'triggerPrice': undefined,
1167
+ 'stopPrice': triggerPrice,
1168
+ 'triggerPrice': triggerPrice,
1138
1169
  'amount': amount,
1139
- 'cost': undefined,
1140
- 'average': average,
1170
+ 'cost': cost,
1171
+ 'average': this.safeString(order, 'avg_deal_price'),
1141
1172
  'filled': filled,
1142
1173
  'remaining': undefined,
1143
- 'status': status,
1174
+ 'status': this.parseOrderStatus(this.safeString(order, 'state')),
1144
1175
  'fee': undefined,
1145
1176
  'trades': undefined,
1146
1177
  }, market);
@@ -1150,46 +1181,79 @@ class bigone extends bigone$1 {
1150
1181
  * @method
1151
1182
  * @name bigone#createOrder
1152
1183
  * @description create a trade order
1184
+ * @see https://open.big.one/docs/spot_orders.html#create-order
1153
1185
  * @param {string} symbol unified symbol of the market to create an order in
1154
1186
  * @param {string} type 'market' or 'limit'
1155
1187
  * @param {string} side 'buy' or 'sell'
1156
1188
  * @param {float} amount how much of currency you want to trade in units of base currency
1157
1189
  * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1158
1190
  * @param {object} [params] extra parameters specific to the bigone api endpoint
1191
+ * @param {float} [params.triggerPrice] the price at which a trigger order is triggered at
1192
+ * @param {bool} [params.postOnly] if true, the order will only be posted to the order book and not executed immediately
1193
+ * @param {string} [params.timeInForce] "GTC", "IOC", or "PO"
1194
+ *
1195
+ * EXCHANGE SPECIFIC PARAMETERS
1196
+ * @param {string} operator *stop order only* GTE or LTE (default)
1197
+ * @param {string} client_order_id must match ^[a-zA-Z0-9-_]{1,36}$ this regex. client_order_id is unique in 24 hours, If created 24 hours later and the order closed, it will be released and can be reused
1159
1198
  * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
1160
1199
  */
1161
1200
  await this.loadMarkets();
1162
1201
  const market = this.market(symbol);
1163
- const requestSide = (side === 'buy') ? 'BID' : 'ASK';
1164
- const uppercaseType = type.toUpperCase();
1202
+ const isBuy = (side === 'buy');
1203
+ const requestSide = isBuy ? 'BID' : 'ASK';
1204
+ let uppercaseType = type.toUpperCase();
1205
+ const isLimit = uppercaseType === 'LIMIT';
1206
+ const exchangeSpecificParam = this.safeValue(params, 'post_only');
1207
+ let postOnly = undefined;
1208
+ [postOnly, params] = this.handlePostOnly((uppercaseType === 'MARKET'), exchangeSpecificParam, params);
1209
+ const triggerPrice = this.safeStringN(params, ['triggerPrice', 'stopPrice', 'stop_price']);
1165
1210
  const request = {
1166
1211
  'asset_pair_name': market['id'],
1167
1212
  'side': requestSide,
1168
- 'amount': this.amountToPrecision(symbol, amount),
1213
+ 'amount': this.amountToPrecision(symbol, amount), // order amount, string, required
1169
1214
  // 'price': this.priceToPrecision (symbol, price), // order price, string, required
1170
- 'type': uppercaseType,
1171
1215
  // 'operator': 'GTE', // stop orders only, GTE greater than and equal, LTE less than and equal
1172
1216
  // 'immediate_or_cancel': false, // limit orders only, must be false when post_only is true
1173
1217
  // 'post_only': false, // limit orders only, must be false when immediate_or_cancel is true
1174
1218
  };
1175
- if (uppercaseType === 'LIMIT') {
1219
+ if (isLimit || (uppercaseType === 'STOP_LIMIT')) {
1176
1220
  request['price'] = this.priceToPrecision(symbol, price);
1221
+ if (isLimit) {
1222
+ const timeInForce = this.safeString(params, 'timeInForce');
1223
+ if (timeInForce === 'IOC') {
1224
+ request['immediate_or_cancel'] = true;
1225
+ }
1226
+ if (postOnly) {
1227
+ request['post_only'] = true;
1228
+ }
1229
+ }
1177
1230
  }
1178
1231
  else {
1179
- const isStopLimit = (uppercaseType === 'STOP_LIMIT');
1180
- const isStopMarket = (uppercaseType === 'STOP_MARKET');
1181
- if (isStopLimit || isStopMarket) {
1182
- const stopPrice = this.safeNumber2(params, 'stop_price', 'stopPrice');
1183
- if (stopPrice === undefined) {
1184
- throw new errors.ArgumentsRequired(this.id + ' createOrder() requires a stop_price parameter');
1232
+ const createMarketBuyOrderRequiresPrice = this.safeValue(this.options, 'createMarketBuyOrderRequiresPrice');
1233
+ if (createMarketBuyOrderRequiresPrice && (side === 'buy')) {
1234
+ if (price === undefined) {
1235
+ throw new errors.InvalidOrder(this.id + ' createOrder() requires price argument for market buy orders on spot markets to calculate the total amount to spend (amount * price), alternatively set the createMarketBuyOrderRequiresPrice option to false and pass in the cost to spend into the amount parameter');
1185
1236
  }
1186
- request['stop_price'] = this.priceToPrecision(symbol, stopPrice);
1187
- params = this.omit(params, ['stop_price', 'stopPrice']);
1237
+ else {
1238
+ const amountString = this.numberToString(amount);
1239
+ const priceString = this.numberToString(price);
1240
+ amount = this.parseNumber(Precise["default"].stringMul(amountString, priceString));
1241
+ }
1242
+ }
1243
+ }
1244
+ request['amount'] = this.amountToPrecision(symbol, amount);
1245
+ if (triggerPrice !== undefined) {
1246
+ request['stop_price'] = this.priceToPrecision(symbol, triggerPrice);
1247
+ request['operator'] = isBuy ? 'GTE' : 'LTE';
1248
+ if (isLimit) {
1249
+ uppercaseType = 'STOP_LIMIT';
1188
1250
  }
1189
- if (isStopLimit) {
1190
- request['price'] = this.priceToPrecision(symbol, price);
1251
+ else if (uppercaseType === 'MARKET') {
1252
+ uppercaseType = 'STOP_MARKET';
1191
1253
  }
1192
1254
  }
1255
+ request['type'] = uppercaseType;
1256
+ params = this.omit(params, ['stop_price', 'stopPrice', 'triggerPrice', 'timeInForce']);
1193
1257
  const response = await this.privatePostOrders(this.extend(request, params));
1194
1258
  //
1195
1259
  // {
@@ -80,15 +80,14 @@ class bithumb extends bithumb$1 {
80
80
  'api': {
81
81
  'public': {
82
82
  'get': [
83
- 'ticker/{currency}',
84
- 'ticker/all',
85
- 'ticker/ALL_BTC',
86
- 'ticker/ALL_KRW',
87
- 'orderbook/{currency}',
88
- 'orderbook/all',
89
- 'transaction_history/{currency}',
90
- 'transaction_history/all',
91
- 'candlestick/{currency}/{interval}',
83
+ 'ticker/ALL_{quoteId}',
84
+ 'ticker/{baseId}_{quoteId}',
85
+ 'orderbook/ALL_{quoteId}',
86
+ 'orderbook/{baseId}_{quoteId}',
87
+ 'transaction_history/{baseId}_{quoteId}',
88
+ 'assetsstatus/ALL',
89
+ 'assetsstatus/{baseId}',
90
+ 'candlestick/{baseId}_{quoteId}/{interval}',
92
91
  ],
93
92
  },
94
93
  'private': {
@@ -107,6 +106,7 @@ class bithumb extends bithumb$1 {
107
106
  'trade/krw_withdrawal',
108
107
  'trade/market_buy',
109
108
  'trade/market_sell',
109
+ 'trade/stop_limit',
110
110
  ],
111
111
  },
112
112
  },
@@ -195,8 +195,10 @@ class bithumb extends bithumb$1 {
195
195
  const quote = quotes[i];
196
196
  const quoteId = quote;
197
197
  const extension = this.safeValue(quoteCurrencies, quote, {});
198
- const method = 'publicGetTickerALL' + quote;
199
- const response = await this[method](params);
198
+ const request = {
199
+ 'quoteId': quoteId,
200
+ };
201
+ const response = await this.publicGetTickerALLQuoteId(this.extend(request, params));
200
202
  const data = this.safeValue(response, 'data');
201
203
  const currencyIds = Object.keys(data);
202
204
  for (let j = 0; j < currencyIds.length; j++) {
@@ -307,12 +309,13 @@ class bithumb extends bithumb$1 {
307
309
  await this.loadMarkets();
308
310
  const market = this.market(symbol);
309
311
  const request = {
310
- 'currency': market['base'] + '_' + market['quote'],
312
+ 'baseId': market['baseId'],
313
+ 'quoteId': market['quoteId'],
311
314
  };
312
315
  if (limit !== undefined) {
313
316
  request['count'] = limit; // default 30, max 30
314
317
  }
315
- const response = await this.publicGetOrderbookCurrency(this.extend(request, params));
318
+ const response = await this.publicGetOrderbookBaseIdQuoteId(this.extend(request, params));
316
319
  //
317
320
  // {
318
321
  // "status":"0000",
@@ -400,8 +403,11 @@ class bithumb extends bithumb$1 {
400
403
  const quotes = Object.keys(quoteCurrencies);
401
404
  for (let i = 0; i < quotes.length; i++) {
402
405
  const quote = quotes[i];
403
- const method = 'publicGetTickerALL' + quote;
404
- const response = await this[method](params);
406
+ const quoteId = quote;
407
+ const request = {
408
+ 'quoteId': quoteId,
409
+ };
410
+ const response = await this.publicGetTickerALLQuoteId(this.extend(request, params));
405
411
  //
406
412
  // {
407
413
  // "status":"0000",
@@ -451,9 +457,10 @@ class bithumb extends bithumb$1 {
451
457
  await this.loadMarkets();
452
458
  const market = this.market(symbol);
453
459
  const request = {
454
- 'currency': market['base'],
460
+ 'baseId': market['baseId'],
461
+ 'quoteId': market['quoteId'],
455
462
  };
456
- const response = await this.publicGetTickerCurrency(this.extend(request, params));
463
+ const response = await this.publicGetTickerBaseIdQuoteId(this.extend(request, params));
457
464
  //
458
465
  // {
459
466
  // "status":"0000",
@@ -511,10 +518,11 @@ class bithumb extends bithumb$1 {
511
518
  await this.loadMarkets();
512
519
  const market = this.market(symbol);
513
520
  const request = {
514
- 'currency': market['base'],
521
+ 'baseId': market['baseId'],
522
+ 'quoteId': market['quoteId'],
515
523
  'interval': this.safeString(this.timeframes, timeframe, timeframe),
516
524
  };
517
- const response = await this.publicGetCandlestickCurrencyInterval(this.extend(request, params));
525
+ const response = await this.publicGetCandlestickBaseIdQuoteIdInterval(this.extend(request, params));
518
526
  //
519
527
  // {
520
528
  // 'status': '0000',
@@ -633,12 +641,13 @@ class bithumb extends bithumb$1 {
633
641
  await this.loadMarkets();
634
642
  const market = this.market(symbol);
635
643
  const request = {
636
- 'currency': market['base'] + '_' + market['quote'],
644
+ 'baseId': market['baseId'],
645
+ 'quoteId': market['quoteId'],
637
646
  };
638
647
  if (limit !== undefined) {
639
648
  request['count'] = limit; // default 20, max 100
640
649
  }
641
- const response = await this.publicGetTransactionHistoryCurrency(this.extend(request, params));
650
+ const response = await this.publicGetTransactionHistoryBaseIdQuoteId(this.extend(request, params));
642
651
  //
643
652
  // {
644
653
  // "status":"0000",
@@ -85,7 +85,7 @@ class bitmart extends bitmart$1 {
85
85
  'fetchWithdrawals': true,
86
86
  'reduceMargin': false,
87
87
  'repayMargin': true,
88
- 'setLeverage': false,
88
+ 'setLeverage': true,
89
89
  'setMarginMode': false,
90
90
  'transfer': true,
91
91
  'withdraw': true,
@@ -148,6 +148,9 @@ class bitmart extends bitmart$1 {
148
148
  'account/sub-account/v1/transfer-history': 7.5,
149
149
  'account/sub-account/main/v1/wallet': 5,
150
150
  'account/sub-account/main/v1/subaccount-list': 7.5,
151
+ 'account/contract/sub-account/main/v1/wallet': 5,
152
+ 'account/contract/sub-account/main/v1/transfer-list': 7.5,
153
+ 'account/contract/sub-account/v1/transfer-history': 7.5,
151
154
  // account
152
155
  'account/v1/wallet': 5,
153
156
  'account/v1/currencies': 30,
@@ -173,9 +176,11 @@ class bitmart extends bitmart$1 {
173
176
  'spot/v1/user_fee': 6,
174
177
  // contract
175
178
  'contract/private/assets-detail': 5,
176
- 'contract/private/order': 2,
179
+ 'contract/private/order': 1.2,
177
180
  'contract/private/order-history': 10,
178
181
  'contract/private/position': 10,
182
+ 'contract/private/get-open-orders': 1.2,
183
+ 'contract/private/trades': 10,
179
184
  },
180
185
  'post': {
181
186
  // sub-account endpoints
@@ -184,6 +189,9 @@ class bitmart extends bitmart$1 {
184
189
  'account/sub-account/main/v1/main-to-sub': 30,
185
190
  'account/sub-account/sub/v1/sub-to-sub': 30,
186
191
  'account/sub-account/main/v1/sub-to-sub': 30,
192
+ 'account/contract/sub-account/main/v1/sub-to-main': 7.5,
193
+ 'account/contract/sub-account/main/v1/main-to-sub': 7.5,
194
+ 'account/contract/sub-account/sub/v1/sub-to-main': 7.5,
187
195
  // account
188
196
  'account/v1/withdraw/apply': 7.5,
189
197
  // transaction and trading
@@ -207,7 +215,14 @@ class bitmart extends bitmart$1 {
207
215
  'spot/v1/margin/isolated/repay': 6,
208
216
  'spot/v1/margin/isolated/transfer': 6,
209
217
  // contract
210
- 'contract/private/trades': 10,
218
+ 'account/v1/transfer-contract-list': 60,
219
+ 'account/v1/transfer-contract': 60,
220
+ 'contract/private/submit-order': 2.5,
221
+ 'contract/private/cancel-order': 1.5,
222
+ 'contract/private/cancel-orders': 30,
223
+ 'contract/private/submit-plan-order': 2.5,
224
+ 'contract/private/cancel-plan-order': 1.5,
225
+ 'contract/private/submit-leverage': 2.5,
211
226
  },
212
227
  },
213
228
  },
@@ -2052,6 +2067,9 @@ class bitmart extends bitmart$1 {
2052
2067
  }
2053
2068
  const [marginMode, query] = this.handleMarginModeAndParams('createOrder', params);
2054
2069
  if (marginMode !== undefined) {
2070
+ if (marginMode !== 'isolated') {
2071
+ throw new errors.NotSupported(this.id + ' only isolated margin is supported');
2072
+ }
2055
2073
  method = 'privatePostSpotV1MarginSubmitOrder';
2056
2074
  }
2057
2075
  const response = await this[method](this.extend(request, query));
@@ -3204,22 +3222,33 @@ class bitmart extends bitmart$1 {
3204
3222
  'info': interest,
3205
3223
  };
3206
3224
  }
3207
- handleMarginModeAndParams(methodName, params = {}, defaultValue = undefined) {
3225
+ async setLeverage(leverage, symbol = undefined, params = {}) {
3208
3226
  /**
3209
- * @ignore
3210
3227
  * @method
3211
- * @description marginMode specified by params["marginMode"], this.options["marginMode"], this.options["defaultMarginMode"], params["margin"] = true or this.options["defaultType"] = 'margin'
3212
- * @param {object} [params] extra parameters specific to the exchange api endpoint
3213
- * @returns {array} the marginMode in lowercase
3228
+ * @name bitmart#setLeverage
3229
+ * @description set the level of leverage for a market
3230
+ * @see https://developer-pro.bitmart.com/en/futures/#submit-leverage-signed
3231
+ * @param {float} leverage the rate of leverage
3232
+ * @param {string} symbol unified market symbol
3233
+ * @param {object} [params] extra parameters specific to the bitmart api endpoint
3234
+ * @param {string} [params.marginMode] 'isolated' or 'cross'
3235
+ * @returns {object} response from the exchange
3214
3236
  */
3237
+ this.checkRequiredSymbol('setLeverage', symbol);
3215
3238
  let marginMode = undefined;
3216
- [marginMode, params] = super.handleMarginModeAndParams(methodName, params, defaultValue);
3217
- if (marginMode !== undefined) {
3218
- if (marginMode !== 'isolated') {
3219
- throw new errors.NotSupported(this.id + ' only isolated margin is supported');
3220
- }
3239
+ [marginMode, params] = this.handleMarginModeAndParams('setLeverage', params);
3240
+ this.checkRequiredArgument('setLeverage', marginMode, 'marginMode', ['isolated', 'cross']);
3241
+ await this.loadMarkets();
3242
+ const market = this.market(symbol);
3243
+ if (!market['swap']) {
3244
+ throw new errors.BadSymbol(this.id + ' setLeverage() supports swap contracts only');
3221
3245
  }
3222
- return [marginMode, params];
3246
+ const request = {
3247
+ 'symbol': market['id'],
3248
+ 'leverage': leverage.toString(),
3249
+ 'open_type': marginMode,
3250
+ };
3251
+ return await this.privatePostContractPrivateSubmitLeverage(this.extend(request, params));
3223
3252
  }
3224
3253
  nonce() {
3225
3254
  return this.milliseconds();
@@ -203,6 +203,7 @@ class exmo extends exmo$1 {
203
203
  'precisionMode': number.TICK_SIZE,
204
204
  'exceptions': {
205
205
  'exact': {
206
+ '140434': errors.BadRequest,
206
207
  '40005': errors.AuthenticationError,
207
208
  '40009': errors.InvalidNonce,
208
209
  '40015': errors.ExchangeError,
@@ -1382,34 +1383,42 @@ class exmo extends exmo$1 {
1382
1383
  * @name exmo#createOrder
1383
1384
  * @description create a trade order
1384
1385
  * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#80daa469-ec59-4d0a-b229-6a311d8dd1cd
1386
+ * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#de6f4321-eeac-468c-87f7-c4ad7062e265 // stop market
1387
+ * @see https://documenter.getpostman.com/view/10287440/SzYXWKPi#3561b86c-9ff1-436e-8e68-ac926b7eb523 // margin
1385
1388
  * @param {string} symbol unified symbol of the market to create an order in
1386
1389
  * @param {string} type 'market' or 'limit'
1387
1390
  * @param {string} side 'buy' or 'sell'
1388
1391
  * @param {float} amount how much of currency you want to trade in units of base currency
1389
1392
  * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1390
1393
  * @param {object} [params] extra parameters specific to the exmo api endpoint
1394
+ * @param {float} [params.stopPrice] the price at which a trigger order is triggered at
1395
+ * @param {string} [params.timeInForce] *spot only* 'fok', 'ioc' or 'post_only'
1396
+ * @param {boolean} [params.postOnly] *spot only* true for post only orders
1391
1397
  * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
1392
1398
  */
1393
1399
  await this.loadMarkets();
1394
1400
  const market = this.market(symbol);
1395
- const prefix = (type === 'market') ? (type + '_') : '';
1396
- const orderType = prefix + side;
1397
1401
  const isMarket = (type === 'market') && (price === undefined);
1402
+ let marginMode = undefined;
1403
+ [marginMode, params] = this.handleMarginModeAndParams('createOrder', params);
1404
+ if (marginMode === 'cross') {
1405
+ throw new errors.BadRequest(this.id + ' only supports isolated margin');
1406
+ }
1407
+ const isSpot = (marginMode !== 'isolated');
1408
+ const triggerPrice = this.safeNumberN(params, ['triggerPrice', 'stopPrice', 'stop_price']);
1398
1409
  const request = {
1399
1410
  'pair': market['id'],
1400
1411
  // 'leverage': 2,
1401
1412
  'quantity': this.amountToPrecision(market['symbol'], amount),
1402
1413
  // spot - buy, sell, market_buy, market_sell, market_buy_total, market_sell_total
1403
1414
  // margin - limit_buy, limit_sell, market_buy, market_sell, stop_buy, stop_sell, stop_limit_buy, stop_limit_sell, trailing_stop_buy, trailing_stop_sell
1404
- 'type': orderType,
1405
- 'price': isMarket ? 0 : this.priceToPrecision(market['symbol'], price),
1406
1415
  // 'stop_price': this.priceToPrecision (symbol, stopPrice),
1407
1416
  // 'distance': 0, // distance for trailing stop orders
1408
1417
  // 'expire': 0, // expiration timestamp in UTC timezone for the order, unless expire is 0
1409
1418
  // 'client_id': 123, // optional, must be a positive integer
1410
1419
  // 'comment': '', // up to 50 latin symbols, whitespaces, underscores
1411
1420
  };
1412
- let method = 'privatePostOrderCreate';
1421
+ let method = isSpot ? 'privatePostOrderCreate' : 'privatePostMarginUserOrderCreate';
1413
1422
  let clientOrderId = this.safeValue2(params, 'client_id', 'clientOrderId');
1414
1423
  if (clientOrderId !== undefined) {
1415
1424
  clientOrderId = this.safeInteger2(params, 'client_id', 'clientOrderId');
@@ -1419,19 +1428,68 @@ class exmo extends exmo$1 {
1419
1428
  else {
1420
1429
  request['client_id'] = clientOrderId;
1421
1430
  }
1422
- params = this.omit(params, ['client_id', 'clientOrderId']);
1423
1431
  }
1424
- if ((type === 'stop') || (type === 'stop_limit') || (type === 'trailing_stop')) {
1425
- const stopPrice = this.safeNumber2(params, 'stop_price', 'stopPrice');
1426
- if (stopPrice === undefined) {
1427
- throw new errors.InvalidOrder(this.id + ' createOrder() requires a stopPrice extra param for a ' + type + ' order');
1432
+ const leverage = this.safeNumber(params, 'leverage');
1433
+ if (!isSpot && (leverage === undefined)) {
1434
+ throw new errors.ArgumentsRequired(this.id + ' createOrder requires an extra param params["leverage"] for margin orders');
1435
+ }
1436
+ params = this.omit(params, ['stopPrice', 'stop_price', 'triggerPrice', 'timeInForce', 'client_id', 'clientOrderId']);
1437
+ if (triggerPrice !== undefined) {
1438
+ if (isSpot) {
1439
+ if (type === 'limit') {
1440
+ throw new errors.BadRequest(this.id + ' createOrder () cannot create stop limit orders for spot, only stop market');
1441
+ }
1442
+ else {
1443
+ method = 'privatePostStopMarketOrderCreate';
1444
+ request['type'] = side;
1445
+ request['trigger_price'] = this.priceToPrecision(symbol, triggerPrice);
1446
+ }
1447
+ }
1448
+ else {
1449
+ request['stop_price'] = this.priceToPrecision(symbol, triggerPrice);
1450
+ if (type === 'limit') {
1451
+ request['type'] = 'stop_limit_' + side;
1452
+ }
1453
+ else if (type === 'market') {
1454
+ request['type'] = 'stop_' + side;
1455
+ }
1456
+ else {
1457
+ request['type'] = type;
1458
+ }
1459
+ }
1460
+ }
1461
+ else {
1462
+ if (isSpot) {
1463
+ const execType = this.safeString(params, 'exec_type');
1464
+ let isPostOnly = undefined;
1465
+ [isPostOnly, params] = this.handlePostOnly(type === 'market', execType === 'post_only', params);
1466
+ const timeInForce = this.safeString(params, 'timeInForce');
1467
+ request['price'] = isMarket ? 0 : this.priceToPrecision(market['symbol'], price);
1468
+ if (type === 'limit') {
1469
+ request['type'] = side;
1470
+ }
1471
+ else if (type === 'market') {
1472
+ request['type'] = 'market_' + side;
1473
+ }
1474
+ if (isPostOnly) {
1475
+ request['exec_type'] = 'post_only';
1476
+ }
1477
+ else if (timeInForce !== undefined) {
1478
+ request['exec_type'] = timeInForce;
1479
+ }
1428
1480
  }
1429
1481
  else {
1430
- params = this.omit(params, ['stopPrice', 'stop_price']);
1431
- request['stop_price'] = this.priceToPrecision(symbol, stopPrice);
1432
- method = 'privatePostMarginUserOrderCreate';
1482
+ if (type === 'limit' || type === 'market') {
1483
+ request['type'] = type + '_' + side;
1484
+ }
1485
+ else {
1486
+ request['type'] = type;
1487
+ }
1433
1488
  }
1434
1489
  }
1490
+ if (price !== undefined) {
1491
+ request['price'] = this.priceToPrecision(market['symbol'], price);
1492
+ }
1435
1493
  const response = await this[method](this.extend(request, params));
1436
1494
  return this.parseOrder(response, market);
1437
1495
  }
@@ -2240,6 +2298,19 @@ class exmo extends exmo$1 {
2240
2298
  if (response === undefined) {
2241
2299
  return undefined; // fallback to default error handler
2242
2300
  }
2301
+ if ('error' in response) {
2302
+ // error: {
2303
+ // code: '140434',
2304
+ // msg: "Your margin balance is not sufficient to place the order for '5 TON'. Please top up your margin wallet by '2.5 USDT'."
2305
+ // }
2306
+ const errorCode = this.safeValue(response, 'error', {});
2307
+ const messageError = this.safeString(errorCode, 'msg');
2308
+ const code = this.safeString(errorCode, 'code');
2309
+ const feedback = this.id + ' ' + body;
2310
+ this.throwExactlyMatchedException(this.exceptions['exact'], code, feedback);
2311
+ this.throwBroadlyMatchedException(this.exceptions['broad'], messageError, feedback);
2312
+ throw new errors.ExchangeError(feedback);
2313
+ }
2243
2314
  if (('result' in response) || ('errmsg' in response)) {
2244
2315
  //
2245
2316
  // {"result":false,"error":"Error 50052: Insufficient funds"}
@@ -4167,7 +4167,7 @@ class gate extends gate$1 {
4167
4167
  type = isMarketOrder ? 'market' : 'limit';
4168
4168
  side = Precise["default"].stringGt(amount, '0') ? 'buy' : 'sell';
4169
4169
  }
4170
- const rawStatus = this.safeStringN(order, ['status', 'finish_as', 'open']);
4170
+ const rawStatus = this.safeStringN(order, ['finish_as', 'status', 'open']);
4171
4171
  let timestamp = this.safeInteger(order, 'create_time_ms');
4172
4172
  if (timestamp === undefined) {
4173
4173
  timestamp = this.safeTimestamp2(order, 'create_time', 'ctime');
@@ -201,6 +201,7 @@ class latoken extends latoken$1 {
201
201
  'defaultType': 'spot',
202
202
  'types': {
203
203
  'wallet': 'ACCOUNT_TYPE_WALLET',
204
+ 'funding': 'ACCOUNT_TYPE_WALLET',
204
205
  'spot': 'ACCOUNT_TYPE_SPOT',
205
206
  },
206
207
  'accounts': {