wayfinder-paths 0.1.30__tar.gz → 0.1.31__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.

Potentially problematic release.


This version of wayfinder-paths might be problematic. Click here for more details.

Files changed (207) hide show
  1. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/PKG-INFO +2 -2
  2. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/pyproject.toml +1 -1
  3. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/hyperliquid_adapter/adapter.py +15 -1
  4. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/hyperliquid_adapter/exchange.py +3 -3
  5. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/hyperliquid_adapter/paired_filler.py +1 -1
  6. wayfinder_paths-0.1.31/wayfinder_paths/adapters/hyperliquid_adapter/test_cancel_order.py +57 -0
  7. wayfinder_paths-0.1.31/wayfinder_paths/adapters/hyperliquid_adapter/test_exchange_mid_prices.py +52 -0
  8. wayfinder_paths-0.1.31/wayfinder_paths/adapters/hyperliquid_adapter/test_hyperliquid_sdk_live.py +64 -0
  9. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/hyperliquid_adapter/util.py +9 -10
  10. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/clients/PoolClient.py +1 -1
  11. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/mcp/tools/execute.py +48 -16
  12. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/mcp/tools/hyperliquid.py +1 -13
  13. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/mcp/tools/quotes.py +42 -7
  14. wayfinder_paths-0.1.31/wayfinder_paths/strategies/basis_trading_strategy/manifest.yaml +24 -0
  15. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/basis_trading_strategy/strategy.py +248 -27
  16. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/basis_trading_strategy/test_strategy.py +125 -15
  17. wayfinder_paths-0.1.31/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/manifest.yaml +29 -0
  18. wayfinder_paths-0.1.31/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/manifest.yaml +33 -0
  19. wayfinder_paths-0.1.31/wayfinder_paths/strategies/stablecoin_yield_strategy/manifest.yaml +23 -0
  20. wayfinder_paths-0.1.31/wayfinder_paths/tests/test_manifests.py +93 -0
  21. wayfinder_paths-0.1.31/wayfinder_paths/tests/test_mcp_balances.py +73 -0
  22. wayfinder_paths-0.1.31/wayfinder_paths/tests/test_mcp_discovery.py +34 -0
  23. wayfinder_paths-0.1.31/wayfinder_paths/tests/test_mcp_execute.py +146 -0
  24. wayfinder_paths-0.1.31/wayfinder_paths/tests/test_mcp_hyperliquid_execute.py +69 -0
  25. wayfinder_paths-0.1.31/wayfinder_paths/tests/test_mcp_idempotency_store.py +14 -0
  26. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/tests/test_mcp_quote_swap.py +60 -0
  27. wayfinder_paths-0.1.31/wayfinder_paths/tests/test_mcp_run_script.py +47 -0
  28. wayfinder_paths-0.1.31/wayfinder_paths/tests/test_mcp_tokens.py +49 -0
  29. wayfinder_paths-0.1.31/wayfinder_paths/tests/test_mcp_utils.py +35 -0
  30. wayfinder_paths-0.1.31/wayfinder_paths/tests/test_mcp_wallets.py +38 -0
  31. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/LICENSE +0 -0
  32. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/README.md +0 -0
  33. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/__init__.py +0 -0
  34. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/__init__.py +0 -0
  35. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/balance_adapter/README.md +0 -0
  36. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/balance_adapter/adapter.py +0 -0
  37. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/balance_adapter/examples.json +0 -0
  38. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/balance_adapter/manifest.yaml +0 -0
  39. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/balance_adapter/test_adapter.py +0 -0
  40. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/boros_adapter/__init__.py +0 -0
  41. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/boros_adapter/adapter.py +0 -0
  42. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/boros_adapter/client.py +0 -0
  43. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/boros_adapter/manifest.yaml +0 -0
  44. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/boros_adapter/parsers.py +0 -0
  45. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/boros_adapter/test_adapter.py +0 -0
  46. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/boros_adapter/test_golden.py +0 -0
  47. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/boros_adapter/types.py +0 -0
  48. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/boros_adapter/utils.py +0 -0
  49. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/brap_adapter/README.md +0 -0
  50. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/brap_adapter/__init__.py +0 -0
  51. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/brap_adapter/adapter.py +0 -0
  52. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/brap_adapter/examples.json +0 -0
  53. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/brap_adapter/manifest.yaml +0 -0
  54. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/brap_adapter/test_adapter.py +0 -0
  55. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/hyperlend_adapter/__init__.py +0 -0
  56. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/hyperlend_adapter/adapter.py +0 -0
  57. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/hyperlend_adapter/manifest.yaml +0 -0
  58. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +0 -0
  59. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/hyperliquid_adapter/__init__.py +0 -0
  60. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/hyperliquid_adapter/executor.py +0 -0
  61. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/hyperliquid_adapter/local_signer.py +0 -0
  62. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/hyperliquid_adapter/manifest.yaml +0 -0
  63. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/hyperliquid_adapter/test_adapter.py +0 -0
  64. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/hyperliquid_adapter/test_adapter_live.py +0 -0
  65. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/hyperliquid_adapter/test_executor.py +0 -0
  66. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/hyperliquid_adapter/test_utils.py +0 -0
  67. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/hyperliquid_adapter/utils.py +0 -0
  68. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/ledger_adapter/README.md +0 -0
  69. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/ledger_adapter/__init__.py +0 -0
  70. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/ledger_adapter/adapter.py +0 -0
  71. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/ledger_adapter/examples.json +0 -0
  72. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/ledger_adapter/manifest.yaml +0 -0
  73. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/ledger_adapter/test_adapter.py +0 -0
  74. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/moonwell_adapter/README.md +0 -0
  75. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/moonwell_adapter/__init__.py +0 -0
  76. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/moonwell_adapter/adapter.py +0 -0
  77. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/moonwell_adapter/manifest.yaml +0 -0
  78. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/moonwell_adapter/test_adapter.py +0 -0
  79. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/multicall_adapter/__init__.py +0 -0
  80. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/multicall_adapter/adapter.py +0 -0
  81. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/multicall_adapter/manifest.yaml +0 -0
  82. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/multicall_adapter/test_adapter.py +0 -0
  83. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/pendle_adapter/README.md +0 -0
  84. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/pendle_adapter/__init__.py +0 -0
  85. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/pendle_adapter/adapter.py +0 -0
  86. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/pendle_adapter/examples.json +0 -0
  87. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/pendle_adapter/manifest.yaml +0 -0
  88. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/pendle_adapter/test_adapter.py +0 -0
  89. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/pool_adapter/README.md +0 -0
  90. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/pool_adapter/__init__.py +0 -0
  91. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/pool_adapter/adapter.py +0 -0
  92. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/pool_adapter/examples.json +0 -0
  93. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/pool_adapter/manifest.yaml +0 -0
  94. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/pool_adapter/test_adapter.py +0 -0
  95. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/token_adapter/README.md +0 -0
  96. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/token_adapter/__init__.py +0 -0
  97. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/token_adapter/adapter.py +0 -0
  98. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/token_adapter/examples.json +0 -0
  99. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/token_adapter/manifest.yaml +0 -0
  100. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/adapters/token_adapter/test_adapter.py +0 -0
  101. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/conftest.py +0 -0
  102. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/__init__.py +0 -0
  103. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/adapters/BaseAdapter.py +0 -0
  104. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/adapters/__init__.py +0 -0
  105. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/adapters/models.py +0 -0
  106. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/analytics/__init__.py +0 -0
  107. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/analytics/bootstrap.py +0 -0
  108. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/analytics/stats.py +0 -0
  109. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/analytics/test_analytics.py +0 -0
  110. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/clients/BRAPClient.py +0 -0
  111. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/clients/BalanceClient.py +0 -0
  112. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/clients/ClientManager.py +0 -0
  113. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/clients/HyperlendClient.py +0 -0
  114. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/clients/LedgerClient.py +0 -0
  115. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/clients/TokenClient.py +0 -0
  116. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/clients/WayfinderClient.py +0 -0
  117. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/clients/__init__.py +0 -0
  118. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/clients/protocols.py +0 -0
  119. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/clients/test_ledger_client.py +0 -0
  120. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/config.py +0 -0
  121. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/constants/__init__.py +0 -0
  122. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/constants/base.py +0 -0
  123. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/constants/chains.py +0 -0
  124. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/constants/contracts.py +0 -0
  125. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/constants/erc20_abi.py +0 -0
  126. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/constants/hype_oft_abi.py +0 -0
  127. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/constants/hyperlend_abi.py +0 -0
  128. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/constants/hyperliquid.py +0 -0
  129. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/constants/moonwell_abi.py +0 -0
  130. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/constants/tokens.py +0 -0
  131. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/engine/manifest.py +0 -0
  132. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/strategies/Strategy.py +0 -0
  133. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/strategies/__init__.py +0 -0
  134. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/strategies/base.py +0 -0
  135. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/strategies/descriptors.py +0 -0
  136. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/strategies/opa_loop.py +0 -0
  137. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/utils/__init__.py +0 -0
  138. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/utils/evm_helpers.py +0 -0
  139. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/utils/test_transaction.py +0 -0
  140. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/utils/tokens.py +0 -0
  141. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/utils/transaction.py +0 -0
  142. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/utils/wallets.py +0 -0
  143. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/core/utils/web3.py +0 -0
  144. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/mcp/__init__.py +0 -0
  145. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/mcp/preview.py +0 -0
  146. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/mcp/scripting.py +0 -0
  147. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/mcp/server.py +0 -0
  148. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/mcp/state/__init__.py +0 -0
  149. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/mcp/state/profile_store.py +0 -0
  150. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/mcp/state/store.py +0 -0
  151. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/mcp/test_scripting.py +0 -0
  152. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/mcp/tools/__init__.py +0 -0
  153. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/mcp/tools/balances.py +0 -0
  154. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/mcp/tools/discovery.py +0 -0
  155. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/mcp/tools/run_script.py +0 -0
  156. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/mcp/tools/strategies.py +0 -0
  157. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/mcp/tools/tokens.py +0 -0
  158. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/mcp/tools/wallets.py +0 -0
  159. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/mcp/utils.py +0 -0
  160. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/policies/enso.py +0 -0
  161. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/policies/erc20.py +0 -0
  162. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/policies/evm.py +0 -0
  163. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/policies/hyper_evm.py +0 -0
  164. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/policies/hyperlend.py +0 -0
  165. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/policies/hyperliquid.py +0 -0
  166. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/policies/lifi.py +0 -0
  167. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/policies/moonwell.py +0 -0
  168. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/policies/prjx.py +0 -0
  169. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/policies/util.py +0 -0
  170. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/run_strategy.py +0 -0
  171. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/__init__.py +0 -0
  172. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/basis_trading_strategy/README.md +0 -0
  173. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/basis_trading_strategy/__init__.py +0 -0
  174. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/basis_trading_strategy/constants.py +0 -0
  175. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/basis_trading_strategy/examples.json +0 -0
  176. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/basis_trading_strategy/snapshot_mixin.py +0 -0
  177. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/basis_trading_strategy/types.py +0 -0
  178. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/boros_hype_strategy/__init__.py +0 -0
  179. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/boros_hype_strategy/boros_ops_mixin.py +0 -0
  180. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/boros_hype_strategy/constants.py +0 -0
  181. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/boros_hype_strategy/examples.json +0 -0
  182. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/boros_hype_strategy/hyperevm_ops_mixin.py +0 -0
  183. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/boros_hype_strategy/hyperliquid_ops_mixin.py +0 -0
  184. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/boros_hype_strategy/manifest.yaml +0 -0
  185. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/boros_hype_strategy/planner.py +0 -0
  186. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/boros_hype_strategy/risk_ops_mixin.py +0 -0
  187. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/boros_hype_strategy/snapshot_mixin.py +0 -0
  188. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/boros_hype_strategy/strategy.py +0 -0
  189. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/boros_hype_strategy/test_planner_golden.py +0 -0
  190. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/boros_hype_strategy/test_strategy.py +0 -0
  191. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/boros_hype_strategy/types.py +0 -0
  192. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/boros_hype_strategy/withdraw_mixin.py +0 -0
  193. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/README.md +0 -0
  194. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/examples.json +0 -0
  195. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +0 -0
  196. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +0 -0
  197. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/README.md +0 -0
  198. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/examples.json +0 -0
  199. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py +0 -0
  200. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/test_strategy.py +0 -0
  201. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/stablecoin_yield_strategy/README.md +0 -0
  202. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/stablecoin_yield_strategy/examples.json +0 -0
  203. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +0 -0
  204. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +0 -0
  205. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/tests/__init__.py +0 -0
  206. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/tests/test_test_coverage.py +0 -0
  207. {wayfinder_paths-0.1.30 → wayfinder_paths-0.1.31}/wayfinder_paths/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.1
