ipor-fusion 4.0.0.dev327__tar.gz → 4.0.0.dev334__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.
Files changed (356) hide show
  1. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/AGENTS.md +4 -2
  2. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/MIGRATION_4.md +10 -10
  3. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/PKG-INFO +6 -5
  4. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/README.md +5 -4
  5. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/pyproject.toml +1 -1
  6. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/about.py +5 -6
  7. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/core/contract.py +9 -1
  8. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/core/multicall.py +16 -1
  9. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/__init__.py +1 -1
  10. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/hypercore/__init__.py +4 -2
  11. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/mcp/models.py +2 -3
  12. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/preflight.py +5 -3
  13. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_multicall.py +82 -0
  14. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_preflight.py +17 -1
  15. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/.claude-plugin/marketplace.json +0 -0
  16. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/.claude-plugin/plugin.json +0 -0
  17. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/.env.example +0 -0
  18. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/.gemini/settings.json +0 -0
  19. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/.git-blame-ignore-revs +0 -0
  20. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/.github/workflows/cd.yml +0 -0
  21. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/.github/workflows/ci.yml +0 -0
  22. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/.github/workflows/commit-lint.yml +0 -0
  23. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/.github/workflows/notify-slack.yml +0 -0
  24. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/.github/workflows/python-build.yml +0 -0
  25. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/.github/workflows/python-publish.yml +0 -0
  26. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/.github/workflows/release.yml +0 -0
  27. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/.github/workflows/report-slack.yml +0 -0
  28. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/.gitignore +0 -0
  29. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/.mcp.json +0 -0
  30. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/.pre-commit-config.yaml +0 -0
  31. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/.python-version +0 -0
  32. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/CHANGELOG.md +0 -0
  33. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/CLAUDE.md +0 -0
  34. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/CODEOWNERS +0 -0
  35. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/LICENSE +0 -0
  36. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/build.sh +0 -0
  37. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/examples/CONTRIBUTING.md +0 -0
  38. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/examples/README.md +0 -0
  39. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/examples/advanced_euler_v2_credit_market_base.py +0 -0
  40. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/examples/advanced_euler_v2_looping_arbitrum.py +0 -0
  41. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py +0 -0
  42. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/examples/external_state_margin_leg_base.py +0 -0
  43. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/examples/hypercore_vault_official_deployment_hyperevm.py +0 -0
  44. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/examples/simple_aave_v3_supply_base.py +0 -0
  45. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/pytest.ini +0 -0
  46. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/scripts/commit-check.sh +0 -0
  47. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/scripts/fusion_error_signatures.py +0 -0
  48. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/skills/ipor-deploy-vault/SKILL.md +0 -0
  49. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/__init__.py +0 -0
  50. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/cache.py +0 -0
  51. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/chains.py +0 -0
  52. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/cli/__init__.py +0 -0
  53. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/cli/address_cmd.py +0 -0
  54. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/cli/changelog_cmd.py +0 -0
  55. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/cli/config_cmd.py +0 -0
  56. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/cli/config_store.py +0 -0
  57. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/cli/main.py +0 -0
  58. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/cli/market_cmd.py +0 -0
  59. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/cli/options.py +0 -0
  60. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/cli/oracle_mapping_view.py +0 -0
  61. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/cli/preflight_cmd.py +0 -0
  62. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/cli/vault_cmd.py +0 -0
  63. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/cli/vault_health.py +0 -0
  64. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/cli/vault_info_view.py +0 -0
  65. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/cli/vault_markets_view.py +0 -0
  66. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/cli/vault_rendering.py +0 -0
  67. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/config/__init__.py +0 -0
  68. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/config/roles.py +0 -0
  69. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/core/__init__.py +0 -0
  70. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/core/access.py +0 -0
  71. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/core/address.py +0 -0
  72. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/core/context.py +0 -0
  73. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/core/context_manager.py +0 -0
  74. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/core/erc20.py +0 -0
  75. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/core/external_state_executor.py +0 -0
  76. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/core/fee_manager.py +0 -0
  77. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/core/fuse.py +0 -0
  78. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/core/fuse_action.py +0 -0
  79. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/core/fuse_decoding.py +0 -0
  80. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/core/fusion_factory.py +0 -0
  81. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/core/logs.py +0 -0
  82. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/core/oracle.py +0 -0
  83. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/core/plasma_vault.py +0 -0
  84. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/core/rewards_manager.py +0 -0
  85. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/core/simulation.py +0 -0
  86. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/core/simulation_result.py +0 -0
  87. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/core/withdraw_manager.py +0 -0
  88. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/ccip/__init__.py +0 -0
  89. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/ccip/chainlink.py +0 -0
  90. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/ccip/codec.py +0 -0
  91. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/ccip/contracts.py +0 -0
  92. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/ccip/events.py +0 -0
  93. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/ccip/indexer.py +0 -0
  94. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/ccip/lane.py +0 -0
  95. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/ccip/quote.py +0 -0
  96. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/ccip/transport.py +0 -0
  97. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/contracts.py +0 -0
  98. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/discovery.py +0 -0
  99. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/errors.py +0 -0
  100. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/fuses/__init__.py +0 -0
  101. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/fuses/base.py +0 -0
  102. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/fuses/ccip.py +0 -0
  103. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/fuses/stargate.py +0 -0
  104. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/lane.py +0 -0
  105. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/logs.py +0 -0
  106. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/messages.py +0 -0
  107. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/simulation.py +0 -0
  108. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/stargate/__init__.py +0 -0
  109. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/stargate/contracts.py +0 -0
  110. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/stargate/lane.py +0 -0
  111. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/stargate/layerzero.py +0 -0
  112. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/stargate/transport.py +0 -0
  113. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/crosschain/transport.py +0 -0
  114. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/dependency_graph.py +0 -0
  115. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/entry_cli.py +0 -0
  116. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/entry_mcp.py +0 -0
  117. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/errors.py +0 -0
  118. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/explorer.py +0 -0
  119. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/field_docs.py +0 -0
  120. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/fuses/__init__.py +0 -0
  121. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/fuses/aave_v3.py +0 -0
  122. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/fuses/async_action.py +0 -0
  123. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/fuses/base.py +0 -0
  124. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/fuses/compound_v3.py +0 -0
  125. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/fuses/erc4626.py +0 -0
  126. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/fuses/euler_v2.py +0 -0
  127. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/fuses/events.py +0 -0
  128. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/fuses/external_state.py +0 -0
  129. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/fuses/external_state_event_decoding.py +0 -0
  130. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/fuses/fluid_instadapp.py +0 -0
  131. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/fuses/gearbox_v3.py +0 -0
  132. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/fuses/hypercore.py +0 -0
  133. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/fuses/hypercore_event_decoding.py +0 -0
  134. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/fuses/merkl.py +0 -0
  135. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/fuses/morpho.py +0 -0
  136. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/fuses/ramses_v2.py +0 -0
  137. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/fuses/uniswap_v3.py +0 -0
  138. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/fuses/universal.py +0 -0
  139. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/fusion_errors.py +0 -0
  140. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/guide/__init__.py +0 -0
  141. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/guide/architecture.md +0 -0
  142. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/guide/glossary.md +0 -0
  143. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/guide/invariants.md +0 -0
  144. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/guide/quickstart.md +0 -0
  145. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/market_ids.py +0 -0
  146. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/market_info.py +0 -0
  147. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/mcp/__init__.py +0 -0
  148. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/mcp/guide.py +0 -0
  149. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/mcp/server.py +0 -0
  150. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/morpho_api.py +0 -0
  151. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/py.typed +0 -0
  152. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/readers/__init__.py +0 -0
  153. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/readers/aave_v3.py +0 -0
  154. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/readers/aave_v4.py +0 -0
  155. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/readers/compound_v3.py +0 -0
  156. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/readers/hypercore.py +0 -0
  157. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/readers/hypercore_outcome.py +0 -0
  158. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/readers/lending_health.py +0 -0
  159. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/readers/morpho.py +0 -0
  160. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/readers/oracle_mapping.py +0 -0
  161. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/readers/oracle_mapping_nodes.py +0 -0
  162. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/readers/oracle_mapping_reader.py +0 -0
  163. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/readers/position_manager.py +0 -0
  164. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/readers/ramses_v2.py +0 -0
  165. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/readers/uniswap_v3.py +0 -0
  166. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/readers/unpriceable.py +0 -0
  167. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/registry.py +0 -0
  168. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/substrates.py +0 -0
  169. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/types.py +0 -0
  170. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/validation.py +0 -0
  171. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/vault_data.py +0 -0
  172. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/vault_erc20.py +0 -0
  173. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/vault_info.py +0 -0
  174. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/vault_managers.py +0 -0
  175. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/vault_positions.py +0 -0
  176. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/src/ipor_fusion/vault_reads.py +0 -0
  177. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/UniswapV3UniversalRouter.py +0 -0
  178. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/_crosschain.py +0 -0
  179. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/_crosschain_lifecycle.py +0 -0
  180. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/_crosschain_recovery.py +0 -0
  181. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/_euler_v2.py +0 -0
  182. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/_event_args.py +0 -0
  183. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/_fake_rpc.py +0 -0
  184. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/_foundry.py +0 -0
  185. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/_golden.py +0 -0
  186. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/_guide.py +0 -0
  187. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/_hypercore_model.py +0 -0
  188. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/_hypercore_shadow.py +0 -0
  189. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/_live.py +0 -0
  190. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/_multicall.py +0 -0
  191. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/_oracle_mapping_fake.py +0 -0
  192. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/_simulate.py +0 -0
  193. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/_validation.py +0 -0
  194. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/addresses.py +0 -0
  195. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/conftest.py +0 -0
  196. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/constants.py +0 -0
  197. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/hypercore_hip3_flow.json +0 -0
  198. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/hypercore_market55.json +0 -0
  199. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/hypercore_official.json +0 -0
  200. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/market_golden/meta_morpho_v1.json +0 -0
  201. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/market_golden/meta_morpho_v1.mcp.json +0 -0
  202. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/market_golden/meta_morpho_v2.json +0 -0
  203. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/market_golden/meta_morpho_v2.mcp.json +0 -0
  204. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/market_golden/morpho_api/market.json +0 -0
  205. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/market_golden/morpho_api/vault_v1.json +0 -0
  206. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/market_golden/morpho_api/vault_v2.json +0 -0
  207. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/market_golden/morpho_api/vault_v2_not_found.json +0 -0
  208. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/market_golden/morpho_blue.json +0 -0
  209. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/market_golden/morpho_blue.mcp.json +0 -0
  210. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/market_golden/morpho_blue_api_error.json +0 -0
  211. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/market_golden/morpho_blue_api_error.mcp.json +0 -0
  212. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/market_golden/morpho_blue_no_api.json +0 -0
  213. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/market_golden/morpho_blue_no_api.mcp.json +0 -0
  214. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/oracle_mapping_golden/mapping.json +0 -0
  215. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/oracle_mapping_golden/mapping.mcp.json +0 -0
  216. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/simulate_v1_request.json +0 -0
  217. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/vault_info_golden/clean.json +0 -0
  218. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/vault_info_golden/clean.mcp.json +0 -0
  219. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/vault_info_golden/clean.txt +0 -0
  220. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/vault_info_golden/deployment_error.json +0 -0
  221. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/vault_info_golden/deployment_error.mcp.json +0 -0
  222. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/vault_info_golden/deployment_error.txt +0 -0
  223. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/vault_info_golden/fetched.cli.json +0 -0
  224. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/vault_info_golden/fetched.json +0 -0
  225. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/vault_info_golden/fetched.mcp.json +0 -0
  226. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/vault_info_golden/full.json +0 -0
  227. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/vault_info_golden/full.mcp.json +0 -0
  228. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/vault_info_golden/full.txt +0 -0
  229. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/vault_info_golden/rich.json +0 -0
  230. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/vault_info_golden/rich.mcp.json +0 -0
  231. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/fixtures/vault_info_golden/rich.txt +0 -0
  232. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_about.py +0 -0
  233. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_access_manager.py +0 -0
  234. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_cache.py +0 -0
  235. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_chains.py +0 -0
  236. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_cli_address.py +0 -0
  237. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_cli_changelog.py +0 -0
  238. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_cli_commands.py +0 -0
  239. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_cli_config_store.py +0 -0
  240. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_cli_helpers.py +0 -0
  241. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_cli_hypercore.py +0 -0
  242. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_cli_lending_health.py +0 -0
  243. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_cli_market_golden.py +0 -0
  244. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_cli_market_morpho_blue.py +0 -0
  245. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_cli_mcp_parity.py +0 -0
  246. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_cli_oracle_mapping.py +0 -0
  247. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_cli_oracle_mapping_golden.py +0 -0
  248. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_cli_pending_requests_scan.py +0 -0
  249. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_cli_preflight.py +0 -0
  250. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_cli_role_accounts.py +0 -0
  251. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_cli_vault_info_golden.py +0 -0
  252. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_cli_vault_predates_getters.py +0 -0
  253. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_cli_vault_validate.py +0 -0
  254. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_contract_call.py +0 -0
  255. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_contract_encoder.py +0 -0
  256. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_crosschain_ccip_events.py +0 -0
  257. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_crosschain_ccip_indexer.py +0 -0
  258. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_crosschain_ccip_quote.py +0 -0
  259. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_crosschain_chainlink.py +0 -0
  260. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_crosschain_contracts.py +0 -0
  261. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_crosschain_encoding.py +0 -0
  262. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_crosschain_errors.py +0 -0
  263. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_crosschain_lane.py +0 -0
  264. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_crosschain_layering.py +0 -0
  265. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_crosschain_transport.py +0 -0
  266. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_docs_typing.py +0 -0
  267. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_erc20.py +0 -0
  268. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_error_hierarchy.py +0 -0
  269. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_examples_crosschain.py +0 -0
  270. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_examples_euler_looping_arbitrum.py +0 -0
  271. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_examples_hypercore_hyperevm.py +0 -0
  272. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_examples_vaults.py +0 -0
  273. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_explorer.py +0 -0
  274. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_external_state_events.py +0 -0
  275. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_external_state_executor.py +0 -0
  276. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_fee_manager.py +0 -0
  277. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_fuse_decoding.py +0 -0
  278. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_fuse_encoding.py +0 -0
  279. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_fusion_errors.py +0 -0
  280. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_fusion_instance.py +0 -0
  281. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_governance_wrappers.py +0 -0
  282. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_guide.py +0 -0
  283. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_hypercore_deployment.py +0 -0
  284. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_hypercore_events.py +0 -0
  285. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_hypercore_flow.py +0 -0
  286. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_hypercore_live.py +0 -0
  287. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_hypercore_outcome.py +0 -0
  288. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_hypercore_readers.py +0 -0
  289. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_hypercore_simulation.py +0 -0
  290. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_logs.py +0 -0
  291. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_mcp_address.py +0 -0
  292. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_mcp_hypercore.py +0 -0
  293. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_mcp_models.py +0 -0
  294. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_mcp_preflight.py +0 -0
  295. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_mcp_server.py +0 -0
  296. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_mcp_vault_validate.py +0 -0
  297. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_oracle.py +0 -0
  298. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_oracle_mapping.py +0 -0
  299. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_plasma_vault.py +0 -0
  300. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_public_api.py +0 -0
  301. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_public_type_reachability.py +0 -0
  302. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_reader_encoding.py +0 -0
  303. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_registry.py +0 -0
  304. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_revert_decoding.py +0 -0
  305. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_rewards_manager.py +0 -0
  306. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_roles.py +0 -0
  307. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_sdk_layering.py +0 -0
  308. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_borrow_aave_v3_mainnet.py +0 -0
  309. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_claim_merkl_wrapper_base.py +0 -0
  310. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_claim_morpho_rewards.py +0 -0
  311. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_crosschain_hyperevm.py +0 -0
  312. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_euler_v2_batch_base.py +0 -0
  313. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_euler_v2_credit_market_base.py +0 -0
  314. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_euler_v2_swap_deploy_base.py +0 -0
  315. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_euler_v2_swap_reconfigure_base.py +0 -0
  316. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_euler_v2_swap_registry_base.py +0 -0
  317. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_examples_arbitrum.py +0 -0
  318. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_examples_base.py +0 -0
  319. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_examples_crosschain.py +0 -0
  320. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_examples_hyperevm.py +0 -0
  321. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_external_state_executor_base.py +0 -0
  322. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_fusion_factory_clone_base.py +0 -0
  323. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_looping_aave_v3_base.py +0 -0
  324. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_looping_morpho_blue_base.py +0 -0
  325. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_morpho_blue.py +0 -0
  326. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_pilot_v3.py +0 -0
  327. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_pilot_v4_uniswap.py +0 -0
  328. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_pilot_v5_ramses.py +0 -0
  329. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_pilot_v5_scheduled.py +0 -0
  330. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_plasma_vault_setters_base.py +0 -0
  331. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_preflight_base.py +0 -0
  332. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_readers_integration.py +0 -0
  333. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_release_funds.py +0 -0
  334. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_swap_on_base.py +0 -0
  335. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_timelock_base.py +0 -0
  336. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulate_vault_from_scratch_base.py +0 -0
  337. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulation_errors.py +0 -0
  338. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_simulation_observation.py +0 -0
  339. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_solidity_compiler.py +0 -0
  340. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_solidity_mirrors.py +0 -0
  341. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_substrates.py +0 -0
  342. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_types_and_events.py +0 -0
  343. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_unpriceable_tokens.py +0 -0
  344. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_validation.py +0 -0
  345. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_vault_data_block.py +0 -0
  346. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_vault_dep_graph.py +0 -0
  347. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_vault_info_fetched_golden.py +0 -0
  348. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_vault_info_onchain_base.py +0 -0
  349. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_vault_info_onchain_base_no_withdraw_manager.py +0 -0
  350. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_vault_reconciliation_onchain_base.py +0 -0
  351. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_vault_simulator_blocks.py +0 -0
  352. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_web3_context.py +0 -0
  353. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/test_withdraw_manager.py +0 -0
  354. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/typed_client/consumer.py +0 -0
  355. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/tests/typed_client/rejected.py +0 -0
  356. {ipor_fusion-4.0.0.dev327 → ipor_fusion-4.0.0.dev334}/uv.lock +0 -0
