wayfinder-paths 0.1.6__py3-none-any.whl → 0.1.8__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 (50) hide show
  1. wayfinder_paths/adapters/balance_adapter/README.md +0 -10
  2. wayfinder_paths/adapters/balance_adapter/adapter.py +0 -20
  3. wayfinder_paths/adapters/balance_adapter/test_adapter.py +0 -30
  4. wayfinder_paths/adapters/brap_adapter/adapter.py +3 -2
  5. wayfinder_paths/adapters/brap_adapter/test_adapter.py +9 -13
  6. wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +14 -7
  7. wayfinder_paths/adapters/hyperliquid_adapter/__init__.py +18 -0
  8. wayfinder_paths/adapters/hyperliquid_adapter/adapter.py +1093 -0
  9. wayfinder_paths/adapters/hyperliquid_adapter/executor.py +549 -0
  10. wayfinder_paths/adapters/hyperliquid_adapter/manifest.yaml +8 -0
  11. wayfinder_paths/adapters/hyperliquid_adapter/paired_filler.py +1050 -0
  12. wayfinder_paths/adapters/hyperliquid_adapter/test_adapter.py +126 -0
  13. wayfinder_paths/adapters/hyperliquid_adapter/test_adapter_live.py +219 -0
  14. wayfinder_paths/adapters/hyperliquid_adapter/test_utils.py +220 -0
  15. wayfinder_paths/adapters/hyperliquid_adapter/utils.py +134 -0
  16. wayfinder_paths/adapters/ledger_adapter/test_adapter.py +7 -6
  17. wayfinder_paths/adapters/pool_adapter/README.md +3 -28
  18. wayfinder_paths/adapters/pool_adapter/adapter.py +0 -72
  19. wayfinder_paths/adapters/pool_adapter/examples.json +0 -43
  20. wayfinder_paths/adapters/pool_adapter/test_adapter.py +4 -54
  21. wayfinder_paths/adapters/token_adapter/test_adapter.py +4 -14
  22. wayfinder_paths/core/adapters/models.py +9 -4
  23. wayfinder_paths/core/analytics/__init__.py +11 -0
  24. wayfinder_paths/core/analytics/bootstrap.py +57 -0
  25. wayfinder_paths/core/analytics/stats.py +48 -0
  26. wayfinder_paths/core/analytics/test_analytics.py +170 -0
  27. wayfinder_paths/core/clients/BRAPClient.py +1 -0
  28. wayfinder_paths/core/clients/LedgerClient.py +2 -7
  29. wayfinder_paths/core/clients/PoolClient.py +0 -16
  30. wayfinder_paths/core/clients/WalletClient.py +0 -27
  31. wayfinder_paths/core/clients/protocols.py +104 -18
  32. wayfinder_paths/scripts/make_wallets.py +9 -0
  33. wayfinder_paths/scripts/run_strategy.py +124 -0
  34. wayfinder_paths/strategies/basis_trading_strategy/README.md +213 -0
  35. wayfinder_paths/strategies/basis_trading_strategy/__init__.py +3 -0
  36. wayfinder_paths/strategies/basis_trading_strategy/constants.py +1 -0
  37. wayfinder_paths/strategies/basis_trading_strategy/examples.json +16 -0
  38. wayfinder_paths/strategies/basis_trading_strategy/manifest.yaml +23 -0
  39. wayfinder_paths/strategies/basis_trading_strategy/snapshot_mixin.py +1011 -0
  40. wayfinder_paths/strategies/basis_trading_strategy/strategy.py +4522 -0
  41. wayfinder_paths/strategies/basis_trading_strategy/test_strategy.py +727 -0
  42. wayfinder_paths/strategies/basis_trading_strategy/types.py +39 -0
  43. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/examples.json +1 -9
  44. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +36 -5
  45. wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +367 -278
  46. wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +204 -7
  47. {wayfinder_paths-0.1.6.dist-info → wayfinder_paths-0.1.8.dist-info}/METADATA +32 -3
  48. {wayfinder_paths-0.1.6.dist-info → wayfinder_paths-0.1.8.dist-info}/RECORD +50 -27
  49. {wayfinder_paths-0.1.6.dist-info → wayfinder_paths-0.1.8.dist-info}/LICENSE +0 -0
  50. {wayfinder_paths-0.1.6.dist-info → wayfinder_paths-0.1.8.dist-info}/WHEEL +0 -0
@@ -61,13 +61,11 @@ def strategy():
61
61
  return (True, 1000000000)
62
62
 
63
63
  s.balance_adapter.get_balance = AsyncMock(side_effect=get_balance_side_effect)
64
- s.balance_adapter.get_all_balances = AsyncMock(
65
- return_value=(True, {"balances": []})
66
- )
67
64
 
68
65
  if hasattr(s, "token_adapter") and s.token_adapter:
69
66
  default_usdc = {
70
67
  "id": "usd-coin-base",
68
+ "token_id": "usd-coin-base",
71
69
  "symbol": "USDC",
72
70
  "name": "USD Coin",
73
71
  "decimals": 6,
@@ -77,6 +75,7 @@ def strategy():
77
75
 
78
76
  default_pool_token = {
79
77
  "id": "test-pool-base",
78
+ "token_id": "test-pool-base",
80
79
  "symbol": "POOL",
81
80
  "name": "Test Pool",
82
81
  "decimals": 18,
@@ -100,6 +99,7 @@ def strategy():
100
99
  True,
101
100
  {
102
101
  "id": "ethereum-base",
102
+ "token_id": "ethereum-base",
103
103
  "symbol": "ETH",
104
104
  "name": "Ethereum",
105
105
  "decimals": 18,
@@ -210,6 +210,7 @@ def strategy():
210
210
  s.DEPOSIT_USDC = 0
211
211
  s.usdc_token_info = {
212
212
  "id": "usd-coin-base",
213
+ "token_id": "usd-coin-base",
213
214
  "symbol": "USDC",
214
215
  "name": "USD Coin",
215
216
  "decimals": 6,
@@ -218,6 +219,7 @@ def strategy():
218
219
  }
219
220
  s.gas_token = {
220
221
  "id": "ethereum-base",
222
+ "token_id": "ethereum-base",
221
223
  "symbol": "ETH",
222
224
  "name": "Ethereum",
223
225
  "decimals": 18,
@@ -226,6 +228,7 @@ def strategy():
226
228
  }
227
229
  s.current_pool = {
228
230
  "id": "usd-coin-base",
231
+ "token_id": "usd-coin-base",
229
232
  "symbol": "USDC",
230
233
  "decimals": 6,
231
234
  "chain": {"code": "base", "id": 8453, "name": "Base"},
@@ -248,9 +251,6 @@ def strategy():
248
251
  side_effect=get_token_price_side_effect
249
252
  )
250
253
 
251
- async def mock_sweep_wallet(target_token):
252
- pass
253
-
254
254
  async def mock_refresh_current_pool_balance():
255
255
  pass
256
256
 
@@ -260,7 +260,6 @@ def strategy():
260
260
  async def mock_has_idle_assets(balances, target):
261
261
  return True
262
262
 
263
- s._sweep_wallet = mock_sweep_wallet
264
263
  s._refresh_current_pool_balance = mock_refresh_current_pool_balance
265
264
  s._rebalance_gas = mock_rebalance_gas
266
265
  s._has_idle_assets = mock_has_idle_assets
@@ -348,3 +347,201 @@ async def test_error_cases(strategy):
348
347
  f"Expected {example_name} update to "
349
348
  f"{'succeed' if expected_success else 'fail'} but got opposite"
350
349
  )
350
+
351
+
352
+ @pytest.mark.asyncio
353
+ async def test_token_tracking_initialization(strategy):
354
+ """Test that tracked_token_ids and tracked_balances are initialized."""
355
+ assert hasattr(strategy, "tracked_token_ids")
356
+ assert hasattr(strategy, "tracked_balances")
357
+ assert isinstance(strategy.tracked_token_ids, set)
358
+ assert isinstance(strategy.tracked_balances, dict)
359
+
360
+
361
+ @pytest.mark.asyncio
362
+ async def test_track_token(strategy):
363
+ """Test that _track_token adds tokens to tracked state."""
364
+ test_token_id = "test-token-base"
365
+ test_balance = 1000000
366
+
367
+ strategy._track_token(test_token_id, test_balance)
368
+
369
+ assert test_token_id in strategy.tracked_token_ids
370
+ assert strategy.tracked_balances.get(test_token_id) == test_balance
371
+
372
+
373
+ @pytest.mark.asyncio
374
+ async def test_update_balance(strategy):
375
+ """Test that _update_balance updates tracked balances."""
376
+ test_token_id = "test-token-base"
377
+ initial_balance = 1000000
378
+ updated_balance = 2000000
379
+
380
+ strategy._track_token(test_token_id, initial_balance)
381
+ assert strategy.tracked_balances.get(test_token_id) == initial_balance
382
+
383
+ strategy._update_balance(test_token_id, updated_balance)
384
+ assert strategy.tracked_balances.get(test_token_id) == updated_balance
385
+
386
+
387
+ @pytest.mark.asyncio
388
+ async def test_get_non_zero_tracked_tokens(strategy):
389
+ """Test that _get_non_zero_tracked_tokens returns only non-zero balances."""
390
+ strategy._track_token("token-1", 1000000)
391
+ strategy._track_token("token-2", 0)
392
+ strategy._track_token("token-3", 5000000)
393
+
394
+ non_zero = strategy._get_non_zero_tracked_tokens()
395
+
396
+ assert len(non_zero) == 2
397
+ token_ids = [token_id for token_id, _ in non_zero]
398
+ assert "token-1" in token_ids
399
+ assert "token-3" in token_ids
400
+ assert "token-2" not in token_ids
401
+
402
+
403
+ @pytest.mark.asyncio
404
+ async def test_refresh_tracked_balances(strategy):
405
+ """Test that _refresh_tracked_balances updates all tracked token balances."""
406
+ # Track some tokens
407
+ strategy._track_token("usd-coin-base")
408
+ strategy._track_token("ethereum-base")
409
+
410
+ # Refresh balances
411
+ await strategy._refresh_tracked_balances()
412
+
413
+ # Verify balances were fetched
414
+ assert "usd-coin-base" in strategy.tracked_balances
415
+ assert "ethereum-base" in strategy.tracked_balances
416
+
417
+
418
+ @pytest.mark.asyncio
419
+ async def test_deposit_tracks_usdc(strategy):
420
+ """Test that deposit operation tracks USDC token."""
421
+ # Clear tracked state
422
+ strategy.tracked_token_ids.clear()
423
+ strategy.tracked_balances.clear()
424
+
425
+ # Perform deposit
426
+ ok, _ = await strategy.deposit(main_token_amount=100.0)
427
+
428
+ # Verify USDC is tracked
429
+ assert ok
430
+ usdc_token_id = strategy.usdc_token_info.get("token_id")
431
+ assert usdc_token_id in strategy.tracked_token_ids
432
+
433
+
434
+ @pytest.mark.asyncio
435
+ async def test_sweep_wallet_uses_tracked_tokens(strategy):
436
+ """Test that _sweep_wallet only swaps tracked tokens."""
437
+ # Import the real implementation to restore it
438
+ from wayfinder_paths.strategies.stablecoin_yield_strategy.strategy import (
439
+ StablecoinYieldStrategy,
440
+ )
441
+
442
+ # Restore the real _sweep_wallet method (fixture mocks it as a no-op)
443
+ strategy._sweep_wallet = StablecoinYieldStrategy._sweep_wallet.__get__(
444
+ strategy, StablecoinYieldStrategy
445
+ )
446
+
447
+ # Setup: track some tokens with balances
448
+ strategy._track_token("token-1", 1000000)
449
+ strategy._track_token("token-2", 2000000)
450
+
451
+ # Track the actual token IDs to avoid issues with gas token
452
+ # Make sure we're not accidentally matching gas token
453
+ assert "token-1" in strategy.tracked_token_ids
454
+ assert "token-2" in strategy.tracked_token_ids
455
+
456
+ # Mock balance adapter to return fresh balances
457
+ async def get_balance_mock(token_id, **kwargs):
458
+ balance = strategy.tracked_balances.get(token_id, 0)
459
+ # Return the balance, ensuring it's an int
460
+ return (True, int(balance) if balance else 0)
461
+
462
+ # Create a new AsyncMock that will track calls
463
+ new_mock = AsyncMock(side_effect=get_balance_mock)
464
+ strategy.balance_adapter.get_balance = new_mock
465
+
466
+ # Mock brap adapter swap
467
+ strategy.brap_adapter.swap_from_token_ids = AsyncMock(
468
+ return_value=(True, "Swap successful")
469
+ )
470
+
471
+ target_token = {
472
+ "token_id": "usd-coin-base",
473
+ "address": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
474
+ "chain": {"code": "base", "name": "Base"},
475
+ }
476
+
477
+ # Call sweep
478
+ await strategy._sweep_wallet(target_token)
479
+
480
+ # Verify that swap was called for tracked tokens (should be called twice, once for each token)
481
+ # If this fails, check: balance_adapter.get_balance was called, tracked_balances has values,
482
+ # and tokens pass the gas/target token checks
483
+ assert strategy.brap_adapter.swap_from_token_ids.call_count >= 1, (
484
+ f"Expected at least 1 swap call, got {strategy.brap_adapter.swap_from_token_ids.call_count}. "
485
+ f"Tracked tokens: {strategy.tracked_token_ids}, "
486
+ f"Tracked balances: {strategy.tracked_balances}, "
487
+ f"Get balance calls: {new_mock.call_count}, "
488
+ f"balance_adapter mock is: {id(strategy.balance_adapter.get_balance)}, new_mock is: {id(new_mock)}"
489
+ )
490
+
491
+
492
+ @pytest.mark.asyncio
493
+ async def test_get_non_gas_balances_uses_tracked_state(strategy):
494
+ """Test that _get_non_gas_balances only checks tracked tokens."""
495
+ # Setup tracked tokens
496
+ usdc_token_id = "usd-coin-base"
497
+ pool_token_id = "test-pool-base"
498
+
499
+ strategy._track_token(usdc_token_id, 100000000)
500
+ strategy._track_token(pool_token_id, 50000000000000000000)
501
+
502
+ # Mock refresh
503
+ strategy.balance_adapter.get_balance = AsyncMock(
504
+ side_effect=lambda token_id, **kwargs: (
505
+ True,
506
+ strategy.tracked_balances.get(token_id, 0),
507
+ )
508
+ )
509
+
510
+ # Get non-gas balances
511
+ balances = await strategy._get_non_gas_balances()
512
+
513
+ # Verify only tracked tokens are returned (excluding gas)
514
+ token_ids = [b["token_id"] for b in balances]
515
+ assert usdc_token_id in token_ids or pool_token_id in token_ids
516
+ assert len(balances) <= len(strategy.tracked_token_ids)
517
+
518
+
519
+ @pytest.mark.asyncio
520
+ async def test_partial_liquidate_uses_tracked_tokens(strategy):
521
+ """Test that partial_liquidate only liquidates tracked tokens."""
522
+ # Setup tracked tokens with balances
523
+ strategy._track_token("usd-coin-base", 50000000) # 50 USDC
524
+ strategy._track_token("test-pool-base", 100000000000000000000) # 100 POOL tokens
525
+
526
+ # Mock balance and token adapters
527
+ strategy.balance_adapter.get_balance = AsyncMock(
528
+ side_effect=lambda token_id, **kwargs: (
529
+ True,
530
+ strategy.tracked_balances.get(token_id, 0),
531
+ )
532
+ )
533
+
534
+ strategy.token_adapter.get_token_price = AsyncMock(
535
+ return_value=(True, {"current_price": 1.0})
536
+ )
537
+
538
+ strategy.brap_adapter.swap_from_token_ids = AsyncMock(
539
+ return_value=(True, "Swap successful")
540
+ )
541
+
542
+ # Call partial liquidate
543
+ ok, msg = await strategy.partial_liquidate(usd_value=75.0)
544
+
545
+ # Verify success
546
+ assert ok
547
+ assert "liquidation completed" in msg.lower()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: wayfinder-paths
3
- Version: 0.1.6
3
+ Version: 0.1.8
4
4
  Summary: Wayfinder Path: strategies and adapters
5
5
  Author: Wayfinder
6
6
  Author-email: dev@wayfinder.ai
@@ -10,6 +10,7 @@ Classifier: Programming Language :: Python :: 3.12
10
10
  Requires-Dist: aiohttp (>=3.13.0,<4.0.0)
11
11
  Requires-Dist: eth-account (>=0.13.7,<0.14.0)
12
12
  Requires-Dist: httpx (>=0.28.1,<0.29.0)
13
+ Requires-Dist: hyperliquid-python-sdk (>=0.21.0,<0.22.0)
13
14
  Requires-Dist: loguru (>=0.7.3,<0.8.0)
14
15
  Requires-Dist: numpy (>=1.26.0,<2.0.0)
15
16
  Requires-Dist: pandas (>=2.2.0,<3.0.0)
@@ -124,6 +125,7 @@ We welcome contributions! This is an open-source project where community members
124
125
  ### Contributor Guidelines
125
126
 
126
127
  #### For Adapters
128
+
127
129
  - **Start from the template**: Copy `wayfinder_paths/templates/adapter/` as a starting point
128
130
  - Extend `BaseAdapter` from `wayfinder_paths/core/adapters/BaseAdapter.py`
129
131
  - Create a `manifest.yaml` (template at `wayfinder_paths/templates/adapter/manifest.yaml`) with:
@@ -137,6 +139,7 @@ We welcome contributions! This is an open-source project where community members
137
139
  - Validate your manifest: `just validate-manifests`
138
140
 
139
141
  #### For Strategies
142
+
140
143
  - **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
141
144
  - Extend `Strategy` from `wayfinder_paths/core/strategies/Strategy.py`
142
145
  - Create a `manifest.yaml` (template at `wayfinder_paths/templates/strategy/manifest.yaml`) with:
@@ -150,6 +153,7 @@ We welcome contributions! This is an open-source project where community members
150
153
  - Validate your manifest: `just validate-manifests`
151
154
 
152
155
  #### General Guidelines
156
+
153
157
  - **Code Quality**: Follow existing patterns and use type hints
154
158
  - **Testing**: See [TESTING.md](TESTING.md) - minimum: smoke test for strategies, basic tests for adapters
155
159
  - **Documentation**: Update README files and add docstrings
@@ -204,6 +208,7 @@ poetry run python wayfinder_paths/run_strategy.py your_strategy --action status
204
208
  ## 🏗️ Architecture
205
209
 
206
210
  ### Client System
211
+
207
212
  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.
208
213
 
209
214
  ### Clients vs Adapters
@@ -230,6 +235,7 @@ Adapter manifests declare the capabilities an adapter provides and the clients i
230
235
  **Template:** Copy `wayfinder_paths/templates/adapter/manifest.yaml` as a starting point.
231
236
 
232
237
  **Schema:**
238
+
233
239
  ```yaml
234
240
  schema_version: "0.1"
235
241
  entrypoint: "adapters.my_adapter.adapter.MyAdapter"
@@ -242,12 +248,14 @@ dependencies:
242
248
  ```
243
249
 
244
250
  **Fields:**
251
+
245
252
  - `schema_version`: Manifest schema version (currently `"0.1"`)
246
253
  - `entrypoint`: Full Python import path to the adapter class (required)
247
254
  - `capabilities`: List of abstract capabilities this adapter provides (required, non-empty)
248
255
  - `dependencies`: List of client class names from `core.clients` that this adapter requires (required, non-empty)
249
256
 
250
257
  **Example** (`wayfinder_paths/adapters/pool_adapter/manifest.yaml`):
258
+
251
259
  ```yaml
252
260
  schema_version: "0.1"
253
261
  entrypoint: "adapters.pool_adapter.adapter.PoolAdapter"
@@ -268,6 +276,7 @@ Strategy manifests declare permissions and required adapters with their capabili
268
276
  **Template:** Copy `wayfinder_paths/templates/strategy/manifest.yaml` as a starting point.
269
277
 
270
278
  **Schema:**
279
+
271
280
  ```yaml
272
281
  schema_version: "0.1"
273
282
  entrypoint: "strategies.my_strategy.strategy.MyStrategy"
@@ -281,6 +290,7 @@ adapters:
281
290
  ```
282
291
 
283
292
  **Fields:**
293
+
284
294
  - `schema_version`: Manifest schema version (currently `"0.1"`)
285
295
  - `entrypoint`: Full Python import path to the strategy class (required)
286
296
  - `name`: Strategy directory name (optional, used for wallet lookup - defaults to directory name)
@@ -290,6 +300,7 @@ adapters:
290
300
  - `capabilities`: List of capabilities required from this adapter
291
301
 
292
302
  **Example** (`wayfinder_paths/strategies/stablecoin_yield_strategy/manifest.yaml`):
303
+
293
304
  ```yaml
294
305
  schema_version: "0.1"
295
306
  entrypoint: "strategies.stablecoin_yield_strategy.strategy.StablecoinYieldStrategy"
@@ -307,12 +318,14 @@ adapters:
307
318
  #### Manifest Validation
308
319
 
309
320
  Manifests are automatically validated to ensure:
321
+
310
322
  - Schema compliance (all required fields present, correct types)
311
323
  - Entrypoint classes exist and are importable
312
324
  - Dependencies are valid client classes
313
325
  - Permissions policies are non-empty
314
326
 
315
327
  **Validate locally:**
328
+
316
329
  ```bash
317
330
  # Validate all manifests
318
331
  just validate-manifests
@@ -347,6 +360,7 @@ The `validate_manifests.py` script performs multi-stage validation:
347
360
  - Policy syntax is not parsed/validated (assumed to be valid at runtime)
348
361
 
349
362
  **Validation Flow:**
363
+
350
364
  ```
351
365
  For each manifest file:
352
366
  1. Load YAML → Parse with Pydantic (schema validation)
@@ -356,6 +370,7 @@ For each manifest file:
356
370
  ```
357
371
 
358
372
  The script automatically discovers all manifests by scanning:
373
+
359
374
  - `wayfinder_paths/adapters/*/manifest.yaml` for adapter manifests
360
375
  - `wayfinder_paths/strategies/*/manifest.yaml` for strategy manifests
361
376
 
@@ -366,12 +381,15 @@ All errors are collected and reported at the end, with the script exiting with c
366
381
  Capabilities are abstract operation identifiers (e.g., `"pool.read"`, `"swap.execute"`) declared in manifests. They represent what operations an adapter can perform, not specific method names. The manifest is the **single source of truth** for capabilities—they are not duplicated in code.
367
382
 
368
383
  When creating an adapter:
384
+
369
385
  1. Declare capabilities in your `manifest.yaml`
370
386
  2. Implement methods that fulfill those capabilities
371
387
  3. Capabilities are validated at manifest validation time (entrypoint must be importable)
372
388
 
373
389
  ### Configuration
390
+
374
391
  Configuration is split between:
392
+
375
393
  - **User Config**: Your credentials and preferences
376
394
  - **System Config**: Platform settings
377
395
  - **Strategy Config**: Strategy-specific parameters
@@ -383,9 +401,11 @@ See [CONFIG_GUIDE.md](wayfinder_paths/CONFIG_GUIDE.md) for details.
383
401
  Wayfinder Paths supports two authentication methods:
384
402
 
385
403
  #### 1. Service Account Authentication (API Key)
404
+
386
405
  For backend services and automated systems with higher rate limits:
387
406
 
388
407
  **Option A: Pass to Strategy Constructor**
408
+
389
409
  ```python
390
410
  from wayfinder_paths.strategies.stablecoin_yield_strategy.strategy import StablecoinYieldStrategy
391
411
 
@@ -396,19 +416,21 @@ strategy = StablecoinYieldStrategy(
396
416
  ```
397
417
 
398
418
  **Option B: Set Environment Variable**
419
+
399
420
  ```bash
400
421
  export WAYFINDER_API_KEY="sk_live_abc123..."
401
422
  # All clients will automatically discover and use this
402
423
  ```
403
424
 
404
425
  **Option C: Add to config.json**
426
+
405
427
  ```json
406
428
  {
407
429
  "user": {
408
430
  "api_key": "sk_live_abc123..."
409
431
  },
410
432
  "system": {
411
- "api_key": "sk_live_abc123..." // Alternative: system-level API key
433
+ "api_key": "sk_live_abc123..." // Alternative: system-level API key
412
434
  }
413
435
  }
414
436
  ```
@@ -418,6 +440,7 @@ export WAYFINDER_API_KEY="sk_live_abc123..."
418
440
  **Note:** API keys in `config.json` are loaded directly by `WayfinderClient` via `_load_config_credentials()`, not through the `UserConfig` or `SystemConfig` dataclasses. This allows flexible credential loading.
419
441
 
420
442
  #### 2. Personal Access Authentication (OAuth)
443
+
421
444
  For standalone SDK users with username/password:
422
445
 
423
446
  ```json
@@ -425,12 +448,13 @@ For standalone SDK users with username/password:
425
448
  "user": {
426
449
  "username": "your_username",
427
450
  "password": "your_password",
428
- "refresh_token": null // Optional: use refresh token instead
451
+ "refresh_token": null // Optional: use refresh token instead
429
452
  }
430
453
  }
431
454
  ```
432
455
 
433
456
  **How It Works:**
457
+
434
458
  - API keys are automatically discovered by all clients (no need to pass explicitly)
435
459
  - When an API key is available, it's used for all API requests (including public endpoints) for rate limiting
436
460
  - If no API key is found, the system falls back to OAuth authentication
@@ -613,6 +637,7 @@ just create-wallets
613
637
  ```
614
638
 
615
639
  This creates:
640
+
616
641
  - `main` wallet - your main wallet for testing (labeled "main" in wallets.json)
617
642
  - `wallets.json` - wallet addresses and private keys for local testing
618
643
 
@@ -688,12 +713,14 @@ This package follows [Semantic Versioning](https://semver.org/) (SemVer) and is
688
713
  3. **Dependent changes**: Only after publishing can dependent changes be merged in other applications
689
714
 
690
715
  **Why this order matters:**
716
+
691
717
  - Other applications depend on this package from PyPI
692
718
  - They cannot merge changes that depend on new versions until those versions are available on PyPI
693
719
  - Publishing from `main` ensures the published version matches what's in the repository
694
720
  - This prevents dependency resolution failures in downstream applications
695
721
 
696
722
  **Example workflow:**
723
+
697
724
  ```bash
698
725
  # 1. Make changes in a feature branch
699
726
  git checkout -b feature/new-adapter
@@ -726,6 +753,7 @@ just publish
726
753
  ```
727
754
 
728
755
  **Important:**
756
+
729
757
  - ⚠️ **Publishing is only allowed from the `main` branch** - the publish command will fail if run from any other branch
730
758
  - ⚠️ **Versions must be unique** - ensure the version in `pyproject.toml` has been bumped and is unique
731
759
  - ⚠️ **Follow the order of operations** - see [Versioning](#-versioning) section above for the required workflow
@@ -748,6 +776,7 @@ pip install git+https://github.com/wayfinder-ai/wayfinder-paths.git
748
776
  ### Managing Package Access
749
777
 
750
778
  To add collaborators who can publish updates:
779
+
751
780
  1. Go to https://pypi.org/project/wayfinder-paths/
752
781
  2. Click "Manage" → "Collaborators"
753
782
  3. Add users as "Maintainers" (can publish) or "Owners" (full control)
@@ -2,59 +2,72 @@ wayfinder_paths/CONFIG_GUIDE.md,sha256=PN2ClAZ8FCF16_sstaUxbfvQkVAyXdtRvTrrj-qJP
2
2
  wayfinder_paths/__init__.py,sha256=YgOg-PRPT3ROh0zg6hgQyQE-YFkFGw6TM77zDvB4_sE,427
3
3
  wayfinder_paths/abis/generic/erc20.json,sha256=geyzVzdTNt3u1XHKxi4seszP_GIWIzPTl0FYgiftRnM,9336
4
4
  wayfinder_paths/adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- wayfinder_paths/adapters/balance_adapter/README.md,sha256=g5LXIJ-_6mM6FRwvEJp3jLJeUXfHxauiNRfnYRhJbps,4046
6
- wayfinder_paths/adapters/balance_adapter/adapter.py,sha256=5-zN_DXypnshpLbMTLEKqG5XI3D0xNKbhWQUxNdnCWA,8991
5
+ wayfinder_paths/adapters/balance_adapter/README.md,sha256=rRq--g4y7X7UOs1KK8c0e-4f-fItZEgHnaTRw0kR76I,3683
6
+ wayfinder_paths/adapters/balance_adapter/adapter.py,sha256=byfucmlGXT4_qGD4eeTvLw5X-2NHgHtiV0uOKp73CfE,8355
7
7
  wayfinder_paths/adapters/balance_adapter/examples.json,sha256=3R1M4B_VsIy29viAuFT9nQbnQShWl8ZbU-rnSNWUW9U,129
8
8
  wayfinder_paths/adapters/balance_adapter/manifest.yaml,sha256=vp2VoQJf-TxFxgkTsUJ1AEeeOoImM_QjrGYCmjyEQYI,189
9
- wayfinder_paths/adapters/balance_adapter/test_adapter.py,sha256=MzwElYxtdffIJnk9xtWCJml8HG1n8Z0omJY2X9MVmDg,2873
9
+ wayfinder_paths/adapters/balance_adapter/test_adapter.py,sha256=Z8iTRU0Rv1UsODuVSo5q4j-DrTXMd4YRxvaxLdZE4Us,1878
10
10
  wayfinder_paths/adapters/brap_adapter/README.md,sha256=euWkSBR6OkYtebhvdNR_PL64sKbzKD5bg5hrYTIWZ1c,7905
11
11
  wayfinder_paths/adapters/brap_adapter/__init__.py,sha256=jpqxZ-Bv_8kBo-lhgO_QCWaVZNq_WwlkNBHD4RsqOJg,90
12
- wayfinder_paths/adapters/brap_adapter/adapter.py,sha256=9Nr_pUhIf5ik98pTg-6pidDtnxH_vt_ZkQHchpAG3oE,26778
12
+ wayfinder_paths/adapters/brap_adapter/adapter.py,sha256=OCXlNxIR7vQUktaoEeM55VcFOXR-PucNJW1NpBkNEUs,26828
13
13
  wayfinder_paths/adapters/brap_adapter/examples.json,sha256=KWuAklUspd2uvk0s2ey8gczg4nbzhdwxQqzhascyMiQ,5287
14
14
  wayfinder_paths/adapters/brap_adapter/manifest.yaml,sha256=bJ8o4j9ZPjfnLxXxHfekoXKUHoBkXmWQ3nokTH1aya4,240
15
- wayfinder_paths/adapters/brap_adapter/test_adapter.py,sha256=36ixuv11Ql3pWgImmoVuE1EqVpsvT5dToGvN9LjpWpE,10874
15
+ wayfinder_paths/adapters/brap_adapter/test_adapter.py,sha256=w2q35tcE7j2QG53jSm_XZgIk7OKL4O51fnFuGMVRSNQ,10754
16
16
  wayfinder_paths/adapters/hyperlend_adapter/__init__.py,sha256=DsWOnEn-Tlu9ZoIoGaFeSqOYI3b4lXGVK3_FTntWpLw,139
17
17
  wayfinder_paths/adapters/hyperlend_adapter/adapter.py,sha256=QevMiOrztvTRHx7vA_dAQGX3ioUFdLY4aVOfsT-DXX8,10555
18
18
  wayfinder_paths/adapters/hyperlend_adapter/manifest.yaml,sha256=Ugc0jNf3txAQRGAXlVvTN3Mbdc4-fUMS1yVs0SZcBwI,259
19
- wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py,sha256=ZnEiJxHRlcI4ijDfwmL2KEsL6A8dcWDYNhhxCEezWI4,9330
19
+ wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py,sha256=iLnrALVnK7JWJV2KFDqBYZlr1ShW1tjHC-kCV6-FlgE,9558
20
+ wayfinder_paths/adapters/hyperliquid_adapter/__init__.py,sha256=QpA258RzVbxzsha86HQduAuNVG0g0qvsI5OcZunQ8DQ,467
21
+ wayfinder_paths/adapters/hyperliquid_adapter/adapter.py,sha256=kG0oBi07OI4JNwDs14cGJ15qDSoNKX6_v-CUHlsctGQ,36598
22
+ wayfinder_paths/adapters/hyperliquid_adapter/executor.py,sha256=uibNnfsgB_KMOYpZzaSDTsiKGQPIKwZyZ6uH34-Xu4A,17447
23
+ wayfinder_paths/adapters/hyperliquid_adapter/manifest.yaml,sha256=IOK5kFaOuqqEcf3EuY5oXufEaUQNoz2oBXRGVbCdSXQ,206
24
+ wayfinder_paths/adapters/hyperliquid_adapter/paired_filler.py,sha256=nOBsrAka8PKv5h8SuoJuLTH4HYS4n0vpTIADUCyDKlA,37546
25
+ wayfinder_paths/adapters/hyperliquid_adapter/test_adapter.py,sha256=JEDeIMSTdrgcSy4BGSVB0CixQzl3NsKpukOZ9mRu3kE,4542
26
+ wayfinder_paths/adapters/hyperliquid_adapter/test_adapter_live.py,sha256=z3vi6AoIkQmOcUW1WyxIPWfv0SIuSNWNp9ABOIkBjzM,7689
27
+ wayfinder_paths/adapters/hyperliquid_adapter/test_utils.py,sha256=2gSrXJgtfrTqNOQIhBS92vUkfcwhFsMLgFRkf1bzLy8,7290
28
+ wayfinder_paths/adapters/hyperliquid_adapter/utils.py,sha256=WjLEaNVvcB8FfYlTrwZBrmw7k2MLS5KhBeW4NNoLlVI,4254
20
29
  wayfinder_paths/adapters/ledger_adapter/README.md,sha256=OIFbJIlck91K3kBKbkPfOWUDx7tJgDjwCAcBLm7FNK4,4104
21
30
  wayfinder_paths/adapters/ledger_adapter/__init__.py,sha256=DK9GShIUiQ57YKSqhCKoS43GCweBxi0lzkUQ9sYVxUA,96
22
31
  wayfinder_paths/adapters/ledger_adapter/adapter.py,sha256=6Fjxltvn9iXp_-CZtN7lDz1Xt0lWaNQX2drx6lgeryw,10260
23
32
  wayfinder_paths/adapters/ledger_adapter/examples.json,sha256=DdqTSe4vnBrfIycQVQQ_JZom7fBGHbL7MR4ppK9ljCY,3936
24
33
  wayfinder_paths/adapters/ledger_adapter/manifest.yaml,sha256=121VPXNpx13vO9qoBww47Wvpi29JLn5WoIFnudCkDYs,271
25
- wayfinder_paths/adapters/ledger_adapter/test_adapter.py,sha256=F5L7YYbYIH1HUGkR-Dra2XU2AdSvx-kfO2qDYzW3xKw,7425
26
- wayfinder_paths/adapters/pool_adapter/README.md,sha256=rF7KYEtxu6BmDa9gi505-IFUddk6BDaMOQPB4YjeOLc,5863
34
+ wayfinder_paths/adapters/ledger_adapter/test_adapter.py,sha256=Z1-rPP9k5fI-8ofWMKgU3syzNegKGH_hGO6CKApQj1c,7470
35
+ wayfinder_paths/adapters/pool_adapter/README.md,sha256=ttfG4aP_Y0Bl7DXxPlrAhrubOs9Yu0mtki3h7JqWvxQ,5293
27
36
  wayfinder_paths/adapters/pool_adapter/__init__.py,sha256=rv56pYzz2Gqiz33uoPJktCQRe3CRt8U9ry5GbjVgK3A,90
28
- wayfinder_paths/adapters/pool_adapter/adapter.py,sha256=jXGq5F-xHXF42JN5R0Hd6LEGDds1qAiwOCGQ4etzuPE,9642
29
- wayfinder_paths/adapters/pool_adapter/examples.json,sha256=hLH74Oy6WlrEvAIOjwqsjpcCDxC-N0efWeLa_-TbntM,3202
37
+ wayfinder_paths/adapters/pool_adapter/adapter.py,sha256=D3J9Bx7urFZjuqfmexg-wDjngKfaeeXi5aNgQXQ2W_Y,7249
38
+ wayfinder_paths/adapters/pool_adapter/examples.json,sha256=FS0cssPu2KB05MmzG4Hc0Ka0DzOn_0nogqfHBGLJns8,2295
30
39
  wayfinder_paths/adapters/pool_adapter/manifest.yaml,sha256=z-OQYBsl2RdV6M34RZzqtQTAFHtQod0po_JD_-9ElNM,217
31
- wayfinder_paths/adapters/pool_adapter/test_adapter.py,sha256=QiEYyLFo0S6gKJuk7j9Md0-mN6yNY5heKDQ_Sm1Yln8,7721
40
+ wayfinder_paths/adapters/pool_adapter/test_adapter.py,sha256=AYk4YWf0H3FXNBc1NKVmXuLQvE7dpMU-QrCp0XWQYFw,5954
32
41
  wayfinder_paths/adapters/token_adapter/README.md,sha256=d2tMJte6HBu62CCYXdjS8GHZXj5f2fU03uZAO6pscBI,2698
33
42
  wayfinder_paths/adapters/token_adapter/__init__.py,sha256=nEmxrvffEygn3iKH3cZTNLkhnUUhlUAEtshmrFRAjq8,62
34
43
  wayfinder_paths/adapters/token_adapter/adapter.py,sha256=JEb7A8wJYHxENFhJ6upAgnQAbPZeVfYi6OGs1hiHxnA,3432
35
44
  wayfinder_paths/adapters/token_adapter/examples.json,sha256=RW-3xazj4wbTPl-AVrzduRH1NCXx8m7-06bRMOUJ-lc,3626
36
45
  wayfinder_paths/adapters/token_adapter/manifest.yaml,sha256=KQgbHAUaJ6JYjTlOJ9HGeRxwmICXVV01qRwW8wJPKMM,143
37
- wayfinder_paths/adapters/token_adapter/test_adapter.py,sha256=xnJ-nglMnCFqYnH9D-xcnIy-pmPZK6_puNZ9hPthIMI,4701
46
+ wayfinder_paths/adapters/token_adapter/test_adapter.py,sha256=oEhV5OooRh1oGnaTTMKtdU9oqvHBKR25KgL6-ZB6Mzo,4304
38
47
  wayfinder_paths/config.example.json,sha256=gDvS7W-cbaNe2IV7Q72di_PYpCDKODojELaXdd77Gx4,605
39
48
  wayfinder_paths/conftest.py,sha256=pqDNijXn9_zmbAdkt_2a18UQLjtsDkNTBJVTgC6H2nA,1136
40
49
  wayfinder_paths/core/__init__.py,sha256=AJK8oS2dCVuJ2pmSxqXOCvuWacNaVEU3yALEqsD3rog,398
41
50
  wayfinder_paths/core/adapters/BaseAdapter.py,sha256=bzc3ER7aKOsmk9cxyoJxGdI54eibbpcMC8nGYJUrsp0,2033
42
51
  wayfinder_paths/core/adapters/__init__.py,sha256=ZqzkliXm5RjWxYJyJR88XHb3npZFiThk7HoVZe3JF60,108
43
52
  wayfinder_paths/core/adapters/base.py,sha256=j10cZ5NwqaAhN2mH_j24tG8r7_7NWtx8F6S7sJ9wOi8,100
44
- wayfinder_paths/core/adapters/models.py,sha256=cQEZMjKZtUz_M29ijBXhZeIfR7FSYlunxov8pMIuUxs,913
53
+ wayfinder_paths/core/adapters/models.py,sha256=06XyteSyCK9zV3MwetBWFmYgufvwwLVWpZBVy-XiO3k,1006
54
+ wayfinder_paths/core/analytics/__init__.py,sha256=AtcSpt2vPpCNgdDaFDLhyZZpKa0QXK6onvg_dTyGTD4,263
55
+ wayfinder_paths/core/analytics/bootstrap.py,sha256=lb_PjL4Vh3O2F8eXgvAbnAFevJczRF59ODG-dxtpCZ8,1782
56
+ wayfinder_paths/core/analytics/stats.py,sha256=qE6h0j8TZAbqbVpDeYlVKe0YbV5CENQcHbREzKyZ_s8,1426
57
+ wayfinder_paths/core/analytics/test_analytics.py,sha256=DNkVTsbWPLc9I1eeCD5wsPPqUDgN-npbGRhBgMKn3GM,5580
45
58
  wayfinder_paths/core/clients/AuthClient.py,sha256=scz8GvnabNYAQq_XYDcLP2lf2LZqurQOixA7MMAfbCY,2796
46
- wayfinder_paths/core/clients/BRAPClient.py,sha256=AtTYNk1FuCS59xj5FFgv2fIts44BQK19Kv0IeXlcPtw,3700
59
+ wayfinder_paths/core/clients/BRAPClient.py,sha256=-cL05ELlroi3pUfT_5nF8Axie2a0n19npnuP408bkAQ,3744
47
60
  wayfinder_paths/core/clients/ClientManager.py,sha256=2p8oEFnCxKCH_TBMKo9gMLAwzwLgeotdgFod8wpoa04,8135
48
61
  wayfinder_paths/core/clients/HyperlendClient.py,sha256=6yAhojEbjrRC7YLckwGL_2z5lwI4xnrRVNzxspqKSTg,6173
49
- wayfinder_paths/core/clients/LedgerClient.py,sha256=c-RSBlf8jSOFWbK-Yr_n91bz5kNNLexEsaiMDGf5g4M,14627
50
- wayfinder_paths/core/clients/PoolClient.py,sha256=s4fg-OPPxq7tfy8Fbk_QtGCkzkiRCx-P8UwANUfJpE0,4070
62
+ wayfinder_paths/core/clients/LedgerClient.py,sha256=M6VlG0yq3H4rQt6qRxc0QQVd7GoPXJpj2FcD0RM_C_k,14430
63
+ wayfinder_paths/core/clients/PoolClient.py,sha256=EMIRRw7nh2bha-Qb5uOcIRgbnnu_v5FIvDU0D61nXGI,3475
51
64
  wayfinder_paths/core/clients/SimulationClient.py,sha256=ViQmXCQKwhpnZA-YkfIgArrpxGr1U11lZNlbBIak1MU,6364
52
65
  wayfinder_paths/core/clients/TokenClient.py,sha256=zg39K-uA1ObkNEcxoXviA1QYSd-fxQXxjBHFOeClY9E,2788
53
66
  wayfinder_paths/core/clients/TransactionClient.py,sha256=APs-8lMdgBnE40wOn5L8_lEdJ3DddTZFcQbW0tIfJWg,2040
54
- wayfinder_paths/core/clients/WalletClient.py,sha256=Hx4iz41ieEQyUcS16_qgw7LdQMrG5UX-KUDCMgZ3jYc,3677
67
+ wayfinder_paths/core/clients/WalletClient.py,sha256=Vc2AwllBxUzkdZKKVRrPR4gl8mtvffRxz5QbrpxcH-0,2819
55
68
  wayfinder_paths/core/clients/WayfinderClient.py,sha256=lLdmD58gAyx5N4yYN4-IYjvRDVzwE3K408XuI07g6g4,10724
56
69
  wayfinder_paths/core/clients/__init__.py,sha256=oNq6fQW8hUnpkuIZxdbOTLPayJRLA6S-k8e7wqsH_7c,1581
57
- wayfinder_paths/core/clients/protocols.py,sha256=p6Juadsi3jVVp6WyWNmT3O8qr6TRmWOrsWVMH5RgWPE,8339
70
+ wayfinder_paths/core/clients/protocols.py,sha256=3TYdOdvz9en72_xA6sMHgahB21ZQFP5w86qE6pwo7YA,10117
58
71
  wayfinder_paths/core/clients/sdk_example.py,sha256=Y6mSyHfsWcOje6E-geNI0C4CQ6uyZaD3V9Q8kPM53eo,2969
59
72
  wayfinder_paths/core/config.py,sha256=A--KQp_EDLXhtituvk3WXPUP2SJv45IcNcm4G_nFMc0,16890
60
73
  wayfinder_paths/core/constants/__init__.py,sha256=KH-TtfNBJgp0WfKIxvHnvS521odH8RS3Qhl8cQhr4Ys,663
@@ -92,20 +105,30 @@ wayfinder_paths/policies/util.py,sha256=r8xQLPvE3kU21_LG6VbkFI9sUSYltcsKunryZdHO
92
105
  wayfinder_paths/run_strategy.py,sha256=HRj5iY2AFWaxRKXukKUKPxaXcz4YN-fb6anSLHJaeDg,14502
93
106
  wayfinder_paths/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
94
107
  wayfinder_paths/scripts/create_strategy.py,sha256=rp2kkGXsmcAbOt1eZthV1iZ2yM6wAbjn4R10IATulOw,6275
95
- wayfinder_paths/scripts/make_wallets.py,sha256=oP3i8MdU9HJT1QWUfkP7XAv2rDuZg_tbawJ-EJg3b5c,5997
108
+ wayfinder_paths/scripts/make_wallets.py,sha256=_diYY5FzpLC5mFVIzZsQUBhlBCUQpvhxL5CtQW0qaT8,6298
109
+ wayfinder_paths/scripts/run_strategy.py,sha256=EQDsE59mLHXR0HO7vzmzNsqSj-YpsuObC9tg2ZYVztA,3633
96
110
  wayfinder_paths/scripts/validate_manifests.py,sha256=sTJhCVTb8X0SFYozArVbX4AMAEv-0R1Imp4dpHfAuHE,7075
97
111
  wayfinder_paths/strategies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
112
+ wayfinder_paths/strategies/basis_trading_strategy/README.md,sha256=rTUXQ2owEoPmXlfHcJfRFCwcQxlU3a4hOJGN5kaWWQ0,7176
113
+ wayfinder_paths/strategies/basis_trading_strategy/__init__.py,sha256=kVcehFjBUtoi5xzSHI56jtDghsy0nYl6XIE6BI1l6aI,79
114
+ wayfinder_paths/strategies/basis_trading_strategy/constants.py,sha256=PJ1WtSALxiuW1FXx-BF30ciFISEhO5VBfrSZyfhPuz0,45
115
+ wayfinder_paths/strategies/basis_trading_strategy/examples.json,sha256=q2wlAH8Gr-LUJeamKzWL1EtChL3TBWe0HQ4_P-VCdqQ,429
116
+ wayfinder_paths/strategies/basis_trading_strategy/manifest.yaml,sha256=cmvAizwBP_SoXvypal8CEHLNh4Du5M_RBKy37ScUjL0,1078
117
+ wayfinder_paths/strategies/basis_trading_strategy/snapshot_mixin.py,sha256=pkYJ3Ax7quuJUZT_AjB6PFNPM3iDmEE6xpXGthXa5UY,38748
118
+ wayfinder_paths/strategies/basis_trading_strategy/strategy.py,sha256=pA11cJXTVuvwBiSc_BYsapshtKBK5FI_Xm-hKxJ9bhg,173962
119
+ wayfinder_paths/strategies/basis_trading_strategy/test_strategy.py,sha256=cFw191y1ud-dtb8jBMTvEbmvhZAXJmLkHaQ3BQBxlXg,28964
120
+ wayfinder_paths/strategies/basis_trading_strategy/types.py,sha256=rlbouTUOVPLfGPzMbsf-fUmMcn0R_OsG-IdfiBJmmqI,845
98
121
  wayfinder_paths/strategies/config.py,sha256=5dv-8tWwoxH3Sxd9jtiw90shrLipEe3UlU-IYUBfciM,2762
99
122
  wayfinder_paths/strategies/hyperlend_stable_yield_strategy/README.md,sha256=8mjDUBkBEYp_GWkM0knbFIbJ2Nmb-63pNR09ztZ67qo,4596
100
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/examples.json,sha256=i1OZXRmjRYXgmGk-_VqXR1hq7VuP6h40j-PWS1W3j-A,413
123
+ wayfinder_paths/strategies/hyperlend_stable_yield_strategy/examples.json,sha256=72lu80KAzPG2Bqu_ct1I0qsnEFVs-lurwCXuHZrefck,95
101
124
  wayfinder_paths/strategies/hyperlend_stable_yield_strategy/manifest.yaml,sha256=__YWl6MEeTBLbNWwUyZjQky0ok1T8B1m8dHPQWtW454,240
102
125
  wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py,sha256=VqHuuULeXZ5bA8g7cK9oD1kgXrK87N8Hxu8bnDBR1Cc,88820
103
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py,sha256=_7q9pFrqCUdf8eraK9tINs-6qyOCoX4-2AdL0z18wCY,12205
126
+ wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py,sha256=xXPYV45EivXvKPuq-3sJP4Ce5m9GWfGzG40miOtwmxI,13371
104
127
  wayfinder_paths/strategies/stablecoin_yield_strategy/README.md,sha256=Qj1b2bU5606pbZXsPf1WOtsx0erfBaXpRygxIDGVIgE,5211
105
128
  wayfinder_paths/strategies/stablecoin_yield_strategy/examples.json,sha256=pL1DNFEvYvXKK7xXD5oQYFPQj3Cm1ocKnk6r_iZk0IY,423
106
129
  wayfinder_paths/strategies/stablecoin_yield_strategy/manifest.yaml,sha256=rBb7-Fmub8twfKJgbBIiCWbwI2nLnuqBNyAJs36WhIg,750
107
- wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py,sha256=uYmXBjbTET8zFL3WLkcMWvJIbEJMzHezChKqlBGyLFY,70502
108
- wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py,sha256=PzBaUJf4HR7QV2fvt5QNIgLrwNocAd32k7q6dt7B40I,13074
130
+ wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py,sha256=6Ug2_cFx3nqw4Of5Oo1e9h1tQL1G3JXk2XcxNoq2Q0g,75607
131
+ wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py,sha256=StGLLqDwthmqYDKLo-Qo0XCUU0pEFD_H65smdxgpBGc,20125
109
132
  wayfinder_paths/templates/adapter/README.md,sha256=QcJ0cwXqqtj1VRK1wAs-unUphTPHdJwoIrIoSU4hTmA,3550
110
133
  wayfinder_paths/templates/adapter/adapter.py,sha256=8wdqcEwqb7XGUxl2gQvGnbFwhPi1h15ZJhB2lgtZieI,814
111
134
  wayfinder_paths/templates/adapter/examples.json,sha256=KLHy3AgPIplAaZN0qY2A-HBMa1xXkMhIyusORovTD9w,79
@@ -120,7 +143,7 @@ wayfinder_paths/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
120
143
  wayfinder_paths/tests/test_smoke_manifest.py,sha256=YjVzHTWys5o6Ae2cUuuJPhk-QgKxT1InDFHLjpouRiY,1267
121
144
  wayfinder_paths/tests/test_test_coverage.py,sha256=9NrZeVmP02D4W7Qc0XjciC05bhvdTCVibYjTGfa_GQk,7893
122
145
  wayfinder_paths/tests/test_utils.py,sha256=pxHT0QKFlyJeJo8bFnKXzWcOdi6t8rbJ0JFCBaFCBRQ,2112
123
- wayfinder_paths-0.1.6.dist-info/LICENSE,sha256=dYKnlkC_xosBAEQNUvB6cHMuhFgcUtN0oBR7E8_aR2Y,1066
124
- wayfinder_paths-0.1.6.dist-info/METADATA,sha256=la0fKZVElWMOQkPIfI-0nXUfsy3LmmsTJ4dqAC_CS9A,31321
125
- wayfinder_paths-0.1.6.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
126
- wayfinder_paths-0.1.6.dist-info/RECORD,,
146
+ wayfinder_paths-0.1.8.dist-info/LICENSE,sha256=dYKnlkC_xosBAEQNUvB6cHMuhFgcUtN0oBR7E8_aR2Y,1066
147
+ wayfinder_paths-0.1.8.dist-info/METADATA,sha256=xHD03utEsSU9sZijwc-UwDmK0kXBiUNUIcQgD0eDfXA,31404
148
+ wayfinder_paths-0.1.8.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
149
+ wayfinder_paths-0.1.8.dist-info/RECORD,,