ipor-fusion 4.0.0.dev282__tar.gz → 4.0.0.dev291__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 (350) hide show
  1. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/MIGRATION_4.md +59 -0
  2. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/PKG-INFO +2 -2
  3. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/README.md +1 -1
  4. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/pyproject.toml +1 -1
  5. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/__init__.py +10 -0
  6. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/core/external_state_executor.py +64 -10
  7. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/fuses/__init__.py +8 -0
  8. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/fuses/external_state.py +11 -0
  9. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/fuses/external_state_event_decoding.py +48 -0
  10. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/fuses/hypercore.py +37 -14
  11. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/fuses/hypercore_event_decoding.py +3 -133
  12. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/hypercore/__init__.py +4 -28
  13. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/mcp/models.py +16 -4
  14. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/readers/hypercore.py +93 -92
  15. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/substrates.py +93 -41
  16. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/types.py +5 -0
  17. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/vault_info.py +12 -8
  18. ipor_fusion-4.0.0.dev291/tests/fixtures/hypercore_official.json +16 -0
  19. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/vault_info_golden/full.json +6 -3
  20. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/vault_info_golden/full.mcp.json +7 -4
  21. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_cli_vault_info_golden.py +7 -5
  22. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_external_state_events.py +23 -3
  23. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_external_state_executor.py +21 -4
  24. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_fuse_encoding.py +17 -2
  25. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_hypercore_deployment.py +14 -0
  26. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_hypercore_events.py +15 -1
  27. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_hypercore_flow.py +2 -5
  28. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_hypercore_live.py +14 -18
  29. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_hypercore_readers.py +107 -64
  30. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_mcp_hypercore.py +8 -6
  31. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_mcp_models.py +7 -3
  32. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_public_api.py +12 -14
  33. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_solidity_mirrors.py +8 -6
  34. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_substrates.py +19 -3
  35. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/typed_client/consumer.py +1 -1
  36. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/.claude-plugin/marketplace.json +0 -0
  37. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/.claude-plugin/plugin.json +0 -0
  38. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/.env.example +0 -0
  39. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/.gemini/settings.json +0 -0
  40. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/.git-blame-ignore-revs +0 -0
  41. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/.github/workflows/cd.yml +0 -0
  42. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/.github/workflows/ci.yml +0 -0
  43. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/.github/workflows/commit-lint.yml +0 -0
  44. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/.github/workflows/notify-slack.yml +0 -0
  45. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/.github/workflows/python-build.yml +0 -0
  46. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/.github/workflows/python-publish.yml +0 -0
  47. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/.github/workflows/release.yml +0 -0
  48. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/.github/workflows/report-slack.yml +0 -0
  49. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/.gitignore +0 -0
  50. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/.mcp.json +0 -0
  51. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/.pre-commit-config.yaml +0 -0
  52. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/.python-version +0 -0
  53. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/AGENTS.md +0 -0
  54. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/CHANGELOG.md +0 -0
  55. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/CLAUDE.md +0 -0
  56. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/CODEOWNERS +0 -0
  57. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/LICENSE +0 -0
  58. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/build.sh +0 -0
  59. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/examples/CONTRIBUTING.md +0 -0
  60. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/examples/README.md +0 -0
  61. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/examples/advanced_euler_v2_credit_market_base.py +0 -0
  62. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/examples/advanced_euler_v2_looping_arbitrum.py +0 -0
  63. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/examples/composed_hypercore_flow_arbitrum_hyperevm.py +0 -0
  64. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py +0 -0
  65. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/examples/external_state_margin_leg_base.py +0 -0
  66. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/examples/simple_aave_v3_supply_base.py +0 -0
  67. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/pytest.ini +0 -0
  68. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/scripts/commit-check.sh +0 -0
  69. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/scripts/crosschain_readiness.py +0 -0
  70. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/skills/ipor-deploy-vault/SKILL.md +0 -0
  71. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/about.py +0 -0
  72. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/cache.py +0 -0
  73. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/chains.py +0 -0
  74. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/cli/__init__.py +0 -0
  75. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/cli/address_cmd.py +0 -0
  76. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/cli/changelog_cmd.py +0 -0
  77. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/cli/config_cmd.py +0 -0
  78. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/cli/config_store.py +0 -0
  79. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/cli/main.py +0 -0
  80. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/cli/market_cmd.py +0 -0
  81. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/cli/options.py +0 -0
  82. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/cli/oracle_mapping_view.py +0 -0
  83. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/cli/vault_cmd.py +0 -0
  84. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/cli/vault_health.py +0 -0
  85. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/cli/vault_info_view.py +0 -0
  86. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/cli/vault_markets_view.py +0 -0
  87. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/cli/vault_rendering.py +0 -0
  88. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/config/__init__.py +0 -0
  89. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/config/roles.py +0 -0
  90. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/core/__init__.py +0 -0
  91. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/core/access.py +0 -0
  92. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/core/address.py +0 -0
  93. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/core/context.py +0 -0
  94. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/core/context_manager.py +0 -0
  95. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/core/contract.py +0 -0
  96. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/core/erc20.py +0 -0
  97. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/core/fee_manager.py +0 -0
  98. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/core/fuse.py +0 -0
  99. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/core/fuse_action.py +0 -0
  100. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/core/fusion_factory.py +0 -0
  101. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/core/logs.py +0 -0
  102. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/core/multicall.py +0 -0
  103. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/core/oracle.py +0 -0
  104. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/core/plasma_vault.py +0 -0
  105. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/core/rewards_manager.py +0 -0
  106. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/core/simulation.py +0 -0
  107. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/core/simulation_result.py +0 -0
  108. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/core/withdraw_manager.py +0 -0
  109. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/__init__.py +0 -0
  110. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/ccip/__init__.py +0 -0
  111. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/ccip/chainlink.py +0 -0
  112. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/ccip/codec.py +0 -0
  113. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/ccip/contracts.py +0 -0
  114. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/ccip/events.py +0 -0
  115. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/ccip/indexer.py +0 -0
  116. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/ccip/lane.py +0 -0
  117. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/ccip/quote.py +0 -0
  118. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/ccip/transport.py +0 -0
  119. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/contracts.py +0 -0
  120. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/discovery.py +0 -0
  121. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/errors.py +0 -0
  122. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/fuses/__init__.py +0 -0
  123. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/fuses/base.py +0 -0
  124. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/fuses/ccip.py +0 -0
  125. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/fuses/stargate.py +0 -0
  126. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/lane.py +0 -0
  127. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/logs.py +0 -0
  128. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/messages.py +0 -0
  129. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/simulation.py +0 -0
  130. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/stargate/__init__.py +0 -0
  131. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/stargate/contracts.py +0 -0
  132. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/stargate/lane.py +0 -0
  133. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/stargate/layerzero.py +0 -0
  134. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/stargate/transport.py +0 -0
  135. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/crosschain/transport.py +0 -0
  136. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/dependency_graph.py +0 -0
  137. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/entry_cli.py +0 -0
  138. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/entry_mcp.py +0 -0
  139. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/errors.py +0 -0
  140. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/explorer.py +0 -0
  141. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/field_docs.py +0 -0
  142. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/fuses/aave_v3.py +0 -0
  143. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/fuses/async_action.py +0 -0
  144. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/fuses/base.py +0 -0
  145. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/fuses/compound_v3.py +0 -0
  146. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/fuses/erc4626.py +0 -0
  147. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/fuses/euler_v2.py +0 -0
  148. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/fuses/events.py +0 -0
  149. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/fuses/fluid_instadapp.py +0 -0
  150. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/fuses/gearbox_v3.py +0 -0
  151. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/fuses/merkl.py +0 -0
  152. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/fuses/morpho.py +0 -0
  153. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/fuses/ramses_v2.py +0 -0
  154. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/fuses/uniswap_v3.py +0 -0
  155. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/fuses/universal.py +0 -0
  156. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/guide/__init__.py +0 -0
  157. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/guide/architecture.md +0 -0
  158. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/guide/glossary.md +0 -0
  159. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/guide/invariants.md +0 -0
  160. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/guide/quickstart.md +0 -0
  161. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/market_ids.py +0 -0
  162. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/market_info.py +0 -0
  163. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/mcp/__init__.py +0 -0
  164. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/mcp/guide.py +0 -0
  165. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/mcp/server.py +0 -0
  166. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/morpho_api.py +0 -0
  167. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/py.typed +0 -0
  168. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/readers/__init__.py +0 -0
  169. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/readers/aave_v3.py +0 -0
  170. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/readers/aave_v4.py +0 -0
  171. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/readers/compound_v3.py +0 -0
  172. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/readers/hypercore_outcome.py +0 -0
  173. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/readers/lending_health.py +0 -0
  174. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/readers/morpho.py +0 -0
  175. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/readers/oracle_mapping.py +0 -0
  176. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/readers/oracle_mapping_nodes.py +0 -0
  177. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/readers/oracle_mapping_reader.py +0 -0
  178. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/readers/position_manager.py +0 -0
  179. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/readers/ramses_v2.py +0 -0
  180. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/readers/uniswap_v3.py +0 -0
  181. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/readers/unpriceable.py +0 -0
  182. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/registry.py +0 -0
  183. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/validation.py +0 -0
  184. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/vault_data.py +0 -0
  185. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/vault_erc20.py +0 -0
  186. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/vault_managers.py +0 -0
  187. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/vault_positions.py +0 -0
  188. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/src/ipor_fusion/vault_reads.py +0 -0
  189. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/UniswapV3UniversalRouter.py +0 -0
  190. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/_crosschain.py +0 -0
  191. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/_crosschain_lifecycle.py +0 -0
  192. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/_crosschain_recovery.py +0 -0
  193. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/_euler_v2.py +0 -0
  194. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/_event_args.py +0 -0
  195. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/_fake_rpc.py +0 -0
  196. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/_foundry.py +0 -0
  197. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/_golden.py +0 -0
  198. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/_guide.py +0 -0
  199. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/_hypercore_model.py +0 -0
  200. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/_hypercore_shadow.py +0 -0
  201. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/_live.py +0 -0
  202. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/_multicall.py +0 -0
  203. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/_oracle_mapping_fake.py +0 -0
  204. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/_simulate.py +0 -0
  205. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/_validation.py +0 -0
  206. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/addresses.py +0 -0
  207. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/conftest.py +0 -0
  208. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/constants.py +0 -0
  209. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/hypercore_hip3_flow.json +0 -0
  210. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/hypercore_market55.json +0 -0
  211. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/market_golden/meta_morpho_v1.json +0 -0
  212. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/market_golden/meta_morpho_v1.mcp.json +0 -0
  213. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/market_golden/meta_morpho_v2.json +0 -0
  214. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/market_golden/meta_morpho_v2.mcp.json +0 -0
  215. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/market_golden/morpho_api/market.json +0 -0
  216. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/market_golden/morpho_api/vault_v1.json +0 -0
  217. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/market_golden/morpho_api/vault_v2.json +0 -0
  218. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/market_golden/morpho_api/vault_v2_not_found.json +0 -0
  219. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/market_golden/morpho_blue.json +0 -0
  220. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/market_golden/morpho_blue.mcp.json +0 -0
  221. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/market_golden/morpho_blue_api_error.json +0 -0
  222. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/market_golden/morpho_blue_api_error.mcp.json +0 -0
  223. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/market_golden/morpho_blue_no_api.json +0 -0
  224. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/market_golden/morpho_blue_no_api.mcp.json +0 -0
  225. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/oracle_mapping_golden/mapping.json +0 -0
  226. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/oracle_mapping_golden/mapping.mcp.json +0 -0
  227. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/simulate_v1_request.json +0 -0
  228. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/vault_info_golden/clean.json +0 -0
  229. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/vault_info_golden/clean.mcp.json +0 -0
  230. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/vault_info_golden/clean.txt +0 -0
  231. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/vault_info_golden/deployment_error.json +0 -0
  232. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/vault_info_golden/deployment_error.mcp.json +0 -0
  233. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/vault_info_golden/deployment_error.txt +0 -0
  234. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/vault_info_golden/fetched.cli.json +0 -0
  235. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/vault_info_golden/fetched.json +0 -0
  236. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/vault_info_golden/fetched.mcp.json +0 -0
  237. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/vault_info_golden/full.txt +0 -0
  238. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/vault_info_golden/rich.json +0 -0
  239. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/vault_info_golden/rich.mcp.json +0 -0
  240. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/fixtures/vault_info_golden/rich.txt +0 -0
  241. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_about.py +0 -0
  242. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_access_manager.py +0 -0
  243. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_cache.py +0 -0
  244. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_chains.py +0 -0
  245. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_cli_address.py +0 -0
  246. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_cli_changelog.py +0 -0
  247. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_cli_commands.py +0 -0
  248. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_cli_config_store.py +0 -0
  249. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_cli_helpers.py +0 -0
  250. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_cli_hypercore.py +0 -0
  251. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_cli_lending_health.py +0 -0
  252. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_cli_market_golden.py +0 -0
  253. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_cli_market_morpho_blue.py +0 -0
  254. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_cli_mcp_parity.py +0 -0
  255. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_cli_oracle_mapping.py +0 -0
  256. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_cli_oracle_mapping_golden.py +0 -0
  257. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_cli_pending_requests_scan.py +0 -0
  258. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_cli_role_accounts.py +0 -0
  259. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_cli_vault_predates_getters.py +0 -0
  260. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_cli_vault_validate.py +0 -0
  261. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_contract_call.py +0 -0
  262. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_contract_encoder.py +0 -0
  263. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_crosschain_ccip_events.py +0 -0
  264. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_crosschain_ccip_indexer.py +0 -0
  265. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_crosschain_ccip_quote.py +0 -0
  266. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_crosschain_chainlink.py +0 -0
  267. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_crosschain_contracts.py +0 -0
  268. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_crosschain_encoding.py +0 -0
  269. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_crosschain_errors.py +0 -0
  270. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_crosschain_lane.py +0 -0
  271. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_crosschain_layering.py +0 -0
  272. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_crosschain_readiness.py +0 -0
  273. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_crosschain_readiness_report.py +0 -0
  274. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_crosschain_transport.py +0 -0
  275. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_docs_typing.py +0 -0
  276. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_erc20.py +0 -0
  277. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_error_hierarchy.py +0 -0
  278. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_examples_composed_hypercore.py +0 -0
  279. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_examples_crosschain.py +0 -0
  280. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_examples_euler_looping_arbitrum.py +0 -0
  281. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_examples_vaults.py +0 -0
  282. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_explorer.py +0 -0
  283. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_fee_manager.py +0 -0
  284. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_fusion_instance.py +0 -0
  285. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_governance_wrappers.py +0 -0
  286. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_guide.py +0 -0
  287. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_hypercore_outcome.py +0 -0
  288. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_hypercore_simulation.py +0 -0
  289. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_logs.py +0 -0
  290. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_mcp_address.py +0 -0
  291. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_mcp_server.py +0 -0
  292. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_mcp_vault_validate.py +0 -0
  293. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_multicall.py +0 -0
  294. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_oracle.py +0 -0
  295. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_oracle_mapping.py +0 -0
  296. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_plasma_vault.py +0 -0
  297. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_public_type_reachability.py +0 -0
  298. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_reader_encoding.py +0 -0
  299. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_readiness_selection.py +0 -0
  300. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_registry.py +0 -0
  301. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_revert_decoding.py +0 -0
  302. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_rewards_manager.py +0 -0
  303. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_roles.py +0 -0
  304. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_sdk_layering.py +0 -0
  305. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_borrow_aave_v3_mainnet.py +0 -0
  306. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_claim_merkl_wrapper_base.py +0 -0
  307. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_claim_morpho_rewards.py +0 -0
  308. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_crosschain_canary.py +0 -0
  309. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_crosschain_hypercore.py +0 -0
  310. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_crosschain_hyperevm.py +0 -0
  311. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_crosschain_lifecycle.py +0 -0
  312. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_euler_v2_batch_base.py +0 -0
  313. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_euler_v2_credit_market_base.py +0 -0
  314. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_euler_v2_swap_deploy_base.py +0 -0
  315. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_euler_v2_swap_reconfigure_base.py +0 -0
  316. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_euler_v2_swap_registry_base.py +0 -0
  317. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_examples_arbitrum.py +0 -0
  318. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_examples_base.py +0 -0
  319. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_examples_crosschain.py +0 -0
  320. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_external_state_executor_base.py +0 -0
  321. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_fusion_factory_clone_base.py +0 -0
  322. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_looping_aave_v3_base.py +0 -0
  323. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_looping_morpho_blue_base.py +0 -0
  324. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_morpho_blue.py +0 -0
  325. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_pilot_v3.py +0 -0
  326. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_pilot_v4_uniswap.py +0 -0
  327. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_pilot_v5_ramses.py +0 -0
  328. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_pilot_v5_scheduled.py +0 -0
  329. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_plasma_vault_setters_base.py +0 -0
  330. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_readers_integration.py +0 -0
  331. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_release_funds.py +0 -0
  332. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_swap_on_base.py +0 -0
  333. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulate_vault_from_scratch_base.py +0 -0
  334. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulation_errors.py +0 -0
  335. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_simulation_observation.py +0 -0
  336. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_solidity_compiler.py +0 -0
  337. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_types_and_events.py +0 -0
  338. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_unpriceable_tokens.py +0 -0
  339. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_validation.py +0 -0
  340. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_vault_data_block.py +0 -0
  341. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_vault_dep_graph.py +0 -0
  342. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_vault_info_fetched_golden.py +0 -0
  343. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_vault_info_onchain_base.py +0 -0
  344. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_vault_info_onchain_base_no_withdraw_manager.py +0 -0
  345. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_vault_reconciliation_onchain_base.py +0 -0
  346. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_vault_simulator_blocks.py +0 -0
  347. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_web3_context.py +0 -0
  348. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/test_withdraw_manager.py +0 -0
  349. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/tests/typed_client/rejected.py +0 -0
  350. {ipor_fusion-4.0.0.dev282 → ipor_fusion-4.0.0.dev291}/uv.lock +0 -0