2
2
  Name: wayfinder-paths
3
- Version: 0.1.30
3
+ Version: 0.1.31
4
4
  Summary: Wayfinder Path: strategies and adapters
5
5
  Author: Wayfinder
6
6
  Author-email: dev@wayfinder.ai
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "wayfinder-paths"
3
- version = "0.1.30"
3
+ version = "0.1.31"
4
4
  description = "Wayfinder Path: strategies and adapters"
5
5
  readme = "README.md"
6
6
  authors = ["Wayfinder <dev@wayfinder.ai>"]
@@ -603,9 +603,23 @@ class HyperliquidAdapter(BaseAdapter):
603
603
  if not self._exchange:
604
604
  raise NotImplementedError("No Hyperliquid exchange configured.")
605
605
 
606
+ try:
607
+ order_id_int = int(order_id)
608
+ except (TypeError, ValueError):
609
+ return (
610
+ False,
611
+ {
612
+ "status": "err",
613
+ "response": {
614
+ "type": "error",
615
+ "data": f"Invalid order_id for cancel_order: {order_id}",
616
+ },
617
+ },
618
+ )
619
+
606
620
  result = await self._exchange.cancel_order(
607
621
  asset_id=asset_id,
608
- order_id=str(order_id) if isinstance(order_id, int) else order_id,
622
+ order_id=order_id_int,
609
623
  address=address,
610
624
  )
