ccxt 4.2.76__py2.py3-none-any.whl → 4.2.78__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.
Files changed (57) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/kucoin.py +1 -0
  3. ccxt/abstract/kucoinfutures.py +1 -0
  4. ccxt/async_support/__init__.py +1 -1
  5. ccxt/async_support/base/exchange.py +1 -1
  6. ccxt/async_support/binance.py +503 -444
  7. ccxt/async_support/bingx.py +1 -1
  8. ccxt/async_support/bitflyer.py +2 -2
  9. ccxt/async_support/bithumb.py +2 -2
  10. ccxt/async_support/blofin.py +11 -2
  11. ccxt/async_support/bybit.py +88 -52
  12. ccxt/async_support/coinbase.py +21 -10
  13. ccxt/async_support/delta.py +65 -51
  14. ccxt/async_support/deribit.py +2 -2
  15. ccxt/async_support/gate.py +3 -2
  16. ccxt/async_support/htx.py +34 -27
  17. ccxt/async_support/hyperliquid.py +7 -5
  18. ccxt/async_support/kraken.py +8 -8
  19. ccxt/async_support/kucoin.py +192 -5
  20. ccxt/async_support/okcoin.py +27 -1
  21. ccxt/async_support/okx.py +20 -2
  22. ccxt/async_support/woo.py +62 -3
  23. ccxt/base/exchange.py +9 -4
  24. ccxt/binance.py +503 -444
  25. ccxt/bingx.py +1 -1
  26. ccxt/bitflyer.py +2 -2
  27. ccxt/bithumb.py +2 -2
  28. ccxt/blofin.py +11 -2
  29. ccxt/bybit.py +88 -52
  30. ccxt/coinbase.py +21 -10
  31. ccxt/delta.py +65 -51
  32. ccxt/deribit.py +2 -2
  33. ccxt/gate.py +3 -2
  34. ccxt/htx.py +34 -27
  35. ccxt/hyperliquid.py +7 -5
  36. ccxt/kraken.py +8 -8
  37. ccxt/kucoin.py +192 -5
  38. ccxt/okcoin.py +27 -1
  39. ccxt/okx.py +20 -2
  40. ccxt/pro/__init__.py +1 -1
  41. ccxt/pro/ascendex.py +1 -1
  42. ccxt/pro/bitvavo.py +1 -1
  43. ccxt/pro/coinex.py +20 -14
  44. ccxt/pro/deribit.py +1 -1
  45. ccxt/pro/exmo.py +1 -1
  46. ccxt/pro/krakenfutures.py +1 -1
  47. ccxt/pro/phemex.py +1 -1
  48. ccxt/pro/poloniex.py +1 -1
  49. ccxt/pro/probit.py +1 -1
  50. ccxt/pro/woo.py +50 -6
  51. ccxt/test/test_async.py +9 -16
  52. ccxt/test/test_sync.py +9 -16
  53. ccxt/woo.py +62 -3
  54. {ccxt-4.2.76.dist-info → ccxt-4.2.78.dist-info}/METADATA +4 -4
  55. {ccxt-4.2.76.dist-info → ccxt-4.2.78.dist-info}/RECORD +57 -57
  56. {ccxt-4.2.76.dist-info → ccxt-4.2.78.dist-info}/WHEEL +0 -0
  57. {ccxt-4.2.76.dist-info → ccxt-4.2.78.dist-info}/top_level.txt +0 -0
ccxt/bingx.py CHANGED
@@ -2323,7 +2323,7 @@ class bingx(Exchange, ImplicitAPI):
2323
2323
  'FILLED': 'closed',
2324
2324
  'CANCELED': 'canceled',
2325
2325
  'CANCELLED': 'canceled',
2326
- 'FAILED': 'failed',
2326
+ 'FAILED': 'canceled',
2327
2327
  }
2328
2328
  return self.safe_string(statuses, status, status)
2329
2329
 
ccxt/bitflyer.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.bitflyer import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Trade, Transaction
9
+ from ccxt.base.types import Balances, Currency, Int, Market, MarketInterface, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Trade, Transaction
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import ArgumentsRequired
@@ -141,7 +141,7 @@ class bitflyer(Exchange, ImplicitAPI):
141
141
  month = self.safe_string(months, monthName)
