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.
Files changed (159) hide show
  1. ccxt/__init__.py +3 -1
  2. ccxt/abstract/coinbaseinternational.py +1 -1
  3. ccxt/abstract/paradex.py +40 -0
  4. ccxt/async_support/__init__.py +3 -1
  5. ccxt/async_support/base/exchange.py +1 -1
  6. ccxt/async_support/blofin.py +63 -6
  7. ccxt/async_support/bybit.py +1 -1
  8. ccxt/async_support/coinbaseinternational.py +155 -2
  9. ccxt/async_support/cryptocom.py +12 -1
  10. ccxt/async_support/paradex.py +1966 -0
  11. ccxt/async_support/poloniex.py +1 -0
  12. ccxt/async_support/woo.py +4 -2
  13. ccxt/base/exchange.py +63 -1
  14. ccxt/blofin.py +63 -6
  15. ccxt/bybit.py +1 -1
  16. ccxt/coinbaseinternational.py +155 -2
  17. ccxt/cryptocom.py +12 -1
  18. ccxt/paradex.py +1966 -0
  19. ccxt/poloniex.py +1 -0
  20. ccxt/pro/__init__.py +5 -1
  21. ccxt/pro/bequant.py +4 -0
  22. ccxt/pro/blofin.py +608 -0
  23. ccxt/pro/coinbaseinternational.py +142 -11
  24. ccxt/pro/cryptocom.py +4 -1
  25. ccxt/pro/hitbtc.py +20 -8
  26. ccxt/pro/okx.py +6 -0
  27. ccxt/pro/paradex.py +340 -0
  28. ccxt/pro/poloniex.py +32 -10
  29. ccxt/pro/woo.py +5 -4
  30. ccxt/static_dependencies/__init__.py +1 -1
  31. ccxt/static_dependencies/lark/__init__.py +38 -0
  32. ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
  33. ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
  34. ccxt/static_dependencies/lark/ast_utils.py +59 -0
  35. ccxt/static_dependencies/lark/common.py +86 -0
  36. ccxt/static_dependencies/lark/exceptions.py +292 -0
  37. ccxt/static_dependencies/lark/grammar.py +130 -0
  38. ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
  39. ccxt/static_dependencies/lark/indenter.py +143 -0
  40. ccxt/static_dependencies/lark/lark.py +658 -0
  41. ccxt/static_dependencies/lark/lexer.py +678 -0
  42. ccxt/static_dependencies/lark/load_grammar.py +1428 -0
  43. ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
  44. ccxt/static_dependencies/lark/parser_frontends.py +257 -0
  45. ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
  46. ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
  47. ccxt/static_dependencies/lark/parsers/earley.py +314 -0
  48. ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
  49. ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
  50. ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
  51. ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
  52. ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
  53. ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
  54. ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
  55. ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
  56. ccxt/static_dependencies/lark/py.typed +0 -0
  57. ccxt/static_dependencies/lark/reconstruct.py +107 -0
  58. ccxt/static_dependencies/lark/tools/__init__.py +70 -0
  59. ccxt/static_dependencies/lark/tools/nearley.py +202 -0
  60. ccxt/static_dependencies/lark/tools/serialize.py +32 -0
  61. ccxt/static_dependencies/lark/tools/standalone.py +196 -0
  62. ccxt/static_dependencies/lark/tree.py +267 -0
  63. ccxt/static_dependencies/lark/tree_matcher.py +186 -0
  64. ccxt/static_dependencies/lark/tree_templates.py +180 -0
  65. ccxt/static_dependencies/lark/utils.py +343 -0
  66. ccxt/static_dependencies/lark/visitors.py +596 -0
  67. ccxt/static_dependencies/marshmallow/__init__.py +81 -0
  68. ccxt/static_dependencies/marshmallow/base.py +65 -0
  69. ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
  70. ccxt/static_dependencies/marshmallow/decorators.py +231 -0
  71. ccxt/static_dependencies/marshmallow/error_store.py +60 -0
  72. ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
  73. ccxt/static_dependencies/marshmallow/fields.py +2114 -0
  74. ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
  75. ccxt/static_dependencies/marshmallow/py.typed +0 -0
  76. ccxt/static_dependencies/marshmallow/schema.py +1228 -0
  77. ccxt/static_dependencies/marshmallow/types.py +12 -0
  78. ccxt/static_dependencies/marshmallow/utils.py +378 -0
  79. ccxt/static_dependencies/marshmallow/validate.py +678 -0
  80. ccxt/static_dependencies/marshmallow/warnings.py +2 -0
  81. ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
  82. ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
  83. ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
  84. ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
  85. ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
  86. ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
  87. ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
  88. ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
  89. ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
  90. ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
  91. ccxt/static_dependencies/starknet/__init__.py +0 -0
  92. ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
  93. ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
  94. ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
  95. ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
  96. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
  97. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
  98. ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
  99. ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
  100. ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
  101. ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
  102. ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
  103. ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
  104. ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
  105. ccxt/static_dependencies/starknet/common.py +15 -0
  106. ccxt/static_dependencies/starknet/constants.py +39 -0
  107. ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
  108. ccxt/static_dependencies/starknet/hash/address.py +79 -0
  109. ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
  110. ccxt/static_dependencies/starknet/hash/selector.py +16 -0
  111. ccxt/static_dependencies/starknet/hash/storage.py +12 -0
  112. ccxt/static_dependencies/starknet/hash/utils.py +78 -0
  113. ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
  114. ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
  115. ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
  116. ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
  117. ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
  118. ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
  119. ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
  120. ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
  121. ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
  122. ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
  123. ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
  124. ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
  125. ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
  126. ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
  127. ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
  128. ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
  129. ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
  130. ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
  131. ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
  132. ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
  133. ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
  134. ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
  135. ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
  136. ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
  137. ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
  138. ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
  139. ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
  140. ccxt/static_dependencies/starknet/utils/schema.py +13 -0
  141. ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
  142. ccxt/static_dependencies/sympy/__init__.py +0 -0
  143. ccxt/static_dependencies/sympy/external/__init__.py +0 -0
  144. ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
  145. ccxt/static_dependencies/sympy/external/importtools.py +187 -0
  146. ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
  147. ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
  148. ccxt/static_dependencies/typing_extensions/__init__.py +0 -0
  149. ccxt/static_dependencies/typing_extensions/typing_extensions.py +3839 -0
  150. ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
  151. ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
  152. ccxt/test/tests_async.py +43 -1
  153. ccxt/test/tests_sync.py +43 -1
  154. ccxt/woo.py +4 -2
  155. {ccxt-4.3.69.dist-info → ccxt-4.3.71.dist-info}/METADATA +8 -7
  156. {ccxt-4.3.69.dist-info → ccxt-4.3.71.dist-info}/RECORD +159 -33
  157. {ccxt-4.3.69.dist-info → ccxt-4.3.71.dist-info}/LICENSE.txt +0 -0
  158. {ccxt-4.3.69.dist-info → ccxt-4.3.71.dist-info}/WHEEL +0 -0
  159. {ccxt-4.3.69.dist-info → ccxt-4.3.71.dist-info}/top_level.txt +0 -0
