ccxt 4.3.80__py2.py3-none-any.whl → 4.3.82__py2.py3-none-any.whl

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.
ccxt/__init__.py CHANGED
@@ -22,7 +22,7 @@
22
22
 
23
23
  # ----------------------------------------------------------------------------
24
24
 
25
- __version__ = '4.3.80'
25
+ __version__ = '4.3.82'
26
26
 
27
27
  # ----------------------------------------------------------------------------
28
28
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.3.80'
7
+ __version__ = '4.3.82'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  # -----------------------------------------------------------------------------
4
4
 
5
- __version__ = '4.3.80'
5
+ __version__ = '4.3.82'
6
6
 
7
7
  # -----------------------------------------------------------------------------
8
8
 
@@ -1210,6 +1210,18 @@ class bybit(Exchange, ImplicitAPI):
1210
1210
  optionType = self.safe_string(optionParts, 3)
1211
1211
  datetime = self.convert_expire_date(expiry)
1212
1212
  timestamp = self.parse8601(datetime)
1213
+ amountPrecision = None
1214
+ pricePrecision = None
1215
+ # hard coded amount and price precisions from fetchOptionMarkets
1216
+ if base == 'BTC':
1217
+ amountPrecision = self.parse_number('0.01')
1218
+ pricePrecision = self.parse_number('5')
1219
+ elif base == 'ETH':
1220
+ amountPrecision = self.parse_number('0.1')
1221
+ pricePrecision = self.parse_number('0.1')
1222
+ elif base == 'SOL':
1223
+ amountPrecision = self.parse_number('1')
1224
+ pricePrecision = self.parse_number('0.01')
1213
1225
  return {
1214
1226
  'id': base + '-' + self.convert_expire_date_to_market_id_date(expiry) + '-' + strike + '-' + optionType,
1215
1227
  'symbol': base + '/' + quote + ':' + settle + '-' + expiry + '-' + strike + '-' + optionType,
@@ -1229,14 +1241,14 @@ class bybit(Exchange, ImplicitAPI):
1229
1241
  'option': True,
1230
1242
  'margin': False,
1231
1243
  'contract': True,
1232
- 'contractSize': None,
1244
+ 'contractSize': self.parse_number('1'),
1233
1245
  'expiry': timestamp,
1234
1246
  'expiryDatetime': datetime,
1235
1247
  'optionType': 'call' if (optionType == 'C') else 'put',
1236
1248
  'strike': self.parse_number(strike),
1237
1249
  'precision': {
1238
- 'amount': None,
1239
- 'price': None,
1250
+ 'amount': amountPrecision,
1251
+ 'price': pricePrecision,
1240
1252
  },
1241
1253
  'limits': {
1242
1254
  'amount': {
@@ -1271,6 +1283,30 @@ class bybit(Exchange, ImplicitAPI):
1271
1283
  return [type, params]
1272
1284
  return [subType, params]
1273
1285
 
1286
+ def get_amount(self, symbol: str, amount: float):
1287
+ # some markets like options might not have the precision available
1288
+ # and we shouldn't crash in those cases
1289
+ market = self.market(symbol)
1290
+ emptyPrecisionAmount = (market['precision']['amount'] is None)
1291
+ amountString = self.number_to_string(amount)
1292
+ if not emptyPrecisionAmount and (amountString != '0'):
1293
+ return self.amount_to_precision(symbol, amount)
1294
+ return amountString
1295
+
1296
+ def get_price(self, symbol: str, price: str):
1297
+ market = self.market(symbol)
1298
+ emptyPrecisionPrice = (market['precision']['price'] is None)
1299
+ if not emptyPrecisionPrice:
1300
+ return self.price_to_precision(symbol, price)
1301
+ return price
1302
+
1303
+ def get_cost(self, symbol: str, cost: str):
1304
+ market = self.market(symbol)
1305
+ emptyPrecisionPrice = (market['precision']['price'] is None)
1306
+ if not emptyPrecisionPrice:
1307
+ return self.cost_to_precision(symbol, cost)
1308
+ return cost
1309
+
1274
1310
  async def fetch_time(self, params={}):
1275
1311
  """
1276
1312
  fetches the current integer timestamp in milliseconds from the exchange server
@@ -1848,7 +1884,7 @@ class bybit(Exchange, ImplicitAPI):
1848
1884
  'inverse': None,
1849
1885
  'taker': self.safe_number(market, 'takerFee', self.parse_number('0.0006')),
1850
1886
  'maker': self.safe_number(market, 'makerFee', self.parse_number('0.0001')),
1851
- 'contractSize': self.safe_number(lotSizeFilter, 'minOrderQty'),
1887
+ 'contractSize': self.parse_number('1'),
1852
1888
  'expiry': expiry,
1853
1889
  'expiryDatetime': self.iso8601(expiry),
1854
1890
  'strike': self.parse_number(strike),
@@ -3474,24 +3510,26 @@ class bybit(Exchange, ImplicitAPI):
3474
3510
  isLimit = lowerCaseType == 'limit'
3475
3511
  isBuy = side == 'buy'
3476
3512
  isAlternativeEndpoint = defaultMethod == 'privatePostV5PositionTradingStop'
3513
+ amountString = self.get_amount(symbol, amount)
3514
+ priceString = self.get_price(symbol, self.number_to_string(price)) if (price is not None) else None
3477
3515
  if isTrailingAmountOrder or isAlternativeEndpoint:
3478
3516
  if isStopLoss or isTakeProfit or isTriggerOrder or market['spot']:
3479
3517
  raise InvalidOrder(self.id + ' the API endpoint used only supports contract trailingAmount, stopLossPrice and takeProfitPrice orders')
3480
3518
  if isStopLossTriggerOrder or isTakeProfitTriggerOrder:
3481
3519
  if isStopLossTriggerOrder:
3482
- request['stopLoss'] = self.price_to_precision(symbol, stopLossTriggerPrice)
3520
+ request['stopLoss'] = self.get_price(symbol, stopLossTriggerPrice)
3483
3521
  if isLimit:
3484
3522
  request['tpslMode'] = 'Partial'
3485
3523
  request['slOrderType'] = 'Limit'
3486
- request['slLimitPrice'] = self.price_to_precision(symbol, price)
3487
- request['slSize'] = self.amount_to_precision(symbol, amount)
3524
+ request['slLimitPrice'] = priceString
3525
+ request['slSize'] = amountString
3488
3526
  elif isTakeProfitTriggerOrder:
3489
- request['takeProfit'] = self.price_to_precision(symbol, takeProfitTriggerPrice)
3527
+ request['takeProfit'] = self.get_price(symbol, takeProfitTriggerPrice)
3490
3528
  if isLimit:
3491
3529
  request['tpslMode'] = 'Partial'
3492
3530
  request['tpOrderType'] = 'Limit'
3493
- request['tpLimitPrice'] = self.price_to_precision(symbol, price)
3494
- request['tpSize'] = self.amount_to_precision(symbol, amount)
3531
+ request['tpLimitPrice'] = priceString
3532
+ request['tpSize'] = amountString
3495
3533
  else:
3496
3534
  request['side'] = self.capitalize(side)
3497
3535
  request['orderType'] = self.capitalize(lowerCaseType)
@@ -3519,7 +3557,7 @@ class bybit(Exchange, ImplicitAPI):
3519
3557
  # mandatory field for options
3520
3558
  request['orderLinkId'] = self.uuid16()
3521
3559
  if isLimit:
3522
- request['price'] = self.price_to_precision(symbol, price)
3560
+ request['price'] = priceString
3523
3561
  if market['spot']:
3524
3562
  request['category'] = 'spot'
3525
3563
  elif market['linear']:
@@ -3540,14 +3578,12 @@ class bybit(Exchange, ImplicitAPI):
3540
3578
  if cost is not None:
3541
3579
  orderCost = cost
3542
3580
  else:
3543
- amountString = self.number_to_string(amount)
3544
- priceString = self.number_to_string(price)
3545
3581
  quoteAmount = Precise.string_mul(amountString, priceString)
3546
3582
  orderCost = quoteAmount
3547
- request['qty'] = self.cost_to_precision(symbol, orderCost)
3583
+ request['qty'] = self.get_cost(symbol, orderCost)
3548
3584
  else:
3549
3585
  request['marketUnit'] = 'baseCoin'
3550
- request['qty'] = self.amount_to_precision(symbol, amount)
3586
+ request['qty'] = amountString
3551
3587
  elif market['spot'] and (type == 'market') and (side == 'buy'):
3552
3588
  # classic accounts
3553
3589
  # for market buy it requires the amount of quote currency to spend
@@ -3557,22 +3593,17 @@ class bybit(Exchange, ImplicitAPI):
3557
3593
  if (price is None) and (cost is None):
3558
3594
  raise InvalidOrder(self.id + ' createOrder() requires the price argument for market buy orders to calculate the total cost to spend(amount * price), alternatively set the createMarketBuyOrderRequiresPrice option or param to False and pass the cost to spend in the amount argument')
3559
3595
  else:
3560
- amountString = self.number_to_string(amount)
3561
- priceString = self.number_to_string(price)
3562
3596
  quoteAmount = Precise.string_mul(amountString, priceString)
3563
3597
  costRequest = cost if (cost is not None) else quoteAmount
3564
- request['qty'] = self.cost_to_precision(symbol, costRequest)
3598
+ request['qty'] = self.get_cost(symbol, costRequest)
3565
3599
  else:
3566
- request['qty'] = self.cost_to_precision(symbol, amount)
3600
+ request['qty'] = self.get_cost(symbol, self.number_to_string(amount))
3567
3601
  else:
3568
3602
  if not isTrailingAmountOrder and not isAlternativeEndpoint:
3569
- if market['option']:
3570
- request['qty'] = self.number_to_string(amount)
3571
- else:
3572
- request['qty'] = self.amount_to_precision(symbol, amount)
3603
+ request['qty'] = amountString
3573
3604
  if isTrailingAmountOrder:
3574
3605
  if trailingTriggerPrice is not None:
3575
- request['activePrice'] = self.price_to_precision(symbol, trailingTriggerPrice)
3606
+ request['activePrice'] = self.get_price(symbol, trailingTriggerPrice)
3576
3607
  request['trailingStop'] = trailingAmount
3577
3608
  elif isTriggerOrder and not isAlternativeEndpoint:
3578
3609
  triggerDirection = self.safe_string(params, 'triggerDirection')
@@ -3585,32 +3616,32 @@ class bybit(Exchange, ImplicitAPI):
3585
3616
  raise ArgumentsRequired(self.id + ' stop/trigger orders require a triggerDirection parameter, either "above" or "below" to determine the direction of the trigger.')
3586
3617
  isAsending = ((triggerDirection == 'above') or (triggerDirection == '1'))
3587
3618
  request['triggerDirection'] = 1 if isAsending else 2
3588
- request['triggerPrice'] = self.price_to_precision(symbol, triggerPrice)
3619
+ request['triggerPrice'] = self.get_price(symbol, triggerPrice)
3589
3620
  elif (isStopLossTriggerOrder or isTakeProfitTriggerOrder) and not isAlternativeEndpoint:
3590
3621
  if isBuy:
3591
3622
  request['triggerDirection'] = 1 if isStopLossTriggerOrder else 2
3592
3623
  else:
3593
3624
  request['triggerDirection'] = 2 if isStopLossTriggerOrder else 1
3594
3625
  triggerPrice = stopLossTriggerPrice if isStopLossTriggerOrder else takeProfitTriggerPrice
3595
- request['triggerPrice'] = self.price_to_precision(symbol, triggerPrice)
3626
+ request['triggerPrice'] = self.get_price(symbol, triggerPrice)
3596
3627
  request['reduceOnly'] = True
3597
3628
  if (isStopLoss or isTakeProfit) and not isAlternativeEndpoint:
3598
3629
  if isStopLoss:
3599
3630
  slTriggerPrice = self.safe_value_2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss)
3600
- request['stopLoss'] = self.price_to_precision(symbol, slTriggerPrice)
3631
+ request['stopLoss'] = self.get_price(symbol, slTriggerPrice)
3601
3632
  slLimitPrice = self.safe_value(stopLoss, 'price')
3602
3633
  if slLimitPrice is not None:
3603
3634
  request['tpslMode'] = 'Partial'
3604
3635
  request['slOrderType'] = 'Limit'
3605
- request['slLimitPrice'] = self.price_to_precision(symbol, slLimitPrice)
3636
+ request['slLimitPrice'] = self.get_price(symbol, slLimitPrice)
3606
3637
  if isTakeProfit:
3607
3638
  tpTriggerPrice = self.safe_value_2(takeProfit, 'triggerPrice', 'stopPrice', takeProfit)
3608
- request['takeProfit'] = self.price_to_precision(symbol, tpTriggerPrice)
3639
+ request['takeProfit'] = self.get_price(symbol, tpTriggerPrice)
3609
3640
  tpLimitPrice = self.safe_value(takeProfit, 'price')
3610
3641
  if tpLimitPrice is not None:
3611
3642
  request['tpslMode'] = 'Partial'
3612
3643
  request['tpOrderType'] = 'Limit'
3613
- request['tpLimitPrice'] = self.price_to_precision(symbol, tpLimitPrice)
3644
+ request['tpLimitPrice'] = self.get_price(symbol, tpLimitPrice)
3614
3645
  params = self.omit(params, ['stopPrice', 'timeInForce', 'stopLossPrice', 'takeProfitPrice', 'postOnly', 'clientOrderId', 'triggerPrice', 'stopLoss', 'takeProfit', 'trailingAmount', 'trailingTriggerPrice'])
3615
3646
  return self.extend(request, params)
3616
3647
 
@@ -3710,7 +3741,7 @@ class bybit(Exchange, ImplicitAPI):
3710
3741
  'side': self.capitalize(side),
3711
3742
  'orderType': self.capitalize(lowerCaseType), # limit or market
3712
3743
  'timeInForce': 'GoodTillCancel', # ImmediateOrCancel, FillOrKill, PostOnly
3713
- 'orderQty': self.amount_to_precision(symbol, amount),
3744
+ 'orderQty': self.get_amount(symbol, amount),
3714
3745
  # 'takeProfit': 123.45, # take profit price, only take effect upon opening the position
3715
3746
  # 'stopLoss': 123.45, # stop loss price, only take effect upon opening the position
3716
3747
  # 'reduceOnly': False, # reduce only, required for linear orders
@@ -3728,7 +3759,7 @@ class bybit(Exchange, ImplicitAPI):
3728
3759
  isMarket = lowerCaseType == 'market'
3729
3760
  isLimit = lowerCaseType == 'limit'
3730
3761
  if isLimit is not None:
3731
- request['orderPrice'] = self.price_to_precision(symbol, price)
3762
+ request['orderPrice'] = self.get_price(symbol, self.number_to_string(price))
3732
3763
  exchangeSpecificParam = self.safe_string(params, 'time_in_force')
3733
3764
  timeInForce = self.safe_string_lower(params, 'timeInForce')
3734
3765
  postOnly = self.is_post_only(isMarket, exchangeSpecificParam == 'PostOnly', params)
@@ -3755,17 +3786,17 @@ class bybit(Exchange, ImplicitAPI):
3755
3786
  request['orderFilter'] = 'StopOrder'
3756
3787
  request['trigger_by'] = 'LastPrice'
3757
3788
  stopPx = stopLossTriggerPrice if isStopLossTriggerOrder else takeProfitTriggerPrice
3758
- preciseStopPrice = self.price_to_precision(symbol, stopPx)
3789
+ preciseStopPrice = self.get_price(symbol, stopPx)
3759
3790
  request['triggerPrice'] = preciseStopPrice
3760
3791
  delta = self.number_to_string(market['precision']['price'])
3761
3792
  request['basePrice'] = Precise.string_sub(preciseStopPrice, delta) if isStopLossTriggerOrder else Precise.string_add(preciseStopPrice, delta)
3762
3793
  elif isStopLoss or isTakeProfit:
3763
3794
  if isStopLoss:
3764
3795
  slTriggerPrice = self.safe_value_2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss)
3765
- request['stopLoss'] = self.price_to_precision(symbol, slTriggerPrice)
3796
+ request['stopLoss'] = self.get_price(symbol, slTriggerPrice)
3766
3797
  if isTakeProfit:
3767
3798
  tpTriggerPrice = self.safe_value_2(takeProfit, 'triggerPrice', 'stopPrice', takeProfit)
3768
- request['takeProfit'] = self.price_to_precision(symbol, tpTriggerPrice)
3799
+ request['takeProfit'] = self.get_price(symbol, tpTriggerPrice)
3769
3800
  else:
3770
3801
  request['orderFilter'] = 'Order'
3771
3802
  clientOrderId = self.safe_string(params, 'clientOrderId')
@@ -3816,9 +3847,9 @@ class bybit(Exchange, ImplicitAPI):
3816
3847
  'orderId': id,
3817
3848
  }
3818
3849
  if amount is not None:
3819
- request['orderQty'] = self.amount_to_precision(symbol, amount)
3850
+ request['orderQty'] = self.get_amount(symbol, amount)
3820
3851
  if price is not None:
3821
- request['orderPrice'] = self.price_to_precision(symbol, price)
3852
+ request['orderPrice'] = self.get_price(symbol, price)
3822
3853
  response = None
3823
3854
  if market['option']:
3824
3855
  response = await self.privatePostOptionUsdcOpenapiPrivateV1ReplaceOrder(self.extend(request, params))
@@ -3833,11 +3864,11 @@ class bybit(Exchange, ImplicitAPI):
3833
3864
  if isStopOrder:
3834
3865
  request['orderFilter'] = 'StopOrder' if isStop else 'Order'
3835
3866
  if triggerPrice is not None:
3836
- request['triggerPrice'] = self.price_to_precision(symbol, triggerPrice)
3867
+ request['triggerPrice'] = self.get_price(symbol, triggerPrice)
3837
3868
  if stopLossPrice is not None:
3838
- request['stopLoss'] = self.price_to_precision(symbol, stopLossPrice)
3869
+ request['stopLoss'] = self.get_price(symbol, stopLossPrice)
3839
3870
  if takeProfitPrice is not None:
3840
- request['takeProfit'] = self.price_to_precision(symbol, takeProfitPrice)
3871
+ request['takeProfit'] = self.get_price(symbol, takeProfitPrice)
3841
3872
  params = self.omit(params, ['stop', 'stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice'])
3842
3873
  response = await self.privatePostPerpetualUsdcOpenapiPrivateV1ReplaceOrder(self.extend(request, params))
3843
3874
  #
@@ -3880,11 +3911,9 @@ class bybit(Exchange, ImplicitAPI):
3880
3911
  elif market['option']:
3881
3912
  request['category'] = 'option'
3882
3913
  if amount is not None:
3883
- request['qty'] = self.amount_to_precision(symbol, amount)
3914
+ request['qty'] = self.get_amount(symbol, amount)
3884
3915
  if price is not None:
3885
- request['price'] = self.price_to_precision(symbol, price)
3886
- if amount is not None:
3887
- request['qty'] = self.amount_to_precision(symbol, amount)
3916
+ request['price'] = self.get_price(symbol, self.number_to_string(price))
3888
3917
  triggerPrice = self.safe_string_2(params, 'triggerPrice', 'stopPrice')
3889
3918
  stopLossTriggerPrice = self.safe_string(params, 'stopLossPrice')
3890
3919
  takeProfitTriggerPrice = self.safe_string(params, 'takeProfitPrice')
@@ -3897,20 +3926,20 @@ class bybit(Exchange, ImplicitAPI):
3897
3926
  if isStopLossTriggerOrder or isTakeProfitTriggerOrder:
3898
3927
  triggerPrice = stopLossTriggerPrice if isStopLossTriggerOrder else takeProfitTriggerPrice
3899
3928
  if triggerPrice is not None:
3900
- triggerPriceRequest = triggerPrice if (triggerPrice == '0') else self.price_to_precision(symbol, triggerPrice)
3929
+ triggerPriceRequest = triggerPrice if (triggerPrice == '0') else self.get_price(symbol, triggerPrice)
3901
3930
  request['triggerPrice'] = triggerPriceRequest
3902
3931
  triggerBy = self.safe_string(params, 'triggerBy', 'LastPrice')
3903
3932
  request['triggerBy'] = triggerBy
3904
3933
  if isStopLoss or isTakeProfit:
3905
3934
  if isStopLoss:
3906
3935
  slTriggerPrice = self.safe_string_2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss)
3907
- stopLossRequest = slTriggerPrice if (slTriggerPrice == '0') else self.price_to_precision(symbol, slTriggerPrice)
3936
+ stopLossRequest = slTriggerPrice if (slTriggerPrice == '0') else self.get_price(symbol, slTriggerPrice)
3908
3937
  request['stopLoss'] = stopLossRequest
3909
3938
  slTriggerBy = self.safe_string(params, 'slTriggerBy', 'LastPrice')
3910
3939
  request['slTriggerBy'] = slTriggerBy
3911
3940
  if isTakeProfit:
3912
3941
  tpTriggerPrice = self.safe_string_2(takeProfit, 'triggerPrice', 'stopPrice', takeProfit)
3913
- takeProfitRequest = tpTriggerPrice if (tpTriggerPrice == '0') else self.price_to_precision(symbol, tpTriggerPrice)
3942
+ takeProfitRequest = tpTriggerPrice if (tpTriggerPrice == '0') else self.get_price(symbol, tpTriggerPrice)
3914
3943
  request['takeProfit'] = takeProfitRequest
3915
3944
  tpTriggerBy = self.safe_string(params, 'tpTriggerBy', 'LastPrice')
3916
3945
  request['tpTriggerBy'] = tpTriggerBy
@@ -3946,9 +3975,9 @@ class bybit(Exchange, ImplicitAPI):
3946
3975
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
3947
3976
  """
3948
3977
  await self.load_markets()
3978
+ market = self.market(symbol)
3949
3979
  if symbol is None:
3950
3980
  raise ArgumentsRequired(self.id + ' editOrder() requires a symbol argument')
3951
- market = self.market(symbol)
3952
3981
  enableUnifiedMargin, enableUnifiedAccount = await self.is_unified_enabled()
3953
3982
  isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
3954
3983
  isUsdcSettled = market['settle'] == 'USDC'
@@ -5732,6 +5761,8 @@ class bybit(Exchange, ImplicitAPI):
5732
5761
  :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
5733
5762
  """
5734
5763
  tag, params = self.handle_withdraw_tag_and_params(tag, params)
5764
+ accountType = None
5765
+ accountType, params = self.handle_option_and_params(params, 'withdraw', 'accountType', 'SPOT')
5735
5766
  await self.load_markets()
5736
5767
  self.check_address(address)
5737
5768
  currency = self.currency(code)
@@ -5740,6 +5771,7 @@ class bybit(Exchange, ImplicitAPI):
5740
5771
  'amount': self.number_to_string(amount),
5741
5772
  'address': address,
5742
5773
  'timestamp': self.milliseconds(),
5774
+ 'accountType': accountType,
5743
5775
  }
5744
5776
  if tag is not None:
5745
5777
  request['tag'] = tag
@@ -1239,7 +1239,8 @@ class wavesexchange(Exchange, ImplicitAPI):
1239
1239
  if (isMarketOrder) and (price is None):
1240
1240
  raise InvalidOrder(self.id + ' createOrder() requires a price argument for ' + type + ' orders to determine the max price for buy and the min price for sell')
1241
1241
  timestamp = self.milliseconds()
1242
- defaultExpiryDelta = self.safe_integer(self.options, 'createOrderDefaultExpiry', 2419200000)
1242
+ defaultExpiryDelta = None
1243
+ defaultExpiryDelta, params = self.handle_option_and_params(params, 'createOrder', 'defaultExpiry', self.safe_integer(self.options, 'createOrderDefaultExpiry', 2419200000))
1243
1244
  expiration = self.sum(timestamp, defaultExpiryDelta)
1244
1245
  matcherFees = await self.get_fees_for_asset(symbol, side, amount, price)
1245
1246
  # {
@@ -1374,11 +1375,11 @@ class wavesexchange(Exchange, ImplicitAPI):
1374
1375
  # }
1375
1376
  #
1376
1377
  if isMarketOrder:
1377
- response = await self.matcherPostMatcherOrderbookMarket(body)
1378
+ response = await self.matcherPostMatcherOrderbookMarket(self.extend(body, params))
1378
1379
  value = self.safe_dict(response, 'message')
1379
1380
  return self.parse_order(value, market)
1380
1381
  else:
1381
- response = await self.matcherPostMatcherOrderbook(body)
1382
+ response = await self.matcherPostMatcherOrderbook(self.extend(body, params))
1382
1383
  value = self.safe_dict(response, 'message')
1383
1384
  return self.parse_order(value, market)
1384
1385
 
@@ -249,6 +249,7 @@ class yobit(Exchange, ImplicitAPI):
249
249
  'XIN': 'XINCoin',
250
250
  'XMT': 'SummitCoin',
251
251
  'XRA': 'Ratecoin',
252
+ 'BCHN': 'BSV',
252
253
  },
253
254
  'options': {
254
255
  'maxUrlLength': 2048,
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.3.80'
7
+ __version__ = '4.3.82'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -1472,14 +1472,6 @@ class Exchange(object):
1472
1472
  return error
1473
1473
  return result
1474
1474
 
1475
- def check_address(self, address):
1476
- """Checks an address is not the same character repeated or an empty sequence"""
1477
- if address is None:
1478
- raise InvalidAddress(self.id + ' address is None')
1479
- if all(letter == address[0] for letter in address) or len(address) < self.minFundingAddressLength or ' ' in address:
1480
- raise InvalidAddress(self.id + ' address is invalid or has less than ' + str(self.minFundingAddressLength) + ' characters: "' + str(address) + '"')
1481
- return address
1482
-
1483
1475
  def precision_from_string(self, str):
1484
1476
  # support string formats like '1e-4'
1485
1477
  if 'e' in str or 'E' in str:
@@ -2312,6 +2304,16 @@ class Exchange(object):
2312
2304
  if proxyAgentSet and proxyUrlSet:
2313
2305
  raise InvalidProxySettings(self.id + ' you have multiple conflicting proxy settings, please use only one from : proxyUrl, httpProxy, httpsProxy, socksProxy')
2314
2306
 
2307
+ def check_address(self, address: Str = None):
2308
+ if address is None:
2309
+ raise InvalidAddress(self.id + ' address is None')
2310
+ # check the address is not the same letter like 'aaaaa' nor too short nor has a space
2311
+ uniqChars = (self.unique(self.string_to_chars_array(address)))
2312
+ length = len(uniqChars) # py transpiler trick
2313
+ if length == 1 or len(address) < self.minFundingAddressLength or address.find(' ') > -1:
2314
+ raise InvalidAddress(self.id + ' address is invalid or has less than ' + str(self.minFundingAddressLength) + ' characters: "' + str(address) + '"')
2315
+ return address
2316
+
2315
2317
  def find_message_hashes(self, client, element: str):
2316
2318
  result = []
2317
2319
  messageHashes = list(client.futures.keys())
@@ -3994,7 +3996,9 @@ class Exchange(object):
3994
3996
  ]
3995
3997
 
3996
3998
  def get_list_from_object_values(self, objects, key: IndexType):
3997
- newArray = self.to_array(objects)
3999
+ newArray = objects
4000
+ if not isinstance(objects, list):
4001
+ newArray = self.to_array(objects)
3998
4002
  results = []
3999
4003
  for i in range(0, len(newArray)):
4000
4004
  results.append(newArray[i][key])
ccxt/bybit.py CHANGED
@@ -1209,6 +1209,18 @@ class bybit(Exchange, ImplicitAPI):
1209
1209
  optionType = self.safe_string(optionParts, 3)
1210
1210
  datetime = self.convert_expire_date(expiry)
1211
1211
  timestamp = self.parse8601(datetime)
1212
+ amountPrecision = None
1213
+ pricePrecision = None
1214
+ # hard coded amount and price precisions from fetchOptionMarkets
1215
+ if base == 'BTC':
1216
+ amountPrecision = self.parse_number('0.01')
1217
+ pricePrecision = self.parse_number('5')
1218
+ elif base == 'ETH':
1219
+ amountPrecision = self.parse_number('0.1')
1220
+ pricePrecision = self.parse_number('0.1')
1221
+ elif base == 'SOL':
1222
+ amountPrecision = self.parse_number('1')
1223
+ pricePrecision = self.parse_number('0.01')
1212
1224
  return {
1213
1225
  'id': base + '-' + self.convert_expire_date_to_market_id_date(expiry) + '-' + strike + '-' + optionType,
1214
1226
  'symbol': base + '/' + quote + ':' + settle + '-' + expiry + '-' + strike + '-' + optionType,
@@ -1228,14 +1240,14 @@ class bybit(Exchange, ImplicitAPI):
1228
1240
  'option': True,
1229
1241
  'margin': False,
1230
1242
  'contract': True,
1231
- 'contractSize': None,
1243
+ 'contractSize': self.parse_number('1'),
1232
1244
  'expiry': timestamp,
1233
1245
  'expiryDatetime': datetime,
1234
1246
  'optionType': 'call' if (optionType == 'C') else 'put',
1235
1247
  'strike': self.parse_number(strike),
1236
1248
  'precision': {
1237
- 'amount': None,
1238
- 'price': None,
1249
+ 'amount': amountPrecision,
1250
+ 'price': pricePrecision,
1239
1251
  },
1240
1252
  'limits': {
1241
1253
  'amount': {
@@ -1270,6 +1282,30 @@ class bybit(Exchange, ImplicitAPI):
1270
1282
  return [type, params]
1271
1283
  return [subType, params]
1272
1284
 
1285
+ def get_amount(self, symbol: str, amount: float):
1286
+ # some markets like options might not have the precision available
1287
+ # and we shouldn't crash in those cases
1288
+ market = self.market(symbol)
1289
+ emptyPrecisionAmount = (market['precision']['amount'] is None)
1290
+ amountString = self.number_to_string(amount)
1291
+ if not emptyPrecisionAmount and (amountString != '0'):
1292
+ return self.amount_to_precision(symbol, amount)
1293
+ return amountString
1294
+
1295
+ def get_price(self, symbol: str, price: str):
1296
+ market = self.market(symbol)
1297
+ emptyPrecisionPrice = (market['precision']['price'] is None)
1298
+ if not emptyPrecisionPrice:
1299
+ return self.price_to_precision(symbol, price)
1300
+ return price
1301
+
1302
+ def get_cost(self, symbol: str, cost: str):
1303
+ market = self.market(symbol)
1304
+ emptyPrecisionPrice = (market['precision']['price'] is None)
1305
+ if not emptyPrecisionPrice:
1306
+ return self.cost_to_precision(symbol, cost)
1307
+ return cost
1308
+
1273
1309
  def fetch_time(self, params={}):
1274
1310
  """
1275
1311
  fetches the current integer timestamp in milliseconds from the exchange server
@@ -1847,7 +1883,7 @@ class bybit(Exchange, ImplicitAPI):
1847
1883
  'inverse': None,
1848
1884
  'taker': self.safe_number(market, 'takerFee', self.parse_number('0.0006')),
1849
1885
  'maker': self.safe_number(market, 'makerFee', self.parse_number('0.0001')),
1850
- 'contractSize': self.safe_number(lotSizeFilter, 'minOrderQty'),
1886
+ 'contractSize': self.parse_number('1'),
1851
1887
  'expiry': expiry,
1852
1888
  'expiryDatetime': self.iso8601(expiry),
1853
1889
  'strike': self.parse_number(strike),
@@ -3473,24 +3509,26 @@ class bybit(Exchange, ImplicitAPI):
3473
3509
  isLimit = lowerCaseType == 'limit'
3474
3510
  isBuy = side == 'buy'
3475
3511
  isAlternativeEndpoint = defaultMethod == 'privatePostV5PositionTradingStop'
3512
+ amountString = self.get_amount(symbol, amount)
3513
+ priceString = self.get_price(symbol, self.number_to_string(price)) if (price is not None) else None
3476
3514
  if isTrailingAmountOrder or isAlternativeEndpoint:
3477
3515
  if isStopLoss or isTakeProfit or isTriggerOrder or market['spot']:
3478
3516
  raise InvalidOrder(self.id + ' the API endpoint used only supports contract trailingAmount, stopLossPrice and takeProfitPrice orders')
3479
3517
  if isStopLossTriggerOrder or isTakeProfitTriggerOrder:
3480
3518
  if isStopLossTriggerOrder:
3481
- request['stopLoss'] = self.price_to_precision(symbol, stopLossTriggerPrice)
3519
+ request['stopLoss'] = self.get_price(symbol, stopLossTriggerPrice)
3482
3520
  if isLimit:
3483
3521
  request['tpslMode'] = 'Partial'
3484
3522
  request['slOrderType'] = 'Limit'
3485
- request['slLimitPrice'] = self.price_to_precision(symbol, price)
3486
- request['slSize'] = self.amount_to_precision(symbol, amount)
3523
+ request['slLimitPrice'] = priceString
3524
+ request['slSize'] = amountString
3487
3525
  elif isTakeProfitTriggerOrder:
3488
- request['takeProfit'] = self.price_to_precision(symbol, takeProfitTriggerPrice)
3526
+ request['takeProfit'] = self.get_price(symbol, takeProfitTriggerPrice)
3489
3527
  if isLimit:
3490
3528
  request['tpslMode'] = 'Partial'
3491
3529
  request['tpOrderType'] = 'Limit'
3492
- request['tpLimitPrice'] = self.price_to_precision(symbol, price)
3493
- request['tpSize'] = self.amount_to_precision(symbol, amount)
3530
+ request['tpLimitPrice'] = priceString
3531
+ request['tpSize'] = amountString
3494
3532
  else:
3495
3533
  request['side'] = self.capitalize(side)
3496
3534
  request['orderType'] = self.capitalize(lowerCaseType)
@@ -3518,7 +3556,7 @@ class bybit(Exchange, ImplicitAPI):
3518
3556
  # mandatory field for options
3519
3557
  request['orderLinkId'] = self.uuid16()
3520
3558
  if isLimit:
3521
- request['price'] = self.price_to_precision(symbol, price)
3559
+ request['price'] = priceString
3522
3560
  if market['spot']:
3523
3561
  request['category'] = 'spot'
3524
3562
  elif market['linear']:
@@ -3539,14 +3577,12 @@ class bybit(Exchange, ImplicitAPI):
3539
3577
  if cost is not None:
3540
3578
  orderCost = cost
3541
3579
  else:
3542
- amountString = self.number_to_string(amount)
3543
- priceString = self.number_to_string(price)
3544
3580
  quoteAmount = Precise.string_mul(amountString, priceString)
3545
3581
  orderCost = quoteAmount
3546
- request['qty'] = self.cost_to_precision(symbol, orderCost)
3582
+ request['qty'] = self.get_cost(symbol, orderCost)
3547
3583
  else:
3548
3584
  request['marketUnit'] = 'baseCoin'
3549
- request['qty'] = self.amount_to_precision(symbol, amount)
3585
+ request['qty'] = amountString
3550
3586
  elif market['spot'] and (type == 'market') and (side == 'buy'):
3551
3587
  # classic accounts
3552
3588
  # for market buy it requires the amount of quote currency to spend
@@ -3556,22 +3592,17 @@ class bybit(Exchange, ImplicitAPI):
3556
3592
  if (price is None) and (cost is None):
3557
3593
  raise InvalidOrder(self.id + ' createOrder() requires the price argument for market buy orders to calculate the total cost to spend(amount * price), alternatively set the createMarketBuyOrderRequiresPrice option or param to False and pass the cost to spend in the amount argument')
3558
3594
  else:
3559
- amountString = self.number_to_string(amount)
3560
- priceString = self.number_to_string(price)
3561
3595
  quoteAmount = Precise.string_mul(amountString, priceString)
3562
3596
  costRequest = cost if (cost is not None) else quoteAmount
3563
- request['qty'] = self.cost_to_precision(symbol, costRequest)
3597
+ request['qty'] = self.get_cost(symbol, costRequest)
3564
3598
  else:
3565
- request['qty'] = self.cost_to_precision(symbol, amount)
3599
+ request['qty'] = self.get_cost(symbol, self.number_to_string(amount))
3566
3600
  else:
3567
3601
  if not isTrailingAmountOrder and not isAlternativeEndpoint:
3568
- if market['option']:
3569
- request['qty'] = self.number_to_string(amount)
3570
- else:
3571
- request['qty'] = self.amount_to_precision(symbol, amount)
3602
+ request['qty'] = amountString
3572
3603
  if isTrailingAmountOrder:
3573
3604
  if trailingTriggerPrice is not None:
3574
- request['activePrice'] = self.price_to_precision(symbol, trailingTriggerPrice)
3605
+ request['activePrice'] = self.get_price(symbol, trailingTriggerPrice)
3575
3606
  request['trailingStop'] = trailingAmount
3576
3607
  elif isTriggerOrder and not isAlternativeEndpoint:
3577
3608
  triggerDirection = self.safe_string(params, 'triggerDirection')
@@ -3584,32 +3615,32 @@ class bybit(Exchange, ImplicitAPI):
3584
3615
  raise ArgumentsRequired(self.id + ' stop/trigger orders require a triggerDirection parameter, either "above" or "below" to determine the direction of the trigger.')
3585
3616
  isAsending = ((triggerDirection == 'above') or (triggerDirection == '1'))
3586
3617
  request['triggerDirection'] = 1 if isAsending else 2
3587
- request['triggerPrice'] = self.price_to_precision(symbol, triggerPrice)
3618
+ request['triggerPrice'] = self.get_price(symbol, triggerPrice)
3588
3619
  elif (isStopLossTriggerOrder or isTakeProfitTriggerOrder) and not isAlternativeEndpoint:
3589
3620
  if isBuy:
3590
3621
  request['triggerDirection'] = 1 if isStopLossTriggerOrder else 2
3591
3622
  else:
3592
3623
  request['triggerDirection'] = 2 if isStopLossTriggerOrder else 1
3593
3624
  triggerPrice = stopLossTriggerPrice if isStopLossTriggerOrder else takeProfitTriggerPrice
3594
- request['triggerPrice'] = self.price_to_precision(symbol, triggerPrice)
3625
+ request['triggerPrice'] = self.get_price(symbol, triggerPrice)
3595
3626
  request['reduceOnly'] = True
3596
3627
  if (isStopLoss or isTakeProfit) and not isAlternativeEndpoint:
3597
3628
  if isStopLoss:
3598
3629
  slTriggerPrice = self.safe_value_2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss)
3599
- request['stopLoss'] = self.price_to_precision(symbol, slTriggerPrice)
3630
+ request['stopLoss'] = self.get_price(symbol, slTriggerPrice)
3600
3631
  slLimitPrice = self.safe_value(stopLoss, 'price')
3601
3632
  if slLimitPrice is not None:
3602
3633
  request['tpslMode'] = 'Partial'
3603
3634
  request['slOrderType'] = 'Limit'
3604
- request['slLimitPrice'] = self.price_to_precision(symbol, slLimitPrice)
3635
+ request['slLimitPrice'] = self.get_price(symbol, slLimitPrice)
3605
3636
  if isTakeProfit:
3606
3637
  tpTriggerPrice = self.safe_value_2(takeProfit, 'triggerPrice', 'stopPrice', takeProfit)
3607
- request['takeProfit'] = self.price_to_precision(symbol, tpTriggerPrice)
3638
+ request['takeProfit'] = self.get_price(symbol, tpTriggerPrice)
3608
3639
  tpLimitPrice = self.safe_value(takeProfit, 'price')
3609
3640
  if tpLimitPrice is not None:
3610
3641
  request['tpslMode'] = 'Partial'
3611
3642
  request['tpOrderType'] = 'Limit'
3612
- request['tpLimitPrice'] = self.price_to_precision(symbol, tpLimitPrice)
3643
+ request['tpLimitPrice'] = self.get_price(symbol, tpLimitPrice)
3613
3644
  params = self.omit(params, ['stopPrice', 'timeInForce', 'stopLossPrice', 'takeProfitPrice', 'postOnly', 'clientOrderId', 'triggerPrice', 'stopLoss', 'takeProfit', 'trailingAmount', 'trailingTriggerPrice'])
3614
3645
  return self.extend(request, params)
3615
3646
 
@@ -3709,7 +3740,7 @@ class bybit(Exchange, ImplicitAPI):
3709
3740
  'side': self.capitalize(side),
3710
3741
  'orderType': self.capitalize(lowerCaseType), # limit or market
3711
3742
  'timeInForce': 'GoodTillCancel', # ImmediateOrCancel, FillOrKill, PostOnly
3712
- 'orderQty': self.amount_to_precision(symbol, amount),
3743
+ 'orderQty': self.get_amount(symbol, amount),
3713
3744
  # 'takeProfit': 123.45, # take profit price, only take effect upon opening the position
3714
3745
  # 'stopLoss': 123.45, # stop loss price, only take effect upon opening the position
3715
3746
  # 'reduceOnly': False, # reduce only, required for linear orders
@@ -3727,7 +3758,7 @@ class bybit(Exchange, ImplicitAPI):
3727
3758
  isMarket = lowerCaseType == 'market'
3728
3759
  isLimit = lowerCaseType == 'limit'
3729
3760
  if isLimit is not None:
3730
- request['orderPrice'] = self.price_to_precision(symbol, price)
3761
+ request['orderPrice'] = self.get_price(symbol, self.number_to_string(price))
3731
3762
  exchangeSpecificParam = self.safe_string(params, 'time_in_force')
3732
3763
  timeInForce = self.safe_string_lower(params, 'timeInForce')
3733
3764
  postOnly = self.is_post_only(isMarket, exchangeSpecificParam == 'PostOnly', params)
@@ -3754,17 +3785,17 @@ class bybit(Exchange, ImplicitAPI):
3754
3785
  request['orderFilter'] = 'StopOrder'
3755
3786
  request['trigger_by'] = 'LastPrice'
3756
3787
  stopPx = stopLossTriggerPrice if isStopLossTriggerOrder else takeProfitTriggerPrice
3757
- preciseStopPrice = self.price_to_precision(symbol, stopPx)
3788
+ preciseStopPrice = self.get_price(symbol, stopPx)
3758
3789
  request['triggerPrice'] = preciseStopPrice
3759
3790
  delta = self.number_to_string(market['precision']['price'])
3760
3791
  request['basePrice'] = Precise.string_sub(preciseStopPrice, delta) if isStopLossTriggerOrder else Precise.string_add(preciseStopPrice, delta)
3761
3792
  elif isStopLoss or isTakeProfit:
3762
3793
  if isStopLoss:
3763
3794
  slTriggerPrice = self.safe_value_2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss)
3764
- request['stopLoss'] = self.price_to_precision(symbol, slTriggerPrice)
3795
+ request['stopLoss'] = self.get_price(symbol, slTriggerPrice)
3765
3796
  if isTakeProfit:
3766
3797
  tpTriggerPrice = self.safe_value_2(takeProfit, 'triggerPrice', 'stopPrice', takeProfit)
3767
- request['takeProfit'] = self.price_to_precision(symbol, tpTriggerPrice)
3798
+ request['takeProfit'] = self.get_price(symbol, tpTriggerPrice)
3768
3799
  else:
3769
3800
  request['orderFilter'] = 'Order'
3770
3801
  clientOrderId = self.safe_string(params, 'clientOrderId')
@@ -3815,9 +3846,9 @@ class bybit(Exchange, ImplicitAPI):
3815
3846
  'orderId': id,
3816
3847
  }