142
142
  return self.parse8601(year + '-' + month + '-' + day + 'T00:00:00Z')
143
143
 
144
- def safe_market(self, marketId=None, market=None, delimiter=None, marketType=None):
144
+ def safe_market(self, marketId: Str = None, market: Market = None, delimiter: Str = None, marketType: Str = None) -> MarketInterface:
145
145
  # Bitflyer has a different type of conflict in markets, because
146
146
  # some of their ids(ETH/BTC and BTC/JPY) are duplicated in US, EU and JP.
147
147
  # Since they're the same we just need to return one
ccxt/bithumb.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.bithumb import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
9
+ from ccxt.base.types import Balances, Currency, Int, Market, MarketInterface, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import PermissionDenied
@@ -189,7 +189,7 @@ class bithumb(Exchange, ImplicitAPI):
189
189
  },
190
190
  })
191
191
 
192
- def safe_market(self, marketId=None, market=None, delimiter=None, marketType=None):
192
+ def safe_market(self, marketId: Str = None, market: Market = None, delimiter: Str = None, marketType: Str = None) -> MarketInterface:
193
193
  # bithumb has a different type of conflict in markets, because
194
194
  # their ids are the base currency(BTC for instance), so we can have
195
195
  # multiple "BTC" ids representing the different markets(BTC/ETH, "BTC/DOGE", etc)
ccxt/blofin.py CHANGED
@@ -1194,6 +1194,7 @@ class blofin(Exchange, ImplicitAPI):
1194
1194
  :param str id: order id
1195
1195
  :param str symbol: unified symbol of the market the order was made in
1196
1196
  :param dict [params]: extra parameters specific to the exchange API endpoint
