ccxt 4.3.70__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/paradex.py +40 -0
- ccxt/async_support/__init__.py +3 -1
- ccxt/async_support/base/exchange.py +1 -1
- ccxt/async_support/paradex.py +1966 -0
- ccxt/async_support/woo.py +4 -2
- ccxt/base/exchange.py +58 -1
- ccxt/paradex.py +1966 -0
- ccxt/pro/__init__.py +3 -1
- ccxt/pro/bequant.py +4 -0
- ccxt/pro/paradex.py +340 -0
- 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.70.dist-info → ccxt-4.3.71.dist-info}/METADATA +7 -6
- {ccxt-4.3.70.dist-info → ccxt-4.3.71.dist-info}/RECORD +141 -16
- {ccxt-4.3.70.dist-info → ccxt-4.3.71.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.3.70.dist-info → ccxt-4.3.71.dist-info}/WHEEL +0 -0
- {ccxt-4.3.70.dist-info → ccxt-4.3.71.dist-info}/top_level.txt +0 -0
ccxt/pro/__init__.py
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
# ----------------------------------------------------------------------------
|
6
6
|
|
7
|
-
__version__ = '4.3.
|
7
|
+
__version__ = '4.3.71'
|
8
8
|
|
9
9
|
# ----------------------------------------------------------------------------
|
10
10
|
|
@@ -70,6 +70,7 @@ from ccxt.pro.okx import okx # noqa
|
|
70
70
|
from ccxt.pro.onetrading import onetrading # noqa: F401
|
71
71
|
from ccxt.pro.oxfun import oxfun # noqa: F401
|
72
72
|
from ccxt.pro.p2b import p2b # noqa: F401
|
73
|
+
from ccxt.pro.paradex import paradex # noqa: F401
|
73
74
|
from ccxt.pro.phemex import phemex # noqa: F401
|
74
75
|
from ccxt.pro.poloniex import poloniex # noqa: F401
|
75
76
|
from ccxt.pro.poloniexfutures import poloniexfutures # noqa: F401
|
@@ -141,6 +142,7 @@ exchanges = [
|
|
141
142
|
'onetrading',
|
142
143
|
'oxfun',
|
143
144
|
'p2b',
|
145
|
+
'paradex',
|
144
146
|
'phemex',
|
145
147
|
'poloniex',
|
146
148
|
'poloniexfutures',
|
ccxt/pro/bequant.py
CHANGED
@@ -25,6 +25,10 @@ class bequant(hitbtc):
|
|
25
25
|
'api': {
|
26
26
|
'public': 'https://api.bequant.io/api/3',
|
27
27
|
'private': 'https://api.bequant.io/api/3',
|
28
|
+
'ws': {
|
29
|
+
'public': 'wss://api.bequant.io/api/3/ws/public',
|
30
|
+
'private': 'wss://api.bequant.io/api/3/ws/trading',
|
31
|
+
},
|
28
32
|
},
|
29
33
|
'www': 'https://bequant.io',
|
30
34
|
'doc': [
|
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)
|
@@ -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,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
|
+
###}
|