mango-explorer/mango/rootbank.py

209 lines
8.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# # # ⚠ Warning
# #
# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
# # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
# # NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# #
# # [🥭 Mango Markets](https://mango.markets/) support is available at:
# # [Docs](https://docs.mango.markets/)
# # [Discord](https://discord.gg/67jySBhxrg)
# # [Twitter](https://twitter.com/mangomarkets)
# # [Github](https://github.com/blockworks-foundation)
# # [Email](mailto:hello@blockworks.foundation)
# import typing
# from datetime import datetime
# from decimal import Decimal
# from solana.publickey import PublicKey
# from .accountinfo import AccountInfo
# from .addressableaccount import AddressableAccount
# from .context import Context
# from .layouts import layouts
# from .metadata import Metadata
# from .version import Version
# # # 🥭 BankBalances class
# #
# # A simple way to package borrow and deposit balances together in a single object.
# #
# class BankBalances(typing.NamedTuple):
# deposits: Decimal
# borrows: Decimal
# def __str__(self) -> str:
# return f"« 𝙱𝚊𝚗𝚔𝙱𝚊𝚕𝚊𝚗𝚌𝚎𝚜 Deposits: {self.deposits:,.8f} Borrows: {self.borrows:,.8f} »"
# def __repr__(self) -> str:
# return f"{self}"
# # # 🥭 NodeBank class
# #
# # `NodeBank` stores details of deposits/borrows and vault.
# #
# class NodeBank(AddressableAccount):
# def __init__(self, account_info: AccountInfo, version: Version, meta_data: Metadata,
# vault: PublicKey, balances: BankBalances) -> None:
# super().__init__(account_info)
# self.version: Version = version
# self.meta_data: Metadata = meta_data
# self.vault: PublicKey = vault
# self.balances: BankBalances = balances
# @staticmethod
# def from_layout(layout: typing.Any, account_info: AccountInfo, version: Version) -> "NodeBank":
# meta_data: Metadata = layout.meta_data
# deposits: Decimal = layout.deposits
# borrows: Decimal = layout.borrows
# balances: BankBalances = BankBalances(deposits=deposits, borrows=borrows)
# vault: PublicKey = layout.vault
# return NodeBank(account_info, version, meta_data, vault, balances)
# @staticmethod
# def parse(account_info: AccountInfo) -> "NodeBank":
# data = account_info.data
# if len(data) != layouts.NODE_BANK.sizeof():
# raise Exception(
# f"NodeBank data length ({len(data)}) does not match expected size ({layouts.NODE_BANK.sizeof()})")
# layout = layouts.NODE_BANK.parse(data)
# return NodeBank.from_layout(layout, account_info, Version.V1)
# @staticmethod
# def load(context: Context, address: PublicKey) -> "NodeBank":
# account_info = AccountInfo.load(context, address)
# if account_info is None:
# raise Exception(f"NodeBank account not found at address '{address}'")
# return NodeBank.parse(account_info)
# def __str__(self) -> str:
# return f"""« 𝙽𝚘𝚍𝚎𝙱𝚊𝚗𝚔 [{self.version}] {self.address}
# {self.meta_data}
# Balances: {self.balances}
# Vault: {self.vault}
# »"""
# def __repr__(self) -> str:
# return f"{self}"
# # # 🥭 RootBank class
# #
# # `RootBank` stores details of how to reach `NodeBank`.
# #
# class RootBank(AddressableAccount):
# def __init__(self, account_info: AccountInfo, version: Version, meta_data: Metadata,
# optimal_util: Decimal, optimal_rate: Decimal, max_rate: Decimal,
# node_banks: typing.Sequence[PublicKey], deposit_index: Decimal,
# borrow_index: Decimal, last_updated: datetime) -> None:
# super().__init__(account_info)
# self.version: Version = version
# self.meta_data: Metadata = meta_data
# self.optimal_util: Decimal = optimal_util
# self.optimal_rate: Decimal = optimal_rate
# self.max_rate: Decimal = max_rate
# self.node_banks: typing.Sequence[PublicKey] = node_banks
# self.deposit_index: Decimal = deposit_index
# self.borrow_index: Decimal = borrow_index
# self.last_updated: datetime = last_updated
# def load_node_banks(self, context: Context) -> typing.Sequence[NodeBank]:
# node_bank_account_infos = AccountInfo.load_multiple(context, self.node_banks)
# return list(map(NodeBank.parse, node_bank_account_infos))
# def pick_node_bank(self, context: Context) -> NodeBank:
# return self.load_node_banks(context)[0]
# def fetch_balances(self, context: Context) -> BankBalances:
# node_banks: typing.Sequence[NodeBank] = self.load_node_banks(context)
# deposits_in_node_banks: Decimal = Decimal(0)
# borrows_in_node_banks: Decimal = Decimal(0)
# for node_bank in node_banks:
# deposits_in_node_banks += node_bank.balances.deposits
# borrows_in_node_banks += node_bank.balances.borrows
# total_deposits: Decimal = deposits_in_node_banks * self.deposit_index
# total_borrows: Decimal = borrows_in_node_banks * self.borrow_index
# return BankBalances(deposits=total_deposits, borrows=total_borrows)
# @staticmethod
# def from_layout(layout: typing.Any, account_info: AccountInfo, version: Version) -> "RootBank":
# meta_data: Metadata = Metadata.from_layout(layout.meta_data)
# optimal_util: Decimal = layout.optimal_util
# optimal_rate: Decimal = layout.optimal_rate
# max_rate: Decimal = layout.max_rate
# num_node_banks: Decimal = layout.num_node_banks
# node_banks: typing.Sequence[PublicKey] = layout.node_banks[0:int(num_node_banks)]
# deposit_index: Decimal = layout.deposit_index
# borrow_index: Decimal = layout.borrow_index
# last_updated: datetime = layout.last_updated
# return RootBank(account_info, version, meta_data, optimal_util, optimal_rate, max_rate, node_banks, deposit_index, borrow_index, last_updated)
# @staticmethod
# def parse(account_info: AccountInfo) -> "RootBank":
# data = account_info.data
# if len(data) != layouts.ROOT_BANK.sizeof():
# raise Exception(
# f"RootBank data length ({len(data)}) does not match expected size ({layouts.ROOT_BANK.sizeof()})")
# layout = layouts.ROOT_BANK.parse(data)
# return RootBank.from_layout(layout, account_info, Version.V1)
# @staticmethod
# def load(context: Context, address: PublicKey) -> "RootBank":
# account_info = AccountInfo.load(context, address)
# if account_info is None:
# raise Exception(f"RootBank account not found at address '{address}'")
# return RootBank.parse(account_info)
# @staticmethod
# def load_multiple(context: Context, addresses: typing.Sequence[PublicKey]) -> typing.Sequence["RootBank"]:
# account_infos = AccountInfo.load_multiple(context, addresses)
# root_banks = []
# for account_info in account_infos:
# root_bank = RootBank.parse(account_info)
# root_banks += [root_bank]
# return root_banks
# @staticmethod
# def find_by_address(values: typing.Sequence["RootBank"], address: PublicKey) -> "RootBank":
# found = [value for value in values if value.address == address]
# if len(found) == 0:
# raise Exception(f"RootBank '{address}' not found in root banks: {values}")
# if len(found) > 1:
# raise Exception(f"RootBank '{address}' matched multiple root banks in: {values}")
# return found[0]
# def __str__(self) -> str:
# return f"""« 𝚁𝚘𝚘𝚝𝙱𝚊𝚗𝚔 [{self.version}] {self.address}
# {self.meta_data}
# Optimal Util: {self.optimal_util:,.4f}
# Optimal Rate: {self.optimal_rate:,.4f}
# Max Rate: {self.max_rate}
# Node Banks:
# {self.node_banks}
# Deposit Index: {self.deposit_index}
# Borrow Index: {self.borrow_index}
# Last Updated: {self.last_updated}
# »"""
# def __repr__(self) -> str:
# return f"{self}"