wayfinder-paths 0.1.28__tar.gz → 0.1.30__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 (193) hide show
  1. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/PKG-INFO +1 -1
  2. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/pyproject.toml +1 -1
  3. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/boros_adapter/adapter.py +445 -14
  4. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/boros_adapter/client.py +7 -5
  5. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/boros_adapter/test_adapter.py +259 -19
  6. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/adapter.py +4 -14
  7. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/exchange.py +2 -2
  8. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/local_signer.py +2 -33
  9. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/multicall_adapter/adapter.py +2 -4
  10. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/TokenClient.py +1 -1
  11. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/constants/__init__.py +23 -1
  12. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/constants/contracts.py +22 -0
  13. wayfinder_paths-0.1.30/wayfinder_paths/core/constants/hype_oft_abi.py +151 -0
  14. wayfinder_paths-0.1.30/wayfinder_paths/core/constants/hyperliquid.py +33 -0
  15. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/engine/manifest.py +1 -1
  16. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/strategies/Strategy.py +1 -2
  17. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/scripting.py +2 -2
  18. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/tools/discovery.py +3 -72
  19. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/tools/execute.py +8 -4
  20. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/tools/hyperliquid.py +1 -1
  21. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/tools/quotes.py +11 -133
  22. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/tools/wallets.py +4 -7
  23. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/utils.py +0 -22
  24. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/policies/lifi.py +5 -2
  25. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/policies/moonwell.py +3 -1
  26. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/policies/util.py +4 -2
  27. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/basis_trading_strategy/strategy.py +2 -4
  28. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/boros_ops_mixin.py +57 -201
  29. wayfinder_paths-0.1.30/wayfinder_paths/strategies/boros_hype_strategy/constants.py +127 -0
  30. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/strategy.py +24 -63
  31. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +2 -0
  32. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py +2 -0
  33. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +4 -1
  34. wayfinder_paths-0.1.28/wayfinder_paths/core/constants/hyperliquid.py +0 -16
  35. wayfinder_paths-0.1.28/wayfinder_paths/core/types.py +0 -19
  36. wayfinder_paths-0.1.28/wayfinder_paths/strategies/boros_hype_strategy/constants.py +0 -271
  37. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/LICENSE +0 -0
  38. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/README.md +0 -0
  39. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/__init__.py +0 -0
  40. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/__init__.py +0 -0
  41. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/balance_adapter/README.md +0 -0
  42. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/balance_adapter/adapter.py +0 -0
  43. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/balance_adapter/examples.json +0 -0
  44. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/balance_adapter/manifest.yaml +0 -0
  45. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/balance_adapter/test_adapter.py +0 -0
  46. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/boros_adapter/__init__.py +0 -0
  47. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/boros_adapter/manifest.yaml +0 -0
  48. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/boros_adapter/parsers.py +0 -0
  49. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/boros_adapter/test_golden.py +0 -0
  50. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/boros_adapter/types.py +0 -0
  51. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/boros_adapter/utils.py +0 -0
  52. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/brap_adapter/README.md +0 -0
  53. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/brap_adapter/__init__.py +0 -0
  54. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/brap_adapter/adapter.py +0 -0
  55. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/brap_adapter/examples.json +0 -0
  56. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/brap_adapter/manifest.yaml +0 -0
  57. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/brap_adapter/test_adapter.py +0 -0
  58. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperlend_adapter/__init__.py +0 -0
  59. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperlend_adapter/adapter.py +0 -0
  60. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperlend_adapter/manifest.yaml +0 -0
  61. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +0 -0
  62. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/__init__.py +0 -0
  63. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/executor.py +0 -0
  64. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/manifest.yaml +0 -0
  65. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/paired_filler.py +0 -0
  66. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/test_adapter.py +0 -0
  67. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/test_adapter_live.py +0 -0
  68. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/test_executor.py +0 -0
  69. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/test_utils.py +0 -0
  70. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/util.py +0 -0
  71. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/hyperliquid_adapter/utils.py +0 -0
  72. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/ledger_adapter/README.md +0 -0
  73. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/ledger_adapter/__init__.py +0 -0
  74. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/ledger_adapter/adapter.py +0 -0
  75. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/ledger_adapter/examples.json +0 -0
  76. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/ledger_adapter/manifest.yaml +0 -0
  77. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/ledger_adapter/test_adapter.py +0 -0
  78. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/moonwell_adapter/README.md +0 -0
  79. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/moonwell_adapter/__init__.py +0 -0
  80. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/moonwell_adapter/adapter.py +0 -0
  81. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/moonwell_adapter/manifest.yaml +0 -0
  82. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/moonwell_adapter/test_adapter.py +0 -0
  83. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/multicall_adapter/__init__.py +0 -0
  84. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/multicall_adapter/manifest.yaml +0 -0
  85. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/multicall_adapter/test_adapter.py +0 -0
  86. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pendle_adapter/README.md +0 -0
  87. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pendle_adapter/__init__.py +0 -0
  88. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pendle_adapter/adapter.py +0 -0
  89. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pendle_adapter/examples.json +0 -0
  90. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pendle_adapter/manifest.yaml +0 -0
  91. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pendle_adapter/test_adapter.py +0 -0
  92. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pool_adapter/README.md +0 -0
  93. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pool_adapter/__init__.py +0 -0
  94. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pool_adapter/adapter.py +0 -0
  95. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pool_adapter/examples.json +0 -0
  96. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pool_adapter/manifest.yaml +0 -0
  97. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/pool_adapter/test_adapter.py +0 -0
  98. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/token_adapter/README.md +0 -0
  99. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/token_adapter/__init__.py +0 -0
  100. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/token_adapter/adapter.py +0 -0
  101. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/token_adapter/examples.json +0 -0
  102. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/token_adapter/manifest.yaml +0 -0
  103. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/adapters/token_adapter/test_adapter.py +0 -0
  104. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/conftest.py +0 -0
  105. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/__init__.py +0 -0
  106. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/adapters/BaseAdapter.py +0 -0
  107. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/adapters/__init__.py +0 -0
  108. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/adapters/models.py +0 -0
  109. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/analytics/__init__.py +0 -0
  110. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/analytics/bootstrap.py +0 -0
  111. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/analytics/stats.py +0 -0
  112. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/analytics/test_analytics.py +0 -0
  113. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/BRAPClient.py +0 -0
  114. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/BalanceClient.py +0 -0
  115. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/ClientManager.py +0 -0
  116. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/HyperlendClient.py +0 -0
  117. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/LedgerClient.py +0 -0
  118. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/PoolClient.py +0 -0
  119. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/WayfinderClient.py +0 -0
  120. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/__init__.py +0 -0
  121. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/protocols.py +0 -0
  122. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/clients/test_ledger_client.py +0 -0
  123. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/config.py +0 -0
  124. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/constants/base.py +0 -0
  125. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/constants/chains.py +0 -0
  126. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/constants/erc20_abi.py +0 -0
  127. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/constants/hyperlend_abi.py +0 -0
  128. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/constants/moonwell_abi.py +0 -0
  129. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/constants/tokens.py +0 -0
  130. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/strategies/__init__.py +0 -0
  131. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/strategies/base.py +0 -0
  132. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/strategies/descriptors.py +0 -0
  133. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/strategies/opa_loop.py +0 -0
  134. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/utils/__init__.py +0 -0
  135. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/utils/evm_helpers.py +0 -0
  136. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/utils/test_transaction.py +0 -0
  137. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/utils/tokens.py +0 -0
  138. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/utils/transaction.py +0 -0
  139. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/utils/wallets.py +0 -0
  140. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/core/utils/web3.py +0 -0
  141. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/__init__.py +0 -0
  142. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/preview.py +0 -0
  143. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/server.py +0 -0
  144. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/state/__init__.py +0 -0
  145. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/state/profile_store.py +0 -0
  146. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/state/store.py +0 -0
  147. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/test_scripting.py +0 -0
  148. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/tools/__init__.py +0 -0
  149. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/tools/balances.py +0 -0
  150. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/tools/run_script.py +0 -0
  151. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/tools/strategies.py +0 -0
  152. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/mcp/tools/tokens.py +0 -0
  153. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/policies/enso.py +0 -0
  154. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/policies/erc20.py +0 -0
  155. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/policies/evm.py +0 -0
  156. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/policies/hyper_evm.py +0 -0
  157. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/policies/hyperlend.py +0 -0
  158. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/policies/hyperliquid.py +0 -0
  159. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/policies/prjx.py +0 -0
  160. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/run_strategy.py +0 -0
  161. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/__init__.py +0 -0
  162. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/basis_trading_strategy/README.md +0 -0
  163. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/basis_trading_strategy/__init__.py +0 -0
  164. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/basis_trading_strategy/constants.py +0 -0
  165. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/basis_trading_strategy/examples.json +0 -0
  166. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/basis_trading_strategy/snapshot_mixin.py +0 -0
  167. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/basis_trading_strategy/test_strategy.py +0 -0
  168. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/basis_trading_strategy/types.py +0 -0
  169. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/__init__.py +0 -0
  170. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/examples.json +0 -0
  171. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/hyperevm_ops_mixin.py +0 -0
  172. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/hyperliquid_ops_mixin.py +0 -0
  173. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/manifest.yaml +0 -0
  174. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/planner.py +0 -0
  175. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/risk_ops_mixin.py +0 -0
  176. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/snapshot_mixin.py +0 -0
  177. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/test_planner_golden.py +0 -0
  178. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/test_strategy.py +0 -0
  179. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/types.py +0 -0
  180. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/boros_hype_strategy/withdraw_mixin.py +0 -0
  181. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/README.md +0 -0
  182. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/examples.json +0 -0
  183. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +0 -0
  184. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/README.md +0 -0
  185. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/examples.json +0 -0
  186. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/test_strategy.py +0 -0
  187. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/stablecoin_yield_strategy/README.md +0 -0
  188. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/stablecoin_yield_strategy/examples.json +0 -0
  189. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +0 -0
  190. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/tests/__init__.py +0 -0
  191. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/tests/test_mcp_quote_swap.py +0 -0
  192. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/tests/test_test_coverage.py +0 -0
  193. {wayfinder_paths-0.1.28 → wayfinder_paths-0.1.30}/wayfinder_paths/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: wayfinder-paths
