wayfinder-paths 0.1.21__py3-none-any.whl → 0.1.23__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 (63) 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 +65 -169
  4. wayfinder_paths/adapters/balance_adapter/test_adapter.py +41 -113
  5. wayfinder_paths/adapters/brap_adapter/README.md +22 -75
  6. wayfinder_paths/adapters/brap_adapter/adapter.py +187 -576
  7. wayfinder_paths/adapters/brap_adapter/examples.json +21 -140
  8. wayfinder_paths/adapters/brap_adapter/test_adapter.py +6 -234
  9. wayfinder_paths/adapters/hyperlend_adapter/adapter.py +39 -86
  10. wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +5 -1
  11. wayfinder_paths/adapters/hyperliquid_adapter/adapter.py +6 -5
  12. wayfinder_paths/adapters/ledger_adapter/README.md +4 -1
  13. wayfinder_paths/adapters/ledger_adapter/adapter.py +3 -3
  14. wayfinder_paths/adapters/moonwell_adapter/adapter.py +108 -198
  15. wayfinder_paths/adapters/moonwell_adapter/test_adapter.py +37 -23
  16. wayfinder_paths/adapters/token_adapter/adapter.py +14 -0
  17. wayfinder_paths/core/__init__.py +0 -3
  18. wayfinder_paths/core/clients/BRAPClient.py +3 -0
  19. wayfinder_paths/core/clients/ClientManager.py +0 -7
  20. wayfinder_paths/core/clients/LedgerClient.py +196 -172
  21. wayfinder_paths/core/clients/WayfinderClient.py +0 -1
  22. wayfinder_paths/core/clients/__init__.py +0 -5
  23. wayfinder_paths/core/clients/protocols.py +0 -13
  24. wayfinder_paths/core/config.py +0 -164
  25. wayfinder_paths/core/constants/__init__.py +58 -2
  26. wayfinder_paths/core/constants/base.py +8 -22
  27. wayfinder_paths/core/constants/chains.py +36 -0
  28. wayfinder_paths/core/constants/contracts.py +39 -0
  29. wayfinder_paths/core/constants/tokens.py +9 -0
  30. wayfinder_paths/core/strategies/Strategy.py +0 -10
  31. wayfinder_paths/core/utils/evm_helpers.py +5 -15
  32. wayfinder_paths/core/utils/tokens.py +28 -0
  33. wayfinder_paths/core/utils/transaction.py +13 -7
  34. wayfinder_paths/core/utils/web3.py +5 -3
  35. wayfinder_paths/policies/enso.py +1 -2
  36. wayfinder_paths/policies/hyper_evm.py +6 -3
  37. wayfinder_paths/policies/hyperlend.py +1 -2
  38. wayfinder_paths/policies/moonwell.py +12 -7
  39. wayfinder_paths/policies/prjx.py +1 -3
  40. wayfinder_paths/run_strategy.py +97 -300
  41. wayfinder_paths/strategies/basis_trading_strategy/constants.py +3 -1
  42. wayfinder_paths/strategies/basis_trading_strategy/strategy.py +19 -14
  43. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +12 -11
  44. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +20 -33
  45. wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py +21 -18
  46. wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +69 -130
  47. wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +32 -42
  48. {wayfinder_paths-0.1.21.dist-info → wayfinder_paths-0.1.23.dist-info}/METADATA +3 -4
  49. {wayfinder_paths-0.1.21.dist-info → wayfinder_paths-0.1.23.dist-info}/RECORD +51 -60
  50. {wayfinder_paths-0.1.21.dist-info → wayfinder_paths-0.1.23.dist-info}/WHEEL +1 -1
  51. wayfinder_paths/core/clients/WalletClient.py +0 -41
  52. wayfinder_paths/core/engine/StrategyJob.py +0 -110
  53. wayfinder_paths/core/services/test_local_evm_txn.py +0 -145
  54. wayfinder_paths/templates/adapter/README.md +0 -150
  55. wayfinder_paths/templates/adapter/adapter.py +0 -16
  56. wayfinder_paths/templates/adapter/examples.json +0 -8
  57. wayfinder_paths/templates/adapter/test_adapter.py +0 -30
  58. wayfinder_paths/templates/strategy/README.md +0 -186
  59. wayfinder_paths/templates/strategy/examples.json +0 -11
  60. wayfinder_paths/templates/strategy/strategy.py +0 -35
  61. wayfinder_paths/templates/strategy/test_strategy.py +0 -166
  62. wayfinder_paths/tests/test_smoke_manifest.py +0 -63
  63. {wayfinder_paths-0.1.21.dist-info → wayfinder_paths-0.1.23.dist-info}/LICENSE +0 -0
@@ -47,17 +47,14 @@ def strategy():
47
47
  )
48
48
 
49
49
  if hasattr(s, "balance_adapter") and s.balance_adapter:
50
- usdc_balance_mock = AsyncMock(return_value=(True, 60000000))
51
- gas_balance_mock = AsyncMock(return_value=(True, 2000000000000000))
52
50
 
53
- def get_balance_side_effect(query, wallet_address, **kwargs):
54
- token_id = (
55
- query if isinstance(query, str) else (query or {}).get("token_id")
56
- )
51
+ def get_balance_side_effect(
52
+ *, wallet_address, token_id=None, token_address=None, chain_id=None
53
+ ):
57
54
  if token_id == "usd-coin-base" or token_id == "usd-coin":
58
- return usdc_balance_mock.return_value
55
+ return (True, 60000000)
59
56
  elif token_id == "ethereum-base" or token_id == "ethereum":
60
- return gas_balance_mock.return_value
57
+ return (True, 2000000000000000)
61
58
  return (True, 1000000000)
62
59
 
63
60
  s.balance_adapter.get_balance = AsyncMock(side_effect=get_balance_side_effect)
@@ -111,10 +108,10 @@ def strategy():
111
108
 
112
109
  if hasattr(s, "balance_adapter") and s.balance_adapter:
113
110
  s.balance_adapter.move_from_main_wallet_to_strategy_wallet = AsyncMock(
114
- return_value=(True, "Transfer successful (simulated)")
111
+ return_value=(True, "0xtxhash_transfer")
115
112
  )
