ipor-fusion 4.2.0.dev16__tar.gz → 4.2.0.dev20__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/PKG-INFO +1 -1
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/examples/advanced_compound_v3_institutional_usdc_ethereum.py +10 -2
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/pyproject.toml +1 -1
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/readers/lending_health.py +16 -6
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/validation.py +3 -2
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_cli_helpers.py +28 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_cli_lending_health.py +125 -1
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_mcp_models.py +31 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/.claude-plugin/marketplace.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/.claude-plugin/plugin.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/.env.example +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/.gemini/settings.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/.git-blame-ignore-revs +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/.github/workflows/cd.yml +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/.github/workflows/ci.yml +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/.github/workflows/commit-lint.yml +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/.github/workflows/notify-slack.yml +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/.github/workflows/python-build.yml +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/.github/workflows/python-publish.yml +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/.github/workflows/release.yml +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/.github/workflows/report-slack.yml +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/.gitignore +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/.mcp.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/.pre-commit-config.yaml +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/.python-version +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/AGENTS.md +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/CHANGELOG.md +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/CLAUDE.md +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/CODEOWNERS +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/LICENSE +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/MIGRATION_4.md +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/README.md +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/build.sh +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/examples/CONTRIBUTING.md +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/examples/README.md +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/examples/advanced_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/examples/advanced_euler_v2_looping_arbitrum.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/examples/external_state_margin_leg_base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/examples/hypercore_vault_official_deployment_hyperevm.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/examples/simple_aave_v3_supply_base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/pytest.ini +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/scripts/commit-check.sh +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/scripts/fusion_error_signatures.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/skills/ipor-deploy-vault/SKILL.md +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/__init__.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/about.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/cache.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/chains.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/cli/__init__.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/cli/address_cmd.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/cli/changelog_cmd.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/cli/config_cmd.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/cli/config_store.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/cli/fuse_cmd.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/cli/main.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/cli/market_cmd.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/cli/options.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/cli/oracle_mapping_view.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/cli/preflight_cmd.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/cli/vault_cmd.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/cli/vault_health.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/cli/vault_info_view.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/cli/vault_markets_view.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/cli/vault_rendering.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/config/__init__.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/config/roles.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/__init__.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/access.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/address.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/context.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/context_manager.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/contract.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/erc20.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/external_state_executor.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/fee_manager.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/fuse.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/fuse_action.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/fuse_decoding.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/fusion_factory.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/logs.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/multicall.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/oracle.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/plasma_vault.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/rewards_manager.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/simulation.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/simulation_result.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/withdraw_manager.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/__init__.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/ccip/__init__.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/ccip/chainlink.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/ccip/codec.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/ccip/contracts.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/ccip/events.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/ccip/indexer.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/ccip/lane.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/ccip/quote.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/ccip/transport.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/contracts.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/discovery.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/errors.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/fuses/__init__.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/fuses/base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/fuses/ccip.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/fuses/stargate.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/lane.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/logs.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/messages.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/simulation.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/stargate/__init__.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/stargate/contracts.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/stargate/lane.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/stargate/layerzero.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/stargate/transport.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/transport.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/dependency_graph.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/entry_cli.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/entry_mcp.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/errors.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/explorer.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/field_docs.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fuse_whitelist.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fuses/__init__.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fuses/aave_v3.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fuses/async_action.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fuses/base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fuses/compound_v3.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fuses/erc4626.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fuses/euler_v2.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fuses/events.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fuses/external_state.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fuses/external_state_event_decoding.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fuses/fluid_instadapp.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fuses/gearbox_v3.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fuses/hypercore.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fuses/hypercore_event_decoding.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fuses/hypercore_pre_hooks.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fuses/merkl.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fuses/morpho.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fuses/ramses_v2.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fuses/uniswap_v3.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fuses/universal.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/fusion_errors.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/guide/__init__.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/guide/architecture.md +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/guide/glossary.md +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/guide/invariants.md +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/guide/quickstart.md +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/hypercore/__init__.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/market_ids.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/market_info.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/mcp/__init__.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/mcp/guide.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/mcp/models.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/mcp/server.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/morpho_api.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/onchain_text.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/preflight.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/py.typed +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/readers/__init__.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/readers/aave_v3.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/readers/aave_v4.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/readers/compound_v3.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/readers/euler_v2.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/readers/hypercore.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/readers/hypercore_outcome.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/readers/morpho.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/readers/oracle_mapping.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/readers/oracle_mapping_nodes.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/readers/oracle_mapping_reader.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/readers/position_manager.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/readers/ramses_v2.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/readers/uniswap_v3.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/readers/unpriceable.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/registry.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/substrates.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/types.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/vault_data.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/vault_erc20.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/vault_info.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/vault_managers.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/vault_positions.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/vault_reads.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/UniswapV3UniversalRouter.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/_addresses.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/_crosschain.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/_crosschain_recovery.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/_euler_v2.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/_event_args.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/_fake_rpc.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/_foundry.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/_golden.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/_guide.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/_hypercore_model.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/_hypercore_shadow.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/_live.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/_multicall.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/_oracle_mapping_fake.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/_simulate.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/_validation.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/addresses.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/conftest.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/constants.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/hypercore_hip3_flow.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/hypercore_market55.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/hypercore_official.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/market_golden/meta_morpho_v1.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/market_golden/meta_morpho_v1.mcp.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/market_golden/meta_morpho_v2.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/market_golden/meta_morpho_v2.mcp.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/market_golden/morpho_api/market.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/market_golden/morpho_api/vault_v1.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/market_golden/morpho_api/vault_v2.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/market_golden/morpho_api/vault_v2_not_found.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/market_golden/morpho_blue.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/market_golden/morpho_blue.mcp.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/market_golden/morpho_blue_api_error.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/market_golden/morpho_blue_api_error.mcp.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/market_golden/morpho_blue_no_api.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/market_golden/morpho_blue_no_api.mcp.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/oracle_mapping_golden/mapping.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/oracle_mapping_golden/mapping.mcp.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/simulate_v1_request.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/vault_info_golden/clean.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/vault_info_golden/clean.mcp.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/vault_info_golden/clean.txt +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/vault_info_golden/deployment_error.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/vault_info_golden/deployment_error.mcp.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/vault_info_golden/deployment_error.txt +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/vault_info_golden/fetched.cli.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/vault_info_golden/fetched.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/vault_info_golden/fetched.mcp.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/vault_info_golden/full.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/vault_info_golden/full.mcp.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/vault_info_golden/full.txt +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/vault_info_golden/rich.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/vault_info_golden/rich.mcp.json +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/fixtures/vault_info_golden/rich.txt +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_about.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_access_manager.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_addresses_helper.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_cache.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_ccip_read_disabled.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_chains.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_cli_address.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_cli_changelog.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_cli_commands.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_cli_config_store.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_cli_hypercore.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_cli_market_golden.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_cli_market_morpho_blue.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_cli_mcp_fuse_whitelist.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_cli_mcp_parity.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_cli_oracle_mapping.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_cli_oracle_mapping_golden.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_cli_pending_requests_scan.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_cli_preflight.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_cli_role_accounts.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_cli_vault_info_golden.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_cli_vault_predates_getters.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_cli_vault_validate.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_contract_call.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_contract_encoder.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_crosschain_ccip_events.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_crosschain_ccip_indexer.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_crosschain_ccip_quote.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_crosschain_chainlink.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_crosschain_contracts.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_crosschain_encoding.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_crosschain_errors.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_crosschain_lane.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_crosschain_layering.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_crosschain_transport.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_docs_typing.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_erc20.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_error_hierarchy.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_examples_compound_v3_ethereum.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_examples_crosschain.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_examples_euler_looping_arbitrum.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_examples_hypercore_hyperevm.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_examples_vaults.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_explorer.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_external_state_events.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_external_state_executor.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_fee_manager.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_fuse_decoding.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_fuse_encoding.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_fuse_whitelist.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_fusion_errors.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_fusion_instance.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_governance_wrappers.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_guide.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_hypercore_deployment.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_hypercore_events.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_hypercore_flow.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_hypercore_live.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_hypercore_outcome.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_hypercore_pre_hooks.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_hypercore_readers.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_hypercore_simulation.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_lending_health_compound_v3_onchain.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_logs.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_mcp_address.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_mcp_hypercore.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_mcp_preflight.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_mcp_server.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_mcp_vault_validate.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_multicall.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_onchain_text.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_oracle.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_oracle_mapping.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_plasma_vault.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_preflight.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_public_api.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_public_type_reachability.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_reader_encoding.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_registry.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_revert_decoding.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_rewards_manager.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_roles.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_sdk_layering.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_borrow_aave_v3_mainnet.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_claim_merkl_wrapper_base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_claim_morpho_rewards.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_compound_v3_institutional_usdc.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_crosschain_hyperevm.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_euler_v2_batch_base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_euler_v2_swap_deploy_base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_euler_v2_swap_reconfigure_base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_euler_v2_swap_registry_base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_examples_arbitrum.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_examples_base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_examples_crosschain.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_examples_ethereum.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_examples_hyperevm.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_external_state_executor_base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_fusion_factory_clone_base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_looping_aave_v3_base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_looping_morpho_blue_base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_morpho_blue.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_pilot_v3.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_pilot_v4_uniswap.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_pilot_v5_ramses.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_pilot_v5_scheduled.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_plasma_vault_setters_base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_preflight_base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_readers_integration.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_release_funds.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_swap_on_base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_timelock_base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulate_vault_from_scratch_base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulation_errors.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_simulation_observation.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_solidity_compiler.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_solidity_mirrors.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_substrates.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_types_and_events.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_unpriceable_tokens.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_validation.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_vault_data_block.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_vault_dep_graph.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_vault_info_fetched_golden.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_vault_info_onchain_base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_vault_info_onchain_base_no_withdraw_manager.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_vault_reconciliation_onchain_base.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_vault_simulator_blocks.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_web3_context.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/test_withdraw_manager.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/typed_client/consumer.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/tests/typed_client/rejected.py +0 -0
- {ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/uv.lock +0 -0
|
@@ -260,7 +260,11 @@ def run_simulation(web3: Web3) -> SimulationResult:
|
|
|
260
260
|
)
|
|
261
261
|
factory = FusionFactory(ETHEREUM_FUSION_FACTORY)
|
|
262
262
|
|
|
263
|
-
#
|
|
263
|
+
# SIMULATION ONLY: the pinned replay has no other clone between this
|
|
264
|
+
# preview and the simulated one, so the predicted stack is the created one.
|
|
265
|
+
# Live, another clone in between moves it: send the clone first, take the
|
|
266
|
+
# stack from factory.decode_clone_receipt(receipt) and build the
|
|
267
|
+
# configuration and operation calldata from those addresses.
|
|
264
268
|
preview = factory.clone(**clone_args()).call(ctx)
|
|
265
269
|
log.info("predicted vault=%s", preview.plasma_vault)
|
|
266
270
|
|
|
@@ -278,6 +282,9 @@ def run_simulation(web3: Web3) -> SimulationResult:
|
|
|
278
282
|
# (or X.calldata to a multisig / timelock).
|
|
279
283
|
# - sim.execute([action]) -> plasma_vault.execute([action]).send(ctx) by the alpha.
|
|
280
284
|
# - read = sim.observe(X), then read.value -> X.call(ctx), a plain read.
|
|
285
|
+
# SIMULATION ONLY (per-call senders): `from_` lets one process act as every
|
|
286
|
+
# actor, because in simulation they are addresses with no keys. In production
|
|
287
|
+
# they are separate signers on separate systems.
|
|
281
288
|
sim = VaultSimulator(
|
|
282
289
|
web3=web3, vault=vault_address, alpha=ALPHA, block=PINNED_BLOCK
|
|
283
290
|
)
|
|
@@ -311,7 +318,8 @@ def run_simulation(web3: Web3) -> SimulationResult:
|
|
|
311
318
|
# UPDATE_MARKETS_BALANCES}, so OWNER must self-grant ATOMIST before it can
|
|
312
319
|
# grant the rest. Each grant uses Period(0) (no execution delay) to keep the
|
|
313
320
|
# simulation legible; production governance often puts a nonzero delay -- a
|
|
314
|
-
# timelock -- on the sensitive roles.
|
|
321
|
+
# timelock -- on the sensitive roles. ALPHA must stay a separate address from
|
|
322
|
+
# OWNER in production: a compromised alpha key must not equal governance.
|
|
315
323
|
for role, holder in (
|
|
316
324
|
(Roles.ATOMIST_ROLE, OWNER),
|
|
317
325
|
(Roles.FUSE_MANAGER_ROLE, OWNER),
|
{ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/readers/lending_health.py
RENAMED
|
@@ -298,6 +298,8 @@ def _compute_morpho_market_health(
|
|
|
298
298
|
position.borrow_shares, market.total_borrow_assets, market.total_borrow_shares
|
|
299
299
|
)
|
|
300
300
|
|
|
301
|
+
# Morpho's own check sees a zero borrow limit here, so the position can be
|
|
302
|
+
# liquidated: a known risk, of which only the LTV has no value.
|
|
301
303
|
if position.collateral == 0 or oracle_price == 0:
|
|
302
304
|
return LendingMarketHealth(
|
|
303
305
|
protocol="morpho",
|
|
@@ -305,7 +307,7 @@ def _compute_morpho_market_health(
|
|
|
305
307
|
market_name=market_name,
|
|
306
308
|
current_ltv=None,
|
|
307
309
|
max_ltv=params.lltv / WAD,
|
|
308
|
-
health_factor=
|
|
310
|
+
health_factor=0.0,
|
|
309
311
|
total_collateral_usd=None,
|
|
310
312
|
total_debt_usd=None,
|
|
311
313
|
ltv_usage_percent=None,
|
|
@@ -322,9 +324,9 @@ def _compute_morpho_market_health(
|
|
|
322
324
|
max_ltv = params.lltv / WAD
|
|
323
325
|
|
|
324
326
|
# health_factor = max_borrow / borrowed
|
|
325
|
-
#
|
|
327
|
+
# Two floors, as in Morpho's _isHealthy.
|
|
326
328
|
max_borrow = (
|
|
327
|
-
position.collateral * oracle_price * params.lltv //
|
|
329
|
+
position.collateral * oracle_price // ORACLE_PRICE_SCALE * params.lltv // WAD
|
|
328
330
|
)
|
|
329
331
|
health_factor = max_borrow / borrowed if borrowed > 0 else None
|
|
330
332
|
|
|
@@ -336,7 +338,7 @@ def _compute_morpho_market_health(
|
|
|
336
338
|
market_name=market_name,
|
|
337
339
|
current_ltv=round(current_ltv, 6),
|
|
338
340
|
max_ltv=round(max_ltv, 6),
|
|
339
|
-
health_factor=round(health_factor, 4) if health_factor else None,
|
|
341
|
+
health_factor=round(health_factor, 4) if health_factor is not None else None,
|
|
340
342
|
total_collateral_usd=None,
|
|
341
343
|
total_debt_usd=None,
|
|
342
344
|
ltv_usage_percent=round(ltv_usage, 2) if ltv_usage is not None else None,
|
|
@@ -574,9 +576,17 @@ def _compute_euler_v2_account_health(
|
|
|
574
576
|
if ltv > 0
|
|
575
577
|
)
|
|
576
578
|
liability = liquidity.liability_value
|
|
579
|
+
# The vault owes, yet its oracle values that at nothing: no ratio means anything.
|
|
580
|
+
if liability == 0:
|
|
581
|
+
return UnreadableLendingMarket(
|
|
582
|
+
protocol="euler_v2",
|
|
583
|
+
market_id=ipor_market_id,
|
|
584
|
+
market_name=market_name,
|
|
585
|
+
reason="debt is valued at zero",
|
|
586
|
+
substrate_id=sub_account,
|
|
587
|
+
)
|
|
577
588
|
current_ltv = liability / collateral if collateral > 0 else None
|
|
578
589
|
max_ltv = adjusted / collateral if collateral > 0 else 0.0
|
|
579
|
-
health_factor = adjusted / liability if liability > 0 else None
|
|
580
590
|
ltv_usage = liability / adjusted * 100 if adjusted > 0 else None
|
|
581
591
|
# The USD unit of account prices in 18 decimals; other units are not USD.
|
|
582
592
|
in_usd = unit_read.value == EULER_USD_UNIT_OF_ACCOUNT
|
|
@@ -587,7 +597,7 @@ def _compute_euler_v2_account_health(
|
|
|
587
597
|
market_name=market_name,
|
|
588
598
|
current_ltv=round(current_ltv, 6) if current_ltv is not None else None,
|
|
589
599
|
max_ltv=round(max_ltv, 6),
|
|
590
|
-
health_factor=round(
|
|
600
|
+
health_factor=round(adjusted / liability, 4),
|
|
591
601
|
total_collateral_usd=round(collateral / WAD, 2) if in_usd else None,
|
|
592
602
|
total_debt_usd=round(liability / WAD, 2) if in_usd else None,
|
|
593
603
|
ltv_usage_percent=round(ltv_usage, 2) if ltv_usage is not None else None,
|
|
@@ -691,8 +691,9 @@ def _lending_health_findings(state: VaultState) -> list[Finding]:
|
|
|
691
691
|
for u in health.unreadable
|
|
692
692
|
]
|
|
693
693
|
for market in health.markets:
|
|
694
|
-
# A
|
|
695
|
-
|
|
694
|
+
# A row with neither value gives no risk metric to judge. Debt against a zero
|
|
695
|
+
# limit has no usage but a critical health factor.
|
|
696
|
+
if market.ltv_usage_percent is None and market.health_factor is None:
|
|
696
697
|
continue
|
|
697
698
|
ltv = f"{market.current_ltv:.4f}" if market.current_ltv is not None else "?"
|
|
698
699
|
usage = (
|
|
@@ -1532,6 +1532,18 @@ class TestPrintLendingHealth:
|
|
|
1532
1532
|
_print_lending_health(data)
|
|
1533
1533
|
assert "N/A" in capsys.readouterr().out
|
|
1534
1534
|
|
|
1535
|
+
def test_debt_without_ltv_is_not_shown_as_no_debt(self, capsys):
|
|
1536
|
+
m = _make_lending_market(
|
|
1537
|
+
current_ltv=None, health_factor=0.0, ltv_usage_percent=None
|
|
1538
|
+
)
|
|
1539
|
+
m.protocol = "aave_v3"
|
|
1540
|
+
m.market_id = MarketId(1)
|
|
1541
|
+
data = _make_data(lending_health=VaultLendingHealth(markets=[m]))
|
|
1542
|
+
_print_lending_health(data)
|
|
1543
|
+
out = capsys.readouterr().out
|
|
1544
|
+
assert "CRITICAL" in out
|
|
1545
|
+
assert "no debt" not in out
|
|
1546
|
+
|
|
1535
1547
|
|
|
1536
1548
|
class TestHealthCheckLendingIntegration:
|
|
1537
1549
|
def test_lending_ok_in_health_check(self, capsys):
|
|
@@ -1556,6 +1568,22 @@ class TestHealthCheckLendingIntegration:
|
|
|
1556
1568
|
assert "CRITICAL" in captured.out
|
|
1557
1569
|
assert "NEAR LIQUIDATION" in captured.out
|
|
1558
1570
|
|
|
1571
|
+
def test_debt_without_ltv_is_critical_not_ok(self, capsys):
|
|
1572
|
+
m = _make_lending_market(
|
|
1573
|
+
current_ltv=None, ltv_usage_percent=None, health_factor=0.0
|
|
1574
|
+
)
|
|
1575
|
+
data = _make_data(lending_health=VaultLendingHealth(markets=[m]))
|
|
1576
|
+
_print_health_check(validate(data, 100 * 10**18))
|
|
1577
|
+
captured = capsys.readouterr()
|
|
1578
|
+
assert "CRITICAL" in captured.out
|
|
1579
|
+
assert "NEAR LIQUIDATION" in captured.out
|
|
1580
|
+
|
|
1581
|
+
def test_lending_warning_without_usage_is_reported(self, capsys):
|
|
1582
|
+
m = _make_lending_market(ltv_usage_percent=None, health_factor=1.08)
|
|
1583
|
+
data = _make_data(lending_health=VaultLendingHealth(markets=[m]))
|
|
1584
|
+
_print_health_check(validate(data, 100 * 10**18))
|
|
1585
|
+
assert "approaching liquidation" in capsys.readouterr().out
|
|
1586
|
+
|
|
1559
1587
|
def test_lending_none_usage_skipped(self, capsys):
|
|
1560
1588
|
m = _make_lending_market(ltv_usage_percent=None, health_factor=None)
|
|
1561
1589
|
data = _make_data(lending_health=VaultLendingHealth(markets=[m]))
|
|
@@ -419,6 +419,115 @@ class TestComputeMorphoMarketHealth:
|
|
|
419
419
|
assert isinstance(result, LendingMarketHealth)
|
|
420
420
|
assert result.current_ltv is None
|
|
421
421
|
assert result.ltv_usage_percent is None
|
|
422
|
+
assert result.health_factor == 0.0
|
|
423
|
+
assert result.is_critical
|
|
424
|
+
|
|
425
|
+
def test_zero_oracle_price_with_debt_is_critical(self):
|
|
426
|
+
reader, ctx = _make_morpho_reader()
|
|
427
|
+
|
|
428
|
+
ctx.call.side_effect = sequenced(
|
|
429
|
+
[
|
|
430
|
+
encode(["uint256", "uint128", "uint128"], [0, 100, 1000]),
|
|
431
|
+
encode(
|
|
432
|
+
["uint128", "uint128", "uint128", "uint128", "uint128", "uint128"],
|
|
433
|
+
[2000, 2000, 1000, 1000, 1700000000, 0],
|
|
434
|
+
),
|
|
435
|
+
encode(
|
|
436
|
+
["address", "address", "address", "address", "uint256"],
|
|
437
|
+
[TOKEN_A, TOKEN_B, ORACLE_ADDR, IRM_ADDR, 860000000000000000],
|
|
438
|
+
),
|
|
439
|
+
encode(["uint256"], [0]),
|
|
440
|
+
]
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
result = _compute_morpho_market_health(
|
|
444
|
+
ctx, reader, MORPHO_MARKET_ID, VAULT_ADDR, 14, "MORPHO"
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
assert isinstance(result, LendingMarketHealth)
|
|
448
|
+
assert result.current_ltv is None
|
|
449
|
+
assert result.health_factor == 0.0
|
|
450
|
+
assert result.is_critical
|
|
451
|
+
|
|
452
|
+
def test_dust_collateral_flooring_the_limit_to_zero_is_critical(self):
|
|
453
|
+
reader, ctx = _make_morpho_reader()
|
|
454
|
+
|
|
455
|
+
ctx.call.side_effect = sequenced(
|
|
456
|
+
[
|
|
457
|
+
encode(["uint256", "uint128", "uint128"], [0, 500 * 10**6, 1]),
|
|
458
|
+
encode(
|
|
459
|
+
["uint128", "uint128", "uint128", "uint128", "uint128", "uint128"],
|
|
460
|
+
[2000, 2000 * 10**6, 1000, 1000 * 10**6, 1700000000, 0],
|
|
461
|
+
),
|
|
462
|
+
encode(
|
|
463
|
+
["address", "address", "address", "address", "uint256"],
|
|
464
|
+
[TOKEN_A, TOKEN_B, ORACLE_ADDR, IRM_ADDR, 860000000000000000],
|
|
465
|
+
),
|
|
466
|
+
encode(["uint256"], [ORACLE_PRICE_SCALE]),
|
|
467
|
+
]
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
result = _compute_morpho_market_health(
|
|
471
|
+
ctx, reader, MORPHO_MARKET_ID, VAULT_ADDR, 14, "MORPHO"
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
assert isinstance(result, LendingMarketHealth)
|
|
475
|
+
assert result.current_ltv is not None
|
|
476
|
+
assert result.health_factor == 0.0
|
|
477
|
+
assert result.is_critical
|
|
478
|
+
|
|
479
|
+
def test_limit_floors_twice_as_morpho_does(self):
|
|
480
|
+
# 2 * 0.9 floors to 1, then 1 * 0.86 floors to 0; one combined floor gives 1.
|
|
481
|
+
reader, ctx = _make_morpho_reader()
|
|
482
|
+
|
|
483
|
+
ctx.call.side_effect = sequenced(
|
|
484
|
+
[
|
|
485
|
+
encode(["uint256", "uint128", "uint128"], [0, 10**6, 2]),
|
|
486
|
+
encode(
|
|
487
|
+
["uint128", "uint128", "uint128", "uint128", "uint128", "uint128"],
|
|
488
|
+
[2000, 2000 * 10**6, 1000, 1000 * 10**6, 1700000000, 0],
|
|
489
|
+
),
|
|
490
|
+
encode(
|
|
491
|
+
["address", "address", "address", "address", "uint256"],
|
|
492
|
+
[TOKEN_A, TOKEN_B, ORACLE_ADDR, IRM_ADDR, 860000000000000000],
|
|
493
|
+
),
|
|
494
|
+
encode(["uint256"], [9 * ORACLE_PRICE_SCALE // 10]),
|
|
495
|
+
]
|
|
496
|
+
)
|
|
497
|
+
|
|
498
|
+
result = _compute_morpho_market_health(
|
|
499
|
+
ctx, reader, MORPHO_MARKET_ID, VAULT_ADDR, 14, "MORPHO"
|
|
500
|
+
)
|
|
501
|
+
|
|
502
|
+
assert isinstance(result, LendingMarketHealth)
|
|
503
|
+
assert result.health_factor == 0.0
|
|
504
|
+
|
|
505
|
+
def test_debt_on_a_zero_lltv_market_is_critical_without_usage(self):
|
|
506
|
+
reader, ctx = _make_morpho_reader()
|
|
507
|
+
|
|
508
|
+
ctx.call.side_effect = sequenced(
|
|
509
|
+
[
|
|
510
|
+
encode(["uint256", "uint128", "uint128"], [0, 500 * 10**6, 1000]),
|
|
511
|
+
encode(
|
|
512
|
+
["uint128", "uint128", "uint128", "uint128", "uint128", "uint128"],
|
|
513
|
+
[2000, 2000 * 10**6, 1000, 1000 * 10**6, 1700000000, 0],
|
|
514
|
+
),
|
|
515
|
+
encode(
|
|
516
|
+
["address", "address", "address", "address", "uint256"],
|
|
517
|
+
[TOKEN_A, TOKEN_B, ORACLE_ADDR, IRM_ADDR, 0],
|
|
518
|
+
),
|
|
519
|
+
encode(["uint256"], [ORACLE_PRICE_SCALE]),
|
|
520
|
+
]
|
|
521
|
+
)
|
|
522
|
+
|
|
523
|
+
result = _compute_morpho_market_health(
|
|
524
|
+
ctx, reader, MORPHO_MARKET_ID, VAULT_ADDR, 14, "MORPHO"
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
assert isinstance(result, LendingMarketHealth)
|
|
528
|
+
assert result.ltv_usage_percent is None
|
|
529
|
+
assert result.health_factor == 0.0
|
|
530
|
+
assert result.is_critical
|
|
422
531
|
|
|
423
532
|
def test_position_read_failure_is_unreadable(self):
|
|
424
533
|
reader, ctx = _make_morpho_reader()
|
|
@@ -1162,6 +1271,8 @@ def _euler_ctx(
|
|
|
1162
1271
|
debt: int = EULER_DEBT,
|
|
1163
1272
|
unit: str = EULER_USD_UNIT_OF_ACCOUNT,
|
|
1164
1273
|
liquidity_reverts: bool = False,
|
|
1274
|
+
adjusted: int = EULER_ADJUSTED_COLLATERAL,
|
|
1275
|
+
liability: int = EULER_LIABILITY,
|
|
1165
1276
|
) -> MagicMock:
|
|
1166
1277
|
"""Answer the TESS sub-account's reads; only the borrow vault is its controller."""
|
|
1167
1278
|
|
|
@@ -1177,7 +1288,7 @@ def _euler_ctx(
|
|
|
1177
1288
|
raise ContractLogicError("E_NoLiability")
|
|
1178
1289
|
return encode(
|
|
1179
1290
|
["address[]", "uint256[]", "uint256"],
|
|
1180
|
-
[[EULER_COLLATERAL], [
|
|
1291
|
+
[[EULER_COLLATERAL], [adjusted], liability],
|
|
1181
1292
|
)
|
|
1182
1293
|
if selector == _SELECTOR_UNIT_OF_ACCOUNT:
|
|
1183
1294
|
return encode(["address"], [unit])
|
|
@@ -1241,6 +1352,19 @@ class TestEulerV2Health:
|
|
|
1241
1352
|
assert result.total_collateral_usd is None
|
|
1242
1353
|
assert result.total_debt_usd is None
|
|
1243
1354
|
|
|
1355
|
+
@pytest.mark.parametrize("adjusted", [0, EULER_ADJUSTED_COLLATERAL])
|
|
1356
|
+
def test_debt_valued_at_zero_is_unreadable_not_no_debt(self, adjusted):
|
|
1357
|
+
result = _compute_euler_v2_account_health(
|
|
1358
|
+
_euler_ctx(adjusted=adjusted, liability=0),
|
|
1359
|
+
EULER_ACCOUNT,
|
|
1360
|
+
MarketId(11),
|
|
1361
|
+
"EULER_V2",
|
|
1362
|
+
)
|
|
1363
|
+
|
|
1364
|
+
assert isinstance(result, UnreadableLendingMarket)
|
|
1365
|
+
assert result.substrate_id == EULER_SUB_ACCOUNT
|
|
1366
|
+
assert result.reason == "debt is valued at zero"
|
|
1367
|
+
|
|
1244
1368
|
def test_failed_debt_read_is_unreadable(self):
|
|
1245
1369
|
ctx = MagicMock()
|
|
1246
1370
|
ctx.call.side_effect = Web3RPCError("rpc down")
|
|
@@ -33,6 +33,7 @@ from ipor_fusion import (
|
|
|
33
33
|
ExecutePreflightJson,
|
|
34
34
|
Fee,
|
|
35
35
|
FuseAddress,
|
|
36
|
+
IporFusionMarkets,
|
|
36
37
|
MarketId,
|
|
37
38
|
MetaMorphoV1Json,
|
|
38
39
|
MetaMorphoV2Json,
|
|
@@ -72,6 +73,12 @@ from ipor_fusion.mcp.models import (
|
|
|
72
73
|
VaultValidationResponse,
|
|
73
74
|
WithdrawManagerDetails,
|
|
74
75
|
)
|
|
76
|
+
from ipor_fusion.readers.lending_health import (
|
|
77
|
+
LendingMarketHealth as LendingMarketHealthRow,
|
|
78
|
+
)
|
|
79
|
+
from ipor_fusion.readers.lending_health import (
|
|
80
|
+
VaultLendingHealth,
|
|
81
|
+
)
|
|
75
82
|
from ipor_fusion.readers.oracle_mapping import (
|
|
76
83
|
OracleAsset,
|
|
77
84
|
OracleMapping,
|
|
@@ -79,6 +86,7 @@ from ipor_fusion.readers.oracle_mapping import (
|
|
|
79
86
|
OraclePrice,
|
|
80
87
|
)
|
|
81
88
|
from ipor_fusion.types import Period, RoleId
|
|
89
|
+
from ipor_fusion.vault_info import _lending_health_json
|
|
82
90
|
|
|
83
91
|
|
|
84
92
|
def _amount(raw: int = 0, formatted: str = "0") -> AmountJson:
|
|
@@ -1307,3 +1315,26 @@ class TestModelsImportGraph:
|
|
|
1307
1315
|
}
|
|
1308
1316
|
)
|
|
1309
1317
|
assert offending == []
|
|
1318
|
+
|
|
1319
|
+
|
|
1320
|
+
def test_debt_without_ltv_passes_through_the_published_model() -> None:
|
|
1321
|
+
row = LendingMarketHealthRow(
|
|
1322
|
+
protocol="morpho",
|
|
1323
|
+
market_id=IporFusionMarkets.MORPHO,
|
|
1324
|
+
market_name="MORPHO",
|
|
1325
|
+
current_ltv=None,
|
|
1326
|
+
max_ltv=0.86,
|
|
1327
|
+
health_factor=0.0,
|
|
1328
|
+
total_collateral_usd=None,
|
|
1329
|
+
total_debt_usd=None,
|
|
1330
|
+
ltv_usage_percent=None,
|
|
1331
|
+
substrate_id="0x" + "ab" * 32,
|
|
1332
|
+
)
|
|
1333
|
+
|
|
1334
|
+
document = _lending_health_json(VaultLendingHealth(markets=[row]))
|
|
1335
|
+
model = mcp_models.LendingHealth.model_validate(document)
|
|
1336
|
+
|
|
1337
|
+
market = model.markets[0]
|
|
1338
|
+
assert market.health_factor == 0.0
|
|
1339
|
+
assert market.current_ltv is None
|
|
1340
|
+
assert market.is_critical
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/examples/advanced_euler_v2_credit_market_base.py
RENAMED
|
File without changes
|
{ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/examples/advanced_euler_v2_looping_arbitrum.py
RENAMED
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/examples/external_state_margin_leg_base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/cli/oracle_mapping_view.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/cli/vault_markets_view.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/external_state_executor.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/simulation_result.py
RENAMED
|
File without changes
|
{ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/core/withdraw_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/ccip/__init__.py
RENAMED
|
File without changes
|
{ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/ccip/chainlink.py
RENAMED
|
File without changes
|
{ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/ccip/codec.py
RENAMED
|
File without changes
|
{ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/ccip/contracts.py
RENAMED
|
File without changes
|
{ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/ccip/events.py
RENAMED
|
File without changes
|
{ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/ccip/indexer.py
RENAMED
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/ccip/quote.py
RENAMED
|
File without changes
|
{ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/ccip/transport.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/fuses/__init__.py
RENAMED
|
File without changes
|
{ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/fuses/base.py
RENAMED
|
File without changes
|
{ipor_fusion-4.2.0.dev16 → ipor_fusion-4.2.0.dev20}/src/ipor_fusion/crosschain/fuses/ccip.py
RENAMED
|
File without changes
|