ipor-fusion 4.0.0.dev255__tar.gz → 4.0.0.dev260__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 (342) hide show
  1. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/AGENTS.md +3 -1
  2. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/PKG-INFO +5 -2
  3. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/README.md +4 -1
  4. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/pyproject.toml +1 -1
  5. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/__init__.py +8 -0
  6. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/types.py +79 -0
  7. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_public_api.py +8 -0
  8. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_types_and_events.py +117 -1
  9. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/.claude-plugin/marketplace.json +0 -0
  10. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/.claude-plugin/plugin.json +0 -0
  11. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/.env.example +0 -0
  12. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/.gemini/settings.json +0 -0
  13. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/.git-blame-ignore-revs +0 -0
  14. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/.github/workflows/cd.yml +0 -0
  15. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/.github/workflows/ci.yml +0 -0
  16. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/.github/workflows/commit-lint.yml +0 -0
  17. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/.github/workflows/notify-slack.yml +0 -0
  18. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/.github/workflows/python-build.yml +0 -0
  19. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/.github/workflows/python-publish.yml +0 -0
  20. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/.github/workflows/release.yml +0 -0
  21. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/.github/workflows/report-slack.yml +0 -0
  22. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/.gitignore +0 -0
  23. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/.mcp.json +0 -0
  24. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/.pre-commit-config.yaml +0 -0
  25. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/.python-version +0 -0
  26. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/CHANGELOG.md +0 -0
  27. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/CLAUDE.md +0 -0
  28. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/CODEOWNERS +0 -0
  29. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/LICENSE +0 -0
  30. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/MIGRATION_4.md +0 -0
  31. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/build.sh +0 -0
  32. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/examples/CONTRIBUTING.md +0 -0
  33. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/examples/README.md +0 -0
  34. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/examples/advanced_euler_v2_credit_market_base.py +0 -0
  35. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/examples/advanced_euler_v2_looping_arbitrum.py +0 -0
  36. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/examples/composed_hypercore_flow_arbitrum_hyperevm.py +0 -0
  37. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py +0 -0
  38. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/examples/external_state_margin_leg_base.py +0 -0
  39. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/examples/simple_aave_v3_supply_base.py +0 -0
  40. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/pytest.ini +0 -0
  41. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/scripts/commit-check.sh +0 -0
  42. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/scripts/crosschain_readiness.py +0 -0
  43. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/skills/ipor-deploy-vault/SKILL.md +0 -0
  44. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/about.py +0 -0
  45. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/cache.py +0 -0
  46. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/chains.py +0 -0
  47. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/cli/__init__.py +0 -0
  48. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/cli/changelog_cmd.py +0 -0
  49. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/cli/config_cmd.py +0 -0
  50. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/cli/config_store.py +0 -0
  51. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/cli/main.py +0 -0
  52. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/cli/market_cmd.py +0 -0
  53. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/cli/options.py +0 -0
  54. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/cli/oracle_mapping_view.py +0 -0
  55. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/cli/vault_cmd.py +0 -0
  56. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/cli/vault_health.py +0 -0
  57. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/cli/vault_info_view.py +0 -0
  58. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/cli/vault_markets_view.py +0 -0
  59. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/cli/vault_rendering.py +0 -0
  60. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/config/__init__.py +0 -0
  61. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/config/roles.py +0 -0
  62. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/core/__init__.py +0 -0
  63. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/core/access.py +0 -0
  64. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/core/address.py +0 -0
  65. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/core/context.py +0 -0
  66. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/core/contract.py +0 -0
  67. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/core/erc20.py +0 -0
  68. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/core/external_state_executor.py +0 -0
  69. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/core/fee_manager.py +0 -0
  70. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/core/fuse.py +0 -0
  71. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/core/fuse_action.py +0 -0
  72. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/core/fusion_factory.py +0 -0
  73. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/core/logs.py +0 -0
  74. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/core/multicall.py +0 -0
  75. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/core/oracle.py +0 -0
  76. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/core/plasma_vault.py +0 -0
  77. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/core/rewards_manager.py +0 -0
  78. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/core/simulation.py +0 -0
  79. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/core/simulation_result.py +0 -0
  80. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/core/withdraw_manager.py +0 -0
  81. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/__init__.py +0 -0
  82. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/ccip/__init__.py +0 -0
  83. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/ccip/chainlink.py +0 -0
  84. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/ccip/codec.py +0 -0
  85. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/ccip/contracts.py +0 -0
  86. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/ccip/events.py +0 -0
  87. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/ccip/indexer.py +0 -0
  88. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/ccip/lane.py +0 -0
  89. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/ccip/quote.py +0 -0
  90. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/ccip/transport.py +0 -0
  91. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/contracts.py +0 -0
  92. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/discovery.py +0 -0
  93. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/errors.py +0 -0
  94. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/fuses/__init__.py +0 -0
  95. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/fuses/base.py +0 -0
  96. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/fuses/ccip.py +0 -0
  97. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/fuses/stargate.py +0 -0
  98. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/lane.py +0 -0
  99. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/logs.py +0 -0
  100. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/messages.py +0 -0
  101. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/simulation.py +0 -0
  102. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/stargate/__init__.py +0 -0
  103. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/stargate/contracts.py +0 -0
  104. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/stargate/lane.py +0 -0
  105. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/stargate/layerzero.py +0 -0
  106. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/stargate/transport.py +0 -0
  107. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/crosschain/transport.py +0 -0
  108. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/dependency_graph.py +0 -0
  109. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/entry_cli.py +0 -0
  110. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/entry_mcp.py +0 -0
  111. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/errors.py +0 -0
  112. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/explorer.py +0 -0
  113. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/field_docs.py +0 -0
  114. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/fuses/__init__.py +0 -0
  115. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/fuses/aave_v3.py +0 -0
  116. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/fuses/async_action.py +0 -0
  117. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/fuses/base.py +0 -0
  118. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/fuses/compound_v3.py +0 -0
  119. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/fuses/erc4626.py +0 -0
  120. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/fuses/euler_v2.py +0 -0
  121. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/fuses/events.py +0 -0
  122. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/fuses/external_state.py +0 -0
  123. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/fuses/external_state_event_decoding.py +0 -0
  124. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/fuses/fluid_instadapp.py +0 -0
  125. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/fuses/gearbox_v3.py +0 -0
  126. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/fuses/hypercore.py +0 -0
  127. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/fuses/hypercore_event_decoding.py +0 -0
  128. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/fuses/merkl.py +0 -0
  129. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/fuses/morpho.py +0 -0
  130. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/fuses/ramses_v2.py +0 -0
  131. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/fuses/uniswap_v3.py +0 -0
  132. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/fuses/universal.py +0 -0
  133. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/guide/__init__.py +0 -0
  134. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/guide/architecture.md +0 -0
  135. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/guide/glossary.md +0 -0
  136. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/guide/invariants.md +0 -0
  137. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/guide/quickstart.md +0 -0
  138. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/hypercore/__init__.py +0 -0
  139. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/market_ids.py +0 -0
  140. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/market_info.py +0 -0
  141. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/mcp/__init__.py +0 -0
  142. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/mcp/guide.py +0 -0
  143. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/mcp/models.py +0 -0
  144. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/mcp/server.py +0 -0
  145. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/morpho_api.py +0 -0
  146. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/py.typed +0 -0
  147. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/readers/__init__.py +0 -0
  148. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/readers/aave_v3.py +0 -0
  149. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/readers/aave_v4.py +0 -0
  150. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/readers/compound_v3.py +0 -0
  151. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/readers/hypercore.py +0 -0
  152. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/readers/hypercore_outcome.py +0 -0
  153. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/readers/lending_health.py +0 -0
  154. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/readers/morpho.py +0 -0
  155. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/readers/oracle_mapping.py +0 -0
  156. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/readers/oracle_mapping_nodes.py +0 -0
  157. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/readers/oracle_mapping_reader.py +0 -0
  158. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/readers/position_manager.py +0 -0
  159. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/readers/ramses_v2.py +0 -0
  160. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/readers/uniswap_v3.py +0 -0
  161. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/readers/unpriceable.py +0 -0
  162. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/substrates.py +0 -0
  163. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/validation.py +0 -0
  164. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/vault_data.py +0 -0
  165. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/vault_erc20.py +0 -0
  166. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/vault_info.py +0 -0
  167. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/vault_managers.py +0 -0
  168. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/vault_positions.py +0 -0
  169. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/src/ipor_fusion/vault_reads.py +0 -0
  170. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/UniswapV3UniversalRouter.py +0 -0
  171. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/_crosschain.py +0 -0
  172. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/_crosschain_lifecycle.py +0 -0
  173. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/_crosschain_recovery.py +0 -0
  174. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/_euler_v2.py +0 -0
  175. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/_event_args.py +0 -0
  176. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/_fake_rpc.py +0 -0
  177. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/_foundry.py +0 -0
  178. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/_golden.py +0 -0
  179. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/_guide.py +0 -0
  180. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/_hypercore_model.py +0 -0
  181. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/_hypercore_shadow.py +0 -0
  182. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/_live.py +0 -0
  183. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/_multicall.py +0 -0
  184. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/_oracle_mapping_fake.py +0 -0
  185. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/_simulate.py +0 -0
  186. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/_validation.py +0 -0
  187. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/addresses.py +0 -0
  188. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/conftest.py +0 -0
  189. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/constants.py +0 -0
  190. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/hypercore_hip3_flow.json +0 -0
  191. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/hypercore_market55.json +0 -0
  192. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/market_golden/meta_morpho_v1.json +0 -0
  193. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/market_golden/meta_morpho_v1.mcp.json +0 -0
  194. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/market_golden/meta_morpho_v2.json +0 -0
  195. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/market_golden/meta_morpho_v2.mcp.json +0 -0
  196. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/market_golden/morpho_api/market.json +0 -0
  197. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/market_golden/morpho_api/vault_v1.json +0 -0
  198. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/market_golden/morpho_api/vault_v2.json +0 -0
  199. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/market_golden/morpho_api/vault_v2_not_found.json +0 -0
  200. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/market_golden/morpho_blue.json +0 -0
  201. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/market_golden/morpho_blue.mcp.json +0 -0
  202. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/market_golden/morpho_blue_api_error.json +0 -0
  203. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/market_golden/morpho_blue_api_error.mcp.json +0 -0
  204. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/market_golden/morpho_blue_no_api.json +0 -0
  205. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/market_golden/morpho_blue_no_api.mcp.json +0 -0
  206. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/oracle_mapping_golden/mapping.json +0 -0
  207. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/oracle_mapping_golden/mapping.mcp.json +0 -0
  208. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/simulate_v1_request.json +0 -0
  209. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/vault_info_golden/clean.json +0 -0
  210. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/vault_info_golden/clean.mcp.json +0 -0
  211. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/vault_info_golden/clean.txt +0 -0
  212. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/vault_info_golden/deployment_error.json +0 -0
  213. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/vault_info_golden/deployment_error.mcp.json +0 -0
  214. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/vault_info_golden/deployment_error.txt +0 -0
  215. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/vault_info_golden/fetched.cli.json +0 -0
  216. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/vault_info_golden/fetched.json +0 -0
  217. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/vault_info_golden/fetched.mcp.json +0 -0
  218. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/vault_info_golden/full.json +0 -0
  219. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/vault_info_golden/full.mcp.json +0 -0
  220. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/vault_info_golden/full.txt +0 -0
  221. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/vault_info_golden/rich.json +0 -0
  222. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/vault_info_golden/rich.mcp.json +0 -0
  223. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/fixtures/vault_info_golden/rich.txt +0 -0
  224. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_about.py +0 -0
  225. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_access_manager.py +0 -0
  226. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_cache.py +0 -0
  227. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_chains.py +0 -0
  228. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_cli_changelog.py +0 -0
  229. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_cli_commands.py +0 -0
  230. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_cli_config_store.py +0 -0
  231. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_cli_helpers.py +0 -0
  232. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_cli_hypercore.py +0 -0
  233. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_cli_lending_health.py +0 -0
  234. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_cli_market_golden.py +0 -0
  235. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_cli_market_morpho_blue.py +0 -0
  236. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_cli_mcp_parity.py +0 -0
  237. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_cli_oracle_mapping.py +0 -0
  238. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_cli_oracle_mapping_golden.py +0 -0
  239. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_cli_pending_requests_scan.py +0 -0
  240. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_cli_role_accounts.py +0 -0
  241. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_cli_vault_info_golden.py +0 -0
  242. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_cli_vault_predates_getters.py +0 -0
  243. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_cli_vault_validate.py +0 -0
  244. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_contract_call.py +0 -0
  245. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_contract_encoder.py +0 -0
  246. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_crosschain_ccip_events.py +0 -0
  247. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_crosschain_ccip_indexer.py +0 -0
  248. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_crosschain_ccip_quote.py +0 -0
  249. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_crosschain_chainlink.py +0 -0
  250. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_crosschain_contracts.py +0 -0
  251. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_crosschain_encoding.py +0 -0
  252. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_crosschain_errors.py +0 -0
  253. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_crosschain_lane.py +0 -0
  254. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_crosschain_layering.py +0 -0
  255. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_crosschain_readiness.py +0 -0
  256. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_crosschain_readiness_report.py +0 -0
  257. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_crosschain_transport.py +0 -0
  258. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_docs_typing.py +0 -0
  259. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_erc20.py +0 -0
  260. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_error_hierarchy.py +0 -0
  261. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_examples_composed_hypercore.py +0 -0
  262. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_examples_crosschain.py +0 -0
  263. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_examples_euler_looping_arbitrum.py +0 -0
  264. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_examples_vaults.py +0 -0
  265. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_explorer.py +0 -0
  266. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_external_state_events.py +0 -0
  267. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_external_state_executor.py +0 -0
  268. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_fee_manager.py +0 -0
  269. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_fuse_encoding.py +0 -0
  270. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_fusion_instance.py +0 -0
  271. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_guide.py +0 -0
  272. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_hypercore_deployment.py +0 -0
  273. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_hypercore_events.py +0 -0
  274. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_hypercore_flow.py +0 -0
  275. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_hypercore_live.py +0 -0
  276. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_hypercore_outcome.py +0 -0
  277. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_hypercore_readers.py +0 -0
  278. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_hypercore_simulation.py +0 -0
  279. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_logs.py +0 -0
  280. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_mcp_hypercore.py +0 -0
  281. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_mcp_models.py +0 -0
  282. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_mcp_server.py +0 -0
  283. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_mcp_vault_validate.py +0 -0
  284. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_multicall.py +0 -0
  285. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_oracle.py +0 -0
  286. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_oracle_mapping.py +0 -0
  287. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_plasma_vault.py +0 -0
  288. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_public_type_reachability.py +0 -0
  289. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_reader_encoding.py +0 -0
  290. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_readiness_selection.py +0 -0
  291. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_revert_decoding.py +0 -0
  292. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_rewards_manager.py +0 -0
  293. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_roles.py +0 -0
  294. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_sdk_layering.py +0 -0
  295. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_borrow_aave_v3_mainnet.py +0 -0
  296. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_claim_merkl_wrapper_base.py +0 -0
  297. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_claim_morpho_rewards.py +0 -0
  298. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_crosschain_canary.py +0 -0
  299. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_crosschain_hypercore.py +0 -0
  300. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_crosschain_hyperevm.py +0 -0
  301. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_crosschain_lifecycle.py +0 -0
  302. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_euler_v2_batch_base.py +0 -0
  303. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_euler_v2_credit_market_base.py +0 -0
  304. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_euler_v2_swap_deploy_base.py +0 -0
  305. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_euler_v2_swap_reconfigure_base.py +0 -0
  306. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_euler_v2_swap_registry_base.py +0 -0
  307. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_examples_arbitrum.py +0 -0
  308. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_examples_base.py +0 -0
  309. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_examples_crosschain.py +0 -0
  310. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_external_state_executor_base.py +0 -0
  311. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_fusion_factory_clone_base.py +0 -0
  312. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_looping_aave_v3_base.py +0 -0
  313. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_looping_morpho_blue_base.py +0 -0
  314. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_morpho_blue.py +0 -0
  315. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_pilot_v3.py +0 -0
  316. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_pilot_v4_uniswap.py +0 -0
  317. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_pilot_v5_ramses.py +0 -0
  318. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_pilot_v5_scheduled.py +0 -0
  319. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_plasma_vault_setters_base.py +0 -0
  320. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_readers_integration.py +0 -0
  321. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_release_funds.py +0 -0
  322. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_swap_on_base.py +0 -0
  323. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulate_vault_from_scratch_base.py +0 -0
  324. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulation_errors.py +0 -0
  325. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_simulation_observation.py +0 -0
  326. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_solidity_compiler.py +0 -0
  327. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_solidity_mirrors.py +0 -0
  328. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_substrates.py +0 -0
  329. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_unpriceable_tokens.py +0 -0
  330. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_validation.py +0 -0
  331. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_vault_data_block.py +0 -0
  332. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_vault_dep_graph.py +0 -0
  333. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_vault_info_fetched_golden.py +0 -0
  334. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_vault_info_onchain_base.py +0 -0
  335. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_vault_info_onchain_base_no_withdraw_manager.py +0 -0
  336. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_vault_reconciliation_onchain_base.py +0 -0
  337. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_vault_simulator_blocks.py +0 -0
  338. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_web3_context.py +0 -0
  339. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/test_withdraw_manager.py +0 -0
  340. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/typed_client/consumer.py +0 -0
  341. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/tests/typed_client/rejected.py +0 -0
  342. {ipor_fusion-4.0.0.dev255 → ipor_fusion-4.0.0.dev260}/uv.lock +0 -0
