ccxt 4.1.91__py2.py3-none-any.whl → 4.1.95__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.
@@ -58,7 +58,7 @@ class bitget(Exchange, ImplicitAPI):
58
58
  'cancelOrder': True,
59
59
  'cancelOrders': True,
60
60
  'closeAllPositions': True,
61
- 'closePosition': False,
61
+ 'closePosition': True,
62
62
  'createMarketBuyOrderWithCost': True,
63
63
  'createMarketOrderWithCost': False,
64
64
  'createMarketSellOrderWithCost': False,
@@ -3432,7 +3432,7 @@ class bitget(Exchange, ImplicitAPI):
3432
3432
 
3433
3433
  def parse_order(self, order, market: Market = None) -> Order:
3434
3434
  #
3435
- # createOrder, editOrder
3435
+ # createOrder, editOrder, closePosition
3436
3436
  #
3437
3437
  # {
3438
3438
  # "clientOid": "abe95dbe-6081-4a6f-a2d3-ae49601cd479",
@@ -3709,8 +3709,12 @@ class bitget(Exchange, ImplicitAPI):
3709
3709
  'clientOrderId': self.safe_string_2(order, 'clientOrderId', 'clientOid'),
3710
3710
  'status': 'rejected',
3711
3711
  }, market)
3712
+ isContractOrder = ('posSide' in order)
3713
+ marketType = 'contract' if isContractOrder else 'spot'
3714
+ if market is not None:
3715
+ marketType = market['type']
3712
3716
  marketId = self.safe_string(order, 'symbol')
3713
- market = self.safe_market(marketId, market)
3717
+ market = self.safe_market(marketId, market, None, marketType)
3714
3718
  timestamp = self.safe_integer_2(order, 'cTime', 'ctime')
3715
3719
  updateTimestamp = self.safe_integer(order, 'uTime')
3716
3720
  rawStatus = self.safe_string_2(order, 'status', 'state')
@@ -4691,31 +4695,36 @@ class bitget(Exchange, ImplicitAPI):
4691
4695
  :param str [params.isPlan]: *swap only* 'plan' for stop orders and 'profit_loss' for tp/sl orders, default is 'plan'
