ipor-fusion 4.0.0.dev86__tar.gz → 4.0.0.dev93__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.dev86 → ipor_fusion-4.0.0.dev93}/AGENTS.md +27 -12
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/MIGRATION_4.md +65 -10
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/PKG-INFO +1 -1
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/examples/advanced_euler_v2_credit_market_base.py +2 -2
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/examples/advanced_euler_v2_looping_arbitrum.py +2 -2
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/examples/external_state_margin_leg_base.py +4 -4
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/examples/simple_aave_v3_supply_base.py +2 -2
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/pyproject.toml +1 -1
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/__init__.py +0 -2
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/cli/vault_cmd.py +4 -16
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/cli/vault_health.py +1 -15
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/cli/vault_info_view.py +16 -37
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/cli/vault_markets_view.py +44 -96
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/core/access.py +3 -8
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/core/context.py +18 -5
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/core/contract.py +26 -33
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/core/external_state_executor.py +10 -11
- ipor_fusion-4.0.0.dev86/src/ipor_fusion/fuses/base.py → ipor_fusion-4.0.0.dev93/src/ipor_fusion/core/fuse.py +17 -8
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/core/multicall.py +6 -4
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/core/oracle.py +2 -2
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/core/plasma_vault.py +5 -9
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/core/withdraw_manager.py +4 -4
- ipor_fusion-4.0.0.dev93/src/ipor_fusion/fuses/base.py +17 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/crosschain/base.py +3 -6
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/crosschain/ccip.py +3 -2
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/crosschain/stargate.py +2 -1
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/universal.py +0 -10
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/mcp/server.py +4 -17
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/readers/aave_v3.py +5 -3
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/readers/lending_health.py +2 -3
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/readers/morpho.py +3 -3
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/readers/unpriceable.py +5 -1
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/validation.py +36 -273
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/vault_data.py +204 -75
- ipor_fusion-4.0.0.dev93/src/ipor_fusion/vault_erc20.py +204 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/vault_info.py +59 -98
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/vault_managers.py +27 -4
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/_crosschain_recovery.py +1 -1
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/_validation.py +6 -7
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/conftest.py +1 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_cli_commands.py +30 -14
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_cli_helpers.py +155 -116
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_cli_hypercore.py +8 -7
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_cli_lending_health.py +9 -7
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_cli_pending_requests_scan.py +11 -4
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_cli_vault_info_golden.py +51 -16
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_cli_vault_predates_getters.py +7 -6
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_cli_vault_validate.py +5 -2
- ipor_fusion-4.0.0.dev93/tests/test_contract_encoder.py +118 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_crosschain_layering.py +13 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_external_state_executor.py +27 -27
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_fee_manager.py +2 -2
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_fuse_encoding.py +17 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_hypercore_flow.py +3 -3
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_mcp_vault_validate.py +3 -8
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_plasma_vault.py +1 -1
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_public_api.py +0 -1
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_fusion_factory_clone_base.py +7 -23
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_plasma_vault_setters_base.py +1 -4
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_solidity_mirrors.py +1 -1
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_validation.py +40 -43
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_vault_info_onchain_base.py +3 -4
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_vault_info_onchain_base_no_withdraw_manager.py +1 -1
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_web3_context.py +24 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_withdraw_manager.py +24 -2
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/typed_client/consumer.py +15 -4
- ipor_fusion-4.0.0.dev86/tests/test_contract_encoder.py +0 -118
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/.claude-plugin/marketplace.json +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/.claude-plugin/plugin.json +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/.env.example +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/.gemini/settings.json +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/.git-blame-ignore-revs +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/.github/workflows/cd.yml +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/.github/workflows/ci.yml +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/.github/workflows/commit-lint.yml +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/.github/workflows/notify-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/.github/workflows/python-build.yml +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/.github/workflows/python-publish.yml +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/.github/workflows/release.yml +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/.github/workflows/report-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/.gitignore +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/.pre-commit-config.yaml +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/.python-version +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/CHANGELOG.md +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/CLAUDE.md +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/CODEOWNERS +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/LICENSE +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/README.md +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/build.sh +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/examples/CONTRIBUTING.md +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/examples/README.md +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/examples/composed_hypercore_flow_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/pytest.ini +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/scripts/commit-check.sh +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/scripts/crosschain_readiness.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/skills/ipor-deploy-vault/SKILL.md +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/about.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/cache.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/chains.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/cli/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/cli/changelog_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/cli/config_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/cli/config_store.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/cli/main.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/cli/market_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/cli/options.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/cli/oracle_mapping_view.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/cli/vault_rendering.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/config/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/config/roles.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/core/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/core/address.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/core/erc20.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/core/fee_manager.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/core/fuse_action.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/core/fusion_factory.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/core/logs.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/core/rewards_manager.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/core/simulation.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/ccip/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/ccip/chainlink.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/ccip/codec.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/ccip/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/ccip/events.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/ccip/indexer.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/ccip/lane.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/ccip/quote.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/ccip/transport.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/discovery.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/errors.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/lane.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/logs.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/messages.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/simulation.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/stargate/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/stargate/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/stargate/lane.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/stargate/layerzero.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/stargate/transport.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/crosschain/transport.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/dependency_graph.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/entry_cli.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/entry_mcp.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/errors.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/explorer.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/field_docs.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/aave_v3.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/async_action.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/crosschain/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/erc4626.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/euler_v2.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/events.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/external_state.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/external_state_events.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/fluid_instadapp.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/gearbox_v3.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/hypercore_events.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/merkl.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/morpho.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/fuses/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/guide/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/guide/architecture.md +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/guide/glossary.md +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/guide/invariants.md +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/guide/quickstart.md +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/market_ids.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/market_info.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/mcp/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/mcp/guide.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/mcp/models.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/morpho_api.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/py.typed +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/readers/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/readers/aave_v4.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/readers/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/readers/hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/readers/hypercore_outcome.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/readers/oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/readers/oracle_mapping_nodes.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/readers/oracle_mapping_reader.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/readers/position_manager.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/readers/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/readers/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/substrates.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/types.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/vault_positions.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/src/ipor_fusion/vault_reads.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/UniswapV3UniversalRouter.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/_euler_v2.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/_foundry.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/_guide.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/_hypercore_model.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/_hypercore_shadow.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/_simulate.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/addresses.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/constants.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/fixtures/hypercore_hip3_flow.json +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/fixtures/hypercore_market55.json +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/fixtures/vault_info_golden/clean.json +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/fixtures/vault_info_golden/clean.txt +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/fixtures/vault_info_golden/rich.json +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/fixtures/vault_info_golden/rich.txt +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_about.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_access_manager.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_cache.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_chains.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_cli_changelog.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_cli_config_store.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_cli_market_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_cli_oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_cli_role_accounts.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_contract_call.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_crosschain_ccip_events.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_crosschain_ccip_indexer.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_crosschain_ccip_quote.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_crosschain_chainlink.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_crosschain_contracts.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_crosschain_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_crosschain_errors.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_crosschain_lane.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_crosschain_readiness.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_crosschain_readiness_report.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_crosschain_transport.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_erc20.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_error_hierarchy.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_examples_composed_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_examples_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_examples_euler_looping_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_examples_vaults.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_explorer.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_external_state_events.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_fusion_instance.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_guide.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_hypercore_deployment.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_hypercore_events.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_hypercore_live.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_hypercore_outcome.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_hypercore_readers.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_hypercore_simulation.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_logs.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_mcp_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_mcp_models.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_mcp_server.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_oracle.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_reader_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_readiness_selection.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_revert_decoding.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_rewards_manager.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_roles.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_sdk_layering.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_borrow_aave_v3_mainnet.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_claim_merkl_wrapper_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_claim_morpho_rewards.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_crosschain_canary.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_crosschain_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_crosschain_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_euler_v2_batch_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_euler_v2_swap_deploy_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_euler_v2_swap_reconfigure_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_euler_v2_swap_registry_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_examples_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_examples_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_examples_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_external_state_executor_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_looping_aave_v3_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_looping_morpho_blue_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_pilot_v3.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_pilot_v4_uniswap.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_pilot_v5_ramses.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_pilot_v5_scheduled.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_readers_integration.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_release_funds.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_swap_on_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_simulate_vault_from_scratch_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_solidity_compiler.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_substrates.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_types_and_events.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_unpriceable_tokens.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_vault_dep_graph.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/tests/test_vault_simulator_blocks.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/uv.lock +0 -0
|
@@ -188,8 +188,9 @@ the lifecycle matrix follows that.
|
|
|
188
188
|
- `substrates.py` — public per-market bytes32 substrate decoding (`decode_substrate`,
|
|
189
189
|
`SubstrateInfo`, `format_market_label`, `market_name`; re-exported from `ipor_fusion`),
|
|
190
190
|
used by the CLI, MCP and `readers/lending_health`
|
|
191
|
-
- `validation.py` — public vault validation (`validate_vault
|
|
192
|
-
`validate_vault_state`
|
|
191
|
+
- `validation.py` — public vault validation (`validate_vault` fetches and validates;
|
|
192
|
+
`validate_vault_state` is a pure function of a snapshot typed by the `VaultState`
|
|
193
|
+
protocol):
|
|
193
194
|
`VaultValidation` with ordered `Finding`s, an ok/warning/critical verdict, the
|
|
194
195
|
`Reconciliation`, `Erc20Holdings` and lending health; `dependency_graph.py` holds the
|
|
195
196
|
balance-graph checks
|
|
@@ -197,9 +198,11 @@ the lifecycle matrix follows that.
|
|
|
197
198
|
`WithdrawManagerData`), `fetch_deployment_info`, cached `resolve_token_symbol` /
|
|
198
199
|
`resolve_token_decimals`; it composes `vault_reads.py` (the shared Multicall3 batch
|
|
199
200
|
and degrade-to-``None`` helpers), `vault_managers.py` (fee and WithdrawManager
|
|
200
|
-
snapshots)
|
|
201
|
-
prices)
|
|
202
|
-
`
|
|
201
|
+
snapshots), `vault_positions.py` (Morpho/Aave position breakdowns and their token
|
|
202
|
+
prices) and `vault_erc20.py` (the ERC20_VAULT_BALANCE holdings);
|
|
203
|
+
`vault_info.py` — `build_vault_info_json(data)`, the `fusion vault info --json`
|
|
204
|
+
document rendered from the snapshot alone (contract names via an injected
|
|
205
|
+
`resolve_name`),
|
|
203
206
|
and `health_check_lists`; `explorer.py` Etherscan V2 (single endpoint, needs API key);
|
|
204
207
|
`cache.py` the on-disk contract and deployment caches (`~/.cache/ipor-fusion/`).
|
|
205
208
|
`morpho_api.py` the Morpho public GraphQL API client (`fetch_market`, `fetch_vault`,
|
|
@@ -218,12 +221,14 @@ the lifecycle matrix follows that.
|
|
|
218
221
|
`simulation` (`VaultSimulator`, eth_simulateV1, `erc20_balance_slot` and ERC-20 balance
|
|
219
222
|
overrides), `oracle`, `fusion_factory`,
|
|
220
223
|
`external_state_executor` (NAV marks for market 50), `erc20`, `fuse_action`
|
|
221
|
-
(`FuseAction`), `
|
|
224
|
+
(`FuseAction`), `fuse` (the `Fuse` base, `StakeFuse`, the shared validators and
|
|
225
|
+
substrate packers), `address` (`_validate_not_zero_address`). `core` imports neither
|
|
222
226
|
`fuses` nor `crosschain` (`tests/test_sdk_layering.py`)
|
|
223
227
|
- `fuses/` — per-protocol fuse encoders (aave_v3, async_action, compound_v3, crosschain/,
|
|
224
228
|
erc4626, euler_v2, external_state, fluid_instadapp, gearbox_v3, merkl, morpho, ramses_v2,
|
|
225
|
-
uniswap_v3, universal, `events.py`); `base.py`
|
|
226
|
-
|
|
229
|
+
uniswap_v3, universal, `events.py`); `base.py` re-exports the `core/fuse.py` base and validators,
|
|
230
|
+
`FuseAction` and `ZERO_ADDRESS` (from `types`). A fuse is a value: equality and
|
|
231
|
+
hash cover its class and every attribute it stores
|
|
227
232
|
- `crosschain/` — crosschain Plasma Vaults (executor on the hub chain, dispatcher at
|
|
228
233
|
the same address on each spoke chain), split like the contracts: shared `messages`
|
|
229
234
|
(`Command`, `MsgType`, envelopes), `contracts` (wrapper bases), `transport`
|
|
@@ -276,7 +281,9 @@ or examples.
|
|
|
276
281
|
- `Call[T]` (`core/contract.py`): every `ContractWrapper` method (one per
|
|
277
282
|
Solidity function) returns a `Call` instead of executing. `.call()` runs
|
|
278
283
|
`eth_call` and decodes to `T`; `.send()` signs and submits, returning a
|
|
279
|
-
`TxReceipt`; `.calldata` hands the bytes to an external signer
|
|
284
|
+
`TxReceipt`; `.calldata` hands the bytes to an external signer (a wrapper
|
|
285
|
+
built with `ctx=None`, e.g. `PlasmaVault(None, address)`, builds calldata
|
|
286
|
+
offline; there is no separate encoder factory);
|
|
280
287
|
`.build_transaction()` / `Web3Context.estimate_gas` preview without signing.
|
|
281
288
|
A `Call` without `output_types` (a write) raises on `.call()`. The same
|
|
282
289
|
`Call` feeds `VaultSimulator.observe`, so reads, sends and simulations share
|
|
@@ -291,6 +298,9 @@ or examples.
|
|
|
291
298
|
via `self._action_raw(solidity_signature, values)`; the shared `_validate_*`
|
|
292
299
|
helpers raise before encoding. `PlasmaVault.execute([actions])` runs the
|
|
293
300
|
batch atomically.
|
|
301
|
+
- Pin reads, never mutate a shared context: `ctx.at_block(n)` is a copy whose
|
|
302
|
+
reads (and `get_logs` upper bound) default to block ``n``; `Call.call(block=n)`
|
|
303
|
+
pins one read.
|
|
294
304
|
- Simulate before sending: `VaultSimulator(web3, vault=, alpha=)` batches
|
|
295
305
|
`execute` and `observe` calls into one `eth_simulateV1` round trip, across
|
|
296
306
|
blocks via `next_block`. Integration tests and examples use it instead of a
|
|
@@ -379,9 +389,14 @@ are not validated.
|
|
|
379
389
|
|
|
380
390
|
## Domain rules (verified against the contracts)
|
|
381
391
|
|
|
382
|
-
- `fetch_vault_data(
|
|
383
|
-
|
|
384
|
-
|
|
392
|
+
- `fetch_vault_data(ctx, vault, *, block=, lending=, metadata=)` is the snapshot:
|
|
393
|
+
it resolves one block (``block``, else a numeric `ctx.default_block`, else latest),
|
|
394
|
+
runs every read on `ctx.at_block(block)` (log scans end there too) and returns
|
|
395
|
+
everything validation and the ``vault info`` document need, so neither reads the
|
|
396
|
+
chain. The chain is `ctx.chain_id`; ``lending=False`` skips lending health, the
|
|
397
|
+
position breakdowns, their prices and the unpriceable check; ``metadata=False``
|
|
398
|
+
skips token symbols/decimals. Add a new chain-state input to the snapshot, never a
|
|
399
|
+
read inside a renderer or validator.
|
|
385
400
|
- PlasmaVault serves governance/view functions via `fallback()` delegatecall to
|
|
386
401
|
PlasmaVaultBase, so Etherscan's ABI for the vault address omits callable
|
|
387
402
|
view functions such as `getDependencyBalanceGraph`. An empty dependency graph
|
|
@@ -57,20 +57,40 @@ names earlier reachable only by module path (`FusionFactory`, `FusionInstance`,
|
|
|
57
57
|
`ipor_fusion`: a module path outside the README's list (*Public API and stability*)
|
|
58
58
|
still works but is internal.
|
|
59
59
|
|
|
60
|
-
**Vault reads and validation.**
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
**Vault reads and validation.** The vault read is one pinned snapshot, and the
|
|
61
|
+
chain is always the context's:
|
|
62
|
+
|
|
63
|
+
- `fetch_vault_data(ctx, vault, *, block=None, lending=True, metadata=True)` takes
|
|
64
|
+
the vault address (not a `PlasmaVault`) and no `chain_id`. It resolves one block
|
|
65
|
+
(``block``, else a numeric `ctx.default_block`, else the latest) and runs every
|
|
66
|
+
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`` skips token symbols
|
|
68
|
+
and decimals. `VaultData` gains `vault`, `chain_id`, `market_balances`, `erc20`,
|
|
69
|
+
`token_symbols` and `token_decimals`; `WithdrawManagerData` gains
|
|
70
|
+
`shares_to_release_assets` and `pending_request_assets`.
|
|
71
|
+
- `validate_vault(ctx, vault, *, block=None)` fetches with ``metadata=False`` and
|
|
72
|
+
validates; it no longer takes ``resolve_symbol``. `validate_vault_state(state)` is
|
|
73
|
+
pure: a custom `VaultState` also provides `vault`, `chain_id`, `market_balances`,
|
|
74
|
+
`erc20` and the queue's `shares_to_release_assets`. `read_erc20_holdings` is gone:
|
|
75
|
+
the holdings are `VaultData.erc20`.
|
|
76
|
+
- `build_vault_info_json(data, *, resolve_name=None)` renders from the snapshot and
|
|
77
|
+
reads nothing; the chain and its label come from `data.chain_id`.
|
|
78
|
+
- `fetch_deployment_info(ctx, vault, *, api_key=None)` and
|
|
79
|
+
`fetch_vault_lending_health(ctx, vault, *, balance_fuse_market_ids,
|
|
80
|
+
market_substrates, aave_pools=None)` take the chain from `ctx`.
|
|
81
|
+
- `Web3Context(web3, chain_id, *, ...)` and `Web3Context.from_url(url, *, ...)` take
|
|
82
|
+
their options by keyword. New: `Web3Context.at_block(block)` (a pinned copy) and
|
|
83
|
+
`Call.call(ctx=None, *, block=None)`. `Web3Context.get_logs(to_block=None)` ends at
|
|
84
|
+
the context's default block and `Web3Context.get_block(block=None)` returns it,
|
|
85
|
+
both instead of ``"latest"``.
|
|
86
|
+
|
|
87
|
+
`ensure_supported_chain` takes `ChainId`. `fetch_unpriceable_priced_tokens` takes the oracle and
|
|
67
88
|
underlying as `ChecksumAddress`. `resolve_token_symbol`, `resolve_token_decimals`,
|
|
68
89
|
`get_contract_name` and `get_deployment_tx` take `HexAddress` (a checksum address
|
|
69
90
|
fits), and the `resolve_name` / `resolve_symbol` callbacks receive one (a callback
|
|
70
91
|
typed for `str` still fits). Market-keyed data is keyed by `MarketId`:
|
|
71
92
|
`VaultData.market_substrates`, `dependency_graph`, `morpho_positions`,
|
|
72
|
-
`aave_positions`; the `VaultState` protocol, `
|
|
73
|
-
(`market_balances`), `fetch_vault_lending_health`, `fetch_unpriceable_priced_tokens`
|
|
93
|
+
`aave_positions`, `market_balances`; the `VaultState` protocol, `fetch_vault_lending_health`, `fetch_unpriceable_priced_tokens`
|
|
74
94
|
and the `dependency_graph` helpers (`compute_update_reach`, `compute_update_groups`,
|
|
75
95
|
`find_orphan_fuse_markets`, `find_markets_missing_erc20_dependency`).
|
|
76
96
|
|
|
@@ -93,7 +113,7 @@ The Uniswap V3 / Ramses V2 position events' `version`, `sender` and `recipient`
|
|
|
93
113
|
`quote_ccip_native_fee(block=)` and `OracleMappingReader.asset_source_events` take a
|
|
94
114
|
`BlockIdentifier`.
|
|
95
115
|
|
|
96
|
-
**Address roles.** `PlasmaVault(ctx, address)`,
|
|
116
|
+
**Address roles.** `PlasmaVault(ctx, address)` (`ctx` may be `None`, see below),
|
|
97
117
|
`validate_vault`, `fetch_deployment_info`, the HyperCore, lending-health and
|
|
98
118
|
oracle-mapping readers, `read_external_state`, `VaultSimulator(vault=)`,
|
|
99
119
|
`CrosschainSimulator`, crosschain discovery, the hub-manager inputs
|
|
@@ -194,6 +214,35 @@ are `ProposalHash`; `ExternalStateEvent.transaction_hash` is a `TxHash`.
|
|
|
194
214
|
except below): `chain_id` fields are `ChainId`, `role_id` `RoleId`, `market_id`
|
|
195
215
|
`MarketId`. Calling an MCP tool function directly from Python takes `ChainId`.
|
|
196
216
|
|
|
217
|
+
**Offline wrappers.** `ContractWrapper.encoder()` (and the `PlasmaVault` /
|
|
218
|
+
`AccessManager` overrides) is gone. Every wrapper constructor takes
|
|
219
|
+
`ctx: Web3Context | None`, so build an offline wrapper with the normal
|
|
220
|
+
constructor and an address: `PlasmaVault(None, vault)`, `ERC20(None, token)`,
|
|
221
|
+
`FusionFactory(None, factory)`, `LegacyPriceOracleMiddleware(None, oracle,
|
|
222
|
+
Decimals(8))`. The address is required (there is no zero-address placeholder) and
|
|
223
|
+
subclass parameters stay required, so the wrapper is fully initialized:
|
|
224
|
+
`.encoder()` skipped the constructor, and a legacy oracle built that way failed to
|
|
225
|
+
decode `get_asset_price`. `.calldata` still needs no context; `.call()`, `.send()`,
|
|
226
|
+
`.build_transaction()` and `.estimate_gas()` raise `ValueError` until one is passed
|
|
227
|
+
to them, and a method that reads the chain itself (log scans such as
|
|
228
|
+
`get_balance_fuses` or `get_pending_requests`, `withdraw_manager_address`,
|
|
229
|
+
`Multicall3.aggregate` / `try_aggregate`, the Aave V3 and Morpho position reads)
|
|
230
|
+
raises `ValueError("Web3Context required: <wrapper> at <address> ...")` instead of
|
|
231
|
+
an `AttributeError` on `None`. `ExternalStateExecutor` still refuses the zero
|
|
232
|
+
address for its hash and event readers.
|
|
233
|
+
|
|
234
|
+
| 3.x | 4.0 |
|
|
235
|
+
|---|---|
|
|
236
|
+
| `PlasmaVault.encoder(vault)` | `PlasmaVault(None, vault)` |
|
|
237
|
+
| `ERC20.encoder()` (no address) | `ERC20(None, token)`: pass the real address |
|
|
238
|
+
| `Cls.__new__(Cls)` + `_ctx` / `_address` | `Cls(None, address)` |
|
|
239
|
+
|
|
240
|
+
**Fuse base.** `Fuse`, `StakeFuse` and the shared validators and substrate packers
|
|
241
|
+
live in `ipor_fusion.core.fuse`; `ipor_fusion.fuses.base`, `ipor_fusion.fuses` and
|
|
242
|
+
`ipor_fusion` re-export them, so existing imports keep working. Fuse equality and
|
|
243
|
+
hash now cover every attribute a fuse stores, not only its class and address (see
|
|
244
|
+
[Behavior changes](#behavior-changes)).
|
|
245
|
+
|
|
197
246
|
**Moved, still importable.** `FuseAction` lives in `ipor_fusion.core.fuse_action` and
|
|
198
247
|
`ZERO_ADDRESS` in `ipor_fusion.types`; both are re-exported from
|
|
199
248
|
`ipor_fusion.fuses.base` and `FuseAction` from `ipor_fusion`. The CLI's internal
|
|
@@ -202,6 +251,12 @@ except below): `chain_id` fields are `ChainId`, `role_id` `RoleId`, `market_id`
|
|
|
202
251
|
|
|
203
252
|
## Behavior changes
|
|
204
253
|
|
|
254
|
+
- Two fuses are equal (and hash alike) only when they have the same class and the
|
|
255
|
+
same stored state. `StakeFuse` subclasses (`GearboxStakeFuse`,
|
|
256
|
+
`FluidInstadappStakingFuse`) with the same fuse address but different
|
|
257
|
+
`staking_address` were equal and collapsed in a set or dict key; they are now
|
|
258
|
+
distinct. A custom `Fuse` subclass is compared on its instance attributes, which
|
|
259
|
+
must be hashable; drop an `__eq__` / `__hash__` override that only added them.
|
|
205
260
|
- The MCP `vault_info` document reports the vault address checksummed (the CLI
|
|
206
261
|
already did).
|
|
207
262
|
- `SubstrateInfo.address` is `None` instead of `""` for a substrate without an
|
{ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/examples/advanced_euler_v2_credit_market_base.py
RENAMED
|
@@ -261,12 +261,12 @@ def clone_args() -> dict:
|
|
|
261
261
|
def unsigned_clone_calldata() -> bytes:
|
|
262
262
|
"""Unsigned creation calldata (selector + ABI-encoded args) for the deploy.
|
|
263
263
|
|
|
264
|
-
Built
|
|
264
|
+
Built on a wrapper with ctx=None, so it needs no provider. Hand these bytes to
|
|
265
265
|
an external signer / multisig instead of calling ``.send()``. NOTE: the owner
|
|
266
266
|
encoded here is the simulation ``OWNER`` (a throwaway EOA) -- set your real
|
|
267
267
|
owner in ``clone_args()`` before deploying, or the vault is owned by it.
|
|
268
268
|
"""
|
|
269
|
-
return FusionFactory
|
|
269
|
+
return FusionFactory(None, BASE_FUSION_FACTORY).clone(**clone_args()).calldata
|
|
270
270
|
|
|
271
271
|
|
|
272
272
|
def market_substrates() -> list[bytes]:
|
{ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/examples/advanced_euler_v2_looping_arbitrum.py
RENAMED
|
@@ -208,7 +208,7 @@ def clone_args() -> dict:
|
|
|
208
208
|
|
|
209
209
|
|
|
210
210
|
def unsigned_clone_calldata() -> bytes:
|
|
211
|
-
return FusionFactory
|
|
211
|
+
return FusionFactory(None, ARBITRUM_FUSION_FACTORY).clone(**clone_args()).calldata
|
|
212
212
|
|
|
213
213
|
|
|
214
214
|
def euler_market_substrates() -> list[bytes]:
|
|
@@ -260,7 +260,7 @@ def enable_euler_actions() -> list[FuseAction]:
|
|
|
260
260
|
def build_swap_action() -> FuseAction:
|
|
261
261
|
"""Swap the borrowed USDC through Uniswap V3 and require flash repayment."""
|
|
262
262
|
transfer_data = (
|
|
263
|
-
ERC20
|
|
263
|
+
ERC20(None, ARBITRUM_USDC)
|
|
264
264
|
.transfer(UNISWAP_UNIVERSAL_ROUTER, BORROW_USDC)
|
|
265
265
|
.calldata
|
|
266
266
|
)
|
{ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev93}/examples/external_state_margin_leg_base.py
RENAMED
|
@@ -438,12 +438,12 @@ def clone_args() -> dict:
|
|
|
438
438
|
def unsigned_clone_calldata() -> bytes:
|
|
439
439
|
"""Unsigned creation calldata (selector + ABI-encoded args) for the deploy.
|
|
440
440
|
|
|
441
|
-
Built
|
|
441
|
+
Built on a wrapper with ctx=None, so it needs no provider. Hand these bytes to
|
|
442
442
|
an external signer / multisig instead of calling ``.send()``. NOTE: the owner
|
|
443
443
|
encoded here is the simulation ``OWNER`` (a throwaway EOA) -- set your real
|
|
444
444
|
owner in ``clone_args()`` before deploying, or the vault is owned by it.
|
|
445
445
|
"""
|
|
446
|
-
return FusionFactory
|
|
446
|
+
return FusionFactory(None, BASE_FUSION_FACTORY).clone(**clone_args()).calldata
|
|
447
447
|
|
|
448
448
|
|
|
449
449
|
def market_substrates() -> list[bytes]:
|
|
@@ -534,9 +534,9 @@ def market_substrates() -> list[bytes]:
|
|
|
534
534
|
def venue_transfer_calldata(amount: Amount) -> bytes:
|
|
535
535
|
"""``USDC.transfer(VENUE_DEPOSIT_ADDRESS, amount)`` calldata, run from the executor.
|
|
536
536
|
|
|
537
|
-
Encoded with
|
|
537
|
+
Encoded with an ERC20 wrapper built with ctx=None -- pure bytes, no chain access.
|
|
538
538
|
"""
|
|
539
|
-
return ERC20
|
|
539
|
+
return ERC20(None, BASE_USDC).transfer(VENUE_DEPOSIT_ADDRESS, amount).calldata
|
|
540
540
|
|
|
541
541
|
|
|
542
542
|
def build_enter_action(amount: Amount) -> FuseAction:
|
|
@@ -201,12 +201,12 @@ def clone_args() -> dict:
|
|
|
201
201
|
def unsigned_clone_calldata() -> bytes:
|
|
202
202
|
"""Unsigned creation calldata (selector + ABI-encoded args) for the deploy.
|
|
203
203
|
|
|
204
|
-
Built
|
|
204
|
+
Built on a wrapper with ctx=None, so it needs no provider. Hand these bytes to
|
|
205
205
|
an external signer / multisig instead of calling ``.send()``. NOTE: the owner
|
|
206
206
|
encoded here is the simulation ``OWNER`` (a throwaway EOA) -- set your real
|
|
207
207
|
owner in ``clone_args()`` before deploying, or the vault is owned by it.
|
|
208
208
|
"""
|
|
209
|
-
return FusionFactory
|
|
209
|
+
return FusionFactory(None, BASE_FUSION_FACTORY).clone(**clone_args()).calldata
|
|
210
210
|
|
|
211
211
|
|
|
212
212
|
def build_supply_action(amount: Amount) -> FuseAction:
|
|
@@ -445,7 +445,6 @@ from ipor_fusion.validation import (
|
|
|
445
445
|
VaultState,
|
|
446
446
|
VaultValidation,
|
|
447
447
|
WithdrawQueue,
|
|
448
|
-
read_erc20_holdings,
|
|
449
448
|
validate_vault,
|
|
450
449
|
validate_vault_state,
|
|
451
450
|
)
|
|
@@ -861,7 +860,6 @@ __all__ = [
|
|
|
861
860
|
"VaultState",
|
|
862
861
|
"VaultValidation",
|
|
863
862
|
"WithdrawQueue",
|
|
864
|
-
"read_erc20_holdings",
|
|
865
863
|
"validate_vault",
|
|
866
864
|
"validate_vault_state",
|
|
867
865
|
"compute_update_groups",
|
|
@@ -2,7 +2,6 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
import sys
|
|
5
|
-
from functools import partial
|
|
6
5
|
from typing import Any
|
|
7
6
|
|
|
8
7
|
import click
|
|
@@ -50,7 +49,6 @@ from ipor_fusion.validation import (
|
|
|
50
49
|
from ipor_fusion.vault_data import (
|
|
51
50
|
_ROLE_SCAN_ERRORS,
|
|
52
51
|
fetch_vault_data,
|
|
53
|
-
resolve_token_symbol,
|
|
54
52
|
)
|
|
55
53
|
from ipor_fusion.vault_info import (
|
|
56
54
|
_erc20_balances_json,
|
|
@@ -207,7 +205,6 @@ def info(
|
|
|
207
205
|
"""
|
|
208
206
|
cfg = load_config()
|
|
209
207
|
chain_id, ctx = _build_ctx(cfg, vault_address, chain_id, block_number)
|
|
210
|
-
checksum_address = vault_address
|
|
211
208
|
|
|
212
209
|
# Cheap single-call probe: friendly errors for "nothing deployed here" and
|
|
213
210
|
# "not a Plasma Vault" (revert and empty-return flavors alike) before the
|
|
@@ -217,17 +214,13 @@ def info(
|
|
|
217
214
|
except (ContractNotFoundError, NotPlasmaVaultError) as exc:
|
|
218
215
|
raise click.UsageError(str(exc)) from exc
|
|
219
216
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
_auto_save_vault(cfg, vault_address, chain_id, plasma_vault)
|
|
217
|
+
_auto_save_vault(cfg, vault_address, chain_id, PlasmaVault(ctx, vault_address))
|
|
223
218
|
|
|
224
219
|
try:
|
|
225
|
-
data = fetch_vault_data(ctx,
|
|
220
|
+
data = fetch_vault_data(ctx, vault_address, block=block_number)
|
|
226
221
|
except UnsupportedVaultVersionError as exc:
|
|
227
222
|
raise click.ClickException(str(exc)) from exc
|
|
228
|
-
_print_vault_info(
|
|
229
|
-
ctx, plasma_vault, cfg, data, vault_address, chain_id, json_output
|
|
230
|
-
)
|
|
223
|
+
_print_vault_info(ctx, cfg, data, json_output)
|
|
231
224
|
|
|
232
225
|
|
|
233
226
|
@vault.command("validate")
|
|
@@ -264,12 +257,7 @@ def validate(
|
|
|
264
257
|
raise click.UsageError(str(exc)) from exc
|
|
265
258
|
|
|
266
259
|
try:
|
|
267
|
-
validation = validate_vault(
|
|
268
|
-
ctx,
|
|
269
|
-
vault_address,
|
|
270
|
-
block_number,
|
|
271
|
-
resolve_symbol=partial(resolve_token_symbol, ctx),
|
|
272
|
-
)
|
|
260
|
+
validation = validate_vault(ctx, vault_address, block=block_number)
|
|
273
261
|
except UnsupportedVaultVersionError as exc:
|
|
274
262
|
raise click.ClickException(str(exc)) from exc
|
|
275
263
|
|
|
@@ -3,32 +3,18 @@
|
|
|
3
3
|
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
|
-
from functools import partial
|
|
7
|
-
|
|
8
6
|
import click
|
|
9
7
|
|
|
10
8
|
from ipor_fusion.cli.vault_rendering import _format_amount, _format_usd, _print_table
|
|
11
|
-
from ipor_fusion.core.context import Web3Context
|
|
12
|
-
from ipor_fusion.core.plasma_vault import PlasmaVault
|
|
13
9
|
from ipor_fusion.substrates import market_name
|
|
14
10
|
from ipor_fusion.validation import (
|
|
15
11
|
Erc20Holdings,
|
|
16
12
|
VaultValidation,
|
|
17
|
-
read_erc20_holdings,
|
|
18
13
|
)
|
|
19
|
-
from ipor_fusion.vault_data import VaultData
|
|
14
|
+
from ipor_fusion.vault_data import VaultData
|
|
20
15
|
from ipor_fusion.vault_info import health_check_lists
|
|
21
16
|
|
|
22
17
|
|
|
23
|
-
def _read_erc20_holdings(
|
|
24
|
-
ctx: Web3Context, plasma_vault: PlasmaVault, data: VaultData
|
|
25
|
-
) -> Erc20Holdings:
|
|
26
|
-
"""ERC20 holdings with token symbols from the CLI's contract cache."""
|
|
27
|
-
return read_erc20_holdings(
|
|
28
|
-
ctx, plasma_vault, data, partial(resolve_token_symbol, ctx)
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
|
|
32
18
|
def _print_erc20_balances(data: VaultData, erc20: Erc20Holdings) -> None:
|
|
33
19
|
if not erc20.tokens:
|
|
34
20
|
has_erc20_market = any(
|
|
@@ -14,7 +14,6 @@ from ipor_fusion.cli.vault_health import (
|
|
|
14
14
|
_print_erc20_balances,
|
|
15
15
|
_print_health_check,
|
|
16
16
|
_print_reconciliation,
|
|
17
|
-
_read_erc20_holdings,
|
|
18
17
|
)
|
|
19
18
|
from ipor_fusion.cli.vault_markets_view import _print_lending_health, _print_markets
|
|
20
19
|
from ipor_fusion.cli.vault_rendering import (
|
|
@@ -26,7 +25,6 @@ from ipor_fusion.cli.vault_rendering import (
|
|
|
26
25
|
)
|
|
27
26
|
from ipor_fusion.core.context import Web3Context
|
|
28
27
|
from ipor_fusion.core.fee_manager import RecipientFee
|
|
29
|
-
from ipor_fusion.core.plasma_vault import PlasmaVault
|
|
30
28
|
from ipor_fusion.explorer import get_contract_name
|
|
31
29
|
from ipor_fusion.readers.hypercore import HyperCorePendingState
|
|
32
30
|
from ipor_fusion.substrates import (
|
|
@@ -48,7 +46,6 @@ from ipor_fusion.vault_info import (
|
|
|
48
46
|
_wad_to_usd,
|
|
49
47
|
build_vault_info_json,
|
|
50
48
|
)
|
|
51
|
-
from ipor_fusion.vault_reads import _safe_call
|
|
52
49
|
|
|
53
50
|
|
|
54
51
|
def _print_role_accounts_table(role_accounts: list[dict[str, Any]]) -> None:
|
|
@@ -76,38 +73,28 @@ def _print_role_accounts(role_accounts: list[dict[str, Any]] | None) -> None:
|
|
|
76
73
|
|
|
77
74
|
|
|
78
75
|
def _print_vault_info(
|
|
79
|
-
ctx: Web3Context,
|
|
80
|
-
plasma_vault: PlasmaVault,
|
|
81
|
-
cfg: FusionConfig,
|
|
82
|
-
data: VaultData,
|
|
83
|
-
vault_address: PlasmaVaultAddress,
|
|
84
|
-
chain_id: ChainId,
|
|
85
|
-
json_output: bool = False,
|
|
76
|
+
ctx: Web3Context, cfg: FusionConfig, data: VaultData, json_output: bool = False
|
|
86
77
|
) -> None:
|
|
87
78
|
api_key = cfg.etherscan_api_key
|
|
79
|
+
chain_id = data.chain_id
|
|
88
80
|
chain_label = CHAIN_NAMES.get(chain_id, str(chain_id))
|
|
89
81
|
|
|
90
82
|
(
|
|
91
83
|
data.deployment_block,
|
|
92
84
|
data.deployment_timestamp,
|
|
93
85
|
data.deployment_error,
|
|
94
|
-
) = fetch_deployment_info(ctx,
|
|
86
|
+
) = fetch_deployment_info(ctx, data.vault, api_key=api_key)
|
|
95
87
|
|
|
96
88
|
if json_output:
|
|
97
89
|
result = build_vault_info_json(
|
|
98
|
-
|
|
99
|
-
plasma_vault,
|
|
100
|
-
data,
|
|
101
|
-
chain_id=chain_id,
|
|
102
|
-
chain_label=chain_label,
|
|
103
|
-
resolve_name=partial(get_contract_name, chain_id, api_key=api_key),
|
|
90
|
+
data, resolve_name=partial(get_contract_name, chain_id, api_key=api_key)
|
|
104
91
|
)
|
|
105
92
|
click.echo(json.dumps(result, indent=2))
|
|
106
93
|
return
|
|
107
94
|
|
|
108
|
-
_print_identity(data,
|
|
95
|
+
_print_identity(data, data.vault, chain_id, chain_label)
|
|
109
96
|
_print_supply(data)
|
|
110
|
-
_print_managers(data
|
|
97
|
+
_print_managers(data)
|
|
111
98
|
click.echo()
|
|
112
99
|
|
|
113
100
|
_print_fees(data)
|
|
@@ -115,15 +102,9 @@ def _print_vault_info(
|
|
|
115
102
|
|
|
116
103
|
_print_role_accounts(_role_accounts_json(data))
|
|
117
104
|
|
|
118
|
-
|
|
105
|
+
_print_markets(data, api_key)
|
|
119
106
|
|
|
120
|
-
validation = validate_vault_state(
|
|
121
|
-
ctx,
|
|
122
|
-
plasma_vault,
|
|
123
|
-
data,
|
|
124
|
-
market_balances,
|
|
125
|
-
_read_erc20_holdings(ctx, plasma_vault, data),
|
|
126
|
-
)
|
|
107
|
+
validation = validate_vault_state(data)
|
|
127
108
|
click.echo("ERC20 Balances (vault holdings):")
|
|
128
109
|
_print_erc20_balances(data, validation.erc20)
|
|
129
110
|
click.echo()
|
|
@@ -131,7 +112,7 @@ def _print_vault_info(
|
|
|
131
112
|
_print_reconciliation(data, validation)
|
|
132
113
|
click.echo()
|
|
133
114
|
|
|
134
|
-
_print_lending_health(
|
|
115
|
+
_print_lending_health(data)
|
|
135
116
|
click.echo()
|
|
136
117
|
_print_hypercore(data)
|
|
137
118
|
|
|
@@ -207,7 +188,7 @@ def _print_supply(data: VaultData) -> None:
|
|
|
207
188
|
)
|
|
208
189
|
|
|
209
190
|
|
|
210
|
-
def _print_managers(data: VaultData
|
|
191
|
+
def _print_managers(data: VaultData) -> None:
|
|
211
192
|
click.echo(f"Access Manager: {data.access_manager}")
|
|
212
193
|
click.echo(f"Price Oracle: {data.price_oracle_addr}")
|
|
213
194
|
click.echo(f"Rewards Manager: {data.rewards_manager or 'N/A'}")
|
|
@@ -222,7 +203,7 @@ def _print_managers(data: VaultData, plasma_vault: PlasmaVault) -> None:
|
|
|
222
203
|
if wmd.last_release_funds_timestamp > 0:
|
|
223
204
|
last_iso = _unix_to_iso(wmd.last_release_funds_timestamp)
|
|
224
205
|
click.echo(f" Last release: {last_iso}")
|
|
225
|
-
_print_pending_requests(data
|
|
206
|
+
_print_pending_requests(data)
|
|
226
207
|
|
|
227
208
|
|
|
228
209
|
def _format_fee_percent(value: float | None) -> str:
|
|
@@ -375,7 +356,7 @@ def _print_hypercore_pending(pending: HyperCorePendingState | None) -> None:
|
|
|
375
356
|
)
|
|
376
357
|
|
|
377
358
|
|
|
378
|
-
def _print_pending_requests(data: VaultData
|
|
359
|
+
def _print_pending_requests(data: VaultData) -> None:
|
|
379
360
|
if (wmd := data.withdraw_manager_data) is None:
|
|
380
361
|
return
|
|
381
362
|
if wmd.pending_requests is None:
|
|
@@ -389,16 +370,14 @@ def _print_pending_requests(data: VaultData, plasma_vault: PlasmaVault) -> None:
|
|
|
389
370
|
return
|
|
390
371
|
|
|
391
372
|
total_shares = Shares(sum(r.shares for r in requests))
|
|
392
|
-
|
|
393
|
-
|
|
373
|
+
request_assets = [wmd.pending_request_assets.get(r.account) for r in requests]
|
|
374
|
+
total_assets = (
|
|
375
|
+
None if None in request_assets else sum(a for a in request_assets if a)
|
|
394
376
|
)
|
|
395
377
|
|
|
396
378
|
click.echo(f" Pending requests ({len(requests)}):")
|
|
397
379
|
rows: list[tuple[str, ...]] = []
|
|
398
|
-
for req in requests:
|
|
399
|
-
assets: int | None = _safe_call(
|
|
400
|
-
lambda s=req.shares: plasma_vault.convert_to_assets(s).call()
|
|
401
|
-
)
|
|
380
|
+
for req, assets in zip(requests, request_assets, strict=True):
|
|
402
381
|
assets_str = (
|
|
403
382
|
f"{_format_amount(assets, data.asset_decimals)} {data.asset_symbol}"
|
|
404
383
|
if assets is not None
|