611
625
 
@@ -84,7 +84,7 @@ class Exchange:
84
84
  ):
85
85
  """Place a market order (IOC limit with slippage)."""
86
86
  asset_name = self.info.asset_to_coin[asset_id]
87
- mids = await self.info.all_dex_mid_prices()
87
+ mids = self.info.all_mids()
88
88
  midprice = float(mids[asset_name])
89
89
 
90
90
  if slippage >= 1 or slippage < 0:
@@ -152,14 +152,14 @@ class Exchange:
152
152
  )
153
153
  return await self.sign_and_broadcast_hypecore(order_actions, address)
154
154
 
155
- async def cancel_order(self, asset_id: int, order_id: str, address: str):
155
+ async def cancel_order(self, asset_id: int, order_id: int, address: str):
156
156
  """Cancel an open order."""
157
157
  order_actions = {
158
158
  "type": "cancel",
159
159
  "cancels": [
160
160
  {
161
161
  "a": asset_id,
162
- "o": order_id,
162
+ "o": int(order_id),
163
163
  }
164
164
  ],
165
165
  }
@@ -243,7 +243,7 @@ class LegConfirmer:
243
243
  if asset_id is None:
244
244
  continue
245
245
  try:
246
- await self.adapter.cancel_order(asset_id, str(oid_int), address)
246
+ await self.adapter.cancel_order(asset_id, oid_int, address)
247
247
  attempted.add(oid_int)
