ccxt 4.3.69__py2.py3-none-any.whl → 4.3.71__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ccxt/__init__.py +3 -1
- ccxt/abstract/coinbaseinternational.py +1 -1
- ccxt/abstract/paradex.py +40 -0
- ccxt/async_support/__init__.py +3 -1
- ccxt/async_support/base/exchange.py +1 -1
- ccxt/async_support/blofin.py +63 -6
- ccxt/async_support/bybit.py +1 -1
- ccxt/async_support/coinbaseinternational.py +155 -2
- ccxt/async_support/cryptocom.py +12 -1
- ccxt/async_support/paradex.py +1966 -0
- ccxt/async_support/poloniex.py +1 -0
- ccxt/async_support/woo.py +4 -2
- ccxt/base/exchange.py +63 -1
- ccxt/blofin.py +63 -6
- ccxt/bybit.py +1 -1
- ccxt/coinbaseinternational.py +155 -2
- ccxt/cryptocom.py +12 -1
- ccxt/paradex.py +1966 -0
- ccxt/poloniex.py +1 -0
- ccxt/pro/__init__.py +5 -1
- ccxt/pro/bequant.py +4 -0
- ccxt/pro/blofin.py +608 -0
- ccxt/pro/coinbaseinternational.py +142 -11
- ccxt/pro/cryptocom.py +4 -1
- ccxt/pro/hitbtc.py +20 -8
- ccxt/pro/okx.py +6 -0
- ccxt/pro/paradex.py +340 -0
- ccxt/pro/poloniex.py +32 -10
- ccxt/pro/woo.py +5 -4
- ccxt/static_dependencies/__init__.py +1 -1
- ccxt/static_dependencies/lark/__init__.py +38 -0
- ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
- ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
- ccxt/static_dependencies/lark/ast_utils.py +59 -0
- ccxt/static_dependencies/lark/common.py +86 -0
- ccxt/static_dependencies/lark/exceptions.py +292 -0
- ccxt/static_dependencies/lark/grammar.py +130 -0
- ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
- ccxt/static_dependencies/lark/indenter.py +143 -0
- ccxt/static_dependencies/lark/lark.py +658 -0
- ccxt/static_dependencies/lark/lexer.py +678 -0
- ccxt/static_dependencies/lark/load_grammar.py +1428 -0
- ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
- ccxt/static_dependencies/lark/parser_frontends.py +257 -0
- ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
- ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
- ccxt/static_dependencies/lark/parsers/earley.py +314 -0
- ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
- ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
- ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
- ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
- ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
- ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
- ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
- ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
- ccxt/static_dependencies/lark/py.typed +0 -0
- ccxt/static_dependencies/lark/reconstruct.py +107 -0
- ccxt/static_dependencies/lark/tools/__init__.py +70 -0
- ccxt/static_dependencies/lark/tools/nearley.py +202 -0
- ccxt/static_dependencies/lark/tools/serialize.py +32 -0
- ccxt/static_dependencies/lark/tools/standalone.py +196 -0
- ccxt/static_dependencies/lark/tree.py +267 -0
- ccxt/static_dependencies/lark/tree_matcher.py +186 -0
- ccxt/static_dependencies/lark/tree_templates.py +180 -0
- ccxt/static_dependencies/lark/utils.py +343 -0
- ccxt/static_dependencies/lark/visitors.py +596 -0
- ccxt/static_dependencies/marshmallow/__init__.py +81 -0
- ccxt/static_dependencies/marshmallow/base.py +65 -0
- ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
- ccxt/static_dependencies/marshmallow/decorators.py +231 -0
- ccxt/static_dependencies/marshmallow/error_store.py +60 -0
- ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
- ccxt/static_dependencies/marshmallow/fields.py +2114 -0
- ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
- ccxt/static_dependencies/marshmallow/py.typed +0 -0
- ccxt/static_dependencies/marshmallow/schema.py +1228 -0
- ccxt/static_dependencies/marshmallow/types.py +12 -0
- ccxt/static_dependencies/marshmallow/utils.py +378 -0
- ccxt/static_dependencies/marshmallow/validate.py +678 -0
- ccxt/static_dependencies/marshmallow/warnings.py +2 -0
- ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
- ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
- ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
- ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
- ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
- ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
- ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
- ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
- ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
- ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
- ccxt/static_dependencies/starknet/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
- ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
- ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
- ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
- ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
- ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
- ccxt/static_dependencies/starknet/common.py +15 -0
- ccxt/static_dependencies/starknet/constants.py +39 -0
- ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
- ccxt/static_dependencies/starknet/hash/address.py +79 -0
- ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
- ccxt/static_dependencies/starknet/hash/selector.py +16 -0
- ccxt/static_dependencies/starknet/hash/storage.py +12 -0
- ccxt/static_dependencies/starknet/hash/utils.py +78 -0
- ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
- ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
- ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
- ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
- ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
- ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
- ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
- ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
- ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
- ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
- ccxt/static_dependencies/starknet/utils/schema.py +13 -0
- ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
- ccxt/static_dependencies/sympy/__init__.py +0 -0
- ccxt/static_dependencies/sympy/external/__init__.py +0 -0
- ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
- ccxt/static_dependencies/sympy/external/importtools.py +187 -0
- ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
- ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
- ccxt/static_dependencies/typing_extensions/__init__.py +0 -0
- ccxt/static_dependencies/typing_extensions/typing_extensions.py +3839 -0
- ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
- ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
- ccxt/test/tests_async.py +43 -1
- ccxt/test/tests_sync.py +43 -1
- ccxt/woo.py +4 -2
- {ccxt-4.3.69.dist-info → ccxt-4.3.71.dist-info}/METADATA +8 -7
- {ccxt-4.3.69.dist-info → ccxt-4.3.71.dist-info}/RECORD +159 -33
- {ccxt-4.3.69.dist-info → ccxt-4.3.71.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.3.69.dist-info → ccxt-4.3.71.dist-info}/WHEEL +0 -0
- {ccxt-4.3.69.dist-info → ccxt-4.3.71.dist-info}/top_level.txt +0 -0
@@ -4,9 +4,9 @@
|
|
4
4
|
# https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
|
5
5
|
|
6
6
|
import ccxt.async_support
|
7
|
-
from ccxt.async_support.base.ws.cache import ArrayCache
|
7
|
+
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheByTimestamp
|
8
8
|
import hashlib
|
9
|
-
from ccxt.base.types import Int, Market, OrderBook, Strings, Ticker, FundingRate, FundingRates, Trade
|
9
|
+
from ccxt.base.types import Int, Market, OrderBook, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade
|
10
10
|
from ccxt.async_support.base.ws.client import Client
|
11
11
|
from typing import List
|
12
12
|
from ccxt.base.errors import ExchangeError
|
@@ -27,12 +27,12 @@ class coinbaseinternational(ccxt.async_support.coinbaseinternational):
|
|
27
27
|
'watchTicker': True,
|
28
28
|
'watchBalance': False,
|
29
29
|
'watchMyTrades': False,
|
30
|
-
'watchOHLCV':
|
30
|
+
'watchOHLCV': True,
|
31
31
|
'watchOHLCVForSymbols': False,
|
32
32
|
'watchOrders': False,
|
33
33
|
'watchOrdersForSymbols': False,
|
34
34
|
'watchPositions': False,
|
35
|
-
'watchTickers':
|
35
|
+
'watchTickers': True,
|
36
36
|
'createOrderWs': False,
|
37
37
|
'editOrderWs': False,
|
38
38
|
'cancelOrderWs': False,
|
@@ -58,6 +58,14 @@ class coinbaseinternational(ccxt.async_support.coinbaseinternational):
|
|
58
58
|
'tradesLimit': 1000,
|
59
59
|
'ordersLimit': 1000,
|
60
60
|
'myTradesLimit': 1000,
|
61
|
+
'timeframes': {
|
62
|
+
'1m': 'CANDLES_ONE_MINUTE',
|
63
|
+
'5m': 'CANDLES_FIVE_MINUTES',
|
64
|
+
'30m': 'CANDLES_THIRTY_MINUTES',
|
65
|
+
'1h': 'CANDLES_ONE_HOUR',
|
66
|
+
'2h': 'CANDLES_TWO_HOURS',
|
67
|
+
'1d': 'CANDLES_ONE_DAY',
|
68
|
+
},
|
61
69
|
},
|
62
70
|
'exceptions': {
|
63
71
|
'exact': {
|
@@ -80,15 +88,18 @@ class coinbaseinternational(ccxt.async_support.coinbaseinternational):
|
|
80
88
|
self.check_required_credentials()
|
81
89
|
market = None
|
82
90
|
messageHash = name
|
83
|
-
productIds =
|
91
|
+
productIds = None
|
84
92
|
if symbols is None:
|
85
|
-
symbols = self.
|
93
|
+
symbols = self.get_active_symbols()
|
86
94
|
symbolsLength = len(symbols)
|
95
|
+
messageHashes = []
|
87
96
|
if symbolsLength > 1:
|
88
97
|
parsedSymbols = self.market_symbols(symbols)
|
89
98
|
marketIds = self.market_ids(parsedSymbols)
|
90
99
|
productIds = marketIds
|
91
|
-
|
100
|
+
for i in range(0, len(parsedSymbols)):
|
101
|
+
messageHashes.append(name + '::' + parsedSymbols[i])
|
102
|
+
# messageHash = messageHash + '::' + ','.join(parsedSymbols)
|
92
103
|
elif symbolsLength == 1:
|
93
104
|
market = self.market(symbols[0])
|
94
105
|
messageHash = name + '::' + market['symbol']
|
@@ -101,13 +112,17 @@ class coinbaseinternational(ccxt.async_support.coinbaseinternational):
|
|
101
112
|
signature = self.hmac(self.encode(auth), self.base64_to_binary(self.secret), hashlib.sha256, 'base64')
|
102
113
|
subscribe: dict = {
|
103
114
|
'type': 'SUBSCRIBE',
|
104
|
-
'product_ids': productIds,
|
115
|
+
# 'product_ids': productIds,
|
105
116
|
'channels': [name],
|
106
117
|
'time': timestamp,
|
107
118
|
'key': self.apiKey,
|
108
119
|
'passphrase': self.password,
|
109
120
|
'signature': signature,
|
110
121
|
}
|
122
|
+
if productIds is not None:
|
123
|
+
subscribe['product_ids'] = productIds
|
124
|
+
if symbolsLength > 1:
|
125
|
+
return await self.watch_multiple(url, messageHashes, self.extend(subscribe, params), messageHashes)
|
111
126
|
return await self.watch(url, messageHash, self.extend(subscribe, params), messageHash)
|
112
127
|
|
113
128
|
async def subscribe_multiple(self, name: str, symbols: Strings = None, params={}):
|
@@ -184,6 +199,7 @@ class coinbaseinternational(ccxt.async_support.coinbaseinternational):
|
|
184
199
|
:see: https://docs.cloud.coinbase.com/intx/docs/websocket-channels#instruments-channel
|
185
200
|
:param str [symbol]: unified symbol of the market to fetch the ticker for
|
186
201
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
202
|
+
:param str [params.channel]: the channel to watch, 'LEVEL1' or 'INSTRUMENTS', default is 'LEVEL1'
|
187
203
|
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
188
204
|
"""
|
189
205
|
await self.load_markets()
|
@@ -191,6 +207,35 @@ class coinbaseinternational(ccxt.async_support.coinbaseinternational):
|
|
191
207
|
channel, params = self.handle_option_and_params(params, 'watchTicker', 'channel', 'LEVEL1')
|
192
208
|
return await self.subscribe(channel, [symbol], params)
|
193
209
|
|
210
|
+
def get_active_symbols(self):
|
211
|
+
symbols = self.symbols
|
212
|
+
output = []
|
213
|
+
for i in range(0, len(symbols)):
|
214
|
+
symbol = symbols[i]
|
215
|
+
market = self.markets[symbol]
|
216
|
+
if market['active']:
|
217
|
+
output.append(symbol)
|
218
|
+
return output
|
219
|
+
|
220
|
+
async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
221
|
+
"""
|
222
|
+
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
223
|
+
:see: https://docs.cloud.coinbase.com/intx/docs/websocket-channels#instruments-channel
|
224
|
+
:param str[] [symbols]: unified symbol of the market to fetch the ticker for
|
225
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
226
|
+
:param str [params.channel]: the channel to watch, 'LEVEL1' or 'INSTRUMENTS', default is 'INSTLEVEL1UMENTS'
|
227
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
228
|
+
"""
|
229
|
+
await self.load_markets()
|
230
|
+
channel = None
|
231
|
+
channel, params = self.handle_option_and_params(params, 'watchTickers', 'channel', 'LEVEL1')
|
232
|
+
ticker = await self.subscribe(channel, symbols, params)
|
233
|
+
if self.newUpdates:
|
234
|
+
result: dict = {}
|
235
|
+
result[ticker['symbol']] = ticker
|
236
|
+
return result
|
237
|
+
return self.filter_by_array(self.tickers, 'symbol', symbols)
|
238
|
+
|
194
239
|
def handle_instrument(self, client: Client, message):
|
195
240
|
#
|
196
241
|
# {
|
@@ -248,6 +293,33 @@ class coinbaseinternational(ccxt.async_support.coinbaseinternational):
|
|
248
293
|
# "channel":"INSTRUMENTS",
|
249
294
|
# "type":"SNAPSHOT"
|
250
295
|
# }
|
296
|
+
# instruments
|
297
|
+
# {
|
298
|
+
# sequence: 0,
|
299
|
+
# instrument_type: 'PERP',
|
300
|
+
# instrument_mode: 'standard',
|
301
|
+
# base_asset_name: 'BTC',
|
302
|
+
# quote_asset_name: 'USDC',
|
303
|
+
# base_increment: '0.0001',
|
304
|
+
# quote_increment: '0.1',
|
305
|
+
# avg_daily_quantity: '502.8845',
|
306
|
+
# avg_daily_volume: '3.1495242961566668E7',
|
307
|
+
# total30_day_quantity: '15086.535',
|
308
|
+
# total30_day_volume: '9.44857288847E8',
|
309
|
+
# total24_hour_quantity: '5.0',
|
310
|
+
# total24_hour_volume: '337016.5',
|
311
|
+
# base_imf: '0.1',
|
312
|
+
# min_quantity: '0.0001',
|
313
|
+
# position_size_limit: '800',
|
314
|
+
# funding_interval: '3600000000000',
|
315
|
+
# trading_state: 'trading',
|
316
|
+
# last_updated_time: '2024-07-30T15:00:00Z',
|
317
|
+
# default_initial_margin: '0.2',
|
318
|
+
# base_asset_multiplier: '1.0',
|
319
|
+
# channel: 'INSTRUMENTS',
|
320
|
+
# type: 'SNAPSHOT',
|
321
|
+
# time: '2024-07-30T15:26:56.766Z',
|
322
|
+
# }
|
251
323
|
#
|
252
324
|
marketId = self.safe_string(ticker, 'product_id')
|
253
325
|
datetime = self.safe_string(ticker, 'time')
|
@@ -270,8 +342,8 @@ class coinbaseinternational(ccxt.async_support.coinbaseinternational):
|
|
270
342
|
'change': None,
|
271
343
|
'percentage': None,
|
272
344
|
'average': None,
|
273
|
-
'baseVolume': self.
|
274
|
-
'quoteVolume': self.
|
345
|
+
'baseVolume': self.safe_string_2(ticker, 'total_24_hour_quantity', 'total24_hour_quantity'),
|
346
|
+
'quoteVolume': self.safe_string_2(ticker, 'total_24_hour_volume', 'total24_hour_volume'),
|
275
347
|
})
|
276
348
|
|
277
349
|
def handle_ticker(self, client: Client, message):
|
@@ -343,6 +415,63 @@ class coinbaseinternational(ccxt.async_support.coinbaseinternational):
|
|
343
415
|
'previousClose': None,
|
344
416
|
})
|
345
417
|
|
418
|
+
async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
419
|
+
"""
|
420
|
+
watches historical candlestick data containing the open, high, low, close price, and the volume of a market
|
421
|
+
:see: https://docs.cdp.coinbase.com/intx/docs/websocket-channels#candles-channel
|
422
|
+
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
423
|
+
:param str timeframe: the length of time each candle represents
|
424
|
+
:param int [since]: timestamp in ms of the earliest candle to fetch
|
425
|
+
:param int [limit]: the maximum amount of candles to fetch
|
426
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
427
|
+
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
428
|
+
"""
|
429
|
+
await self.load_markets()
|
430
|
+
market = self.market(symbol)
|
431
|
+
symbol = market['symbol']
|
432
|
+
options = self.safe_dict(self.options, 'timeframes', {})
|
433
|
+
interval = self.safe_string(options, timeframe, timeframe)
|
434
|
+
ohlcv = await self.subscribe(interval, [symbol], params)
|
435
|
+
if self.newUpdates:
|
436
|
+
limit = ohlcv.getLimit(symbol, limit)
|
437
|
+
return self.filter_by_since_limit(ohlcv, since, limit, 0, True)
|
438
|
+
|
439
|
+
def handle_ohlcv(self, client: Client, message):
|
440
|
+
#
|
441
|
+
# {
|
442
|
+
# "sequence": 0,
|
443
|
+
# "product_id": "BTC-PERP",
|
444
|
+
# "channel": "CANDLES_ONE_MINUTE",
|
445
|
+
# "type": "SNAPSHOT",
|
446
|
+
# "candles": [
|
447
|
+
# {
|
448
|
+
# "time": "2023-05-10T14:58:47.000Z",
|
449
|
+
# "low": "28787.8",
|
450
|
+
# "high": "28788.8",
|
451
|
+
# "open": "28788.8",
|
452
|
+
# "close": "28787.8",
|
453
|
+
# "volume": "0.466"
|
454
|
+
# },
|
455
|
+
# ]
|
456
|
+
# }
|
457
|
+
#
|
458
|
+
messageHash = self.safe_string(message, 'channel')
|
459
|
+
marketId = self.safe_string(message, 'product_id')
|
460
|
+
market = self.safe_market(marketId)
|
461
|
+
symbol = market['symbol']
|
462
|
+
timeframe = self.find_timeframe(messageHash)
|
463
|
+
self.ohlcvs[symbol] = self.safe_value(self.ohlcvs, symbol, {})
|
464
|
+
if self.safe_value(self.ohlcvs[symbol], timeframe) is None:
|
465
|
+
limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
|
466
|
+
self.ohlcvs[symbol][timeframe] = ArrayCacheByTimestamp(limit)
|
467
|
+
stored = self.ohlcvs[symbol][timeframe]
|
468
|
+
data = self.safe_list(message, 'candles', [])
|
469
|
+
for i in range(0, len(data)):
|
470
|
+
tick = data[i]
|
471
|
+
parsed = self.parse_ohlcv(tick, market)
|
472
|
+
stored.append(parsed)
|
473
|
+
client.resolve(stored, messageHash + '::' + symbol)
|
474
|
+
|
346
475
|
async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
347
476
|
"""
|
348
477
|
get the list of most recent trades for a particular symbol
|
@@ -606,7 +735,7 @@ class coinbaseinternational(ccxt.async_support.coinbaseinternational):
|
|
606
735
|
def handle_message(self, client, message):
|
607
736
|
if self.handle_error_message(client, message):
|
608
737
|
return
|
609
|
-
channel = self.safe_string(message, 'channel')
|
738
|
+
channel = self.safe_string(message, 'channel', '')
|
610
739
|
methods: dict = {
|
611
740
|
'SUBSCRIPTIONS': self.handle_subscription_status,
|
612
741
|
'INSTRUMENTS': self.handle_instrument,
|
@@ -620,6 +749,8 @@ class coinbaseinternational(ccxt.async_support.coinbaseinternational):
|
|
620
749
|
if type == 'error':
|
621
750
|
errorMessage = self.safe_string(message, 'message')
|
622
751
|
raise ExchangeError(errorMessage)
|
752
|
+
if channel.find('CANDLES') > -1:
|
753
|
+
self.handle_ohlcv(client, message)
|
623
754
|
method = self.safe_value(methods, channel)
|
624
755
|
if method is not None:
|
625
756
|
method(client, message)
|
ccxt/pro/cryptocom.py
CHANGED
@@ -9,6 +9,7 @@ import hashlib
|
|
9
9
|
from ccxt.base.types import Balances, Int, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Trade
|
10
10
|
from ccxt.async_support.base.ws.client import Client
|
11
11
|
from typing import List
|
12
|
+
from ccxt.base.errors import ExchangeError
|
12
13
|
from ccxt.base.errors import AuthenticationError
|
13
14
|
from ccxt.base.errors import NetworkError
|
14
15
|
from ccxt.base.errors import ChecksumError
|
@@ -827,6 +828,7 @@ class cryptocom(ccxt.async_support.cryptocom):
|
|
827
828
|
# "message": "invalid channel {"channels":["trade.BTCUSD-PERP"]}"
|
828
829
|
# }
|
829
830
|
#
|
831
|
+
id = self.safe_string(message, 'id')
|
830
832
|
errorCode = self.safe_string(message, 'code')
|
831
833
|
try:
|
832
834
|
if errorCode and errorCode != '0':
|
@@ -835,6 +837,7 @@ class cryptocom(ccxt.async_support.cryptocom):
|
|
835
837
|
messageString = self.safe_value(message, 'message')
|
836
838
|
if messageString is not None:
|
837
839
|
self.throw_broadly_matched_exception(self.exceptions['broad'], messageString, feedback)
|
840
|
+
raise ExchangeError(feedback)
|
838
841
|
return False
|
839
842
|
except Exception as e:
|
840
843
|
if isinstance(e, AuthenticationError):
|
@@ -843,7 +846,7 @@ class cryptocom(ccxt.async_support.cryptocom):
|
|
843
846
|
if messageHash in client.subscriptions:
|
844
847
|
del client.subscriptions[messageHash]
|
845
848
|
else:
|
846
|
-
client.reject(e)
|
849
|
+
client.reject(e, id)
|
847
850
|
return True
|
848
851
|
|
849
852
|
def handle_subscribe(self, client: Client, message):
|
ccxt/pro/hitbtc.py
CHANGED
@@ -1137,7 +1137,8 @@ class hitbtc(ccxt.async_support.hitbtc):
|
|
1137
1137
|
return message
|
1138
1138
|
|
1139
1139
|
def handle_message(self, client: Client, message):
|
1140
|
-
self.handle_error(client, message)
|
1140
|
+
if self.handle_error(client, message):
|
1141
|
+
return
|
1141
1142
|
channel = self.safe_string_2(message, 'ch', 'method')
|
1142
1143
|
if channel is not None:
|
1143
1144
|
splitChannel = channel.split('/')
|
@@ -1206,11 +1207,22 @@ class hitbtc(ccxt.async_support.hitbtc):
|
|
1206
1207
|
#
|
1207
1208
|
error = self.safe_value(message, 'error')
|
1208
1209
|
if error is not None:
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1210
|
+
try:
|
1211
|
+
code = self.safe_value(error, 'code')
|
1212
|
+
errorMessage = self.safe_string(error, 'message')
|
1213
|
+
description = self.safe_string(error, 'description')
|
1214
|
+
feedback = self.id + ' ' + description
|
1215
|
+
self.throw_exactly_matched_exception(self.exceptions['exact'], code, feedback)
|
1216
|
+
self.throw_broadly_matched_exception(self.exceptions['broad'], errorMessage, feedback)
|
1217
|
+
raise ExchangeError(feedback) # unknown message
|
1218
|
+
except Exception as e:
|
1219
|
+
if isinstance(e, AuthenticationError):
|
1220
|
+
messageHash = 'authenticated'
|
1221
|
+
client.reject(e, messageHash)
|
1222
|
+
if messageHash in client.subscriptions:
|
1223
|
+
del client.subscriptions[messageHash]
|
1224
|
+
else:
|
1225
|
+
id = self.safe_string(message, 'id')
|
1226
|
+
client.reject(e, id)
|
1227
|
+
return True
|
1216
1228
|
return None
|
ccxt/pro/okx.py
CHANGED
@@ -1764,6 +1764,12 @@ class okx(ccxt.async_support.okx):
|
|
1764
1764
|
self.throw_broadly_matched_exception(self.exceptions['broad'], messageString, feedback)
|
1765
1765
|
raise ExchangeError(feedback)
|
1766
1766
|
except Exception as e:
|
1767
|
+
# if the message contains an id, it means it is a response to a request
|
1768
|
+
# so we only reject that promise, instead of deleting all futures, destroying the authentication future
|
1769
|
+
id = self.safe_string(message, 'id')
|
1770
|
+
if id is not None:
|
1771
|
+
client.reject(e, id)
|
1772
|
+
return False
|
1767
1773
|
client.reject(e)
|
1768
1774
|
return False
|
1769
1775
|
return message
|