ipor-fusion 4.0.0.dev66__tar.gz → 4.0.0.dev71__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.dev66 → ipor_fusion-4.0.0.dev71}/MIGRATION_4.md +18 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/PKG-INFO +1 -1
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/pyproject.toml +1 -1
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/__init__.py +2 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/market_cmd.py +1 -1
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/options.py +2 -2
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/vault_info_view.py +4 -4
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/context.py +16 -17
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/contract.py +3 -3
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/fusion_factory.py +64 -1
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/logs.py +13 -3
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/simulation.py +15 -12
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/ccip/quote.py +1 -3
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/simulation.py +2 -6
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/stargate/contracts.py +16 -9
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/stargate/layerzero.py +10 -10
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/stargate/transport.py +7 -4
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/errors.py +3 -3
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/explorer.py +1 -1
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/base.py +5 -1
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/crosschain/ccip.py +4 -4
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/crosschain/stargate.py +4 -3
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/universal.py +5 -1
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/aave_v3.py +2 -4
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/morpho.py +9 -3
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/oracle_mapping_nodes.py +1 -3
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/oracle_mapping_reader.py +2 -2
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/types.py +3 -1
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/vault_info.py +1 -1
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_encoding.py +3 -1
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_external_state_executor.py +1 -1
- ipor_fusion-4.0.0.dev71/tests/test_fusion_instance.py +70 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_crosschain_hyperevm.py +1 -3
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_vault_simulator_blocks.py +11 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_web3_context.py +1 -1
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/typed_client/consumer.py +8 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/.claude-plugin/marketplace.json +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/.claude-plugin/plugin.json +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/.env.example +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/.gemini/settings.json +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/.git-blame-ignore-revs +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/.github/workflows/cd.yml +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/.github/workflows/ci.yml +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/.github/workflows/commit-lint.yml +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/.github/workflows/notify-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/.github/workflows/python-build.yml +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/.github/workflows/python-publish.yml +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/.github/workflows/release.yml +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/.github/workflows/report-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/.gitignore +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/.pre-commit-config.yaml +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/.python-version +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/AGENTS.md +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/CHANGELOG.md +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/CLAUDE.md +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/CODEOWNERS +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/LICENSE +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/README.md +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/build.sh +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/examples/CONTRIBUTING.md +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/examples/README.md +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/examples/advanced_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/examples/advanced_euler_v2_looping_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/examples/composed_hypercore_flow_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/examples/external_state_margin_leg_base.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/examples/simple_aave_v3_supply_base.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/pytest.ini +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/scripts/commit-check.sh +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/scripts/crosschain_readiness.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/skills/ipor-deploy-vault/SKILL.md +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/about.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cache.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/chains.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/changelog_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/config_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/config_store.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/main.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/oracle_mapping_view.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/vault_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/vault_health.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/vault_markets_view.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/vault_rendering.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/config/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/config/roles.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/access.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/address.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/erc20.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/external_state_executor.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/fee_manager.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/fuse_action.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/multicall.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/oracle.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/plasma_vault.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/rewards_manager.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/ccip/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/ccip/chainlink.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/ccip/codec.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/ccip/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/ccip/events.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/ccip/indexer.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/ccip/lane.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/ccip/transport.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/discovery.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/errors.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/lane.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/logs.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/messages.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/stargate/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/stargate/lane.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/transport.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/dependency_graph.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/entry_cli.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/entry_mcp.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/field_docs.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/aave_v3.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/async_action.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/crosschain/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/crosschain/base.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/erc4626.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/euler_v2.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/events.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/external_state.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/external_state_events.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/fluid_instadapp.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/gearbox_v3.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/hypercore_events.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/merkl.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/morpho.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/guide/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/guide/architecture.md +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/guide/glossary.md +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/guide/invariants.md +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/guide/quickstart.md +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/market_ids.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/market_info.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/mcp/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/mcp/guide.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/mcp/models.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/mcp/server.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/morpho_api.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/py.typed +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/aave_v4.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/hypercore_outcome.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/lending_health.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/position_manager.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/unpriceable.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/substrates.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/validation.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/vault_data.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/vault_managers.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/vault_positions.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/vault_reads.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/UniswapV3UniversalRouter.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/_crosschain_recovery.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/_euler_v2.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/_foundry.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/_guide.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/_hypercore_model.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/_hypercore_shadow.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/_simulate.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/_validation.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/addresses.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/conftest.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/constants.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/fixtures/hypercore_hip3_flow.json +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/fixtures/hypercore_market55.json +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/fixtures/vault_info_golden/clean.json +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/fixtures/vault_info_golden/clean.txt +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/fixtures/vault_info_golden/rich.json +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/fixtures/vault_info_golden/rich.txt +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_about.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_access_manager.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_cache.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_chains.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_cli_changelog.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_cli_commands.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_cli_config_store.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_cli_helpers.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_cli_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_cli_lending_health.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_cli_market_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_cli_oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_cli_pending_requests_scan.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_cli_role_accounts.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_cli_vault_info_golden.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_cli_vault_predates_getters.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_cli_vault_validate.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_contract_call.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_contract_encoder.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_ccip_events.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_ccip_indexer.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_ccip_quote.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_chainlink.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_contracts.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_errors.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_lane.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_layering.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_readiness.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_readiness_report.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_transport.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_erc20.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_examples_composed_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_examples_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_examples_euler_looping_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_examples_vaults.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_explorer.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_external_state_events.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_fee_manager.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_fuse_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_guide.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_hypercore_deployment.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_hypercore_events.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_hypercore_flow.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_hypercore_live.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_hypercore_outcome.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_hypercore_readers.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_hypercore_simulation.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_logs.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_mcp_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_mcp_models.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_mcp_server.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_mcp_vault_validate.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_oracle.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_plasma_vault.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_reader_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_readiness_selection.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_revert_decoding.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_rewards_manager.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_roles.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_sdk_layering.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_borrow_aave_v3_mainnet.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_claim_merkl_wrapper_base.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_claim_morpho_rewards.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_crosschain_canary.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_crosschain_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_euler_v2_batch_base.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_euler_v2_swap_deploy_base.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_euler_v2_swap_reconfigure_base.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_euler_v2_swap_registry_base.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_examples_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_examples_base.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_examples_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_external_state_executor_base.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_fusion_factory_clone_base.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_looping_aave_v3_base.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_looping_morpho_blue_base.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_pilot_v3.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_pilot_v4_uniswap.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_pilot_v5_ramses.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_pilot_v5_scheduled.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_plasma_vault_setters_base.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_readers_integration.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_release_funds.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_swap_on_base.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_vault_from_scratch_base.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_solidity_compiler.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_solidity_mirrors.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_substrates.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_types_and_events.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_unpriceable_tokens.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_validation.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_vault_dep_graph.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_vault_info_onchain_base.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_vault_info_onchain_base_no_withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/tests/test_withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/uv.lock +0 -0
|
@@ -110,6 +110,24 @@ Every fuse constructor, `FuseAction.fuse`, `BalanceFuse.fuse`,
|
|
|
110
110
|
`FusionInstance.access_manager` return one. `resolve_access_manager` still takes any
|
|
111
111
|
`ChecksumAddress`: it is what checks that the address is a vault.
|
|
112
112
|
|
|
113
|
+
**Simulation and factory records.** `VaultSimulator(web3, *, vault=None, alpha=None,
|
|
114
|
+
block=...)` takes every argument after `web3` by keyword, and `vault` and `alpha` are
|
|
115
|
+
optional: a simulator that only observes, deploys or sends `execute_call(call,
|
|
116
|
+
from_=...)` needs neither, so drop a zero-address placeholder. `execute()` without
|
|
117
|
+
`vault` and `alpha` raises `ValueError`, as does `execute_call` without `from_` or
|
|
118
|
+
`alpha`. `FusionInstance.from_dict(data)` rebuilds a stored instance (the
|
|
119
|
+
`dataclasses.asdict` form) with every field parsed; use it instead of
|
|
120
|
+
`FusionInstance(**data)`, which passes raw strings into the role-typed fields.
|
|
121
|
+
|
|
122
|
+
**Transactions, LayerZero and constants.** `Web3Context.build_transaction` and
|
|
123
|
+
`Call.build_transaction` return web3's `TxParams` (the same keys; `data` is `0x` hex,
|
|
124
|
+
the fee fields are `Wei`). LayerZero endpoint ids are `LayerZeroEid`:
|
|
125
|
+
`StargateChain.eid`, `Packet.src_eid` / `dst_eid`, `EnforcedOptionParam.eid`,
|
|
126
|
+
`executor_eid()` and `eid_of()` return it and `chain_id_of`, `peers`, `lz_receive_calldata(src_eid=)`
|
|
127
|
+
and the Stargate fuse's `eid=` take it (`LayerZeroEid(30101)`).
|
|
128
|
+
`encode_oft_compose_msg(*, nonce=, src_eid=, amount_ld=, compose_msg=)` takes
|
|
129
|
+
keyword arguments only. `ZERO_ADDRESS` is a `ChecksumAddress` (same value).
|
|
130
|
+
|
|
113
131
|
**Markets and substrates.** Every `IporFusionMarkets` member is a `MarketId`.
|
|
114
132
|
`decode_substrate`, `market_name`, `format_market_label` take `MarketId`.
|
|
115
133
|
|
|
@@ -325,6 +325,7 @@ from ipor_fusion.types import (
|
|
|
325
325
|
HyperCoreClientOrderId,
|
|
326
326
|
HyperCoreOrderId,
|
|
327
327
|
HyperCoreTokenIndex,
|
|
328
|
+
LayerZeroEid,
|
|
328
329
|
Liquidity,
|
|
329
330
|
MappingStatus,
|
|
330
331
|
MarginTableId,
|
|
@@ -650,6 +651,7 @@ __all__ = [
|
|
|
650
651
|
"ProposalId",
|
|
651
652
|
"ReturnRequestId",
|
|
652
653
|
"StargateAssetId",
|
|
654
|
+
"LayerZeroEid",
|
|
653
655
|
"TransferId",
|
|
654
656
|
"Price",
|
|
655
657
|
"Period",
|
|
@@ -51,7 +51,7 @@ class MarketIdType(click.ParamType):
|
|
|
51
51
|
|
|
52
52
|
name = "marketId"
|
|
53
53
|
|
|
54
|
-
def convert(self, value, param, ctx):
|
|
54
|
+
def convert(self, value, param, ctx):
|
|
55
55
|
if not isinstance(value, str):
|
|
56
56
|
self.fail(f"expected string, got {type(value).__name__}", param, ctx)
|
|
57
57
|
try:
|
|
@@ -51,7 +51,7 @@ class VaultAddressType(AddressType):
|
|
|
51
51
|
"""An address the command treats as a Plasma Vault; the command's probe
|
|
52
52
|
(`resolve_access_manager`) is what checks it on chain."""
|
|
53
53
|
|
|
54
|
-
def convert(self, value, param, ctx) -> PlasmaVaultAddress:
|
|
54
|
+
def convert(self, value, param, ctx) -> PlasmaVaultAddress:
|
|
55
55
|
return PlasmaVaultAddress(super().convert(value, param, ctx))
|
|
56
56
|
|
|
57
57
|
|
|
@@ -63,7 +63,7 @@ class ChainType(click.ParamType):
|
|
|
63
63
|
|
|
64
64
|
name = "chain"
|
|
65
65
|
|
|
66
|
-
def convert(self, value, param, ctx) -> ChainId:
|
|
66
|
+
def convert(self, value, param, ctx) -> ChainId:
|
|
67
67
|
if isinstance(value, int):
|
|
68
68
|
return ChainId(value)
|
|
69
69
|
try:
|
|
@@ -32,7 +32,7 @@ from ipor_fusion.readers.hypercore import HyperCorePendingState
|
|
|
32
32
|
from ipor_fusion.substrates import (
|
|
33
33
|
format_market_label,
|
|
34
34
|
)
|
|
35
|
-
from ipor_fusion.types import ZERO_ADDRESS, ChainId, PlasmaVaultAddress
|
|
35
|
+
from ipor_fusion.types import ZERO_ADDRESS, ChainId, PlasmaVaultAddress, Shares
|
|
36
36
|
from ipor_fusion.validation import (
|
|
37
37
|
validate_vault_state,
|
|
38
38
|
)
|
|
@@ -388,16 +388,16 @@ def _print_pending_requests(data: VaultData, plasma_vault: PlasmaVault) -> None:
|
|
|
388
388
|
click.echo(" Pending requests: (none)")
|
|
389
389
|
return
|
|
390
390
|
|
|
391
|
-
total_shares = sum(
|
|
391
|
+
total_shares = Shares(sum(r.shares for r in requests))
|
|
392
392
|
total_assets: int | None = _safe_call(
|
|
393
|
-
lambda ts=total_shares: plasma_vault.convert_to_assets(ts).call()
|
|
393
|
+
lambda ts=total_shares: plasma_vault.convert_to_assets(ts).call()
|
|
394
394
|
)
|
|
395
395
|
|
|
396
396
|
click.echo(f" Pending requests ({len(requests)}):")
|
|
397
397
|
rows: list[tuple[str, ...]] = []
|
|
398
398
|
for req in requests:
|
|
399
399
|
assets: int | None = _safe_call(
|
|
400
|
-
lambda s=req.shares: plasma_vault.convert_to_assets(s).call()
|
|
400
|
+
lambda s=req.shares: plasma_vault.convert_to_assets(s).call()
|
|
401
401
|
)
|
|
402
402
|
assets_str = (
|
|
403
403
|
f"{_format_amount(assets, data.asset_decimals)} {data.asset_symbol}"
|
|
@@ -3,7 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
|
|
5
5
|
from eth_account import Account
|
|
6
|
-
from eth_typing import ChecksumAddress
|
|
6
|
+
from eth_typing import ChecksumAddress, HexStr
|
|
7
|
+
from eth_utils import encode_hex
|
|
7
8
|
from hexbytes import HexBytes
|
|
8
9
|
from requests import ConnectionError as RequestsConnectionError
|
|
9
10
|
from requests import HTTPError, Timeout
|
|
@@ -14,7 +15,7 @@ from web3.providers.rpc.utils import (
|
|
|
14
15
|
REQUEST_RETRY_ALLOWLIST,
|
|
15
16
|
ExceptionRetryConfiguration,
|
|
16
17
|
)
|
|
17
|
-
from web3.types import BlockIdentifier, LogReceipt, TxReceipt
|
|
18
|
+
from web3.types import BlockIdentifier, LogReceipt, TxParams, TxReceipt, Wei
|
|
18
19
|
|
|
19
20
|
from ipor_fusion.chains import GET_LOGS_RANGE_HINTS
|
|
20
21
|
from ipor_fusion.core.logs import (
|
|
@@ -182,7 +183,7 @@ class Web3Context:
|
|
|
182
183
|
data: bytes,
|
|
183
184
|
*,
|
|
184
185
|
block: BlockIdentifier = "latest",
|
|
185
|
-
) ->
|
|
186
|
+
) -> TxParams:
|
|
186
187
|
"""Build the transaction dict for ``data`` against ``to`` without signing
|
|
187
188
|
or broadcasting — the same dict `send` would submit, ready to hand to an
|
|
188
189
|
external signer or to inspect for a gas/cost preview (`gas` and
|
|
@@ -211,7 +212,7 @@ class Web3Context:
|
|
|
211
212
|
max_fee_per_gas = self._calculate_max_fee_per_gas(
|
|
212
213
|
gas_price, base_fee, max_priority_fee_per_gas
|
|
213
214
|
)
|
|
214
|
-
data_hex =
|
|
215
|
+
data_hex = encode_hex(data)
|
|
215
216
|
estimated_gas = self._estimate_gas(to, data_hex, signer, block)
|
|
216
217
|
return {
|
|
217
218
|
"chainId": self.chain_id,
|
|
@@ -262,7 +263,7 @@ class Web3Context:
|
|
|
262
263
|
`build_transaction`.
|
|
263
264
|
"""
|
|
264
265
|
signer = self._require_signer("estimate gas")
|
|
265
|
-
return self._estimate_gas(to,
|
|
266
|
+
return self._estimate_gas(to, encode_hex(data), signer, block)
|
|
266
267
|
|
|
267
268
|
def get_logs(
|
|
268
269
|
self,
|
|
@@ -323,12 +324,12 @@ class Web3Context:
|
|
|
323
324
|
def _estimate_gas(
|
|
324
325
|
self,
|
|
325
326
|
to: ChecksumAddress,
|
|
326
|
-
data:
|
|
327
|
-
from_address:
|
|
327
|
+
data: HexStr,
|
|
328
|
+
from_address: ChecksumAddress,
|
|
328
329
|
block: BlockIdentifier = "latest",
|
|
329
330
|
) -> int:
|
|
330
331
|
estimated = self.web3.eth.estimate_gas(
|
|
331
|
-
{"to": to, "from": from_address, "data": data},
|
|
332
|
+
{"to": to, "from": from_address, "data": data},
|
|
332
333
|
block_identifier=block,
|
|
333
334
|
)
|
|
334
335
|
# State can shift between estimate and execution, so pad the limit; it is
|
|
@@ -337,25 +338,23 @@ class Web3Context:
|
|
|
337
338
|
|
|
338
339
|
def _calculate_max_fee_per_gas(
|
|
339
340
|
self, gas_price: int, base_fee: int | None, max_priority_fee_per_gas: int
|
|
340
|
-
) ->
|
|
341
|
+
) -> Wei:
|
|
341
342
|
# Prefer a base-fee-relative ceiling on EIP-1559 chains; fall back to a
|
|
342
343
|
# gas-price margin where the block carries no base fee.
|
|
343
344
|
if base_fee is None:
|
|
344
|
-
return gas_price + self._percent_of(gas_price, self.GAS_PRICE_MARGIN)
|
|
345
|
-
return
|
|
345
|
+
return Wei(gas_price + self._percent_of(gas_price, self.GAS_PRICE_MARGIN))
|
|
346
|
+
return Wei(
|
|
347
|
+
base_fee * self.BASE_FEE_HEADROOM_MULTIPLIER + max_priority_fee_per_gas
|
|
348
|
+
)
|
|
346
349
|
|
|
347
|
-
def _get_max_priority_fee(self, gas_price: int) ->
|
|
348
|
-
return min(self.DEFAULT_TRANSACTION_MAX_PRIORITY_FEE, gas_price // 10)
|
|
350
|
+
def _get_max_priority_fee(self, gas_price: int) -> Wei:
|
|
351
|
+
return Wei(min(self.DEFAULT_TRANSACTION_MAX_PRIORITY_FEE, gas_price // 10))
|
|
349
352
|
|
|
350
353
|
def _require_signer(self, action: str) -> ChecksumAddress:
|
|
351
354
|
if self.signer is None:
|
|
352
355
|
raise ValueError(f"Signer required to {action}")
|
|
353
356
|
return self.signer
|
|
354
357
|
|
|
355
|
-
@staticmethod
|
|
356
|
-
def _data_hex(data: bytes) -> str:
|
|
357
|
-
return f"0x{data.hex()}"
|
|
358
|
-
|
|
359
358
|
@staticmethod
|
|
360
359
|
def _percent_of(value: int, percentage: int) -> int:
|
|
361
360
|
return value * percentage // 100
|
|
@@ -8,7 +8,7 @@ from eth_abi import decode, encode
|
|
|
8
8
|
from eth_typing import ChecksumAddress
|
|
9
9
|
from eth_utils import function_signature_to_4byte_selector
|
|
10
10
|
from web3 import Web3
|
|
11
|
-
from web3.types import BlockIdentifier, TxReceipt
|
|
11
|
+
from web3.types import BlockIdentifier, TxParams, TxReceipt
|
|
12
12
|
|
|
13
13
|
from ipor_fusion.core.context import Web3Context
|
|
14
14
|
from ipor_fusion.errors import EmptyCallResultError
|
|
@@ -105,7 +105,7 @@ class Call(Generic[T]):
|
|
|
105
105
|
|
|
106
106
|
def build_transaction(
|
|
107
107
|
self, ctx: Web3Context | None = None, *, block: BlockIdentifier = "latest"
|
|
108
|
-
) ->
|
|
108
|
+
) -> TxParams:
|
|
109
109
|
"""Build the transaction dict for this Call without signing or sending —
|
|
110
110
|
mirrors `.send()`, delegating to `Web3Context.build_transaction`. Returns
|
|
111
111
|
the dict a signer would submit; needs a signer address, no key."""
|
|
@@ -165,7 +165,7 @@ class ContractWrapper:
|
|
|
165
165
|
and so rejects input that is genuinely the caller's.
|
|
166
166
|
"""
|
|
167
167
|
instance = cls.__new__(cls)
|
|
168
|
-
instance._ctx = None
|
|
168
|
+
instance._ctx = None
|
|
169
169
|
instance._address = (
|
|
170
170
|
Web3.to_checksum_address(address)
|
|
171
171
|
if address is not None
|
|
@@ -22,7 +22,9 @@ For external-signer flows, grab the bytes directly:
|
|
|
22
22
|
|
|
23
23
|
from __future__ import annotations
|
|
24
24
|
|
|
25
|
+
from collections.abc import Callable, Mapping
|
|
25
26
|
from dataclasses import dataclass
|
|
27
|
+
from typing import Any
|
|
26
28
|
|
|
27
29
|
from eth_abi import decode as abi_decode
|
|
28
30
|
from eth_typing import ChecksumAddress
|
|
@@ -31,7 +33,13 @@ from web3 import Web3
|
|
|
31
33
|
from web3.types import TxReceipt
|
|
32
34
|
|
|
33
35
|
from ipor_fusion.core.contract import Call, ContractWrapper
|
|
34
|
-
from ipor_fusion.types import
|
|
36
|
+
from ipor_fusion.types import (
|
|
37
|
+
AccessManagerAddress,
|
|
38
|
+
Period,
|
|
39
|
+
PlasmaVaultAddress,
|
|
40
|
+
parse_access_manager_address,
|
|
41
|
+
parse_plasma_vault_address,
|
|
42
|
+
)
|
|
35
43
|
|
|
36
44
|
|
|
37
45
|
@dataclass(slots=True, frozen=True)
|
|
@@ -70,6 +78,61 @@ class FusionInstance:
|
|
|
70
78
|
context_manager: ChecksumAddress
|
|
71
79
|
price_manager: ChecksumAddress
|
|
72
80
|
|
|
81
|
+
@classmethod
|
|
82
|
+
def from_dict(
|
|
83
|
+
cls, data: Mapping[str, Any]
|
|
84
|
+
) -> FusionInstance: # proctor: ignore[primitives-untyped-dict]
|
|
85
|
+
"""Rebuild an instance from its JSON form (``dataclasses.asdict``),
|
|
86
|
+
parsing every field: role addresses through their parsers, the rest
|
|
87
|
+
checksummed, integers and strings type-checked. Raises ``ValueError``
|
|
88
|
+
on a missing, extra or malformed field."""
|
|
89
|
+
missing = _INSTANCE_FIELDS.keys() - data.keys()
|
|
90
|
+
extra = data.keys() - _INSTANCE_FIELDS.keys()
|
|
91
|
+
if missing or extra:
|
|
92
|
+
raise ValueError(
|
|
93
|
+
f"FusionInstance fields: missing {sorted(missing)}, extra {sorted(extra)}"
|
|
94
|
+
)
|
|
95
|
+
return cls(
|
|
96
|
+
**{name: parse(data[name]) for name, parse in _INSTANCE_FIELDS.items()}
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _integer(value: Any) -> int:
|
|
101
|
+
if type(value) is not int:
|
|
102
|
+
raise ValueError(f"expected an integer: {value!r}")
|
|
103
|
+
return value
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _text(value: Any) -> str:
|
|
107
|
+
if not isinstance(value, str):
|
|
108
|
+
raise ValueError(f"expected a string: {value!r}")
|
|
109
|
+
return value
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _address(value: Any) -> ChecksumAddress:
|
|
113
|
+
return Web3.to_checksum_address(_text(value))
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
_INSTANCE_FIELDS: dict[str, Callable[[Any], Any]] = {
|
|
117
|
+
"index": _integer,
|
|
118
|
+
"version": _integer,
|
|
119
|
+
"asset_name": _text,
|
|
120
|
+
"asset_symbol": _text,
|
|
121
|
+
"asset_decimals": _integer,
|
|
122
|
+
"underlying_token": _address,
|
|
123
|
+
"underlying_token_symbol": _text,
|
|
124
|
+
"underlying_token_decimals": _integer,
|
|
125
|
+
"initial_owner": _address,
|
|
126
|
+
"plasma_vault": lambda value: parse_plasma_vault_address(_text(value)),
|
|
127
|
+
"plasma_vault_base": _address,
|
|
128
|
+
"access_manager": lambda value: parse_access_manager_address(_text(value)),
|
|
129
|
+
"fee_manager": _address,
|
|
130
|
+
"rewards_manager": _address,
|
|
131
|
+
"withdraw_manager": _address,
|
|
132
|
+
"context_manager": _address,
|
|
133
|
+
"price_manager": _address,
|
|
134
|
+
}
|
|
135
|
+
|
|
73
136
|
|
|
74
137
|
_FUSION_INSTANCE_OUTPUT_TYPES: list[str] = [
|
|
75
138
|
"uint256", # index
|
|
@@ -19,7 +19,9 @@ from concurrent.futures import ThreadPoolExecutor
|
|
|
19
19
|
from typing import Protocol
|
|
20
20
|
|
|
21
21
|
import requests
|
|
22
|
-
from eth_typing import ChecksumAddress
|
|
22
|
+
from eth_typing import ChecksumAddress, HexStr
|
|
23
|
+
from eth_utils import encode_hex
|
|
24
|
+
from hexbytes import HexBytes
|
|
23
25
|
from web3 import Web3
|
|
24
26
|
from web3.exceptions import Web3Exception
|
|
25
27
|
from web3.types import BlockIdentifier, FilterParams, LogReceipt
|
|
@@ -158,6 +160,14 @@ class _Rejected(Exception):
|
|
|
158
160
|
self.size = size
|
|
159
161
|
|
|
160
162
|
|
|
163
|
+
def _topic_filter(topic: str | list[str]) -> HexStr | list[HexStr]:
|
|
164
|
+
"""A topic (or an OR-list of them) as the canonical hex `eth_getLogs`
|
|
165
|
+
filters by; raises on text that is not hex."""
|
|
166
|
+
if isinstance(topic, str):
|
|
167
|
+
return encode_hex(HexBytes(topic))
|
|
168
|
+
return [encode_hex(HexBytes(alternative)) for alternative in topic]
|
|
169
|
+
|
|
170
|
+
|
|
161
171
|
class _Scan:
|
|
162
172
|
def __init__(
|
|
163
173
|
self,
|
|
@@ -169,7 +179,7 @@ class _Scan:
|
|
|
169
179
|
):
|
|
170
180
|
self._web3 = web3
|
|
171
181
|
self._address = address
|
|
172
|
-
self._topics = topics
|
|
182
|
+
self._topics = [_topic_filter(topic) for topic in topics]
|
|
173
183
|
self._timeout_s = timeout_s
|
|
174
184
|
self._deadline = time.monotonic() + timeout_s
|
|
175
185
|
self._stopped = threading.Event()
|
|
@@ -219,7 +229,7 @@ class _Scan:
|
|
|
219
229
|
self._check(low, high)
|
|
220
230
|
params: FilterParams = {
|
|
221
231
|
"address": self._address,
|
|
222
|
-
"topics": self._topics,
|
|
232
|
+
"topics": self._topics,
|
|
223
233
|
"fromBlock": low,
|
|
224
234
|
"toBlock": high,
|
|
225
235
|
}
|
|
@@ -16,7 +16,7 @@ from web3.utils.address import get_create_address
|
|
|
16
16
|
from ipor_fusion.core.contract import Call, _encode_calldata
|
|
17
17
|
from ipor_fusion.core.fuse_action import FuseAction
|
|
18
18
|
from ipor_fusion.errors import SimulationError, decode_custom_error
|
|
19
|
-
from ipor_fusion.types import
|
|
19
|
+
from ipor_fusion.types import PlasmaVaultAddress
|
|
20
20
|
|
|
21
21
|
#: ``n`` (the sent block's index in the run) -> account overrides for it.
|
|
22
22
|
StateOverrideProvider = Callable[[int], Mapping[str, Mapping[str, Any]]]
|
|
@@ -190,15 +190,16 @@ class VaultSimulator:
|
|
|
190
190
|
def __init__(
|
|
191
191
|
self,
|
|
192
192
|
web3: Web3,
|
|
193
|
-
|
|
194
|
-
|
|
193
|
+
*,
|
|
194
|
+
vault: PlasmaVaultAddress | None = None,
|
|
195
|
+
alpha: ChecksumAddress | None = None,
|
|
195
196
|
block: BlockIdentifier = "latest",
|
|
196
197
|
validation: bool = False,
|
|
197
198
|
trace_transfers: bool = False,
|
|
198
199
|
):
|
|
199
200
|
self._web3 = web3
|
|
200
|
-
self._vault =
|
|
201
|
-
self._alpha =
|
|
201
|
+
self._vault = vault
|
|
202
|
+
self._alpha = alpha
|
|
202
203
|
self._block: BlockIdentifier = block
|
|
203
204
|
self._validation = validation
|
|
204
205
|
self._trace_transfers = trace_transfers
|
|
@@ -341,6 +342,8 @@ class VaultSimulator:
|
|
|
341
342
|
|
|
342
343
|
def execute(self, actions: list[FuseAction]) -> VaultSimulator:
|
|
343
344
|
"""Queue a default `execute((address,bytes)[])` batch on the vault, from alpha."""
|
|
345
|
+
if self._vault is None or self._alpha is None:
|
|
346
|
+
raise ValueError("execute needs a simulator built with vault= and alpha=")
|
|
344
347
|
data = FuseAction.encode_execute_payload(actions, "execute((address,bytes)[])")
|
|
345
348
|
return self._queue_execute(self._vault, data, self._alpha)
|
|
346
349
|
|
|
@@ -351,11 +354,12 @@ class VaultSimulator:
|
|
|
351
354
|
e.g. `RewardsManager.claim_rewards(...)` where the wrapper differs from
|
|
352
355
|
`PlasmaVault.execute`. `from_` defaults to alpha.
|
|
353
356
|
"""
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
357
|
+
sender = from_ or self._alpha
|
|
358
|
+
if sender is None:
|
|
359
|
+
raise ValueError(
|
|
360
|
+
"execute_call needs from_ or a simulator built with alpha="
|
|
361
|
+
)
|
|
362
|
+
return self._queue_execute(call.to, call.data, sender)
|
|
359
363
|
|
|
360
364
|
def _queue_execute(
|
|
361
365
|
self, to: ChecksumAddress, data: bytes, from_: ChecksumAddress
|
|
@@ -751,8 +755,7 @@ def erc20_balance_slot(
|
|
|
751
755
|
if max_slot < 0:
|
|
752
756
|
raise ValueError(no_slot)
|
|
753
757
|
|
|
754
|
-
|
|
755
|
-
sim = VaultSimulator(web3, vault=zero, alpha=zero, block=block)
|
|
758
|
+
sim = VaultSimulator(web3, block=block)
|
|
756
759
|
for slot in range(max_slot + 1):
|
|
757
760
|
holder = Web3.to_checksum_address(
|
|
758
761
|
"0x" + keccak(encode(["uint256"], [slot]))[-20:].hex()
|
{ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/ccip/quote.py
RENAMED
|
@@ -18,13 +18,11 @@ from web3.types import BlockIdentifier
|
|
|
18
18
|
|
|
19
19
|
from ipor_fusion.core.contract import Call
|
|
20
20
|
from ipor_fusion.core.simulation import VaultSimulator
|
|
21
|
-
from ipor_fusion.types import parse_plasma_vault_address
|
|
22
21
|
|
|
23
22
|
#: Selector of ``CcipInsufficientNativeFeeBalance(uint256 balance, uint256 required)``.
|
|
24
23
|
INSUFFICIENT_NATIVE_FEE_SELECTOR: bytes = keccak(
|
|
25
24
|
text="CcipInsufficientNativeFeeBalance(uint256,uint256)"
|
|
26
25
|
)[:4]
|
|
27
|
-
_NO_VAULT = parse_plasma_vault_address(bytes(20))
|
|
28
26
|
|
|
29
27
|
|
|
30
28
|
def quote_ccip_native_fee(
|
|
@@ -45,7 +43,7 @@ def quote_ccip_native_fee(
|
|
|
45
43
|
valid at ``block`` up to the fee check; a revert before it, or a call that
|
|
46
44
|
sends no message, raises ``ValueError``.
|
|
47
45
|
"""
|
|
48
|
-
simulator = VaultSimulator(web3,
|
|
46
|
+
simulator = VaultSimulator(web3, alpha=from_, block=block)
|
|
49
47
|
simulator.with_state_override(payer, balance=hex(0))
|
|
50
48
|
simulator.add_call(call, from_=from_, label="quote", gas=gas)
|
|
51
49
|
(result,) = simulator.run().calls
|
{ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/simulation.py
RENAMED
|
@@ -25,7 +25,6 @@ Example -- bridge from a source vault and let the dispatcher settle::
|
|
|
25
25
|
from __future__ import annotations
|
|
26
26
|
|
|
27
27
|
from collections.abc import Mapping
|
|
28
|
-
from typing import Any
|
|
29
28
|
|
|
30
29
|
from eth_typing import ChecksumAddress
|
|
31
30
|
from web3 import Web3
|
|
@@ -41,7 +40,7 @@ from ipor_fusion.crosschain.transport import (
|
|
|
41
40
|
CrosschainTransport,
|
|
42
41
|
OutboundMessage,
|
|
43
42
|
)
|
|
44
|
-
from ipor_fusion.types import
|
|
43
|
+
from ipor_fusion.types import ChainId, PlasmaVaultAddress
|
|
45
44
|
|
|
46
45
|
#: What the synthetic token source holds: enough for any test amount.
|
|
47
46
|
SYNTHETIC_BALANCE = 2**96
|
|
@@ -89,10 +88,7 @@ class CrosschainSimulator:
|
|
|
89
88
|
raise ValueError(f"chain {chain_id} is not configured on the transport")
|
|
90
89
|
if chain_id in self._chains:
|
|
91
90
|
raise ValueError(f"chain {chain_id} already added")
|
|
92
|
-
|
|
93
|
-
sim = VaultSimulator(
|
|
94
|
-
web3, vault=vault or zero, alpha=alpha or zero, block=block
|
|
95
|
-
)
|
|
91
|
+
sim = VaultSimulator(web3, vault=vault, alpha=alpha, block=block)
|
|
96
92
|
# A chain without a real token holder to impersonate gets a synthetic
|
|
97
93
|
# one, funded once by a storage override; deliveries transfer from it.
|
|
98
94
|
for token in self._transport.synthetic_credit_tokens(chain_id):
|
{ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/stargate/contracts.py
RENAMED
|
@@ -23,6 +23,7 @@ from ipor_fusion.types import (
|
|
|
23
23
|
ChainId,
|
|
24
24
|
CommandId,
|
|
25
25
|
DeploymentRequestId,
|
|
26
|
+
LayerZeroEid,
|
|
26
27
|
PlasmaVaultAddress,
|
|
27
28
|
PositionSetHash,
|
|
28
29
|
ProposalId,
|
|
@@ -122,10 +123,12 @@ class StargateCrosschainExecutor(CrosschainExecutor):
|
|
|
122
123
|
def proposal_count(self) -> Call[int]:
|
|
123
124
|
return self._view("proposalCount()", output_types=["uint256"])
|
|
124
125
|
|
|
125
|
-
def eid_of(self, chain_id: ChainId) -> Call[
|
|
126
|
-
return self._view(
|
|
126
|
+
def eid_of(self, chain_id: ChainId) -> Call[LayerZeroEid]:
|
|
127
|
+
return self._view(
|
|
128
|
+
"eidOf(uint256)", chain_id, output_types=["uint32"], decoder=LayerZeroEid
|
|
129
|
+
)
|
|
127
130
|
|
|
128
|
-
def chain_id_of(self, eid:
|
|
131
|
+
def chain_id_of(self, eid: LayerZeroEid) -> Call[ChainId]:
|
|
129
132
|
return self._view(
|
|
130
133
|
"chainIdOf(uint32)", eid, output_types=["uint256"], decoder=ChainId
|
|
131
134
|
)
|
|
@@ -252,8 +255,10 @@ class StargateCrosschainDispatcher(CrosschainDispatcher):
|
|
|
252
255
|
def stargate_pool(self) -> Call[ChecksumAddress]:
|
|
253
256
|
return self._view("STARGATE_POOL()", output_types=["address"], decoder=_address)
|
|
254
257
|
|
|
255
|
-
def executor_eid(self) -> Call[
|
|
256
|
-
return self._view(
|
|
258
|
+
def executor_eid(self) -> Call[LayerZeroEid]:
|
|
259
|
+
return self._view(
|
|
260
|
+
"EXECUTOR_EID()", output_types=["uint32"], decoder=LayerZeroEid
|
|
261
|
+
)
|
|
257
262
|
|
|
258
263
|
def observation(self) -> Call[Observation]:
|
|
259
264
|
"""``trackedIdle`` in local decimals plus ``convertToAssets`` of every
|
|
@@ -299,7 +304,7 @@ class StargateTokenMessaging(ContractWrapper):
|
|
|
299
304
|
"""Stargate V2 ``TokenMessaging``, the OApp that carries taxi packets:
|
|
300
305
|
``peers`` tells whether a route to an endpoint id exists."""
|
|
301
306
|
|
|
302
|
-
def peers(self, eid:
|
|
307
|
+
def peers(self, eid: LayerZeroEid) -> Call[bytes]:
|
|
303
308
|
"""The peer OApp on ``eid`` as bytes32; zero when no route exists."""
|
|
304
309
|
return self._view("peers(uint32)", eid, output_types=["bytes32"])
|
|
305
310
|
|
|
@@ -332,10 +337,12 @@ class StargateCrosschainFactory(CrosschainFactory):
|
|
|
332
337
|
decoder=_address,
|
|
333
338
|
)
|
|
334
339
|
|
|
335
|
-
def eid_of(self, chain_id: ChainId) -> Call[
|
|
336
|
-
return self._view(
|
|
340
|
+
def eid_of(self, chain_id: ChainId) -> Call[LayerZeroEid]:
|
|
341
|
+
return self._view(
|
|
342
|
+
"eidOf(uint256)", chain_id, output_types=["uint32"], decoder=LayerZeroEid
|
|
343
|
+
)
|
|
337
344
|
|
|
338
|
-
def chain_id_of(self, eid:
|
|
345
|
+
def chain_id_of(self, eid: LayerZeroEid) -> Call[ChainId]:
|
|
339
346
|
return self._view(
|
|
340
347
|
"chainIdOf(uint32)", eid, output_types=["uint256"], decoder=ChainId
|
|
341
348
|
)
|
{ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/stargate/layerzero.py
RENAMED
|
@@ -30,7 +30,7 @@ from web3 import Web3
|
|
|
30
30
|
from ipor_fusion.core.address import _validate_not_zero_address
|
|
31
31
|
from ipor_fusion.core.contract import _encode_calldata
|
|
32
32
|
from ipor_fusion.crosschain.logs import log_bytes
|
|
33
|
-
from ipor_fusion.types import ZERO_ADDRESS, MessageId, StargateAssetId
|
|
33
|
+
from ipor_fusion.types import ZERO_ADDRESS, LayerZeroEid, MessageId, StargateAssetId
|
|
34
34
|
|
|
35
35
|
_TYPE_3 = b"\x00\x03"
|
|
36
36
|
_EXECUTOR_WORKER_ID = 1
|
|
@@ -129,7 +129,7 @@ class EnforcedOptionParam:
|
|
|
129
129
|
``msg_type`` 1 and must carry a non-zero ``lzReceive`` gas; the compose
|
|
130
130
|
(asset) lane is 2."""
|
|
131
131
|
|
|
132
|
-
eid:
|
|
132
|
+
eid: LayerZeroEid
|
|
133
133
|
msg_type: int
|
|
134
134
|
options: bytes | OptionsBuilder
|
|
135
135
|
|
|
@@ -149,9 +149,9 @@ class Packet:
|
|
|
149
149
|
"""One ``PacketV1Codec`` packet: the payload of a ``PacketSent`` event."""
|
|
150
150
|
|
|
151
151
|
nonce: int
|
|
152
|
-
src_eid:
|
|
152
|
+
src_eid: LayerZeroEid
|
|
153
153
|
sender: ChecksumAddress
|
|
154
|
-
dst_eid:
|
|
154
|
+
dst_eid: LayerZeroEid
|
|
155
155
|
receiver: ChecksumAddress
|
|
156
156
|
guid: MessageId
|
|
157
157
|
message: bytes
|
|
@@ -162,9 +162,9 @@ class Packet:
|
|
|
162
162
|
raise ValueError("not a version-1 LayerZero packet")
|
|
163
163
|
return cls(
|
|
164
164
|
nonce=int.from_bytes(encoded[1:9], "big"),
|
|
165
|
-
src_eid=int.from_bytes(encoded[9:13], "big"),
|
|
165
|
+
src_eid=LayerZeroEid(int.from_bytes(encoded[9:13], "big")),
|
|
166
166
|
sender=bytes32_to_address(encoded[13:45]),
|
|
167
|
-
dst_eid=int.from_bytes(encoded[45:49], "big"),
|
|
167
|
+
dst_eid=LayerZeroEid(int.from_bytes(encoded[45:49], "big")),
|
|
168
168
|
receiver=bytes32_to_address(encoded[49:81]),
|
|
169
169
|
guid=MessageId(encoded[81:113]),
|
|
170
170
|
message=encoded[113:],
|
|
@@ -213,7 +213,7 @@ class TaxiMessage:
|
|
|
213
213
|
|
|
214
214
|
|
|
215
215
|
def encode_oft_compose_msg(
|
|
216
|
-
nonce: int, src_eid:
|
|
216
|
+
*, nonce: int, src_eid: LayerZeroEid, amount_ld: int, compose_msg: bytes
|
|
217
217
|
) -> bytes:
|
|
218
218
|
"""``OFTComposeMsgCodec.encode(nonce, srcEid, amountLD, composeMsg)``: the
|
|
219
219
|
message the endpoint passes to ``lzCompose`` after a Stargate delivery.
|
|
@@ -228,12 +228,12 @@ def encode_oft_compose_msg(
|
|
|
228
228
|
|
|
229
229
|
def lz_receive_calldata(
|
|
230
230
|
*,
|
|
231
|
-
src_eid:
|
|
231
|
+
src_eid: LayerZeroEid,
|
|
232
232
|
sender: ChecksumAddress,
|
|
233
233
|
nonce: int,
|
|
234
234
|
guid: MessageId,
|
|
235
235
|
message: bytes,
|
|
236
|
-
executor: ChecksumAddress = ZERO_ADDRESS,
|
|
236
|
+
executor: ChecksumAddress = ZERO_ADDRESS,
|
|
237
237
|
extra_data: bytes = b"",
|
|
238
238
|
) -> bytes:
|
|
239
239
|
"""``lzReceive(Origin, guid, message, executor, extraData)`` as the endpoint calls it."""
|
|
@@ -252,7 +252,7 @@ def lz_compose_calldata(
|
|
|
252
252
|
from_: ChecksumAddress,
|
|
253
253
|
guid: MessageId,
|
|
254
254
|
message: bytes,
|
|
255
|
-
executor: ChecksumAddress = ZERO_ADDRESS,
|
|
255
|
+
executor: ChecksumAddress = ZERO_ADDRESS,
|
|
256
256
|
extra_data: bytes = b"",
|
|
257
257
|
) -> bytes:
|
|
258
258
|
"""``lzCompose(from, guid, message, executor, extraData)`` as the endpoint calls it."""
|
{ipor_fusion-4.0.0.dev66 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/stargate/transport.py
RENAMED
|
@@ -29,7 +29,7 @@ from ipor_fusion.crosschain.transport import (
|
|
|
29
29
|
OutboundMessage,
|
|
30
30
|
transfer_call,
|
|
31
31
|
)
|
|
32
|
-
from ipor_fusion.types import ChainId, StargateAssetId
|
|
32
|
+
from ipor_fusion.types import ChainId, LayerZeroEid, StargateAssetId
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
@dataclass(frozen=True, slots=True)
|
|
@@ -45,7 +45,7 @@ class StargateChain:
|
|
|
45
45
|
"""
|
|
46
46
|
|
|
47
47
|
chain_id: ChainId
|
|
48
|
-
eid:
|
|
48
|
+
eid: LayerZeroEid
|
|
49
49
|
endpoint: ChecksumAddress
|
|
50
50
|
token_messaging: ChecksumAddress
|
|
51
51
|
stargate_pool: ChecksumAddress
|
|
@@ -87,7 +87,7 @@ class StargateTransport(CrosschainTransport):
|
|
|
87
87
|
|
|
88
88
|
def __init__(self, chains: Iterable[StargateChain]) -> None:
|
|
89
89
|
self._chains: dict[ChainId, StargateChain] = {}
|
|
90
|
-
self._by_eid: dict[
|
|
90
|
+
self._by_eid: dict[LayerZeroEid, StargateChain] = {}
|
|
91
91
|
for chain in chains:
|
|
92
92
|
if chain.chain_id in self._chains:
|
|
93
93
|
raise ValueError(f"duplicate Stargate chain_id {chain.chain_id}")
|
|
@@ -194,7 +194,10 @@ class StargateTransport(CrosschainTransport):
|
|
|
194
194
|
]
|
|
195
195
|
taxi: TaxiMessage = message.raw[1]
|
|
196
196
|
compose = encode_oft_compose_msg(
|
|
197
|
-
packet.nonce,
|
|
197
|
+
nonce=packet.nonce,
|
|
198
|
+
src_eid=packet.src_eid,
|
|
199
|
+
amount_ld=message.token_amount,
|
|
200
|
+
compose_msg=taxi.compose_msg,
|
|
198
201
|
)
|
|
199
202
|
return [
|
|
200
203
|
transfer_call(
|