ipor-fusion 4.0.0.dev215__tar.gz → 4.0.0.dev222__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 (341) hide show
  1. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/AGENTS.md +5 -2
  2. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/MIGRATION_4.md +7 -0
  3. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/PKG-INFO +1 -1
  4. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/pyproject.toml +1 -1
  5. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/substrates.py +87 -5
  6. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_substrates.py +108 -6
  7. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/.claude-plugin/marketplace.json +0 -0
  8. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/.claude-plugin/plugin.json +0 -0
  9. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/.env.example +0 -0
  10. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/.gemini/settings.json +0 -0
  11. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/.git-blame-ignore-revs +0 -0
  12. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/.github/workflows/cd.yml +0 -0
  13. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/.github/workflows/ci.yml +0 -0
  14. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/.github/workflows/commit-lint.yml +0 -0
  15. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/.github/workflows/notify-slack.yml +0 -0
  16. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/.github/workflows/python-build.yml +0 -0
  17. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/.github/workflows/python-publish.yml +0 -0
  18. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/.github/workflows/release.yml +0 -0
  19. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/.github/workflows/report-slack.yml +0 -0
  20. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/.gitignore +0 -0
  21. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/.mcp.json +0 -0
  22. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/.pre-commit-config.yaml +0 -0
  23. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/.python-version +0 -0
  24. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/CHANGELOG.md +0 -0
  25. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/CLAUDE.md +0 -0
  26. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/CODEOWNERS +0 -0
  27. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/LICENSE +0 -0
  28. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/README.md +0 -0
  29. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/build.sh +0 -0
  30. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/examples/CONTRIBUTING.md +0 -0
  31. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/examples/README.md +0 -0
  32. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/examples/advanced_euler_v2_credit_market_base.py +0 -0
  33. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/examples/advanced_euler_v2_looping_arbitrum.py +0 -0
  34. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/examples/composed_hypercore_flow_arbitrum_hyperevm.py +0 -0
  35. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py +0 -0
  36. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/examples/external_state_margin_leg_base.py +0 -0
  37. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/examples/simple_aave_v3_supply_base.py +0 -0
  38. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/pytest.ini +0 -0
  39. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/scripts/commit-check.sh +0 -0
  40. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/scripts/crosschain_readiness.py +0 -0
  41. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/skills/ipor-deploy-vault/SKILL.md +0 -0
  42. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/__init__.py +0 -0
  43. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/about.py +0 -0
  44. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/cache.py +0 -0
  45. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/chains.py +0 -0
  46. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/cli/__init__.py +0 -0
  47. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/cli/changelog_cmd.py +0 -0
  48. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/cli/config_cmd.py +0 -0
  49. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/cli/config_store.py +0 -0
  50. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/cli/main.py +0 -0
  51. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/cli/market_cmd.py +0 -0
  52. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/cli/options.py +0 -0
  53. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/cli/oracle_mapping_view.py +0 -0
  54. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/cli/vault_cmd.py +0 -0
  55. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/cli/vault_health.py +0 -0
  56. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/cli/vault_info_view.py +0 -0
  57. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/cli/vault_markets_view.py +0 -0
  58. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/cli/vault_rendering.py +0 -0
  59. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/config/__init__.py +0 -0
  60. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/config/roles.py +0 -0
  61. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/core/__init__.py +0 -0
  62. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/core/access.py +0 -0
  63. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/core/address.py +0 -0
  64. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/core/context.py +0 -0
  65. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/core/contract.py +0 -0
  66. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/core/erc20.py +0 -0
  67. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/core/external_state_executor.py +0 -0
  68. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/core/fee_manager.py +0 -0
  69. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/core/fuse.py +0 -0
  70. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/core/fuse_action.py +0 -0
  71. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/core/fusion_factory.py +0 -0
  72. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/core/logs.py +0 -0
  73. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/core/multicall.py +0 -0
  74. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/core/oracle.py +0 -0
  75. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/core/plasma_vault.py +0 -0
  76. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/core/rewards_manager.py +0 -0
  77. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/core/simulation.py +0 -0
  78. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/core/simulation_result.py +0 -0
  79. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/core/withdraw_manager.py +0 -0
  80. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/__init__.py +0 -0
  81. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/ccip/__init__.py +0 -0
  82. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/ccip/chainlink.py +0 -0
  83. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/ccip/codec.py +0 -0
  84. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/ccip/contracts.py +0 -0
  85. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/ccip/events.py +0 -0
  86. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/ccip/indexer.py +0 -0
  87. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/ccip/lane.py +0 -0
  88. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/ccip/quote.py +0 -0
  89. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/ccip/transport.py +0 -0
  90. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/contracts.py +0 -0
  91. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/discovery.py +0 -0
  92. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/errors.py +0 -0
  93. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/fuses/__init__.py +0 -0
  94. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/fuses/base.py +0 -0
  95. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/fuses/ccip.py +0 -0
  96. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/fuses/stargate.py +0 -0
  97. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/lane.py +0 -0
  98. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/logs.py +0 -0
  99. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/messages.py +0 -0
  100. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/simulation.py +0 -0
  101. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/stargate/__init__.py +0 -0
  102. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/stargate/contracts.py +0 -0
  103. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/stargate/lane.py +0 -0
  104. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/stargate/layerzero.py +0 -0
  105. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/stargate/transport.py +0 -0
  106. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/crosschain/transport.py +0 -0
  107. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/dependency_graph.py +0 -0
  108. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/entry_cli.py +0 -0
  109. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/entry_mcp.py +0 -0
  110. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/errors.py +0 -0
  111. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/explorer.py +0 -0
  112. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/field_docs.py +0 -0
  113. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/fuses/__init__.py +0 -0
  114. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/fuses/aave_v3.py +0 -0
  115. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/fuses/async_action.py +0 -0
  116. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/fuses/base.py +0 -0
  117. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/fuses/compound_v3.py +0 -0
  118. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/fuses/erc4626.py +0 -0
  119. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/fuses/euler_v2.py +0 -0
  120. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/fuses/events.py +0 -0
  121. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/fuses/external_state.py +0 -0
  122. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/fuses/external_state_event_decoding.py +0 -0
  123. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/fuses/fluid_instadapp.py +0 -0
  124. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/fuses/gearbox_v3.py +0 -0
  125. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/fuses/hypercore.py +0 -0
  126. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/fuses/hypercore_event_decoding.py +0 -0
  127. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/fuses/merkl.py +0 -0
  128. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/fuses/morpho.py +0 -0
  129. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/fuses/ramses_v2.py +0 -0
  130. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/fuses/uniswap_v3.py +0 -0
  131. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/fuses/universal.py +0 -0
  132. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/guide/__init__.py +0 -0
  133. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/guide/architecture.md +0 -0
  134. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/guide/glossary.md +0 -0
  135. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/guide/invariants.md +0 -0
  136. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/guide/quickstart.md +0 -0
  137. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/hypercore/__init__.py +0 -0
  138. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/market_ids.py +0 -0
  139. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/market_info.py +0 -0
  140. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/mcp/__init__.py +0 -0
  141. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/mcp/guide.py +0 -0
  142. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/mcp/models.py +0 -0
  143. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/mcp/server.py +0 -0
  144. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/morpho_api.py +0 -0
  145. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/py.typed +0 -0
  146. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/readers/__init__.py +0 -0
  147. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/readers/aave_v3.py +0 -0
  148. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/readers/aave_v4.py +0 -0
  149. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/readers/compound_v3.py +0 -0
  150. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/readers/hypercore.py +0 -0
  151. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/readers/hypercore_outcome.py +0 -0
  152. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/readers/lending_health.py +0 -0
  153. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/readers/morpho.py +0 -0
  154. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/readers/oracle_mapping.py +0 -0
  155. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/readers/oracle_mapping_nodes.py +0 -0
  156. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/readers/oracle_mapping_reader.py +0 -0
  157. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/readers/position_manager.py +0 -0
  158. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/readers/ramses_v2.py +0 -0
  159. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/readers/uniswap_v3.py +0 -0
  160. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/readers/unpriceable.py +0 -0
  161. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/types.py +0 -0
  162. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/validation.py +0 -0
  163. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/vault_data.py +0 -0
  164. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/vault_erc20.py +0 -0
  165. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/vault_info.py +0 -0
  166. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/vault_managers.py +0 -0
  167. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/vault_positions.py +0 -0
  168. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/src/ipor_fusion/vault_reads.py +0 -0
  169. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/UniswapV3UniversalRouter.py +0 -0
  170. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/_crosschain.py +0 -0
  171. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/_crosschain_lifecycle.py +0 -0
  172. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/_crosschain_recovery.py +0 -0
  173. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/_euler_v2.py +0 -0
  174. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/_event_args.py +0 -0
  175. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/_fake_rpc.py +0 -0
  176. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/_foundry.py +0 -0
  177. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/_golden.py +0 -0
  178. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/_guide.py +0 -0
  179. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/_hypercore_model.py +0 -0
  180. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/_hypercore_shadow.py +0 -0
  181. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/_live.py +0 -0
  182. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/_multicall.py +0 -0
  183. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/_oracle_mapping_fake.py +0 -0
  184. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/_simulate.py +0 -0
  185. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/_validation.py +0 -0
  186. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/addresses.py +0 -0
  187. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/conftest.py +0 -0
  188. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/constants.py +0 -0
  189. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/hypercore_hip3_flow.json +0 -0
  190. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/hypercore_market55.json +0 -0
  191. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/market_golden/meta_morpho_v1.json +0 -0
  192. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/market_golden/meta_morpho_v1.mcp.json +0 -0
  193. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/market_golden/meta_morpho_v2.json +0 -0
  194. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/market_golden/meta_morpho_v2.mcp.json +0 -0
  195. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/market_golden/morpho_api/market.json +0 -0
  196. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/market_golden/morpho_api/vault_v1.json +0 -0
  197. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/market_golden/morpho_api/vault_v2.json +0 -0
  198. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/market_golden/morpho_api/vault_v2_not_found.json +0 -0
  199. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/market_golden/morpho_blue.json +0 -0
  200. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/market_golden/morpho_blue.mcp.json +0 -0
  201. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/market_golden/morpho_blue_api_error.json +0 -0
  202. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/market_golden/morpho_blue_api_error.mcp.json +0 -0
  203. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/market_golden/morpho_blue_no_api.json +0 -0
  204. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/market_golden/morpho_blue_no_api.mcp.json +0 -0
  205. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/oracle_mapping_golden/mapping.json +0 -0
  206. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/oracle_mapping_golden/mapping.mcp.json +0 -0
  207. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/simulate_v1_request.json +0 -0
  208. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/vault_info_golden/clean.json +0 -0
  209. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/vault_info_golden/clean.mcp.json +0 -0
  210. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/vault_info_golden/clean.txt +0 -0
  211. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/vault_info_golden/deployment_error.json +0 -0
  212. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/vault_info_golden/deployment_error.mcp.json +0 -0
  213. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/vault_info_golden/deployment_error.txt +0 -0
  214. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/vault_info_golden/fetched.cli.json +0 -0
  215. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/vault_info_golden/fetched.json +0 -0
  216. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/vault_info_golden/fetched.mcp.json +0 -0
  217. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/vault_info_golden/full.json +0 -0
  218. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/vault_info_golden/full.mcp.json +0 -0
  219. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/vault_info_golden/full.txt +0 -0
  220. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/vault_info_golden/rich.json +0 -0
  221. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/vault_info_golden/rich.mcp.json +0 -0
  222. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/fixtures/vault_info_golden/rich.txt +0 -0
  223. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_about.py +0 -0
  224. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_access_manager.py +0 -0
  225. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_cache.py +0 -0
  226. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_chains.py +0 -0
  227. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_cli_changelog.py +0 -0
  228. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_cli_commands.py +0 -0
  229. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_cli_config_store.py +0 -0
  230. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_cli_helpers.py +0 -0
  231. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_cli_hypercore.py +0 -0
  232. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_cli_lending_health.py +0 -0
  233. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_cli_market_golden.py +0 -0
  234. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_cli_market_morpho_blue.py +0 -0
  235. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_cli_oracle_mapping.py +0 -0
  236. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_cli_oracle_mapping_golden.py +0 -0
  237. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_cli_pending_requests_scan.py +0 -0
  238. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_cli_role_accounts.py +0 -0
  239. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_cli_vault_info_golden.py +0 -0
  240. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_cli_vault_predates_getters.py +0 -0
  241. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_cli_vault_validate.py +0 -0
  242. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_contract_call.py +0 -0
  243. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_contract_encoder.py +0 -0
  244. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_crosschain_ccip_events.py +0 -0
  245. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_crosschain_ccip_indexer.py +0 -0
  246. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_crosschain_ccip_quote.py +0 -0
  247. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_crosschain_chainlink.py +0 -0
  248. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_crosschain_contracts.py +0 -0
  249. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_crosschain_encoding.py +0 -0
  250. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_crosschain_errors.py +0 -0
  251. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_crosschain_lane.py +0 -0
  252. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_crosschain_layering.py +0 -0
  253. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_crosschain_readiness.py +0 -0
  254. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_crosschain_readiness_report.py +0 -0
  255. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_crosschain_transport.py +0 -0
  256. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_docs_typing.py +0 -0
  257. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_erc20.py +0 -0
  258. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_error_hierarchy.py +0 -0
  259. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_examples_composed_hypercore.py +0 -0
  260. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_examples_crosschain.py +0 -0
  261. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_examples_euler_looping_arbitrum.py +0 -0
  262. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_examples_vaults.py +0 -0
  263. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_explorer.py +0 -0
  264. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_external_state_events.py +0 -0
  265. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_external_state_executor.py +0 -0
  266. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_fee_manager.py +0 -0
  267. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_fuse_encoding.py +0 -0
  268. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_fusion_instance.py +0 -0
  269. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_guide.py +0 -0
  270. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_hypercore_deployment.py +0 -0
  271. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_hypercore_events.py +0 -0
  272. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_hypercore_flow.py +0 -0
  273. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_hypercore_live.py +0 -0
  274. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_hypercore_outcome.py +0 -0
  275. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_hypercore_readers.py +0 -0
  276. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_hypercore_simulation.py +0 -0
  277. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_logs.py +0 -0
  278. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_mcp_hypercore.py +0 -0
  279. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_mcp_models.py +0 -0
  280. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_mcp_server.py +0 -0
  281. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_mcp_vault_validate.py +0 -0
  282. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_multicall.py +0 -0
  283. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_oracle.py +0 -0
  284. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_oracle_mapping.py +0 -0
  285. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_plasma_vault.py +0 -0
  286. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_public_api.py +0 -0
  287. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_public_type_reachability.py +0 -0
  288. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_reader_encoding.py +0 -0
  289. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_readiness_selection.py +0 -0
  290. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_revert_decoding.py +0 -0
  291. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_rewards_manager.py +0 -0
  292. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_roles.py +0 -0
  293. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_sdk_layering.py +0 -0
  294. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_borrow_aave_v3_mainnet.py +0 -0
  295. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_claim_merkl_wrapper_base.py +0 -0
  296. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_claim_morpho_rewards.py +0 -0
  297. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_crosschain_canary.py +0 -0
  298. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_crosschain_hypercore.py +0 -0
  299. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_crosschain_hyperevm.py +0 -0
  300. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_crosschain_lifecycle.py +0 -0
  301. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_euler_v2_batch_base.py +0 -0
  302. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_euler_v2_credit_market_base.py +0 -0
  303. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_euler_v2_swap_deploy_base.py +0 -0
  304. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_euler_v2_swap_reconfigure_base.py +0 -0
  305. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_euler_v2_swap_registry_base.py +0 -0
  306. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_examples_arbitrum.py +0 -0
  307. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_examples_base.py +0 -0
  308. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_examples_crosschain.py +0 -0
  309. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_external_state_executor_base.py +0 -0
  310. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_fusion_factory_clone_base.py +0 -0
  311. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_looping_aave_v3_base.py +0 -0
  312. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_looping_morpho_blue_base.py +0 -0
  313. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_morpho_blue.py +0 -0
  314. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_pilot_v3.py +0 -0
  315. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_pilot_v4_uniswap.py +0 -0
  316. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_pilot_v5_ramses.py +0 -0
  317. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_pilot_v5_scheduled.py +0 -0
  318. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_plasma_vault_setters_base.py +0 -0
  319. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_readers_integration.py +0 -0
  320. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_release_funds.py +0 -0
  321. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_swap_on_base.py +0 -0
  322. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulate_vault_from_scratch_base.py +0 -0
  323. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulation_errors.py +0 -0
  324. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_simulation_observation.py +0 -0
  325. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_solidity_compiler.py +0 -0
  326. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_solidity_mirrors.py +0 -0
  327. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_types_and_events.py +0 -0
  328. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_unpriceable_tokens.py +0 -0
  329. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_validation.py +0 -0
  330. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_vault_data_block.py +0 -0
  331. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_vault_dep_graph.py +0 -0
  332. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_vault_info_fetched_golden.py +0 -0
  333. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_vault_info_onchain_base.py +0 -0
  334. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_vault_info_onchain_base_no_withdraw_manager.py +0 -0
  335. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_vault_reconciliation_onchain_base.py +0 -0
  336. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_vault_simulator_blocks.py +0 -0
  337. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_web3_context.py +0 -0
  338. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/test_withdraw_manager.py +0 -0
  339. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/typed_client/consumer.py +0 -0
  340. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/tests/typed_client/rejected.py +0 -0
  341. {ipor_fusion-4.0.0.dev215 → ipor_fusion-4.0.0.dev222}/uv.lock +0 -0