@@ -159,7 +159,8 @@ checkout's default profile), the pending reader included.
159
159
  - No AI attribution trailers or "generated with" lines in commits or PRs.
160
160
  - Branch and open a PR; `main` only moves through PRs and the release workflow.
161
161
  - Dependencies: `>=x,<next-major` ranges in `pyproject.toml`, resolved by
162
- `uv.lock`; `pyright` is pinned exactly.
162
+ `uv.lock`; `pyright` is pinned exactly. `certifi` is the deliberate exception: it
163
+ is calendar-versioned, and its floor only forces a CA bundle with recent revocations.
163
164
  - English only, US spelling, in code, comments, docstrings and user-facing
164
165
  strings (`field_docs.py` ships as API documentation). Comments only for edge
165
166
  cases and non-obvious logic.
@@ -304,7 +305,8 @@ checkout's default profile), the pending reader included.
304
305
  `ccip/quote` (`quote_ccip_native_fee`: the exact native fee of a send, from a
305
306
  simulation with the payer's balance at zero);
306
307
  `ccip/events` decodes the executor/dispatcher/factory events by topic (one
307
- registry, mirrored from the v3 source; the v2 pair emits a subset of it);
308
+ registry, mirrored from the released contracts; earlier deployments' events
309
+ are not decoded where their signatures differ);
308
310
  `ccip/chainlink` also wraps the 2.0 OffRamp, verifier resolver and committee verifier