@@ -419,7 +419,9 @@ or examples.
419
419
  round re-resolves it. Labels only name calls in `result.calls` and failures.
420
420
  Integration tests and examples use it instead of a local node.
421
421
  - Amounts are raw on-chain integers; `types.py` `NewType`s (`Amount`, `Shares`,
422
- `MarketId`, ...) name the unit, and nothing scales by decimals.
422
+ `MarketId`, ...) name the unit, and nothing scales by decimals except the exact
423
+ boundary converters `parse_amount` / `format_amount` (and the `*_shares` pair):
424
+ decimal text in, raw integer out, no float ever.
423
425
  - Three address roles are nominal: `PlasmaVaultAddress`, `FuseAddress` and
424
426
  `AccessManagerAddress` (NewTypes of `ChecksumAddress`). Their wrappers, getters and
425
427
  records return them, so a vault, a fuse and an access manager cannot be passed for
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: ipor-fusion
3
- Version: 4.0.0.dev255
3
+ Version: 4.0.0.dev260
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
@@ -170,7 +170,10 @@ Fuse, factory and manager addresses per chain are published in
170
170
  [ipor-abi](https://github.com/IPOR-Labs/ipor-abi) (`mainnet/mainnet-<chain>-fusion/addresses.json`).
171
171
  A fuse must also be registered on the vault; `vault.get_fuses().call(ctx)` lists the registered ones.
172
172
 
173
- Amounts are raw on-chain integers (`Amount`, `Shares` in `ipor_fusion.types`); the SDK never scales by decimals.
173
+ Amounts are raw on-chain integers (`Amount`, `Shares` in `ipor_fusion.types`); the SDK scales by decimals
174
+ only in explicit boundary converters.
175
+ `parse_amount("1.5", Decimals(6))` and `format_amount(Amount(1_500_000), Decimals(6))` convert exactly at the
176
+ boundary (no floats, no rounding; `parse_shares` / `format_shares` for shares at the share token's decimals).
174
177
 
175
178
  ### Read, send, or simulate
176
179
 
@@ -122,7 +122,10 @@ Fuse, factory and manager addresses per chain are published in
122
122
  [ipor-abi](https://github.com/IPOR-Labs/ipor-abi) (`mainnet/mainnet-<chain>-fusion/addresses.json`).
123
123
  A fuse must also be registered on the vault; `vault.get_fuses().call(ctx)` lists the registered ones.
124
124
 
125
- Amounts are raw on-chain integers (`Amount`, `Shares` in `ipor_fusion.types`); the SDK never scales by decimals.
125
+ Amounts are raw on-chain integers (`Amount`, `Shares` in `ipor_fusion.types`); the SDK scales by decimals
126
+ only in explicit boundary converters.
127
+ `parse_amount("1.5", Decimals(6))` and `format_amount(Amount(1_500_000), Decimals(6))` convert exactly at the
128
+ boundary (no floats, no rounding; `parse_shares` / `format_shares` for shares at the share token's decimals).
126
129
 
127
130
  ### Read, send, or simulate
128
131
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ipor-fusion"
3
- version = "4.0.0.dev255"
3
+ version = "4.0.0.dev260"
4
4
  description = "The IPOR Fusion SDK for Python"
5
5
  authors = [
6
6
  { name = "Adam Mydlarz", email = "amydlarz@gmail.com" },
@@ -333,11 +333,15 @@ from ipor_fusion.types import (
333
333
  TokenId,
334
334
  TxHash,
335
335
  Verdict,
336
+ format_amount,
337
+ format_shares,
336
338
  parse_access_manager_address,
339
+ parse_amount,
337
340
  parse_fuse_address,
338
341
  parse_hex_address,
339
342
  parse_morpho_market_id,
340
343
  parse_plasma_vault_address,
344
+ parse_shares,
341
345
  parse_tx_hash,
342
346
  )
343
347
  from ipor_fusion.validation import (
@@ -617,6 +621,10 @@ __all__ = [
617
621
  "parse_plasma_vault_address",
618
622
  "parse_morpho_market_id",
619
623
  "parse_tx_hash",
624
+ "parse_amount",
625
+ "parse_shares",
626
+ "format_amount",
627
+ "format_shares",
620
628
  "Price",
621
629
  "Period",
622
630
  "MAX_UINT256",
@@ -1,3 +1,4 @@
1
+ import re
1
2
  from dataclasses import dataclass
2
3
  from typing import ClassVar, Literal, NewType, TypeAlias
3
4
 
@@ -196,3 +197,81 @@ def parse_fuse_address(value: str | bytes) -> FuseAddress:
196
197
  def parse_access_manager_address(value: str | bytes) -> AccessManagerAddress:
197
198
  """An access manager's address, checksummed; see `parse_plasma_vault_address`."""
198
199
  return AccessManagerAddress(_checksum(value))
200
+
201
+
202
+ # ASCII digits only: ``\d`` would also take other scripts' digits, which int() reads.
203
+ _DECIMAL_TEXT = re.compile(r"([0-9]*)(?:\.([0-9]*))?")
204
+
205
+
206
+ _UINT256_DIGITS = len(str(MAX_UINT256))
207
+
208
+
209
+ def _check_decimals(decimals: Decimals) -> None:
210
+ if not 0 <= decimals <= 255:
211
+ raise ValueError(f"decimals must be 0..255 (ERC-20 uint8), got {decimals}")
212
+
213
+
214
+ def _parse_units(text: str, decimals: Decimals, what: str) -> int:
215
+ if not isinstance(text, str):
216
+ raise TypeError(
217
+ f"{what} must be text, not {type(text).__name__}: floats lose precision"
218
+ )
219
+ _check_decimals(decimals)
220
+ match = _DECIMAL_TEXT.fullmatch(text.strip())
221
+ if match is None or not (match.group(1) or match.group(2)):
222
+ raise ValueError(f"not a decimal {what}: {text!r}")
223
+ whole, fraction = match.group(1).lstrip("0"), match.group(2) or ""
224
+ if len(fraction) > decimals:
225
+ raise ValueError(
226
+ f"{what} {text!r} has {len(fraction)} fractional digits,"
227
+ f" more than the {decimals} the token carries"
228
+ )
229
+ # Bounded before int(): a longer whole part overflows uint256 at any scale.
230
+ if len(whole) > _UINT256_DIGITS:
231
+ raise ValueError(f"{what} {text!r} exceeds uint256")
232
+ value = int(whole + fraction.ljust(decimals, "0") or "0")
233
+ if value > MAX_UINT256:
234
+ raise ValueError(f"{what} {text!r} exceeds uint256")
235
+ return value
236
+
237
+
238
+ def _format_units(value: int, decimals: Decimals, what: str) -> str:
239
+ if not 0 <= value <= MAX_UINT256:
240
+ raise ValueError(f"{what} must be within uint256, got {value}")
241
+ _check_decimals(decimals)
242
+ whole, fraction = divmod(value, 10**decimals)
243
+ if fraction == 0:
244
+ return str(whole)
245
+ return f"{whole}.{str(fraction).zfill(decimals).rstrip('0')}"
246
+
247
+
248
+ def parse_amount(text: str, decimals: Decimals) -> Amount:
249
+ """The raw `Amount` of ``text`` token units at ``decimals``, exactly:
250
+ ``parse_amount("1.5", Decimals(6))`` is ``Amount(1_500_000)``.
251
+
252
+ ``text`` is digits with at most one ``.`` (surrounding whitespace ignored);
253
+ no sign, exponent or separators. ``decimals`` is 0..255, an ERC-20 uint8.
254
+ Raises ``ValueError`` for anything else, for more fractional digits than
255
+ ``decimals`` (nothing is rounded) and for a value above uint256; ``TypeError`` for a non-string, so a float is never
256
+ accepted. Inverse of `format_amount`.
257
+ """
258
+ return Amount(_parse_units(text, decimals, "amount"))
259
+
260
+
261
+ def parse_shares(text: str, decimals: Decimals) -> Shares:
262
+ """`parse_amount` for vault shares at the share token's ``decimals``
263
+ (`PlasmaVault.decimals`, not the asset's)."""
264
+ return Shares(_parse_units(text, decimals, "shares"))
265
+
266
+
267
+ def format_amount(amount: Amount, decimals: Decimals) -> str:
268
+ """``amount`` in token units as exact decimal text, no trailing zeros:
269
+ ``format_amount(Amount(1_500_000), Decimals(6))`` is ``"1.5"``; a whole
270
+ number has no ``.``. Raises ``ValueError`` on an amount outside uint256 or
271
+ ``decimals`` outside 0..255. Inverse of `parse_amount`."""
272
+ return _format_units(amount, decimals, "amount")
273
+
274
+
275
+ def format_shares(shares: Shares, decimals: Decimals) -> str:
276
+ """`format_amount` for vault shares."""
277
+ return _format_units(shares, decimals, "shares")
@@ -367,7 +367,9 @@ _ALL_SNAPSHOT: dict[str, frozenset[str]] = {
367
367
  "find_creation_block",
368
368
  "find_markets_missing_erc20_dependency",
369
369
  "find_orphan_fuse_markets",
370
+ "format_amount",
370
371
  "format_market_label",
372
+ "format_shares",
371
373
  "get_contract_name",
372
374
  "get_deployment_tx",
373
375
  "get_logs_adaptive",
@@ -377,10 +379,12 @@ _ALL_SNAPSHOT: dict[str, frozenset[str]] = {
377
379
  "morpho_blue_address",
378
380
  "package_version",
379
381
  "parse_access_manager_address",
382
+ "parse_amount",
380
383
  "parse_fuse_address",
381
384
  "parse_hex_address",
382
385
  "parse_morpho_market_id",
383
386
  "parse_plasma_vault_address",
387
+ "parse_shares",
384
388
  "parse_tx_hash",
385
389
  "price_oracle_middleware",
386
390
  "read_changelog",
@@ -1107,11 +1111,15 @@ _MODULE_PATH_SNAPSHOT: dict[str, frozenset[str]] = {
1107
1111
  "TxHash",
1108
1112
  "Verdict",
1109
1113
  "ZERO_ADDRESS",
1114
+ "format_amount",
1115
+ "format_shares",
1110
1116
  "parse_access_manager_address",
1117
+ "parse_amount",
1111
1118
  "parse_fuse_address",
1112
1119
  "parse_hex_address",
1113
1120
  "parse_morpho_market_id",
1114
1121
  "parse_plasma_vault_address",
1122
+ "parse_shares",
1115
1123
  "parse_tx_hash",
1116
1124
  }
1117
1125
  ),
@@ -6,7 +6,7 @@ from hexbytes import HexBytes
6
6
  from web3 import Web3
7
7
 
8
8
  from ipor_fusion.fuses.events import extract_events
9
- from ipor_fusion.types import Amount, Decimals, Price
9
+ from ipor_fusion.types import MAX_UINT256, Amount, Decimals, Price, Shares
10
10
 
11
11
  ADDR = Web3.to_checksum_address("0x1111111111111111111111111111111111111111")
12
12
 
@@ -155,3 +155,119 @@ class TestRoleParsers:
155
155
  assert parser(bytes.fromhex(self.LOWER[2:])) == checksum
156
156
  with pytest.raises(ValueError):
157
157
  parser("0x1234")
158
+
159
+
160
+ class TestAmountText:
161
+ @pytest.mark.parametrize(
162
+ ("text", "decimals", "raw"),
163
+ [
164
+ ("1.5", 6, 1_500_000),
165
+ ("0.000001", 6, 1),
166
+ ("1", 18, 10**18),
167
+ ("1.", 6, 1_000_000),
168
+ (".5", 6, 500_000),
169
+ (" 42 ", 0, 42),
170
+ ("0", 6, 0),
171
+ ("1.000000", 6, 1_000_000),
172
+ (str(MAX_UINT256), 0, MAX_UINT256),
173
+ (
174
+ "115792089237316195423570985008687907853269984665640564039457.584007913129639935",
175
+ 18,
176
+ MAX_UINT256,
177
+ ),
178
+ ],
179
+ )
180
+ def test_parse_amount_is_exact(self, text, decimals, raw):
181
+ from ipor_fusion import parse_amount
182
+
183
+ assert parse_amount(text, Decimals(decimals)) == raw
184
+
185
+ @pytest.mark.parametrize(
186
+ "text",
187
+ [
188
+ "",
189
+ ".",
190
+ "-1",
191
+ "+1",
192
+ "1e6",
193
+ "1,000",
194
+ "1_000",
195
+ "1.5.0",
196
+ "0x10",
197
+ "1 0",
198
+ "nan",
199
+ "\u0663",
200
+ "\uff11.5",
201
+ ],
202
+ )
203
+ def test_parse_amount_rejects_anything_but_plain_decimal_text(self, text):
204
+ from ipor_fusion import parse_amount
205
+
206
+ with pytest.raises(ValueError, match="not a decimal amount"):
207
+ parse_amount(text, Decimals(6))
208
+
209
+ def test_parse_amount_never_rounds(self):
210
+ from ipor_fusion import parse_amount
211
+
212
+ with pytest.raises(ValueError, match="7 fractional digits"):
213
+ parse_amount("1.0000001", Decimals(6))
214
+
215
+ def test_parse_amount_rejects_uint256_overflow_and_floats(self):
216
+ from ipor_fusion import parse_amount
217
+
218
+ with pytest.raises(ValueError, match="exceeds uint256"):
219
+ parse_amount(str(MAX_UINT256 + 1), Decimals(0))
220
+ with pytest.raises(TypeError, match="floats lose precision"):
221
+ parse_amount(1.5, Decimals(6))
222
+ with pytest.raises(ValueError, match="decimals"):
223
+ parse_amount("1", Decimals(-1))
224
+ with pytest.raises(ValueError, match="0..255"):
225
+ parse_amount("1", Decimals(256))
226
+
227
+ def test_parse_amount_bounds_digits_before_converting(self):
228
+ from ipor_fusion import parse_amount
229
+
230
+ # Leading zeros are not significant, past Python's int() digit limit too.
231
+ assert parse_amount("0" * 5000 + "1", Decimals(0)) == 1
232
+ with pytest.raises(ValueError, match="exceeds uint256"):
233
+ parse_amount("1" * 5000, Decimals(0))
234
+ assert parse_amount("0." + "0" * 254 + "1", Decimals(255)) == 1
235
+
236
+ @pytest.mark.parametrize(
237
+ ("raw", "decimals", "text"),
238
+ [
239
+ (1_500_000, 6, "1.5"),
240
+ (1, 6, "0.000001"),
241
+ (10**18, 18, "1"),
242
+ (0, 6, "0"),
243
+ (42, 0, "42"),
244
+ (123_456_789, 4, "12345.6789"),
245
+ (
246
+ MAX_UINT256,
247
+ 18,
248
+ "115792089237316195423570985008687907853269984665640564039457.584007913129639935",
249
+ ),
250
+ ],
251
+ )
252
+ def test_format_amount_round_trips(self, raw, decimals, text):
253
+ from ipor_fusion import format_amount, parse_amount
254
+
255
+ assert format_amount(Amount(raw), Decimals(decimals)) == text
256
+ assert parse_amount(text, Decimals(decimals)) == raw
257
+
258
+ @pytest.mark.parametrize("raw", [-1, MAX_UINT256 + 1])
259
+ def test_format_amount_rejects_values_outside_uint256(self, raw):
260
+ from ipor_fusion import format_amount, format_shares
261
+
262
+ with pytest.raises(ValueError, match="within uint256"):
263
+ format_amount(Amount(raw), Decimals(6))
264
+ with pytest.raises(ValueError, match="within uint256"):
265
+ format_shares(Shares(raw), Decimals(6))
266
+ with pytest.raises(ValueError, match="0..255"):
267
+ format_amount(Amount(1), Decimals(256))
268
+
269
+ def test_shares_pair_mirrors_amounts(self):
270
+ from ipor_fusion import format_shares, parse_shares
271
+
272
+ assert parse_shares("2.5", Decimals(8)) == Shares(250_000_000)
273
+ assert format_shares(Shares(250_000_000), Decimals(8)) == "2.5"