@@ -447,8 +447,11 @@ decoder sets a `type_label` (enum name or a protocol tag like `EULER_VAULT`);
447
447
  a label-less decode renders as a generic placeholder in every consumer.
448
448
  Plain-address decoding only when the fuses check `isSubstrateAsAssetGranted`;
449
449
  typed layouts get their own decoder with the enum labels carried over. A
450
- market with no substrate semantics stays unregistered ON PURPOSE and renders
451
- as a loud `no_decoder(NAME)` (e.g. LITE_PSM=48). Never default to
450
+ market with no substrate semantics, or whose layout cannot be verified, stays
451
+ unregistered ON PURPOSE with its reason in `_UNREGISTERED_ON_PURPOSE` and
452
+ renders as a loud `no_decoder(NAME)` (e.g. LITE_PSM=48);
453
+ `test_every_market_has_a_decoder_or_a_reason` fails for a member that has
454
+ neither. Never default to
452
455
  plain-address or guess a layout: a wrong decoder renders plausible-looking
453
456
  garbage addresses that consumers act on, so it is worse than none (Aave V4,
454
457
  id 49, is the documented case in `substrates.py`). `decode_substrate` handles
@@ -990,6 +990,13 @@ and `log_index` was passed through as given (a hex string from a raw log); the e
990
990
  These apply to every caller, type-checked or not. Changes described in full above
