ccxt 4.3.34__py2.py3-none-any.whl → 4.3.36__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.
Potentially problematic release.
This version of ccxt might be problematic. Click here for more details.
- ccxt/__init__.py +1 -1
- ccxt/abstract/bitbay.py +6 -0
- ccxt/abstract/zonda.py +6 -0
- ccxt/alpaca.py +1 -1
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/alpaca.py +1 -1
- ccxt/async_support/base/exchange.py +42 -42
- ccxt/async_support/binance.py +2 -2
- ccxt/async_support/bingx.py +4 -3
- ccxt/async_support/bit2c.py +2 -1
- ccxt/async_support/bitget.py +11 -5
- ccxt/async_support/bitmart.py +2 -7
- ccxt/async_support/btcmarkets.py +3 -1
- ccxt/async_support/bybit.py +1 -1
- ccxt/async_support/coinbase.py +60 -3
- ccxt/async_support/coinex.py +26 -19
- ccxt/async_support/gemini.py +1 -1
- ccxt/async_support/kraken.py +3 -1
- ccxt/async_support/paymium.py +4 -1
- ccxt/async_support/whitebit.py +24 -3
- ccxt/async_support/zaif.py +30 -2
- ccxt/async_support/zonda.py +6 -0
- ccxt/base/exchange.py +85 -76
- ccxt/binance.py +2 -2
- ccxt/bingx.py +4 -3
- ccxt/bit2c.py +2 -1
- ccxt/bitget.py +11 -5
- ccxt/bitmart.py +2 -7
- ccxt/btcmarkets.py +3 -1
- ccxt/bybit.py +1 -1
- ccxt/coinbase.py +60 -3
- ccxt/coinex.py +26 -19
- ccxt/gemini.py +1 -1
- ccxt/kraken.py +3 -1
- ccxt/paymium.py +4 -1
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/binance.py +4 -4
- ccxt/pro/bingx.py +9 -4
- ccxt/pro/bitfinex2.py +4 -4
- ccxt/pro/bitget.py +24 -1
- ccxt/pro/bitmart.py +9 -7
- ccxt/pro/bybit.py +6 -6
- ccxt/pro/htx.py +5 -6
- ccxt/pro/kraken.py +1 -1
- ccxt/pro/okx.py +4 -5
- ccxt/pro/woo.py +4 -4
- ccxt/test/base/test_crypto.py +1 -1
- ccxt/whitebit.py +24 -3
- ccxt/zaif.py +30 -2
- ccxt/zonda.py +6 -0
- {ccxt-4.3.34.dist-info → ccxt-4.3.36.dist-info}/METADATA +4 -4
- {ccxt-4.3.34.dist-info → ccxt-4.3.36.dist-info}/RECORD +54 -54
- {ccxt-4.3.34.dist-info → ccxt-4.3.36.dist-info}/WHEEL +0 -0
- {ccxt-4.3.34.dist-info → ccxt-4.3.36.dist-info}/top_level.txt +0 -0
ccxt/bit2c.py
CHANGED
@@ -448,7 +448,8 @@ class bit2c(Exchange, ImplicitAPI):
|
|
448
448
|
request: dict = {
|
449
449
|
'id': id,
|
450
450
|
}
|
451
|
-
|
451
|
+
response = self.privatePostOrderCancelOrder(self.extend(request, params))
|
452
|
+
return self.parse_order(response)
|
452
453
|
|
453
454
|
def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
454
455
|
"""
|
ccxt/bitget.py
CHANGED
@@ -1249,6 +1249,7 @@ class bitget(Exchange, ImplicitAPI):
|
|
1249
1249
|
'40712': InsufficientFunds, # Insufficient margin
|
1250
1250
|
'40713': ExchangeError, # Cannot exceed the maximum transferable margin amount
|
1251
1251
|
'40714': ExchangeError, # No direct margin call is allowed
|
1252
|
+
'40762': InsufficientFunds, # {"code":"40762","msg":"The order amount exceeds the balance","requestTime":1716572156622,"data":null}
|
1252
1253
|
'40768': OrderNotFound, # Order does not exist"
|
1253
1254
|
'41114': OnMaintenance, # {"code":"41114","msg":"The current trading pair is under maintenance, please refer to the official announcement for the opening time","requestTime":1679196062544,"data":null}
|
1254
1255
|
'43011': InvalidOrder, # The parameter does not meet the specification executePrice <= 0
|
@@ -2723,7 +2724,7 @@ class bitget(Exchange, ImplicitAPI):
|
|
2723
2724
|
request: dict = {}
|
2724
2725
|
type = None
|
2725
2726
|
type, params = self.handle_market_type_and_params('fetchTickers', market, params)
|
2726
|
-
# Calls like `.
|
2727
|
+
# Calls like `.fetchTickers(None, {subType:'inverse'})` should be supported for self exchange, so
|
2727
2728
|
# as "options.defaultSubType" is also set in exchange options, we should consider `params.subType`
|
2728
2729
|
# with higher priority and only default to spot, if `subType` is not set in params
|
2729
2730
|
passedSubType = self.safe_string(params, 'subType')
|
@@ -4138,18 +4139,23 @@ class bitget(Exchange, ImplicitAPI):
|
|
4138
4139
|
marginMode = 'cross'
|
4139
4140
|
marginModeRequest = 'crossed' if (marginMode == 'cross') else 'isolated'
|
4140
4141
|
request['marginMode'] = marginModeRequest
|
4141
|
-
|
4142
|
-
params = self.
|
4142
|
+
hedged = None
|
4143
|
+
hedged, params = self.handle_param_bool(params, 'hedged', False)
|
4144
|
+
# backward compatibility for `oneWayMode`
|
4145
|
+
oneWayMode = None
|
4146
|
+
oneWayMode, params = self.handle_param_bool(params, 'oneWayMode')
|
4147
|
+
if oneWayMode is not None:
|
4148
|
+
hedged = not oneWayMode
|
4143
4149
|
requestSide = side
|
4144
4150
|
if reduceOnly:
|
4145
|
-
if
|
4151
|
+
if not hedged:
|
4146
4152
|
request['reduceOnly'] = 'YES'
|
4147
4153
|
else:
|
4148
4154
|
# on bitget hedge mode if the position is long the side is always buy, and if the position is short the side is always sell
|
4149
4155
|
requestSide = 'sell' if (side == 'buy') else 'buy'
|
4150
4156
|
request['tradeSide'] = 'Close'
|
4151
4157
|
else:
|
4152
|
-
if
|
4158
|
+
if hedged:
|
4153
4159
|
request['tradeSide'] = 'Open'
|
4154
4160
|
request['side'] = requestSide
|
4155
4161
|
elif marketType == 'spot':
|
ccxt/bitmart.py
CHANGED
@@ -1180,14 +1180,9 @@ class bitmart(Exchange, ImplicitAPI):
|
|
1180
1180
|
market = self.safe_market(marketId, market)
|
1181
1181
|
symbol = market['symbol']
|
1182
1182
|
last = self.safe_string_2(ticker, 'close_24h', 'last_price')
|
1183
|
-
percentage = self.safe_string(ticker, 'price_change_percent_24h')
|
1183
|
+
percentage = Precise.string_abs(self.safe_string(ticker, 'price_change_percent_24h'))
|
1184
1184
|
if percentage is None:
|
1185
|
-
|
1186
|
-
if (percentageRaw is not None) and (percentageRaw != '0'): # a few tickers show strictly '0' in fluctuation field
|
1187
|
-
direction = percentageRaw[0]
|
1188
|
-
percentage = direction + Precise.string_mul(percentageRaw.replace(direction, ''), '100')
|
1189
|
-
elif percentageRaw == '0':
|
1190
|
-
percentage = '0'
|
1185
|
+
percentage = Precise.string_abs(Precise.string_mul(self.safe_string(ticker, 'fluctuation'), '100'))
|
1191
1186
|
baseVolume = self.safe_string(ticker, 'base_volume_24h')
|
1192
1187
|
quoteVolume = self.safe_string(ticker, 'quote_volume_24h')
|
1193
1188
|
if quoteVolume is None:
|
ccxt/btcmarkets.py
CHANGED
@@ -876,7 +876,9 @@ class btcmarkets(Exchange, ImplicitAPI):
|
|
876
876
|
"""
|
877
877
|
calculates the presumptive fee that would be charged for an order
|
878
878
|
:param str symbol: unified market symbol
|
879
|
-
:param str type: not used by btcmarkets.
|
879
|
+
:param str type: not used by btcmarkets.calculateFee
|
880
|
+
:param str side: not used by btcmarkets.calculateFee
|
881
|
+
:param float amount: how much you want to trade, in units of the base currency on most exchanges, or number of contracts
|
880
882
|
:param float price: the price for the order to be filled at, in units of the quote currency
|
881
883
|
:param str takerOrMaker: 'taker' or 'maker'
|
882
884
|
:param dict params:
|
ccxt/bybit.py
CHANGED
@@ -2079,7 +2079,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
2079
2079
|
}
|
2080
2080
|
type = None
|
2081
2081
|
type, params = self.handle_market_type_and_params('fetchTickers', market, params)
|
2082
|
-
# Calls like `.
|
2082
|
+
# Calls like `.fetchTickers(None, {subType:'inverse'})` should be supported for self exchange, so
|
2083
2083
|
# as "options.defaultSubType" is also set in exchange options, we should consider `params.subType`
|
2084
2084
|
# with higher priority and only default to spot, if `subType` is not set in params
|
2085
2085
|
passedSubType = self.safe_string(params, 'subType')
|
ccxt/coinbase.py
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
from ccxt.base.exchange import Exchange
|
7
7
|
from ccxt.abstract.coinbase import ImplicitAPI
|
8
8
|
import hashlib
|
9
|
-
from ccxt.base.types import Account, Balances, Conversion, Currencies, Currency, Int, Market, MarketInterface, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
|
9
|
+
from ccxt.base.types import Account, Balances, Conversion, Currencies, Currency, Int, Market, MarketInterface, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFees, Transaction
|
10
10
|
from typing import List
|
11
11
|
from ccxt.base.errors import ExchangeError
|
12
12
|
from ccxt.base.errors import AuthenticationError
|
@@ -121,8 +121,8 @@ class coinbase(Exchange, ImplicitAPI):
|
|
121
121
|
'fetchTickers': True,
|
122
122
|
'fetchTime': True,
|
123
123
|
'fetchTrades': True,
|
124
|
-
'fetchTradingFee':
|
125
|
-
'fetchTradingFees':
|
124
|
+
'fetchTradingFee': 'emulated',
|
125
|
+
'fetchTradingFees': True,
|
126
126
|
'fetchWithdrawals': True,
|
127
127
|
'reduceMargin': False,
|
128
128
|
'setLeverage': False,
|
@@ -4272,6 +4272,63 @@ class coinbase(Exchange, ImplicitAPI):
|
|
4272
4272
|
'takeProfitPrice': None,
|
4273
4273
|
})
|
4274
4274
|
|
4275
|
+
def fetch_trading_fees(self, params={}) -> TradingFees:
|
4276
|
+
"""
|
4277
|
+
:see: https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_gettransactionsummary/
|
4278
|
+
fetch the trading fees for multiple markets
|
4279
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
4280
|
+
:param str [params.type]: 'spot' or 'swap'
|
4281
|
+
:returns dict: a dictionary of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>` indexed by market symbols
|
4282
|
+
"""
|
4283
|
+
self.load_markets()
|
4284
|
+
type = None
|
4285
|
+
type, params = self.handle_market_type_and_params('fetchTradingFees', None, params)
|
4286
|
+
isSpot = (type == 'spot')
|
4287
|
+
productType = 'SPOT' if isSpot else 'FUTURE'
|
4288
|
+
request: dict = {
|
4289
|
+
'product_type': productType,
|
4290
|
+
}
|
4291
|
+
response = self.v3PrivateGetBrokerageTransactionSummary(self.extend(request, params))
|
4292
|
+
#
|
4293
|
+
# {
|
4294
|
+
# total_volume: '0',
|
4295
|
+
# total_fees: '0',
|
4296
|
+
# fee_tier: {
|
4297
|
+
# pricing_tier: 'Advanced 1',
|
4298
|
+
# usd_from: '0',
|
4299
|
+
# usd_to: '1000',
|
4300
|
+
# taker_fee_rate: '0.008',
|
4301
|
+
# maker_fee_rate: '0.006',
|
4302
|
+
# aop_from: '',
|
4303
|
+
# aop_to: ''
|
4304
|
+
# },
|
4305
|
+
# margin_rate: null,
|
4306
|
+
# goods_and_services_tax: null,
|
4307
|
+
# advanced_trade_only_volume: '0',
|
4308
|
+
# advanced_trade_only_fees: '0',
|
4309
|
+
# coinbase_pro_volume: '0',
|
4310
|
+
# coinbase_pro_fees: '0',
|
4311
|
+
# total_balance: '',
|
4312
|
+
# has_promo_fee: False
|
4313
|
+
# }
|
4314
|
+
#
|
4315
|
+
data = self.safe_dict(response, 'fee_tier', {})
|
4316
|
+
taker_fee = self.safe_number(data, 'taker_fee_rate')
|
4317
|
+
marker_fee = self.safe_number(data, 'maker_fee_rate')
|
4318
|
+
result: dict = {}
|
4319
|
+
for i in range(0, len(self.symbols)):
|
4320
|
+
symbol = self.symbols[i]
|
4321
|
+
market = self.market(symbol)
|
4322
|
+
if (isSpot and market['spot']) or (not isSpot and not market['spot']):
|
4323
|
+
result[symbol] = {
|
4324
|
+
'info': response,
|
4325
|
+
'symbol': symbol,
|
4326
|
+
'maker': taker_fee,
|
4327
|
+
'taker': marker_fee,
|
4328
|
+
'percentage': True,
|
4329
|
+
}
|
4330
|
+
return result
|
4331
|
+
|
4275
4332
|
def create_auth_token(self, seconds: Int, method: Str = None, url: Str = None):
|
4276
4333
|
# it may not work for v2
|
4277
4334
|
uri = None
|
ccxt/coinex.py
CHANGED
@@ -4374,7 +4374,7 @@ class coinex(Exchange, ImplicitAPI):
|
|
4374
4374
|
def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
|
4375
4375
|
"""
|
4376
4376
|
make a withdrawal
|
4377
|
-
:see: https://
|
4377
|
+
:see: https://docs.coinex.com/api/v2/assets/deposit-withdrawal/http/withdrawal
|
4378
4378
|
:param str code: unified currency code
|
4379
4379
|
:param float amount: the amount to withdraw
|
4380
4380
|
:param str address: the address to withdraw to
|
@@ -4387,35 +4387,42 @@ class coinex(Exchange, ImplicitAPI):
|
|
4387
4387
|
self.check_address(address)
|
4388
4388
|
self.load_markets()
|
4389
4389
|
currency = self.currency(code)
|
4390
|
-
networkCode = self.
|
4390
|
+
networkCode = self.safe_string_upper_2(params, 'network', 'chain')
|
4391
4391
|
params = self.omit(params, 'network')
|
4392
4392
|
if tag:
|
4393
4393
|
address = address + ':' + tag
|
4394
4394
|
request: dict = {
|
4395
|
-
'
|
4396
|
-
'
|
4397
|
-
'
|
4398
|
-
'transfer_method': 'onchain', # onchain, local
|
4395
|
+
'ccy': currency['id'],
|
4396
|
+
'to_address': address, # must be authorized, inter-user transfer by a registered mobile phone number or an email address is supported
|
4397
|
+
'amount': self.number_to_string(amount), # the actual amount without fees, https://www.coinex.com/fees
|
4399
4398
|
}
|
4400
4399
|
if networkCode is not None:
|
4401
|
-
request['
|
4402
|
-
response = self.
|
4400
|
+
request['chain'] = self.network_code_to_id(networkCode) # required for on-chain, not required for inter-user transfer
|
4401
|
+
response = self.v2PrivatePostAssetsWithdraw(self.extend(request, params))
|
4403
4402
|
#
|
4404
4403
|
# {
|
4405
4404
|
# "code": 0,
|
4406
4405
|
# "data": {
|
4407
|
-
# "
|
4408
|
-
# "
|
4409
|
-
# "
|
4410
|
-
# "
|
4411
|
-
# "
|
4406
|
+
# "withdraw_id": 31193755,
|
4407
|
+
# "created_at": 1716874165038,
|
4408
|
+
# "withdraw_method": "ON_CHAIN",
|
4409
|
+
# "ccy": "USDT",
|
4410
|
+
# "amount": "17.3",
|
4411
|
+
# "actual_amount": "15",
|
4412
|
+
# "chain": "TRC20",
|
4413
|
+
# "tx_fee": "2.3",
|
4414
|
+
# "fee_asset": "USDT",
|
4415
|
+
# "fee_amount": "2.3",
|
4416
|
+
# "to_address": "TY5vq3MT6b5cQVAHWHtpGyPg1ERcQgi3UN",
|
4417
|
+
# "memo": "",
|
4418
|
+
# "tx_id": "",
|
4412
4419
|
# "confirmations": 0,
|
4413
|
-
# "
|
4414
|
-
# "
|
4415
|
-
# "
|
4416
|
-
# "
|
4420
|
+
# "explorer_address_url": "https://tronscan.org/#/address/TY5vq3MT6b5cQVAHWHtpGyPg1ERcQgi3UN",
|
4421
|
+
# "explorer_tx_url": "https://tronscan.org/#/transaction/",
|
4422
|
+
# "remark": "",
|
4423
|
+
# "status": "audit_required"
|
4417
4424
|
# },
|
4418
|
-
# "message": "
|
4425
|
+
# "message": "OK"
|
4419
4426
|
# }
|
4420
4427
|
#
|
4421
4428
|
transaction = self.safe_dict(response, 'data', {})
|
@@ -4519,7 +4526,7 @@ class coinex(Exchange, ImplicitAPI):
|
|
4519
4526
|
# "remark": ""
|
4520
4527
|
# }
|
4521
4528
|
#
|
4522
|
-
# fetchWithdrawals
|
4529
|
+
# fetchWithdrawals and withdraw
|
4523
4530
|
#
|
4524
4531
|
# {
|
4525
4532
|
# "withdraw_id": 259364,
|
ccxt/gemini.py
CHANGED
@@ -831,7 +831,7 @@ class gemini(Exchange, ImplicitAPI):
|
|
831
831
|
:see: https://docs.gemini.com/rest-api/#ticker-v2
|
832
832
|
:param str symbol: unified symbol of the market to fetch the ticker for
|
833
833
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
834
|
-
:param dict [params.fetchTickerMethod]: 'fetchTickerV2', 'fetchTickerV1' or 'fetchTickerV1AndV2' - 'fetchTickerV1' for original ccxt.gemini.
|
834
|
+
:param dict [params.fetchTickerMethod]: 'fetchTickerV2', 'fetchTickerV1' or 'fetchTickerV1AndV2' - 'fetchTickerV1' for original ccxt.gemini.fetchTicker - 'fetchTickerV1AndV2' for 2 api calls to get the result of both fetchTicker methods - default = 'fetchTickerV1'
|
835
835
|
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
836
836
|
"""
|
837
837
|
method = self.safe_value(self.options, 'fetchTickerMethod', 'fetchTickerV1')
|
ccxt/kraken.py
CHANGED
@@ -970,7 +970,9 @@ class kraken(Exchange, ImplicitAPI):
|
|
970
970
|
else:
|
971
971
|
request['interval'] = timeframe
|
972
972
|
if since is not None:
|
973
|
-
|
973
|
+
scaledSince = self.parse_to_int(since / 1000)
|
974
|
+
timeFrameInSeconds = parsedTimeframe * 60
|
975
|
+
request['since'] = self.number_to_string(scaledSince - timeFrameInSeconds) # expected to be in seconds
|
974
976
|
response = self.publicGetOHLC(self.extend(request, params))
|
975
977
|
#
|
976
978
|
# {
|
ccxt/paymium.py
CHANGED
@@ -407,7 +407,10 @@ class paymium(Exchange, ImplicitAPI):
|
|
407
407
|
request: dict = {
|
408
408
|
'uuid': id,
|
409
409
|
}
|
410
|
-
|
410
|
+
response = self.privateDeleteUserOrdersUuidCancel(self.extend(request, params))
|
411
|
+
return self.safe_order({
|
412
|
+
'info': response,
|
413
|
+
})
|
411
414
|
|
412
415
|
def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
|
413
416
|
"""
|
ccxt/pro/__init__.py
CHANGED
ccxt/pro/binance.py
CHANGED
@@ -691,10 +691,10 @@ class binance(ccxt.async_support.binance):
|
|
691
691
|
# todo: self is a synch blocking call - make it async
|
692
692
|
# default 100, max 1000, valid limits 5, 10, 20, 50, 100, 500, 1000
|
693
693
|
snapshot = await self.fetch_rest_order_book_safe(symbol, limit, params)
|
694
|
-
|
695
|
-
if orderbook is None:
|
694
|
+
if self.safe_value(self.orderbooks, symbol) is None:
|
696
695
|
# if the orderbook is dropped before the snapshot is received
|
697
696
|
return
|
697
|
+
orderbook = self.orderbooks[symbol]
|
698
698
|
orderbook.reset(snapshot)
|
699
699
|
# unroll the accumulated deltas
|
700
700
|
messages = orderbook.cache
|
@@ -770,8 +770,7 @@ class binance(ccxt.async_support.binance):
|
|
770
770
|
symbol = market['symbol']
|
771
771
|
name = 'depth'
|
772
772
|
messageHash = market['lowercaseId'] + '@' + name
|
773
|
-
|
774
|
-
if orderbook is None:
|
773
|
+
if not (symbol in self.orderbooks):
|
775
774
|
#
|
776
775
|
# https://github.com/ccxt/ccxt/issues/6672
|
777
776
|
#
|
@@ -781,6 +780,7 @@ class binance(ccxt.async_support.binance):
|
|
781
780
|
# therefore it is safe to drop these premature messages.
|
782
781
|
#
|
783
782
|
return
|
783
|
+
orderbook = self.orderbooks[symbol]
|
784
784
|
nonce = self.safe_integer(orderbook, 'nonce')
|
785
785
|
if nonce is None:
|
786
786
|
# 2. Buffer the events you receive from the stream.
|
ccxt/pro/bingx.py
CHANGED
@@ -928,13 +928,16 @@ class bingx(ccxt.async_support.bingx):
|
|
928
928
|
# }
|
929
929
|
#
|
930
930
|
isSpot = ('dataType' in message)
|
931
|
-
result = self.
|
931
|
+
result = self.safe_dict_2(message, 'data', 'o', {})
|
932
932
|
cachedTrades = self.myTrades
|
933
933
|
if cachedTrades is None:
|
934
934
|
limit = self.safe_integer(self.options, 'tradesLimit', 1000)
|
935
935
|
cachedTrades = ArrayCacheBySymbolById(limit)
|
936
936
|
self.myTrades = cachedTrades
|
937
|
-
|
937
|
+
type = 'spot' if isSpot else 'swap'
|
938
|
+
marketId = self.safe_string(result, 's')
|
939
|
+
market = self.safe_market(marketId, None, '-', type)
|
940
|
+
parsed = self.parse_trade(result, market)
|
938
941
|
symbol = parsed['symbol']
|
939
942
|
spotHash = 'spot:mytrades'
|
940
943
|
swapHash = 'swap:mytrades'
|
@@ -980,10 +983,12 @@ class bingx(ccxt.async_support.bingx):
|
|
980
983
|
# }
|
981
984
|
# }
|
982
985
|
#
|
983
|
-
a = self.
|
984
|
-
data = self.
|
986
|
+
a = self.safe_dict(message, 'a', {})
|
987
|
+
data = self.safe_list(a, 'B', [])
|
985
988
|
timestamp = self.safe_integer_2(message, 'T', 'E')
|
986
989
|
type = 'swap' if ('P' in a) else 'spot'
|
990
|
+
if not (type in self.balance):
|
991
|
+
self.balance[type] = {}
|
987
992
|
self.balance[type]['info'] = data
|
988
993
|
self.balance[type]['timestamp'] = timestamp
|
989
994
|
self.balance[type]['datetime'] = self.iso8601(timestamp)
|
ccxt/pro/bitfinex2.py
CHANGED
@@ -551,8 +551,7 @@ class bitfinex2(ccxt.async_support.bitfinex2):
|
|
551
551
|
prec = self.safe_string(subscription, 'prec', 'P0')
|
552
552
|
isRaw = (prec == 'R0')
|
553
553
|
# if it is an initial snapshot
|
554
|
-
|
555
|
-
if orderbook is None:
|
554
|
+
if not (symbol in self.orderbooks):
|
556
555
|
limit = self.safe_integer(subscription, 'len')
|
557
556
|
if isRaw:
|
558
557
|
# raw order books
|
@@ -571,7 +570,7 @@ class bitfinex2(ccxt.async_support.bitfinex2):
|
|
571
570
|
bookside = orderbook[side]
|
572
571
|
idString = self.safe_string(delta, 0)
|
573
572
|
price = self.safe_float(delta, 1)
|
574
|
-
bookside.
|
573
|
+
bookside.storeArray([price, size, idString])
|
575
574
|
else:
|
576
575
|
deltas = message[1]
|
577
576
|
for i in range(0, len(deltas)):
|
@@ -582,10 +581,11 @@ class bitfinex2(ccxt.async_support.bitfinex2):
|
|
582
581
|
size = -amount if (amount < 0) else amount
|
583
582
|
side = 'asks' if (amount < 0) else 'bids'
|
584
583
|
bookside = orderbook[side]
|
585
|
-
bookside.
|
584
|
+
bookside.storeArray([price, size, counter])
|
586
585
|
orderbook['symbol'] = symbol
|
587
586
|
client.resolve(orderbook, messageHash)
|
588
587
|
else:
|
588
|
+
orderbook = self.orderbooks[symbol]
|
589
589
|
deltas = message[1]
|
590
590
|
orderbookItem = self.orderbooks[symbol]
|
591
591
|
if isRaw:
|
ccxt/pro/bitget.py
CHANGED
@@ -917,7 +917,9 @@ class bitget(ccxt.async_support.bitget):
|
|
917
917
|
:param int [limit]: the maximum number of order structures to retrieve
|
918
918
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
919
919
|
:param boolean [params.stop]: *contract only* set to True for watching trigger orders
|
920
|
-
:param str [params.marginMode]: 'isolated' or 'cross' for watching spot margin orders
|
920
|
+
:param str [params.marginMode]: 'isolated' or 'cross' for watching spot margin orders]
|
921
|
+
:param str [params.type]: 'spot', 'swap'
|
922
|
+
:param str [params.subType]: 'linear', 'inverse'
|
921
923
|
:returns dict[]: a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure
|
922
924
|
"""
|
923
925
|
await self.load_markets()
|
@@ -932,10 +934,21 @@ class bitget(ccxt.async_support.bitget):
|
|
932
934
|
symbol = market['symbol']
|
933
935
|
marketId = market['id']
|
934
936
|
messageHash = messageHash + ':' + symbol
|
937
|
+
productType = self.safe_string(params, 'productType')
|
935
938
|
type = None
|
936
939
|
type, params = self.handle_market_type_and_params('watchOrders', market, params)
|
940
|
+
subType = None
|
941
|
+
subType, params = self.handle_sub_type_and_params('watchOrders', market, params, 'linear')
|
937
942
|
if (type == 'spot') and (symbol is None):
|
938
943
|
raise ArgumentsRequired(self.id + ' watchOrders requires a symbol argument for ' + type + ' markets.')
|
944
|
+
if (productType is None) and (type != 'spot') and (symbol is None):
|
945
|
+
messageHash = messageHash + ':' + subType
|
946
|
+
elif productType == 'USDT-FUTURES':
|
947
|
+
messageHash = messageHash + ':linear'
|
948
|
+
elif productType == 'COIN-FUTURES':
|
949
|
+
messageHash = messageHash + ':inverse'
|
950
|
+
elif productType == 'USDC-FUTURES':
|
951
|
+
messageHash = messageHash + ':usdcfutures' # non unified channel
|
939
952
|
instType = None
|
940
953
|
instType, params = self.get_inst_type(market, params)
|
941
954
|
if type == 'spot':
|
@@ -952,6 +965,7 @@ class bitget(ccxt.async_support.bitget):
|
|
952
965
|
channel = 'orders-isolated'
|
953
966
|
else:
|
954
967
|
channel = 'orders-crossed'
|
968
|
+
subscriptionHash = subscriptionHash + ':' + instType
|
955
969
|
args: dict = {
|
956
970
|
'instType': instType,
|
957
971
|
'channel': channel,
|
@@ -1007,6 +1021,9 @@ class bitget(ccxt.async_support.bitget):
|
|
1007
1021
|
marketType = 'spot'
|
1008
1022
|
else:
|
1009
1023
|
marketType = 'contract'
|
1024
|
+
isLinearSwap = (instType == 'USDT-FUTURES')
|
1025
|
+
isInverseSwap = (instType == 'COIN-FUTURES')
|
1026
|
+
isUSDCFutures = (instType == 'USDC-FUTURES')
|
1010
1027
|
data = self.safe_value(message, 'data', [])
|
1011
1028
|
if self.orders is None:
|
1012
1029
|
limit = self.safe_integer(self.options, 'ordersLimit', 1000)
|
@@ -1030,6 +1047,12 @@ class bitget(ccxt.async_support.bitget):
|
|
1030
1047
|
innerMessageHash = messageHash + ':' + symbol
|
1031
1048
|
client.resolve(stored, innerMessageHash)
|
1032
1049
|
client.resolve(stored, messageHash)
|
1050
|
+
if isLinearSwap:
|
1051
|
+
client.resolve(stored, 'order:linear')
|
1052
|
+
if isInverseSwap:
|
1053
|
+
client.resolve(stored, 'order:inverse')
|
1054
|
+
if isUSDCFutures:
|
1055
|
+
client.resolve(stored, 'order:usdcfutures')
|
1033
1056
|
|
1034
1057
|
def parse_ws_order(self, order, market=None):
|
1035
1058
|
#
|
ccxt/pro/bitmart.py
CHANGED
@@ -12,7 +12,6 @@ from ccxt.async_support.base.ws.client import Client
|
|
12
12
|
from typing import List
|
13
13
|
from ccxt.base.errors import ExchangeError
|
14
14
|
from ccxt.base.errors import AuthenticationError
|
15
|
-
from ccxt.base.errors import ArgumentsRequired
|
16
15
|
from ccxt.base.errors import NotSupported
|
17
16
|
|
18
17
|
|
@@ -333,9 +332,9 @@ class bitmart(ccxt.async_support.bitmart):
|
|
333
332
|
|
334
333
|
async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
335
334
|
"""
|
336
|
-
:see: https://developer-pro.bitmart.com/en/spot/#private-order-channel
|
337
|
-
:see: https://developer-pro.bitmart.com/en/futures/#private-order-channel
|
338
335
|
watches information on multiple orders made by the user
|
336
|
+
:see: https://developer-pro.bitmart.com/en/spot/#private-order-progress
|
337
|
+
:see: https://developer-pro.bitmart.com/en/futures/#private-order-channel
|
339
338
|
:param str symbol: unified market symbol of the market orders were made in
|
340
339
|
:param int [since]: the earliest time in ms to fetch orders for
|
341
340
|
:param int [limit]: the maximum number of order structures to retrieve
|
@@ -354,11 +353,14 @@ class bitmart(ccxt.async_support.bitmart):
|
|
354
353
|
await self.authenticate(type, params)
|
355
354
|
request = None
|
356
355
|
if type == 'spot':
|
357
|
-
|
358
|
-
|
356
|
+
argsRequest = 'spot/user/order:'
|
357
|
+
if symbol is not None:
|
358
|
+
argsRequest += market['id']
|
359
|
+
else:
|
360
|
+
argsRequest = 'spot/user/orders:ALL_SYMBOLS'
|
359
361
|
request = {
|
360
362
|
'op': 'subscribe',
|
361
|
-
'args': [
|
363
|
+
'args': [argsRequest],
|
362
364
|
}
|
363
365
|
else:
|
364
366
|
request = {
|
@@ -506,7 +508,7 @@ class bitmart(ccxt.async_support.bitmart):
|
|
506
508
|
amount = self.safe_string(order, 'size')
|
507
509
|
type = self.safe_string(order, 'type')
|
508
510
|
rawState = self.safe_string(order, 'state')
|
509
|
-
status = self.
|
511
|
+
status = self.parse_order_status_by_type(market['type'], rawState)
|
510
512
|
timestamp = self.safe_integer(order, 'ms_t')
|
511
513
|
symbol = market['symbol']
|
512
514
|
side = self.safe_string_lower(order, 'side')
|
ccxt/pro/bybit.py
CHANGED
@@ -678,21 +678,21 @@ class bybit(ccxt.async_support.bybit):
|
|
678
678
|
isSpot = client.url.find('spot') >= 0
|
679
679
|
type = self.safe_string(message, 'type')
|
680
680
|
isSnapshot = (type == 'snapshot')
|
681
|
-
data = self.
|
681
|
+
data = self.safe_dict(message, 'data', {})
|
682
682
|
marketId = self.safe_string(data, 's')
|
683
683
|
marketType = 'spot' if isSpot else 'contract'
|
684
684
|
market = self.safe_market(marketId, None, None, marketType)
|
685
685
|
symbol = market['symbol']
|
686
686
|
timestamp = self.safe_integer(message, 'ts')
|
687
|
-
|
688
|
-
|
689
|
-
|
687
|
+
if not (symbol in self.orderbooks):
|
688
|
+
self.orderbooks[symbol] = self.order_book()
|
689
|
+
orderbook = self.orderbooks[symbol]
|
690
690
|
if isSnapshot:
|
691
691
|
snapshot = self.parse_order_book(data, symbol, timestamp, 'b', 'a')
|
692
692
|
orderbook.reset(snapshot)
|
693
693
|
else:
|
694
|
-
asks = self.
|
695
|
-
bids = self.
|
694
|
+
asks = self.safe_list(data, 'a', [])
|
695
|
+
bids = self.safe_list(data, 'b', [])
|
696
696
|
self.handle_deltas(orderbook['asks'], asks)
|
697
697
|
self.handle_deltas(orderbook['bids'], bids)
|
698
698
|
orderbook['timestamp'] = timestamp
|
ccxt/pro/htx.py
CHANGED
@@ -608,19 +608,18 @@ class htx(ccxt.async_support.htx):
|
|
608
608
|
# }
|
609
609
|
#
|
610
610
|
messageHash = self.safe_string(message, 'ch')
|
611
|
-
tick = self.
|
611
|
+
tick = self.safe_dict(message, 'tick')
|
612
612
|
event = self.safe_string(tick, 'event')
|
613
|
-
ch = self.
|
613
|
+
ch = self.safe_string(message, 'ch')
|
614
614
|
parts = ch.split('.')
|
615
615
|
marketId = self.safe_string(parts, 1)
|
616
616
|
symbol = self.safe_symbol(marketId)
|
617
|
-
|
618
|
-
if orderbook is None:
|
617
|
+
if not (symbol in self.orderbooks):
|
619
618
|
size = self.safe_string(parts, 3)
|
620
619
|
sizeParts = size.split('_')
|
621
620
|
limit = self.safe_integer(sizeParts, 1)
|
622
|
-
|
623
|
-
|
621
|
+
self.orderbooks[symbol] = self.order_book({}, limit)
|
622
|
+
orderbook = self.orderbooks[symbol]
|
624
623
|
if (event is None) and (orderbook['nonce'] is None):
|
625
624
|
orderbook.cache.append(message)
|
626
625
|
else:
|
ccxt/pro/kraken.py
CHANGED
@@ -1230,7 +1230,7 @@ class kraken(ccxt.async_support.kraken):
|
|
1230
1230
|
messageHashes = []
|
1231
1231
|
for i in range(0, len(symbols)):
|
1232
1232
|
messageHashes.append(self.get_message_hash(unifiedName, None, self.symbol(symbols[i])))
|
1233
|
-
# for WS subscriptions, we can't use .
|
1233
|
+
# for WS subscriptions, we can't use .marketIds(symbols), instead a custom is field needed
|
1234
1234
|
markets = self.markets_for_symbols(symbols)
|
1235
1235
|
wsMarketIds = []
|
1236
1236
|
for i in range(0, len(markets)):
|
ccxt/pro/okx.py
CHANGED
@@ -164,7 +164,7 @@ class okx(ccxt.async_support.okx):
|
|
164
164
|
self.deep_extend(firstArgument, params),
|
165
165
|
],
|
166
166
|
}
|
167
|
-
return self.watch(url, messageHash, request, messageHash)
|
167
|
+
return await self.watch(url, messageHash, request, messageHash)
|
168
168
|
|
169
169
|
async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
170
170
|
"""
|
@@ -1004,10 +1004,9 @@ class okx(ccxt.async_support.okx):
|
|
1004
1004
|
self.handle_order_book_message(client, update, orderbook, messageHash)
|
1005
1005
|
client.resolve(orderbook, messageHash)
|
1006
1006
|
elif (channel == 'books5') or (channel == 'bbo-tbt'):
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
self.orderbooks[symbol] = orderbook
|
1007
|
+
if not (symbol in self.orderbooks):
|
1008
|
+
self.orderbooks[symbol] = self.order_book({}, limit)
|
1009
|
+
orderbook = self.orderbooks[symbol]
|
1011
1010
|
for i in range(0, len(data)):
|
1012
1011
|
update = data[i]
|
1013
1012
|
timestamp = self.safe_integer(update, 'ts')
|
ccxt/pro/woo.py
CHANGED
@@ -130,14 +130,14 @@ class woo(ccxt.async_support.woo):
|
|
130
130
|
# }
|
131
131
|
# }
|
132
132
|
#
|
133
|
-
data = self.
|
133
|
+
data = self.safe_dict(message, 'data')
|
134
134
|
marketId = self.safe_string(data, 'symbol')
|
135
135
|
market = self.safe_market(marketId)
|
136
136
|
symbol = market['symbol']
|
137
137
|
topic = self.safe_string(message, 'topic')
|
138
|
-
|
139
|
-
|
140
|
-
|
138
|
+
if not (symbol in self.orderbooks):
|
139
|
+
self.orderbooks[symbol] = self.order_book({})
|
140
|
+
orderbook = self.orderbooks[symbol]
|
141
141
|
timestamp = self.safe_integer(message, 'ts')
|
142
142
|
snapshot = self.parse_order_book(data, symbol, timestamp, 'bids', 'asks')
|
143
143
|
orderbook.reset(snapshot)
|
ccxt/test/base/test_crypto.py
CHANGED
@@ -42,7 +42,7 @@ assert hash(encode('sexyfish'), 'md5', 'hex') == 'c8a35464aa9d5683585786f44d5889
|
|
42
42
|
assert hash(encode(''), 'sha1', 'hex') == 'da39a3ee5e6b4b0d3255bfef95601890afd80709'
|
43
43
|
assert hash(encode('nutella'), 'sha1', 'hex') == 'b3d60a34b744159793c483b067c56d8affc5111a'
|
44
44
|
assert hmac(encode('hello'), encode('there'), hashlib.sha256, 'hex') == '551e1c1ecbce0fe9b643745a376584a6289f5f43a46861b315fac9edc8d52a26'
|
45
|
-
assert hmac(encode('a message'), encode('a secret'),
|
45
|
+
assert hmac(encode('a message'), encode('a secret'), hashlib.md5, 'hex') == '0bfa503bdbc7358185fcd49b4869e23d'
|
46
46
|
|
47
47
|
# ---------------------------------------------------------------------------------------------------------------------
|
48
48
|
|