3
- Version: 0.1.28
3
+ Version: 0.1.30
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.28"
3
+ version = "0.1.30"
4
4
  description = "Wayfinder Path: strategies and adapters"
5
5
  readme = "README.md"
6
6
  authors = ["Wayfinder <dev@wayfinder.ai>"]
@@ -5,15 +5,20 @@ import time
5
5
  from collections.abc import Callable
6
6
  from typing import Any
7
7
 
8
- from eth_abi import encode
8
+ from eth_abi import decode, encode
9
9
  from eth_utils import function_signature_to_4byte_selector, to_checksum_address
10
10
  from loguru import logger
11
11
 
12
12
  from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
13
- from wayfinder_paths.core.constants.base import DEFAULT_TRANSACTION_TIMEOUT
14
- from wayfinder_paths.core.constants.contracts import BOROS_MARKET_HUB, BOROS_ROUTER
13
+ from wayfinder_paths.core.constants.chains import CHAIN_ID_HYPEREVM
14
+ from wayfinder_paths.core.constants.contracts import (
15
+ BOROS_MARKET_HUB,
16
+ BOROS_ROUTER,
17
+ HYPE_OFT_ADDRESS,
18
+ )
19
+ from wayfinder_paths.core.constants.hype_oft_abi import HYPE_OFT_ABI
15
20
  from wayfinder_paths.core.utils.tokens import build_approve_transaction