@@ -390,6 +390,65 @@ module was renamed to match. Import the decoders with `from ipor_fusion import
390
390
  external_state_events` and `from ipor_fusion.hypercore import hypercore_events`;
391
391
  the modules are internal.
392
392
 
393
+ #### HyperCore follows the released contracts
394
+
395
+ 4.0 reads and encodes the HyperCore contracts `ipor-abi` publishes on HyperEVM
396
+ (contracts release 2026-10-21), not the earlier market-55 test deployment.
397
+
398
+ - **Pending reader.** `HYPERCORE_PENDING_READERS[999]` is
399
+ `0x1EFFb12434f5fb59a636C54D8CBaC93b13DF1A9E`. `HyperCorePendingReader.is_pending()`
400
+ is gone (the released reader has no `isPending()`): call `is_action_pending()`,
401
+ and `is_order_in_flight()` for the order rate limit. `pending_state()` decodes
402
+ the released 23-word tuple only; the earlier reader `0x83F54bc9…` returns 18
403
+ words and is no longer supported. A vault of the earlier build (its pre-hooks
404
+ predate the transfer effect) reads through the released reader only while
405
+ nothing is in flight: the struct only grew, so a settled state decodes the same,
406
+ but during an action the released reader derives `pending`/`settled` from effect
407
+ fields the earlier hooks never write, so it can disagree with what that vault
408
+ enforces.
409
+ - **`HyperCorePendingState`.** Removed: `settlement_mode`, `reported_result`,
410
+ `result_l1_block`, `refreshing` (the contracts no longer write them). Added:
411
+ `effect_kind` (`HyperCoreEffectKind`), `effect_token_index`, `effect_evm_asset`,
412
+ `expected_balance`, `timeout_at`, `last_order_l1_block`. A transfer with an effect
413
+ settles when the expected balance is observed or `timeout_at` passes.
414
+ - **`vault info` / `vault_info`.** `hypercore.pending` drops `refreshing`,
415
+ `settlement_mode`, `reported_result` and gains the six fields above.
416
+ - **Settlement mode removed.** `SettlementMode` and `HyperCoreReportedResult` are
417
+ gone, and so are the settlement fuse and reporter events
418
+ (`HyperCoreReportedActionSettled`, `ReportSubmitted`, `ObserverSetProposed`,
419
+ `ObserverSetChanged`, `RecoveryProposed`, `RecoveryExecuted` and their `*Args`
420
+ / `*Event` classes): orders settle by time, transfers by time and effect.
421
+ `HyperCoreConfigKey.WINDOW_ORDER_SECONDS` and `SETTLEMENT_MODE` keep their
422
+ numbers but are reserved and ignored (`RESERVED_HYPERCORE_CONFIG_KEYS`); a
423
+ decoded substrate of either carries `extra["reserved"] == "true"`.
424
+ - **New substrates.** `HyperCoreSubstrates.perp_position_cap(asset,
425
+ max_position_notional_usd6)` (type 7) and `HyperCoreConfigKey`
426
+ `TRANSFER_TIMEOUT_SECONDS`, `ACTIVATION_FEE_ALLOWANCE_USDC_WEI`, `MAX_NAV_JUMP_BPS`,
427
+ `MAX_MARK_ORACLE_DEVIATION_BPS`, `NAV_JUMP_FLOOR_USD6` (7..11); `decode_substrate`
428
+ decodes them instead of flagging them as errors.
429
+
430
+ #### ExternalState: two executor builds, one custodian marker
431
+
432
+ The 2026-10-21 contracts release (on Arbitrum in `ipor-abi`) changes what the
433
+ balance fuse and the pre-hook compare to detect an unprocessed custodian
434
+ update: the executor's confirm count instead of the last confirmed update's
435
+ timestamp. HyperEVM, Base and Ethereum still publish the earlier build, so both
436
+ exist; the comparison is equality either way.
437
+
438
+ - `ExternalStateVaultState.last_checked_custodian_timestamp` is
439
+ `last_checked_custodian_marker` and `BalanceFuseSnapshot.last_custodian_update_timestamp`
440
+ is `custodian_marker`, both a `CustodianMarker` (an opaque value the
441
+ contracts only compare for equality): a timestamp on an earlier executor, the
442
+ confirm count on a released one. `ExternalStateExecutor.confirm_count()`
443
+ exists only on the released executor (it reverts on an earlier one), and
444
+ `last_custodian_update_timestamp()` reads the timestamp on both.
445
+ - New on the released build: `ExternalStateExecutor.unforwarded_credit(asset)`,
446
+ `proposal_base_balance(account)`, `ExternalStateOperationFuse.sweep_surplus(asset)`,
447
+ and the events `ExternalStateBalanceFuseLastCustodianConfirmCountUpdated` and
448
+ `ExternalStateOperationFuseSweepSurplus` (the released balance fuse no longer
449
+ emits `...LastCustodianTimestampUpdated`; it stays registered for the earlier
450
+ build).
451
+
393
452
  **Removed.**
