Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor/ injective market parsing #362

Open
wants to merge 9 commits into
base: development
Choose a base branch
from

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
MSG_CANCEL_DERIVATIVE_ORDER = "/injective.exchange.v1beta1.MsgCancelDerivativeOrder"
MSG_BATCH_UPDATE_ORDERS = "/injective.exchange.v1beta1.MsgBatchUpdateOrders"

MARKETS_LIST_URL = "https://raw.githubusercontent.com/InjectiveLabs/utils-go/master/pkg/curatedLists/hummingbot/markets.json"

INJ_DERIVATIVE_TX_EVENT_TYPES = [
MSG_CREATE_DERIVATIVE_LIMIT_ORDER,
MSG_CANCEL_DERIVATIVE_ORDER,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import grpc
import pandas as pd
from aioresponses import aioresponses
from pyinjective.orderhash import OrderHashResponse
from pyinjective.proto.exchange.injective_accounts_rpc_pb2 import (
StreamSubaccountBalanceResponse,
Expand All @@ -14,21 +15,16 @@
)
from pyinjective.proto.exchange.injective_derivative_exchange_rpc_pb2 import (
DerivativeLimitOrderbookV2,
DerivativeMarketInfo,
DerivativeOrderHistory,
DerivativePosition,
DerivativeTrade,
FundingPayment,
FundingPaymentsResponse,
FundingRate,
FundingRatesResponse,
MarketResponse,
MarketsResponse,
OrderbooksV2Response,
OrdersHistoryResponse,
Paging,
PerpetualMarketFunding,
PerpetualMarketInfo,
PositionDelta,
PositionsResponse,
PriceLevel,
Expand All @@ -37,7 +33,6 @@
StreamOrdersHistoryResponse,
StreamPositionsResponse,
StreamTradesResponse,
TokenMeta,
TradesResponse,
)
from pyinjective.proto.exchange.injective_explorer_rpc_pb2 import (
Expand All @@ -56,18 +51,14 @@
SubaccountBalanceV2,
SubaccountDeposit,
)
from pyinjective.proto.exchange.injective_spot_exchange_rpc_pb2 import (
MarketsResponse as SpotMarketsResponse,
SpotMarketInfo,
TokenMeta as SpotTokenMeta,
)

from hummingbot.connector.constants import s_decimal_0
from hummingbot.connector.gateway.clob_perp.data_sources.injective_perpetual.injective_perpetual_constants import (
BASE_GAS,
DERIVATIVE_CANCEL_ORDER_GAS,
DERIVATIVE_SUBMIT_ORDER_GAS,
GAS_BUFFER,
MARKETS_LIST_URL,
)
from hummingbot.core.data_type.common import OrderType, PositionSide, TradeType
from hummingbot.core.data_type.in_flight_order import InFlightOrder
Expand Down Expand Up @@ -182,7 +173,7 @@ def taker_fee_rate(self) -> Decimal:
def exchange_trading_pair(self) -> str:
return self.market_id

def start(self):
def start(self, mock_api):
self.injective_async_client_mock = self.injective_async_client_mock_patch.start()
self.injective_async_client_mock.return_value = self.injective_async_client_mock
self.gateway_instance_mock = self.gateway_instance_mock_patch.start()
Expand All @@ -201,7 +192,23 @@ def start(self):
self.injective_async_client_mock.stream_oracle_prices.return_value = StreamMock()
self.injective_async_client_mock.stream_derivative_positions.return_value = StreamMock()

self.configure_active_derivative_markets_response(timestamp=self.initial_timestamp)
params = {
"inj_base": self.inj_base,
"base": self.base,
"quote": self.quote,
"base_coin_address": self.base_coin_address,
"quote_coin_address": self.quote_coin_address,
"base_decimals": self.base_decimals,
"quote_decimals": self.quote_decimals,
"initial_timestamp": self.initial_timestamp,
"market_id": self.market_id,
"inj_market_id": self.inj_market_id,
"base_tokens": [self.inj_base, self.base],
"min_price_tick_size": self.min_price_tick_size,
"min_quantity_tick_size": self.min_quantity_tick_size,
}

InjectivePerpetualClientMock.configure_active_derivative_markets_response(mock_api=mock_api, **params)
self.configure_get_funding_info_response(
index_price=Decimal("200"),
mark_price=Decimal("202"),
Expand Down Expand Up @@ -923,14 +930,6 @@ def configure_get_funding_info_response(
taker_fee=AddedToCostTradeFee(flat_fees=[TokenAmount(token=self.quote, amount=Decimal("0"))]),
)

derivative_market_info = self._get_derivative_market_info(
market_id=self.market_id,
base_token=self.base,
next_funding_time=next_funding_time,
)
market_info_response = MarketResponse(market=derivative_market_info)
self.injective_async_client_mock.get_derivative_market.return_value = market_info_response

def configure_get_funding_payments_response(
self, timestamp: float, funding_rate: Decimal, amount: Decimal
):
Expand Down Expand Up @@ -1176,79 +1175,12 @@ def configure_cancelation_transaction_stream_event(self, timestamp: float, trans
)
self.injective_async_client_mock.stream_txs.return_value.add(transaction_event)

def configure_active_derivative_markets_response(self, timestamp: float):
custom_derivative_market_info = self._get_derivative_market_info(
market_id=self.market_id, base_token=self.base
)

inj_derivative_market_info = self._get_derivative_market_info(
market_id=self.inj_market_id, base_token=self.inj_base
)
perp_markets = MarketsResponse()
perp_markets.markets.append(custom_derivative_market_info)
perp_markets.markets.append(inj_derivative_market_info)

self.injective_async_client_mock.get_derivative_markets.return_value = perp_markets

min_spot_price_tick_size = str(
self.min_price_tick_size * Decimal(f"1e{self.quote_decimals - self.base_decimals}"))
min_spot_quantity_tick_size = str(self.min_quantity_tick_size * Decimal(f"1e{self.base_decimals}"))
inj_spot_pair_min_price_tick_size = str(self.min_price_tick_size * Decimal(f"1e{18 - self.base_decimals}"))
inj_spot_pair_min_quantity_tick_size = str(self.min_quantity_tick_size * Decimal(f"1e{self.base_decimals}"))
base_token_meta = SpotTokenMeta(
name="Coin",
address=self.base_coin_address,
symbol=self.base,
decimals=self.base_decimals,
updated_at=int(timestamp * 1e3),
)
quote_token_meta = SpotTokenMeta(
name="Alpha",
address=self.quote_coin_address,
symbol=self.quote,
decimals=self.quote_decimals,
updated_at=int(timestamp * 1e3),
)
inj_token_meta = SpotTokenMeta(
name="Injective Protocol",
address="0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30", # noqa: mock
symbol=self.inj_base,
decimals=18,
updated_at=int(timestamp * 1e3),
)
custom_spot_market_info = SpotMarketInfo(
market_id=self.market_id,
market_status="active",
ticker=f"{self.base}/{self.quote}",
base_denom=self.base_denom,
base_token_meta=base_token_meta,
quote_denom=self.quote_denom,
quote_token_meta=quote_token_meta,
maker_fee_rate=str(self.maker_fee_rate),
taker_fee_rate=str(self.taker_fee_rate),
service_provider_fee="0.4",
min_price_tick_size=min_spot_price_tick_size,
min_quantity_tick_size=min_spot_quantity_tick_size,
)
inj_spot_market_info = SpotMarketInfo(
market_id=self.inj_market_id,
market_status="active",
ticker=f"{self.inj_base}/{self.quote}",
base_denom="inj",
base_token_meta=inj_token_meta,
quote_denom=self.quote_denom,
quote_token_meta=quote_token_meta,
maker_fee_rate=str(self.maker_fee_rate),
taker_fee_rate=str(self.taker_fee_rate),
service_provider_fee="0.4",
min_price_tick_size=inj_spot_pair_min_price_tick_size,
min_quantity_tick_size=inj_spot_pair_min_quantity_tick_size,
)
spot_markets = SpotMarketsResponse()
spot_markets.markets.append(custom_spot_market_info)
spot_markets.markets.append(inj_spot_market_info)

self.injective_async_client_mock.get_spot_markets.return_value = spot_markets
@staticmethod
def configure_active_derivative_markets_response(mock_api: aioresponses, **kwargs):
url = MARKETS_LIST_URL
response = InjectivePerpetualClientMock.get_derivative_market_info(**kwargs)
mock_api.get(url, body=json.dumps(response), repeat=True)
return url

def configure_get_derivative_positions_response(
self,
Expand Down Expand Up @@ -1285,7 +1217,7 @@ def configure_get_derivative_positions_response(
entry_price=str(main_position_price * Decimal(f"1e{self.quote_decimals}")),
margin=str(margin),
liquidation_price="0",
mark_price=str(main_position_mark_price * Decimal(f"1e{self.oracle_scale_factor}")),
mark_price=str(main_position_mark_price * Decimal(f"1e{self.quote_decimals}")),
aggregate_reduce_only_quantity="0",
updated_at=1680511486496,
created_at=-62135596800000,
Expand All @@ -1307,7 +1239,7 @@ def configure_get_derivative_positions_response(
entry_price=str(inj_position_price * Decimal(f"1e{self.quote_decimals}")),
margin=str(margin),
liquidation_price="0",
mark_price=str(inj_position_mark_price * Decimal(f"1e{self.oracle_scale_factor}")),
mark_price=str(inj_position_mark_price * Decimal(f"1e{self.quote_decimals}")),
aggregate_reduce_only_quantity="0",
updated_at=1680511486496,
created_at=-62135596800000,
Expand All @@ -1332,7 +1264,7 @@ def configure_position_event(
direction="long" if side == PositionSide.LONG else "short",
subaccount_id=self.sub_account_id,
quantity=str(size),
mark_price=str(mark_price * Decimal(f"1e{self.oracle_scale_factor}")),
mark_price=str(mark_price * Decimal(f"1e{self.quote_decimals}")),
entry_price=str(entry_price * Decimal(f"1e{self.quote_decimals}")),
margin=str(margin * Decimal(f"1e{self.quote_decimals}")),
aggregate_reduce_only_quantity="0",
Expand All @@ -1342,54 +1274,57 @@ def configure_position_event(
position_event = StreamPositionsResponse(position=position)
self.injective_async_client_mock.stream_derivative_positions.return_value.add(position_event)

def _get_derivative_market_info(
self,
market_id: str,
base_token: str,
next_funding_time: float = 123123123
@staticmethod
def get_derivative_market_info(
inj_base: str,
base: str,
quote: str,
initial_timestamp: float,
base_coin_address = "someBaseCoinAddress",
quote_coin_address = "someQuoteCoinAddress",
base_decimals: int = 18,
quote_decimals: int = 8,
market_id: str = "someMarketId",
inj_market_id: str = "anotherMarketId",
base_tokens: List[str] = [],
min_price_tick_size=Decimal("0.000001"),
min_quantity_tick_size=Decimal("0.001"),
):
quote_token_meta = TokenMeta(
name="Alpha",
address=self.quote_coin_address,
symbol=self.quote,
decimals=self.quote_decimals,
updated_at=int(self.initial_timestamp * 1e3),
)
min_perpetual_price_tick_size = str(self.min_price_tick_size * Decimal(f"1e{self.quote_decimals}"))
min_perpetual_quantity_tick_size = str(self.min_quantity_tick_size)
perpetual_market_info = PerpetualMarketInfo(
hourly_funding_rate_cap="0.0000625",
hourly_interest_rate="0.00000416666",
next_funding_timestamp=int(next_funding_time * 1e3),
funding_interval=3600,
)
perpetual_market_funding = PerpetualMarketFunding(
cumulative_funding="6749828879.286921884648585187",
cumulative_price="1.502338165156193724",
last_timestamp=1677660809,
)
derivative_market_info = DerivativeMarketInfo(
market_id=market_id,
market_status="active",
ticker=f"{base_token}/{self.quote} PERP",
oracle_base=base_token,
oracle_quote=self.quote,
oracle_type="bandibc",
oracle_scale_factor=self.oracle_scale_factor,
initial_margin_ratio="0.095",
maintenance_margin_ratio="0.05",
quote_denom=self.quote_coin_address,
quote_token_meta=quote_token_meta,
maker_fee_rate=str(self.maker_fee_rate),
taker_fee_rate=str(self.taker_fee_rate),
service_provider_fee="0.4",
is_perpetual=True,
min_price_tick_size=min_perpetual_price_tick_size,
min_quantity_tick_size=min_perpetual_quantity_tick_size,
perpetual_market_info=perpetual_market_info,
perpetual_market_funding=perpetual_market_funding,
)
return derivative_market_info
market_ids = {base: market_id, inj_base: inj_market_id}
markets = {"markets": []}
for base_token in base_tokens:
markets["markets"].append(
{
"marketId": market_ids[base_token],
"ticker": f"{base_token}/{quote} PERP",
"baseDenom": base_coin_address,
"baseTokenMeta":
{
"name": base_token,
"address": base_coin_address,
"symbol": base_token,
"logo": "https://static.alchemyapi.io/images/assets/2396.png",
"decimals": base_decimals,
"updatedAt": int(initial_timestamp * 1e3)
},
"quoteDenom": quote_coin_address,
"quoteTokenMeta":
{
"name": "Alpha",
"address": quote_coin_address,
"symbol": quote,
"logo": "https://static.alchemyapi.io/images/assets/3408.png",
"decimals": quote_decimals,
"updatedAt": int(initial_timestamp * 1e3)
},
"makerFeeRate": "-0.0001",
"takerFeeRate": "0.001",
"serviceProviderFee": "0.4",
"minPriceTickSize": str(min_price_tick_size * Decimal(f"1e{quote_decimals}")),
"minQuantityTickSize": str(min_quantity_tick_size)
}
)
return markets

def configure_fetch_last_fee_payment_response(
self, amount: Decimal, funding_rate: Decimal, timestamp: float
Expand Down
Loading