ipor-fusion 4.0.0.dev116__tar.gz → 4.0.0.dev120__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.0.0.dev116 → ipor_fusion-4.0.0.dev120}/AGENTS.md +3 -1
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/MIGRATION_4.md +27 -10
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/PKG-INFO +1 -1
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/pyproject.toml +1 -1
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/cli/vault_cmd.py +3 -1
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/cli/vault_info_view.py +1 -1
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/core/access.py +2 -4
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/core/context.py +22 -2
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/core/external_state_executor.py +9 -10
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/mcp/server.py +1 -1
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/readers/hypercore.py +14 -14
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/readers/hypercore_outcome.py +12 -12
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/readers/lending_health.py +5 -5
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/readers/oracle_mapping.py +7 -7
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/validation.py +11 -6
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/vault_data.py +38 -29
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/vault_erc20.py +59 -34
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/vault_info.py +1 -1
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_cli_helpers.py +25 -17
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_cli_lending_health.py +4 -4
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_cli_vault_info_golden.py +19 -18
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_cli_vault_predates_getters.py +3 -3
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_cli_vault_validate.py +2 -2
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_mcp_vault_validate.py +2 -2
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_validation.py +85 -13
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_web3_context.py +98 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/.claude-plugin/marketplace.json +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/.claude-plugin/plugin.json +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/.env.example +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/.gemini/settings.json +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/.git-blame-ignore-revs +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/.github/workflows/cd.yml +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/.github/workflows/ci.yml +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/.github/workflows/commit-lint.yml +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/.github/workflows/notify-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/.github/workflows/python-build.yml +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/.github/workflows/python-publish.yml +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/.github/workflows/release.yml +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/.github/workflows/report-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/.gitignore +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/.pre-commit-config.yaml +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/.python-version +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/CHANGELOG.md +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/CLAUDE.md +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/CODEOWNERS +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/LICENSE +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/README.md +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/build.sh +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/examples/CONTRIBUTING.md +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/examples/README.md +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/examples/advanced_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/examples/advanced_euler_v2_looping_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/examples/composed_hypercore_flow_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/examples/external_state_margin_leg_base.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/examples/simple_aave_v3_supply_base.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/pytest.ini +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/scripts/commit-check.sh +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/scripts/crosschain_readiness.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/skills/ipor-deploy-vault/SKILL.md +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/about.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/cache.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/chains.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/cli/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/cli/changelog_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/cli/config_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/cli/config_store.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/cli/main.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/cli/market_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/cli/options.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/cli/oracle_mapping_view.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/cli/vault_health.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/cli/vault_markets_view.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/cli/vault_rendering.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/config/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/config/roles.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/core/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/core/address.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/core/contract.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/core/erc20.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/core/fee_manager.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/core/fuse.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/core/fuse_action.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/core/fusion_factory.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/core/logs.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/core/multicall.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/core/oracle.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/core/plasma_vault.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/core/rewards_manager.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/core/simulation.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/core/withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/ccip/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/ccip/chainlink.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/ccip/codec.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/ccip/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/ccip/events.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/ccip/indexer.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/ccip/lane.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/ccip/quote.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/ccip/transport.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/discovery.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/errors.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/fuses/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/fuses/base.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/fuses/ccip.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/fuses/stargate.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/lane.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/logs.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/messages.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/simulation.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/stargate/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/stargate/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/stargate/lane.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/stargate/layerzero.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/stargate/transport.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/crosschain/transport.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/dependency_graph.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/entry_cli.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/entry_mcp.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/errors.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/explorer.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/field_docs.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/fuses/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/fuses/aave_v3.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/fuses/async_action.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/fuses/base.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/fuses/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/fuses/erc4626.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/fuses/euler_v2.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/fuses/events.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/fuses/external_state.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/fuses/external_state_events.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/fuses/fluid_instadapp.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/fuses/gearbox_v3.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/fuses/hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/fuses/hypercore_events.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/fuses/merkl.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/fuses/morpho.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/fuses/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/fuses/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/fuses/universal.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/guide/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/guide/architecture.md +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/guide/glossary.md +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/guide/invariants.md +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/guide/quickstart.md +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/market_ids.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/market_info.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/mcp/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/mcp/guide.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/mcp/models.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/morpho_api.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/py.typed +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/readers/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/readers/aave_v3.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/readers/aave_v4.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/readers/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/readers/morpho.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/readers/oracle_mapping_nodes.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/readers/oracle_mapping_reader.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/readers/position_manager.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/readers/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/readers/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/readers/unpriceable.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/substrates.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/types.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/vault_managers.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/vault_positions.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/vault_reads.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/UniswapV3UniversalRouter.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/_crosschain_recovery.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/_euler_v2.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/_foundry.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/_guide.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/_hypercore_model.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/_hypercore_shadow.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/_simulate.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/_validation.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/addresses.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/conftest.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/constants.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/fixtures/hypercore_hip3_flow.json +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/fixtures/hypercore_market55.json +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/fixtures/vault_info_golden/clean.json +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/fixtures/vault_info_golden/clean.txt +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/fixtures/vault_info_golden/rich.json +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/fixtures/vault_info_golden/rich.txt +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_about.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_access_manager.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_cache.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_chains.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_cli_changelog.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_cli_commands.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_cli_config_store.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_cli_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_cli_market_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_cli_oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_cli_pending_requests_scan.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_cli_role_accounts.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_contract_call.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_contract_encoder.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_crosschain_ccip_events.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_crosschain_ccip_indexer.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_crosschain_ccip_quote.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_crosschain_chainlink.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_crosschain_contracts.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_crosschain_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_crosschain_errors.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_crosschain_lane.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_crosschain_layering.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_crosschain_readiness.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_crosschain_readiness_report.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_crosschain_transport.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_erc20.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_error_hierarchy.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_examples_composed_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_examples_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_examples_euler_looping_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_examples_vaults.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_explorer.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_external_state_events.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_external_state_executor.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_fee_manager.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_fuse_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_fusion_instance.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_guide.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_hypercore_deployment.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_hypercore_events.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_hypercore_flow.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_hypercore_live.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_hypercore_outcome.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_hypercore_readers.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_hypercore_simulation.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_logs.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_mcp_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_mcp_models.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_mcp_server.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_oracle.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_plasma_vault.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_public_api.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_reader_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_readiness_selection.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_revert_decoding.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_rewards_manager.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_roles.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_sdk_layering.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_borrow_aave_v3_mainnet.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_claim_merkl_wrapper_base.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_claim_morpho_rewards.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_crosschain_canary.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_crosschain_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_crosschain_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_euler_v2_batch_base.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_euler_v2_swap_deploy_base.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_euler_v2_swap_reconfigure_base.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_euler_v2_swap_registry_base.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_examples_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_examples_base.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_examples_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_external_state_executor_base.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_fusion_factory_clone_base.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_looping_aave_v3_base.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_looping_morpho_blue_base.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_pilot_v3.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_pilot_v4_uniswap.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_pilot_v5_ramses.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_pilot_v5_scheduled.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_plasma_vault_setters_base.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_readers_integration.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_release_funds.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_swap_on_base.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_simulate_vault_from_scratch_base.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_solidity_compiler.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_solidity_mirrors.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_substrates.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_types_and_events.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_unpriceable_tokens.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_vault_dep_graph.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_vault_info_onchain_base.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_vault_info_onchain_base_no_withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_vault_simulator_blocks.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/test_withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/typed_client/consumer.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/tests/typed_client/rejected.py +0 -0
- {ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/uv.lock +0 -0
|
@@ -429,7 +429,9 @@ are not validated.
|
|
|
429
429
|
everything validation and the ``vault info`` document need, so neither reads the
|
|
430
430
|
chain. The chain is `ctx.chain_id`; ``lending=False`` skips lending health, the
|
|
431
431
|
position breakdowns, their prices and the unpriceable check; ``metadata=False``
|
|
432
|
-
|
|
432
|
+
reads no token symbol or decimals at all (`validate_vault`'s default), and
|
|
433
|
+
``metadata=True`` reads them in one cached Multicall3 batch that also names the
|
|
434
|
+
ERC20 holdings. Add a new chain-state input to the snapshot, never a
|
|
433
435
|
read inside a renderer or validator.
|
|
434
436
|
- PlasmaVault serves governance/view functions via `fallback()` delegatecall to
|
|
435
437
|
PlasmaVaultBase, so Etherscan's ABI for the vault address omits callable
|
|
@@ -14,10 +14,11 @@ type-checked or not. In particular, `fetch_market` and
|
|
|
14
14
|
(pyright, mypy, Pylance) also wraps literals and raw values as below. Values the SDK
|
|
15
15
|
returns already carry their type and go back in unwrapped.
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
`USDC_TOKEN_INDEX` and `hip3_action_asset
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
The SDK's own types are importable from `ipor_fusion` (and `ipor_fusion.types`),
|
|
18
|
+
as are `USDC_TOKEN_INDEX` and `hip3_action_asset`. Third-party types are not
|
|
19
|
+
re-exported: `ChecksumAddress` and `HexAddress` come from `eth_typing`, and
|
|
20
|
+
`BlockIdentifier`, `Timestamp` and `TxParams` from `web3.types`. The wrappers label
|
|
21
|
+
values; they do not validate byte widths or address spelling.
|
|
21
22
|
|
|
22
23
|
## Building the types
|
|
23
24
|
|
|
@@ -64,12 +65,15 @@ chain is always the context's:
|
|
|
64
65
|
the vault address (not a `PlasmaVault`) and no `chain_id`. It resolves one block
|
|
65
66
|
(``block``, else a numeric `ctx.default_block`, else the latest) and runs every
|
|
66
67
|
read, log scans included, on `ctx.at_block(block)`; `ctx` is not modified. The old
|
|
67
|
-
``chain_id=0`` switch is ``lending=False``; ``metadata=False``
|
|
68
|
-
|
|
68
|
+
``chain_id=0`` switch is ``lending=False``; ``metadata=False`` reads no token
|
|
69
|
+
symbol or decimals (the ERC20 holdings' symbols are then `"?"`), and with
|
|
70
|
+
``metadata=True`` the holdings are named by the same cached, batched read as
|
|
71
|
+
`token_symbols`. `VaultData` gains `vault`, `chain_id`, `market_balances`, `erc20`,
|
|
69
72
|
`token_symbols` and `token_decimals`; `WithdrawManagerData` gains
|
|
70
73
|
`shares_to_release_assets` and `pending_request_assets`.
|
|
71
|
-
- `validate_vault(ctx, vault, *, block=None)` fetches
|
|
72
|
-
validates; it no longer takes ``resolve_symbol``.
|
|
74
|
+
- `validate_vault(ctx, vault, *, block=None, metadata=False)` fetches (by default
|
|
75
|
+
without token metadata) and validates; it no longer takes ``resolve_symbol``.
|
|
76
|
+
``metadata=True`` names the ERC20 holdings in the result and its findings. `validate_vault_state(state)` is
|
|
73
77
|
pure: a custom `VaultState` also provides `vault`, `chain_id`, `market_balances`,
|
|
74
78
|
`erc20` and the queue's `shares_to_release_assets`. `read_erc20_holdings` is gone:
|
|
75
79
|
the holdings are `VaultData.erc20`.
|
|
@@ -92,6 +96,10 @@ are `Fee`, `management_fee_last_update` a `Timestamp`, `unrealized_management_fe
|
|
|
92
96
|
`Amount`; `WithdrawManagerData.withdraw_window` is a `Period`, its fees `Fee`,
|
|
93
97
|
`shares_to_release` `Shares`, `last_release_funds_timestamp` a `Timestamp` and the
|
|
94
98
|
converted amounts `Amount`. A custom `VaultState` annotates the same.
|
|
99
|
+
`VaultValidation.block_timestamp` is a `Timestamp` and `asset_decimals` `Decimals`;
|
|
100
|
+
`Erc20Holding.decimals` / `balance` are `Decimals | None` / `Amount | None` and
|
|
101
|
+
`Erc20Holdings.value_in_asset` / `market_cached_value` `Amount`;
|
|
102
|
+
`VaultData.token_decimals` values and `resolve_token_decimals` are `Decimals | None`.
|
|
95
103
|
`PlasmaVault.total_supply()`, `balance_of()` and `get_total_supply_cap()` return
|
|
96
104
|
`Shares` (vault shares), and `transfer` / `approve` / `transfer_from` /
|
|
97
105
|
`set_total_supply_cap` take `Shares`; `ERC20` keeps `Amount`. The supply cap is
|
|
@@ -114,13 +122,15 @@ typed for `str` still fits). Market-keyed data is keyed by `MarketId`:
|
|
|
114
122
|
and the `dependency_graph` helpers (`compute_update_reach`, `compute_update_groups`,
|
|
115
123
|
`find_orphan_fuse_markets`, `find_markets_missing_erc20_dependency`).
|
|
116
124
|
|
|
117
|
-
`VaultData.
|
|
125
|
+
`VaultData.price_oracle_addr` is renamed `price_oracle`, like its sibling
|
|
126
|
+
address fields (a custom `VaultState` renames it too).
|
|
127
|
+
`VaultData.asset`, `price_oracle`, `rewards_manager`, `withdraw_manager`,
|
|
118
128
|
`FeeData.fee_manager` / `ipor_dao_fee_recipient` and `VaultValidation.vault` /
|
|
119
129
|
`asset` are `ChecksumAddress` (`VaultValidation.vault` a `PlasmaVaultAddress`);
|
|
120
130
|
`VaultData.access_manager` is an `AccessManagerAddress`, `fuses` / `instant_fuses`
|
|
121
131
|
and the `fuse_markets` keys are `FuseAddress`, `balance_fuses` is
|
|
122
132
|
`list[BalanceFuse]`, and `token_prices_usd` is keyed by lowercase `HexAddress`. A
|
|
123
|
-
custom `VaultState` implementation annotates `asset` and `
|
|
133
|
+
custom `VaultState` implementation annotates `asset` and `price_oracle` as
|
|
124
134
|
`ChecksumAddress`, `fuse_markets` keys as `FuseAddress`, and its
|
|
125
135
|
`unpriceable_priced_tokens` items' `market_id` as `MarketId` (`UnpriceableToken`).
|
|
126
136
|
The Uniswap V3 / Ramses V2 position events' `version`, `sender` and `recipient` are
|
|
@@ -155,6 +165,13 @@ Every fuse constructor, `FuseAction.fuse`, `BalanceFuse.fuse`,
|
|
|
155
165
|
`FusionInstance.access_manager` return one. `resolve_access_manager` still takes any
|
|
156
166
|
`ChecksumAddress`: it is what checks that the address is a vault.
|
|
157
167
|
|
|
168
|
+
The vault parameter is named `vault` throughout: `validate_vault`,
|
|
169
|
+
`fetch_deployment_info`, `fetch_vault_lending_health`, `build_oracle_mapping`,
|
|
170
|
+
`read_external_state`, `ExternalStateExecutor.for_vault`, `read_hypercore_nav`,
|
|
171
|
+
`read_hypercore_vault_state`, `read_hypercore_transfer_snapshot`,
|
|
172
|
+
`read_hypercore_evm_exit_ceiling` and `resolve_access_manager` renamed
|
|
173
|
+
``vault_address`` to ``vault``; only a call that passes it by keyword changes.
|
|
174
|
+
|
|
158
175
|
**Simulation and factory records.** `VaultSimulator(web3, *, vault=None, alpha=None,
|
|
159
176
|
block=...)` takes every argument after `web3` by keyword, and `vault` and `alpha` are
|
|
160
177
|
optional: a simulator that only observes, deploys or sends `execute_call(call,
|
|
@@ -257,7 +257,9 @@ def validate(
|
|
|
257
257
|
raise click.UsageError(str(exc)) from exc
|
|
258
258
|
|
|
259
259
|
try:
|
|
260
|
-
validation = validate_vault(
|
|
260
|
+
validation = validate_vault(
|
|
261
|
+
ctx, vault_address, block=block_number, metadata=True
|
|
262
|
+
)
|
|
261
263
|
except UnsupportedVaultVersionError as exc:
|
|
262
264
|
raise click.ClickException(str(exc)) from exc
|
|
263
265
|
|
{ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/cli/vault_info_view.py
RENAMED
|
@@ -191,7 +191,7 @@ def _print_supply(data: VaultData) -> None:
|
|
|
191
191
|
|
|
192
192
|
def _print_managers(data: VaultData) -> None:
|
|
193
193
|
click.echo(f"Access Manager: {data.access_manager}")
|
|
194
|
-
click.echo(f"Price Oracle: {data.
|
|
194
|
+
click.echo(f"Price Oracle: {data.price_oracle}")
|
|
195
195
|
click.echo(f"Rewards Manager: {data.rewards_manager or 'N/A'}")
|
|
196
196
|
click.echo(f"Withdraw Manager: {data.withdraw_manager or 'N/A'}")
|
|
197
197
|
if data.withdraw_manager_data:
|
|
@@ -182,9 +182,7 @@ class AccessManager(ContractWrapper):
|
|
|
182
182
|
)
|
|
183
183
|
|
|
184
184
|
|
|
185
|
-
def resolve_access_manager(
|
|
186
|
-
ctx: Web3Context, vault_address: ChecksumAddress
|
|
187
|
-
) -> AccessManager:
|
|
185
|
+
def resolve_access_manager(ctx: Web3Context, vault: ChecksumAddress) -> AccessManager:
|
|
188
186
|
"""Resolve a vault address to its AccessManager, with typed guards. An
|
|
189
187
|
eager resolver: it reads on ``ctx`` and returns a context-free wrapper.
|
|
190
188
|
|
|
@@ -195,7 +193,7 @@ def resolve_access_manager(
|
|
|
195
193
|
(InsufficientDataBytes) or a revert (ContractLogicError).
|
|
196
194
|
Provider/transport errors propagate unchanged.
|
|
197
195
|
"""
|
|
198
|
-
checksum = Web3.to_checksum_address(
|
|
196
|
+
checksum = Web3.to_checksum_address(vault)
|
|
199
197
|
# Same block as the eth_call below, or a pre-deployment pin would pass
|
|
200
198
|
# this guard and get misdiagnosed as "not a vault".
|
|
201
199
|
code = ctx.web3.eth.get_code(checksum, block_identifier=ctx.default_block)
|
|
@@ -21,6 +21,7 @@ from web3.providers.rpc.utils import (
|
|
|
21
21
|
from web3.types import (
|
|
22
22
|
BlockIdentifier,
|
|
23
23
|
LogReceipt,
|
|
24
|
+
MakeBatchRequestFn,
|
|
24
25
|
MakeRequestFn,
|
|
25
26
|
RPCEndpoint,
|
|
26
27
|
RPCResponse,
|
|
@@ -192,7 +193,14 @@ class Web3Context:
|
|
|
192
193
|
# and leaves every other block untouched.
|
|
193
194
|
web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
|
|
194
195
|
if max_concurrent_requests is not None:
|
|
195
|
-
|
|
196
|
+
# Innermost (layer 0, injected last): a slot covers only the provider
|
|
197
|
+
# call, so a middleware that issues its own request (the gas price
|
|
198
|
+
# strategy reads a block) never waits on the slot it already holds.
|
|
199
|
+
web3.middleware_onion.inject(
|
|
200
|
+
_in_flight_limit(max_concurrent_requests),
|
|
201
|
+
name="in_flight_limit",
|
|
202
|
+
layer=0,
|
|
203
|
+
)
|
|
196
204
|
chain_id = ChainId(web3.eth.chain_id)
|
|
197
205
|
|
|
198
206
|
return cls(
|
|
@@ -411,7 +419,8 @@ class Web3Context:
|
|
|
411
419
|
|
|
412
420
|
def _in_flight_limit(limit: int) -> type[Web3Middleware]:
|
|
413
421
|
"""A middleware class (web3 instantiates it per Web3) holding a semaphore
|
|
414
|
-
slot for the duration of each provider
|
|
422
|
+
slot for the duration of each provider call; a JSON-RPC batch is one HTTP
|
|
423
|
+
request, so it takes one slot whatever its item count."""
|
|
415
424
|
if limit < 1:
|
|
416
425
|
raise ValueError(f"max_concurrent_requests must be at least 1, got {limit}")
|
|
417
426
|
slots = threading.BoundedSemaphore(limit)
|
|
@@ -424,4 +433,15 @@ def _in_flight_limit(limit: int) -> type[Web3Middleware]:
|
|
|
424
433
|
|
|
425
434
|
return limited
|
|
426
435
|
|
|
436
|
+
def wrap_make_batch_request(
|
|
437
|
+
self, make_batch_request: MakeBatchRequestFn
|
|
438
|
+
) -> MakeBatchRequestFn:
|
|
439
|
+
def limited(
|
|
440
|
+
requests_info: list[tuple[RPCEndpoint, Any]],
|
|
441
|
+
) -> list[RPCResponse] | RPCResponse:
|
|
442
|
+
with slots:
|
|
443
|
+
return make_batch_request(requests_info)
|
|
444
|
+
|
|
445
|
+
return limited
|
|
446
|
+
|
|
427
447
|
return InFlightLimit
|
|
@@ -234,7 +234,7 @@ def _snapshot_block(ctx: Web3Context) -> tuple[BlockIdentifier, int]:
|
|
|
234
234
|
|
|
235
235
|
|
|
236
236
|
def read_external_state(
|
|
237
|
-
ctx: Web3Context,
|
|
237
|
+
ctx: Web3Context, vault: PlasmaVaultAddress
|
|
238
238
|
) -> ExternalStateVaultState:
|
|
239
239
|
"""Read the external-state market's vault state as one coherent snapshot.
|
|
240
240
|
|
|
@@ -249,19 +249,19 @@ def read_external_state(
|
|
|
249
249
|
executor word is ``None`` (no executor deployed), which is a state, while
|
|
250
250
|
an RPC or decoding failure raises.
|
|
251
251
|
"""
|
|
252
|
-
|
|
252
|
+
checksum = Web3.to_checksum_address(vault)
|
|
253
253
|
read_at, block = _snapshot_block(ctx)
|
|
254
254
|
base = ExternalStateExecutor._EXECUTOR_STORAGE_SLOT
|
|
255
255
|
words = [
|
|
256
|
-
_storage_word(ctx.get_storage_at(
|
|
256
|
+
_storage_word(ctx.get_storage_at(checksum, base + i, read_at)) for i in range(4)
|
|
257
257
|
]
|
|
258
258
|
if words[0] >> 160:
|
|
259
259
|
raise ExternalStateError(
|
|
260
|
-
f"malformed executor word in the external-state storage of {
|
|
260
|
+
f"malformed executor word in the external-state storage of {checksum}"
|
|
261
261
|
)
|
|
262
262
|
if words[3] not in (0, 1):
|
|
263
263
|
raise ExternalStateError(
|
|
264
|
-
f"malformed pause flag in the external-state storage of {
|
|
264
|
+
f"malformed pause flag in the external-state storage of {checksum}"
|
|
265
265
|
)
|
|
266
266
|
return ExternalStateVaultState(
|
|
267
267
|
executor=Web3.to_checksum_address(f"0x{words[0]:040x}") if words[0] else None,
|
|
@@ -321,7 +321,7 @@ class ExternalStateExecutor(ContractWrapper):
|
|
|
321
321
|
|
|
322
322
|
@classmethod
|
|
323
323
|
def for_vault(
|
|
324
|
-
cls, ctx: Web3Context,
|
|
324
|
+
cls, ctx: Web3Context, vault: PlasmaVaultAddress
|
|
325
325
|
) -> ExternalStateExecutor:
|
|
326
326
|
"""Resolve the per-vault executor from vault storage (at
|
|
327
327
|
``ctx.default_block``) and wrap it. An eager resolver: the wrapper it
|
|
@@ -334,17 +334,16 @@ class ExternalStateExecutor(ContractWrapper):
|
|
|
334
334
|
"""
|
|
335
335
|
word = _storage_word(
|
|
336
336
|
ctx.get_storage_at(
|
|
337
|
-
Web3.to_checksum_address(
|
|
337
|
+
Web3.to_checksum_address(vault), cls._EXECUTOR_STORAGE_SLOT
|
|
338
338
|
)
|
|
339
339
|
)
|
|
340
340
|
if word >> 160:
|
|
341
341
|
raise ExternalStateError(
|
|
342
|
-
f"malformed executor word in the external-state storage of "
|
|
343
|
-
f"{vault_address}"
|
|
342
|
+
f"malformed executor word in the external-state storage of {vault}"
|
|
344
343
|
)
|
|
345
344
|
if word == 0:
|
|
346
345
|
raise ExternalStateError(
|
|
347
|
-
f"no ExternalStateExecutor deployed for vault {
|
|
346
|
+
f"no ExternalStateExecutor deployed for vault {vault}"
|
|
348
347
|
)
|
|
349
348
|
return cls(Web3.to_checksum_address(f"0x{word:040x}"))
|
|
350
349
|
|
|
@@ -245,7 +245,7 @@ def vault_validate(
|
|
|
245
245
|
# Same cheap probe as vault_info: "not a vault" fails before the fetch.
|
|
246
246
|
resolve_access_manager(ctx, checksum)
|
|
247
247
|
|
|
248
|
-
validation = validate_vault(ctx, checksum, block=effective_block)
|
|
248
|
+
validation = validate_vault(ctx, checksum, block=effective_block, metadata=True)
|
|
249
249
|
return VaultValidationResponse.from_validation(
|
|
250
250
|
validation, CHAIN_NAMES.get(chain_id, str(chain_id))
|
|
251
251
|
)
|
|
@@ -575,7 +575,7 @@ def _perp_leg(
|
|
|
575
575
|
|
|
576
576
|
def read_hypercore_nav(
|
|
577
577
|
ctx: Web3Context,
|
|
578
|
-
|
|
578
|
+
vault: PlasmaVaultAddress,
|
|
579
579
|
market_id: MarketId = HYPERCORE_MARKET,
|
|
580
580
|
) -> HyperCoreNav:
|
|
581
581
|
"""Reproduce ``HyperCoreValuationLib.liveValueWad(market_id)`` for the
|
|
@@ -589,17 +589,17 @@ def read_hypercore_nav(
|
|
|
589
589
|
library reverts on (no price, overflow, a failed precompile) raise
|
|
590
590
|
:class:`~ipor_fusion.errors.HyperCoreValuationError`.
|
|
591
591
|
"""
|
|
592
|
-
|
|
592
|
+
pv = PlasmaVault(vault)
|
|
593
593
|
reader = HyperCoreReader()
|
|
594
594
|
multicall = Multicall3(ctx)
|
|
595
595
|
substrates, oracle_address, exists, native = multicall.aggregate(
|
|
596
596
|
cast(
|
|
597
597
|
list[Call[Any]],
|
|
598
598
|
[
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
reader.core_user_exists(
|
|
602
|
-
reader.account_margin_summary(NATIVE_PERP_DEX,
|
|
599
|
+
pv.get_market_substrates(market_id),
|
|
600
|
+
pv.get_price_oracle_middleware_address(),
|
|
601
|
+
reader.core_user_exists(vault),
|
|
602
|
+
reader.account_margin_summary(NATIVE_PERP_DEX, vault),
|
|
603
603
|
],
|
|
604
604
|
)
|
|
605
605
|
)
|
|
@@ -611,11 +611,11 @@ def read_hypercore_nav(
|
|
|
611
611
|
calls: list[Call[Any]] = []
|
|
612
612
|
for index, evm_asset in tokens:
|
|
613
613
|
calls += [
|
|
614
|
-
reader.spot_balance(
|
|
614
|
+
reader.spot_balance(vault, index),
|
|
615
615
|
reader.token_info(index),
|
|
616
616
|
oracle.get_asset_price(evm_asset),
|
|
617
617
|
]
|
|
618
|
-
calls += [reader.account_margin_summary(dex,
|
|
618
|
+
calls += [reader.account_margin_summary(dex, vault) for dex in dexes]
|
|
619
619
|
results = multicall.try_aggregate(calls)
|
|
620
620
|
spot = tuple(
|
|
621
621
|
_spot_leg(index, evm_asset, *results[3 * i : 3 * i + 3])
|
|
@@ -685,7 +685,7 @@ def _granted_perp_markets(
|
|
|
685
685
|
|
|
686
686
|
def read_hypercore_vault_state(
|
|
687
687
|
ctx: Web3Context,
|
|
688
|
-
|
|
688
|
+
vault: PlasmaVaultAddress,
|
|
689
689
|
balance_fuse: FuseAddress,
|
|
690
690
|
market_id: MarketId = HYPERCORE_MARKET,
|
|
691
691
|
*,
|
|
@@ -695,14 +695,14 @@ def read_hypercore_vault_state(
|
|
|
695
695
|
the vault's context, the pending state (when a reader is known for the
|
|
696
696
|
chain or given) and the granted perp markets with their coin names, all
|
|
697
697
|
at ``ctx.default_block``."""
|
|
698
|
-
nav = read_hypercore_nav(ctx,
|
|
699
|
-
|
|
698
|
+
nav = read_hypercore_nav(ctx, vault, market_id)
|
|
699
|
+
pv = PlasmaVault(vault)
|
|
700
700
|
reader = HyperCoreReader()
|
|
701
701
|
pending_reader = pending_reader or HYPERCORE_PENDING_READERS.get(ctx.chain_id)
|
|
702
|
-
granted = _granted_perp_markets(
|
|
703
|
-
calls: list[Call[Any]] = [
|
|
702
|
+
granted = _granted_perp_markets(pv.get_market_substrates(market_id).call(ctx))
|
|
703
|
+
calls: list[Call[Any]] = [pv.balance_fuse_value(balance_fuse)]
|
|
704
704
|
if pending_reader is not None:
|
|
705
|
-
calls.append(HyperCorePendingReader(
|
|
705
|
+
calls.append(HyperCorePendingReader(pv, pending_reader).pending_state())
|
|
706
706
|
calls += [reader.perp_asset_info(read_index_of(asset)) for asset, _, _ in granted]
|
|
707
707
|
results = Multicall3(ctx).try_aggregate(calls)
|
|
708
708
|
fuse_value = results[0]
|
{ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/readers/hypercore_outcome.py
RENAMED
|
@@ -110,7 +110,7 @@ def _pinned_context(ctx: Web3Context) -> tuple[Web3Context, int]:
|
|
|
110
110
|
|
|
111
111
|
def read_hypercore_transfer_snapshot(
|
|
112
112
|
ctx: Web3Context,
|
|
113
|
-
|
|
113
|
+
vault: PlasmaVaultAddress,
|
|
114
114
|
evm_token: ChecksumAddress,
|
|
115
115
|
*,
|
|
116
116
|
token_index: HyperCoreTokenIndex = USDC_TOKEN_INDEX,
|
|
@@ -128,21 +128,21 @@ def read_hypercore_transfer_snapshot(
|
|
|
128
128
|
raise UnsupportedChainError(
|
|
129
129
|
f"no HyperCorePendingReader known for chain {ctx.chain_id}"
|
|
130
130
|
)
|
|
131
|
-
|
|
131
|
+
pv = PlasmaVault(vault)
|
|
132
132
|
reader = HyperCoreReader()
|
|
133
133
|
calls = cast(
|
|
134
134
|
list[Call[Any]],
|
|
135
135
|
[
|
|
136
|
-
reader.core_user_exists(
|
|
137
|
-
reader.spot_balance(
|
|
138
|
-
ERC20(evm_token).balance_of(
|
|
139
|
-
HyperCorePendingReader(
|
|
136
|
+
reader.core_user_exists(vault),
|
|
137
|
+
reader.spot_balance(vault, token_index),
|
|
138
|
+
ERC20(evm_token).balance_of(vault),
|
|
139
|
+
HyperCorePendingReader(pv, pending_reader).pending_state(),
|
|
140
140
|
],
|
|
141
141
|
)
|
|
142
142
|
exists, spot, evm_balance, pending = Multicall3(pinned).aggregate(calls)
|
|
143
143
|
return HyperCoreTransferSnapshot(
|
|
144
144
|
block_number=block,
|
|
145
|
-
vault=
|
|
145
|
+
vault=vault,
|
|
146
146
|
token_index=token_index,
|
|
147
147
|
evm_token=evm_token,
|
|
148
148
|
action_nonce=pending.action_nonce,
|
|
@@ -258,26 +258,26 @@ def read_hypercore_transfer_outcome(
|
|
|
258
258
|
|
|
259
259
|
|
|
260
260
|
def read_hypercore_evm_exit_ceiling(
|
|
261
|
-
ctx: Web3Context,
|
|
261
|
+
ctx: Web3Context, vault: PlasmaVaultAddress, holder: ChecksumAddress
|
|
262
262
|
) -> HyperCoreEvmExitCeiling:
|
|
263
263
|
"""Read the holder's upper bound for an immediate EVM underlying exit.
|
|
264
264
|
|
|
265
265
|
This uses idle ERC-20 only and is a ceiling, not an executable quote.
|
|
266
266
|
"""
|
|
267
267
|
pinned, _ = _pinned_context(ctx)
|
|
268
|
-
|
|
268
|
+
pv = PlasmaVault(vault)
|
|
269
269
|
shares, asset = Multicall3(pinned).aggregate(
|
|
270
270
|
cast(
|
|
271
271
|
list[Call[Any]],
|
|
272
|
-
[
|
|
272
|
+
[pv.balance_of(holder), pv.underlying_asset_address()],
|
|
273
273
|
)
|
|
274
274
|
)
|
|
275
275
|
share_assets, idle = Multicall3(pinned).aggregate(
|
|
276
276
|
cast(
|
|
277
277
|
list[Call[Any]],
|
|
278
278
|
[
|
|
279
|
-
|
|
280
|
-
ERC20(asset).balance_of(
|
|
279
|
+
pv.convert_to_assets(shares),
|
|
280
|
+
ERC20(asset).balance_of(vault),
|
|
281
281
|
],
|
|
282
282
|
)
|
|
283
283
|
)
|
{ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/readers/lending_health.py
RENAMED
|
@@ -392,7 +392,7 @@ def _collect_lending_markets(
|
|
|
392
392
|
|
|
393
393
|
def fetch_vault_lending_health(
|
|
394
394
|
ctx: Web3Context,
|
|
395
|
-
|
|
395
|
+
vault: PlasmaVaultAddress,
|
|
396
396
|
*,
|
|
397
397
|
balance_fuse_market_ids: list[MarketId],
|
|
398
398
|
market_substrates: dict[MarketId, list[bytes]],
|
|
@@ -402,7 +402,7 @@ def fetch_vault_lending_health(
|
|
|
402
402
|
|
|
403
403
|
Args:
|
|
404
404
|
ctx: Web3 context for on-chain calls.
|
|
405
|
-
|
|
405
|
+
vault: The Plasma Vault address.
|
|
406
406
|
balance_fuse_market_ids: List of market IDs from balance fuses.
|
|
407
407
|
market_substrates: Map of market_id -> list of raw substrate bytes.
|
|
408
408
|
Morpho market ids and Aave V4 Spokes are read from it.
|
|
@@ -434,7 +434,7 @@ def fetch_vault_lending_health(
|
|
|
434
434
|
ctx,
|
|
435
435
|
morpho_reader,
|
|
436
436
|
morpho_mid,
|
|
437
|
-
|
|
437
|
+
vault,
|
|
438
438
|
ipor_mid,
|
|
439
439
|
name,
|
|
440
440
|
)
|
|
@@ -447,7 +447,7 @@ def fetch_vault_lending_health(
|
|
|
447
447
|
_compute_aave_market_health,
|
|
448
448
|
ctx,
|
|
449
449
|
AaveV3Reader(aave_pool),
|
|
450
|
-
|
|
450
|
+
vault,
|
|
451
451
|
ipor_mid,
|
|
452
452
|
name,
|
|
453
453
|
)
|
|
@@ -459,7 +459,7 @@ def fetch_vault_lending_health(
|
|
|
459
459
|
_compute_aave_v4_market_health,
|
|
460
460
|
ctx,
|
|
461
461
|
spoke,
|
|
462
|
-
|
|
462
|
+
vault,
|
|
463
463
|
ipor_mid,
|
|
464
464
|
name,
|
|
465
465
|
)
|
{ipor_fusion-4.0.0.dev116 → ipor_fusion-4.0.0.dev120}/src/ipor_fusion/readers/oracle_mapping.py
RENAMED
|
@@ -427,23 +427,23 @@ def _enumerate_assets(
|
|
|
427
427
|
|
|
428
428
|
def build_oracle_mapping(
|
|
429
429
|
ctx: Web3Context,
|
|
430
|
-
|
|
430
|
+
vault: PlasmaVaultAddress,
|
|
431
431
|
effective_block: int,
|
|
432
432
|
max_depth: int = 6,
|
|
433
433
|
) -> OracleMapping:
|
|
434
|
-
"""Build the full oracle mapping for ``
|
|
434
|
+
"""Build the full oracle mapping for ``vault``.
|
|
435
435
|
|
|
436
436
|
``ctx`` must already be pinned to ``effective_block`` (the caller sets
|
|
437
437
|
``ctx.default_block``); the block is echoed in the output. Raises
|
|
438
438
|
`UnsupportedVaultVersionError` for a vault that exposes no price-oracle
|
|
439
439
|
getter.
|
|
440
440
|
"""
|
|
441
|
-
|
|
442
|
-
oracle_addr =
|
|
443
|
-
asset_addr =
|
|
441
|
+
pv = PlasmaVault(vault)
|
|
442
|
+
oracle_addr = pv.read_price_oracle_address(ctx)
|
|
443
|
+
asset_addr = pv.underlying_asset_address().call(ctx)
|
|
444
444
|
|
|
445
445
|
try:
|
|
446
|
-
vault_name =
|
|
446
|
+
vault_name = pv.name().call(ctx)
|
|
447
447
|
except Exception:
|
|
448
448
|
vault_name = None
|
|
449
449
|
|
|
@@ -468,7 +468,7 @@ def build_oracle_mapping(
|
|
|
468
468
|
)
|
|
469
469
|
|
|
470
470
|
return OracleMapping(
|
|
471
|
-
vault=
|
|
471
|
+
vault=vault,
|
|
472
472
|
vault_name=vault_name,
|
|
473
473
|
asset=OracleAsset(
|
|
474
474
|
address=asset_addr,
|
|
@@ -120,7 +120,7 @@ class VaultState(Protocol):
|
|
|
120
120
|
@property
|
|
121
121
|
def underlying_balance_on_vault(self) -> Amount: ...
|
|
122
122
|
@property
|
|
123
|
-
def
|
|
123
|
+
def price_oracle(self) -> ChecksumAddress: ...
|
|
124
124
|
@property
|
|
125
125
|
def balance_fuses(self) -> Sequence[BalanceFuse]: ...
|
|
126
126
|
@property
|
|
@@ -202,10 +202,10 @@ class VaultValidation:
|
|
|
202
202
|
vault: PlasmaVaultAddress
|
|
203
203
|
chain_id: ChainId
|
|
204
204
|
block_number: int
|
|
205
|
-
block_timestamp:
|
|
205
|
+
block_timestamp: Timestamp
|
|
206
206
|
asset: ChecksumAddress
|
|
207
207
|
asset_symbol: str
|
|
208
|
-
asset_decimals:
|
|
208
|
+
asset_decimals: Decimals
|
|
209
209
|
asset_price_usd: float | None
|
|
210
210
|
findings: tuple[Finding, ...]
|
|
211
211
|
reconciliation: Reconciliation
|
|
@@ -236,15 +236,20 @@ class VaultValidation:
|
|
|
236
236
|
|
|
237
237
|
def validate_vault(
|
|
238
238
|
ctx: Web3Context,
|
|
239
|
-
|
|
239
|
+
vault: PlasmaVaultAddress,
|
|
240
240
|
*,
|
|
241
241
|
block: int | None = None,
|
|
242
|
+
metadata: bool = False,
|
|
242
243
|
) -> VaultValidation:
|
|
243
244
|
"""Fetch the vault's snapshot at one block (`fetch_vault_data`: ``block``,
|
|
244
245
|
else the context's numeric default block, else the latest) and validate
|
|
245
|
-
it; ``ctx`` itself is not modified.
|
|
246
|
+
it; ``ctx`` itself is not modified.
|
|
247
|
+
|
|
248
|
+
The checks need no token metadata, so none is read by default and the
|
|
249
|
+
ERC20 holdings are named ``"?"``; ``metadata=True`` adds one batched,
|
|
250
|
+
cached symbol read that names them in the holdings and findings."""
|
|
246
251
|
return validate_vault_state(
|
|
247
|
-
fetch_vault_data(ctx,
|
|
252
|
+
fetch_vault_data(ctx, vault, block=block, metadata=metadata)
|
|
248
253
|
)
|
|
249
254
|
|
|
250
255
|
|