Skip to content

Commit

Permalink
(feat) Added from chain price and value translation to all market cla…
Browse files Browse the repository at this point in the history
…sses. Fixed an error SendToInjective example script
  • Loading branch information
abel committed Sep 12, 2023
1 parent 203500c commit 9370531
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 43 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ make tests

### Changelogs
**0.8.4**
* Added keepalive options to gRPC channels.
* Added methods to SpotMarket, DerivativeMarket and BianaryOptionMarket to translate chain prices and quantities to human-readable format.

**0.8.3**
* Fix dependency issue in setup.py.
Expand Down
6 changes: 0 additions & 6 deletions examples/SendToInjective.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
import json
import requests

import asyncio
import logging

from pyinjective.core.network import Network
from pyinjective.sendtocosmos import Peggo

import importlib.resources as pkg_resources
import pyinjective

async def main() -> None:
# select network: testnet, mainnet
network = Network.testnet()
Expand Down
40 changes: 6 additions & 34 deletions pyinjective/async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,6 @@
DEFAULT_SESSION_RENEWAL_OFFSET = 120 # seconds
DEFAULT_BLOCK_TIME = 2 # seconds

GRPC_CHANNEL_OPTIONS = [
("grpc.keepalive_time_ms", 45000),
("grpc.keepalive_timeout_ms", 5000),
("grpc.http2.max_pings_without_data", 5),
("grpc.keepalive_permit_without_calls", 1),
]