1197
+ :param boolean [params.trigger]: True if cancelling a trigger/conditional order/tp sl orders
1197
1198
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1198
1199
  """
1199
1200
  if symbol is None:
@@ -1203,12 +1204,20 @@ class blofin(Exchange, ImplicitAPI):
1203
1204
  request = {
1204
1205
  'instId': market['id'],
1205
1206
  }
1207
+ isTrigger = self.safe_bool_n(params, ['stop', 'trigger', 'tpsl'], False)
1206
1208
  clientOrderId = self.safe_string(params, 'clientOrderId')
1207
1209
  if clientOrderId is not None:
1208
1210
  request['clientOrderId'] = clientOrderId
1209
1211
  else:
1210
- request['orderId'] = id
1211
- query = self.omit(params, ['orderId', 'clientOrderId'])
1212
+ if not isTrigger:
1213
+ request['orderId'] = str(id)
1214
+ else:
1215
+ request['tpslId'] = str(id)
1216
+ query = self.omit(params, ['orderId', 'clientOrderId', 'stop', 'trigger', 'tpsl'])
1217
+ if isTrigger:
1218
+ tpslResponse = self.cancel_orders([id], symbol, params)
1219
+ first = self.safe_dict(tpslResponse, 0)
1220
+ return first
1212
1221
  response = self.privatePostTradeCancelOrder(self.extend(request, query))
1213
1222
  data = self.safe_list(response, 'data', [])
1214
1223
  order = self.safe_dict(data, 0)
ccxt/bybit.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.bybit import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Currency, Greeks, Int, Leverage, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
9
+ from ccxt.base.types import Balances, Currency, Greeks, Int, Leverage, Market, MarketInterface, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import PermissionDenied
@@ -977,6 +977,9 @@ class bybit(Exchange, ImplicitAPI):
977
977
  'precisionMode': TICK_SIZE,
978
978
  'options': {
979
979
  'fetchMarkets': ['spot', 'linear', 'inverse', 'option'],
980
+ 'createOrder': {
981
+ 'method': 'privatePostV5OrderCreate', # 'privatePostV5PositionTradingStop'
982
+ },
980
983
  'enableUnifiedMargin': None,
981
984
  'enableUnifiedAccount': None,
982
985
  'createMarketBuyOrderRequiresPrice': True, # only True for classic accounts
@@ -1253,7 +1256,7 @@ class bybit(Exchange, ImplicitAPI):
1253
1256
  'info': None,
1254
1257
  }
1255
1258
 
1256
- def safe_market(self, marketId=None, market=None, delimiter=None, marketType=None):
1259
+ def safe_market(self, marketId: Str = None, market: Market = None, delimiter: Str = None, marketType: Str = None) -> MarketInterface:
1257
1260
  isOption = (marketId is not None) and ((marketId.find('-C') > -1) or (marketId.find('-P') > -1))
1258
1261
  if isOption and not (marketId in self.markets_by_id):
1259
1262
  # handle expired option contracts
@@ -3356,8 +3359,10 @@ class bybit(Exchange, ImplicitAPI):
3356
3359
  trailingAmount = self.safe_string_2(params, 'trailingAmount', 'trailingStop')
3357
3360
  isTrailingAmountOrder = trailingAmount is not None
3358
3361
  orderRequest = self.create_order_request(symbol, type, side, amount, price, params, enableUnifiedAccount)
3362
+ options = self.safe_value(self.options, 'createOrder', {})
3363
+ defaultMethod = self.safe_string(options, 'method', 'privatePostV5OrderCreate')
3359
3364
  response = None
3360
- if isTrailingAmountOrder:
3365
+ if isTrailingAmountOrder or (defaultMethod == 'privatePostV5PositionTradingStop'):
3361
3366
  response = self.privatePostV5PositionTradingStop(orderRequest)
3362
3367
  else:
3363
3368
  response = self.privatePostV5OrderCreate(orderRequest) # already extended inside createOrderRequest
@@ -3382,10 +3387,12 @@ class bybit(Exchange, ImplicitAPI):
3382
3387
  lowerCaseType = type.lower()
3383
3388
  if (price is None) and (lowerCaseType == 'limit'):
3384
3389
  raise ArgumentsRequired(self.id + ' createOrder requires a price argument for limit orders')
3390
+ defaultMethod = None
3391
+ defaultMethod, params = self.handle_option_and_params(params, 'createOrder', 'method', 'privatePostV5OrderCreate')
3385
3392
  request = {
3386
3393
  'symbol': market['id'],
3387
- 'side': self.capitalize(side),
3388
- 'orderType': self.capitalize(lowerCaseType), # limit or market
3394
+ # 'side': self.capitalize(side),
3395
+ # 'orderType': self.capitalize(lowerCaseType), # limit or market
3389
3396
  # 'timeInForce': 'GTC', # IOC, FOK, PostOnly
3390
3397
  # 'takeProfit': 123.45, # take profit price, only take effect upon opening the position
3391
3398
  # 'stopLoss': 123.45, # stop loss price, only take effect upon opening the position
@@ -3407,6 +3414,69 @@ class bybit(Exchange, ImplicitAPI):
3407
3414
  # Valid for option only.
3408
3415
  # 'orderIv': '0', # Implied volatility; parameters are passed according to the real value; for example, for 10%, 0.1 is passed
3409
3416
  }
3417
+ triggerPrice = self.safe_value_2(params, 'triggerPrice', 'stopPrice')
3418
+ stopLossTriggerPrice = self.safe_value(params, 'stopLossPrice')
3419
+ takeProfitTriggerPrice = self.safe_value(params, 'takeProfitPrice')
3420
+ stopLoss = self.safe_value(params, 'stopLoss')
3421
+ takeProfit = self.safe_value(params, 'takeProfit')
3422
+ trailingTriggerPrice = self.safe_string_2(params, 'trailingTriggerPrice', 'activePrice', self.number_to_string(price))
3423
+ trailingAmount = self.safe_string_2(params, 'trailingAmount', 'trailingStop')
3424
+ isTrailingAmountOrder = trailingAmount is not None
3425
+ isTriggerOrder = triggerPrice is not None
3426
+ isStopLossTriggerOrder = stopLossTriggerPrice is not None
3427
+ isTakeProfitTriggerOrder = takeProfitTriggerPrice is not None
3428
+ isStopLoss = stopLoss is not None
3429
+ isTakeProfit = takeProfit is not None
3430
+ isMarket = lowerCaseType == 'market'
3431
+ isLimit = lowerCaseType == 'limit'
3432
+ isBuy = side == 'buy'
3433
+ isAlternativeEndpoint = defaultMethod == 'privatePostV5PositionTradingStop'
3434
+ if isTrailingAmountOrder or isAlternativeEndpoint:
3435
+ if isStopLoss or isTakeProfit or isTriggerOrder or market['spot']:
3436
+ raise InvalidOrder(self.id + ' the API endpoint used only supports contract trailingAmount, stopLossPrice and takeProfitPrice orders')
3437
+ if isStopLossTriggerOrder or isTakeProfitTriggerOrder:
3438
+ if isStopLossTriggerOrder:
3439
+ request['stopLoss'] = self.price_to_precision(symbol, stopLossTriggerPrice)
3440
+ if isLimit:
3441
+ request['tpslMode'] = 'Partial'
3442
+ request['slOrderType'] = 'Limit'
3443
+ request['slLimitPrice'] = self.price_to_precision(symbol, price)
3444
+ request['slSize'] = self.amount_to_precision(symbol, amount)
3445
+ elif isTakeProfitTriggerOrder:
3446
+ request['takeProfit'] = self.price_to_precision(symbol, takeProfitTriggerPrice)
3447
+ if isLimit:
3448
+ request['tpslMode'] = 'Partial'
3449
+ request['tpOrderType'] = 'Limit'
3450
+ request['tpLimitPrice'] = self.price_to_precision(symbol, price)
3451
+ request['tpSize'] = self.amount_to_precision(symbol, amount)
3452
+ else:
3453
+ request['side'] = self.capitalize(side)
3454
+ request['orderType'] = self.capitalize(lowerCaseType)
3455
+ timeInForce = self.safe_string_lower(params, 'timeInForce') # self is same specific param
3456
+ postOnly = None
3457
+ postOnly, params = self.handle_post_only(isMarket, timeInForce == 'postonly', params)
3458
+ if postOnly:
3459
+ request['timeInForce'] = 'PostOnly'
3460
+ elif timeInForce == 'gtc':
3461
+ request['timeInForce'] = 'GTC'
3462
+ elif timeInForce == 'fok':
3463
+ request['timeInForce'] = 'FOK'
3464
+ elif timeInForce == 'ioc':
3465
+ request['timeInForce'] = 'IOC'
3466
+ if market['spot']:
3467
+ # only works for spot market
3468
+ if triggerPrice is not None:
3469
+ request['orderFilter'] = 'StopOrder'
3470
+ elif stopLossTriggerPrice is not None or takeProfitTriggerPrice is not None or isStopLoss or isTakeProfit:
3471
+ request['orderFilter'] = 'tpslOrder'
3472
+ clientOrderId = self.safe_string(params, 'clientOrderId')
3473
+ if clientOrderId is not None:
3474
+ request['orderLinkId'] = clientOrderId
3475
+ elif market['option']:
3476
+ # mandatory field for options
3477
+ request['orderLinkId'] = self.uuid16()
3478
+ if isLimit:
3479
+ request['price'] = self.price_to_precision(symbol, price)
3410
3480
  if market['spot']:
3411
3481
  request['category'] = 'spot'
3412
3482
  elif market['linear']:
@@ -3452,40 +3522,13 @@ class bybit(Exchange, ImplicitAPI):
3452
3522
  else:
3453
3523
  request['qty'] = self.cost_to_precision(symbol, amount)
3454
3524
  else:
3455
- request['qty'] = self.amount_to_precision(symbol, amount)
3456
- isMarket = lowerCaseType == 'market'
3457
- isLimit = lowerCaseType == 'limit'
3458
- if isLimit:
3459
- request['price'] = self.price_to_precision(symbol, price)
3460
- timeInForce = self.safe_string_lower(params, 'timeInForce') # self is same specific param
3461
- postOnly = None
3462
- postOnly, params = self.handle_post_only(isMarket, timeInForce == 'postonly', params)
3463
- if postOnly:
3464
- request['timeInForce'] = 'PostOnly'
3465
- elif timeInForce == 'gtc':
3466
- request['timeInForce'] = 'GTC'
3467
- elif timeInForce == 'fok':
3468
- request['timeInForce'] = 'FOK'
3469
- elif timeInForce == 'ioc':
3470
- request['timeInForce'] = 'IOC'
3471
- triggerPrice = self.safe_value_2(params, 'triggerPrice', 'stopPrice')
3472
- stopLossTriggerPrice = self.safe_value(params, 'stopLossPrice')
3473
- takeProfitTriggerPrice = self.safe_value(params, 'takeProfitPrice')
3474
- stopLoss = self.safe_value(params, 'stopLoss')
3475
- takeProfit = self.safe_value(params, 'takeProfit')
3476
- trailingTriggerPrice = self.safe_string_2(params, 'trailingTriggerPrice', 'activePrice', self.number_to_string(price))
3477
- trailingAmount = self.safe_string_2(params, 'trailingAmount', 'trailingStop')
3478
- isTrailingAmountOrder = trailingAmount is not None
3479
- isStopLossTriggerOrder = stopLossTriggerPrice is not None
3480
- isTakeProfitTriggerOrder = takeProfitTriggerPrice is not None
3481
- isStopLoss = stopLoss is not None
3482
- isTakeProfit = takeProfit is not None
3483
- isBuy = side == 'buy'
3525
+ if not isTrailingAmountOrder and not isAlternativeEndpoint:
3526
+ request['qty'] = self.amount_to_precision(symbol, amount)
3484
3527
  if isTrailingAmountOrder:
3485
3528
  if trailingTriggerPrice is not None:
3486
3529
  request['activePrice'] = self.price_to_precision(symbol, trailingTriggerPrice)
3487
3530
  request['trailingStop'] = trailingAmount
3488
- elif triggerPrice is not None:
3531
+ elif isTriggerOrder and not isAlternativeEndpoint:
3489
3532
  triggerDirection = self.safe_string(params, 'triggerDirection')
3490
3533
  params = self.omit(params, ['triggerPrice', 'stopPrice', 'triggerDirection'])
3491
3534
  if market['spot']:
@@ -3497,7 +3540,7 @@ class bybit(Exchange, ImplicitAPI):
3497
3540
  isAsending = ((triggerDirection == 'above') or (triggerDirection == '1'))
3498
3541
  request['triggerDirection'] = 1 if isAsending else 2
3499
3542
  request['triggerPrice'] = self.price_to_precision(symbol, triggerPrice)
3500
- elif isStopLossTriggerOrder or isTakeProfitTriggerOrder:
3543
+ elif (isStopLossTriggerOrder or isTakeProfitTriggerOrder) and not isAlternativeEndpoint:
3501
3544
  if isBuy:
3502
3545
  request['triggerDirection'] = 1 if isStopLossTriggerOrder else 2
3503
3546
  else:
@@ -3505,7 +3548,7 @@ class bybit(Exchange, ImplicitAPI):
3505
3548
  triggerPrice = stopLossTriggerPrice if isStopLossTriggerOrder else takeProfitTriggerPrice
3506
3549
  request['triggerPrice'] = self.price_to_precision(symbol, triggerPrice)
3507
3550
  request['reduceOnly'] = True
3508
- if isStopLoss or isTakeProfit:
3551
+ if (isStopLoss or isTakeProfit) and not isAlternativeEndpoint:
3509
3552
  if isStopLoss:
3510
3553
  slTriggerPrice = self.safe_value_2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss)
3511
3554
  request['stopLoss'] = self.price_to_precision(symbol, slTriggerPrice)
@@ -3522,18 +3565,6 @@ class bybit(Exchange, ImplicitAPI):
3522
3565
  request['tpslMode'] = 'Partial'
3523
3566
  request['tpOrderType'] = 'Limit'
3524
3567
  request['tpLimitPrice'] = self.price_to_precision(symbol, tpLimitPrice)
3525
- if market['spot']:
3526
- # only works for spot market
3527
- if triggerPrice is not None:
3528
- request['orderFilter'] = 'StopOrder'
3529
- elif stopLossTriggerPrice is not None or takeProfitTriggerPrice is not None or isStopLoss or isTakeProfit:
3530
- request['orderFilter'] = 'tpslOrder'
3531
- clientOrderId = self.safe_string(params, 'clientOrderId')
3532
- if clientOrderId is not None:
3533
- request['orderLinkId'] = clientOrderId
3534
- elif market['option']:
3535
- # mandatory field for options
3536
- request['orderLinkId'] = self.uuid16()
3537
3568
  params = self.omit(params, ['stopPrice', 'timeInForce', 'stopLossPrice', 'takeProfitPrice', 'postOnly', 'clientOrderId', 'triggerPrice', 'stopLoss', 'takeProfit', 'trailingAmount', 'trailingTriggerPrice'])
3538
3569
  return self.extend(request, params)
3539
3570
 
@@ -4847,7 +4878,9 @@ class bybit(Exchange, ImplicitAPI):
4847
4878
  return self.fetch_paginated_call_cursor('fetchMyTrades', symbol, since, limit, params, 'nextPageCursor', 'cursor', None, 100)
4848
4879
  enableUnifiedMargin, enableUnifiedAccount = self.is_unified_enabled()
4849
4880
  isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
4850
- request = {}
4881
+ request = {
4882
+ 'execType': 'Trade',
4883
+ }
4851
4884
  market = None
4852
4885
  isUsdcSettled = False
4853
4886
  if symbol is not None:
@@ -7492,11 +7525,14 @@ class bybit(Exchange, ImplicitAPI):
7492
7525
  tier = info[i]
7493
7526
  marketId = self.safe_string(info, 'symbol')
7494
7527
  market = self.safe_market(marketId)
7528
+ minNotional = self.parse_number('0')
7529
+ if i != 0:
7530
+ minNotional = self.safe_number(info[i - 1], 'riskLimitValue')
7495
7531
  tiers.append({
7496
7532
  'tier': self.safe_integer(tier, 'id'),
7497
7533
  'currency': market['settle'],
7498
- 'minNotional': None,
7499
- 'maxNotional': None,
7534
+ 'minNotional': minNotional,
7535
+ 'maxNotional': self.safe_number(tier, 'riskLimitValue'),
7500
7536
  'maintenanceMarginRate': self.safe_number(tier, 'maintenanceMargin'),
7501
7537
  'maxLeverage': self.safe_number(tier, 'maxLeverage'),
7502
7538
  'info': tier,
ccxt/coinbase.py CHANGED
@@ -1040,7 +1040,9 @@ class coinbase(Exchange, ImplicitAPI):
1040
1040
  :returns dict[]: an array of objects representing market data
1041
1041
  """
