ccxt 4.3.23__py2.py3-none-any.whl → 4.3.27__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/coinex.py CHANGED
@@ -457,8 +457,15 @@ class coinex(Exchange, ImplicitAPI):
457
457
  'fetchDepositAddress': {
458
458
  'fillResponseFromRequest': True,
459
459
  },
460
+ 'accountsByType': {
461
+ 'spot': 'SPOT',
462
+ 'margin': 'MARGIN',
463
+ 'swap': 'FUTURES',
464
+ },
460
465
  'accountsById': {
461
- 'spot': '0',
466
+ 'SPOT': 'spot',
467
+ 'MARGIN': 'margin',
468
+ 'FUTURES': 'swap',
462
469
  },
463
470
  'networks': {
464
471
  'BEP20': 'BSC',
@@ -3453,7 +3460,10 @@ class coinex(Exchange, ImplicitAPI):
3453
3460
  :param str [params.marginMode]: 'cross' or 'isolated' for fetching spot margin orders
3454
3461
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
3455
3462
  """
3456
- return self.fetch_orders_by_status('pending', symbol, since, limit, params)
3463
+ openOrders = self.fetch_orders_by_status('pending', symbol, since, limit, params)
3464
+ for i in range(0, len(openOrders)):
3465
+ openOrders[i]['status'] = 'open'
3466
+ return openOrders
3457
3467
 
3458
3468
  def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
3459
3469
  """
@@ -4598,40 +4608,42 @@ class coinex(Exchange, ImplicitAPI):
4598
4608
  def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
4599
4609
  """
4600
4610
  transfer currency internally between wallets on the same account
4601
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot002_account014_balance_contract_transfer
4602
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot002_account013_margin_transfer
4611
+ :see: https://docs.coinex.com/api/v2/assets/transfer/http/transfer
4603
4612
  :param str code: unified currency code
4604
4613
  :param float amount: amount to transfer
4605
4614
  :param str fromAccount: account to transfer from
4606
4615
  :param str toAccount: account to transfer to
4607
4616
  :param dict [params]: extra parameters specific to the exchange API endpoint
4617
+ :param str [params.symbol]: unified ccxt symbol, required when either the fromAccount or toAccount is margin
4608
4618
  :returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
4609
4619
  """
4610
4620
  self.load_markets()
4611
4621
  currency = self.currency(code)
4612
4622
  amountToPrecision = self.currency_to_precision(code, amount)
4623
+ accountsByType = self.safe_dict(self.options, 'accountsById', {})
4624
+ fromId = self.safe_string(accountsByType, fromAccount, fromAccount)
4625
+ toId = self.safe_string(accountsByType, toAccount, toAccount)
4613
4626
  request = {
4627
+ 'ccy': currency['id'],
4614
4628
  'amount': amountToPrecision,
4615
- 'coin_type': currency['id'],
4629
+ 'from_account_type': fromId,
4630
+ 'to_account_type': toId,
4616
4631
  }
4617
- response = None
4618
- if (fromAccount == 'spot') and (toAccount == 'swap'):
4619
- request['transfer_side'] = 'in' # 'in' spot to swap, 'out' swap to spot
4620
- response = self.v1PrivatePostContractBalanceTransfer(self.extend(request, params))
4621
- elif (fromAccount == 'swap') and (toAccount == 'spot'):
4622
- request['transfer_side'] = 'out' # 'in' spot to swap, 'out' swap to spot
4623
- response = self.v1PrivatePostContractBalanceTransfer(self.extend(request, params))
4624
- else:
4625
- accountsById = self.safe_value(self.options, 'accountsById', {})
4626
- fromId = self.safe_string(accountsById, fromAccount, fromAccount)
4627
- toId = self.safe_string(accountsById, toAccount, toAccount)
4628
- # fromAccount and toAccount must be integers for margin transfers
4629
- # spot is 0, use fetchBalance() to find the margin account id
4630
- request['from_account'] = int(fromId)
4631
- request['to_account'] = int(toId)
4632
- response = self.v1PrivatePostMarginTransfer(self.extend(request, params))
4632
+ if (fromAccount == 'margin') or (toAccount == 'margin'):
4633
+ symbol = self.safe_string(params, 'symbol')
4634
+ if symbol is None:
4635
+ raise ArgumentsRequired(self.id + ' transfer() the symbol parameter must be defined for a margin account')
4636
+ params = self.omit(params, 'symbol')
4637
+ request['market'] = self.market_id(symbol)
4638
+ if (fromAccount != 'spot') and (toAccount != 'spot'):
4639
+ raise BadRequest(self.id + ' transfer() can only be between spot and swap, or spot and margin, either the fromAccount or toAccount must be spot')
4640
+ response = self.v2PrivatePostAssetsTransfer(self.extend(request, params))
4633
4641
  #
4634
- # {"code": 0, "data": null, "message": "Success"}
4642
+ # {
4643
+ # "code": 0,
4644
+ # "data": {},
4645
+ # "message": "OK"
4646
+ # }
4635
4647
  #
4636
4648
  return self.extend(self.parse_transfer(response, currency), {
4637
4649
  'amount': self.parse_number(amountToPrecision),
@@ -4639,158 +4651,85 @@ class coinex(Exchange, ImplicitAPI):
4639
4651
  'toAccount': toAccount,
4640
4652
  })
4641
4653
 
4642
- def parse_transfer_status(self, status: Str) -> Str:
4654
+ def parse_transfer_status(self, status):
4643
4655
  statuses = {
4644
4656
  '0': 'ok',
4645
4657
  'SUCCESS': 'ok',
4658
+ 'OK': 'ok',
4659
+ 'finished': 'ok',
4660
+ 'FINISHED': 'ok',
4646
4661
  }
4647
4662
  return self.safe_string(statuses, status, status)
4648
4663
 
4649
4664
  def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
4650
- #
4651
- # fetchTransfers Swap
4652
- #
4653
- # {
4654
- # "amount": "10",
4655
- # "asset": "USDT",
4656
- # "transfer_type": "transfer_out", # from swap to spot
4657
- # "created_at": 1651633422
4658
- # },
4659
- #
4660
- # fetchTransfers Margin
4661
- #
4662
- # {
4663
- # "id": 7580062,
4664
- # "updated_at": 1653684379,
4665
- # "user_id": 3620173,
4666
- # "from_account_id": 0,
4667
- # "to_account_id": 1,
4668
- # "asset": "BTC",
4669
- # "amount": "0.00160829",
4670
- # "balance": "0.00160829",
4671
- # "transfer_type": "IN",
4672
- # "status": "SUCCESS",
4673
- # "created_at": 1653684379
4674
- # },
4675
- #
4676
- timestamp = self.safe_timestamp(transfer, 'created_at')
4677
- transferType = self.safe_string(transfer, 'transfer_type')
4678
- fromAccount = None
4679
- toAccount = None
4680
- if transferType == 'transfer_out':
4681
- fromAccount = 'swap'
4682
- toAccount = 'spot'
4683
- elif transferType == 'transfer_in':
4684
- fromAccount = 'spot'
4685
- toAccount = 'swap'
4686
- elif transferType == 'IN':
4687
- fromAccount = 'spot'
4688
- toAccount = 'margin'
4689
- elif transferType == 'OUT':
4690
- fromAccount = 'margin'
4691
- toAccount = 'spot'
4692
- currencyId = self.safe_string(transfer, 'asset')
4693
- currencyCode = self.safe_currency_code(currencyId, currency)
4665
+ timestamp = self.safe_integer(transfer, 'created_at')
4666
+ currencyId = self.safe_string(transfer, 'ccy')
4667
+ fromId = self.safe_string(transfer, 'from_account_type')
4668
+ toId = self.safe_string(transfer, 'to_account_type')
4669
+ accountsById = self.safe_value(self.options, 'accountsById', {})
4694
4670
  return {
4695
- 'info': transfer,
4696
- 'id': self.safe_string(transfer, 'id'),
4671
+ 'id': None,
4697
4672
  'timestamp': timestamp,
4698
4673
  'datetime': self.iso8601(timestamp),
4699
- 'currency': currencyCode,
4674
+ 'currency': self.safe_currency_code(currencyId, currency),
4700
4675
  'amount': self.safe_number(transfer, 'amount'),
4701
- 'fromAccount': fromAccount,
4702
- 'toAccount': toAccount,
4676
+ 'fromAccount': self.safe_string(accountsById, fromId, fromId),
4677
+ 'toAccount': self.safe_string(accountsById, toId, toId),
4703
4678
  'status': self.parse_transfer_status(self.safe_string_2(transfer, 'code', 'status')),
4704
4679
  }
4705
4680
 
4706
4681
  def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> TransferEntries:
4707
4682
  """
4708
4683
  fetch a history of internal transfers made on an account
4709
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot002_account025_margin_transfer_history
4710
- :see: https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot002_account024_contract_transfer_history
4684
+ :see: https://docs.coinex.com/api/v2/assets/transfer/http/list-transfer-history
4711
4685
  :param str code: unified currency code of the currency transferred
4712
4686
  :param int [since]: the earliest time in ms to fetch transfers for
4713
- :param int [limit]: the maximum number of transfers structures to retrieve
4687
+ :param int [limit]: the maximum number of transfer structures to retrieve
4714
4688
  :param dict [params]: extra parameters specific to the exchange API endpoint
4689
+ :param str [params.marginMode]: 'cross' or 'isolated' for fetching transfers to and from your margin account
4715
4690
  :returns dict[]: a list of `transfer structures <https://docs.ccxt.com/#/?id=transfer-structure>`
4716
4691
  """
4717
4692
  self.load_markets()
4718
- currency = None
4693
+ if code is None:
4694
+ raise ArgumentsRequired(self.id + ' fetchTransfers() requires a code argument')
4695
+ currency = self.currency(code)
4719
4696
  request = {
4720
- 'page': 1,
4721
- # 'limit': limit,
4722
- # 'asset': 'USDT',
4723
- # 'start_time': since,
4724
- # 'end_time': 1515806440,
4725
- # 'transfer_type': 'transfer_in', # transfer_in: from Spot to Swap Account, transfer_out: from Swap to Spot Account
4697
+ 'ccy': currency['id'],
4726
4698
  }
4727
- page = self.safe_integer(params, 'page')
4728
- if page is not None:
4729
- request['page'] = page
4730
- if code is not None:
4731
- currency = self.currency(code)
4732
- request['asset'] = currency['id']
4733
- if since is not None:
4734
- request['start_time'] = since
4735
- if limit is not None:
4736
- request['limit'] = limit
4737
- else:
4738
- request['limit'] = 100
4739
- params = self.omit(params, 'page')
4740
4699
  marginMode = None
4741
4700
  marginMode, params = self.handle_margin_mode_and_params('fetchTransfers', params)
4742
- response = None
4743
4701
  if marginMode is not None:
4744
- response = self.v1PrivateGetMarginTransferHistory(self.extend(request, params))
4702
+ request['transfer_type'] = 'MARGIN'
4745
4703
  else:
4746
- response = self.v1PrivateGetContractTransferHistory(self.extend(request, params))
4747
- #
4748
- # Swap
4704
+ request['transfer_type'] = 'FUTURES'
4705
+ if since is not None:
4706
+ request['start_time'] = since
4707
+ if limit is not None:
4708
+ request['limit'] = limit
4709
+ request, params = self.handle_until_option('end_time', request, params)
4710
+ response = self.v2PrivateGetAssetsTransferHistory(self.extend(request, params))
4749
4711
  #
4750
4712
  # {
4751
- # "code": 0,
4752
- # "data": {
4753
- # "records": [
4754
- # {
4755
- # "amount": "10",
4756
- # "asset": "USDT",
4757
- # "transfer_type": "transfer_out",
4758
- # "created_at": 1651633422
4759
- # },
4760
- # ],
4761
- # "total": 5
4713
+ # "data": [
4714
+ # {
4715
+ # "created_at": 1715848480646,
4716
+ # "from_account_type": "SPOT",
4717
+ # "to_account_type": "FUTURES",
4718
+ # "ccy": "USDT",
4719
+ # "amount": "10",
4720
+ # "status": "finished"
4721
+ # },
4722
+ # ],
4723
+ # "pagination": {
4724
+ # "total": 8,
4725
+ # "has_next": False
4762
4726
  # },
4763
- # "message": "Success"
4764
- # }
4765
- #
4766
- # Margin
4767
- #
4768
- # {
4769
4727
  # "code": 0,
4770
- # "data": {
4771
- # "records": [
4772
- # {
4773
- # "id": 7580062,
4774
- # "updated_at": 1653684379,
4775
- # "user_id": 3620173,
4776
- # "from_account_id": 0,
4777
- # "to_account_id": 1,
4778
- # "asset": "BTC",
4779
- # "amount": "0.00160829",
4780
- # "balance": "0.00160829",
4781
- # "transfer_type": "IN",
4782
- # "status": "SUCCESS",
4783
- # "created_at": 1653684379
4784
- # }
4785
- # ],
4786
- # "total": 1
4787
- # },
4788
- # "message": "Success"
4728
+ # "message": "OK"
4789
4729
  # }
4790
4730
  #
4791
- data = self.safe_value(response, 'data', {})
4792
- transfers = self.safe_list(data, 'records', [])
4793
- return self.parse_transfers(transfers, currency, since, limit)
4731
+ data = self.safe_list(response, 'data', [])
4732
+ return self.parse_transfers(data, currency, since, limit)
4794
4733
 
4795
4734
  def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
4796
4735
  """
ccxt/kraken.py CHANGED
@@ -58,6 +58,9 @@ class kraken(Exchange, ImplicitAPI):
58
58
  'cancelOrder': True,
59
59
  'cancelOrders': True,
60
60
  'createDepositAddress': True,
61
+ 'createMarketBuyOrderWithCost': True,
62
+ 'createMarketOrderWithCost': False,
63
+ 'createMarketSellOrderWithCost': False,
61
64
  'createOrder': True,
62
65
  'createStopLimitOrder': True,
63
66
  'createStopMarketOrder': True,
@@ -1308,6 +1311,33 @@ class kraken(Exchange, ImplicitAPI):
1308
1311
  #
1309
1312
  return self.parse_balance(response)
1310
1313
 
1314
+ def create_market_order_with_cost(self, symbol: str, side: OrderSide, cost: float, params={}):
1315
+ """
1316
+ create a market order by providing the symbol, side and cost
1317
+ :see: https://docs.kraken.com/rest/#tag/Trading/operation/addOrder
1318
+ :param str symbol: unified symbol of the market to create an order in(only USD markets are supported)
1319
+ :param str side: 'buy' or 'sell'
1320
+ :param float cost: how much you want to trade in units of the quote currency
1321
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1322
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1323
+ """
1324
+ self.load_markets()
1325
+ # only buy orders are supported by the endpoint
1326
+ params['cost'] = cost
1327
+ return self.create_order(symbol, 'market', side, cost, None, params)
1328
+
1329
+ def create_market_buy_order_with_cost(self, symbol: str, cost: float, params={}):
1330
+ """
1331
+ create a market buy order by providing the symbol, side and cost
1332
+ :see: https://docs.kraken.com/rest/#tag/Trading/operation/addOrder
1333
+ :param str symbol: unified symbol of the market to create an order in
1334
+ :param float cost: how much you want to trade in units of the quote currency
1335
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1336
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1337
+ """
1338
+ self.load_markets()
1339
+ return self.create_market_order_with_cost(symbol, 'buy', cost, params)
1340
+
1311
1341
  def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1312
1342
  """
1313
1343
  :see: https://docs.kraken.com/rest/#tag/Trading/operation/addOrder
@@ -1336,7 +1366,7 @@ class kraken(Exchange, ImplicitAPI):
1336
1366
  'ordertype': type,
1337
1367
  'volume': self.amount_to_precision(symbol, amount),
1338
1368
  }