ccxt/pro/paradex.py ADDED
@@ -0,0 +1,340 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
+ # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
+
6
+ import ccxt.async_support
7
+ from ccxt.async_support.base.ws.cache import ArrayCache
8
+ from ccxt.base.types import Int, OrderBook, Strings, Ticker, Tickers, Trade
9
+ from ccxt.async_support.base.ws.client import Client
10
+ from typing import List
11
+
12
+
13
+ class paradex(ccxt.async_support.paradex):
14
+
15
+ def describe(self):
16
+ return self.deep_extend(super(paradex, self).describe(), {
17
+ 'has': {
18
+ 'ws': True,
19
+ 'watchTicker': True,
20
+ 'watchTickers': True,
21
+ 'watchOrderBook': True,
22
+ 'watchOrders': False,
23
+ 'watchTrades': True,
24
+ 'watchBalance': False,
25
+ 'watchOHLCV': False,
26
+ },
27
+ 'urls': {
28
+ 'logo': 'https://x.com/tradeparadex/photo',
29
+ 'api': {
30
+ 'ws': 'wss://ws.api.prod.paradex.trade/v1',
31
+ },
32
+ 'test': {
33
+ 'ws': 'wss://ws.api.testnet.paradex.trade/v1',
34
+ },
35
+ 'www': 'https://www.paradex.trade/',
36
+ 'doc': 'https://docs.api.testnet.paradex.trade/',
37
+ 'fees': 'https://docs.paradex.trade/getting-started/trading-fees',
38
+ 'referral': '',
39
+ },
40
+ 'options': {},
41
+ 'streaming': {},
42
+ })
43
+
44
+ async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
45
+ """
46
+ get the list of most recent trades for a particular symbol
47
+ :see: https://docs.api.testnet.paradex.trade/#sub-trades-market_symbol-operation
48
+ :param str symbol: unified symbol of the market to fetch trades for
49
+ :param int [since]: timestamp in ms of the earliest trade to fetch
50
+ :param int [limit]: the maximum amount of trades to fetch
51
+ :param dict [params]: extra parameters specific to the exchange API endpoint
52
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
53
+ """
54
+ await self.load_markets()
55
+ messageHash = 'trades.'
56
+ if symbol is not None:
57
+ market = self.market(symbol)
58
+ messageHash += market['id']
59
+ else:
60
+ messageHash += 'ALL'
61
+ url = self.urls['api']['ws']
62
+ request: dict = {
63
+ 'jsonrpc': '2.0',
64
+ 'method': 'subscribe',
65
+ 'params': {
66
+ 'channel': messageHash,
67
+ },
68
+ }
69
+ trades = await self.watch(url, messageHash, self.deep_extend(request, params), messageHash)
70
+ if self.newUpdates:
71
+ limit = trades.getLimit(symbol, limit)
72
+ return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
73
+
74
+ def handle_trade(self, client: Client, message):
75
+ #
76
+ # {
77
+ # "jsonrpc": "2.0",
78
+ # "method": "subscription",
79
+ # "params": {
80
+ # "channel": "trades.ALL",
81
+ # "data": {
82
+ # "id": "1718179273230201709233240002",
83
+ # "market": "kBONK-USD-PERP",
84
+ # "side": "BUY",
85
+ # "size": "34028",
86
+ # "price": "0.028776",
87
+ # "created_at": 1718179273230,
88
+ # "trade_type": "FILL"
89
+ # }
90
+ # }
91
+ # }
92
+ #
93
+ params = self.safe_dict(message, 'params', {})
94
+ data = self.safe_dict(params, 'data', {})
95
+ parsedTrade = self.parse_trade(data)
96
+ symbol = parsedTrade['symbol']
97
+ messageHash = self.safe_string(params, 'channel')
98
+ stored = self.safe_value(self.trades, symbol)
99
+ if stored is None:
100
+ stored = ArrayCache(self.safe_integer(self.options, 'tradesLimit', 1000))
101
+ self.trades[symbol] = stored
102
+ stored.append(parsedTrade)
103
+ client.resolve(stored, messageHash)
104
+ return message
105
+
106
+ async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
107
+ """
108
+ watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
109
+ :see: https://docs.api.testnet.paradex.trade/#sub-order_book-market_symbol-snapshot-15-refresh_rate-operation
110
+ :param str symbol: unified symbol of the market to fetch the order book for
111
+ :param int [limit]: the maximum amount of order book entries to return
112
+ :param dict [params]: extra parameters specific to the exchange API endpoint
113
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
114
+ """
115
+ market = self.market(symbol)
116
+ messageHash = 'order_book.' + market['id'] + '.snapshot@15@100ms'
117
+ url = self.urls['api']['ws']
118
+ request: dict = {
119
+ 'jsonrpc': '2.0',
120
+ 'method': 'subscribe',
121
+ 'params': {
122
+ 'channel': messageHash,
123
+ },
124
+ }
125
+ orderbook = await self.watch(url, messageHash, self.deep_extend(request, params), messageHash)
126
+ return orderbook.limit()
127
+
128
+ def handle_order_book(self, client: Client, message):
129
+ #
130
+ # {
131
+ # "jsonrpc": "2.0",
132
+ # "method": "subscription",
133
+ # "params": {
134
+ # "channel": "order_book.BTC-USD-PERP.snapshot@15@50ms",
135
+ # "data": {
136
+ # "seq_no": 14127815,
137
+ # "market": "BTC-USD-PERP",
138
+ # "last_updated_at": 1718267837265,
139
+ # "update_type": "s",
140
+ # "inserts": [
141
+ # {
142
+ # "side": "BUY",
143
+ # "price": "67629.7",
144
+ # "size": "0.992"
145
+ # },
146
+ # {
147
+ # "side": "SELL",
148
+ # "price": "69378.6",
149
+ # "size": "3.137"
150
+ # }
151
+ # ],
152
+ # "updates": [],
153
+ # "deletes": []
154
+ # }
155
+ # }
156
+ # }
157
+ #
158
+ params = self.safe_dict(message, 'params', {})
159
+ data = self.safe_dict(params, 'data', {})
160
+ marketId = self.safe_string(data, 'market')
161
+ market = self.safe_market(marketId)
162
+ timestamp = self.safe_integer(data, 'last_updated_at')
163
+ symbol = market['symbol']
164
+ if not (symbol in self.orderbooks):
165
+ self.orderbooks[symbol] = self.order_book()
166
+ orderbookData = {
167
+ 'bids': [],
168
+ 'asks': [],
169
+ }
170
+ inserts = self.safe_list(data, 'inserts')
171
+ for i in range(0, len(inserts)):
172
+ insert = self.safe_dict(inserts, i)
173
+ side = self.safe_string(insert, 'side')
174
+ price = self.safe_string(insert, 'price')
175
+ size = self.safe_string(insert, 'size')
176
+ if side == 'BUY':
177
+ orderbookData['bids'].append([price, size])
178
+ else:
179
+ orderbookData['asks'].append([price, size])
180
+ orderbook = self.orderbooks[symbol]
181
+ snapshot = self.parse_order_book(orderbookData, symbol, timestamp, 'bids', 'asks')
182
+ snapshot['nonce'] = self.safe_number(data, 'seq_no')
183
+ orderbook.reset(snapshot)
184
+ messageHash = self.safe_string(params, 'channel')
185
+ client.resolve(orderbook, messageHash)
186
+
187
+ async def watch_ticker(self, symbol: str, params={}) -> Ticker:
188
+ """
189
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
190
+ :see: https://docs.api.testnet.paradex.trade/#sub-markets_summary-operation
191
+ :param str symbol: unified symbol of the market to fetch the ticker for
192
+ :param dict [params]: extra parameters specific to the exchange API endpoint
193
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
194
+ """
195
+ await self.load_markets()
196
+ symbol = self.symbol(symbol)
197
+ channel = 'markets_summary'
198
+ url = self.urls['api']['ws']
199
+ request: dict = {
200
+ 'jsonrpc': '2.0',
201
+ 'method': 'subscribe',
202
+ 'params': {
203
+ 'channel': channel,
204
+ },
205
+ }
206
+ messageHash = channel + '.' + symbol
207
+ return await self.watch(url, messageHash, self.deep_extend(request, params), messageHash)
208
+
209
+ async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
210
+ """
211
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
212
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
213
+ :param dict [params]: extra parameters specific to the exchange API endpoint
214
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
215
+ """
216
+ symbols = self.market_symbols(symbols)
217
+ channel = 'markets_summary'
218
+ url = self.urls['api']['ws']
219
+ request: dict = {
220
+ 'jsonrpc': '2.0',
221
+ 'method': 'subscribe',
222
+ 'params': {
223
+ 'channel': channel,
224
+ },
225
+ }
226
+ messageHashes = []
227
+ if isinstance(symbols, list):
228
+ for i in range(0, len(symbols)):
229
+ messageHash = channel + '.' + symbols[i]
230
+ messageHashes.append(messageHash)
231
+ else:
232
+ messageHashes.append(channel)
233
+ newTickers = await self.watch_multiple(url, messageHashes, self.deep_extend(request, params), messageHashes)
234
+ if self.newUpdates:
235
+ result: dict = {}
236
+ result[newTickers['symbol']] = newTickers
237
+ return result
238
+ return self.filter_by_array(self.tickers, 'symbol', symbols)
239
+
240
+ def handle_ticker(self, client: Client, message):
241
+ #
242
+ # {
243
+ # "jsonrpc": "2.0",
244
+ # "method": "subscription",
245
+ # "params": {
246
+ # "channel": "markets_summary",
247
+ # "data": {
248
+ # "symbol": "ORDI-USD-PERP",
249
+ # "oracle_price": "49.80885481",
250
+ # "mark_price": "49.80885481",
251
+ # "last_traded_price": "62.038",
252
+ # "bid": "49.822",
253
+ # "ask": "58.167",
254
+ # "volume_24h": "0",
255
+ # "total_volume": "54542628.66054200416",
256
+ # "created_at": 1718334307698,
257
+ # "underlying_price": "47.93",
258
+ # "open_interest": "6999.5",
259
+ # "funding_rate": "0.03919997509811",
260
+ # "price_change_rate_24h": ""
261
+ # }
262
+ # }
263
+ # }
264
+ #
265
+ params = self.safe_dict(message, 'params', {})
266
+ data = self.safe_dict(params, 'data', {})
267
+ marketId = self.safe_string(data, 'symbol')
268
+ market = self.safe_market(marketId)
269
+ symbol = market['symbol']
270
+ channel = self.safe_string(params, 'channel')
271
+ messageHash = channel + '.' + symbol
272
+ ticker = self.parse_ticker(data, market)
273
+ self.tickers[symbol] = ticker
274
+ client.resolve(ticker, channel)
275
+ client.resolve(ticker, messageHash)
276
+ return message
277
+
278
+ def handle_error_message(self, client: Client, message):
279
+ #
280
+ # {
281
+ # "jsonrpc": "2.0",
282
+ # "id": 0,
283
+ # "error": {
284
+ # "code": -32600,
285
+ # "message": "invalid subscribe request",
286
+ # "data": "invalid channel"
287
+ # },
288
+ # "usIn": 1718179125962419,
289
+ # "usDiff": 76,
290
+ # "usOut": 1718179125962495
291
+ # }
292
+ #
293
+ error = self.safe_dict(message, 'error')
294
+ if error is None:
295
+ return True
296
+ else:
297
+ errorCode = self.safe_string(error, 'code')
298
+ if errorCode is not None:
299
+ feedback = self.id + ' ' + self.json(error)
300
+ self.throw_exactly_matched_exception(self.exceptions['exact'], '-32600', feedback)
301
+ messageString = self.safe_value(error, 'message')
302
+ if messageString is not None:
303
+ self.throw_broadly_matched_exception(self.exceptions['broad'], messageString, feedback)
304
+ return False
305
+
306
+ def handle_message(self, client: Client, message):
307
+ if not self.handle_error_message(client, message):
308
+ return
309
+ #
310
+ # {
311
+ # "jsonrpc": "2.0",
312
+ # "method": "subscription",
313
+ # "params": {
314
+ # "channel": "trades.ALL",
315
+ # "data": {
316
+ # "id": "1718179273230201709233240002",
317
+ # "market": "kBONK-USD-PERP",
318
+ # "side": "BUY",
319
+ # "size": "34028",
320
+ # "price": "0.028776",
321
+ # "created_at": 1718179273230,
322
+ # "trade_type": "FILL"
323
+ # }
324
+ # }
325
+ # }
326
+ #
327
+ data = self.safe_dict(message, 'params')
328
+ if data is not None:
329
+ channel = self.safe_string(data, 'channel')
330
+ parts = channel.split('.')
331
+ name = self.safe_string(parts, 0)
332
+ methods: dict = {
333
+ 'trades': self.handle_trade,
334
+ 'order_book': self.handle_order_book,
335
+ 'markets_summary': self.handle_ticker,
336
+ # ...
337
+ }
338
+ method = self.safe_value(methods, name)
339
+ if method is not None:
340
+ method(client, message)
ccxt/pro/poloniex.py CHANGED
@@ -1100,13 +1100,7 @@ class poloniex(ccxt.async_support.poloniex):
1100
1100
  if type == 'auth':
