ipor-fusion 4.1.0.dev35__tar.gz → 4.1.0.dev40__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/PKG-INFO +1 -1
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/examples/hypercore_vault_official_deployment_hyperevm.py +10 -6
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/pyproject.toml +1 -1
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/fuses/hypercore.py +5 -2
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/hypercore/__init__.py +8 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/readers/hypercore.py +16 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/readers/oracle_mapping.py +26 -9
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/vault_data.py +21 -3
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_cli_commands.py +36 -9
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_hypercore_readers.py +12 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_oracle_mapping.py +20 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_public_api.py +4 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_vault_data_block.py +11 -1
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/.claude-plugin/marketplace.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/.claude-plugin/plugin.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/.env.example +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/.gemini/settings.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/.git-blame-ignore-revs +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/.github/workflows/cd.yml +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/.github/workflows/ci.yml +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/.github/workflows/commit-lint.yml +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/.github/workflows/notify-slack.yml +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/.github/workflows/python-build.yml +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/.github/workflows/python-publish.yml +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/.github/workflows/release.yml +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/.github/workflows/report-slack.yml +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/.gitignore +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/.pre-commit-config.yaml +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/.python-version +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/AGENTS.md +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/CHANGELOG.md +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/CLAUDE.md +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/CODEOWNERS +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/LICENSE +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/MIGRATION_4.md +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/README.md +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/build.sh +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/examples/CONTRIBUTING.md +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/examples/README.md +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/examples/advanced_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/examples/advanced_euler_v2_looping_arbitrum.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/examples/external_state_margin_leg_base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/examples/simple_aave_v3_supply_base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/pytest.ini +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/scripts/commit-check.sh +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/scripts/fusion_error_signatures.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/skills/ipor-deploy-vault/SKILL.md +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/about.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/cache.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/chains.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/cli/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/cli/address_cmd.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/cli/changelog_cmd.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/cli/config_cmd.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/cli/config_store.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/cli/main.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/cli/market_cmd.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/cli/options.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/cli/oracle_mapping_view.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/cli/preflight_cmd.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/cli/vault_cmd.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/cli/vault_health.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/cli/vault_info_view.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/cli/vault_markets_view.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/cli/vault_rendering.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/config/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/config/roles.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/core/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/core/access.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/core/address.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/core/context.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/core/context_manager.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/core/contract.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/core/erc20.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/core/external_state_executor.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/core/fee_manager.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/core/fuse.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/core/fuse_action.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/core/fuse_decoding.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/core/fusion_factory.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/core/logs.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/core/multicall.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/core/oracle.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/core/plasma_vault.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/core/rewards_manager.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/core/simulation.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/core/simulation_result.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/core/withdraw_manager.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/ccip/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/ccip/chainlink.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/ccip/codec.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/ccip/contracts.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/ccip/events.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/ccip/indexer.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/ccip/lane.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/ccip/quote.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/ccip/transport.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/contracts.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/discovery.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/errors.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/fuses/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/fuses/base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/fuses/ccip.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/fuses/stargate.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/lane.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/logs.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/messages.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/simulation.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/stargate/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/stargate/contracts.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/stargate/lane.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/stargate/layerzero.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/stargate/transport.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/crosschain/transport.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/dependency_graph.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/entry_cli.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/entry_mcp.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/errors.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/explorer.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/field_docs.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/fuses/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/fuses/aave_v3.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/fuses/async_action.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/fuses/base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/fuses/compound_v3.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/fuses/erc4626.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/fuses/euler_v2.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/fuses/events.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/fuses/external_state.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/fuses/external_state_event_decoding.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/fuses/fluid_instadapp.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/fuses/gearbox_v3.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/fuses/hypercore_event_decoding.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/fuses/hypercore_pre_hooks.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/fuses/merkl.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/fuses/morpho.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/fuses/ramses_v2.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/fuses/uniswap_v3.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/fuses/universal.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/fusion_errors.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/guide/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/guide/architecture.md +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/guide/glossary.md +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/guide/invariants.md +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/guide/quickstart.md +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/market_ids.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/market_info.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/mcp/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/mcp/guide.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/mcp/models.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/mcp/server.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/morpho_api.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/preflight.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/py.typed +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/readers/__init__.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/readers/aave_v3.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/readers/aave_v4.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/readers/compound_v3.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/readers/euler_v2.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/readers/hypercore_outcome.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/readers/lending_health.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/readers/morpho.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/readers/oracle_mapping_nodes.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/readers/oracle_mapping_reader.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/readers/position_manager.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/readers/ramses_v2.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/readers/uniswap_v3.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/readers/unpriceable.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/registry.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/substrates.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/types.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/validation.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/vault_erc20.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/vault_info.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/vault_managers.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/vault_positions.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/vault_reads.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/UniswapV3UniversalRouter.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/_addresses.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/_crosschain.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/_crosschain_recovery.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/_euler_v2.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/_event_args.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/_fake_rpc.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/_foundry.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/_golden.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/_guide.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/_hypercore_model.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/_hypercore_shadow.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/_live.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/_multicall.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/_oracle_mapping_fake.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/_simulate.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/_validation.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/addresses.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/conftest.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/constants.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/hypercore_hip3_flow.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/hypercore_market55.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/hypercore_official.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/market_golden/meta_morpho_v1.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/market_golden/meta_morpho_v1.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/market_golden/meta_morpho_v2.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/market_golden/meta_morpho_v2.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/market_golden/morpho_api/market.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/market_golden/morpho_api/vault_v1.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/market_golden/morpho_api/vault_v2.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/market_golden/morpho_api/vault_v2_not_found.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/market_golden/morpho_blue.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/market_golden/morpho_blue.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/market_golden/morpho_blue_api_error.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/market_golden/morpho_blue_api_error.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/market_golden/morpho_blue_no_api.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/market_golden/morpho_blue_no_api.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/oracle_mapping_golden/mapping.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/oracle_mapping_golden/mapping.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/simulate_v1_request.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/vault_info_golden/clean.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/vault_info_golden/clean.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/vault_info_golden/clean.txt +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/vault_info_golden/deployment_error.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/vault_info_golden/deployment_error.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/vault_info_golden/deployment_error.txt +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/vault_info_golden/fetched.cli.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/vault_info_golden/fetched.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/vault_info_golden/fetched.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/vault_info_golden/full.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/vault_info_golden/full.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/vault_info_golden/full.txt +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/vault_info_golden/rich.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/vault_info_golden/rich.mcp.json +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/fixtures/vault_info_golden/rich.txt +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_about.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_access_manager.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_addresses_helper.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_cache.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_chains.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_cli_address.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_cli_changelog.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_cli_config_store.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_cli_helpers.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_cli_hypercore.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_cli_lending_health.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_cli_market_golden.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_cli_market_morpho_blue.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_cli_mcp_parity.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_cli_oracle_mapping.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_cli_oracle_mapping_golden.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_cli_pending_requests_scan.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_cli_preflight.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_cli_role_accounts.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_cli_vault_info_golden.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_cli_vault_predates_getters.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_cli_vault_validate.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_contract_call.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_contract_encoder.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_crosschain_ccip_events.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_crosschain_ccip_indexer.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_crosschain_ccip_quote.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_crosschain_chainlink.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_crosschain_contracts.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_crosschain_encoding.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_crosschain_errors.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_crosschain_lane.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_crosschain_layering.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_crosschain_transport.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_docs_typing.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_erc20.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_error_hierarchy.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_examples_crosschain.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_examples_euler_looping_arbitrum.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_examples_hypercore_hyperevm.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_examples_vaults.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_explorer.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_external_state_events.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_external_state_executor.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_fee_manager.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_fuse_decoding.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_fuse_encoding.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_fusion_errors.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_fusion_instance.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_governance_wrappers.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_guide.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_hypercore_deployment.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_hypercore_events.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_hypercore_flow.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_hypercore_live.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_hypercore_outcome.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_hypercore_pre_hooks.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_hypercore_simulation.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_logs.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_mcp_address.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_mcp_hypercore.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_mcp_models.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_mcp_preflight.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_mcp_server.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_mcp_vault_validate.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_multicall.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_oracle.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_plasma_vault.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_preflight.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_public_type_reachability.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_reader_encoding.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_registry.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_revert_decoding.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_rewards_manager.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_roles.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_sdk_layering.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_borrow_aave_v3_mainnet.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_claim_merkl_wrapper_base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_claim_morpho_rewards.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_crosschain_hyperevm.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_euler_v2_batch_base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_euler_v2_swap_deploy_base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_euler_v2_swap_reconfigure_base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_euler_v2_swap_registry_base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_examples_arbitrum.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_examples_base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_examples_crosschain.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_examples_hyperevm.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_external_state_executor_base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_fusion_factory_clone_base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_looping_aave_v3_base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_looping_morpho_blue_base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_morpho_blue.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_pilot_v3.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_pilot_v4_uniswap.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_pilot_v5_ramses.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_pilot_v5_scheduled.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_plasma_vault_setters_base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_preflight_base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_readers_integration.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_release_funds.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_swap_on_base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_timelock_base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulate_vault_from_scratch_base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulation_errors.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_simulation_observation.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_solidity_compiler.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_solidity_mirrors.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_substrates.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_types_and_events.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_unpriceable_tokens.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_validation.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_vault_dep_graph.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_vault_info_fetched_golden.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_vault_info_onchain_base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_vault_info_onchain_base_no_withdraw_manager.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_vault_reconciliation_onchain_base.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_vault_simulator_blocks.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_web3_context.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/test_withdraw_manager.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/typed_client/consumer.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/tests/typed_client/rejected.py +0 -0
- {ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/uv.lock +0 -0
|
@@ -95,12 +95,14 @@ from ipor_fusion import (
|
|
|
95
95
|
Web3Context,
|
|
96
96
|
decode_substrate,
|
|
97
97
|
erc20_balance_slot,
|
|
98
|
+
format_amount,
|
|
98
99
|
is_simulate_v1_supported,
|
|
99
100
|
parse_checksum_address,
|
|
100
101
|
parse_fuse_address,
|
|
101
102
|
)
|
|
102
103
|
from ipor_fusion.hypercore import (
|
|
103
104
|
HYPERCORE_PENDING_READERS,
|
|
105
|
+
ORDER_DECIMALS,
|
|
104
106
|
SPOT_DEX,
|
|
105
107
|
USDC_SYSTEM_ADDRESS,
|
|
106
108
|
USDC_TOKEN_INDEX,
|
|
@@ -119,6 +121,7 @@ from ipor_fusion.hypercore import (
|
|
|
119
121
|
TimeInForce,
|
|
120
122
|
decode_hypercore_event,
|
|
121
123
|
hip3_action_asset,
|
|
124
|
+
perp_px_decimals,
|
|
122
125
|
precompile_index_of,
|
|
123
126
|
)
|
|
124
127
|
from ipor_fusion.market_ids import IporFusionMarkets
|
|
@@ -224,9 +227,10 @@ BRIDGE_AMOUNT = Amount(15_000_000) # 15 USDC EVM -> Core
|
|
|
224
227
|
# whose default is that same 1 USDC in Core wei.
|
|
225
228
|
ACTIVATION_FEE_WEI = 100_000_000
|
|
226
229
|
TO_DEX_WEI = 1_000_000_000 # 10 USDC spot -> xyz dex
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
+
# 0.05 xyz:NVDA, a multiple of its 10**(ORDER_DECIMALS - 3) lot
|
|
231
|
+
ORDER_SIZE = 5 * 10 ** (ORDER_DECIMALS - 2)
|
|
232
|
+
LIMIT_BUY_PX = 230 * 10**ORDER_DECIMALS # pays at most 230 USD
|
|
233
|
+
LIMIT_SELL_PX = 220 * 10**ORDER_DECIMALS # sells at no less than 220 USD
|
|
230
234
|
# Core -> EVM: a spot -> spot sendAsset to the USDC system address. The amount
|
|
231
235
|
# must be a multiple of 100 Core wei (representable in 6 EVM decimals); Core
|
|
232
236
|
# takes its transfer fee from what stays on spot.
|
|
@@ -374,7 +378,7 @@ def core_ledger() -> tuple[CoreAnswers, ...]:
|
|
|
374
378
|
bridged = BRIDGE_AMOUNT * CORE_WEI_PER_EVM_UNIT - ACTIVATION_FEE_WEI
|
|
375
379
|
mark = 225_000
|
|
376
380
|
on_dex = TO_DEX_WEI // 100 # Core wei -> USD6
|
|
377
|
-
filled = ORDER_SIZE // 10 ** (
|
|
381
|
+
filled = ORDER_SIZE // 10 ** (ORDER_DECIMALS - XYZ_NVDA_SZ_DECIMALS)
|
|
378
382
|
return (
|
|
379
383
|
CoreAnswers(False, 0, 0, 0, mark), # before the bridge: no Core account
|
|
380
384
|
CoreAnswers(True, bridged, 0, 0, mark), # the bridge landed
|
|
@@ -481,7 +485,7 @@ def check_core_metadata(
|
|
|
481
485
|
f"{XYZ_NVDA_COIN} szDecimals is {nvda_info.sz_decimals}",
|
|
482
486
|
)
|
|
483
487
|
_check(
|
|
484
|
-
ORDER_SIZE % 10 ** (
|
|
488
|
+
ORDER_SIZE % 10 ** (ORDER_DECIMALS - nvda_info.sz_decimals) == 0,
|
|
485
489
|
"the order size is not a whole number of lots",
|
|
486
490
|
)
|
|
487
491
|
|
|
@@ -512,7 +516,7 @@ def read_core_metadata_at_head(web3: Web3) -> None:
|
|
|
512
516
|
wallet_token,
|
|
513
517
|
nvda_info.coin,
|
|
514
518
|
nvda_info.sz_decimals,
|
|
515
|
-
mark
|
|
519
|
+
format_amount(Amount(mark), perp_px_decimals(nvda_info.sz_decimals)),
|
|
516
520
|
)
|
|
517
521
|
|
|
518
522
|
|
|
@@ -17,7 +17,7 @@ native perp dex is 0. A HIP-3 builder-deployed market is addressed by its
|
|
|
17
17
|
action asset ``100_000 + dex * 10_000 + index_in_dex`` in orders, cancels and
|
|
18
18
|
the PerpMarket substrate; the read precompiles take ``dex * 10_000 +
|
|
19
19
|
index_in_dex`` instead (:func:`precompile_index_of`). Amounts are Core integers:
|
|
20
|
-
``limit_px`` and ``sz`` carry
|
|
20
|
+
``limit_px`` and ``sz`` carry :data:`ORDER_DECIMALS` implied decimals, ``usd6`` 6, and
|
|
21
21
|
``amount_wei`` is Core wei (8 decimals for USDC).
|
|
22
22
|
|
|
23
23
|
ABI (one struct argument per method)::
|
|
@@ -64,6 +64,8 @@ from ipor_fusion.types import (
|
|
|
64
64
|
SPOT_DEX = 0xFFFFFFFF
|
|
65
65
|
#: ``HyperCoreLib.NATIVE_PERP_DEX``: Hyperliquid's own perp dex.
|
|
66
66
|
NATIVE_PERP_DEX = 0
|
|
67
|
+
#: Decimals of ``limit_px`` and ``sz`` in :meth:`HyperCoreOrderFuse.enter`.
|
|
68
|
+
ORDER_DECIMALS = 8
|
|
67
69
|
#: Core token index of USDC.
|
|
68
70
|
USDC_TOKEN_INDEX = HyperCoreTokenIndex(0)
|
|
69
71
|
#: Core -> EVM route for token 0: a spot -> spot ``sendAsset`` to this address
|
|
@@ -297,7 +299,8 @@ class HyperCoreOrderFuse(Fuse):
|
|
|
297
299
|
cloid: HyperCoreClientOrderId,
|
|
298
300
|
reduce_only: bool = False,
|
|
299
301
|
) -> FuseAction:
|
|
300
|
-
"""Place ``sz``
|
|
302
|
+
"""Place ``sz`` of ``asset`` at ``limit_px``, both with
|
|
303
|
+
:data:`ORDER_DECIMALS` decimals.
|
|
301
304
|
The fuse enforces the market's notional cap and lot size and, for
|
|
302
305
|
HIP-3 markets, that this is the vault's only PerpMarket grant."""
|
|
303
306
|
_validate_uint(asset, 32, "asset")
|
|
@@ -8,6 +8,7 @@ with no backward compatibility, which is why they live here rather than in
|
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
from ipor_fusion.fuses.hypercore import (
|
|
11
|
+
ORDER_DECIMALS,
|
|
11
12
|
RESERVED_HYPERCORE_CONFIG_KEYS,
|
|
12
13
|
SPOT_DEX,
|
|
13
14
|
USDC_SYSTEM_ADDRESS,
|
|
@@ -68,6 +69,8 @@ from ipor_fusion.fuses.hypercore_pre_hooks import (
|
|
|
68
69
|
from ipor_fusion.readers.hypercore import (
|
|
69
70
|
HYPERCORE_MARKET,
|
|
70
71
|
HYPERCORE_PENDING_READERS,
|
|
72
|
+
PERP_MAX_DECIMALS,
|
|
73
|
+
USD6_DECIMALS,
|
|
71
74
|
HyperCoreAccountMarginSummary,
|
|
72
75
|
HyperCoreActionClass,
|
|
73
76
|
HyperCoreEffectKind,
|
|
@@ -84,6 +87,7 @@ from ipor_fusion.readers.hypercore import (
|
|
|
84
87
|
HyperCoreTokenInfo,
|
|
85
88
|
HyperCoreVaultState,
|
|
86
89
|
convert_to_wad_int,
|
|
90
|
+
perp_px_decimals,
|
|
87
91
|
read_hypercore_nav,
|
|
88
92
|
read_hypercore_vault_state,
|
|
89
93
|
)
|
|
@@ -110,9 +114,12 @@ from ipor_fusion.types import (
|
|
|
110
114
|
|
|
111
115
|
__all__ = [
|
|
112
116
|
"MarginTableId",
|
|
117
|
+
"ORDER_DECIMALS",
|
|
118
|
+
"PERP_MAX_DECIMALS",
|
|
113
119
|
"PayloadHash",
|
|
114
120
|
"SPOT_DEX",
|
|
115
121
|
"TransferDirection",
|
|
122
|
+
"USD6_DECIMALS",
|
|
116
123
|
"USDC_SYSTEM_ADDRESS",
|
|
117
124
|
"USDC_TOKEN_INDEX",
|
|
118
125
|
"HYPERCORE_CAPITAL_FLOW_SELECTORS",
|
|
@@ -190,6 +197,7 @@ __all__ = [
|
|
|
190
197
|
"is_hip3_asset",
|
|
191
198
|
"is_native_perp_asset",
|
|
192
199
|
"perp_dex_of",
|
|
200
|
+
"perp_px_decimals",
|
|
193
201
|
"precompile_index_of",
|
|
194
202
|
"read_hypercore_evm_exit_ceiling",
|
|
195
203
|
"read_hypercore_nav",
|
|
@@ -81,6 +81,10 @@ HYPERCORE_PENDING_READERS: dict[ChainId, ChecksumAddress] = {
|
|
|
81
81
|
WAD_DECIMALS = 18
|
|
82
82
|
#: ``accountMarginSummary`` reports USD with 6 decimals.
|
|
83
83
|
USD6_DECIMALS = 6
|
|
84
|
+
#: The most decimals a perp price can carry: Hyperliquid's ``MAX_DECIMALS``,
|
|
85
|
+
#: which is 6 for perps (8 for spot). A perp's price has
|
|
86
|
+
#: ``PERP_MAX_DECIMALS - szDecimals`` decimals (:func:`perp_px_decimals`).
|
|
87
|
+
PERP_MAX_DECIMALS = 6
|
|
84
88
|
_INT256_MAX = (1 << 255) - 1
|
|
85
89
|
|
|
86
90
|
|
|
@@ -111,6 +115,16 @@ def _validate_uint(value: int, bits: int, name: str) -> None:
|
|
|
111
115
|
raise ValueError(f"{name} must fit in uint{bits}, got {value}")
|
|
112
116
|
|
|
113
117
|
|
|
118
|
+
def perp_px_decimals(sz_decimals: Decimals) -> Decimals:
|
|
119
|
+
"""Decimals of a perp's :meth:`HyperCoreReader.mark_px` and
|
|
120
|
+
:meth:`HyperCoreReader.oracle_px`, from its ``szDecimals``."""
|
|
121
|
+
if not 0 <= sz_decimals <= PERP_MAX_DECIMALS:
|
|
122
|
+
raise ValueError(
|
|
123
|
+
f"sz_decimals must be in 0..{PERP_MAX_DECIMALS}, got {sz_decimals}"
|
|
124
|
+
)
|
|
125
|
+
return Decimals(PERP_MAX_DECIMALS - sz_decimals)
|
|
126
|
+
|
|
127
|
+
|
|
114
128
|
@dataclass(frozen=True, slots=True)
|
|
115
129
|
class HyperCoreSpotBalance:
|
|
116
130
|
"""``spotBalance`` precompile result, all in Core wei of the token."""
|
|
@@ -306,10 +320,12 @@ class HyperCoreReader:
|
|
|
306
320
|
return self._read(WITHDRAWABLE_PRECOMPILE, ["address"], [user], ["uint64"])
|
|
307
321
|
|
|
308
322
|
def oracle_px(self, read_index: int) -> Call[int]:
|
|
323
|
+
"""A perp's oracle price, with :func:`perp_px_decimals` decimals."""
|
|
309
324
|
_validate_uint(read_index, 32, "read_index")
|
|
310
325
|
return self._read(ORACLE_PX_PRECOMPILE, ["uint32"], [read_index], ["uint64"])
|
|
311
326
|
|
|
312
327
|
def mark_px(self, read_index: int) -> Call[int]:
|
|
328
|
+
"""A perp's mark price, with :func:`perp_px_decimals` decimals."""
|
|
313
329
|
_validate_uint(read_index, 32, "read_index")
|
|
314
330
|
return self._read(MARK_PX_PRECOMPILE, ["uint32"], [read_index], ["uint64"])
|
|
315
331
|
|
{ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/readers/oracle_mapping.py
RENAMED
|
@@ -236,15 +236,32 @@ def _resolve_middleware_fallback(
|
|
|
236
236
|
node.source_type = TYPE_MIDDLEWARE_FALLBACK
|
|
237
237
|
node.status = "resolved"
|
|
238
238
|
if underlying_middleware is not None:
|
|
239
|
-
# Same asset, different oracle
|
|
240
|
-
#
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
239
|
+
# Same asset, different oracle: the asset key is not in `visited` yet,
|
|
240
|
+
# so the hop is keyed by (oracle, asset) — a manager chain that loops
|
|
241
|
+
# back ends as a cycle instead of running to max_depth.
|
|
242
|
+
hop = f"{underlying_middleware.lower()}/{asset.lower()}"
|
|
243
|
+
if hop in visited:
|
|
244
|
+
return _partial(
|
|
245
|
+
asset,
|
|
246
|
+
symbol,
|
|
247
|
+
decimals,
|
|
248
|
+
source,
|
|
249
|
+
TYPE_UNKNOWN,
|
|
250
|
+
"cycle_detected",
|
|
251
|
+
[label],
|
|
252
|
+
price,
|
|
253
|
+
)
|
|
254
|
+
visited.add(hop)
|
|
255
|
+
try:
|
|
256
|
+
dep = _resolve(
|
|
257
|
+
reader.delegate(underlying_middleware),
|
|
258
|
+
asset,
|
|
259
|
+
depth + 1,
|
|
260
|
+
visited,
|
|
261
|
+
max_depth,
|
|
262
|
+
)
|
|
263
|
+
finally:
|
|
264
|
+
visited.discard(hop)
|
|
248
265
|
node.dependencies = [dep]
|
|
249
266
|
# dep re-resolves the same asset, so drop its leading label from the path.
|
|
250
267
|
node.path = [label, "middleware fallback", *dep.path[1:]]
|
|
@@ -312,7 +312,21 @@ def resolve_token_decimals(ctx: Web3Context, address: HexAddress) -> Decimals |
|
|
|
312
312
|
return decimals
|
|
313
313
|
|
|
314
314
|
|
|
315
|
-
def
|
|
315
|
+
def _latest_head(ctx: Web3Context) -> tuple[int, Timestamp]:
|
|
316
|
+
"""The latest block's number and timestamp from one read.
|
|
317
|
+
|
|
318
|
+
Reading the head number first and the block by number second can reach a
|
|
319
|
+
node behind a load balancer that has not seen that block yet.
|
|
320
|
+
"""
|
|
321
|
+
head = ctx.web3.eth.get_block("latest")
|
|
322
|
+
return head["number"], head["timestamp"]
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
def _block_timestamp(
|
|
326
|
+
ctx: Web3Context, block: int, known: Timestamp | None
|
|
327
|
+
) -> Timestamp:
|
|
328
|
+
if known is not None:
|
|
329
|
+
return known
|
|
316
330
|
return ctx.web3.eth.get_block(block)["timestamp"]
|
|
317
331
|
|
|
318
332
|
|
|
@@ -634,14 +648,18 @@ def fetch_vault_data(
|
|
|
634
648
|
ensure_supported_chain(ctx.chain_id)
|
|
635
649
|
if block is None:
|
|
636
650
|
block = _pinned_default_block(ctx)
|
|
637
|
-
resolved_block = ctx.web3.eth.block_number if block is None else block
|
|
638
651
|
is_latest = block is None
|
|
652
|
+
head_timestamp: Timestamp | None = None
|
|
653
|
+
if block is None:
|
|
654
|
+
resolved_block, head_timestamp = _latest_head(ctx)
|
|
655
|
+
else:
|
|
656
|
+
resolved_block = block
|
|
639
657
|
ctx = ctx.at_block(resolved_block)
|
|
640
658
|
plasma_vault = PlasmaVault(vault)
|
|
641
659
|
with ThreadPoolExecutor() as pool:
|
|
642
660
|
# Independent pipelines, each a short chain of batched reads; none of
|
|
643
661
|
# them waits on a pool future, so they cannot starve the pool.
|
|
644
|
-
f_timestamp = pool.submit(_block_timestamp, ctx, resolved_block)
|
|
662
|
+
f_timestamp = pool.submit(_block_timestamp, ctx, resolved_block, head_timestamp)
|
|
645
663
|
f_vault = pool.submit(_fetch_vault_reads, ctx, plasma_vault)
|
|
646
664
|
f_fees = pool.submit(_fetch_fee_data, ctx, plasma_vault)
|
|
647
665
|
f_withdraw = pool.submit(_fetch_withdraw_manager, ctx, plasma_vault)
|
|
@@ -443,7 +443,10 @@ class TestVaultInfo:
|
|
|
443
443
|
mock_ctx.cache = NullCache()
|
|
444
444
|
mock_ctx.web3.eth.block_number = 12345678
|
|
445
445
|
mock_ctx.default_block = "latest"
|
|
446
|
-
mock_ctx.web3.eth.get_block.return_value = {
|
|
446
|
+
mock_ctx.web3.eth.get_block.return_value = {
|
|
447
|
+
"number": 12345678,
|
|
448
|
+
"timestamp": 1700000000,
|
|
449
|
+
}
|
|
447
450
|
mock_ctx.chain_id = 1
|
|
448
451
|
mock_ctx.at_block.return_value = mock_ctx
|
|
449
452
|
mock_ctx_cls.from_url.return_value = mock_ctx
|
|
@@ -573,7 +576,10 @@ class TestVaultInfo:
|
|
|
573
576
|
mock_ctx.cache = NullCache()
|
|
574
577
|
mock_ctx.web3.eth.block_number = 12345678
|
|
575
578
|
mock_ctx.default_block = "latest"
|
|
576
|
-
mock_ctx.web3.eth.get_block.return_value = {
|
|
579
|
+
mock_ctx.web3.eth.get_block.return_value = {
|
|
580
|
+
"number": 12345678,
|
|
581
|
+
"timestamp": 1700000000,
|
|
582
|
+
}
|
|
577
583
|
mock_ctx.chain_id = 1
|
|
578
584
|
mock_ctx.at_block.return_value = mock_ctx
|
|
579
585
|
mock_ctx_cls.from_url.return_value = mock_ctx
|
|
@@ -654,7 +660,10 @@ class TestVaultInfo:
|
|
|
654
660
|
mock_ctx.cache = NullCache()
|
|
655
661
|
mock_ctx.web3.eth.block_number = 100
|
|
656
662
|
mock_ctx.default_block = "latest"
|
|
657
|
-
mock_ctx.web3.eth.get_block.return_value = {
|
|
663
|
+
mock_ctx.web3.eth.get_block.return_value = {
|
|
664
|
+
"number": 100,
|
|
665
|
+
"timestamp": 1700000000,
|
|
666
|
+
}
|
|
658
667
|
mock_ctx.chain_id = 1
|
|
659
668
|
mock_ctx.at_block.return_value = mock_ctx
|
|
660
669
|
mock_ctx_cls.from_url.return_value = mock_ctx
|
|
@@ -723,7 +732,10 @@ class TestVaultInfo:
|
|
|
723
732
|
mock_ctx.cache = NullCache()
|
|
724
733
|
mock_ctx.web3.eth.block_number = 100
|
|
725
734
|
mock_ctx.default_block = "latest"
|
|
726
|
-
mock_ctx.web3.eth.get_block.return_value = {
|
|
735
|
+
mock_ctx.web3.eth.get_block.return_value = {
|
|
736
|
+
"number": 100,
|
|
737
|
+
"timestamp": 1700000000,
|
|
738
|
+
}
|
|
727
739
|
mock_ctx.chain_id = 1
|
|
728
740
|
mock_ctx.at_block.return_value = mock_ctx
|
|
729
741
|
mock_ctx_cls.from_url.return_value = mock_ctx
|
|
@@ -804,7 +816,10 @@ class TestVaultInfo:
|
|
|
804
816
|
mock_ctx.cache = NullCache()
|
|
805
817
|
mock_ctx.web3.eth.block_number = 100
|
|
806
818
|
mock_ctx.default_block = "latest"
|
|
807
|
-
mock_ctx.web3.eth.get_block.return_value = {
|
|
819
|
+
mock_ctx.web3.eth.get_block.return_value = {
|
|
820
|
+
"number": 100,
|
|
821
|
+
"timestamp": 1700000000,
|
|
822
|
+
}
|
|
808
823
|
mock_ctx.web3.eth.get_transaction.return_value = {"blockNumber": 18500000}
|
|
809
824
|
mock_ctx.chain_id = 1
|
|
810
825
|
mock_ctx.at_block.return_value = mock_ctx
|
|
@@ -875,7 +890,10 @@ class TestVaultInfo:
|
|
|
875
890
|
mock_ctx.cache = NullCache()
|
|
876
891
|
mock_ctx.web3.eth.block_number = 100
|
|
877
892
|
mock_ctx.default_block = "latest"
|
|
878
|
-
mock_ctx.web3.eth.get_block.return_value = {
|
|
893
|
+
mock_ctx.web3.eth.get_block.return_value = {
|
|
894
|
+
"number": 100,
|
|
895
|
+
"timestamp": 1700000000,
|
|
896
|
+
}
|
|
879
897
|
mock_ctx.chain_id = 1
|
|
880
898
|
mock_ctx.at_block.return_value = mock_ctx
|
|
881
899
|
mock_ctx_cls.from_url.return_value = mock_ctx
|
|
@@ -986,7 +1004,10 @@ class TestVaultInfoJson:
|
|
|
986
1004
|
mock_ctx.chain_id = 1
|
|
987
1005
|
mock_ctx.web3.eth.block_number = 12345678
|
|
988
1006
|
mock_ctx.default_block = "latest"
|
|
989
|
-
mock_ctx.web3.eth.get_block.return_value = {
|
|
1007
|
+
mock_ctx.web3.eth.get_block.return_value = {
|
|
1008
|
+
"number": 12345678,
|
|
1009
|
+
"timestamp": 1700000000,
|
|
1010
|
+
}
|
|
990
1011
|
mock_ctx.chain_id = 1
|
|
991
1012
|
mock_ctx.at_block.return_value = mock_ctx
|
|
992
1013
|
mock_ctx_cls.from_url.return_value = mock_ctx
|
|
@@ -1165,7 +1186,10 @@ class TestVaultInfoJson:
|
|
|
1165
1186
|
mock_ctx.cache = NullCache()
|
|
1166
1187
|
mock_ctx.web3.eth.block_number = 100
|
|
1167
1188
|
mock_ctx.default_block = "latest"
|
|
1168
|
-
mock_ctx.web3.eth.get_block.return_value = {
|
|
1189
|
+
mock_ctx.web3.eth.get_block.return_value = {
|
|
1190
|
+
"number": 100,
|
|
1191
|
+
"timestamp": 1700000000,
|
|
1192
|
+
}
|
|
1169
1193
|
mock_ctx.web3.eth.get_transaction.return_value = {"blockNumber": 18500000}
|
|
1170
1194
|
mock_ctx.chain_id = 1
|
|
1171
1195
|
mock_ctx.at_block.return_value = mock_ctx
|
|
@@ -1246,7 +1270,10 @@ class TestVaultInfoJson:
|
|
|
1246
1270
|
mock_ctx.cache = NullCache()
|
|
1247
1271
|
mock_ctx.web3.eth.block_number = 100
|
|
1248
1272
|
mock_ctx.default_block = "latest"
|
|
1249
|
-
mock_ctx.web3.eth.get_block.return_value = {
|
|
1273
|
+
mock_ctx.web3.eth.get_block.return_value = {
|
|
1274
|
+
"number": 100,
|
|
1275
|
+
"timestamp": 1700000000,
|
|
1276
|
+
}
|
|
1250
1277
|
mock_ctx.chain_id = 1
|
|
1251
1278
|
mock_ctx.at_block.return_value = mock_ctx
|
|
1252
1279
|
mock_ctx_cls.from_url.return_value = mock_ctx
|
|
@@ -29,6 +29,7 @@ from ipor_fusion.hypercore import (
|
|
|
29
29
|
HyperCoreSpotBalance,
|
|
30
30
|
HyperCoreTokenInfo,
|
|
31
31
|
convert_to_wad_int,
|
|
32
|
+
perp_px_decimals,
|
|
32
33
|
read_hypercore_nav,
|
|
33
34
|
)
|
|
34
35
|
from ipor_fusion.readers.hypercore import (
|
|
@@ -335,6 +336,17 @@ def test_convert_to_wad_int_rounds_like_ipor_math(value, decimals, expected):
|
|
|
335
336
|
assert convert_to_wad_int(value, decimals) == expected
|
|
336
337
|
|
|
337
338
|
|
|
339
|
+
@pytest.mark.parametrize(("sz_decimals", "expected"), [(0, 6), (5, 1), (6, 0)])
|
|
340
|
+
def test_perp_px_decimals(sz_decimals, expected):
|
|
341
|
+
assert perp_px_decimals(sz_decimals) == expected
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
@pytest.mark.parametrize("sz_decimals", [-1, 7])
|
|
345
|
+
def test_perp_px_decimals_rejects_out_of_range(sz_decimals):
|
|
346
|
+
with pytest.raises(ValueError, match="sz_decimals"):
|
|
347
|
+
perp_px_decimals(sz_decimals)
|
|
348
|
+
|
|
349
|
+
|
|
338
350
|
def _universal_read(data: bytes) -> bytes:
|
|
339
351
|
"""`PlasmaVault.read` double: the pending reader or the balance fuse."""
|
|
340
352
|
target, inner = decode(["address", "bytes"], data[4:])
|
|
@@ -636,6 +636,26 @@ class TestResolve:
|
|
|
636
636
|
"chainlink_feed_registry": None,
|
|
637
637
|
}
|
|
638
638
|
|
|
639
|
+
def test_manager_delegating_to_itself_ends_as_a_cycle(self):
|
|
640
|
+
r = FakeReader()
|
|
641
|
+
weth = addr(1)
|
|
642
|
+
mw = addr(0x51)
|
|
643
|
+
zero = Web3.to_checksum_address(om.ZERO_ADDRESS)
|
|
644
|
+
r.symbols[weth] = "WETH"
|
|
645
|
+
r.decimals[weth] = 18
|
|
646
|
+
r.sources[weth] = zero
|
|
647
|
+
r.prices[weth] = Price(asset=weth, amount=2_000 * 10**18, decimals=18)
|
|
648
|
+
r.underlying_mw = mw
|
|
649
|
+
r.delegated = r # the manager names itself as its underlying middleware
|
|
650
|
+
|
|
651
|
+
node = om.resolve_asset(r, weth, max_depth=50)
|
|
652
|
+
|
|
653
|
+
# one hop back to the same manager, not 50 down to max_depth
|
|
654
|
+
(dep,) = node.dependencies
|
|
655
|
+
assert dep.reason == "cycle_detected"
|
|
656
|
+
assert not dep.dependencies
|
|
657
|
+
assert node.status == "partially_resolved"
|
|
658
|
+
|
|
639
659
|
def test_zero_underlying_middleware_treated_as_absent(self):
|
|
640
660
|
r = FakeReader()
|
|
641
661
|
asset = addr(1)
|
|
@@ -516,10 +516,13 @@ _ALL_SNAPSHOT: dict[str, frozenset[str]] = {
|
|
|
516
516
|
"HyperCoreTransferStatus",
|
|
517
517
|
"HyperCoreVaultState",
|
|
518
518
|
"MarginTableId",
|
|
519
|
+
"ORDER_DECIMALS",
|
|
520
|
+
"PERP_MAX_DECIMALS",
|
|
519
521
|
"PayloadHash",
|
|
520
522
|
"SPOT_DEX",
|
|
521
523
|
"TimeInForce",
|
|
522
524
|
"TransferDirection",
|
|
525
|
+
"USD6_DECIMALS",
|
|
523
526
|
"USDC_SYSTEM_ADDRESS",
|
|
524
527
|
"USDC_TOKEN_INDEX",
|
|
525
528
|
"compare_hypercore_transfer",
|
|
@@ -532,6 +535,7 @@ _ALL_SNAPSHOT: dict[str, frozenset[str]] = {
|
|
|
532
535
|
"is_hip3_asset",
|
|
533
536
|
"is_native_perp_asset",
|
|
534
537
|
"perp_dex_of",
|
|
538
|
+
"perp_px_decimals",
|
|
535
539
|
"precompile_index_of",
|
|
536
540
|
"read_hypercore_evm_exit_ceiling",
|
|
537
541
|
"read_hypercore_nav",
|
|
@@ -5,7 +5,7 @@ import pytest
|
|
|
5
5
|
from ipor_fusion import Web3Context
|
|
6
6
|
from ipor_fusion.cache import NullCache
|
|
7
7
|
from ipor_fusion.types import ChainId
|
|
8
|
-
from ipor_fusion.vault_data import _pinned_default_block
|
|
8
|
+
from ipor_fusion.vault_data import _latest_head, _pinned_default_block
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def _ctx() -> tuple[Web3Context, MagicMock]:
|
|
@@ -32,3 +32,13 @@ def test_tag_or_hash_resolves_to_its_number_once(tag: str):
|
|
|
32
32
|
ctx, web3 = _ctx()
|
|
33
33
|
assert _pinned_default_block(ctx.at_block(tag)) == 4242 # type: ignore[arg-type]
|
|
34
34
|
web3.eth.get_block.assert_called_once_with(tag)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def test_latest_head_reads_number_and_timestamp_in_one_call():
|
|
38
|
+
# The head number and then get_block(number) can reach a node behind a
|
|
39
|
+
# load balancer that has not seen that block yet.
|
|
40
|
+
web3 = MagicMock()
|
|
41
|
+
web3.eth.get_block.return_value = {"number": 4242, "timestamp": 1_700_000_000}
|
|
42
|
+
ctx = Web3Context(web3, ChainId(1), cache=NullCache())
|
|
43
|
+
assert _latest_head(ctx) == (4242, 1_700_000_000)
|
|
44
|
+
web3.eth.get_block.assert_called_once_with("latest")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/examples/advanced_euler_v2_credit_market_base.py
RENAMED
|
File without changes
|
{ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/examples/advanced_euler_v2_looping_arbitrum.py
RENAMED
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/examples/external_state_margin_leg_base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/cli/oracle_mapping_view.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ipor_fusion-4.1.0.dev35 → ipor_fusion-4.1.0.dev40}/src/ipor_fusion/cli/vault_markets_view.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|