1339
- orderRequest = self.order_request('createOrder', symbol, type, request, price, params)
1369
+ orderRequest = self.order_request('createOrder', symbol, type, request, amount, price, params)
1340
1370
  response = self.privatePostAddOrder(self.extend(orderRequest[0], orderRequest[1]))
1341
1371
  #
1342
1372
  # {
@@ -1616,7 +1646,7 @@ class kraken(Exchange, ImplicitAPI):
1616
1646
  'trades': trades,
1617
1647
  }, market)
1618
1648
 
1619
- def order_request(self, method, symbol, type, request, price=None, params={}):
1649
+ def order_request(self, method: str, symbol: str, type: str, request: dict, amount: Num, price: Num = None, params={}):
1620
1650
  clientOrderId = self.safe_string_2(params, 'userref', 'clientOrderId')
1621
1651
  params = self.omit(params, ['userref', 'clientOrderId'])
1622
1652
  if clientOrderId is not None:
@@ -1630,9 +1660,21 @@ class kraken(Exchange, ImplicitAPI):
1630
1660
  trailingLimitAmount = self.safe_string(params, 'trailingLimitAmount')
1631
1661
  isTrailingAmountOrder = trailingAmount is not None
1632
1662
  isLimitOrder = type.endswith('limit') # supporting limit, stop-loss-limit, take-profit-limit, etc