394
453
 
395
454
  - `IporFusionMarkets.RWA`: market 50 is `IporFusionMarkets.EXTERNAL_STATE`.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: ipor-fusion
3
- Version: 4.0.0.dev282
3
+ Version: 4.0.0.dev291
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
@@ -463,7 +463,7 @@ Fuse.method() --> FuseAction --> PlasmaVault.execute([actions]) --> Call
463
463
  | `PriceOracleMiddleware` | Asset price feeds |
464
464
  | `PriceOracleMiddlewareManager` | Per-vault price-source overrides |
465
465
  | `ExternalStateExecutor` | NAV propose/confirm for off-vault capital (market 50); the executor's thresholds (`staleness_max`, `big_change_bps`, `dust_threshold`, `min_update_interval`), the live aggregate (`get_balance_fuse_snapshot`) and the pre-hook's staleness clock (`get_oldest_update_timestamp`) |
466
- | `read_external_state`, `ExternalStateVaultState` | The market's vault-scoped state from the vault's ERC-7201 storage at one block: executor, the balance fuse's cached total, the custodian timestamp it last checked and the pause flag the pre-hook enforces (no getter exposes them) |
466
+ | `read_external_state`, `ExternalStateVaultState` | The market's vault-scoped state from the vault's ERC-7201 storage at one block: executor, the balance fuse's cached total, the custodian marker it last checked (a timestamp on the earlier executor build, the confirm count on the 2026-10-21 one) and the pause flag the pre-hook enforces (no getter exposes them) |
467
467
  | `decode_external_state_event`, `EXTERNAL_STATE_TOPICS` | The ExternalState events the vault emits (big change, cache updates, unpause, rescue, executor creation and deployment, operation enter/exit), decoded by topic with their raw log identity; a malformed listed log raises |
