ipor-fusion 4.0.0.dev162__tar.gz → 4.0.0.dev164__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 (303) hide show
  1. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/MIGRATION_4.md +25 -9
  2. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/PKG-INFO +1 -1
  3. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/pyproject.toml +1 -1
  4. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/__init__.py +54 -4
  5. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/fuses/__init__.py +34 -2
  6. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/fuses/external_state_events.py +106 -35
  7. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/fuses/hypercore_events.py +157 -36
  8. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/_event_args.py +14 -3
  9. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_external_state_events.py +8 -6
  10. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_hypercore_events.py +21 -14
  11. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_public_api.py +44 -3
  12. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/typed_client/consumer.py +24 -6
  13. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/typed_client/rejected.py +4 -0
  14. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/.claude-plugin/marketplace.json +0 -0
  15. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/.claude-plugin/plugin.json +0 -0
  16. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/.env.example +0 -0
  17. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/.gemini/settings.json +0 -0
  18. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/.git-blame-ignore-revs +0 -0
  19. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/.github/workflows/cd.yml +0 -0
  20. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/.github/workflows/ci.yml +0 -0
  21. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/.github/workflows/commit-lint.yml +0 -0
  22. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/.github/workflows/notify-slack.yml +0 -0
  23. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/.github/workflows/python-build.yml +0 -0
  24. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/.github/workflows/python-publish.yml +0 -0
  25. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/.github/workflows/release.yml +0 -0
  26. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/.github/workflows/report-slack.yml +0 -0
  27. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/.gitignore +0 -0
  28. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/.mcp.json +0 -0
  29. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/.pre-commit-config.yaml +0 -0
  30. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/.python-version +0 -0
  31. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/AGENTS.md +0 -0
  32. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/CHANGELOG.md +0 -0
  33. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/CLAUDE.md +0 -0
  34. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/CODEOWNERS +0 -0
  35. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/LICENSE +0 -0
  36. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/README.md +0 -0
  37. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/build.sh +0 -0
  38. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/examples/CONTRIBUTING.md +0 -0
  39. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/examples/README.md +0 -0
  40. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/examples/advanced_euler_v2_credit_market_base.py +0 -0
  41. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/examples/advanced_euler_v2_looping_arbitrum.py +0 -0
  42. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/examples/composed_hypercore_flow_arbitrum_hyperevm.py +0 -0
  43. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/examples/crosschain_ccip_usdc_arbitrum_hyperevm.py +0 -0
  44. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/examples/external_state_margin_leg_base.py +0 -0
  45. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/examples/simple_aave_v3_supply_base.py +0 -0
  46. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/pytest.ini +0 -0
  47. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/scripts/commit-check.sh +0 -0
  48. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/scripts/crosschain_readiness.py +0 -0
  49. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/skills/ipor-deploy-vault/SKILL.md +0 -0
  50. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/about.py +0 -0
  51. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/cache.py +0 -0
  52. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/chains.py +0 -0
  53. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/cli/__init__.py +0 -0
  54. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/cli/changelog_cmd.py +0 -0
  55. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/cli/config_cmd.py +0 -0
  56. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/cli/config_store.py +0 -0
  57. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/cli/main.py +0 -0
  58. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/cli/market_cmd.py +0 -0
  59. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/cli/options.py +0 -0
  60. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/cli/oracle_mapping_view.py +0 -0
  61. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/cli/vault_cmd.py +0 -0
  62. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/cli/vault_health.py +0 -0
  63. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/cli/vault_info_view.py +0 -0
  64. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/cli/vault_markets_view.py +0 -0
  65. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/cli/vault_rendering.py +0 -0
  66. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/config/__init__.py +0 -0
  67. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/config/roles.py +0 -0
  68. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/core/__init__.py +0 -0
  69. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/core/access.py +0 -0
  70. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/core/address.py +0 -0
  71. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/core/context.py +0 -0
  72. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/core/contract.py +0 -0
  73. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/core/erc20.py +0 -0
  74. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/core/external_state_executor.py +0 -0
  75. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/core/fee_manager.py +0 -0
  76. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/core/fuse.py +0 -0
  77. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/core/fuse_action.py +0 -0
  78. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/core/fusion_factory.py +0 -0
  79. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/core/logs.py +0 -0
  80. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/core/multicall.py +0 -0
  81. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/core/oracle.py +0 -0
  82. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/core/plasma_vault.py +0 -0
  83. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/core/rewards_manager.py +0 -0
  84. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/core/simulation.py +0 -0
  85. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/core/withdraw_manager.py +0 -0
  86. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/__init__.py +0 -0
  87. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/ccip/__init__.py +0 -0
  88. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/ccip/chainlink.py +0 -0
  89. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/ccip/codec.py +0 -0
  90. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/ccip/contracts.py +0 -0
  91. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/ccip/events.py +0 -0
  92. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/ccip/indexer.py +0 -0
  93. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/ccip/lane.py +0 -0
  94. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/ccip/quote.py +0 -0
  95. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/ccip/transport.py +0 -0
  96. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/contracts.py +0 -0
  97. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/discovery.py +0 -0
  98. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/errors.py +0 -0
  99. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/fuses/__init__.py +0 -0
  100. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/fuses/base.py +0 -0
  101. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/fuses/ccip.py +0 -0
  102. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/fuses/stargate.py +0 -0
  103. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/lane.py +0 -0
  104. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/logs.py +0 -0
  105. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/messages.py +0 -0
  106. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/simulation.py +0 -0
  107. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/stargate/__init__.py +0 -0
  108. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/stargate/contracts.py +0 -0
  109. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/stargate/lane.py +0 -0
  110. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/stargate/layerzero.py +0 -0
  111. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/stargate/transport.py +0 -0
  112. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/crosschain/transport.py +0 -0
  113. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/dependency_graph.py +0 -0
  114. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/entry_cli.py +0 -0
  115. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/entry_mcp.py +0 -0
  116. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/errors.py +0 -0
  117. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/explorer.py +0 -0
  118. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/field_docs.py +0 -0
  119. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/fuses/aave_v3.py +0 -0
  120. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/fuses/async_action.py +0 -0
  121. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/fuses/base.py +0 -0
  122. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/fuses/compound_v3.py +0 -0
  123. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/fuses/erc4626.py +0 -0
  124. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/fuses/euler_v2.py +0 -0
  125. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/fuses/events.py +0 -0
  126. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/fuses/external_state.py +0 -0
  127. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/fuses/fluid_instadapp.py +0 -0
  128. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/fuses/gearbox_v3.py +0 -0
  129. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/fuses/hypercore.py +0 -0
  130. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/fuses/merkl.py +0 -0
  131. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/fuses/morpho.py +0 -0
  132. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/fuses/ramses_v2.py +0 -0
  133. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/fuses/uniswap_v3.py +0 -0
  134. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/fuses/universal.py +0 -0
  135. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/guide/__init__.py +0 -0
  136. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/guide/architecture.md +0 -0
  137. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/guide/glossary.md +0 -0
  138. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/guide/invariants.md +0 -0
  139. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/guide/quickstart.md +0 -0
  140. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/market_ids.py +0 -0
  141. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/market_info.py +0 -0
  142. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/mcp/__init__.py +0 -0
  143. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/mcp/guide.py +0 -0
  144. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/mcp/models.py +0 -0
  145. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/mcp/server.py +0 -0
  146. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/morpho_api.py +0 -0
  147. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/py.typed +0 -0
  148. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/readers/__init__.py +0 -0
  149. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/readers/aave_v3.py +0 -0
  150. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/readers/aave_v4.py +0 -0
  151. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/readers/compound_v3.py +0 -0
  152. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/readers/hypercore.py +0 -0
  153. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/readers/hypercore_outcome.py +0 -0
  154. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/readers/lending_health.py +0 -0
  155. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/readers/morpho.py +0 -0
  156. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/readers/oracle_mapping.py +0 -0
  157. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/readers/oracle_mapping_nodes.py +0 -0
  158. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/readers/oracle_mapping_reader.py +0 -0
  159. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/readers/position_manager.py +0 -0
  160. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/readers/ramses_v2.py +0 -0
  161. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/readers/uniswap_v3.py +0 -0
  162. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/readers/unpriceable.py +0 -0
  163. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/substrates.py +0 -0
  164. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/types.py +0 -0
  165. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/validation.py +0 -0
  166. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/vault_data.py +0 -0
  167. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/vault_erc20.py +0 -0
  168. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/vault_info.py +0 -0
  169. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/vault_managers.py +0 -0
  170. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/vault_positions.py +0 -0
  171. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/src/ipor_fusion/vault_reads.py +0 -0
  172. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/UniswapV3UniversalRouter.py +0 -0
  173. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/_crosschain.py +0 -0
  174. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/_crosschain_lifecycle.py +0 -0
  175. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/_crosschain_recovery.py +0 -0
  176. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/_euler_v2.py +0 -0
  177. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/_foundry.py +0 -0
  178. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/_guide.py +0 -0
  179. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/_hypercore_model.py +0 -0
  180. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/_hypercore_shadow.py +0 -0
  181. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/_multicall.py +0 -0
  182. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/_simulate.py +0 -0
  183. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/_validation.py +0 -0
  184. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/addresses.py +0 -0
  185. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/conftest.py +0 -0
  186. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/constants.py +0 -0
  187. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/fixtures/hypercore_hip3_flow.json +0 -0
  188. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/fixtures/hypercore_market55.json +0 -0
  189. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/fixtures/simulate_v1_request.json +0 -0
  190. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/fixtures/vault_info_golden/clean.json +0 -0
  191. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/fixtures/vault_info_golden/clean.txt +0 -0
  192. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/fixtures/vault_info_golden/rich.json +0 -0
  193. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/fixtures/vault_info_golden/rich.txt +0 -0
  194. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_about.py +0 -0
  195. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_access_manager.py +0 -0
  196. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_cache.py +0 -0
  197. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_chains.py +0 -0
  198. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_cli_changelog.py +0 -0
  199. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_cli_commands.py +0 -0
  200. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_cli_config_store.py +0 -0
  201. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_cli_helpers.py +0 -0
  202. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_cli_hypercore.py +0 -0
  203. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_cli_lending_health.py +0 -0
  204. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_cli_market_morpho_blue.py +0 -0
  205. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_cli_oracle_mapping.py +0 -0
  206. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_cli_pending_requests_scan.py +0 -0
  207. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_cli_role_accounts.py +0 -0
  208. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_cli_vault_info_golden.py +0 -0
  209. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_cli_vault_predates_getters.py +0 -0
  210. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_cli_vault_validate.py +0 -0
  211. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_contract_call.py +0 -0
  212. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_contract_encoder.py +0 -0
  213. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_crosschain_ccip_events.py +0 -0
  214. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_crosschain_ccip_indexer.py +0 -0
  215. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_crosschain_ccip_quote.py +0 -0
  216. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_crosschain_chainlink.py +0 -0
  217. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_crosschain_contracts.py +0 -0
  218. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_crosschain_encoding.py +0 -0
  219. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_crosschain_errors.py +0 -0
  220. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_crosschain_lane.py +0 -0
  221. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_crosschain_layering.py +0 -0
  222. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_crosschain_readiness.py +0 -0
  223. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_crosschain_readiness_report.py +0 -0
  224. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_crosschain_transport.py +0 -0
  225. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_docs_typing.py +0 -0
  226. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_erc20.py +0 -0
  227. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_error_hierarchy.py +0 -0
  228. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_examples_composed_hypercore.py +0 -0
  229. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_examples_crosschain.py +0 -0
  230. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_examples_euler_looping_arbitrum.py +0 -0
  231. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_examples_vaults.py +0 -0
  232. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_explorer.py +0 -0
  233. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_external_state_executor.py +0 -0
  234. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_fee_manager.py +0 -0
  235. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_fuse_encoding.py +0 -0
  236. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_fusion_instance.py +0 -0
  237. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_guide.py +0 -0
  238. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_hypercore_deployment.py +0 -0
  239. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_hypercore_flow.py +0 -0
  240. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_hypercore_live.py +0 -0
  241. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_hypercore_outcome.py +0 -0
  242. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_hypercore_readers.py +0 -0
  243. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_hypercore_simulation.py +0 -0
  244. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_logs.py +0 -0
  245. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_mcp_hypercore.py +0 -0
  246. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_mcp_models.py +0 -0
  247. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_mcp_server.py +0 -0
  248. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_mcp_vault_validate.py +0 -0
  249. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_multicall.py +0 -0
  250. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_oracle.py +0 -0
  251. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_oracle_mapping.py +0 -0
  252. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_plasma_vault.py +0 -0
  253. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_public_type_reachability.py +0 -0
  254. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_reader_encoding.py +0 -0
  255. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_readiness_selection.py +0 -0
  256. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_revert_decoding.py +0 -0
  257. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_rewards_manager.py +0 -0
  258. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_roles.py +0 -0
  259. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_sdk_layering.py +0 -0
  260. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_borrow_aave_v3_mainnet.py +0 -0
  261. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_claim_merkl_wrapper_base.py +0 -0
  262. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_claim_morpho_rewards.py +0 -0
  263. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_crosschain_canary.py +0 -0
  264. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_crosschain_hypercore.py +0 -0
  265. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_crosschain_hyperevm.py +0 -0
  266. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_crosschain_lifecycle.py +0 -0
  267. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_euler_v2_batch_base.py +0 -0
  268. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_euler_v2_credit_market_base.py +0 -0
  269. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_euler_v2_swap_deploy_base.py +0 -0
  270. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_euler_v2_swap_reconfigure_base.py +0 -0
  271. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_euler_v2_swap_registry_base.py +0 -0
  272. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_examples_arbitrum.py +0 -0
  273. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_examples_base.py +0 -0
  274. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_examples_crosschain.py +0 -0
  275. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_external_state_executor_base.py +0 -0
  276. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_fusion_factory_clone_base.py +0 -0
  277. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_looping_aave_v3_base.py +0 -0
  278. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_looping_morpho_blue_base.py +0 -0
  279. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_morpho_blue.py +0 -0
  280. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_pilot_v3.py +0 -0
  281. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_pilot_v4_uniswap.py +0 -0
  282. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_pilot_v5_ramses.py +0 -0
  283. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_pilot_v5_scheduled.py +0 -0
  284. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_plasma_vault_setters_base.py +0 -0
  285. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_readers_integration.py +0 -0
  286. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_release_funds.py +0 -0
  287. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_swap_on_base.py +0 -0
  288. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulate_vault_from_scratch_base.py +0 -0
  289. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_simulation_observation.py +0 -0
  290. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_solidity_compiler.py +0 -0
  291. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_solidity_mirrors.py +0 -0
  292. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_substrates.py +0 -0
  293. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_types_and_events.py +0 -0
  294. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_unpriceable_tokens.py +0 -0
  295. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_validation.py +0 -0
  296. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_vault_data_block.py +0 -0
  297. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_vault_dep_graph.py +0 -0
  298. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_vault_info_onchain_base.py +0 -0
  299. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_vault_info_onchain_base_no_withdraw_manager.py +0 -0
  300. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_vault_simulator_blocks.py +0 -0
  301. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_web3_context.py +0 -0
  302. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/tests/test_withdraw_manager.py +0 -0
  303. {ipor_fusion-4.0.0.dev162 → ipor_fusion-4.0.0.dev164}/uv.lock +0 -0