3817
3848
  if amount is not None:
3818
- request['orderQty'] = self.amount_to_precision(symbol, amount)
3849
+ request['orderQty'] = self.get_amount(symbol, amount)
3819
3850
  if price is not None:
3820
- request['orderPrice'] = self.price_to_precision(symbol, price)
3851
+ request['orderPrice'] = self.get_price(symbol, price)
3821
3852
  response = None
3822
3853
  if market['option']:
3823
3854
  response = self.privatePostOptionUsdcOpenapiPrivateV1ReplaceOrder(self.extend(request, params))
@@ -3832,11 +3863,11 @@ class bybit(Exchange, ImplicitAPI):
3832
3863
  if isStopOrder:
3833
3864
  request['orderFilter'] = 'StopOrder' if isStop else 'Order'
3834
3865
  if triggerPrice is not None:
3835
- request['triggerPrice'] = self.price_to_precision(symbol, triggerPrice)
3866
+ request['triggerPrice'] = self.get_price(symbol, triggerPrice)
3836
3867
  if stopLossPrice is not None:
3837
- request['stopLoss'] = self.price_to_precision(symbol, stopLossPrice)
3868
+ request['stopLoss'] = self.get_price(symbol, stopLossPrice)
3838
3869
  if takeProfitPrice is not None:
3839
- request['takeProfit'] = self.price_to_precision(symbol, takeProfitPrice)
3870
+ request['takeProfit'] = self.get_price(symbol, takeProfitPrice)
3840
3871
  params = self.omit(params, ['stop', 'stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice'])
3841
3872
  response = self.privatePostPerpetualUsdcOpenapiPrivateV1ReplaceOrder(self.extend(request, params))
3842
3873
  #
@@ -3879,11 +3910,9 @@ class bybit(Exchange, ImplicitAPI):
3879
3910
  elif market['option']:
3880
3911
  request['category'] = 'option'
3881
3912
  if amount is not None:
3882
- request['qty'] = self.amount_to_precision(symbol, amount)
3913
+ request['qty'] = self.get_amount(symbol, amount)
3883
3914
  if price is not None:
3884
- request['price'] = self.price_to_precision(symbol, price)
3885
- if amount is not None:
3886
- request['qty'] = self.amount_to_precision(symbol, amount)
3915
+ request['price'] = self.get_price(symbol, self.number_to_string(price))
3887
3916
  triggerPrice = self.safe_string_2(params, 'triggerPrice', 'stopPrice')
3888
3917
  stopLossTriggerPrice = self.safe_string(params, 'stopLossPrice')
3889
3918
  takeProfitTriggerPrice = self.safe_string(params, 'takeProfitPrice')