468
468
  | `erc20_balance_slot`, `VaultSimulator.with_erc20_balance` | Fund any address with any ERC-20 in a simulation by a storage override (slot found by probing), no holder to impersonate |
469
469
  | `ERC20` | Token reads and approvals |
@@ -414,7 +414,7 @@ Fuse.method() --> FuseAction --> PlasmaVault.execute([actions]) --> Call
414
414
  | `PriceOracleMiddleware` | Asset price feeds |
415
415
  | `PriceOracleMiddlewareManager` | Per-vault price-source overrides |
416
416
  | `ExternalStateExecutor` | NAV propose/confirm for off-vault capital (market 50); the executor's thresholds (`staleness_max`, `big_change_bps`, `dust_threshold`, `min_update_interval`), the live aggregate (`get_balance_fuse_snapshot`) and the pre-hook's staleness clock (`get_oldest_update_timestamp`) |
417
- | `read_external_state`, `ExternalStateVaultState` | The market's vault-scoped state from the vault's ERC-7201 storage at one block: executor, the balance fuse's cached total, the custodian timestamp it last checked and the pause flag the pre-hook enforces (no getter exposes them) |
417
+ | `read_external_state`, `ExternalStateVaultState` | The market's vault-scoped state from the vault's ERC-7201 storage at one block: executor, the balance fuse's cached total, the custodian marker it last checked (a timestamp on the earlier executor build, the confirm count on the 2026-10-21 one) and the pause flag the pre-hook enforces (no getter exposes them) |
418
418
  | `decode_external_state_event`, `EXTERNAL_STATE_TOPICS` | The ExternalState events the vault emits (big change, cache updates, unpause, rescue, executor creation and deployment, operation enter/exit), decoded by topic with their raw log identity; a malformed listed log raises |
