Skip to content

Commit

Permalink
Merge pull request #322 from djeck1432/feat/calculate-ltv-zklend
Browse files Browse the repository at this point in the history
Calculate LTV
  • Loading branch information
djeck1432 authored Dec 4, 2024
2 parents 2736d4b + 553bbbd commit 5bc25c2
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 21 deletions.
2 changes: 1 addition & 1 deletion web_app/api/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ async def get_dashboard(wallet_id: str) -> DashboardResponse:
)
# Fetch zkLend position for the wallet ID
health_ratio = await HealthRatioMixin.get_health_ratio(
contract_address, first_opened_position["token_symbol"]
contract_address
)

# Fetch balances (assuming you have a method for this)
Expand Down
4 changes: 2 additions & 2 deletions web_app/api/serializers/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ class DashboardResponse(BaseModel):
"""
DashboardResponse class for dashboard details.
"""
health_ratio: str = Field(
..., example="0.5", description="The health ratio of the user."
health_ratio: dict[str, str] = Field(
..., example={"health_factor": "2.0", "ltv": "0.5"}, description="The health ratio of the user."
)
balances: Dict[str, Any] = Field(
...,
Expand Down
24 changes: 18 additions & 6 deletions web_app/contract_tools/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class TokenConfig:
name: str
decimals: Decimal
collateral_factor: Decimal = Decimal("0.0")
debt_factor: Decimal = Decimal("0.0")
borrow_factor: Decimal = Decimal("0.0")


@dataclass(frozen=True)
Expand All @@ -50,21 +50,21 @@ class TokenParams:
address="0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7",
decimals=Decimal("18"),
collateral_factor=Decimal("0.80"),
debt_factor=Decimal("1"),
borrow_factor=Decimal("1"),
)
STRK = TokenConfig(
name="STRK",
address="0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d",
decimals=Decimal("18"),
collateral_factor=Decimal("0.50"),
debt_factor=Decimal("1"),
borrow_factor=Decimal("1"),
)
USDC = TokenConfig(
name="USDC",
address="0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8",
decimals=Decimal("6"),
collateral_factor=Decimal("0.80"),
debt_factor=Decimal("1"),
borrow_factor=Decimal("1"),
)

@classmethod
Expand All @@ -86,6 +86,18 @@ def get_token_address(cls, token_name: str) -> str:
return token.address
raise ValueError(f"Token {token_name} not found")

@classmethod
def get_borrow_factor(cls, token_identifier):
"""
Get the borrow factor for a given token.
:param token_identifier: Token identifier: symbol or address
:return: Token borrow factor
"""
for token in cls.tokens():
if token.address == token_identifier or token.name == token_identifier:
return token.borrow_factor
raise ValueError(f"Token {token_identifier} not found")

@classmethod
def get_token_decimals(cls, token_address: str) -> int:
"""
Expand Down Expand Up @@ -113,9 +125,9 @@ def get_token_symbol(cls, token_address: str) -> str:
@classmethod
def get_token_collateral_factor(cls, token_identifier: str) -> Decimal:
"""
Get the token collateral factor for a given token.
Get the collateral factor for a given token.
:param token_identifier: Token identifier: symbol or address
:return: Token symbol
:return: Token collateral factor
"""
for token in cls.tokens():
if token.address == token_identifier or token.name == token_identifier:
Expand Down
48 changes: 36 additions & 12 deletions web_app/contract_tools/mixins/health_ratio.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ async def _get_z_balances(
token: Decimal(balance)
for token, balance in zip(reserves.keys(), await asyncio.gather(*tasks))
}
print(balances)
return balances

@classmethod
Expand Down Expand Up @@ -89,46 +90,69 @@ async def _get_pragma_prices(cls, tokens: set) -> dict[str, Decimal]:
token: price for token, price in zip(tokens, await asyncio.gather(*tasks))
}

@classmethod
def _get_ltv(cls, borrowed_token: str, debt_usdc: Decimal, collateral_value_usdc: Decimal):
borrow_factor = TokenParams.get_borrow_factor(borrowed_token)
return (debt_usdc / borrow_factor) / collateral_value_usdc

@classmethod
async def _get_borrowed_token(
cls, deposit_contract_address: str
) -> tuple[str, int]:
"""
:return: Tuple with borrowed token and current debt on ZkLend
"""
tasks = [CLIENT.get_zklend_debt(deposit_contract_address, token.address) for token in TokenParams.tokens()]
non_zero_debt = [
(token.address, debt[0]) for token, debt in (zip(TokenParams.tokens(), await asyncio.gather(*tasks)))
if debt[0] != 0
]
return non_zero_debt[0]

@classmethod
async def get_health_ratio(
cls, deposit_contract_address: str, borrowed_token: str
) -> str:
cls, deposit_contract_address: str
) -> dict[str, str]:
"""
Calculate the health ratio of a deposit contract.
:param deposit_contract_address: The address of the deposit contract.
:param borrowed_token: The symbol of the borrowed token.
:param borrowed_token: The symbol of the borrowed token. Defaults to USDC.
:return: The health ratio as a string.
"""
borrowed_token_address, debt_raw = await cls._get_borrowed_token(deposit_contract_address)
borrowed_token = TokenParams.get_token_symbol(borrowed_token_address)
deposits = await cls._get_deposited_tokens(deposit_contract_address)
debt_raw = await CLIENT.get_zklend_debt(
deposit_contract_address, TokenParams.get_token_address(borrowed_token)
)
prices = await cls._get_pragma_prices(set(deposits.keys()) | {borrowed_token})

deposit_usdc = sum(
amount * Decimal(prices[token])
for token, amount in deposits.items()
if amount != 0
)

borrowed_address = TokenParams.get_token_address(borrowed_token)
debt_usdc = (
debt_raw[0]
debt_raw
* prices[borrowed_token]
/ 10 ** int(TokenParams.get_token_decimals(borrowed_address))
)

return (
f"{round(deposit_usdc / Decimal(debt_usdc), 2)}" if debt_usdc != 0 else "0"
)
return {
"health_factor": f"{round(deposit_usdc / Decimal(debt_usdc), 2)}" if debt_usdc != 0 else "0",
"ltv": f"{round((debt_usdc / TokenParams.get_borrow_factor(borrowed_token)) / deposit_usdc, 2)}"
}


if __name__ == "__main__":
print(
asyncio.run(
HealthRatioMixin.get_health_ratio(
"0x0582d5Bc3CcfCeF2F7aF1FdA976767B010E453fF487A7FD2ccf9df1524f4D8fC",
"0x0582d5bc3ccfcef2f7af1fda976767b010e453ff487a7fd2ccf9df1524f4d8fc",
"ETH",
)
)
)
# print(asyncio.run(CLIENT.get_balance(
# "0x01b5bd713e72fdc5d63ffd83762f81297f6175a5e0a4771cdadbc1dd5fe72cb1",
# "0x43523d3d7eb62a882efff9dc1664d7ceae8fe154866f3385d9c0bf0697a2c21", 18 )
# ))

0 comments on commit 5bc25c2

Please sign in to comment.