ipor-fusion 4.0.0.dev156__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.dev156 → ipor_fusion-4.0.0.dev162}/AGENTS.md +7 -5
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/MIGRATION_4.md +62 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/PKG-INFO +1 -1
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/pyproject.toml +1 -1
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/__init__.py +86 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/oracle_mapping_view.py +9 -5
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/context.py +2 -3
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/contract.py +6 -6
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/external_state_executor.py +15 -7
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/plasma_vault.py +16 -14
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/simulation.py +124 -40
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/__init__.py +36 -0
- ipor_fusion-4.0.0.dev162/src/ipor_fusion/fuses/events.py +45 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/external_state_events.py +93 -8
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/hypercore_events.py +185 -10
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/mcp/models.py +251 -39
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/__init__.py +26 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/hypercore.py +2 -2
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/oracle_mapping_nodes.py +158 -10
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/vault_data.py +155 -61
- ipor_fusion-4.0.0.dev162/tests/_event_args.py +29 -0
- ipor_fusion-4.0.0.dev162/tests/fixtures/simulate_v1_request.json +1 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_cli_oracle_mapping.py +13 -5
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_cli_vault_predates_getters.py +9 -9
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_external_state_events.py +23 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_external_state_executor.py +12 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_hypercore_events.py +20 -7
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_mcp_models.py +159 -17
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_mcp_server.py +1 -1
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_oracle_mapping.py +59 -43
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_public_api.py +71 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_validation.py +20 -20
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_vault_simulator_blocks.py +62 -1
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/typed_client/consumer.py +31 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/typed_client/rejected.py +17 -0
- ipor_fusion-4.0.0.dev156/src/ipor_fusion/fuses/events.py +0 -25
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/.claude-plugin/marketplace.json +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/.claude-plugin/plugin.json +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/.env.example +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/.gemini/settings.json +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/.git-blame-ignore-revs +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/.github/workflows/cd.yml +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/.github/workflows/ci.yml +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/.github/workflows/commit-lint.yml +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/.github/workflows/notify-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/.github/workflows/python-build.yml +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/.github/workflows/python-publish.yml +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/.github/workflows/release.yml +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/.github/workflows/report-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/.gitignore +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/.pre-commit-config.yaml +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/.python-version +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/CHANGELOG.md +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/CLAUDE.md +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/CODEOWNERS +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/LICENSE +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/README.md +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/build.sh +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/examples/CONTRIBUTING.md +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/examples/README.md +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/examples/advanced_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/examples/advanced_euler_v2_looping_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/examples/composed_hypercore_flow_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/examples/external_state_margin_leg_base.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/examples/simple_aave_v3_supply_base.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/pytest.ini +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/scripts/commit-check.sh +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/scripts/crosschain_readiness.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/skills/ipor-deploy-vault/SKILL.md +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/about.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cache.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/chains.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/changelog_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/config_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/config_store.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/main.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/market_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/options.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/vault_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/vault_health.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/vault_info_view.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/vault_markets_view.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/vault_rendering.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/config/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/config/roles.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/access.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/address.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/erc20.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/fee_manager.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/fuse.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/fuse_action.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/fusion_factory.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/logs.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/multicall.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/oracle.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/rewards_manager.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/core/withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/ccip/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/ccip/chainlink.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/ccip/codec.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/ccip/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/ccip/events.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/ccip/indexer.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/ccip/lane.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/ccip/quote.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/ccip/transport.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/discovery.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/errors.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/fuses/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/fuses/base.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/fuses/ccip.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/fuses/stargate.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/lane.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/logs.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/messages.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/simulation.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/stargate/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/stargate/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/stargate/lane.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/stargate/layerzero.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/stargate/transport.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/crosschain/transport.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/dependency_graph.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/entry_cli.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/entry_mcp.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/errors.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/explorer.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/field_docs.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/aave_v3.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/async_action.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/base.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/erc4626.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/euler_v2.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/external_state.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/fluid_instadapp.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/gearbox_v3.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/merkl.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/morpho.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/fuses/universal.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/guide/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/guide/architecture.md +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/guide/glossary.md +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/guide/invariants.md +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/guide/quickstart.md +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/market_ids.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/market_info.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/mcp/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/mcp/guide.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/mcp/server.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/morpho_api.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/py.typed +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/aave_v3.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/aave_v4.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/hypercore_outcome.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/lending_health.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/morpho.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/oracle_mapping_reader.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/position_manager.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/readers/unpriceable.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/substrates.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/types.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/validation.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/vault_erc20.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/vault_info.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/vault_managers.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/vault_positions.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/vault_reads.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/UniswapV3UniversalRouter.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/_crosschain_recovery.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/_euler_v2.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/_foundry.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/_guide.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/_hypercore_model.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/_hypercore_shadow.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/_simulate.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/_validation.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/addresses.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/conftest.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/constants.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/fixtures/hypercore_hip3_flow.json +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/fixtures/hypercore_market55.json +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/fixtures/vault_info_golden/clean.json +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/fixtures/vault_info_golden/clean.txt +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/fixtures/vault_info_golden/rich.json +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/fixtures/vault_info_golden/rich.txt +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_about.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_access_manager.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_cache.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_chains.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_cli_changelog.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_cli_commands.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_cli_config_store.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_cli_helpers.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_cli_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_cli_lending_health.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_cli_market_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_cli_pending_requests_scan.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_cli_role_accounts.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_cli_vault_info_golden.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_cli_vault_validate.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_contract_call.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_contract_encoder.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_ccip_events.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_ccip_indexer.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_ccip_quote.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_chainlink.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_contracts.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_errors.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_lane.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_layering.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_readiness.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_readiness_report.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_crosschain_transport.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_docs_typing.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_erc20.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_error_hierarchy.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_examples_composed_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_examples_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_examples_euler_looping_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_examples_vaults.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_explorer.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_fee_manager.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_fuse_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_fusion_instance.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_guide.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_hypercore_deployment.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_hypercore_flow.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_hypercore_live.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_hypercore_outcome.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_hypercore_readers.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_hypercore_simulation.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_logs.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_mcp_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_mcp_vault_validate.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_oracle.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_plasma_vault.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_public_type_reachability.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_reader_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_readiness_selection.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_revert_decoding.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_rewards_manager.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_roles.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_sdk_layering.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_borrow_aave_v3_mainnet.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_claim_merkl_wrapper_base.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_claim_morpho_rewards.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_crosschain_canary.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_crosschain_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_crosschain_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_euler_v2_batch_base.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_euler_v2_swap_deploy_base.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_euler_v2_swap_reconfigure_base.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_euler_v2_swap_registry_base.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_examples_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_examples_base.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_examples_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_external_state_executor_base.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_fusion_factory_clone_base.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_looping_aave_v3_base.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_looping_morpho_blue_base.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_pilot_v3.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_pilot_v4_uniswap.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_pilot_v5_ramses.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_pilot_v5_scheduled.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_plasma_vault_setters_base.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_readers_integration.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_release_funds.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_swap_on_base.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulate_vault_from_scratch_base.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_simulation_observation.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_solidity_compiler.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_solidity_mirrors.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_substrates.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_types_and_events.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_unpriceable_tokens.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_vault_data_block.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_vault_dep_graph.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_vault_info_onchain_base.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_vault_info_onchain_base_no_withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_web3_context.py +0 -0
- {ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/tests/test_withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev156 → 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
|
|
|
@@ -787,6 +814,7 @@ untyped code needs none of this section.
|
|
|
787
814
|
| `build_morpho_blue_market_json` | `MorphoBlueMarketJson` |
|
|
788
815
|
| `build_meta_morpho_json` | `MetaMorphoV1Json \| MetaMorphoV2Json`, told apart by `doc["version"]` |
|
|
789
816
|
| `RoleAccount.to_dict` | `RoleAccountJson` |
|
|
817
|
+
| `OracleMapping.to_dict` / `OracleNode.to_dict` | `OracleMappingJson` / `OracleNodeJson` |
|
|
790
818
|
|
|
791
819
|
Every nested block has its own TypedDict (`FeesJson`, `WithdrawManagerJson`,
|
|
792
820
|
`BalanceFuseJson`, `ReconciliationJson`, `HyperCoreJson`, `MorphoSupplyingVaultJson`,
|
|
@@ -813,12 +841,46 @@ that only some entries carry is `NotRequired` (a balance fuse's `pct_of_total` a
|
|
|
813
841
|
age) or `DeploymentErrorJson` (`{"error": ...}`) or `None`; `share_price` is
|
|
814
842
|
`SharePriceJson` (`asset`, and `usd` when the asset is priced); `dependency_graph`
|
|
815
843
|
is `DependencyGraphJson` (`edges`, `update_reach`, `update_groups`).
|
|
844
|
+
- `OracleNode.source_detail` is `SourceDetailJson`, one TypedDict per feed kind
|
|
845
|
+
(`ChainlinkDetailJson`, `DualXrefDetailJson`, `Erc4626DetailJson`,
|
|
846
|
+
`MorphoFeedDetailJson`, `MiddlewareFallbackDetailJson`; importable from
|
|
847
|
+
`ipor_fusion` and `ipor_fusion.readers`). Narrow by a key before reading a
|
|
848
|
+
kind-specific one: `if detail is not None and "aggregator" in detail:
|
|
849
|
+
detail["description"]`.
|
|
850
|
+
- Event `args` are typed per event kind: `ExternalStateEvent.args` is
|
|
851
|
+
`ExternalStateEventArgs` and `HyperCoreEvent.args` is `HyperCoreEventArgs`, a union
|
|
852
|
+
of one TypedDict per event (`ExternalStateUnpausedArgs`,
|
|
853
|
+
`HyperCoreDepositFuseEnterArgs`, ...; `EXTERNAL_STATE_EVENT_ARGS` /
|
|
854
|
+
`HYPERCORE_EVENT_ARGS` map an event name to its shape). Values carry nominal types
|
|
855
|
+
(`Amount`, `MarketId`, `FuseAddress`, `HyperCoreTokenIndex`, `PayloadHash`, web3's
|
|
856
|
+
`Timestamp`, ...). `event.args["signer"]` no longer type-checks on its own: narrow
|
|
857
|
+
with a key test (`if "signer" in event.args:`). `HyperCoreEvent.fuse` is a
|
|
858
|
+
`FuseAddress | None`.
|
|
859
|
+
- `RawLog` (the log shape `ExternalStateExecutor.parse_balance_proposed` /
|
|
860
|
+
`find_balance_proposed` accept) is `Mapping[str, object]`, not `Mapping[str, Any]`;
|
|
861
|
+
a web3 `LogReceipt` still fits it.
|
|
816
862
|
|
|
817
863
|
## Behavior changes
|
|
818
864
|
|
|
819
865
|
These apply to every caller, type-checked or not. Changes described in full above
|
|
820
866
|
are listed with a link.
|
|
821
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
|
+
|
|
822
884
|
- **Vault reads are pinned to one block**: every read of `fetch_vault_data`, log
|
|
823
885
|
scans included, runs at the resolved block; see
|
|
824
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,
|
|
@@ -314,15 +316,44 @@ from ipor_fusion.fuses import (
|
|
|
314
316
|
system_address,
|
|
315
317
|
)
|
|
316
318
|
from ipor_fusion.fuses.external_state_events import (
|
|
319
|
+
EXTERNAL_STATE_EVENT_ARGS,
|
|
317
320
|
EXTERNAL_STATE_EVENT_SPECS,
|
|
318
321
|
EXTERNAL_STATE_EVENTS,
|
|
319
322
|
EXTERNAL_STATE_TOPICS,
|
|
323
|
+
ExternalStateAssetRescuedArgs,
|
|
324
|
+
ExternalStateBigChangeDetectedArgs,
|
|
325
|
+
ExternalStateCustodianTimestampUpdatedArgs,
|
|
320
326
|
ExternalStateEvent,
|
|
327
|
+
ExternalStateEventArgs,
|
|
321
328
|
ExternalStateEventSpec,
|
|
329
|
+
ExternalStateExecutorArgs,
|
|
330
|
+
ExternalStateOperationArgs,
|
|
331
|
+
ExternalStateTotalBalanceUpdatedArgs,
|
|
332
|
+
ExternalStateUnpausedArgs,
|
|
322
333
|
decode_external_state_event,
|
|
323
334
|
external_state_event_name,
|
|
324
335
|
external_state_events,
|
|
325
336
|
)
|
|
337
|
+
from ipor_fusion.fuses.hypercore_events import (
|
|
338
|
+
HYPERCORE_EVENT_ARGS,
|
|
339
|
+
HyperCoreActionEnqueuedArgs,
|
|
340
|
+
HyperCoreActionSettledArgs,
|
|
341
|
+
HyperCoreBuilderFeeFuseEnterArgs,
|
|
342
|
+
HyperCoreCancelByCloidArgs,
|
|
343
|
+
HyperCoreCancelByOidArgs,
|
|
344
|
+
HyperCoreDepositFuseEnterArgs,
|
|
345
|
+
HyperCoreEventArgs,
|
|
346
|
+
HyperCoreMarginFuseEnterArgs,
|
|
347
|
+
HyperCoreObserverSetChangedArgs,
|
|
348
|
+
HyperCoreObserverSetProposedArgs,
|
|
349
|
+
HyperCoreOrderFuseEnterArgs,
|
|
350
|
+
HyperCoreRecoveryExecutedArgs,
|
|
351
|
+
HyperCoreRecoveryProposedArgs,
|
|
352
|
+
HyperCoreReportedActionSettledArgs,
|
|
353
|
+
HyperCoreReportSubmittedArgs,
|
|
354
|
+
HyperCoreSendFuseSendAssetArgs,
|
|
355
|
+
HyperCoreSendFuseSpotSendArgs,
|
|
356
|
+
)
|
|
326
357
|
from ipor_fusion.market_ids import IporFusionMarkets
|
|
327
358
|
from ipor_fusion.market_info import (
|
|
328
359
|
MetaMorphoAdapterJson,
|
|
@@ -422,6 +453,20 @@ from ipor_fusion.readers import (
|
|
|
422
453
|
read_hypercore_transfer_snapshot,
|
|
423
454
|
read_hypercore_vault_state,
|
|
424
455
|
)
|
|
456
|
+
from ipor_fusion.readers.oracle_mapping_nodes import (
|
|
457
|
+
AggregatorDetailJson,
|
|
458
|
+
AggregatorFeedDetailJson,
|
|
459
|
+
ChainlinkDetailJson,
|
|
460
|
+
DualXrefDetailJson,
|
|
461
|
+
Erc4626DetailJson,
|
|
462
|
+
MiddlewareFallbackDetailJson,
|
|
463
|
+
MorphoFeedDetailJson,
|
|
464
|
+
OracleAssetJson,
|
|
465
|
+
OracleMappingJson,
|
|
466
|
+
OracleNodeJson,
|
|
467
|
+
OraclePriceJson,
|
|
468
|
+
SourceDetailJson,
|
|
469
|
+
)
|
|
425
470
|
from ipor_fusion.substrates import (
|
|
426
471
|
SubstrateInfo,
|
|
427
472
|
decode_substrate,
|
|
@@ -546,6 +591,15 @@ __all__ = [
|
|
|
546
591
|
"EXTERNAL_STATE_EVENTS",
|
|
547
592
|
"EXTERNAL_STATE_TOPICS",
|
|
548
593
|
"ExternalStateEvent",
|
|
594
|
+
"EXTERNAL_STATE_EVENT_ARGS",
|
|
595
|
+
"ExternalStateAssetRescuedArgs",
|
|
596
|
+
"ExternalStateBigChangeDetectedArgs",
|
|
597
|
+
"ExternalStateCustodianTimestampUpdatedArgs",
|
|
598
|
+
"ExternalStateEventArgs",
|
|
599
|
+
"ExternalStateExecutorArgs",
|
|
600
|
+
"ExternalStateOperationArgs",
|
|
601
|
+
"ExternalStateTotalBalanceUpdatedArgs",
|
|
602
|
+
"ExternalStateUnpausedArgs",
|
|
549
603
|
"ExternalStateEventDecodeError",
|
|
550
604
|
"ExternalStateEventSpec",
|
|
551
605
|
"decode_external_state_event",
|
|
@@ -554,6 +608,24 @@ __all__ = [
|
|
|
554
608
|
"HYPERCORE_EVENTS",
|
|
555
609
|
"HYPERCORE_EVENT_SPECS",
|
|
556
610
|
"HyperCoreEvent",
|
|
611
|
+
"HYPERCORE_EVENT_ARGS",
|
|
612
|
+
"HyperCoreActionEnqueuedArgs",
|
|
613
|
+
"HyperCoreActionSettledArgs",
|
|
614
|
+
"HyperCoreBuilderFeeFuseEnterArgs",
|
|
615
|
+
"HyperCoreCancelByCloidArgs",
|
|
616
|
+
"HyperCoreCancelByOidArgs",
|
|
617
|
+
"HyperCoreDepositFuseEnterArgs",
|
|
618
|
+
"HyperCoreEventArgs",
|
|
619
|
+
"HyperCoreMarginFuseEnterArgs",
|
|
620
|
+
"HyperCoreObserverSetChangedArgs",
|
|
621
|
+
"HyperCoreObserverSetProposedArgs",
|
|
622
|
+
"HyperCoreOrderFuseEnterArgs",
|
|
623
|
+
"HyperCoreRecoveryExecutedArgs",
|
|
624
|
+
"HyperCoreRecoveryProposedArgs",
|
|
625
|
+
"HyperCoreReportSubmittedArgs",
|
|
626
|
+
"HyperCoreReportedActionSettledArgs",
|
|
627
|
+
"HyperCoreSendFuseSendAssetArgs",
|
|
628
|
+
"HyperCoreSendFuseSpotSendArgs",
|
|
557
629
|
"HyperCoreEventSpec",
|
|
558
630
|
"decode_hypercore_event",
|
|
559
631
|
"find_hypercore_events",
|
|
@@ -579,6 +651,8 @@ __all__ = [
|
|
|
579
651
|
"MULTICALL3_ADDRESS",
|
|
580
652
|
"VaultSimulator",
|
|
581
653
|
"StateOverrideProvider",
|
|
654
|
+
"AccountOverride",
|
|
655
|
+
"BlockOverrides",
|
|
582
656
|
"SimulationObservation",
|
|
583
657
|
"SimulationResult",
|
|
584
658
|
"SimulatedCallResult",
|
|
@@ -945,6 +1019,18 @@ __all__ = [
|
|
|
945
1019
|
"OracleAsset",
|
|
946
1020
|
"OracleMapping",
|
|
947
1021
|
"OracleNode",
|
|
1022
|
+
"AggregatorDetailJson",
|
|
1023
|
+
"AggregatorFeedDetailJson",
|
|
1024
|
+
"ChainlinkDetailJson",
|
|
1025
|
+
"DualXrefDetailJson",
|
|
1026
|
+
"Erc4626DetailJson",
|
|
1027
|
+
"MiddlewareFallbackDetailJson",
|
|
1028
|
+
"MorphoFeedDetailJson",
|
|
1029
|
+
"OracleAssetJson",
|
|
1030
|
+
"OracleMappingJson",
|
|
1031
|
+
"OracleNodeJson",
|
|
1032
|
+
"OraclePriceJson",
|
|
1033
|
+
"SourceDetailJson",
|
|
948
1034
|
"OraclePrice",
|
|
949
1035
|
"build_oracle_mapping",
|
|
950
1036
|
"OracleMappingReader",
|
{ipor_fusion-4.0.0.dev156 → ipor_fusion-4.0.0.dev162}/src/ipor_fusion/cli/oracle_mapping_view.py
RENAMED
|
@@ -24,21 +24,25 @@ def _format_wad_price(price: OraclePrice | None) -> str:
|
|
|
24
24
|
|
|
25
25
|
def _print_feed_line(node: OracleNode) -> None:
|
|
26
26
|
"""The feed's self-declared units — key for confirming what a value means."""
|
|
27
|
-
detail = node.source_detail
|
|
27
|
+
detail = node.source_detail
|
|
28
28
|
if node.source_type in (TYPE_CHAINLINK, TYPE_CHAINLINK_STYLE):
|
|
29
|
-
if detail
|
|
29
|
+
if detail is not None and "aggregator" in detail and detail["description"]:
|
|
30
30
|
click.echo(f" Feed: {detail['description']}")
|
|
31
31
|
else:
|
|
32
32
|
# only chainlink_style can land here — the confirmed tier
|
|
33
33
|
# requires a non-empty description
|
|
34
34
|
click.secho(" Feed: (no description)", fg="yellow")
|
|
35
|
-
elif
|
|
35
|
+
elif (
|
|
36
|
+
node.source_type == TYPE_DUAL_XREF
|
|
37
|
+
and detail is not None
|
|
38
|
+
and "asset_x" in detail
|
|
39
|
+
):
|
|
36
40
|
rendered = [
|
|
37
41
|
# quoted — the descriptions themselves contain " / "
|
|
38
42
|
f'"{d}"' if d else click.style("(no description)", fg="yellow")
|
|
39
43
|
for d in (
|
|
40
|
-
|
|
41
|
-
|
|
44
|
+
detail["asset_x_asset_y_feed"]["description"],
|
|
45
|
+
detail["asset_y_usd_feed"]["description"],
|
|
42
46
|
)
|
|
43
47
|
]
|
|
44
48
|
click.echo(f" Feed: {' × '.join(rendered)}")
|
|
@@ -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
|
|
@@ -18,7 +18,7 @@ from __future__ import annotations
|
|
|
18
18
|
|
|
19
19
|
from collections.abc import Iterable, Mapping
|
|
20
20
|
from dataclasses import dataclass, replace
|
|
21
|
-
from typing import
|
|
21
|
+
from typing import TypeAlias
|
|
22
22
|
|
|
23
23
|
from eth_abi import decode, encode
|
|
24
24
|
from eth_abi.exceptions import DecodingError
|
|
@@ -44,8 +44,9 @@ from ipor_fusion.types import (
|
|
|
44
44
|
# (HexBytes fields, checksummed address), and a raw JSON-RPC or
|
|
45
45
|
# `eth_simulateV1` row (0x-hex strings, lowercase address). Looser than
|
|
46
46
|
# `web3.types.LogReceipt`, which the rest of `core/` uses, because those rows
|
|
47
|
-
# carry neither its field types nor all of its required keys.
|
|
48
|
-
|
|
47
|
+
# carry neither its field types nor all of its required keys. Every field is
|
|
48
|
+
# read as `object` and narrowed; a `LogReceipt` is one of these mappings.
|
|
49
|
+
RawLog: TypeAlias = Mapping[str, object]
|
|
49
50
|
|
|
50
51
|
|
|
51
52
|
def _log_emitter(log: RawLog) -> ChecksumAddress | None:
|
|
@@ -55,7 +56,7 @@ def _log_emitter(log: RawLog) -> ChecksumAddress | None:
|
|
|
55
56
|
matched against an expected emitter, and a caller scanning foreign rows
|
|
56
57
|
should skip such a log rather than have the scan abort on it."""
|
|
57
58
|
emitter = log.get("address")
|
|
58
|
-
if emitter
|
|
59
|
+
if not isinstance(emitter, str | bytes):
|
|
59
60
|
return None
|
|
60
61
|
try:
|
|
61
62
|
return Web3.to_checksum_address(emitter)
|
|
@@ -590,11 +591,14 @@ class ExternalStateExecutor(ContractWrapper):
|
|
|
590
591
|
event -- the rule `_log_emitter` already applies to an unreadable
|
|
591
592
|
address, and it keeps a raise meaning "ours, but the payload is broken".
|
|
592
593
|
"""
|
|
593
|
-
topics = log.get("topics")
|
|
594
|
-
if not topics:
|
|
594
|
+
topics = log.get("topics")
|
|
595
|
+
if not isinstance(topics, list | tuple) or not topics:
|
|
596
|
+
return False
|
|
597
|
+
topic = topics[0]
|
|
598
|
+
if not isinstance(topic, str | bytes | bytearray):
|
|
595
599
|
return False
|
|
596
600
|
try:
|
|
597
|
-
return HexBytes(
|
|
601
|
+
return HexBytes(topic) == cls._BALANCE_PROPOSED_TOPIC
|
|
598
602
|
except (ValueError, TypeError):
|
|
599
603
|
return False
|
|
600
604
|
|
|
@@ -652,6 +656,10 @@ class ExternalStateExecutor(ContractWrapper):
|
|
|
652
656
|
data = log.get("data")
|
|
653
657
|
if data is None:
|
|
654
658
|
raise ExternalStateError("BalanceProposed log carries no data")
|
|
659
|
+
if not isinstance(data, str | bytes | bytearray):
|
|
660
|
+
raise ExternalStateError(
|
|
661
|
+
f"malformed BalanceProposed data: {type(data).__name__}"
|
|
662
|
+
)
|
|
655
663
|
try:
|
|
656
664
|
# Unpacked in the order `BalanceProposed` declares them; all six
|
|
657
665
|
# are unindexed, so topics carries topic0 alone.
|
|
@@ -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(
|