wayfinder-paths 0.1.22__py3-none-any.whl → 0.1.24__py3-none-any.whl

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 (156) hide show
  1. wayfinder_paths/__init__.py +0 -4
  2. wayfinder_paths/adapters/balance_adapter/README.md +0 -1
  3. wayfinder_paths/adapters/balance_adapter/adapter.py +313 -167
  4. wayfinder_paths/adapters/balance_adapter/manifest.yaml +8 -0
  5. wayfinder_paths/adapters/balance_adapter/test_adapter.py +41 -124
  6. wayfinder_paths/adapters/boros_adapter/__init__.py +17 -0
  7. wayfinder_paths/adapters/boros_adapter/adapter.py +1574 -0
  8. wayfinder_paths/adapters/boros_adapter/client.py +476 -0
  9. wayfinder_paths/adapters/boros_adapter/manifest.yaml +10 -0
  10. wayfinder_paths/adapters/boros_adapter/parsers.py +88 -0
  11. wayfinder_paths/adapters/boros_adapter/test_adapter.py +460 -0
  12. wayfinder_paths/adapters/boros_adapter/test_golden.py +156 -0
  13. wayfinder_paths/adapters/boros_adapter/types.py +70 -0
  14. wayfinder_paths/adapters/boros_adapter/utils.py +85 -0
  15. wayfinder_paths/adapters/brap_adapter/README.md +22 -75
  16. wayfinder_paths/adapters/brap_adapter/adapter.py +187 -576
  17. wayfinder_paths/adapters/brap_adapter/examples.json +21 -140
  18. wayfinder_paths/adapters/brap_adapter/manifest.yaml +9 -0
  19. wayfinder_paths/adapters/brap_adapter/test_adapter.py +6 -234
  20. wayfinder_paths/adapters/hyperlend_adapter/adapter.py +180 -92
  21. wayfinder_paths/adapters/hyperlend_adapter/manifest.yaml +9 -0
  22. wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +82 -14
  23. wayfinder_paths/adapters/hyperliquid_adapter/__init__.py +2 -9
  24. wayfinder_paths/adapters/hyperliquid_adapter/adapter.py +586 -61
  25. wayfinder_paths/adapters/hyperliquid_adapter/executor.py +47 -68
  26. wayfinder_paths/adapters/hyperliquid_adapter/manifest.yaml +14 -0
  27. wayfinder_paths/adapters/hyperliquid_adapter/paired_filler.py +2 -3
  28. wayfinder_paths/adapters/hyperliquid_adapter/test_adapter.py +17 -21
  29. wayfinder_paths/adapters/hyperliquid_adapter/test_adapter_live.py +3 -6
  30. wayfinder_paths/adapters/hyperliquid_adapter/test_executor.py +4 -8
  31. wayfinder_paths/adapters/hyperliquid_adapter/test_utils.py +2 -2
  32. wayfinder_paths/adapters/ledger_adapter/README.md +4 -1
  33. wayfinder_paths/adapters/ledger_adapter/adapter.py +3 -3
  34. wayfinder_paths/adapters/ledger_adapter/manifest.yaml +7 -0
  35. wayfinder_paths/adapters/ledger_adapter/test_adapter.py +1 -2
  36. wayfinder_paths/adapters/moonwell_adapter/adapter.py +649 -547
  37. wayfinder_paths/adapters/moonwell_adapter/manifest.yaml +14 -0
  38. wayfinder_paths/adapters/moonwell_adapter/test_adapter.py +160 -239
  39. wayfinder_paths/adapters/multicall_adapter/__init__.py +7 -0
  40. wayfinder_paths/adapters/multicall_adapter/adapter.py +166 -0
  41. wayfinder_paths/adapters/multicall_adapter/manifest.yaml +5 -0
  42. wayfinder_paths/adapters/multicall_adapter/test_adapter.py +97 -0
  43. wayfinder_paths/adapters/pendle_adapter/README.md +102 -0
  44. wayfinder_paths/adapters/pendle_adapter/__init__.py +7 -0
  45. wayfinder_paths/adapters/pendle_adapter/adapter.py +1992 -0
  46. wayfinder_paths/adapters/pendle_adapter/examples.json +11 -0
  47. wayfinder_paths/adapters/pendle_adapter/manifest.yaml +21 -0
  48. wayfinder_paths/adapters/pendle_adapter/test_adapter.py +666 -0
  49. wayfinder_paths/adapters/pool_adapter/manifest.yaml +6 -0
  50. wayfinder_paths/adapters/token_adapter/adapter.py +14 -0
  51. wayfinder_paths/adapters/token_adapter/examples.json +0 -4
  52. wayfinder_paths/adapters/token_adapter/manifest.yaml +7 -0
  53. wayfinder_paths/conftest.py +24 -17
  54. wayfinder_paths/core/__init__.py +0 -3
  55. wayfinder_paths/core/adapters/BaseAdapter.py +0 -25
  56. wayfinder_paths/core/adapters/models.py +17 -7
  57. wayfinder_paths/core/clients/BRAPClient.py +4 -1
  58. wayfinder_paths/core/clients/ClientManager.py +0 -7
  59. wayfinder_paths/core/clients/LedgerClient.py +196 -172
  60. wayfinder_paths/core/clients/TokenClient.py +47 -1
  61. wayfinder_paths/core/clients/WayfinderClient.py +1 -3
  62. wayfinder_paths/core/clients/__init__.py +0 -5
  63. wayfinder_paths/core/clients/protocols.py +21 -35
  64. wayfinder_paths/core/clients/test_ledger_client.py +448 -0
  65. wayfinder_paths/core/config.py +10 -162
  66. wayfinder_paths/core/constants/__init__.py +73 -2
  67. wayfinder_paths/core/constants/base.py +8 -17
  68. wayfinder_paths/core/constants/chains.py +36 -0
  69. wayfinder_paths/core/constants/contracts.py +52 -0
  70. wayfinder_paths/core/constants/erc20_abi.py +0 -1
  71. wayfinder_paths/core/constants/hyperlend_abi.py +0 -4
  72. wayfinder_paths/core/constants/hyperliquid.py +16 -0
  73. wayfinder_paths/core/constants/moonwell_abi.py +0 -15
  74. wayfinder_paths/core/constants/tokens.py +9 -0
  75. wayfinder_paths/core/engine/manifest.py +66 -0
  76. wayfinder_paths/core/strategies/Strategy.py +0 -71
  77. wayfinder_paths/core/strategies/__init__.py +10 -1
  78. wayfinder_paths/core/strategies/opa_loop.py +167 -0
  79. wayfinder_paths/core/utils/evm_helpers.py +5 -15
  80. wayfinder_paths/core/utils/test_transaction.py +289 -0
  81. wayfinder_paths/core/utils/tokens.py +28 -0
  82. wayfinder_paths/core/utils/transaction.py +57 -8
  83. wayfinder_paths/core/utils/web3.py +8 -3
  84. wayfinder_paths/mcp/__init__.py +5 -0
  85. wayfinder_paths/mcp/preview.py +185 -0
  86. wayfinder_paths/mcp/scripting.py +84 -0
  87. wayfinder_paths/mcp/server.py +52 -0
  88. wayfinder_paths/mcp/state/profile_store.py +195 -0
  89. wayfinder_paths/mcp/state/store.py +89 -0
  90. wayfinder_paths/mcp/test_scripting.py +267 -0
  91. wayfinder_paths/mcp/tools/__init__.py +0 -0
  92. wayfinder_paths/mcp/tools/balances.py +290 -0
  93. wayfinder_paths/mcp/tools/discovery.py +158 -0
  94. wayfinder_paths/mcp/tools/execute.py +770 -0
  95. wayfinder_paths/mcp/tools/hyperliquid.py +931 -0
  96. wayfinder_paths/mcp/tools/quotes.py +288 -0
  97. wayfinder_paths/mcp/tools/run_script.py +286 -0
  98. wayfinder_paths/mcp/tools/strategies.py +188 -0
  99. wayfinder_paths/mcp/tools/tokens.py +46 -0
  100. wayfinder_paths/mcp/tools/wallets.py +354 -0
  101. wayfinder_paths/mcp/utils.py +129 -0
  102. wayfinder_paths/policies/enso.py +1 -2
  103. wayfinder_paths/policies/hyper_evm.py +6 -3
  104. wayfinder_paths/policies/hyperlend.py +1 -2
  105. wayfinder_paths/policies/hyperliquid.py +1 -1
  106. wayfinder_paths/policies/lifi.py +18 -0
  107. wayfinder_paths/policies/moonwell.py +12 -7
  108. wayfinder_paths/policies/prjx.py +1 -3
  109. wayfinder_paths/policies/util.py +8 -2
  110. wayfinder_paths/run_strategy.py +97 -300
  111. wayfinder_paths/strategies/basis_trading_strategy/constants.py +3 -1
  112. wayfinder_paths/strategies/basis_trading_strategy/strategy.py +47 -133
  113. wayfinder_paths/strategies/basis_trading_strategy/test_strategy.py +24 -53
  114. wayfinder_paths/strategies/boros_hype_strategy/__init__.py +3 -0
  115. wayfinder_paths/strategies/boros_hype_strategy/boros_ops_mixin.py +450 -0
  116. wayfinder_paths/strategies/boros_hype_strategy/constants.py +255 -0
  117. wayfinder_paths/strategies/boros_hype_strategy/examples.json +37 -0
  118. wayfinder_paths/strategies/boros_hype_strategy/hyperevm_ops_mixin.py +114 -0
  119. wayfinder_paths/strategies/boros_hype_strategy/hyperliquid_ops_mixin.py +642 -0
  120. wayfinder_paths/strategies/boros_hype_strategy/manifest.yaml +36 -0
  121. wayfinder_paths/strategies/boros_hype_strategy/planner.py +460 -0
  122. wayfinder_paths/strategies/boros_hype_strategy/risk_ops_mixin.py +886 -0
  123. wayfinder_paths/strategies/boros_hype_strategy/snapshot_mixin.py +494 -0
  124. wayfinder_paths/strategies/boros_hype_strategy/strategy.py +1194 -0
  125. wayfinder_paths/strategies/boros_hype_strategy/test_planner_golden.py +374 -0
  126. wayfinder_paths/{templates/strategy → strategies/boros_hype_strategy}/test_strategy.py +99 -63
  127. wayfinder_paths/strategies/boros_hype_strategy/types.py +365 -0
  128. wayfinder_paths/strategies/boros_hype_strategy/withdraw_mixin.py +997 -0
  129. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +15 -23
  130. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +27 -62
  131. wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py +84 -58
  132. wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/test_strategy.py +5 -15
  133. wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +69 -164
  134. wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +43 -76
  135. wayfinder_paths/tests/test_mcp_quote_swap.py +165 -0
  136. wayfinder_paths/tests/test_test_coverage.py +1 -4
  137. wayfinder_paths-0.1.24.dist-info/METADATA +378 -0
  138. wayfinder_paths-0.1.24.dist-info/RECORD +185 -0
  139. {wayfinder_paths-0.1.22.dist-info → wayfinder_paths-0.1.24.dist-info}/WHEEL +1 -1
  140. wayfinder_paths/core/clients/WalletClient.py +0 -41
  141. wayfinder_paths/core/engine/StrategyJob.py +0 -110
  142. wayfinder_paths/core/services/test_local_evm_txn.py +0 -145
  143. wayfinder_paths/scripts/create_strategy.py +0 -139
  144. wayfinder_paths/scripts/make_wallets.py +0 -142
  145. wayfinder_paths/templates/adapter/README.md +0 -150
  146. wayfinder_paths/templates/adapter/adapter.py +0 -16
  147. wayfinder_paths/templates/adapter/examples.json +0 -8
  148. wayfinder_paths/templates/adapter/test_adapter.py +0 -30
  149. wayfinder_paths/templates/strategy/README.md +0 -186
  150. wayfinder_paths/templates/strategy/examples.json +0 -11
  151. wayfinder_paths/templates/strategy/strategy.py +0 -35
  152. wayfinder_paths/tests/test_smoke_manifest.py +0 -63
  153. wayfinder_paths-0.1.22.dist-info/METADATA +0 -355
  154. wayfinder_paths-0.1.22.dist-info/RECORD +0 -129
  155. /wayfinder_paths/{scripts → mcp/state}/__init__.py +0 -0
  156. {wayfinder_paths-0.1.22.dist-info → wayfinder_paths-0.1.24.dist-info}/LICENSE +0 -0