1101
1101
  self.handle_authenticate(client, message)
1102
1102
  elif type is None:
1103
- data = self.safe_value(message, 'data')
1104
- item = self.safe_value(data, 0)
1105
- orderId = self.safe_string(item, 'orderId')
1106
- if orderId == '0':
1107
- self.handle_error_message(client, item)
1108
- else:
1109
- self.handle_order_request(client, message)
1103
+ self.handle_order_request(client, message)
1110
1104
  else:
1111
1105
  data = self.safe_value(message, 'data', [])
1112
1106
  dataLength = len(data)
@@ -1131,12 +1125,40 @@ class poloniex(ccxt.async_support.poloniex):
1131
1125
  # "event": "error",
1132
1126
  # "message": "Platform in maintenance mode"
1133
1127
  # }
1128
+ # {
1129
+ # "id":"1722386782048",
1130
+ # "data":[
1131
+ # {
1132
+ # "orderId":0,
1133
+ # "clientOrderId":null,
1134
+ # "message":"available insufficient",
1135
+ # "code":21721
1136
+ # }
1137
+ # ]
1138
+ # }
1134
1139
  #
1140
+ id = self.safe_string(message, 'id')
1135
1141
  event = self.safe_string(message, 'event')
1136
- orderId = self.safe_string(message, 'orderId')
1142
+ data = self.safe_list(message, 'data')
1143
+ first = self.safe_dict(data, 0)
1144
+ orderId = self.safe_string(first, 'orderId')
1137
1145
  if (event == 'error') or (orderId == '0'):