1633
- if isLimitOrder and not isTrailingAmountOrder:
1663
+ isMarketOrder = type == 'market'
1664
+ cost = self.safe_string(params, 'cost')
1665
+ flags = self.safe_string(params, 'oflags')
1666
+ params = self.omit(params, ['cost', 'oflags'])
1667
+ isViqcOrder = (flags is not None) and (flags.find('viqc') > -1) # volume in quote currency
1668
+ if isMarketOrder and (cost is not None or isViqcOrder):
1669
+ if cost is None and (amount is not None):
1670
+ request['volume'] = self.cost_to_precision(symbol, self.number_to_string(amount))
1671
+ else:
1672
+ request['volume'] = self.cost_to_precision(symbol, cost)
1673
+ extendedOflags = flags + ',viqc' if (flags is not None) else 'viqc'
1674
+ request['oflags'] = extendedOflags
1675
+ elif isLimitOrder and not isTrailingAmountOrder:
1634
1676
  request['price'] = self.price_to_precision(symbol, price)
1635
- reduceOnly = self.safe_value_2(params, 'reduceOnly', 'reduce_only')
1677
+ reduceOnly = self.safe_bool_2(params, 'reduceOnly', 'reduce_only')
1636
1678
  if isStopLossOrTakeProfitTrigger:
