ipor-fusion 4.0.0.dev86__tar.gz → 4.0.0.dev88__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.dev86 → ipor_fusion-4.0.0.dev88}/AGENTS.md +8 -4
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/MIGRATION_4.md +36 -1
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/PKG-INFO +1 -1
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/examples/advanced_euler_v2_credit_market_base.py +2 -2
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/examples/advanced_euler_v2_looping_arbitrum.py +2 -2
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/examples/external_state_margin_leg_base.py +4 -4
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/examples/simple_aave_v3_supply_base.py +2 -2
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/pyproject.toml +1 -1
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/core/access.py +3 -8
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/core/contract.py +14 -30
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/core/external_state_executor.py +10 -11
- ipor_fusion-4.0.0.dev86/src/ipor_fusion/fuses/base.py → ipor_fusion-4.0.0.dev88/src/ipor_fusion/core/fuse.py +17 -8
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/core/multicall.py +6 -4
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/core/oracle.py +2 -2
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/core/plasma_vault.py +5 -9
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/core/withdraw_manager.py +4 -4
- ipor_fusion-4.0.0.dev88/src/ipor_fusion/fuses/base.py +17 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/crosschain/base.py +3 -6
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/crosschain/ccip.py +3 -2
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/crosschain/stargate.py +2 -1
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/universal.py +0 -10
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/readers/aave_v3.py +5 -3
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/readers/morpho.py +3 -3
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/_crosschain_recovery.py +1 -1
- ipor_fusion-4.0.0.dev88/tests/test_contract_encoder.py +118 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_crosschain_layering.py +13 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_external_state_executor.py +27 -27
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_fee_manager.py +2 -2
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_fuse_encoding.py +17 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_hypercore_flow.py +3 -3
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_plasma_vault.py +1 -1
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_fusion_factory_clone_base.py +7 -23
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_plasma_vault_setters_base.py +1 -4
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_solidity_mirrors.py +1 -1
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/typed_client/consumer.py +8 -0
- ipor_fusion-4.0.0.dev86/tests/test_contract_encoder.py +0 -118
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/.claude-plugin/marketplace.json +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/.claude-plugin/plugin.json +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/.env.example +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/.gemini/settings.json +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/.git-blame-ignore-revs +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/.github/workflows/cd.yml +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/.github/workflows/ci.yml +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/.github/workflows/commit-lint.yml +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/.github/workflows/notify-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/.github/workflows/python-build.yml +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/.github/workflows/python-publish.yml +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/.github/workflows/release.yml +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/.github/workflows/report-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/.gitignore +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/.pre-commit-config.yaml +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/.python-version +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/CHANGELOG.md +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/CLAUDE.md +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/CODEOWNERS +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/LICENSE +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/README.md +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/build.sh +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/examples/CONTRIBUTING.md +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/examples/README.md +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/examples/composed_hypercore_flow_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/pytest.ini +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/scripts/commit-check.sh +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/scripts/crosschain_readiness.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/skills/ipor-deploy-vault/SKILL.md +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/about.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/cache.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/chains.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/cli/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/cli/changelog_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/cli/config_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/cli/config_store.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/cli/main.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/cli/market_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/cli/options.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/cli/oracle_mapping_view.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/cli/vault_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/cli/vault_health.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/cli/vault_info_view.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/cli/vault_markets_view.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/cli/vault_rendering.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/config/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/config/roles.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/core/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/core/address.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/core/context.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/core/erc20.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/core/fee_manager.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/core/fuse_action.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/core/fusion_factory.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/core/logs.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/core/rewards_manager.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/core/simulation.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/ccip/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/ccip/chainlink.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/ccip/codec.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/ccip/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/ccip/events.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/ccip/indexer.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/ccip/lane.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/ccip/quote.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/ccip/transport.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/discovery.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/errors.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/lane.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/logs.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/messages.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/simulation.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/stargate/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/stargate/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/stargate/lane.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/stargate/layerzero.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/stargate/transport.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/crosschain/transport.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/dependency_graph.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/entry_cli.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/entry_mcp.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/errors.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/explorer.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/field_docs.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/aave_v3.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/async_action.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/crosschain/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/erc4626.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/euler_v2.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/events.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/external_state.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/external_state_events.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/fluid_instadapp.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/gearbox_v3.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/hypercore_events.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/merkl.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/morpho.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/guide/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/guide/architecture.md +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/guide/glossary.md +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/guide/invariants.md +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/guide/quickstart.md +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/market_ids.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/market_info.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/mcp/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/mcp/guide.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/mcp/models.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/mcp/server.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/morpho_api.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/py.typed +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/readers/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/readers/aave_v4.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/readers/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/readers/hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/readers/hypercore_outcome.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/readers/lending_health.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/readers/oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/readers/oracle_mapping_nodes.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/readers/oracle_mapping_reader.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/readers/position_manager.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/readers/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/readers/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/readers/unpriceable.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/substrates.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/types.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/validation.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/vault_data.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/vault_info.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/vault_managers.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/vault_positions.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/vault_reads.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/UniswapV3UniversalRouter.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/_euler_v2.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/_foundry.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/_guide.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/_hypercore_model.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/_hypercore_shadow.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/_simulate.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/_validation.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/addresses.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/conftest.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/constants.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/fixtures/hypercore_hip3_flow.json +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/fixtures/hypercore_market55.json +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/fixtures/vault_info_golden/clean.json +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/fixtures/vault_info_golden/clean.txt +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/fixtures/vault_info_golden/rich.json +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/fixtures/vault_info_golden/rich.txt +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_about.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_access_manager.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_cache.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_chains.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_cli_changelog.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_cli_commands.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_cli_config_store.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_cli_helpers.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_cli_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_cli_lending_health.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_cli_market_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_cli_oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_cli_pending_requests_scan.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_cli_role_accounts.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_cli_vault_info_golden.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_cli_vault_predates_getters.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_cli_vault_validate.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_contract_call.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_crosschain_ccip_events.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_crosschain_ccip_indexer.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_crosschain_ccip_quote.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_crosschain_chainlink.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_crosschain_contracts.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_crosschain_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_crosschain_errors.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_crosschain_lane.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_crosschain_readiness.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_crosschain_readiness_report.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_crosschain_transport.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_erc20.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_error_hierarchy.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_examples_composed_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_examples_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_examples_euler_looping_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_examples_vaults.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_explorer.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_external_state_events.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_fusion_instance.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_guide.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_hypercore_deployment.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_hypercore_events.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_hypercore_live.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_hypercore_outcome.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_hypercore_readers.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_hypercore_simulation.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_logs.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_mcp_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_mcp_models.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_mcp_server.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_mcp_vault_validate.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_oracle.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_public_api.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_reader_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_readiness_selection.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_revert_decoding.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_rewards_manager.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_roles.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_sdk_layering.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_borrow_aave_v3_mainnet.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_claim_merkl_wrapper_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_claim_morpho_rewards.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_crosschain_canary.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_crosschain_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_crosschain_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_euler_v2_batch_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_euler_v2_swap_deploy_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_euler_v2_swap_reconfigure_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_euler_v2_swap_registry_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_examples_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_examples_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_examples_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_external_state_executor_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_looping_aave_v3_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_looping_morpho_blue_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_pilot_v3.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_pilot_v4_uniswap.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_pilot_v5_ramses.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_pilot_v5_scheduled.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_readers_integration.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_release_funds.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_swap_on_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_simulate_vault_from_scratch_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_solidity_compiler.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_substrates.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_types_and_events.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_unpriceable_tokens.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_validation.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_vault_dep_graph.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_vault_info_onchain_base.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_vault_info_onchain_base_no_withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_vault_simulator_blocks.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_web3_context.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/tests/test_withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/uv.lock +0 -0
|
@@ -218,12 +218,14 @@ the lifecycle matrix follows that.
|
|
|
218
218
|
`simulation` (`VaultSimulator`, eth_simulateV1, `erc20_balance_slot` and ERC-20 balance
|
|
219
219
|
overrides), `oracle`, `fusion_factory`,
|
|
220
220
|
`external_state_executor` (NAV marks for market 50), `erc20`, `fuse_action`
|
|
221
|
-
(`FuseAction`), `
|
|
221
|
+
(`FuseAction`), `fuse` (the `Fuse` base, `StakeFuse`, the shared validators and
|
|
222
|
+
substrate packers), `address` (`_validate_not_zero_address`). `core` imports neither
|
|
222
223
|
`fuses` nor `crosschain` (`tests/test_sdk_layering.py`)
|
|
223
224
|
- `fuses/` — per-protocol fuse encoders (aave_v3, async_action, compound_v3, crosschain/,
|
|
224
225
|
erc4626, euler_v2, external_state, fluid_instadapp, gearbox_v3, merkl, morpho, ramses_v2,
|
|
225
|
-
uniswap_v3, universal, `events.py`); `base.py`
|
|
226
|
-
|
|
226
|
+
uniswap_v3, universal, `events.py`); `base.py` re-exports the `core/fuse.py` base and validators,
|
|
227
|
+
`FuseAction` and `ZERO_ADDRESS` (from `types`). A fuse is a value: equality and
|
|
228
|
+
hash cover its class and every attribute it stores
|
|
227
229
|
- `crosschain/` — crosschain Plasma Vaults (executor on the hub chain, dispatcher at
|
|
228
230
|
the same address on each spoke chain), split like the contracts: shared `messages`
|
|
229
231
|
(`Command`, `MsgType`, envelopes), `contracts` (wrapper bases), `transport`
|
|
@@ -276,7 +278,9 @@ or examples.
|
|
|
276
278
|
- `Call[T]` (`core/contract.py`): every `ContractWrapper` method (one per
|
|
277
279
|
Solidity function) returns a `Call` instead of executing. `.call()` runs
|
|
278
280
|
`eth_call` and decodes to `T`; `.send()` signs and submits, returning a
|
|
279
|
-
`TxReceipt`; `.calldata` hands the bytes to an external signer
|
|
281
|
+
`TxReceipt`; `.calldata` hands the bytes to an external signer (a wrapper
|
|
282
|
+
built with `ctx=None`, e.g. `PlasmaVault(None, address)`, builds calldata
|
|
283
|
+
offline; there is no separate encoder factory);
|
|
280
284
|
`.build_transaction()` / `Web3Context.estimate_gas` preview without signing.
|
|
281
285
|
A `Call` without `output_types` (a write) raises on `.call()`. The same
|
|
282
286
|
`Call` feeds `VaultSimulator.observe`, so reads, sends and simulations share
|
|
@@ -93,7 +93,7 @@ The Uniswap V3 / Ramses V2 position events' `version`, `sender` and `recipient`
|
|
|
93
93
|
`quote_ccip_native_fee(block=)` and `OracleMappingReader.asset_source_events` take a
|
|
94
94
|
`BlockIdentifier`.
|
|
95
95
|
|
|
96
|
-
**Address roles.** `PlasmaVault(ctx, address)`,
|
|
96
|
+
**Address roles.** `PlasmaVault(ctx, address)` (`ctx` may be `None`, see below),
|
|
97
97
|
`validate_vault`, `fetch_deployment_info`, the HyperCore, lending-health and
|
|
98
98
|
oracle-mapping readers, `read_external_state`, `VaultSimulator(vault=)`,
|
|
99
99
|
`CrosschainSimulator`, crosschain discovery, the hub-manager inputs
|
|
@@ -194,6 +194,35 @@ are `ProposalHash`; `ExternalStateEvent.transaction_hash` is a `TxHash`.
|
|
|
194
194
|
except below): `chain_id` fields are `ChainId`, `role_id` `RoleId`, `market_id`
|
|
195
195
|
`MarketId`. Calling an MCP tool function directly from Python takes `ChainId`.
|
|
196
196
|
|
|
197
|
+
**Offline wrappers.** `ContractWrapper.encoder()` (and the `PlasmaVault` /
|
|
198
|
+
`AccessManager` overrides) is gone. Every wrapper constructor takes
|
|
199
|
+
`ctx: Web3Context | None`, so build an offline wrapper with the normal
|
|
200
|
+
constructor and an address: `PlasmaVault(None, vault)`, `ERC20(None, token)`,
|
|
201
|
+
`FusionFactory(None, factory)`, `LegacyPriceOracleMiddleware(None, oracle,
|
|
202
|
+
Decimals(8))`. The address is required (there is no zero-address placeholder) and
|
|
203
|
+
subclass parameters stay required, so the wrapper is fully initialized:
|
|
204
|
+
`.encoder()` skipped the constructor, and a legacy oracle built that way failed to
|
|
205
|
+
decode `get_asset_price`. `.calldata` still needs no context; `.call()`, `.send()`,
|
|
206
|
+
`.build_transaction()` and `.estimate_gas()` raise `ValueError` until one is passed
|
|
207
|
+
to them, and a method that reads the chain itself (log scans such as
|
|
208
|
+
`get_balance_fuses` or `get_pending_requests`, `withdraw_manager_address`,
|
|
209
|
+
`Multicall3.aggregate` / `try_aggregate`, the Aave V3 and Morpho position reads)
|
|
210
|
+
raises `ValueError("Web3Context required: <wrapper> at <address> ...")` instead of
|
|
211
|
+
an `AttributeError` on `None`. `ExternalStateExecutor` still refuses the zero
|
|
212
|
+
address for its hash and event readers.
|
|
213
|
+
|
|
214
|
+
| 3.x | 4.0 |
|
|
215
|
+
|---|---|
|
|
216
|
+
| `PlasmaVault.encoder(vault)` | `PlasmaVault(None, vault)` |
|
|
217
|
+
| `ERC20.encoder()` (no address) | `ERC20(None, token)`: pass the real address |
|
|
218
|
+
| `Cls.__new__(Cls)` + `_ctx` / `_address` | `Cls(None, address)` |
|
|
219
|
+
|
|
220
|
+
**Fuse base.** `Fuse`, `StakeFuse` and the shared validators and substrate packers
|
|
221
|
+
live in `ipor_fusion.core.fuse`; `ipor_fusion.fuses.base`, `ipor_fusion.fuses` and
|
|
222
|
+
`ipor_fusion` re-export them, so existing imports keep working. Fuse equality and
|
|
223
|
+
hash now cover every attribute a fuse stores, not only its class and address (see
|
|
224
|
+
[Behavior changes](#behavior-changes)).
|
|
225
|
+
|
|
197
226
|
**Moved, still importable.** `FuseAction` lives in `ipor_fusion.core.fuse_action` and
|
|
198
227
|
`ZERO_ADDRESS` in `ipor_fusion.types`; both are re-exported from
|
|
199
228
|
`ipor_fusion.fuses.base` and `FuseAction` from `ipor_fusion`. The CLI's internal
|
|
@@ -202,6 +231,12 @@ except below): `chain_id` fields are `ChainId`, `role_id` `RoleId`, `market_id`
|
|
|
202
231
|
|
|
203
232
|
## Behavior changes
|
|
204
233
|
|
|
234
|
+
- Two fuses are equal (and hash alike) only when they have the same class and the
|
|
235
|
+
same stored state. `StakeFuse` subclasses (`GearboxStakeFuse`,
|
|
236
|
+
`FluidInstadappStakingFuse`) with the same fuse address but different
|
|
237
|
+
`staking_address` were equal and collapsed in a set or dict key; they are now
|
|
238
|
+
distinct. A custom `Fuse` subclass is compared on its instance attributes, which
|
|
239
|
+
must be hashable; drop an `__eq__` / `__hash__` override that only added them.
|
|
205
240
|
- The MCP `vault_info` document reports the vault address checksummed (the CLI
|
|
206
241
|
already did).
|
|
207
242
|
- `SubstrateInfo.address` is `None` instead of `""` for a substrate without an
|
{ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/examples/advanced_euler_v2_credit_market_base.py
RENAMED
|
@@ -261,12 +261,12 @@ def clone_args() -> dict:
|
|
|
261
261
|
def unsigned_clone_calldata() -> bytes:
|
|
262
262
|
"""Unsigned creation calldata (selector + ABI-encoded args) for the deploy.
|
|
263
263
|
|
|
264
|
-
Built
|
|
264
|
+
Built on a wrapper with ctx=None, so it needs no provider. Hand these bytes to
|
|
265
265
|
an external signer / multisig instead of calling ``.send()``. NOTE: the owner
|
|
266
266
|
encoded here is the simulation ``OWNER`` (a throwaway EOA) -- set your real
|
|
267
267
|
owner in ``clone_args()`` before deploying, or the vault is owned by it.
|
|
268
268
|
"""
|
|
269
|
-
return FusionFactory
|
|
269
|
+
return FusionFactory(None, BASE_FUSION_FACTORY).clone(**clone_args()).calldata
|
|
270
270
|
|
|
271
271
|
|
|
272
272
|
def market_substrates() -> list[bytes]:
|
{ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/examples/advanced_euler_v2_looping_arbitrum.py
RENAMED
|
@@ -208,7 +208,7 @@ def clone_args() -> dict:
|
|
|
208
208
|
|
|
209
209
|
|
|
210
210
|
def unsigned_clone_calldata() -> bytes:
|
|
211
|
-
return FusionFactory
|
|
211
|
+
return FusionFactory(None, ARBITRUM_FUSION_FACTORY).clone(**clone_args()).calldata
|
|
212
212
|
|
|
213
213
|
|
|
214
214
|
def euler_market_substrates() -> list[bytes]:
|
|
@@ -260,7 +260,7 @@ def enable_euler_actions() -> list[FuseAction]:
|
|
|
260
260
|
def build_swap_action() -> FuseAction:
|
|
261
261
|
"""Swap the borrowed USDC through Uniswap V3 and require flash repayment."""
|
|
262
262
|
transfer_data = (
|
|
263
|
-
ERC20
|
|
263
|
+
ERC20(None, ARBITRUM_USDC)
|
|
264
264
|
.transfer(UNISWAP_UNIVERSAL_ROUTER, BORROW_USDC)
|
|
265
265
|
.calldata
|
|
266
266
|
)
|
{ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/examples/external_state_margin_leg_base.py
RENAMED
|
@@ -438,12 +438,12 @@ def clone_args() -> dict:
|
|
|
438
438
|
def unsigned_clone_calldata() -> bytes:
|
|
439
439
|
"""Unsigned creation calldata (selector + ABI-encoded args) for the deploy.
|
|
440
440
|
|
|
441
|
-
Built
|
|
441
|
+
Built on a wrapper with ctx=None, so it needs no provider. Hand these bytes to
|
|
442
442
|
an external signer / multisig instead of calling ``.send()``. NOTE: the owner
|
|
443
443
|
encoded here is the simulation ``OWNER`` (a throwaway EOA) -- set your real
|
|
444
444
|
owner in ``clone_args()`` before deploying, or the vault is owned by it.
|
|
445
445
|
"""
|
|
446
|
-
return FusionFactory
|
|
446
|
+
return FusionFactory(None, BASE_FUSION_FACTORY).clone(**clone_args()).calldata
|
|
447
447
|
|
|
448
448
|
|
|
449
449
|
def market_substrates() -> list[bytes]:
|
|
@@ -534,9 +534,9 @@ def market_substrates() -> list[bytes]:
|
|
|
534
534
|
def venue_transfer_calldata(amount: Amount) -> bytes:
|
|
535
535
|
"""``USDC.transfer(VENUE_DEPOSIT_ADDRESS, amount)`` calldata, run from the executor.
|
|
536
536
|
|
|
537
|
-
Encoded with
|
|
537
|
+
Encoded with an ERC20 wrapper built with ctx=None -- pure bytes, no chain access.
|
|
538
538
|
"""
|
|
539
|
-
return ERC20
|
|
539
|
+
return ERC20(None, BASE_USDC).transfer(VENUE_DEPOSIT_ADDRESS, amount).calldata
|
|
540
540
|
|
|
541
541
|
|
|
542
542
|
def build_enter_action(amount: Amount) -> FuseAction:
|
|
@@ -201,12 +201,12 @@ def clone_args() -> dict:
|
|
|
201
201
|
def unsigned_clone_calldata() -> bytes:
|
|
202
202
|
"""Unsigned creation calldata (selector + ABI-encoded args) for the deploy.
|
|
203
203
|
|
|
204
|
-
Built
|
|
204
|
+
Built on a wrapper with ctx=None, so it needs no provider. Hand these bytes to
|
|
205
205
|
an external signer / multisig instead of calling ``.send()``. NOTE: the owner
|
|
206
206
|
encoded here is the simulation ``OWNER`` (a throwaway EOA) -- set your real
|
|
207
207
|
owner in ``clone_args()`` before deploying, or the vault is owned by it.
|
|
208
208
|
"""
|
|
209
|
-
return FusionFactory
|
|
209
|
+
return FusionFactory(None, BASE_FUSION_FACTORY).clone(**clone_args()).calldata
|
|
210
210
|
|
|
211
211
|
|
|
212
212
|
def build_supply_action(amount: Amount) -> FuseAction:
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from collections.abc import Callable
|
|
2
2
|
from dataclasses import dataclass
|
|
3
|
-
from typing import Self
|
|
4
3
|
|
|
5
4
|
from eth_abi import decode
|
|
6
5
|
from eth_abi.exceptions import InsufficientDataBytes
|
|
@@ -68,17 +67,13 @@ def _role_status_decoder(values: tuple) -> RoleStatus:
|
|
|
68
67
|
class AccessManager(ContractWrapper):
|
|
69
68
|
"""Manages role-based access control for PlasmaVault operations."""
|
|
70
69
|
|
|
71
|
-
def __init__(self, ctx: Web3Context, address: AccessManagerAddress):
|
|
70
|
+
def __init__(self, ctx: Web3Context | None, address: AccessManagerAddress):
|
|
72
71
|
super().__init__(ctx, address)
|
|
73
72
|
|
|
74
73
|
@property
|
|
75
74
|
def address(self) -> AccessManagerAddress:
|
|
76
75
|
return AccessManagerAddress(self._address)
|
|
77
76
|
|
|
78
|
-
@classmethod
|
|
79
|
-
def encoder(cls, address: AccessManagerAddress | None = None) -> Self: # type: ignore[override]
|
|
80
|
-
return super().encoder(address)
|
|
81
|
-
|
|
82
77
|
def grant_role(
|
|
83
78
|
self, role_id: RoleId | Roles, account: ChecksumAddress, execution_delay: Period
|
|
84
79
|
) -> Call[None]:
|
|
@@ -161,7 +156,7 @@ class AccessManager(ContractWrapper):
|
|
|
161
156
|
if predicate(role_id, account):
|
|
162
157
|
candidates[(role_id, account)] = None
|
|
163
158
|
|
|
164
|
-
statuses = Multicall3(self.
|
|
159
|
+
statuses = Multicall3(self._require_ctx()).aggregate(
|
|
165
160
|
[self.has_role(role_id, account) for role_id, account in candidates]
|
|
166
161
|
)
|
|
167
162
|
return [
|
|
@@ -180,7 +175,7 @@ class AccessManager(ContractWrapper):
|
|
|
180
175
|
Web3.keccak(text="RoleGranted(uint64,address,uint32,uint48,bool)")
|
|
181
176
|
).to_0x_hex()
|
|
182
177
|
return list(
|
|
183
|
-
self.
|
|
178
|
+
self._require_ctx().get_logs(
|
|
184
179
|
contract_address=self._address, topics=[event_signature_hash]
|
|
185
180
|
)
|
|
186
181
|
)
|
|
@@ -129,18 +129,19 @@ class Call(Generic[T]):
|
|
|
129
129
|
return actual
|
|
130
130
|
|
|
131
131
|
|
|
132
|
-
_ENCODER_PLACEHOLDER_ADDRESS: ChecksumAddress = cast(
|
|
133
|
-
ChecksumAddress, "0x0000000000000000000000000000000000000000"
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
|
|
137
132
|
class ContractWrapper:
|
|
138
133
|
"""Base wrapper. Subclasses expose one method per Solidity function that
|
|
139
134
|
returns a `Call[T]` — never executing eagerly. Callers chain `.call()` for
|
|
140
135
|
reads, `.send()` for writes, or hand the `Call` to `VaultSimulator`.
|
|
136
|
+
|
|
137
|
+
`ctx` may be ``None`` for offline use, e.g. external-signer flows (HTTP
|
|
138
|
+
signing service, multisig) that only need `Call.calldata`: every builder
|
|
139
|
+
works, and `.call()` / `.send()` on its Calls raise until a context is
|
|
140
|
+
passed to them. Methods that read the chain themselves (log scans, storage
|
|
141
|
+
reads, batched reads) raise `ValueError` on such a wrapper.
|
|
141
142
|
"""
|
|
142
143
|
|
|
143
|
-
def __init__(self, ctx: Web3Context, address: ChecksumAddress):
|
|
144
|
+
def __init__(self, ctx: Web3Context | None, address: ChecksumAddress):
|
|
144
145
|
self._ctx = ctx
|
|
145
146
|
self._address = Web3.to_checksum_address(address)
|
|
146
147
|
|
|
@@ -148,30 +149,13 @@ class ContractWrapper:
|
|
|
148
149
|
def address(self) -> ChecksumAddress:
|
|
149
150
|
return self._address
|
|
150
151
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
access, decoders included. Calling `.call()` or `.send()` on a Call
|
|
159
|
-
produced this way raises (no ctx).
|
|
160
|
-
|
|
161
|
-
Pass `address` unless `.calldata` really is the only consumer. The
|
|
162
|
-
encoding ignores it, but a builder that reads `self._address`
|
|
163
|
-
semantically — matching it against a log's emitter, say, or folding it
|
|
164
|
-
into a hash — runs against the placeholder zero address without one,
|
|
165
|
-
and so rejects input that is genuinely the caller's.
|
|
166
|
-
"""
|
|
167
|
-
instance = cls.__new__(cls)
|
|
168
|
-
instance._ctx = None
|
|
169
|
-
instance._address = (
|
|
170
|
-
Web3.to_checksum_address(address)
|
|
171
|
-
if address is not None
|
|
172
|
-
else _ENCODER_PLACEHOLDER_ADDRESS
|
|
173
|
-
)
|
|
174
|
-
return instance
|
|
152
|
+
def _require_ctx(self) -> Web3Context:
|
|
153
|
+
if self._ctx is None:
|
|
154
|
+
raise ValueError(
|
|
155
|
+
f"Web3Context required: {type(self).__name__} at {self._address} "
|
|
156
|
+
"was built without one (ctx=None), which only builds calldata."
|
|
157
|
+
)
|
|
158
|
+
return self._ctx
|
|
175
159
|
|
|
176
160
|
def _view(
|
|
177
161
|
self,
|
{ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/core/external_state_executor.py
RENAMED
|
@@ -463,13 +463,13 @@ class ExternalStateExecutor(ContractWrapper):
|
|
|
463
463
|
The hash is bound to a chain. `chain_id` defaults to this wrapper's
|
|
464
464
|
context; pass it explicitly when the context that executes the call is
|
|
465
465
|
not the one the wrapper was built with (`Call.call(other_ctx)`), or to
|
|
466
|
-
read through a
|
|
466
|
+
read through a wrapper built with `ctx=None`.
|
|
467
467
|
"""
|
|
468
468
|
account = Web3.to_checksum_address(balance_account)
|
|
469
469
|
|
|
470
470
|
def to_proposal(values: tuple[int, str, int, int]) -> BalanceProposal | None:
|
|
471
471
|
# Both hash inputs first, before the empty-slot return. Resolved
|
|
472
|
-
# inside the decoder so a calldata-only `
|
|
472
|
+
# inside the decoder so a calldata-only (`ctx=None`) wrapper keeps
|
|
473
473
|
# working like every sibling, but ahead of the sentinel so a
|
|
474
474
|
# misconfigured poller fails on its first read rather than on the
|
|
475
475
|
# first read that happens to find a proposal.
|
|
@@ -504,29 +504,28 @@ class ExternalStateExecutor(ContractWrapper):
|
|
|
504
504
|
)
|
|
505
505
|
|
|
506
506
|
def _require_address(self) -> ChecksumAddress:
|
|
507
|
-
"""This executor's address, or a clear error
|
|
508
|
-
`encoder()`.
|
|
507
|
+
"""This executor's address, or a clear error for the zero address.
|
|
509
508
|
|
|
510
|
-
The other half of the hash's binding, and the
|
|
511
|
-
|
|
509
|
+
The other half of the hash's binding, and the zero address is not a
|
|
510
|
+
usable stand-in for it: it stamps a hash bound to no contract,
|
|
512
511
|
and it matches only a log claiming to come from none."""
|
|
513
512
|
if self._address == ZERO_ADDRESS:
|
|
514
513
|
raise ValueError(
|
|
515
514
|
"executor address required: the proposal hash binds it and the "
|
|
516
515
|
"event readers match it against a log's emitter, so build this "
|
|
517
|
-
"wrapper with
|
|
516
|
+
"wrapper with the executor's address, not the zero address."
|
|
518
517
|
)
|
|
519
518
|
return self._address
|
|
520
519
|
|
|
521
520
|
def _require_chain_id(self, override: ChainId | None = None) -> ChainId:
|
|
522
521
|
"""`override` if the caller named one, else the wrapper's chain, else a
|
|
523
|
-
clear error on a
|
|
522
|
+
clear error on a wrapper built with `ctx=None`."""
|
|
524
523
|
if override is not None:
|
|
525
524
|
return override
|
|
526
525
|
if self._ctx is None:
|
|
527
526
|
raise ValueError(
|
|
528
527
|
"Web3Context required: the proposal hash is bound to a chain id, "
|
|
529
|
-
"so build this wrapper with a ctx rather than
|
|
528
|
+
"so build this wrapper with a ctx rather than ctx=None, "
|
|
530
529
|
"or pass chain_id= to this method."
|
|
531
530
|
)
|
|
532
531
|
return self._ctx.chain_id
|
|
@@ -673,7 +672,7 @@ class ExternalStateExecutor(ContractWrapper):
|
|
|
673
672
|
|
|
674
673
|
The hash is bound to a chain. `chain_id` defaults to this wrapper's
|
|
675
674
|
context; a caller with no context -- decoding indexer or `get_logs`
|
|
676
|
-
rows --
|
|
675
|
+
rows -- builds it with `ExternalStateExecutor(None, address)` and passes `chain_id`
|
|
677
676
|
explicitly. Either way the whole path is pure, with no RPC.
|
|
678
677
|
|
|
679
678
|
`find_balance_proposed` applies the same emitter check while scanning.
|
|
@@ -755,7 +754,7 @@ class ExternalStateExecutor(ContractWrapper):
|
|
|
755
754
|
|
|
756
755
|
The hash is bound to a chain. `chain_id` defaults to this wrapper's
|
|
757
756
|
context; pass it explicitly to verify against a different chain, or to
|
|
758
|
-
scan through a
|
|
757
|
+
scan through a wrapper built with `ctx=None`.
|
|
759
758
|
|
|
760
759
|
Over a `get_logs` range this still answers a different question than
|
|
761
760
|
`pending_proposals`: a proposal may have been confirmed since, which
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
"""The fuse encoder base: `Fuse`, `StakeFuse` and the shared validators and
|
|
2
|
+
substrate packers.
|
|
3
|
+
|
|
4
|
+
It lives in ``core`` so encoders outside ``ipor_fusion.fuses`` can build on it
|
|
5
|
+
without importing that package, whose ``__init__`` loads every encoder.
|
|
6
|
+
``ipor_fusion.fuses.base`` re-exports all of it.
|
|
7
|
+
"""
|
|
8
|
+
|
|
1
9
|
from abc import ABC
|
|
2
10
|
|
|
3
11
|
from eth_abi import encode
|
|
@@ -8,11 +16,16 @@ from ipor_fusion.core.address import _validate_not_zero_address
|
|
|
8
16
|
from ipor_fusion.core.contract import _parse_param_types
|
|
9
17
|
from ipor_fusion.core.fuse_action import FuseAction
|
|
10
18
|
from ipor_fusion.types import MAX_UINT256, Amount, FuseAddress
|
|
11
|
-
from ipor_fusion.types import ZERO_ADDRESS as ZERO_ADDRESS
|
|
12
19
|
|
|
13
20
|
|
|
14
21
|
class Fuse(ABC): # noqa: B024 # ABC marks intent; no shared abstract method
|
|
15
|
-
"""Abstract base class for all protocol fuse adapters.
|
|
22
|
+
"""Abstract base class for all protocol fuse adapters.
|
|
23
|
+
|
|
24
|
+
A fuse is a value: two fuses are equal (and hash alike) when they are of the
|
|
25
|
+
same class and carry the same constructor state (the fuse address, plus e.g.
|
|
26
|
+
a `StakeFuse`'s staking contract), so a subclass that stores more state is
|
|
27
|
+
compared on it without overriding anything. That state must be hashable.
|
|
28
|
+
"""
|
|
16
29
|
|
|
17
30
|
def __init__(self, address: FuseAddress):
|
|
18
31
|
_validate_not_zero_address(address, "fuse address")
|
|
@@ -42,14 +55,10 @@ class Fuse(ABC): # noqa: B024 # ABC marks intent; no shared abstract method
|
|
|
42
55
|
raise ValueError(f"{name} must not be negative, got {value}")
|
|
43
56
|
|
|
44
57
|
def __eq__(self, other: object) -> bool:
|
|
45
|
-
return (
|
|
46
|
-
isinstance(other, Fuse)
|
|
47
|
-
and type(self) is type(other)
|
|
48
|
-
and self._address == other._address
|
|
49
|
-
)
|
|
58
|
+
return type(self) is type(other) and vars(self) == vars(other)
|
|
50
59
|
|
|
51
60
|
def __hash__(self) -> int:
|
|
52
|
-
return hash((type(self), self.
|
|
61
|
+
return hash((type(self), *sorted(vars(self).items())))
|
|
53
62
|
|
|
54
63
|
def _action_raw(self, signature: str, values: list) -> FuseAction:
|
|
55
64
|
selector = function_signature_to_4byte_selector(signature)
|
|
@@ -43,7 +43,7 @@ class Multicall3(ContractWrapper):
|
|
|
43
43
|
|
|
44
44
|
def __init__(
|
|
45
45
|
self,
|
|
46
|
-
ctx: Web3Context,
|
|
46
|
+
ctx: Web3Context | None,
|
|
47
47
|
address: ChecksumAddress = MULTICALL3_ADDRESS,
|
|
48
48
|
batch_size: int = DEFAULT_BATCH_SIZE,
|
|
49
49
|
):
|
|
@@ -66,20 +66,22 @@ class Multicall3(ContractWrapper):
|
|
|
66
66
|
|
|
67
67
|
def aggregate(self, calls: Sequence[Call[T]]) -> list[T]:
|
|
68
68
|
"""Execute all `calls`; raise as `Call.call()` would on any failure."""
|
|
69
|
+
ctx = self._require_ctx()
|
|
69
70
|
raw = self._fetch(calls)
|
|
70
71
|
if raw is None:
|
|
71
|
-
return [call.call(
|
|
72
|
+
return [call.call(ctx) for call in calls]
|
|
72
73
|
return [
|
|
73
|
-
call.decode(data) if ok and data else call.call(
|
|
74
|
+
call.decode(data) if ok and data else call.call(ctx)
|
|
74
75
|
for call, (ok, data) in zip(calls, raw, strict=True)
|
|
75
76
|
]
|
|
76
77
|
|
|
77
78
|
def try_aggregate(self, calls: Sequence[Call[T]]) -> list[T | None]:
|
|
78
79
|
"""Execute all `calls`; ``None`` for each that reverts, returns no data
|
|
79
80
|
or returns data its `Call` cannot decode."""
|
|
81
|
+
ctx = self._require_ctx()
|
|
80
82
|
raw = self._fetch(calls)
|
|
81
83
|
if raw is None:
|
|
82
|
-
return [_try_call(call,
|
|
84
|
+
return [_try_call(call, ctx) for call in calls]
|
|
83
85
|
return [
|
|
84
86
|
_try_decode(call, ok, data)
|
|
85
87
|
for call, (ok, data) in zip(calls, raw, strict=True)
|
|
@@ -78,7 +78,7 @@ class PriceOracleMiddleware(ContractWrapper):
|
|
|
78
78
|
Web3.keccak(text="AssetPriceSourceUpdated(address,address)")
|
|
79
79
|
).to_0x_hex()
|
|
80
80
|
return list(
|
|
81
|
-
self.
|
|
81
|
+
self._require_ctx().get_logs(
|
|
82
82
|
contract_address=self._address, topics=[event_signature_hash]
|
|
83
83
|
)
|
|
84
84
|
)
|
|
@@ -91,7 +91,7 @@ class LegacyPriceOracleMiddleware(PriceOracleMiddleware):
|
|
|
91
91
|
|
|
92
92
|
def __init__(
|
|
93
93
|
self,
|
|
94
|
-
ctx: Web3Context,
|
|
94
|
+
ctx: Web3Context | None,
|
|
95
95
|
address: ChecksumAddress,
|
|
96
96
|
base_currency_decimals: Decimals,
|
|
97
97
|
):
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
from collections.abc import Callable, Sequence
|
|
4
4
|
from concurrent.futures import ThreadPoolExecutor
|
|
5
5
|
from dataclasses import dataclass
|
|
6
|
-
from typing import Any,
|
|
6
|
+
from typing import Any, TypeVar
|
|
7
7
|
|
|
8
8
|
from eth_abi import decode, encode
|
|
9
9
|
from eth_typing import ChecksumAddress
|
|
@@ -148,17 +148,13 @@ class PlasmaVault(ContractWrapper):
|
|
|
148
148
|
service, multisig), grab the bytes directly: `vault.add_fuses(...).calldata`.
|
|
149
149
|
"""
|
|
150
150
|
|
|
151
|
-
def __init__(self, ctx: Web3Context, address: PlasmaVaultAddress):
|
|
151
|
+
def __init__(self, ctx: Web3Context | None, address: PlasmaVaultAddress):
|
|
152
152
|
super().__init__(ctx, address)
|
|
153
153
|
|
|
154
154
|
@property
|
|
155
155
|
def address(self) -> PlasmaVaultAddress:
|
|
156
156
|
return PlasmaVaultAddress(self._address)
|
|
157
157
|
|
|
158
|
-
@classmethod
|
|
159
|
-
def encoder(cls, address: PlasmaVaultAddress | None = None) -> Self: # type: ignore[override]
|
|
160
|
-
return super().encoder(address)
|
|
161
|
-
|
|
162
158
|
def execute(self, actions: list[FuseAction]) -> Call[None]:
|
|
163
159
|
data = FuseAction.encode_execute_payload(actions, "execute((address,bytes)[])")
|
|
164
160
|
return Call(to=self._address, data=data, ctx=self._ctx)
|
|
@@ -573,7 +569,7 @@ class PlasmaVault(ContractWrapper):
|
|
|
573
569
|
]
|
|
574
570
|
|
|
575
571
|
def _address_at(self, slot: int) -> ChecksumAddress:
|
|
576
|
-
return _address_in_word(self.
|
|
572
|
+
return _address_in_word(self._require_ctx().get_storage_at(self._address, slot))
|
|
577
573
|
|
|
578
574
|
def _is_own_withdraw_manager(self, candidate: ChecksumAddress) -> bool:
|
|
579
575
|
call = Call(
|
|
@@ -650,7 +646,7 @@ class PlasmaVault(ContractWrapper):
|
|
|
650
646
|
Web3.keccak(text="WithdrawManagerChanged(address)")
|
|
651
647
|
).to_0x_hex()
|
|
652
648
|
return list(
|
|
653
|
-
self.
|
|
649
|
+
self._require_ctx().get_logs(
|
|
654
650
|
contract_address=self._address, topics=[event_signature_hash]
|
|
655
651
|
)
|
|
656
652
|
)
|
|
@@ -658,7 +654,7 @@ class PlasmaVault(ContractWrapper):
|
|
|
658
654
|
def _get_balance_fuse_events(self) -> list[LogReceipt]:
|
|
659
655
|
"""BalanceFuseAdded and BalanceFuseRemoved logs, from one eth_getLogs."""
|
|
660
656
|
return list(
|
|
661
|
-
self.
|
|
657
|
+
self._require_ctx().get_logs(
|
|
662
658
|
contract_address=self._address,
|
|
663
659
|
topics=[
|
|
664
660
|
[
|
{ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/core/withdraw_manager.py
RENAMED
|
@@ -120,7 +120,7 @@ class WithdrawManager(ContractWrapper):
|
|
|
120
120
|
|
|
121
121
|
Replays `WithdrawRequestUpdated` from ``from_block``, or from the
|
|
122
122
|
WithdrawManager's creation when None."""
|
|
123
|
-
current_timestamp = self.
|
|
123
|
+
current_timestamp = self._require_ctx().get_block()["timestamp"]
|
|
124
124
|
events = self._get_withdraw_request_updated_events(from_block=from_block)
|
|
125
125
|
|
|
126
126
|
accounts: list[str] = []
|
|
@@ -137,7 +137,7 @@ class WithdrawManager(ContractWrapper):
|
|
|
137
137
|
|
|
138
138
|
checksummed = [Web3.to_checksum_address(account) for account in accounts]
|
|
139
139
|
calls = [self.request_info(account) for account in checksummed]
|
|
140
|
-
infos = Multicall3(self.
|
|
140
|
+
infos = Multicall3(self._require_ctx()).try_aggregate(calls)
|
|
141
141
|
results: list[AccountRequest] = []
|
|
142
142
|
for account, call, req in zip(checksummed, calls, infos, strict=True):
|
|
143
143
|
if req is None:
|
|
@@ -164,7 +164,7 @@ class WithdrawManager(ContractWrapper):
|
|
|
164
164
|
self,
|
|
165
165
|
from_block: BlockNumber | None = None,
|
|
166
166
|
) -> PendingRequestsInfo:
|
|
167
|
-
current_timestamp = self.
|
|
167
|
+
current_timestamp = self._require_ctx().get_block()["timestamp"]
|
|
168
168
|
requests = self.get_pending_requests(from_block=from_block)
|
|
169
169
|
total = sum(r.shares for r in requests)
|
|
170
170
|
return PendingRequestsInfo(
|
|
@@ -180,7 +180,7 @@ class WithdrawManager(ContractWrapper):
|
|
|
180
180
|
Web3.keccak(text="WithdrawRequestUpdated(address,uint256,uint32)")
|
|
181
181
|
).to_0x_hex()
|
|
182
182
|
return list(
|
|
183
|
-
self.
|
|
183
|
+
self._require_ctx().get_logs(
|
|
184
184
|
contract_address=self._address,
|
|
185
185
|
topics=[event_signature_hash],
|
|
186
186
|
from_block=from_block,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Public path of the fuse encoder base, defined in `ipor_fusion.core.fuse`."""
|
|
2
|
+
|
|
3
|
+
from ipor_fusion.core.address import (
|
|
4
|
+
_validate_not_zero_address as _validate_not_zero_address,
|
|
5
|
+
)
|
|
6
|
+
from ipor_fusion.core.fuse import Fuse as Fuse
|
|
7
|
+
from ipor_fusion.core.fuse import StakeFuse as StakeFuse
|
|
8
|
+
from ipor_fusion.core.fuse import (
|
|
9
|
+
_encode_address_substrate as _encode_address_substrate,
|
|
10
|
+
)
|
|
11
|
+
from ipor_fusion.core.fuse import (
|
|
12
|
+
_encode_uint248_substrate as _encode_uint248_substrate,
|
|
13
|
+
)
|
|
14
|
+
from ipor_fusion.core.fuse import _substrate_address_bytes as _substrate_address_bytes
|
|
15
|
+
from ipor_fusion.core.fuse import _validate_selector as _validate_selector
|
|
16
|
+
from ipor_fusion.core.fuse_action import FuseAction as FuseAction
|
|
17
|
+
from ipor_fusion.types import ZERO_ADDRESS as ZERO_ADDRESS
|
{ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/crosschain/base.py
RENAMED
|
@@ -31,13 +31,10 @@ from eth_typing import ChecksumAddress
|
|
|
31
31
|
from eth_utils import keccak
|
|
32
32
|
from web3 import Web3
|
|
33
33
|
|
|
34
|
+
from ipor_fusion.core.address import _validate_not_zero_address
|
|
35
|
+
from ipor_fusion.core.fuse import Fuse, _substrate_address_bytes
|
|
36
|
+
from ipor_fusion.core.fuse_action import FuseAction
|
|
34
37
|
from ipor_fusion.crosschain.messages import Command
|
|
35
|
-
from ipor_fusion.fuses.base import (
|
|
36
|
-
Fuse,
|
|
37
|
-
FuseAction,
|
|
38
|
-
_substrate_address_bytes,
|
|
39
|
-
_validate_not_zero_address,
|
|
40
|
-
)
|
|
41
38
|
from ipor_fusion.types import Amount, ChainId, MarketId
|
|
42
39
|
|
|
43
40
|
_NO_CHAIN = ChainId(0)
|
{ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/crosschain/ccip.py
RENAMED
|
@@ -22,15 +22,16 @@ from enum import IntEnum
|
|
|
22
22
|
|
|
23
23
|
from eth_typing import ChecksumAddress
|
|
24
24
|
|
|
25
|
+
from ipor_fusion.core.fuse import Fuse
|
|
26
|
+
from ipor_fusion.core.fuse_action import FuseAction
|
|
25
27
|
from ipor_fusion.crosschain.ccip.contracts import CcipRouteConfig
|
|
26
28
|
from ipor_fusion.crosschain.messages import COMMAND_TUPLE_TYPE, EMPTY_COMMAND, Command
|
|
27
|
-
from ipor_fusion.fuses.base import ZERO_ADDRESS, Fuse, FuseAction
|
|
28
29
|
from ipor_fusion.fuses.crosschain.base import (
|
|
29
30
|
CrosschainCommandFuse,
|
|
30
31
|
CrosschainSupplyFuse,
|
|
31
32
|
SendParams,
|
|
32
33
|
)
|
|
33
|
-
from ipor_fusion.types import Amount, ChainId
|
|
34
|
+
from ipor_fusion.types import ZERO_ADDRESS, Amount, ChainId
|
|
34
35
|
|
|
35
36
|
|
|
36
37
|
@dataclass(frozen=True, slots=True)
|
{ipor_fusion-4.0.0.dev86 → ipor_fusion-4.0.0.dev88}/src/ipor_fusion/fuses/crosschain/stargate.py
RENAMED
|
@@ -20,6 +20,8 @@ from enum import IntEnum
|
|
|
20
20
|
|
|
21
21
|
from eth_typing import ChecksumAddress
|
|
22
22
|
|
|
23
|
+
from ipor_fusion.core.fuse import Fuse
|
|
24
|
+
from ipor_fusion.core.fuse_action import FuseAction
|
|
23
25
|
from ipor_fusion.crosschain.messages import (
|
|
24
26
|
COMMAND_TUPLE_TYPE,
|
|
25
27
|
EMPTY_COMMAND,
|
|
@@ -27,7 +29,6 @@ from ipor_fusion.crosschain.messages import (
|
|
|
27
29
|
Command,
|
|
28
30
|
)
|
|
29
31
|
from ipor_fusion.crosschain.stargate.layerzero import OptionsBuilder
|
|
30
|
-
from ipor_fusion.fuses.base import Fuse, FuseAction
|
|
31
32
|
from ipor_fusion.fuses.crosschain.base import (
|
|
32
33
|
CrosschainCommandFuse,
|
|
33
34
|
CrosschainSupplyFuse,
|
|
@@ -64,16 +64,6 @@ class UniversalTokenSwapperFuse(Fuse):
|
|
|
64
64
|
super().__init__(address)
|
|
65
65
|
self._abi = abi
|
|
66
66
|
|
|
67
|
-
def __eq__(self, other: object) -> bool:
|
|
68
|
-
return (
|
|
69
|
-
isinstance(other, UniversalTokenSwapperFuse)
|
|
70
|
-
and super().__eq__(other)
|
|
71
|
-
and self._abi is other._abi
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
def __hash__(self) -> int:
|
|
75
|
-
return hash((type(self), self._address, self._abi))
|
|
76
|
-
|
|
77
67
|
def swap(
|
|
78
68
|
self,
|
|
79
69
|
*,
|