@@ -1,16 +0,0 @@
1
- from typing import Any
2
-
3
- from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
4
-
5
-
6
- class MyAdapter(BaseAdapter):
7
- adapter_type: str = "MY_ADAPTER"
8
-
9
- def __init__(self, config: dict[str, Any] | None = None):
10
- super().__init__("my_adapter", config)
11
-
12
- async def connect(self) -> bool:
13
- return True
14
-
15
- async def example_operation(self, **kwargs) -> tuple[bool, str]:
16
- return (True, "example.op executed")
@@ -1,8 +0,0 @@
1
- {
2
- "connect": {},
3
- "example_operation": {
4
- "args": {"foo": "bar"}
5
- }
6
- }
7
-
8
-
@@ -1,30 +0,0 @@
1
- import pytest
2
-
3
- # TODO: Replace MyAdapter with your actual adapter class name
4
- from .adapter import MyAdapter
5
-
6
- # For mocking clients, uncomment when needed:
7
-
8
-
9
- class TestMyAdapter:
10
- @pytest.fixture
11
- def adapter(self):
12
- return MyAdapter(config={})
13
-
14
- @pytest.mark.asyncio
15
- async def test_health_check(self, adapter):
16
- health = await adapter.health_check()
17
- assert isinstance(health, dict)
18
- assert health.get("status") in {"healthy", "unhealthy", "error"}
19
-
20
- @pytest.mark.asyncio
21
- async def test_connect(self, adapter):
22
- ok = await adapter.connect()
23
- assert isinstance(ok, bool)
24
-
25
- def test_capabilities(self, adapter):
26
- assert hasattr(adapter, "adapter_type")
27
-
28
- @pytest.mark.asyncio
29
- async def test_basic_functionality(self, adapter):
30
- assert adapter is not None
@@ -1,186 +0,0 @@
1
- # Strategy Template
2
-
3
- This template provides scaffolding for a new strategy.
4
-
5
- ## Quick Start
6
-
7
- 1. Copy the template:
8
- ```bash
9
- cp -r wayfinder_paths/templates/strategy wayfinder_paths/strategies/my_strategy
10
- ```
11
- Or use the convenience command:
12
- ```bash
13
- just create-strategy "My Strategy Name"
14
- ```
15
- 2. Rename the class in `strategy.py` to match your strategy name.
16
- 3. Implement the required methods (`deposit`, `update`, `exit`, `_status`).
17
- 4. Add tests in `test_strategy.py`.
18
- 5. Fill out `examples.json` with sample CLI invocations.
19
-
20
- ## Directory Structure
21
-
22
- ```
23
- my_strategy/
24
- ├── strategy.py # Strategy implementation
25
- ├── examples.json # Example CLI payloads
26
- ├── test_strategy.py # Pytest tests
27
- └── README.md # Strategy documentation
28
- ```
29
-
30
- ## Required Methods
31
-
32
- ```python
33
- async def deposit(self, main_token_amount: float, gas_token_amount: float) -> StatusTuple:
34
- """Move funds from main wallet into strategy wallet and deploy capital."""
35
-
36
- async def update(self) -> StatusTuple:
37
- """Periodic rebalance/optimization loop."""
38
-
39
- async def exit(self, **kwargs) -> StatusTuple:
40
- """Transfer funds from strategy wallet back to main wallet."""
41
-
42
- async def _status(self) -> StatusDict:
43
- """Return portfolio_value, net_deposit, and strategy_status."""
44
- ```
45
-
46
- ## Optional Methods
47
-
48
- ```python
49
- async def withdraw(self, **kwargs) -> StatusTuple:
50
- """Unwind positions. Default implementation unwinds ledger operations."""
51
-
52
- async def partial_liquidate(self, usd_value: float) -> tuple[bool, LiquidationResult]:
53
- """Liquidate a portion of the position by USD value."""
54
-
55
- async def setup(self) -> None:
56
- """Post-construction initialization."""
57
-
58
- async def health_check(self) -> dict:
59
- """Check strategy and adapter health."""
60
- ```
61
-
62
- ## Strategy Structure
63
-
64
- ```python
65
- from wayfinder_paths.core.strategies.Strategy import StatusDict, StatusTuple, Strategy
66
- from wayfinder_paths.adapters.balance_adapter.adapter import BalanceAdapter
67
-
68
-
69
- class MyStrategy(Strategy):
70
- name = "My Strategy"
71
-
72
- def __init__(self, config: dict | None = None, **kwargs):
73
- super().__init__(config, **kwargs)
74
- self.config = config or {}
75
-
76
- # Initialize and register adapters
77
- balance_adapter = BalanceAdapter(
78
- self.config,
79
- main_wallet_signing_callback=kwargs.get("main_wallet_signing_callback"),
80
- strategy_wallet_signing_callback=kwargs.get("strategy_wallet_signing_callback"),
81
- )
82
- self.register_adapters([balance_adapter])
83
- self.balance_adapter = balance_adapter
84
-
85
- async def deposit(
86
- self, main_token_amount: float = 0.0, gas_token_amount: float = 0.0
87
- ) -> StatusTuple:
88
- if main_token_amount <= 0:
89
- return (False, "Nothing to deposit")
90
-
91
- # Implement deposit logic
92
- return (True, f"Deposited {main_token_amount} tokens")
93
-
94
- async def update(self) -> StatusTuple:
95
- # Implement rebalancing logic
96
- return (True, "Update complete")
97
-
98
- async def exit(self, **kwargs) -> StatusTuple:
99
- # Implement exit logic
100
- return (True, "Exit complete")
101
-
102
- async def _status(self) -> StatusDict:
103
- return {
104
- "portfolio_value": 0.0,
105
- "net_deposit": 0.0,
106
- "strategy_status": {"message": "healthy"},
107
- "gas_available": 0.0,
108
- "gassed_up": True,
109
- }
110
- ```
111
-
112
- ## Testing
113
-
114
- Create `test_strategy.py` using `examples.json`:
115
-
116
- ```python
117
- import pytest
118
- from pathlib import Path
119
- from tests.test_utils import load_strategy_examples
120
- from .strategy import MyStrategy
121
-
122
-
123
- @pytest.mark.asyncio
124
- async def test_smoke():
125
- """Basic strategy lifecycle test."""
126
- examples = load_strategy_examples(Path(__file__))
127
- smoke_example = examples["smoke"]
128
-
129
- s = MyStrategy()
130
-
131
- # Deposit
132
- deposit_params = smoke_example.get("deposit", {})
133
- ok, _ = await s.deposit(**deposit_params)
134
- assert ok
135
-
136
- # Update
137
- ok, _ = await s.update()
138
- assert ok
139
-
140
- # Status
141
- st = await s._status()
142
- assert "portfolio_value" in st
143
- assert "net_deposit" in st
144
- assert "strategy_status" in st
145
- ```
146
-
147
- Run tests:
148
-
149
- ```bash
150
- poetry run pytest wayfinder_paths/strategies/my_strategy/ -v
151
- ```
152
-
153
- ## Running the Strategy
154
-
155
- ```bash
156
- # Install dependencies
157
- poetry install
158
-
159
- # Generate wallets
160
- just create-wallets
161
- just create-wallet my_strategy
162
-
163
- # Configure API key in config.json
164
-
165
- # Check status
166
- poetry run python wayfinder_paths/run_strategy.py my_strategy --action status --config config.json
167
-
168
- # Deposit
169
- poetry run python wayfinder_paths/run_strategy.py my_strategy \
170
- --action deposit --main-token-amount 100 --gas-token-amount 0.01 --config config.json
171
-
172
- # Run update
173
- poetry run python wayfinder_paths/run_strategy.py my_strategy --action update --config config.json
174
-
175
- # Withdraw
176
- poetry run python wayfinder_paths/run_strategy.py my_strategy --action withdraw --config config.json
177
- ```
178
-
179
- ## Best Practices
180
-
181
- - Return `(success: bool, message: str)` tuples from all action methods
182
- - Always populate `portfolio_value`, `net_deposit`, and `strategy_status` in `_status`
183
- - Register adapters via `register_adapters()` in `__init__`
184
- - Use adapters for external operations, not clients directly
185
- - Keep strategy logic clear and well-documented
186
- - Add error handling with informative messages
@@ -1,11 +0,0 @@
1
- {
2
- "deposit": {
3
- "main_token_amount": 100,
4
- "gas_token_amount": 0.001
5
- },
6
- "update": {},
7
- "status": {},
8
- "withdraw": {}
9
- }
10
-
11
-
@@ -1,35 +0,0 @@
1
- from wayfinder_paths.core.strategies.Strategy import StatusDict, StatusTuple, Strategy
2
-
3
-
4
- class MyStrategy(Strategy):
5
- name = "My Strategy"
6
- description = "Short description of what the strategy does."
7
- summary = "One-line summary for discovery."
8
-
9
- def __init__(self):
10
- super().__init__()
11
-
12
- async def setup(self):
13
- return None
14
-
15
- async def deposit(
16
- self, main_token_amount: float, gas_token_amount: float
17
- ) -> StatusTuple:
18
- return (True, "Deposit successful")
19
-
20
- async def withdraw(self, amount: float | None = None) -> StatusTuple:
21
- return await super().withdraw(amount=amount)
22
-
23
- async def update(self) -> StatusTuple:
24
- return (True, "Update successful")
25
-
26
- async def _status(self) -> StatusDict:
27
- return {
28
- "portfolio_value": 0.0,
29
- "net_deposit": 0.0,
30
- "strategy_status": {},
31
- }
32
-
33
- @staticmethod
34
- def policies() -> list[str]:
35
- return []
@@ -1,63 +0,0 @@
1
- import pytest
2
-
3
- from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
4
- from wayfinder_paths.core.strategies.Strategy import StatusDict, StatusTuple, Strategy
5
-
6
-
7
- class FakeAdapter(BaseAdapter):
8
- adapter_type = "FAKE"
9
-
10
- async def connect(self) -> bool:
11
- return True
12
-
13
- async def get_balance(self, asset: str):
14
- return {"asset": asset, "amount": 100}
15
-
16
-
17
- class FakeLedgerAdapter(BaseAdapter):
18
- adapter_type = "LEDGER"
19
-
20
- async def connect(self) -> bool:
21
- return True
22
-
23
- async def record_strategy_snapshot(self, **kwargs):
24
- pass
25
-
26
-
27
- class FakeStrategy(Strategy):
28
- name = "Fake Strategy"
29
-
30
- async def deposit(self, amount: float = 0) -> StatusTuple:
31
- return (True, "deposited")
32
-
33
- async def update(self) -> StatusTuple:
34
- return (True, "updated")
35
-
36
- async def withdraw(self, amount: float = 0) -> StatusTuple:
37
- return (True, "withdrew")
38
-
39
- async def _status(self) -> StatusDict:
40
- return {"total_earned": 0.0, "strategy_status": {"ok": True}}
41
-
42
- @staticmethod
43
- def policy() -> str:
44
- return "wallet.id == 'TEST'"
45
-
46
-
47
- @pytest.mark.asyncio
48
- async def test_smoke_deposit_update_withdraw_status():
49
- s = FakeStrategy(
50
- config={
51
- "strategy_wallet": {"address": "0x1234567890123456789012345678901234567890"}
52
- }
53
- )
54
- s.register_adapters([FakeAdapter("fake")])
55
- s.ledger_adapter = FakeLedgerAdapter("ledger")
56
- ok, msg = await s.deposit(amount=1)
57
- assert ok
58
- ok, msg = await s.update()
59
- assert ok
60
- ok, msg = await s.withdraw(amount=1)
61
- assert ok
62
- st = await s.status()
63
- assert "total_earned" in st