1637
1679
  if isStopLossTriggerOrder:
1638
1680
  request['price'] = self.price_to_precision(symbol, stopLossTriggerPrice)
@@ -1666,7 +1708,7 @@ class kraken(Exchange, ImplicitAPI):
1666
1708
  request['reduce_only'] = True # ws request can't have stringified bool
1667
1709
  else:
1668
1710
  request['reduce_only'] = 'true' # not using hasattr(self, boolean) case, because the urlencodedNested transforms it into 'True' string
1669
- close = self.safe_value(params, 'close')
1711
+ close = self.safe_dict(params, 'close')
1670
1712
  if close is not None:
1671
1713
  close = self.extend({}, close)
1672
1714
  closePrice = self.safe_value(close, 'price')
@@ -1683,7 +1725,8 @@ class kraken(Exchange, ImplicitAPI):
1683
1725
  postOnly = None
1684
1726
  postOnly, params = self.handle_post_only(isMarket, False, params)
1685
1727
  if postOnly:
1686
- request['oflags'] = 'post'
1728
+ extendedPostFlags = flags + ',post' if (flags is not None) else 'post'
1729
+ request['oflags'] = extendedPostFlags
1687
1730
  params = self.omit(params, ['timeInForce', 'reduceOnly', 'stopLossPrice', 'takeProfitPrice', 'trailingAmount', 'trailingLimitAmount', 'offset'])