@@ -3896,20 +3925,20 @@ class bybit(Exchange, ImplicitAPI):
3896
3925
  if isStopLossTriggerOrder or isTakeProfitTriggerOrder:
3897
3926
  triggerPrice = stopLossTriggerPrice if isStopLossTriggerOrder else takeProfitTriggerPrice
3898
3927
  if triggerPrice is not None:
3899
- triggerPriceRequest = triggerPrice if (triggerPrice == '0') else self.price_to_precision(symbol, triggerPrice)
3928
+ triggerPriceRequest = triggerPrice if (triggerPrice == '0') else self.get_price(symbol, triggerPrice)
3900
3929
  request['triggerPrice'] = triggerPriceRequest
3901
3930
  triggerBy = self.safe_string(params, 'triggerBy', 'LastPrice')
3902
3931
  request['triggerBy'] = triggerBy
3903
3932
  if isStopLoss or isTakeProfit:
3904
3933
  if isStopLoss:
3905
3934
  slTriggerPrice = self.safe_string_2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss)
3906
- stopLossRequest = slTriggerPrice if (slTriggerPrice == '0') else self.price_to_precision(symbol, slTriggerPrice)
3935
+ stopLossRequest = slTriggerPrice if (slTriggerPrice == '0') else self.get_price(symbol, slTriggerPrice)
3907
3936
  request['stopLoss'] = stopLossRequest
