ipor-fusion 4.0.0.dev171__tar.gz → 4.0.0.dev185__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.dev171 → ipor_fusion-4.0.0.dev185}/.github/workflows/python-publish.yml +5 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/AGENTS.md +19 -7
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/MIGRATION_4.md +115 -54
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/PKG-INFO +14 -13
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/README.md +13 -12
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/examples/advanced_euler_v2_credit_market_base.py +14 -2
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/examples/advanced_euler_v2_looping_arbitrum.py +14 -2
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/examples/composed_hypercore_flow_arbitrum_hyperevm.py +16 -8
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/examples/external_state_margin_leg_base.py +30 -11
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/examples/simple_aave_v3_supply_base.py +15 -2
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/pyproject.toml +12 -7
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/scripts/crosschain_readiness.py +378 -115
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/__init__.py +14 -4
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/cli/market_cmd.py +5 -2
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/cli/options.py +16 -5
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/cli/vault_markets_view.py +1 -1
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/core/__init__.py +66 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/core/access.py +2 -2
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/core/contract.py +18 -6
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/core/external_state_executor.py +2 -10
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/core/fee_manager.py +6 -2
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/core/fuse.py +3 -2
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/core/fusion_factory.py +24 -17
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/core/logs.py +10 -1
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/core/oracle.py +3 -3
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/core/plasma_vault.py +7 -5
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/core/rewards_manager.py +6 -6
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/core/simulation.py +52 -219
- ipor_fusion-4.0.0.dev185/src/ipor_fusion/core/simulation_result.py +311 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/core/withdraw_manager.py +6 -4
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/ccip/chainlink.py +3 -1
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/ccip/codec.py +4 -4
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/ccip/contracts.py +24 -4
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/ccip/events.py +6 -5
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/ccip/quote.py +1 -1
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/ccip/transport.py +3 -2
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/contracts.py +5 -2
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/lane.py +5 -4
- ipor_fusion-4.0.0.dev185/src/ipor_fusion/crosschain/logs.py +38 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/messages.py +11 -5
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/stargate/contracts.py +22 -3
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/stargate/layerzero.py +3 -2
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/stargate/transport.py +3 -2
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/transport.py +3 -2
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/errors.py +6 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/fuses/__init__.py +54 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/fuses/euler_v2.py +35 -17
- ipor_fusion-4.0.0.dev185/src/ipor_fusion/fuses/events.py +178 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/fuses/external_state_event_decoding.py +14 -116
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/fuses/hypercore_event_decoding.py +23 -40
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/readers/aave_v3.py +20 -3
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/readers/aave_v4.py +3 -1
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/readers/hypercore.py +33 -12
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/readers/morpho.py +20 -5
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/readers/position_manager.py +25 -8
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/readers/unpriceable.py +7 -3
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/vault_erc20.py +10 -3
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/vault_positions.py +2 -2
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/_euler_v2.py +1 -1
- ipor_fusion-4.0.0.dev185/tests/_fake_rpc.py +106 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/_simulate.py +14 -2
- ipor_fusion-4.0.0.dev185/tests/fixtures/vault_info_golden/fetched.cli.json +199 -0
- ipor_fusion-4.0.0.dev185/tests/fixtures/vault_info_golden/fetched.json +197 -0
- ipor_fusion-4.0.0.dev185/tests/fixtures/vault_info_golden/fetched.mcp.json +207 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_contract_call.py +40 -1
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_crosschain_contracts.py +1 -1
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_crosschain_errors.py +1 -1
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_crosschain_lane.py +1 -1
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_crosschain_transport.py +2 -1
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_error_hierarchy.py +2 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_examples_vaults.py +1 -1
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_external_state_executor.py +10 -9
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_hypercore_events.py +62 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_oracle.py +4 -3
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_public_api.py +76 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_revert_decoding.py +7 -6
- ipor_fusion-4.0.0.dev185/tests/test_simulation_observation.py +267 -0
- ipor_fusion-4.0.0.dev185/tests/test_vault_info_fetched_golden.py +209 -0
- ipor_fusion-4.0.0.dev171/src/ipor_fusion/crosschain/logs.py +0 -27
- ipor_fusion-4.0.0.dev171/src/ipor_fusion/fuses/events.py +0 -45
- ipor_fusion-4.0.0.dev171/tests/test_simulation_observation.py +0 -126
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/.claude-plugin/marketplace.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/.claude-plugin/plugin.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/.env.example +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/.gemini/settings.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/.git-blame-ignore-revs +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/.github/workflows/cd.yml +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/.github/workflows/ci.yml +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/.github/workflows/commit-lint.yml +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/.github/workflows/notify-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/.github/workflows/python-build.yml +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/.github/workflows/release.yml +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/.github/workflows/report-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/.gitignore +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/.pre-commit-config.yaml +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/.python-version +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/CHANGELOG.md +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/CLAUDE.md +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/CODEOWNERS +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/LICENSE +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/build.sh +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/examples/CONTRIBUTING.md +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/examples/README.md +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/pytest.ini +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/scripts/commit-check.sh +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/skills/ipor-deploy-vault/SKILL.md +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/about.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/cache.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/chains.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/cli/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/cli/changelog_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/cli/config_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/cli/config_store.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/cli/main.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/cli/oracle_mapping_view.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/cli/vault_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/cli/vault_health.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/cli/vault_info_view.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/cli/vault_rendering.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/config/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/config/roles.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/core/address.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/core/context.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/core/erc20.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/core/fuse_action.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/core/multicall.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/ccip/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/ccip/indexer.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/ccip/lane.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/discovery.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/errors.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/fuses/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/fuses/base.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/fuses/ccip.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/fuses/stargate.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/simulation.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/stargate/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/crosschain/stargate/lane.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/dependency_graph.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/entry_cli.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/entry_mcp.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/explorer.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/field_docs.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/fuses/aave_v3.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/fuses/async_action.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/fuses/base.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/fuses/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/fuses/erc4626.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/fuses/external_state.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/fuses/fluid_instadapp.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/fuses/gearbox_v3.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/fuses/hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/fuses/merkl.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/fuses/morpho.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/fuses/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/fuses/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/fuses/universal.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/guide/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/guide/architecture.md +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/guide/glossary.md +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/guide/invariants.md +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/guide/quickstart.md +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/market_ids.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/market_info.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/mcp/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/mcp/guide.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/mcp/models.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/mcp/server.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/morpho_api.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/py.typed +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/readers/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/readers/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/readers/hypercore_outcome.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/readers/lending_health.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/readers/oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/readers/oracle_mapping_nodes.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/readers/oracle_mapping_reader.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/readers/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/readers/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/substrates.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/types.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/validation.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/vault_data.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/vault_info.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/vault_managers.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/src/ipor_fusion/vault_reads.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/UniswapV3UniversalRouter.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/_crosschain_recovery.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/_event_args.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/_foundry.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/_golden.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/_guide.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/_hypercore_model.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/_hypercore_shadow.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/_oracle_mapping_fake.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/_validation.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/addresses.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/conftest.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/constants.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/hypercore_hip3_flow.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/hypercore_market55.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/market_golden/meta_morpho_v1.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/market_golden/meta_morpho_v1.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/market_golden/meta_morpho_v2.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/market_golden/meta_morpho_v2.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/market_golden/morpho_api/market.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/market_golden/morpho_api/vault_v1.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/market_golden/morpho_api/vault_v2.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/market_golden/morpho_api/vault_v2_not_found.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/market_golden/morpho_blue.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/market_golden/morpho_blue.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/market_golden/morpho_blue_api_error.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/market_golden/morpho_blue_api_error.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/market_golden/morpho_blue_no_api.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/market_golden/morpho_blue_no_api.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/oracle_mapping_golden/mapping.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/oracle_mapping_golden/mapping.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/simulate_v1_request.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/vault_info_golden/clean.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/vault_info_golden/clean.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/vault_info_golden/clean.txt +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/vault_info_golden/deployment_error.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/vault_info_golden/deployment_error.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/vault_info_golden/deployment_error.txt +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/vault_info_golden/full.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/vault_info_golden/full.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/vault_info_golden/full.txt +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/vault_info_golden/rich.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/vault_info_golden/rich.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/fixtures/vault_info_golden/rich.txt +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_about.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_access_manager.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_cache.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_chains.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_cli_changelog.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_cli_commands.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_cli_config_store.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_cli_helpers.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_cli_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_cli_lending_health.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_cli_market_golden.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_cli_market_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_cli_oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_cli_oracle_mapping_golden.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_cli_pending_requests_scan.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_cli_role_accounts.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_cli_vault_info_golden.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_cli_vault_predates_getters.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_cli_vault_validate.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_contract_encoder.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_crosschain_ccip_events.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_crosschain_ccip_indexer.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_crosschain_ccip_quote.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_crosschain_chainlink.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_crosschain_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_crosschain_layering.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_crosschain_readiness.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_crosschain_readiness_report.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_docs_typing.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_erc20.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_examples_composed_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_examples_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_examples_euler_looping_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_explorer.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_external_state_events.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_fee_manager.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_fuse_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_fusion_instance.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_guide.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_hypercore_deployment.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_hypercore_flow.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_hypercore_live.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_hypercore_outcome.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_hypercore_readers.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_hypercore_simulation.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_logs.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_mcp_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_mcp_models.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_mcp_server.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_mcp_vault_validate.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_plasma_vault.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_public_type_reachability.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_reader_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_readiness_selection.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_rewards_manager.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_roles.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_sdk_layering.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_borrow_aave_v3_mainnet.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_claim_merkl_wrapper_base.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_claim_morpho_rewards.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_crosschain_canary.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_crosschain_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_crosschain_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_euler_v2_batch_base.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_euler_v2_swap_deploy_base.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_euler_v2_swap_reconfigure_base.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_euler_v2_swap_registry_base.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_examples_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_examples_base.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_examples_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_external_state_executor_base.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_fusion_factory_clone_base.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_looping_aave_v3_base.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_looping_morpho_blue_base.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_pilot_v3.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_pilot_v4_uniswap.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_pilot_v5_ramses.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_pilot_v5_scheduled.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_plasma_vault_setters_base.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_readers_integration.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_release_funds.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_swap_on_base.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulate_vault_from_scratch_base.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_simulation_errors.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_solidity_compiler.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_solidity_mirrors.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_substrates.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_types_and_events.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_unpriceable_tokens.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_validation.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_vault_data_block.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_vault_dep_graph.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_vault_info_onchain_base.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_vault_info_onchain_base_no_withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_vault_simulator_blocks.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_web3_context.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/test_withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/typed_client/consumer.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/tests/typed_client/rejected.py +0 -0
- {ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/uv.lock +0 -0
|
@@ -133,6 +133,11 @@ jobs:
|
|
|
133
133
|
run: uv run ruff check ./
|
|
134
134
|
id: static-code-analyze
|
|
135
135
|
|
|
136
|
+
- name: Type check
|
|
137
|
+
if: inputs.static-code-analysis-enabled
|
|
138
|
+
run: uv run pyright
|
|
139
|
+
id: type-check
|
|
140
|
+
|
|
136
141
|
- name: Version release (semantic)
|
|
137
142
|
if: inputs.publish-enabled && !inputs.skip-version-bump && !inputs.dev-build
|
|
138
143
|
id: release
|
|
@@ -26,7 +26,7 @@ repository-local work that does not require protocol context.
|
|
|
26
26
|
uv sync --all-extras --locked # install, same as CI
|
|
27
27
|
uv run ruff format ./ # format (CI runs --check)
|
|
28
28
|
uv run ruff check ./ # lint: bandit S, C901 max-complexity 10, PLR limits
|
|
29
|
-
uv run pyright # types, basic mode, src + tests
|
|
29
|
+
uv run pyright # types, basic mode, src + tests + examples + scripts
|
|
30
30
|
uv run pytest # all tests + coverage gate (fail_under = 95)
|
|
31
31
|
uv run pytest -m "cli or mcp" --no-cov # fast offline subset
|
|
32
32
|
uv run pytest --run-readiness -m readiness --no-cov -rA # opt-in live Ethereum-hub POC checks
|
|
@@ -40,8 +40,12 @@ uv lock --check # uv.lock in sync
|
|
|
40
40
|
`fusion market morpho-blue|meta-morpho --json`, `fusion vault oracle-mapping
|
|
41
41
|
--json` and the matching MCP tools (`vault_info`, `market_morpho_blue`,
|
|
42
42
|
`market_meta_morpho`, `vault_oracle_mapping`, called through the server) is pinned
|
|
43
|
-
in `tests/fixtures/*_golden/` (`tests/_golden.py`, the `*_golden.py` tests),
|
|
44
|
-
|
|
43
|
+
in `tests/fixtures/*_golden/` (`tests/_golden.py`, the `*_golden.py` tests), with
|
|
44
|
+
no network. Most scenarios render synthetic snapshots (a hand-built `VaultData` or
|
|
45
|
+
fixed reader answers over a fake chain) to cover every rendering branch;
|
|
46
|
+
`test_vault_info_fetched_golden.py` runs `fetch_vault_data` unpatched over a fake
|
|
47
|
+
JSON-RPC provider (`tests/_fake_rpc.py`) to pin the whole fetch-to-output path. A
|
|
48
|
+
change to any of them fails those tests;
|
|
45
49
|
regenerate with `UPDATE_GOLDEN=1` only when the change is intended and review the
|
|
46
50
|
fixture diff. Without it the tests only compare.
|
|
47
51
|
|
|
@@ -252,14 +256,19 @@ the lifecycle matrix follows that.
|
|
|
252
256
|
prefer a storage or view read over a scan, as `read_balance_fuses` and
|
|
253
257
|
`read_withdraw_manager_address` do), `plasma_vault`, `access`, `withdraw_manager`, `rewards_manager`, `fee_manager`,
|
|
254
258
|
`simulation` (`VaultSimulator`, eth_simulateV1, `erc20_balance_slot` and ERC-20 balance
|
|
255
|
-
overrides), `
|
|
259
|
+
overrides), `simulation_result` (the run's records, `SimulatedLog`, and the parsing
|
|
260
|
+
of the node's response), `oracle`, `fusion_factory`,
|
|
256
261
|
`external_state_executor` (NAV marks for market 50), `erc20`, `fuse_action`
|
|
257
262
|
(`FuseAction`), `fuse` (the `Fuse` base, `StakeFuse`, the shared validators and
|
|
258
263
|
substrate packers), `address` (`_validate_not_zero_address`). `core` imports neither
|
|
259
264
|
`fuses` nor `crosschain` (`tests/test_sdk_layering.py`)
|
|
260
265
|
- `fuses/` — per-protocol fuse encoders (aave_v3, async_action, compound_v3,
|
|
261
266
|
erc4626, euler_v2, external_state, fluid_instadapp, gearbox_v3, merkl, morpho, ramses_v2,
|
|
262
|
-
uniswap_v3, universal
|
|
267
|
+
uniswap_v3, universal); `events.py` (`extract_events`, `abi_value` and the raw-log
|
|
268
|
+
event decoder both event families share), `external_state_event_decoding.py` and
|
|
269
|
+
`hypercore_event_decoding.py` (the ExternalState and HyperCore event specs, classes
|
|
270
|
+
and decoders; internal modules, the names are exported from `ipor_fusion.fuses`);
|
|
271
|
+
`base.py` re-exports the `core/fuse.py` base and validators,
|
|
263
272
|
`FuseAction` and `ZERO_ADDRESS` (from `types`). A fuse is a value: equality and
|
|
264
273
|
hash cover its class and every attribute it stores
|
|
265
274
|
- `crosschain/` — crosschain Plasma Vaults (executor on the hub chain, dispatcher at
|
|
@@ -389,9 +398,12 @@ or examples.
|
|
|
389
398
|
`MorphoBlueMarketId` is always `0x` + 64 lowercase hex, built by
|
|
390
399
|
`parse_morpho_market_id`. Raw input
|
|
391
400
|
is parsed once at the boundary (click param types, MCP tools, the user config).
|
|
392
|
-
`src/`, `examples/` and `tests/typed_client/` are checked with
|
|
401
|
+
`src/`, `examples/`, `scripts/` and `tests/typed_client/` are checked with
|
|
393
402
|
`reportArgumentType` on, so a bare `int`/`str` passed for one fails pyright; the
|
|
394
|
-
other tests keep it off and pass literals.
|
|
403
|
+
other tests keep it off and pass literals. The same roots turn on
|
|
404
|
+
`reportMissingTypeArgument` and `reportUnknownParameterType`: spell every type
|
|
405
|
+
argument (`tuple[int, str]` for a decoded ABI tuple, `Call[object]` where the
|
|
406
|
+
result is ignored, `RawLog` for a raw log), never a bare generic.
|
|
395
407
|
- Addresses: fuse, factory and manager addresses per chain come from
|
|
396
408
|
`ipor-abi` `addresses.json`; a fuse must be registered on the vault
|
|
397
409
|
(`PlasmaVault.get_fuses()`) and its market granted substrates before an
|
|
@@ -23,41 +23,58 @@ the details, and each change is described once, in its section.
|
|
|
23
23
|
Work through these in order; each is what breaks first at run time after the one
|
|
24
24
|
before it is fixed.
|
|
25
25
|
|
|
26
|
-
1. **
|
|
26
|
+
1. **Removed and renamed imports fail first, at import.** The crosschain encoders
|
|
27
|
+
left `ipor_fusion.fuses.crosschain` for `ipor_fusion.crosschain.fuses` (no shim);
|
|
28
|
+
the event decoder modules `ipor_fusion.fuses.external_state_events` and
|
|
29
|
+
`ipor_fusion.fuses.hypercore_events` are renamed `external_state_event_decoding`
|
|
30
|
+
and `hypercore_event_decoding` (import their names from `ipor_fusion` or
|
|
31
|
+
`ipor_fusion.fuses`); `IporFusionMarkets.RWA`, `MORPHO_BLUE_ADDRESS`, the 3.x cache
|
|
32
|
+
functions, `read_erc20_holdings`, `ExternalStateExecutor.mark_nav` and `NavMark`
|
|
33
|
+
are gone. See [Moved, removed and reshaped](#moved-removed-and-reshaped).
|
|
34
|
+
2. **Wrappers are built from an address; execution takes the context.**
|
|
27
35
|
`PlasmaVault(vault)`, `ERC20(token)`, `AccessManager(manager)`; then
|
|
28
36
|
`.call(ctx)`, `.send(ctx)`, `.build_transaction(ctx)`, `.estimate_gas(ctx)`. See
|
|
29
37
|
[Context-free wrappers](#context-free-wrappers).
|
|
30
|
-
|
|
38
|
+
3. **Methods that read the chain to answer are `read_*(ctx, ...)`**:
|
|
31
39
|
`vault.get_balance_fuses()` is `vault.read_balance_fuses(ctx)`,
|
|
32
40
|
`access_manager.owner()` is `read_owner(ctx)`. See
|
|
33
41
|
[Renamed methods](#renamed-methods).
|
|
34
|
-
|
|
42
|
+
4. **Pin a block with `ctx = ctx.at_block(n)`.** Assigning `ctx.default_block`
|
|
35
43
|
raises `AttributeError`. See [Vault reads and validation](#vault-reads-and-validation).
|
|
36
|
-
|
|
44
|
+
5. **The vault read is one snapshot.** `fetch_vault_data(ctx, vault, *, block=None,
|
|
37
45
|
lending=True, metadata=True)` takes the vault address and the chain from `ctx`;
|
|
38
46
|
`validate_vault_state(state)` and `build_vault_info_json(data, *,
|
|
39
47
|
resolve_name=None)` are pure. See [Vault reads and validation](#vault-reads-and-validation).
|
|
40
|
-
|
|
41
|
-
`
|
|
42
|
-
`
|
|
43
|
-
`
|
|
48
|
+
6. **Simulations return typed observations.** `sim.observe("label", call)` raises
|
|
49
|
+
`TypeError`: `read = sim.observe(call, label="label")` returns a
|
|
50
|
+
`SimulationObservation`, read as `read.value` after `run()`;
|
|
51
|
+
`SimulationResult.get`, `SimulationResult.observations` and
|
|
52
|
+
`SimulatedCallResult.decoded` are removed (`AttributeError`). `label` is
|
|
53
|
+
keyword-only on `observe`, `add_call`, `add_transaction` and `deploy_contract`.
|
|
54
|
+
A failed `run()` leaves every observation unresolved instead of holding the
|
|
55
|
+
previous run's value. The result records are frozen, logs are `SimulatedLog`
|
|
56
|
+
records, and a failed call always carries an `error`. See
|
|
57
|
+
[Typed batches and simulation observations](#typed-batches-and-simulation-observations)
|
|
58
|
+
and [Behavior changes](#behavior-changes).
|
|
59
|
+
7. **Options by keyword and other reshaped signatures.** Several functions take
|
|
44
60
|
their options by keyword or renamed a parameter. See
|
|
45
61
|
[Moved, removed and reshaped](#moved-removed-and-reshaped).
|
|
46
|
-
|
|
47
|
-
class (empty call results, crosschain discovery, simulation, Morpho API
|
|
48
|
-
[Errors](#errors).
|
|
49
|
-
|
|
62
|
+
8. **Errors.** Every SDK exception derives from `IporFusionError`; some raises changed
|
|
63
|
+
class (empty call results, crosschain discovery, simulation, Morpho API, malformed
|
|
64
|
+
HyperCore logs). See [Errors](#errors).
|
|
65
|
+
9. **Cache and request limit.** `Web3Context.from_url` bounds requests in flight at
|
|
50
66
|
8 (`max_concurrent_requests`; `InFlightLimit` to share a bound, `None` to lift
|
|
51
67
|
it), and the contract cache is injected per context (`NullCache()` keeps
|
|
52
68
|
nothing). See [Contract cache and request limit](#contract-cache-and-request-limit).
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
69
|
+
10. **Typed callers** (pyright, mypy, Pylance): ids, addresses and amounts are
|
|
70
|
+
nominal types. Wrap literals and raw values, `ChainId(8453)`, `Period(0)`,
|
|
71
|
+
`Amount(n)`, `parse_fuse_address(...)`; values the SDK returns already carry
|
|
72
|
+
their type. See [Nominal types](#nominal-types).
|
|
73
|
+
11. **Typed JSON documents and events.** `build_vault_info_json` and the `fusion
|
|
74
|
+
market` builders return TypedDicts (`VaultInfoJson`, ...); code annotating them
|
|
75
|
+
`dict[str, Any]` switches to the TypedDict or `Mapping[str, object]`. Decoded
|
|
76
|
+
events are discriminated unions narrowed by `event.name`. See
|
|
77
|
+
[Typed JSON documents](#typed-json-documents) and [Decoded events](#decoded-events).
|
|
61
78
|
|
|
62
79
|
Then read [Behavior changes](#behavior-changes): they apply to every caller,
|
|
63
80
|
type-checked or not.
|
|
@@ -174,7 +191,13 @@ assets.value, fuses.value, name.value
|
|
|
174
191
|
instead of the simulator, so it no longer chains, and its label is optional (it
|
|
175
192
|
names the read in `result.calls` and in failures). After `run()`,
|
|
176
193
|
`observation.value` is the read decoded as its `Call` decodes it, from the latest
|
|
177
|
-
run; `observation.result` is its `SimulatedCallResult`.
|
|
194
|
+
run; `observation.result` is its `SimulatedCallResult`. Every `run()` unresolves the
|
|
195
|
+
observations when it starts and resolves them only once the whole response has
|
|
196
|
+
parsed: after a failed run (a transport error, an RPC error, a malformed response,
|
|
197
|
+
raised as `SimulationRunError` for the last two) reading one raises `RuntimeError`
|
|
198
|
+
until a run succeeds. `label` is keyword-only on `add_call` and `add_transaction`
|
|
199
|
+
too, as on `observe` and `deploy_contract`: `sim.add_call(call, from_, "label")`
|
|
200
|
+
raises `TypeError`, pass `label="label"`.
|
|
178
201
|
`CrosschainSimulator.observe(chain_id, call, *, label=None)` returns the same,
|
|
179
202
|
resolved by every relay round. `SimulationResult.get`, `SimulationResult.observations`
|
|
180
203
|
and `SimulatedCallResult.decoded` are removed: a list of results of many types has no
|
|
@@ -189,9 +212,16 @@ sim.run()
|
|
|
189
212
|
after.value - before.value
|
|
190
213
|
```
|
|
191
214
|
|
|
192
|
-
`Call` is a frozen dataclass and covariant in its result type:
|
|
193
|
-
field raises,
|
|
194
|
-
`
|
|
215
|
+
`Call` is a frozen, hashable dataclass and covariant in its result type:
|
|
216
|
+
assigning to a field raises, `output_types` is stored as a tuple (whatever sequence
|
|
217
|
+
it was built with, so compare it with a tuple), and a `Call[Amount]` is a
|
|
218
|
+
`Call[int]` and a `Call[object]`, so a `Sequence[Call[object]]` takes any calls
|
|
219
|
+
without a cast. `add_call` and `execute_call` take a `Call[object]`.
|
|
220
|
+
|
|
221
|
+
The logs of a simulated call (`SimulatedCallResult.logs`,
|
|
222
|
+
`SimulationResult.execute_logs`) are `SimulatedLog` TypedDicts: `address`, `topics`
|
|
223
|
+
and `data` as the node's `0x` text, plus its block and transaction identity fields
|
|
224
|
+
when it sends them. Other keys a node adds are not kept.
|
|
195
225
|
|
|
196
226
|
### Renamed methods
|
|
197
227
|
|
|
@@ -214,6 +244,7 @@ field raises, and a `Call[Amount]` is a `Call[int]` and a `Call[object]`, so a
|
|
|
214
244
|
| `AaveV3FuseReader.pool()` | `AaveV3FuseReader.read_pool(ctx)` |
|
|
215
245
|
| `PlasmaVault.read(target, data)` / `read_as(target, data, ...)` | `PlasmaVault.universal_read(target, data)` / `universal_read_decoded(target, data, ...)` (they build a Call; `read_*` names only methods that execute) |
|
|
216
246
|
| `read_index_of(asset)` | `precompile_index_of(asset)` (it reads nothing) |
|
|
247
|
+
| `EulerSwapStaticParams.to_tuple()` (and `EulerSwapDynamicParams`, `EulerSwapInitialState`, `EulerV2BatchItem`) | `.as_tuple()`, a typed tuple instead of a list |
|
|
217
248
|
| `ctx.default_block = n` | `ctx = ctx.at_block(n)` |
|
|
218
249
|
|
|
219
250
|
A service that caches wrappers per chain can now share one wrapper across chains and
|
|
@@ -406,9 +437,15 @@ is the wrong one.
|
|
|
406
437
|
- `Call.call(ctx)` and `Call.decode()` on a write-only `Call` raise `ValueError`, not
|
|
407
438
|
`RuntimeError`. `CrosschainSimulator.relay` raises `ValueError`, not
|
|
408
439
|
`RuntimeError`, for a message to a chain that was not added.
|
|
409
|
-
- `VaultSimulator.run` (provider error from `eth_simulateV1`,
|
|
410
|
-
does not match the queued calls
|
|
411
|
-
`
|
|
440
|
+
- `VaultSimulator.run` (provider error from `eth_simulateV1`, a result count that
|
|
441
|
+
does not match the queued calls, or a response not in the documented shape, which
|
|
442
|
+
raised `KeyError`, `TypeError` or `ValueError` before: a call result without a
|
|
443
|
+
`0x0`/`0x1` `status`, which 3.x read as a success, or `logs` that is not a list) and
|
|
444
|
+
`CrosschainSimulator.relay` (not settled within `max_rounds`) raise the new
|
|
445
|
+
`SimulationRunError`, still a `RuntimeError`.
|
|
446
|
+
- `decode_hypercore_event` raises the new `HyperCoreEventDecodeError` (a
|
|
447
|
+
`ValueError`) for a log whose topic it recognizes but whose other parts are
|
|
448
|
+
malformed; see [Decoded events](#decoded-events).
|
|
412
449
|
- The Morpho API client raises `MorphoApiError` for every answer it cannot use and
|
|
413
450
|
every transport failure, never `KeyError`, `TypeError` or `ValueError`:
|
|
414
451
|
- a required market id or address (market and V1 allocation ids, V1 flow-cap ids,
|
|
@@ -855,34 +892,58 @@ that only some entries carry is `NotRequired` (a balance fuse's `pct_of_total` a
|
|
|
855
892
|
`ipor_fusion` and `ipor_fusion.readers`). Narrow by a key before reading a
|
|
856
893
|
kind-specific one: `if detail is not None and "aggregator" in detail:
|
|
857
894
|
detail["description"]`.
|
|
858
|
-
- Decoded events are discriminated unions. `ExternalStateEvent` and `HyperCoreEvent`
|
|
859
|
-
are type aliases over one frozen dataclass per event (`ExternalStateUnpausedEvent`,
|
|
860
|
-
`HyperCoreDepositFuseEnterEvent`, ...), each with `name: Literal["<event>"]` and
|
|
861
|
-
`args` typed as that event's TypedDict (`ExternalStateUnpausedArgs`, ...). Comparing
|
|
862
|
-
`name` narrows the event and its `args`, with no key test:
|
|
863
|
-
|
|
864
|
-
```python
|
|
865
|
-
for event in external_state_events(receipt):
|
|
866
|
-
if event.name == "ExternalStateUnpaused":
|
|
867
|
-
event.args["signer"] # ChecksumAddress
|
|
868
|
-
match hc_event:
|
|
869
|
-
case HyperCoreDepositFuseEnterEvent(args=args):
|
|
870
|
-
args["evmAsset"]
|
|
871
|
-
```
|
|
872
|
-
|
|
873
|
-
Without that comparison `event.args["signer"]` does not type-check.
|
|
874
|
-
`isinstance(x, ExternalStateEvent)` still works (the alias is a union); the events
|
|
875
|
-
are no longer built positionally (`ExternalStateEvent(...)` is not a class: build
|
|
876
|
-
the event's own class with keywords, its `name` is preset).
|
|
877
|
-
`EXTERNAL_STATE_EVENT_CLASSES` / `HYPERCORE_EVENT_CLASSES` map an event name to its
|
|
878
|
-
class; they replace `EXTERNAL_STATE_EVENT_ARGS` / `HYPERCORE_EVENT_ARGS`, which are
|
|
879
|
-
removed. An event's args TypedDict is its class's `args` annotation:
|
|
880
|
-
`typing.get_type_hints(EXTERNAL_STATE_EVENT_CLASSES[name])["args"]`. Values carry nominal types (`Amount`, `MarketId`, `FuseAddress`,
|
|
881
|
-
`HyperCoreTokenIndex`, `PayloadHash`, web3's `Timestamp`, ...), and
|
|
882
|
-
`HyperCoreEvent.fuse` is a `FuseAddress | None` on every event.
|
|
883
895
|
- `RawLog` (the log shape `ExternalStateExecutor.parse_balance_proposed` /
|
|
884
|
-
`find_balance_proposed
|
|
885
|
-
a web3 `LogReceipt`
|
|
896
|
+
`find_balance_proposed`, the event decoders and the crosschain log helpers
|
|
897
|
+
accept) is `Mapping[str, object]`, not `Mapping[str, Any]`; a web3 `LogReceipt`
|
|
898
|
+
still fits it.
|
|
899
|
+
- `Command.decode_action_data()` returns `tuple[object, ...]`: narrow each value
|
|
900
|
+
(an `int`, a lowercase hex `str` address or `bytes`, by the action) before use.
|
|
901
|
+
- `CrosschainLane.proposal_id_from_receipt(receipt)` is typed to take web3's
|
|
902
|
+
`TxReceipt`; for a raw JSON-RPC or minimal `{"logs": ...}` receipt call
|
|
903
|
+
`lane.proposal_id_from_logs(receipt["logs"])`, which takes any `RawLog`s.
|
|
904
|
+
|
|
905
|
+
## Decoded events
|
|
906
|
+
|
|
907
|
+
Decoded events are discriminated unions. `ExternalStateEvent` and `HyperCoreEvent`
|
|
908
|
+
are type aliases over one frozen dataclass per event (`ExternalStateUnpausedEvent`,
|
|
909
|
+
`HyperCoreDepositFuseEnterEvent`, ...), each with `name: Literal["<event>"]` and
|
|
910
|
+
`args` typed as that event's TypedDict (`ExternalStateUnpausedArgs`, ...). Comparing
|
|
911
|
+
`name` narrows the event and its `args`, with no key test:
|
|
912
|
+
|
|
913
|
+
```python
|
|
914
|
+
for event in external_state_events(receipt):
|
|
915
|
+
if event.name == "ExternalStateUnpaused":
|
|
916
|
+
event.args["signer"] # ChecksumAddress
|
|
917
|
+
match hc_event:
|
|
918
|
+
case HyperCoreDepositFuseEnterEvent(args=args):
|
|
919
|
+
args["evmAsset"]
|
|
920
|
+
```
|
|
921
|
+
|
|
922
|
+
Without that comparison `event.args["signer"]` does not type-check.
|
|
923
|
+
`isinstance(x, ExternalStateEvent)` still works (the alias is a union); the events
|
|
924
|
+
are no longer built positionally (`ExternalStateEvent(...)` is not a class: build the
|
|
925
|
+
event's own class with keywords, its `name` is preset).
|
|
926
|
+
`EXTERNAL_STATE_EVENT_CLASSES` / `HYPERCORE_EVENT_CLASSES` map an event name to its
|
|
927
|
+
class. An event's args TypedDict is its class's `args` annotation:
|
|
928
|
+
`typing.get_type_hints(EXTERNAL_STATE_EVENT_CLASSES[name])["args"]`. Values carry
|
|
929
|
+
nominal types (`Amount`, `MarketId`, `FuseAddress`, `HyperCoreTokenIndex`,
|
|
930
|
+
`PayloadHash`, web3's `Timestamp`, ...), and `HyperCoreEvent.fuse` is a
|
|
931
|
+
`FuseAddress | None` on every event. Every name is importable from `ipor_fusion` and
|
|
932
|
+
from `ipor_fusion.fuses`.
|
|
933
|
+
|
|
934
|
+
The two families share one input contract. `decode_external_state_event(log)` and
|
|
935
|
+
`decode_hypercore_event(log)` take a web3 receipt log or a raw JSON-RPC / indexer
|
|
936
|
+
mapping (hex text topics, data, hashes and quantities) and return `None` when topic0
|
|
937
|
+
is not one of theirs, or cannot be a topic; once the topic is recognized, a malformed
|
|
938
|
+
part raises `ExternalStateEventDecodeError` / `HyperCoreEventDecodeError` (both an
|
|
939
|
+
`IporFusionError` and a `ValueError`). `external_state_event_name(topic)` and
|
|
940
|
+
`hypercore_event_name(topic)` return `None` for any other topic or a value that
|
|
941
|
+
cannot be one. For HyperCore this changes 3.x: `decode_hypercore_event` took only a
|
|
942
|
+
receipt log with bytes topics and let eth_abi's errors through,
|
|
943
|
+
`hypercore_event_name` raised on bad hex and also matched hex text without `0x`
|
|
944
|
+
(which now returns `None`: pass `"0x" + topic.hex()` or `HexBytes(topic).to_0x_hex()`),
|
|
945
|
+
and `log_index` was passed through as given (a hex string from a raw log); the events now also carry `block_number` and
|
|
946
|
+
`transaction_hash`, like the ExternalState ones.
|
|
886
947
|
|
|
887
948
|
## Behavior changes
|
|
888
949
|
|
|
@@ -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.dev185
|
|
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
|
|
@@ -123,7 +123,7 @@ alt="Release">
|
|
|
123
123
|
> vault read is one pinned snapshot, and several modules and names moved. A 3.x call
|
|
124
124
|
> such as `PlasmaVault(ctx, address)` fails only when it runs, so a broad
|
|
125
125
|
> `except Exception` can hide it. Follow the ordered checklist in
|
|
126
|
-
> [MIGRATION_4.md, *Start here*](MIGRATION_4.md#start-here).
|
|
126
|
+
> [MIGRATION_4.md, *Start here*](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/MIGRATION_4.md#start-here).
|
|
127
127
|
|
|
128
128
|
## Quickstart
|
|
129
129
|
|
|
@@ -298,7 +298,7 @@ resources `fusion://glossary`, `fusion://architecture`, `fusion://invariants` an
|
|
|
298
298
|
|
|
299
299
|
## Agent skills
|
|
300
300
|
|
|
301
|
-
[`skills/ipor-deploy-vault/SKILL.md`](skills/ipor-deploy-vault/SKILL.md) teaches a
|
|
301
|
+
[`skills/ipor-deploy-vault/SKILL.md`](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/skills/ipor-deploy-vault/SKILL.md) teaches a
|
|
302
302
|
coding agent the full clone → roles → market → access posture → deposit → execute
|
|
303
303
|
walk, with the invariants and the revert selectors, before it writes vault code.
|
|
304
304
|
Its body is `fusion://invariants` and `fusion://quickstart` from `ipor_fusion.guide`
|
|
@@ -318,7 +318,7 @@ npx skills add IPOR-Labs/ipor-fusion.py -g -a codex # or gemini-cli, cursor
|
|
|
318
318
|
|
|
319
319
|
## Common errors
|
|
320
320
|
|
|
321
|
-
Reverts on the deploy-and-configure path, keyed by selector so a failed transaction is greppable. This table and the full invariants ship in the wheel as [`ipor_fusion.guide`](src/ipor_fusion/guide/invariants.md), which `fusion-mcp` serves as `fusion://invariants`.
|
|
321
|
+
Reverts on the deploy-and-configure path, keyed by selector so a failed transaction is greppable. This table and the full invariants ship in the wheel as [`ipor_fusion.guide`](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/src/ipor_fusion/guide/invariants.md), which `fusion-mcp` serves as `fusion://invariants`.
|
|
322
322
|
|
|
323
323
|
| Selector | Revert | What happened | Fix |
|
|
324
324
|
|---|---|---|---|
|
|
@@ -334,7 +334,7 @@ Configuration order on a fresh vault: `add_fuses` → `grant_market_substrates`
|
|
|
334
334
|
|
|
335
335
|
A flash-loan fuse also needs `update_callback_handler(handler, sender, selector)` before its first `execute`: Morpho Blue calls back `onMorphoFlashLoan(uint256,bytes)`, the Euler EVC `onEulerFlashLoan(bytes)`, and an unregistered callback reverts `HandlerNotFound()`.
|
|
336
336
|
|
|
337
|
-
The full clone → configure → deposit → execute sequence is exercised in [`tests/test_simulate_vault_from_scratch_base.py`](tests/test_simulate_vault_from_scratch_base.py).
|
|
337
|
+
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).
|
|
338
338
|
|
|
339
339
|
Custom errors of the crosschain contracts decode by name: importing
|
|
340
340
|
`ipor_fusion.crosschain` registers their signatures (`CROSSCHAIN_ERROR_SIGNATURES`),
|
|
@@ -346,22 +346,22 @@ raises `SimulationError` naming the first failed call.
|
|
|
346
346
|
## Vault construction examples
|
|
347
347
|
|
|
348
348
|
Runnable, canonical examples for building and configuring a vault from scratch live in
|
|
349
|
-
[`examples`](examples). They preview and simulate through `eth_simulateV1` — nothing is
|
|
349
|
+
[`examples`](https://github.com/IPOR-Labs/ipor-fusion.py/tree/main/examples). They preview and simulate through `eth_simulateV1` — nothing is
|
|
350
350
|
ever signed or broadcast.
|
|
351
351
|
|
|
352
|
-
- [Simple Aave V3 supply vault](examples/simple_aave_v3_supply_base.py) — start here for vault
|
|
352
|
+
- [Simple Aave V3 supply vault](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/examples/simple_aave_v3_supply_base.py) — start here for vault
|
|
353
353
|
creation, role bootstrap, and configuring a single supported market.
|
|
354
|
-
- [Advanced Euler V2 credit-market vault](examples/advanced_euler_v2_credit_market_base.py) —
|
|
354
|
+
- [Advanced Euler V2 credit-market vault](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/examples/advanced_euler_v2_credit_market_base.py) —
|
|
355
355
|
continue here for composing multiple functional fuses, typed Euler substrates and sub-accounts,
|
|
356
356
|
and an ordered collateral → borrow → repay → unwind lifecycle.
|
|
357
|
-
- [External-state margin leg](examples/external_state_margin_leg_base.py) — a vault whose capital
|
|
357
|
+
- [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
|
|
358
358
|
sits off-chain: typed market-50 substrates, a dual-custodian propose/confirm marking the NAV,
|
|
359
359
|
the scheduled-withdrawal prep an alpha performs, and a mismatched confirmation being rejected.
|
|
360
|
-
- [Crosschain CCIP lifecycle](examples/crosschain_ccip_usdc_arbitrum_hyperevm.py) (preview feature) — a vault
|
|
360
|
+
- [Crosschain CCIP lifecycle](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py) (preview feature) — a vault
|
|
361
361
|
whose capital works on another chain: supply USDC from an Arbitrum hub to a HyperEVM spoke
|
|
362
362
|
over CCIP, attest the remote balance with two keys, deposit and redeem on the spoke, recall
|
|
363
363
|
and claim, driven through `CrosschainLane` and relayed by `CrosschainSimulator`.
|
|
364
|
-
- [Composed HyperCore flow](examples/composed_hypercore_flow_arbitrum_hyperevm.py) (preview feature) — the
|
|
364
|
+
- [Composed HyperCore flow](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/examples/composed_hypercore_flow_arbitrum_hyperevm.py) (preview feature) — the
|
|
365
365
|
same hub funding a HyperCore vault (market 55) that trades on Hyperliquid Core: the Core leg
|
|
366
366
|
(bridge, dex transfer, order, close, exit) built from the vault's substrate grants and estimated
|
|
367
367
|
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
|
|
@@ -448,6 +448,7 @@ Fuse.method() --> FuseAction --> PlasmaVault.execute([actions]) --> Call
|
|
|
448
448
|
| `ExternalStateExecutor` | NAV propose/confirm for off-vault capital (market 50); the executor's thresholds (`staleness_max`, `big_change_bps`, `dust_threshold`, `min_update_interval`), the live aggregate (`get_balance_fuse_snapshot`) and the pre-hook's staleness clock (`get_oldest_update_timestamp`) |
|
|
449
449
|
| `read_external_state`, `ExternalStateVaultState` | The market's vault-scoped state from the vault's ERC-7201 storage at one block: executor, the balance fuse's cached total, the custodian timestamp it last checked and the pause flag the pre-hook enforces (no getter exposes them) |
|
|
450
450
|
| `decode_external_state_event`, `EXTERNAL_STATE_TOPICS` | The ExternalState events the vault emits (big change, cache updates, unpause, rescue, executor creation and deployment, operation enter/exit), decoded by topic with their raw log identity; a malformed listed log raises |
|
|
451
|
+
| `decode_hypercore_event`, `hypercore_events` | **Preview.** The HyperCore fuse, pending-library, settlement and reporter events, decoded by topic with their raw log identity under the same input contract; a malformed listed log raises `HyperCoreEventDecodeError` |
|
|
451
452
|
| `StargateCrosschainExecutor`, `CcipCrosschainExecutor` | **Preview.** Crosschain executor reads and attestation (`propose_balance`, `approve_balance`) |
|
|
452
453
|
| `StargateCrosschainDispatcher`, `CcipCrosschainDispatcher` | Remote dispatcher state (`observation`, tracked idle, command lane) |
|
|
453
454
|
| `StargateCrosschainFactory`, `CcipCrosschainFactory` | Executor creation and route/asset configuration reads |
|
|
@@ -475,11 +476,11 @@ Fuse.method() --> FuseAction --> PlasmaVault.execute([actions]) --> Call
|
|
|
475
476
|
| Universal | `UniversalTokenSwapperFuse` |
|
|
476
477
|
| Off-vault capital | `AsyncActionFuse` (market 40), `ExternalStateOperationFuse` (market 50) |
|
|
477
478
|
| Crosschain (preview) | `StargateCrosschainSupplyFuse`, `StargateCrosschainCommandFuse`, `CcipCrosschainSupplyFuse`, `CcipCrosschainCommandFuse`, `CrosschainClaimFuse` (market 54); transport-agnostic bases `CrosschainSupplyFuse` / `CrosschainCommandFuse` with `StargateSendParams` / `CcipSendParams`, plus `Command`, `CrosschainSubstrateLib`, `OptionsBuilder` |
|
|
479
|
+
| HyperCore (Hyperliquid, market 55, preview) | `HyperCoreDepositFuse`, `HyperCoreMarginFuse`, `HyperCoreSendFuse`, `HyperCoreOrderFuse`, `HyperCoreCancelFuse`, `HyperCoreBuilderFeeFuse`, `HyperCoreSubstrates` |
|
|
478
480
|
|
|
479
481
|
The mainnet crosschain POC vault uses a keccak-derived market ID, not 54. Use
|
|
480
482
|
`crosschain_market_id("IPOR_FUSION_CROSSCHAIN_USDC_POC_V1")` for that deployment;
|
|
481
483
|
`open_lane` discovers the vault's actual market grants rather than assuming 54.
|
|
482
|
-
| HyperCore (Hyperliquid, market 55, preview) | `HyperCoreDepositFuse`, `HyperCoreMarginFuse`, `HyperCoreSendFuse`, `HyperCoreOrderFuse`, `HyperCoreCancelFuse`, `HyperCoreBuilderFeeFuse`, `HyperCoreSubstrates` |
|
|
483
484
|
|
|
484
485
|
### Readers (`ipor_fusion.readers`)
|
|
485
486
|
|
|
@@ -543,7 +544,7 @@ cp .env.example .env
|
|
|
543
544
|
# Edit .env with ARBITRUM_PROVIDER_URL, ETHEREUM_PROVIDER_URL, BASE_PROVIDER_URL
|
|
544
545
|
```
|
|
545
546
|
|
|
546
|
-
Contributor and coding-agent instructions (commands, conventions, invariants, domain rules) live in [AGENTS.md](AGENTS.md).
|
|
547
|
+
Contributor and coding-agent instructions (commands, conventions, invariants, domain rules) live in [AGENTS.md](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/AGENTS.md).
|
|
547
548
|
|
|
548
549
|
## Examples
|
|
549
550
|
|
|
@@ -75,7 +75,7 @@ alt="Release">
|
|
|
75
75
|
> vault read is one pinned snapshot, and several modules and names moved. A 3.x call
|
|
76
76
|
> such as `PlasmaVault(ctx, address)` fails only when it runs, so a broad
|
|
77
77
|
> `except Exception` can hide it. Follow the ordered checklist in
|
|
78
|
-
> [MIGRATION_4.md, *Start here*](MIGRATION_4.md#start-here).
|
|
78
|
+
> [MIGRATION_4.md, *Start here*](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/MIGRATION_4.md#start-here).
|
|
79
79
|
|
|
80
80
|
## Quickstart
|
|
81
81
|
|
|
@@ -250,7 +250,7 @@ resources `fusion://glossary`, `fusion://architecture`, `fusion://invariants` an
|
|
|
250
250
|
|
|
251
251
|
## Agent skills
|
|
252
252
|
|
|
253
|
-
[`skills/ipor-deploy-vault/SKILL.md`](skills/ipor-deploy-vault/SKILL.md) teaches a
|
|
253
|
+
[`skills/ipor-deploy-vault/SKILL.md`](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/skills/ipor-deploy-vault/SKILL.md) teaches a
|
|
254
254
|
coding agent the full clone → roles → market → access posture → deposit → execute
|
|
255
255
|
walk, with the invariants and the revert selectors, before it writes vault code.
|
|
256
256
|
Its body is `fusion://invariants` and `fusion://quickstart` from `ipor_fusion.guide`
|
|
@@ -270,7 +270,7 @@ npx skills add IPOR-Labs/ipor-fusion.py -g -a codex # or gemini-cli, cursor
|
|
|
270
270
|
|
|
271
271
|
## Common errors
|
|
272
272
|
|
|
273
|
-
Reverts on the deploy-and-configure path, keyed by selector so a failed transaction is greppable. This table and the full invariants ship in the wheel as [`ipor_fusion.guide`](src/ipor_fusion/guide/invariants.md), which `fusion-mcp` serves as `fusion://invariants`.
|
|
273
|
+
Reverts on the deploy-and-configure path, keyed by selector so a failed transaction is greppable. This table and the full invariants ship in the wheel as [`ipor_fusion.guide`](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/src/ipor_fusion/guide/invariants.md), which `fusion-mcp` serves as `fusion://invariants`.
|
|
274
274
|
|
|
275
275
|
| Selector | Revert | What happened | Fix |
|
|
276
276
|
|---|---|---|---|
|
|
@@ -286,7 +286,7 @@ Configuration order on a fresh vault: `add_fuses` → `grant_market_substrates`
|
|
|
286
286
|
|
|
287
287
|
A flash-loan fuse also needs `update_callback_handler(handler, sender, selector)` before its first `execute`: Morpho Blue calls back `onMorphoFlashLoan(uint256,bytes)`, the Euler EVC `onEulerFlashLoan(bytes)`, and an unregistered callback reverts `HandlerNotFound()`.
|
|
288
288
|
|
|
289
|
-
The full clone → configure → deposit → execute sequence is exercised in [`tests/test_simulate_vault_from_scratch_base.py`](tests/test_simulate_vault_from_scratch_base.py).
|
|
289
|
+
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).
|
|
290
290
|
|
|
291
291
|
Custom errors of the crosschain contracts decode by name: importing
|
|
292
292
|
`ipor_fusion.crosschain` registers their signatures (`CROSSCHAIN_ERROR_SIGNATURES`),
|
|
@@ -298,22 +298,22 @@ raises `SimulationError` naming the first failed call.
|
|
|
298
298
|
## Vault construction examples
|
|
299
299
|
|
|
300
300
|
Runnable, canonical examples for building and configuring a vault from scratch live in
|
|
301
|
-
[`examples`](examples). They preview and simulate through `eth_simulateV1` — nothing is
|
|
301
|
+
[`examples`](https://github.com/IPOR-Labs/ipor-fusion.py/tree/main/examples). They preview and simulate through `eth_simulateV1` — nothing is
|
|
302
302
|
ever signed or broadcast.
|
|
303
303
|
|
|
304
|
-
- [Simple Aave V3 supply vault](examples/simple_aave_v3_supply_base.py) — start here for vault
|
|
304
|
+
- [Simple Aave V3 supply vault](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/examples/simple_aave_v3_supply_base.py) — start here for vault
|
|
305
305
|
creation, role bootstrap, and configuring a single supported market.
|
|
306
|
-
- [Advanced Euler V2 credit-market vault](examples/advanced_euler_v2_credit_market_base.py) —
|
|
306
|
+
- [Advanced Euler V2 credit-market vault](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/examples/advanced_euler_v2_credit_market_base.py) —
|
|
307
307
|
continue here for composing multiple functional fuses, typed Euler substrates and sub-accounts,
|
|
308
308
|
and an ordered collateral → borrow → repay → unwind lifecycle.
|
|
309
|
-
- [External-state margin leg](examples/external_state_margin_leg_base.py) — a vault whose capital
|
|
309
|
+
- [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
|
|
310
310
|
sits off-chain: typed market-50 substrates, a dual-custodian propose/confirm marking the NAV,
|
|
311
311
|
the scheduled-withdrawal prep an alpha performs, and a mismatched confirmation being rejected.
|
|
312
|
-
- [Crosschain CCIP lifecycle](examples/crosschain_ccip_usdc_arbitrum_hyperevm.py) (preview feature) — a vault
|
|
312
|
+
- [Crosschain CCIP lifecycle](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py) (preview feature) — a vault
|
|
313
313
|
whose capital works on another chain: supply USDC from an Arbitrum hub to a HyperEVM spoke
|
|
314
314
|
over CCIP, attest the remote balance with two keys, deposit and redeem on the spoke, recall
|
|
315
315
|
and claim, driven through `CrosschainLane` and relayed by `CrosschainSimulator`.
|
|
316
|
-
- [Composed HyperCore flow](examples/composed_hypercore_flow_arbitrum_hyperevm.py) (preview feature) — the
|
|
316
|
+
- [Composed HyperCore flow](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/examples/composed_hypercore_flow_arbitrum_hyperevm.py) (preview feature) — the
|
|
317
317
|
same hub funding a HyperCore vault (market 55) that trades on Hyperliquid Core: the Core leg
|
|
318
318
|
(bridge, dex transfer, order, close, exit) built from the vault's substrate grants and estimated
|
|
319
319
|
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
|
|
@@ -400,6 +400,7 @@ Fuse.method() --> FuseAction --> PlasmaVault.execute([actions]) --> Call
|
|
|
400
400
|
| `ExternalStateExecutor` | NAV propose/confirm for off-vault capital (market 50); the executor's thresholds (`staleness_max`, `big_change_bps`, `dust_threshold`, `min_update_interval`), the live aggregate (`get_balance_fuse_snapshot`) and the pre-hook's staleness clock (`get_oldest_update_timestamp`) |
|
|
401
401
|
| `read_external_state`, `ExternalStateVaultState` | The market's vault-scoped state from the vault's ERC-7201 storage at one block: executor, the balance fuse's cached total, the custodian timestamp it last checked and the pause flag the pre-hook enforces (no getter exposes them) |
|
|
402
402
|
| `decode_external_state_event`, `EXTERNAL_STATE_TOPICS` | The ExternalState events the vault emits (big change, cache updates, unpause, rescue, executor creation and deployment, operation enter/exit), decoded by topic with their raw log identity; a malformed listed log raises |
|
|
403
|
+
| `decode_hypercore_event`, `hypercore_events` | **Preview.** The HyperCore fuse, pending-library, settlement and reporter events, decoded by topic with their raw log identity under the same input contract; a malformed listed log raises `HyperCoreEventDecodeError` |
|
|
403
404
|
| `StargateCrosschainExecutor`, `CcipCrosschainExecutor` | **Preview.** Crosschain executor reads and attestation (`propose_balance`, `approve_balance`) |
|
|
404
405
|
| `StargateCrosschainDispatcher`, `CcipCrosschainDispatcher` | Remote dispatcher state (`observation`, tracked idle, command lane) |
|
|
405
406
|
| `StargateCrosschainFactory`, `CcipCrosschainFactory` | Executor creation and route/asset configuration reads |
|
|
@@ -427,11 +428,11 @@ Fuse.method() --> FuseAction --> PlasmaVault.execute([actions]) --> Call
|
|
|
427
428
|
| Universal | `UniversalTokenSwapperFuse` |
|
|
428
429
|
| Off-vault capital | `AsyncActionFuse` (market 40), `ExternalStateOperationFuse` (market 50) |
|
|
429
430
|
| Crosschain (preview) | `StargateCrosschainSupplyFuse`, `StargateCrosschainCommandFuse`, `CcipCrosschainSupplyFuse`, `CcipCrosschainCommandFuse`, `CrosschainClaimFuse` (market 54); transport-agnostic bases `CrosschainSupplyFuse` / `CrosschainCommandFuse` with `StargateSendParams` / `CcipSendParams`, plus `Command`, `CrosschainSubstrateLib`, `OptionsBuilder` |
|
|
431
|
+
| HyperCore (Hyperliquid, market 55, preview) | `HyperCoreDepositFuse`, `HyperCoreMarginFuse`, `HyperCoreSendFuse`, `HyperCoreOrderFuse`, `HyperCoreCancelFuse`, `HyperCoreBuilderFeeFuse`, `HyperCoreSubstrates` |
|
|
430
432
|
|
|
431
433
|
The mainnet crosschain POC vault uses a keccak-derived market ID, not 54. Use
|
|
432
434
|
`crosschain_market_id("IPOR_FUSION_CROSSCHAIN_USDC_POC_V1")` for that deployment;
|
|
433
435
|
`open_lane` discovers the vault's actual market grants rather than assuming 54.
|
|
434
|
-
| HyperCore (Hyperliquid, market 55, preview) | `HyperCoreDepositFuse`, `HyperCoreMarginFuse`, `HyperCoreSendFuse`, `HyperCoreOrderFuse`, `HyperCoreCancelFuse`, `HyperCoreBuilderFeeFuse`, `HyperCoreSubstrates` |
|
|
435
436
|
|
|
436
437
|
### Readers (`ipor_fusion.readers`)
|
|
437
438
|
|
|
@@ -495,7 +496,7 @@ cp .env.example .env
|
|
|
495
496
|
# Edit .env with ARBITRUM_PROVIDER_URL, ETHEREUM_PROVIDER_URL, BASE_PROVIDER_URL
|
|
496
497
|
```
|
|
497
498
|
|
|
498
|
-
Contributor and coding-agent instructions (commands, conventions, invariants, domain rules) live in [AGENTS.md](AGENTS.md).
|
|
499
|
+
Contributor and coding-agent instructions (commands, conventions, invariants, domain rules) live in [AGENTS.md](https://github.com/IPOR-Labs/ipor-fusion.py/blob/main/AGENTS.md).
|
|
499
500
|
|
|
500
501
|
## Examples
|
|
501
502
|
|
|
@@ -43,6 +43,7 @@ from __future__ import annotations
|
|
|
43
43
|
import logging
|
|
44
44
|
import os
|
|
45
45
|
import sys
|
|
46
|
+
from typing import TypedDict
|
|
46
47
|
|
|
47
48
|
from eth_abi import encode
|
|
48
49
|
from eth_typing import ChecksumAddress
|
|
@@ -238,7 +239,18 @@ def _evault_debt_of(
|
|
|
238
239
|
# ── Pure builders (no chain access -- safe to import and unit-test offline) ───
|
|
239
240
|
|
|
240
241
|
|
|
241
|
-
|
|
242
|
+
class CloneKwargs(TypedDict):
|
|
243
|
+
"""The keyword arguments of ``FusionFactory.clone``."""
|
|
244
|
+
|
|
245
|
+
asset_name: str
|
|
246
|
+
asset_symbol: str
|
|
247
|
+
underlying_token: ChecksumAddress
|
|
248
|
+
redemption_delay_seconds: Period
|
|
249
|
+
owner: ChecksumAddress
|
|
250
|
+
dao_fee_package_index: int
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def clone_args() -> CloneKwargs:
|
|
242
254
|
"""Arguments for FusionFactory.clone(...).
|
|
243
255
|
|
|
244
256
|
The preview and the in-batch create MUST use identical args: same args plus
|
|
@@ -250,7 +262,7 @@ def clone_args() -> dict:
|
|
|
250
262
|
"asset_name": "IPOR WETH Euler Credit Vault (example)",
|
|
251
263
|
"asset_symbol": "ipWETHec",
|
|
252
264
|
"underlying_token": BASE_WETH,
|
|
253
|
-
"redemption_delay_seconds": 0,
|
|
265
|
+
"redemption_delay_seconds": Period(0),
|
|
254
266
|
"owner": OWNER,
|
|
255
267
|
"dao_fee_package_index": 0,
|
|
256
268
|
}
|
{ipor_fusion-4.0.0.dev171 → ipor_fusion-4.0.0.dev185}/examples/advanced_euler_v2_looping_arbitrum.py
RENAMED
|
@@ -27,6 +27,7 @@ from __future__ import annotations
|
|
|
27
27
|
import logging
|
|
28
28
|
import os
|
|
29
29
|
import sys
|
|
30
|
+
from typing import TypedDict
|
|
30
31
|
|
|
31
32
|
from eth_abi import encode
|
|
32
33
|
from eth_abi.packed import encode_packed
|
|
@@ -193,12 +194,23 @@ def _debt_of(
|
|
|
193
194
|
# ── Pure builders (no chain access) ──────────────────────────────────────────
|
|
194
195
|
|
|
195
196
|
|
|
196
|
-
|
|
197
|
+
class CloneKwargs(TypedDict):
|
|
198
|
+
"""The keyword arguments of ``FusionFactory.clone``."""
|
|
199
|
+
|
|
200
|
+
asset_name: str
|
|
201
|
+
asset_symbol: str
|
|
202
|
+
underlying_token: ChecksumAddress
|
|
203
|
+
redemption_delay_seconds: Period
|
|
204
|
+
owner: ChecksumAddress
|
|
205
|
+
dao_fee_package_index: int
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def clone_args() -> CloneKwargs:
|
|
197
209
|
return {
|
|
198
210
|
"asset_name": "IPOR WBTC Euler Loop Vault (example)",
|
|
199
211
|
"asset_symbol": "ipWBTCel",
|
|
200
212
|
"underlying_token": ARBITRUM_WBTC,
|
|
201
|
-
"redemption_delay_seconds": 0,
|
|
213
|
+
"redemption_delay_seconds": Period(0),
|
|
202
214
|
"owner": OWNER,
|
|
203
215
|
"dao_fee_package_index": 0,
|
|
204
216
|
}
|