1688
1731
  return [request, params]
1689
1732
 
@@ -1716,7 +1759,7 @@ class kraken(Exchange, ImplicitAPI):
1716
1759
  }
1717
1760
  if amount is not None:
1718
1761
  request['volume'] = self.amount_to_precision(symbol, amount)
1719
- orderRequest = self.order_request('editOrder', symbol, type, request, price, params)
1762
+ orderRequest = self.order_request('editOrder', symbol, type, request, amount, price, params)
1720
1763
  response = self.privatePostEditOrder(self.extend(orderRequest[0], orderRequest[1]))
1721
1764
  #
1722
1765
  # {
@@ -2808,6 +2851,8 @@ class kraken(Exchange, ImplicitAPI):
2808
2851
  raise CancelPending(self.id + ' ' + body)
2809
2852
  if body.find('Invalid arguments:volume') >= 0:
2810
2853
  raise InvalidOrder(self.id + ' ' + body)
2854
+ if body.find('Invalid arguments:viqc') >= 0:
2855
+ raise InvalidOrder(self.id + ' ' + body)
2811
2856
  if body.find('Rate limit exceeded') >= 0:
2812
2857
  raise RateLimitExceeded(self.id + ' ' + body)
2813
2858
  if response is None:
ccxt/kucoin.py CHANGED
@@ -4489,6 +4489,7 @@ class kucoin(Exchange, ImplicitAPI):
4489
4489
  partnerSignature = self.hmac(self.encode(partnerPayload), self.encode(partnerSecret), hashlib.sha256, 'base64')
