ipor-fusion 4.0.0.dev308__tar.gz → 4.0.0.dev315__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.dev308 → ipor_fusion-4.0.0.dev315}/AGENTS.md +15 -52
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/MIGRATION_4.md +49 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/PKG-INFO +13 -24
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/README.md +12 -23
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/examples/README.md +0 -23
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/pyproject.toml +1 -1
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/pytest.ini +0 -1
- ipor_fusion-4.0.0.dev315/scripts/fusion_error_signatures.py +137 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/core/contract.py +13 -1
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/__init__.py +6 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/ccip/contracts.py +38 -5
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/ccip/events.py +125 -63
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/ccip/lane.py +5 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/ccip/transport.py +23 -9
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/contracts.py +12 -9
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/errors.py +72 -4
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/fuses/ccip.py +21 -3
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/lane.py +34 -2
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/messages.py +51 -12
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/simulation.py +4 -1
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/stargate/contracts.py +17 -4
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/stargate/lane.py +1 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/transport.py +14 -1
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/errors.py +4 -0
- ipor_fusion-4.0.0.dev315/src/ipor_fusion/fusion_errors.py +1437 -0
- ipor_fusion-4.0.0.dev315/tests/_crosschain.py +252 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/_crosschain_lifecycle.py +20 -115
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/_crosschain_recovery.py +7 -3
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/conftest.py +0 -13
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_contract_call.py +15 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_contract_encoder.py +1 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_crosschain_ccip_events.py +36 -16
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_crosschain_contracts.py +46 -15
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_crosschain_encoding.py +69 -15
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_crosschain_lane.py +53 -8
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_crosschain_transport.py +13 -0
- ipor_fusion-4.0.0.dev315/tests/test_fusion_errors.py +122 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_public_api.py +3 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_claim_merkl_wrapper_base.py +3 -1
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_crosschain_hyperevm.py +86 -428
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_timelock_base.py +1 -1
- ipor_fusion-4.0.0.dev308/examples/composed_hypercore_flow_arbitrum_hyperevm.py +0 -1026
- ipor_fusion-4.0.0.dev308/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py +0 -707
- ipor_fusion-4.0.0.dev308/scripts/crosschain_readiness.py +0 -1129
- ipor_fusion-4.0.0.dev308/tests/_crosschain.py +0 -574
- ipor_fusion-4.0.0.dev308/tests/test_crosschain_readiness.py +0 -160
- ipor_fusion-4.0.0.dev308/tests/test_crosschain_readiness_report.py +0 -821
- ipor_fusion-4.0.0.dev308/tests/test_examples_composed_hypercore.py +0 -239
- ipor_fusion-4.0.0.dev308/tests/test_examples_crosschain.py +0 -138
- ipor_fusion-4.0.0.dev308/tests/test_readiness_selection.py +0 -84
- ipor_fusion-4.0.0.dev308/tests/test_simulate_crosschain_canary.py +0 -127
- ipor_fusion-4.0.0.dev308/tests/test_simulate_crosschain_hypercore.py +0 -385
- ipor_fusion-4.0.0.dev308/tests/test_simulate_crosschain_lifecycle.py +0 -18
- ipor_fusion-4.0.0.dev308/tests/test_simulate_examples_crosschain.py +0 -44
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/.claude-plugin/marketplace.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/.claude-plugin/plugin.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/.env.example +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/.gemini/settings.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/.git-blame-ignore-revs +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/.github/workflows/cd.yml +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/.github/workflows/ci.yml +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/.github/workflows/commit-lint.yml +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/.github/workflows/notify-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/.github/workflows/python-build.yml +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/.github/workflows/python-publish.yml +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/.github/workflows/release.yml +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/.github/workflows/report-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/.gitignore +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/.pre-commit-config.yaml +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/.python-version +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/CHANGELOG.md +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/CLAUDE.md +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/CODEOWNERS +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/LICENSE +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/build.sh +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/examples/CONTRIBUTING.md +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/examples/advanced_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/examples/advanced_euler_v2_looping_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/examples/external_state_margin_leg_base.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/examples/simple_aave_v3_supply_base.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/scripts/commit-check.sh +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/skills/ipor-deploy-vault/SKILL.md +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/about.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/cache.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/chains.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/cli/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/cli/address_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/cli/changelog_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/cli/config_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/cli/config_store.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/cli/main.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/cli/market_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/cli/options.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/cli/oracle_mapping_view.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/cli/preflight_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/cli/vault_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/cli/vault_health.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/cli/vault_info_view.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/cli/vault_markets_view.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/cli/vault_rendering.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/config/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/config/roles.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/core/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/core/access.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/core/address.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/core/context.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/core/context_manager.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/core/erc20.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/core/external_state_executor.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/core/fee_manager.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/core/fuse.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/core/fuse_action.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/core/fuse_decoding.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/core/fusion_factory.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/core/logs.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/core/multicall.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/core/oracle.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/core/plasma_vault.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/core/rewards_manager.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/core/simulation.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/core/simulation_result.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/core/withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/ccip/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/ccip/chainlink.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/ccip/codec.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/ccip/indexer.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/ccip/quote.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/discovery.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/fuses/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/fuses/base.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/fuses/stargate.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/logs.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/stargate/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/stargate/layerzero.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/stargate/transport.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/dependency_graph.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/entry_cli.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/entry_mcp.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/explorer.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/field_docs.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/fuses/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/fuses/aave_v3.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/fuses/async_action.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/fuses/base.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/fuses/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/fuses/erc4626.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/fuses/euler_v2.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/fuses/events.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/fuses/external_state.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/fuses/external_state_event_decoding.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/fuses/fluid_instadapp.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/fuses/gearbox_v3.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/fuses/hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/fuses/hypercore_event_decoding.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/fuses/merkl.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/fuses/morpho.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/fuses/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/fuses/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/fuses/universal.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/guide/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/guide/architecture.md +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/guide/glossary.md +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/guide/invariants.md +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/guide/quickstart.md +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/hypercore/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/market_ids.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/market_info.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/mcp/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/mcp/guide.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/mcp/models.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/mcp/server.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/morpho_api.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/preflight.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/py.typed +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/readers/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/readers/aave_v3.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/readers/aave_v4.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/readers/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/readers/hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/readers/hypercore_outcome.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/readers/lending_health.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/readers/morpho.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/readers/oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/readers/oracle_mapping_nodes.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/readers/oracle_mapping_reader.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/readers/position_manager.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/readers/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/readers/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/readers/unpriceable.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/registry.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/substrates.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/types.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/validation.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/vault_data.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/vault_erc20.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/vault_info.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/vault_managers.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/vault_positions.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/vault_reads.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/UniswapV3UniversalRouter.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/_euler_v2.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/_event_args.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/_fake_rpc.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/_foundry.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/_golden.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/_guide.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/_hypercore_model.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/_hypercore_shadow.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/_live.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/_oracle_mapping_fake.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/_simulate.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/_validation.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/addresses.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/constants.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/hypercore_hip3_flow.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/hypercore_market55.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/hypercore_official.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/market_golden/meta_morpho_v1.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/market_golden/meta_morpho_v1.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/market_golden/meta_morpho_v2.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/market_golden/meta_morpho_v2.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/market_golden/morpho_api/market.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/market_golden/morpho_api/vault_v1.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/market_golden/morpho_api/vault_v2.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/market_golden/morpho_api/vault_v2_not_found.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/market_golden/morpho_blue.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/market_golden/morpho_blue.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/market_golden/morpho_blue_api_error.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/market_golden/morpho_blue_api_error.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/market_golden/morpho_blue_no_api.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/market_golden/morpho_blue_no_api.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/oracle_mapping_golden/mapping.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/oracle_mapping_golden/mapping.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/simulate_v1_request.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/vault_info_golden/clean.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/vault_info_golden/clean.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/vault_info_golden/clean.txt +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/vault_info_golden/deployment_error.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/vault_info_golden/deployment_error.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/vault_info_golden/deployment_error.txt +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/vault_info_golden/fetched.cli.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/vault_info_golden/fetched.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/vault_info_golden/fetched.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/vault_info_golden/full.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/vault_info_golden/full.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/vault_info_golden/full.txt +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/vault_info_golden/rich.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/vault_info_golden/rich.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/fixtures/vault_info_golden/rich.txt +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_about.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_access_manager.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_cache.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_chains.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_cli_address.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_cli_changelog.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_cli_commands.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_cli_config_store.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_cli_helpers.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_cli_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_cli_lending_health.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_cli_market_golden.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_cli_market_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_cli_mcp_parity.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_cli_oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_cli_oracle_mapping_golden.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_cli_pending_requests_scan.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_cli_preflight.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_cli_role_accounts.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_cli_vault_info_golden.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_cli_vault_predates_getters.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_cli_vault_validate.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_crosschain_ccip_indexer.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_crosschain_ccip_quote.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_crosschain_chainlink.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_crosschain_errors.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_crosschain_layering.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_docs_typing.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_erc20.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_error_hierarchy.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_examples_euler_looping_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_examples_vaults.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_explorer.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_external_state_events.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_external_state_executor.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_fee_manager.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_fuse_decoding.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_fuse_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_fusion_instance.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_governance_wrappers.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_guide.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_hypercore_deployment.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_hypercore_events.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_hypercore_flow.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_hypercore_live.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_hypercore_outcome.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_hypercore_readers.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_hypercore_simulation.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_logs.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_mcp_address.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_mcp_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_mcp_models.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_mcp_preflight.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_mcp_server.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_mcp_vault_validate.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_oracle.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_plasma_vault.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_preflight.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_public_type_reachability.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_reader_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_registry.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_revert_decoding.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_rewards_manager.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_roles.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_sdk_layering.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_borrow_aave_v3_mainnet.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_claim_morpho_rewards.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_euler_v2_batch_base.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_euler_v2_swap_deploy_base.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_euler_v2_swap_reconfigure_base.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_euler_v2_swap_registry_base.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_examples_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_examples_base.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_external_state_executor_base.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_fusion_factory_clone_base.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_looping_aave_v3_base.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_looping_morpho_blue_base.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_pilot_v3.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_pilot_v4_uniswap.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_pilot_v5_ramses.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_pilot_v5_scheduled.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_plasma_vault_setters_base.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_preflight_base.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_readers_integration.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_release_funds.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_swap_on_base.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulate_vault_from_scratch_base.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulation_errors.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_simulation_observation.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_solidity_compiler.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_solidity_mirrors.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_substrates.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_types_and_events.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_unpriceable_tokens.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_validation.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_vault_data_block.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_vault_dep_graph.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_vault_info_fetched_golden.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_vault_info_onchain_base.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_vault_info_onchain_base_no_withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_vault_reconciliation_onchain_base.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_vault_simulator_blocks.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_web3_context.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/test_withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/typed_client/consumer.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/tests/typed_client/rejected.py +0 -0
- {ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/uv.lock +0 -0
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
`ipor-fusion` is the Python SDK for IPOR Fusion Plasma Vaults: typed fuse
|
|
4
4
|
encoders, on-chain readers, and a `fusion` CLI plus `fusion-mcp` MCP server
|
|
5
5
|
built on the same SDK. Published to PyPI. It is a library and inspection
|
|
6
|
-
tooling, not an automation service.
|
|
7
|
-
read-only diagnostic run on demand, not a keeper or production monitor; any
|
|
8
|
-
scheduled run of it belongs to the monitoring repository.
|
|
6
|
+
tooling, not an automation service.
|
|
9
7
|
|
|
10
8
|
Related repositories (siblings, referenced by name; clone paths vary):
|
|
11
9
|
- [ipor-fusion](https://github.com/IPOR-Labs/ipor-fusion) — Solidity contracts, the source of truth for market ids, roles and substrates.
|
|
@@ -29,8 +27,6 @@ uv run ruff check ./ # lint: bandit S,
|
|
|
29
27
|
uv run pyright # types, basic mode, src + tests + examples + scripts
|
|
30
28
|
uv run pytest # all tests + coverage gate (fail_under = 98, mcp/ included)
|
|
31
29
|
uv run pytest -m "cli or mcp" --no-cov # CLI/MCP subset (the full suite is mostly offline too)
|
|
32
|
-
uv run pytest --run-readiness -m readiness --no-cov -rA # opt-in live Ethereum-hub POC checks
|
|
33
|
-
uv run python scripts/crosschain_readiness.py --output /tmp/crosschain-readiness.json # live Arbitrum/HyperEVM report
|
|
34
30
|
uv run pytest tests/test_fuse_encoding.py -k aave --no-cov # single file / test
|
|
35
31
|
UPDATE_GOLDEN=1 uv run pytest -k golden --no-cov # rewrite pinned CLI/MCP output (tests/fixtures/*_golden/)
|
|
36
32
|
uv lock --check # uv.lock in sync with pyproject.toml
|
|
@@ -74,14 +70,13 @@ public Solidity sources from GitHub). Skip only for an unavailable source; an
|
|
|
74
70
|
exception from the
|
|
75
71
|
SDK is a test failure, never a skip. Never print `.env` or a provider URL: they
|
|
76
72
|
embed API keys, so skip and fail messages carry the exception type only.
|
|
77
|
-
`HYPEREVM_PROVIDER_URL` is used by the HyperEVM
|
|
78
|
-
|
|
79
|
-
`test_simulate_crosschain_hyperevm.py` rehearses Arbitrum → HyperEVM on pinned blocks
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
`
|
|
84
|
-
that revision (the fuses are compiled from it); a checkout without `node_modules` also
|
|
73
|
+
`HYPEREVM_PROVIDER_URL` is used by the Arbitrum → HyperEVM rehearsal and the
|
|
74
|
+
HyperCore tests; general PR CI does not supply it.
|
|
75
|
+
`test_simulate_crosschain_hyperevm.py` rehearses Arbitrum → HyperEVM on pinned blocks
|
|
76
|
+
with a CCIP factory pair compiled from `FUSE_SOURCE_REVISION` (the contracts release
|
|
77
|
+
the official deployment was built from) and built inside the simulation; the SDK
|
|
78
|
+
supports only that release, so there is no live-pair generation. It needs
|
|
79
|
+
`IPOR_FUSION_CONTRACTS_DIR` at that revision; a checkout without `node_modules` also
|
|
85
80
|
needs `IPOR_FUSION_FOUNDRY_REMAPPINGS` for OpenZeppelin. `test_crosschain_ccip_events.py`
|
|
86
81
|
mirrors the CCIP event registry from a checkout at its own `CONTRACTS_REVISION`.
|
|
87
82
|
`test_solidity_compiler.py` unit-tests that compiler helper (`tests/_foundry.py`)
|
|
@@ -89,18 +84,6 @@ offline, with `forge` and `git` mocked. The checkout-based tests above skip when
|
|
|
89
84
|
external prerequisites are unavailable. `test_hypercore_live.py`,
|
|
90
85
|
`test_hypercore_deployment.py` and `test_hypercore_simulation.py` need
|
|
91
86
|
`HYPEREVM_PROVIDER_URL` as well.
|
|
92
|
-
`test_simulate_crosschain_lifecycle.py` drives the mainnet POC deployment from
|
|
93
|
-
Ethereum to every spoke on every transport through `CrosschainLane` and
|
|
94
|
-
`CrosschainSimulator`; the fixtures (`Chain`, `Deployment`, `Spoke`, pinned
|
|
95
|
-
blocks) live in `tests/_crosschain.py`. A planned spoke (HyperEVM) is a
|
|
96
|
-
`pending` chain there and an `xfail(strict=True)` param until it is wired.
|
|
97
|
-
`test_simulate_crosschain_canary.py` runs the same lifecycle on `CANARY` and
|
|
98
|
-
`CANARY_V3`, the live Arbitrum → HyperEVM USDC canaries on the pilot-v2 and v3 CCIP
|
|
99
|
-
factory pairs, each pinned right after its last transaction, then checks the final gates and every delivery's receiver
|
|
100
|
-
gas against its route limit; a `Chain.simulated_gas_limit` lifts HyperEVM's 3 M
|
|
101
|
-
small-block pin to 30 M and `Deployment.ccip_debits_sent_amount` /
|
|
102
|
-
`attestation_zero_dust_sd` carry the executor generation's accounting into `Run`.
|
|
103
|
-
It needs `ARBITRUM_PROVIDER_URL` and `HYPEREVM_PROVIDER_URL`.
|
|
104
87
|
HyperCore (market 55) cannot be simulated directly: the HyperEVM RPC ignores code
|
|
105
88
|
overrides at the precompile addresses `0x800`–`0x813`, and the public Hyperliquid RPC
|
|
106
89
|
has no `eth_simulateV1`. `tests/_hypercore_shadow.py` therefore compiles the HyperCore
|
|
@@ -110,33 +93,8 @@ CoreWriter constants redirected to ordinary addresses, proves the rest is identi
|
|
|
110
93
|
the deployed runtimes, and `tests/_hypercore_model.py` answers those addresses through
|
|
111
94
|
`VaultSimulator.with_state_override_provider`. Core never applies anything there: the
|
|
112
95
|
tests prove EVM validation under supplied Core state. `test_hypercore_simulation.py`
|
|
113
|
-
runs one vault cycle;
|
|
114
|
-
|
|
115
|
-
CCIP delivery to its route gas limit. Both skip without the source directory;
|
|
116
|
-
`test_hypercore_simulation.py` also needs `HYPEREVM_PROVIDER_URL`, the composed flow
|
|
117
|
-
`ARBITRUM_PROVIDER_URL` as well.
|
|
118
|
-
`test_crosschain_readiness.py` checks the Ethereum-hub POC's live bridge and IPOR
|
|
119
|
-
preconditions. Its `readiness` marker requires `--run-readiness`: ordinary runs
|
|
120
|
-
exclude it even with `-m sdk`. Known HyperEVM gaps are non-strict xfails restricted
|
|
121
|
-
to assertion failures, so availability improving is an XPASS, not broken CI.
|
|
122
|
-
Readiness RPC clients fail on missing/unreachable providers or wrong chain IDs;
|
|
123
|
-
they pin a snapshot per chain and do not require `eth_simulateV1`.
|
|
124
|
-
`scripts/crosschain_readiness.py` separately reports both Arbitrum/HyperEVM USDC
|
|
125
|
-
directions and the v3 factory pair's configuration (creation codes, routes, the
|
|
126
|
-
dispatcher deployment gas limit, the canary creator's allowance, balance and HyperEVM
|
|
127
|
-
big-block flag) with snapshot block numbers/hashes/timestamps. `hyperevm_delivery`
|
|
128
|
-
flags manual execution into HyperEVM per message kind: `manual_execution_required` for
|
|
129
|
-
commands and recalls (the hub route's `messageGasLimit`) and `dispatcher_deployment_manual`
|
|
130
|
-
for the one-time deployment ticket. A delivery above the 3 M small block is manual
|
|
131
|
-
unless every Chainlink executor seen delivering on HyperEVM's CCIP 2.0 OffRamp over
|
|
132
|
-
the last ~2 weeks (`chainlink_executors`: `ExecutionStateChanged` senders from every
|
|
133
|
-
source, the canary EOA excluded, at least 20 executions) sends into big blocks; a
|
|
134
|
-
ticket below a dispatcher creation's gas is manual regardless. The executor set is
|
|
135
|
-
derived on every run; `eth_usingBigBlocks` is read at the latest block.
|
|
136
|
-
Blocked availability is a successful observation, not acceptance; incomplete probes
|
|
137
|
-
fail. There is no GitHub workflow for it in this repository: run it locally with
|
|
138
|
-
the Arbitrum and HyperEVM provider URLs from `.env`. A `Spoke` declares which transports reach it;
|
|
139
|
-
the lifecycle matrix follows that.
|
|
96
|
+
runs one vault cycle; it skips without the source directory and needs
|
|
97
|
+
`HYPEREVM_PROVIDER_URL`.
|
|
140
98
|
|
|
141
99
|
## Conventions
|
|
142
100
|
|
|
@@ -237,6 +195,11 @@ the lifecycle matrix follows that.
|
|
|
237
195
|
|
|
238
196
|
- `chains.py` chain registry; `market_ids.py` `IporFusionMarkets`; `types.py`; `errors.py`
|
|
239
197
|
defines every SDK exception class (`tests/test_error_hierarchy.py` pins it)
|
|
198
|
+
- `fusion_errors.py` — `FUSION_ERROR_SIGNATURES`, every custom error of the
|
|
199
|
+
ipor-fusion contracts and their imports, registered by `errors.py` so reverts
|
|
200
|
+
decode by name; generated, never edited by hand: `uv run python
|
|
201
|
+
scripts/fusion_error_signatures.py ../ipor-fusion --source <commit>` (needs the
|
|
202
|
+
checkout's `npm ci`)
|
|
240
203
|
- `about.py` — package version, repository URL, CHANGELOG parsing (`fusion changelog`,
|
|
241
204
|
`server_info`); `field_docs.py` — `DOCS`, the JSON field descriptions shared by CLI
|
|
242
205
|
output and MCP models
|
|
@@ -503,6 +503,55 @@ fails at run time:
|
|
|
503
503
|
`dataclasses.asdict` form) with every field parsed; use it instead of
|
|
504
504
|
`FusionInstance(**data)`, which passes raw strings into the role-typed fields.
|
|
505
505
|
|
|
506
|
+
#### Crosschain follows the released contracts
|
|
507
|
+
|
|
508
|
+
4.0 encodes and decodes the crosschain contracts of the 2026-10-21 contracts
|
|
509
|
+
release (`ipor-abi`: the CCIP and Stargate factories, fuses and NAV pre-hook at
|
|
510
|
+
one CREATE3 address on Arbitrum and HyperEVM). Earlier crosschain deployments
|
|
511
|
+
are not supported: their fuses reject the new calldata, their envelopes fail
|
|
512
|
+
the version check, and their dispatcher `observation()` raises
|
|
513
|
+
`UnsupportedContractVersionError`, so an earlier-generation lane is unreadable
|
|
514
|
+
on the spoke side.
|
|
515
|
+
|
|
516
|
+
- **Envelopes.** `CODEC_VERSION` is 4 (Stargate), `CCIP_VERSION` 3.
|
|
517
|
+
- **`Command`.** New `min_execution_gas` before `action_data` (0 = the lane's
|
|
518
|
+
default, at most `MAX_COMMAND_EXECUTION_GAS`); `as_tuple()` / `from_tuple()`
|
|
519
|
+
have six members and `COMMAND_TUPLE_TYPE` is
|
|
520
|
+
`(bytes32,uint64,uint64,uint8,uint64,bytes)`.
|
|
521
|
+
- **REQUEST_SHARES.** `Command.request_shares(withdraw_manager, vault, shares,
|
|
522
|
+
max_fee_shares)`: the fee ceiling in shares is required (`NO_FEE_CEILING` for
|
|
523
|
+
none).
|
|
524
|
+
- **CCIP supply.** `CcipSendParams.min_delivered` is the delivered-amount floor
|
|
525
|
+
the supply `enter` carries (0 = none, at most the amount).
|
|
526
|
+
`CcipCommandType.CANCEL_DEPLOYMENT` cancels an expired dispatcher deployment.
|
|
527
|
+
- **Observations.** `CcipObservation` gains `unpriced_count` and
|
|
528
|
+
`unpriced_codes` (`unpriced_reason(index)` returns a `TrackedVaultPricing`); the
|
|
529
|
+
Stargate `Observation` gains `vault_valued` and `unpriced_count`;
|
|
530
|
+
`LaneObservation` gains `unpriced_count`.
|
|
531
|
+
- **Attestation.** `CrosschainLane.attestation(...)` takes `receipt_at`, the hub's
|
|
532
|
+
`LaneHubState.last_value_moving_receipt_at` (0 on Stargate). The executor
|
|
533
|
+
refuses an observation that is not strictly later than its last value-moving
|
|
534
|
+
receipt; the method raises `ValueError` for it and while a tracked vault is
|
|
535
|
+
unpriced. New: `LaneHubState.last_value_moving_receipt_at`,
|
|
536
|
+
`CrosschainLane.last_value_moving_receipt_at()` (`None` on Stargate) and
|
|
537
|
+
`CcipCrosschainExecutor.last_value_moving_receipt_at`.
|
|
538
|
+
- **Core.** `Call` gains an optional `decode_error` field: a wrapper maps an
|
|
539
|
+
undecodable answer to a named SDK exception (the earlier-generation
|
|
540
|
+
`observation()` raises `UnsupportedContractVersionError` this way), and it
|
|
541
|
+
survives `Call.map()`.
|
|
542
|
+
- **Removed.** `CrosschainDispatcher.pending_request_shares` (neither released
|
|
543
|
+
dispatcher has it). From the repository: `scripts/crosschain_readiness.py`, the
|
|
544
|
+
pytest `--run-readiness` option and `readiness` marker, and the examples
|
|
545
|
+
`crosschain_ccip_usdc_arbitrum_hyperevm.py` and
|
|
546
|
+
`composed_hypercore_flow_arbitrum_hyperevm.py`, which drove an earlier
|
|
547
|
+
deployment.
|
|
548
|
+
- **Events and errors.** `CCIP_EVENTS` mirrors the released contracts:
|
|
549
|
+
`ReturnFinalized` / `LateReturnFinalized` gain `debitedSD`, `SharesRequested`
|
|
550
|
+
gains `feeShares`, and new events are registered. The crosschain error registry
|
|
551
|
+
decodes every error the released contracts declare.
|
|
552
|
+
- **Routes.** The released CCIP README requires a route `messageGasLimit` of at
|
|
553
|
+
least 2.7 M for commands.
|
|
554
|
+
|
|
506
555
|
## Errors
|
|
507
556
|
|
|
508
557
|
Every exception class the SDK defines now derives from `IporFusionError` and is
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: ipor-fusion
|
|
3
|
-
Version: 4.0.0.
|
|
3
|
+
Version: 4.0.0.dev315
|
|
4
4
|
Summary: The IPOR Fusion SDK for Python
|
|
5
5
|
Project-URL: homepage, https://ipor.io
|
|
6
6
|
Project-URL: repository, https://github.com/IPOR-Labs/ipor-fusion.py
|
|
@@ -369,10 +369,12 @@ A flash-loan fuse also needs `update_callback_handler(handler, sender, selector)
|
|
|
369
369
|
|
|
370
370
|
The full clone → configure → deposit → execute sequence is exercised in [`tests/test_simulate_vault_from_scratch_base.py`](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/tests/test_simulate_vault_from_scratch_base.py).
|
|
371
371
|
|
|
372
|
-
Custom errors of the
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
`SimulationResult.revert_reason` and `TransactionError`
|
|
372
|
+
Custom errors of the IPOR Fusion contracts and the libraries they import
|
|
373
|
+
(OpenZeppelin included) decode by name, so a simulated or sent call that reverts
|
|
374
|
+
reads `AccessManagedUnauthorized(0x...)`, `UnsupportedFuse()` or
|
|
375
|
+
`NavSettledStale(8453)` in `SimulationResult.revert_reason` and `TransactionError`
|
|
376
|
+
instead of a bare selector. Importing `ipor_fusion.crosschain` also registers
|
|
377
|
+
`CROSSCHAIN_ERROR_SIGNATURES`.
|
|
376
378
|
`register_custom_errors([...])` adds your own, and `SimulationResult.raise_for_failure()`
|
|
377
379
|
raises `SimulationError` naming the first failed call.
|
|
378
380
|
|
|
@@ -390,24 +392,11 @@ ever signed or broadcast.
|
|
|
390
392
|
- [External-state margin leg](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/examples/external_state_margin_leg_base.py) — a vault whose capital
|
|
391
393
|
sits off-chain: typed market-50 substrates, a dual-custodian propose/confirm marking the NAV,
|
|
392
394
|
the scheduled-withdrawal prep an alpha performs, and a mismatched confirmation being rejected.
|
|
393
|
-
- [Crosschain CCIP lifecycle](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py) (preview feature) — a vault
|
|
394
|
-
whose capital works on another chain: supply USDC from an Arbitrum hub to a HyperEVM spoke
|
|
395
|
-
over CCIP, attest the remote balance with two keys, deposit and redeem on the spoke, recall
|
|
396
|
-
and claim, driven through `CrosschainLane` and relayed by `CrosschainSimulator`.
|
|
397
|
-
- [Composed HyperCore flow](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/examples/composed_hypercore_flow_arbitrum_hyperevm.py) (preview feature) — the
|
|
398
|
-
same hub funding a HyperCore vault (market 55) that trades on Hyperliquid Core: the Core leg
|
|
399
|
-
(bridge, dex transfer, order, close, exit) built from the vault's substrate grants and estimated
|
|
400
|
-
with `eth_estimateGas` at head (EVM acceptance only, Core executes later), the REDEEM sized by the vault's EVM exit ceiling behind the executor's
|
|
401
|
-
fee gate, then recall, residual attestation and claim replayed in `CrosschainSimulator` at
|
|
402
|
-
blocks pinned inside the second live cycle.
|
|
403
|
-
|
|
404
395
|
```bash
|
|
405
396
|
export BASE_PROVIDER_URL="https://base-mainnet.g.alchemy.com/v2/YOUR_KEY"
|
|
406
397
|
uv run python examples/simple_aave_v3_supply_base.py
|
|
407
398
|
uv run python examples/advanced_euler_v2_credit_market_base.py
|
|
408
399
|
uv run python examples/external_state_margin_leg_base.py
|
|
409
|
-
uv run python examples/crosschain_ccip_usdc_arbitrum_hyperevm.py # needs ARBITRUM_PROVIDER_URL and HYPEREVM_PROVIDER_URL
|
|
410
|
-
uv run python examples/composed_hypercore_flow_arbitrum_hyperevm.py # same two providers
|
|
411
400
|
```
|
|
412
401
|
|
|
413
402
|
No RPC key? `BASE_PROVIDER_URL=https://mainnet.base.org` (Base's public RPC) runs the examples out of
|
|
@@ -528,12 +517,12 @@ the pilot executors and factories). Pin an exact version if you depend on them.
|
|
|
528
517
|
| Crosschain fuses (market 54): `StargateCrosschainSupplyFuse`, `StargateCrosschainCommandFuse`, `CcipCrosschainSupplyFuse`, `CcipCrosschainCommandFuse`, `CrosschainClaimFuse`; transport-agnostic bases `CrosschainSupplyFuse` / `CrosschainCommandFuse` with `StargateSendParams` / `CcipSendParams`, plus `Command`, `CrosschainSubstrateLib`, `OptionsBuilder` | `ipor_fusion.crosschain` |
|
|
529
518
|
| HyperCore fuses (market 55): `HyperCoreDepositFuse`, `HyperCoreMarginFuse`, `HyperCoreSendFuse`, `HyperCoreOrderFuse`, `HyperCoreCancelFuse`, `HyperCoreBuilderFeeFuse`, `HyperCoreSubstrates` | `ipor_fusion.hypercore`, with `HyperCoreReader`, `read_hypercore_vault_state` and the event decoders |
|
|
530
519
|
|
|
531
|
-
The
|
|
532
|
-
`
|
|
533
|
-
|
|
534
|
-
`
|
|
535
|
-
|
|
536
|
-
passed.
|
|
520
|
+
The crosschain API supports only the contracts of the 2026-10-21 release; earlier
|
|
521
|
+
deployments are unreadable (`MIGRATION_4.md`). `open_lane` and `discover_deployment`
|
|
522
|
+
take the market ID explicitly (54, or a keccak-derived one from
|
|
523
|
+
`crosschain_market_id(name)` for a vault built with its own): `discover_deployment`
|
|
524
|
+
reads the market's executor grants; `open_lane` takes an executor address and uses the
|
|
525
|
+
market ID to find the vault's matching fuses unless they are passed.
|
|
537
526
|
|
|
538
527
|
### Readers (`ipor_fusion.readers`)
|
|
539
528
|
|
|
@@ -320,10 +320,12 @@ A flash-loan fuse also needs `update_callback_handler(handler, sender, selector)
|
|
|
320
320
|
|
|
321
321
|
The full clone → configure → deposit → execute sequence is exercised in [`tests/test_simulate_vault_from_scratch_base.py`](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/tests/test_simulate_vault_from_scratch_base.py).
|
|
322
322
|
|
|
323
|
-
Custom errors of the
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
`SimulationResult.revert_reason` and `TransactionError`
|
|
323
|
+
Custom errors of the IPOR Fusion contracts and the libraries they import
|
|
324
|
+
(OpenZeppelin included) decode by name, so a simulated or sent call that reverts
|
|
325
|
+
reads `AccessManagedUnauthorized(0x...)`, `UnsupportedFuse()` or
|
|
326
|
+
`NavSettledStale(8453)` in `SimulationResult.revert_reason` and `TransactionError`
|
|
327
|
+
instead of a bare selector. Importing `ipor_fusion.crosschain` also registers
|
|
328
|
+
`CROSSCHAIN_ERROR_SIGNATURES`.
|
|
327
329
|
`register_custom_errors([...])` adds your own, and `SimulationResult.raise_for_failure()`
|
|
328
330
|
raises `SimulationError` naming the first failed call.
|
|
329
331
|
|
|
@@ -341,24 +343,11 @@ ever signed or broadcast.
|
|
|
341
343
|
- [External-state margin leg](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/examples/external_state_margin_leg_base.py) — a vault whose capital
|
|
342
344
|
sits off-chain: typed market-50 substrates, a dual-custodian propose/confirm marking the NAV,
|
|
343
345
|
the scheduled-withdrawal prep an alpha performs, and a mismatched confirmation being rejected.
|
|
344
|
-
- [Crosschain CCIP lifecycle](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py) (preview feature) — a vault
|
|
345
|
-
whose capital works on another chain: supply USDC from an Arbitrum hub to a HyperEVM spoke
|
|
346
|
-
over CCIP, attest the remote balance with two keys, deposit and redeem on the spoke, recall
|
|
347
|
-
and claim, driven through `CrosschainLane` and relayed by `CrosschainSimulator`.
|
|
348
|
-
- [Composed HyperCore flow](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/examples/composed_hypercore_flow_arbitrum_hyperevm.py) (preview feature) — the
|
|
349
|
-
same hub funding a HyperCore vault (market 55) that trades on Hyperliquid Core: the Core leg
|
|
350
|
-
(bridge, dex transfer, order, close, exit) built from the vault's substrate grants and estimated
|
|
351
|
-
with `eth_estimateGas` at head (EVM acceptance only, Core executes later), the REDEEM sized by the vault's EVM exit ceiling behind the executor's
|
|
352
|
-
fee gate, then recall, residual attestation and claim replayed in `CrosschainSimulator` at
|
|
353
|
-
blocks pinned inside the second live cycle.
|
|
354
|
-
|
|
355
346
|
```bash
|
|
356
347
|
export BASE_PROVIDER_URL="https://base-mainnet.g.alchemy.com/v2/YOUR_KEY"
|
|
357
348
|
uv run python examples/simple_aave_v3_supply_base.py
|
|
358
349
|
uv run python examples/advanced_euler_v2_credit_market_base.py
|
|
359
350
|
uv run python examples/external_state_margin_leg_base.py
|
|
360
|
-
uv run python examples/crosschain_ccip_usdc_arbitrum_hyperevm.py # needs ARBITRUM_PROVIDER_URL and HYPEREVM_PROVIDER_URL
|
|
361
|
-
uv run python examples/composed_hypercore_flow_arbitrum_hyperevm.py # same two providers
|
|
362
351
|
```
|
|
363
352
|
|
|
364
353
|
No RPC key? `BASE_PROVIDER_URL=https://mainnet.base.org` (Base's public RPC) runs the examples out of
|
|
@@ -479,12 +468,12 @@ the pilot executors and factories). Pin an exact version if you depend on them.
|
|
|
479
468
|
| Crosschain fuses (market 54): `StargateCrosschainSupplyFuse`, `StargateCrosschainCommandFuse`, `CcipCrosschainSupplyFuse`, `CcipCrosschainCommandFuse`, `CrosschainClaimFuse`; transport-agnostic bases `CrosschainSupplyFuse` / `CrosschainCommandFuse` with `StargateSendParams` / `CcipSendParams`, plus `Command`, `CrosschainSubstrateLib`, `OptionsBuilder` | `ipor_fusion.crosschain` |
|
|
480
469
|
| HyperCore fuses (market 55): `HyperCoreDepositFuse`, `HyperCoreMarginFuse`, `HyperCoreSendFuse`, `HyperCoreOrderFuse`, `HyperCoreCancelFuse`, `HyperCoreBuilderFeeFuse`, `HyperCoreSubstrates` | `ipor_fusion.hypercore`, with `HyperCoreReader`, `read_hypercore_vault_state` and the event decoders |
|
|
481
470
|
|
|
482
|
-
The
|
|
483
|
-
`
|
|
484
|
-
|
|
485
|
-
`
|
|
486
|
-
|
|
487
|
-
passed.
|
|
471
|
+
The crosschain API supports only the contracts of the 2026-10-21 release; earlier
|
|
472
|
+
deployments are unreadable (`MIGRATION_4.md`). `open_lane` and `discover_deployment`
|
|
473
|
+
take the market ID explicitly (54, or a keccak-derived one from
|
|
474
|
+
`crosschain_market_id(name)` for a vault built with its own): `discover_deployment`
|
|
475
|
+
reads the market's executor grants; `open_lane` takes an executor address and uses the
|
|
476
|
+
market ID to find the vault's matching fuses unless they are passed.
|
|
488
477
|
|
|
489
478
|
### Readers (`ipor_fusion.readers`)
|
|
490
479
|
|
|
@@ -38,29 +38,6 @@ transaction.
|
|
|
38
38
|
brings the margin home and releases it for a user's scheduled withdrawal, then
|
|
39
39
|
demonstrates the executor rejecting a confirmation that does not match its
|
|
40
40
|
proposal.
|
|
41
|
-
- [`crosschain_ccip_usdc_arbitrum_hyperevm.py`](crosschain_ccip_usdc_arbitrum_hyperevm.py) --
|
|
42
|
-
a vault whose capital works on another chain. Opens a `CrosschainLane` on a
|
|
43
|
-
live Arbitrum hub vault whose executor has a dispatcher on HyperEVM, then
|
|
44
|
-
drives the whole lifecycle over CCIP: supply USDC to the spoke, have a
|
|
45
|
-
proposer and an approver attest the dispatcher's balance into the hub NAV,
|
|
46
|
-
DEPOSIT into and REDEEM from the spoke vault by command, re-attest, recall
|
|
47
|
-
the idle to the hub and claim it back into the vault. Both chains run under
|
|
48
|
-
`eth_simulateV1` and `CrosschainSimulator` relays each CCIP message between
|
|
49
|
-
them, so it needs an Arbitrum and a HyperEVM archive RPC.
|
|
50
|
-
- [`composed_hypercore_flow_arbitrum_hyperevm.py`](composed_hypercore_flow_arbitrum_hyperevm.py) --
|
|
51
|
-
the composed flow: the same Arbitrum hub funding a HyperCore vault on
|
|
52
|
-
HyperEVM (a Plasma Vault that is itself a Hyperliquid Core account) and the
|
|
53
|
-
trade inside it. Part A builds the Core leg from the vault's market-55
|
|
54
|
-
substrate grants (bridge EVM -> Core, spot -> perp dex, a limit order and its
|
|
55
|
-
reduce-only close, dex -> spot, Core -> EVM) and estimates each action with
|
|
56
|
-
`eth_estimateGas` at head -- six independent previews, EVM acceptance only --
|
|
57
|
-
with a balance override where the vault holds no USDC and sized to the live
|
|
58
|
-
Core inventory where the fuse checks a Core balance or dex equity, because
|
|
59
|
-
`eth_simulateV1` cannot run the HyperCore precompiles.
|
|
60
|
-
Part B replays the hub legs of the second live cycle in `CrosschainSimulator`
|
|
61
|
-
at pinned blocks: the REDEEM sized by `read_hypercore_evm_exit_ceiling` behind
|
|
62
|
-
the executor's maxFee gate, then recall, token return, the residual
|
|
63
|
-
attestation and the claim. Nothing is signed; it needs the same two RPCs.
|
|
64
41
|
|
|
65
42
|
## Prerequisites
|
|
66
43
|
|
|
@@ -4,7 +4,6 @@ log_cli_level = INFO
|
|
|
4
4
|
addopts = --cov=src/ipor_fusion --cov-report=term-missing --cov-report=xml:coverage.xml
|
|
5
5
|
testpaths = tests
|
|
6
6
|
markers =
|
|
7
|
-
readiness: live crosschain availability checks (requires --run-readiness; excluded by default)
|
|
8
7
|
sdk: SDK core and fuse tests (integration ones need *_PROVIDER_URL, auto-skip otherwise)
|
|
9
8
|
cli: CLI unit tests (no network required)
|
|
10
9
|
mcp: MCP server tests (no network required)
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Regenerate ``src/ipor_fusion/fusion_errors.py`` from an ipor-fusion checkout.
|
|
3
|
+
|
|
4
|
+
Collects every ``error`` declaration of the Solidity files reachable by import
|
|
5
|
+
from ``contracts/`` (the contracts and the libraries they import, OpenZeppelin
|
|
6
|
+
included, resolved through the checkout's ``foundry.toml`` remappings) and
|
|
7
|
+
writes them as
|
|
8
|
+
canonical ``Name(type,...)`` signatures: enums become ``uint8``, contract,
|
|
9
|
+
interface and library types ``address``, ``uint``/``int`` their 256-bit form.
|
|
10
|
+
Any other parameter type (a struct, a user-defined value type) stops the run,
|
|
11
|
+
because its canonical form needs the compiler.
|
|
12
|
+
|
|
13
|
+
uv run python scripts/fusion_error_signatures.py ../ipor-fusion --source <commit>
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import argparse
|
|
19
|
+
import re
|
|
20
|
+
import sys
|
|
21
|
+
import tomllib
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
|
|
24
|
+
_OUTPUT = Path(__file__).resolve().parent.parent / "src/ipor_fusion/fusion_errors.py"
|
|
25
|
+
_IMPORT = re.compile(r'^\s*import\s+(?:[^"\']*\s+from\s+)?["\']([^"\']+)["\']', re.M)
|
|
26
|
+
_ERROR = re.compile(r"\berror\s+(\w+)\s*\(([^)]*)\)\s*;")
|
|
27
|
+
_ENUM = re.compile(r"\benum\s+(\w+)")
|
|
28
|
+
_CONTRACT = re.compile(r"\b(?:abstract\s+)?(?:contract|interface|library)\s+(\w+)")
|
|
29
|
+
_ELEMENTARY = re.compile(
|
|
30
|
+
r"^(address|bool|string|bytes([1-9]|[12]\d|3[0-2])?|u?int(8|16|24|32|40|48|56|64"
|
|
31
|
+
r"|72|80|88|96|104|112|120|128|136|144|152|160|168|176|184|192|200|208|216|224"
|
|
32
|
+
r"|232|240|248|256)?)$"
|
|
33
|
+
)
|
|
34
|
+
_COMMENTS = re.compile(r"//[^\n]*|/\*.*?\*/", re.S)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class _Resolver:
|
|
38
|
+
"""Forge's import resolution: relative paths, then the longest matching
|
|
39
|
+
remapping, then the checkout root and each ``libs`` directory."""
|
|
40
|
+
|
|
41
|
+
def __init__(self, root: Path) -> None:
|
|
42
|
+
profile = tomllib.loads((root / "foundry.toml").read_text())["profile"]
|
|
43
|
+
default = profile["default"]
|
|
44
|
+
pairs = [entry.split("=", 1) for entry in default["remappings"]]
|
|
45
|
+
self._root = root
|
|
46
|
+
self._remappings = sorted(pairs, key=lambda pair: -len(pair[0]))
|
|
47
|
+
self._bases = [root, *(root / lib for lib in default["libs"])]
|
|
48
|
+
|
|
49
|
+
def __call__(self, spec: str, importer: Path) -> Path:
|
|
50
|
+
if spec.startswith("."):
|
|
51
|
+
return (importer.parent / spec).resolve()
|
|
52
|
+
for prefix, target in self._remappings:
|
|
53
|
+
if spec.startswith(prefix):
|
|
54
|
+
return (self._root / (target + spec.removeprefix(prefix))).resolve()
|
|
55
|
+
for base in self._bases:
|
|
56
|
+
if (base / spec).is_file():
|
|
57
|
+
return (base / spec).resolve()
|
|
58
|
+
return (self._root / spec).resolve()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _closure(root: Path) -> dict[Path, str]:
|
|
62
|
+
resolve = _Resolver(root)
|
|
63
|
+
pending = sorted((root / "contracts").rglob("*.sol"))
|
|
64
|
+
sources: dict[Path, str] = {}
|
|
65
|
+
while pending:
|
|
66
|
+
path = pending.pop()
|
|
67
|
+
if path in sources:
|
|
68
|
+
continue
|
|
69
|
+
if not path.is_file():
|
|
70
|
+
raise SystemExit(f"unresolved import: {path}")
|
|
71
|
+
text = _COMMENTS.sub("", path.read_text())
|
|
72
|
+
sources[path] = text
|
|
73
|
+
pending.extend(resolve(spec, path) for spec in _IMPORT.findall(text))
|
|
74
|
+
return sources
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _canonical(param: str, enums: set[str], contracts: set[str], where: str) -> str:
|
|
78
|
+
kind = param.split()[0].split(".")[-1]
|
|
79
|
+
if kind in ("uint", "int"):
|
|
80
|
+
return f"{kind}256"
|
|
81
|
+
if _ELEMENTARY.fullmatch(kind):
|
|
82
|
+
return kind
|
|
83
|
+
if kind in enums:
|
|
84
|
+
return "uint8"
|
|
85
|
+
if kind in contracts:
|
|
86
|
+
return "address"
|
|
87
|
+
raise SystemExit(f"{where}: no canonical form for parameter type {kind!r}")
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def collect(root: Path) -> list[str]:
|
|
91
|
+
sources = _closure(root)
|
|
92
|
+
enums = {name for text in sources.values() for name in _ENUM.findall(text)}
|
|
93
|
+
contracts = {name for text in sources.values() for name in _CONTRACT.findall(text)}
|
|
94
|
+
signatures: set[str] = set()
|
|
95
|
+
for path, text in sources.items():
|
|
96
|
+
for name, params in _ERROR.findall(text):
|
|
97
|
+
types = [
|
|
98
|
+
_canonical(p.strip(), enums, contracts, f"{path}: {name}")
|
|
99
|
+
for p in params.split(",")
|
|
100
|
+
if p.strip()
|
|
101
|
+
]
|
|
102
|
+
signatures.add(f"{name}({','.join(types)})")
|
|
103
|
+
return sorted(signatures)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def render(signatures: list[str], source: str) -> str:
|
|
107
|
+
lines = "\n".join(f' "{signature}",' for signature in signatures)
|
|
108
|
+
return f'''"""Custom errors of the IPOR Fusion contracts and the libraries they import
|
|
109
|
+
(OpenZeppelin included), registered by :mod:`ipor_fusion.errors` so revert data
|
|
110
|
+
decodes by name (``AccessManagedUnauthorized(0x...)``, ``UnsupportedFuse()``)
|
|
111
|
+
instead of a bare selector.
|
|
112
|
+
|
|
113
|
+
Generated by ``scripts/fusion_error_signatures.py`` from ipor-fusion {source};
|
|
114
|
+
do not edit by hand.
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
#: ``Name(type,...)`` signatures, sorted; the selector is the keccak of each.
|
|
118
|
+
FUSION_ERROR_SIGNATURES: tuple[str, ...] = (
|
|
119
|
+
{lines}
|
|
120
|
+
)
|
|
121
|
+
'''
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def main() -> None:
|
|
125
|
+
parser = argparse.ArgumentParser(description="Regenerate fusion_errors.py.")
|
|
126
|
+
parser.add_argument("checkout", type=Path, help="ipor-fusion checkout")
|
|
127
|
+
parser.add_argument(
|
|
128
|
+
"--source", required=True, help="what the checkout is, e.g. a commit"
|
|
129
|
+
)
|
|
130
|
+
args = parser.parse_args()
|
|
131
|
+
signatures = collect(args.checkout.resolve())
|
|
132
|
+
_OUTPUT.write_text(render(signatures, args.source))
|
|
133
|
+
print(f"{len(signatures)} signatures -> {_OUTPUT}", file=sys.stderr)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
if __name__ == "__main__":
|
|
137
|
+
main()
|
|
@@ -5,6 +5,7 @@ from dataclasses import dataclass
|
|
|
5
5
|
from typing import Generic, TypeVar, cast
|
|
6
6
|
|
|
7
7
|
from eth_abi import decode, encode
|
|
8
|
+
from eth_abi.exceptions import DecodingError
|
|
8
9
|
from eth_typing import ChecksumAddress
|
|
9
10
|
from eth_utils import function_signature_to_4byte_selector
|
|
10
11
|
from web3 import Web3
|
|
@@ -53,6 +54,9 @@ class Call(Generic[T_co]):
|
|
|
53
54
|
data: bytes
|
|
54
55
|
output_types: Sequence[str] | None = None
|
|
55
56
|
decoder: Callable[..., T_co] | None = None
|
|
57
|
+
#: Turns an ABI decoding failure of the return data into a named error
|
|
58
|
+
#: (for a contract build whose return layout differs); ``None`` re-raises.
|
|
59
|
+
decode_error: Callable[[DecodingError], Exception] | None = None
|
|
56
60
|
|
|
57
61
|
def __post_init__(self) -> None:
|
|
58
62
|
if self.output_types is not None:
|
|
@@ -81,6 +85,7 @@ class Call(Generic[T_co]):
|
|
|
81
85
|
data=self.data,
|
|
82
86
|
output_types=self.output_types,
|
|
83
87
|
decoder=mapped,
|
|
88
|
+
decode_error=self.decode_error,
|
|
84
89
|
)
|
|
85
90
|
|
|
86
91
|
def call(self, ctx: Web3Context, *, block: BlockIdentifier | None = None) -> T_co:
|
|
@@ -112,7 +117,12 @@ class Call(Generic[T_co]):
|
|
|
112
117
|
of `.call(ctx)`, for return data fetched elsewhere (e.g. `Multicall3`)."""
|
|
113
118
|
if not self.output_types:
|
|
114
119
|
raise ValueError("Call.decode() on a write-only Call.")
|
|
115
|
-
|
|
120
|
+
try:
|
|
121
|
+
values = tuple(decode(self.output_types, bytes(raw)))
|
|
122
|
+
except DecodingError as exc:
|
|
123
|
+
if self.decode_error is None:
|
|
124
|
+
raise
|
|
125
|
+
raise self.decode_error(exc) from exc
|
|
116
126
|
single: object = values[0] if len(values) == 1 else values
|
|
117
127
|
if self.decoder is not None:
|
|
118
128
|
return self.decoder(single)
|
|
@@ -163,12 +173,14 @@ class ContractWrapper:
|
|
|
163
173
|
*args: object,
|
|
164
174
|
output_types: Sequence[str],
|
|
165
175
|
decoder: Callable[..., T] | None = None,
|
|
176
|
+
decode_error: Callable[[DecodingError], Exception] | None = None,
|
|
166
177
|
) -> Call[T]:
|
|
167
178
|
return Call(
|
|
168
179
|
to=self._address,
|
|
169
180
|
data=_encode_calldata(signature, *args),
|
|
170
181
|
output_types=output_types,
|
|
171
182
|
decoder=decoder,
|
|
183
|
+
decode_error=decode_error,
|
|
172
184
|
)
|
|
173
185
|
|
|
174
186
|
def _write(self, signature: str, *args: object) -> Call[None]:
|
{ipor_fusion-4.0.0.dev308 → ipor_fusion-4.0.0.dev315}/src/ipor_fusion/crosschain/__init__.py
RENAMED
|
@@ -110,6 +110,8 @@ from ipor_fusion.crosschain.messages import (
|
|
|
110
110
|
CCIP_VERSION,
|
|
111
111
|
CODEC_VERSION,
|
|
112
112
|
EMPTY_COMMAND,
|
|
113
|
+
MAX_COMMAND_EXECUTION_GAS,
|
|
114
|
+
NO_FEE_CEILING,
|
|
113
115
|
BusinessAction,
|
|
114
116
|
CcipMsgType,
|
|
115
117
|
Command,
|
|
@@ -117,6 +119,7 @@ from ipor_fusion.crosschain.messages import (
|
|
|
117
119
|
CrosschainTransportKind,
|
|
118
120
|
DeploymentStatus,
|
|
119
121
|
MsgType,
|
|
122
|
+
TrackedVaultPricing,
|
|
120
123
|
decode_ccip_envelope,
|
|
121
124
|
decode_command,
|
|
122
125
|
decode_envelope,
|
|
@@ -254,6 +257,9 @@ __all__ = [
|
|
|
254
257
|
"CrosschainTransportKind",
|
|
255
258
|
"DeploymentStatus",
|
|
256
259
|
"EMPTY_COMMAND",
|
|
260
|
+
"MAX_COMMAND_EXECUTION_GAS",
|
|
261
|
+
"NO_FEE_CEILING",
|
|
262
|
+
"TrackedVaultPricing",
|
|
257
263
|
"EVMTokenAmount",
|
|
258
264
|
"EnforcedOptionParam",
|
|
259
265
|
"ExecutorInitParams",
|