ccxt 4.4.90__py2.py3-none-any.whl → 4.4.91__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 +1 -3
- ccxt/async_support/__init__.py +1 -3
- ccxt/async_support/base/exchange.py +6 -3
- ccxt/async_support/base/ws/client.py +173 -64
- ccxt/async_support/base/ws/future.py +23 -50
- ccxt/async_support/binance.py +1 -1
- ccxt/async_support/bitmex.py +2 -1
- ccxt/async_support/cex.py +61 -0
- ccxt/async_support/cryptocom.py +17 -2
- ccxt/async_support/cryptomus.py +1 -1
- ccxt/async_support/exmo.py +14 -7
- ccxt/async_support/gate.py +2 -2
- ccxt/async_support/hyperliquid.py +104 -53
- ccxt/async_support/kraken.py +26 -1
- ccxt/async_support/mexc.py +1 -0
- ccxt/async_support/modetrade.py +2 -2
- ccxt/async_support/paradex.py +1 -1
- ccxt/base/exchange.py +8 -5
- ccxt/binance.py +1 -1
- ccxt/bitmex.py +2 -1
- ccxt/cex.py +61 -0
- ccxt/cryptocom.py +17 -2
- ccxt/cryptomus.py +1 -1
- ccxt/exmo.py +13 -7
- ccxt/gate.py +2 -2
- ccxt/hyperliquid.py +104 -53
- ccxt/kraken.py +26 -1
- ccxt/mexc.py +1 -0
- ccxt/modetrade.py +2 -2
- ccxt/paradex.py +1 -1
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/bitstamp.py +1 -1
- ccxt/pro/bybit.py +6 -136
- ccxt/pro/kraken.py +246 -258
- ccxt/pro/mexc.py +0 -1
- {ccxt-4.4.90.dist-info → ccxt-4.4.91.dist-info}/METADATA +6 -7
- {ccxt-4.4.90.dist-info → ccxt-4.4.91.dist-info}/RECORD +40 -57
- ccxt/abstract/coinlist.py +0 -57
- ccxt/async_support/base/ws/aiohttp_client.py +0 -147
- ccxt/async_support/bitcoincom.py +0 -18
- ccxt/async_support/bitfinex1.py +0 -1711
- ccxt/async_support/bitpanda.py +0 -17
- ccxt/async_support/coinlist.py +0 -2542
- ccxt/async_support/poloniexfutures.py +0 -1875
- ccxt/bitcoincom.py +0 -18
- ccxt/bitfinex1.py +0 -1710
- ccxt/bitpanda.py +0 -17
- ccxt/coinlist.py +0 -2542
- ccxt/poloniexfutures.py +0 -1875
- ccxt/pro/bitcoincom.py +0 -35
- ccxt/pro/bitfinex1.py +0 -635
- ccxt/pro/bitpanda.py +0 -16
- ccxt/pro/poloniexfutures.py +0 -1004
- ccxt/pro/wazirx.py +0 -766
- {ccxt-4.4.90.dist-info → ccxt-4.4.91.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.90.dist-info → ccxt-4.4.91.dist-info}/WHEEL +0 -0
- {ccxt-4.4.90.dist-info → ccxt-4.4.91.dist-info}/top_level.txt +0 -0
ccxt/pro/wazirx.py
DELETED
@@ -1,766 +0,0 @@
|
|
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, ArrayCacheBySymbolById, ArrayCacheByTimestamp
|
8
|
-
from ccxt.base.types import Any, Balances, Int, Order, OrderBook, Str, Strings, Ticker, Tickers, Trade
|
9
|
-
from ccxt.async_support.base.ws.client import Client
|
10
|
-
from typing import List
|
11
|
-
from ccxt.base.errors import ExchangeError
|
12
|
-
from ccxt.base.errors import NotSupported
|
13
|
-
|
14
|
-
|
15
|
-
class wazirx(ccxt.async_support.wazirx):
|
16
|
-
|
17
|
-
def describe(self) -> Any:
|
18
|
-
return self.deep_extend(super(wazirx, self).describe(), {
|
19
|
-
'has': {
|
20
|
-
'ws': True,
|
21
|
-
'watchBalance': True,
|
22
|
-
'watchTicker': True,
|
23
|
-
'watchTickers': True,
|
24
|
-
'watchTrades': True,
|
25
|
-
'watchTradesForSymbols': False,
|
26
|
-
'watchMyTrades': True,
|
27
|
-
'watchOrders': True,
|
28
|
-
'watchOrderBook': True,
|
29
|
-
'watchOHLCV': True,
|
30
|
-
},
|
31
|
-
'urls': {
|
32
|
-
'api': {
|
33
|
-
'ws': 'wss://stream.wazirx.com/stream',
|
34
|
-
},
|
35
|
-
},
|
36
|
-
'options': {
|
37
|
-
},
|
38
|
-
'streaming': {
|
39
|
-
},
|
40
|
-
'exceptions': {
|
41
|
-
},
|
42
|
-
'api': {
|
43
|
-
'private': {
|
44
|
-
'post': {
|
45
|
-
'create_auth_token': 1,
|
46
|
-
},
|
47
|
-
},
|
48
|
-
},
|
49
|
-
})
|
50
|
-
|
51
|
-
async def watch_balance(self, params={}) -> Balances:
|
52
|
-
"""
|
53
|
-
watch balance and get the amount of funds available for trading or funds locked in orders
|
54
|
-
|
55
|
-
https://docs.wazirx.com/#account-update
|
56
|
-
|
57
|
-
:param dict [params]: extra parameters specific to the exchange API endpoint
|
58
|
-
:returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
|
59
|
-
"""
|
60
|
-
await self.load_markets()
|
61
|
-
token = await self.authenticate(params)
|
62
|
-
messageHash = 'balance'
|
63
|
-
url = self.urls['api']['ws']
|
64
|
-
subscribe: dict = {
|
65
|
-
'event': 'subscribe',
|
66
|
-
'streams': ['outboundAccountPosition'],
|
67
|
-
'auth_key': token,
|
68
|
-
}
|
69
|
-
request = self.deep_extend(subscribe, params)
|
70
|
-
return await self.watch(url, messageHash, request, messageHash)
|
71
|
-
|
72
|
-
def handle_balance(self, client: Client, message):
|
73
|
-
#
|
74
|
-
# {
|
75
|
-
# "data":
|
76
|
-
# {
|
77
|
-
# "B": [
|
78
|
-
# {
|
79
|
-
# "a":"wrx",
|
80
|
-
# "b":"2043856.426455209",
|
81
|
-
# "l":"3001318.98"
|
82
|
-
# }
|
83
|
-
# ],
|
84
|
-
# "E":1631683058909
|
85
|
-
# },
|
86
|
-
# "stream":"outboundAccountPosition"
|
87
|
-
# }
|
88
|
-
#
|
89
|
-
data = self.safe_value(message, 'data', {})
|
90
|
-
balances = self.safe_value(data, 'B', [])
|
91
|
-
timestamp = self.safe_integer(data, 'E')
|
92
|
-
self.balance['info'] = balances
|
93
|
-
self.balance['timestamp'] = timestamp
|
94
|
-
self.balance['datetime'] = self.iso8601(timestamp)
|
95
|
-
for i in range(0, len(balances)):
|
96
|
-
balance = balances[i]
|
97
|
-
currencyId = self.safe_string(balance, 'a')
|
98
|
-
code = self.safe_currency_code(currencyId)
|
99
|
-
available = self.safe_string(balance, 'b')
|
100
|
-
locked = self.safe_string(balance, 'l')
|
101
|
-
account = self.account()
|
102
|
-
account['free'] = available
|
103
|
-
account['used'] = locked
|
104
|
-
self.balance[code] = account
|
105
|
-
self.balance = self.safe_balance(self.balance)
|
106
|
-
messageHash = 'balance'
|
107
|
-
client.resolve(self.balance, messageHash)
|
108
|
-
|
109
|
-
def parse_ws_trade(self, trade, market=None):
|
110
|
-
#
|
111
|
-
# trade
|
112
|
-
# {
|
113
|
-
# "E": 1631681323000, Event time
|
114
|
-
# "S": "buy", Side
|
115
|
-
# "a": 26946138, Buyer order ID
|
116
|
-
# "b": 26946169, Seller order ID
|
117
|
-
# "m": True, Is buyer maker?
|
118
|
-
# "p": "7.0", Price
|
119
|
-
# "q": "15.0", Quantity
|
120
|
-
# "s": "btcinr", Symbol
|
121
|
-
# "t": 17376030 Trade ID
|
122
|
-
# }
|
123
|
-
# ownTrade
|
124
|
-
# {
|
125
|
-
# "E": 1631683058000,
|
126
|
-
# "S": "ask",
|
127
|
-
# "U": "inr",
|
128
|
-
# "a": 114144050,
|
129
|
-
# "b": 114144121,
|
130
|
-
# "f": "0.2",
|
131
|
-
# "m": True,
|
132
|
-
# "o": 26946170,
|
133
|
-
# "p": "5.0",
|
134
|
-
# "q": "20.0",
|
135
|
-
# "s": "btcinr",
|
136
|
-
# "t": 17376032,
|
137
|
-
# "w": "100.0"
|
138
|
-
# }
|
139
|
-
#
|
140
|
-
timestamp = self.safe_integer(trade, 'E')
|
141
|
-
marketId = self.safe_string(trade, 's')
|
142
|
-
market = self.safe_market(marketId, market)
|
143
|
-
feeCost = self.safe_string(trade, 'f')
|
144
|
-
feeCurrencyId = self.safe_string(trade, 'U')
|
145
|
-
isMaker = self.safe_value(trade, 'm') is True
|
146
|
-
fee = None
|
147
|
-
if feeCost is not None:
|
148
|
-
fee = {
|
149
|
-
'cost': feeCost,
|
150
|
-
'currency': self.safe_currency_code(feeCurrencyId),
|
151
|
-
'rate': None,
|
152
|
-
}
|
153
|
-
return self.safe_trade({
|
154
|
-
'id': self.safe_string(trade, 't'),
|
155
|
-
'info': trade,
|
156
|
-
'timestamp': timestamp,
|
157
|
-
'datetime': self.iso8601(timestamp),
|
158
|
-
'symbol': market['symbol'],
|
159
|
-
'order': self.safe_string_n(trade, ['o']),
|
160
|
-
'type': None,
|
161
|
-
'side': self.safe_string(trade, 'S'),
|
162
|
-
'takerOrMaker': 'maker' if isMaker else 'taker',
|
163
|
-
'price': self.safe_string(trade, 'p'),
|
164
|
-
'amount': self.safe_string(trade, 'q'),
|
165
|
-
'cost': None,
|
166
|
-
'fee': fee,
|
167
|
-
}, market)
|
168
|
-
|
169
|
-
async def watch_ticker(self, symbol: str, params={}) -> Ticker:
|
170
|
-
"""
|
171
|
-
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
172
|
-
|
173
|
-
https://docs.wazirx.com/#all-market-tickers-stream
|
174
|
-
|
175
|
-
:param str symbol: unified symbol of the market to fetch the ticker for
|
176
|
-
:param dict [params]: extra parameters specific to the exchange API endpoint
|
177
|
-
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
178
|
-
"""
|
179
|
-
await self.load_markets()
|
180
|
-
market = self.market(symbol)
|
181
|
-
url = self.urls['api']['ws']
|
182
|
-
messageHash = 'ticker:' + market['symbol']
|
183
|
-
subscribeHash = 'tickers'
|
184
|
-
stream = '!' + 'ticker@arr'
|
185
|
-
subscribe: dict = {
|
186
|
-
'event': 'subscribe',
|
187
|
-
'streams': [stream],
|
188
|
-
}
|
189
|
-
request = self.deep_extend(subscribe, params)
|
190
|
-
return await self.watch(url, messageHash, request, subscribeHash)
|
191
|
-
|
192
|
-
async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
193
|
-
"""
|
194
|
-
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
|
195
|
-
|
196
|
-
https://docs.wazirx.com/#all-market-tickers-stream
|
197
|
-
|
198
|
-
:param str[] symbols: unified symbol of the market to fetch the ticker for
|
199
|
-
:param dict [params]: extra parameters specific to the exchange API endpoint
|
200
|
-
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
201
|
-
"""
|
202
|
-
await self.load_markets()
|
203
|
-
symbols = self.market_symbols(symbols)
|
204
|
-
url = self.urls['api']['ws']
|
205
|
-
messageHash = 'tickers'
|
206
|
-
stream = '!' + 'ticker@arr'
|
207
|
-
subscribe: dict = {
|
208
|
-
'event': 'subscribe',
|
209
|
-
'streams': [stream],
|
210
|
-
}
|
211
|
-
request = self.deep_extend(subscribe, params)
|
212
|
-
tickers = await self.watch(url, messageHash, request, messageHash)
|
213
|
-
return self.filter_by_array(tickers, 'symbol', symbols, False)
|
214
|
-
|
215
|
-
def handle_ticker(self, client: Client, message):
|
216
|
-
#
|
217
|
-
# {
|
218
|
-
# "data":
|
219
|
-
# [
|
220
|
-
# {
|
221
|
-
# "E":1631625534000, # Event time
|
222
|
-
# "T":"SPOT", # Type
|
223
|
-
# "U":"wrx", # Quote unit
|
224
|
-
# "a":"0.0", # Best sell price
|
225
|
-
# "b":"0.0", # Best buy price
|
226
|
-
# "c":"5.0", # Last price
|
227
|
-
# "h":"5.0", # High price
|
228
|
-
# "l":"5.0", # Low price
|
229
|
-
# "o":"5.0", # Open price
|
230
|
-
# "q":"0.0", # Quantity
|
231
|
-
# "s":"btcwrx", # Symbol
|
232
|
-
# "u":"btc" # Base unit
|
233
|
-
# }
|
234
|
-
# ],
|
235
|
-
# "stream":"not ticker@arr"
|
236
|
-
# }
|
237
|
-
#
|
238
|
-
data = self.safe_value(message, 'data', [])
|
239
|
-
for i in range(0, len(data)):
|
240
|
-
ticker = data[i]
|
241
|
-
parsedTicker = self.parse_ws_ticker(ticker)
|
242
|
-
symbol = parsedTicker['symbol']
|
243
|
-
self.tickers[symbol] = parsedTicker
|
244
|
-
messageHash = 'ticker:' + symbol
|
245
|
-
client.resolve(parsedTicker, messageHash)
|
246
|
-
client.resolve(self.tickers, 'tickers')
|
247
|
-
|
248
|
-
def parse_ws_ticker(self, ticker, market=None):
|
249
|
-
#
|
250
|
-
# {
|
251
|
-
# "E":1631625534000, # Event time
|
252
|
-
# "T":"SPOT", # Type
|
253
|
-
# "U":"wrx", # Quote unit
|
254
|
-
# "a":"0.0", # Best sell price
|
255
|
-
# "b":"0.0", # Best buy price
|
256
|
-
# "c":"5.0", # Last price
|
257
|
-
# "h":"5.0", # High price
|
258
|
-
# "l":"5.0", # Low price
|
259
|
-
# "o":"5.0", # Open price
|
260
|
-
# "q":"0.0", # Quantity
|
261
|
-
# "s":"btcwrx", # Symbol
|
262
|
-
# "u":"btc" # Base unit
|
263
|
-
# }
|
264
|
-
#
|
265
|
-
marketId = self.safe_string(ticker, 's')
|
266
|
-
timestamp = self.safe_integer(ticker, 'E')
|
267
|
-
return self.safe_ticker({
|
268
|
-
'symbol': self.safe_symbol(marketId, market),
|
269
|
-
'timestamp': timestamp,
|
270
|
-
'datetime': self.iso8601(timestamp),
|
271
|
-
'high': self.safe_string(ticker, 'h'),
|
272
|
-
'low': self.safe_string(ticker, 'l'),
|
273
|
-
'bid': self.safe_number(ticker, 'b'),
|
274
|
-
'bidVolume': None,
|
275
|
-
'ask': self.safe_number(ticker, 'a'),
|
276
|
-
'askVolume': None,
|
277
|
-
'vwap': None,
|
278
|
-
'open': self.safe_string(ticker, 'o'),
|
279
|
-
'close': None,
|
280
|
-
'last': self.safe_string(ticker, 'l'),
|
281
|
-
'previousClose': None,
|
282
|
-
'change': None,
|
283
|
-
'percentage': None,
|
284
|
-
'average': None,
|
285
|
-
'baseVolume': None,
|
286
|
-
'quoteVolume': self.safe_string(ticker, 'q'),
|
287
|
-
'info': ticker,
|
288
|
-
}, market)
|
289
|
-
|
290
|
-
async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
291
|
-
"""
|
292
|
-
get the list of most recent trades for a particular symbol
|
293
|
-
|
294
|
-
https://docs.wazirx.com/#trade-streams
|
295
|
-
|
296
|
-
:param str symbol: unified symbol of the market to fetch trades for
|
297
|
-
:param int [since]: timestamp in ms of the earliest trade to fetch
|
298
|
-
:param int [limit]: the maximum amount of trades to fetch
|
299
|
-
:param dict [params]: extra parameters specific to the exchange API endpoint
|
300
|
-
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
301
|
-
"""
|
302
|
-
await self.load_markets()
|
303
|
-
market = self.market(symbol)
|
304
|
-
symbol = market['symbol']
|
305
|
-
messageHash = market['id'] + '@trades'
|
306
|
-
url = self.urls['api']['ws']
|
307
|
-
message: dict = {
|
308
|
-
'event': 'subscribe',
|
309
|
-
'streams': [messageHash],
|
310
|
-
}
|
311
|
-
request = self.extend(message, params)
|
312
|
-
trades = await self.watch(url, messageHash, request, messageHash)
|
313
|
-
if self.newUpdates:
|
314
|
-
limit = trades.getLimit(symbol, limit)
|
315
|
-
return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
|
316
|
-
|
317
|
-
def handle_trades(self, client: Client, message):
|
318
|
-
#
|
319
|
-
# {
|
320
|
-
# "data": {
|
321
|
-
# "trades": [{
|
322
|
-
# "E": 1631681323000, Event time
|
323
|
-
# "S": "buy", Side
|
324
|
-
# "a": 26946138, Buyer order ID
|
325
|
-
# "b": 26946169, Seller order ID
|
326
|
-
# "m": True, Is buyer maker?
|
327
|
-
# "p": "7.0", Price
|
328
|
-
# "q": "15.0", Quantity
|
329
|
-
# "s": "btcinr", Symbol
|
330
|
-
# "t": 17376030 Trade ID
|
331
|
-
# }]
|
332
|
-
# },
|
333
|
-
# "stream": "btcinr@trades"
|
334
|
-
# }
|
335
|
-
#
|
336
|
-
data = self.safe_value(message, 'data', {})
|
337
|
-
rawTrades = self.safe_value(data, 'trades', [])
|
338
|
-
messageHash = self.safe_string(message, 'stream')
|
339
|
-
split = messageHash.split('@')
|
340
|
-
marketId = self.safe_string(split, 0)
|
341
|
-
market = self.safe_market(marketId)
|
342
|
-
symbol = self.safe_symbol(marketId, market)
|
343
|
-
trades = self.safe_value(self.trades, symbol)
|
344
|
-
if trades is None:
|
345
|
-
limit = self.safe_integer(self.options, 'tradesLimit', 1000)
|
346
|
-
trades = ArrayCache(limit)
|
347
|
-
self.trades[symbol] = trades
|
348
|
-
for i in range(0, len(rawTrades)):
|
349
|
-
parsedTrade = self.parse_ws_trade(rawTrades[i], market)
|
350
|
-
trades.append(parsedTrade)
|
351
|
-
client.resolve(trades, messageHash)
|
352
|
-
|
353
|
-
async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
354
|
-
"""
|
355
|
-
watch trades by user
|
356
|
-
|
357
|
-
https://docs.wazirx.com/#trade-update
|
358
|
-
|
359
|
-
:param str symbol: unified symbol of the market to fetch trades for
|
360
|
-
:param int [since]: timestamp in ms of the earliest trade to fetch
|
361
|
-
:param int [limit]: the maximum amount of trades to fetch
|
362
|
-
:param dict [params]: extra parameters specific to the exchange API endpoint
|
363
|
-
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
364
|
-
"""
|
365
|
-
await self.load_markets()
|
366
|
-
token = await self.authenticate(params)
|
367
|
-
if symbol is not None:
|
368
|
-
market = self.market(symbol)
|
369
|
-
symbol = market['symbol']
|
370
|
-
url = self.urls['api']['ws']
|
371
|
-
messageHash = 'myTrades'
|
372
|
-
message: dict = {
|
373
|
-
'event': 'subscribe',
|
374
|
-
'streams': ['ownTrade'],
|
375
|
-
'auth_key': token,
|
376
|
-
}
|
377
|
-
request = self.deep_extend(message, params)
|
378
|
-
trades = await self.watch(url, messageHash, request, messageHash)
|
379
|
-
if self.newUpdates:
|
380
|
-
limit = trades.getLimit(symbol, limit)
|
381
|
-
return self.filter_by_symbol_since_limit(trades, symbol, since, limit, True)
|
382
|
-
|
383
|
-
async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
384
|
-
"""
|
385
|
-
watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
386
|
-
|
387
|
-
https://docs.wazirx.com/#kline-candlestick-stream
|
388
|
-
|
389
|
-
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
390
|
-
:param str timeframe: the length of time each candle represents
|
391
|
-
:param int [since]: timestamp in ms of the earliest candle to fetch
|
392
|
-
:param int [limit]: the maximum amount of candles to fetch
|
393
|
-
:param dict [params]: extra parameters specific to the exchange API endpoint
|
394
|
-
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
395
|
-
"""
|
396
|
-
await self.load_markets()
|
397
|
-
market = self.market(symbol)
|
398
|
-
symbol = market['symbol']
|
399
|
-
url = self.urls['api']['ws']
|
400
|
-
messageHash = 'ohlcv:' + symbol + ':' + timeframe
|
401
|
-
stream = market['id'] + '@kline_' + timeframe
|
402
|
-
message: dict = {
|
403
|
-
'event': 'subscribe',
|
404
|
-
'streams': [stream],
|
405
|
-
}
|
406
|
-
request = self.deep_extend(message, params)
|
407
|
-
ohlcv = await self.watch(url, messageHash, request, messageHash)
|
408
|
-
if self.newUpdates:
|
409
|
-
limit = ohlcv.getLimit(symbol, limit)
|
410
|
-
return self.filter_by_since_limit(ohlcv, since, limit, 0, True)
|
411
|
-
|
412
|
-
def handle_ohlcv(self, client: Client, message):
|
413
|
-
#
|
414
|
-
# {
|
415
|
-
# "data": {
|
416
|
-
# "E":1631683058904, Event time
|
417
|
-
# "s": "btcinr", Symbol
|
418
|
-
# "t": 1638747660000, Kline start time
|
419
|
-
# "T": 1638747719999, Kline close time
|
420
|
-
# "i": "1m", Interval
|
421
|
-
# "o": "0.0010", Open price
|
422
|
-
# "c": "0.0020", Close price
|
423
|
-
# "h": "0.0025", High price
|
424
|
-
# "l": "0.0015", Low price
|
425
|
-
# "v": "1000", Base asset volume
|
426
|
-
# },
|
427
|
-
# "stream": "btcinr@kline_1m"
|
428
|
-
# }
|
429
|
-
#
|
430
|
-
data = self.safe_value(message, 'data', {})
|
431
|
-
marketId = self.safe_string(data, 's')
|
432
|
-
market = self.safe_market(marketId)
|
433
|
-
symbol = self.safe_symbol(marketId, market)
|
434
|
-
timeframe = self.safe_string(data, 'i')
|
435
|
-
self.ohlcvs[symbol] = self.safe_value(self.ohlcvs, symbol, {})
|
436
|
-
stored = self.safe_value(self.ohlcvs[symbol], timeframe)
|
437
|
-
if stored is None:
|
438
|
-
limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
|
439
|
-
stored = ArrayCacheByTimestamp(limit)
|
440
|
-
self.ohlcvs[symbol][timeframe] = stored
|
441
|
-
parsed = self.parse_ws_ohlcv(data, market)
|
442
|
-
stored.append(parsed)
|
443
|
-
messageHash = 'ohlcv:' + symbol + ':' + timeframe
|
444
|
-
client.resolve(stored, messageHash)
|
445
|
-
|
446
|
-
def parse_ws_ohlcv(self, ohlcv, market=None) -> list:
|
447
|
-
#
|
448
|
-
# {
|
449
|
-
# "E":1631683058904, Event time
|
450
|
-
# "s": "btcinr", Symbol
|
451
|
-
# "t": 1638747660000, Kline start time
|
452
|
-
# "T": 1638747719999, Kline close time
|
453
|
-
# "i": "1m", Interval
|
454
|
-
# "o": "0.0010", Open price
|
455
|
-
# "c": "0.0020", Close price
|
456
|
-
# "h": "0.0025", High price
|
457
|
-
# "l": "0.0015", Low price
|
458
|
-
# "v": "1000", Base asset volume
|
459
|
-
# }
|
460
|
-
#
|
461
|
-
return [
|
462
|
-
self.safe_integer(ohlcv, 't'),
|
463
|
-
self.safe_number(ohlcv, 'o'),
|
464
|
-
self.safe_number(ohlcv, 'c'),
|
465
|
-
self.safe_number(ohlcv, 'h'),
|
466
|
-
self.safe_number(ohlcv, 'l'),
|
467
|
-
self.safe_number(ohlcv, 'v'),
|
468
|
-
]
|
469
|
-
|
470
|
-
async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
471
|
-
"""
|
472
|
-
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
473
|
-
|
474
|
-
https://docs.wazirx.com/#depth-stream
|
475
|
-
|
476
|
-
:param str symbol: unified symbol of the market to fetch the order book for
|
477
|
-
:param int [limit]: the maximum amount of order book entries to return
|
478
|
-
:param dict [params]: extra parameters specific to the exchange API endpoint
|
479
|
-
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
480
|
-
"""
|
481
|
-
await self.load_markets()
|
482
|
-
market = self.market(symbol)
|
483
|
-
symbol = market['symbol']
|
484
|
-
url = self.urls['api']['ws']
|
485
|
-
messageHash = 'orderbook:' + symbol
|
486
|
-
stream = market['id'] + '@depth'
|
487
|
-
subscribe: dict = {
|
488
|
-
'event': 'subscribe',
|
489
|
-
'streams': [stream],
|
490
|
-
}
|
491
|
-
request = self.deep_extend(subscribe, params)
|
492
|
-
orderbook = await self.watch(url, messageHash, request, messageHash)
|
493
|
-
return orderbook.limit()
|
494
|
-
|
495
|
-
def handle_delta(self, bookside, delta):
|
496
|
-
bidAsk = self.parse_bid_ask(delta, 0, 1)
|
497
|
-
bookside.storeArray(bidAsk)
|
498
|
-
|
499
|
-
def handle_deltas(self, bookside, deltas):
|
500
|
-
for i in range(0, len(deltas)):
|
501
|
-
self.handle_delta(bookside, deltas[i])
|
502
|
-
|
503
|
-
def handle_order_book(self, client: Client, message):
|
504
|
-
#
|
505
|
-
# {
|
506
|
-
# "data": {
|
507
|
-
# "E": 1659475095000,
|
508
|
-
# "a": [
|
509
|
-
# ["23051.0", "1.30141"],
|
510
|
-
# ],
|
511
|
-
# "b": [
|
512
|
-
# ["22910.0", "1.30944"],
|
513
|
-
# ],
|
514
|
-
# "s": "btcusdt"
|
515
|
-
# },
|
516
|
-
# "stream": "btcusdt@depth"
|
517
|
-
# }
|
518
|
-
#
|
519
|
-
data = self.safe_value(message, 'data', {})
|
520
|
-
timestamp = self.safe_integer(data, 'E')
|
521
|
-
marketId = self.safe_string(data, 's')
|
522
|
-
market = self.safe_market(marketId)
|
523
|
-
symbol = market['symbol']
|
524
|
-
messageHash = 'orderbook:' + symbol
|
525
|
-
# currentOrderBook = self.safe_value(self.orderbooks, symbol)
|
526
|
-
if not (symbol in self.orderbooks):
|
527
|
-
snapshot = self.parse_order_book(data, symbol, timestamp, 'b', 'a')
|
528
|
-
self.orderbooks[symbol] = self.order_book(snapshot)
|
529
|
-
else:
|
530
|
-
orderbook = self.orderbooks[symbol]
|
531
|
-
asks = self.safe_list(data, 'a', [])
|
532
|
-
bids = self.safe_list(data, 'b', [])
|
533
|
-
self.handle_deltas(orderbook['asks'], asks)
|
534
|
-
self.handle_deltas(orderbook['bids'], bids)
|
535
|
-
orderbook['nonce'] = timestamp
|
536
|
-
orderbook['timestamp'] = timestamp
|
537
|
-
orderbook['datetime'] = self.iso8601(timestamp)
|
538
|
-
self.orderbooks[symbol] = orderbook
|
539
|
-
client.resolve(self.orderbooks[symbol], messageHash)
|
540
|
-
|
541
|
-
async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
542
|
-
await self.load_markets()
|
543
|
-
if symbol is not None:
|
544
|
-
market = self.market(symbol)
|
545
|
-
symbol = market['symbol']
|
546
|
-
token = await self.authenticate(params)
|
547
|
-
messageHash = 'orders'
|
548
|
-
message: dict = {
|
549
|
-
'event': 'subscribe',
|
550
|
-
'streams': ['orderUpdate'],
|
551
|
-
'auth_key': token,
|
552
|
-
}
|
553
|
-
url = self.urls['api']['ws']
|
554
|
-
request = self.deep_extend(message, params)
|
555
|
-
orders = await self.watch(url, messageHash, request, messageHash, request)
|
556
|
-
if self.newUpdates:
|
557
|
-
limit = orders.getLimit(symbol, limit)
|
558
|
-
return self.filter_by_symbol_since_limit(orders, symbol, since, limit, True)
|
559
|
-
|
560
|
-
def handle_order(self, client: Client, message):
|
561
|
-
#
|
562
|
-
# {
|
563
|
-
# "data": {
|
564
|
-
# "E": 1631683058904,
|
565
|
-
# "O": 1631683058000,
|
566
|
-
# "S": "ask",
|
567
|
-
# "V": "70.0",
|
568
|
-
# "X": "wait",
|
569
|
-
# "i": 26946170,
|
570
|
-
# "m": True,
|
571
|
-
# "o": "sell",
|
572
|
-
# "p": "5.0",
|
573
|
-
# "q": "70.0",
|
574
|
-
# "s": "wrxinr",
|
575
|
-
# "v": "0.0"
|
576
|
-
# },
|
577
|
-
# "stream": "orderUpdate"
|
578
|
-
# }
|
579
|
-
#
|
580
|
-
order = self.safe_value(message, 'data', {})
|
581
|
-
parsedOrder = self.parse_ws_order(order)
|
582
|
-
if self.orders is None:
|
583
|
-
limit = self.safe_integer(self.options, 'ordersLimit', 1000)
|
584
|
-
self.orders = ArrayCacheBySymbolById(limit)
|
585
|
-
orders = self.orders
|
586
|
-
orders.append(parsedOrder)
|
587
|
-
messageHash = 'orders'
|
588
|
-
client.resolve(self.orders, messageHash)
|
589
|
-
messageHash += ':' + parsedOrder['symbol']
|
590
|
-
client.resolve(self.orders, messageHash)
|
591
|
-
|
592
|
-
def parse_ws_order(self, order, market=None):
|
593
|
-
#
|
594
|
-
# {
|
595
|
-
# "E": 1631683058904,
|
596
|
-
# "O": 1631683058000,
|
597
|
-
# "S": "ask",
|
598
|
-
# "V": "70.0",
|
599
|
-
# "X": "wait",
|
600
|
-
# "i": 26946170,
|
601
|
-
# "m": True,
|
602
|
-
# "o": "sell",
|
603
|
-
# "p": "5.0",
|
604
|
-
# "q": "70.0",
|
605
|
-
# "s": "wrxinr",
|
606
|
-
# "v": "0.0"
|
607
|
-
# }
|
608
|
-
#
|
609
|
-
timestamp = self.safe_integer(order, 'O')
|
610
|
-
marketId = self.safe_string(order, 's')
|
611
|
-
status = self.safe_string(order, 'X')
|
612
|
-
market = self.safe_market(marketId)
|
613
|
-
return self.safe_order({
|
614
|
-
'info': order,
|
615
|
-
'id': self.safe_string(order, 'i'),
|
616
|
-
'clientOrderId': self.safe_string(order, 'c'),
|
617
|
-
'datetime': self.iso8601(timestamp),
|
618
|
-
'timestamp': timestamp,
|
619
|
-
'lastTradeTimestamp': None,
|
620
|
-
'symbol': market['symbol'],
|
621
|
-
'type': 'limit' if self.safe_value(order, 'm') else 'market',
|
622
|
-
'timeInForce': None,
|
623
|
-
'postOnly': None,
|
624
|
-
'side': self.safe_string(order, 'o'),
|
625
|
-
'price': self.safe_string(order, 'p'),
|
626
|
-
'stopPrice': None,
|
627
|
-
'triggerPrice': None,
|
628
|
-
'amount': self.safe_string(order, 'V'),
|
629
|
-
'filled': None,
|
630
|
-
'remaining': self.safe_string(order, 'q'),
|
631
|
-
'cost': None,
|
632
|
-
'average': self.safe_string(order, 'v'),
|
633
|
-
'status': self.parse_order_status(status),
|
634
|
-
'fee': None,
|
635
|
-
'trades': None,
|
636
|
-
}, market)
|
637
|
-
|
638
|
-
def handle_my_trades(self, client: Client, message):
|
639
|
-
#
|
640
|
-
# {
|
641
|
-
# "data": {
|
642
|
-
# "E": 1631683058000,
|
643
|
-
# "S": "ask",
|
644
|
-
# "U": "usdt",
|
645
|
-
# "a": 114144050,
|
646
|
-
# "b": 114144121,
|
647
|
-
# "f": "0.2",
|
648
|
-
# "ga": "0.0",
|
649
|
-
# "gc": "usdt",
|
650
|
-
# "m": True,
|
651
|
-
# "o": 26946170,
|
652
|
-
# "p": "5.0",
|
653
|
-
# "q": "20.0",
|
654
|
-
# "s": "btcusdt",
|
655
|
-
# "t": 17376032,
|
656
|
-
# "w": "100.0"
|
657
|
-
# },
|
658
|
-
# "stream": "ownTrade"
|
659
|
-
# }
|
660
|
-
#
|
661
|
-
trade = self.safe_value(message, 'data', {})
|
662
|
-
messageHash = 'myTrades'
|
663
|
-
myTrades = None
|
664
|
-
if self.myTrades is None:
|
665
|
-
limit = self.safe_integer(self.options, 'tradesLimit', 1000)
|
666
|
-
myTrades = ArrayCacheBySymbolById(limit)
|
667
|
-
self.myTrades = myTrades
|
668
|
-
else:
|
669
|
-
myTrades = self.myTrades
|
670
|
-
parsedTrade = self.parse_ws_trade(trade)
|
671
|
-
myTrades.append(parsedTrade)
|
672
|
-
client.resolve(myTrades, messageHash)
|
673
|
-
|
674
|
-
def handle_connected(self, client: Client, message):
|
675
|
-
#
|
676
|
-
# {
|
677
|
-
# "data": {
|
678
|
-
# "timeout_duration": 1800
|
679
|
-
# },
|
680
|
-
# "event": "connected"
|
681
|
-
# }
|
682
|
-
#
|
683
|
-
return message
|
684
|
-
|
685
|
-
def handle_subscribed(self, client: Client, message):
|
686
|
-
#
|
687
|
-
# {
|
688
|
-
# "data": {
|
689
|
-
# "streams": ["not ticker@arr"]
|
690
|
-
# },
|
691
|
-
# "event": "subscribed",
|
692
|
-
# "id": 0
|
693
|
-
# }
|
694
|
-
#
|
695
|
-
return message
|
696
|
-
|
697
|
-
def handle_error(self, client: Client, message):
|
698
|
-
#
|
699
|
-
# {
|
700
|
-
# "data": {
|
701
|
-
# "code": 400,
|
702
|
-
# "message": "Invalid request: streams must be an array"
|
703
|
-
# },
|
704
|
-
# "event": "error",
|
705
|
-
# "id": 0
|
706
|
-
# }
|
707
|
-
#
|
708
|
-
# {
|
709
|
-
# "message": "HeartBeat message not received, closing the connection",
|
710
|
-
# "status": "error"
|
711
|
-
# }
|
712
|
-
#
|
713
|
-
raise ExchangeError(self.id + ' ' + self.json(message))
|
714
|
-
|
715
|
-
def handle_message(self, client: Client, message):
|
716
|
-
status = self.safe_string(message, 'status')
|
717
|
-
if status == 'error':
|
718
|
-
self.handle_error(client, message)
|
719
|
-
return
|
720
|
-
event = self.safe_string(message, 'event')
|
721
|
-
eventHandlers: dict = {
|
722
|
-
'error': self.handle_error,
|
723
|
-
'connected': self.handle_connected,
|
724
|
-
'subscribed': self.handle_subscribed,
|
725
|
-
}
|
726
|
-
eventHandler = self.safe_value(eventHandlers, event)
|
727
|
-
if eventHandler is not None:
|
728
|
-
eventHandler(client, message)
|
729
|
-
return
|
730
|
-
stream = self.safe_string(message, 'stream', '')
|
731
|
-
streamHandlers: dict = {
|
732
|
-
'ticker@arr': self.handle_ticker,
|
733
|
-
'@depth': self.handle_order_book,
|
734
|
-
'@kline': self.handle_ohlcv,
|
735
|
-
'@trades': self.handle_trades,
|
736
|
-
'outboundAccountPosition': self.handle_balance,
|
737
|
-
'orderUpdate': self.handle_order,
|
738
|
-
'ownTrade': self.handle_my_trades,
|
739
|
-
}
|
740
|
-
streams = list(streamHandlers.keys())
|
741
|
-
for i in range(0, len(streams)):
|
742
|
-
streamContains = stream.find(streams[i]) > -1
|
743
|
-
if streamContains:
|
744
|
-
handler = streamHandlers[streams[i]]
|
745
|
-
handler(client, message)
|
746
|
-
return
|
747
|
-
raise NotSupported(self.id + ' self message type is not supported yet. Message: ' + self.json(message))
|
748
|
-
|
749
|
-
async def authenticate(self, params={}):
|
750
|
-
url = self.urls['api']['ws']
|
751
|
-
client = self.client(url)
|
752
|
-
messageHash = 'authenticated'
|
753
|
-
now = self.milliseconds()
|
754
|
-
subscription = self.safe_value(client.subscriptions, messageHash)
|
755
|
-
expires = self.safe_integer(subscription, 'expires')
|
756
|
-
if subscription is None or now > expires:
|
757
|
-
subscription = await self.privatePostCreateAuthToken()
|
758
|
-
subscription['expires'] = now + self.safe_integer(subscription, 'timeout_duration') * 1000
|
759
|
-
#
|
760
|
-
# {
|
761
|
-
# "auth_key": "Xx***dM",
|
762
|
-
# "timeout_duration": 900
|
763
|
-
# }
|
764
|
-
#
|
765
|
-
client.subscriptions[messageHash] = subscription
|
766
|
-
return self.safe_string(subscription, 'auth_key')
|