705 lines
28 KiB
Python
705 lines
28 KiB
Python
# -*- 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, 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 AuthenticationError
|
|
from ccxt.base.errors import UnsubscribeError
|
|
|
|
|
|
class derive(ccxt.async_support.derive):
|
|
|
|
def describe(self) -> Any:
|
|
return self.deep_extend(super(derive, self).describe(), {
|
|
'has': {
|
|
'ws': False,
|
|
'watchBalance': False,
|
|
'watchMyTrades': True,
|
|
'watchOHLCV': False,
|
|
'watchOrderBook': True,
|
|
'watchOrders': True,
|
|
'watchTicker': True,
|
|
'watchTickers': False,
|
|
'watchBidsAsks': False,
|
|
'watchTrades': True,
|
|
'watchTradesForSymbols': False,
|
|
'watchPositions': False,
|
|
},
|
|
'urls': {
|
|
'api': {
|
|
'ws': 'wss://api.lyra.finance/ws',
|
|
},
|
|
'test': {
|
|
'ws': 'wss://api-demo.lyra.finance/ws',
|
|
},
|
|
},
|
|
'options': {
|
|
'tradesLimit': 1000,
|
|
'ordersLimit': 1000,
|
|
'requestId': {},
|
|
},
|
|
'streaming': {
|
|
'keepAlive': 9000,
|
|
},
|
|
'exceptions': {
|
|
'ws': {
|
|
'exact': {},
|
|
},
|
|
},
|
|
})
|
|
|
|
def request_id(self, url):
|
|
options = self.safe_value(self.options, 'requestId', {})
|
|
previousValue = self.safe_integer(options, url, 0)
|
|
newValue = self.sum(previousValue, 1)
|
|
self.options['requestId'][url] = newValue
|
|
return newValue
|
|
|
|
async def watch_public(self, messageHash, message, subscription):
|
|
url = self.urls['api']['ws']
|
|
requestId = self.request_id(url)
|
|
request = self.extend(message, {
|
|
'id': requestId,
|
|
})
|
|
subscription = self.extend(subscription, {
|
|
'id': requestId,
|
|
'method': 'subscribe',
|
|
})
|
|
return await self.watch(url, messageHash, request, messageHash, subscription)
|
|
|
|
async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
|
"""
|
|
|
|
https://docs.derive.xyz/reference/orderbook-instrument_name-group-depth
|
|
|
|
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
|
: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
|
|
"""
|
|
await self.load_markets()
|
|
if limit is None:
|
|
limit = 10
|
|
market = self.market(symbol)
|
|
topic = 'orderbook.' + market['id'] + '.10.' + self.number_to_string(limit)
|
|
request: dict = {
|
|
'method': 'subscribe',
|
|
'params': {
|
|
'channels': [
|
|
topic,
|
|
],
|
|
},
|
|
}
|
|
subscription: dict = {
|
|
'name': topic,
|
|
'symbol': symbol,
|
|
'limit': limit,
|
|
'params': params,
|
|
}
|
|
orderbook = await self.watch_public(topic, request, subscription)
|
|
return orderbook.limit()
|
|
|
|
def handle_order_book(self, client: Client, message):
|
|
#
|
|
# {
|
|
# method: 'subscription',
|
|
# params: {
|
|
# channel: 'orderbook.BTC-PERP.10.1',
|
|
# data: {
|
|
# timestamp: 1738331231506,
|
|
# instrument_name: 'BTC-PERP',
|
|
# publish_id: 628419,
|
|
# bids: [['104669', '40']],
|
|
# asks: [['104736', '40']]
|
|
# }
|
|
# }
|
|
# }
|
|
#
|
|
params = self.safe_dict(message, 'params')
|
|
data = self.safe_dict(params, 'data')
|
|
marketId = self.safe_string(data, 'instrument_name')
|
|
market = self.safe_market(marketId)
|
|
symbol = market['symbol']
|
|
topic = self.safe_string(params, 'channel')
|
|
if not (symbol in self.orderbooks):
|
|
defaultLimit = self.safe_integer(self.options, 'watchOrderBookLimit', 1000)
|
|
subscription = client.subscriptions[topic]
|
|
limit = self.safe_integer(subscription, 'limit', defaultLimit)
|
|
self.orderbooks[symbol] = self.order_book({}, limit)
|
|
orderbook = self.orderbooks[symbol]
|
|
timestamp = self.safe_integer(data, 'timestamp')
|
|
snapshot = self.parse_order_book(data, symbol, timestamp, 'bids', 'asks')
|
|
orderbook.reset(snapshot)
|
|
client.resolve(orderbook, topic)
|
|
|
|
async def watch_ticker(self, symbol: str, params={}) -> Ticker:
|
|
"""
|
|
|
|
https://docs.derive.xyz/reference/ticker-instrument_name-interval
|
|
|
|
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
:param str symbol: unified symbol of the market to fetch the ticker for
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
|
"""
|
|
await self.load_markets()
|
|
market = self.market(symbol)
|
|
topic = 'ticker.' + market['id'] + '.100'
|
|
request: dict = {
|
|
'method': 'subscribe',
|
|
'params': {
|
|
'channels': [
|
|
topic,
|
|
],
|
|
},
|
|
}
|
|
subscription: dict = {
|
|
'name': topic,
|
|
'symbol': symbol,
|
|
'params': params,
|
|
}
|
|
return await self.watch_public(topic, request, subscription)
|
|
|
|
def handle_ticker(self, client: Client, message):
|
|
#
|
|
# {
|
|
# method: 'subscription',
|
|
# params: {
|
|
# channel: 'ticker.BTC-PERP.100',
|
|
# data: {
|
|
# timestamp: 1738485104439,
|
|
# instrument_ticker: {
|
|
# instrument_type: 'perp',
|
|
# instrument_name: 'BTC-PERP',
|
|
# scheduled_activation: 1701840228,
|
|
# scheduled_deactivation: '9223372036854775807',
|
|
# is_active: True,
|
|
# tick_size: '0.1',
|
|
# minimum_amount: '0.01',
|
|
# maximum_amount: '10000',
|
|
# amount_step: '0.001',
|
|
# mark_price_fee_rate_cap: '0',
|
|
# maker_fee_rate: '0.0001',
|
|
# taker_fee_rate: '0.0003',
|
|
# base_fee: '0.1',
|
|
# base_currency: 'BTC',
|
|
# quote_currency: 'USD',
|
|
# option_details: null,
|
|
# perp_details: {
|
|
# index: 'BTC-USD',
|
|
# max_rate_per_hour: '0.004',
|
|
# min_rate_per_hour: '-0.004',
|
|
# static_interest_rate: '0.0000125',
|
|
# aggregate_funding: '10581.779418721074588722',
|
|
# funding_rate: '0.000024792239208858'
|
|
# },
|
|
# erc20_details: null,
|
|
# base_asset_address: '0xDBa83C0C654DB1cd914FA2710bA743e925B53086',
|
|
# base_asset_sub_id: '0',
|
|
# pro_rata_fraction: '0',
|
|
# fifo_min_allocation: '0',
|
|
# pro_rata_amount_step: '0.1',
|
|
# best_ask_amount: '0.131',
|
|
# best_ask_price: '99898.6',
|
|
# best_bid_amount: '0.056',
|
|
# best_bid_price: '99889.1',
|
|
# five_percent_bid_depth: '11.817',
|
|
# five_percent_ask_depth: '9.116',
|
|
# option_pricing: null,
|
|
# index_price: '99883.8',
|
|
# mark_price: '99897.52408421244763303548098',
|
|
# stats: {
|
|
# contract_volume: '92.395',
|
|
# num_trades: '2924',
|
|
# open_interest: '33.743468027373780786',
|
|
# high: '102320.4',
|
|
# low: '99064.3',
|
|
# percent_change: '-0.021356',
|
|
# usd_change: '-2178'
|
|
# },
|
|
# timestamp: 1738485165881,
|
|
# min_price: '97939.1',
|
|
# max_price: '101895.2'
|
|
# }
|
|
# }
|
|
# }
|
|
# }
|
|
#
|
|
params = self.safe_dict(message, 'params')
|
|
rawData = self.safe_dict(params, 'data')
|
|
data = self.safe_dict(rawData, 'instrument_ticker')
|
|
topic = self.safe_value(params, 'channel')
|
|
ticker = self.parse_ticker(data)
|
|
self.tickers[ticker['symbol']] = ticker
|
|
client.resolve(ticker, topic)
|
|
return message
|
|
|
|
async def un_watch_order_book(self, symbol: str, params={}) -> Any:
|
|
"""
|
|
unsubscribe from the orderbook channel
|
|
:param str symbol: unified symbol of the market to fetch the order book for
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:param int [params.limit]: orderbook limit, default is None
|
|
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
|
"""
|
|
await self.load_markets()
|
|
limit = self.safe_integer(params, 'limit')
|
|
if limit is None:
|
|
limit = 10
|
|
market = self.market(symbol)
|
|
topic = 'orderbook.' + market['id'] + '.10.' + self.number_to_string(limit)
|
|
messageHash = 'unwatch' + topic
|
|
request: dict = {
|
|
'method': 'unsubscribe',
|
|
'params': {
|
|
'channels': [
|
|
topic,
|
|
],
|
|
},
|
|
}
|
|
subscription: dict = {
|
|
'name': topic,
|
|
}
|
|
return await self.un_watch_public(messageHash, request, subscription)
|
|
|
|
async def un_watch_trades(self, symbol: str, params={}) -> Any:
|
|
"""
|
|
unsubscribe from the trades channel
|
|
:param str symbol: unified symbol of the market to unwatch the trades for
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:returns any: status of the unwatch request
|
|
"""
|
|
await self.load_markets()
|
|
market = self.market(symbol)
|
|
topic = 'trades.' + market['id']
|
|
messageHah = 'unwatch' + topic
|
|
request: dict = {
|
|
'method': 'unsubscribe',
|
|
'params': {
|
|
'channels': [
|
|
topic,
|
|
],
|
|
},
|
|
}
|
|
subscription: dict = {
|
|
'name': topic,
|
|
}
|
|
return await self.un_watch_public(messageHah, request, subscription)
|
|
|
|
async def un_watch_public(self, messageHash, message, subscription):
|
|
url = self.urls['api']['ws']
|
|
requestId = self.request_id(url)
|
|
request = self.extend(message, {
|
|
'id': requestId,
|
|
})
|
|
subscription = self.extend(subscription, {
|
|
'id': requestId,
|
|
'method': 'unsubscribe',
|
|
})
|
|
return await self.watch(url, messageHash, request, messageHash, subscription)
|
|
|
|
def handle_order_book_un_subscription(self, client: Client, topic):
|
|
parsedTopic = topic.split('.')
|
|
marketId = self.safe_string(parsedTopic, 1)
|
|
market = self.safe_market(marketId)
|
|
symbol = market['symbol']
|
|
if symbol in self.orderbooks:
|
|
del self.orderbooks[symbol]
|
|
if topic in client.subscriptions:
|
|
del client.subscriptions[topic]
|
|
error = UnsubscribeError(self.id + ' orderbook ' + symbol)
|
|
client.reject(error, topic)
|
|
client.resolve(error, 'unwatch' + topic)
|
|
|
|
def handle_trades_un_subscription(self, client: Client, topic):
|
|
parsedTopic = topic.split('.')
|
|
marketId = self.safe_string(parsedTopic, 1)
|
|
market = self.safe_market(marketId)
|
|
symbol = market['symbol']
|
|
if symbol in self.orderbooks:
|
|
del self.trades[symbol]
|
|
if topic in client.subscriptions:
|
|
del client.subscriptions[topic]
|
|
error = UnsubscribeError(self.id + ' trades ' + symbol)
|
|
client.reject(error, topic)
|
|
client.resolve(error, 'unwatch' + topic)
|
|
|
|
def handle_un_subscribe(self, client: Client, message):
|
|
#
|
|
# {
|
|
# id: 1,
|
|
# result: {
|
|
# status: {'orderbook.BTC-PERP.10.10': 'ok'},
|
|
# remaining_subscriptions: []
|
|
# }
|
|
# }
|
|
#
|
|
result = self.safe_dict(message, 'result')
|
|
status = self.safe_dict(result, 'status')
|
|
if status is not None:
|
|
topics = list(status.keys())
|
|
for i in range(0, len(topics)):
|
|
topic = topics[i]
|
|
if topic.find('orderbook') >= 0:
|
|
self.handle_order_book_un_subscription(client, topic)
|
|
elif topic.find('trades') >= 0:
|
|
self.handle_trades_un_subscription(client, topic)
|
|
return message
|
|
|
|
async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
|
"""
|
|
watches information on multiple trades made in a market
|
|
|
|
https://docs.derive.xyz/reference/trades-instrument_name
|
|
|
|
:param str symbol: unified market symbol of the market trades were made in
|
|
:param int [since]: the earliest time in ms to fetch trades for
|
|
:param int [limit]: the maximum number of trade structures to retrieve
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
|
|
"""
|
|
await self.load_markets()
|
|
market = self.market(symbol)
|
|
topic = 'trades.' + market['id']
|
|
request: dict = {
|
|
'method': 'subscribe',
|
|
'params': {
|
|
'channels': [
|
|
topic,
|
|
],
|
|
},
|
|
}
|
|
subscription: dict = {
|
|
'name': topic,
|
|
'symbol': symbol,
|
|
'params': params,
|
|
}
|
|
trades = await self.watch_public(topic, request, subscription)
|
|
if self.newUpdates:
|
|
limit = trades.getLimit(market['symbol'], limit)
|
|
return self.filter_by_symbol_since_limit(trades, symbol, since, limit, True)
|
|
|
|
def handle_trade(self, client: Client, message):
|
|
#
|
|
#
|
|
params = self.safe_dict(message, 'params')
|
|
data = self.safe_dict(params, 'data')
|
|
topic = self.safe_value(params, 'channel')
|
|
parsedTopic = topic.split('.')
|
|
marketId = self.safe_string(parsedTopic, 1)
|
|
market = self.safe_market(marketId)
|
|
symbol = market['symbol']
|
|
tradesArray = self.safe_value(self.trades, symbol)
|
|
if tradesArray is None:
|
|
limit = self.safe_integer(self.options, 'tradesLimit', 1000)
|
|
tradesArray = ArrayCache(limit)
|
|
for i in range(0, len(data)):
|
|
trade = self.parse_trade(data[i])
|
|
tradesArray.append(trade)
|
|
self.trades[symbol] = tradesArray
|
|
client.resolve(tradesArray, topic)
|
|
|
|
async def authenticate(self, params={}):
|
|
self.check_required_credentials()
|
|
url = self.urls['api']['ws']
|
|
client = self.client(url)
|
|
messageHash = 'authenticated'
|
|
future = client.reusableFuture(messageHash)
|
|
authenticated = self.safe_value(client.subscriptions, messageHash)
|
|
if authenticated is None:
|
|
requestId = self.request_id(url)
|
|
now = str(self.milliseconds())
|
|
signature = self.signMessage(now, self.privateKey)
|
|
deriveWalletAddress = self.safe_string(self.options, 'deriveWalletAddress')
|
|
request: dict = {
|
|
'id': requestId,
|
|
'method': 'public/login',
|
|
'params': {
|
|
'wallet': deriveWalletAddress,
|
|
'timestamp': now,
|
|
'signature': signature,
|
|
},
|
|
}
|
|
# subscription: Dict = {
|
|
# 'name': topic,
|
|
# 'symbol': symbol,
|
|
# 'params': params,
|
|
# }
|
|
message = self.extend(request, params)
|
|
self.watch(url, messageHash, message, messageHash, message)
|
|
return await future
|
|
|
|
async def watch_private(self, messageHash, message, subscription):
|
|
await self.authenticate()
|
|
url = self.urls['api']['ws']
|
|
requestId = self.request_id(url)
|
|
request = self.extend(message, {
|
|
'id': requestId,
|
|
})
|
|
subscription = self.extend(subscription, {
|
|
'id': requestId,
|
|
'method': 'subscribe',
|
|
})
|
|
return await self.watch(url, messageHash, request, messageHash, subscription)
|
|
|
|
async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
|
"""
|
|
|
|
https://docs.derive.xyz/reference/subaccount_id-orders
|
|
|
|
watches information on multiple orders made by the user
|
|
:param str symbol: unified market symbol of the market orders were made in
|
|
:param int [since]: the earliest time in ms to fetch orders for
|
|
:param int [limit]: the maximum number of order structures to retrieve
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:param str [params.subaccount_id]: *required* the subaccount id
|
|
:returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
|
"""
|
|
await self.load_markets()
|
|
subaccountId = None
|
|
subaccountId, params = self.handleDeriveSubaccountId('watchOrders', params)
|
|
topic = self.number_to_string(subaccountId) + '.orders'
|
|
messageHash = topic
|
|
if symbol is not None:
|
|
market = self.market(symbol)
|
|
symbol = market['symbol']
|
|
messageHash += ':' + symbol
|
|
request: dict = {
|
|
'method': 'subscribe',
|
|
'params': {
|
|
'channels': [
|
|
topic,
|
|
],
|
|
},
|
|
}
|
|
subscription: dict = {
|
|
'name': topic,
|
|
'params': params,
|
|
}
|
|
message = self.extend(request, params)
|
|
orders = await self.watch_private(messageHash, message, subscription)
|
|
if self.newUpdates:
|
|
limit = orders.getLimit(symbol, limit)
|
|
return self.filter_by_symbol_since_limit(orders, symbol, since, limit, True)
|
|
|
|
def handle_order(self, client: Client, message):
|
|
#
|
|
# {
|
|
# method: 'subscription',
|
|
# params: {
|
|
# channel: '130837.orders',
|
|
# data: [
|
|
# {
|
|
# subaccount_id: 130837,
|
|
# order_id: '1f44c564-5658-4b69-b8c4-4019924207d5',
|
|
# instrument_name: 'BTC-PERP',
|
|
# direction: 'buy',
|
|
# label: 'test1234',
|
|
# quote_id: null,
|
|
# creation_timestamp: 1738578974146,
|
|
# last_update_timestamp: 1738578974146,
|
|
# limit_price: '10000',
|
|
# amount: '0.01',
|
|
# filled_amount: '0',
|
|
# average_price: '0',
|
|
# order_fee: '0',
|
|
# order_type: 'limit',
|
|
# time_in_force: 'post_only',
|
|
# order_status: 'untriggered',
|
|
# max_fee: '219',
|
|
# signature_expiry_sec: 1746354973,
|
|
# nonce: 1738578973570,
|
|
# signer: '0x30CB7B06AdD6749BbE146A6827502B8f2a79269A',
|
|
# signature: '0xc6927095f74a0d3b1aeef8c0579d120056530479f806e9d2e6616df742a8934c69046361beae833b32b25c0145e318438d7d1624bb835add956f63aa37192f571c',
|
|
# cancel_reason: '',
|
|
# mmp: False,
|
|
# is_transfer: False,
|
|
# replaced_order_id: null,
|
|
# trigger_type: 'stoploss',
|
|
# trigger_price_type: 'mark',
|
|
# trigger_price: '102800',
|
|
# trigger_reject_message: null
|
|
# }
|
|
# ]
|
|
# }
|
|
# }
|
|
#
|
|
params = self.safe_dict(message, 'params')
|
|
topic = self.safe_string(params, 'channel')
|
|
rawOrders = self.safe_list(params, 'data')
|
|
for i in range(0, len(rawOrders)):
|
|
data = rawOrders[i]
|
|
parsed = self.parse_order(data)
|
|
symbol = self.safe_string(parsed, 'symbol')
|
|
orderId = self.safe_string(parsed, 'id')
|
|
if symbol is not None:
|
|
if self.orders is None:
|
|
limit = self.safe_integer(self.options, 'ordersLimit', 1000)
|
|
self.orders = ArrayCacheBySymbolById(limit)
|
|
cachedOrders = self.orders
|
|
orders = self.safe_value(cachedOrders.hashmap, symbol, {})
|
|
order = self.safe_value(orders, orderId)
|
|
if order is not None:
|
|
fee = self.safe_value(order, 'fee')
|
|
if fee is not None:
|
|
parsed['fee'] = fee
|
|
fees = self.safe_value(order, 'fees')
|
|
if fees is not None:
|
|
parsed['fees'] = fees
|
|
parsed['trades'] = self.safe_value(order, 'trades')
|
|
parsed['timestamp'] = self.safe_integer(order, 'timestamp')
|
|
parsed['datetime'] = self.safe_string(order, 'datetime')
|
|
cachedOrders.append(parsed)
|
|
messageHashSymbol = topic + ':' + symbol
|
|
client.resolve(self.orders, messageHashSymbol)
|
|
client.resolve(self.orders, topic)
|
|
|
|
async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
|
"""
|
|
|
|
https://docs.derive.xyz/reference/subaccount_id-trades
|
|
|
|
watches information on multiple trades made by the user
|
|
:param str symbol: unified market symbol of the market orders were made in
|
|
:param int [since]: the earliest time in ms to fetch orders for
|
|
:param int [limit]: the maximum number of order structures to retrieve
|
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
:param str [params.subaccount_id]: *required* the subaccount id
|
|
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
|
|
"""
|
|
await self.load_markets()
|
|
subaccountId = None
|
|
subaccountId, params = self.handleDeriveSubaccountId('watchMyTrades', params)
|
|
topic = self.number_to_string(subaccountId) + '.trades'
|
|
messageHash = topic
|
|
if symbol is not None:
|
|
market = self.market(symbol)
|
|
symbol = market['symbol']
|
|
messageHash += ':' + symbol
|
|
request: dict = {
|
|
'method': 'subscribe',
|
|
'params': {
|
|
'channels': [
|
|
topic,
|
|
],
|
|
},
|
|
}
|
|
subscription: dict = {
|
|
'name': topic,
|
|
'params': params,
|
|
}
|
|
message = self.extend(request, params)
|
|
trades = await self.watch_private(messageHash, message, subscription)
|
|
if self.newUpdates:
|
|
limit = trades.getLimit(symbol, limit)
|
|
return self.filter_by_symbol_since_limit(trades, symbol, since, limit, True)
|
|
|
|
def handle_my_trade(self, client: Client, message):
|
|
#
|
|
#
|
|
myTrades = self.myTrades
|
|
if myTrades is None:
|
|
limit = self.safe_integer(self.options, 'tradesLimit', 1000)
|
|
myTrades = ArrayCacheBySymbolById(limit)
|
|
params = self.safe_dict(message, 'params')
|
|
topic = self.safe_string(params, 'channel')
|
|
rawTrades = self.safe_list(params, 'data')
|
|
for i in range(0, len(rawTrades)):
|
|
trade = self.parse_trade(message)
|
|
myTrades.append(trade)
|
|
client.resolve(myTrades, topic)
|
|
messageHash = topic + trade['symbol']
|
|
client.resolve(myTrades, messageHash)
|
|
|
|
def handle_error_message(self, client: Client, message) -> Bool:
|
|
#
|
|
# {
|
|
# id: '690c6276-0fc6-4121-aafa-f28bf5adedcb',
|
|
# error: {code: -32600, message: 'Invalid Request'}
|
|
# }
|
|
#
|
|
if not ('error' in message):
|
|
return False
|
|
errorMessage = self.safe_dict(message, 'error')
|
|
errorCode = self.safe_string(errorMessage, 'code')
|
|
try:
|
|
if errorCode is not None:
|
|
feedback = self.id + ' ' + self.json(message)
|
|
self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
|
|
raise ExchangeError(feedback)
|
|
return False
|
|
except Exception as error:
|
|
if isinstance(error, AuthenticationError):
|
|
messageHash = 'authenticated'
|
|
client.reject(error, messageHash)
|
|
if messageHash in client.subscriptions:
|
|
del client.subscriptions[messageHash]
|
|
else:
|
|
client.reject(error)
|
|
return True
|
|
|
|
def handle_message(self, client: Client, message):
|
|
if self.handle_error_message(client, message):
|
|
return
|
|
methods: dict = {
|
|
'orderbook': self.handle_order_book,
|
|
'ticker': self.handle_ticker,
|
|
'trades': self.handle_trade,
|
|
'orders': self.handle_order,
|
|
'mytrades': self.handle_my_trade,
|
|
}
|
|
event = None
|
|
params = self.safe_dict(message, 'params')
|
|
if params is not None:
|
|
channel = self.safe_string(params, 'channel')
|
|
if channel is not None:
|
|
parsedChannel = channel.split('.')
|
|
if (channel.find('orders') >= 0) or channel.find('trades') > 0:
|
|
event = self.safe_string(parsedChannel, 1)
|
|
# {subaccounr_id}.trades
|
|
if event == 'trades':
|
|
event = 'mytrades'
|
|
else:
|
|
event = self.safe_string(parsedChannel, 0)
|
|
method = self.safe_value(methods, event)
|
|
if method is not None:
|
|
method(client, message)
|
|
return
|
|
if 'id' in message:
|
|
id = self.safe_string(message, 'id')
|
|
subscriptionsById = self.index_by(client.subscriptions, 'id')
|
|
subscription = self.safe_value(subscriptionsById, id, {})
|
|
if 'method' in subscription:
|
|
if subscription['method'] == 'public/login':
|
|
self.handle_auth(client, message)
|
|
elif subscription['method'] == 'unsubscribe':
|
|
self.handle_un_subscribe(client, message)
|
|
# could handleSubscribe
|
|
|
|
def handle_auth(self, client: Client, message):
|
|
#
|
|
# {
|
|
# id: 1,
|
|
# result: [130837]
|
|
# }
|
|
#
|
|
messageHash = 'authenticated'
|
|
ids = self.safe_list(message, 'result')
|
|
if len(ids) > 0:
|
|
# client.resolve(message, messageHash)
|
|
future = self.safe_value(client.futures, 'authenticated')
|
|
future.resolve(True)
|
|
else:
|
|
error = AuthenticationError(self.json(message))
|
|
client.reject(error, messageHash)
|
|
# allows further authentication attempts
|
|
if messageHash in client.subscriptions:
|
|
del client.subscriptions['authenticated']
|