ipor-fusion 4.0.0.dev37__tar.gz → 4.0.0.dev39__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 (285) hide show
  1. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/PKG-INFO +1 -1
  2. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/pyproject.toml +1 -1
  3. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/cli/market_cmd.py +1 -1
  4. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/cli/vault_markets_view.py +1 -1
  5. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/market_info.py +1 -1
  6. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/morpho_api.py +24 -20
  7. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/vault_info.py +1 -1
  8. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_cli_helpers.py +31 -2
  9. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_cli_market_morpho_blue.py +55 -0
  10. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/.claude-plugin/marketplace.json +0 -0
  11. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/.claude-plugin/plugin.json +0 -0
  12. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/.env.example +0 -0
  13. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/.gemini/settings.json +0 -0
  14. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/.git-blame-ignore-revs +0 -0
  15. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/.github/workflows/cd.yml +0 -0
  16. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/.github/workflows/ci.yml +0 -0
  17. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/.github/workflows/commit-lint.yml +0 -0
  18. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/.github/workflows/notify-slack.yml +0 -0
  19. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/.github/workflows/python-build.yml +0 -0
  20. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/.github/workflows/python-publish.yml +0 -0
  21. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/.github/workflows/release.yml +0 -0
  22. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/.github/workflows/report-slack.yml +0 -0
  23. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/.gitignore +0 -0
  24. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/.mcp.json +0 -0
  25. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/.pre-commit-config.yaml +0 -0
  26. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/.python-version +0 -0
  27. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/AGENTS.md +0 -0
  28. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/CHANGELOG.md +0 -0
  29. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/CLAUDE.md +0 -0
  30. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/CODEOWNERS +0 -0
  31. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/LICENSE +0 -0
  32. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/README.md +0 -0
  33. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/build.sh +0 -0
  34. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/examples/CONTRIBUTING.md +0 -0
  35. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/examples/README.md +0 -0
  36. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/examples/advanced_euler_v2_credit_market_base.py +0 -0
  37. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/examples/advanced_euler_v2_looping_arbitrum.py +0 -0
  38. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/examples/composed_hypercore_flow_arbitrum_hyperevm.py +0 -0
  39. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py +0 -0
  40. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/examples/external_state_margin_leg_base.py +0 -0
  41. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/examples/simple_aave_v3_supply_base.py +0 -0
  42. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/pytest.ini +0 -0
  43. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/scripts/commit-check.sh +0 -0
  44. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/scripts/crosschain_readiness.py +0 -0
  45. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/skills/ipor-deploy-vault/SKILL.md +0 -0
  46. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/__init__.py +0 -0
  47. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/about.py +0 -0
  48. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/cache.py +0 -0
  49. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/chains.py +0 -0
  50. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/cli/__init__.py +0 -0
  51. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/cli/changelog_cmd.py +0 -0
  52. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/cli/config_cmd.py +0 -0
  53. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/cli/config_store.py +0 -0
  54. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/cli/main.py +0 -0
  55. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/cli/options.py +0 -0
  56. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/cli/oracle_mapping_view.py +0 -0
  57. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/cli/vault_cmd.py +0 -0
  58. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/cli/vault_health.py +0 -0
  59. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/cli/vault_info_view.py +0 -0
  60. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/cli/vault_rendering.py +0 -0
  61. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/config/__init__.py +0 -0
  62. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/config/roles.py +0 -0
  63. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/core/__init__.py +0 -0
  64. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/core/access.py +0 -0
  65. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/core/address.py +0 -0
  66. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/core/context.py +0 -0
  67. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/core/contract.py +0 -0
  68. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/core/erc20.py +0 -0
  69. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/core/external_state_executor.py +0 -0
  70. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/core/fee_manager.py +0 -0
  71. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/core/fuse_action.py +0 -0
  72. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/core/fusion_factory.py +0 -0
  73. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/core/logs.py +0 -0
  74. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/core/multicall.py +0 -0
  75. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/core/oracle.py +0 -0
  76. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/core/plasma_vault.py +0 -0
  77. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/core/rewards_manager.py +0 -0
  78. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/core/simulation.py +0 -0
  79. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/core/withdraw_manager.py +0 -0
  80. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/__init__.py +0 -0
  81. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/ccip/__init__.py +0 -0
  82. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/ccip/chainlink.py +0 -0
  83. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/ccip/codec.py +0 -0
  84. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/ccip/contracts.py +0 -0
  85. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/ccip/events.py +0 -0
  86. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/ccip/indexer.py +0 -0
  87. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/ccip/lane.py +0 -0
  88. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/ccip/quote.py +0 -0
  89. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/ccip/transport.py +0 -0
  90. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/contracts.py +0 -0
  91. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/discovery.py +0 -0
  92. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/errors.py +0 -0
  93. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/lane.py +0 -0
  94. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/logs.py +0 -0
  95. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/messages.py +0 -0
  96. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/simulation.py +0 -0
  97. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/stargate/__init__.py +0 -0
  98. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/stargate/contracts.py +0 -0
  99. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/stargate/lane.py +0 -0
  100. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/stargate/layerzero.py +0 -0
  101. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/stargate/transport.py +0 -0
  102. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/crosschain/transport.py +0 -0
  103. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/dependency_graph.py +0 -0
  104. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/entry_cli.py +0 -0
  105. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/entry_mcp.py +0 -0
  106. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/errors.py +0 -0
  107. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/explorer.py +0 -0
  108. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/field_docs.py +0 -0
  109. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/__init__.py +0 -0
  110. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/aave_v3.py +0 -0
  111. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/async_action.py +0 -0
  112. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/base.py +0 -0
  113. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/compound_v3.py +0 -0
  114. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/crosschain/__init__.py +0 -0
  115. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/crosschain/base.py +0 -0
  116. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/crosschain/ccip.py +0 -0
  117. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/crosschain/stargate.py +0 -0
  118. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/erc4626.py +0 -0
  119. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/euler_v2.py +0 -0
  120. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/events.py +0 -0
  121. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/external_state.py +0 -0
  122. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/external_state_events.py +0 -0
  123. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/fluid_instadapp.py +0 -0
  124. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/gearbox_v3.py +0 -0
  125. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/hypercore.py +0 -0
  126. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/hypercore_events.py +0 -0
  127. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/merkl.py +0 -0
  128. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/morpho.py +0 -0
  129. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/ramses_v2.py +0 -0
  130. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/uniswap_v3.py +0 -0
  131. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/fuses/universal.py +0 -0
  132. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/guide/__init__.py +0 -0
  133. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/guide/architecture.md +0 -0
  134. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/guide/glossary.md +0 -0
  135. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/guide/invariants.md +0 -0
  136. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/guide/quickstart.md +0 -0
  137. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/market_ids.py +0 -0
  138. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/mcp/__init__.py +0 -0
  139. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/mcp/guide.py +0 -0
  140. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/mcp/models.py +0 -0
  141. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/mcp/server.py +0 -0
  142. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/py.typed +0 -0
  143. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/readers/__init__.py +0 -0
  144. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/readers/aave_v3.py +0 -0
  145. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/readers/aave_v4.py +0 -0
  146. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/readers/compound_v3.py +0 -0
  147. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/readers/hypercore.py +0 -0
  148. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/readers/hypercore_outcome.py +0 -0
  149. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/readers/lending_health.py +0 -0
  150. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/readers/morpho.py +0 -0
  151. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/readers/oracle_mapping.py +0 -0
  152. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/readers/position_manager.py +0 -0
  153. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/readers/ramses_v2.py +0 -0
  154. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/readers/uniswap_v3.py +0 -0
  155. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/readers/unpriceable.py +0 -0
  156. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/substrates.py +0 -0
  157. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/types.py +0 -0
  158. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/validation.py +0 -0
  159. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/src/ipor_fusion/vault_data.py +0 -0
  160. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/UniswapV3UniversalRouter.py +0 -0
  161. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/_crosschain.py +0 -0
  162. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/_crosschain_lifecycle.py +0 -0
  163. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/_crosschain_recovery.py +0 -0
  164. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/_euler_v2.py +0 -0
  165. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/_foundry.py +0 -0
  166. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/_guide.py +0 -0
  167. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/_hypercore_model.py +0 -0
  168. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/_hypercore_shadow.py +0 -0
  169. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/_multicall.py +0 -0
  170. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/_simulate.py +0 -0
  171. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/_validation.py +0 -0
  172. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/addresses.py +0 -0
  173. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/conftest.py +0 -0
  174. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/constants.py +0 -0
  175. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/fixtures/hypercore_hip3_flow.json +0 -0
  176. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/fixtures/hypercore_market55.json +0 -0
  177. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/fixtures/vault_info_golden/clean.json +0 -0
  178. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/fixtures/vault_info_golden/clean.txt +0 -0
  179. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/fixtures/vault_info_golden/rich.json +0 -0
  180. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/fixtures/vault_info_golden/rich.txt +0 -0
  181. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_about.py +0 -0
  182. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_access_manager.py +0 -0
  183. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_cache.py +0 -0
  184. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_chains.py +0 -0
  185. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_cli_changelog.py +0 -0
  186. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_cli_commands.py +0 -0
  187. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_cli_config_store.py +0 -0
  188. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_cli_hypercore.py +0 -0
  189. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_cli_lending_health.py +0 -0
  190. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_cli_oracle_mapping.py +0 -0
  191. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_cli_pending_requests_scan.py +0 -0
  192. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_cli_role_accounts.py +0 -0
  193. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_cli_vault_info_golden.py +0 -0
  194. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_cli_vault_predates_getters.py +0 -0
  195. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_cli_vault_validate.py +0 -0
  196. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_contract_call.py +0 -0
  197. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_contract_encoder.py +0 -0
  198. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_crosschain_ccip_events.py +0 -0
  199. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_crosschain_ccip_indexer.py +0 -0
  200. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_crosschain_ccip_quote.py +0 -0
  201. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_crosschain_chainlink.py +0 -0
  202. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_crosschain_contracts.py +0 -0
  203. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_crosschain_encoding.py +0 -0
  204. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_crosschain_errors.py +0 -0
  205. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_crosschain_lane.py +0 -0
  206. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_crosschain_layering.py +0 -0
  207. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_crosschain_readiness.py +0 -0
  208. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_crosschain_readiness_report.py +0 -0
  209. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_crosschain_transport.py +0 -0
  210. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_erc20.py +0 -0
  211. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_examples_composed_hypercore.py +0 -0
  212. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_examples_crosschain.py +0 -0
  213. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_examples_euler_looping_arbitrum.py +0 -0
  214. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_examples_vaults.py +0 -0
  215. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_explorer.py +0 -0
  216. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_external_state_events.py +0 -0
  217. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_external_state_executor.py +0 -0
  218. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_fee_manager.py +0 -0
  219. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_fuse_encoding.py +0 -0
  220. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_guide.py +0 -0
  221. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_hypercore_deployment.py +0 -0
  222. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_hypercore_events.py +0 -0
  223. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_hypercore_flow.py +0 -0
  224. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_hypercore_live.py +0 -0
  225. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_hypercore_outcome.py +0 -0
  226. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_hypercore_readers.py +0 -0
  227. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_hypercore_simulation.py +0 -0
  228. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_logs.py +0 -0
  229. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_mcp_hypercore.py +0 -0
  230. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_mcp_models.py +0 -0
  231. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_mcp_server.py +0 -0
  232. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_mcp_vault_validate.py +0 -0
  233. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_multicall.py +0 -0
  234. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_oracle.py +0 -0
  235. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_oracle_mapping.py +0 -0
  236. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_plasma_vault.py +0 -0
  237. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_reader_encoding.py +0 -0
  238. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_readiness_selection.py +0 -0
  239. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_revert_decoding.py +0 -0
  240. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_rewards_manager.py +0 -0
  241. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_roles.py +0 -0
  242. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_sdk_layering.py +0 -0
  243. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_borrow_aave_v3_mainnet.py +0 -0
  244. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_claim_merkl_wrapper_base.py +0 -0
  245. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_claim_morpho_rewards.py +0 -0
  246. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_crosschain_canary.py +0 -0
  247. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_crosschain_hypercore.py +0 -0
  248. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_crosschain_hyperevm.py +0 -0
  249. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_crosschain_lifecycle.py +0 -0
  250. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_euler_v2_batch_base.py +0 -0
  251. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_euler_v2_credit_market_base.py +0 -0
  252. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_euler_v2_swap_deploy_base.py +0 -0
  253. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_euler_v2_swap_reconfigure_base.py +0 -0
  254. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_euler_v2_swap_registry_base.py +0 -0
  255. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_examples_arbitrum.py +0 -0
  256. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_examples_base.py +0 -0
  257. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_examples_crosschain.py +0 -0
  258. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_external_state_executor_base.py +0 -0
  259. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_fusion_factory_clone_base.py +0 -0
  260. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_looping_aave_v3_base.py +0 -0
  261. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_looping_morpho_blue_base.py +0 -0
  262. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_morpho_blue.py +0 -0
  263. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_pilot_v3.py +0 -0
  264. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_pilot_v4_uniswap.py +0 -0
  265. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_pilot_v5_ramses.py +0 -0
  266. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_pilot_v5_scheduled.py +0 -0
  267. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_plasma_vault_setters_base.py +0 -0
  268. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_readers_integration.py +0 -0
  269. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_release_funds.py +0 -0
  270. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_swap_on_base.py +0 -0
  271. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_simulate_vault_from_scratch_base.py +0 -0
  272. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_solidity_compiler.py +0 -0
  273. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_solidity_mirrors.py +0 -0
  274. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_substrates.py +0 -0
  275. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_types_and_events.py +0 -0
  276. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_unpriceable_tokens.py +0 -0
  277. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_validation.py +0 -0
  278. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_vault_dep_graph.py +0 -0
  279. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_vault_info_onchain_base.py +0 -0
  280. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_vault_info_onchain_base_no_withdraw_manager.py +0 -0
  281. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_vault_simulator_blocks.py +0 -0
  282. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_web3_context.py +0 -0
  283. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/test_withdraw_manager.py +0 -0
  284. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/tests/typed_client/consumer.py +0 -0
  285. {ipor_fusion-4.0.0.dev37 → ipor_fusion-4.0.0.dev39}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: ipor-fusion