309
311
  (`CcipOffRamp.execute` is the permissionless delivery) and `ccip/indexer` fetches a
310
312
  message's verifier result from Chainlink's public indexers and builds that
@@ -346,12 +346,12 @@ could not hold. 4.0 exports them only from their subpackages.
346
346
  `CrosschainSimulator`. It also covers the crosschain ids (`AssetId`, `CommandId`,
347
347
  `MessageId`, `LayerZeroEid`, `CcipChainSelector`, ...), which still import from
348
348
  `ipor_fusion.types` too.
349
- - **HyperCore:** the 97 HyperCore names import from the new
349
+ - **HyperCore:** the HyperCore names import from the new
350
350
  `ipor_fusion.hypercore`. That covers the fuses and `HyperCoreSubstrates`, the
351
351
  readers and `read_hypercore_*`, the event classes, specs and decoders, and the
352
352
  ids (`HyperCoreAsset`, `HyperCoreTokenIndex`, `MarginTableId`, `PayloadHash`,
353
353
  ...). It also covers the constants and helpers (`SPOT_DEX`, `USDC_TOKEN_INDEX`,
354
- `USDC_SYSTEM_ADDRESS`, `system_address`, `precompile_index_of`, `SettlementMode`,
354
+ `USDC_SYSTEM_ADDRESS`, `system_address`, `precompile_index_of`,
355
355
  `TimeInForce`, `TransferDirection`, ...). `HYPEREVM_CHAIN_ID` stays a top-level
