ipor-fusion 4.1.0.dev56__tar.gz → 4.2.0.dev9__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.1.0.dev56 → ipor_fusion-4.2.0.dev9}/.claude-plugin/plugin.json +1 -1
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/AGENTS.md +11 -3
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/CHANGELOG.md +126 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/PKG-INFO +6 -2
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/README.md +5 -1
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/pyproject.toml +1 -1
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/skills/ipor-deploy-vault/SKILL.md +14 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/__init__.py +40 -0
- ipor_fusion-4.2.0.dev9/src/ipor_fusion/cli/fuse_cmd.py +108 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/cli/main.py +2 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/erc20.py +7 -2
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/plasma_vault.py +4 -1
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/simulation_result.py +2 -1
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/errors.py +2 -1
- ipor_fusion-4.2.0.dev9/src/ipor_fusion/fuse_whitelist.py +401 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/guide/invariants.md +12 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/guide/quickstart.md +2 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/mcp/models.py +26 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/mcp/server.py +29 -0
- ipor_fusion-4.2.0.dev9/src/ipor_fusion/onchain_text.py +30 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/preflight.py +42 -1
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/readers/oracle_mapping_reader.py +4 -1
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/registry.py +15 -2
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/types.py +1 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/validation.py +100 -8
- ipor_fusion-4.2.0.dev9/tests/test_cli_mcp_fuse_whitelist.py +115 -0
- ipor_fusion-4.2.0.dev9/tests/test_fuse_whitelist.py +411 -0
- ipor_fusion-4.2.0.dev9/tests/test_onchain_text.py +62 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_preflight.py +7 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_public_api.py +42 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_registry.py +39 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_preflight_base.py +16 -2
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_validation.py +9 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/uv.lock +1 -1
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/.claude-plugin/marketplace.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/.env.example +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/.gemini/settings.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/.git-blame-ignore-revs +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/.github/workflows/cd.yml +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/.github/workflows/ci.yml +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/.github/workflows/commit-lint.yml +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/.github/workflows/notify-slack.yml +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/.github/workflows/python-build.yml +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/.github/workflows/python-publish.yml +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/.github/workflows/release.yml +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/.github/workflows/report-slack.yml +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/.gitignore +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/.pre-commit-config.yaml +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/.python-version +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/CLAUDE.md +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/CODEOWNERS +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/LICENSE +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/MIGRATION_4.md +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/build.sh +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/examples/CONTRIBUTING.md +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/examples/README.md +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/examples/advanced_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/examples/advanced_euler_v2_looping_arbitrum.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/examples/external_state_margin_leg_base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/examples/hypercore_vault_official_deployment_hyperevm.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/examples/simple_aave_v3_supply_base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/pytest.ini +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/scripts/commit-check.sh +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/scripts/fusion_error_signatures.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/about.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/cache.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/chains.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/cli/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/cli/address_cmd.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/cli/changelog_cmd.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/cli/config_cmd.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/cli/config_store.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/cli/market_cmd.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/cli/options.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/cli/oracle_mapping_view.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/cli/preflight_cmd.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/cli/vault_cmd.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/cli/vault_health.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/cli/vault_info_view.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/cli/vault_markets_view.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/cli/vault_rendering.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/config/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/config/roles.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/access.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/address.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/context.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/context_manager.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/contract.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/external_state_executor.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/fee_manager.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/fuse.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/fuse_action.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/fuse_decoding.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/fusion_factory.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/logs.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/multicall.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/oracle.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/rewards_manager.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/simulation.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/withdraw_manager.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/ccip/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/ccip/chainlink.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/ccip/codec.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/ccip/contracts.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/ccip/events.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/ccip/indexer.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/ccip/lane.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/ccip/quote.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/ccip/transport.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/contracts.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/discovery.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/errors.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/fuses/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/fuses/base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/fuses/ccip.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/fuses/stargate.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/lane.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/logs.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/messages.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/simulation.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/stargate/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/stargate/contracts.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/stargate/lane.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/stargate/layerzero.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/stargate/transport.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/crosschain/transport.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/dependency_graph.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/entry_cli.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/entry_mcp.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/explorer.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/field_docs.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/fuses/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/fuses/aave_v3.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/fuses/async_action.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/fuses/base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/fuses/compound_v3.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/fuses/erc4626.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/fuses/euler_v2.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/fuses/events.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/fuses/external_state.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/fuses/external_state_event_decoding.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/fuses/fluid_instadapp.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/fuses/gearbox_v3.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/fuses/hypercore.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/fuses/hypercore_event_decoding.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/fuses/hypercore_pre_hooks.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/fuses/merkl.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/fuses/morpho.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/fuses/ramses_v2.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/fuses/uniswap_v3.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/fuses/universal.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/fusion_errors.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/guide/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/guide/architecture.md +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/guide/glossary.md +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/hypercore/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/market_ids.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/market_info.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/mcp/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/mcp/guide.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/morpho_api.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/py.typed +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/readers/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/readers/aave_v3.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/readers/aave_v4.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/readers/compound_v3.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/readers/euler_v2.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/readers/hypercore.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/readers/hypercore_outcome.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/readers/lending_health.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/readers/morpho.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/readers/oracle_mapping.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/readers/oracle_mapping_nodes.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/readers/position_manager.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/readers/ramses_v2.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/readers/uniswap_v3.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/readers/unpriceable.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/substrates.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/vault_data.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/vault_erc20.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/vault_info.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/vault_managers.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/vault_positions.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/vault_reads.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/UniswapV3UniversalRouter.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/_addresses.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/_crosschain.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/_crosschain_recovery.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/_euler_v2.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/_event_args.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/_fake_rpc.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/_foundry.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/_golden.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/_guide.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/_hypercore_model.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/_hypercore_shadow.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/_live.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/_multicall.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/_oracle_mapping_fake.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/_simulate.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/_validation.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/addresses.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/conftest.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/constants.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/hypercore_hip3_flow.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/hypercore_market55.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/hypercore_official.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/market_golden/meta_morpho_v1.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/market_golden/meta_morpho_v1.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/market_golden/meta_morpho_v2.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/market_golden/meta_morpho_v2.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/market_golden/morpho_api/market.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/market_golden/morpho_api/vault_v1.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/market_golden/morpho_api/vault_v2.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/market_golden/morpho_api/vault_v2_not_found.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/market_golden/morpho_blue.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/market_golden/morpho_blue.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/market_golden/morpho_blue_api_error.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/market_golden/morpho_blue_api_error.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/market_golden/morpho_blue_no_api.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/market_golden/morpho_blue_no_api.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/oracle_mapping_golden/mapping.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/oracle_mapping_golden/mapping.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/simulate_v1_request.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/vault_info_golden/clean.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/vault_info_golden/clean.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/vault_info_golden/clean.txt +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/vault_info_golden/deployment_error.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/vault_info_golden/deployment_error.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/vault_info_golden/deployment_error.txt +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/vault_info_golden/fetched.cli.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/vault_info_golden/fetched.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/vault_info_golden/fetched.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/vault_info_golden/full.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/vault_info_golden/full.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/vault_info_golden/full.txt +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/vault_info_golden/rich.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/vault_info_golden/rich.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/fixtures/vault_info_golden/rich.txt +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_about.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_access_manager.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_addresses_helper.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_cache.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_ccip_read_disabled.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_chains.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_cli_address.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_cli_changelog.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_cli_commands.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_cli_config_store.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_cli_helpers.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_cli_hypercore.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_cli_lending_health.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_cli_market_golden.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_cli_market_morpho_blue.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_cli_mcp_parity.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_cli_oracle_mapping.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_cli_oracle_mapping_golden.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_cli_pending_requests_scan.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_cli_preflight.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_cli_role_accounts.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_cli_vault_info_golden.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_cli_vault_predates_getters.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_cli_vault_validate.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_contract_call.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_contract_encoder.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_crosschain_ccip_events.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_crosschain_ccip_indexer.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_crosschain_ccip_quote.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_crosschain_chainlink.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_crosschain_contracts.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_crosschain_encoding.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_crosschain_errors.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_crosschain_lane.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_crosschain_layering.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_crosschain_transport.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_docs_typing.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_erc20.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_error_hierarchy.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_examples_crosschain.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_examples_euler_looping_arbitrum.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_examples_hypercore_hyperevm.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_examples_vaults.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_explorer.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_external_state_events.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_external_state_executor.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_fee_manager.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_fuse_decoding.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_fuse_encoding.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_fusion_errors.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_fusion_instance.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_governance_wrappers.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_guide.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_hypercore_deployment.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_hypercore_events.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_hypercore_flow.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_hypercore_live.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_hypercore_outcome.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_hypercore_pre_hooks.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_hypercore_readers.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_hypercore_simulation.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_logs.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_mcp_address.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_mcp_hypercore.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_mcp_models.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_mcp_preflight.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_mcp_server.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_mcp_vault_validate.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_multicall.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_oracle.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_oracle_mapping.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_plasma_vault.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_public_type_reachability.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_reader_encoding.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_revert_decoding.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_rewards_manager.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_roles.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_sdk_layering.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_borrow_aave_v3_mainnet.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_claim_merkl_wrapper_base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_claim_morpho_rewards.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_crosschain_hyperevm.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_euler_v2_batch_base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_euler_v2_swap_deploy_base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_euler_v2_swap_reconfigure_base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_euler_v2_swap_registry_base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_examples_arbitrum.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_examples_base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_examples_crosschain.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_examples_hyperevm.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_external_state_executor_base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_fusion_factory_clone_base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_looping_aave_v3_base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_looping_morpho_blue_base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_morpho_blue.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_pilot_v3.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_pilot_v4_uniswap.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_pilot_v5_ramses.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_pilot_v5_scheduled.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_plasma_vault_setters_base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_readers_integration.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_release_funds.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_swap_on_base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_timelock_base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulate_vault_from_scratch_base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulation_errors.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_simulation_observation.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_solidity_compiler.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_solidity_mirrors.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_substrates.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_types_and_events.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_unpriceable_tokens.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_vault_data_block.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_vault_dep_graph.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_vault_info_fetched_golden.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_vault_info_onchain_base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_vault_info_onchain_base_no_withdraw_manager.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_vault_reconciliation_onchain_base.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_vault_simulator_blocks.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_web3_context.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/test_withdraw_manager.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/typed_client/consumer.py +0 -0
- {ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/tests/typed_client/rejected.py +0 -0
|
@@ -174,7 +174,7 @@ checkout's default profile), the pending reader included.
|
|
|
174
174
|
subpackages do not list them). Their exceptions stay in `errors` and the top
|
|
175
175
|
level. `ipor_fusion.guide` keeps its own namespace. The
|
|
176
176
|
public modules (`about`, `cache`, `chains`, `dependency_graph`, `errors`, `explorer`,
|
|
177
|
-
`field_docs`, `market_ids`, `market_info`, `morpho_api`, `preflight`, `registry`, `substrates`, `types`,
|
|
177
|
+
`field_docs`, `fuse_whitelist`, `market_ids`, `market_info`, `morpho_api`, `preflight`, `registry`, `substrates`, `types`,
|
|
178
178
|
`validation`, `vault_data`, `vault_info`) stay importable for the names they
|
|
179
179
|
define and the moved names README lists; `cli`, `mcp`, every other module and
|
|
180
180
|
every submodule of a public subpackage (`core.contract`, `fuses.base`, ...) are
|
|
@@ -246,6 +246,13 @@ checkout's default profile), the pending reader included.
|
|
|
246
246
|
`registry.py` the ipor-abi address registry (`fetch_address_registry` →
|
|
247
247
|
`AddressRegistry`, one raw-GitHub file per chain in `REGISTRY_CHAIN_IDS`, cached ten
|
|
248
248
|
minutes in the process, for good at a commit ref) and the `fusion address` documents;
|
|
249
|
+
`fuse_whitelist.py` the on-chain Fuse Whitelist (`IporFusionFuseWhitelistProxy`,
|
|
250
|
+
resolved through `registry.py`): `read_market_fuses` / `read_fuse_entries` in
|
|
251
|
+
Multicall3 batches, `check_fuses` + `fuse_whitelist_issues` (the warnings
|
|
252
|
+
`validate_vault` and `preflight_execute` add, each naming the active
|
|
253
|
+
replacement) and the `fusion fuse whitelist` document; `getFusesByMarketId`
|
|
254
|
+
returns deprecated fuses too, so state is always read alongside; it reads the
|
|
255
|
+
registry with a 5 s timeout and `stale_if_error`, since the check is optional;
|
|
249
256
|
`morpho_api.py` the Morpho public GraphQL API client (`fetch_market`, `fetch_vault`,
|
|
250
257
|
`PUBLIC_ALLOCATOR_ADDRESSES`; it narrows the GraphQL body from `object`);
|
|
251
258
|
`market_info.py` — `build_morpho_blue_market_json`, `build_meta_morpho_json`, the
|
|
@@ -477,7 +484,8 @@ byte, e.g. Ebisu ZAPPER/REGISTRY).
|
|
|
477
484
|
## CLI and MCP
|
|
478
485
|
|
|
479
486
|
`fusion address` (lookup, names, list; the ipor-abi registry through `registry.py`),
|
|
480
|
-
`fusion config` (set-provider, set-etherscan-key, show), `fusion
|
|
487
|
+
`fusion config` (set-provider, set-etherscan-key, show), `fusion fuse`
|
|
488
|
+
(whitelist; the on-chain Fuse Whitelist through `fuse_whitelist.py`), `fusion market`
|
|
481
489
|
(morpho-blue, meta-morpho), `fusion vault` (add, remove, list, info, validate,
|
|
482
490
|
role-accounts, oracle-mapping, preflight). `vault info` runs independent fetch pipelines
|
|
483
491
|
(vault/asset, fees, WithdrawManager, markets, roles) concurrently on a
|
|
@@ -495,7 +503,7 @@ Every CLI command has an MCP tool (`fusion changelog` maps to `server_info`;
|
|
|
495
503
|
the rest share names). Read-only: `vault_info`, `vault_validate`, `vault_preflight`,
|
|
496
504
|
`vault_list`, `vault_role_accounts`, `vault_oracle_mapping`, `market_morpho_blue`,
|
|
497
505
|
`market_meta_morpho`, `address_lookup`, `address_names`, `address_list`,
|
|
498
|
-
`config_show`, `server_info`. Mutating: `vault_add`,
|
|
506
|
+
`fuse_whitelist`, `config_show`, `server_info`. Mutating: `vault_add`,
|
|
499
507
|
`vault_remove`, `config_set_provider`, `config_set_etherscan_key`. Every new
|
|
500
508
|
CLI command gets a matching MCP tool with the same argument names; an optional
|
|
501
509
|
chain or block is `None` when omitted (`ChainArg`, `BlockArg`); a chain of
|
|
@@ -2,6 +2,132 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- version list -->
|
|
4
4
|
|
|
5
|
+
## v4.1.0 (2026-11-03)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- **cli**: Accept a 0X prefix in address arguments
|
|
10
|
+
([`cc23ff7`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/cc23ff7be50ca760eb6adc1a245746bc93a62553))
|
|
11
|
+
|
|
12
|
+
- **cli**: Check address arguments with parse_checksum_address
|
|
13
|
+
([`4023d07`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/4023d0789ed78d1ab76ce8f44d76a98b65c366f6))
|
|
14
|
+
|
|
15
|
+
- **cli**: Print a set-provider hint that runs as shown
|
|
16
|
+
([`6dd2894`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/6dd2894693038bae57b256293a4128160f35fc02))
|
|
17
|
+
|
|
18
|
+
- **cli**: Read --block-number 0 as the latest block
|
|
19
|
+
([`8dd339f`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/8dd339f0d8412389c6a473a57f119e79473e9ef6))
|
|
20
|
+
|
|
21
|
+
- **mcp**: Name the preflight sender in its parse errors
|
|
22
|
+
([`b1a6115`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/b1a61158a1f25eb9516f0e96d1a5c794ff943c65))
|
|
23
|
+
|
|
24
|
+
- **mcp**: Read block_number=0 as the latest block
|
|
25
|
+
([`320bb93`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/320bb935726d83fd7787cab9bb82430681ee6a11))
|
|
26
|
+
|
|
27
|
+
- **mcp**: Reject a wrong EIP-55 checksum in the MetaMorpho vault
|
|
28
|
+
([`02a5159`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/02a5159d727f768a40e97aad6869ff3b0356c418))
|
|
29
|
+
|
|
30
|
+
- **mcp**: Reject a wrong EIP-55 checksum in the preflight sender
|
|
31
|
+
([`4d5af23`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/4d5af236721c2cd3e9e8a0f52ed045b06039b4fa))
|
|
32
|
+
|
|
33
|
+
- **mcp**: Reject a wrong EIP-55 checksum in vault arguments
|
|
34
|
+
([`37625ec`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/37625ecb172a3478fc7fb5e522027c71c0a98dcf))
|
|
35
|
+
|
|
36
|
+
- **sdk**: Check EIP-55 in every FusionInstance address field
|
|
37
|
+
([`951f49a`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/951f49a4ccceecef4a06b8c600c12564da0c6ce5))
|
|
38
|
+
|
|
39
|
+
- **sdk**: Do not follow CCIP-Read lookups from contracts
|
|
40
|
+
([`51c8ef2`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/51c8ef25e19b9e33c8ea4317a9e1df26ad87dccd))
|
|
41
|
+
|
|
42
|
+
- **sdk**: Read the latest block's number and timestamp in one call
|
|
43
|
+
([`60a4a8f`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/60a4a8f545714f1013a2f30145837b2d8ad421cb))
|
|
44
|
+
|
|
45
|
+
- **sdk**: Reject a 0X-prefixed zero address
|
|
46
|
+
([`556ee32`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/556ee329d7954ac39f2b0dff607fa2aba7ba3bdd))
|
|
47
|
+
|
|
48
|
+
- **sdk**: Reject a wrong EIP-55 checksum in the address parsers
|
|
49
|
+
([`deac726`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/deac7262bb5ccfdc0932eab8d22ed02bd66d4c3b))
|
|
50
|
+
|
|
51
|
+
- **sdk**: Report Euler V2 lending health and never drop a borrow market
|
|
52
|
+
([`1de4598`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/1de4598248b2a73d322d68359baaa74421244b2e))
|
|
53
|
+
|
|
54
|
+
- **sdk**: Stop reporting a rounding gap as a stale ERC20 cache
|
|
55
|
+
([`29ffb53`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/29ffb53377cd91308815a0d3ede18acfe640ee4a))
|
|
56
|
+
|
|
57
|
+
- **sdk**: Stop the oracle mapping at a price oracle manager delegation cycle
|
|
58
|
+
([`1470d93`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/1470d93f85f477e24a85e6a28013f4456149d128))
|
|
59
|
+
|
|
60
|
+
### Build System
|
|
61
|
+
|
|
62
|
+
- Bump aiohttp, multidict and mcp in the lock
|
|
63
|
+
([`3c266b1`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/3c266b195f3b6ae4b72bdf8e7ae5a2c165838cc1))
|
|
64
|
+
|
|
65
|
+
### Documentation
|
|
66
|
+
|
|
67
|
+
- Block 0 reads the latest block in the tools and the CLI
|
|
68
|
+
([`308ccd2`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/308ccd22cff554c3f31f1414a8e825fac8b00625))
|
|
69
|
+
|
|
70
|
+
- Keep the CCIP example's command gas inside HyperEVM's small block
|
|
71
|
+
([`5e3a093`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/5e3a093b66c79c9565f89b7c91615cb95c2e1ff7))
|
|
72
|
+
|
|
73
|
+
- **examples**: Build address literals with parse_checksum_address
|
|
74
|
+
([`c449d13`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/c449d13ab481ec9b13497bb435569d9651f5b38c))
|
|
75
|
+
|
|
76
|
+
- **sdk**: Say the HyperCore pre-hooks take no pre-hook substrates
|
|
77
|
+
([`b609593`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/b609593ebb4b05bfd2b866e6139f02321323f6a3))
|
|
78
|
+
|
|
79
|
+
- **sdk**: Wire the HyperCore example's pre-hooks with the helper
|
|
80
|
+
([`edd2776`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/edd277677da59872f5074d8dcba2b6b5cad2daa2))
|
|
81
|
+
|
|
82
|
+
### Features
|
|
83
|
+
|
|
84
|
+
- **sdk**: Add parse_checksum_address
|
|
85
|
+
([`a9a6b84`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/a9a6b848e606318fc76fa82dc2c54c7d5b4a94d9))
|
|
86
|
+
|
|
87
|
+
- **sdk**: Expose the HyperCore order and price scales
|
|
88
|
+
([`b75c645`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/b75c645f95c525114e181519fe75c2348b7962b7))
|
|
89
|
+
|
|
90
|
+
- **sdk**: HyperCore pre-hook wiring
|
|
91
|
+
([`6f16ae6`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/6f16ae6cbe2d0f3298308f4592538cb06e52eab6))
|
|
92
|
+
|
|
93
|
+
- **sdk**: Read the HyperCore best bid and ask
|
|
94
|
+
([`5fda9ee`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/5fda9ee754eb8085df3f8c432ce65565c045bddf))
|
|
95
|
+
|
|
96
|
+
- **sdk**: Report the feeds behind a Morpho oracle in the oracle mapping
|
|
97
|
+
([`c692d72`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/c692d72449805ee98ae786f14d41d28e6de2c24e))
|
|
98
|
+
|
|
99
|
+
- **sdk**: Support TAC (239) in the vault tooling again
|
|
100
|
+
([`0cc00c3`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/0cc00c3e8d30f5937296ec6dc40896a4e1c766f7))
|
|
101
|
+
|
|
102
|
+
### Refactoring
|
|
103
|
+
|
|
104
|
+
- **mcp**: Share _vault_arg's input normalization
|
|
105
|
+
([`80744af`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/80744afd6d52d33ba7e8a075478083aef4048384))
|
|
106
|
+
|
|
107
|
+
- **sdk**: Decode Euler V2 and Dolomite substrates into typed values
|
|
108
|
+
([`8f4f1ad`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/8f4f1ad5045772da897a3e31d8514b32c6386610))
|
|
109
|
+
|
|
110
|
+
- **sdk**: Make HyperCorePreHookWiring.selectors a class constant
|
|
111
|
+
([`ae9bf3e`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/ae9bf3e72f31fe795ef5683cd7287b40a1c83d14))
|
|
112
|
+
|
|
113
|
+
- **sdk**: Move the HyperCore pre-hook wiring to its own module
|
|
114
|
+
([`b150389`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/b1503891468fe4f54379d8ba49ce68d6b3c7e041))
|
|
115
|
+
|
|
116
|
+
- **sdk**: Name the 0x813 precompile POSITION2_PRECOMPILE
|
|
117
|
+
([`9529f22`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/9529f22e8a1517ef096fe1b4bff56dcaa8139e5a))
|
|
118
|
+
|
|
119
|
+
- **sdk**: Stop coercing HyperCorePreHookWiring's hooks
|
|
120
|
+
([`759448d`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/759448d02b3d690a5de636ee91363263e7dd0e40))
|
|
121
|
+
|
|
122
|
+
### Testing
|
|
123
|
+
|
|
124
|
+
- Share a miscased-address helper
|
|
125
|
+
([`5f769ac`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/5f769ac98160baa0fe2099b3255b0f91d2b4b223))
|
|
126
|
+
|
|
127
|
+
- **sdk**: Probe the core modules' CLI isolation in one subprocess
|
|
128
|
+
([`3fc160a`](https://github.com/IPOR-Labs/ipor-fusion.py/commit/3fc160a5766171dc7bb471968d2740521b59d69e))
|
|
129
|
+
|
|
130
|
+
|
|
5
131
|
## v4.0.0 (2026-10-23)
|
|
6
132
|
|
|
7
133
|
### Bug Fixes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: ipor-fusion
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.2.0.dev9
|
|
4
4
|
Summary: The IPOR Fusion SDK for Python
|
|
5
5
|
Project-URL: homepage, https://ipor.io
|
|
6
6
|
Project-URL: repository, https://github.com/IPOR-Labs/ipor-fusion.py
|
|
@@ -251,6 +251,9 @@ fusion market meta-morpho 0xVAULT_ADDRESS --chain ethereum
|
|
|
251
251
|
# Find IPOR Fusion contracts in the ipor-abi registry
|
|
252
252
|
fusion address lookup SupplyFuseAaveV3 --chain base
|
|
253
253
|
fusion address list --chain base
|
|
254
|
+
|
|
255
|
+
# Whitelisted fuses of a market: reuse one instead of deploying a copy
|
|
256
|
+
fusion fuse whitelist --chain arbitrum --market-id 11
|
|
254
257
|
```
|
|
255
258
|
|
|
256
259
|
## MCP Server
|
|
@@ -309,7 +312,7 @@ Available tools:
|
|
|
309
312
|
| `config_set_provider` | Set RPC provider URL for a chain (auto-detects chain ID) |
|
|
310
313
|
| `config_set_etherscan_key` | Set Etherscan API key (enables contract name resolution) |
|
|
311
314
|
| `vault_info` | Full on-chain vault state — assets, fuses, balances, fees, lending health, reconciliation |
|
|
312
|
-
| `vault_validate` | Health verdict (ok / warning / critical) with the reconciliation, lending-health and ERC20 numbers behind it |
|
|
315
|
+
| `vault_validate` | Health verdict (ok / warning / critical) with the reconciliation, lending-health and ERC20 numbers behind it, plus a warning for each fuse not active in the Fuse Whitelist |
|
|
313
316
|
| `vault_preflight` | Check execute calldata as its sender would send it: permission, fuses, balance fuses, simulation |
|
|
314
317
|
| `vault_role_accounts` | Accounts holding each AccessManager role on a vault |
|
|
315
318
|
| `vault_oracle_mapping` | Price-oracle sources per asset for a vault |
|
|
@@ -321,6 +324,7 @@ Available tools:
|
|
|
321
324
|
| `address_lookup` | IPOR Fusion contracts by name substring or address (ipor-abi registry) |
|
|
322
325
|
| `address_names` | Contract names in the registry, with the chains that have them |
|
|
323
326
|
| `address_list` | One chain's full `{name: address}` registry |
|
|
327
|
+
| `fuse_whitelist` | The fuses the chain's Fuse Whitelist lists for a market (active first) |
|
|
324
328
|
|
|
325
329
|
Configure providers and vaults via `fusion config` or the MCP config tools first.
|
|
326
330
|
|
|
@@ -202,6 +202,9 @@ fusion market meta-morpho 0xVAULT_ADDRESS --chain ethereum
|
|
|
202
202
|
# Find IPOR Fusion contracts in the ipor-abi registry
|
|
203
203
|
fusion address lookup SupplyFuseAaveV3 --chain base
|
|
204
204
|
fusion address list --chain base
|
|
205
|
+
|
|
206
|
+
# Whitelisted fuses of a market: reuse one instead of deploying a copy
|
|
207
|
+
fusion fuse whitelist --chain arbitrum --market-id 11
|
|
205
208
|
```
|
|
206
209
|
|
|
207
210
|
## MCP Server
|
|
@@ -260,7 +263,7 @@ Available tools:
|
|
|
260
263
|
| `config_set_provider` | Set RPC provider URL for a chain (auto-detects chain ID) |
|
|
261
264
|
| `config_set_etherscan_key` | Set Etherscan API key (enables contract name resolution) |
|
|
262
265
|
| `vault_info` | Full on-chain vault state — assets, fuses, balances, fees, lending health, reconciliation |
|
|
263
|
-
| `vault_validate` | Health verdict (ok / warning / critical) with the reconciliation, lending-health and ERC20 numbers behind it |
|
|
266
|
+
| `vault_validate` | Health verdict (ok / warning / critical) with the reconciliation, lending-health and ERC20 numbers behind it, plus a warning for each fuse not active in the Fuse Whitelist |
|
|
264
267
|
| `vault_preflight` | Check execute calldata as its sender would send it: permission, fuses, balance fuses, simulation |
|
|
265
268
|
| `vault_role_accounts` | Accounts holding each AccessManager role on a vault |
|
|
266
269
|
| `vault_oracle_mapping` | Price-oracle sources per asset for a vault |
|
|
@@ -272,6 +275,7 @@ Available tools:
|
|
|
272
275
|
| `address_lookup` | IPOR Fusion contracts by name substring or address (ipor-abi registry) |
|
|
273
276
|
| `address_names` | Contract names in the registry, with the chains that have them |
|
|
274
277
|
| `address_list` | One chain's full `{name: address}` registry |
|
|
278
|
+
| `fuse_whitelist` | The fuses the chain's Fuse Whitelist lists for a market (active first) |
|
|
275
279
|
|
|
276
280
|
Configure providers and vaults via `fusion config` or the MCP config tools first.
|
|
277
281
|
|
|
@@ -68,6 +68,18 @@ greppable.
|
|
|
68
68
|
`AaveV3WithPriceOracleMiddlewareBalanceFuse`, Arbitrum only the latter, so a
|
|
69
69
|
name that resolves on one chain may not exist on the next. Resolve
|
|
70
70
|
`(chain, name)` in `ipor-abi`; never reuse an address across chains.
|
|
71
|
+
A registry entry is not a whitelist entry. Before adding or deploying a
|
|
72
|
+
fuse, check the chain's Fuse Whitelist: `fusion fuse whitelist --chain base
|
|
73
|
+
--market-id 11` or the MCP tool `fuse_whitelist` lists a market's active
|
|
74
|
+
fuses. On-chain it is `IporFusionFuseWhitelistProxy` in the same
|
|
75
|
+
`addresses.json`: `getFusesByMarketId(market_id)` returns a market's fuses,
|
|
76
|
+
active and deprecated together, and only those whose
|
|
77
|
+
`getFuseByAddress(fuse)` reports `fuseState` 1 (active) belong in a new
|
|
78
|
+
vault. Use an active fuse when one covers the action. A redeployed or
|
|
79
|
+
forked copy of a whitelisted fuse is never whitelisted, and the IPOR app
|
|
80
|
+
shows its market as unknown; a fuse for an action no active fuse covers
|
|
81
|
+
goes through the whitelist review at
|
|
82
|
+
https://ipor.io/docs/build-on-fusion/integrating-a-new-market.md.
|
|
71
83
|
6. **`.send(ctx)` signs locally and needs a private key in the `Web3Context`;
|
|
72
84
|
`.call(ctx)` previews without one.** Sending through a context built with
|
|
73
85
|
`signer=` alone raises `ValueError("Private key required for sending
|
|
@@ -238,6 +250,8 @@ Resolve fuse addresses by registry name and chain from `ipor-abi`
|
|
|
238
250
|
`fusion address lookup SupplyFuseAaveV3 --chain base`, or the MCP tool
|
|
239
251
|
`address_lookup` (the hosted server's `fusion_address_lookup`). The SDK class
|
|
240
252
|
for a registry name swaps the parts: `SupplyFuseAaveV3` is `AaveV3SupplyFuse`.
|
|
253
|
+
Then confirm the fuse is active in the chain's Fuse Whitelist with
|
|
254
|
+
`fusion fuse whitelist` or the MCP tool `fuse_whitelist` (invariant 5).
|
|
241
255
|
|
|
242
256
|
## Pointers
|
|
243
257
|
|
|
@@ -146,6 +146,26 @@ from ipor_fusion.errors import (
|
|
|
146
146
|
)
|
|
147
147
|
from ipor_fusion.explorer import get_contract_name, get_deployment_tx
|
|
148
148
|
from ipor_fusion.field_docs import DOCS
|
|
149
|
+
from ipor_fusion.fuse_whitelist import (
|
|
150
|
+
FUSE_WHITELIST_READ_ERRORS,
|
|
151
|
+
FUSE_WHITELIST_REGISTRY_NAME,
|
|
152
|
+
FuseIssueKind,
|
|
153
|
+
FuseRole,
|
|
154
|
+
FuseState,
|
|
155
|
+
FuseWhitelist,
|
|
156
|
+
FuseWhitelistCheck,
|
|
157
|
+
FuseWhitelistIssue,
|
|
158
|
+
FuseWhitelistJson,
|
|
159
|
+
WhitelistEntry,
|
|
160
|
+
WhitelistEntryJson,
|
|
161
|
+
build_fuse_whitelist_json,
|
|
162
|
+
check_fuses,
|
|
163
|
+
fetch_fuse_whitelist_json,
|
|
164
|
+
fuse_whitelist_for_chain,
|
|
165
|
+
fuse_whitelist_issues,
|
|
166
|
+
read_fuse_entries,
|
|
167
|
+
read_market_fuses,
|
|
168
|
+
)
|
|
149
169
|
from ipor_fusion.fuses import (
|
|
150
170
|
AaveV3BorrowFuse,
|
|
151
171
|
AaveV3SupplyFuse,
|
|
@@ -405,6 +425,7 @@ from ipor_fusion.validation import (
|
|
|
405
425
|
VaultState,
|
|
406
426
|
VaultValidation,
|
|
407
427
|
WithdrawQueue,
|
|
428
|
+
read_vault_fuse_whitelist,
|
|
408
429
|
validate_vault,
|
|
409
430
|
validate_vault_state,
|
|
410
431
|
)
|
|
@@ -537,6 +558,24 @@ __all__ = [
|
|
|
537
558
|
"fetch_address_registries",
|
|
538
559
|
"fetch_address_registry",
|
|
539
560
|
"registry_url",
|
|
561
|
+
"FUSE_WHITELIST_READ_ERRORS",
|
|
562
|
+
"FUSE_WHITELIST_REGISTRY_NAME",
|
|
563
|
+
"FuseIssueKind",
|
|
564
|
+
"FuseRole",
|
|
565
|
+
"FuseState",
|
|
566
|
+
"FuseWhitelist",
|
|
567
|
+
"FuseWhitelistCheck",
|
|
568
|
+
"FuseWhitelistIssue",
|
|
569
|
+
"FuseWhitelistJson",
|
|
570
|
+
"WhitelistEntry",
|
|
571
|
+
"WhitelistEntryJson",
|
|
572
|
+
"build_fuse_whitelist_json",
|
|
573
|
+
"check_fuses",
|
|
574
|
+
"fetch_fuse_whitelist_json",
|
|
575
|
+
"fuse_whitelist_for_chain",
|
|
576
|
+
"fuse_whitelist_issues",
|
|
577
|
+
"read_fuse_entries",
|
|
578
|
+
"read_market_fuses",
|
|
540
579
|
"ContextManager",
|
|
541
580
|
"Call",
|
|
542
581
|
"get_logs_adaptive",
|
|
@@ -791,6 +830,7 @@ __all__ = [
|
|
|
791
830
|
"WithdrawQueue",
|
|
792
831
|
"validate_vault",
|
|
793
832
|
"validate_vault_state",
|
|
833
|
+
"read_vault_fuse_whitelist",
|
|
794
834
|
"compute_update_groups",
|
|
795
835
|
"compute_update_reach",
|
|
796
836
|
"find_markets_missing_erc20_dependency",
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""`fusion fuse whitelist` — the fuses the chain's Fuse Whitelist lists for a market."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json as json_lib
|
|
6
|
+
from datetime import UTC, datetime
|
|
7
|
+
|
|
8
|
+
import click
|
|
9
|
+
|
|
10
|
+
from ipor_fusion.cli.config_store import load_config
|
|
11
|
+
from ipor_fusion.cli.options import BLOCK_NUMBER, CHAIN, _resolve_provider
|
|
12
|
+
from ipor_fusion.cli.vault_rendering import _print_table
|
|
13
|
+
from ipor_fusion.core.context import Web3Context
|
|
14
|
+
from ipor_fusion.errors import (
|
|
15
|
+
AddressNotInRegistryError,
|
|
16
|
+
AddressRegistryError,
|
|
17
|
+
EmptyCallResultError,
|
|
18
|
+
UnsupportedChainError,
|
|
19
|
+
)
|
|
20
|
+
from ipor_fusion.fuse_whitelist import MAX_MARKET_ID, fetch_fuse_whitelist_json
|
|
21
|
+
from ipor_fusion.types import ChainId, MarketId
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@click.group()
|
|
25
|
+
def fuse() -> None:
|
|
26
|
+
"""Inspect fuses: which ones IPOR whitelists for a market."""
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@fuse.command("whitelist")
|
|
30
|
+
@click.option(
|
|
31
|
+
"--chain",
|
|
32
|
+
"chain_id",
|
|
33
|
+
type=CHAIN,
|
|
34
|
+
required=True,
|
|
35
|
+
help="Chain ID or name (ethereum, base, arbitrum, ...).",
|
|
36
|
+
)
|
|
37
|
+
@click.option(
|
|
38
|
+
"--market-id",
|
|
39
|
+
"market_id",
|
|
40
|
+
type=click.IntRange(min=0, max=MAX_MARKET_ID),
|
|
41
|
+
required=True,
|
|
42
|
+
help="Numeric market ID (IporFusionMarkets), e.g. 11 for EULER_V2.",
|
|
43
|
+
)
|
|
44
|
+
@click.option(
|
|
45
|
+
"--block-number",
|
|
46
|
+
"--block",
|
|
47
|
+
"block_number",
|
|
48
|
+
type=BLOCK_NUMBER,
|
|
49
|
+
default=None,
|
|
50
|
+
help="Block number for on-chain reads (0 or omitted: latest).",
|
|
51
|
+
)
|
|
52
|
+
@click.option(
|
|
53
|
+
"--include-deprecated",
|
|
54
|
+
is_flag=True,
|
|
55
|
+
default=False,
|
|
56
|
+
help="Also list deprecated and removed fuses.",
|
|
57
|
+
)
|
|
58
|
+
@click.option(
|
|
59
|
+
"--json",
|
|
60
|
+
"json_output",
|
|
61
|
+
is_flag=True,
|
|
62
|
+
default=False,
|
|
63
|
+
help="Emit machine-readable JSON instead of a table.",
|
|
64
|
+
)
|
|
65
|
+
def whitelist(
|
|
66
|
+
chain_id: ChainId,
|
|
67
|
+
market_id: int,
|
|
68
|
+
block_number: int | None,
|
|
69
|
+
include_deprecated: bool,
|
|
70
|
+
json_output: bool,
|
|
71
|
+
) -> None:
|
|
72
|
+
"""List the whitelisted fuses of a market: use one of these instead of
|
|
73
|
+
deploying a copy, which the IPOR app would show as unknown."""
|
|
74
|
+
ctx = Web3Context.from_url(_resolve_provider(load_config(), chain_id))
|
|
75
|
+
if block_number is not None:
|
|
76
|
+
ctx = ctx.at_block(block_number)
|
|
77
|
+
try:
|
|
78
|
+
document = fetch_fuse_whitelist_json(
|
|
79
|
+
ctx, MarketId(market_id), include_deprecated=include_deprecated
|
|
80
|
+
)
|
|
81
|
+
except (
|
|
82
|
+
AddressNotInRegistryError,
|
|
83
|
+
AddressRegistryError,
|
|
84
|
+
EmptyCallResultError,
|
|
85
|
+
UnsupportedChainError,
|
|
86
|
+
) as exc:
|
|
87
|
+
raise click.UsageError(str(exc)) from exc
|
|
88
|
+
if json_output:
|
|
89
|
+
click.echo(json_lib.dumps(document, indent=2))
|
|
90
|
+
return
|
|
91
|
+
click.secho(
|
|
92
|
+
f"Fuse Whitelist {document['whitelist']} on {document['chain']},"
|
|
93
|
+
f" market {document['market']}",
|
|
94
|
+
bold=True,
|
|
95
|
+
)
|
|
96
|
+
_print_table(
|
|
97
|
+
("Fuse", "State", "Type", "Role", "Added"),
|
|
98
|
+
[
|
|
99
|
+
(
|
|
100
|
+
f["fuse"],
|
|
101
|
+
f["state"],
|
|
102
|
+
f["type_name"],
|
|
103
|
+
f["role"] or "?",
|
|
104
|
+
datetime.fromtimestamp(f["added_at"], UTC).date().isoformat(),
|
|
105
|
+
)
|
|
106
|
+
for f in document["fuses"]
|
|
107
|
+
],
|
|
108
|
+
)
|
|
@@ -8,6 +8,7 @@ import click
|
|
|
8
8
|
from ipor_fusion.cli.address_cmd import address
|
|
9
9
|
from ipor_fusion.cli.changelog_cmd import changelog
|
|
10
10
|
from ipor_fusion.cli.config_cmd import config
|
|
11
|
+
from ipor_fusion.cli.fuse_cmd import fuse
|
|
11
12
|
from ipor_fusion.cli.market_cmd import market
|
|
12
13
|
from ipor_fusion.cli.preflight_cmd import preflight
|
|
13
14
|
from ipor_fusion.cli.vault_cmd import vault
|
|
@@ -34,6 +35,7 @@ def cli(ctx: click.Context, verbose: bool, quiet: bool, no_color: bool) -> None:
|
|
|
34
35
|
cli.add_command(address)
|
|
35
36
|
cli.add_command(changelog)
|
|
36
37
|
cli.add_command(config)
|
|
38
|
+
cli.add_command(fuse)
|
|
37
39
|
cli.add_command(market)
|
|
38
40
|
cli.add_command(vault)
|
|
39
41
|
vault.add_command(preflight)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from eth_typing import ChecksumAddress
|
|
2
2
|
|
|
3
3
|
from ipor_fusion.core.contract import Call, ContractWrapper
|
|
4
|
+
from ipor_fusion.onchain_text import sanitize_onchain_text
|
|
4
5
|
from ipor_fusion.types import Amount, Decimals
|
|
5
6
|
|
|
6
7
|
|
|
@@ -26,10 +27,14 @@ class ERC20(ContractWrapper):
|
|
|
26
27
|
return self._view("decimals()", output_types=["uint256"], decoder=Decimals)
|
|
27
28
|
|
|
28
29
|
def symbol(self) -> Call[str]:
|
|
29
|
-
return self._view(
|
|
30
|
+
return self._view(
|
|
31
|
+
"symbol()", output_types=["string"], decoder=sanitize_onchain_text
|
|
32
|
+
)
|
|
30
33
|
|
|
31
34
|
def name(self) -> Call[str]:
|
|
32
|
-
return self._view(
|
|
35
|
+
return self._view(
|
|
36
|
+
"name()", output_types=["string"], decoder=sanitize_onchain_text
|
|
37
|
+
)
|
|
33
38
|
|
|
34
39
|
def total_supply(self) -> Call[Amount]:
|
|
35
40
|
return self._view("totalSupply()", output_types=["uint256"], decoder=Amount)
|
|
@@ -18,6 +18,7 @@ from ipor_fusion.core.context import Web3Context
|
|
|
18
18
|
from ipor_fusion.core.contract import Call, ContractWrapper
|
|
19
19
|
from ipor_fusion.core.fuse_action import FuseAction
|
|
20
20
|
from ipor_fusion.errors import EmptyCallResultError, UnsupportedVaultVersionError
|
|
21
|
+
from ipor_fusion.onchain_text import sanitize_onchain_text
|
|
21
22
|
from ipor_fusion.types import (
|
|
22
23
|
ZERO_ADDRESS,
|
|
23
24
|
AccessManagerAddress,
|
|
@@ -614,7 +615,9 @@ class PlasmaVault(ContractWrapper):
|
|
|
614
615
|
return self._view("totalSupply()", output_types=["uint256"], decoder=Shares)
|
|
615
616
|
|
|
616
617
|
def name(self) -> Call[str]:
|
|
617
|
-
return self._view(
|
|
618
|
+
return self._view(
|
|
619
|
+
"name()", output_types=["string"], decoder=sanitize_onchain_text
|
|
620
|
+
)
|
|
618
621
|
|
|
619
622
|
def underlying_asset_address(self) -> Call[ChecksumAddress]:
|
|
620
623
|
return self._view(
|
{ipor_fusion-4.1.0.dev56 → ipor_fusion-4.2.0.dev9}/src/ipor_fusion/core/simulation_result.py
RENAMED
|
@@ -13,6 +13,7 @@ from eth_typing import ChecksumAddress
|
|
|
13
13
|
from hexbytes import HexBytes
|
|
14
14
|
|
|
15
15
|
from ipor_fusion.errors import SimulationError, SimulationRunError, decode_custom_error
|
|
16
|
+
from ipor_fusion.onchain_text import sanitize_onchain_text
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
class QueuedCall(Protocol):
|
|
@@ -295,7 +296,7 @@ def _decode_revert(return_data: HexBytes, error: str | None) -> str | None:
|
|
|
295
296
|
if selector == b"\x08\xc3\x79\xa0": # Error(string)
|
|
296
297
|
try:
|
|
297
298
|
(msg,) = decode(["string"], bytes(return_data[4:]))
|
|
298
|
-
return msg
|
|
299
|
+
return sanitize_onchain_text(msg)
|
|
299
300
|
except (DecodingError, OverflowError, ValueError):
|
|
300
301
|
pass
|
|
301
302
|
if selector == b"\x4e\x48\x7b\x71": # Panic(uint256)
|
|
@@ -11,6 +11,7 @@ from web3 import Web3
|
|
|
11
11
|
from web3.types import TxParams, TxReceipt
|
|
12
12
|
|
|
13
13
|
from ipor_fusion.fusion_errors import FUSION_ERROR_SIGNATURES
|
|
14
|
+
from ipor_fusion.onchain_text import sanitize_onchain_text
|
|
14
15
|
from ipor_fusion.types import TxHash
|
|
15
16
|
|
|
16
17
|
log = logging.getLogger(__name__)
|
|
@@ -95,7 +96,7 @@ def _decode_revert_reason(data: bytes) -> str:
|
|
|
95
96
|
if selector == ERROR_SELECTOR:
|
|
96
97
|
try:
|
|
97
98
|
(reason,) = abi_decode(["string"], payload)
|
|
98
|
-
return f'Error("{reason}")'
|
|
99
|
+
return f'Error("{sanitize_onchain_text(reason)}")'
|
|
99
100
|
except Exception:
|
|
100
101
|
return f"Error(<decode failed>: 0x{payload.hex()[:64]})"
|
|
101
102
|
|