1042
1042
  method = self.safe_string(self.options, 'fetchMarkets', 'fetchMarketsV3')
1043
- return getattr(self, method)(params)
1043
+ if method == 'fetchMarketsV3':
1044
+ return self.fetch_markets_v3(params)
1045
+ return self.fetch_markets_v2(params)
1044
1046
 
1045
1047
  def fetch_markets_v2(self, params={}):
1046
1048
  response = self.fetch_currencies_from_cache(params)
@@ -1112,7 +1114,13 @@ class coinbase(Exchange, ImplicitAPI):
1112
1114
  return result
1113
1115
 
1114
1116
  def fetch_markets_v3(self, params={}):
1115
- response = self.v3PrivateGetBrokerageProducts(params)
1117
+ promisesUnresolved = [
1118
+ self.v3PrivateGetBrokerageProducts(params),
1119
+ self.v3PrivateGetBrokerageTransactionSummary(params),
1120
+ ]
1121
+ # response = self.v3PrivateGetBrokerageProducts(params)
1122
+ promises = promisesUnresolved
1123
+ response = self.safe_dict(promises, 0, {})
1116
1124
  #
1117
1125
  # [
1118
1126
  # {
@@ -1147,7 +1155,8 @@ class coinbase(Exchange, ImplicitAPI):
1147
1155
  # ...