3908
3937
  slTriggerBy = self.safe_string(params, 'slTriggerBy', 'LastPrice')
3909
3938
  request['slTriggerBy'] = slTriggerBy
3910
3939
  if isTakeProfit:
3911
3940
  tpTriggerPrice = self.safe_string_2(takeProfit, 'triggerPrice', 'stopPrice', takeProfit)
3912
- takeProfitRequest = tpTriggerPrice if (tpTriggerPrice == '0') else self.price_to_precision(symbol, tpTriggerPrice)
3941
+ takeProfitRequest = tpTriggerPrice if (tpTriggerPrice == '0') else self.get_price(symbol, tpTriggerPrice)
3913
3942
  request['takeProfit'] = takeProfitRequest
3914
3943
  tpTriggerBy = self.safe_string(params, 'tpTriggerBy', 'LastPrice')
3915
3944
  request['tpTriggerBy'] = tpTriggerBy
@@ -3945,9 +3974,9 @@ class bybit(Exchange, ImplicitAPI):
3945
3974
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
3946
3975
  """
3947
3976
  self.load_markets()
3977
+ market = self.market(symbol)
3948
3978
  if symbol is None:
3949
3979
  raise ArgumentsRequired(self.id + ' editOrder() requires a symbol argument')
3950
- market = self.market(symbol)
3951
3980
  enableUnifiedMargin, enableUnifiedAccount = self.is_unified_enabled()
3952
3981
  isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
3953
3982
  isUsdcSettled = market['settle'] == 'USDC'
@@ -5731,6 +5760,8 @@ class bybit(Exchange, ImplicitAPI):
5731
5760
  :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
5732
5761
  """