3
- Version: 4.0.0.dev37
3
+ Version: 4.0.0.dev39
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.dev37"
3
+ version = "4.0.0.dev39"
4
4
  description = "The IPOR Fusion SDK for Python"
5
5
  authors = [
6
6
  { name = "Adam Mydlarz", email = "amydlarz@gmail.com" },
@@ -551,7 +551,7 @@ def _print_vault_v1(
551
551
  return
552
552
  rows: list[tuple[str, ...]] = []
553
553
  for alloc in allocations:
554
- flow = vault.public_allocator_flow_caps.get(alloc.market_id.lower(), (0, 0))
554
+ flow = vault.public_allocator_flow_caps.get(alloc.market_id, (0, 0))
555
555
  flow_str = (
556
556
  f"in {_format_amount(flow[0], alloc.loan_decimals)}" if flow[0] else "—"
557
557
  )
@@ -53,7 +53,7 @@ def _print_lending_health( # noqa: C901
53
53
  for pb in positions:
54
54
  coll_sym = resolve_token_symbol(ctx, pb.collateral_token) or "?"
55
55
  loan_sym = resolve_token_symbol(ctx, pb.loan_token) or "?"
56
- click.echo(f" morpho market 0x{pb.market_id} ({coll_sym}/{loan_sym}):")
56
+ click.echo(f" morpho market {pb.market_id} ({coll_sym}/{loan_sym}):")
57
57
  click.echo(
58
58
  f" Collateral: {_format_token_amount(ctx, int(pb.collateral), pb.collateral_token, prices)}"
59
59
  )
@@ -34,7 +34,7 @@ def build_morpho_blue_market_json(
34
34
  market's parameters, state and rates (from `MorphoReader`), plus the
35
35
  MetaMorpho vaults supplying it when ``api_market`` (`fetch_market`) is
36
36
  given, or ``api_error`` when that lookup failed. ``market_id`` is the
37
- 64-hex-char id without ``0x``."""
37
+ canonical id (`parse_morpho_market_id`) and is written as is."""
38
38
  out: dict = {
39
39
  "market_id": market_id,
40
40
  "chain_id": chain_id,
@@ -180,8 +180,9 @@ def fetch_market(
180
180
 
181
181
  def _parse_market(raw: dict) -> MorphoApiMarket:
182
182
  state = raw.get("state") or {}
183
+ market_id = _api_market_id(raw.get("marketId"))
183
184
  return MorphoApiMarket(
184
- market_id=_api_market_id(raw.get("marketId")),
185
+ market_id=market_id,
185
186
  lltv=int(raw["lltv"]),
186
187
  loan_token=_api_address(raw["loanAsset"]["address"]),
187
188
  loan_symbol=raw["loanAsset"]["symbol"],
@@ -199,9 +200,7 @@ def _parse_market(raw: dict) -> MorphoApiMarket:
199
200
  borrow_apy=float(state.get("borrowApy") or 0.0),
200
201
  fee_wad=int(state.get("fee") or 0),
201
202
  timestamp=int(state.get("timestamp") or 0),
202
- vaults=[
203
- _parse_vault(v, raw["marketId"]) for v in raw.get("supplyingVaults") or []
204
- ],
203
+ vaults=[_parse_vault(v, market_id) for v in raw.get("supplyingVaults") or []],
205
204
  )
206
205
 
207
206
 
@@ -373,7 +372,9 @@ class VaultV1Info:
373
372
  allocators: list[ChecksumAddress]
374
373
  allocations: list[VaultV1MarketAllocation]
375
374
  public_allocator: VaultFlowCap | None # vault-level (no flowCap filtering)
376
- public_allocator_flow_caps: dict[str, tuple[int, int]] # marketId -> (maxIn,maxOut)
375
+ public_allocator_flow_caps: dict[
376
+ MorphoBlueMarketId, tuple[int, int]
377
+ ] # (maxIn, maxOut)
377
378
 
378
379
 
379
380
  def fetch_vault(
@@ -618,7 +619,7 @@ def _parse_vault_v1(raw: dict) -> VaultV1Info:
618
619
 
619
620
  pac = raw.get("publicAllocatorConfig")
620
621
  flow_cap_summary: VaultFlowCap | None = None
621
- flow_caps: dict[str, tuple[int, int]] = {}
622
+ flow_caps: dict[MorphoBlueMarketId, tuple[int, int]] = {}
622
623
  if pac:
623
624
  flow_cap_summary = VaultFlowCap(
624
625
  fee_wei=int(pac.get("fee") or 0),
@@ -627,9 +628,11 @@ def _parse_vault_v1(raw: dict) -> VaultV1Info:
627
628
  admin=pac.get("admin"),
628
629
  )
629
630
  for fc in pac.get("flowCaps") or []:
630
- mid = ((fc.get("market") or {}).get("marketId") or "").lower()
631
- if mid:
632
- flow_caps[mid] = (int(fc.get("maxIn") or 0), int(fc.get("maxOut") or 0))
631
+ if raw_mid := (fc.get("market") or {}).get("marketId"):
632
+ flow_caps[_api_market_id(raw_mid)] = (
633
+ int(fc.get("maxIn") or 0),
634
+ int(fc.get("maxOut") or 0),
635
+ )
633
636
 
634
637
  return VaultV1Info(
635
638
  address=_api_address(raw.get("address")),
@@ -655,27 +658,28 @@ def _parse_vault_v1(raw: dict) -> VaultV1Info:
655
658
  )
656
659
 
657
660
 
661
+ def _is_market(entry: dict, market_id: MorphoBlueMarketId) -> bool:
662
+ """Whether an allocation or flow-cap ``entry`` names ``market_id``, in any
663
+ spelling the API returns."""
664
+ raw = (entry.get("market") or {}).get("marketId")
665
+ try:
666
+ return parse_morpho_market_id(str(raw or "")) == market_id
667
+ except ValueError:
668
+ return False
669
+
670
+
658
671
  def _parse_vault(raw: dict, market_id: MorphoBlueMarketId) -> VaultAllocation:
659
672
  asset = raw.get("asset") or {}
660
673
  state = raw.get("state") or {}
661
674
  allocation_for_market: dict = next(
662
- (
663
- a
664
- for a in (state.get("allocation") or [])
665
- if (a.get("market") or {}).get("marketId", "").lower() == market_id
666
- ),
675
+ (a for a in (state.get("allocation") or []) if _is_market(a, market_id)),
667
676
  {},
668
677
  )
669
678
  pac = raw.get("publicAllocatorConfig")
670
679
  flow_cap: VaultFlowCap | None = None
671
680
  if pac:
672
681
  flow_for_market = next(
673
- (
674
- fc
675
- for fc in (pac.get("flowCaps") or [])
676
- if (fc.get("market") or {}).get("marketId", "").lower()
677
- == market_id.lower()
678
- ),
682
+ (fc for fc in (pac.get("flowCaps") or []) if _is_market(fc, market_id)),
679
683
  None,
680
684
  )
681
685
  if flow_for_market:
@@ -505,7 +505,7 @@ def _morpho_breakdown_json(
505
505
  prices = data.token_prices_usd
506
506
  return [
507
507
  {
508
- "morpho_market_id": "0x" + str(pb.market_id),
508
+ "morpho_market_id": pb.market_id,
509
509
  "collateral_symbol": resolve_token_symbol(ctx, pb.collateral_token) or None,
510
510
  "loan_symbol": resolve_token_symbol(ctx, pb.loan_token) or None,
511
511
  "collateral": _build_breakdown_amount_json(
@@ -63,7 +63,11 @@ from ipor_fusion.readers.lending_health import (
63
63
  )
64
64
  from ipor_fusion.readers.morpho import MORPHO_BLUE_ADDRESSES, MorphoPositionBreakdown
65
65
  from ipor_fusion.substrates import decode_substrate, market_name
66
- from ipor_fusion.types import Amount, MarketId, MorphoBlueMarketId
66
+ from ipor_fusion.types import (
67
+ Amount,
68
+ MarketId,
69
+ parse_morpho_market_id,
70
+ )
67
71
  from ipor_fusion.validation import Erc20Holdings
68
72
  from ipor_fusion.vault_data import (
69
73
  FeeData,
@@ -86,6 +90,7 @@ from ipor_fusion.vault_info import (
86
90
  _build_dependency_graph_json,
87
91
  _build_fees_json,
88
92
  _build_share_price_json,
93
+ _morpho_breakdown_json,
89
94
  _partition_balance_fuses,
90
95
  )
91
96
 
@@ -1509,7 +1514,7 @@ _TOKEN_WETH = Web3.to_checksum_address("0x" + "33" * 20)
1509
1514
 
1510
1515
  def _morpho_breakdown(market_id: str = "ab" * 32):
1511
1516
  return MorphoPositionBreakdown(
1512
- market_id=MorphoBlueMarketId(market_id),
1517
+ market_id=parse_morpho_market_id(market_id),
1513
1518
  loan_token=_TOKEN_USDC,
1514
1519
  collateral_token=_TOKEN_WETH,
1515
1520
  collateral=Amount(10 * 10**18),
@@ -1705,6 +1710,30 @@ class TestFetcherCollectors:
1705
1710
  assert 14 in out and 1 not in out
1706
1711
  assert len(out[14]) == 1
1707
1712
 
1713
+ @patch("ipor_fusion.vault_info.resolve_token_decimals", return_value=18)
1714
+ @patch("ipor_fusion.vault_info.resolve_token_symbol", return_value="WETH")
1715
+ @patch("ipor_fusion.vault_data.resolve_token_decimals", return_value=18)
1716
+ @patch("ipor_fusion.vault_data.resolve_token_symbol", return_value="WETH")
1717
+ def test_collected_morpho_id_renders_with_one_prefix(
1718
+ self, _sym, _dec, _view_sym, _view_dec, capsys
1719
+ ):
1720
+ (market_id,) = _collect_morpho_substrates({14: [bytes.fromhex("ab" * 32)]})[14]
1721
+ breakdown = MorphoPositionBreakdown(
1722
+ market_id=market_id,
1723
+ loan_token=_TOKEN_USDC,
1724
+ collateral_token=_TOKEN_WETH,
1725
+ collateral=Amount(0),
1726
+ borrow_assets=Amount(0),
1727
+ supply_assets=Amount(0),
1728
+ )
1729
+ data = _make_data(morpho_positions={14: [breakdown]})
1730
+ (entry,) = _morpho_breakdown_json(MagicMock(), data, [breakdown])
1731
+ assert entry["morpho_market_id"] == "0x" + "ab" * 32
1732
+ _print_lending_health(MagicMock(), data)
1733
+ out = capsys.readouterr().out
1734
+ assert f"morpho market 0x{'ab' * 32} " in out
1735
+ assert "0x0x" not in out
1736
+
1708
1737
  def test_collect_morpho_substrates_skips_wrong_length(self):
1709
1738
  bad = bytes.fromhex("aa" * 16) # wrong length
1710
1739
  out = _collect_morpho_substrates({14: [bad]})
@@ -21,6 +21,7 @@ from ipor_fusion.morpho_api import (
21
21
  fetch_market,
22
22
  fetch_vault,
23
23
  )
24
+ from ipor_fusion.types import parse_morpho_market_id
24
25
 
25
26
  MARKET_ID = "ad656d430bb3d8c1469bf45c8ad4ebae1b04be04757c69fa424eec78d7b3f4dc"
26
27
  LOAN_TOKEN = Web3.to_checksum_address("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
@@ -381,6 +382,60 @@ class TestMorphoApiClient:
381
382
  assert vault.flow_cap.admin == ADMIN_ADDR
382
383
  assert vault.allocators == [PUBLIC_ALLOCATOR_ETH, ADMIN_ADDR]
383
384
 
385
+ def test_fetch_market_matches_allocations_in_any_spelling(self):
386
+ upper = "0x" + MARKET_ID.upper()
387
+ market = {"market": {"marketId": upper}}
388
+ body = {
389
+ "data": {
390
+ "marketById": {
391
+ "marketId": upper,
392
+ "lltv": "915000000000000000",
393
+ "loanAsset": {
394
+ "address": LOAN_TOKEN,
395
+ "symbol": "USDC",
396
+ "decimals": 6,
397
+ },
398
+ "collateralAsset": {
399
+ "address": COLLATERAL_TOKEN,
400
+ "symbol": "WOUSD",
401
+ "decimals": 18,
402
+ },
403
+ "oracle": {"address": ORACLE},
404
+ "irmAddress": IRM,
405
+ "state": {},
406
+ "supplyingVaults": [
407
+ {
408
+ "address": VAULT_ADDR,
409
+ "symbol": "v",
410
+ "name": "v",
411
+ "asset": {"symbol": "USDC", "decimals": 6},
412
+ "state": {
413
+ "allocation": [
414
+ {**market, "supplyAssets": 123, "supplyCap": 456}
415
+ ]
416
+ },
417
+ "publicAllocatorConfig": {
418
+ "fee": 0,
419
+ "flowCaps": [{**market, "maxIn": 7, "maxOut": 8}],
420
+ },
421
+ }
422
+ ],
423
+ }
424
+ }
425
+ }
426
+ with patch("ipor_fusion.morpho_api.urlopen") as mock_open:
427
+ mock_resp = MagicMock()
428
+ mock_resp.read.return_value = json.dumps(body).encode()
429
+ mock_open.return_value.__enter__.return_value = mock_resp
430
+
431
+ result = fetch_market(parse_morpho_market_id(MARKET_ID), 1)
432
+
433
+ assert result.market_id == "0x" + MARKET_ID.lower()
434
+ vault = result.vaults[0]
435
+ assert (vault.supply_assets, vault.supply_cap) == (123, 456)
436
+ assert vault.flow_cap is not None
437
+ assert (vault.flow_cap.max_in, vault.flow_cap.max_out) == (7, 8)
438
+
384
439
  def test_fetch_market_handles_missing_market(self):
385
440
  with patch("ipor_fusion.morpho_api.urlopen") as mock_open:
386
441
  mock_resp = MagicMock()