991
991
  are listed with a link.
992
992
 
993
+ - **More markets decode their substrates.** VELODROME_SUPERCHAIN (31, Gauge /
994
+ Pool), AGUA_GLOBAL_CARRY (51, VAULT / ASSET), TERM_FINANCE (52, SERVICER address
995
+ or COLLATERAL_TOKEN pair key), META_MORPHO_0001, MERKL and
996
+ ASSETS_BALANCE_VALIDATION (plain addresses) were `no_decoder(NAME)` in 3.x and
997
+ now decode per their Solidity substrate libraries and grant checks. The markets
998
+ still without a decoder are listed with their reason.
999
+
993
1000
  - **`CcipLane.open` refuses a spoke it cannot reach.** The executor's
994
1001
  `ccipRoute(spoke)` must be registered and point at the dispatcher at the
995
1002
  executor's own address; otherwise `open` (and `open_lane` / `open_lanes`)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: ipor-fusion
3
- Version: 4.0.0.dev215
3
+ Version: 4.0.0.dev222
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ipor-fusion"
3
- version = "4.0.0.dev215"
3
+ version = "4.0.0.dev222"
4
4
  description = "The IPOR Fusion SDK for Python"
5
5
  authors = [
6
6
  { name = "Adam Mydlarz", email = "amydlarz@gmail.com" },
@@ -77,6 +77,45 @@ def _decode_plain_address(hex_str: str) -> SubstrateInfo:
77
77
  return SubstrateInfo(address=_address(hex_str[24:]))
78
78
 
79
79
 
80
+ def _noncanonical(hex_str: str) -> SubstrateInfo:
81
+ return SubstrateInfo(
82
+ raw_hex=f"0x{hex_str}", type_label="noncanonical", is_error=True
83
+ )
84
+
85
+
86
+ def _decode_strict_plain_address(hex_str: str) -> SubstrateInfo:
87
+ """A substrate-as-asset address: ``isSubstrateAsAssetGranted`` grants only
88
+ the zero-padded word, so dirty upper bits are no grant of the low address."""
89
+ if hex_str[:24] != "0" * 24:
90
+ return _noncanonical(hex_str)
91
+ return _decode_plain_address(hex_str)
92
+
93
+
94
+ def _decode_strict_type_lshift160(hex_str: str, types: dict[int, str]) -> SubstrateInfo:
95
+ """type<<160 | address where Solidity converts the whole ``word >> 160`` to
96
+ the enum: any other upper bits, or a value outside it, reverts there."""
97
+ if hex_str[:22] != "0" * 22 or int(hex_str[22:24], 16) not in types:
98
+ return _noncanonical(hex_str)
99
+ return _decode_type_lshift160(hex_str, types)
100
+
101
+
102
+ def _decode_term_finance(hex_str: str) -> SubstrateInfo:
103
+ """TermFinanceSubstrateLib.sol: a SERVICER is the TermRepoServicer address
104
+ in the plain zero-padded form (the whole upper 96 bits zero, as the fuses'
105
+ strict ``isServicerSubstrate`` requires); a COLLATERAL_TOKEN is type byte
106
+ 0x01 over ``keccak256(abi.encode(servicer, collateralToken))`` truncated to
107
+ 248 bits, a pair key and not an address."""
108
+ if hex_str[:24] == "0" * 24:
109
+ return SubstrateInfo(address=_address(hex_str[24:]), type_label="SERVICER")
110
+ if hex_str[:2] == "01":
111
+ return SubstrateInfo(raw_hex=f"0x{hex_str}", type_label="COLLATERAL_TOKEN")
112
+ return SubstrateInfo(
113
+ raw_hex=f"0x{hex_str}",
114
+ type_label=f"type={int(hex_str[:2], 16)}",
115
+ is_error=True,
116
+ )
117
+
118
+
80
119
  def _decode_morpho(hex_str: str) -> SubstrateInfo:
81
120
  """Raw bytes32 Morpho market ID — no structure."""
82
121
  return SubstrateInfo(raw_hex=f"0x{hex_str}", type_label="morpho_market_id")
@@ -441,6 +480,19 @@ _register_markets(
441
480
  ],
442
481
  _decode_plain_address,
443
482
  )