1148
1156
  # ]
1149
1157
  #
1150
- fees = self.v3PrivateGetBrokerageTransactionSummary(params)
1158
+ # fees = self.v3PrivateGetBrokerageTransactionSummary(params)
1159
+ fees = self.safe_dict(promises, 1, {})
1151
1160
  #
1152
1161
  # {
1153
1162
  # "total_volume": 0,
@@ -1831,6 +1840,8 @@ class coinbase(Exchange, ImplicitAPI):
1831
1840
  response = self.v2PrivateGetAccountsAccountIdTransactions(self.extend(request, params))
1832
1841
  ledger = self.parse_ledger(response['data'], currency, since, limit)
1833
1842
  length = len(ledger)
1843
+ if length == 0:
1844
+ return ledger
1834
1845
  lastIndex = length - 1
1835
1846
  last = self.safe_dict(ledger, lastIndex)
1836
1847
  pagination = self.safe_dict(response, 'pagination', {})
@@ -2164,9 +2175,9 @@ class coinbase(Exchange, ImplicitAPI):
2164
2175
  'fee': fee,
2165
2176
  }
2166
2177
 
2167
- def find_account_id(self, code):
2178
+ def find_account_id(self, code, params={}):
2168
2179
  self.load_markets()
2169
- self.load_accounts()
2180
+ self.load_accounts(False, params)
2170
2181
  for i in range(0, len(self.accounts)):
