ipor-fusion 4.1.0.dev26__tar.gz → 4.1.0.dev35__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 (361) hide show
  1. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/PKG-INFO +1 -1
  2. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/pyproject.toml +1 -1
  3. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/cli/options.py +16 -20
  4. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/core/fusion_factory.py +4 -3
  5. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/mcp/server.py +16 -6
  6. ipor_fusion-4.1.0.dev35/tests/_addresses.py +17 -0
  7. ipor_fusion-4.1.0.dev35/tests/test_addresses_helper.py +20 -0
  8. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_cli_helpers.py +15 -12
  9. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_fusion_instance.py +3 -0
  10. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_mcp_preflight.py +9 -0
  11. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_mcp_server.py +15 -5
  12. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_types_and_events.py +2 -3
  13. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/.claude-plugin/marketplace.json +0 -0
  14. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/.claude-plugin/plugin.json +0 -0
  15. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/.env.example +0 -0
  16. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/.gemini/settings.json +0 -0
  17. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/.git-blame-ignore-revs +0 -0
  18. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/.github/workflows/cd.yml +0 -0
  19. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/.github/workflows/ci.yml +0 -0
  20. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/.github/workflows/commit-lint.yml +0 -0
  21. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/.github/workflows/notify-slack.yml +0 -0
  22. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/.github/workflows/python-build.yml +0 -0
  23. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/.github/workflows/python-publish.yml +0 -0
  24. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/.github/workflows/release.yml +0 -0
  25. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/.github/workflows/report-slack.yml +0 -0
  26. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/.gitignore +0 -0
  27. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/.mcp.json +0 -0
  28. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/.pre-commit-config.yaml +0 -0
  29. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/.python-version +0 -0
  30. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/AGENTS.md +0 -0
  31. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/CHANGELOG.md +0 -0
  32. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/CLAUDE.md +0 -0
  33. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/CODEOWNERS +0 -0
  34. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/LICENSE +0 -0
  35. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/MIGRATION_4.md +0 -0
  36. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/README.md +0 -0
  37. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/build.sh +0 -0
  38. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/examples/CONTRIBUTING.md +0 -0
  39. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/examples/README.md +0 -0
  40. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/examples/advanced_euler_v2_credit_market_base.py +0 -0
  41. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/examples/advanced_euler_v2_looping_arbitrum.py +0 -0
  42. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py +0 -0
  43. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/examples/external_state_margin_leg_base.py +0 -0
  44. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/examples/hypercore_vault_official_deployment_hyperevm.py +0 -0
  45. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/examples/simple_aave_v3_supply_base.py +0 -0
  46. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/pytest.ini +0 -0
  47. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/scripts/commit-check.sh +0 -0
  48. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/scripts/fusion_error_signatures.py +0 -0
  49. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/skills/ipor-deploy-vault/SKILL.md +0 -0
  50. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/__init__.py +0 -0
  51. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/about.py +0 -0
  52. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/cache.py +0 -0
  53. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/chains.py +0 -0
  54. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/cli/__init__.py +0 -0
  55. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/cli/address_cmd.py +0 -0
  56. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/cli/changelog_cmd.py +0 -0
  57. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/cli/config_cmd.py +0 -0
  58. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/cli/config_store.py +0 -0
  59. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/cli/main.py +0 -0
  60. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/cli/market_cmd.py +0 -0
  61. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/cli/oracle_mapping_view.py +0 -0
  62. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/cli/preflight_cmd.py +0 -0
  63. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/cli/vault_cmd.py +0 -0
  64. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/cli/vault_health.py +0 -0
  65. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/cli/vault_info_view.py +0 -0
  66. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/cli/vault_markets_view.py +0 -0
  67. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/cli/vault_rendering.py +0 -0
  68. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/config/__init__.py +0 -0
  69. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/config/roles.py +0 -0
  70. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/core/__init__.py +0 -0
  71. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/core/access.py +0 -0
  72. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/core/address.py +0 -0
  73. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/core/context.py +0 -0
  74. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/core/context_manager.py +0 -0
  75. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/core/contract.py +0 -0
  76. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/core/erc20.py +0 -0
  77. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/core/external_state_executor.py +0 -0
  78. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/core/fee_manager.py +0 -0
  79. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/core/fuse.py +0 -0
  80. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/core/fuse_action.py +0 -0
  81. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/core/fuse_decoding.py +0 -0
  82. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/core/logs.py +0 -0
  83. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/core/multicall.py +0 -0
  84. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/core/oracle.py +0 -0
  85. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/core/plasma_vault.py +0 -0
  86. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/core/rewards_manager.py +0 -0
  87. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/core/simulation.py +0 -0
  88. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/core/simulation_result.py +0 -0
  89. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/core/withdraw_manager.py +0 -0
  90. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/__init__.py +0 -0
  91. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/ccip/__init__.py +0 -0
  92. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/ccip/chainlink.py +0 -0
  93. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/ccip/codec.py +0 -0
  94. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/ccip/contracts.py +0 -0
  95. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/ccip/events.py +0 -0
  96. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/ccip/indexer.py +0 -0
  97. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/ccip/lane.py +0 -0
  98. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/ccip/quote.py +0 -0
  99. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/ccip/transport.py +0 -0
  100. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/contracts.py +0 -0
  101. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/discovery.py +0 -0
  102. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/errors.py +0 -0
  103. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/fuses/__init__.py +0 -0
  104. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/fuses/base.py +0 -0
  105. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/fuses/ccip.py +0 -0
  106. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/fuses/stargate.py +0 -0
  107. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/lane.py +0 -0
  108. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/logs.py +0 -0
  109. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/messages.py +0 -0
  110. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/simulation.py +0 -0
  111. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/stargate/__init__.py +0 -0
  112. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/stargate/contracts.py +0 -0
  113. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/stargate/lane.py +0 -0
  114. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/stargate/layerzero.py +0 -0
  115. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/stargate/transport.py +0 -0
  116. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/crosschain/transport.py +0 -0
  117. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/dependency_graph.py +0 -0
  118. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/entry_cli.py +0 -0
  119. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/entry_mcp.py +0 -0
  120. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/errors.py +0 -0
  121. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/explorer.py +0 -0
  122. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/field_docs.py +0 -0
  123. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/fuses/__init__.py +0 -0
  124. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/fuses/aave_v3.py +0 -0
  125. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/fuses/async_action.py +0 -0
  126. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/fuses/base.py +0 -0
  127. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/fuses/compound_v3.py +0 -0
  128. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/fuses/erc4626.py +0 -0
  129. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/fuses/euler_v2.py +0 -0
  130. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/fuses/events.py +0 -0
  131. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/fuses/external_state.py +0 -0
  132. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/fuses/external_state_event_decoding.py +0 -0
  133. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/fuses/fluid_instadapp.py +0 -0
  134. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/fuses/gearbox_v3.py +0 -0
  135. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/fuses/hypercore.py +0 -0
  136. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/fuses/hypercore_event_decoding.py +0 -0
  137. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/fuses/hypercore_pre_hooks.py +0 -0
  138. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/fuses/merkl.py +0 -0
  139. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/fuses/morpho.py +0 -0
  140. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/fuses/ramses_v2.py +0 -0
  141. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/fuses/uniswap_v3.py +0 -0
  142. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/fuses/universal.py +0 -0
  143. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/fusion_errors.py +0 -0
  144. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/guide/__init__.py +0 -0
  145. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/guide/architecture.md +0 -0
  146. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/guide/glossary.md +0 -0
  147. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/guide/invariants.md +0 -0
  148. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/guide/quickstart.md +0 -0
  149. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/hypercore/__init__.py +0 -0
  150. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/market_ids.py +0 -0
  151. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/market_info.py +0 -0
  152. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/mcp/__init__.py +0 -0
  153. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/mcp/guide.py +0 -0
  154. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/mcp/models.py +0 -0
  155. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/morpho_api.py +0 -0
  156. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/preflight.py +0 -0
  157. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/py.typed +0 -0
  158. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/readers/__init__.py +0 -0
  159. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/readers/aave_v3.py +0 -0
  160. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/readers/aave_v4.py +0 -0
  161. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/readers/compound_v3.py +0 -0
  162. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/readers/euler_v2.py +0 -0
  163. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/readers/hypercore.py +0 -0
  164. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/readers/hypercore_outcome.py +0 -0
  165. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/readers/lending_health.py +0 -0
  166. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/readers/morpho.py +0 -0
  167. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/readers/oracle_mapping.py +0 -0
  168. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/readers/oracle_mapping_nodes.py +0 -0
  169. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/readers/oracle_mapping_reader.py +0 -0
  170. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/readers/position_manager.py +0 -0
  171. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/readers/ramses_v2.py +0 -0
  172. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/readers/uniswap_v3.py +0 -0
  173. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/readers/unpriceable.py +0 -0
  174. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/registry.py +0 -0
  175. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/substrates.py +0 -0
  176. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/types.py +0 -0
  177. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/validation.py +0 -0
  178. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/vault_data.py +0 -0
  179. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/vault_erc20.py +0 -0
  180. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/vault_info.py +0 -0
  181. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/vault_managers.py +0 -0
  182. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/vault_positions.py +0 -0
  183. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/src/ipor_fusion/vault_reads.py +0 -0
  184. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/UniswapV3UniversalRouter.py +0 -0
  185. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/_crosschain.py +0 -0
  186. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/_crosschain_lifecycle.py +0 -0
  187. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/_crosschain_recovery.py +0 -0
  188. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/_euler_v2.py +0 -0
  189. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/_event_args.py +0 -0
  190. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/_fake_rpc.py +0 -0
  191. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/_foundry.py +0 -0
  192. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/_golden.py +0 -0
  193. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/_guide.py +0 -0
  194. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/_hypercore_model.py +0 -0
  195. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/_hypercore_shadow.py +0 -0
  196. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/_live.py +0 -0
  197. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/_multicall.py +0 -0
  198. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/_oracle_mapping_fake.py +0 -0
  199. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/_simulate.py +0 -0
  200. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/_validation.py +0 -0
  201. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/addresses.py +0 -0
  202. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/conftest.py +0 -0
  203. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/constants.py +0 -0
  204. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/hypercore_hip3_flow.json +0 -0
  205. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/hypercore_market55.json +0 -0
  206. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/hypercore_official.json +0 -0
  207. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/market_golden/meta_morpho_v1.json +0 -0
  208. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/market_golden/meta_morpho_v1.mcp.json +0 -0
  209. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/market_golden/meta_morpho_v2.json +0 -0
  210. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/market_golden/meta_morpho_v2.mcp.json +0 -0
  211. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/market_golden/morpho_api/market.json +0 -0
  212. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/market_golden/morpho_api/vault_v1.json +0 -0
  213. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/market_golden/morpho_api/vault_v2.json +0 -0
  214. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/market_golden/morpho_api/vault_v2_not_found.json +0 -0
  215. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/market_golden/morpho_blue.json +0 -0
  216. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/market_golden/morpho_blue.mcp.json +0 -0
  217. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/market_golden/morpho_blue_api_error.json +0 -0
  218. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/market_golden/morpho_blue_api_error.mcp.json +0 -0
  219. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/market_golden/morpho_blue_no_api.json +0 -0
  220. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/market_golden/morpho_blue_no_api.mcp.json +0 -0
  221. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/oracle_mapping_golden/mapping.json +0 -0
  222. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/oracle_mapping_golden/mapping.mcp.json +0 -0
  223. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/simulate_v1_request.json +0 -0
  224. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/vault_info_golden/clean.json +0 -0
  225. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/vault_info_golden/clean.mcp.json +0 -0
  226. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/vault_info_golden/clean.txt +0 -0
  227. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/vault_info_golden/deployment_error.json +0 -0
  228. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/vault_info_golden/deployment_error.mcp.json +0 -0
  229. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/vault_info_golden/deployment_error.txt +0 -0
  230. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/vault_info_golden/fetched.cli.json +0 -0
  231. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/vault_info_golden/fetched.json +0 -0
  232. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/vault_info_golden/fetched.mcp.json +0 -0
  233. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/vault_info_golden/full.json +0 -0
  234. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/vault_info_golden/full.mcp.json +0 -0
  235. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/vault_info_golden/full.txt +0 -0
  236. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/vault_info_golden/rich.json +0 -0
  237. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/vault_info_golden/rich.mcp.json +0 -0
  238. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/fixtures/vault_info_golden/rich.txt +0 -0
  239. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_about.py +0 -0
  240. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_access_manager.py +0 -0
  241. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_cache.py +0 -0
  242. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_chains.py +0 -0
  243. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_cli_address.py +0 -0
  244. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_cli_changelog.py +0 -0
  245. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_cli_commands.py +0 -0
  246. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_cli_config_store.py +0 -0
  247. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_cli_hypercore.py +0 -0
  248. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_cli_lending_health.py +0 -0
  249. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_cli_market_golden.py +0 -0
  250. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_cli_market_morpho_blue.py +0 -0
  251. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_cli_mcp_parity.py +0 -0
  252. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_cli_oracle_mapping.py +0 -0
  253. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_cli_oracle_mapping_golden.py +0 -0
  254. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_cli_pending_requests_scan.py +0 -0
  255. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_cli_preflight.py +0 -0
  256. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_cli_role_accounts.py +0 -0
  257. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_cli_vault_info_golden.py +0 -0
  258. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_cli_vault_predates_getters.py +0 -0
  259. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_cli_vault_validate.py +0 -0
  260. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_contract_call.py +0 -0
  261. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_contract_encoder.py +0 -0
  262. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_crosschain_ccip_events.py +0 -0
  263. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_crosschain_ccip_indexer.py +0 -0
  264. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_crosschain_ccip_quote.py +0 -0
  265. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_crosschain_chainlink.py +0 -0
  266. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_crosschain_contracts.py +0 -0
  267. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_crosschain_encoding.py +0 -0
  268. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_crosschain_errors.py +0 -0
  269. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_crosschain_lane.py +0 -0
  270. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_crosschain_layering.py +0 -0
  271. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_crosschain_transport.py +0 -0
  272. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_docs_typing.py +0 -0
  273. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_erc20.py +0 -0
  274. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_error_hierarchy.py +0 -0
  275. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_examples_crosschain.py +0 -0
  276. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_examples_euler_looping_arbitrum.py +0 -0
  277. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_examples_hypercore_hyperevm.py +0 -0
  278. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_examples_vaults.py +0 -0
  279. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_explorer.py +0 -0
  280. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_external_state_events.py +0 -0
  281. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_external_state_executor.py +0 -0
  282. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_fee_manager.py +0 -0
  283. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_fuse_decoding.py +0 -0
  284. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_fuse_encoding.py +0 -0
  285. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_fusion_errors.py +0 -0
  286. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_governance_wrappers.py +0 -0
  287. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_guide.py +0 -0
  288. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_hypercore_deployment.py +0 -0
  289. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_hypercore_events.py +0 -0
  290. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_hypercore_flow.py +0 -0
  291. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_hypercore_live.py +0 -0
  292. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_hypercore_outcome.py +0 -0
  293. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_hypercore_pre_hooks.py +0 -0
  294. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_hypercore_readers.py +0 -0
  295. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_hypercore_simulation.py +0 -0
  296. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_logs.py +0 -0
  297. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_mcp_address.py +0 -0
  298. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_mcp_hypercore.py +0 -0
  299. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_mcp_models.py +0 -0
  300. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_mcp_vault_validate.py +0 -0
  301. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_multicall.py +0 -0
  302. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_oracle.py +0 -0
  303. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_oracle_mapping.py +0 -0
  304. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_plasma_vault.py +0 -0
  305. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_preflight.py +0 -0
  306. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_public_api.py +0 -0
  307. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_public_type_reachability.py +0 -0
  308. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_reader_encoding.py +0 -0
  309. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_registry.py +0 -0
  310. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_revert_decoding.py +0 -0
  311. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_rewards_manager.py +0 -0
  312. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_roles.py +0 -0
  313. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_sdk_layering.py +0 -0
  314. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_borrow_aave_v3_mainnet.py +0 -0
  315. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_claim_merkl_wrapper_base.py +0 -0
  316. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_claim_morpho_rewards.py +0 -0
  317. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_crosschain_hyperevm.py +0 -0
  318. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_euler_v2_batch_base.py +0 -0
  319. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_euler_v2_credit_market_base.py +0 -0
  320. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_euler_v2_swap_deploy_base.py +0 -0
  321. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_euler_v2_swap_reconfigure_base.py +0 -0
  322. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_euler_v2_swap_registry_base.py +0 -0
  323. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_examples_arbitrum.py +0 -0
  324. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_examples_base.py +0 -0
  325. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_examples_crosschain.py +0 -0
  326. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_examples_hyperevm.py +0 -0
  327. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_external_state_executor_base.py +0 -0
  328. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_fusion_factory_clone_base.py +0 -0
  329. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_looping_aave_v3_base.py +0 -0
  330. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_looping_morpho_blue_base.py +0 -0
  331. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_morpho_blue.py +0 -0
  332. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_pilot_v3.py +0 -0
  333. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_pilot_v4_uniswap.py +0 -0
  334. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_pilot_v5_ramses.py +0 -0
  335. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_pilot_v5_scheduled.py +0 -0
  336. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_plasma_vault_setters_base.py +0 -0
  337. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_preflight_base.py +0 -0
  338. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_readers_integration.py +0 -0
  339. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_release_funds.py +0 -0
  340. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_swap_on_base.py +0 -0
  341. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_timelock_base.py +0 -0
  342. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulate_vault_from_scratch_base.py +0 -0
  343. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulation_errors.py +0 -0
  344. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_simulation_observation.py +0 -0
  345. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_solidity_compiler.py +0 -0
  346. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_solidity_mirrors.py +0 -0
  347. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_substrates.py +0 -0
  348. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_unpriceable_tokens.py +0 -0
  349. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_validation.py +0 -0
  350. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_vault_data_block.py +0 -0
  351. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_vault_dep_graph.py +0 -0
  352. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_vault_info_fetched_golden.py +0 -0
  353. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_vault_info_onchain_base.py +0 -0
  354. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_vault_info_onchain_base_no_withdraw_manager.py +0 -0
  355. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_vault_reconciliation_onchain_base.py +0 -0
  356. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_vault_simulator_blocks.py +0 -0
  357. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_web3_context.py +0 -0
  358. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/test_withdraw_manager.py +0 -0
  359. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/typed_client/consumer.py +0 -0
  360. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/tests/typed_client/rejected.py +0 -0
  361. {ipor_fusion-4.1.0.dev26 → ipor_fusion-4.1.0.dev35}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: ipor-fusion