483
+ # Substrate-as-asset markets registered from their grant checks, decoded
484
+ # strictly (a word with dirty upper bits grants nothing):
485
+ # META_MORPHO_0001 is deployed as Erc4626SupplyFuse (the MetaMorpho vault),
486
+ # MERKL as MerklClaimWrapperFuse (the reward tokens it forwards) and
487
+ # ASSETS_BALANCE_VALIDATION as PlasmaVaultBalanceAssetsValidationFuse.
488
+ _register_markets(
489
+ [
490
+ 200_001,
491
+ IporFusionMarkets.MERKL,
492
+ IporFusionMarkets.ASSETS_BALANCE_VALIDATION,
493
+ ],
494
+ _decode_strict_plain_address,
495
+ )
444
496
  # Morpho markets — raw bytes32 market ids. MORPHO_FLASH_LOAN (19) is NOT one:
445
497
  # MorphoFlashLoanFuse gates the loan token via isSubstrateAsAssetGranted, and
446
498
  # every live market-19 substrate is the zero-padded address form (registry
@@ -478,6 +530,21 @@ _register_markets(
478
530
  [32],
479
531
  lambda h: _decode_type_lshift160(h, {0: "UNDEFINED", 1: "Gauge", 2: "Pool"}),
480
532
  )
533
+ # Velodrome Superchain (VelodromeSuperchainLib.sol): the same type<<160 Gauge /
534
+ # Pool layout, decoded strictly
535
+ _register_markets(
536
+ [31],
537
+ lambda h: _decode_strict_type_lshift160(h, {0: "UNDEFINED", 1: "Gauge", 2: "Pool"}),
538
+ )
539
+ # Agua Global Carry (AguaSubstrateLib.sol): type<<160 | address
540
+ _register_markets(
541
+ [51],
542
+ lambda h: _decode_strict_type_lshift160(
543
+ h, {0: "UNDEFINED", 1: "VAULT", 2: "ASSET"}
544
+ ),
545
+ )
546
+ # Term Finance (TermFinanceSubstrateLib.sol): SERVICER / COLLATERAL_TOKEN
547
+ _register_markets([52], _decode_term_finance)
481
548
  # Aave V4 (id 49 per IporFusionMarkets.sol) — typed Reserve substrates per
