diff --git a/eth_defi/vault/base.py b/eth_defi/vault/base.py index a400d893..ca2c3b75 100644 --- a/eth_defi/vault/base.py +++ b/eth_defi/vault/base.py @@ -5,6 +5,8 @@ - Helps to create automated trading agents against any vault easily - Handle both trading (asset management role) and investor management (deposits/redemptions) + +- See :py:class:`VaultBase` to get started """ from abc import ABC, abstractmethod @@ -65,7 +67,9 @@ class TradingUniverse: @dataclass class VaultPortfolio: - """Get the vault asset balances. + """Track assets and balances in a vault. + + - Offchain method to track what assets a vault contains - Takes :py:class:`TradingUniverse` as an input and resolves all relevant balances the vault holds for this trading universe @@ -102,7 +106,10 @@ def get_raw_spot_balances(self, web3: Web3) -> dict[HexAddress, int]: class VaultFlowManager(ABC): - """Manage deposit/redemption events + """Manage deposit/redemption events. + + - For some vault structures, we need to know how much redemptions there are in the queue, so + we can rebalance to have enough cash - Create a replay of flow events that happened for a vault within a specific block range diff --git a/eth_defi/vault/valuation.py b/eth_defi/vault/valuation.py index f31feb46..9dcda5ea 100644 --- a/eth_defi/vault/valuation.py +++ b/eth_defi/vault/valuation.py @@ -360,11 +360,62 @@ def get_path_combinations( class NetAssetValueCalculator: """Calculate valuation of all vault spot assets, assuming we would sell them on Uniswap market sell or similar. - - Query valuations using onchain data / direct quoter smart contracts + - Query valuations using *only* onchain data / direct quoter smart contracts - Price impact and fees included - Pack more RPC punch by using Multicall library + + - Bruteforces all possible route combinations + + .. note :: + + Early prototype code. + + Example: + + .. code-block:: + + vault = lagoon_vault + + universe = TradingUniverse( + spot_token_addresses={ + base_weth.address, + base_usdc.address, + base_dino.address, + } + ) + latest_block = get_almost_latest_block_number(web3) + portfolio = vault.fetch_portfolio(universe, latest_block) + assert portfolio.get_position_count() == 3 + + uniswap_v2_quoter_v2 = UniswapV2Router02Quoter(uniswap_v2.router) + + nav_calculator = NetAssetValueCalculator( + web3, + denomination_token=base_usdc, + intermediary_tokens={base_weth.address}, # Allow DINO->WETH->USDC + quoters={uniswap_v2_quoter_v2}, + debug=True, + ) + + routes = nav_calculator.create_route_diagnostics(portfolio) + + print(routes) + + Outputs: + + .. code-block:: text + + # Routes and their sell values: + + Asset Address Balance Router Works Value + Path + USDC USDC 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 0.35 yes 0.35 + WETH -> USDC WETH 0x4200000000000000000000000000000000000006 0.000000 UniswapV2Router02Quoter yes 0.00 + DINO -> USDC DINO 0x85E90a5430AF45776548ADB82eE4cD9E33B08077 547942.000069 UniswapV2Router02Quoter no - + DINO -> WETH -> USDC DINO 0x85E90a5430AF45776548ADB82eE4cD9E33B08077 547942.000069 UniswapV2Router02Quoter yes 36.69 + """ def __init__( diff --git a/tests/lagoon/test_lagoon_valuation.py b/tests/lagoon/test_lagoon_valuation.py index 6969eefc..e8058ba9 100644 --- a/tests/lagoon/test_lagoon_valuation.py +++ b/tests/lagoon/test_lagoon_valuation.py @@ -1,5 +1,5 @@ """NAV calcualtion and valuation commitee tests.""" -import time + from decimal import Decimal import pytest @@ -8,7 +8,6 @@ from safe_eth.eth.constants import NULL_ADDRESS from web3 import Web3 -from eth_defi.confirmation import wait_transactions_to_complete from eth_defi.lagoon.vault import LagoonVault from eth_defi.provider.broken_provider import get_almost_latest_block_number from eth_defi.safe.trace import assert_execute_module_success @@ -215,7 +214,11 @@ def test_lagoon_post_valuation( ): """Update vault NAV. - To debug the multisig settle tx: + - Value vault portfolio + + - Post NAV update using Roles multisig hack + + - Read back the share price .. code-block:: shell