4692
4696
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
4693
4697
  """
4694
- if symbol is None:
4695
- raise ArgumentsRequired(self.id + ' fetchOpenOrders() requires a symbol argument')
4696
4698
  await self.load_markets()
4697
4699
  sandboxMode = self.safe_value(self.options, 'sandboxMode', False)
4698
4700
  market = None
4699
- if sandboxMode:
4700
- sandboxSymbol = self.convert_symbol_for_sandbox(symbol)
4701
- market = self.market(sandboxSymbol)
4702
- else:
4703
- market = self.market(symbol)
4701
+ type = None
4702
+ request = {}
4704
4703
  marginMode = None
4705
4704
  marginMode, params = self.handle_margin_mode_and_params('fetchOpenOrders', params)
4705
+ if symbol is not None:
4706
+ if sandboxMode:
4707
+ sandboxSymbol = self.convert_symbol_for_sandbox(symbol)
4708
+ market = self.market(sandboxSymbol)
4709
+ else:
4710
+ market = self.market(symbol)
4711
+ request['symbol'] = market['id']
4712
+ defaultType = self.safe_string_2(self.options, 'fetchOpenOrders', 'defaultType', 'spot')
4713
+ marketType = market['type'] if ('type' in market) else defaultType
4714
+ type = self.safe_string(params, 'type', marketType)
4715
+ else:
4716
+ defaultType = self.safe_string_2(self.options, 'fetchOpenOrders', 'defaultType', 'spot')
4717
+ type = self.safe_string(params, 'type', defaultType)
4706
4718
  paginate = False
4707
4719
  paginate, params = self.handle_option_and_params(params, 'fetchOpenOrders', 'paginate')
4708
4720
  if paginate:
4709
4721
  cursorReceived = None
4710
- if market['spot']:
4722
+ if type == 'spot':
4711
4723
  if marginMode is not None:
4712
4724
  cursorReceived = 'minId'
4713
4725
  else:
4714
4726
  cursorReceived = 'endId'
4715
4727
  return await self.fetch_paginated_call_cursor('fetchOpenOrders', symbol, since, limit, params, cursorReceived, 'idLessThan')
4716
- request = {
4717
- 'symbol': market['id'],
4718
- }
4719
4728
  response = None
4720
4729
  stop = self.safe_value_2(params, 'stop', 'trigger')
4721
4730
  params = self.omit(params, ['stop', 'trigger'])
@@ -4724,35 +4733,37 @@ class bitget(Exchange, ImplicitAPI):
4724
4733
  request['startTime'] = since
4725
4734
  if limit is not None:
4726
4735
  request['limit'] = limit
4727
- if (market['swap']) or (market['future']) or (marginMode is not None):
4736
+ if (type == 'swap') or (type == 'future') or (marginMode is not None):
4728
4737
  clientOrderId = self.safe_string_2(params, 'clientOid', 'clientOrderId')
4729
4738
  params = self.omit(params, 'clientOrderId')
4730
4739
  if clientOrderId is not None:
4731
4740
  request['clientOid'] = clientOrderId
4732
- if market['spot']:
4741
+ query = None
4742
+ query = self.omit(params, ['type'])
4743
+ if type == 'spot':
4733
4744
  if marginMode is not None:
4734
4745
  if since is None:
4735
4746
  since = self.milliseconds() - 7776000000
4736
4747
  request['startTime'] = since
4737
4748
  if marginMode == 'isolated':
4738
- response = await self.privateMarginGetV2MarginIsolatedOpenOrders(self.extend(request, params))
4749
+ response = await self.privateMarginGetV2MarginIsolatedOpenOrders(self.extend(request, query))
4739
4750
  elif marginMode == 'cross':
4740
- response = await self.privateMarginGetV2MarginCrossedOpenOrders(self.extend(request, params))
4751
+ response = await self.privateMarginGetV2MarginCrossedOpenOrders(self.extend(request, query))
4741
4752
  else:
4742
4753
  if stop:
4743
- response = await self.privateSpotGetV2SpotTradeCurrentPlanOrder(self.extend(request, params))
4754
+ response = await self.privateSpotGetV2SpotTradeCurrentPlanOrder(self.extend(request, query))
4744
4755
  else:
4745
- response = await self.privateSpotGetV2SpotTradeUnfilledOrders(self.extend(request, params))
4756
+ response = await self.privateSpotGetV2SpotTradeUnfilledOrders(self.extend(request, query))
4746
4757
  else:
4747
4758
  productType = None
4748
- productType, params = self.handle_product_type_and_params(market, params)
4759
+ productType, query = self.handle_product_type_and_params(market, query)
4749
4760
  request['productType'] = productType
4750
4761
  if stop:
4751
- planType = self.safe_string(params, 'planType', 'normal_plan')
4762
+ planType = self.safe_string(query, 'planType', 'normal_plan')
4752
4763
  request['planType'] = planType
4753
- response = await self.privateMixGetV2MixOrderOrdersPlanPending(self.extend(request, params))
4764
+ response = await self.privateMixGetV2MixOrderOrdersPlanPending(self.extend(request, query))
4754
4765
  else:
4755
- response = await self.privateMixGetV2MixOrderOrdersPending(self.extend(request, params))
4766
+ response = await self.privateMixGetV2MixOrderOrdersPending(self.extend(request, query))
4756
4767
  #
4757
4768
  # spot
4758
4769
  #
@@ -4929,7 +4940,7 @@ class bitget(Exchange, ImplicitAPI):
4929
4940
  # }
4930
4941
  #
4931
4942
  data = self.safe_value(response, 'data')
4932
- if market['spot']:
4943
+ if type == 'spot':
4933
4944
  if (marginMode is not None) or stop:
4934
4945
  resultList = self.safe_value(data, 'orderList', [])
4935
4946
  return self.parse_orders(resultList, market, since, limit)
@@ -4954,12 +4965,13 @@ class bitget(Exchange, ImplicitAPI):
4954
4965
  :param int [params.until]: the latest time in ms to fetch entries for
4955
4966
  :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
4956
4967
  :param str [params.isPlan]: *swap only* 'plan' for stop orders and 'profit_loss' for tp/sl orders, default is 'plan'
4968
+ :param str [params.productType]: *contract only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
4957
4969
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
4958
4970
  """