5733
5762
  tag, params = self.handle_withdraw_tag_and_params(tag, params)
5763
+ accountType = None
5764
+ accountType, params = self.handle_option_and_params(params, 'withdraw', 'accountType', 'SPOT')
5734
5765
  self.load_markets()
5735
5766
  self.check_address(address)
5736
5767
  currency = self.currency(code)
@@ -5739,6 +5770,7 @@ class bybit(Exchange, ImplicitAPI):
5739
5770
  'amount': self.number_to_string(amount),
5740
5771
  'address': address,
5741
5772
  'timestamp': self.milliseconds(),
5773
+ 'accountType': accountType,
5742
5774
  }
5743
5775
  if tag is not None:
5744
5776
  request['tag'] = tag
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.3.80'
7
+ __version__ = '4.3.82'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
ccxt/wavesexchange.py CHANGED
@@ -1238,7 +1238,8 @@ class wavesexchange(Exchange, ImplicitAPI):
1238
1238
  if (isMarketOrder) and (price is None):
1239
1239
  raise InvalidOrder(self.id + ' createOrder() requires a price argument for ' + type + ' orders to determine the max price for buy and the min price for sell')
1240
1240
  timestamp = self.milliseconds()
1241
- defaultExpiryDelta = self.safe_integer(self.options, 'createOrderDefaultExpiry', 2419200000)
1241
+ defaultExpiryDelta = None
1242
+ defaultExpiryDelta, params = self.handle_option_and_params(params, 'createOrder', 'defaultExpiry', self.safe_integer(self.options, 'createOrderDefaultExpiry', 2419200000))
1242
1243
  expiration = self.sum(timestamp, defaultExpiryDelta)
1243
1244
  matcherFees = self.get_fees_for_asset(symbol, side, amount, price)
1244
1245
  # {
@@ -1373,11 +1374,11 @@ class wavesexchange(Exchange, ImplicitAPI):
1373
1374
  # }
1374
1375
  #
1375
1376
  if isMarketOrder:
1376
- response = self.matcherPostMatcherOrderbookMarket(body)
1377
+ response = self.matcherPostMatcherOrderbookMarket(self.extend(body, params))
1377
1378
  value = self.safe_dict(response, 'message')
1378
1379
  return self.parse_order(value, market)
1379
1380
  else:
1380
- response = self.matcherPostMatcherOrderbook(body)
1381
+ response = self.matcherPostMatcherOrderbook(self.extend(body, params))
1381
1382
  value = self.safe_dict(response, 'message')
1382
1383
  return self.parse_order(value, market)
1383
1384
 
ccxt/yobit.py CHANGED
@@ -248,6 +248,7 @@ class yobit(Exchange, ImplicitAPI):
248
248
  'XIN': 'XINCoin',
249
249
  'XMT': 'SummitCoin',