4490
4490
  headers['KC-API-PARTNER-SIGN'] = partnerSignature
4491
4491
  headers['KC-API-PARTNER'] = partnerId
4492
+ headers['KC-API-PARTNER-VERIFY'] = 'true'
4492
4493
  if isBroker:
4493
4494
  brokerName = self.safe_string(partner, 'name')
4494
4495
  if brokerName is not None:
ccxt/phemex.py CHANGED
@@ -2168,7 +2168,7 @@ class phemex(Exchange, ImplicitAPI):
2168
2168
  if feeCost is not None:
2169
2169
  fee = {
2170
2170
  'cost': feeCost,
2171
- 'currency': None,
2171
+ 'currency': self.safe_currency_code(self.safe_string(order, 'feeCurrency')),
2172
2172
  }
2173
2173
  timeInForce = self.parse_time_in_force(self.safe_string(order, 'timeInForce'))
2174
2174
  stopPrice = self.parse_number(self.omit_zero(self.from_ep(self.safe_string(order, 'stopPxEp'))))
@@ -2313,6 +2313,7 @@ class phemex(Exchange, ImplicitAPI):
2313
2313
  clientOrderId = None
2314
2314
  marketId = self.safe_string(order, 'symbol')
2315
2315
  symbol = self.safe_symbol(marketId, market)
2316
+ market = self.safe_market(marketId, market)
2316
2317
  status = self.parse_order_status(self.safe_string(order, 'ordStatus'))
2317
2318
  side = self.parse_order_side(self.safe_string_lower(order, 'side'))
2318
2319
  type = self.parse_order_type(self.safe_string(order, 'orderType'))
@@ -2338,6 +2339,19 @@ class phemex(Exchange, ImplicitAPI):
2338
2339
  reduceOnly = True
2339
2340
  takeProfit = self.safe_string(order, 'takeProfitRp')
2340
2341
  stopLoss = self.safe_string(order, 'stopLossRp')
2342
+ feeValue = self.omit_zero(self.safe_string(order, 'execFeeRv'))
2343
+ ptFeeRv = self.omit_zero(self.safe_string(order, 'ptFeeRv'))
2344
+ fee = None
2345
+ if feeValue is not None:
2346
+ fee = {
2347
+ 'cost': feeValue,
2348
+ 'currency': market['quote'],
2349
+ }
2350
+ elif ptFeeRv is not None:
2351
+ fee = {
2352
+ 'cost': ptFeeRv,
2353
+ 'currency': 'PT',
2354
+ }
2341
2355
  return self.safe_order({
2342
2356
  'info': order,
2343
2357
  'id': id,
@@ -2362,7 +2376,7 @@ class phemex(Exchange, ImplicitAPI):
2362
2376
  'cost': cost,
2363
2377
  'average': None,
2364
2378
  'status': status,
2365
- 'fee': None,
2379
+ 'fee': fee,
2366
2380
  'trades': None,
2367
2381
  })
2368
2382
 
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.3.23'
7
+ __version__ = '4.3.27'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
@@ -36,8 +36,8 @@ from ccxt.pro.blockchaincom import blockchaincom # noqa
36
36
  from ccxt.pro.bybit import bybit # noqa: F401
37
37
  from ccxt.pro.cex import cex # noqa: F401
38
38
  from ccxt.pro.coinbase import coinbase # noqa: F401