116
113
  s.balance_adapter.move_from_strategy_wallet_to_main_wallet = AsyncMock(
117
- return_value=(True, "Transfer successful (simulated)")
114
+ return_value=(True, "0xtxhash_transfer")
118
115
  )
119
116
 
120
117
  if hasattr(s, "ledger_adapter") and s.ledger_adapter:
@@ -154,46 +151,36 @@ def strategy():
154
151
 
155
152
  if hasattr(s, "brap_adapter") and s.brap_adapter:
156
153
 
157
- def get_swap_quote_side_effect(*args, **kwargs):
154
+ def best_quote_side_effect(*args, **kwargs):
158
155
  to_token_address = kwargs.get("to_token_address", "")
159
156
  if to_token_address == "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913":
160
- return (
161
- True,
162
- {
163
- "quotes": {
164
- "best_quote": {
165
- "output_amount": "99900000",
166
- }
167
- }
168
- },
169
- )
157
+ return (True, {"output_amount": "99900000"})
170
158
  return (
171
159
  True,
172
160
  {
173
- "quotes": {
174
- "best_quote": {
175
- "output_amount": "105000000",
176
- "input_amount": "50000000000000",
177
- "toAmount": "105000000",
178
- "estimatedGas": "1000000000",
179
- "fromAmount": "100000000",
180
- "fromToken": {"symbol": "USDC"},
181
- "toToken": {"symbol": "POOL"},
182
- }
183
- }
161
+ "output_amount": "105000000",
162
+ "input_amount": "50000000000000",
163
+ "toAmount": "105000000",
164
+ "estimatedGas": "1000000000",
165
+ "fromAmount": "100000000",
166
+ "fromToken": {"symbol": "USDC"},
167
+ "toToken": {"symbol": "POOL"},
184
168
  },
185
169
  )
186
170
 
187
- s.brap_adapter.get_swap_quote = AsyncMock(
188
- side_effect=get_swap_quote_side_effect
189
- )
171
+ s.brap_adapter.best_quote = AsyncMock(side_effect=best_quote_side_effect)
190
172
 
191
173
  if (
192
174
  hasattr(s, "brap_adapter")
193
175
  and s.brap_adapter
194
176
  and hasattr(s.brap_adapter, "swap_from_quote")
195
177
  ):
196
- s.brap_adapter.swap_from_quote = AsyncMock(return_value=None)
178
+ s.brap_adapter.swap_from_quote = AsyncMock(
179
+ return_value=(
180
+ True,
181
+ {"tx_hash": "0xmockhash", "from_amount": "100", "to_amount": "99"},
182
+ )
183
+ )
197
184
 
198
185
  s.DEPOSIT_USDC = 0