1138
- error = self.safe_string(message, 'message')
1139
- raise ExchangeError(self.id + ' error: ' + self.json(error))
1146
+ try:
1147
+ error = self.safe_string(first, 'message')
1148
+ code = self.safe_string(first, 'code')
1149
+ feedback = self.id + ' ' + self.json(message)
1150
+ self.throw_exactly_matched_exception(self.exceptions['exact'], code, feedback)
1151
+ self.throw_broadly_matched_exception(self.exceptions['broad'], error, feedback)
1152
+ raise ExchangeError(feedback)
1153
+ except Exception as e:
1154
+ if isinstance(e, AuthenticationError):
1155
+ messageHash = 'authenticated'
1156
+ client.reject(e, messageHash)
1157
+ if messageHash in client.subscriptions:
1158
+ del client.subscriptions[messageHash]
1159
+ else:
1160
+ client.reject(e, id)
1161
+ return True
1140
1162
  return False
1141
1163
 
1142
1164
  def handle_authenticate(self, client: Client, message):
ccxt/pro/woo.py CHANGED
@@ -34,7 +34,7 @@ class woo(ccxt.async_support.woo):
34
34
  'api': {
35
35
  'ws': {
36
36
  'public': 'wss://wss.woo.org/ws/stream',
37
- 'private': 'wss://wss.woo.network/v2/ws/private/stream',
37
+ 'private': 'wss://wss.woo.org/v2/ws/private/stream',
38
38
  },
39
39
  },