419
419
  | `erc20_balance_slot`, `VaultSimulator.with_erc20_balance` | Fund any address with any ERC-20 in a simulation by a storage override (slot found by probing), no holder to impersonate |
420
420
  | `ERC20` | Token reads and approvals |
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ipor-fusion"
3
- version = "4.0.0.dev282"
3
+ version = "4.0.0.dev291"
4
4
  description = "The IPOR Fusion SDK for Python"
5
5
  authors = [
6
6
  { name = "Adam Mydlarz", email = "amydlarz@gmail.com" },
@@ -196,10 +196,12 @@ from ipor_fusion.fuses.external_state_event_decoding import (
196
196
  EXTERNAL_STATE_TOPICS,
197
197
  ExternalStateAssetRescuedArgs,
198
198
  ExternalStateAssetRescuedEvent,
199
+ ExternalStateBalanceFuseLastCustodianConfirmCountUpdatedEvent,
199
200
  ExternalStateBalanceFuseLastCustodianTimestampUpdatedEvent,
200
201
  ExternalStateBalanceFuseLastTotalBalanceUpdatedEvent,
201
202
  ExternalStateBigChangeDetectedArgs,
202
203
  ExternalStateBigChangeDetectedEvent,
204
+ ExternalStateCustodianConfirmCountUpdatedArgs,
203
205
  ExternalStateCustodianTimestampUpdatedArgs,
204
206
  ExternalStateEvent,
205
207
  ExternalStateEventArgs,
@@ -210,6 +212,8 @@ from ipor_fusion.fuses.external_state_event_decoding import (
210
212
  ExternalStateOperationArgs,
211
213
  ExternalStateOperationFuseEnterEvent,
212
214
  ExternalStateOperationFuseExitEvent,
215
+ ExternalStateOperationFuseSweepSurplusArgs,
216
+ ExternalStateOperationFuseSweepSurplusEvent,
213
217
  ExternalStateTotalBalanceUpdatedArgs,
214
218
  ExternalStateUnpausedArgs,
215
219
  ExternalStateUnpausedEvent,
@@ -333,6 +337,7 @@ from ipor_fusion.types import (
333
337
  AssetSource,
334
338
  ChainId,
335
339
  Check,
340
+ CustodianMarker,
336
341
  Decimals,
337
342
  Fee,
338
343
  FuseAddress,
@@ -437,6 +442,8 @@ __all__ = [
437
442
  "EXTERNAL_STATE_EVENT_CLASSES",
438
443
  "ExternalStateBigChangeDetectedEvent",
439
444
  "ExternalStateBalanceFuseLastCustodianTimestampUpdatedEvent",
445
+ "ExternalStateBalanceFuseLastCustodianConfirmCountUpdatedEvent",
446
+ "ExternalStateOperationFuseSweepSurplusEvent",
440
447
  "ExternalStateBalanceFuseLastTotalBalanceUpdatedEvent",
441
448
  "ExternalStateUnpausedEvent",
442
449
  "ExternalStateAssetRescuedEvent",
@@ -447,6 +454,8 @@ __all__ = [
447
454
  "ExternalStateAssetRescuedArgs",
448
455
  "ExternalStateBigChangeDetectedArgs",
449
456
  "ExternalStateCustodianTimestampUpdatedArgs",
457
+ "ExternalStateCustodianConfirmCountUpdatedArgs",
458
+ "ExternalStateOperationFuseSweepSurplusArgs",
450
459
  "ExternalStateEventArgs",
451
460
  "ExternalStateExecutorArgs",
452
461
  "ExternalStateOperationArgs",
@@ -664,6 +673,7 @@ __all__ = [
664
673
  "format_amount",
665
674
  "format_shares",
666
675
  "Price",
676
+ "CustodianMarker",
667
677
  "Period",
668
678
  "MAX_UINT256",
669
679
  "ZERO_ADDRESS",
@@ -35,6 +35,7 @@ from ipor_fusion.types import (
35
35
  ZERO_ADDRESS,
36
36
  Amount,
37
37
  ChainId,
38
+ CustodianMarker,
38
39
  Period,
39
40
  PlasmaVaultAddress,
40
41
  ProposalHash,
@@ -127,10 +128,15 @@ class ExternalStateVaultState:
127
128
  `last_total_balance` is the balance fuse's cache of the executor's total in
128
129
  raw underlying units, as of the fuse's last refresh -- not the live total,
129
130
  which `ExternalStateExecutor.get_balance_fuse_snapshot` reads;
130
- `last_checked_custodian_timestamp` is the executor custodian timestamp the
131
- balance fuse last processed -- not necessarily the latest custodian update
131
+ `last_checked_custodian_marker` is the executor's custodian marker the
132
+ balance fuse last processed -- the last confirmed custodian update's block
133
+ timestamp on executors of the contracts before the 2026-10-21 release, the
134
+ executor's confirm count (`ExternalStateExecutor.confirm_count`) on the
135
+ executors of that release; either way not necessarily the latest update
132
136
  and not the pre-hook's staleness clock, which is
133
- `ExternalStateExecutor.get_oldest_update_timestamp`; `paused` is the flag
137
+ `ExternalStateExecutor.get_oldest_update_timestamp`. The fuse and the
138
+ pre-hook only compare it for equality with
139
+ `BalanceFuseSnapshot.custodian_marker`; `paused` is the flag
134
140
  the balance fuse sets on a big change and `ExternalStateUnpauseFuse` clears
135
141
  with an atomist signature. `ExternalStatePausePreHook` blocks the vault's
136
142
  gated user operations while the flag is set, and also, flag or not, while
@@ -141,7 +147,7 @@ class ExternalStateVaultState:
141
147
 
142
148
  executor: ChecksumAddress | None
143
149
  last_total_balance: Amount
144
- last_checked_custodian_timestamp: Timestamp
150
+ last_checked_custodian_marker: CustodianMarker
145
151
  paused: bool
146
152
  block: int
147
153
 
@@ -150,11 +156,14 @@ class ExternalStateVaultState:
150
156
  class BalanceFuseSnapshot:
151
157
  """`ExternalStateExecutor.getBalanceFuseSnapshot()`: the live sum of the
152
158
  tracked balances in raw underlying units, the cached big-change threshold
153
- in basis points and the timestamp of the last confirmed custodian update."""
159
+ in basis points and the custodian marker: the last confirmed custodian
160
+ update's timestamp on executors before the 2026-10-21 contracts release,
161
+ the confirm count on the executors of that release (two confirms in one
162
+ block then still differ)."""
154
163
 
155
164
  total_balance: Amount
156
165
  big_change_bps: int
157
- last_custodian_update_timestamp: Timestamp
166
+ custodian_marker: CustodianMarker
158
167
 
159
168
 
160
169
  def _storage_word(raw: bytes) -> int:
@@ -226,7 +235,7 @@ def read_external_state(
226
235
  return ExternalStateVaultState(
227
236
  executor=Web3.to_checksum_address(f"0x{words[0]:040x}") if words[0] else None,
228
237
  last_total_balance=Amount(words[1]),
229
- last_checked_custodian_timestamp=Timestamp(words[2]),
238
+ last_checked_custodian_marker=CustodianMarker(words[2]),
230
239
  paused=words[3] == 1,
231
240
  block=block,
232
241
  )
@@ -344,18 +353,63 @@ class ExternalStateExecutor(ContractWrapper):
344
353
 
345
354
  def get_balance_fuse_snapshot(self) -> Call[BalanceFuseSnapshot]:
346
355
  """The live aggregate the balance fuse reads: the sum of the tracked
347
- balances, the big-change threshold and the last confirmed custodian
348
- update timestamp, in one call. Pin the context's block to the one
356
+ balances, the big-change threshold and the custodian marker, in one
357
+ call. Pin the context's block to the one
349
358
  `read_external_state` returned to compare live against cached."""
350
359
  return self._view(
351
360
  "getBalanceFuseSnapshot()",
352
361
  output_types=["uint256", "uint256", "uint256"],
353
362
  ).map(
354
363
  lambda values: BalanceFuseSnapshot(
355
- Amount(values[0]), int(values[1]), Timestamp(values[2])
364
+ Amount(values[0]), int(values[1]), CustodianMarker(values[2])
356
365
  )
357
366
  )
358
367
 
368
+ def confirm_count(self) -> Call[CustodianMarker]:
369
+ """Executors of the 2026-10-21 contracts release only: the count of
370
+ confirmed custodian updates across every balance account, the marker
371
+ `get_balance_fuse_snapshot` reports. An earlier executor has no such
372
+ function and the call reverts."""
373
+ return self._view(
374
+ "confirmCount()", output_types=["uint256"], decoder=CustodianMarker
375
+ )
376
+
377
+ def last_custodian_update_timestamp(self) -> Call[Timestamp]:
378
+ """Block timestamp of the last confirmed custodian update on any
379
+ balance account."""
380
+ return self._view(
381
+ "lastCustodianUpdateTimestamp()",
382
+ output_types=["uint256"],
383
+ decoder=Timestamp,
384
+ )
385
+
386
+ def unforwarded_credit(self, asset: ChecksumAddress) -> Call[Amount]:
387
+ """Executors of the 2026-10-21 contracts release only: tokens of
388
+ `asset` credited through the vault path that have not left the
389
+ executor. The executor's `asset` balance above it is surplus (a
390
+ donation or a payout sent straight to the executor):
391
+ `ExternalStateOperationFuse.sweep_surplus` moves it to the vault, and
392
+ custodians should not propose while it exists unless they know whether
393
+ their report counts it."""
394
+ return self._view(
395
+ "unforwardedCredit(address)",
396
+ asset,
397
+ output_types=["uint256"],
398
+ decoder=Amount,
399
+ )
400
+
401
+ def proposal_base_balance(self, balance_account: ChecksumAddress) -> Call[Amount]:
402
+ """Executors of the 2026-10-21 contracts release only: the account
403
+ balance when the pending proposal was made. `confirmBalance` reverts
404
+ `ExternalStateExecutorBalanceChangedSinceProposal` once the balance
405
+ differs from it (an alpha flow ran in between): propose again."""
406
+ return self._view(
407
+ "proposalBaseBalance(address)",
408
+ balance_account,
409
+ output_types=["uint256"],
410
+ decoder=Amount,
411
+ )
412
+
359
413
  def get_oldest_update_timestamp(self) -> Call[Timestamp]:
360
414
  """The pre-hook's staleness clock: the oldest non-zero `lastUpdated`
361
415
  across the balance accounts, 0 when no account was ever updated. The
@@ -30,10 +30,12 @@ from ipor_fusion.fuses.external_state_event_decoding import (
30
30
  EXTERNAL_STATE_TOPICS,
31
31
  ExternalStateAssetRescuedArgs,
32
32
  ExternalStateAssetRescuedEvent,
33
+ ExternalStateBalanceFuseLastCustodianConfirmCountUpdatedEvent,
33
34
  ExternalStateBalanceFuseLastCustodianTimestampUpdatedEvent,
34
35
  ExternalStateBalanceFuseLastTotalBalanceUpdatedEvent,
35
36
  ExternalStateBigChangeDetectedArgs,
36
37
  ExternalStateBigChangeDetectedEvent,
38
+ ExternalStateCustodianConfirmCountUpdatedArgs,
37
39
  ExternalStateCustodianTimestampUpdatedArgs,
38
40
  ExternalStateEvent,
39
41
  ExternalStateEventArgs,
@@ -44,6 +46,8 @@ from ipor_fusion.fuses.external_state_event_decoding import (
44
46
  ExternalStateOperationArgs,
45
47
  ExternalStateOperationFuseEnterEvent,
46
48
  ExternalStateOperationFuseExitEvent,
49
+ ExternalStateOperationFuseSweepSurplusArgs,
50
+ ExternalStateOperationFuseSweepSurplusEvent,
47
51
  ExternalStateTotalBalanceUpdatedArgs,
48
52
  ExternalStateUnpausedArgs,
49
53
  ExternalStateUnpausedEvent,
@@ -146,10 +150,14 @@ __all__ = [
146
150
  "ExternalStateAssetRescuedArgs",
147
151
  "ExternalStateAssetRescuedEvent",
148
152
  "ExternalStateBalanceFuseLastCustodianTimestampUpdatedEvent",
153
+ "ExternalStateBalanceFuseLastCustodianConfirmCountUpdatedEvent",
154
+ "ExternalStateOperationFuseSweepSurplusEvent",
149
155
  "ExternalStateBalanceFuseLastTotalBalanceUpdatedEvent",
150
156
  "ExternalStateBigChangeDetectedArgs",
151
157
  "ExternalStateBigChangeDetectedEvent",
152
158
  "ExternalStateCustodianTimestampUpdatedArgs",
159
+ "ExternalStateCustodianConfirmCountUpdatedArgs",
160
+ "ExternalStateOperationFuseSweepSurplusArgs",
153
161
  "ExternalStateEvent",
154
162
  "ExternalStateEventArgs",
155
163
  "ExternalStateEventSpec",
@@ -92,6 +92,17 @@ class ExternalStateOperationFuse(Fuse):
92
92
  """
93
93
  return self._action_raw("createExecutor()", [])
94
94
 
95
+ def sweep_surplus(self, asset: ChecksumAddress) -> FuseAction:
96
+ """Operation fuses of the 2026-10-21 contracts release only: move to
97
+ the vault the executor's ``asset`` balance above its unforwarded
98
+ credit (tokens that did not arrive through the vault path, such as a
99
+ donation), emitting ``ExternalStateOperationFuseSweepSurplus``. The
100
+ swept tokens enter NAV at once only when ``asset`` is the underlying.
101
+ Use it for tokens the confirmed custodian report no longer counts; a
102
+ payout it still counts is booked with ``exit`` instead."""
103
+ self._validate_address(asset, "asset")
104
+ return self._action_raw("sweepSurplus(address)", [asset])
105
+
95
106
  def _build(
96
107
  self,
97
108
  method: str,
@@ -65,6 +65,10 @@ EXTERNAL_STATE_EVENT_SPECS: tuple[ExternalStateEventSpec, ...] = (
65
65
  "ExternalStateBalanceFuseLastCustodianTimestampUpdated",
66
66
  (("uint256", "oldTimestamp"), ("uint256", "newTimestamp")),
67
67
  ),
68
+ ExternalStateEventSpec(
69
+ "ExternalStateBalanceFuseLastCustodianConfirmCountUpdated",
70
+ (("uint256", "oldConfirmCount"), ("uint256", "newConfirmCount")),
71
+ ),
68
72
  ExternalStateEventSpec(
69
73
  "ExternalStateBalanceFuseLastTotalBalanceUpdated",
70
74
  (("uint256", "oldTotalBalance"), ("uint256", "newTotalBalance")),
@@ -106,6 +110,10 @@ EXTERNAL_STATE_EVENT_SPECS: tuple[ExternalStateEventSpec, ...] = (
106
110
  ("uint256", "actionsCount"),
107
111
  ),
108
112
  ),
113
+ ExternalStateEventSpec(
114
+ "ExternalStateOperationFuseSweepSurplus",
115
+ (("address", "version"), ("address", "asset"), ("uint256", "amount")),
116
+ ),
109
117
  # ExternalStateExecutorStorageLib
110
118
  ExternalStateEventSpec(
111
119
  "ExternalStateExecutorDeployed",
@@ -127,6 +135,24 @@ class ExternalStateCustodianTimestampUpdatedArgs(TypedDict):
127
135
  newTimestamp: Timestamp
128
136
 
129
137
 
138
+ class ExternalStateCustodianConfirmCountUpdatedArgs(TypedDict):
139
+ """``ExternalStateBalanceFuseLastCustodianConfirmCountUpdated`` (balance
140
+ fuses of the 2026-10-21 contracts release; earlier ones emit the
141
+ timestamp event)."""
142
+
143
+ oldConfirmCount: int
144
+ newConfirmCount: int
145
+
146
+
147
+ class ExternalStateOperationFuseSweepSurplusArgs(TypedDict):
148
+ """``ExternalStateOperationFuseSweepSurplus``: ``amount`` of ``asset``
149
+ swept from the executor to the vault."""
150
+
151
+ version: FuseAddress
152
+ asset: ChecksumAddress
153
+ amount: Amount
154
+
155
+
130
156
  class ExternalStateTotalBalanceUpdatedArgs(TypedDict):
131
157
  """``ExternalStateBalanceFuseLastTotalBalanceUpdated``."""
132
158
 
@@ -213,6 +239,24 @@ class ExternalStateBalanceFuseLastCustodianTimestampUpdatedEvent(
213
239
  args: ExternalStateCustodianTimestampUpdatedArgs
214
240
 
215
241
 
242
+ @dataclass(frozen=True, slots=True, kw_only=True)
243
+ class ExternalStateBalanceFuseLastCustodianConfirmCountUpdatedEvent(
244
+ _ExternalStateEventBase
245
+ ):
246
+ name: Literal["ExternalStateBalanceFuseLastCustodianConfirmCountUpdated"] = (
247
+ "ExternalStateBalanceFuseLastCustodianConfirmCountUpdated"
248
+ )
249
+ args: ExternalStateCustodianConfirmCountUpdatedArgs
250
+
251
+
252
+ @dataclass(frozen=True, slots=True, kw_only=True)
253
+ class ExternalStateOperationFuseSweepSurplusEvent(_ExternalStateEventBase):
254
+ name: Literal["ExternalStateOperationFuseSweepSurplus"] = (
255
+ "ExternalStateOperationFuseSweepSurplus"
256
+ )
257
+ args: ExternalStateOperationFuseSweepSurplusArgs
258
+
259
+
216
260
  @dataclass(frozen=True, slots=True, kw_only=True)
217
261
  class ExternalStateBalanceFuseLastTotalBalanceUpdatedEvent(_ExternalStateEventBase):
218
262
  name: Literal["ExternalStateBalanceFuseLastTotalBalanceUpdated"] = (
@@ -262,6 +306,8 @@ class ExternalStateExecutorDeployedEvent(_ExternalStateEventBase):
262
306
  ExternalStateEvent: TypeAlias = (
263
307
  ExternalStateBigChangeDetectedEvent
264
308
  | ExternalStateBalanceFuseLastCustodianTimestampUpdatedEvent
309
+ | ExternalStateBalanceFuseLastCustodianConfirmCountUpdatedEvent
310
+ | ExternalStateOperationFuseSweepSurplusEvent
265
311
  | ExternalStateBalanceFuseLastTotalBalanceUpdatedEvent
266
312
  | ExternalStateUnpausedEvent
267
313
  | ExternalStateAssetRescuedEvent
@@ -275,6 +321,8 @@ ExternalStateEvent: TypeAlias = (
275
321
  EXTERNAL_STATE_EVENT_CLASSES: dict[str, type[ExternalStateEvent]] = {
276
322
  "ExternalStateBigChangeDetected": ExternalStateBigChangeDetectedEvent,
277
323
  "ExternalStateBalanceFuseLastCustodianTimestampUpdated": ExternalStateBalanceFuseLastCustodianTimestampUpdatedEvent,
324
+ "ExternalStateBalanceFuseLastCustodianConfirmCountUpdated": ExternalStateBalanceFuseLastCustodianConfirmCountUpdatedEvent,
325
+ "ExternalStateOperationFuseSweepSurplus": ExternalStateOperationFuseSweepSurplusEvent,
278
326
  "ExternalStateBalanceFuseLastTotalBalanceUpdated": ExternalStateBalanceFuseLastTotalBalanceUpdatedEvent,
279
327
  "ExternalStateUnpaused": ExternalStateUnpausedEvent,
280
328
  "ExternalStateAssetRescued": ExternalStateAssetRescuedEvent,
@@ -95,15 +95,12 @@ class TimeInForce(IntEnum):
95
95
  IOC = 3
96
96
 
97
97
 
98
- class SettlementMode(IntEnum):
99
- """``Config{SettlementMode}``: how a pending action is cleared."""
100
-
101
- TIMING = 1
102
- REPORTED = 2
103
-
104
-
105
98
  class HyperCoreConfigKey(IntEnum):
106
- """``HyperCoreSubstrateLib.ConfigKey`` (the Undefined member is invalid)."""
99
+ """``HyperCoreSubstrateLib.ConfigKey`` (the Undefined member is invalid).
100
+
101
+ The numbering is stable: ``WINDOW_ORDER_SECONDS`` (2) and
102
+ ``SETTLEMENT_MODE`` (5) are reserved and ignored by the fuses; orders
103
+ settle by time and the observed effect only."""
107
104
 
108
105
  WINDOW_TRANSFER_SECONDS = 1
109
106
  WINDOW_ORDER_SECONDS = 2
@@ -111,6 +108,17 @@ class HyperCoreConfigKey(IntEnum):
111
108
  PERP_DEX_IDS = 4
112
109
  SETTLEMENT_MODE = 5
113
110
  SPOT_SEND_BRIDGE_ENABLED = 6
111
+ TRANSFER_TIMEOUT_SECONDS = 7
112
+ ACTIVATION_FEE_ALLOWANCE_USDC_WEI = 8
113
+ MAX_NAV_JUMP_BPS = 9
114
+ MAX_MARK_ORACLE_DEVIATION_BPS = 10
115
+ NAV_JUMP_FLOOR_USD6 = 11
116
+
117
+
118
+ #: Config keys the fuses ignore (kept for their stable numbering).
119
+ RESERVED_HYPERCORE_CONFIG_KEYS = frozenset(
120
+ {HyperCoreConfigKey.WINDOW_ORDER_SECONDS, HyperCoreConfigKey.SETTLEMENT_MODE}
121
+ )
114
122
 
115
123
 
116
124
  def hip3_action_asset(dex: int, index_in_dex: int) -> HyperCoreAsset:
@@ -347,11 +355,13 @@ class HyperCoreSubstrates:
347
355
  (at most one when any of them is HIP-3), Destinations for ``sendAsset`` /
348
356
  ``spotSend`` (only the vault itself and, for the Core -> EVM route, the
349
357
  token's :func:`system_address` are accepted by the fuses), a SendCap per
350
- token (mandatory: a token without one cannot be sent), Builders, and the
351
- Config keys. ``WINDOW_ORDER_SECONDS`` and ``SETTLEMENT_MODE`` are required
352
- before any order or cancel, ``MAX_USD_CLASS_TRANSFER_USD6`` before a margin
353
- transfer; ``WINDOW_TRANSFER_SECONDS`` defaults to 2 s and
354
- ``SPOT_SEND_BRIDGE_ENABLED`` to disabled. :func:`ipor_fusion.decode_substrate`
358
+ token (mandatory: a token without one cannot be sent), Builders, a
359
+ PerpPositionCap per market whose open position is capped, and the Config
360
+ keys. ``MAX_USD_CLASS_TRANSFER_USD6`` is required before a margin transfer;
361
+ ``WINDOW_TRANSFER_SECONDS`` defaults to 2 s, ``SPOT_SEND_BRIDGE_ENABLED`` to
362
+ disabled, ``TRANSFER_TIMEOUT_SECONDS`` to 600 s (at least 60),
363
+ ``MAX_NAV_JUMP_BPS`` to 5000 and ``MAX_MARK_ORACLE_DEVIATION_BPS`` to 500;
364
+ the reserved keys are ignored. :func:`ipor_fusion.decode_substrate`
355
365
  inverts these.
356
366
  """
357
367
 
@@ -394,7 +404,9 @@ class HyperCoreSubstrates:
394
404
  @staticmethod
395
405
  def config(key: HyperCoreConfigKey, value: int) -> bytes:
396
406
  """One Config key; ``PERP_DEX_IDS`` is a bitmap (bit i enables perp
397
- dex i, bit 0 stays clear), ``SETTLEMENT_MODE`` a :class:`SettlementMode`."""
407
+ dex i, bit 0 stays clear). The reserved keys
408
+ (:data:`RESERVED_HYPERCORE_CONFIG_KEYS`) encode but the fuses ignore
409
+ them."""
398
410
  key = HyperCoreConfigKey(key)
399
411
  _validate_uint(value, 240, "value")
400
412
  return _word(5, (int(key) << 240) | value)
@@ -405,3 +417,14 @@ class HyperCoreSubstrates:
405
417
  _validate_uint(token_index, 64, "token_index")
406
418
  _validate_uint(max_wei, 128, "max_wei")
407
419
  return _word(6, (token_index << 128) | max_wei)
420
+
421
+ @staticmethod
422
+ def perp_position_cap(
423
+ asset: HyperCoreAsset, max_position_notional_usd6: int
424
+ ) -> bytes:
425
+ """Cap on the open position notional of action asset ``asset`` in USD
426
+ (6 decimals); the order fuse reverts
427
+ ``HyperCoreOrderFusePositionCapExceeded`` above it."""
428
+ _validate_uint(asset, 32, "asset")
429
+ _validate_uint(max_position_notional_usd6, 88, "max_position_notional_usd6")
430
+ return _word(7, (asset << 216) | (max_position_notional_usd6 << 128))