356
356
  chain constant. `ipor_fusion.fuses`
357
357
  and `ipor_fusion.readers` no longer list them; the ids still import from
@@ -540,11 +540,12 @@ on the spoke side.
540
540
  `observation()` raises `UnsupportedContractVersionError` this way), and it
541
541
  survives `Call.map()`.
542
542
  - **Removed.** `CrosschainDispatcher.pending_request_shares` (neither released
543
- dispatcher has it). From the repository: `scripts/crosschain_readiness.py`, the
544
- pytest `--run-readiness` option and `readiness` marker, and the examples
545
- `crosschain_ccip_usdc_arbitrum_hyperevm.py` and
546
- `composed_hypercore_flow_arbitrum_hyperevm.py`, which drove an earlier
547
- deployment.
543
+ dispatcher has it). From the repository: `scripts/crosschain_readiness.py` and the
544
+ pytest `--run-readiness` option and `readiness` marker. The example
545
+ `crosschain_ccip_usdc_arbitrum_hyperevm.py` is rewritten for the released
546
+ contracts under the same name, and `composed_hypercore_flow_arbitrum_hyperevm.py`,
547
+ which drove an earlier deployment, is replaced by
548
+ `hypercore_vault_official_deployment_hyperevm.py`.
548
549
  - **Events and errors.** `CCIP_EVENTS` mirrors the released contracts:
549
550
  `ReturnFinalized` / `LateReturnFinalized` gain `debitedSD`, `SharesRequested`
550
551
  gains `feeShares`, and new events are registered. The crosschain error registry
@@ -851,7 +852,7 @@ oracle-mapping readers, `read_external_state`, `VaultSimulator(vault=)`,
851
852
  `CrosschainSimulator`, crosschain discovery, the hub-manager inputs
852
853
  (`ExecutorInitParams.manager`, `create_executor(manager=)`, `executors_of(manager=)`),
853
854
  the async command helpers `Command.request_shares` / `redeem_from_request`,
854
- `pending_request_shares` and `WithdrawManager.update_plasma_vault_address` take a
855
+ and `WithdrawManager.update_plasma_vault_address` take a
855
856
  `PlasmaVaultAddress`; `.address`, `FusionInstance.plasma_vault` and the executor's
856
857
  `manager()` return one. Crosschain deposit and redeem destinations stay
857
858
  `ChecksumAddress`: `Command.deposit` / `redeem`, `is_allowed_vault`,
@@ -928,8 +929,7 @@ and `pending_deployment_created_at()` return a `Timestamp`. Decimals are
928
929
  `shared_decimals` of `CcipCrosschainFactory.asset_config()`, `schedule_asset` and
929
930
  `execute_asset`. Token amounts are `Amount` (`EVMTokenAmount.amount`,
930
931
  `TokenTransferV1.amount`, `TaxiMessage.amount_sd`, `OutboundMessage.token_amount`,
931
- `StargateChain.to_local_decimals`), and `pending_request_shares()` returns
932
- `Shares`. Counters, sequences, epochs, versions, bps and gas limits stay `int`.
932
+ `StargateChain.to_local_decimals`). Counters, sequences, epochs, versions, bps and gas limits stay `int`.
933
933
  Decoded event values
934
934
  (`ccip_events` → `CcipEvent.values`) stay a generic mapping: convert a value
935
935
  before passing it on.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: ipor-fusion
3
- Version: 4.0.0.dev327
3
+ Version: 4.0.0.dev334
4
4
  Summary: The IPOR Fusion SDK for Python
5
5
  Project-URL: homepage, https://ipor.io
6
6
  Project-URL: repository, https://github.com/IPOR-Labs/ipor-fusion.py
@@ -58,9 +58,10 @@ Maintained by <a href="https://ipor.io">IPOR Labs AG</a>.
58
58
 
59
59
  > **Preview, not production:** the crosschain market (54: Stargate and CCIP executors,
60
60
  > dispatchers, lanes, fuses) and the HyperCore market (55: fuses, readers, events) are
61
- > under active development. Their contracts are not production releases, the mainnet
62
- > deployments are a proof of concept and IPOR Labs canaries, and their interfaces may
63
- > change between minor versions. Route no production capital through them. Everything
61
+ > under active development. The SDK follows their official deployment (the 2026-10-21
62
+ > contracts release, listed in ipor-abi) and nothing earlier, and their interfaces may
63
+ > change or be removed between minor versions, with no backward compatibility. Route
64
+ > no production capital through them. Everything
64
65
  > else in the package is production. `server_info` and `fusion changelog` list the same
65
66
  > status (`PREVIEW_FEATURES`).
66
67
 
@@ -540,7 +541,7 @@ the pilot executors and factories). Pin an exact version if you depend on them.
540
541
  | `discover_deployment`, `open_lanes` | Read a vault's crosschain market from the hub alone (executors with transport, factory, fuses, attestation keys and spokes served; remote vaults per spoke) and open every lane; `LANES` maps a transport kind to its lane class |
541
542
  | `CrosschainSimulator` | Multi-chain `eth_simulateV1` relay: replays LayerZero and CCIP messages between pinned chains by impersonating the endpoint or router on delivery, no bridge needed |
542
543
  | `ccip_token_lane` | Whether a CCIP message lane exists from a chain and whether a token's pool serves it, read on Chainlink's Router, OnRamp, TokenAdminRegistry and pool |
543
- | `decode_hypercore_event`, `hypercore_events` | The HyperCore fuse, pending-library, settlement and reporter events, decoded by topic with their raw log identity under the same input contract as `decode_external_state_event`; a malformed listed log raises `HyperCoreEventDecodeError` |
544
+ | `decode_hypercore_event`, `hypercore_events` | The HyperCore fuse events and the pending library's `HyperCoreActionEnqueued` / `HyperCoreActionSettled`, decoded by topic with their raw log identity under the same input contract as `decode_external_state_event`; a malformed listed log raises `HyperCoreEventDecodeError` |
544
545
  | Crosschain fuses (market 54): `StargateCrosschainSupplyFuse`, `StargateCrosschainCommandFuse`, `CcipCrosschainSupplyFuse`, `CcipCrosschainCommandFuse`, `CrosschainClaimFuse`; transport-agnostic bases `CrosschainSupplyFuse` / `CrosschainCommandFuse` with `StargateSendParams` / `CcipSendParams`, plus `Command`, `CrosschainSubstrateLib`, `OptionsBuilder` | `ipor_fusion.crosschain` |
545
546
  | HyperCore fuses (market 55): `HyperCoreDepositFuse`, `HyperCoreMarginFuse`, `HyperCoreSendFuse`, `HyperCoreOrderFuse`, `HyperCoreCancelFuse`, `HyperCoreBuilderFeeFuse`, `HyperCoreSubstrates` | `ipor_fusion.hypercore`, with `HyperCoreReader`, `read_hypercore_vault_state` and the event decoders |
546
547
 
@@ -9,9 +9,10 @@ Maintained by <a href="https://ipor.io">IPOR Labs AG</a>.
9
9
 