248
248
  except Exception as exc:
249
249
  logger.info(f"Cancel failed for oid {oid_int}: {exc}")
@@ -0,0 +1,57 @@
1
+ from types import SimpleNamespace
2
+ from unittest.mock import AsyncMock
3
+
4
+ import pytest
5
+
6
+ from wayfinder_paths.adapters.hyperliquid_adapter.adapter import HyperliquidAdapter
7
+ from wayfinder_paths.adapters.hyperliquid_adapter.exchange import Exchange
8
+
9
+
10
+ class TestHyperliquidCancelOrder:
11
+ @pytest.mark.asyncio
12
+ async def test_exchange_cancel_order_uses_int_oid(self):
13
+ ex = Exchange(
14
+ info=SimpleNamespace(),
15
+ util=SimpleNamespace(),
16
+ sign_callback=AsyncMock(return_value="0x"),
17
+ signing_type="eip712",
18
+ )
19
+ ex.sign_and_broadcast_hypecore = AsyncMock(return_value={"status": "ok"})
20
+
21
+ await ex.cancel_order(asset_id=10210, order_id=306356655993, address="0xabc")
22
+
23
+ args, _ = ex.sign_and_broadcast_hypecore.await_args
24
+ action = args[0]
25
+ assert action["type"] == "cancel"
26
+ assert action["cancels"][0]["a"] == 10210
27
+ assert isinstance(action["cancels"][0]["o"], int)
28
+ assert action["cancels"][0]["o"] == 306356655993
29
+
30
+ @pytest.mark.asyncio
31
+ async def test_adapter_cancel_order_parses_string_oid(self):
32
+ adapter = object.__new__(HyperliquidAdapter)
33
+ adapter.simulation = False
34
+ adapter._exchange = SimpleNamespace()
35
+ adapter._exchange.cancel_order = AsyncMock(return_value={"status": "ok"})
36
+
37
+ ok, _ = await adapter.cancel_order(
38
+ asset_id=10210, order_id="306356655993", address="0xabc"
39
+ )
40
+ assert ok is True
41
+
42
+ adapter._exchange.cancel_order.assert_awaited_once_with(
43
+ asset_id=10210, order_id=306356655993, address="0xabc"
44
+ )
45
+
46
+ @pytest.mark.asyncio
47
+ async def test_adapter_cancel_order_rejects_bad_oid(self):
48
+ adapter = object.__new__(HyperliquidAdapter)
49
+ adapter.simulation = False
50
+ adapter._exchange = SimpleNamespace()
51
+ adapter._exchange.cancel_order = AsyncMock(return_value={"status": "ok"})
52
+
53
+ ok, res = await adapter.cancel_order(
54
+ asset_id=1, order_id="not-a-number", address="0xabc"
55
+ )
56
+ assert ok is False
57
+ assert res["status"] == "err"
@@ -0,0 +1,52 @@
1
+ from types import SimpleNamespace
2
+ from unittest.mock import AsyncMock
3
+
4
+ import pytest
5
+
6
+ from wayfinder_paths.adapters.hyperliquid_adapter.exchange import Exchange
7
+
8
+
9
+ class _InfoStub(SimpleNamespace):
10
+ def all_mids(self):
11
+ return {"HYPE": "1.0"}
12
+
13
+ async def all_dex_mid_prices(self): # pragma: no cover
14
+ raise AssertionError(
15
+ "Exchange must use Info.all_mids(), not all_dex_mid_prices"
16
+ )
17
+
18
+
19
+ class _UtilStub(SimpleNamespace):
20
+ def get_price_decimals_for_hypecore_asset(self, asset_id: int) -> int:
21
+ return 6
22
+
23
+
24
+ class TestExchangeMidPriceFetch:
25
+ @pytest.mark.asyncio
26
+ async def test_place_market_order_uses_all_mids(self):
27
+ info = _InfoStub(asset_to_coin={7: "HYPE"})
28
+ util = _UtilStub()
29
+ ex = Exchange(
30
+ info=info,
31
+ util=util,
32
+ sign_callback=AsyncMock(return_value="0x"),
33
+ signing_type="eip712",
34
+ )
35
+
36
+ async def _no_broadcast(action, address):
37
+ return action
38
+
39
+ ex.sign_and_broadcast_hypecore = _no_broadcast
40
+
41
+ action = await ex.place_market_order(
42
+ asset_id=7,
43
+ is_buy=True,
44
+ slippage=0.01,
45
+ size=1.0,
46
+ address="0xabc",
47
+ )
48
+
49
+ assert action["type"] == "order"
50
+ assert action["orders"][0]["a"] == 7
51
+ assert action["orders"][0]["b"] is True
52
+ assert action["orders"][0]["p"] == "1.01"
@@ -0,0 +1,64 @@
1
+ from unittest.mock import AsyncMock
2
+
3
+ import pytest
4
+
5
+ from wayfinder_paths.adapters.hyperliquid_adapter.adapter import HyperliquidAdapter
6
+ from wayfinder_paths.adapters.hyperliquid_adapter.exchange import Exchange
7
+
8
+
9
+ @pytest.fixture
10
+ def live_adapter():
11
+ return HyperliquidAdapter(config={}, simulation=True)
12
+
13
+
14
+ class TestHyperliquidSdkCompat:
15
+ @pytest.mark.asyncio
16
+ async def test_util_mid_prices_live(self, live_adapter):
17
+ mids = await live_adapter.util.get_hypecore_all_dex_mid_prices()
18
+ assert isinstance(mids, dict)
19
+ assert len(mids) > 0
20
+
21
+ # Sanity check some common keys exist (perp coins or spot tickers like @107).
22
+ assert "HYPE" in mids or "BTC" in mids or any(k.startswith("@") for k in mids)
23
+
24
+ @pytest.mark.asyncio
25
+ async def test_util_meta_live(self, live_adapter):
26
+ meta = await live_adapter.util.get_hypecore_all_dex_meta_universe()
27
+ assert isinstance(meta, dict)
28
+ assert "universe" in meta
29
+
30
+
31
+ class TestExchangeUsesLiveMids:
32
+ @pytest.mark.asyncio
33
+ async def test_place_market_order_builds_ioc_limit(self, live_adapter):
34
+ # Use a perp id to avoid spot naming edge-cases.
35
+ asset_id = live_adapter.coin_to_asset["HYPE"]
36
+
37
+ ex = Exchange(
38
+ info=live_adapter.info,
39
+ util=live_adapter.util,
40
+ sign_callback=AsyncMock(return_value="0x"),
41
+ signing_type="eip712",
42
+ )
43
+
44
+ async def _no_broadcast(action, address):
45
+ return action
46
+
47
+ ex.sign_and_broadcast_hypecore = _no_broadcast
48
+
49
+ action = await ex.place_market_order(
50
+ asset_id=asset_id,
51
+ is_buy=True,
52
+ slippage=0.01,
53
+ size=1.0,
54
+ address="0x0000000000000000000000000000000000000000",
55
+ )
56
+
57
+ assert action["type"] == "order"
58
+ assert action["orders"][0]["a"] == asset_id
59
+ assert action["orders"][0]["b"] is True
60
+
61
+ # Price should be at/above current mid for a buy (within rounding tolerance).
62
+ mid = float(live_adapter.info.all_mids()["HYPE"])
63
+ px = float(action["orders"][0]["p"])
64
+ assert px >= mid * 0.999
@@ -1,4 +1,3 @@
1
- import asyncio
2
1
  import time