40
40
  'test': {
@@ -79,7 +79,8 @@ class woo(ccxt.async_support.woo):
79
79
  return newValue
80
80
 
81
81
  async def watch_public(self, messageHash, message):
82
- url = self.urls['api']['ws']['public'] + '/' + self.uid
82
+ urlUid = '/' + self.uid if (self.uid) else ''
83
+ url = self.urls['api']['ws']['public'] + urlUid
83
84
  requestId = self.request_id(url)
84
85
  subscribe: dict = {
85
86
  'id': requestId,
@@ -456,7 +457,7 @@ class woo(ccxt.async_support.woo):
456
457
  marketId = self.safe_string(trade, 'symbol')
457
458
  market = self.safe_market(marketId, market)
458
459
  symbol = market['symbol']
459
- price = self.safe_string(trade, 'executedPrice', 'price')
460
+ price = self.safe_string_2(trade, 'executedPrice', 'price')
460
461
  amount = self.safe_string_2(trade, 'executedQuantity', 'size')
461
462
  cost = Precise.string_mul(price, amount)
462
463
  side = self.safe_string_lower(trade, 'side')
@@ -492,7 +493,7 @@ class woo(ccxt.async_support.woo):
492
493
  def check_required_uid(self, error=True):
493
494
  if not self.uid:
494
495
  if error:
495
- raise AuthenticationError(self.id + ' requires `uid` credential')
496
+ raise AuthenticationError(self.id + ' requires `uid` credential(woox calls it `application_id`)')
496
497
  else:
497
498
  return False
498
499
  return True
@@ -1 +1 @@
1
- __all__ = ['ecdsa', 'keccak', 'aiohttp_socks', 'ethereum', 'parsimonious', 'toolz']
1
+ __all__ = ['ecdsa', 'keccak', 'aiohttp_socks', 'ethereum', 'parsimonious', 'toolz', 'starknet', 'marshmallow', 'marshmallow_oneofschema', 'lark', 'starkware', 'sympy']
@@ -0,0 +1,38 @@
1
+ from .exceptions import (
2
+ GrammarError,
3
+ LarkError,
4
+ LexError,
5
+ ParseError,
6
+ UnexpectedCharacters,
7
+ UnexpectedEOF,
8
+ UnexpectedInput,
9
+ UnexpectedToken,
10
+ )
11
+ from .lark import Lark
12
+ from .lexer import Token
13
+ from .tree import ParseTree, Tree
14
+ from .utils import logger
15
+ from .visitors import Discard, Transformer, Transformer_NonRecursive, Visitor, v_args
16
+
17
+ __version__: str = "1.2.0"
18
+
19
+ __all__ = (
20
+ "GrammarError",
21
+ "LarkError",
22
+ "LexError",
23
+ "ParseError",
24
+ "UnexpectedCharacters",
25
+ "UnexpectedEOF",
26
+ "UnexpectedInput",
27
+ "UnexpectedToken",
28
+ "Lark",
29
+ "Token",
30
+ "ParseTree",
31
+ "Tree",
32
+ "logger",
33
+ "Discard",
34
+ "Transformer",
35
+ "Transformer_NonRecursive",
36
+ "Visitor",
37
+ "v_args",
38
+ )
@@ -0,0 +1,6 @@
1
+ # For usage of lark with PyInstaller. See https://pyinstaller-sample-hook.readthedocs.io/en/latest/index.html
2
+
3
+ import os
4
+
5
+ def get_hook_dirs():
6
+ return [os.path.dirname(__file__)]
@@ -0,0 +1,14 @@
1
+ #-----------------------------------------------------------------------------
2
+ # Copyright (c) 2017-2020, PyInstaller Development Team.
3
+ #
4
+ # Distributed under the terms of the GNU General Public License (version 2
5
+ # or later) with exception for distributing the bootloader.
6
+ #
7
+ # The full license is in the file COPYING.txt, distributed with this software.
8
+ #
9
+ # SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
10
+ #-----------------------------------------------------------------------------
11
+
12
+ from PyInstaller.utils.hooks import collect_data_files
13
+
14
+ datas = collect_data_files('lark')
@@ -0,0 +1,59 @@
1
+ """
2
+ Module of utilities for transforming a lark.Tree into a custom Abstract Syntax Tree (AST defined in classes)
3
+ """
4
+
5
+ import inspect, re
6
+ import types
7
+ from typing import Optional, Callable
8
+
9
+ from lark import Transformer, v_args
10
+
11
+ class Ast:
12
+ """Abstract class
13
+
14
+ Subclasses will be collected by `create_transformer()`
15
+ """
16
+ pass
17
+
18
+ class AsList:
19
+ """Abstract class
20
+
21
+ Subclasses will be instantiated with the parse results as a single list, instead of as arguments.
22
+ """
23
+
24
+ class WithMeta:
25
+ """Abstract class
26
+
27
+ Subclasses will be instantiated with the Meta instance of the tree. (see ``v_args`` for more detail)
28
+ """
29
+ pass
30
+
31
+ def camel_to_snake(name):
32
+ return re.sub(r'(?<!^)(?=[A-Z])', '_', name).lower()
33
+
34
+ def create_transformer(ast_module: types.ModuleType,
35
+ transformer: Optional[Transformer]=None,
36
+ decorator_factory: Callable=v_args) -> Transformer:
37
+ """Collects `Ast` subclasses from the given module, and creates a Lark transformer that builds the AST.
38
+
39
+ For each class, we create a corresponding rule in the transformer, with a matching name.
40
+ CamelCase names will be converted into snake_case. Example: "CodeBlock" -> "code_block".
41
+
42
+ Classes starting with an underscore (`_`) will be skipped.
43
+
44
+ Parameters:
45
+ ast_module: A Python module containing all the subclasses of ``ast_utils.Ast``
46
+ transformer (Optional[Transformer]): An initial transformer. Its attributes may be overwritten.
47
+ decorator_factory (Callable): An optional callable accepting two booleans, inline, and meta,
48
+ and returning a decorator for the methods of ``transformer``. (default: ``v_args``).
49
+ """
50
+ t = transformer or Transformer()
51
+
52
+ for name, obj in inspect.getmembers(ast_module):
53
+ if not name.startswith('_') and inspect.isclass(obj):
54
+ if issubclass(obj, Ast):
55
+ wrapper = decorator_factory(inline=not issubclass(obj, AsList), meta=issubclass(obj, WithMeta))
56
+ obj = wrapper(obj).__get__(t)
57
+ setattr(t, camel_to_snake(name), obj)
58
+
59
+ return t
@@ -0,0 +1,86 @@
1
+ from copy import deepcopy
2
+ import sys
3
+ from types import ModuleType
4
+ from typing import Callable, Collection, Dict, Optional, TYPE_CHECKING, List
5
+
6
+ if TYPE_CHECKING:
7
+ from .lark import PostLex
8
+ from .lexer import Lexer
9
+ from .grammar import Rule
10
+ from typing import Union, Type
11
+ from typing import Literal
12
+ if sys.version_info >= (3, 10):
13
+ from typing import TypeAlias
14
+ else:
15
+ from typing_extensions import TypeAlias
16
+
17
+ from .utils import Serialize
18
+ from .lexer import TerminalDef, Token
19
+
20
+ ###{standalone
21
+
22
+ _ParserArgType: 'TypeAlias' = 'Literal["earley", "lalr", "cyk", "auto"]'
23
+ _LexerArgType: 'TypeAlias' = 'Union[Literal["auto", "basic", "contextual", "dynamic", "dynamic_complete"], Type[Lexer]]'
24
+ _LexerCallback = Callable[[Token], Token]
25
+ ParserCallbacks = Dict[str, Callable]
26
+
27
+ class LexerConf(Serialize):
28
+ __serialize_fields__ = 'terminals', 'ignore', 'g_regex_flags', 'use_bytes', 'lexer_type'
29
+ __serialize_namespace__ = TerminalDef,
30
+
31
+ terminals: Collection[TerminalDef]
32
+ re_module: ModuleType
33
+ ignore: Collection[str]
34
+ postlex: 'Optional[PostLex]'
35
+ callbacks: Dict[str, _LexerCallback]
36
+ g_regex_flags: int
37
+ skip_validation: bool
38
+ use_bytes: bool
39
+ lexer_type: Optional[_LexerArgType]
40
+ strict: bool
41
+
42
+ def __init__(self, terminals: Collection[TerminalDef], re_module: ModuleType, ignore: Collection[str]=(), postlex: 'Optional[PostLex]'=None,
43
+ callbacks: Optional[Dict[str, _LexerCallback]]=None, g_regex_flags: int=0, skip_validation: bool=False, use_bytes: bool=False, strict: bool=False):
44
+ self.terminals = terminals
45
+ self.terminals_by_name = {t.name: t for t in self.terminals}
46
+ assert len(self.terminals) == len(self.terminals_by_name)
47
+ self.ignore = ignore
48
+ self.postlex = postlex
49
+ self.callbacks = callbacks or {}
50
+ self.g_regex_flags = g_regex_flags
51
+ self.re_module = re_module
52
+ self.skip_validation = skip_validation
53
+ self.use_bytes = use_bytes
54
+ self.strict = strict
55
+ self.lexer_type = None
56
+
57
+ def _deserialize(self):
58
+ self.terminals_by_name = {t.name: t for t in self.terminals}
59
+
60
+ def __deepcopy__(self, memo=None):
61
+ return type(self)(
62
+ deepcopy(self.terminals, memo),
63
+ self.re_module,
64
+ deepcopy(self.ignore, memo),
65
+ deepcopy(self.postlex, memo),
66
+ deepcopy(self.callbacks, memo),
67
+ deepcopy(self.g_regex_flags, memo),
68
+ deepcopy(self.skip_validation, memo),
69
+ deepcopy(self.use_bytes, memo),
70
+ )
71
+
72
+ class ParserConf(Serialize):
73
+ __serialize_fields__ = 'rules', 'start', 'parser_type'
74
+
75
+ rules: List['Rule']
76
+ callbacks: ParserCallbacks
77
+ start: List[str]
78
+ parser_type: _ParserArgType
79
+
80
+ def __init__(self, rules: List['Rule'], callbacks: ParserCallbacks, start: List[str]):
81
+ assert isinstance(start, list)
82
+ self.rules = rules
83
+ self.callbacks = callbacks
84
+ self.start = start
85
+
86
+ ###}