ipor-fusion 4.0.0.dev68__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.dev68 → ipor_fusion-4.0.0.dev71}/MIGRATION_4.md +9 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/PKG-INFO +1 -1
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/pyproject.toml +1 -1
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/__init__.py +2 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/market_cmd.py +1 -1
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/options.py +2 -2
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/vault_info_view.py +4 -4
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/context.py +16 -17
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/contract.py +3 -3
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/logs.py +13 -3
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/stargate/contracts.py +16 -9
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/stargate/layerzero.py +10 -10
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/stargate/transport.py +7 -4
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/errors.py +3 -3
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/explorer.py +1 -1
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/base.py +5 -1
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/crosschain/ccip.py +4 -4
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/crosschain/stargate.py +4 -3
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/universal.py +5 -1
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/aave_v3.py +2 -4
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/morpho.py +9 -3
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/oracle_mapping_nodes.py +1 -3
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/oracle_mapping_reader.py +2 -2
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/types.py +3 -1
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/vault_info.py +1 -1
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_encoding.py +3 -1
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_web3_context.py +1 -1
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/typed_client/consumer.py +8 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/.claude-plugin/marketplace.json +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/.claude-plugin/plugin.json +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/.env.example +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/.gemini/settings.json +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/.git-blame-ignore-revs +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/.github/workflows/cd.yml +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/.github/workflows/ci.yml +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/.github/workflows/commit-lint.yml +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/.github/workflows/notify-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/.github/workflows/python-build.yml +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/.github/workflows/python-publish.yml +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/.github/workflows/release.yml +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/.github/workflows/report-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/.gitignore +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/.pre-commit-config.yaml +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/.python-version +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/AGENTS.md +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/CHANGELOG.md +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/CLAUDE.md +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/CODEOWNERS +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/LICENSE +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/README.md +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/build.sh +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/examples/CONTRIBUTING.md +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/examples/README.md +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/examples/advanced_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/examples/advanced_euler_v2_looping_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/examples/composed_hypercore_flow_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/examples/external_state_margin_leg_base.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/examples/simple_aave_v3_supply_base.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/pytest.ini +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/scripts/commit-check.sh +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/scripts/crosschain_readiness.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/skills/ipor-deploy-vault/SKILL.md +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/about.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cache.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/chains.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/changelog_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/config_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/config_store.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/main.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/oracle_mapping_view.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/vault_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/vault_health.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/vault_markets_view.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/cli/vault_rendering.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/config/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/config/roles.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/access.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/address.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/erc20.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/external_state_executor.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/fee_manager.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/fuse_action.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/fusion_factory.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/multicall.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/oracle.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/plasma_vault.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/rewards_manager.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/simulation.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/core/withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/ccip/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/ccip/chainlink.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/ccip/codec.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/ccip/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/ccip/events.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/ccip/indexer.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/ccip/lane.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/ccip/quote.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/ccip/transport.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/discovery.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/errors.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/lane.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/logs.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/messages.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/simulation.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/stargate/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/stargate/lane.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/crosschain/transport.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/dependency_graph.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/entry_cli.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/entry_mcp.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/field_docs.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/aave_v3.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/async_action.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/crosschain/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/crosschain/base.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/erc4626.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/euler_v2.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/events.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/external_state.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/external_state_events.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/fluid_instadapp.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/gearbox_v3.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/hypercore_events.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/merkl.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/morpho.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/guide/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/guide/architecture.md +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/guide/glossary.md +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/guide/invariants.md +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/guide/quickstart.md +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/market_ids.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/market_info.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/mcp/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/mcp/guide.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/mcp/models.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/mcp/server.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/morpho_api.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/py.typed +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/aave_v4.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/hypercore_outcome.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/lending_health.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/position_manager.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/unpriceable.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/substrates.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/validation.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/vault_data.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/vault_managers.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/vault_positions.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/vault_reads.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/UniswapV3UniversalRouter.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/_crosschain_recovery.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/_euler_v2.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/_foundry.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/_guide.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/_hypercore_model.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/_hypercore_shadow.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/_simulate.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/_validation.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/addresses.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/conftest.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/constants.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/fixtures/hypercore_hip3_flow.json +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/fixtures/hypercore_market55.json +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/fixtures/vault_info_golden/clean.json +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/fixtures/vault_info_golden/clean.txt +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/fixtures/vault_info_golden/rich.json +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/fixtures/vault_info_golden/rich.txt +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_about.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_access_manager.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_cache.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_chains.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_cli_changelog.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_cli_commands.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_cli_config_store.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_cli_helpers.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_cli_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_cli_lending_health.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_cli_market_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_cli_oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_cli_pending_requests_scan.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_cli_role_accounts.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_cli_vault_info_golden.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_cli_vault_predates_getters.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_cli_vault_validate.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_contract_call.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_contract_encoder.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_ccip_events.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_ccip_indexer.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_ccip_quote.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_chainlink.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_contracts.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_errors.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_lane.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_layering.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_readiness.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_readiness_report.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_crosschain_transport.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_erc20.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_examples_composed_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_examples_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_examples_euler_looping_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_examples_vaults.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_explorer.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_external_state_events.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_external_state_executor.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_fee_manager.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_fuse_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_fusion_instance.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_guide.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_hypercore_deployment.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_hypercore_events.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_hypercore_flow.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_hypercore_live.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_hypercore_outcome.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_hypercore_readers.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_hypercore_simulation.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_logs.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_mcp_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_mcp_models.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_mcp_server.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_mcp_vault_validate.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_oracle.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_plasma_vault.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_reader_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_readiness_selection.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_revert_decoding.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_rewards_manager.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_roles.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_sdk_layering.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_borrow_aave_v3_mainnet.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_claim_merkl_wrapper_base.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_claim_morpho_rewards.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_crosschain_canary.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_crosschain_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_crosschain_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_euler_v2_batch_base.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_euler_v2_swap_deploy_base.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_euler_v2_swap_reconfigure_base.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_euler_v2_swap_registry_base.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_examples_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_examples_base.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_examples_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_external_state_executor_base.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_fusion_factory_clone_base.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_looping_aave_v3_base.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_looping_morpho_blue_base.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_pilot_v3.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_pilot_v4_uniswap.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_pilot_v5_ramses.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_pilot_v5_scheduled.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_plasma_vault_setters_base.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_readers_integration.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_release_funds.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_swap_on_base.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_simulate_vault_from_scratch_base.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_solidity_compiler.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_solidity_mirrors.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_substrates.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_types_and_events.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_unpriceable_tokens.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_validation.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_vault_dep_graph.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_vault_info_onchain_base.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_vault_info_onchain_base_no_withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_vault_simulator_blocks.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/tests/test_withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/uv.lock +0 -0
|
@@ -119,6 +119,15 @@ from_=...)` needs neither, so drop a zero-address placeholder. `execute()` witho
|
|
|
119
119
|
`dataclasses.asdict` form) with every field parsed; use it instead of
|
|
120
120
|
`FusionInstance(**data)`, which passes raw strings into the role-typed fields.
|
|
121
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
|
+
|
|
122
131
|
**Markets and substrates.** Every `IporFusionMarkets` member is a `MarketId`.
|
|
123
132
|
`decode_substrate`, `market_name`, `format_market_label` take `MarketId`.
|
|
124
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
|
|
@@ -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
|
}
|
{ipor_fusion-4.0.0.dev68 → 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.dev68 → 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.dev68 → 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(
|
|
@@ -9,7 +9,7 @@ from eth_abi.exceptions import InsufficientDataBytes
|
|
|
9
9
|
from eth_typing import ChecksumAddress
|
|
10
10
|
from eth_utils import function_signature_to_4byte_selector
|
|
11
11
|
from web3 import Web3
|
|
12
|
-
from web3.types import TxReceipt
|
|
12
|
+
from web3.types import TxParams, TxReceipt
|
|
13
13
|
|
|
14
14
|
from ipor_fusion.types import TxHash
|
|
15
15
|
|
|
@@ -119,7 +119,7 @@ def get_revert_reason(web3: Web3, tx_hash: TxHash, receipt: TxReceipt) -> str |
|
|
|
119
119
|
"""Replay a failed tx as eth_call to capture revert data."""
|
|
120
120
|
try:
|
|
121
121
|
tx = web3.eth.get_transaction(tx_hash)
|
|
122
|
-
call_params = {
|
|
122
|
+
call_params: TxParams = {
|
|
123
123
|
"from": tx["from"],
|
|
124
124
|
"to": tx["to"],
|
|
125
125
|
"data": tx["input"],
|
|
@@ -129,7 +129,7 @@ def get_revert_reason(web3: Web3, tx_hash: TxHash, receipt: TxReceipt) -> str |
|
|
|
129
129
|
call_params["gas"] = tx["gas"]
|
|
130
130
|
|
|
131
131
|
block_number = receipt["blockNumber"]
|
|
132
|
-
web3.eth.call(call_params, block_identifier=block_number)
|
|
132
|
+
web3.eth.call(call_params, block_identifier=block_number)
|
|
133
133
|
return None # replay succeeded — can't determine reason
|
|
134
134
|
except Exception as exc:
|
|
135
135
|
exc_data = getattr(exc, "data", None)
|
|
@@ -141,7 +141,7 @@ def _fetch_getsourcecode(
|
|
|
141
141
|
with urlopen(url, timeout=10) as resp: # noqa: S310
|
|
142
142
|
data = json.loads(resp.read().decode())
|
|
143
143
|
if data.get("status") == "1" and data.get("result"):
|
|
144
|
-
return data["result"][0]
|
|
144
|
+
return data["result"][0]
|
|
145
145
|
if "rate limit" in str(data.get("result", "")).lower():
|
|
146
146
|
time.sleep(_RETRY_DELAY * (attempt + 1))
|
|
147
147
|
continue
|
|
@@ -42,7 +42,11 @@ class Fuse(ABC): # noqa: B024 # ABC marks intent; no shared abstract method
|
|
|
42
42
|
raise ValueError(f"{name} must not be negative, got {value}")
|
|
43
43
|
|
|
44
44
|
def __eq__(self, other: object) -> bool:
|
|
45
|
-
return
|
|
45
|
+
return (
|
|
46
|
+
isinstance(other, Fuse)
|
|
47
|
+
and type(self) is type(other)
|
|
48
|
+
and self._address == other._address
|
|
49
|
+
)
|
|
46
50
|
|
|
47
51
|
def __hash__(self) -> int:
|
|
48
52
|
return hash((type(self), self._address))
|
{ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/crosschain/ccip.py
RENAMED
|
@@ -42,7 +42,7 @@ class CcipSendParams(SendParams):
|
|
|
42
42
|
|
|
43
43
|
max_fee: int
|
|
44
44
|
gas_limit: int
|
|
45
|
-
fee_token: ChecksumAddress = ZERO_ADDRESS
|
|
45
|
+
fee_token: ChecksumAddress = ZERO_ADDRESS
|
|
46
46
|
|
|
47
47
|
@classmethod
|
|
48
48
|
def from_route(cls, route: CcipRouteConfig, *, token: bool) -> CcipSendParams:
|
|
@@ -148,8 +148,8 @@ class CcipCommandType(IntEnum):
|
|
|
148
148
|
|
|
149
149
|
_EMPTY_ROUTE = CcipRouteConfig(
|
|
150
150
|
chain_selector=0,
|
|
151
|
-
peer=ZERO_ADDRESS,
|
|
152
|
-
fee_token=ZERO_ADDRESS,
|
|
151
|
+
peer=ZERO_ADDRESS,
|
|
152
|
+
fee_token=ZERO_ADDRESS,
|
|
153
153
|
message_gas_limit=0,
|
|
154
154
|
token_gas_limit=0,
|
|
155
155
|
max_fee=0,
|
|
@@ -255,7 +255,7 @@ class CcipCrosschainCommandFuse(CrosschainCommandFuse):
|
|
|
255
255
|
command: Command = EMPTY_COMMAND,
|
|
256
256
|
max_fee: int = 0,
|
|
257
257
|
gas_limit: int = 0,
|
|
258
|
-
fee_token: ChecksumAddress = ZERO_ADDRESS,
|
|
258
|
+
fee_token: ChecksumAddress = ZERO_ADDRESS,
|
|
259
259
|
) -> FuseAction:
|
|
260
260
|
"""Forward one operation to the executor (or its factory):
|
|
261
261
|
|
{ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/fuses/crosschain/stargate.py
RENAMED
|
@@ -33,9 +33,10 @@ from ipor_fusion.fuses.crosschain.base import (
|
|
|
33
33
|
CrosschainSupplyFuse,
|
|
34
34
|
SendParams,
|
|
35
35
|
)
|
|
36
|
-
from ipor_fusion.types import Amount, ChainId, DeploymentRequestId
|
|
36
|
+
from ipor_fusion.types import Amount, ChainId, DeploymentRequestId, LayerZeroEid
|
|
37
37
|
|
|
38
38
|
_NO_CHAIN = ChainId(0)
|
|
39
|
+
_NO_EID = LayerZeroEid(0)
|
|
39
40
|
_NO_REQUEST = DeploymentRequestId(0)
|
|
40
41
|
_ZERO_AMOUNT = Amount(0)
|
|
41
42
|
|
|
@@ -172,7 +173,7 @@ class StargateCrosschainCommandFuse(CrosschainCommandFuse):
|
|
|
172
173
|
*,
|
|
173
174
|
executor: ChecksumAddress,
|
|
174
175
|
chain_id: ChainId = _NO_CHAIN,
|
|
175
|
-
eid:
|
|
176
|
+
eid: LayerZeroEid = _NO_EID,
|
|
176
177
|
enforced_options: bytes = b"",
|
|
177
178
|
plasma_vaults: Sequence[ChecksumAddress] = (),
|
|
178
179
|
request_id: DeploymentRequestId = _NO_REQUEST,
|
|
@@ -264,7 +265,7 @@ class StargateCrosschainCommandFuse(CrosschainCommandFuse):
|
|
|
264
265
|
self,
|
|
265
266
|
command_type: StargateCrosschainCommandType,
|
|
266
267
|
chain_id: ChainId,
|
|
267
|
-
eid:
|
|
268
|
+
eid: LayerZeroEid,
|
|
268
269
|
request_id: DeploymentRequestId,
|
|
269
270
|
command: Command,
|
|
270
271
|
) -> None:
|
|
@@ -65,7 +65,11 @@ class UniversalTokenSwapperFuse(Fuse):
|
|
|
65
65
|
self._abi = abi
|
|
66
66
|
|
|
67
67
|
def __eq__(self, other: object) -> bool:
|
|
68
|
-
return
|
|
68
|
+
return (
|
|
69
|
+
isinstance(other, UniversalTokenSwapperFuse)
|
|
70
|
+
and super().__eq__(other)
|
|
71
|
+
and self._abi is other._abi
|
|
72
|
+
)
|
|
69
73
|
|
|
70
74
|
def __hash__(self) -> int:
|
|
71
75
|
return hash((type(self), self._address, self._abi))
|
|
@@ -6,9 +6,7 @@ from web3 import Web3
|
|
|
6
6
|
from ipor_fusion.core.contract import Call, ContractWrapper
|
|
7
7
|
from ipor_fusion.core.erc20 import ERC20
|
|
8
8
|
from ipor_fusion.core.multicall import Multicall3
|
|
9
|
-
from ipor_fusion.types import Amount
|
|
10
|
-
|
|
11
|
-
_ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"
|
|
9
|
+
from ipor_fusion.types import ZERO_ADDRESS, Amount
|
|
12
10
|
|
|
13
11
|
# DataTypes.ReserveDataLegacy returned by Pool.getReserveData(address).
|
|
14
12
|
# All fields are static, so the struct is encoded inline as a flat sequence.
|
|
@@ -163,7 +161,7 @@ class AaveV3Reader(ContractWrapper):
|
|
|
163
161
|
tokens.variable_debt_token,
|
|
164
162
|
tokens.stable_debt_token,
|
|
165
163
|
)
|
|
166
|
-
listed = [token for token in reserve_tokens if token.lower() !=
|
|
164
|
+
listed = [token for token in reserve_tokens if token.lower() != ZERO_ADDRESS]
|
|
167
165
|
balances = iter(
|
|
168
166
|
Multicall3(self._ctx).aggregate(
|
|
169
167
|
[ERC20(self._ctx, token).balance_of(user) for token in listed]
|
|
@@ -13,12 +13,18 @@ from ipor_fusion.core.context import Web3Context
|
|
|
13
13
|
from ipor_fusion.core.contract import Call, ContractWrapper
|
|
14
14
|
from ipor_fusion.core.multicall import Multicall3
|
|
15
15
|
from ipor_fusion.errors import MorphoMarketNotFoundError, UnsupportedChainError
|
|
16
|
-
from ipor_fusion.types import
|
|
16
|
+
from ipor_fusion.types import (
|
|
17
|
+
ZERO_ADDRESS,
|
|
18
|
+
Amount,
|
|
19
|
+
ChainId,
|
|
20
|
+
Fee,
|
|
21
|
+
MorphoBlueMarketId,
|
|
22
|
+
Shares,
|
|
23
|
+
)
|
|
17
24
|
|
|
18
25
|
WAD = 10**18
|
|
19
26
|
SECONDS_PER_YEAR = 365 * 24 * 60 * 60 # matches Morpho IRM YEAR constant
|
|
20
27
|
|
|
21
|
-
_ZERO_ADDRESS = Web3.to_checksum_address("0x" + "00" * 20)
|
|
22
28
|
_addr = Web3.to_checksum_address
|
|
23
29
|
|
|
24
30
|
# Morpho Blue sits at its CREATE2 address (0xBBBB…EEFFCb) on Ethereum and Base
|
|
@@ -257,7 +263,7 @@ class MorphoReader(ContractWrapper):
|
|
|
257
263
|
Use this when the caller has already read `market()` and `market_params()`
|
|
258
264
|
to avoid two redundant RPC roundtrips.
|
|
259
265
|
"""
|
|
260
|
-
if params.irm ==
|
|
266
|
+
if params.irm == ZERO_ADDRESS:
|
|
261
267
|
# Morpho skips the IRM when irm == address(0) (MetaMorpho "idle"
|
|
262
268
|
# markets): no interest accrues, so every rate is zero.
|
|
263
269
|
rate_wad = 0
|
{ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/oracle_mapping_nodes.py
RENAMED
|
@@ -14,6 +14,7 @@ from eth_typing import ChecksumAddress
|
|
|
14
14
|
|
|
15
15
|
from ipor_fusion.readers.oracle_mapping_reader import OracleMappingReader
|
|
16
16
|
from ipor_fusion.types import (
|
|
17
|
+
ZERO_ADDRESS,
|
|
17
18
|
AssetSource,
|
|
18
19
|
MappingStatus,
|
|
19
20
|
NodeStatus,
|
|
@@ -21,9 +22,6 @@ from ipor_fusion.types import (
|
|
|
21
22
|
Price,
|
|
22
23
|
)
|
|
23
24
|
|
|
24
|
-
ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"
|
|
25
|
-
|
|
26
|
-
|
|
27
25
|
# source_type values (also the human label in the path / output). Adding a
|
|
28
26
|
# type? Follow the "Adding a feed type" checklist in readers/oracle_mapping.py.
|
|
29
27
|
TYPE_CHAINLINK = "ChainlinkAggregator"
|
{ipor_fusion-4.0.0.dev68 → ipor_fusion-4.0.0.dev71}/src/ipor_fusion/readers/oracle_mapping_reader.py
RENAMED
|
@@ -33,8 +33,8 @@ ASSET_PRICE_SOURCE_UPDATED_TOPIC = (
|
|
|
33
33
|
)
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
def _addr(value:
|
|
37
|
-
return Web3.to_checksum_address(value)
|
|
36
|
+
def _addr(value: str) -> ChecksumAddress:
|
|
37
|
+
return Web3.to_checksum_address(value)
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
class _Erc4626Feed(ContractWrapper):
|