wayfinder-paths 0.1.19__py3-none-any.whl → 0.1.21__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.
- wayfinder_paths/__init__.py +0 -2
- wayfinder_paths/adapters/balance_adapter/README.md +59 -45
- wayfinder_paths/adapters/balance_adapter/adapter.py +1 -22
- wayfinder_paths/adapters/balance_adapter/test_adapter.py +0 -14
- wayfinder_paths/adapters/brap_adapter/README.md +61 -184
- wayfinder_paths/adapters/brap_adapter/__init__.py +0 -4
- wayfinder_paths/adapters/brap_adapter/adapter.py +1 -148
- wayfinder_paths/adapters/brap_adapter/test_adapter.py +0 -15
- wayfinder_paths/adapters/hyperlend_adapter/__init__.py +0 -4
- wayfinder_paths/adapters/hyperlend_adapter/adapter.py +1 -10
- wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +0 -17
- wayfinder_paths/adapters/hyperliquid_adapter/adapter.py +3 -312
- wayfinder_paths/adapters/hyperliquid_adapter/executor.py +1 -71
- wayfinder_paths/adapters/hyperliquid_adapter/paired_filler.py +0 -57
- wayfinder_paths/adapters/hyperliquid_adapter/test_adapter.py +0 -17
- wayfinder_paths/adapters/hyperliquid_adapter/test_adapter_live.py +2 -42
- wayfinder_paths/adapters/hyperliquid_adapter/test_executor.py +1 -9
- wayfinder_paths/adapters/hyperliquid_adapter/test_utils.py +15 -47
- wayfinder_paths/adapters/hyperliquid_adapter/utils.py +0 -7
- wayfinder_paths/adapters/ledger_adapter/README.md +54 -74
- wayfinder_paths/adapters/ledger_adapter/__init__.py +0 -4
- wayfinder_paths/adapters/ledger_adapter/adapter.py +0 -106
- wayfinder_paths/adapters/ledger_adapter/test_adapter.py +0 -12
- wayfinder_paths/adapters/moonwell_adapter/README.md +67 -106
- wayfinder_paths/adapters/moonwell_adapter/__init__.py +0 -4
- wayfinder_paths/adapters/moonwell_adapter/adapter.py +10 -122
- wayfinder_paths/adapters/moonwell_adapter/test_adapter.py +84 -83
- wayfinder_paths/adapters/pool_adapter/README.md +30 -51
- wayfinder_paths/adapters/pool_adapter/__init__.py +0 -4
- wayfinder_paths/adapters/pool_adapter/adapter.py +0 -19
- wayfinder_paths/adapters/pool_adapter/test_adapter.py +0 -8
- wayfinder_paths/adapters/token_adapter/README.md +41 -49
- wayfinder_paths/adapters/token_adapter/adapter.py +0 -32
- wayfinder_paths/adapters/token_adapter/test_adapter.py +1 -12
- wayfinder_paths/conftest.py +0 -8
- wayfinder_paths/core/__init__.py +0 -2
- wayfinder_paths/core/adapters/BaseAdapter.py +0 -22
- wayfinder_paths/core/adapters/__init__.py +0 -5
- wayfinder_paths/core/adapters/models.py +0 -5
- wayfinder_paths/core/analytics/__init__.py +0 -2
- wayfinder_paths/core/analytics/bootstrap.py +0 -16
- wayfinder_paths/core/analytics/stats.py +0 -7
- wayfinder_paths/core/analytics/test_analytics.py +5 -34
- wayfinder_paths/core/clients/BRAPClient.py +0 -35
- wayfinder_paths/core/clients/ClientManager.py +0 -51
- wayfinder_paths/core/clients/HyperlendClient.py +0 -77
- wayfinder_paths/core/clients/LedgerClient.py +2 -122
- wayfinder_paths/core/clients/PoolClient.py +0 -2
- wayfinder_paths/core/clients/TokenClient.py +0 -39
- wayfinder_paths/core/clients/WalletClient.py +0 -15
- wayfinder_paths/core/clients/WayfinderClient.py +0 -24
- wayfinder_paths/core/clients/__init__.py +0 -4
- wayfinder_paths/core/clients/protocols.py +25 -98
- wayfinder_paths/core/config.py +0 -24
- wayfinder_paths/core/constants/__init__.py +0 -7
- wayfinder_paths/core/constants/base.py +2 -9
- wayfinder_paths/core/constants/erc20_abi.py +0 -5
- wayfinder_paths/core/constants/hyperlend_abi.py +0 -7
- wayfinder_paths/core/constants/moonwell_abi.py +0 -35
- wayfinder_paths/core/engine/StrategyJob.py +0 -32
- wayfinder_paths/core/strategies/Strategy.py +0 -99
- wayfinder_paths/core/strategies/__init__.py +0 -2
- wayfinder_paths/core/utils/__init__.py +0 -1
- wayfinder_paths/core/utils/evm_helpers.py +0 -50
- wayfinder_paths/core/utils/{erc20_service.py → tokens.py} +25 -21
- wayfinder_paths/core/utils/transaction.py +0 -1
- wayfinder_paths/run_strategy.py +0 -46
- wayfinder_paths/scripts/create_strategy.py +0 -17
- wayfinder_paths/scripts/make_wallets.py +1 -4
- wayfinder_paths/strategies/basis_trading_strategy/README.md +71 -163
- wayfinder_paths/strategies/basis_trading_strategy/snapshot_mixin.py +0 -24
- wayfinder_paths/strategies/basis_trading_strategy/strategy.py +36 -400
- wayfinder_paths/strategies/basis_trading_strategy/test_strategy.py +15 -64
- wayfinder_paths/strategies/basis_trading_strategy/types.py +0 -4
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/README.md +65 -56
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +4 -27
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +0 -10
- wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/README.md +71 -72
- wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py +23 -227
- wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/test_strategy.py +120 -113
- wayfinder_paths/strategies/stablecoin_yield_strategy/README.md +64 -59
- wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +4 -44
- wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +2 -35
- wayfinder_paths/templates/adapter/README.md +107 -46
- wayfinder_paths/templates/adapter/adapter.py +0 -9
- wayfinder_paths/templates/adapter/test_adapter.py +0 -19
- wayfinder_paths/templates/strategy/README.md +113 -59
- wayfinder_paths/templates/strategy/strategy.py +0 -22
- wayfinder_paths/templates/strategy/test_strategy.py +0 -28
- wayfinder_paths/tests/test_test_coverage.py +2 -12
- wayfinder_paths/tests/test_utils.py +1 -31
- wayfinder_paths-0.1.21.dist-info/METADATA +355 -0
- wayfinder_paths-0.1.21.dist-info/RECORD +129 -0
- {wayfinder_paths-0.1.19.dist-info → wayfinder_paths-0.1.21.dist-info}/WHEEL +1 -1
- wayfinder_paths/core/adapters/base.py +0 -5
- wayfinder_paths-0.1.19.dist-info/METADATA +0 -592
- wayfinder_paths-0.1.19.dist-info/RECORD +0 -130
- {wayfinder_paths-0.1.19.dist-info → wayfinder_paths-0.1.21.dist-info}/LICENSE +0 -0
|
@@ -1,592 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.3
|
|
2
|
-
Name: wayfinder-paths
|
|
3
|
-
Version: 0.1.19
|
|
4
|
-
Summary: Wayfinder Path: strategies and adapters
|
|
5
|
-
Author: Wayfinder
|
|
6
|
-
Author-email: dev@wayfinder.ai
|
|
7
|
-
Requires-Python: >=3.12,<4.0
|
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
|
9
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
-
Requires-Dist: aiohttp (>=3.13.0,<4.0.0)
|
|
12
|
-
Requires-Dist: eth-account (>=0.13.7,<0.14.0)
|
|
13
|
-
Requires-Dist: httpx (>=0.28.1,<0.29.0)
|
|
14
|
-
Requires-Dist: hyperliquid-python-sdk (>=0.21.0,<0.22.0)
|
|
15
|
-
Requires-Dist: loguru (>=0.7.3,<0.8.0)
|
|
16
|
-
Requires-Dist: numpy (>=1.26.0,<2.0.0)
|
|
17
|
-
Requires-Dist: pandas (>=2.2.0,<3.0.0)
|
|
18
|
-
Requires-Dist: pydantic (>=2.11.9,<3.0.0)
|
|
19
|
-
Requires-Dist: pyyaml (>=6.0.1,<7.0.0)
|
|
20
|
-
Requires-Dist: web3 (>=7.13.0,<8.0.0)
|
|
21
|
-
Description-Content-Type: text/markdown
|
|
22
|
-
|
|
23
|
-
# 🔐 Wayfinder Paths
|
|
24
|
-
|
|
25
|
-
[](https://www.python.org/downloads/)
|
|
26
|
-
[](https://www.docker.com/)
|
|
27
|
-
[](https://discord.gg/fUVwGMXjm3)
|
|
28
|
-
|
|
29
|
-
Open-source platform for community-contributed crypto trading strategies and adapters. Build, test, and deploy automated trading strategies with direct wallet integration.
|
|
30
|
-
|
|
31
|
-
## 🚀 Quick Start
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
# Clone the repository
|
|
35
|
-
git clone https://github.com/wayfinder-ai/wayfinder-paths.git
|
|
36
|
-
cd wayfinder-paths
|
|
37
|
-
|
|
38
|
-
# Install Poetry (if not already installed)
|
|
39
|
-
curl -sSL https://install.python-poetry.org | python3 -
|
|
40
|
-
|
|
41
|
-
# Install dependencies
|
|
42
|
-
poetry install
|
|
43
|
-
|
|
44
|
-
# ⚠️ Generate test wallets FIRST (required!)
|
|
45
|
-
# This creates config.json with a main wallet for local testing
|
|
46
|
-
just create-wallets
|
|
47
|
-
# Or manually: poetry run python wayfinder_paths/scripts/make_wallets.py -n 1
|
|
48
|
-
|
|
49
|
-
# To test a specific strategy
|
|
50
|
-
just create-wallet stablecoin_yield_strategy
|
|
51
|
-
|
|
52
|
-
# Copy and configure
|
|
53
|
-
cp wayfinder_paths/config.example.json config.json
|
|
54
|
-
# Edit config.json with your Wayfinder credentials
|
|
55
|
-
|
|
56
|
-
# Run a strategy locally (one-shot status check)
|
|
57
|
-
poetry run python wayfinder_paths/run_strategy.py stablecoin_yield_strategy --action status --config config.json
|
|
58
|
-
|
|
59
|
-
# Run continuously (production mode)
|
|
60
|
-
poetry run python wayfinder_paths/run_strategy.py stablecoin_yield_strategy --config config.json
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
## 📁 Repository Structure
|
|
64
|
-
|
|
65
|
-
```
|
|
66
|
-
wayfinder_paths/
|
|
67
|
-
├── wayfinder_paths/ # Main package directory
|
|
68
|
-
│ ├── core/ # Core engine (maintained by team)
|
|
69
|
-
│ │ ├── clients/ # API client managers
|
|
70
|
-
│ │ ├── adapters/ # Base adapter interfaces
|
|
71
|
-
│ │ ├── engine/ # Trading engine & StrategyJob
|
|
72
|
-
│ │ ├── strategies/ # Base strategy classes
|
|
73
|
-
│ │ └── config.py # Configuration system
|
|
74
|
-
│ ├── adapters/ # Your exchange/protocol integrations (community contributions)
|
|
75
|
-
│ │ ├── balance_adapter/
|
|
76
|
-
│ │ │ ├── adapter.py # Adapter implementation
|
|
77
|
-
│ │ │ ├── examples.json # Example inputs for smoke
|
|
78
|
-
│ │ │ ├── README.md # Local notes
|
|
79
|
-
│ │ │ └── test_adapter.py # Local smoke test
|
|
80
|
-
│ │ ├── brap_adapter/
|
|
81
|
-
│ │ └── ...
|
|
82
|
-
│ ├── strategies/ # Your trading strategies (community contributions)
|
|
83
|
-
│ │ ├── stablecoin_yield_strategy/
|
|
84
|
-
│ │ │ ├── strategy.py # Strategy implementation
|
|
85
|
-
│ │ │ ├── examples.json # Example inputs
|
|
86
|
-
│ │ │ ├── README.md # Local notes
|
|
87
|
-
│ │ │ └── test_strategy.py # Local smoke test
|
|
88
|
-
│ │ └── ...
|
|
89
|
-
│ ├── tests/ # Test suite
|
|
90
|
-
│ ├── CONFIG_GUIDE.md # Configuration documentation
|
|
91
|
-
│ ├── config.example.json # Example configuration
|
|
92
|
-
│ ├── scripts/ # Utility scripts
|
|
93
|
-
│ └── run_strategy.py # Strategy runner script
|
|
94
|
-
├── config.json # Your local config with credentials and wallets
|
|
95
|
-
├── pyproject.toml # Poetry configuration
|
|
96
|
-
└── README.md # This file
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
## 🤝 Contributing
|
|
100
|
-
|
|
101
|
-
We welcome contributions! This is an open-source project where community members can contribute adapters and strategies.
|
|
102
|
-
|
|
103
|
-
### Quick Contribution Guide
|
|
104
|
-
|
|
105
|
-
1. **Fork the repository** and clone your fork
|
|
106
|
-
2. **Create a feature branch**: `git checkout -b feature/my-strategy`
|
|
107
|
-
3. **Copy a template** to get started:
|
|
108
|
-
- **For adapters**: Copy `wayfinder_paths/templates/adapter/` to `wayfinder_paths/adapters/my_adapter/`
|
|
109
|
-
- **For strategies**: Copy `wayfinder_paths/templates/strategy/` to `wayfinder_paths/strategies/my_strategy/`
|
|
110
|
-
4. **Customize** the template (rename classes, implement methods)
|
|
111
|
-
5. **Test your code** thoroughly using the provided test framework
|
|
112
|
-
6. **Submit a Pull Request** with a clear description of your changes
|
|
113
|
-
|
|
114
|
-
### What You Can Contribute
|
|
115
|
-
|
|
116
|
-
- **Adapters**: Exchange/protocol integrations (e.g., Uniswap, Aave, Compound)
|
|
117
|
-
- **Strategies**: Trading algorithms and yield optimization strategies
|
|
118
|
-
- **Improvements**: Bug fixes, documentation, or core system enhancements
|
|
119
|
-
|
|
120
|
-
### Contributor Guidelines
|
|
121
|
-
|
|
122
|
-
#### For Adapters
|
|
123
|
-
|
|
124
|
-
- **Start from the template**: Copy `wayfinder_paths/templates/adapter/` as a starting point
|
|
125
|
-
- Extend `BaseAdapter` from `wayfinder_paths/core/adapters/BaseAdapter.py`
|
|
126
|
-
- Implement your adapter methods
|
|
127
|
-
- Add comprehensive tests in `test_adapter.py`
|
|
128
|
-
- Include usage examples in `examples.json`
|
|
129
|
-
- Document your adapter in `README.md`
|
|
130
|
-
|
|
131
|
-
#### For Strategies
|
|
132
|
-
|
|
133
|
-
- **Start from the template**: Use `just create-strategy "Strategy Name"` to create a new strategy with its own wallet, or copy `wayfinder_paths/templates/strategy/` manually
|
|
134
|
-
- Extend `Strategy` from `wayfinder_paths/core/strategies/Strategy.py`
|
|
135
|
-
- Implement required methods: `deposit()`, `update()`, `status()`, `withdraw()`
|
|
136
|
-
- Include test cases in `test_strategy.py`
|
|
137
|
-
- Add example configurations in `examples.json`
|
|
138
|
-
|
|
139
|
-
#### General Guidelines
|
|
140
|
-
|
|
141
|
-
- **Code Quality**: Follow existing patterns and use type hints
|
|
142
|
-
- **Testing**: See [TESTING.md](TESTING.md) - minimum: smoke test for strategies, basic tests for adapters
|
|
143
|
-
- **Documentation**: Update README files and add docstrings
|
|
144
|
-
- **Security**: Never hardcode API keys or private keys
|
|
145
|
-
- **Architecture**: Use adapters for external integrations, not direct API calls
|
|
146
|
-
|
|
147
|
-
### Development Setup
|
|
148
|
-
|
|
149
|
-
```bash
|
|
150
|
-
# 1. Fork and clone the repository
|
|
151
|
-
git clone https://github.com/yourusername/wayfinder-paths.git
|
|
152
|
-
cd wayfinder-paths
|
|
153
|
-
|
|
154
|
-
# 2. Install dependencies
|
|
155
|
-
poetry install
|
|
156
|
-
|
|
157
|
-
# 3. Generate test wallets (required before testing!)
|
|
158
|
-
# Creates a main wallet (or use 'just create-strategy' which auto-creates wallets)
|
|
159
|
-
just create-wallets
|
|
160
|
-
# Or manually: poetry run python wayfinder_paths/scripts/make_wallets.py -n 1
|
|
161
|
-
|
|
162
|
-
# 4. Create a new strategy (recommended - automatically creates wallet)
|
|
163
|
-
just create-strategy "My Strategy Name"
|
|
164
|
-
|
|
165
|
-
# Or manually copy a template:
|
|
166
|
-
# For adapters:
|
|
167
|
-
cp -r wayfinder_paths/templates/adapter wayfinder_paths/adapters/my_adapter
|
|
168
|
-
# For strategies:
|
|
169
|
-
cp -r wayfinder_paths/templates/strategy wayfinder_paths/strategies/my_strategy
|
|
170
|
-
|
|
171
|
-
# 5. Customize the template (see template README.md files for details)
|
|
172
|
-
|
|
173
|
-
# 6. Run tests
|
|
174
|
-
poetry run pytest -k smoke -v
|
|
175
|
-
|
|
176
|
-
# Or test your specific contribution
|
|
177
|
-
poetry run pytest wayfinder_paths/strategies/your_strategy/ -v
|
|
178
|
-
poetry run pytest wayfinder_paths/adapters/your_adapter/ -v
|
|
179
|
-
|
|
180
|
-
# 8. Test your contribution locally
|
|
181
|
-
poetry run python wayfinder_paths/run_strategy.py your_strategy --action status
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
### Getting Help
|
|
185
|
-
|
|
186
|
-
- 📖 Check existing adapters/strategies for examples
|
|
187
|
-
- 🐛 Open an issue for bugs or feature requests
|
|
188
|
-
|
|
189
|
-
## 🏗️ Architecture
|
|
190
|
-
|
|
191
|
-
### Client System
|
|
192
|
-
|
|
193
|
-
The platform uses a unified client system for all API interactions. Clients are thin wrappers that handle low-level API calls, authentication, and network communication. **Strategies should not call clients directly** - use adapters instead for domain-specific operations.
|
|
194
|
-
|
|
195
|
-
### Clients vs Adapters
|
|
196
|
-
|
|
197
|
-
- **Clients**: Low-level, reusable service wrappers that talk to networks and external APIs. They handle auth, headers, retries, and response parsing, and expose generic capabilities (e.g., token info, tx building). Examples: `TokenClient`, `WalletClient`.
|
|
198
|
-
- **Adapters**: Strategy-facing integrations for a specific exchange/protocol. They compose one or more clients to implement a set of capabilities (e.g., `supply`, `borrow`, `place_order`). Adapters encapsulate protocol-specific semantics and raise `NotImplementedError` for unsupported ops.
|
|
199
|
-
|
|
200
|
-
Recommended usage:
|
|
201
|
-
|
|
202
|
-
- Strategies call adapters (not clients directly) for domain actions.
|
|
203
|
-
- Add or change a client when you need a new low-level capability shared across adapters.
|
|
204
|
-
- Add or change an adapter when integrating a new protocol/exchange or changing protocol-specific behavior.
|
|
205
|
-
|
|
206
|
-
Data flow: `Strategy` → `Adapter` → `Client(s)` → network/API.
|
|
207
|
-
|
|
208
|
-
### Configuration
|
|
209
|
-
|
|
210
|
-
Configuration is split between:
|
|
211
|
-
|
|
212
|
-
- **User Config**: Your credentials and preferences
|
|
213
|
-
- **System Config**: Platform settings
|
|
214
|
-
- **Strategy Config**: Strategy-specific parameters
|
|
215
|
-
|
|
216
|
-
See [CONFIG_GUIDE.md](wayfinder_paths/CONFIG_GUIDE.md) for details.
|
|
217
|
-
|
|
218
|
-
### Authentication
|
|
219
|
-
|
|
220
|
-
Wayfinder Paths uses API key authentication via the `X-API-KEY` header.
|
|
221
|
-
|
|
222
|
-
**Add API key to config.json:**
|
|
223
|
-
|
|
224
|
-
```json
|
|
225
|
-
{
|
|
226
|
-
"system": {
|
|
227
|
-
"api_key": "sk_live_abc123...",
|
|
228
|
-
"api_base_url": "https://wayfinder.ai/api/v1",
|
|
229
|
-
"wallets_path": "wallets.json"
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
**How It Works:**
|
|
235
|
-
|
|
236
|
-
- API key is automatically loaded from `system.api_key` in config.json
|
|
237
|
-
- The API key is sent as the `X-API-KEY` header on all API requests
|
|
238
|
-
- All clients automatically include the API key header
|
|
239
|
-
- No need to pass API keys explicitly to strategies or clients
|
|
240
|
-
|
|
241
|
-
See [CONFIG_GUIDE.md](wayfinder_paths/CONFIG_GUIDE.md) for detailed configuration documentation.
|
|
242
|
-
|
|
243
|
-
## 🔌 Creating Adapters
|
|
244
|
-
|
|
245
|
-
Adapters connect to exchanges and DeFi protocols using the client system.
|
|
246
|
-
|
|
247
|
-
```python
|
|
248
|
-
# wayfinder_paths/adapters/my_adapter/adapter.py
|
|
249
|
-
from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
|
|
250
|
-
from wayfinder_paths.core.clients.PoolClient import PoolClient
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
class MyAdapter(BaseAdapter):
|
|
254
|
-
"""Thin wrapper around PoolClient that exposes pool metadata to strategies."""
|
|
255
|
-
|
|
256
|
-
adapter_type = "POOL"
|
|
257
|
-
|
|
258
|
-
def __init__(self, config: dict | None = None):
|
|
259
|
-
super().__init__("my_adapter", config)
|
|
260
|
-
self.pool_client = PoolClient()
|
|
261
|
-
|
|
262
|
-
async def connect(self) -> bool:
|
|
263
|
-
"""No-op for read-only adapters, but kept for interface consistency."""
|
|
264
|
-
return True
|
|
265
|
-
|
|
266
|
-
async def get_pools(self, pool_ids: list[str]):
|
|
267
|
-
data = await self.pool_client.get_pools_by_ids(
|
|
268
|
-
pool_ids=pool_ids
|
|
269
|
-
)
|
|
270
|
-
return (True, data)
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
## 📈 Building Strategies
|
|
274
|
-
|
|
275
|
-
Strategies implement trading logic using adapters and the unified client system.
|
|
276
|
-
|
|
277
|
-
```python
|
|
278
|
-
# wayfinder_paths/strategies/my_strategy/strategy.py
|
|
279
|
-
from wayfinder_paths.core.strategies.Strategy import StatusDict, StatusTuple, Strategy
|
|
280
|
-
from wayfinder_paths.adapters.balance_adapter.adapter import BalanceAdapter
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
class MyStrategy(Strategy):
|
|
284
|
-
name = "Demo Strategy"
|
|
285
|
-
|
|
286
|
-
def __init__(
|
|
287
|
-
self,
|
|
288
|
-
config: dict | None = None,
|
|
289
|
-
*,
|
|
290
|
-
api_key: str | None = None, # Optional: API key for service account auth
|
|
291
|
-
):
|
|
292
|
-
super().__init__(api_key=api_key) # Pass to base class for auto-discovery
|
|
293
|
-
self.config = config or {}
|
|
294
|
-
# Adapters automatically discover API key from constructor or config.json
|
|
295
|
-
balance_adapter = BalanceAdapter(self.config)
|
|
296
|
-
self.register_adapters([balance_adapter])
|
|
297
|
-
self.balance_adapter = balance_adapter
|
|
298
|
-
|
|
299
|
-
async def deposit(
|
|
300
|
-
self, main_token_amount: float = 0.0, gas_token_amount: float = 0.0
|
|
301
|
-
) -> StatusTuple:
|
|
302
|
-
"""Move funds from main wallet into the strategy wallet."""
|
|
303
|
-
if main_token_amount <= 0:
|
|
304
|
-
return (False, "Nothing to deposit")
|
|
305
|
-
|
|
306
|
-
success, _ = await self.balance_adapter.get_balance(
|
|
307
|
-
query=self.config.get("token_id"),
|
|
308
|
-
wallet_address=self.config.get("main_wallet", {}).get("address"),
|
|
309
|
-
)
|
|
310
|
-
if not success:
|
|
311
|
-
return (False, "Unable to fetch balances")
|
|
312
|
-
|
|
313
|
-
self.last_deposit = main_token_amount
|
|
314
|
-
return (True, f"Deposited {main_token_amount} tokens")
|
|
315
|
-
|
|
316
|
-
async def update(self) -> StatusTuple:
|
|
317
|
-
"""Periodic strategy update"""
|
|
318
|
-
return (True, "No-op update")
|
|
319
|
-
|
|
320
|
-
async def _status(self) -> StatusDict:
|
|
321
|
-
"""Report balances back to the runner"""
|
|
322
|
-
success, balance = await self.balance_adapter.get_balance(
|
|
323
|
-
query=self.config.get("token_id"),
|
|
324
|
-
wallet_address=self.config.get("strategy_wallet", {}).get("address"),
|
|
325
|
-
)
|
|
326
|
-
return {
|
|
327
|
-
"portfolio_value": float(balance or 0),
|
|
328
|
-
"net_deposit": float(getattr(self, "last_deposit", 0.0)),
|
|
329
|
-
"strategy_status": {"message": "healthy" if success else "unknown"},
|
|
330
|
-
}
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
### Built-in Strategies
|
|
334
|
-
|
|
335
|
-
The following strategies are available and can be run using the CLI:
|
|
336
|
-
|
|
337
|
-
| Strategy | Description | Chain |
|
|
338
|
-
| --------------------------------- | --------------------------- | -------- |
|
|
339
|
-
| `basis_trading_strategy` | Delta-neutral basis trading | - |
|
|
340
|
-
| `hyperlend_stable_yield_strategy` | Stable yield on HyperLend | HyperEVM |
|
|
341
|
-
| `moonwell_wsteth_loop_strategy` | Leveraged wstETH yield loop | Base |
|
|
342
|
-
|
|
343
|
-
#### Running Strategies
|
|
344
|
-
|
|
345
|
-
### Built-in adapters
|
|
346
|
-
|
|
347
|
-
- **BALANCE (BalanceAdapter)**: wraps `WalletClient`/`TokenClient` to read wallet, token, and pool balances and now orchestrates transfers between the main/strategy wallets with ledger bookkeeping. Requires a `Web3Service` so it can share the same wallet provider as the strategy.
|
|
348
|
-
- **POOL (PoolAdapter)**: composes `PoolClient` to fetch pools, llama analytics, combined reports, high-yield searches, and search helpers.
|
|
349
|
-
- **BRAP (BRAPAdapter)**: integrates the cross-chain quote service for swaps/bridges, including fee breakdowns, route comparisons, validation helpers, and swap execution/ledger recording when provided a `Web3Service`.
|
|
350
|
-
- **LEDGER (LedgerAdapter)**: records deposits, withdrawals, custom operations, and cashflows via `LedgerClient`, and can read strategy transaction summaries.
|
|
351
|
-
- **TOKEN (TokenAdapter)**: lightweight wrapper around `TokenClient` for token metadata, live price snapshots, and gas token lookups.
|
|
352
|
-
- **HYPERLEND (HyperlendAdapter)**: connects to `HyperlendClient` for lending/supply caps inside the HyperLend strategy.
|
|
353
|
-
- **MOONWELL (MoonwellAdapter)**: interfaces with Moonwell protocol on Base for lending, borrowing, collateral management, and WELL rewards.
|
|
354
|
-
|
|
355
|
-
Strategies register the adapters they need in their `__init__` method. Adapters implement their specific capabilities and raise `NotImplementedError` for unsupported operations.
|
|
356
|
-
|
|
357
|
-
## 🧪 Testing
|
|
358
|
-
|
|
359
|
-
**📖 For detailed testing guidance, see [TESTING.md](TESTING.md)**
|
|
360
|
-
|
|
361
|
-
### Quick Start
|
|
362
|
-
|
|
363
|
-
```bash
|
|
364
|
-
# 1. Generate test wallets (required!)
|
|
365
|
-
# Creates a main wallet (or use 'just create-strategy' which auto-creates wallets)
|
|
366
|
-
just create-wallets
|
|
367
|
-
# Or manually: poetry run python wayfinder_paths/scripts/make_wallets.py -n 1
|
|
368
|
-
|
|
369
|
-
# 2. Run smoke tests
|
|
370
|
-
poetry run pytest -k smoke -v
|
|
371
|
-
|
|
372
|
-
# 3. Test your specific contribution
|
|
373
|
-
poetry run pytest wayfinder_paths/strategies/my_strategy/ -v # Strategy
|
|
374
|
-
poetry run pytest wayfinder_paths/adapters/my_adapter/ -v # Adapter
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
### Testing Your Contribution
|
|
378
|
-
|
|
379
|
-
**Strategies**: Add a simple smoke test in `test_strategy.py` that exercises deposit → update → status → withdraw.
|
|
380
|
-
|
|
381
|
-
**Adapters**: Add basic functionality tests with mocked dependencies. Use `examples.json` to drive your tests.
|
|
382
|
-
|
|
383
|
-
See [TESTING.md](TESTING.md) for complete examples and best practices.
|
|
384
|
-
|
|
385
|
-
## 💻 Local Development
|
|
386
|
-
|
|
387
|
-
### Setup
|
|
388
|
-
|
|
389
|
-
```bash
|
|
390
|
-
# Clone repo
|
|
391
|
-
git clone https://github.com/wayfinder-ai/wayfinder-paths.git
|
|
392
|
-
cd wayfinder-paths
|
|
393
|
-
|
|
394
|
-
# Install dependencies
|
|
395
|
-
poetry install
|
|
396
|
-
|
|
397
|
-
# Generate test wallets (essential!)
|
|
398
|
-
# Creates a main wallet (or use 'just create-strategy' which auto-creates wallets)
|
|
399
|
-
just create-wallets
|
|
400
|
-
# Or manually: poetry run python wayfinder_paths/scripts/make_wallets.py -n 1
|
|
401
|
-
|
|
402
|
-
# Copy and configure
|
|
403
|
-
cp wayfinder_paths/config.example.json config.json
|
|
404
|
-
# Edit config.json with your Wayfinder credentials
|
|
405
|
-
|
|
406
|
-
# Run a strategy (status check)
|
|
407
|
-
poetry run python wayfinder_paths/run_strategy.py stablecoin_yield_strategy --action status --config config.json
|
|
408
|
-
|
|
409
|
-
# Run with custom config
|
|
410
|
-
poetry run python wayfinder_paths/run_strategy.py stablecoin_yield_strategy --config my_config.json
|
|
411
|
-
|
|
412
|
-
# Run continuously with debug output
|
|
413
|
-
poetry run python wayfinder_paths/run_strategy.py stablecoin_yield_strategy --debug --config config.json
|
|
414
|
-
```
|
|
415
|
-
|
|
416
|
-
### Wallet Generation for Testing
|
|
417
|
-
|
|
418
|
-
**Before running any strategies, generate test wallets.** This creates `config.json` in the repository root with throwaway wallets for local testing:
|
|
419
|
-
|
|
420
|
-
```bash
|
|
421
|
-
# Essential: Create main wallet for testing
|
|
422
|
-
just create-wallets
|
|
423
|
-
# Or manually: poetry run python wayfinder_paths/scripts/make_wallets.py -n 1
|
|
424
|
-
```
|
|
425
|
-
|
|
426
|
-
This creates:
|
|
427
|
-
|
|
428
|
-
- `main` wallet - your main wallet for testing (labeled "main" in config.json)
|
|
429
|
-
- `config.json` - wallet addresses and private keys for local testing
|
|
430
|
-
|
|
431
|
-
**Note:** Strategy-specific wallets are automatically created when you use `just create-strategy "Strategy Name"`. For manual creation, use `just create-wallet "strategy_name"` or `poetry run python wayfinder_paths/scripts/make_wallets.py --label "strategy_name"`.
|
|
432
|
-
|
|
433
|
-
**Important:** These wallets are for testing only. Never use them with real funds or on mainnet.
|
|
434
|
-
|
|
435
|
-
**Per-Strategy Wallets:** Each strategy should have its own dedicated wallet. When you create a new strategy using `just create-strategy`, a wallet is automatically generated with a label matching the strategy directory name. The system automatically uses this wallet when running the strategy. See [CONFIG_GUIDE.md](wayfinder_paths/CONFIG_GUIDE.md) for details.
|
|
436
|
-
|
|
437
|
-
Additional options:
|
|
438
|
-
|
|
439
|
-
```bash
|
|
440
|
-
# Add 3 extra wallets for multi-account testing
|
|
441
|
-
poetry run python wayfinder_paths/scripts/make_wallets.py -n 3
|
|
442
|
-
|
|
443
|
-
# Create a wallet with a specific label (e.g., for a strategy)
|
|
444
|
-
poetry run python wayfinder_paths/scripts/make_wallets.py --label "my_strategy_name"
|
|
445
|
-
|
|
446
|
-
# Generate keystore files (for geth/web3 compatibility)
|
|
447
|
-
poetry run python wayfinder_paths/scripts/make_wallets.py -n 1 --keystore-password "my-password"
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
### Configuration
|
|
451
|
-
|
|
452
|
-
See [CONFIG_GUIDE.md](wayfinder_paths/CONFIG_GUIDE.md) for detailed configuration documentation.
|
|
453
|
-
|
|
454
|
-
#### Setup Configuration
|
|
455
|
-
|
|
456
|
-
```bash
|
|
457
|
-
# Copy example config
|
|
458
|
-
cp wayfinder_paths/config.example.json config.json
|
|
459
|
-
|
|
460
|
-
# Edit config.json with your settings
|
|
461
|
-
# Required fields:
|
|
462
|
-
# - user.username: Your Wayfinder username
|
|
463
|
-
# - user.password: Your Wayfinder password
|
|
464
|
-
# - OR user.refresh_token: Your refresh token
|
|
465
|
-
# - system.wallets_path: Path to config.json (default: "config.json")
|
|
466
|
-
#
|
|
467
|
-
# Wallet addresses are auto-loaded from config.json by default.
|
|
468
|
-
# Then run with:
|
|
469
|
-
poetry run python wayfinder_paths/run_strategy.py stablecoin_yield_strategy --config config.json
|
|
470
|
-
```
|
|
471
|
-
|
|
472
|
-
## 📦 Versioning
|
|
473
|
-
|
|
474
|
-
This package follows [Semantic Versioning](https://semver.org/) (SemVer) and is published to PyPI as a public package.
|
|
475
|
-
|
|
476
|
-
### Version Format: MAJOR.MINOR.PATCH
|
|
477
|
-
|
|
478
|
-
- **MAJOR** (X.0.0): Breaking changes that require code updates
|
|
479
|
-
- **MINOR** (0.X.0): New features, backward compatible
|
|
480
|
-
- **PATCH** (0.0.X): Bug fixes, backward compatible
|
|
481
|
-
|
|
482
|
-
### Version Bumping Rules
|
|
483
|
-
|
|
484
|
-
- **PATCH**: Bug fixes, security patches, documentation updates
|
|
485
|
-
- **MINOR**: New adapters, new strategies, new features (backward compatible)
|
|
486
|
-
- **MAJOR**: Breaking API changes, removed features, incompatible changes
|
|
487
|
-
|
|
488
|
-
### Important Notes
|
|
489
|
-
|
|
490
|
-
- **Versions are immutable**: Once published to PyPI, a version cannot be changed or deleted
|
|
491
|
-
- **Versions must be unique**: Each release must have a new, unique version number
|
|
492
|
-
- **Publishing is restricted**: Only publish from the `main` branch to prevent accidental releases
|
|
493
|
-
|
|
494
|
-
### Publishing Workflow and Order of Operations
|
|
495
|
-
|
|
496
|
-
**Critical**: Changes must follow this strict order:
|
|
497
|
-
|
|
498
|
-
1. **Merge to main**: All changes must be merged to the `main` branch first
|
|
499
|
-
2. **Publish to PyPI**: The new version must be published to PyPI from `main` branch
|
|
500
|
-
3. **Dependent changes**: Only after publishing can dependent changes be merged in other applications
|
|
501
|
-
|
|
502
|
-
**Why this order matters:**
|
|
503
|
-
|
|
504
|
-
- Other applications depend on this package from PyPI
|
|
505
|
-
- They cannot merge changes that depend on new versions until those versions are available on PyPI
|
|
506
|
-
- Publishing from `main` ensures the published version matches what's in the repository
|
|
507
|
-
- This prevents dependency resolution failures in downstream applications
|
|
508
|
-
|
|
509
|
-
**Example workflow:**
|
|
510
|
-
|
|
511
|
-
```bash
|
|
512
|
-
# 1. Make changes in a feature branch
|
|
513
|
-
git checkout -b feature/new-adapter
|
|
514
|
-
# ... make changes ...
|
|
515
|
-
git commit -m "Add new adapter"
|
|
516
|
-
|
|
517
|
-
# 2. Merge to main
|
|
518
|
-
git checkout main
|
|
519
|
-
git merge feature/new-adapter
|
|
520
|
-
|
|
521
|
-
# 3. Bump version in pyproject.toml (e.g., 0.1.3 → 0.2.0)
|
|
522
|
-
# Edit pyproject.toml: version = "0.2.0"
|
|
523
|
-
git commit -m "Bump version to 0.2.0"
|
|
524
|
-
git push origin main
|
|
525
|
-
|
|
526
|
-
# 4. Publish to PyPI (must be on main branch)
|
|
527
|
-
just publish
|
|
528
|
-
|
|
529
|
-
# 5. Now dependent applications can update their dependencies
|
|
530
|
-
# pip install wayfinder-paths==0.2.0
|
|
531
|
-
```
|
|
532
|
-
|
|
533
|
-
## 📦 Publishing
|
|
534
|
-
|
|
535
|
-
Publish to PyPI:
|
|
536
|
-
|
|
537
|
-
```bash
|
|
538
|
-
export PUBLISH_TOKEN="your_pypi_token"
|
|
539
|
-
just publish
|
|
540
|
-
```
|
|
541
|
-
|
|
542
|
-
**Important:**
|
|
543
|
-
|
|
544
|
-
- ⚠️ **Publishing is only allowed from the `main` branch** - the publish command will fail if run from any other branch
|
|
545
|
-
- ⚠️ **Versions must be unique** - ensure the version in `pyproject.toml` has been bumped and is unique
|
|
546
|
-
- ⚠️ **Follow the order of operations** - see [Versioning](#-versioning) section above for the required workflow
|
|
547
|
-
- ⚠️ **Versions are immutable** - once published, a version cannot be changed or deleted from PyPI
|
|
548
|
-
|
|
549
|
-
Install the published package:
|
|
550
|
-
|
|
551
|
-
```bash
|
|
552
|
-
pip install wayfinder-paths
|
|
553
|
-
# or
|
|
554
|
-
poetry add wayfinder-paths
|
|
555
|
-
```
|
|
556
|
-
|
|
557
|
-
Install from Git (development):
|
|
558
|
-
|
|
559
|
-
```bash
|
|
560
|
-
pip install git+https://github.com/wayfinder-ai/wayfinder-paths.git
|
|
561
|
-
```
|
|
562
|
-
|
|
563
|
-
### Managing Package Access
|
|
564
|
-
|
|
565
|
-
To add collaborators who can publish updates:
|
|
566
|
-
|
|
567
|
-
1. Go to https://pypi.org/project/wayfinder-paths/
|
|
568
|
-
2. Click "Manage" → "Collaborators"
|
|
569
|
-
3. Add users as "Maintainers" (can publish) or "Owners" (full control)
|
|
570
|
-
|
|
571
|
-
## 🔒 Security
|
|
572
|
-
|
|
573
|
-
- **Never hardcode API keys or Private keys** - use config.json for credentials
|
|
574
|
-
- **Never commit config.json** - add it to .gitignore
|
|
575
|
-
- **Test on testnet first** - use test network when available
|
|
576
|
-
- **Validate all inputs** - sanitize user data
|
|
577
|
-
- **Set gas limits** - prevent excessive fees
|
|
578
|
-
|
|
579
|
-
## 📊 Backtesting
|
|
580
|
-
|
|
581
|
-
Coming soon
|
|
582
|
-
|
|
583
|
-
## 🌟 Community
|
|
584
|
-
|
|
585
|
-
Need help or want to discuss strategies? Join our [Discord](https://discord.gg/fUVwGMXjm3)!
|
|
586
|
-
|
|
587
|
-
## 📄 License
|
|
588
|
-
|
|
589
|
-
MIT License - see [LICENSE](LICENSE) file for details
|
|
590
|
-
|
|
591
|
-
🚀 **Happy Wayfinding!**
|
|
592
|
-
|