250
250
  'XRA': 'Ratecoin',
251
+ 'BCHN': 'BSV',
251
252
  },
252
253
  'options': {
253
254
  'maxUrlLength': 2048,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ccxt
3
- Version: 4.3.80
3
+ Version: 4.3.82
4
4
  Summary: A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 100+ exchanges
5
5
  Home-page: https://ccxt.com
6
6
  Author: Igor Kroitor
@@ -270,13 +270,13 @@ console.log(version, Object.keys(exchanges));
270
270
 
271
271
  All-in-one browser bundle (dependencies included), served from a CDN of your choice:
272
272
 
273
- * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.3.80/dist/ccxt.browser.min.js
274
- * unpkg: https://unpkg.com/ccxt@4.3.80/dist/ccxt.browser.min.js
273
+ * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.3.82/dist/ccxt.browser.min.js
274
+ * unpkg: https://unpkg.com/ccxt@4.3.82/dist/ccxt.browser.min.js
275
275
 
276
276
  CDNs are not updated in real-time and may have delays. Defaulting to the most recent version without specifying the version number is not recommended. Please, keep in mind that we are not responsible for the correct operation of those CDN servers.
277
277
 
278
278
  ```HTML
279
- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.3.80/dist/ccxt.browser.min.js"></script>
279
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.3.82/dist/ccxt.browser.min.js"></script>
280
280
  ```
281
281
 
282
282
  Creates a global `ccxt` object:
@@ -1,4 +1,4 @@
1
- ccxt/__init__.py,sha256=mXY0nDx2xo6TTvvOZOaLDW48wkmWcZ2nRKTRPgfneEY,16417
1
+ ccxt/__init__.py,sha256=Yrk5PWqhPkUaLUBLIM2PZCt2XYEru5fPHDA1rTe5HbQ,16417
2
2
  ccxt/ace.py,sha256=Gee4ymA83iAuBFm3J8NaTb7qmu9buV2trA676KCtSVg,42383
3
3
  ccxt/alpaca.py,sha256=HQuhQZSFGRlT-BaCUSEZmxpzYp6tll2zn63qn3gTmoU,47470
4
4
  ccxt/ascendex.py,sha256=4aEwibO_me6khr66z8JFqDBxe2gtFOWIFBE7ulBEJPs,151933
@@ -35,7 +35,7 @@ ccxt/btcalpha.py,sha256=UcCCDZ_7EM-Q2tHU1IQPEA2DErFsLhrSfX-Oy-Q2uL4,36715
35
35
  ccxt/btcbox.py,sha256=9-P15L-OiZRzz0ZOtgO3bf73kuHro9u3NYf3QjeYv4k,27744
36
36
  ccxt/btcmarkets.py,sha256=0gMC0vvmuDJwcnllHMUZsQRV6QWA1-Cbq1N1F9rIUW8,52697
37
37
  ccxt/btcturk.py,sha256=bQ8sJq5iEj9oq2R17uDadPWKcnIQG8id5UmdlpHfFy8,36992
38
- ccxt/bybit.py,sha256=eqP9ZKLYn9SfhZW8dYBdq0xagQRAKF7FJBLA73iuNi8,417795
38
+ ccxt/bybit.py,sha256=8RVgRPc2A4-fs2_EdLYHMB9_Lx-2e4EC4H3B84tKrUQ,418859
39
39
  ccxt/cex.py,sha256=YQtARIBP7cY3y-AqRarEH_mVh7_ftt18jLebhpL3hxQ,70084
40
40
  ccxt/coinbase.py,sha256=3L5CDWhg4MQlDkdZnuJxxOjmsWEh-gnqcV4R6nCq7rg,217483
41
41
  ccxt/coinbaseadvanced.py,sha256=d5g6nRx-NCcCwZDdtp8FsI2D-pRjSvnAP9ISSKY_nCQ,538
@@ -99,13 +99,13 @@ ccxt/tokocrypto.py,sha256=aV-98hzr75iQO3GEmiUyTNufDqHfoze04Z2Fk195B3Q,123192
99
99
  ccxt/tradeogre.py,sha256=DCxTLjtGW7ADRA-jekCkGAn81-GIgdOAxbJFcBLYOFU,24211
100
100
  ccxt/upbit.py,sha256=W_W8aETJyopwhYfZd2tWvhPvi7BjQ4KSIOdn8nzyWv8,85413
101
101
  ccxt/vertex.py,sha256=YoKnzxhem56C19SckA6yHUPH1bk86PfZ4Z-T01TFygg,121761
102
- ccxt/wavesexchange.py,sha256=8KrV-euIdDeARQ-h-T-nTlFJ9hk6TLuwGl8U7Xr_Lgk,114825
102
+ ccxt/wavesexchange.py,sha256=vmzv9h1QjthvpKUGajQn_tdCJ5tWmzEA6r7ow_y6ASY,114980
103
103
  ccxt/wazirx.py,sha256=LVHNdononi8FrZpT0pYiJoS-NrNi7_uIZ6Qbu8dJRPc,52405
104
104
  ccxt/whitebit.py,sha256=fkM0Clt74bSiOJ_L-CehR2Gkn3v3kZksCQT0JCCG5rs,119340
105
105
  ccxt/woo.py,sha256=VSW2iQ6t9SCB5GYlRClLfUD468HNW2SOhM6uEo3A_e4,153142
106
106
  ccxt/woofipro.py,sha256=-qGU-7u764-744FvsmqVTvWXsuGxjlNCgJfAj_Yq6PA,115464
107
107
  ccxt/xt.py,sha256=a9f_Oq5KyDdytyCqW15jjXXdHGumbZwCqutt8cbfsPo,202616
108
- ccxt/yobit.py,sha256=q1oj-wf0VwNw3U7kC5AOyHRSxWVZO6s8xGscBJiSLhI,54553
108
+ ccxt/yobit.py,sha256=NeQpnOTzkjRKj5gVfI-riru5cNltagRH-DSfEEfByLw,54584
109
109
  ccxt/zaif.py,sha256=LgeOsvAo4ShQW1s-RidgUYK4DnRU-Dk0eJG0Ca6M_9U,28862
110
110
  ccxt/zonda.py,sha256=KZfv46H6YsVpTQLSt4BvMiGFQr0WRLmbUpeODVv21O0,81419
111
111
  ccxt/abstract/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -218,7 +218,7 @@ ccxt/abstract/xt.py,sha256=JkWvsic3L2O968BCr9H5Wd5NIbRE9aTT2A-9WbAtl0c,27146
218
218
  ccxt/abstract/yobit.py,sha256=8ycfCO8ORFly9hc0Aa47sZyX4_ZKPXS9h9yJzI-uQ7Q,1339
219
219
  ccxt/abstract/zaif.py,sha256=m15WHdl3gYy0GOXNZ8NEH8eE7sVh8c0T_ITNuU8vXeU,3935
220
220
  ccxt/abstract/zonda.py,sha256=X-hCW0SdX3YKZWixDyW-O2211M58Rno8kKJ6quY7rw4,7183
221
- ccxt/async_support/__init__.py,sha256=gvxdFG_MnNGhdGsC4FNnvGj1CnQ9umhcakuCO50RDQc,16230
221
+ ccxt/async_support/__init__.py,sha256=ShVKd-IbmeJKBKH0V68UpB8cupTo9CTrp2de1CPDFxo,16230
222
222
  ccxt/async_support/ace.py,sha256=zBmLUKH691a2BH1sPzlJPg-uO7lD6Ys92Rv8WSzNtoo,42607
223
223
  ccxt/async_support/alpaca.py,sha256=495vDvdF1IWlsh9QhUnMtkMuINdD0EzeFGlUVqCf8TE,47682
224
224
  ccxt/async_support/ascendex.py,sha256=LK259BdUqU0_STGRH6DmTgaR-7lXqFpZHFVACf2um5c,152721
@@ -255,7 +255,7 @@ ccxt/async_support/btcalpha.py,sha256=DgzrJ6cczUCDZr-QLUxMpazeudEFdQ_OzXiQiJM4Hb
255
255
  ccxt/async_support/btcbox.py,sha256=FGIj8il6VZL56_dDYsAMwp4DpdKNt_vbMXV6VZ2boCI,27968
256
256
  ccxt/async_support/btcmarkets.py,sha256=x1-s5uVioHyvNJoBxhxP8eUUslTDwQnZMU0FWfu1Fd4,53047
257
257
  ccxt/async_support/btcturk.py,sha256=P3bg0XG0sAi-8ge9ZFzQqZHsoGOGfxBjkhIDo4VPSK4,37210
258
- ccxt/async_support/bybit.py,sha256=Q2BXgxR57AmDMVI_83LTAph_aL-vEFdPK2IJMYOGnjw,419671
258
+ ccxt/async_support/bybit.py,sha256=PcNgqEEBqggWY4xHLUX2TZHhY7-U96Ne1Ps5CDGfoIw,420735
259
259
  ccxt/async_support/cex.py,sha256=5KZ9qt4WsUAkH2rkHn7zW7SwlB9FumruLELdKF4LFoE,70434
260
260
  ccxt/async_support/coinbase.py,sha256=Ch_hFo2zj0qp4kuDUnebGD16pUeKs6h3HJxs5Fdpkco,218637
261
261
  ccxt/async_support/coinbaseadvanced.py,sha256=Kupwnuxiu_qTjwCNV2asacoDUNFQvcaHNAznUJPhdQs,552
@@ -319,17 +319,17 @@ ccxt/async_support/tokocrypto.py,sha256=nzJhrGTCTWMbbjI4P_IKfO1O84td8pSssCgZhTqQ
319
319
  ccxt/async_support/tradeogre.py,sha256=A4DEbbRL_g_5WAp7WOB96s08-zgXfGQ9lYZnDX5H1eI,24405
320
320
  ccxt/async_support/upbit.py,sha256=GmhV24xdjd5NSCronYkqLCM8rr_hNdpt4NEDA5jEkLw,85895
321
321
  ccxt/async_support/vertex.py,sha256=_KDPAVq5Bew-w77wiGQpivZCGRs6yGKoW9HGh8PhOLc,122261
322
- ccxt/async_support/wavesexchange.py,sha256=kdF7Nm5a34mtgIj2HWTLuV3plt4K3EBKMpLENIxtoMk,115375
322
+ ccxt/async_support/wavesexchange.py,sha256=wHxvsBQydDEYRgeAZKI9WO4TLBKmmSPTLm0eT0pKB5g,115530
323
323
  ccxt/async_support/wazirx.py,sha256=bnUpw9be3o4l2Hxm3jcfNXn5bMyZlgqoG8BGPusuIzs,52707
324
324
  ccxt/async_support/whitebit.py,sha256=haF5nFYGuJzkplHBIyLLDJ6N3ThIDPpgjeI3S-TYs98,119990
325
325
  ccxt/async_support/woo.py,sha256=uaNh3timNm6_DNhiOn5l4Za4wagj4AhlxkDh4Fbhxfk,154110
326
326
  ccxt/async_support/woofipro.py,sha256=wLOSXkKdEqpw4q-9uzM67wFdhWDp0Li1wb8nPHmBwT4,116144
327
327
  ccxt/async_support/xt.py,sha256=_U-r4Gp0oBCOE6Ngo98Sn_Q6tr_81CUDDSliF0FMezE,203770
328
- ccxt/async_support/yobit.py,sha256=JuH_yClCl_cd5L-BMTt3MPAvIF61Wpqc3W7H-fno6Hs,54881
328
+ ccxt/async_support/yobit.py,sha256=GQhvYrsGHQrVdTrNHQxx9isEGqUABexlllzao9HL3f8,54912
329
329
  ccxt/async_support/zaif.py,sha256=-ZTr8M2JaIRCL90VrbCDXBMAsZwbiwsFChSQ2rWODuQ,29044
330
330
  ccxt/async_support/zonda.py,sha256=jncr6Wg12S72CTpu6mCKCse1pm1f8oefVQurQSrFvP0,81733
331
331
  ccxt/async_support/base/__init__.py,sha256=aVYSsFi--b4InRs9zDN_wtCpj8odosAB726JdUHavrk,67
332
- ccxt/async_support/base/exchange.py,sha256=wmK5Ls6kXKaCJYNVXKVJQh1oZN7ljh7zGUg3E5JscUk,110799
332
+ ccxt/async_support/base/exchange.py,sha256=QKnrZhy6RCzRR3C-r6A1JLaJKx6jc9_7Sgmrp31pqNg,110799
333
333
  ccxt/async_support/base/throttler.py,sha256=tvDVcdRUVYi8fZRlEcnqtgzcgB_KMUMRs5Pu8tuU-tU,1847
334
334
  ccxt/async_support/base/ws/__init__.py,sha256=uockzpLuwntKGZbs5EOWFe-Zg-k6Cj7GhNJLc_RX0so,1791
335
335
  ccxt/async_support/base/ws/aiohttp_client.py,sha256=5IEiT0elWI9a7Vr-KV0jgmlbpLJWBzIlrLaCkTKGaqY,5752
@@ -343,10 +343,10 @@ ccxt/async_support/base/ws/order_book_side.py,sha256=GhnGUt78pJ-AYL_Dq9produGjmB
343
343
  ccxt/base/__init__.py,sha256=eTx1OE3HJjspFUQjGm6LBhaQiMKJnXjkdP-JUXknyQ0,1320
344
344
  ccxt/base/decimal_to_precision.py,sha256=fgWRBzRTtsf3r2INyS4f7WHlzgjB5YM1ekiwqD21aac,6634
345
345
  ccxt/base/errors.py,sha256=tosnf1tDaBn4YMCbWVNWyDYzqft-ImVtyjqJb6q83Y4,4369
346
- ccxt/base/exchange.py,sha256=QDmTRgOgGrNdilQd7oFL3sOhy2efnwu40KNIBOawixc,295715
346
+ ccxt/base/exchange.py,sha256=aTruoZiEhm40hCTqbxvYDiQqwrfFs3vrtpUtwA-QKuA,295904
347
347
  ccxt/base/precise.py,sha256=koce64Yrp6vFbGijJtUt-QQ6XhJgeGTCksZ871FPp_A,8886
348
348
  ccxt/base/types.py,sha256=TaP_RElKjGEZWuzyp4o4u2YhREyTG3rUeVT6gDffY9A,9613
349
- ccxt/pro/__init__.py,sha256=dLg8Q9dPmtQU9OWcHNk7pfzsohkqpI0BjmVfCbusrOE,7608
349
+ ccxt/pro/__init__.py,sha256=7b_tKNpb9iGmSG-ObTled4qVXYnCsO3Dq4x21OkUHCo,7608
350
350
  ccxt/pro/alpaca.py,sha256=xh1yg1Ok-Zh_Mfx-MBjNrfJDs6MUU0exFfEj3GuQPC4,27631
351
351
  ccxt/pro/ascendex.py,sha256=181FIeztchLqGmgecRJEN8F8xEM45D5aMKhC-5nuNfU,35467
352
352
  ccxt/pro/bequant.py,sha256=33OEUWBi4D9-2w8CmkwN3aF1qS-AlLqX3pxrWwNbXPY,1552
@@ -648,8 +648,8 @@ ccxt/test/tests_async.py,sha256=NShOLO2-HzYsh07U7aiUGssiv-AZ_p88h-NuQub9OKU,8468
648
648
  ccxt/test/tests_helpers.py,sha256=xhOILoZ_x3RSfQjtKt6AQlkp9DkOtpTQe8GAUUZoM6s,10069
649
649
  ccxt/test/tests_init.py,sha256=eVwwUHujX9t4rjgo4TqEeg7DDhR1Hb_e2SJN8NVGyl0,998
650
650
  ccxt/test/tests_sync.py,sha256=6Arr2TcJpNg9eEpH_JQeBbLzaMPlb94J1P11HGlbpPg,83761
651
- ccxt-4.3.80.dist-info/LICENSE.txt,sha256=EIb9221AhMHV7xF1_55STFdKTFsnJVJYkRpY2Lnvo5w,1068
652
- ccxt-4.3.80.dist-info/METADATA,sha256=Q2E5zZZ8R_FKimgd6FpdPpSotXT_Xk42kdfCWlOBMf0,116642
653
- ccxt-4.3.80.dist-info/WHEEL,sha256=z9j0xAa_JmUKMpmz72K0ZGALSM_n-wQVmGbleXx2VHg,110
654
- ccxt-4.3.80.dist-info/top_level.txt,sha256=CkQDuCTDKNcImPV60t36G6MdYfxsAPNiSaEwifVoVMo,5
655
- ccxt-4.3.80.dist-info/RECORD,,
651
+ ccxt-4.3.82.dist-info/LICENSE.txt,sha256=EIb9221AhMHV7xF1_55STFdKTFsnJVJYkRpY2Lnvo5w,1068
652
+ ccxt-4.3.82.dist-info/METADATA,sha256=x9Jn56o7pcvpgLkau0eijaJ4wHQ0xNvdbibC55_ot_g,116642
653
+ ccxt-4.3.82.dist-info/WHEEL,sha256=z9j0xAa_JmUKMpmz72K0ZGALSM_n-wQVmGbleXx2VHg,110
654
+ ccxt-4.3.82.dist-info/top_level.txt,sha256=CkQDuCTDKNcImPV60t36G6MdYfxsAPNiSaEwifVoVMo,5
655
+ ccxt-4.3.82.dist-info/RECORD,,
File without changes