ipor-fusion 4.0.0.dev108__tar.gz → 4.0.0.dev114__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.dev108 → ipor_fusion-4.0.0.dev114}/AGENTS.md +1 -1
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/MIGRATION_4.md +22 -3
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/PKG-INFO +1 -1
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/pyproject.toml +1 -1
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/cli/vault_info_view.py +6 -8
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/cli/vault_markets_view.py +19 -26
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/core/plasma_vault.py +11 -10
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/validation.py +17 -8
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/vault_data.py +34 -24
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/vault_info.py +9 -7
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/vault_managers.py +18 -18
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/fixtures/vault_info_golden/clean.txt +1 -1
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_cache.py +46 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_cli_commands.py +6 -18
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_cli_helpers.py +28 -52
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_cli_vault_info_golden.py +58 -17
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_cli_vault_predates_getters.py +3 -1
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/.claude-plugin/marketplace.json +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/.claude-plugin/plugin.json +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/.env.example +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/.gemini/settings.json +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/.git-blame-ignore-revs +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/.github/workflows/cd.yml +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/.github/workflows/ci.yml +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/.github/workflows/commit-lint.yml +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/.github/workflows/notify-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/.github/workflows/python-build.yml +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/.github/workflows/python-publish.yml +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/.github/workflows/release.yml +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/.github/workflows/report-slack.yml +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/.gitignore +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/.mcp.json +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/.pre-commit-config.yaml +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/.python-version +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/CHANGELOG.md +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/CLAUDE.md +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/CODEOWNERS +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/LICENSE +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/README.md +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/build.sh +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/examples/CONTRIBUTING.md +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/examples/README.md +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/examples/advanced_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/examples/advanced_euler_v2_looping_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/examples/composed_hypercore_flow_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/examples/external_state_margin_leg_base.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/examples/simple_aave_v3_supply_base.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/pytest.ini +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/scripts/commit-check.sh +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/scripts/crosschain_readiness.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/skills/ipor-deploy-vault/SKILL.md +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/about.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/cache.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/chains.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/cli/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/cli/changelog_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/cli/config_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/cli/config_store.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/cli/main.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/cli/market_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/cli/options.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/cli/oracle_mapping_view.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/cli/vault_cmd.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/cli/vault_health.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/cli/vault_rendering.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/config/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/config/roles.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/core/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/core/access.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/core/address.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/core/context.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/core/contract.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/core/erc20.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/core/external_state_executor.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/core/fee_manager.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/core/fuse.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/core/fuse_action.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/core/fusion_factory.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/core/logs.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/core/multicall.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/core/oracle.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/core/rewards_manager.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/core/simulation.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/core/withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/ccip/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/ccip/chainlink.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/ccip/codec.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/ccip/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/ccip/events.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/ccip/indexer.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/ccip/lane.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/ccip/quote.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/ccip/transport.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/discovery.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/errors.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/fuses/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/fuses/base.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/fuses/ccip.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/fuses/stargate.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/lane.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/logs.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/messages.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/simulation.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/stargate/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/stargate/contracts.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/stargate/lane.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/stargate/layerzero.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/stargate/transport.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/crosschain/transport.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/dependency_graph.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/entry_cli.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/entry_mcp.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/errors.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/explorer.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/field_docs.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/fuses/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/fuses/aave_v3.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/fuses/async_action.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/fuses/base.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/fuses/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/fuses/erc4626.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/fuses/euler_v2.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/fuses/events.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/fuses/external_state.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/fuses/external_state_events.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/fuses/fluid_instadapp.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/fuses/gearbox_v3.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/fuses/hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/fuses/hypercore_events.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/fuses/merkl.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/fuses/morpho.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/fuses/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/fuses/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/fuses/universal.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/guide/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/guide/architecture.md +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/guide/glossary.md +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/guide/invariants.md +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/guide/quickstart.md +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/market_ids.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/market_info.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/mcp/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/mcp/guide.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/mcp/models.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/mcp/server.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/morpho_api.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/py.typed +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/readers/__init__.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/readers/aave_v3.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/readers/aave_v4.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/readers/compound_v3.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/readers/hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/readers/hypercore_outcome.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/readers/lending_health.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/readers/morpho.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/readers/oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/readers/oracle_mapping_nodes.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/readers/oracle_mapping_reader.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/readers/position_manager.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/readers/ramses_v2.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/readers/uniswap_v3.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/readers/unpriceable.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/substrates.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/types.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/vault_erc20.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/vault_positions.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/vault_reads.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/UniswapV3UniversalRouter.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/_crosschain_recovery.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/_euler_v2.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/_foundry.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/_guide.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/_hypercore_model.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/_hypercore_shadow.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/_simulate.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/_validation.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/addresses.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/conftest.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/constants.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/fixtures/hypercore_hip3_flow.json +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/fixtures/hypercore_market55.json +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/fixtures/vault_info_golden/clean.json +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/fixtures/vault_info_golden/rich.json +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/fixtures/vault_info_golden/rich.txt +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_about.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_access_manager.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_chains.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_cli_changelog.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_cli_config_store.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_cli_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_cli_lending_health.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_cli_market_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_cli_oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_cli_pending_requests_scan.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_cli_role_accounts.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_cli_vault_validate.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_contract_call.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_contract_encoder.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_crosschain_ccip_events.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_crosschain_ccip_indexer.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_crosschain_ccip_quote.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_crosschain_chainlink.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_crosschain_contracts.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_crosschain_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_crosschain_errors.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_crosschain_lane.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_crosschain_layering.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_crosschain_readiness.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_crosschain_readiness_report.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_crosschain_transport.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_erc20.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_error_hierarchy.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_examples_composed_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_examples_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_examples_euler_looping_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_examples_vaults.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_explorer.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_external_state_events.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_external_state_executor.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_fee_manager.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_fuse_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_fusion_instance.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_guide.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_hypercore_deployment.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_hypercore_events.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_hypercore_flow.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_hypercore_live.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_hypercore_outcome.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_hypercore_readers.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_hypercore_simulation.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_logs.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_mcp_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_mcp_models.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_mcp_server.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_mcp_vault_validate.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_multicall.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_oracle.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_oracle_mapping.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_plasma_vault.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_public_api.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_reader_encoding.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_readiness_selection.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_revert_decoding.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_rewards_manager.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_roles.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_sdk_layering.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_borrow_aave_v3_mainnet.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_claim_merkl_wrapper_base.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_claim_morpho_rewards.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_crosschain_canary.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_crosschain_hypercore.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_crosschain_hyperevm.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_crosschain_lifecycle.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_euler_v2_batch_base.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_euler_v2_credit_market_base.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_euler_v2_swap_deploy_base.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_euler_v2_swap_reconfigure_base.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_euler_v2_swap_registry_base.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_examples_arbitrum.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_examples_base.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_examples_crosschain.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_external_state_executor_base.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_fusion_factory_clone_base.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_looping_aave_v3_base.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_looping_morpho_blue_base.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_morpho_blue.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_pilot_v3.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_pilot_v4_uniswap.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_pilot_v5_ramses.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_pilot_v5_scheduled.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_plasma_vault_setters_base.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_readers_integration.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_release_funds.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_swap_on_base.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_simulate_vault_from_scratch_base.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_solidity_compiler.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_solidity_mirrors.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_substrates.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_types_and_events.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_unpriceable_tokens.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_validation.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_vault_dep_graph.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_vault_info_onchain_base.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_vault_info_onchain_base_no_withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_vault_simulator_blocks.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_web3_context.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/test_withdraw_manager.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/typed_client/consumer.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/tests/typed_client/rejected.py +0 -0
- {ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/uv.lock +0 -0
|
@@ -158,7 +158,7 @@ the lifecycle matrix follows that.
|
|
|
158
158
|
subpackage (`core`, `config`, `fuses`, `readers`, `crosschain`,
|
|
159
159
|
`crosschain.fuses`, `crosschain.ccip`, `crosschain.stargate`) also goes in that
|
|
160
160
|
subpackage's `__all__`. `ipor_fusion.guide` keeps its own namespace. The
|
|
161
|
-
public modules (`about`, `chains`, `dependency_graph`, `errors`, `explorer`,
|
|
161
|
+
public modules (`about`, `cache`, `chains`, `dependency_graph`, `errors`, `explorer`,
|
|
162
162
|
`field_docs`, `market_ids`, `market_info`, `morpho_api`, `substrates`, `types`,
|
|
163
163
|
`validation`, `vault_data`, `vault_info`) stay importable for the names they
|
|
164
164
|
define; `cli`, `mcp` and every other module are internal. Examples, the guide
|
|
@@ -84,6 +84,20 @@ chain is always the context's:
|
|
|
84
84
|
the context's default block and `Web3Context.get_block(block=None)` returns it,
|
|
85
85
|
both instead of ``"latest"``.
|
|
86
86
|
|
|
87
|
+
Snapshot fields carry their units: `VaultData.total_assets`,
|
|
88
|
+
`underlying_balance_on_vault` and `market_balances` values are `Amount`;
|
|
89
|
+
`total_supply` and `supply_cap` are `Shares`; `share_decimals` / `asset_decimals` are `Decimals`;
|
|
90
|
+
`block_timestamp` and `deployment_timestamp` are `Timestamp`. `FeeData` fee fields
|
|
91
|
+
are `Fee`, `management_fee_last_update` a `Timestamp`, `unrealized_management_fee` an
|
|
92
|
+
`Amount`; `WithdrawManagerData.withdraw_window` is a `Period`, its fees `Fee`,
|
|
93
|
+
`shares_to_release` `Shares`, `last_release_funds_timestamp` a `Timestamp` and the
|
|
94
|
+
converted amounts `Amount`. A custom `VaultState` annotates the same.
|
|
95
|
+
`PlasmaVault.total_supply()`, `balance_of()` and `get_total_supply_cap()` return
|
|
96
|
+
`Shares` (vault shares), and `transfer` / `approve` / `transfer_from` /
|
|
97
|
+
`set_total_supply_cap` take `Shares`; `ERC20` keeps `Amount`. The supply cap is
|
|
98
|
+
now shown in share decimals labelled `shares` (``fusion vault info``) and its JSON
|
|
99
|
+
``formatted`` uses `share_decimals`; it was formatted with the asset's decimals.
|
|
100
|
+
|
|
87
101
|
`ensure_supported_chain` takes `ChainId`. `fetch_unpriceable_priced_tokens` takes the oracle and
|
|
88
102
|
underlying as `ChecksumAddress`. `resolve_token_symbol`, `resolve_token_decimals`,
|
|
89
103
|
`get_contract_name` and `get_deployment_tx` take `HexAddress` (a checksum address
|
|
@@ -351,8 +365,12 @@ Contract names, token symbols and decimals and deployment blocks are cached in a
|
|
|
351
365
|
(`fetch_vault_data(metadata=True)`) and `fetch_deployment_info` use `ctx.cache`.
|
|
352
366
|
`get_contract_name(chain_id, address, api_key=None, *, cache=None)` takes the cache
|
|
353
367
|
explicitly (default: the file cache); pass `cache=ctx.cache` to share the
|
|
354
|
-
context's policy.
|
|
355
|
-
|
|
368
|
+
context's policy. The CLI's text and JSON output name contracts through the
|
|
369
|
+
context's cache.
|
|
370
|
+
- `build_vault_info_json(data)` without `resolve_name` names no contract (every
|
|
371
|
+
`contract` is `"?"`) instead of reading names from the on-disk cache; pass
|
|
372
|
+
`resolve_name=partial(get_contract_name, chain_id, api_key=..., cache=ctx.cache)`
|
|
373
|
+
for the CLI's document.
|
|
356
374
|
- `ipor_fusion.cache` is a public module now and exports `ContractCache`,
|
|
357
375
|
`FileContractCache`, `NullCache`, `CacheKey`, `CacheField`, `cache_key` and
|
|
358
376
|
`default_contract_cache` (also from `ipor_fusion`). Its 3.x functions and constants
|
|
@@ -384,7 +402,8 @@ Etherscan key) and the old file can be deleted.
|
|
|
384
402
|
- A cache never fails a read: a corrupt or unreadable file reads as empty (logged
|
|
385
403
|
warning from `ipor_fusion.cache`) and is rewritten by the next write; an unwritable
|
|
386
404
|
directory (read-only file system) keeps the entries in memory for the process; a
|
|
387
|
-
custom cache that raises is treated as a miss
|
|
405
|
+
custom cache that raises is treated as a miss, and so is a stored number that does
|
|
406
|
+
not parse.
|
|
388
407
|
- `fetch_deployment_info` returns `rpc-fetch-failed` only when the creation
|
|
389
408
|
transaction or its block cannot be read; a cache failure is no longer reported as
|
|
390
409
|
one (the deployment block is returned).
|
{ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/cli/vault_info_view.py
RENAMED
|
@@ -85,13 +85,11 @@ def _print_vault_info(
|
|
|
85
85
|
data.deployment_error,
|
|
86
86
|
) = fetch_deployment_info(ctx, data.vault, api_key=api_key)
|
|
87
87
|
|
|
88
|
+
resolve_name = partial(
|
|
89
|
+
get_contract_name, chain_id, api_key=api_key, cache=ctx.cache
|
|
90
|
+
)
|
|
88
91
|
if json_output:
|
|
89
|
-
result = build_vault_info_json(
|
|
90
|
-
data,
|
|
91
|
-
resolve_name=partial(
|
|
92
|
-
get_contract_name, chain_id, api_key=api_key, cache=ctx.cache
|
|
93
|
-
),
|
|
94
|
-
)
|
|
92
|
+
result = build_vault_info_json(data, resolve_name=resolve_name)
|
|
95
93
|
click.echo(json.dumps(result, indent=2))
|
|
96
94
|
return
|
|
97
95
|
|
|
@@ -105,7 +103,7 @@ def _print_vault_info(
|
|
|
105
103
|
|
|
106
104
|
_print_role_accounts(_role_accounts_json(data))
|
|
107
105
|
|
|
108
|
-
_print_markets(data,
|
|
106
|
+
_print_markets(data, resolve_name)
|
|
109
107
|
|
|
110
108
|
validation = validate_vault_state(data)
|
|
111
109
|
click.echo("ERC20 Balances (vault holdings):")
|
|
@@ -187,7 +185,7 @@ def _print_supply(data: VaultData) -> None:
|
|
|
187
185
|
else:
|
|
188
186
|
click.echo(
|
|
189
187
|
f"Supply Cap: "
|
|
190
|
-
f"{_format_amount(data.supply_cap, data.
|
|
188
|
+
f"{_format_amount(data.supply_cap, data.share_decimals)} shares"
|
|
191
189
|
)
|
|
192
190
|
|
|
193
191
|
|
{ipor_fusion-4.0.0.dev108 → ipor_fusion-4.0.0.dev114}/src/ipor_fusion/cli/vault_markets_view.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from collections.abc import Sequence
|
|
3
|
+
from collections.abc import Callable, Sequence
|
|
4
4
|
from concurrent.futures import Future, ThreadPoolExecutor
|
|
5
5
|
from typing import Any
|
|
6
6
|
|
|
@@ -13,12 +13,11 @@ from ipor_fusion.cli.vault_rendering import (
|
|
|
13
13
|
_print_table,
|
|
14
14
|
_substrate_details,
|
|
15
15
|
)
|
|
16
|
-
from ipor_fusion.explorer import get_contract_name
|
|
17
16
|
from ipor_fusion.substrates import (
|
|
18
17
|
decode_substrate,
|
|
19
18
|
format_market_label,
|
|
20
19
|
)
|
|
21
|
-
from ipor_fusion.types import
|
|
20
|
+
from ipor_fusion.types import FuseAddress, MarketId, parse_hex_address
|
|
22
21
|
from ipor_fusion.vault_data import (
|
|
23
22
|
GET_MARKET_SUBSTRATES,
|
|
24
23
|
VaultData,
|
|
@@ -27,6 +26,10 @@ from ipor_fusion.vault_info import (
|
|
|
27
26
|
_CAPABILITY_BALANCE_FUSES,
|
|
28
27
|
)
|
|
29
28
|
|
|
29
|
+
# Address to contract name, "" when unknown (`get_contract_name` bound to the
|
|
30
|
+
# chain, API key and the context's cache).
|
|
31
|
+
NameResolver = Callable[[HexAddress], str]
|
|
32
|
+
|
|
30
33
|
|
|
31
34
|
def _print_lending_health(data: VaultData) -> None: # noqa: C901
|
|
32
35
|
lh = data.lending_health
|
|
@@ -154,16 +157,14 @@ def _print_health_lines(market: Any, indent: str) -> None:
|
|
|
154
157
|
click.secho(f"{indent}Status: {status}", fg=color, bold=bold)
|
|
155
158
|
|
|
156
159
|
|
|
157
|
-
def _print_markets(data: VaultData,
|
|
160
|
+
def _print_markets(data: VaultData, resolve_name: NameResolver) -> None:
|
|
158
161
|
"""Fuses, balance fuses, dependency graph and substrates."""
|
|
159
|
-
chain_id = data.chain_id
|
|
160
162
|
_print_fuse_section(
|
|
161
163
|
"Fuses",
|
|
162
164
|
data.fuses,
|
|
163
165
|
data.fuse_markets,
|
|
164
166
|
data.market_substrates,
|
|
165
|
-
|
|
166
|
-
api_key,
|
|
167
|
+
resolve_name,
|
|
167
168
|
)
|
|
168
169
|
click.echo()
|
|
169
170
|
|
|
@@ -172,18 +173,17 @@ def _print_markets(data: VaultData, api_key: str | None) -> None:
|
|
|
172
173
|
data.instant_fuses,
|
|
173
174
|
data.fuse_markets,
|
|
174
175
|
data.market_substrates,
|
|
175
|
-
|
|
176
|
-
api_key,
|
|
176
|
+
resolve_name,
|
|
177
177
|
)
|
|
178
178
|
click.echo()
|
|
179
179
|
|
|
180
|
-
_print_balance_fuses_table(data,
|
|
180
|
+
_print_balance_fuses_table(data, resolve_name)
|
|
181
181
|
click.echo()
|
|
182
182
|
|
|
183
183
|
_print_dependency_graph(data)
|
|
184
184
|
|
|
185
185
|
click.echo("Substrates per Market:")
|
|
186
|
-
_print_market_substrates(data,
|
|
186
|
+
_print_market_substrates(data, resolve_name)
|
|
187
187
|
click.echo()
|
|
188
188
|
|
|
189
189
|
|
|
@@ -235,8 +235,7 @@ def _print_fuse_section(
|
|
|
235
235
|
fuses: Sequence[FuseAddress],
|
|
236
236
|
fuse_markets: dict[FuseAddress, MarketId] | None,
|
|
237
237
|
market_substrates: dict[MarketId, list[bytes]] | None,
|
|
238
|
-
|
|
239
|
-
api_key: str | None,
|
|
238
|
+
resolve_name: NameResolver,
|
|
240
239
|
) -> None:
|
|
241
240
|
"""Render a fuse section (regular or instant-withdrawal) with a unified
|
|
242
241
|
layout.
|
|
@@ -262,10 +261,7 @@ def _print_fuse_section(
|
|
|
262
261
|
return
|
|
263
262
|
|
|
264
263
|
with ThreadPoolExecutor() as pool:
|
|
265
|
-
name_futs = {
|
|
266
|
-
addr: pool.submit(get_contract_name, chain_id, addr, api_key)
|
|
267
|
-
for addr in counts
|
|
268
|
-
}
|
|
264
|
+
name_futs = {addr: pool.submit(resolve_name, addr) for addr in counts}
|
|
269
265
|
rows: list[tuple[str, ...]] = []
|
|
270
266
|
for idx, addr in enumerate(counts, 1):
|
|
271
267
|
market_label = "?"
|
|
@@ -285,7 +281,7 @@ def _print_fuse_section(
|
|
|
285
281
|
_print_table(("#", "Address", "Contract", "Market", "Substrates"), rows)
|
|
286
282
|
|
|
287
283
|
|
|
288
|
-
def _print_balance_fuses_table(data: VaultData,
|
|
284
|
+
def _print_balance_fuses_table(data: VaultData, resolve_name: NameResolver) -> None:
|
|
289
285
|
balance_fuses = data.balance_fuses
|
|
290
286
|
decimals = data.asset_decimals
|
|
291
287
|
asset_symbol = data.asset_symbol
|
|
@@ -294,9 +290,7 @@ def _print_balance_fuses_table(data: VaultData, api_key: str | None) -> None:
|
|
|
294
290
|
futures: list[tuple[int, MarketId, str, Future]] = []
|
|
295
291
|
for idx, balance_fuse in enumerate(balance_fuses, 1):
|
|
296
292
|
market_id_str = format_market_label(balance_fuse.market_id)
|
|
297
|
-
f_contract = pool.submit(
|
|
298
|
-
get_contract_name, data.chain_id, balance_fuse.fuse, api_key
|
|
299
|
-
)
|
|
293
|
+
f_contract = pool.submit(resolve_name, balance_fuse.fuse)
|
|
300
294
|
futures.append((idx, balance_fuse.market_id, market_id_str, f_contract))
|
|
301
295
|
|
|
302
296
|
venue_rows: list[tuple[str, ...]] = []
|
|
@@ -328,18 +322,18 @@ def _print_balance_fuses_table(data: VaultData, api_key: str | None) -> None:
|
|
|
328
322
|
_print_table(header, [(str(i), *row) for i, row in enumerate(zero_rows, 1)])
|
|
329
323
|
|
|
330
324
|
|
|
331
|
-
def _print_market_substrates(data: VaultData,
|
|
325
|
+
def _print_market_substrates(data: VaultData, resolve_name: NameResolver) -> set[str]:
|
|
332
326
|
if GET_MARKET_SUBSTRATES in data.unimplemented_getters:
|
|
333
327
|
click.secho(
|
|
334
328
|
f" (unavailable: the vault predates {GET_MARKET_SUBSTRATES})",
|
|
335
329
|
fg="yellow",
|
|
336
330
|
)
|
|
337
331
|
return set()
|
|
338
|
-
return _print_substrates(data,
|
|
332
|
+
return _print_substrates(data, resolve_name)
|
|
339
333
|
|
|
340
334
|
|
|
341
335
|
def _print_substrates( # noqa: C901
|
|
342
|
-
data: VaultData,
|
|
336
|
+
data: VaultData, resolve_name: NameResolver
|
|
343
337
|
) -> set[str]:
|
|
344
338
|
substrates_by_market = data.market_substrates or {}
|
|
345
339
|
balance_fuses = data.balance_fuses
|
|
@@ -364,8 +358,7 @@ def _print_substrates( # noqa: C901
|
|
|
364
358
|
resolved_symbols = data.token_symbols
|
|
365
359
|
with ThreadPoolExecutor() as pool:
|
|
366
360
|
contract_futs = {
|
|
367
|
-
addr: pool.submit(
|
|
368
|
-
for addr in all_addresses
|
|
361
|
+
addr: pool.submit(resolve_name, addr) for addr in all_addresses
|
|
369
362
|
}
|
|
370
363
|
resolved_contracts = {addr: fut.result() for addr, fut in contract_futs.items()}
|
|
371
364
|
|
|
@@ -191,7 +191,7 @@ class PlasmaVault(ContractWrapper):
|
|
|
191
191
|
`addFuses` steps must be reverted before the vault is usable."""
|
|
192
192
|
return self._write("removeFuses(address[])", fuses)
|
|
193
193
|
|
|
194
|
-
def set_total_supply_cap(self, cap:
|
|
194
|
+
def set_total_supply_cap(self, cap: Shares) -> Call[None]:
|
|
195
195
|
return self._write("setTotalSupplyCap(uint256)", cap)
|
|
196
196
|
|
|
197
197
|
def convert_to_public_vault(self) -> Call[None]:
|
|
@@ -362,25 +362,26 @@ class PlasmaVault(ContractWrapper):
|
|
|
362
362
|
"configureInstantWithdrawalFuses((address,bytes32[])[])", normalized
|
|
363
363
|
)
|
|
364
364
|
|
|
365
|
-
def transfer(self, to: ChecksumAddress, value:
|
|
365
|
+
def transfer(self, to: ChecksumAddress, value: Shares) -> Call[None]:
|
|
366
366
|
return self._write("transfer(address,uint256)", to, value)
|
|
367
367
|
|
|
368
|
-
def approve(self, account: ChecksumAddress, amount:
|
|
368
|
+
def approve(self, account: ChecksumAddress, amount: Shares) -> Call[None]:
|
|
369
369
|
return self._write("approve(address,uint256)", account, amount)
|
|
370
370
|
|
|
371
371
|
def transfer_from(
|
|
372
|
-
self, _from: ChecksumAddress, to: ChecksumAddress, amount:
|
|
372
|
+
self, _from: ChecksumAddress, to: ChecksumAddress, amount: Shares
|
|
373
373
|
) -> Call[None]:
|
|
374
374
|
return self._write("transferFrom(address,address,uint256)", _from, to, amount)
|
|
375
375
|
|
|
376
|
-
def balance_of(self, account: ChecksumAddress) -> Call[
|
|
376
|
+
def balance_of(self, account: ChecksumAddress) -> Call[Shares]:
|
|
377
377
|
return self._view(
|
|
378
|
-
"balanceOf(address)", account, output_types=["uint256"], decoder=
|
|
378
|
+
"balanceOf(address)", account, output_types=["uint256"], decoder=Shares
|
|
379
379
|
)
|
|
380
380
|
|
|
381
|
-
def get_total_supply_cap(self) -> Call[
|
|
381
|
+
def get_total_supply_cap(self) -> Call[Shares]:
|
|
382
|
+
"""The maximum total supply, in shares (``2**256 - 1``: uncapped)."""
|
|
382
383
|
return self._view(
|
|
383
|
-
"getTotalSupplyCap()", output_types=["uint256"], decoder=
|
|
384
|
+
"getTotalSupplyCap()", output_types=["uint256"], decoder=Shares
|
|
384
385
|
)
|
|
385
386
|
|
|
386
387
|
def max_withdraw(self, account: ChecksumAddress) -> Call[Amount]:
|
|
@@ -418,8 +419,8 @@ class PlasmaVault(ContractWrapper):
|
|
|
418
419
|
def total_assets(self) -> Call[Amount]:
|
|
419
420
|
return self._view("totalAssets()", output_types=["uint256"], decoder=Amount)
|
|
420
421
|
|
|
421
|
-
def total_supply(self) -> Call[
|
|
422
|
-
return self._view("totalSupply()", output_types=["uint256"], decoder=
|
|
422
|
+
def total_supply(self) -> Call[Shares]:
|
|
423
|
+
return self._view("totalSupply()", output_types=["uint256"], decoder=Shares)
|
|
423
424
|
|
|
424
425
|
def name(self) -> Call[str]:
|
|
425
426
|
return self._view("name()", output_types=["string"])
|
|
@@ -13,6 +13,7 @@ from dataclasses import dataclass, field
|
|
|
13
13
|
from typing import Protocol, TypeVar
|
|
14
14
|
|
|
15
15
|
from eth_typing import ChecksumAddress
|
|
16
|
+
from web3.types import Timestamp
|
|
16
17
|
|
|
17
18
|
from ipor_fusion.core.context import Web3Context
|
|
18
19
|
from ipor_fusion.core.plasma_vault import BalanceFuse
|
|
@@ -24,7 +25,15 @@ from ipor_fusion.dependency_graph import (
|
|
|
24
25
|
from ipor_fusion.market_ids import IporFusionMarkets
|
|
25
26
|
from ipor_fusion.readers.lending_health import VaultLendingHealth
|
|
26
27
|
from ipor_fusion.substrates import decode_substrate, format_market_label
|
|
27
|
-
from ipor_fusion.types import
|
|
28
|
+
from ipor_fusion.types import (
|
|
29
|
+
Amount,
|
|
30
|
+
ChainId,
|
|
31
|
+
Decimals,
|
|
32
|
+
FuseAddress,
|
|
33
|
+
MarketId,
|
|
34
|
+
PlasmaVaultAddress,
|
|
35
|
+
Shares,
|
|
36
|
+
)
|
|
28
37
|
from ipor_fusion.types import Check as Check
|
|
29
38
|
from ipor_fusion.types import Severity as Severity
|
|
30
39
|
from ipor_fusion.types import Verdict as Verdict
|
|
@@ -57,9 +66,9 @@ class WithdrawQueue(Protocol):
|
|
|
57
66
|
"""The WithdrawManager state the reconciliation needs."""
|
|
58
67
|
|
|
59
68
|
@property
|
|
60
|
-
def shares_to_release(self) ->
|
|
69
|
+
def shares_to_release(self) -> Shares: ...
|
|
61
70
|
@property
|
|
62
|
-
def shares_to_release_assets(self) ->
|
|
71
|
+
def shares_to_release_assets(self) -> Amount | None: ...
|
|
63
72
|
|
|
64
73
|
|
|
65
74
|
class UnpriceableToken(Protocol):
|
|
@@ -97,19 +106,19 @@ class VaultState(Protocol):
|
|
|
97
106
|
@property
|
|
98
107
|
def block_number(self) -> int: ...
|
|
99
108
|
@property
|
|
100
|
-
def block_timestamp(self) ->
|
|
109
|
+
def block_timestamp(self) -> Timestamp: ...
|
|
101
110
|
@property
|
|
102
111
|
def asset(self) -> ChecksumAddress: ...
|
|
103
112
|
@property
|
|
104
113
|
def asset_symbol(self) -> str: ...
|
|
105
114
|
@property
|
|
106
|
-
def asset_decimals(self) ->
|
|
115
|
+
def asset_decimals(self) -> Decimals: ...
|
|
107
116
|
@property
|
|
108
117
|
def asset_price_usd(self) -> float | None: ...
|
|
109
118
|
@property
|
|
110
|
-
def total_assets(self) ->
|
|
119
|
+
def total_assets(self) -> Amount: ...
|
|
111
120
|
@property
|
|
112
|
-
def underlying_balance_on_vault(self) ->
|
|
121
|
+
def underlying_balance_on_vault(self) -> Amount: ...
|
|
113
122
|
@property
|
|
114
123
|
def price_oracle_addr(self) -> ChecksumAddress: ...
|
|
115
124
|
@property
|
|
@@ -129,7 +138,7 @@ class VaultState(Protocol):
|
|
|
129
138
|
@property
|
|
130
139
|
def unimplemented_getters(self) -> Sequence[str]: ...
|
|
131
140
|
@property
|
|
132
|
-
def market_balances(self) -> Mapping[MarketId,
|
|
141
|
+
def market_balances(self) -> Mapping[MarketId, Amount]: ...
|
|
133
142
|
@property
|
|
134
143
|
def erc20(self) -> Erc20Holdings: ...
|
|
135
144
|
|
|
@@ -18,7 +18,7 @@ from typing import Any, TypeVar
|
|
|
18
18
|
from eth_typing import HexAddress
|
|
19
19
|
from eth_utils import function_signature_to_4byte_selector
|
|
20
20
|
from web3 import Web3
|
|
21
|
-
from web3.types import ChecksumAddress
|
|
21
|
+
from web3.types import ChecksumAddress, Timestamp
|
|
22
22
|
|
|
23
23
|
from ipor_fusion.cache import CacheKey, cache_get, cache_key, cache_put
|
|
24
24
|
from ipor_fusion.chains import ensure_supported_chain
|
|
@@ -57,10 +57,13 @@ from ipor_fusion.readers.unpriceable import (
|
|
|
57
57
|
from ipor_fusion.substrates import decode_substrate
|
|
58
58
|
from ipor_fusion.types import (
|
|
59
59
|
AccessManagerAddress,
|
|
60
|
+
Amount,
|
|
60
61
|
ChainId,
|
|
62
|
+
Decimals,
|
|
61
63
|
FuseAddress,
|
|
62
64
|
MarketId,
|
|
63
65
|
PlasmaVaultAddress,
|
|
66
|
+
Shares,
|
|
64
67
|
parse_hex_address,
|
|
65
68
|
)
|
|
66
69
|
from ipor_fusion.vault_erc20 import Erc20Holdings, _Asset, _read_erc20_holdings
|
|
@@ -115,12 +118,12 @@ class VaultData:
|
|
|
115
118
|
chain_id: ChainId
|
|
116
119
|
block_number: int
|
|
117
120
|
is_latest: bool
|
|
118
|
-
block_timestamp:
|
|
119
|
-
share_decimals:
|
|
120
|
-
asset_decimals:
|
|
121
|
-
total_assets:
|
|
122
|
-
total_supply:
|
|
123
|
-
supply_cap:
|
|
121
|
+
block_timestamp: Timestamp
|
|
122
|
+
share_decimals: Decimals
|
|
123
|
+
asset_decimals: Decimals
|
|
124
|
+
total_assets: Amount
|
|
125
|
+
total_supply: Shares
|
|
126
|
+
supply_cap: Shares
|
|
124
127
|
asset: ChecksumAddress
|
|
125
128
|
asset_symbol: str
|
|
126
129
|
access_manager: AccessManagerAddress
|
|
@@ -135,10 +138,10 @@ class VaultData:
|
|
|
135
138
|
# totalAssets via ERC4626 base accounting; by design NOT tracked as an
|
|
136
139
|
# ERC20_VAULT_BALANCE substrate, so it is read directly in
|
|
137
140
|
# fetch_vault_data rather than derived from substrates.
|
|
138
|
-
underlying_balance_on_vault:
|
|
141
|
+
underlying_balance_on_vault: Amount = Amount(0)
|
|
139
142
|
vault_name: str = ""
|
|
140
143
|
deployment_block: int | None = None
|
|
141
|
-
deployment_timestamp:
|
|
144
|
+
deployment_timestamp: Timestamp | None = None
|
|
142
145
|
# Short error code from `fetch_deployment_info` when block/timestamp could
|
|
143
146
|
# not be resolved. Surfaced in CLI output and the JSON `deployment` field
|
|
144
147
|
# so users can distinguish "lookup not attempted/failed" from
|
|
@@ -186,7 +189,7 @@ class VaultData:
|
|
|
186
189
|
unimplemented_getters: list[str] = field(default_factory=list)
|
|
187
190
|
# totalAssetsInMarket of every balance-fuse market, once per market, in
|
|
188
191
|
# balance-fuse order.
|
|
189
|
-
market_balances: dict[MarketId,
|
|
192
|
+
market_balances: dict[MarketId, Amount] = field(default_factory=dict)
|
|
190
193
|
# The ERC20_VAULT_BALANCE tokens read directly (empty without that market).
|
|
191
194
|
erc20: Erc20Holdings = field(default_factory=Erc20Holdings)
|
|
192
195
|
# Symbols (lowercase address keys) of the substrate and breakdown tokens,
|
|
@@ -215,7 +218,7 @@ def _fuse_market_id_call(fuse: ChecksumAddress) -> Call[int]:
|
|
|
215
218
|
)
|
|
216
219
|
|
|
217
220
|
|
|
218
|
-
_UNCAPPED = 2**256 - 1
|
|
221
|
+
_UNCAPPED = Shares(2**256 - 1)
|
|
219
222
|
|
|
220
223
|
|
|
221
224
|
def _missing_required_getter(
|
|
@@ -252,9 +255,16 @@ def resolve_token_symbol(ctx: Web3Context, address: HexAddress) -> str:
|
|
|
252
255
|
return symbol
|
|
253
256
|
|
|
254
257
|
|
|
255
|
-
def
|
|
256
|
-
|
|
257
|
-
|
|
258
|
+
def _cached_int(cached: dict[CacheKey, str], key: CacheKey) -> int | None:
|
|
259
|
+
"""A cached non-negative integer; anything else (a corrupt or foreign
|
|
260
|
+
entry) is a miss."""
|
|
261
|
+
value = cached.get(key, "")
|
|
262
|
+
if not (value.isascii() and value.isdigit()):
|
|
263
|
+
return None
|
|
264
|
+
try:
|
|
265
|
+
return int(value)
|
|
266
|
+
except ValueError: # beyond the int-string conversion limit
|
|
267
|
+
return None
|
|
258
268
|
|
|
259
269
|
|
|
260
270
|
def resolve_token_decimals(ctx: Web3Context, address: HexAddress) -> int | None:
|
|
@@ -262,7 +272,7 @@ def resolve_token_decimals(ctx: Web3Context, address: HexAddress) -> int | None:
|
|
|
262
272
|
(not cached) when ``address`` has no code at the context's block or does
|
|
263
273
|
not answer."""
|
|
264
274
|
key = cache_key(ctx.chain_id, address, "decimals")
|
|
265
|
-
if (cached :=
|
|
275
|
+
if (cached := _cached_int(cache_get(ctx.cache, [key]), key)) is not None:
|
|
266
276
|
return cached
|
|
267
277
|
|
|
268
278
|
checksum = Web3.to_checksum_address(address)
|
|
@@ -278,7 +288,7 @@ def resolve_token_decimals(ctx: Web3Context, address: HexAddress) -> int | None:
|
|
|
278
288
|
return decimals
|
|
279
289
|
|
|
280
290
|
|
|
281
|
-
def _block_timestamp(ctx: Web3Context, block: int) ->
|
|
291
|
+
def _block_timestamp(ctx: Web3Context, block: int) -> Timestamp:
|
|
282
292
|
return ctx.web3.eth.get_block(block)["timestamp"]
|
|
283
293
|
|
|
284
294
|
|
|
@@ -428,7 +438,7 @@ class _MarketReads:
|
|
|
428
438
|
# Only markets with at least one substrate.
|
|
429
439
|
market_substrates: dict[MarketId, list[bytes]]
|
|
430
440
|
aave_pools: dict[MarketId, ChecksumAddress]
|
|
431
|
-
market_balances: dict[MarketId,
|
|
441
|
+
market_balances: dict[MarketId, Amount]
|
|
432
442
|
# False when the vault predates getMarketSubstrates (substrates unknown).
|
|
433
443
|
substrates_available: bool = True
|
|
434
444
|
|
|
@@ -696,7 +706,7 @@ def _token_metadata(
|
|
|
696
706
|
decimals: dict[HexAddress, int | None] = {
|
|
697
707
|
a: value
|
|
698
708
|
for a, k in decimals_keys.items()
|
|
699
|
-
if (value :=
|
|
709
|
+
if (value := _cached_int(cached, k)) is not None
|
|
700
710
|
}
|
|
701
711
|
missing_symbols = sorted((breakdown | substrate_addresses) - symbols.keys())
|
|
702
712
|
missing_decimals = sorted(breakdown - decimals.keys())
|
|
@@ -756,7 +766,7 @@ def fetch_deployment_info(
|
|
|
756
766
|
vault_address: PlasmaVaultAddress,
|
|
757
767
|
*,
|
|
758
768
|
api_key: str | None = None,
|
|
759
|
-
) -> tuple[int | None,
|
|
769
|
+
) -> tuple[int | None, Timestamp | None, str | None]:
|
|
760
770
|
"""Return ``(block, timestamp, error)`` for the vault deployment, cached in
|
|
761
771
|
``ctx.cache``.
|
|
762
772
|
|
|
@@ -771,10 +781,10 @@ def fetch_deployment_info(
|
|
|
771
781
|
block_key = cache_key(chain_id, vault_address, "deployment_block")
|
|
772
782
|
time_key = cache_key(chain_id, vault_address, "deployment_timestamp")
|
|
773
783
|
cached = cache_get(ctx.cache, [block_key, time_key])
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
return
|
|
784
|
+
block = _cached_int(cached, block_key)
|
|
785
|
+
stamp = _cached_int(cached, time_key)
|
|
786
|
+
if block is not None and stamp is not None:
|
|
787
|
+
return block, Timestamp(stamp), None
|
|
778
788
|
|
|
779
789
|
tx_hash, error = get_deployment_tx(chain_id, vault_address, api_key)
|
|
780
790
|
if not tx_hash:
|
|
@@ -783,7 +793,7 @@ def fetch_deployment_info(
|
|
|
783
793
|
try:
|
|
784
794
|
tx = ctx.web3.eth.get_transaction(tx_hash)
|
|
785
795
|
block_number: int = tx["blockNumber"]
|
|
786
|
-
timestamp:
|
|
796
|
+
timestamp: Timestamp = ctx.web3.eth.get_block(block_number)["timestamp"]
|
|
787
797
|
except Exception:
|
|
788
798
|
return None, None, "rpc-fetch-failed"
|
|
789
799
|
cache_put(ctx.cache, {block_key: str(block_number), time_key: str(timestamp)})
|
|
@@ -6,7 +6,6 @@ from __future__ import annotations
|
|
|
6
6
|
from collections.abc import Callable
|
|
7
7
|
from concurrent.futures import Future, ThreadPoolExecutor
|
|
8
8
|
from datetime import UTC, datetime
|
|
9
|
-
from functools import partial
|
|
10
9
|
from typing import Any
|
|
11
10
|
|
|
12
11
|
from eth_typing import HexAddress
|
|
@@ -14,7 +13,6 @@ from eth_typing import HexAddress
|
|
|
14
13
|
from ipor_fusion.chains import CHAIN_NAMES
|
|
15
14
|
from ipor_fusion.core.fee_manager import HighWaterMarkPerformanceFee, RecipientFee
|
|
16
15
|
from ipor_fusion.core.plasma_vault import BalanceFuse
|
|
17
|
-
from ipor_fusion.explorer import get_contract_name
|
|
18
16
|
from ipor_fusion.field_docs import DOCS
|
|
19
17
|
from ipor_fusion.readers.aave_v3 import AaveV3PositionBreakdown
|
|
20
18
|
from ipor_fusion.readers.hypercore import HyperCorePendingState, HyperCorePerpLeg
|
|
@@ -647,7 +645,7 @@ def _supply_cap_json(data: VaultData) -> dict[str, Any]:
|
|
|
647
645
|
"formatted": (
|
|
648
646
|
"unlimited"
|
|
649
647
|
if data.supply_cap == UINT256_MAX
|
|
650
|
-
else _format_amount(data.supply_cap, data.
|
|
648
|
+
else _format_amount(data.supply_cap, data.share_decimals)
|
|
651
649
|
),
|
|
652
650
|
}
|
|
653
651
|
|
|
@@ -705,6 +703,10 @@ def _markets_json(
|
|
|
705
703
|
return markets
|
|
706
704
|
|
|
707
705
|
|
|
706
|
+
def _no_name(_address: HexAddress) -> str:
|
|
707
|
+
return ""
|
|
708
|
+
|
|
709
|
+
|
|
708
710
|
def build_vault_info_json(
|
|
709
711
|
data: VaultData,
|
|
710
712
|
*,
|
|
@@ -716,14 +718,14 @@ def build_vault_info_json(
|
|
|
716
718
|
``data`` comes from `fetch_vault_data` (with ``metadata=True`` for token
|
|
717
719
|
symbols); set its ``deployment_*`` fields first (`fetch_deployment_info`)
|
|
718
720
|
for the ``deployment`` block. ``resolve_name`` names the fuses and
|
|
719
|
-
substrate contracts (address to contract name, ``""`` when unknown)
|
|
720
|
-
|
|
721
|
-
|
|
721
|
+
substrate contracts (address to contract name, ``""`` when unknown), for
|
|
722
|
+
example `ipor_fusion.explorer.get_contract_name` bound to the chain, an
|
|
723
|
+
API key and ``ctx.cache``; without it no contract is named.
|
|
722
724
|
"""
|
|
723
725
|
chain_id = data.chain_id
|
|
724
726
|
chain_label = CHAIN_NAMES.get(chain_id, str(chain_id))
|
|
725
727
|
if resolve_name is None:
|
|
726
|
-
resolve_name =
|
|
728
|
+
resolve_name = _no_name
|
|
727
729
|
|
|
728
730
|
markets = _markets_json(data, resolve_name)
|
|
729
731
|
validation = validate_vault_state(data)
|