10
10
  > **Preview, not production:** the crosschain market (54: Stargate and CCIP executors,
11
11
  > dispatchers, lanes, fuses) and the HyperCore market (55: fuses, readers, events) are
12
- > under active development. Their contracts are not production releases, the mainnet
13
- > deployments are a proof of concept and IPOR Labs canaries, and their interfaces may
14
- > change between minor versions. Route no production capital through them. Everything
12
+ > under active development. The SDK follows their official deployment (the 2026-10-21
13
+ > contracts release, listed in ipor-abi) and nothing earlier, and their interfaces may
14
+ > change or be removed between minor versions, with no backward compatibility. Route
15
+ > no production capital through them. Everything
15
16
  > else in the package is production. `server_info` and `fusion changelog` list the same
16
17
  > status (`PREVIEW_FEATURES`).
17
18
 
@@ -491,7 +492,7 @@ the pilot executors and factories). Pin an exact version if you depend on them.
491
492
  | `discover_deployment`, `open_lanes` | Read a vault's crosschain market from the hub alone (executors with transport, factory, fuses, attestation keys and spokes served; remote vaults per spoke) and open every lane; `LANES` maps a transport kind to its lane class |
492
493
  | `CrosschainSimulator` | Multi-chain `eth_simulateV1` relay: replays LayerZero and CCIP messages between pinned chains by impersonating the endpoint or router on delivery, no bridge needed |
493
494
  | `ccip_token_lane` | Whether a CCIP message lane exists from a chain and whether a token's pool serves it, read on Chainlink's Router, OnRamp, TokenAdminRegistry and pool |
494
- | `decode_hypercore_event`, `hypercore_events` | The HyperCore fuse, pending-library, settlement and reporter events, decoded by topic with their raw log identity under the same input contract as `decode_external_state_event`; a malformed listed log raises `HyperCoreEventDecodeError` |
495
+ | `decode_hypercore_event`, `hypercore_events` | The HyperCore fuse events and the pending library's `HyperCoreActionEnqueued` / `HyperCoreActionSettled`, decoded by topic with their raw log identity under the same input contract as `decode_external_state_event`; a malformed listed log raises `HyperCoreEventDecodeError` |
495
496
  | Crosschain fuses (market 54): `StargateCrosschainSupplyFuse`, `StargateCrosschainCommandFuse`, `CcipCrosschainSupplyFuse`, `CcipCrosschainCommandFuse`, `CrosschainClaimFuse`; transport-agnostic bases `CrosschainSupplyFuse` / `CrosschainCommandFuse` with `StargateSendParams` / `CcipSendParams`, plus `Command`, `CrosschainSubstrateLib`, `OptionsBuilder` | `ipor_fusion.crosschain` |
496
497
  | HyperCore fuses (market 55): `HyperCoreDepositFuse`, `HyperCoreMarginFuse`, `HyperCoreSendFuse`, `HyperCoreOrderFuse`, `HyperCoreCancelFuse`, `HyperCoreBuilderFeeFuse`, `HyperCoreSubstrates` | `ipor_fusion.hypercore`, with `HyperCoreReader`, `read_hypercore_vault_state` and the event decoders |
497
498
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ipor-fusion"
3
- version = "4.0.0.dev327"
3
+ version = "4.0.0.dev334"
4
4
  description = "The IPOR Fusion SDK for Python"