3
2
  from decimal import ROUND_DOWN, Decimal
4
3
  from typing import Any
@@ -61,10 +60,12 @@ class Util:
61
60
  return assets.get(asset_name)
62
61
 
63
62
  async def get_hypecore_all_dex_mid_prices(self):
64
- return await self.info.all_dex_mid_prices()
63
+ # Backwards compatible wrapper: the Hyperliquid SDK now exposes `all_mids()`.
64
+ return self.info.all_mids()
65
65
 
66
66
  async def get_hypecore_all_dex_meta_universe(self):
67
- return await self.info.all_dex_meta_universe()
67
+ # Backwards compatible wrapper: the Hyperliquid SDK now exposes `meta()`.
68
+ return self.info.meta()
68
69
 
69
70
  def get_size_decimals_for_hypecore_asset(self, asset_id: int):
70
71
  return self.info.asset_to_sz_decimals[asset_id]
@@ -107,11 +108,9 @@ class Util:
107
108
  return perp_user_state
108
109
 
109
110
  async def get_hypecore_user(self, address):
110
- perp_user_state, spot_user_state, open_orders = await asyncio.gather(
111
- self.info.all_dex_user_state(address),
112
- self.info.spot_user_state(address),
113
- self.info.all_dex_open_orders(address),
114
- )
111
+ perp_user_state = self.info.user_state(address)
112
+ spot_user_state = self.info.spot_user_state(address)
113
+ open_orders = self.info.open_orders(address)
115
114
  formatted_perp_state = self._reformat_perp_user_state(perp_user_state)