199
186
  s.usdc_token_info = {
@@ -426,8 +413,9 @@ async def test_sweep_wallet_uses_tracked_tokens(strategy):
426
413
  assert "token-2" in strategy.tracked_token_ids
427
414
 
428
415
  # Mock balance adapter to return fresh balances
429
- async def get_balance_mock(query, **kwargs):
430
- token_id = query if isinstance(query, str) else (query or {}).get("token_id")
416
+ def get_balance_mock(
417
+ *, wallet_address, token_id=None, token_address=None, chain_id=None
418
+ ):
431
419
  balance = strategy.tracked_balances.get(token_id, 0)
432
420
  return (True, int(balance) if balance else 0)
433
421
 
@@ -468,8 +456,9 @@ async def test_get_non_gas_balances_uses_tracked_state(strategy):
468
456
  strategy._track_token(pool_token_id, 50000000000000000000)
469
457
 
470
458
  # Mock refresh
471
- def _get_balance_effect(query, **kwargs):
472
- token_id = query if isinstance(query, str) else (query or {}).get("token_id")
459
+ def _get_balance_effect(
460
+ *, wallet_address, token_id=None, token_address=None, chain_id=None
461
+ ):
473
462
  return (True, strategy.tracked_balances.get(token_id, 0))
474
463
 
475
464
  strategy.balance_adapter.get_balance = AsyncMock(side_effect=_get_balance_effect)
@@ -488,8 +477,9 @@ async def test_partial_liquidate_uses_tracked_tokens(strategy):
488
477
  strategy._track_token("test-pool-base", 100000000000000000000)
489
478
 
490
479
  # Mock balance and token adapters
491
- def _get_balance_effect_partial(query, **kwargs):
492
- token_id = query if isinstance(query, str) else (query or {}).get("token_id")
480
+ def _get_balance_effect_partial(
481
+ *, wallet_address, token_id=None, token_address=None, chain_id=None
482
+ ):
493
483
  return (True, strategy.tracked_balances.get(token_id, 0))
494
484
 
495
485
  strategy.balance_adapter.get_balance = AsyncMock(
@@ -1,17 +1,16 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: wayfinder-paths
3
- Version: 0.1.21
3
+ Version: 0.1.23
4
4
  Summary: Wayfinder Path: strategies and adapters
5
5
  Author: Wayfinder
6
6
  Author-email: dev@wayfinder.ai
7
7
  Requires-Python: >=3.12,<4.0
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: Programming Language :: Python :: 3.12
10
- Classifier: Programming Language :: Python :: 3.13
11
10
  Requires-Dist: aiohttp (>=3.13.0,<4.0.0)
12
11
  Requires-Dist: eth-account (>=0.13.7,<0.14.0)
13
12
  Requires-Dist: httpx (>=0.28.1,<0.29.0)
14
- Requires-Dist: hyperliquid-python-sdk (>=0.21.0,<0.22.0)
13
+ Requires-Dist: hyperliquid-felix
15
14
  Requires-Dist: loguru (>=0.7.3,<0.8.0)
16
15
  Requires-Dist: numpy (>=1.26.0,<2.0.0)
17
16
  Requires-Dist: pandas (>=2.2.0,<3.0.0)
@@ -98,7 +97,7 @@ Strategy Layer - Trading logic (deposit, update, withdraw, exit)
98
97
 
99
98
  Adapter Layer - Protocol integrations (BalanceAdapter, PoolAdapter, etc.)
100
99
 
101
- Client Layer - API wrappers (TokenClient, WalletClient, PoolClient, etc.)
100
+ Client Layer - API wrappers (TokenClient, PoolClient, LedgerClient, etc.)
102
101
 
103
102
  Network - RPCs, Wayfinder API, external services
104
103
  ```
@@ -1,19 +1,19 @@
1
- wayfinder_paths/__init__.py,sha256=xKU94QbtPMmpY-Y3ktZfHwC7Rgaspl69GE8a8LQdAHs,337
1
+ wayfinder_paths/__init__.py,sha256=9BJHuTJIFFa1dLrY45VWjdJI-m0NchcGJej4lC1jN-U,230
2
2
  wayfinder_paths/adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- wayfinder_paths/adapters/balance_adapter/README.md,sha256=mq4cSYrrW5TNcXKnGBg9PwQcjCYZtXFNzEAfNGYumb8,2402
4
- wayfinder_paths/adapters/balance_adapter/adapter.py,sha256=VrttK4gyZQbszU2qLYYKQSEdx09tyAow88ukoYvHL4c,10084
3
+ wayfinder_paths/adapters/balance_adapter/README.md,sha256=xek-ZekUPDCUEiyciSYHOp3Z_QA1bgEW1RzXvwTySVE,2363
4
+ wayfinder_paths/adapters/balance_adapter/adapter.py,sha256=pbB8O5rphic6HGTYSLtVwe86AipohSCE-W59kyIagAA,6305
5
5
  wayfinder_paths/adapters/balance_adapter/examples.json,sha256=3R1M4B_VsIy29viAuFT9nQbnQShWl8ZbU-rnSNWUW9U,129
6
- wayfinder_paths/adapters/balance_adapter/test_adapter.py,sha256=gf7WlA-RkMmSDP1jIYi0hUXkMfqfGTjzUZjQa9H07nU,5334
7
- wayfinder_paths/adapters/brap_adapter/README.md,sha256=u_UZNB3RBLAHrwklgd-ZPftNiIpIutzfH1FulJ4QB-Y,2673
6
+ wayfinder_paths/adapters/balance_adapter/test_adapter.py,sha256=ijB1wsKoyMH3eYfvAow6trhFh1Go_l5EXJNplRHrxY8,3169
7
+ wayfinder_paths/adapters/brap_adapter/README.md,sha256=ZzVTYvVmQ-J8PakH2iy_oBKT1YwTEhkOtluCpZFcK1Q,1466
8
8
  wayfinder_paths/adapters/brap_adapter/__init__.py,sha256=Hx4JW1tDijXS5YQhVliE0syw1RD1YKO2MM37wN_to9M,60
9
- wayfinder_paths/adapters/brap_adapter/adapter.py,sha256=z_uGXGx8IHd2fBXZUbnjFeAwX5mZCrM1c46ToIDEhqM,26210
10
- wayfinder_paths/adapters/brap_adapter/examples.json,sha256=FGZhNaMCAQ56KhovEGSsV1BHOcMd_QqQBNmCU6m8zfQ,5389
11
- wayfinder_paths/adapters/brap_adapter/test_adapter.py,sha256=CmK8TUxmnf4IzExToJ68FgUyE4FB7B2IOeB6GF5-B0E,11361
9
+ wayfinder_paths/adapters/brap_adapter/adapter.py,sha256=3DeYmsF1v830dfs9VBfNup7o7WOYc0929dUBbvla2ck,10881
10
+ wayfinder_paths/adapters/brap_adapter/examples.json,sha256=XBr7JqtSLyECs9XywZ6oJ9OXJ0TaPPpwCzHcqQZOxCg,1994
11
+ wayfinder_paths/adapters/brap_adapter/test_adapter.py,sha256=YZq6I0S895ZKPbwv_TbdPjwlIfRVIRf-DVqQhitIvqc,2924
12
12
  wayfinder_paths/adapters/hyperlend_adapter/__init__.py,sha256=IDgYOx5rF2Zd8DjZ_VzmZc6EUGS34SfIVQ_M1PdZ0YQ,112
13
- wayfinder_paths/adapters/hyperlend_adapter/adapter.py,sha256=y7zy09-bkCiYTsE3E3-DoWe8A4ft4pHzuQ527oyxGFE,9625
14
- wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py,sha256=f7YEJTT8o8FdN8OmDFuNYcIZRZ99kCAWcDHEFsgYFIQ,10884
13
+ wayfinder_paths/adapters/hyperlend_adapter/adapter.py,sha256=-8MXTp36BsQU1ZAyB9QDjH20gX8LKN4EtGhUv0yR-GA,7971
14
+ wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py,sha256=e6bk1ilvQJ17nHCk3RFPLxcgD_OohrUyW8Ejk1Gu3yE,11028
15
15
  wayfinder_paths/adapters/hyperliquid_adapter/__init__.py,sha256=QpA258RzVbxzsha86HQduAuNVG0g0qvsI5OcZunQ8DQ,467
16
- wayfinder_paths/adapters/hyperliquid_adapter/adapter.py,sha256=GCI4up7fGuyiiYd_5zw00y497UdggjDSJ_G-ZhU_tgA,25217
16
+ wayfinder_paths/adapters/hyperliquid_adapter/adapter.py,sha256=0rU8ZKBqhXo6KoXBR_D2OdjSvcLlf7IVPly-fhIMmIQ,25159
17
17
  wayfinder_paths/adapters/hyperliquid_adapter/executor.py,sha256=h7Kwcj1R6udb-m_ckw8LHdNZ_gsfvBTSCosY-4tWjSk,16277
18
18
  wayfinder_paths/adapters/hyperliquid_adapter/paired_filler.py,sha256=FFRZJVkZMvcIfzvyttNcAdvAAdpMoiz1oBMPcfpQ1TU,35193
19
19
  wayfinder_paths/adapters/hyperliquid_adapter/test_adapter.py,sha256=3533NANBEAGYpisXWF7u6lxF8e3LyqLmlL-C3HIWZ1Q,3847
@@ -21,15 +21,15 @@ wayfinder_paths/adapters/hyperliquid_adapter/test_adapter_live.py,sha256=7hWBW2y
21
21
  wayfinder_paths/adapters/hyperliquid_adapter/test_executor.py,sha256=w3iXOx7JfS54E05Zr-hxzKSe3mr5dtLloUrQ6LyJyao,3746
22
22
  wayfinder_paths/adapters/hyperliquid_adapter/test_utils.py,sha256=BhsymEuDfaRlRhEX1qcWAZmmgnJPno84dupV1Q2aX-A,5604
23
23
  wayfinder_paths/adapters/hyperliquid_adapter/utils.py,sha256=J0UcXR60BHLj147qMZHocrcvIQ71GhGx90u3JDZ3gg8,3838
24
- wayfinder_paths/adapters/ledger_adapter/README.md,sha256=qdKwZTiLyjD21zI_LTipiT44tNTPA-N7YEklQD8laoQ,2482
24
+ wayfinder_paths/adapters/ledger_adapter/README.md,sha256=hxBXJg_wfH7gDTYqUL6yXkDARKTb1zdyYYIIxbvQMDQ,2574
25
25
  wayfinder_paths/adapters/ledger_adapter/__init__.py,sha256=CrFEf6_7I27g5CQPPOAFYzQvm33IpdkbQHCKiDdwiWk,64
26
- wayfinder_paths/adapters/ledger_adapter/adapter.py,sha256=6K6N0Xjjw_ZxnraJ30NijaNlnD1HQQ5lDCHzsy8Pzvg,6628
26
+ wayfinder_paths/adapters/ledger_adapter/adapter.py,sha256=Ei0Dhj7nSki67ZF8MQP-WJbXVhNtaOlYasgzndtKcO4,6661
27
27
  wayfinder_paths/adapters/ledger_adapter/examples.json,sha256=DdqTSe4vnBrfIycQVQQ_JZom7fBGHbL7MR4ppK9ljCY,3936
28
28
  wayfinder_paths/adapters/ledger_adapter/test_adapter.py,sha256=haPVZQGL0f-vZPvNMUcfoq63Bu7F4FumVBuAJKiRmwg,6827
29
29
  wayfinder_paths/adapters/moonwell_adapter/README.md,sha256=A-xKZo4ssLh1-uJqlp9ihMrnlZ8hB-KW2e0MRH4pnhU,3036
30
30
  wayfinder_paths/adapters/moonwell_adapter/__init__.py,sha256=5wMDRIM6z0QbSqKEqaV8tUGkpwrAABqz1T0hP4YJbMg,109
31
- wayfinder_paths/adapters/moonwell_adapter/adapter.py,sha256=V6qoIOQm7JZqPgJRE435Q7zJOHifNooSc0J_KTDbbQI,39518
32
- wayfinder_paths/adapters/moonwell_adapter/test_adapter.py,sha256=Uv9jtHJEifAZ_IUafo5e5tsNkjslAhFhnZqRkwmxXQ0,25391
31
+ wayfinder_paths/adapters/moonwell_adapter/adapter.py,sha256=z5xbYENfrFvlJ7oqH5qWcns8CyvdwQ8Jyjt0y-O8c3c,36362
32
+ wayfinder_paths/adapters/moonwell_adapter/test_adapter.py,sha256=AN142y4eI5kb7MA5fg75U8hVbgbB2tfSfIVI3iJi9b8,25773
33
33
  wayfinder_paths/adapters/pool_adapter/README.md,sha256=qxXNcTgxQ4-YEDC-ZHiQ5wTpV_76t-vK58vyDh0IBgU,1282
34
34
  wayfinder_paths/adapters/pool_adapter/__init__.py,sha256=LTbty0SuACoj3X5yeGESDUdtJQt8zyB2Loq8BuEp7rE,60
35
35
  wayfinder_paths/adapters/pool_adapter/adapter.py,sha256=NHxtFOt10l320AClQUWchUVrQp0ivST25UOczS7aYeQ,1298
@@ -37,11 +37,11 @@ wayfinder_paths/adapters/pool_adapter/examples.json,sha256=NW-7J6_zXxky8uMDRym3j
37
37
  wayfinder_paths/adapters/pool_adapter/test_adapter.py,sha256=GGocdzXbeZMYXeVy7SOkY_ifC719rwYdqTIwQoxRJSo,2262
38
38
  wayfinder_paths/adapters/token_adapter/README.md,sha256=JlZhT6MK3gYQ73uJU-DOrEx5eMZXvqceqrawJqNdygI,1623
39
39
  wayfinder_paths/adapters/token_adapter/__init__.py,sha256=nEmxrvffEygn3iKH3cZTNLkhnUUhlUAEtshmrFRAjq8,62
40
- wayfinder_paths/adapters/token_adapter/adapter.py,sha256=3qZ9vHdCEMeMzbcFCh4ZE3VYTQ0OWKsRihNilop8wyI,2751
40
+ wayfinder_paths/adapters/token_adapter/adapter.py,sha256=WmNU8-qQoR1DjNMBKBLI7Lv8iWRdS4MItl7LBOyjI1c,3257
41
41
  wayfinder_paths/adapters/token_adapter/examples.json,sha256=bvwP9XL9c_endFlMQgkavXh_IzNEEUyJd4gh5QjrcqY,2944
42
42
  wayfinder_paths/adapters/token_adapter/test_adapter.py,sha256=jDenD0BYbbb_xE3jKrA84io8iVEcvjk5SExf6UjQ410,3980
43
43
  wayfinder_paths/conftest.py,sha256=1KWNevxGIsnZfgUntkF2qo2fqfE7Wr-lM5km01gMcHo,816
44
- wayfinder_paths/core/__init__.py,sha256=nwf9NigPlXUDAqXpYNOQGBdjwMyvj40RdNTMEklqBH0,363
44
+ wayfinder_paths/core/__init__.py,sha256=sVbC4eAGYolLE48ZhmbRVE8qsTd5KAA_R5TeskJRXro,257
45
45
  wayfinder_paths/core/adapters/BaseAdapter.py,sha256=PnzwbUOyHDrmBlUeJWO4KHYDxpkLiGK_TWCAsJ-7Vg0,1326
46
46
  wayfinder_paths/core/adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
47
  wayfinder_paths/core/adapters/models.py,sha256=bopGe59hFtvMqFdMfI4M04Nh5-f1O8orGzJyA7qfY64,891
@@ -49,81 +49,72 @@ wayfinder_paths/core/analytics/__init__.py,sha256=d_upri6nw5-oUdhOCb45P-ojAqpb0J
49
49
  wayfinder_paths/core/analytics/bootstrap.py,sha256=npbLf9Jzx0tl4fHVumeUID5NnBwyHnjbQdIg7Ol-s-Y,1194
50
50
  wayfinder_paths/core/analytics/stats.py,sha256=5JzhHEHivXuK5xvQa9BWgkpRD7WwVvQdJDGuILlS7Pc,1161
51
51
  wayfinder_paths/core/analytics/test_analytics.py,sha256=COyUP9UBhE6471z9lQA2yM51SNKXZz0i3bkBztcilbs,4193
52
- wayfinder_paths/core/clients/BRAPClient.py,sha256=tlB0DpoTfWPBHfH_UcXgxU3jH6M3CAenbw4Isfq1GJM,3229
53
- wayfinder_paths/core/clients/ClientManager.py,sha256=J86ENEXaPt92LOa9WbZMjJCX5RCwqGRxjwSMmydeq3M,2481
52
+ wayfinder_paths/core/clients/BRAPClient.py,sha256=HaSi1TH4VD5MdA9oqt2m6F3_GYJrrpVBdXzERwrVz8A,3343
53
+ wayfinder_paths/core/clients/ClientManager.py,sha256=rNGGcqU9Y7gdnlkNlXtWUW2EB8W50I7i-sxQVc8IZT8,2179
54
54
  wayfinder_paths/core/clients/HyperlendClient.py,sha256=_10Hrbo3M4VbW3Nwlt1_rJMrz955u_AIanQotG0fwE8,5508
55
- wayfinder_paths/core/clients/LedgerClient.py,sha256=IHjJtKXYMgCdIhykyCTDwrrVOCucafLFBJOQtoe3Bz0,10230
55
+ wayfinder_paths/core/clients/LedgerClient.py,sha256=9PtXW2o_WZGfvu7wIwBuCPzXYex2B1rsMDN70tKgJeA,11713
56
56
  wayfinder_paths/core/clients/PoolClient.py,sha256=ij0aVwV73UiUndOmBrtpg1BhalSIr_Ab78pP7xQQHzY,4266
57
57
  wayfinder_paths/core/clients/TokenClient.py,sha256=5yZiVcuGV4FTEUIRhjaSxGU8CChf3Qf1H5rLkviVLCY,3141
58
- wayfinder_paths/core/clients/WalletClient.py,sha256=sjPLmzuAnY_NOSsDIoIViPRXKeHvp1s1uOf1W4E6bpk,1215
59
- wayfinder_paths/core/clients/WayfinderClient.py,sha256=OKMuKKxfg3O2tNlZeywIZHpDQX7RWgKjiN0hy8BT_rI,3555
60
- wayfinder_paths/core/clients/__init__.py,sha256=wrQQ4_Lfgc3kHiqO-jDCVFqtZxeOpDvth73GMhakC0E,1122
61
- wayfinder_paths/core/clients/protocols.py,sha256=97VCgOq5Z9IoVrmzMS4aR3WfbaNfSuiNG2ikNO7lz2o,5604
62
- wayfinder_paths/core/config.py,sha256=GUKtDpS7-jlb-KxVT_1l4XuO93pu2qr4IgUKWbnYRs8,7007
63
- wayfinder_paths/core/constants/__init__.py,sha256=k_PUZFCfCsPkUOcpDCniKKbJhomTnOFrVVRW6qyNzuU,315
64
- wayfinder_paths/core/constants/base.py,sha256=lV2oSIuqXZfCXQcgIlwBcNNcShsZrkHwuQ-Fx61kiQI,1178
58
+ wayfinder_paths/core/clients/WayfinderClient.py,sha256=4ySx6Hpx54tbg5dSHTJ9Tcv12p3ahvfyQx8i37AGx5A,3519
59
+ wayfinder_paths/core/clients/__init__.py,sha256=8JbfbYKnVlXwEp9gbFKMY41xh-kQ9BTfC_QLZ9VhYS8,951
60
+ wayfinder_paths/core/clients/protocols.py,sha256=akkUD4LuxoNhjtsLwtylV3Ms3LNmXUSq4etA9ldRFBY,5289
61
+ wayfinder_paths/core/config.py,sha256=LhipEoC384EdUlKOmW-R5u6-kDW4KHzAj-wkseSBhYg,1003
62
+ wayfinder_paths/core/constants/__init__.py,sha256=YcsGM3iV6R2KNybhF22OPqKZT1rNvIEMiYR4bjH36Rk,1726
63
+ wayfinder_paths/core/constants/base.py,sha256=pxnIWM5b4GJ2lBJ7plzxw0QOgyAm8ZfIJ4SBY4qZqX0,552
64
+ wayfinder_paths/core/constants/chains.py,sha256=DA03zVjukRGndBB2EROaxvc1uW8bt2550ySh9Cn2J34,729
65
+ wayfinder_paths/core/constants/contracts.py,sha256=XdH5cHOh4JSBTf9BR-Z0VGPP1l1TtOlzCIXcK5l06Uc,1640
65
66
  wayfinder_paths/core/constants/erc20_abi.py,sha256=-eN5Or7J2K9PoGrvLpNd0fDIGdcC5_XCHfzaOZyNaUE,2733
66
67
  wayfinder_paths/core/constants/hyperlend_abi.py,sha256=999Y2lKM35gMvYbiHVa0i8HK7e5Th6Q-DD5kB9nrFS4,4110
67
68
  wayfinder_paths/core/constants/moonwell_abi.py,sha256=DFpM3_6j0n6-zu2M5qdCAD3Ss2sMZEXOHyHEPjG1tjY,11634
68
- wayfinder_paths/core/engine/StrategyJob.py,sha256=zR02cV4DXuw4RU8_GE_VOmyuQRH5fxt7xzxpai6qRf8,4042
69
- wayfinder_paths/core/services/test_local_evm_txn.py,sha256=tmP3pt4QBihA6T3PgCSd8hjBkVh4ImNtKGFiFKOkWWA,4829
70
- wayfinder_paths/core/strategies/Strategy.py,sha256=5fB1eLsy1hNqQ7_l4GrtS2wD90UooDNYSlRL3aiKgGA,6449
69
+ wayfinder_paths/core/constants/tokens.py,sha256=lkpZXRJcnygcNKVvrIBgnUozPvcbpHT-BkqqpEG9Xug,326
70
+ wayfinder_paths/core/strategies/Strategy.py,sha256=Nfv5406CKyK04U2319wkjbcBlK0Lbz_7qNiBC8YSEyc,5973
71
71
  wayfinder_paths/core/strategies/__init__.py,sha256=r3v5Eriz5mb7vurIGxB-2Hzo4ZApGt8dZ8OFf0lwCWk,105
72
72
  wayfinder_paths/core/strategies/base.py,sha256=-s0qeiGZl5CHTUL2PavGXM7ACkNlaa0c4jeZR_4DuBM,155
73
73
  wayfinder_paths/core/strategies/descriptors.py,sha256=2Olef0VWols1CWb-TWcb5pil2rztC0jP6F_Trpv2hIw,1958
74
74
  wayfinder_paths/core/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
- wayfinder_paths/core/utils/evm_helpers.py,sha256=VIXDd_4uDrnttqqapoPGd1PCfmWzX1T_CsMZ1bPe77w,4147
76
- wayfinder_paths/core/utils/tokens.py,sha256=G7hHILLaFKw88uA0W03Qoeb1bgY10Y5yWoxydoSNS3M,3488
77
- wayfinder_paths/core/utils/transaction.py,sha256=OC-hig-H9IeCLFh64Hal2y-Du7RCK2ka7KjBohEV17c,6729
75
+ wayfinder_paths/core/utils/evm_helpers.py,sha256=m_h9eMjcMW5a3Di6PGkpZOwpZkZ-tVdwiLsTZqFJacE,3809
76
+ wayfinder_paths/core/utils/tokens.py,sha256=bSrfu1_58SKcc75j5u01mp1upKWdnMllbo2xUMCxDAs,4328
77
+ wayfinder_paths/core/utils/transaction.py,sha256=sSJQmF7oXpxtfVezf-d6dEhUVpiDIfUTjRkyMXdLig4,6963
78
78
  wayfinder_paths/core/utils/wallets.py,sha256=ccCQ128lDShO265AFMOCdijzPLucWe-Neg5wjLrOsnk,1948
79
- wayfinder_paths/core/utils/web3.py,sha256=r0vHvKvFC167MygHhmxr2nfYtLYN0ttSUEI--hPetO0,1877
80
- wayfinder_paths/policies/enso.py,sha256=oytco04eeGjiRbZPGFE1YpH4NxvV0tfVM14QmlyzjkY,428
79
+ wayfinder_paths/core/utils/web3.py,sha256=pRtoiFViBZSnuXFVWX8yAHew9je9RHG6s5xuzJVoZz0,1948
80
+ wayfinder_paths/policies/enso.py,sha256=JdmjzGBrIBsqq0nTQN5sbWbcGk5wktoxqAIl9NIvHV0,433
81
81
  wayfinder_paths/policies/erc20.py,sha256=K5PQCUivBrU2nYmIdsIARzRiFy36Rijver-RJnaxNT8,960
82
82
  wayfinder_paths/policies/evm.py,sha256=8fJpjAl6XVxr51sVMw_VkWmIaI_lj2T7qrLcR8_sWgs,713
83
- wayfinder_paths/policies/hyper_evm.py,sha256=wLkrE158rPaDjfU5q-PyRXuQ6KA67VcqWo484UHsLb8,649
84
- wayfinder_paths/policies/hyperlend.py,sha256=4u0NP80t7rpHlw_nvParUN90sIXypWyXACfE0OPqFys,370
83
+ wayfinder_paths/policies/hyper_evm.py,sha256=WNbU2JjWa236HY3AxeQLO6ofFmKoU0bFboTt8KWZVmY,641
84
+ wayfinder_paths/policies/hyperlend.py,sha256=70Zf133lL0Q1HudaZlFEcqINeAYkU5SEncONDMYrb-o,375
85
85
  wayfinder_paths/policies/hyperliquid.py,sha256=hAxNtWdxavwf_a-AnlXMOmEYakkNBkrPTrvprIQqBDQ,796
86
- wayfinder_paths/policies/moonwell.py,sha256=sKWLbruMKiW7Yh1DhXdVPRe0JBP-nooNybRz0G9PgvA,1605
87
- wayfinder_paths/policies/prjx.py,sha256=6kfZ6OQFroFHYJl4vSWT-svwwfvoHlS_ZrcHt8nmZMU,743
86
+ wayfinder_paths/policies/moonwell.py,sha256=aWp3ZgB_NWWuJuIo6idGEiCQN3DRqigXm5ButDRzjAM,1622
87
+ wayfinder_paths/policies/prjx.py,sha256=ncXOGXTkSrzPgtw2VhIC-ep3Il5-V4o9kRX_etIOEEM,702
88
88
  wayfinder_paths/policies/util.py,sha256=r8xQLPvE3kU21_LG6VbkFI9sUSYltcsKunryZdHOUDA,912
89
- wayfinder_paths/run_strategy.py,sha256=C0uwRlq2Xy1ASgC8Z8SjQZvHY8t4-Y8b0T_5UxEdJ2Y,11858
89
+ wayfinder_paths/run_strategy.py,sha256=n2beh0jxi88jNr0nhijz6lP4O77F9j10zFnjQyjugyU,5036
90
90
  wayfinder_paths/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
91
91
  wayfinder_paths/scripts/create_strategy.py,sha256=s9rQd880VbSSwOJdwjtOLfdW5evZqes69f5tm6VsrhQ,4688
92
92
  wayfinder_paths/scripts/make_wallets.py,sha256=vKcf7g0QX9pCpQGVImoychzV70hvHpfMo7d0_wxd-js,4980
93
93
  wayfinder_paths/strategies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
94
94
  wayfinder_paths/strategies/basis_trading_strategy/README.md,sha256=kZtG5NVVZwWsuz65n2SrwPMUGow9xsfIRplbHI0ARgE,3540
95
95
  wayfinder_paths/strategies/basis_trading_strategy/__init__.py,sha256=kVcehFjBUtoi5xzSHI56jtDghsy0nYl6XIE6BI1l6aI,79
96
- wayfinder_paths/strategies/basis_trading_strategy/constants.py,sha256=PJ1WtSALxiuW1FXx-BF30ciFISEhO5VBfrSZyfhPuz0,45
96
+ wayfinder_paths/strategies/basis_trading_strategy/constants.py,sha256=dYQn_297CB1x9whic8YEMdEig0vibclDGCasjJL10mI,122
97
97
  wayfinder_paths/strategies/basis_trading_strategy/examples.json,sha256=q2wlAH8Gr-LUJeamKzWL1EtChL3TBWe0HQ4_P-VCdqQ,429
98
98
  wayfinder_paths/strategies/basis_trading_strategy/snapshot_mixin.py,sha256=F324ILz9w6uT7fkOVUa7gltp2LMEyGBlw3tz-ANcff8,37634
99
- wayfinder_paths/strategies/basis_trading_strategy/strategy.py,sha256=g51mw8iSjW4p21XF3QWNzbN1ksMShS4tGllfAkzhIbc,146949
99
+ wayfinder_paths/strategies/basis_trading_strategy/strategy.py,sha256=jyvOje3O7bI__CFzSumnfZtH8i8HyRnlOLqpafwHu9Q,147072
100
100
  wayfinder_paths/strategies/basis_trading_strategy/test_strategy.py,sha256=SJoCR9PcyXzdd8--6LCySc27B5rjgUeQrbALMouFOLU,35306
101
101
  wayfinder_paths/strategies/basis_trading_strategy/types.py,sha256=xTkLYqwvS0meMdlRAvIKNH9AANRyz63bQSYFSxLI6n4,740
102
102
  wayfinder_paths/strategies/hyperlend_stable_yield_strategy/README.md,sha256=cqCmcWIPiOpCwt-82dnOgHnN64ZUITITR3jqIUYDXmA,2906
103
103
  wayfinder_paths/strategies/hyperlend_stable_yield_strategy/examples.json,sha256=GbVo2p6QiG6M7Ma5s671lw8G9JwnMl1h0n9mrtt-ZS8,164
104
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py,sha256=8qwYmREVq-CDBS91pZfCxgBTKYr7ePfXbakHCkmX3Fw,92955
105
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py,sha256=5DZiu1Sc2AVHnKEhP5lBlXbGYfuznXeK8vVh_mysBWQ,15907
104
+ wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py,sha256=CNBpKlc8urCJhutyg5TatK8c7ptPzybtFDSqNLGwNQc,93041
105
+ wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py,sha256=2j_ixs9OO0eRBW3b0BTnpIb9W_jWxUR4IxKMZy5yDTw,15485
106
106
  wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/README.md,sha256=PZVbRXfoMNNrZUZY3YOWBW9A-6By7vi-IBBDIfvcdNc,3594
107
107
  wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/examples.json,sha256=kgNRdZcqne8XTm-Y8Hv1a1pdajRQsey4Qhd5La-iWss,164
108
- wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py,sha256=uW_Vef9eNFOSMmWYeE68LDxyVwHyWYje4B817-CQDZk,151446
108
+ wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py,sha256=uQbfMaWw9T7ISzwR8tGX74zZ8n_m27EGZuyKhCTnYgg,151390
109
109
  wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/test_strategy.py,sha256=U6_vaCzYRfu6k2vlOQhVXhPexvPNOfv8e6s8OiIySiw,37466
110
110
  wayfinder_paths/strategies/stablecoin_yield_strategy/README.md,sha256=efyLd2AJHL_JtHF3eZsnHk2wF4NWzEnuLKRA2vOpLtE,2844
111
111
  wayfinder_paths/strategies/stablecoin_yield_strategy/examples.json,sha256=pL1DNFEvYvXKK7xXD5oQYFPQj3Cm1ocKnk6r_iZk0IY,423
112
- wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py,sha256=qETYPjCocCxOk_WX9C4sUgYPq1tZOSBx2F9Sih5zhvE,75816
113
- wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py,sha256=ITM-JmRfrT1MKW1iVN3VlFs2CwZK2AXx9JYdMVQHLcQ,18881
114
- wayfinder_paths/templates/adapter/README.md,sha256=z0ULmM-vkyrZ0Y-a8iJzfLdrRgOuWaj9FqwE7xOZrwU,4179
115
- wayfinder_paths/templates/adapter/adapter.py,sha256=o7ZY6q-42zl6AnQFmDWbYoRJCZwjuUbiK8GT7bs0Nds,442
116
- wayfinder_paths/templates/adapter/examples.json,sha256=KLHy3AgPIplAaZN0qY2A-HBMa1xXkMhIyusORovTD9w,79
117
- wayfinder_paths/templates/adapter/test_adapter.py,sha256=iuth05S9Twz5_ALh-rbPrQHoIEyxRy30X9fxELXnPWc,839
118
- wayfinder_paths/templates/strategy/README.md,sha256=r7v4VcpO5Abz6q-mmjNmBcuagYM-Q-0H78CzMwwQksg,5298
119
- wayfinder_paths/templates/strategy/examples.json,sha256=s8UdlD5uxLITQrRMCqgiaAP0IE0tdnnLfX-Zn-OChIc,135
120
- wayfinder_paths/templates/strategy/strategy.py,sha256=Mw23A4yYoUqQ4sh4wdID0EypE9jo_RY0u_Qs2tMzGjY,968
121
- wayfinder_paths/templates/strategy/test_strategy.py,sha256=72Wtft_SEykxKVlVq3eZzE4ZdzIxwkeM8Sb_aaXof9E,6335
112
+ wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py,sha256=ZjMf6EUTItpi7pRY8gc6b9SgVXlioDgZprkd4uxnGIs,73222
113
+ wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py,sha256=RgTYY_aZgENS_3do-v8suAwjN-7BR5CaNCkLbySxiPc,18238
122
114
  wayfinder_paths/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
123
- wayfinder_paths/tests/test_smoke_manifest.py,sha256=kTcIa4qikcspVh2ohQIk0aHUdIvBvcQBfNbm3PNiVvg,1636
124
115
  wayfinder_paths/tests/test_test_coverage.py,sha256=paZd0U-J7oVDtkJ-DCBBEOHdupMRLsvs7WG5NrpAPRA,7203
125
116
  wayfinder_paths/tests/test_utils.py,sha256=VzweYVaO20deZOwR8RKGYFrDnKTW0gZLm3dBwZiMK28,1015
126
- wayfinder_paths-0.1.21.dist-info/LICENSE,sha256=dYKnlkC_xosBAEQNUvB6cHMuhFgcUtN0oBR7E8_aR2Y,1066
127
- wayfinder_paths-0.1.21.dist-info/METADATA,sha256=C4F3K1w_NCRe7uRQmSNlwYE5TIB5LnZKIG1W0nDtwG0,11662
128
- wayfinder_paths-0.1.21.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
129
- wayfinder_paths-0.1.21.dist-info/RECORD,,
117
+ wayfinder_paths-0.1.23.dist-info/LICENSE,sha256=dYKnlkC_xosBAEQNUvB6cHMuhFgcUtN0oBR7E8_aR2Y,1066
118
+ wayfinder_paths-0.1.23.dist-info/METADATA,sha256=dkGLujv7ZMYlIvqwZrwg-PwWPkV1hpmL7zunZaewRik,11587
119
+ wayfinder_paths-0.1.23.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
120
+ wayfinder_paths-0.1.23.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.1
2
+ Generator: poetry-core 1.8.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,41 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import NotRequired, Required, TypedDict
4
-
5
- from wayfinder_paths.core.clients.WayfinderClient import WayfinderClient
6
- from wayfinder_paths.core.config import get_api_base_url
7
-
8
-
9
- class AddressBalance(TypedDict):
10
- balance: Required[int]
11
- balance_human: NotRequired[float | None]
12
- usd_value: NotRequired[float | None]
13
- address: NotRequired[str]
14
- token_id: NotRequired[str | None]
15
- wallet_address: NotRequired[str]
16
- chain_id: NotRequired[int]
17
-
18
-
19
- class WalletClient(WayfinderClient):
20
- def __init__(self):
21
- super().__init__()
22
- self.api_base_url = get_api_base_url()
23
-
24
- async def get_token_balance_for_address(
25
- self,
26
- *,
27
- wallet_address: str,
28
- query: str,
29
- chain_id: int | None = None,
30
- ) -> AddressBalance:
31
- if chain_id is None:
32
- raise ValueError("chain_id is required")
33
-
34
- url = f"{self.api_base_url}/v1/blockchain/balances/address/"
35
- params = {
36
- "wallet_address": wallet_address,
37
- "chain_id": chain_id,
38
- "query": query,
39
- }
40
- response = await self._authed_request("GET", url, params=params)
41
- return response.json()
@@ -1,110 +0,0 @@
1
- import asyncio
2
- from typing import Any
3
-
4
- from loguru import logger
5
-
6
- from wayfinder_paths.core.clients.ClientManager import ClientManager
7
- from wayfinder_paths.core.config import StrategyJobConfig
8
- from wayfinder_paths.core.strategies.Strategy import Strategy
9
-
10
-
11
- class StrategyJob:
12
- def __init__(
13
- self,
14
- strategy: Strategy,
15
- config: StrategyJobConfig,
16
- clients: dict[str, Any] | None = None,
17
- skip_auth: bool = False,
18
- ):
19
- self.strategy = strategy
20
- self.config = config
21
-
22
- self.job_id = strategy.name or "unknown"
23
- self.clients = ClientManager(clients=clients, skip_auth=skip_auth)
24
-
25
- def _setup_strategy(self):
26
- if not self.strategy:
27
- raise ValueError("No strategy provided to StrategyJob")
28
-
29
- self.strategy.log = self.log
30
-
31
- async def setup(self):
32
- self._setup_strategy()
33
-
34
- # Ensure API key is set for API calls
35
- # All clients inherit from WayfinderClient and have _ensure_api_key()
36
- if not self.clients._skip_auth:
37
- # Ensure API key on any client (they all share the same method)
38
- token_client = self.clients.token
39
- if token_client:
40
- token_client._ensure_api_key()
41
-
42
- existing_cfg = dict(getattr(self.strategy, "config", {}) or {})
43
- strategy_cfg = dict(self.config.strategy_config or {})
44
- merged_cfg = {**strategy_cfg, **existing_cfg}
45
- self.strategy.config = merged_cfg
46
- self.strategy.clients = self.clients
47
- await self.strategy.setup()
48
-
49
- async def execute_strategy(self, action: str, **kwargs) -> dict[str, Any]:
50
- try:
51
- if action == "deposit":
52
- result = await self.strategy.deposit(**kwargs)
53
- elif action == "withdraw":
54
- result = await self.strategy.withdraw(**kwargs)
55
- elif action == "update":
56
- result = await self.strategy.update()
57
- elif action == "status":
58
- result = await self.strategy.status()
59
- elif action == "exit":
60
- result = await self.strategy.exit(**kwargs)
61
- elif action == "partial_liquidate":
62
- usd_value = kwargs.get("usd_value")
63
- if usd_value is None:
64
- result = (
65
- False,
66
- "usd_value parameter is required for partial_liquidate",
67
- )
68
- else:
69
- result = await self.strategy.partial_liquidate(usd_value)
70
- else:
71
- result = {"success": False, "message": f"Unknown action: {action}"}
72
-
73
- await self.log(f"Strategy action '{action}' completed: {result}")
74
- return result
75
-
76
- except Exception as e:
77
- error_msg = f"Strategy action '{action}' failed: {str(e)}"
78
- await self.log(error_msg)
79
- await self.handle_error({"error": str(e), "action": action})
80
- return {"success": False, "error": str(e)}
81
-
82
- async def run_continuous(self, interval_seconds: int | None = None):
83
- interval = interval_seconds or self.config.system.update_interval
84
- logger.info(
85
- f"Starting continuous execution for strategy: {self.strategy.name} with interval {interval}s"
86
- )
87
-
88
- while True:
89
- try:
90
- await self.execute_strategy("update")
91
- await asyncio.sleep(interval)
92
-
93
- except asyncio.CancelledError:
94
- logger.info("Continuous execution cancelled")
95
- break
96
- except Exception as e:
97
- logger.error(f"Error in continuous execution: {str(e)}")
98
- await asyncio.sleep(interval)
99
-
100
- async def log(self, msg: str):
101
- logger.info(f"Job {self.job_id}: {msg}")
102
-
103
- async def handle_error(self, error_data: dict[str, Any]) -> None:
104
- pass
105
-
106
- async def stop(self):
107
- if hasattr(self.strategy, "stop"):
108
- await self.strategy.stop()
109
-
110
- logger.info(f"Strategy job {self.job_id} stopped")