5
5
  authors = [
6
6
  { name = "Adam Mydlarz", email = "amydlarz@gmail.com" },
@@ -23,9 +23,9 @@ class PreviewFeature:
23
23
 
24
24
  # Stated once here and surfaced by `server_info`, `fusion changelog`, the
25
25
  # README and the module docstrings, so no reader can miss it: the contracts
26
- # behind these are under active development, their mainnet deployments are
27
- # a proof of concept and IPOR Labs canaries, and their interfaces may change
28
- # between minor versions. Nothing under these names should route production
26
+ # behind these are under active development, the SDK follows only their
27
+ # official deployment, and their interfaces may change or be removed between
28
+ # minor versions. Nothing under these names should route production
29
29
  # capital. Every other feature of the package is production.
30
30
  PREVIEW_FEATURES: tuple[PreviewFeature, ...] = (
31
31
  PreviewFeature(
@@ -40,9 +40,8 @@ PREVIEW_FEATURES: tuple[PreviewFeature, ...] = (
40
40
  )
41
41
  PREVIEW_STATEMENT = (
42
42
  "Preview, not production: the contracts are under active development, the "
43
- "mainnet deployments are a proof of concept and IPOR Labs canaries, and "
44
- "interfaces may change or be removed between minor versions, with no "
45
- "backward compatibility."
43
+ "SDK follows only their official deployment, and interfaces may change or "
44
+ "be removed between minor versions, with no backward compatibility."
46
45
  )
47
46
 
48
47
  _DISTRIBUTION = "ipor-fusion"
@@ -19,6 +19,12 @@ T_co = TypeVar("T_co", covariant=True)
19
19
  U = TypeVar("U")
20
20
 
21
21
 
22
+ class _AbiDecodeFailure(DecodingError):
23
+ """The cause `Call.decode` chains a ``decode_error`` translation from, so an
24
+ optional batch read can tell an undecodable answer (``None``) apart from any
25
+ other error a decoder raises."""
26
+
27
+
22
28
  # No ``slots=True``: on early 3.11 and 3.12 patch releases (3.11.1, 3.12.0 and
23
29
  # 3.12.1 checked) ``Call[int](...)`` on a slotted frozen generic dataclass
24
30
  # raises ``TypeError`` when typing sets ``__orig_class__`` on the instance.
@@ -122,7 +128,9 @@ class Call(Generic[T_co]):
122
128
  except DecodingError as exc:
123
129
  if self.decode_error is None:
124
130
  raise
125
- raise self.decode_error(exc) from exc
131
+ marker = _AbiDecodeFailure(str(exc))
132
+ marker.__cause__ = exc
133
+ raise self.decode_error(exc) from marker
126
134
  single: object = values[0] if len(values) == 1 else values
127
135
  if self.decoder is not None:
128
136
  return self.decoder(single)
@@ -9,7 +9,7 @@ from web3 import Web3
9
9
  from web3.exceptions import ContractLogicError
10
10
 
11
11
  from ipor_fusion.core.context import Web3Context
12
- from ipor_fusion.core.contract import Call, ContractWrapper
12
+ from ipor_fusion.core.contract import Call, ContractWrapper, _AbiDecodeFailure
13
13
  from ipor_fusion.errors import EmptyCallResultError
14
14
 
15
15
  T = TypeVar("T")
@@ -226,6 +226,13 @@ class Multicall3Batch:
226
226
  settle(result)
227
227
 
228
228
 
229
+ def _translated_decode_failure(exc: Exception) -> bool:
230
+ """Whether ``exc`` is a `Call.decode_error` translation of an undecodable
231
+ answer: it names the failure for required reads, while an optional read of
232
+ the same answer is ``None``."""
233
+ return isinstance(exc.__cause__, _AbiDecodeFailure)
234
+
235
+
229
236
  def _try_decode(call: Call[T], ok: bool, data: bytes) -> T | None:
230
237
  if not ok or not data:
231
238
  return None
@@ -233,6 +240,10 @@ def _try_decode(call: Call[T], ok: bool, data: bytes) -> T | None:
233
240
  return call.decode(data)
234
241
  except DecodingError:
235
242
  return None
243
+ except Exception as exc:
244
+ if _translated_decode_failure(exc):
245
+ return None
246
+ raise
236
247
 
237
248
 
238
249
  def _try_call(call: Call[T], ctx: Web3Context) -> T | None:
@@ -240,3 +251,7 @@ def _try_call(call: Call[T], ctx: Web3Context) -> T | None:
240
251
  return call.call(ctx)
241
252
  except _CALL_FAILURES:
242
253
  return None
254
+ except Exception as exc:
255
+ if _translated_decode_failure(exc):
256
+ return None
257
+ raise
@@ -7,7 +7,7 @@ transport and lane. This namespace exports all of it; the transport
7
7
  subpackages export only their codecs and wrappers, because the encoders import
8
8
  those and a package's ``__init__`` runs before any of its modules.
9
9
 
10
- Status: preview, not production. The contracts behind it are under active development, the mainnet deployments are a proof of concept and IPOR Labs canaries, and interfaces may change between minor versions; see ``ipor_fusion.about.PREVIEW_FEATURES``.
10
+ Status: preview, not production. The contracts behind it are under active development, the SDK follows only their official deployment, and interfaces may change or be removed between minor versions, with no backward compatibility; see ``ipor_fusion.about.PREVIEW_FEATURES``.
11
11
  """
12
12
 
13
13
  from ipor_fusion.crosschain.ccip.chainlink import (
@@ -1,8 +1,10 @@
1
1
  """HyperCore (Hyperliquid) vaults, market 55: preview.
2
2
 
3
3
  The fuses, readers, events and identifiers of the HyperCore market. A
4
- preview feature (`ipor_fusion.PREVIEW_FEATURES`): its names may change in a
5
- minor release, which is why they live here rather than in `ipor_fusion`.
4
+ preview feature (`ipor_fusion.PREVIEW_FEATURES`) that follows only the
5
+ official deployment: its names may change or be removed in a minor release,
6
+ with no backward compatibility, which is why they live here rather than in
7
+ `ipor_fusion`.
6
8
  """
7
9
 
8
10
  from ipor_fusion.fuses.hypercore import (
@@ -1175,9 +1175,8 @@ class PreviewFeatureModel(_Base):
1175
1175
  status: Literal["preview"] = Field(
1176
1176
  default="preview",
1177
1177
  description="Always 'preview': not production. The contracts are under "
1178
- "active development, the mainnet deployments are a proof of concept "
1179
- "and IPOR Labs canaries, and interfaces may change or be removed "
1180
- "between minor versions, with no backward compatibility. Route no "
1178
+ "active development, the SDK follows only their official deployment, "
1179
+ "and interfaces may change or be removed between minor versions, with no backward compatibility. Route no "
1181
1180
  "production capital through these features.",
1182
1181
  )
1183
1182
 
@@ -141,8 +141,9 @@ def _market_id_call(fuse: FuseAddress) -> Call[MarketId]:
141
141
 
142
142
 
143
143
  def _pinned(ctx: Web3Context) -> tuple[Web3Context, int]:
144
- default = ctx.default_block
145
- block = default if isinstance(default, int) else ctx.web3.eth.block_number
144
+ """``ctx`` pinned to the number of the block it names (a number, hash or tag
145
+ such as ``finalized``), resolved once."""
146
+ block = int(ctx.web3.eth.get_block(ctx.default_block)["number"])
146
147
  return ctx.at_block(block), block
147
148
 
148
149
 
@@ -321,7 +322,8 @@ def preflight_execute(
321
322
  simulate: bool = True,
322
323
  ) -> ExecutePreflight:
323
324
  """Check ``actions`` as ``sender``'s `PlasmaVault.execute` on the state of one
324
- base block (``ctx.default_block`` when it is a number, else the latest).
325
+ base block: the one ``ctx.default_block`` names (a number, hash or tag),
326
+ resolved once.
325
327
 
326
328
  The static checks take a few Multicall3 batches (one per dependency-graph
327
329
  level), the ``canCall`` read, the balance-fuse storage reads and, for a
@@ -370,3 +370,85 @@ class TestBatch:
370
370
  batch.run()
371
371
  assert [to for to, _ in seen] == [MULTICALL3_ADDRESS, TOKEN_B]
372
372
  assert {block for _, block in seen} == {TestPinnedContext.BLOCK}
373
+
374
+
375
+ class TestNamedDecodeErrors:
376
+ """A Call whose decode_error names an undecodable answer (an earlier
377
+ dispatcher's six-word observation): required reads raise the named error,
378
+ optional reads are None, with Multicall3 and without it."""
379
+
380
+ DISPATCHER = Web3.to_checksum_address("0x" + "cc" * 20)
381
+ SIX_WORDS = encode(["uint256"] * 6, [1, 2, 3, 4, 5, 6])
382
+
383
+ def _observation(self) -> Call[object]:
384
+ from ipor_fusion.crosschain import CcipCrosschainDispatcher
385
+
386
+ return CcipCrosschainDispatcher(self.DISPATCHER).observation()
387
+
388
+ def _answer(self, _to: str, _data: bytes) -> bytes:
389
+ return self.SIX_WORDS
390
+
391
+ def _contexts(self) -> list[MagicMock]:
392
+ return [
393
+ _ctx(self._answer),
394
+ TestWithoutMulticall3._ctx_without_multicall(self._answer),
395
+ ]
396
+
397
+ def test_required_reads_raise_the_named_error(self):
398
+ from ipor_fusion.errors import UnsupportedContractVersionError
399
+
400
+ for ctx in self._contexts():
401
+ with pytest.raises(
402
+ UnsupportedContractVersionError, match="released 8-field"
403
+ ):
404
+ self._observation().call(ctx)
405
+ with pytest.raises(UnsupportedContractVersionError):
406
+ Multicall3(ctx).aggregate([self._observation()])
407
+ batch = Multicall3(ctx).batch()
408
+ batch.add(self._observation())
409
+ with pytest.raises(UnsupportedContractVersionError):
410
+ batch.run()
411
+
412
+ def test_optional_reads_are_none(self):
413
+ for ctx in self._contexts():
414
+ assert Multicall3(ctx).try_aggregate([self._observation()]) == [None]
415
+ batch = Multicall3(ctx).batch()
416
+ read = batch.try_add(self._observation())
417
+ mapped = batch.try_add(self._observation().map(lambda o: o))
418
+ batch.run()
419
+ assert (read.value, mapped.value) == (None, None)
420
+
421
+ def test_other_decoder_errors_still_propagate_from_optional_reads(self):
422
+ from eth_abi.exceptions import DecodingError
423
+
424
+ def buggy(_value: object) -> object:
425
+ raise ValueError("decoder bug") from DecodingError("inner")
426
+
427
+ def translate(exc: Exception) -> Exception:
428
+ return RuntimeError(f"named: {exc}")
429
+
430
+ valid = encode(["uint256"], [7])
431
+ decoded_badly = Call(
432
+ to=self.DISPATCHER,
433
+ data=SELECTOR,
434
+ output_types=["uint256"],
435
+ decoder=buggy,
436
+ decode_error=translate,
437
+ )
438
+ mapped_badly = Call(
439
+ to=self.DISPATCHER,
440
+ data=SELECTOR,
441
+ output_types=["uint256"],
442
+ decode_error=translate,
443
+ ).map(buggy)
444
+ for ctx in [
445
+ _ctx(lambda _to, _data: valid),
446
+ TestWithoutMulticall3._ctx_without_multicall(lambda _to, _data: valid),
447
+ ]:
448
+ for call in (decoded_badly, mapped_badly):
449
+ with pytest.raises(ValueError, match="decoder bug"):
450
+ Multicall3(ctx).try_aggregate([call])
451
+ batch = Multicall3(ctx).batch()
452
+ batch.try_add(call)
453
+ with pytest.raises(ValueError, match="decoder bug"):
454
+ batch.run()
@@ -85,7 +85,7 @@ def _ctx(
85
85
  ctx.chain_id = 8453
86
86
  ctx.at_block.return_value = ctx
87
87
  ctx.call.side_effect = multicall_aware(handler)
88
- ctx.web3.eth.get_block.return_value = {"timestamp": NOW}
88
+ ctx.web3.eth.get_block.return_value = {"number": BLOCK, "timestamp": NOW}
89
89
  return ctx
90
90
 
91
91
 
@@ -231,6 +231,22 @@ class _FakeSimulator:
231
231
  return self.outcome
232
232
 
233
233
 
234
+ @pytest.mark.parametrize("named", ["finalized", "safe", "0x" + "ab" * 32, "latest"])
235
+ def test_the_block_the_context_names_is_resolved_and_pinned(monkeypatch, named):
236
+ monkeypatch.setattr(preflight_module, "is_simulate_v1_supported", lambda w3: True)
237
+ monkeypatch.setattr(preflight_module, "VaultSimulator", _FakeSimulator)
238
+ ctx = _ctx()
239
+ ctx.default_block = named
240
+
241
+ result = preflight_execute(ctx, VAULT, [_supply()], sender=SENDER)
242
+
243
+ ctx.web3.eth.get_block.assert_called_once_with(named)
244
+ ctx.at_block.assert_called_once_with(BLOCK)
245
+ # _FakeSimulator asserts it was built with block=BLOCK: the simulation
246
+ # runs on top of the resolved block, not the latest.
247
+ assert result.block_number == BLOCK
248
+
249
+
234
250
  def test_the_simulation_reports_total_assets_and_a_revert(monkeypatch):
235
251
  monkeypatch.setattr(preflight_module, "is_simulate_v1_supported", lambda w3: True)
236
252
  monkeypatch.setattr(preflight_module, "VaultSimulator", _FakeSimulator)