4959
- if symbol is None:
4960
- raise ArgumentsRequired(self.id + ' fetchClosedOrders() requires a symbol argument')
4961
4971
  await self.load_markets()
4962
- market = self.market(symbol)
4972
+ market = None
4973
+ if symbol is not None:
4974
+ market = self.market(symbol)
4963
4975
  response = await self.fetch_canceled_and_closed_orders(symbol, since, limit, params)
4964
4976
  result = []
4965
4977
  for i in range(0, len(response)):
@@ -4985,12 +4997,13 @@ class bitget(Exchange, ImplicitAPI):
4985
4997
  :param int [params.until]: the latest time in ms to fetch entries for
4986
4998
  :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
4987
4999
  :param str [params.isPlan]: *swap only* 'plan' for stop orders and 'profit_loss' for tp/sl orders, default is 'plan'
5000
+ :param str [params.productType]: *contract only* 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
4988
5001
  :returns dict: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
4989
5002
  """
4990
- if symbol is None:
4991
- raise ArgumentsRequired(self.id + ' fetchCanceledOrders() requires a symbol argument')
4992
5003
  await self.load_markets()
4993
- market = self.market(symbol)
5004
+ market = None
5005
+ if symbol is not None:
5006
+ market = self.market(symbol)
4994
5007
  response = await self.fetch_canceled_and_closed_orders(symbol, since, limit, params)
4995
5008
  result = []
4996
5009
  for i in range(0, len(response)):
@@ -5005,25 +5018,27 @@ class bitget(Exchange, ImplicitAPI):
5005
5018
  sandboxMode = self.safe_value(self.options, 'sandboxMode', False)
5006
5019
  market = None
5007
5020
  if sandboxMode:
5008
- sandboxSymbol = self.convert_symbol_for_sandbox(symbol)
5009
- market = self.market(sandboxSymbol)
5010
- else:
5021
+ if symbol is not None:
5022
+ sandboxSymbol = self.convert_symbol_for_sandbox(symbol)
5023
+ symbol = sandboxSymbol
5024
+ request = {}
5025
+ if symbol is not None:
5011
5026
  market = self.market(symbol)
5027
+ request['symbol'] = market['id']
5028
+ marketType = None
5029
+ marketType, params = self.handle_market_type_and_params('fetchCanceledAndClosedOrders', market, params)
5012
5030
  marginMode = None
5013
5031
  marginMode, params = self.handle_margin_mode_and_params('fetchCanceledAndClosedOrders', params)
5014
5032
  paginate = False
5015
5033
  paginate, params = self.handle_option_and_params(params, 'fetchCanceledAndClosedOrders', 'paginate')
5016
5034
  if paginate:
5017
5035
  cursorReceived = None
5018
- if market['spot']:
5036
+ if marketType == 'spot':
5019
5037
  if marginMode is not None:
5020
5038
  cursorReceived = 'minId'
5021
5039
  else:
5022
5040
  cursorReceived = 'endId'
5023
5041
  return await self.fetch_paginated_call_cursor('fetchCanceledAndClosedOrders', symbol, since, limit, params, cursorReceived, 'idLessThan')
5024
- request = {
5025
- 'symbol': market['id'],
5026
- }
5027
5042
  response = None
5028
5043
  stop = self.safe_value_2(params, 'stop', 'trigger')
5029
5044
  params = self.omit(params, ['stop', 'trigger'])
@@ -5032,13 +5047,13 @@ class bitget(Exchange, ImplicitAPI):
5032
5047
  request['startTime'] = since
5033
5048
  if limit is not None:
5034
5049
  request['limit'] = limit
5035
- if (market['swap']) or (market['future']) or (marginMode is not None):
5050
+ if (marketType == 'swap') or (marketType == 'future') or (marginMode is not None):
5036
5051
  clientOrderId = self.safe_string_2(params, 'clientOid', 'clientOrderId')
5037
5052
  params = self.omit(params, 'clientOrderId')
5038
5053
  if clientOrderId is not None:
5039
5054
  request['clientOid'] = clientOrderId
5040
5055
  now = self.milliseconds()
5041
- if market['spot']:
5056
+ if marketType == 'spot':
5042
5057
  if marginMode is not None:
5043
5058
  if since is None:
5044
5059
  since = now - 7776000000
@@ -5049,6 +5064,8 @@ class bitget(Exchange, ImplicitAPI):
5049
5064
  response = await self.privateMarginGetV2MarginCrossedHistoryOrders(self.extend(request, params))
5050
5065
  else:
5051
5066
  if stop:
5067
+ if symbol is None:
5068
+ raise ArgumentsRequired(self.id + ' fetchCanceledAndClosedOrders() requires a symbol argument')
5052
5069
  endTime = self.safe_integer_n(params, ['endTime', 'until', 'till'])
5053
5070
  params = self.omit(params, ['until', 'till'])
5054
5071
  if since is None:
@@ -5248,7 +5265,7 @@ class bitget(Exchange, ImplicitAPI):
5248
5265
  # }
5249
5266
  #
5250
5267
  data = self.safe_value(response, 'data', {})
5251
- if market['spot']:
5268
+ if marketType == 'spot':
5252
5269
  if (marginMode is not None) or stop:
5253
5270
  return self.safe_value(data, 'orderList', [])
5254
5271
  else:
@@ -5880,11 +5897,10 @@ class bitget(Exchange, ImplicitAPI):
5880
5897
  #
5881
5898
  # closeAllPositions
5882
5899
  #
5883
- # {
5884
- # "symbol": "XRPUSDT_UMCBL",
5885
- # "orderId": "1111861847410757635",
5886
- # "clientOid": "1111861847410757637"
5887
- # }
5900
+ # {
5901
+ # "orderId": "1120923953904893955",
5902
+ # "clientOid": "1120923953904893956"
5903
+ # }
5888
5904
  #
5889
5905
  marketId = self.safe_string(position, 'symbol')
5890
5906
  market = self.safe_market(marketId, market, None, 'contract')
@@ -5943,7 +5959,7 @@ class bitget(Exchange, ImplicitAPI):
5943
5959
  percentage = Precise.string_mul(Precise.string_div(unrealizedPnl, initialMargin, 4), '100')
5944
5960
  return self.safe_position({
5945
5961
  'info': position,
5946
- 'id': None,
5962
+ 'id': self.safe_string(position, 'orderId'),
5947
5963
  'symbol': symbol,
5948
5964
  'notional': self.parse_number(notional),
5949
5965
  'marginMode': marginMode,
@@ -7457,57 +7473,87 @@ class bitget(Exchange, ImplicitAPI):
7457
7473
  'info': info,
7458
7474
  }
7459
7475
 
7476
+ async def close_position(self, symbol: str, side: OrderSide = None, params={}) -> Order:
7477
+ """
7478
+ closes an open position for a market
7479
+ :see: https://www.bitget.com/api-doc/contract/trade/Flash-Close-Position
7480
+ :param str symbol: unified CCXT market symbol
7481
+ :param str [side]: one-way mode: 'buy' or 'sell', hedge-mode: 'long' or 'short'
7482
+ :param dict [params]: extra parameters specific to the exchange API endpoint
7483
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
7484
+ """
7485
+ await self.load_markets()
7486
+ sandboxMode = self.safe_value(self.options, 'sandboxMode', False)
7487
+ market = None
7488
+ if sandboxMode:
7489
+ sandboxSymbol = self.convert_symbol_for_sandbox(symbol)
7490
+ market = self.market(sandboxSymbol)
7491
+ else:
7492
+ market = self.market(symbol)
7493
+ productType = None
7494
+ productType, params = self.handle_product_type_and_params(market, params)
7495
+ request = {
7496
+ 'symbol': market['id'],
7497
+ 'productType': productType,
7498
+ }
7499
+ if side is not None:
7500
+ request['holdSide'] = side
7501
+ response = await self.privateMixPostV2MixOrderClosePositions(self.extend(request, params))
7502
+ #
7503
+ # {
7504
+ # "code": "00000",
7505
+ # "msg": "success",
7506
+ # "requestTime": 1702975017017,
7507
+ # "data": {
7508
+ # "successList": [
7509
+ # {
7510
+ # "orderId": "1120923953904893955",
7511
+ # "clientOid": "1120923953904893956"
7512
+ # }
7513
+ # ],
7514
+ # "failureList": [],
7515
+ # "result": False
7516
+ # }
7517
+ # }
7518
+ #
7519
+ data = self.safe_value(response, 'data', {})
7520
+ order = self.safe_value(data, 'successList', [])
7521
+ return self.parse_order(order[0], market)
7522
+
7460
7523
  async def close_all_positions(self, params={}) -> List[Position]:
7461
7524
  """