482
549
  # AaveV4SubstrateLib.sol; an earlier draft enum (Asset/Spoke, address in the
483
550
  # low bytes) shipped here and decoded live substrates to garbage addresses
@@ -514,11 +581,6 @@ _register_markets([40], _decode_async_action)
514
581
  # / four uint248 guards).
515
582
  _register_markets([50], _decode_external_state)
516
583
  # Uniswap V4 (id 53 per IporFusionMarkets.sol): PoolId or pool currency.
517
- # TERM_FINANCE (52) stays unregistered on purpose — its substrate library is
518
- # not mirrored here yet, and no_decoder(TERM_FINANCE) is the honest answer.
519
- # SPOL_UNSTAKE (424243) likewise: SPOLUnstakeFuse is not in the public
520
- # contracts repo, so its substrate grant check cannot be verified — the market
521
- # doc says the sPOLController address, but no_decoder until the fuse is mirrored
522
584
  _register_markets([53], _decode_uniswap_v4)
523
585
  # Crosschain (id 54 on the contracts' crosschain branch): EXECUTOR /
524
586
  # REMOTE_VAULT typed substrates per CrosschainSubstrateLib.sol. The mainnet
@@ -538,6 +600,26 @@ _register_markets(
538
600
  _register_markets([55], _decode_hypercore)
539
601
 
540
602
 
603
+ # Markets left without a decoder on purpose, each with the reason; they decode
604
+ # as no_decoder(NAME). tests/test_substrates.py holds every IporFusionMarkets
605
+ # member to a decoder or an entry here, so a new market cannot go unnoticed.
606
+ _UNREGISTERED_ON_PURPOSE: dict[MarketId, str] = {
607
+ IporFusionMarkets.LITE_PSM: "IporFusionMarkets.sol declares no substrates "
608
+ "(a ZeroBalanceFuse market)",
609
+ IporFusionMarkets.SPOL_UNSTAKE: "SPOLUnstakeFuse is not in the public contracts "
610
+ "repository, so its grant check cannot be verified",
611
+ **{
612
+ MarketId(mid): "no deployment or layout verified in the address registry; "
613
+ "META_MORPHO_0001 is an Erc4626SupplyFuse, but a later one is not assumed"
614
+ for mid in range(200_002, 200_011)
615
+ },
616
+ IporFusionMarkets.EXCHANGE_RATE_VALIDATOR: "packed hook and validator words "
617
+ "(ExchangeRateValidatorConfigLib), not addresses; not mirrored here yet",
618
+ IporFusionMarkets.ZERO_BALANCE_MARKET: "a capability market: no fuse defines a "
619
+ "substrate layout for it",
620
+ }
621
+
622
+
541
623
  def _build_market_lookup() -> dict[int, str]:
542
624
  lookup: dict[int, str] = {}
543
625
  for name in dir(IporFusionMarkets):
@@ -8,7 +8,10 @@ mainnet by tx 0x9321732ec456e44a46d6f10ba9eee956333c13f5a45fec3bd242218ce8c3ce93
8
8
  from __future__ import annotations
9
9
 
10
10
  import pytest
11
+ from eth_abi import encode
12
+ from eth_utils import keccak
11
13
 
14
+ from ipor_fusion import substrates
12
15
  from ipor_fusion.market_ids import IporFusionMarkets
13
16
  from ipor_fusion.substrates import SubstrateInfo, decode_substrate, market_name
14
17
 
@@ -269,16 +272,115 @@ def test_market_ids_52_and_53_follow_ipor_fusion_markets_sol():
269
272
  assert IporFusionMarkets.UNISWAP_V4 == 53
270
273
  assert market_name(52) == "TERM_FINANCE"
271
274
  assert market_name(53) == "UNISWAP_V4"
272
- # no substrate library mirrored for Term Finance yet: loud, never guessed
273
- info = decode_substrate("0x" + "11" * 32, market_id=52)
275
+
276
+
277
+ SERVICER = "0x" + "5e" * 20
278
+
279
+
280
+ def test_term_finance_servicer_is_the_plain_address():
281
+ info = decode_substrate("0x" + "00" * 12 + SERVICER[2:], market_id=52)
282
+ assert info == SubstrateInfo(address=SERVICER, type_label="SERVICER")
283
+
284
+
285
+ def test_term_finance_collateral_pair_key_is_not_an_address():
286
+ # TermFinanceSubstrateLib.collateralPairKey: 0x01 << 248 | keccak(...)[low 248]
287
+ key = keccak(encode(["address", "address"], [SERVICER, USDE]))
288
+ raw = "0x01" + key.hex()[2:]
289
+ info = decode_substrate(raw, market_id=52)
290
+ assert info == SubstrateInfo(raw_hex=raw, type_label="COLLATERAL_TOKEN")
291
+
292
+
293
+ def test_term_finance_unknown_word_is_an_error():
294
+ info = decode_substrate("0x02" + "11" * 31, market_id=52)
295
+ assert info.is_error
296
+ assert info.address is None
297
+ assert info.type_label == "type=2"
298
+
299
+
300
+ @pytest.mark.parametrize(("type_byte", "label"), [(1, "Gauge"), (2, "Pool")])
301
+ def test_velodrome_superchain_shares_the_slipstream_layout(type_byte, label):
302
+ raw = "0x" + "00" * 11 + f"{type_byte:02x}" + BOLD[2:]
303
+ for market_id in (31, 32):
304
+ info = decode_substrate(raw, market_id=market_id)
305
+ assert info == SubstrateInfo(address=BOLD, type_label=label)
306
+
307
+
308
+ @pytest.mark.parametrize(("type_byte", "label"), [(1, "VAULT"), (2, "ASSET")])
309
+ def test_agua_typed_substrates(type_byte, label):
310
+ raw = "0x" + "00" * 11 + f"{type_byte:02x}" + USDE[2:]
311
+ info = decode_substrate(raw, market_id=51)
312
+ assert info == SubstrateInfo(address=USDE, type_label=label)
313
+
314
+
315
+ @pytest.mark.parametrize(
316
+ "market_id",
317
+ [
318
+ IporFusionMarkets.MERKL,
319
+ IporFusionMarkets.ASSETS_BALANCE_VALIDATION,
320
+ IporFusionMarkets.META_MORPHO_0001,
321
+ ],
322
+ )
323
+ def test_substrate_as_asset_markets_decode_plain_addresses(market_id):
324
+ info = decode_substrate("0x" + "00" * 12 + USDE[2:], market_id=market_id)
325
+ assert info == SubstrateInfo(address=USDE)
326
+
327
+
328
+ def test_term_finance_dirty_servicer_padding_is_an_error():
329
+ raw = "0x00" + "11" * 11 + SERVICER[2:]
330
+ info = decode_substrate(raw, market_id=52)
331
+ assert info.is_error
332
+ assert info.address is None
333
+
334
+
335
+ @pytest.mark.parametrize("market_id", [31, 51])
336
+ @pytest.mark.parametrize(
337
+ "raw",
338
+ [
339
+ # dirty bits above the type byte: Solidity converts the whole word >> 160
340
+ "0x01" + "00" * 10 + "01" + USDE[2:],
341
+ # out-of-range enum value: Solidity reverts on it
342
+ "0x" + "00" * 11 + "03" + USDE[2:],
343
+ ],
344
+ )
345
+ def test_strict_typed_markets_flag_noncanonical_words(market_id, raw):
346
+ info = decode_substrate(raw, market_id=market_id)
347
+ assert info == SubstrateInfo(raw_hex=raw, type_label="noncanonical", is_error=True)
348
+
349
+
350
+ @pytest.mark.parametrize(
351
+ "market_id",
352
+ [
353
+ IporFusionMarkets.MERKL,
354
+ IporFusionMarkets.ASSETS_BALANCE_VALIDATION,
355
+ IporFusionMarkets.META_MORPHO_0001,
356
+ ],
357
+ )
358
+ def test_strict_plain_markets_flag_dirty_padding(market_id):
359
+ raw = "0x" + "00" * 11 + "01" + USDE[2:]
360
+ info = decode_substrate(raw, market_id=market_id)
361
+ assert info.is_error
274
362
  assert info.address is None
275
- assert info.type_label == "no_decoder(TERM_FINANCE)"
276
363
 
277
364
 
278
- def test_market_without_decoder_is_labelled_not_guessed():
279
- info = decode_substrate("0x" + "11" * 32, market_id=31)
365
+ def test_every_market_has_a_decoder_or_a_reason():
366
+ members = {
367
+ getattr(IporFusionMarkets, name)
368
+ for name in dir(IporFusionMarkets)
369
+ if not name.startswith("_")
370
+ and isinstance(getattr(IporFusionMarkets, name), int)
371
+ }
372
+ registered = set(substrates._SUBSTRATE_DECODERS)
373
+ on_purpose = set(substrates._UNREGISTERED_ON_PURPOSE)
374
+ assert not registered & on_purpose
375
+ assert members - registered == on_purpose
376
+ assert all(reason for reason in substrates._UNREGISTERED_ON_PURPOSE.values())
377
+
378
+
379
+ @pytest.mark.parametrize("market_id", sorted(substrates._UNREGISTERED_ON_PURPOSE))
380
+ def test_a_market_without_a_decoder_is_labelled_not_guessed(market_id):
381
+ info = decode_substrate("0x" + "11" * 32, market_id=market_id)
280
382
  assert info.address is None
281
- assert info.type_label == "no_decoder(VELODROME_SUPERCHAIN)"
383
+ assert info.type_label == f"no_decoder({market_name(market_id)})"
282
384
 
283
385
 
284
386
  def test_external_state_is_market_50():