ipor-fusion 4.0.0.dev159__tar.gz → 4.0.0.dev162__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.dev159 → ipor_fusion-4.0.0.dev162}/AGENTS.md +7 -5
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/MIGRATION_4.md +43 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/PKG-INFO +1 -1
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/pyproject.toml +1 -1
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/__init__.py +4 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/context.py +2 -3
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/contract.py +6 -6
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/plasma_vault.py +16 -14
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/simulation.py +124 -40
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/mcp/models.py +251 -41
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/hypercore.py +2 -2
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/vault_data.py +155 -61
- ipor_fusion-4.0.0.dev162/tests/fixtures/simulate_v1_request.json +1 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_cli_vault_predates_getters.py +9 -9
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_mcp_models.py +145 -15
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_mcp_server.py +1 -1
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_public_api.py +2 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_validation.py +20 -20
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_vault_simulator_blocks.py +62 -1
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/typed_client/consumer.py +3 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/typed_client/rejected.py +10 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/.claude-plugin/marketplace.json +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/.claude-plugin/plugin.json +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/.env.example +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/.gemini/settings.json +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/.git-blame-ignore-revs +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/.github/workflows/cd.yml +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/.github/workflows/ci.yml +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/.github/workflows/commit-lint.yml +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/.github/workflows/notify-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/.github/workflows/python-build.yml +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/.github/workflows/python-publish.yml +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/.github/workflows/release.yml +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/.github/workflows/report-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/.gitignore +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/.pre-commit-config.yaml +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/.python-version +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/CHANGELOG.md +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/CLAUDE.md +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/CODEOWNERS +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/LICENSE +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/README.md +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/build.sh +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/examples/CONTRIBUTING.md +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/examples/README.md +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/examples/advanced_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/examples/advanced_euler_v2_looping_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/examples/composed_hypercore_flow_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/examples/external_state_margin_leg_base.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/examples/simple_aave_v3_supply_base.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/pytest.ini +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/scripts/commit-check.sh +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/scripts/crosschain_readiness.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/skills/ipor-deploy-vault/SKILL.md +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/about.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cache.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/chains.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/changelog_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/config_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/config_store.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/main.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/market_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/options.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/oracle_mapping_view.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/vault_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/vault_health.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/vault_info_view.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/vault_markets_view.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/vault_rendering.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/config/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/config/roles.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/access.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/address.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/erc20.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/external_state_executor.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/fee_manager.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/fuse.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/fuse_action.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/fusion_factory.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/logs.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/multicall.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/oracle.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/rewards_manager.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/ccip/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/ccip/chainlink.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/ccip/codec.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/ccip/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/ccip/events.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/ccip/indexer.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/ccip/lane.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/ccip/quote.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/ccip/transport.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/discovery.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/errors.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/fuses/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/fuses/base.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/fuses/ccip.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/fuses/stargate.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/lane.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/logs.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/messages.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/simulation.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/stargate/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/stargate/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/stargate/lane.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/stargate/layerzero.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/stargate/transport.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/transport.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/dependency_graph.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/entry_cli.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/entry_mcp.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/errors.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/explorer.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/field_docs.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/aave_v3.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/async_action.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/base.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/erc4626.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/euler_v2.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/events.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/external_state.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/external_state_events.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/fluid_instadapp.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/gearbox_v3.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/hypercore_events.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/merkl.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/morpho.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/universal.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/guide/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/guide/architecture.md +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/guide/glossary.md +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/guide/invariants.md +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/guide/quickstart.md +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/market_ids.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/market_info.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/mcp/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/mcp/guide.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/mcp/server.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/morpho_api.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/py.typed +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/aave_v3.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/aave_v4.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/hypercore_outcome.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/lending_health.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/morpho.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/oracle_mapping_nodes.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/oracle_mapping_reader.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/position_manager.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/unpriceable.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/substrates.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/types.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/validation.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/vault_erc20.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/vault_info.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/vault_managers.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/vault_positions.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/vault_reads.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/UniswapV3UniversalRouter.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/_crosschain_recovery.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/_euler_v2.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/_event_args.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/_foundry.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/_guide.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/_hypercore_model.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/_hypercore_shadow.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/_simulate.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/_validation.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/addresses.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/conftest.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/constants.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/fixtures/hypercore_hip3_flow.json +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/fixtures/hypercore_market55.json +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/fixtures/vault_info_golden/clean.json +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/fixtures/vault_info_golden/clean.txt +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/fixtures/vault_info_golden/rich.json +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/fixtures/vault_info_golden/rich.txt +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_about.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_access_manager.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_cache.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_chains.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_cli_changelog.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_cli_commands.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_cli_config_store.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_cli_helpers.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_cli_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_cli_lending_health.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_cli_market_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_cli_oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_cli_pending_requests_scan.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_cli_role_accounts.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_cli_vault_info_golden.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_cli_vault_validate.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_contract_call.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_contract_encoder.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_ccip_events.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_ccip_indexer.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_ccip_quote.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_chainlink.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_contracts.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_errors.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_lane.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_layering.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_readiness.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_readiness_report.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_transport.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_docs_typing.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_erc20.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_error_hierarchy.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_examples_composed_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_examples_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_examples_euler_looping_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_examples_vaults.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_explorer.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_external_state_events.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_external_state_executor.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_fee_manager.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_fuse_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_fusion_instance.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_guide.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_hypercore_deployment.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_hypercore_events.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_hypercore_flow.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_hypercore_live.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_hypercore_outcome.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_hypercore_readers.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_hypercore_simulation.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_logs.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_mcp_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_mcp_vault_validate.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_oracle.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_plasma_vault.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_public_type_reachability.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_reader_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_readiness_selection.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_revert_decoding.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_rewards_manager.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_roles.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_sdk_layering.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_borrow_aave_v3_mainnet.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_claim_merkl_wrapper_base.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_claim_morpho_rewards.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_crosschain_canary.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_crosschain_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_crosschain_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_euler_v2_batch_base.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_euler_v2_swap_deploy_base.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_euler_v2_swap_reconfigure_base.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_euler_v2_swap_registry_base.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_examples_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_examples_base.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_examples_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_external_state_executor_base.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_fusion_factory_clone_base.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_looping_aave_v3_base.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_looping_morpho_blue_base.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_pilot_v3.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_pilot_v4_uniswap.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_pilot_v5_ramses.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_pilot_v5_scheduled.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_plasma_vault_setters_base.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_readers_integration.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_release_funds.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_swap_on_base.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_vault_from_scratch_base.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_simulation_observation.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_solidity_compiler.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_solidity_mirrors.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_substrates.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_types_and_events.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_unpriceable_tokens.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_vault_data_block.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_vault_dep_graph.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_vault_info_onchain_base.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_vault_info_onchain_base_no_withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_web3_context.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/tests/test_withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev159 → ipor_fusion-4.0.0.dev162}/uv.lock +0 -0
|
@@ -449,11 +449,13 @@ schema. Adding a field to `build_vault_info_json` (or a `fusion market` document
|
|
|
449
449
|
means adding it to its TypedDict, to the matching model (with a default for
|
|
450
450
|
back-compat) and to the `_full_vault_info_dict` fixture;
|
|
451
451
|
`TestTypedDocumentsMirrorModels` in `test_mcp_models.py` holds every TypedDict to
|
|
452
|
-
its model block by block
|
|
453
|
-
|
|
454
|
-
`
|
|
455
|
-
|
|
456
|
-
|
|
452
|
+
its model block by block, a union block (`deployment`, `position_breakdown`,
|
|
453
|
+
`source_detail`) shape by shape. Every block is a model; a block whose optional keys
|
|
454
|
+
the producer omits is a `_Sparse` model, which dumps only the fields it was given,
|
|
455
|
+
so the key stays absent rather than null. `TestNestedBlocksDumpVerbatim` pins that
|
|
456
|
+
the typed blocks dump exactly what the producer wrote. The substrate entries stay
|
|
457
|
+
open-ended on both sides (`SubstrateEntryJson`, `dict[str, str | bool]`): each
|
|
458
|
+
decoder adds its own fields.
|
|
457
459
|
|
|
458
460
|
## Domain rules (verified against the contracts)
|
|
459
461
|
|
|
@@ -741,6 +741,28 @@ fuse's `eid=` take it (`LayerZeroEid(30101)`). CCIP chain selectors are
|
|
|
741
741
|
(`CcipChainSelector(4949039107694359620)`). `ZERO_ADDRESS` is a `ChecksumAddress`
|
|
742
742
|
(same value).
|
|
743
743
|
|
|
744
|
+
**Simulation.** The `VaultSimulator` override methods name the keys `eth_simulateV1`
|
|
745
|
+
accepts instead of taking `**Any`; the keys and the request they produce are
|
|
746
|
+
unchanged. `with_state_override(address, **overrides)` takes `AccountOverride` keys
|
|
747
|
+
(`balance`, `nonce`, `code`, `movePrecompileToAddress`: `0x` hex strings; `state`,
|
|
748
|
+
`stateDiff`: `0x` slot to `0x` word), and a `StateOverrideProvider` returns
|
|
749
|
+
`Mapping[str, AccountOverride]`. `with_block_override(**fields)` takes
|
|
750
|
+
`BlockOverrides` keys (`number`, `time`, `gasLimit`, `baseFeePerGas`, `blobBaseFee`:
|
|
751
|
+
an `int`, sent as hex, or a hex string; `feeRecipient`, `prevRandao`: strings) and
|
|
752
|
+
raises `TypeError` for any other value type (`withdrawals` is not supported).
|
|
753
|
+
Both TypedDicts are exported from `ipor_fusion`. A misspelled key or an `int` balance
|
|
754
|
+
now fails type checking instead of reaching the node:
|
|
755
|
+
|
|
756
|
+
```python
|
|
757
|
+
sim.with_state_override(holder, balance=hex(10**18), nonce=hex(0))
|
|
758
|
+
sim.with_block_override(gasLimit=30_000_000)
|
|
759
|
+
sim.with_state_override_provider(lambda n: {oracle: {"code": code_hex}})
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
`add_transaction(transaction)` takes web3's `TxParams`, the shape
|
|
763
|
+
`Call.build_transaction` returns; a node-shaped dict carrying `input` instead of `data`
|
|
764
|
+
is still accepted at run time.
|
|
765
|
+
|
|
744
766
|
**HyperCore (preview).** The fuses, `HyperCoreSubstrates`, `HyperCoreReader`,
|
|
745
767
|
`read_hypercore_transfer_snapshot` and the helpers `system_address`,
|
|
746
768
|
`precompile_index_of`, `perp_dex_of`, `is_native_perp_asset`, `is_hip3_asset` take the
|
|
@@ -774,6 +796,11 @@ except as listed under [Behavior changes](#behavior-changes)): `chain_id` fields
|
|
|
774
796
|
string). Calling an MCP tool function
|
|
775
797
|
directly from Python takes `ChainId`. Their amount, decimals and time fields stay
|
|
776
798
|
`int`: they are JSON output models, and the SDK values above fit them unchanged.
|
|
799
|
+
The nested blocks that were `dict[str, Any]` are models now (`deployment`,
|
|
800
|
+
`share_price`, `links`, `dependency_graph`, a balance fuse's `position_breakdown`, an
|
|
801
|
+
oracle node's `source_detail`, the Morpho `asset`, `adapters`, `caps`,
|
|
802
|
+
`liquidity_adapter`, `public_allocator` and `allocations`): read them by attribute
|
|
803
|
+
(`result.caps[0].loan_token`, not `["loan_token"]`).
|
|
777
804
|
|
|
778
805
|
## Typed JSON documents
|
|
779
806
|
|
|
@@ -838,6 +865,22 @@ that only some entries carry is `NotRequired` (a balance fuse's `pct_of_total` a
|
|
|
838
865
|
These apply to every caller, type-checked or not. Changes described in full above
|
|
839
866
|
are listed with a link.
|
|
840
867
|
|
|
868
|
+
- **MCP `outputSchema` describes every nested block.** The tool output is
|
|
869
|
+
byte-identical; the schemas of `vault_info`, `vault_oracle_mapping`,
|
|
870
|
+
`market_morpho_blue` and `market_meta_morpho` replace each free-form object with
|
|
871
|
+
the block's own definition: `links` (`VaultLinks`), `deployment`
|
|
872
|
+
(`DeploymentModel` or `DeploymentErrorModel`), `share_price` (`SharePriceModel`),
|
|
873
|
+
`dependency_graph` (`DependencyGraphModel`), `position_breakdown` (a list of
|
|
874
|
+
`MorphoBreakdownEntry` or of `AaveBreakdownEntry`, amounts `BreakdownAmount`),
|
|
875
|
+
substrate entries (string or boolean values), `source_detail` (`ChainlinkDetail`,
|
|
876
|
+
`DualXrefDetail`, `Erc4626Detail`, `MorphoFeedDetail` or
|
|
877
|
+
`MiddlewareFallbackDetail`), a supplying vault's `asset` (`MorphoVaultAssetModel`)
|
|
878
|
+
and the MetaMorpho `asset`, `liquidity_adapter` / `adapters`, `caps`,
|
|
879
|
+
`public_allocator` (with `flow_caps`) and `allocations`. Fixed-shape blocks now declare their
|
|
880
|
+
required and optional fields and reject unknown keys (`additionalProperties:
|
|
881
|
+
false`), as the documents always wrote them; substrate entries and keyed maps
|
|
882
|
+
(`flow_caps`, `edges`, `update_reach`) stay open with typed values.
|
|
883
|
+
|
|
841
884
|
- **Vault reads are pinned to one block**: every read of `fetch_vault_data`, log
|
|
842
885
|
scans included, runs at the resolved block; see
|
|
843
886
|
[Vault reads and validation](#vault-reads-and-validation).
|
|
@@ -72,6 +72,8 @@ from ipor_fusion.core.plasma_vault import (
|
|
|
72
72
|
)
|
|
73
73
|
from ipor_fusion.core.rewards_manager import RewardsManager, VestingData
|
|
74
74
|
from ipor_fusion.core.simulation import (
|
|
75
|
+
AccountOverride,
|
|
76
|
+
BlockOverrides,
|
|
75
77
|
SimulatedCallResult,
|
|
76
78
|
SimulationObservation,
|
|
77
79
|
SimulationResult,
|
|
@@ -649,6 +651,8 @@ __all__ = [
|
|
|
649
651
|
"MULTICALL3_ADDRESS",
|
|
650
652
|
"VaultSimulator",
|
|
651
653
|
"StateOverrideProvider",
|
|
654
|
+
"AccountOverride",
|
|
655
|
+
"BlockOverrides",
|
|
652
656
|
"SimulationObservation",
|
|
653
657
|
"SimulationResult",
|
|
654
658
|
"SimulatedCallResult",
|
|
@@ -3,7 +3,6 @@ from __future__ import annotations
|
|
|
3
3
|
import copy
|
|
4
4
|
import logging
|
|
5
5
|
import threading
|
|
6
|
-
from typing import Any
|
|
7
6
|
|
|
8
7
|
from eth_account import Account
|
|
9
8
|
from eth_typing import ChecksumAddress, HexStr
|
|
@@ -453,7 +452,7 @@ class InFlightLimit:
|
|
|
453
452
|
def _slot_middleware(slots: threading.BoundedSemaphore) -> type[Web3Middleware]:
|
|
454
453
|
class InFlightLimitMiddleware(Web3Middleware):
|
|
455
454
|
def wrap_make_request(self, make_request: MakeRequestFn) -> MakeRequestFn:
|
|
456
|
-
def limited(method: RPCEndpoint, params:
|
|
455
|
+
def limited(method: RPCEndpoint, params: object) -> RPCResponse:
|
|
457
456
|
with slots:
|
|
458
457
|
return make_request(method, params)
|
|
459
458
|
|
|
@@ -463,7 +462,7 @@ def _slot_middleware(slots: threading.BoundedSemaphore) -> type[Web3Middleware]:
|
|
|
463
462
|
self, make_batch_request: MakeBatchRequestFn
|
|
464
463
|
) -> MakeBatchRequestFn:
|
|
465
464
|
def limited(
|
|
466
|
-
requests_info: list[tuple[RPCEndpoint,
|
|
465
|
+
requests_info: list[tuple[RPCEndpoint, object]],
|
|
467
466
|
) -> list[RPCResponse] | RPCResponse:
|
|
468
467
|
with slots:
|
|
469
468
|
return make_batch_request(requests_info)
|
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from collections.abc import Callable
|
|
4
4
|
from dataclasses import dataclass
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import Generic, TypeVar, cast
|
|
6
6
|
|
|
7
7
|
from eth_abi import decode, encode
|
|
8
8
|
from eth_typing import ChecksumAddress
|
|
@@ -60,7 +60,7 @@ class Call(Generic[T_co]):
|
|
|
60
60
|
raise ValueError("cannot map a write-only Call without output types")
|
|
61
61
|
decoder = self.decoder
|
|
62
62
|
|
|
63
|
-
def mapped(value:
|
|
63
|
+
def mapped(value: object) -> U:
|
|
64
64
|
decoded = decoder(value) if decoder is not None else cast(T_co, value)
|
|
65
65
|
return transform(decoded)
|
|
66
66
|
|
|
@@ -101,7 +101,7 @@ class Call(Generic[T_co]):
|
|
|
101
101
|
if not self.output_types:
|
|
102
102
|
raise ValueError("Call.decode() on a write-only Call.")
|
|
103
103
|
values = tuple(decode(self.output_types, bytes(raw)))
|
|
104
|
-
single:
|
|
104
|
+
single: object = values[0] if len(values) == 1 else values
|
|
105
105
|
if self.decoder is not None:
|
|
106
106
|
return self.decoder(single)
|
|
107
107
|
return cast(T_co, single)
|
|
@@ -148,7 +148,7 @@ class ContractWrapper:
|
|
|
148
148
|
def _view(
|
|
149
149
|
self,
|
|
150
150
|
signature: str,
|
|
151
|
-
*args:
|
|
151
|
+
*args: object,
|
|
152
152
|
output_types: list[str],
|
|
153
153
|
decoder: Callable[..., T] | None = None,
|
|
154
154
|
) -> Call[T]:
|
|
@@ -159,11 +159,11 @@ class ContractWrapper:
|
|
|
159
159
|
decoder=decoder,
|
|
160
160
|
)
|
|
161
161
|
|
|
162
|
-
def _write(self, signature: str, *args:
|
|
162
|
+
def _write(self, signature: str, *args: object) -> Call[None]:
|
|
163
163
|
return Call(to=self._address, data=_encode_calldata(signature, *args))
|
|
164
164
|
|
|
165
165
|
|
|
166
|
-
def _encode_calldata(signature: str, *args:
|
|
166
|
+
def _encode_calldata(signature: str, *args: object) -> bytes:
|
|
167
167
|
selector = function_signature_to_4byte_selector(signature)
|
|
168
168
|
types = _parse_param_types(signature)
|
|
169
169
|
return selector + encode(types, list(args)) if types else selector
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
from collections.abc import Callable, Sequence
|
|
4
4
|
from concurrent.futures import ThreadPoolExecutor
|
|
5
5
|
from dataclasses import dataclass
|
|
6
|
-
from typing import
|
|
6
|
+
from typing import TypeVar, cast
|
|
7
7
|
|
|
8
8
|
from eth_abi import decode, encode
|
|
9
9
|
from eth_typing import ChecksumAddress
|
|
@@ -91,19 +91,21 @@ def _market_id_list_decoder(value: list) -> list[MarketId]:
|
|
|
91
91
|
_BALANCE_OF_SELECTOR = function_signature_to_4byte_selector("balanceOf()")
|
|
92
92
|
|
|
93
93
|
|
|
94
|
+
def _read_result_data(result: tuple[bytes]) -> bytes:
|
|
95
|
+
"""``ReadResult.data``, undecoded."""
|
|
96
|
+
return bytes(result[0])
|
|
97
|
+
|
|
98
|
+
|
|
94
99
|
def _universal_read_decoder(
|
|
95
|
-
output_types: list[str]
|
|
96
|
-
) -> Callable[[tuple],
|
|
97
|
-
"""Unwrap ``ReadResult.data`` and
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
def _decode(result: tuple) ->
|
|
101
|
-
|
|
102
|
-
if
|
|
103
|
-
|
|
104
|
-
values = tuple(decode(output_types, payload))
|
|
105
|
-
single: Any = values[0] if len(values) == 1 else values
|
|
106
|
-
return decoder(single) if decoder is not None else single
|
|
100
|
+
output_types: list[str], decoder: Callable[..., T] | None
|
|
101
|
+
) -> Callable[[tuple[bytes]], T]:
|
|
102
|
+
"""Unwrap ``ReadResult.data`` and decode it the way `Call.decode` decodes a
|
|
103
|
+
view's return data."""
|
|
104
|
+
|
|
105
|
+
def _decode(result: tuple[bytes]) -> T:
|
|
106
|
+
values = tuple(decode(output_types, _read_result_data(result)))
|
|
107
|
+
single: object = values[0] if len(values) == 1 else values
|
|
108
|
+
return decoder(single) if decoder is not None else cast(T, single)
|
|
107
109
|
|
|
108
110
|
return _decode
|
|
109
111
|
|
|
@@ -265,7 +267,7 @@ class PlasmaVault(ContractWrapper):
|
|
|
265
267
|
target,
|
|
266
268
|
data,
|
|
267
269
|
output_types=["(bytes)"],
|
|
268
|
-
decoder=
|
|
270
|
+
decoder=_read_result_data,
|
|
269
271
|
)
|
|
270
272
|
|
|
271
273
|
def universal_read_decoded(
|
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from collections.abc import Callable, Mapping
|
|
4
4
|
from dataclasses import dataclass, field
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import Final, Generic, NotRequired, TypedDict, TypeVar, Unpack
|
|
6
6
|
|
|
7
7
|
from eth_abi import decode, encode
|
|
8
8
|
from eth_abi.exceptions import DecodingError
|
|
@@ -10,7 +10,7 @@ from eth_typing import ChecksumAddress
|
|
|
10
10
|
from eth_utils import keccak
|
|
11
11
|
from hexbytes import HexBytes
|
|
12
12
|
from web3 import Web3
|
|
13
|
-
from web3.types import BlockIdentifier, Nonce, RPCEndpoint, Timestamp
|
|
13
|
+
from web3.types import BlockIdentifier, Nonce, RPCEndpoint, Timestamp, TxParams
|
|
14
14
|
from web3.utils.address import get_create_address
|
|
15
15
|
|
|
16
16
|
from ipor_fusion.core.contract import Call, _encode_calldata
|
|
@@ -27,12 +27,78 @@ from ipor_fusion.types import PlasmaVaultAddress
|
|
|
27
27
|
T = TypeVar("T")
|
|
28
28
|
T_co = TypeVar("T_co", covariant=True)
|
|
29
29
|
|
|
30
|
+
|
|
31
|
+
class AccountOverride(TypedDict, total=False):
|
|
32
|
+
"""One account's ``eth_simulateV1`` state override, sent as given:
|
|
33
|
+
quantities and code are ``0x`` hex strings, storage maps a ``0x`` slot to a
|
|
34
|
+
``0x`` word. ``state`` replaces the account's storage, ``stateDiff``
|
|
35
|
+
patches it."""
|
|
36
|
+
|
|
37
|
+
balance: str
|
|
38
|
+
nonce: str
|
|
39
|
+
code: str
|
|
40
|
+
state: Mapping[str, str]
|
|
41
|
+
stateDiff: Mapping[str, str]
|
|
42
|
+
movePrecompileToAddress: str
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class BlockOverrides(TypedDict, total=False):
|
|
46
|
+
"""``eth_simulateV1`` block overrides; an ``int`` is sent as ``0x`` hex."""
|
|
47
|
+
|
|
48
|
+
number: int | str
|
|
49
|
+
time: int | str
|
|
50
|
+
gasLimit: int | str
|
|
51
|
+
feeRecipient: str
|
|
52
|
+
prevRandao: str
|
|
53
|
+
baseFeePerGas: int | str
|
|
54
|
+
blobBaseFee: int | str
|
|
55
|
+
|
|
56
|
+
|
|
30
57
|
#: ``n`` (the sent block's index in the run) -> account overrides for it.
|
|
31
|
-
StateOverrideProvider = Callable[[int], Mapping[str,
|
|
58
|
+
StateOverrideProvider = Callable[[int], Mapping[str, AccountOverride]]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class _AccessListEntry(TypedDict):
|
|
62
|
+
address: ChecksumAddress
|
|
63
|
+
storageKeys: list[str]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
# One entry of a block's ``calls``; functional syntax because ``from`` is a
|
|
67
|
+
# keyword. ``to`` is absent for a contract creation.
|
|
68
|
+
_SimulatedCall = TypedDict(
|
|
69
|
+
"_SimulatedCall",
|
|
70
|
+
{
|
|
71
|
+
"from": NotRequired[ChecksumAddress],
|
|
72
|
+
"to": NotRequired[ChecksumAddress],
|
|
73
|
+
"input": str,
|
|
74
|
+
"nonce": NotRequired[str],
|
|
75
|
+
"gas": NotRequired[str],
|
|
76
|
+
"value": NotRequired[str],
|
|
77
|
+
"chainId": NotRequired[str],
|
|
78
|
+
"type": NotRequired[str],
|
|
79
|
+
"gasPrice": NotRequired[str],
|
|
80
|
+
"maxFeePerGas": NotRequired[str],
|
|
81
|
+
"maxPriorityFeePerGas": NotRequired[str],
|
|
82
|
+
"accessList": NotRequired[list[_AccessListEntry]],
|
|
83
|
+
},
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class _BlockStateCall(TypedDict):
|
|
88
|
+
calls: list[_SimulatedCall]
|
|
89
|
+
blockOverrides: dict[str, str]
|
|
90
|
+
stateOverrides: NotRequired[dict[str, AccountOverride]]
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class _SimulateRequest(TypedDict):
|
|
94
|
+
blockStateCalls: list[_BlockStateCall]
|
|
95
|
+
validation: bool
|
|
96
|
+
traceTransfers: bool
|
|
97
|
+
|
|
32
98
|
|
|
33
99
|
DEFAULT_BLOCK_TIME_INCREMENT = 12
|
|
34
100
|
|
|
35
|
-
_TRANSACTION_QUANTITIES = (
|
|
101
|
+
_TRANSACTION_QUANTITIES: Final = (
|
|
36
102
|
"nonce",
|
|
37
103
|
"gas",
|
|
38
104
|
"value",
|
|
@@ -64,15 +130,15 @@ class _Call:
|
|
|
64
130
|
gas: int | None = None
|
|
65
131
|
predicted_address: ChecksumAddress | None = None
|
|
66
132
|
# A complete serialized transaction (`add_transaction`), sent as is.
|
|
67
|
-
transaction:
|
|
133
|
+
transaction: _SimulatedCall | None = None
|
|
68
134
|
observation: SimulationObservation[object] | None = None
|
|
69
135
|
|
|
70
136
|
|
|
71
137
|
@dataclass(slots=True)
|
|
72
138
|
class _Block:
|
|
73
139
|
calls: list[_Call] = field(default_factory=list)
|
|
74
|
-
block_overrides: dict[str,
|
|
75
|
-
state_overrides: dict[str,
|
|
140
|
+
block_overrides: dict[str, str] = field(default_factory=dict)
|
|
141
|
+
state_overrides: dict[str, AccountOverride] = field(default_factory=dict)
|
|
76
142
|
override_provider: StateOverrideProvider | None = None
|
|
77
143
|
|
|
78
144
|
|
|
@@ -297,15 +363,21 @@ class VaultSimulator:
|
|
|
297
363
|
self._current.block_overrides["time"] = hex(self._baseline() + int(seconds))
|
|
298
364
|
return self
|
|
299
365
|
|
|
300
|
-
def with_block_override(self, **fields:
|
|
366
|
+
def with_block_override(self, **fields: Unpack[BlockOverrides]) -> VaultSimulator:
|
|
367
|
+
"""Set block overrides on the current block, in the order given."""
|
|
301
368
|
for key, value in fields.items():
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
)
|
|
369
|
+
if isinstance(value, int):
|
|
370
|
+
value = hex(value)
|
|
371
|
+
elif not isinstance(value, str):
|
|
372
|
+
raise TypeError(
|
|
373
|
+
f"block override {key} must be an int or a hex string, "
|
|
374
|
+
f"got {type(value).__name__}"
|
|
375
|
+
)
|
|
376
|
+
self._current.block_overrides[key] = value
|
|
305
377
|
return self
|
|
306
378
|
|
|
307
379
|
def with_state_override(
|
|
308
|
-
self, address: ChecksumAddress, **overrides:
|
|
380
|
+
self, address: ChecksumAddress, **overrides: Unpack[AccountOverride]
|
|
309
381
|
) -> VaultSimulator:
|
|
310
382
|
"""Merge an account override into the current block.
|
|
311
383
|
|
|
@@ -313,9 +385,9 @@ class VaultSimulator:
|
|
|
313
385
|
a later ``stateDiff`` patches it. One call cannot contain both forms.
|
|
314
386
|
"""
|
|
315
387
|
checksum_address = Web3.to_checksum_address(address)
|
|
316
|
-
current = self._current.state_overrides.get(checksum_address
|
|
388
|
+
current = self._current.state_overrides.get(checksum_address)
|
|
317
389
|
self._current.state_overrides[checksum_address] = _compose_account_overrides(
|
|
318
|
-
current, overrides
|
|
390
|
+
current or AccountOverride(), overrides
|
|
319
391
|
)
|
|
320
392
|
return self
|
|
321
393
|
|
|
@@ -455,7 +527,7 @@ class VaultSimulator:
|
|
|
455
527
|
return self
|
|
456
528
|
|
|
457
529
|
def add_transaction(
|
|
458
|
-
self, transaction:
|
|
530
|
+
self, transaction: TxParams, label: str | None = None
|
|
459
531
|
) -> VaultSimulator:
|
|
460
532
|
"""Queue a complete transaction dict exactly as a signer would receive it,
|
|
461
533
|
e.g. the output of `Call.build_transaction` or `Web3Context.build_transaction`.
|
|
@@ -465,7 +537,8 @@ class VaultSimulator:
|
|
|
465
537
|
signed rather than a call rebuilt from its calldata. With
|
|
466
538
|
``validation=True`` the node also checks nonce, fees and balance. The
|
|
467
539
|
result counts toward ``success`` and ``gas_used`` like `execute`. An
|
|
468
|
-
unknown key raises instead of being dropped.
|
|
540
|
+
unknown key raises instead of being dropped. The calldata may come as
|
|
541
|
+
``input`` instead of ``data``.
|
|
469
542
|
"""
|
|
470
543
|
unknown = set(transaction) - _TRANSACTION_KEYS
|
|
471
544
|
if unknown:
|
|
@@ -474,7 +547,7 @@ class VaultSimulator:
|
|
|
474
547
|
raise ValueError("transaction cannot carry both data and input")
|
|
475
548
|
if not transaction.get("from") or not transaction.get("to"):
|
|
476
549
|
raise ValueError("transaction requires from and to")
|
|
477
|
-
data = HexBytes(
|
|
550
|
+
data = HexBytes(_transaction_data(transaction))
|
|
478
551
|
serialized = _serialize_transaction(transaction, data)
|
|
479
552
|
self._current.calls.append(
|
|
480
553
|
_Call(
|
|
@@ -562,12 +635,12 @@ class VaultSimulator:
|
|
|
562
635
|
if not non_empty_blocks:
|
|
563
636
|
raise ValueError("No calls buffered — call execute() or observe() first")
|
|
564
637
|
|
|
565
|
-
block_state_calls: list[
|
|
638
|
+
block_state_calls: list[_BlockStateCall] = []
|
|
566
639
|
# A block with no calls is not sent, but its overrides still apply to
|
|
567
640
|
# everything after it (state carries between blocks), so they fold
|
|
568
641
|
# into the next block that is sent; that block's own values win.
|
|
569
|
-
block_overrides: dict[str,
|
|
570
|
-
state_overrides: dict[str,
|
|
642
|
+
block_overrides: dict[str, str] = {}
|
|
643
|
+
state_overrides: dict[str, AccountOverride] = {}
|
|
571
644
|
modeled_time = self._baseline()
|
|
572
645
|
previous_sent_time = modeled_time
|
|
573
646
|
provider: StateOverrideProvider | None = None
|
|
@@ -591,21 +664,22 @@ class VaultSimulator:
|
|
|
591
664
|
if modeled_time <= previous_sent_time:
|
|
592
665
|
raise ValueError("simulated block times must be strictly increasing")
|
|
593
666
|
previous_sent_time = modeled_time
|
|
594
|
-
entry:
|
|
595
|
-
"calls": [self._serialize_call(c) for c in block.calls]
|
|
667
|
+
entry: _BlockStateCall = {
|
|
668
|
+
"calls": [self._serialize_call(c) for c in block.calls],
|
|
669
|
+
"blockOverrides": block_overrides,
|
|
596
670
|
}
|
|
597
|
-
entry["blockOverrides"] = block_overrides
|
|
598
671
|
if state_overrides:
|
|
599
672
|
entry["stateOverrides"] = state_overrides
|
|
600
673
|
block_state_calls.append(entry)
|
|
601
674
|
block_overrides, state_overrides = {}, {}
|
|
602
675
|
|
|
676
|
+
request: _SimulateRequest = {
|
|
677
|
+
"blockStateCalls": block_state_calls,
|
|
678
|
+
"validation": self._validation,
|
|
679
|
+
"traceTransfers": self._trace_transfers,
|
|
680
|
+
}
|
|
603
681
|
payload = [
|
|
604
|
-
|
|
605
|
-
"blockStateCalls": block_state_calls,
|
|
606
|
-
"validation": self._validation,
|
|
607
|
-
"traceTransfers": self._trace_transfers,
|
|
608
|
-
},
|
|
682
|
+
request,
|
|
609
683
|
self._block if isinstance(self._block, str) else hex(int(self._block)),
|
|
610
684
|
]
|
|
611
685
|
|
|
@@ -618,10 +692,10 @@ class VaultSimulator:
|
|
|
618
692
|
|
|
619
693
|
return self._parse_response(response["result"])
|
|
620
694
|
|
|
621
|
-
def _serialize_call(self, call: _Call) ->
|
|
695
|
+
def _serialize_call(self, call: _Call) -> _SimulatedCall:
|
|
622
696
|
if call.transaction is not None:
|
|
623
|
-
return
|
|
624
|
-
out:
|
|
697
|
+
return call.transaction.copy()
|
|
698
|
+
out: _SimulatedCall = {"input": "0x" + call.data.hex()}
|
|
625
699
|
if call.to is not None:
|
|
626
700
|
out["to"] = call.to
|
|
627
701
|
if call.from_:
|
|
@@ -699,10 +773,20 @@ class VaultSimulator:
|
|
|
699
773
|
)
|
|
700
774
|
|
|
701
775
|
|
|
702
|
-
def
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
776
|
+
def _transaction_data(transaction: TxParams) -> bytes | bytearray | str:
|
|
777
|
+
"""The calldata under ``data``, or under ``input``, which `TxParams` does
|
|
778
|
+
not name but a node-shaped transaction carries."""
|
|
779
|
+
if "data" in transaction:
|
|
780
|
+
return transaction["data"]
|
|
781
|
+
fields: Mapping[str, object] = transaction
|
|
782
|
+
data = fields.get("input", b"")
|
|
783
|
+
if not isinstance(data, bytes | bytearray | str):
|
|
784
|
+
raise TypeError(f"transaction input must be bytes or hex, got {data!r}")
|
|
785
|
+
return data
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
def _serialize_transaction(transaction: TxParams, data: HexBytes) -> _SimulatedCall:
|
|
789
|
+
out: _SimulatedCall = {
|
|
706
790
|
"from": Web3.to_checksum_address(transaction["from"]),
|
|
707
791
|
"to": Web3.to_checksum_address(transaction["to"]),
|
|
708
792
|
"input": data.to_0x_hex(),
|
|
@@ -723,7 +807,7 @@ def _serialize_transaction(
|
|
|
723
807
|
|
|
724
808
|
|
|
725
809
|
def _apply_override_provider(
|
|
726
|
-
overrides: dict[str,
|
|
810
|
+
overrides: dict[str, AccountOverride],
|
|
727
811
|
provider: StateOverrideProvider | None,
|
|
728
812
|
sent_block: int,
|
|
729
813
|
) -> None:
|
|
@@ -732,18 +816,18 @@ def _apply_override_provider(
|
|
|
732
816
|
return
|
|
733
817
|
for address, fields in provider(sent_block).items():
|
|
734
818
|
overrides[address] = _compose_account_overrides(
|
|
735
|
-
|
|
819
|
+
AccountOverride(**fields), overrides.get(address) or AccountOverride()
|
|
736
820
|
)
|
|
737
821
|
|
|
738
822
|
|
|
739
823
|
def _compose_account_overrides(
|
|
740
|
-
earlier:
|
|
741
|
-
) ->
|
|
824
|
+
earlier: AccountOverride, later: AccountOverride
|
|
825
|
+
) -> AccountOverride:
|
|
742
826
|
for fields in (earlier, later):
|
|
743
827
|
if "state" in fields and "stateDiff" in fields:
|
|
744
828
|
raise ValueError("account override cannot contain both state and stateDiff")
|
|
745
829
|
|
|
746
|
-
merged = {**earlier, **later}
|
|
830
|
+
merged: AccountOverride = {**earlier, **later}
|
|
747
831
|
if "state" in later:
|
|
748
832
|
merged["state"] = dict(later["state"])
|
|
749
833
|
merged.pop("stateDiff", None)
|