@@ -847,15 +847,31 @@ that only some entries carry is `NotRequired` (a balance fuse's `pct_of_total` a
847
847
  `ipor_fusion` and `ipor_fusion.readers`). Narrow by a key before reading a
848
848
  kind-specific one: `if detail is not None and "aggregator" in detail:
849
849
  detail["description"]`.
850
- - Event `args` are typed per event kind: `ExternalStateEvent.args` is
851
- `ExternalStateEventArgs` and `HyperCoreEvent.args` is `HyperCoreEventArgs`, a union
852
- of one TypedDict per event (`ExternalStateUnpausedArgs`,
853
- `HyperCoreDepositFuseEnterArgs`, ...; `EXTERNAL_STATE_EVENT_ARGS` /
854
- `HYPERCORE_EVENT_ARGS` map an event name to its shape). Values carry nominal types
855
- (`Amount`, `MarketId`, `FuseAddress`, `HyperCoreTokenIndex`, `PayloadHash`, web3's
856
- `Timestamp`, ...). `event.args["signer"]` no longer type-checks on its own: narrow
857
- with a key test (`if "signer" in event.args:`). `HyperCoreEvent.fuse` is a
858
- `FuseAddress | None`.
850
+ - Decoded events are discriminated unions. `ExternalStateEvent` and `HyperCoreEvent`
851
+ are type aliases over one frozen dataclass per event (`ExternalStateUnpausedEvent`,
852
+ `HyperCoreDepositFuseEnterEvent`, ...), each with `name: Literal["<event>"]` and
853
+ `args` typed as that event's TypedDict (`ExternalStateUnpausedArgs`, ...). Comparing
854
+ `name` narrows the event and its `args`, with no key test:
855
+
856
+ ```python
857
+ for event in external_state_events(receipt):
858
+ if event.name == "ExternalStateUnpaused":
859
+ event.args["signer"] # ChecksumAddress
860
+ match hc_event:
861
+ case HyperCoreDepositFuseEnterEvent(args=args):
862
+ args["evmAsset"]
863
+ ```
864
+
865
+ Without that comparison `event.args["signer"]` does not type-check.
866
+ `isinstance(x, ExternalStateEvent)` still works (the alias is a union); the events
867
+ are no longer built positionally (`ExternalStateEvent(...)` is not a class: build
868
+ the event's own class with keywords, its `name` is preset).
869
+ `EXTERNAL_STATE_EVENT_CLASSES` / `HYPERCORE_EVENT_CLASSES` map an event name to its
870
+ class; they replace `EXTERNAL_STATE_EVENT_ARGS` / `HYPERCORE_EVENT_ARGS`, which are
871
+ removed. An event's args TypedDict is its class's `args` annotation:
872
+ `typing.get_type_hints(EXTERNAL_STATE_EVENT_CLASSES[name])["args"]`. Values carry nominal types (`Amount`, `MarketId`, `FuseAddress`,
873
+ `HyperCoreTokenIndex`, `PayloadHash`, web3's `Timestamp`, ...), and
874
+ `HyperCoreEvent.fuse` is a `FuseAddress | None` on every event.
859
875
  - `RawLog` (the log shape `ExternalStateExecutor.parse_balance_proposed` /
860
876
  `find_balance_proposed` accept) is `Mapping[str, object]`, not `Mapping[str, Any]`;
861
877
  a web3 `LogReceipt` still fits it.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: ipor-fusion
3
- Version: 4.0.0.dev162
3
+ Version: 4.0.0.dev164
4
4
  Summary: The IPOR Fusion SDK for Python
5
5
  Project-URL: homepage, https://ipor.io
6
6
  Project-URL: repository, https://github.com/IPOR-Labs/ipor-fusion.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ipor-fusion"
3
- version = "4.0.0.dev162"
3
+ version = "4.0.0.dev164"
4
4
  description = "The IPOR Fusion SDK for Python"
5
5
  authors = [
6
6
  { name = "Adam Mydlarz", email = "amydlarz@gmail.com" },
@@ -316,43 +316,68 @@ from ipor_fusion.fuses import (
316
316
  system_address,
317
317
  )
318
318
  from ipor_fusion.fuses.external_state_events import (
319
- EXTERNAL_STATE_EVENT_ARGS,
319
+ EXTERNAL_STATE_EVENT_CLASSES,
320
320
  EXTERNAL_STATE_EVENT_SPECS,
321
321
  EXTERNAL_STATE_EVENTS,
322
322
  EXTERNAL_STATE_TOPICS,
323
323
  ExternalStateAssetRescuedArgs,
324
+ ExternalStateAssetRescuedEvent,
325
+ ExternalStateBalanceFuseLastCustodianTimestampUpdatedEvent,
326
+ ExternalStateBalanceFuseLastTotalBalanceUpdatedEvent,
324
327
  ExternalStateBigChangeDetectedArgs,
328
+ ExternalStateBigChangeDetectedEvent,
325
329
  ExternalStateCustodianTimestampUpdatedArgs,
326
330
  ExternalStateEvent,
327
331
  ExternalStateEventArgs,
328
332
  ExternalStateEventSpec,
329
333
  ExternalStateExecutorArgs,
334
+ ExternalStateExecutorCreatedEvent,
335
+ ExternalStateExecutorDeployedEvent,
330
336
  ExternalStateOperationArgs,
337
+ ExternalStateOperationFuseEnterEvent,
338
+ ExternalStateOperationFuseExitEvent,
331
339
  ExternalStateTotalBalanceUpdatedArgs,
332
340
  ExternalStateUnpausedArgs,
341
+ ExternalStateUnpausedEvent,
333
342
  decode_external_state_event,
334
343
  external_state_event_name,
335
344
  external_state_events,
336
345
  )
337
346
  from ipor_fusion.fuses.hypercore_events import (
338
- HYPERCORE_EVENT_ARGS,
347
+ HYPERCORE_EVENT_CLASSES,
339
348
  HyperCoreActionEnqueuedArgs,
349
+ HyperCoreActionEnqueuedEvent,
340
350
  HyperCoreActionSettledArgs,
351
+ HyperCoreActionSettledEvent,
341
352
  HyperCoreBuilderFeeFuseEnterArgs,
353
+ HyperCoreBuilderFeeFuseEnterEvent,
342
354
  HyperCoreCancelByCloidArgs,
343
355
  HyperCoreCancelByOidArgs,
356
+ HyperCoreCancelFuseCancelByCloidEvent,
357
+ HyperCoreCancelFuseCancelByOidEvent,
344
358
  HyperCoreDepositFuseEnterArgs,
359
+ HyperCoreDepositFuseEnterEvent,
345
360
  HyperCoreEventArgs,
346
361
  HyperCoreMarginFuseEnterArgs,
362
+ HyperCoreMarginFuseEnterEvent,
347
363
  HyperCoreObserverSetChangedArgs,
364
+ HyperCoreObserverSetChangedEvent,
348
365
  HyperCoreObserverSetProposedArgs,
366
+ HyperCoreObserverSetProposedEvent,
349
367
  HyperCoreOrderFuseEnterArgs,
368
+ HyperCoreOrderFuseEnterEvent,
350
369
  HyperCoreRecoveryExecutedArgs,
370
+ HyperCoreRecoveryExecutedEvent,
351
371
  HyperCoreRecoveryProposedArgs,
372
+ HyperCoreRecoveryProposedEvent,
352
373
  HyperCoreReportedActionSettledArgs,
374
+ HyperCoreReportedActionSettledEvent,
353
375
  HyperCoreReportSubmittedArgs,
376
+ HyperCoreReportSubmittedEvent,
354
377
  HyperCoreSendFuseSendAssetArgs,
378
+ HyperCoreSendFuseSendAssetEvent,
355
379
  HyperCoreSendFuseSpotSendArgs,
380
+ HyperCoreSendFuseSpotSendEvent,
356
381
  )
357
382
  from ipor_fusion.market_ids import IporFusionMarkets
358
383
  from ipor_fusion.market_info import (
@@ -591,7 +616,16 @@ __all__ = [
591
616
  "EXTERNAL_STATE_EVENTS",
592
617
  "EXTERNAL_STATE_TOPICS",
593
618
  "ExternalStateEvent",
594
- "EXTERNAL_STATE_EVENT_ARGS",
619
+ "EXTERNAL_STATE_EVENT_CLASSES",
620
+ "ExternalStateBigChangeDetectedEvent",
621
+ "ExternalStateBalanceFuseLastCustodianTimestampUpdatedEvent",
622
+ "ExternalStateBalanceFuseLastTotalBalanceUpdatedEvent",
623
+ "ExternalStateUnpausedEvent",
624
+ "ExternalStateAssetRescuedEvent",
625
+ "ExternalStateExecutorCreatedEvent",
626
+ "ExternalStateOperationFuseEnterEvent",
627
+ "ExternalStateOperationFuseExitEvent",
628
+ "ExternalStateExecutorDeployedEvent",
595
629
  "ExternalStateAssetRescuedArgs",
596
630
  "ExternalStateBigChangeDetectedArgs",
597
631
  "ExternalStateCustodianTimestampUpdatedArgs",
@@ -608,7 +642,23 @@ __all__ = [
608
642
  "HYPERCORE_EVENTS",
609
643
  "HYPERCORE_EVENT_SPECS",
610
644
  "HyperCoreEvent",
611
- "HYPERCORE_EVENT_ARGS",
645
+ "HYPERCORE_EVENT_CLASSES",
646
+ "HyperCoreDepositFuseEnterEvent",
647
+ "HyperCoreMarginFuseEnterEvent",
648
+ "HyperCoreSendFuseSpotSendEvent",
649
+ "HyperCoreSendFuseSendAssetEvent",
650
+ "HyperCoreOrderFuseEnterEvent",
651
+ "HyperCoreCancelFuseCancelByOidEvent",
652
+ "HyperCoreCancelFuseCancelByCloidEvent",
653
+ "HyperCoreBuilderFeeFuseEnterEvent",
654
+ "HyperCoreActionEnqueuedEvent",
655
+ "HyperCoreActionSettledEvent",
656
+ "HyperCoreReportedActionSettledEvent",
657
+ "HyperCoreReportSubmittedEvent",
658
+ "HyperCoreObserverSetProposedEvent",
659
+ "HyperCoreObserverSetChangedEvent",
660
+ "HyperCoreRecoveryProposedEvent",
661
+ "HyperCoreRecoveryExecutedEvent",
612
662
  "HyperCoreActionEnqueuedArgs",
613
663
  "HyperCoreActionSettledArgs",
614
664
  "HyperCoreBuilderFeeFuseEnterArgs",
@@ -50,28 +50,44 @@ from ipor_fusion.fuses.hypercore import (
50
50
  system_address,
51
51
  )
52
52
  from ipor_fusion.fuses.hypercore_events import (
53
- HYPERCORE_EVENT_ARGS,
53
+ HYPERCORE_EVENT_CLASSES,
54
54
  HYPERCORE_EVENT_SPECS,
55
55
  HYPERCORE_EVENTS,
56
56
  HyperCoreActionEnqueuedArgs,
57
+ HyperCoreActionEnqueuedEvent,
57
58
  HyperCoreActionSettledArgs,
59
+ HyperCoreActionSettledEvent,
58
60
  HyperCoreBuilderFeeFuseEnterArgs,
61
+ HyperCoreBuilderFeeFuseEnterEvent,
59
62
  HyperCoreCancelByCloidArgs,
60
63
  HyperCoreCancelByOidArgs,
64
+ HyperCoreCancelFuseCancelByCloidEvent,
65
+ HyperCoreCancelFuseCancelByOidEvent,
61
66
  HyperCoreDepositFuseEnterArgs,
67
+ HyperCoreDepositFuseEnterEvent,
62
68
  HyperCoreEvent,
63
69
  HyperCoreEventArgs,
64
70
  HyperCoreEventSpec,
65
71
  HyperCoreMarginFuseEnterArgs,
72
+ HyperCoreMarginFuseEnterEvent,
66
73
  HyperCoreObserverSetChangedArgs,
74
+ HyperCoreObserverSetChangedEvent,
67
75
  HyperCoreObserverSetProposedArgs,
76
+ HyperCoreObserverSetProposedEvent,
68
77
  HyperCoreOrderFuseEnterArgs,
78
+ HyperCoreOrderFuseEnterEvent,
69
79
  HyperCoreRecoveryExecutedArgs,
80
+ HyperCoreRecoveryExecutedEvent,
70
81
  HyperCoreRecoveryProposedArgs,
82
+ HyperCoreRecoveryProposedEvent,
71
83
  HyperCoreReportedActionSettledArgs,
84
+ HyperCoreReportedActionSettledEvent,
72
85
  HyperCoreReportSubmittedArgs,
86
+ HyperCoreReportSubmittedEvent,
73
87
  HyperCoreSendFuseSendAssetArgs,
88
+ HyperCoreSendFuseSendAssetEvent,
74
89
  HyperCoreSendFuseSpotSendArgs,
90
+ HyperCoreSendFuseSpotSendEvent,
75
91
  decode_hypercore_event,
76
92
  find_hypercore_events,
77
93
  hypercore_event_name,
@@ -112,7 +128,23 @@ __all__ = [
112
128
  "HYPERCORE_EVENTS",
113
129
  "HYPERCORE_EVENT_SPECS",
114
130
  "HyperCoreEvent",
115
- "HYPERCORE_EVENT_ARGS",
131
+ "HYPERCORE_EVENT_CLASSES",
132
+ "HyperCoreDepositFuseEnterEvent",
133
+ "HyperCoreMarginFuseEnterEvent",
134
+ "HyperCoreSendFuseSpotSendEvent",
135
+ "HyperCoreSendFuseSendAssetEvent",
136
+ "HyperCoreOrderFuseEnterEvent",
137
+ "HyperCoreCancelFuseCancelByOidEvent",
138
+ "HyperCoreCancelFuseCancelByCloidEvent",
139
+ "HyperCoreBuilderFeeFuseEnterEvent",
140
+ "HyperCoreActionEnqueuedEvent",
141
+ "HyperCoreActionSettledEvent",
142
+ "HyperCoreReportedActionSettledEvent",
143
+ "HyperCoreReportSubmittedEvent",
144
+ "HyperCoreObserverSetProposedEvent",
145
+ "HyperCoreObserverSetChangedEvent",
146
+ "HyperCoreRecoveryProposedEvent",
147
+ "HyperCoreRecoveryExecutedEvent",
116
148
  "HyperCoreActionEnqueuedArgs",
117
149
  "HyperCoreActionSettledArgs",
118
150
  "HyperCoreBuilderFeeFuseEnterArgs",
@@ -22,9 +22,9 @@ raises ``ExternalStateEventDecodeError``.
22
22
 
23
23
  from __future__ import annotations
24
24
 
25
- from collections.abc import Mapping
25
+ from collections.abc import Callable, Mapping
26
26
  from dataclasses import dataclass
27
- from typing import TypeAlias, TypedDict, cast
27
+ from typing import Literal, TypeAlias, TypedDict, cast
28
28
 
29
29
  from eth_abi import decode
30
30
  from eth_abi.exceptions import DecodingError
@@ -165,8 +165,7 @@ class ExternalStateOperationArgs(TypedDict):
165
165
  actionsCount: int
166
166
 
167
167
 
168
- #: The parameters of one ExternalState event, by its Solidity names; tell the
169
- #: shapes apart by ``ExternalStateEvent.name`` or a key (``"signer" in args``).
168
+ #: The parameters of one ExternalState event, by its Solidity names.
170
169
  ExternalStateEventArgs: TypeAlias = (
171
170
  ExternalStateBigChangeDetectedArgs
172
171
  | ExternalStateCustodianTimestampUpdatedArgs
@@ -177,23 +176,6 @@ ExternalStateEventArgs: TypeAlias = (
177
176
  | ExternalStateOperationArgs
178
177
  )
179
178
 
180
- #: Event name -> the TypedDict its ``args`` is.
181
- EXTERNAL_STATE_EVENT_ARGS: dict[str, type] = {
182
- "ExternalStateBigChangeDetected": ExternalStateBigChangeDetectedArgs,
183
- "ExternalStateBalanceFuseLastCustodianTimestampUpdated": (
184
- ExternalStateCustodianTimestampUpdatedArgs
185
- ),
186
- "ExternalStateBalanceFuseLastTotalBalanceUpdated": (
187
- ExternalStateTotalBalanceUpdatedArgs
188
- ),
189
- "ExternalStateUnpaused": ExternalStateUnpausedArgs,
190
- "ExternalStateAssetRescued": ExternalStateAssetRescuedArgs,
191
- "ExecutorCreated": ExternalStateExecutorArgs,
192
- "ExternalStateOperationFuseEnter": ExternalStateOperationArgs,
193
- "ExternalStateOperationFuseExit": ExternalStateOperationArgs,
194
- "ExternalStateExecutorDeployed": ExternalStateExecutorArgs,
195
- }
196
-
197
179
  #: topic0 -> spec, for every ExternalState event the vault emits.
198
180
  EXTERNAL_STATE_EVENTS: dict[bytes, ExternalStateEventSpec] = {
199
181
  spec.topic: spec for spec in EXTERNAL_STATE_EVENT_SPECS
@@ -204,9 +186,10 @@ EXTERNAL_STATE_TOPICS: tuple[str, ...] = tuple(
204
186
  )
205
187
 
206
188
 
207
- @dataclass(frozen=True, slots=True)
208
- class ExternalStateEvent:
209
- """One decoded ExternalState log with its raw identity."""
189
+ @dataclass(frozen=True, slots=True, kw_only=True)
190
+ class _ExternalStateEventBase:
191
+ """One decoded ExternalState log with its raw identity; each event is a
192
+ subclass that pins ``name`` to a literal and ``args`` to its shape."""
210
193
 
211
194
  name: str
212
195
  emitter: ChecksumAddress
@@ -216,6 +199,94 @@ class ExternalStateEvent:
216
199
  log_index: int | None = None
217
200
 
218
201
 
202
+ @dataclass(frozen=True, slots=True, kw_only=True)
203
+ class ExternalStateBigChangeDetectedEvent(_ExternalStateEventBase):
204
+ name: Literal["ExternalStateBigChangeDetected"] = "ExternalStateBigChangeDetected"
205
+ args: ExternalStateBigChangeDetectedArgs
206
+
207
+
208
+ @dataclass(frozen=True, slots=True, kw_only=True)
209
+ class ExternalStateBalanceFuseLastCustodianTimestampUpdatedEvent(
210
+ _ExternalStateEventBase
211
+ ):
212
+ name: Literal["ExternalStateBalanceFuseLastCustodianTimestampUpdated"] = (
213
+ "ExternalStateBalanceFuseLastCustodianTimestampUpdated"
214
+ )
215
+ args: ExternalStateCustodianTimestampUpdatedArgs
216
+
217
+
218
+ @dataclass(frozen=True, slots=True, kw_only=True)
219
+ class ExternalStateBalanceFuseLastTotalBalanceUpdatedEvent(_ExternalStateEventBase):
220
+ name: Literal["ExternalStateBalanceFuseLastTotalBalanceUpdated"] = (
221
+ "ExternalStateBalanceFuseLastTotalBalanceUpdated"
222
+ )
223
+ args: ExternalStateTotalBalanceUpdatedArgs
224
+
225
+
226
+ @dataclass(frozen=True, slots=True, kw_only=True)
227
+ class ExternalStateUnpausedEvent(_ExternalStateEventBase):
228
+ name: Literal["ExternalStateUnpaused"] = "ExternalStateUnpaused"
229
+ args: ExternalStateUnpausedArgs
230
+
231
+
232
+ @dataclass(frozen=True, slots=True, kw_only=True)
233
+ class ExternalStateAssetRescuedEvent(_ExternalStateEventBase):
234
+ name: Literal["ExternalStateAssetRescued"] = "ExternalStateAssetRescued"
235
+ args: ExternalStateAssetRescuedArgs
236
+
237
+
238
+ @dataclass(frozen=True, slots=True, kw_only=True)
239
+ class ExternalStateExecutorCreatedEvent(_ExternalStateEventBase):
240
+ name: Literal["ExecutorCreated"] = "ExecutorCreated"
241
+ args: ExternalStateExecutorArgs
242
+
243
+
244
+ @dataclass(frozen=True, slots=True, kw_only=True)
245
+ class ExternalStateOperationFuseEnterEvent(_ExternalStateEventBase):
246
+ name: Literal["ExternalStateOperationFuseEnter"] = "ExternalStateOperationFuseEnter"
247
+ args: ExternalStateOperationArgs
248
+
249
+
250
+ @dataclass(frozen=True, slots=True, kw_only=True)
251
+ class ExternalStateOperationFuseExitEvent(_ExternalStateEventBase):
252
+ name: Literal["ExternalStateOperationFuseExit"] = "ExternalStateOperationFuseExit"
253
+ args: ExternalStateOperationArgs
254
+
255
+
256
+ @dataclass(frozen=True, slots=True, kw_only=True)
257
+ class ExternalStateExecutorDeployedEvent(_ExternalStateEventBase):
258
+ name: Literal["ExternalStateExecutorDeployed"] = "ExternalStateExecutorDeployed"
259
+ args: ExternalStateExecutorArgs
260
+
261
+
262
+ #: One decoded ExternalState event; ``event.name == "..."`` narrows it, and
263
+ #: its ``args``, to that event's class.
264
+ ExternalStateEvent: TypeAlias = (
265
+ ExternalStateBigChangeDetectedEvent
266
+ | ExternalStateBalanceFuseLastCustodianTimestampUpdatedEvent
267
+ | ExternalStateBalanceFuseLastTotalBalanceUpdatedEvent
268
+ | ExternalStateUnpausedEvent
269
+ | ExternalStateAssetRescuedEvent
270
+ | ExternalStateExecutorCreatedEvent
271
+ | ExternalStateOperationFuseEnterEvent
272
+ | ExternalStateOperationFuseExitEvent
273
+ | ExternalStateExecutorDeployedEvent
274
+ )
275
+
276
+ #: Event name -> its event class (``args`` annotation: its TypedDict).
277
+ EXTERNAL_STATE_EVENT_CLASSES: dict[str, type[ExternalStateEvent]] = {
278
+ "ExternalStateBigChangeDetected": ExternalStateBigChangeDetectedEvent,
279
+ "ExternalStateBalanceFuseLastCustodianTimestampUpdated": ExternalStateBalanceFuseLastCustodianTimestampUpdatedEvent,
280
+ "ExternalStateBalanceFuseLastTotalBalanceUpdated": ExternalStateBalanceFuseLastTotalBalanceUpdatedEvent,
281
+ "ExternalStateUnpaused": ExternalStateUnpausedEvent,
282
+ "ExternalStateAssetRescued": ExternalStateAssetRescuedEvent,
283
+ "ExecutorCreated": ExternalStateExecutorCreatedEvent,
284
+ "ExternalStateOperationFuseEnter": ExternalStateOperationFuseEnterEvent,
285
+ "ExternalStateOperationFuseExit": ExternalStateOperationFuseExitEvent,
286
+ "ExternalStateExecutorDeployed": ExternalStateExecutorDeployedEvent,
287
+ }
288
+
289
+
219
290
  def _as_bytes(value: object, what: str) -> bytes:
220
291
  """Raw log bytes from what a node or an indexer serves: bytes-like
221
292
  (bytes, bytearray, HexBytes) or ``0x``-prefixed hex text. Anything else —
@@ -310,15 +381,11 @@ def decode_external_state_event( # proctor: ignore[primitives-untyped-dict]
310
381
  values = decode([abi_type for abi_type, _ in spec.params], raw)
311
382
  except DecodingError as exc:
312
383
  raise ExternalStateEventDecodeError(f"{spec.name}: {exc}") from exc
313
- # Each value is narrowed to its ABI type; the key set is the spec's, which
314
- # EXTERNAL_STATE_EVENT_ARGS mirrors (pinned by the tests).
315
- args = cast(
316
- ExternalStateEventArgs,
317
- {
318
- name: abi_value(abi_type, value)
319
- for (abi_type, name), value in zip(spec.params, values, strict=True)
320
- },
321
- )
384
+ # Each value is narrowed to its ABI type.
385
+ args = {
386
+ name: abi_value(abi_type, value)
387
+ for (abi_type, name), value in zip(spec.params, values, strict=True)
388
+ }
322
389
  address = log.get("address")
323
390
  if not isinstance(address, str | bytes):
324
391
  raise ExternalStateEventDecodeError(f"{spec.name}: emitter")
@@ -326,8 +393,12 @@ def decode_external_state_event( # proctor: ignore[primitives-untyped-dict]
326
393
  emitter = Web3.to_checksum_address(address)
327
394
  except ValueError as exc:
328
395
  raise ExternalStateEventDecodeError(f"{spec.name}: emitter") from exc
329
- return ExternalStateEvent(
330
- name=spec.name,
396
+ # The class's args TypedDict is the spec's shape (pinned by the tests), so
397
+ # the decoded dict is that class's args.
398
+ event_class = cast(
399
+ Callable[..., ExternalStateEvent], EXTERNAL_STATE_EVENT_CLASSES[spec.name]
400
+ )
401
+ return event_class(
331
402
  emitter=emitter,
332
403
  args=args,
333
404
  block_number=_as_quantity(log.get("blockNumber"), "blockNumber"),
@@ -14,8 +14,9 @@ Status: preview, not production. The contracts behind it are under active develo
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
+ from collections.abc import Callable
17
18
  from dataclasses import dataclass
18
- from typing import TypeAlias, TypedDict, cast
19
+ from typing import Literal, TypeAlias, TypedDict, cast
19
20
 
20
21
  from eth_abi import decode
21
22
  from eth_typing import ChecksumAddress
@@ -287,8 +288,7 @@ class HyperCoreRecoveryExecutedArgs(TypedDict):
287
288
  reasonHash: bytes
288
289
 
289
290
 
290
- #: The parameters of one HyperCore event; tell the shapes apart by
291
- #: ``HyperCoreEvent.name`` or a key (``"evmAsset" in args``).
291
+ #: The parameters of one HyperCore event.
292
292
  HyperCoreEventArgs: TypeAlias = (
293
293
  HyperCoreDepositFuseEnterArgs
294
294
  | HyperCoreMarginFuseEnterArgs
@@ -308,26 +308,6 @@ HyperCoreEventArgs: TypeAlias = (
308
308
  | HyperCoreRecoveryExecutedArgs
309
309
  )
310
310
 
311
- #: Event name -> the TypedDict its ``args`` is.
312
- HYPERCORE_EVENT_ARGS: dict[str, type] = {
313
- "HyperCoreDepositFuseEnter": HyperCoreDepositFuseEnterArgs,
314
- "HyperCoreMarginFuseEnter": HyperCoreMarginFuseEnterArgs,
315
- "HyperCoreSendFuseSpotSend": HyperCoreSendFuseSpotSendArgs,
316
- "HyperCoreSendFuseSendAsset": HyperCoreSendFuseSendAssetArgs,
317
- "HyperCoreOrderFuseEnter": HyperCoreOrderFuseEnterArgs,
318
- "HyperCoreCancelFuseCancelByOid": HyperCoreCancelByOidArgs,
319
- "HyperCoreCancelFuseCancelByCloid": HyperCoreCancelByCloidArgs,
320
- "HyperCoreBuilderFeeFuseEnter": HyperCoreBuilderFeeFuseEnterArgs,
321
- "HyperCoreActionEnqueued": HyperCoreActionEnqueuedArgs,
322
- "HyperCoreActionSettled": HyperCoreActionSettledArgs,
323
- "HyperCoreReportedActionSettled": HyperCoreReportedActionSettledArgs,
324
- "ReportSubmitted": HyperCoreReportSubmittedArgs,
325
- "ObserverSetProposed": HyperCoreObserverSetProposedArgs,
326
- "ObserverSetChanged": HyperCoreObserverSetChangedArgs,
327
- "RecoveryProposed": HyperCoreRecoveryProposedArgs,
328
- "RecoveryExecuted": HyperCoreRecoveryExecutedArgs,
329
- }
330
-
331
311
  #: topic0 -> spec, for every HyperCore event.
332
312
  HYPERCORE_EVENTS: dict[bytes, HyperCoreEventSpec] = {
333
313
  spec.topic: spec for spec in HYPERCORE_EVENT_SPECS
@@ -340,9 +320,10 @@ HYPERCORE_FUSE_EVENTS = frozenset(
340
320
  )
341
321
 
342
322
 
343
- @dataclass(frozen=True, slots=True)
344
- class HyperCoreEvent:
345
- """One decoded HyperCore log."""
323
+ @dataclass(frozen=True, slots=True, kw_only=True)
324
+ class _HyperCoreEventBase:
325
+ """One decoded HyperCore log; each event is a subclass that pins ``name``
326
+ to a literal and ``args`` to its shape."""
346
327
 
347
328
  name: str
348
329
  emitter: ChecksumAddress
@@ -357,6 +338,146 @@ class HyperCoreEvent:
357
338
  return self.args["version"]
358
339
 
359
340
 
341
+ @dataclass(frozen=True, slots=True, kw_only=True)
342
+ class HyperCoreDepositFuseEnterEvent(_HyperCoreEventBase):
343
+ name: Literal["HyperCoreDepositFuseEnter"] = "HyperCoreDepositFuseEnter"
344
+ args: HyperCoreDepositFuseEnterArgs
345
+
346
+
347
+ @dataclass(frozen=True, slots=True, kw_only=True)
348
+ class HyperCoreMarginFuseEnterEvent(_HyperCoreEventBase):
349
+ name: Literal["HyperCoreMarginFuseEnter"] = "HyperCoreMarginFuseEnter"
350
+ args: HyperCoreMarginFuseEnterArgs
351
+
352
+
353
+ @dataclass(frozen=True, slots=True, kw_only=True)
354
+ class HyperCoreSendFuseSpotSendEvent(_HyperCoreEventBase):
355
+ name: Literal["HyperCoreSendFuseSpotSend"] = "HyperCoreSendFuseSpotSend"
356
+ args: HyperCoreSendFuseSpotSendArgs
357
+
358
+
359
+ @dataclass(frozen=True, slots=True, kw_only=True)
360
+ class HyperCoreSendFuseSendAssetEvent(_HyperCoreEventBase):
361
+ name: Literal["HyperCoreSendFuseSendAsset"] = "HyperCoreSendFuseSendAsset"
362
+ args: HyperCoreSendFuseSendAssetArgs
363
+
364
+
365
+ @dataclass(frozen=True, slots=True, kw_only=True)
366
+ class HyperCoreOrderFuseEnterEvent(_HyperCoreEventBase):
367
+ name: Literal["HyperCoreOrderFuseEnter"] = "HyperCoreOrderFuseEnter"
368
+ args: HyperCoreOrderFuseEnterArgs
369
+
370
+
371
+ @dataclass(frozen=True, slots=True, kw_only=True)
372
+ class HyperCoreCancelFuseCancelByOidEvent(_HyperCoreEventBase):
373
+ name: Literal["HyperCoreCancelFuseCancelByOid"] = "HyperCoreCancelFuseCancelByOid"
374
+ args: HyperCoreCancelByOidArgs
375
+
376
+
377
+ @dataclass(frozen=True, slots=True, kw_only=True)
378
+ class HyperCoreCancelFuseCancelByCloidEvent(_HyperCoreEventBase):
379
+ name: Literal["HyperCoreCancelFuseCancelByCloid"] = (
380
+ "HyperCoreCancelFuseCancelByCloid"
381
+ )
382
+ args: HyperCoreCancelByCloidArgs
383
+
384
+
385
+ @dataclass(frozen=True, slots=True, kw_only=True)
386
+ class HyperCoreBuilderFeeFuseEnterEvent(_HyperCoreEventBase):
387
+ name: Literal["HyperCoreBuilderFeeFuseEnter"] = "HyperCoreBuilderFeeFuseEnter"
388
+ args: HyperCoreBuilderFeeFuseEnterArgs
389
+
390
+
391
+ @dataclass(frozen=True, slots=True, kw_only=True)
392
+ class HyperCoreActionEnqueuedEvent(_HyperCoreEventBase):
393
+ name: Literal["HyperCoreActionEnqueued"] = "HyperCoreActionEnqueued"
394
+ args: HyperCoreActionEnqueuedArgs
395
+
396
+
397
+ @dataclass(frozen=True, slots=True, kw_only=True)
398
+ class HyperCoreActionSettledEvent(_HyperCoreEventBase):
399
+ name: Literal["HyperCoreActionSettled"] = "HyperCoreActionSettled"
400
+ args: HyperCoreActionSettledArgs
401
+
402
+
403
+ @dataclass(frozen=True, slots=True, kw_only=True)
404
+ class HyperCoreReportedActionSettledEvent(_HyperCoreEventBase):
405
+ name: Literal["HyperCoreReportedActionSettled"] = "HyperCoreReportedActionSettled"
406
+ args: HyperCoreReportedActionSettledArgs
407
+
408
+
409
+ @dataclass(frozen=True, slots=True, kw_only=True)
410
+ class HyperCoreReportSubmittedEvent(_HyperCoreEventBase):
411
+ name: Literal["ReportSubmitted"] = "ReportSubmitted"
412
+ args: HyperCoreReportSubmittedArgs
413
+
414
+
415
+ @dataclass(frozen=True, slots=True, kw_only=True)
416
+ class HyperCoreObserverSetProposedEvent(_HyperCoreEventBase):
417
+ name: Literal["ObserverSetProposed"] = "ObserverSetProposed"
418
+ args: HyperCoreObserverSetProposedArgs
419
+
420
+
421
+ @dataclass(frozen=True, slots=True, kw_only=True)
422
+ class HyperCoreObserverSetChangedEvent(_HyperCoreEventBase):
423
+ name: Literal["ObserverSetChanged"] = "ObserverSetChanged"
424
+ args: HyperCoreObserverSetChangedArgs
425
+
426
+
427
+ @dataclass(frozen=True, slots=True, kw_only=True)
428
+ class HyperCoreRecoveryProposedEvent(_HyperCoreEventBase):
429
+ name: Literal["RecoveryProposed"] = "RecoveryProposed"
430
+ args: HyperCoreRecoveryProposedArgs
431
+
432
+
433
+ @dataclass(frozen=True, slots=True, kw_only=True)
434
+ class HyperCoreRecoveryExecutedEvent(_HyperCoreEventBase):
435
+ name: Literal["RecoveryExecuted"] = "RecoveryExecuted"
436
+ args: HyperCoreRecoveryExecutedArgs
437
+
438
+
439
+ #: One decoded HyperCore event; ``event.name == "..."`` narrows it, and its
440
+ #: ``args``, to that event's class.
441
+ HyperCoreEvent: TypeAlias = (
442
+ HyperCoreDepositFuseEnterEvent
443
+ | HyperCoreMarginFuseEnterEvent
444
+ | HyperCoreSendFuseSpotSendEvent
445
+ | HyperCoreSendFuseSendAssetEvent
446
+ | HyperCoreOrderFuseEnterEvent
447
+ | HyperCoreCancelFuseCancelByOidEvent
448
+ | HyperCoreCancelFuseCancelByCloidEvent
449
+ | HyperCoreBuilderFeeFuseEnterEvent
450
+ | HyperCoreActionEnqueuedEvent
451
+ | HyperCoreActionSettledEvent
452
+ | HyperCoreReportedActionSettledEvent
453
+ | HyperCoreReportSubmittedEvent
454
+ | HyperCoreObserverSetProposedEvent
455
+ | HyperCoreObserverSetChangedEvent
456
+ | HyperCoreRecoveryProposedEvent
457
+ | HyperCoreRecoveryExecutedEvent
458
+ )
459
+
460
+ #: Event name -> its event class (``args`` annotation: its TypedDict).
461
+ HYPERCORE_EVENT_CLASSES: dict[str, type[HyperCoreEvent]] = {
462
+ "HyperCoreDepositFuseEnter": HyperCoreDepositFuseEnterEvent,
463
+ "HyperCoreMarginFuseEnter": HyperCoreMarginFuseEnterEvent,
464
+ "HyperCoreSendFuseSpotSend": HyperCoreSendFuseSpotSendEvent,
465
+ "HyperCoreSendFuseSendAsset": HyperCoreSendFuseSendAssetEvent,
466
+ "HyperCoreOrderFuseEnter": HyperCoreOrderFuseEnterEvent,
467
+ "HyperCoreCancelFuseCancelByOid": HyperCoreCancelFuseCancelByOidEvent,
468
+ "HyperCoreCancelFuseCancelByCloid": HyperCoreCancelFuseCancelByCloidEvent,
469
+ "HyperCoreBuilderFeeFuseEnter": HyperCoreBuilderFeeFuseEnterEvent,
470
+ "HyperCoreActionEnqueued": HyperCoreActionEnqueuedEvent,
471
+ "HyperCoreActionSettled": HyperCoreActionSettledEvent,
472
+ "HyperCoreReportedActionSettled": HyperCoreReportedActionSettledEvent,
473
+ "ReportSubmitted": HyperCoreReportSubmittedEvent,
474
+ "ObserverSetProposed": HyperCoreObserverSetProposedEvent,
475
+ "ObserverSetChanged": HyperCoreObserverSetChangedEvent,
476
+ "RecoveryProposed": HyperCoreRecoveryProposedEvent,
477
+ "RecoveryExecuted": HyperCoreRecoveryExecutedEvent,
478
+ }
479
+
480
+
360
481
  def hypercore_event_name(topic: bytes | str) -> str | None:
361
482
  """The HyperCore event behind ``topic0``, or None for any other log."""
362
483
  raw = (
@@ -377,17 +498,17 @@ def decode_hypercore_event(log: LogReceipt) -> HyperCoreEvent | None:
377
498
  if spec is None:
378
499
  return None
379
500
  values = decode([abi_type for abi_type, _ in spec.params], bytes(log["data"]))
380
- # Each value is narrowed to its ABI type; the key set is the spec's, which
381
- # HYPERCORE_EVENT_ARGS mirrors (pinned by the tests).
382
- args = cast(
383
- HyperCoreEventArgs,
384
- {
385
- name: abi_value(abi_type, value)
386
- for (abi_type, name), value in zip(spec.params, values, strict=True)
387
- },
501
+ # Each value is narrowed to its ABI type.
502
+ args = {
503
+ name: abi_value(abi_type, value)
504
+ for (abi_type, name), value in zip(spec.params, values, strict=True)
505
+ }
506
+ # The class's args TypedDict is the spec's shape (pinned by the tests), so
507
+ # the decoded dict is that class's args.
508
+ event_class = cast(
509
+ Callable[..., HyperCoreEvent], HYPERCORE_EVENT_CLASSES[spec.name]
388
510
  )
389
- return HyperCoreEvent(
390
- name=spec.name,
511
+ return event_class(
391
512
  emitter=Web3.to_checksum_address(log["address"]),
392
513
  args=args,
393
514
  log_index=log.get("logIndex"),