add
This commit is contained in:
558
ccxt/pro/probit.py
Normal file
558
ccxt/pro/probit.py
Normal file
@@ -0,0 +1,558 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
|
||||
# https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
|
||||
|
||||
import ccxt.async_support
|
||||
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById
|
||||
from ccxt.base.types import Any, Balances, Bool, Int, Order, OrderBook, Str, Ticker, Trade
|
||||
from ccxt.async_support.base.ws.client import Client
|
||||
from typing import List
|
||||
from ccxt.base.errors import ExchangeError
|
||||
from ccxt.base.errors import NotSupported
|
||||
|
||||
|
||||
class probit(ccxt.async_support.probit):
|
||||
|
||||
def describe(self) -> Any:
|
||||
return self.deep_extend(super(probit, self).describe(), {
|
||||
'has': {
|
||||
'ws': True,
|
||||
'watchBalance': True,
|
||||
'watchTicker': True,
|
||||
'watchTickers': False,
|
||||
'watchTrades': True,
|
||||
'watchTradesForSymbols': False,
|
||||
'watchMyTrades': True,
|
||||
'watchOrders': True,
|
||||
'watchOrderBook': True,
|
||||
'watchOHLCV': False,
|
||||
},
|
||||
'urls': {
|
||||
'api': {
|
||||
'ws': 'wss://api.probit.com/api/exchange/v1/ws',
|
||||
},
|
||||
'test': {
|
||||
'ws': 'wss://demo-api.probit.com/api/exchange/v1/ws',
|
||||
},
|
||||
},
|
||||
'options': {
|
||||
'watchOrderBook': {
|
||||
'filter': 'order_books_l2',
|
||||
'interval': 100, # or 500
|
||||
},
|
||||
},
|
||||
'streaming': {
|
||||
},
|
||||
})
|
||||
|
||||
async def watch_balance(self, params={}) -> Balances:
|
||||
"""
|
||||
watch balance and get the amount of funds available for trading or funds locked in orders
|
||||
|
||||
https://docs-en.probit.com/reference/balance-1
|
||||
|
||||
:param dict [params]: extra parameters specific to the exchange API endpoint
|
||||
:returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
|
||||
"""
|
||||
await self.authenticate(params)
|
||||
messageHash = 'balance'
|
||||
return await self.subscribe_private(messageHash, 'balance', params)
|
||||
|
||||
def handle_balance(self, client: Client, message):
|
||||
#
|
||||
# {
|
||||
# "channel": "balance",
|
||||
# "reset": False,
|
||||
# "data": {
|
||||
# "USDT": {
|
||||
# "available": "15",
|
||||
# "total": "15"
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
#
|
||||
messageHash = 'balance'
|
||||
self.parse_ws_balance(message)
|
||||
client.resolve(self.balance, messageHash)
|
||||
|
||||
def parse_ws_balance(self, message):
|
||||
#
|
||||
# {
|
||||
# "channel": "balance",
|
||||
# "reset": False,
|
||||
# "data": {
|
||||
# "USDT": {
|
||||
# "available": "15",
|
||||
# "total": "15"
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
#
|
||||
reset = self.safe_bool(message, 'reset', False)
|
||||
data = self.safe_value(message, 'data', {})
|
||||
currencyIds = list(data.keys())
|
||||
if reset:
|
||||
self.balance = {}
|
||||
for i in range(0, len(currencyIds)):
|
||||
currencyId = currencyIds[i]
|
||||
entry = data[currencyId]
|
||||
code = self.safe_currency_code(currencyId)
|
||||
account = self.account()
|
||||
account['free'] = self.safe_string(entry, 'available')
|
||||
account['total'] = self.safe_string(entry, 'total')
|
||||
self.balance[code] = account
|
||||
self.balance = self.safe_balance(self.balance)
|
||||
|
||||
async def watch_ticker(self, symbol: str, params={}) -> Ticker:
|
||||
"""
|
||||
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
||||
|
||||
https://docs-en.probit.com/reference/marketdata
|
||||
|
||||
:param str symbol: unified symbol of the market to fetch the ticker for
|
||||
:param dict [params]: extra parameters specific to the exchange API endpoint
|
||||
:param int [params.interval]: Unit time to synchronize market information(ms). Available units: 100, 500
|
||||
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
||||
"""
|
||||
channel = 'ticker'
|
||||
return await self.subscribe_public('watchTicker', symbol, 'ticker', channel, params)
|
||||
|
||||
def handle_ticker(self, client: Client, message):
|
||||
#
|
||||
# {
|
||||
# "channel": "marketdata",
|
||||
# "market_id": "BTC-USDT",
|
||||
# "status": "ok",
|
||||
# "lag": 0,
|
||||
# "ticker": {
|
||||
# "time": "2022-07-21T14:18:04.000Z",
|
||||
# "last": "22591.3",
|
||||
# "low": "22500.1",
|
||||
# "high": "39790.7",
|
||||
# "change": "-1224",
|
||||
# "base_volume": "1002.32005445",
|
||||
# "quote_volume": "23304489.385351021"
|
||||
# },
|
||||
# "reset": True
|
||||
# }
|
||||
#
|
||||
marketId = self.safe_string(message, 'market_id')
|
||||
symbol = self.safe_symbol(marketId)
|
||||
ticker = self.safe_value(message, 'ticker', {})
|
||||
market = self.safe_market(marketId)
|
||||
parsedTicker = self.parse_ticker(ticker, market)
|
||||
messageHash = 'ticker:' + symbol
|
||||
self.tickers[symbol] = parsedTicker
|
||||
client.resolve(parsedTicker, messageHash)
|
||||
|
||||
async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
||||
"""
|
||||
get the list of most recent trades for a particular symbol
|
||||
|
||||
https://docs-en.probit.com/reference/trade_history
|
||||
|
||||
:param str symbol: unified symbol of the market to fetch trades for
|
||||
:param int [since]: timestamp in ms of the earliest trade to fetch
|
||||
:param int [limit]: the maximum amount of trades to fetch
|
||||
:param dict [params]: extra parameters specific to the exchange API endpoint
|
||||
:param int [params.interval]: Unit time to synchronize market information(ms). Available units: 100, 500
|
||||
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
||||
"""
|
||||
channel = 'recent_trades'
|
||||
symbol = self.safe_symbol(symbol)
|
||||
trades = await self.subscribe_public('watchTrades', symbol, 'trades', channel, params)
|
||||
if self.newUpdates:
|
||||
limit = trades.getLimit(symbol, limit)
|
||||
return self.filter_by_symbol_since_limit(trades, symbol, since, limit, True)
|
||||
|
||||
def handle_trades(self, client: Client, message):
|
||||
#
|
||||
# {
|
||||
# "channel": "marketdata",
|
||||
# "market_id": "BTC-USDT",
|
||||
# "status": "ok",
|
||||
# "lag": 0,
|
||||
# "recent_trades": [
|
||||
# {
|
||||
# "id": "BTC-USDT:8010233",
|
||||
# "price": "22701.4",
|
||||
# "quantity": "0.011011",
|
||||
# "time": "2022-07-21T13:40:40.983Z",
|
||||
# "side": "buy",
|
||||
# "tick_direction": "up"
|
||||
# }
|
||||
# ...
|
||||
# ]
|
||||
# "reset": True
|
||||
# }
|
||||
#
|
||||
marketId = self.safe_string(message, 'market_id')
|
||||
symbol = self.safe_symbol(marketId)
|
||||
market = self.safe_market(marketId)
|
||||
trades = self.safe_value(message, 'recent_trades', [])
|
||||
if self.safe_bool(message, 'reset', False):
|
||||
return # see comment in handleMessage
|
||||
messageHash = 'trades:' + symbol
|
||||
stored = self.safe_value(self.trades, symbol)
|
||||
if stored is None:
|
||||
limit = self.safe_integer(self.options, 'tradesLimit', 1000)
|
||||
stored = ArrayCache(limit)
|
||||
self.trades[symbol] = stored
|
||||
for i in range(0, len(trades)):
|
||||
trade = trades[i]
|
||||
parsed = self.parse_trade(trade, market)
|
||||
stored.append(parsed)
|
||||
self.trades[symbol] = stored
|
||||
client.resolve(self.trades[symbol], messageHash)
|
||||
|
||||
async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
||||
"""
|
||||
get the list of trades associated with the user
|
||||
|
||||
https://docs-en.probit.com/reference/trade_history
|
||||
|
||||
:param str symbol: unified symbol of the market to fetch trades for
|
||||
:param int [since]: timestamp in ms of the earliest trade to fetch
|
||||
:param int [limit]: the maximum amount of trades to fetch
|
||||
:param dict [params]: extra parameters specific to the exchange API endpoint
|
||||
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
||||
"""
|
||||
await self.load_markets()
|
||||
await self.authenticate(params)
|
||||
messageHash = 'trades'
|
||||
if symbol is not None:
|
||||
symbol = self.safe_symbol(symbol)
|
||||
messageHash = messageHash + ':' + symbol
|
||||
trades = await self.subscribe_private(messageHash, 'trade_history', params)
|
||||
if self.newUpdates:
|
||||
limit = trades.getLimit(symbol, limit)
|
||||
return self.filter_by_symbol_since_limit(trades, symbol, since, limit, True)
|
||||
|
||||
def handle_my_trades(self, client: Client, message):
|
||||
#
|
||||
# {
|
||||
# "channel": "trade_history",
|
||||
# "reset": False,
|
||||
# "data": [{
|
||||
# "id": "BTC-USDT:8010722",
|
||||
# "order_id": "4124999207",
|
||||
# "side": "buy",
|
||||
# "fee_amount": "0.0134999868096",
|
||||
# "fee_currency_id": "USDT",
|
||||
# "status": "settled",
|
||||
# "price": "23136.7",
|
||||
# "quantity": "0.00032416",
|
||||
# "cost": "7.499992672",
|
||||
# "time": "2022-07-21T17:09:33.056Z",
|
||||
# "market_id": "BTC-USDT"
|
||||
# }]
|
||||
# }
|
||||
#
|
||||
rawTrades = self.safe_value(message, 'data', [])
|
||||
length = len(rawTrades)
|
||||
if length == 0:
|
||||
return
|
||||
if self.safe_bool(message, 'reset', False):
|
||||
return # see comment in handleMessage
|
||||
messageHash = 'trades'
|
||||
stored = self.myTrades
|
||||
if stored is None:
|
||||
limit = self.safe_integer(self.options, 'tradesLimit', 1000)
|
||||
stored = ArrayCacheBySymbolById(limit)
|
||||
self.myTrades = stored
|
||||
trades = self.parse_trades(rawTrades)
|
||||
tradeSymbols: dict = {}
|
||||
for j in range(0, len(trades)):
|
||||
trade = trades[j]
|
||||
# don't include 'executed' state, because it's just blanket state of the trade, emited before actual trade event
|
||||
if self.safe_string(trade['info'], 'status') == 'executed':
|
||||
continue
|
||||
tradeSymbols[trade['symbol']] = True
|
||||
stored.append(trade)
|
||||
unique = list(tradeSymbols.keys())
|
||||
uniqueLength = len(unique)
|
||||
if uniqueLength == 0:
|
||||
return
|
||||
for i in range(0, len(unique)):
|
||||
symbol = unique[i]
|
||||
symbolSpecificMessageHash = messageHash + ':' + symbol
|
||||
client.resolve(stored, symbolSpecificMessageHash)
|
||||
client.resolve(stored, messageHash)
|
||||
|
||||
async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
||||
"""
|
||||
watches information on an order made by the user
|
||||
|
||||
https://docs-en.probit.com/reference/open_order
|
||||
|
||||
:param str symbol: unified symbol of the market the order was made in
|
||||
:param int [since]: timestamp in ms of the earliest order to watch
|
||||
:param int [limit]: the maximum amount of orders to watch
|
||||
:param dict [params]: extra parameters specific to the exchange API endpoint
|
||||
:param str [params.channel]: choose what channel to use. Can open_order or order_history.
|
||||
:returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
||||
"""
|
||||
await self.authenticate(params)
|
||||
messageHash = 'orders'
|
||||
if symbol is not None:
|
||||
symbol = self.safe_symbol(symbol)
|
||||
messageHash = messageHash + ':' + symbol
|
||||
orders = await self.subscribe_private(messageHash, 'open_order', params)
|
||||
if self.newUpdates:
|
||||
limit = orders.getLimit(symbol, limit)
|
||||
return self.filter_by_symbol_since_limit(orders, symbol, since, limit, True)
|
||||
|
||||
def handle_orders(self, client: Client, message):
|
||||
#
|
||||
# {
|
||||
# "channel": "order_history",
|
||||
# "reset": True,
|
||||
# "data": [{
|
||||
# "id": "4124999207",
|
||||
# "user_id": "633dc56a-621b-4680-8a4e-85a823499b6d",
|
||||
# "market_id": "BTC-USDT",
|
||||
# "type": "market",
|
||||
# "side": "buy",
|
||||
# "limit_price": "0",
|
||||
# "time_in_force": "ioc",
|
||||
# "filled_cost": "7.499992672",
|
||||
# "filled_quantity": "0.00032416",
|
||||
# "open_quantity": "0",
|
||||
# "status": "filled",
|
||||
# "time": "2022-07-21T17:09:33.056Z",
|
||||
# "client_order_id": '',
|
||||
# "cost": "7.5"
|
||||
# },
|
||||
# ...
|
||||
# ]
|
||||
# }
|
||||
#
|
||||
rawOrders = self.safe_value(message, 'data', [])
|
||||
length = len(rawOrders)
|
||||
if length == 0:
|
||||
return
|
||||
messageHash = 'orders'
|
||||
reset = self.safe_bool(message, 'reset', False)
|
||||
stored = self.orders
|
||||
if stored is None or reset:
|
||||
limit = self.safe_integer(self.options, 'ordersLimit', 1000)
|
||||
stored = ArrayCacheBySymbolById(limit)
|
||||
self.orders = stored
|
||||
orderSymbols: dict = {}
|
||||
for i in range(0, len(rawOrders)):
|
||||
rawOrder = rawOrders[i]
|
||||
order = self.parse_order(rawOrder)
|
||||
orderSymbols[order['symbol']] = True
|
||||
stored.append(order)
|
||||
unique = list(orderSymbols.keys())
|
||||
for i in range(0, len(unique)):
|
||||
symbol = unique[i]
|
||||
symbolSpecificMessageHash = messageHash + ':' + symbol
|
||||
client.resolve(stored, symbolSpecificMessageHash)
|
||||
client.resolve(stored, messageHash)
|
||||
|
||||
async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
||||
"""
|
||||
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
||||
|
||||
https://docs-en.probit.com/reference/marketdata
|
||||
|
||||
:param str symbol: unified symbol of the market to fetch the order book for
|
||||
:param int [limit]: the maximum amount of order book entries to return
|
||||
:param dict [params]: extra parameters specific to the exchange API endpoint
|
||||
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
||||
"""
|
||||
channel = None
|
||||
channel, params = self.handle_option_and_params(params, 'watchOrderBook', 'filter', 'order_books')
|
||||
orderbook = await self.subscribe_public('watchOrderBook', symbol, 'orderbook', channel, params)
|
||||
return orderbook.limit()
|
||||
|
||||
async def subscribe_private(self, messageHash, channel, params):
|
||||
url = self.urls['api']['ws']
|
||||
subscribe: dict = {
|
||||
'type': 'subscribe',
|
||||
'channel': channel,
|
||||
}
|
||||
request = self.extend(subscribe, params)
|
||||
subscribeHash = messageHash
|
||||
return await self.watch(url, messageHash, request, subscribeHash)
|
||||
|
||||
async def subscribe_public(self, methodName: str, symbol: str, dataType, filter, params={}):
|
||||
await self.load_markets()
|
||||
market = self.market(symbol)
|
||||
symbol = market['symbol']
|
||||
url = self.urls['api']['ws']
|
||||
client = self.client(url)
|
||||
subscribeHash = 'marketdata:' + symbol
|
||||
messageHash = dataType + ':' + symbol
|
||||
filters = {}
|
||||
if subscribeHash in client.subscriptions:
|
||||
# already subscribed
|
||||
filters = client.subscriptions[subscribeHash]
|
||||
if not (filter in filters):
|
||||
# resubscribe
|
||||
del client.subscriptions[subscribeHash]
|
||||
filters[filter] = True
|
||||
keys = list(filters.keys())
|
||||
interval = None
|
||||
interval, params = self.handle_option_and_params(params, methodName, 'interval', 100)
|
||||
request: dict = {
|
||||
'type': 'subscribe',
|
||||
'channel': 'marketdata',
|
||||
'market_id': market['id'],
|
||||
'filter': keys,
|
||||
'interval': interval,
|
||||
}
|
||||
request = self.extend(request, params)
|
||||
return await self.watch(url, messageHash, request, subscribeHash, filters)
|
||||
|
||||
def handle_order_book(self, client: Client, message, orderBook):
|
||||
#
|
||||
# {
|
||||
# "channel": "marketdata",
|
||||
# "market_id": "BTC-USDT",
|
||||
# "status": "ok",
|
||||
# "lag": 0,
|
||||
# "order_books": [
|
||||
# {side: "buy", price: '1420.7', quantity: "0.057"},
|
||||
# ...
|
||||
# ],
|
||||
# "reset": True
|
||||
# }
|
||||
#
|
||||
marketId = self.safe_string(message, 'market_id')
|
||||
symbol = self.safe_symbol(marketId)
|
||||
dataBySide = self.group_by(orderBook, 'side')
|
||||
messageHash = 'orderbook:' + symbol
|
||||
# orderbook = self.safe_value(self.orderbooks, symbol)
|
||||
if not (symbol in self.orderbooks):
|
||||
self.orderbooks[symbol] = self.order_book({})
|
||||
orderbook = self.orderbooks[symbol]
|
||||
reset = self.safe_bool(message, 'reset', False)
|
||||
if reset:
|
||||
snapshot = self.parse_order_book(dataBySide, symbol, None, 'buy', 'sell', 'price', 'quantity')
|
||||
orderbook.reset(snapshot)
|
||||
else:
|
||||
self.handle_delta(orderbook, dataBySide)
|
||||
client.resolve(orderbook, messageHash)
|
||||
|
||||
def handle_bid_asks(self, bookSide, bidAsks):
|
||||
for i in range(0, len(bidAsks)):
|
||||
bidAsk = bidAsks[i]
|
||||
parsed = self.parse_bid_ask(bidAsk, 'price', 'quantity')
|
||||
bookSide.storeArray(parsed)
|
||||
|
||||
def handle_delta(self, orderbook, delta):
|
||||
storedBids = orderbook['bids']
|
||||
storedAsks = orderbook['asks']
|
||||
asks = self.safe_value(delta, 'sell', [])
|
||||
bids = self.safe_value(delta, 'buy', [])
|
||||
self.handle_bid_asks(storedBids, bids)
|
||||
self.handle_bid_asks(storedAsks, asks)
|
||||
|
||||
def handle_error_message(self, client: Client, message) -> Bool:
|
||||
#
|
||||
# {
|
||||
# "errorCode": "INVALID_ARGUMENT",
|
||||
# "message": '',
|
||||
# "details": {
|
||||
# "interval": "invalid"
|
||||
# }
|
||||
# }
|
||||
#
|
||||
code = self.safe_string(message, 'errorCode')
|
||||
errMessage = self.safe_string(message, 'message', '')
|
||||
details = self.safe_value(message, 'details')
|
||||
feedback = self.id + ' ' + code + ' ' + errMessage + ' ' + self.json(details)
|
||||
if 'exact' in self.exceptions:
|
||||
self.throw_exactly_matched_exception(self.exceptions['exact'], code, feedback)
|
||||
if 'broad' in self.exceptions:
|
||||
self.throw_broadly_matched_exception(self.exceptions['broad'], errMessage, feedback)
|
||||
raise ExchangeError(feedback)
|
||||
|
||||
def handle_authenticate(self, client: Client, message):
|
||||
#
|
||||
# {type: "authorization", result: "ok"}
|
||||
#
|
||||
result = self.safe_string(message, 'result')
|
||||
future = client.subscriptions['authenticated']
|
||||
if result == 'ok':
|
||||
messageHash = 'authenticated'
|
||||
client.resolve(message, messageHash)
|
||||
else:
|
||||
future.reject(message)
|
||||
del client.subscriptions['authenticated']
|
||||
|
||||
def handle_market_data(self, client: Client, message):
|
||||
ticker = self.safe_value(message, 'ticker')
|
||||
if ticker is not None:
|
||||
self.handle_ticker(client, message)
|
||||
trades = self.safe_value(message, 'recent_trades', [])
|
||||
tradesLength = len(trades)
|
||||
if tradesLength:
|
||||
self.handle_trades(client, message)
|
||||
orderBook = self.safe_value_n(message, ['order_books', 'order_books_l1', 'order_books_l2', 'order_books_l3', 'order_books_l4'], [])
|
||||
orderBookLength = len(orderBook)
|
||||
if orderBookLength:
|
||||
self.handle_order_book(client, message, orderBook)
|
||||
|
||||
def handle_message(self, client: Client, message):
|
||||
#
|
||||
# {
|
||||
# "errorCode": "INVALID_ARGUMENT",
|
||||
# "message": '',
|
||||
# "details": {
|
||||
# "interval": "invalid"
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# Note about 'reset' field
|
||||
# 'reset': True field - it happens once after initial subscription, which just returns old items by the moment of subscription(like "fetchMyTrades" does)
|
||||
#
|
||||
errorCode = self.safe_string(message, 'errorCode')
|
||||
if errorCode is not None:
|
||||
self.handle_error_message(client, message)
|
||||
return
|
||||
type = self.safe_string(message, 'type')
|
||||
if type == 'authorization':
|
||||
self.handle_authenticate(client, message)
|
||||
return
|
||||
handlers: dict = {
|
||||
'marketdata': self.handle_market_data,
|
||||
'balance': self.handle_balance,
|
||||
'trade_history': self.handle_my_trades,
|
||||
'open_order': self.handle_orders,
|
||||
'order_history': self.handle_orders,
|
||||
}
|
||||
channel = self.safe_string(message, 'channel')
|
||||
handler = self.safe_value(handlers, channel)
|
||||
if handler is not None:
|
||||
handler(client, message)
|
||||
return
|
||||
error = NotSupported(self.id + ' handleMessage: unknown message: ' + self.json(message))
|
||||
client.reject(error)
|
||||
|
||||
async def authenticate(self, params={}):
|
||||
url = self.urls['api']['ws']
|
||||
client = self.client(url)
|
||||
messageHash = 'authenticated'
|
||||
expires = self.safe_integer(self.options, 'expires', 0)
|
||||
future = self.safe_value(client.subscriptions, messageHash)
|
||||
if (future is None) or (self.milliseconds() > expires):
|
||||
response = await self.sign_in()
|
||||
#
|
||||
# {
|
||||
# "access_token": "0ttDv/2hTTn3bLi8GP1gKaneiEQ6+0hOBenPrxNQt2s=",
|
||||
# "token_type": "bearer",
|
||||
# "expires_in": 900
|
||||
# }
|
||||
#
|
||||
accessToken = self.safe_string(response, 'access_token')
|
||||
request: dict = {
|
||||
'type': 'authorization',
|
||||
'token': accessToken,
|
||||
}
|
||||
future = await self.watch(url, messageHash, self.extend(request, params), messageHash)
|
||||
client.subscriptions[messageHash] = future
|
||||
return future
|
||||
Reference in New Issue
Block a user