16
- from wayfinder_paths.core.utils.transaction import send_transaction
21
+ from wayfinder_paths.core.utils.transaction import encode_call, send_transaction
17
22
  from wayfinder_paths.core.utils.web3 import web3_from_chain_id
18
23
 
19
24
  from .client import BorosClient
@@ -115,6 +120,120 @@ class BorosAdapter(BaseAdapter):
115
120
  }
116
121
  ]
117
122
 
123
+ @staticmethod
124
+ def _pad_address_bytes32(address: str) -> bytes:
125
+ checksum = to_checksum_address(address)
126
+ return bytes.fromhex(checksum[2:]).rjust(32, b"\x00")
127
+
128
+ async def get_cash_fee_data(self, *, token_id: int) -> tuple[bool, dict[str, Any]]:
129
+ """Read MarketHub.getCashFeeData(tokenId) from chain.
130
+
131
+ This is useful for guarding Boros actions that require a minimum amount
132
+ of cross cash (e.g., MMInsufficientMinCash()).
133
+ """
134
+ try:
135
+ selector = function_signature_to_4byte_selector("getCashFeeData(uint16)")
136
+ params = encode(["uint16"], [int(token_id)])
137
+ data = "0x" + selector.hex() + params.hex()
138
+
139
+ async with web3_from_chain_id(self.chain_id) as web3:
140
+ raw: bytes = await web3.eth.call(
141
+ {
142
+ "to": to_checksum_address(BOROS_MARKET_HUB),
143
+ "data": data,
144
+ }
145
+ )
146
+
147
+ if len(raw) % 32 != 0:
148
+ return False, {"error": f"Unexpected getCashFeeData() size: {len(raw)}"}
149
+
150
+ n_words = len(raw) // 32
151
+ values = decode(["uint256"] * n_words, raw)
152
+ if len(values) < 4:
153
+ return False, {
154
+ "error": f"Unexpected getCashFeeData() words: {len(values)}"
155
+ }
156
+
157
+ # Empirically (2026-02-01 on Arbitrum MarketHub), the return is 4 uint256s.
158
+ # We expose all 4, and provide float conversions for the commonly used ones.
159
+ scaling_factor_wei = int(values[0])
160
+ fee_rate_wei = int(values[1])
161
+ min_cash_cross_wei = int(values[2])
162
+ min_cash_isolated_wei = int(values[3])
163
+
164
+ return True, {
165
+ "token_id": int(token_id),
166
+ "scaling_factor_wei": scaling_factor_wei,
167
+ "fee_rate_wei": fee_rate_wei,
168
+ "min_cash_cross_wei": min_cash_cross_wei,
169
+ "min_cash_isolated_wei": min_cash_isolated_wei,
170
+ "fee_rate": fee_rate_wei / 1e18,
171
+ "min_cash_cross": min_cash_cross_wei / 1e18,
172
+ "min_cash_isolated": min_cash_isolated_wei / 1e18,
173
+ }
174
+ except Exception as exc: # noqa: BLE001
175
+ return False, {"error": str(exc)}
176
+
177
+ async def sweep_isolated_to_cross(
178
+ self,
179
+ *,
180
+ token_id: int,
181
+ market_id: int | None = None,
182
+ ) -> tuple[bool, dict[str, Any]]:
183
+ """Sweep isolated cash -> cross cash for a given token (optionally per-market).
184
+
185
+ Boros deposits can sometimes show up as isolated cash for the target market;
186
+ this helper moves that isolated cash back to cross margin using cash_transfer.
187
+
188
+ Notes:
189
+ - Uses `get_account_balances()` (collaterals endpoint) to find isolated cash.
190
+ - cash_transfer uses 1e18 internal cash units, not token native decimals.
191
+ - This does NOT touch isolated positions for other markets unless market_id is None.
192
+ """
193
+ if self.simulation:
194
+ return True, {"status": "simulated"}
195
+
196
+ ok_bal, balances = await self.get_account_balances(token_id=int(token_id))
197
+ if not ok_bal or not isinstance(balances, dict):
198
+ return False, {"error": f"Failed to read Boros balances: {balances}"}
199
+
200
+ isolated_positions = balances.get("isolated_positions") or []
201
+ if not isinstance(isolated_positions, list):
202
+ isolated_positions = []
203
+
204
+ moved: list[dict[str, Any]] = []
205
+ for iso in isolated_positions:
206
+ try:
207
+ iso_market_id = int(iso.get("market_id"))
208
+ if market_id is not None and iso_market_id != int(market_id):
209
+ continue
210
+ balance_wei = int(iso.get("balance_wei") or 0)
211
+ if balance_wei <= 0:
212
+ continue
213
+
214
+ tx_ok, tx_res = await self.cash_transfer(
215
+ market_id=iso_market_id,
216
+ amount_wei=balance_wei,
217
+ is_deposit=False, # isolated -> cross
218
+ )
219
+ moved.append(
220
+ {
221
+ "market_id": iso_market_id,
222
+ "balance_wei": balance_wei,
223
+ "ok": tx_ok,
224
+ "tx": tx_res,
225
+ }
226
+ )
227
+ if not tx_ok:
228
+ return False, {
229
+ "error": f"Failed sweep isolated->cross for market {iso_market_id}",
230
+ "moved": moved,
231
+ }
232
+ except Exception as exc: # noqa: BLE001
233
+ return False, {"error": f"Failed sweep isolated->cross: {exc}"}
234
+
235
+ return True, {"status": "ok", "moved": moved}
236
+
118
237
  @staticmethod