7462
- closes open positions for a market
7463
- :see: https://bitgetlimited.github.io/apidoc/en/mix/#close-all-position
7464
- :param dict [params]: extra parameters specific to the okx api endpoint
7465
- :param str [params.subType]: 'linear' or 'inverse'
7466
- :param str [params.settle]: *required and only valid when params.subType == "linear"* 'USDT' or 'USDC'
7467
- :returns dict[]: `A list of position structures <https://docs.ccxt.com/#/?id=position-structure>`
7525
+ closes all open positions for a market type
7526
+ :see: https://www.bitget.com/api-doc/contract/trade/Flash-Close-Position
7527
+ :param dict [params]: extra parameters specific to the exchange API endpoint
7528
+ :param str [params.productType]: 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
7529
+ :returns dict[]: A list of `position structures <https://docs.ccxt.com/#/?id=position-structure>`
7468
7530
  """
7469
7531
  await self.load_markets()
7470
- subType = None
7471
- settle = None
7472
- subType, params = self.handle_sub_type_and_params('closeAllPositions', None, params)
7473
- settle = self.safe_string(params, 'settle', 'USDT')
7474
- params = self.omit(params, ['settle'])
7475
- productType = self.safe_string(params, 'productType')
7476
- request = {}
7477
- if productType is None:
7478
- sandboxMode = self.safe_value(self.options, 'sandboxMode', False)
7479
- localProductType = None
7480
- if subType == 'inverse':
7481
- localProductType = 'dmcbl'
7482
- else:
7483
- if settle == 'USDT':
7484
- localProductType = 'umcbl'
7485
- elif settle == 'USDC':
7486
- localProductType = 'cmcbl'
7487
- if sandboxMode:
7488
- localProductType = 's' + localProductType
7489
- request['productType'] = localProductType
7490
- response = await self.privateMixPostMixV1OrderCloseAllPositions(self.extend(request, params))
7491
- #
7492
- # {
7493
- # "code": "00000",
7494
- # "msg": "success",
7495
- # "requestTime": 1700814442466,
7496
- # "data": {
7497
- # "orderInfo": [
7498
- # {
7499
- # "symbol": "XRPUSDT_UMCBL",
7500
- # "orderId": "1111861847410757635",
7501
- # "clientOid": "1111861847410757637"
7502
- # },
7503
- # ],
7504
- # "failure": [],
7505
- # "result": True
7506
- # }
7507
- # }
7532
+ productType = None
7533
+ productType, params = self.handle_product_type_and_params(None, params)
7534
+ request = {
7535
+ 'productType': productType,
7536
+ }
7537
+ response = await self.privateMixPostV2MixOrderClosePositions(self.extend(request, params))
7538
+ #
7539
+ # {
7540
+ # "code": "00000",
7541
+ # "msg": "success",
7542
+ # "requestTime": 1702975017017,
7543
+ # "data": {
7544
+ # "successList": [
7545
+ # {
7546
+ # "orderId": "1120923953904893955",
7547
+ # "clientOid": "1120923953904893956"
7548
+ # }
7549
+ # ],
7550
+ # "failureList": [],
7551
+ # "result": False
7552
+ # }
7553
+ # }
7508
7554
  #
7509
7555
  data = self.safe_value(response, 'data', {})
7510
- orderInfo = self.safe_value(data, 'orderInfo', [])
7556
+ orderInfo = self.safe_value(data, 'successList', [])
7511
7557
  return self.parse_positions(orderInfo, None, params)
7512
7558
 
7513
7559
  def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
@@ -1484,15 +1484,8 @@ class bitrue(Exchange, ImplicitAPI):
1484
1484
  first = self.safe_string(symbols, 0)
1485
1485
  market = self.market(first)
1486
1486
  if market['swap']:
1487
- request['contractName'] = market['id']
1488
- if market['linear']:
1489
- response = await self.fapiV1PublicGetTicker(self.extend(request, params))
1490
- elif market['inverse']:
1491
- response = await self.dapiV1PublicGetTicker(self.extend(request, params))
1492
- response['symbol'] = market['id']
1493
- data = [response]
1487
+ raise NotSupported(self.id + ' fetchTickers does not support swap markets, please use fetchTicker instead')
1494
1488
  elif market['spot']:
1495
- request['symbol'] = market['id']
1496
1489
  response = await self.spotV1PublicGetTicker24hr(self.extend(request, params))
1497
1490
  data = response
1498
1491
  else:
@@ -1500,7 +1493,7 @@ class bitrue(Exchange, ImplicitAPI):
1500
1493
  else:
1501
1494
  type, params = self.handle_market_type_and_params('fetchTickers', None, params)
1502
1495
  if type != 'spot':
1503
- raise NotSupported(self.id + ' fetchTickers only support spot when symbols is not set')
1496
+ raise NotSupported(self.id + ' fetchTickers only support spot when symbols are not proved')
1504
1497
  response = await self.spotV1PublicGetTicker24hr(self.extend(request, params))
1505
1498
  data = response
1506
1499
  #
@@ -312,6 +312,7 @@ class bybit(Exchange, ImplicitAPI):
312
312
  'v5/account/fee-rate': 10, # 5/s = 1000 / (20 * 10)
313
313
  'v5/account/info': 5,
314
314
  'v5/account/transaction-log': 1,
315
+ 'v5/account/smp-group': 1,
315
316
  'v5/account/mmp-state': 5,
316
317
  # asset
317
318
  'v5/asset/exchange/order-record': 5, # 10/s => cost = 50 / 10 = 5
@@ -207,6 +207,8 @@ class coinbase(Exchange, ImplicitAPI):
207
207
  'brokerage/products/{product_id}',
208
208
  'brokerage/products/{product_id}/candles',
209
209
  'brokerage/products/{product_id}/ticker',
210
+ 'brokerage/portfolios',
211
+ 'brokerage/portfolios/{portfolio_uuid}',
210
212
  'brokerage/transaction_summary',
211
213
  'brokerage/product_book',
212
214
  'brokerage/best_bid_ask',
@@ -218,9 +220,17 @@ class coinbase(Exchange, ImplicitAPI):
218
220
  'brokerage/orders/batch_cancel',
219
221
  'brokerage/orders/edit',
220
222
  'brokerage/orders/edit_preview',
223
+ 'brokerage/portfolios',
224
+ 'brokerage/portfolios/move_funds',
221
225
  'brokerage/convert/quote',
222
226
  'brokerage/convert/trade/{trade_id}',
223
227
  ],
228
+ 'put': [
229
+ 'brokerage/portfolios/{portfolio_uuid}',
230
+ ],
231
+ 'delete': [
232
+ 'brokerage/portfolios/{portfolio_uuid}',
233
+ ],
224
234
  },
225
235
  },
226
236
  },
@@ -277,6 +287,8 @@ class coinbase(Exchange, ImplicitAPI):
277
287
  'not_found': ExchangeError, # 404 Resource not found
278
288
  'rate_limit_exceeded': RateLimitExceeded, # 429 Rate limit exceeded
279
289
  'internal_server_error': ExchangeError, # 500 Internal server error
290
+ 'UNSUPPORTED_ORDER_CONFIGURATION': BadRequest,
291
+ 'INSUFFICIENT_FUND': BadRequest,
280
292
  },
281
293
  'broad': {
282
294
  'request timestamp expired': InvalidNonce, # {"errors":[{"id":"authentication_error","message":"request timestamp expired"}]}
@@ -2171,6 +2183,8 @@ class coinbase(Exchange, ImplicitAPI):
2171
2183
  params = self.omit(params, ['timeInForce', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice', 'stopPrice', 'stop_price', 'stopDirection', 'stop_direction', 'clientOrderId', 'postOnly', 'post_only', 'end_time'])
2172
2184
  response = await self.v3PrivatePostBrokerageOrders(self.extend(request, params))
2173
2185
  #
2186
+ # successful order
2187
+ #
2174
2188
  # {
2175
2189
  # "success": True,
2176
2190
  # "failure_reason": "UNKNOWN_FAILURE_REASON",
@@ -2184,9 +2198,36 @@ class coinbase(Exchange, ImplicitAPI):
2184
2198
  # "order_configuration": null
2185
2199
  # }
2186
2200
  #
2201
+ # failed order
2202
+ #
2203
+ # {
2204
+ # "success": False,
2205
+ # "failure_reason": "UNKNOWN_FAILURE_REASON",
2206
+ # "order_id": "",
2207
+ # "error_response": {
2208
+ # "error": "UNSUPPORTED_ORDER_CONFIGURATION",
2209
+ # "message": "source is not enabled for trading",
2210
+ # "error_details": "",
2211
+ # "new_order_failure_reason": "UNSUPPORTED_ORDER_CONFIGURATION"
2212
+ # },
2213
+ # "order_configuration": {
2214
+ # "limit_limit_gtc": {
2215
+ # "base_size": "100",
2216
+ # "limit_price": "40000",
2217
+ # "post_only": False
2218
+ # }
2219
+ # }
2220
+ # }
2221
+ #
2187
2222
  success = self.safe_value(response, 'success')
2188
2223
  if success is not True:
2189
- raise BadRequest(self.id + ' createOrder() has failed, check your arguments and parameters')
2224
+ errorResponse = self.safe_value(response, 'error_response')
2225
+ errorTitle = self.safe_string(errorResponse, 'error')
2226
+ errorMessage = self.safe_string(errorResponse, 'message')
2227
+ if errorResponse is not None:
2228
+ self.throw_exactly_matched_exception(self.exceptions['exact'], errorTitle, errorMessage)
2229
+ self.throw_broadly_matched_exception(self.exceptions['broad'], errorTitle, errorMessage)
2230
+ raise ExchangeError(errorMessage)
2190
2231
  data = self.safe_value(response, 'success_response', {})
2191
2232
  return self.parse_order(data, market)
2192
2233