class AsyncClient:
def __init__(
Expand All @@ -95,16 +88,9 @@ def __init__(

# chain stubs
self.chain_channel = (
grpc.aio.secure_channel(
target=network.grpc_endpoint,
credentials=credentials,
options=GRPC_CHANNEL_OPTIONS,
)
grpc.aio.secure_channel(network.grpc_endpoint, credentials)
if (network.use_secure_connection and credentials is not None)
else grpc.aio.insecure_channel(
target=network.grpc_endpoint,
options=GRPC_CHANNEL_OPTIONS,
)
else grpc.aio.insecure_channel(network.grpc_endpoint)
)

self.stubCosmosTendermint = tendermint_query_grpc.ServiceStub(
Expand All @@ -120,16 +106,9 @@ def __init__(

# exchange stubs
self.exchange_channel = (
grpc.aio.secure_channel(
target=network.grpc_exchange_endpoint,
credentials=credentials,
options=GRPC_CHANNEL_OPTIONS,
)
grpc.aio.secure_channel(network.grpc_exchange_endpoint, credentials)
if (network.use_secure_connection and credentials is not None)
else grpc.aio.insecure_channel(
target=network.grpc_exchange_endpoint,
options=GRPC_CHANNEL_OPTIONS,
)
else grpc.aio.insecure_channel(network.grpc_exchange_endpoint)
)
self.stubMeta = exchange_meta_rpc_grpc.InjectiveMetaRPCStub(
self.exchange_channel
Expand Down Expand Up @@ -158,16 +137,9 @@ def __init__(

# explorer stubs
self.explorer_channel = (
grpc.aio.secure_channel(
target=network.grpc_explorer_endpoint,
credentials=credentials,
options=GRPC_CHANNEL_OPTIONS,
)
grpc.aio.secure_channel(network.grpc_explorer_endpoint, credentials)
if (network.use_secure_connection and credentials is not None)
else grpc.aio.insecure_channel(
target=network.grpc_explorer_endpoint,
options=GRPC_CHANNEL_OPTIONS,
)
else grpc.aio.insecure_channel(network.grpc_explorer_endpoint)
)
self.stubExplorer = explorer_rpc_grpc.InjectiveExplorerRPCStub(
self.explorer_channel
Expand Down
27 changes: 26 additions & 1 deletion pyinjective/core/market.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ def price_to_chain_format(self, human_readable_value: Decimal) -> Decimal:

return extended_chain_formatted_value

def quantity_from_chain_format(self, chain_value: Decimal) -> Decimal:
return chain_value / Decimal(f"1e{self.base_token.decimals}")

def price_from_chain_format(self, chain_value: Decimal) -> Decimal:
decimals = self.base_token.decimals - self.quote_token.decimals
return chain_value * Decimal(f"1e{decimals}")

@dataclass(eq=True, frozen=True)
class DerivativeMarket:
id: str
Expand Down Expand Up @@ -92,6 +99,15 @@ def calculate_margin_in_chain_format(

return extended_chain_formatted_margin

def quantity_from_chain_format(self, chain_value: Decimal) -> Decimal:
return chain_value

def price_from_chain_format(self, chain_value: Decimal) -> Decimal:
return chain_value * Decimal(f"1e-{self.quote_token.decimals}")

def margin_from_chain_format(self, chain_value: Decimal) -> Decimal:
return chain_value * Decimal(f"1e-{self.quote_token.decimals}")

@dataclass(eq=True, frozen=True)
class BinaryOptionMarket:
id: str
Expand Down Expand Up @@ -148,4 +164,13 @@ def calculate_margin_in_chain_format(
quantized_margin = (margin // min_quantity_tick_size) * min_quantity_tick_size
extended_chain_formatted_margin = quantized_margin * Decimal(f"1e{ADDITIONAL_CHAIN_FORMAT_DECIMALS}")

return extended_chain_formatted_margin
return extended_chain_formatted_margin

def quantity_from_chain_format(self, chain_value: Decimal, special_denom: Optional[Denom] = None) -> Decimal:
# Binary option markets do not have a base market to provide the number of decimals
decimals = 0 if special_denom is None else special_denom.base
return chain_value * Decimal(f"1e-{decimals}")

def price_from_chain_format(self, chain_value: Decimal, special_denom: Optional[Denom] = None) -> Decimal:
decimals = self.quote_token.decimals if special_denom is None else special_denom.quote
return chain_value * Decimal(f"1e-{decimals}")
2 changes: 1 addition & 1 deletion pyinjective/sendtocosmos.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
class Peggo:
def __init__(self, network: str):
self.network = network
def sendToInjective(self, ethereum_endpoint: str, private_key: str, token_contract: str, receiver: str, amount: int,
def sendToInjective(self, ethereum_endpoint: str, private_key: str, token_contract: str, receiver: str, amount: float,
maxFeePerGas: int, maxPriorityFeePerGas: int, peggo_abi: str, data: str, decimals=18):
if self.network == 'testnet':
peggy_proxy_address = "0xd2C6753F6B1783EF0a3857275e16e79D91b539a3"
Expand Down
97 changes: 97 additions & 0 deletions tests/core/test_market.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,24 @@ def test_convert_price_to_chain_format(self, inj_usdt_spot_market: SpotMarket):

assert (quantized_chain_format_value == chain_value)

def test_convert_quantity_from_chain_format(self, inj_usdt_spot_market: SpotMarket):
expected_quantity = Decimal("123.456")

chain_format_quantity = expected_quantity * Decimal(f"1e{inj_usdt_spot_market.base_token.decimals}")
human_readable_quantity = inj_usdt_spot_market.quantity_from_chain_format(chain_value=chain_format_quantity)

assert (expected_quantity == human_readable_quantity)

def test_convert_price_from_chain_format(self, inj_usdt_spot_market: SpotMarket):
expected_price = Decimal("123.456")

price_decimals = inj_usdt_spot_market.quote_token.decimals - inj_usdt_spot_market.base_token.decimals
chain_format_price = expected_price * Decimal(f"1e{price_decimals}")
human_readable_price = inj_usdt_spot_market.price_from_chain_format(chain_value=chain_format_price)

assert (expected_price == human_readable_price)



class TestDerivativeMarket:

Expand Down Expand Up @@ -76,6 +94,32 @@ def test_convert_margin_to_chain_format(self, btc_usdt_perp_market: DerivativeMa

assert (quantized_chain_format_value == chain_value)

def test_convert_quantity_from_chain_format(self, btc_usdt_perp_market: DerivativeMarket):
expected_quantity = Decimal("123.456")

chain_format_quantity = expected_quantity
human_readable_quantity = btc_usdt_perp_market.quantity_from_chain_format(chain_value=chain_format_quantity)

assert (expected_quantity == human_readable_quantity)

def test_convert_price_from_chain_format(self, btc_usdt_perp_market: DerivativeMarket):
expected_price = Decimal("123.456")

price_decimals = btc_usdt_perp_market.quote_token.decimals
chain_format_price = expected_price * Decimal(f"1e{price_decimals}")
human_readable_price = btc_usdt_perp_market.price_from_chain_format(chain_value=chain_format_price)

assert (expected_price == human_readable_price)

def test_convert_margin_from_chain_format(self, btc_usdt_perp_market: DerivativeMarket):
expected_margin = Decimal("123.456")

price_decimals = btc_usdt_perp_market.quote_token.decimals
chain_format_margin = expected_margin * Decimal(f"1e{price_decimals}")
human_readable_margin = btc_usdt_perp_market.margin_from_chain_format(chain_value=chain_format_margin)

assert (expected_margin == human_readable_margin)

class TestBinaryOptionMarket:

def test_convert_quantity_to_chain_format_with_fixed_denom(self, first_match_bet_market: BinaryOptionMarket):
Expand Down Expand Up @@ -211,3 +255,56 @@ def test_calculate_margin_for_sell_without_fixed_denom(self, first_match_bet_mar
quantized_chain_format_margin = quantized_margin * Decimal(f"1e18")

assert (quantized_chain_format_margin == chain_value)

def test_convert_quantity_from_chain_format_with_fixed_denom(self, first_match_bet_market: BinaryOptionMarket):
original_quantity = Decimal("123.456789")
fixed_denom = Denom(
description="Fixed denom",
base=2,
quote=4,
min_quantity_tick_size=100,
min_price_tick_size=10000,
)

chain_formatted_quantity = original_quantity * Decimal(f"1e{fixed_denom.base}")

human_readable_quantity = first_match_bet_market.quantity_from_chain_format(
chain_value=chain_formatted_quantity, special_denom=fixed_denom
)

assert (original_quantity == human_readable_quantity)

def test_convert_quantity_from_chain_format_without_fixed_denom(self, first_match_bet_market: BinaryOptionMarket):
original_quantity = Decimal("123.456789")

chain_formatted_quantity = original_quantity

human_readable_quantity = first_match_bet_market.quantity_from_chain_format(chain_value=chain_formatted_quantity)

assert (original_quantity == human_readable_quantity)

def test_convert_price_from_chain_format_with_fixed_denom(self, first_match_bet_market: BinaryOptionMarket):
original_price = Decimal("123.456789")
fixed_denom = Denom(
description="Fixed denom",
base=2,
quote=4,
min_quantity_tick_size=100,
min_price_tick_size=10000,
)

chain_formatted_price = original_price * Decimal(f"1e{fixed_denom.quote}")

human_readable_price = first_match_bet_market.price_from_chain_format(
chain_value=chain_formatted_price, special_denom=fixed_denom
)

assert (original_price == human_readable_price)

def test_convert_price_from_chain_format_without_fixed_denom(self, first_match_bet_market: BinaryOptionMarket):
original_price = Decimal("123.456789")
chain_formatted_price = original_price * Decimal(f"1e{first_match_bet_market.quote_token.decimals}")

human_readable_price = first_match_bet_market.price_from_chain_format(chain_value=chain_formatted_price)

assert (original_price == human_readable_price)

0 comments on commit 9370531

Please sign in to comment.