3
- Version: 4.1.0.dev26
3
+ Version: 4.1.0.dev35
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.1.0.dev26"
3
+ version = "4.1.0.dev35"
4
4
  description = "The IPOR Fusion SDK for Python"
5
5
  authors = [
6
6
  { name = "Adam Mydlarz", email = "amydlarz@gmail.com" },
@@ -2,7 +2,6 @@ from __future__ import annotations
2
2
 
3
3
  import click
4
4
  from eth_typing import ChecksumAddress
5
- from web3 import Web3
6
5
 
7
6
  from ipor_fusion.chains import CHAIN_NAME_TO_ID, ensure_supported_chain
8
7
  from ipor_fusion.cli.config_store import (
@@ -13,7 +12,12 @@ from ipor_fusion.core.context import Web3Context
13
12
  from ipor_fusion.errors import (
14
13
  UnsupportedChainError,
15
14
  )
16
- from ipor_fusion.types import ChainId, PlasmaVaultAddress
15
+ from ipor_fusion.types import (
16
+ ChainId,
17
+ PlasmaVaultAddress,
18
+ parse_checksum_address,
19
+ parse_hex_address,
20
+ )
17
21
 
18
22
 
19
23
  # click < 8.4 does not make ParamType generic, so it cannot be subscripted.
@@ -27,26 +31,18 @@ class AddressType(click.ParamType): # pyright: ignore[reportMissingTypeArgument
27
31
  self.fail(f"expected string, got {type(value).__name__}", param, ctx)
28
32
 
29
33
  value = value.strip()
30
- if not value.startswith("0x"):
31
- value = "0x" + value
34
+ if value[:2] in ("0x", "0X"):
35
+ value = value[2:]
36
+ value = "0x" + value
32
37
 
33
- raw = value[2:]
34
- if len(raw) != 40 or not all(c in "0123456789abcdefABCDEF" for c in raw):
38
+ try:
39
+ parse_hex_address(value)
40
+ except ValueError:
35
41
  self.fail(f"invalid Ethereum address: {value}", param, ctx)
36
-
37
- if not raw.islower() and not raw.isupper():
38
- try:
39
- checksum = Web3.to_checksum_address(value)
40
- except Exception:
41
- self.fail(f"invalid address checksum: {value}", param, ctx)
42
- if checksum != value:
43
- self.fail(
44
- f"bad checksum — expected {checksum}, got {value}",
45
- param,
46
- ctx,
47
- )
48
-
49
- return Web3.to_checksum_address(value)
42
+ try:
43
+ return parse_checksum_address(value)
44
+ except ValueError as exc:
45
+ self.fail(str(exc), param, ctx)
50
46
 
51
47
 
52
48
  ADDRESS = AddressType()
@@ -38,6 +38,7 @@ from ipor_fusion.types import (
38
38
  Period,
39
39
  PlasmaVaultAddress,
40
40
  parse_access_manager_address,
41
+ parse_checksum_address,
41
42
  parse_plasma_vault_address,
42
43
  )
43
44
 
@@ -82,8 +83,8 @@ class FusionInstance:
82
83
  def from_dict(cls, data: Mapping[str, object]) -> FusionInstance:
83
84
  """Rebuild an instance from its JSON form (``dataclasses.asdict``),
84
85
  parsing every field: role addresses through their parsers, the rest
85
- checksummed, integers and strings type-checked. Raises ``ValueError``
86
- on a missing, extra or malformed field."""
86
+ through `parse_checksum_address`, integers and strings type-checked.
87
+ Raises ``ValueError`` on a missing, extra or malformed field."""
87
88
  names = {f.name for f in fields(cls)}
88
89
  missing = names - data.keys()
89
90
  extra = data.keys() - names
@@ -128,7 +129,7 @@ def _text(value: object) -> str:
128
129
 
129
130
 
130
131
  def _address(value: object) -> ChecksumAddress:
131
- return Web3.to_checksum_address(_text(value))
132
+ return parse_checksum_address(_text(value))
132
133
 
133
134
 
134
135
  _FUSION_INSTANCE_OUTPUT_TYPES: list[str] = [
@@ -8,6 +8,7 @@ from collections.abc import Callable
8
8
  from functools import partial
9
9
  from typing import Annotated, Literal
10
10
 
11
+ from eth_typing import ChecksumAddress
11
12
  from mcp.server.fastmcp import FastMCP
12
13
  from pydantic import AfterValidator, BeforeValidator, Field
13
14
  from web3 import Web3
@@ -76,8 +77,8 @@ from ipor_fusion.registry import (
76
77
  from ipor_fusion.types import (
77
78
  ChainId,
78
79
  PlasmaVaultAddress,
80
+ parse_checksum_address,
79
81
  parse_morpho_market_id,
80
- parse_plasma_vault_address,
81
82
  )
82
83
  from ipor_fusion.validation import validate_vault
83
84
  from ipor_fusion.vault_data import (
@@ -117,14 +118,19 @@ def _resolve_provider(cfg: FusionConfig, chain_id: ChainId) -> str:
117
118
  )
118
119
 
119
120
 
120
- def _vault_arg(raw: str) -> PlasmaVaultAddress:
121
- """A vault address as a tool caller sends it: surrounding whitespace and a
121
+ def _address_arg(raw: str) -> ChecksumAddress:
122
+ """An address as a tool caller sends it: surrounding whitespace and a
122
123
  missing ``0x`` are accepted, as in 3.x; letter case follows
123
124
  `parse_checksum_address`, so a wrong EIP-55 checksum is refused."""
124
125
  value = raw.strip()
125
126
  if value[:2] not in ("0x", "0X"):
126
127
  value = "0x" + value
127
- return parse_plasma_vault_address(value)
128
+ return parse_checksum_address(value)
129
+
130
+
131
+ def _vault_arg(raw: str) -> PlasmaVaultAddress:
132
+ """`_address_arg`, labeled as a Plasma Vault's address."""
133
+ return PlasmaVaultAddress(_address_arg(raw))
128
134
 
129
135
 
130
136
  def _resolve_chain_id(
@@ -341,6 +347,10 @@ def vault_preflight(
341
347
  raise ValueError(f"calldata: {exc}") from exc
342
348
  if not actions:
343
349
  raise ValueError("calldata: the batch has no actions")
350
+ try:
351
+ sender_address = _address_arg(sender)
352
+ except ValueError as exc:
353
+ raise ValueError(f"sender: {exc}") from exc
344
354
  cfg = load_config()
345
355
  checksum = _vault_arg(vault_address)
346
356
  chain_id = _resolve_chain_id(cfg, checksum, chain_id)
@@ -350,7 +360,7 @@ def vault_preflight(
350
360
  ctx,
351
361
  checksum,
352
362
  actions,
353
- sender=Web3.to_checksum_address(sender),
363
+ sender=sender_address,
354
364
  simulate=simulate,
355
365
  )
356
366
  return ExecutePreflightResponse.model_validate(build_execute_preflight_json(result))
@@ -752,7 +762,7 @@ def market_meta_morpho(
752
762
  vault_address: MetaMorpho V1 or Vault V2 address.
753
763
  chain_id: EVM chain ID.
754
764
  """
755
- info = fetch_vault(Web3.to_checksum_address(vault_address), chain_id)
765
+ info = fetch_vault(_address_arg(vault_address), chain_id)
756
766
  payload = build_meta_morpho_json(info, chain_id)
757
767
  return MetaMorphoVaultResponse.model_validate(payload)
758
768
 
@@ -0,0 +1,17 @@
1
+ """Address spellings that EIP-55 must reject."""
2
+
3
+ from web3 import Web3
4
+
5
+
6
+ def miscased(address: str) -> str:
7
+ """``address`` checksummed with one letter's case flipped: the same 20 bytes,
8
+ a wrong checksum. Only a mixed-case result carries a checksum, so the first
9
+ flip that leaves the digits mixed case is taken."""
10
+ checksummed = Web3.to_checksum_address(address)
11
+ for i, c in enumerate(checksummed[2:], start=2):
12
+ if c.isalpha():
13
+ flipped = checksummed[:i] + c.swapcase() + checksummed[i + 1 :]
14
+ digits = flipped[2:]
15
+ if digits not in (digits.lower(), digits.upper()):
16
+ return flipped
17
+ raise AssertionError(f"no wrong checksum is possible for {address}")
@@ -0,0 +1,20 @@
1
+ """The ``miscased`` test helper returns a spelling EIP-55 rejects, or fails."""
2
+
3
+ import pytest
4
+ from _addresses import miscased
5
+
6
+ from ipor_fusion.types import parse_checksum_address
7
+
8
+
9
+ def test_skips_a_flip_that_leaves_one_case():
10
+ # Flipping B gives all lowercase, which carries no checksum.
11
+ address = "0xBca0000000000000000000000000000000000000"
12
+ bad = miscased(address)
13
+ assert bad.lower() == address.lower()
14
+ with pytest.raises(ValueError, match="invalid address checksum"):
15
+ parse_checksum_address(bad)
16
+
17
+
18
+ def test_fails_when_no_flip_leaves_mixed_case():
19
+ with pytest.raises(AssertionError, match="no wrong checksum"):
20
+ miscased("0xCc00000000000000000000000000000000000000")
@@ -6,6 +6,7 @@ from unittest.mock import MagicMock, patch
6
6
 
7
7
  import click
8
8
  import pytest
9
+ from _addresses import miscased
9
10
  from _multicall import decode_aggregate3, multicall_aware
10
11
  from _validation import holding, validate
11
12
  from click.testing import CliRunner
@@ -131,9 +132,20 @@ class TestAddressType:
131
132
  checksum = Web3.to_checksum_address("0x" + "1a2b3c4d5e" * 4)
132
133
  assert ADDRESS.convert(checksum, None, None) == checksum
133
134
 
135
+ @pytest.mark.parametrize(
136
+ "raw",
137
+ [
138
+ "0X" + "ab" * 20,
139
+ "0X" + "AB" * 20,
140
+ "0X" + VALID_CHECKSUM[2:],
141
+ ],
142
+ )
143
+ def test_valid_with_uppercase_0x_prefix(self, raw: str):
144
+ assert _convert_via_cli(raw) == VALID_CHECKSUM
145
+
134
146
  def test_bad_checksum_mixed_case(self):
135
147
  good = str(Web3.to_checksum_address("0x" + "1a2b3c4d5e" * 4))
136
- bad = good[:-1] + good[-1].swapcase()
148
+ bad = miscased(good)
137
149
  runner = CliRunner()
138
150
 
139
151
  @click.command()
@@ -143,6 +155,8 @@ class TestAddressType:
143
155
 
144
156
  result = runner.invoke(cmd, [bad])
145
157
  assert result.exit_code != 0
158
+ assert "invalid address checksum" in result.output
159
+ assert good not in result.output
146
160
 
147
161
  def test_too_short(self):
148
162
  runner = CliRunner()
@@ -1158,17 +1172,6 @@ class TestPrintBalanceFusesTable:
1158
1172
  assert "Zero-Balance Fuses" not in out
1159
1173
 
1160
1174
 
1161
- class TestAddressTypeChecksumException:
1162
- @patch("ipor_fusion.cli.options.Web3.to_checksum_address")
1163
- def test_checksum_exception_caught(self, mock_checksum):
1164
- mock_checksum.side_effect = Exception("unexpected error")
1165
- mixed = "0xAbCdEf1234567890aBcDeF1234567890AbCdEf12"
1166
- with pytest.raises(
1167
- click.exceptions.BadParameter, match="invalid address checksum"
1168
- ):
1169
- ADDRESS.convert(mixed, None, None)
1170
-
1171
-
1172
1175
  class TestPrintReconciliation:
1173
1176
  def test_within_threshold(self, capsys):
1174
1177
  data = VaultData(
@@ -6,6 +6,7 @@ from __future__ import annotations
6
6
  from dataclasses import asdict
7
7
 
8
8
  import pytest
9
+ from _addresses import miscased
9
10
  from web3 import Web3
10
11
 
11
12
  from ipor_fusion.core.fusion_factory import FusionInstance
@@ -58,6 +59,8 @@ def test_from_dict_checksums_every_address_and_round_trips():
58
59
  (lambda d: d.update(extra=1), "extra"),
59
60
  (lambda d: d.update(plasma_vault="0x1234"), "address"),
60
61
  (lambda d: d.update(plasma_vault=" " + d["plasma_vault"]), "address"),
62
+ (lambda d: d.update(plasma_vault=miscased(d["plasma_vault"])), "checksum"),
63
+ (lambda d: d.update(price_manager=miscased(d["price_manager"])), "checksum"),
61
64
  (lambda d: d.update(asset_decimals="8"), "integer"),
62
65
  (lambda d: d.update(index=True), "integer"),
63
66
  (lambda d: d.update(asset_symbol=None), "string"),
@@ -4,6 +4,7 @@ import asyncio
4
4
  from unittest.mock import MagicMock, patch
5
5
 
6
6
  import pytest
7
+ from _addresses import miscased
7
8
  from mcp.server.fastmcp.exceptions import ToolError
8
9
  from web3 import Web3
9
10
 
@@ -26,6 +27,8 @@ from ipor_fusion.types import (
26
27
 
27
28
  VAULT = PlasmaVaultAddress(Web3.to_checksum_address("0x" + "11" * 20))
28
29
  SENDER = Web3.to_checksum_address("0x" + "33" * 20)
30
+ # Hex letters, so it can carry a wrong checksum; SENDER has none.
31
+ SENDER_HEX = "0x" + "ab" * 20
29
32
  FUSE = FuseAddress(Web3.to_checksum_address("0x" + "55" * 20))
30
33
  ACTION = AaveV3SupplyFuse(FUSE).supply(
31
34
  asset=Web3.to_checksum_address("0x" + "44" * 20), amount=Amount(10)
@@ -84,3 +87,9 @@ def test_bad_calldata_is_a_tool_error(preflight):
84
87
  with pytest.raises(ToolError, match="no actions"):
85
88
  _call(vault_address=VAULT, calldata=empty, sender=SENDER)
86
89
  preflight.assert_not_called()
90
+
91
+
92
+ def test_wrong_sender_checksum_is_a_tool_error(preflight):
93
+ with pytest.raises(ToolError, match="sender: invalid address checksum"):
94
+ _call(vault_address=VAULT, calldata=CALLDATA, sender=miscased(SENDER_HEX))
95
+ preflight.assert_not_called()
@@ -5,6 +5,7 @@ import importlib.metadata
5
5
  from unittest.mock import ANY, MagicMock, patch
6
6
 
7
7
  import pytest
8
+ from _addresses import miscased
8
9
  from mcp.server.fastmcp.exceptions import ToolError
9
10
  from web3 import Web3
10
11
 
@@ -770,7 +771,7 @@ _LOAN = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
770
771
  _COLLAT = "0xD2af830E8CBdFed6CC11Bab697bB25496ed6FA62"
771
772
  _ORACLE = "0x7C65985C35181D51eF7571FA40211B57659B7d80"
772
773
  _IRM = "0x870Ac11D48B15db9a138Cf899d20F13F79Ba00BC"
773
- _VAULT = "0xf9bDdD4A9b3a45F980E11Fdde96E16364DDBec49"
774
+ _VAULT = Web3.to_checksum_address("0xf9bddd4a9b3a45f980e11fdde96e16364ddbec49")
774
775
 
775
776
 
776
777
  def _stub_reader_instance():
@@ -1085,6 +1086,17 @@ class TestMarketMetaMorpho:
1085
1086
  with pytest.raises(MorphoApiError, match="not found"):
1086
1087
  market_meta_morpho(vault_address=_VAULT, chain_id=1)
1087
1088
 
1089
+ @patch("ipor_fusion.mcp.server.fetch_vault", return_value=_v1_info())
1090
+ def test_accepts_padded_bare_lowercase_address(self, fetch):
1091
+ market_meta_morpho(vault_address=f" {_VAULT[2:].lower()} ", chain_id=1)
1092
+ fetch.assert_called_once_with(_VAULT, 1)
1093
+
1094
+ @patch("ipor_fusion.mcp.server.fetch_vault", return_value=_v1_info())
1095
+ def test_rejects_a_wrong_checksum(self, fetch):
1096
+ with pytest.raises(ValueError, match="invalid address checksum"):
1097
+ market_meta_morpho(vault_address=miscased(_VAULT), chain_id=1)
1098
+ fetch.assert_not_called()
1099
+
1088
1100
 
1089
1101
  class TestVaultAddressArgument:
1090
1102
  """Tool callers may pad an address with whitespace or omit its ``0x``; the
@@ -1114,10 +1126,8 @@ class TestVaultAddressArgument:
1114
1126
  _vault_arg(raw)
1115
1127
 
1116
1128
  def test_rejects_a_wrong_checksum(self):
1117
- checksum = Web3.to_checksum_address(self.VAULT)
1118
- i = next(i for i, c in enumerate(checksum) if c in "abcdefABCDEF")
1119
- miscased = checksum[:i] + checksum[i].swapcase() + checksum[i + 1 :]
1120
- for raw in (miscased, "0X" + miscased[2:], miscased[2:]):
1129
+ bad = miscased(self.VAULT)
1130
+ for raw in (bad, "0X" + bad[2:], bad[2:]):
1121
1131
  with pytest.raises(ValueError, match="invalid address checksum"):
1122
1132
  _vault_arg(raw)
1123
1133
 
@@ -1,6 +1,7 @@
1
1
  from dataclasses import dataclass
2
2
 
3
3
  import pytest
4
+ from _addresses import miscased
4
5
  from eth_abi import encode
5
6
  from hexbytes import HexBytes
6
7
  from web3 import Web3
@@ -161,10 +162,8 @@ class TestChecksumParsers:
161
162
  for bad in ("0x1234", " " + self.LOWER):
162
163
  with pytest.raises(ValueError):
163
164
  parser(bad)
164
- i = next(i for i, c in enumerate(checksum) if c in "abcdefABCDEF")
165
- miscased = checksum[:i] + checksum[i].swapcase() + checksum[i + 1 :]
166
165
  with pytest.raises(ValueError, match="invalid address checksum"):
167
- parser(miscased)
166
+ parser(miscased(checksum))
168
167
  # Two characters swapped: a different address that looks right.
169
168
  swapped = checksum[:2] + checksum[3] + checksum[2] + checksum[4:]
170
169
  assert swapped[2:4] != checksum[2:4]