39
+ from ccxt.pro.coinbaseexchange import coinbaseexchange # noqa: F401
39
40
  from ccxt.pro.coinbaseinternational import coinbaseinternational # noqa: F401
40
- from ccxt.pro.coinbasepro import coinbasepro # noqa: F401
41
41
  from ccxt.pro.coincheck import coincheck # noqa: F401
42
42
  from ccxt.pro.coinex import coinex # noqa: F401
43
43
  from ccxt.pro.coinone import coinone # noqa: F401
@@ -103,8 +103,8 @@ exchanges = [
103
103
  'bybit',
104
104
  'cex',
105
105
  'coinbase',
106
+ 'coinbaseexchange',
106
107
  'coinbaseinternational',
107
- 'coinbasepro',
108
108
  'coincheck',
109
109
  'coinex',
110
110
  'coinone',
ccxt/pro/binance.py CHANGED
@@ -1951,7 +1951,7 @@ class binance(ccxt.async_support.binance):
1951
1951
  orders = self.parse_orders(result)
1952
1952
  client.resolve(orders, messageHash)
1953
1953
 
1954
- async def edit_order_ws(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}) -> Order:
1954
+ async def edit_order_ws(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}) -> Order:
1955
1955
  """
1956
1956
  edit a trade order
1957
1957
  :see: https://binance-docs.github.io/apidocs/websocket_api/en/#cancel-and-replace-order-trade
ccxt/pro/bitget.py CHANGED
@@ -1060,7 +1060,7 @@ class bitget(ccxt.async_support.bitget):
1060
1060
  # "executePrice": "35123", # self is limit price
1061
1061
  # "triggerType": "fill_price",
1062
1062
  # "planType": "amount",
1063
- # #### in case order had fill: ####
1063
+ # #### in case order had a partial fill: ####
1064
1064
  # fillPrice: '35123',
1065
1065
  # tradeId: '1171775539946528779',
1066
1066
  # baseVolume: '7', # field present in market order
@@ -1177,13 +1177,19 @@ class bitget(ccxt.async_support.bitget):
1177
1177
  totalAmount = None
1178
1178
  filledAmount = None
1179
1179
  cost = None
1180
+ remaining = None
1181
+ totalFilled = self.safe_string(order, 'accBaseVolume')
1180
1182
  if isSpot:
1181
1183
  if isMargin:
1182
1184
  filledAmount = self.omit_zero(self.safe_string(order, 'fillTotalAmount'))
1183
1185
  totalAmount = self.omit_zero(self.safe_string(order, 'baseSize')) # for margin trading
1184
1186
  cost = self.safe_string(order, 'quoteSize')
1185
1187
  else:
1186
- filledAmount = self.omit_zero(self.safe_string_2(order, 'accBaseVolume', 'baseVolume'))
1188
+ partialFillAmount = self.safe_string(order, 'baseVolume')
1189
+ if partialFillAmount is not None:
1190
+ filledAmount = partialFillAmount
1191
+ else:
1192
+ filledAmount = totalFilled
1187
1193
  if isMarketOrder:
1188
1194
  if isBuy:
1189
1195
  totalAmount = accBaseVolume
@@ -1199,6 +1205,7 @@ class bitget(ccxt.async_support.bitget):
1199
1205
  filledAmount = self.safe_string(order, 'baseVolume')
1200
1206
  totalAmount = self.safe_string(order, 'size')
1201
1207
  cost = self.safe_string(order, 'fillNotionalUsd')
1208
+ remaining = self.omit_zero(Precise.string_sub(totalAmount, totalFilled))
1202
1209
  return self.safe_order({
1203
1210
  'info': order,
1204
1211
  'symbol': symbol,
@@ -1217,7 +1224,7 @@ class bitget(ccxt.async_support.bitget):
1217
1224
  'cost': cost,
1218
1225
  'average': avgPrice,
1219
1226
  'filled': filledAmount,
1220
- 'remaining': None,
1227
+ 'remaining': remaining,
1221
1228
  'status': self.parse_ws_order_status(rawStatus),
1222
1229
  'fee': feeObject,
1223
1230
  'trades': None,
@@ -16,10 +16,10 @@ from ccxt.base.errors import BadRequest
16
16
  from ccxt.base.errors import BadSymbol
17
17
 
18
18
 
19
- class coinbasepro(ccxt.async_support.coinbasepro):
19
+ class coinbaseexchange(ccxt.async_support.coinbaseexchange):
20
20
 
21
21
  def describe(self):
22
- return self.deep_extend(super(coinbasepro, self).describe(), {
22
+ return self.deep_extend(super(coinbaseexchange, self).describe(), {
23
23
  'has': {
24
24
  'ws': True,
25
25
  'watchOHLCV': False, # missing on the exchange side
@@ -38,7 +38,7 @@ class coinbasepro(ccxt.async_support.coinbasepro):
38
38
  },
39
39
  'urls': {
40
40
  'api': {
41
- 'ws': 'wss://ws-feed.pro.coinbase.com',
41
+ 'ws': 'wss://ws-feed.exchange.coinbase.com',
42
42
  },
43
43
  'test': {
44
44
  'ws': 'wss://ws-feed-public.sandbox.exchange.coinbase.com',
@@ -437,7 +437,7 @@ class coinbasepro(ccxt.async_support.coinbasepro):
437
437
  # "side": "buy",
438
438
  # "order_type": "limit"
439
439
  # }
440
- parsed = super(coinbasepro, self).parse_trade(trade)
440
+ parsed = super(coinbaseexchange, self).parse_trade(trade)
441
441
  feeRate = None
442
442
  isMaker = False
443
443
  if 'maker_fee_rate' in trade:
@@ -727,7 +727,7 @@ class coinbasepro(ccxt.async_support.coinbasepro):
727
727
  #
728
728
  type = self.safe_string(ticker, 'type')
729
729
  if type is None:
730
- return super(coinbasepro, self).parse_ticker(ticker, market)
730
+ return super(coinbaseexchange, self).parse_ticker(ticker, market)
731
731
  marketId = self.safe_string(ticker, 'product_id')
732
732
  symbol = self.safe_symbol(marketId, market, '-')
733
733
  timestamp = self.parse8601(self.safe_string(ticker, 'time'))
ccxt/pro/cryptocom.py CHANGED
@@ -103,13 +103,16 @@ class cryptocom(ccxt.async_support.cryptocom):
103
103
  if topicParams is None:
104
104
  params['params'] = {}
105
105
  bookSubscriptionType = None
106
- bookSubscriptionType, params = self.handle_option_and_params_2(params, 'watchOrderBook', 'watchOrderBookForSymbols', 'bookSubscriptionType', 'SNAPSHOT_AND_UPDATE')
107
- if bookSubscriptionType is not None:
108
- params['params']['bookSubscriptionType'] = bookSubscriptionType
106
+ bookSubscriptionType2 = None
107
+ bookSubscriptionType, params = self.handle_option_and_params(params, 'watchOrderBook', 'bookSubscriptionType', 'SNAPSHOT_AND_UPDATE')
108
+ bookSubscriptionType2, params = self.handle_option_and_params(params, 'watchOrderBookForSymbols', 'bookSubscriptionType', bookSubscriptionType)
109
+ params['params']['bookSubscriptionType'] = bookSubscriptionType2
109
110
  bookUpdateFrequency = None
110
- bookUpdateFrequency, params = self.handle_option_and_params_2(params, 'watchOrderBook', 'watchOrderBookForSymbols', 'bookUpdateFrequency')
111
- if bookUpdateFrequency is not None:
112
- params['params']['bookSubscriptionType'] = bookSubscriptionType
111
+ bookUpdateFrequency2 = None
112
+ bookUpdateFrequency, params = self.handle_option_and_params(params, 'watchOrderBook', 'bookUpdateFrequency')
113
+ bookUpdateFrequency2, params = self.handle_option_and_params(params, 'watchOrderBookForSymbols', 'bookUpdateFrequency', bookUpdateFrequency)
114
+ if bookUpdateFrequency2 is not None:
115
+ params['params']['bookSubscriptionType'] = bookUpdateFrequency2
113
116
  for i in range(0, len(symbols)):
114
117
  symbol = symbols[i]
115
118
  market = self.market(symbol)