119
238
  def _unwrap_tx_payload(payload: dict[str, Any]) -> dict[str, Any]:
120
239
  """Best-effort unwrap of API payloads that may nest the tx dict."""
@@ -195,7 +314,6 @@ class BorosAdapter(BaseAdapter):
195
314
  self,
196
315
  calldata: dict[str, Any],
197
316
  *,
198
- timeout: int = DEFAULT_TRANSACTION_TIMEOUT,
199
317
  max_retries: int = 2,
200
318
  ) -> tuple[bool, dict[str, Any]]:
201
319
  """Broadcast calldata from Boros API with retry logic.
@@ -292,14 +410,6 @@ class BorosAdapter(BaseAdapter):
292
410
  "attempts": max_retries + 1,
293
411
  }
294
412
 
295
- async def connect(self) -> bool:
296
- try:
297
- markets = await self.boros_client.list_markets(limit=1)
298
- return len(markets) > 0
299
- except Exception as exc:
300
- logger.error(f"BorosAdapter connection failed: {exc}")
301
- return False
302
-
303
413
  # ------------------------------------------------------------------ #
304
414
  # Tick Math Utilities #
305
415
  # ------------------------------------------------------------------ #
@@ -1015,6 +1125,14 @@ class BorosAdapter(BaseAdapter):
1015
1125
  token_id: int,
1016
1126
  market_id: int,
1017
1127
  ) -> tuple[bool, dict[str, Any]]:
1128
+ """Deposit collateral into Boros cross margin.
1129
+
1130
+ IMPORTANT: amount_wei is in the collateral token's native decimals.
1131
+ Example: USDT has 6 decimals, so 1 USDT = 1_000_000.
1132
+
1133
+ After deposit, Boros may credit the cash as isolated for market_id. This
1134
+ helper sweeps isolated -> cross for that market to match the method name.
1135
+ """
1018
1136
  if self.simulation:
1019
1137
  logger.info(
1020
1138
  f"[SIMULATION] deposit_to_cross_margin: {amount_wei} wei, "
@@ -1074,7 +1192,24 @@ class BorosAdapter(BaseAdapter):
1074
1192
  "tx": tx_res,
1075
1193
  }
1076
1194
 
1077
- return True, {"status": "ok", "approve": approve_res, "tx": tx_res}
1195
+ sweep_ok, sweep_res = await self.sweep_isolated_to_cross(
1196
+ token_id=int(token_id),
1197
+ market_id=int(market_id),
1198
+ )
1199
+ if not sweep_ok:
1200
+ return False, {
1201
+ "error": f"Deposit succeeded but isolated->cross sweep failed: {sweep_res}",
1202
+ "approve": approve_res,
1203
+ "tx": tx_res,
1204
+ "sweep": sweep_res,
1205
+ }
1206
+
1207
+ return True, {
1208
+ "status": "ok",
1209
+ "approve": approve_res,
1210
+ "tx": tx_res,
1211
+ "sweep": sweep_res,
1212
+ }
1078
1213
  except Exception as e:
1079
1214
  logger.error(f"Failed to deposit to cross margin: {e}")
1080
1215
  return False, {"error": str(e)}
@@ -1174,6 +1309,302 @@ class BorosAdapter(BaseAdapter):
1174
1309
  logger.error(f"Failed to cash transfer: {e}")
1175
1310
  return False, {"error": str(e)}
1176
1311
 
1312
+ async def bridge_hype_oft_hyperevm_to_arbitrum(
1313
+ self,
1314
+ *,
1315
+ amount_wei: int,
1316
+ max_value_wei: int | None = None,
1317
+ to_address: str | None = None,
1318
+ from_address: str | None = None,
1319
+ dst_eid: int = 30110,
1320
+ min_amount_wei: int = 0,
1321
+ ) -> tuple[bool, dict[str, Any]]:
1322
+ """Bridge native HYPE from HyperEVM -> Arbitrum via LayerZero OFT.
1323
+
1324
+ Notes:
1325
+ - Uses HyperEVM chain id (999) for the transaction.
1326
+ - `amount_wei` is in 1e18 (native HYPE).
1327
+ - The OFT bridge requires `msg.value = amount + nativeFee`.
1328
+ - Amount must be rounded down to `decimalConversionRate()`.
1329
+ - If `max_value_wei` is provided, clamps amount so that (amount + fee) <= max_value_wei.
1330
+ """
1331
+ if amount_wei <= 0:
1332
+ return True, {"status": "no_op", "amount_wei": 0}
1333
+
1334
+ if self.simulation:
1335
+ return True, {
1336
+ "status": "simulated",
1337
+ "amount_wei": int(amount_wei),
1338
+ "dst_eid": int(dst_eid),
1339
+ "to": to_address or self.user_address,
1340
+ }
1341
+
1342
+ if not self.sign_callback:
1343
+ return False, {"error": "sign_callback not configured"}
1344
+
1345
+ sender = from_address or self.user_address
1346
+ recipient = to_address or self.user_address
1347
+ if not sender or not recipient:
1348
+ return False, {"error": "from_address/to_address not configured"}
1349
+
1350
+ try:
1351
+ async with web3_from_chain_id(CHAIN_ID_HYPEREVM) as w3:
1352
+ contract = w3.eth.contract(
1353
+ address=w3.to_checksum_address(HYPE_OFT_ADDRESS),
1354
+ abi=HYPE_OFT_ABI,
1355
+ )
1356
+
1357
+ conversion_rate = int(
1358
+ await contract.functions.decimalConversionRate().call()
1359
+ )
1360
+ if conversion_rate > 0:
1361
+ amount_wei = (int(amount_wei) // conversion_rate) * conversion_rate
1362
+ else:
1363
+ amount_wei = int(amount_wei)
1364
+
1365
+ if amount_wei <= 0:
1366
+ return True, {"status": "no_op", "amount_wei": 0}
1367
+
1368
+ to_bytes32 = self._pad_address_bytes32(recipient)
1369
+
1370
+ def _send_params(amount_ld: int) -> tuple[Any, ...]:
1371
+ return (
1372
+ int(dst_eid),
1373
+ to_bytes32,
1374
+ int(amount_ld),
1375
+ int(min_amount_wei),
1376
+ b"",
1377
+ b"",
1378
+ b"",
1379
+ )
1380
+
1381
+ send_params = _send_params(int(amount_wei))
1382
+ fee = await contract.functions.quoteSend(send_params, False).call()
1383
+ native_fee_wei = int(fee[0])
1384
+ lz_token_fee_wei = int(fee[1])
1385
+
1386
+ if max_value_wei is not None:
1387
+ max_send_amount_wei = max(0, int(max_value_wei) - native_fee_wei)
1388
+ if conversion_rate > 0:
1389
+ max_send_amount_wei = (
1390
+ max_send_amount_wei // conversion_rate
1391
+ ) * conversion_rate
1392
+ if amount_wei > max_send_amount_wei:
1393
+ amount_wei = int(max_send_amount_wei)
1394
+ if amount_wei <= 0:
1395
+ return False, {
1396
+ "error": "Insufficient balance to cover OFT fee",
1397
+ "native_fee_wei": native_fee_wei,
1398
+ "max_value_wei": int(max_value_wei),
1399
+ }
1400
+ send_params = _send_params(int(amount_wei))
1401
+ fee = await contract.functions.quoteSend(
1402
+ send_params, False
1403
+ ).call()
1404
+ native_fee_wei = int(fee[0])
1405
+ lz_token_fee_wei = int(fee[1])
1406
+
1407
+ total_value_wei = int(amount_wei) + int(native_fee_wei)
1408
+ if max_value_wei is not None and total_value_wei > int(max_value_wei):
1409
+ return False, {
1410
+ "error": "Insufficient balance after fee quote",
1411
+ "amount_wei": int(amount_wei),
1412
+ "native_fee_wei": int(native_fee_wei),
1413
+ "total_value_wei": int(total_value_wei),
1414
+ "max_value_wei": int(max_value_wei),
1415
+ }
1416
+
1417
+ tx = await encode_call(
1418
+ target=HYPE_OFT_ADDRESS,
1419
+ abi=HYPE_OFT_ABI,
1420
+ fn_name="send",
1421
+ args=[
1422
+ send_params,
1423
+ (int(native_fee_wei), int(lz_token_fee_wei)),
1424
+ to_checksum_address(sender),
1425
+ ],
1426
+ from_address=sender,
1427
+ chain_id=CHAIN_ID_HYPEREVM,
1428
+ value=int(total_value_wei),
1429
+ )
1430
+ tx_hash = await send_transaction(
1431
+ tx, self.sign_callback, wait_for_receipt=True
1432
+ )
1433
+ return True, {
1434
+ "status": "ok",
1435
+ "tx_hash": tx_hash,
1436
+ "amount_wei": int(amount_wei),
1437
+ "native_fee_wei": int(native_fee_wei),
1438
+ "lz_token_fee_wei": int(lz_token_fee_wei),
1439
+ "total_value_wei": int(total_value_wei),
1440
+ "dst_eid": int(dst_eid),
1441
+ "to": recipient,
1442
+ "from": sender,
1443
+ "layerzeroscan": f"https://layerzeroscan.com/tx/{tx_hash}",
1444
+ }
1445
+ except Exception as exc: # noqa: BLE001
1446
+ return False, {"error": str(exc)}
1447
+
1448
+ async def close_positions_except(
1449
+ self,
1450
+ *,
1451
+ keep_market_id: int,
1452
+ token_id: int = 3,
1453
+ market_ids: list[int] | None = None,
1454
+ best_effort: bool = True,
1455
+ ) -> tuple[bool, dict[str, Any]]:
1456
+ """Close all Boros positions except `keep_market_id` (best-effort by default)."""
1457
+ if self.simulation:
1458
+ return True, {
1459
+ "status": "simulated",
1460
+ "keep_market_id": int(keep_market_id),
1461
+ "markets": market_ids or [],
1462
+ }
1463
+
1464
+ if market_ids is None:
1465
+ ok_pos, positions = await self.get_active_positions()
1466
+ if not ok_pos:
1467
+ return False, {"error": f"Failed to get positions: {positions}"}
1468
+ market_ids = sorted(
1469
+ {
1470
+ int(p.get("marketId"))
1471
+ for p in positions
1472
+ if p.get("marketId") is not None
1473
+ }
1474
+ )
1475
+
1476
+ results: list[dict[str, Any]] = []
1477
+ failures: list[dict[str, Any]] = []
1478
+ for mid in market_ids:
1479
+ if int(mid) == int(keep_market_id):
1480
+ continue
1481
+ ok_close, res_close = await self.close_positions_market(
1482
+ int(mid), token_id=int(token_id)
1483
+ )
1484
+ entry = {"market_id": int(mid), "ok": bool(ok_close), "res": res_close}
1485
+ results.append(entry)
1486
+ if not ok_close:
1487
+ failures.append(entry)
1488
+ if not best_effort:
1489
+ return False, {
1490
+ "error": f"Failed to close position for market {mid}",
1491
+ "results": results,
1492
+ }
1493
+
1494
+ return True, {"status": "ok", "results": results, "failures": failures}
1495
+
1496
+ async def ensure_position_size_yu(
1497
+ self,
1498
+ *,
1499
+ market_id: int,
1500
+ token_id: int,
1501
+ target_size_yu: float,
1502
+ tif: str = "IOC",
1503
+ min_resize_excess_usd: float | None = None,
1504
+ yu_to_usd: float | None = None,
1505
+ ) -> tuple[bool, dict[str, Any]]:
1506
+ """Ensure the Boros position size (YU) for a market.
1507
+
1508
+ - Uses `place_rate_order(... side="short")` to increase the position.
1509
+ - Uses `close_positions_market(..., size_yu_wei=...)` to decrease it.
1510
+ - If `min_resize_excess_usd` is provided, uses `yu_to_usd` to skip small resizes.
1511
+ """
1512
+ if self.simulation:
1513
+ return True, {
1514
+ "status": "simulated",
1515
+ "market_id": int(market_id),
1516
+ "token_id": int(token_id),
1517
+ "target_size_yu": float(target_size_yu),
1518
+ }
1519
+
1520
+ ok_pos, positions = await self.get_active_positions(market_id=int(market_id))
1521
+ if not ok_pos:
1522
+ return False, {"error": f"Failed to get positions: {positions}"}
1523
+
1524
+ if positions:
1525
+ current_size_yu = abs(float(positions[0].get("size", 0) or 0.0))
1526
+ else:
1527
+ current_size_yu = 0.0
1528
+
1529
+ diff_yu = float(target_size_yu) - float(current_size_yu)
1530
+ diff_abs_yu = abs(diff_yu)
1531
+
1532
+ if min_resize_excess_usd is not None:
1533
+ if yu_to_usd is None or yu_to_usd <= 0:
1534
+ return False, {
1535
+ "error": "yu_to_usd required when min_resize_excess_usd is set",
1536
+ "yu_to_usd": yu_to_usd,
1537
+ }
1538
+ diff_usd_equiv = diff_abs_yu * float(yu_to_usd)
1539
+ if diff_usd_equiv < float(min_resize_excess_usd):
1540
+ return True, {
1541
+ "status": "ok",
1542
+ "action": "no_op",
1543
+ "market_id": int(market_id),
1544
+ "token_id": int(token_id),
1545
+ "current_size_yu": float(current_size_yu),
1546
+ "target_size_yu": float(target_size_yu),
1547
+ "diff_yu": float(diff_yu),
1548
+ }
1549
+
1550
+ if diff_abs_yu < 1e-9:
1551
+ return True, {
1552
+ "status": "ok",
1553
+ "action": "no_op",
1554
+ "market_id": int(market_id),
1555
+ "token_id": int(token_id),
1556
+ "current_size_yu": float(current_size_yu),
1557
+ "target_size_yu": float(target_size_yu),
1558
+ "diff_yu": float(diff_yu),
1559
+ }
1560
+
1561
+ size_yu_wei = int(diff_abs_yu * 1e18)
1562
+
1563
+ if diff_yu > 0:
1564
+ ok_open, res_open = await self.place_rate_order(
1565
+ market_id=int(market_id),
1566
+ token_id=int(token_id),
1567
+ size_yu_wei=int(size_yu_wei),
1568
+ side="short",
1569
+ tif=tif,
1570
+ )
1571
+ if not ok_open:
1572
+ return False, {
1573
+ "error": f"Failed to open/increase position: {res_open}",
1574
+ "market_id": int(market_id),
1575
+ }
1576
+ return True, {
1577
+ "status": "ok",
1578
+ "action": "increase_short",
1579
+ "market_id": int(market_id),
1580
+ "token_id": int(token_id),
1581
+ "current_size_yu": float(current_size_yu),
1582
+ "target_size_yu": float(target_size_yu),
1583
+ "diff_yu": float(diff_yu),
1584
+ "tx": res_open,
1585
+ }
1586
+
1587
+ ok_close, res_close = await self.close_positions_market(
1588
+ market_id=int(market_id),
1589
+ token_id=int(token_id),
1590
+ size_yu_wei=int(size_yu_wei),
1591
+ )
1592
+ if not ok_close:
1593
+ return False, {
1594
+ "error": f"Failed to close/decrease position: {res_close}",
1595
+ "market_id": int(market_id),
1596
+ }
1597
+ return True, {
1598
+ "status": "ok",
1599
+ "action": "decrease",
1600
+ "market_id": int(market_id),
1601
+ "token_id": int(token_id),
1602
+ "current_size_yu": float(current_size_yu),
1603
+ "target_size_yu": float(target_size_yu),
1604
+ "diff_yu": float(diff_yu),
1605
+ "tx": res_close,
1606
+ }
1607
+
1177
1608
  async def place_rate_order(
1178
1609
  self,
1179
1610
  *,
@@ -250,10 +250,11 @@ class BorosClient:
250
250
 
251
251
  Args:
252
252
  token_id: Boros token ID (e.g., 3 for USDT).
253
- amount_wei: Amount in scaled wei (1e18).
254
- market_id: Target market ID.
255
- user_address: User wallet address.
256
- account_id: Boros account ID (0 = cross margin).
253
+ amount_wei: Amount in NATIVE token decimals (despite the param name).
254
+ Example: USDT has 6 decimals, so 1 USDT = 1_000_000.
255
+ market_id: Target market ID.
256
+ user_address: User wallet address.
257
+ account_id: Boros account ID (0 = cross margin).
257
258
 
258
259
  Returns:
259
260
  Calldata dictionary with 'to', 'data', 'value' fields.
@@ -283,7 +284,8 @@ class BorosClient:
283
284
 
284
285
  Args:
285
286
  token_id: Boros token ID.
286
- amount_wei: Amount in scaled wei.
287
+ amount_wei: Amount in NATIVE token decimals (despite the param name).
288
+ Example: USDT has 6 decimals, so 1 USDT = 1_000_000.
287
289
  user_address: User wallet address.
288
290
  account_id: Account ID.
289
291