2171
2182
  account = self.accounts[i]
2172
2183
  if account['code'] == code:
@@ -2190,7 +2201,7 @@ class coinbase(Exchange, ImplicitAPI):
2190
2201
  if accountId is None:
2191
2202
  if code is None:
2192
2203
  raise ArgumentsRequired(self.id + ' prepareAccountRequestWithCurrencyCode() method requires an account_id(or accountId) parameter OR a currency code argument')
2193
- accountId = self.find_account_id(code)
2204
+ accountId = self.find_account_id(code, params)
2194
2205
  if accountId is None:
2195
2206
  raise ExchangeError(self.id + ' prepareAccountRequestWithCurrencyCode() could not find account id for ' + code)
2196
2207
  request = {
@@ -2743,7 +2754,7 @@ class coinbase(Exchange, ImplicitAPI):
2743
2754
  paginate = False
2744
2755
  paginate, params = self.handle_option_and_params(params, 'fetchOrders', 'paginate')
2745
2756
  if paginate:
2746
- return self.fetch_paginated_call_cursor('fetchOrders', symbol, since, limit, params, 'cursor', 'cursor', None, 100)
2757
+ return self.fetch_paginated_call_cursor('fetchOrders', symbol, since, limit, params, 'cursor', 'cursor', None, 1000)
2747
2758
  market = None
2748
2759
  if symbol is not None:
2749
2760
  market = self.market(symbol)
@@ -3219,7 +3230,7 @@ class coinbase(Exchange, ImplicitAPI):
3219
3230
  if accountId is None:
3220
3231
  if code is None:
3221
3232
  raise ArgumentsRequired(self.id + ' withdraw() requires an account_id(or accountId) parameter OR a currency code argument')
3222
- accountId = self.find_account_id(code)
3233
+ accountId = self.find_account_id(code, params)
3223
3234
  if accountId is None:
3224
3235
  raise ExchangeError(self.id + ' withdraw() could not find account id for ' + code)
3225
3236
  request = {
@@ -3436,7 +3447,7 @@ class coinbase(Exchange, ImplicitAPI):
3436
3447
  if accountId is None:
3437
3448
  if code is None:
3438
3449
  raise ArgumentsRequired(self.id + ' deposit() requires an account_id(or accountId) parameter OR a currency code argument')
3439
- accountId = self.find_account_id(code)
3450
+ accountId = self.find_account_id(code, params)
3440
3451
  if accountId is None:
3441
3452
  raise ExchangeError(self.id + ' deposit() could not find account id for ' + code)
3442
3453
  request = {
@@ -3501,7 +3512,7 @@ class coinbase(Exchange, ImplicitAPI):
3501
3512
  if accountId is None:
3502
3513
  if code is None:
3503
3514
  raise ArgumentsRequired(self.id + ' fetchDeposit() requires an account_id(or accountId) parameter OR a currency code argument')
3504
- accountId = self.find_account_id(code)
3515
+ accountId = self.find_account_id(code, params)
3505
3516
  if accountId is None:
3506
3517
  raise ExchangeError(self.id + ' fetchDeposit() could not find account id for ' + code)
3507
3518
  request = {