116
115
  state = {
117
116
  "perp_user_state": formatted_perp_state,
@@ -172,7 +171,7 @@ class Util:
172
171
  out = []
173
172
  while True:
174
173
  try:
175
- batch = await self.info.user_fills_by_time(wallet, start, end, False)
174
+ batch = self.info.user_fills_by_time(wallet, start, end, False)
176
175
  except Exception as e:
177
176
  logger.error(f"Failed to fetch fills via node/public/SDK: {e}")
178
177
  break
@@ -185,7 +184,7 @@ class Util:
185
184
  return out
186
185
 
187
186
  async def get_hypecore_position(self, address, asset_name):
188
- perp_user_state = await self.info.all_dex_user_state(address)
187
+ perp_user_state = self.info.user_state(address)
189
188
  formatted_perp_user_state = self._reformat_perp_user_state(perp_user_state)
190
189
 
191
190
  for pos in formatted_perp_user_state.get("assetPositions", []):
@@ -99,7 +99,7 @@ class PoolClient(WayfinderClient):
99
99
  self.api_base_url = get_api_base_url()
100
100
 
101
101
  def _pools_url(self) -> str:
102
- return f"{self.api_base_url}/v1/blockchain/pools/"
102
+ return f"{self.api_base_url}/blockchain/pools/"
103
103
 
104
104
  async def get_pools(
105
105
  self,
@@ -257,19 +257,40 @@ def _compact_quote(
257
257
  """Create a compact summary of quote data, stripping verbose nested structures."""
258
258
  result: dict[str, Any] = {}
259
259
 
260
- # Extract provider list from quotes (API returns quotes as a list at top level)
261
- all_quotes = quote_data.get("quotes", [])
262
- if not isinstance(all_quotes, list):
263
- all_quotes = []
264
- if isinstance(all_quotes, list):
265
- result["providers"] = list(
266
- {
267
- q.get("provider")
268
- for q in all_quotes
269
- if isinstance(q, dict) and q.get("provider")
270
- }
271
- )
272
- result["quote_count"] = len(all_quotes)
260
+ # Extract provider list from quotes. BRAP quotes may appear as either:
261
+ # 1) {"quotes": [...], "best_quote": {...}}
262
+ # 2) {"quotes": {"all_quotes": [...], "best_quote": {...}, "quote_count": N}}
263
+ all_quotes: list[dict[str, Any]] = []
264
+ raw_quotes = quote_data.get("quotes", [])
265
+ quote_count = None
266
+
267
+ if isinstance(raw_quotes, list):
268
+ all_quotes = [q for q in raw_quotes if isinstance(q, dict)]
269
+ elif isinstance(raw_quotes, dict):
270
+ nested = raw_quotes.get("all_quotes") or raw_quotes.get("quotes") or []
271
+ if isinstance(nested, list):
272
+ all_quotes = [q for q in nested if isinstance(q, dict)]
273
+ qc = raw_quotes.get("quote_count")
274
+ try:
275
+ quote_count = int(qc) if qc is not None else None
276
+ except (TypeError, ValueError):
277
+ quote_count = None
278
+
279
+ providers: list[str] = []
280
+ seen: set[str] = set()
281
+ for q in all_quotes:
282
+ p = q.get("provider")
283
+ if not p:
284
+ continue
285
+ p_str = str(p)
286
+ if p_str in seen:
287
+ continue
288
+ seen.add(p_str)
289
+ providers.append(p_str)
290
+
291
+ if providers:
292
+ result["providers"] = providers
293
+ result["quote_count"] = quote_count if quote_count is not None else len(all_quotes)
273
294
 
274
295
  # Compact best_quote - only essential fields
275
296
  if isinstance(best_quote, dict):
@@ -511,9 +532,20 @@ async def execute(
511
532
  store.put(key, tool_input, response)
512
533
  return response
513
534
 
514
- best_quote = (
515
- quote_data.get("best_quote") if isinstance(quote_data, dict) else None
516
- )
535
+ # BRAP quote responses have historically appeared in two shapes:
536
+ # 1) {"quotes": [...], "best_quote": {...}}
537
+ # 2) {"quotes": {"all_quotes": [...], "best_quote": {...}, "quote_count": N}}
538
+ best_quote = None
539
+ if isinstance(quote_data, dict):
540
+ if isinstance(quote_data.get("best_quote"), dict):
541
+ best_quote = quote_data.get("best_quote")
542
+ else:
543
+ quotes_block = quote_data.get("quotes")
544
+ if isinstance(quotes_block, dict) and isinstance(
545
+ quotes_block.get("best_quote"), dict
546
+ ):
547
+ best_quote = quotes_block.get("best_quote")
548
+
517
549
  if not isinstance(best_quote, dict):
518
550
  response = err(
519
551
  "quote_error", "No best_quote returned", {"quote": quote_data}
@@ -5,9 +5,6 @@ import re
5
5
  from typing import Any, Literal
6
6
 
7
7
  from wayfinder_paths.adapters.hyperliquid_adapter.adapter import HyperliquidAdapter
8
- from wayfinder_paths.adapters.hyperliquid_adapter.executor import (
9
- LocalHyperliquidExecutor,
10
- )
11
8
  from wayfinder_paths.core.constants.hyperliquid import (
12
9
  DEFAULT_HYPERLIQUID_BUILDER_FEE_TENTHS_BP,
13
10
  HYPE_FEE_WALLET,
@@ -404,16 +401,7 @@ async def hyperliquid_execute(
404
401
 
405
402
  effects: list[dict[str, Any]] = []
406
403
 
407
- executor = None
408
- if not dry:
409
- try:
410
- executor = LocalHyperliquidExecutor(config=config, network="mainnet")
411
- except Exception as exc: # noqa: BLE001
412
- response = err("executor_error", str(exc))
413
- store.put(key, tool_input, response)
414
- return response
415
-
416
- adapter = HyperliquidAdapter(config=config, simulation=dry, executor=executor)
404
+ adapter = HyperliquidAdapter(config=config, simulation=dry)
417
405
 
418
406
  if action == "withdraw":
419
407
  if amount_usdc is None:
@@ -21,6 +21,47 @@ def _slippage_float(slippage_bps: int) -> float:
21
21
  return max(0.0, float(int(slippage_bps)) / 10_000.0)
22
22
 
23
23
 
24
+ def _unwrap_brap_quote_response(
25
+ data: Any,
26
+ ) -> tuple[list[dict[str, Any]], dict[str, Any] | None, int]:
27
+ """
28
+ BRAP quote responses have historically appeared in two shapes:
29
+
30
+ 1) {"quotes": [...], "best_quote": {...}}
31
+ 2) {"quotes": {"all_quotes": [...], "best_quote": {...}, "quote_count": N}}
32
+
33
+ This helper normalizes both to (all_quotes, best_quote, quote_count).
34
+ """
35
+ if not isinstance(data, dict):
36
+ return [], None, 0
37
+
38
+ raw_quotes = data.get("quotes")
39
+ best_quote = data.get("best_quote")
40
+
41
+ if isinstance(raw_quotes, list) or isinstance(best_quote, dict):
42
+ all_quotes = raw_quotes if isinstance(raw_quotes, list) else []
43
+ best = best_quote if isinstance(best_quote, dict) else None
44
+ return all_quotes, best, len(all_quotes)
45
+
46
+ # Legacy/nested payload under `quotes`
47
+ if isinstance(raw_quotes, dict):
48
+ all_quotes = raw_quotes.get("all_quotes") or raw_quotes.get("quotes") or []
49
+ if not isinstance(all_quotes, list):
50
+ all_quotes = []
51
+ best = raw_quotes.get("best_quote")
52
+ best_out = best if isinstance(best, dict) else None
53
+
54
+ quote_count = raw_quotes.get("quote_count")
55
+ try:
56
+ quote_count_i = int(quote_count)
57
+ except (TypeError, ValueError):
58
+ quote_count_i = len(all_quotes)
59
+
60
+ return all_quotes, best_out, quote_count_i
61
+
62
+ return [], None, 0
63
+
64
+
24
65
  async def quote_swap(
25
66
  *,
26
67
  wallet_label: str,
@@ -84,13 +125,7 @@ async def quote_swap(
84
125
  except Exception as exc: # noqa: BLE001
85
126
  return err("quote_error", str(exc))
86
127
 
87
- # API returns {"quotes": [...], "best_quote": {...}} at top level
88
- raw_quotes = data.get("quotes", []) if isinstance(data, dict) else []
89
- if not isinstance(raw_quotes, list):
90
- raw_quotes = []
91
- all_quotes = raw_quotes
92
- best_quote = data.get("best_quote") if isinstance(data, dict) else None
93
- quote_count = len(all_quotes)
128
+ all_quotes, best_quote, quote_count = _unwrap_brap_quote_response(data)
94
129
 
95
130
  providers: list[str] = []
96
131
  seen: set[str] = set()
@@ -0,0 +1,24 @@
1
+ schema_version: "0.1"
2
+ entrypoint: "wayfinder_paths.strategies.basis_trading_strategy.strategy.BasisTradingStrategy"
3
+ permissions:
4
+ policy: |
5
+ (wallet.id == 'FORMAT_WALLET_ID') AND (
6
+ # Allow Hyperliquid EIP-712 order/transfer actions
7
+ (action.type == 'hyperliquid_order') OR
8
+ (action.type == 'hyperliquid_cancel') OR
9
+ (action.type == 'hyperliquid_transfer') OR
10
+ (action.type == 'hyperliquid_withdraw') OR
11
+ # Allow USDC transfers to Hyperliquid bridge
12
+ (action.type == 'erc20_transfer' AND action.to == '0x2Df1c51E09aECF9cacB7bc98cB1742757f163dF7') OR
13
+ # Allow withdrawals to main wallet
14
+ (action.type == 'erc20_transfer' AND action.to == main_wallet.address)
15
+ )
16
+ adapters:
17
+ - name: "BALANCE"
18
+ capabilities: ["wallet_read", "wallet_transfer"]
19
+ - name: "LEDGER"
20
+ capabilities: ["ledger.read", "ledger.write", "strategy.transactions"]
21
+ - name: "TOKEN"
22
+ capabilities: ["token.read"]
23
+ - name: "HYPERLIQUID"
24
+ capabilities: ["market.read", "market.meta", "market.funding", "market.candles", "market.orderbook", "order.execute", "order.cancel", "position.manage", "transfer", "withdraw"]