wayfinder-paths 0.1.15__py3-none-any.whl → 0.1.16__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 (47) hide show
  1. wayfinder_paths/adapters/balance_adapter/README.md +19 -20
  2. wayfinder_paths/adapters/balance_adapter/adapter.py +66 -37
  3. wayfinder_paths/adapters/balance_adapter/test_adapter.py +2 -8
  4. wayfinder_paths/adapters/brap_adapter/README.md +22 -19
  5. wayfinder_paths/adapters/brap_adapter/adapter.py +33 -34
  6. wayfinder_paths/adapters/brap_adapter/test_adapter.py +2 -18
  7. wayfinder_paths/adapters/hyperlend_adapter/adapter.py +40 -56
  8. wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +1 -8
  9. wayfinder_paths/adapters/moonwell_adapter/README.md +29 -31
  10. wayfinder_paths/adapters/moonwell_adapter/adapter.py +301 -662
  11. wayfinder_paths/adapters/moonwell_adapter/test_adapter.py +275 -179
  12. wayfinder_paths/core/config.py +8 -47
  13. wayfinder_paths/core/constants/base.py +0 -1
  14. wayfinder_paths/core/constants/erc20_abi.py +13 -13
  15. wayfinder_paths/core/strategies/Strategy.py +6 -2
  16. wayfinder_paths/core/utils/erc20_service.py +100 -0
  17. wayfinder_paths/core/utils/evm_helpers.py +1 -1
  18. wayfinder_paths/core/utils/transaction.py +191 -0
  19. wayfinder_paths/core/utils/web3.py +66 -0
  20. wayfinder_paths/run_strategy.py +37 -6
  21. wayfinder_paths/strategies/basis_trading_strategy/strategy.py +200 -224
  22. wayfinder_paths/strategies/basis_trading_strategy/test_strategy.py +128 -151
  23. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/README.md +0 -1
  24. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +52 -78
  25. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +0 -12
  26. wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/README.md +0 -1
  27. wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py +39 -64
  28. wayfinder_paths/strategies/stablecoin_yield_strategy/README.md +0 -1
  29. wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +42 -85
  30. wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +0 -8
  31. wayfinder_paths/templates/strategy/README.md +1 -5
  32. {wayfinder_paths-0.1.15.dist-info → wayfinder_paths-0.1.16.dist-info}/METADATA +3 -41
  33. {wayfinder_paths-0.1.15.dist-info → wayfinder_paths-0.1.16.dist-info}/RECORD +35 -44
  34. {wayfinder_paths-0.1.15.dist-info → wayfinder_paths-0.1.16.dist-info}/WHEEL +1 -1
  35. wayfinder_paths/core/clients/sdk_example.py +0 -125
  36. wayfinder_paths/core/engine/__init__.py +0 -5
  37. wayfinder_paths/core/services/__init__.py +0 -0
  38. wayfinder_paths/core/services/base.py +0 -131
  39. wayfinder_paths/core/services/local_evm_txn.py +0 -350
  40. wayfinder_paths/core/services/local_token_txn.py +0 -238
  41. wayfinder_paths/core/services/web3_service.py +0 -43
  42. wayfinder_paths/core/wallets/README.md +0 -88
  43. wayfinder_paths/core/wallets/WalletManager.py +0 -56
  44. wayfinder_paths/core/wallets/__init__.py +0 -7
  45. wayfinder_paths/scripts/run_strategy.py +0 -152
  46. wayfinder_paths/strategies/config.py +0 -85
  47. {wayfinder_paths-0.1.15.dist-info → wayfinder_paths-0.1.16.dist-info}/LICENSE +0 -0
@@ -8,6 +8,7 @@ so the position remains safe under a stETH/ETH depeg.
8
8
 
9
9
  import asyncio
10
10
  import time
11
+ from collections.abc import Awaitable, Callable
11
12
  from dataclasses import dataclass
12
13
  from typing import Any, Optional
13
14
 
@@ -21,9 +22,6 @@ from wayfinder_paths.adapters.ledger_adapter.adapter import LedgerAdapter
21
22
  from wayfinder_paths.adapters.moonwell_adapter.adapter import MoonwellAdapter
22
23
  from wayfinder_paths.adapters.token_adapter.adapter import TokenAdapter
23
24
  from wayfinder_paths.core.constants.erc20_abi import ERC20_ABI
24
- from wayfinder_paths.core.services.base import Web3Service
25
- from wayfinder_paths.core.services.local_token_txn import LocalTokenTxnService
26
- from wayfinder_paths.core.services.web3_service import DefaultWeb3Service
27
25
  from wayfinder_paths.core.strategies.descriptors import (
28
26
  Complexity,
29
27
  Directionality,
@@ -33,7 +31,7 @@ from wayfinder_paths.core.strategies.descriptors import (
33
31
  Volatility,
34
32
  )
35
33
  from wayfinder_paths.core.strategies.Strategy import StatusDict, StatusTuple, Strategy
36
- from wayfinder_paths.core.wallets.WalletManager import WalletManager
34
+ from wayfinder_paths.core.utils.web3 import web3_from_chain_id
37
35
  from wayfinder_paths.policies.enso import ENSO_ROUTER, enso_swap
38
36
  from wayfinder_paths.policies.erc20 import erc20_spender_for_any_token
39
37
  from wayfinder_paths.policies.moonwell import (
@@ -191,9 +189,16 @@ class MoonwellWstethLoopStrategy(Strategy):
191
189
  main_wallet: dict | None = None,
192
190
  strategy_wallet: dict | None = None,
193
191
  simulation: bool = False,
194
- web3_service: Web3Service | None = None,
192
+ api_key: str | None = None,
193
+ main_wallet_signing_callback: Callable[[dict], Awaitable[str]] | None = None,
194
+ strategy_wallet_signing_callback: Callable[[dict], Awaitable[str]]
195
+ | None = None,
195
196
  ):
196
- super().__init__()
197
+ super().__init__(
198
+ api_key=api_key,
199
+ main_wallet_signing_callback=main_wallet_signing_callback,
200
+ strategy_wallet_signing_callback=strategy_wallet_signing_callback,
201
+ )
197
202
  merged_config: dict[str, Any] = dict(config or {})
198
203
  if main_wallet is not None:
199
204
  merged_config["main_wallet"] = main_wallet
@@ -202,7 +207,6 @@ class MoonwellWstethLoopStrategy(Strategy):
202
207
 
203
208
  self.config = merged_config
204
209
  self.simulation = simulation
205
- self.web3_service = web3_service
206
210
 
207
211
  # Adapter references
208
212
  self.balance_adapter: BalanceAdapter | None = None
@@ -231,32 +235,24 @@ class MoonwellWstethLoopStrategy(Strategy):
231
235
  "strategy": self.config,
232
236
  }
233
237
 
234
- # Initialize web3_service if not provided
235
- if self.web3_service is None:
236
- wallet_provider = WalletManager.get_provider(adapter_config)
237
- token_transaction_service = LocalTokenTxnService(
238
- adapter_config,
239
- wallet_provider=wallet_provider,
240
- )
241
- web3_service = DefaultWeb3Service(
242
- wallet_provider=wallet_provider,
243
- evm_transactions=token_transaction_service,
244
- )
245
- else:
246
- web3_service = self.web3_service
247
- token_transaction_service = web3_service.token_transactions
248
-
249
238
  # Initialize adapters
250
- balance = BalanceAdapter(adapter_config, web3_service=web3_service)
239
+ balance = BalanceAdapter(
240
+ adapter_config,
241
+ simulation=self.simulation,
242
+ main_wallet_signing_callback=self.main_wallet_signing_callback,
243
+ strategy_wallet_signing_callback=self.strategy_wallet_signing_callback,
244
+ )
251
245
  token_adapter = TokenAdapter()
252
246
  ledger_adapter = LedgerAdapter()
253
247
  brap_adapter = BRAPAdapter(
254
- web3_service=web3_service,
248
+ adapter_config,
249
+ simulation=self.simulation,
250
+ strategy_wallet_signing_callback=self.strategy_wallet_signing_callback,
255
251
  )
256
252
  moonwell_adapter = MoonwellAdapter(
257
253
  adapter_config,
258
254
  simulation=self.simulation,
259
- web3_service=web3_service,
255
+ strategy_wallet_signing_callback=self.strategy_wallet_signing_callback,
260
256
  )
261
257
 
262
258
  self.register_adapters(
@@ -266,7 +262,6 @@ class MoonwellWstethLoopStrategy(Strategy):
266
262
  ledger_adapter,
267
263
  brap_adapter,
268
264
  moonwell_adapter,
269
- token_transaction_service,
270
265
  ]
271
266
  )
272
267
 
@@ -275,7 +270,6 @@ class MoonwellWstethLoopStrategy(Strategy):
275
270
  self.ledger_adapter = ledger_adapter
276
271
  self.brap_adapter = brap_adapter
277
272
  self.moonwell_adapter = moonwell_adapter
278
- self.web3_service = web3_service
279
273
 
280
274
  except Exception as e:
281
275
  logger.error(f"Failed to initialize strategy adapters: {e}")
@@ -1893,7 +1887,7 @@ class MoonwellWstethLoopStrategy(Strategy):
1893
1887
  return 0
1894
1888
 
1895
1889
  # Tests/simulations patch adapters; avoid RPC calls there.
1896
- if self.simulation or self.web3_service is None:
1890
+ if self.simulation:
1897
1891
  if self.balance_adapter is None:
1898
1892
  return 0
1899
1893
  success, raw = await self.balance_adapter.get_balance(
@@ -1927,25 +1921,23 @@ class MoonwellWstethLoopStrategy(Strategy):
1927
1921
  last_error: Exception | None = None
1928
1922
 
1929
1923
  for attempt in range(max_retries):
1930
- w3 = None
1931
1924
  try:
1932
- w3 = self.web3_service.get_web3(BASE_CHAIN_ID)
1925
+ async with web3_from_chain_id(BASE_CHAIN_ID) as w3:
1926
+ if token_id == ETH_TOKEN_ID:
1927
+ bal = await w3.eth.get_balance(
1928
+ to_checksum_address(wallet_address),
1929
+ block_identifier=block_id,
1930
+ )
1931
+ return int(bal)
1933
1932
 
1934
- if token_id == ETH_TOKEN_ID:
1935
- bal = await w3.eth.get_balance(
1936
- to_checksum_address(wallet_address),
1937
- block_identifier=block_id,
1933
+ contract = w3.eth.contract(
1934
+ address=to_checksum_address(str(token_address)),
1935
+ abi=ERC20_ABI,
1938
1936
  )
1937
+ bal = await contract.functions.balanceOf(
1938
+ to_checksum_address(wallet_address)
1939
+ ).call(block_identifier=block_id)
1939
1940
  return int(bal)
1940
-
1941
- contract = w3.eth.contract(
1942
- address=to_checksum_address(str(token_address)),
1943
- abi=ERC20_ABI,
1944
- )
1945
- bal = await contract.functions.balanceOf(
1946
- to_checksum_address(wallet_address)
1947
- ).call(block_identifier=block_id)
1948
- return int(bal)
1949
1941
  except Exception as exc:
1950
1942
  last_error = exc if isinstance(exc, Exception) else Exception(str(exc))
1951
1943
  err = str(exc)
@@ -1959,16 +1951,6 @@ class MoonwellWstethLoopStrategy(Strategy):
1959
1951
  f"On-chain balance read failed for {token_id} at block {block_id}: {exc}"
1960
1952
  )
1961
1953
  return 0
1962
- finally:
1963
- if w3 is not None:
1964
- try:
1965
- close_web3 = getattr(
1966
- self.web3_service.evm_transactions, "_close_web3", None
1967
- )
1968
- if close_web3 is not None:
1969
- await close_web3(w3)
1970
- except Exception:
1971
- pass
1972
1954
 
1973
1955
  logger.warning(
1974
1956
  f"On-chain balance read failed after {max_retries} attempts for {token_id} "
@@ -3231,22 +3213,15 @@ class MoonwellWstethLoopStrategy(Strategy):
3231
3213
  logger.info("UPDATE START")
3232
3214
  logger.info("=" * 60)
3233
3215
 
3234
- # Best-effort top-up if we dipped below MIN_GAS (non-critical).
3235
- topup_success, topup_msg = await self._transfer_gas_to_vault()
3236
- if not topup_success:
3237
- logger.warning(f"Gas top-up failed (non-critical): {topup_msg}")
3238
-
3216
+ # Check gas balance - deposit() should have provided sufficient gas
3239
3217
  gas_amt = await self._get_gas_balance()
3240
3218
  logger.info(
3241
3219
  f"Gas balance: {gas_amt / 10**18:.6f} ETH (min: {self.MAINTENANCE_GAS} ETH)"
3242
3220
  )
3243
3221
  if gas_amt < int(self.MAINTENANCE_GAS * 10**18):
3244
- logger.error(
3245
- f"Insufficient gas: {gas_amt / 10**18:.6f} < {self.MAINTENANCE_GAS}"
3246
- )
3247
- return (
3248
- False,
3249
- f"Less than {self.MAINTENANCE_GAS} ETH in strategy wallet. Please transfer more gas.",
3222
+ logger.warning(
3223
+ f"Low gas: {gas_amt / 10**18:.6f} < {self.MAINTENANCE_GAS} ETH. "
3224
+ f"Transactions may fail. Call deposit() with gas to top up."
3250
3225
  )
3251
3226
 
3252
3227
  # Pre-fetch collateral factors once (saves RPC + makes decisions consistent)
@@ -32,7 +32,6 @@ Transactions are scoped to the strategy wallet and Enso Router approval/swap cal
32
32
  - `BRAPAdapter` to source swap quotes and execute rotations.
33
33
  - `TokenAdapter` for metadata (gas token, USDC info).
34
34
  - `LedgerAdapter` for net-deposit tracking and cooldown enforcement.
35
- - `LocalTokenTxnService` (via `DefaultWeb3Service`) for lower-level sends/approvals used by adapters.
36
35
 
37
36
  ## Actions
38
37
 
@@ -1,6 +1,7 @@
1
1
  import asyncio
2
2
  import math
3
3
  import time
4
+ from collections.abc import Awaitable, Callable
4
5
  from datetime import UTC, datetime, timedelta
5
6
  from typing import Any
6
7
 
@@ -12,10 +13,6 @@ from wayfinder_paths.adapters.ledger_adapter.adapter import LedgerAdapter
12
13
  from wayfinder_paths.adapters.pool_adapter.adapter import PoolAdapter
13
14
  from wayfinder_paths.adapters.token_adapter.adapter import TokenAdapter
14
15
  from wayfinder_paths.core.constants.base import DEFAULT_SLIPPAGE
15
- from wayfinder_paths.core.services.local_token_txn import (
16
- LocalTokenTxnService,
17
- )
18
- from wayfinder_paths.core.services.web3_service import DefaultWeb3Service
19
16
  from wayfinder_paths.core.strategies.descriptors import (
20
17
  Complexity,
21
18
  Directionality,
@@ -25,7 +22,6 @@ from wayfinder_paths.core.strategies.descriptors import (
25
22
  Volatility,
26
23
  )
27
24
  from wayfinder_paths.core.strategies.Strategy import StatusDict, StatusTuple, Strategy
28
- from wayfinder_paths.core.wallets.WalletManager import WalletManager
29
25
 
30
26
 
31
27
  class StablecoinYieldStrategy(Strategy):
@@ -156,9 +152,16 @@ class StablecoinYieldStrategy(Strategy):
156
152
  *,
157
153
  main_wallet: dict[str, Any] | None = None,
158
154
  strategy_wallet: dict[str, Any] | None = None,
159
- web3_service=None,
155
+ api_key: str | None = None,
156
+ main_wallet_signing_callback: Callable[[dict], Awaitable[str]] | None = None,
157
+ strategy_wallet_signing_callback: Callable[[dict], Awaitable[str]]
158
+ | None = None,
160
159
  ):
161
- super().__init__()
160
+ super().__init__(
161
+ api_key=api_key,
162
+ main_wallet_signing_callback=main_wallet_signing_callback,
163
+ strategy_wallet_signing_callback=strategy_wallet_signing_callback,
164
+ )
162
165
  merged_config: dict[str, Any] = dict(config or {})
163
166
  if main_wallet is not None:
164
167
  merged_config["main_wallet"] = main_wallet
@@ -170,16 +173,16 @@ class StablecoinYieldStrategy(Strategy):
170
173
  self.current_pool = None
171
174
  self.current_apy = 0
172
175
  self.balance_adapter = None
173
- self.tx_adapter = None
174
- self.web3_service = web3_service
175
176
  self.token_adapter = None
176
177
  self.ledger_adapter = None
177
178
  self.pool_adapter = None
178
179
  self.brap_adapter = None
179
180
 
180
181
  # State tracking for deterministic token management
181
- self.tracked_token_ids: set[str] = set() # All tokens strategy might hold
182
- self.tracked_balances: dict[str, int] = {} # token_id -> balance in wei
182
+ # All tokens strategy might hold
183
+ self.tracked_token_ids: set[str] = set()
184
+ # token_id -> balance in wei
185
+ self.tracked_balances: dict[str, int] = {}
183
186
 
184
187
  try:
185
188
  main_wallet_cfg = self.config.get("main_wallet")
@@ -191,23 +194,18 @@ class StablecoinYieldStrategy(Strategy):
191
194
  "strategy": self.config,
192
195
  }
193
196
 
194
- if self.web3_service is None:
195
- wallet_provider = WalletManager.get_provider(adapter_config)
196
- tx_adapter = LocalTokenTxnService(
197
- adapter_config,
198
- wallet_provider=wallet_provider,
199
- )
200
- web3_service = DefaultWeb3Service(
201
- wallet_provider=wallet_provider, evm_transactions=tx_adapter
202
- )
203
- else:
204
- web3_service = self.web3_service
205
- tx_adapter = web3_service.token_transactions
206
- balance = BalanceAdapter(adapter_config, web3_service=web3_service)
197
+ balance = BalanceAdapter(
198
+ adapter_config,
199
+ main_wallet_signing_callback=self.main_wallet_signing_callback,
200
+ strategy_wallet_signing_callback=self.strategy_wallet_signing_callback,
201
+ )
207
202
  token_adapter = TokenAdapter()
208
203
  ledger_adapter = LedgerAdapter()
209
204
  pool_adapter = PoolAdapter()
210
- brap_adapter = BRAPAdapter(web3_service=web3_service)
205
+ brap_adapter = BRAPAdapter(
206
+ adapter_config,
207
+ strategy_wallet_signing_callback=self.strategy_wallet_signing_callback,
208
+ )
211
209
 
212
210
  self.register_adapters(
213
211
  [
@@ -216,12 +214,9 @@ class StablecoinYieldStrategy(Strategy):
216
214
  ledger_adapter,
217
215
  pool_adapter,
218
216
  brap_adapter,
219
- tx_adapter,
220
217
  ]
221
218
  )
222
219
  self.balance_adapter = balance
223
- self.tx_adapter = tx_adapter
224
- self.web3_service = web3_service
225
220
  self.token_adapter = token_adapter
226
221
  self.ledger_adapter = ledger_adapter
227
222
  self.pool_adapter = pool_adapter
@@ -1010,83 +1005,45 @@ class StablecoinYieldStrategy(Strategy):
1010
1005
  )
1011
1006
 
1012
1007
  await self._sweep_wallet(self.usdc_token_info)
1013
- withdrawn_breakdown = []
1014
- withdrawn_token_ids = set()
1015
1008
 
1016
- if self.usdc_token_info.get("token_id") in withdrawn_token_ids:
1017
- pass
1009
+ # Get final USDC balance in strategy wallet
1018
1010
  status, raw_balance = await self.balance_adapter.get_balance(
1019
1011
  query=self.usdc_token_info.get("token_id"),
1020
1012
  wallet_address=self._get_strategy_wallet_address(),
1021
1013
  )
1022
- if not status or not raw_balance:
1023
- pass
1024
- amount = float(raw_balance) / 10 ** self.usdc_token_info.get("decimals")
1025
- if amount > 0:
1026
- (
1027
- move_status,
1028
- move_message,
1029
- ) = await self.balance_adapter.move_from_strategy_wallet_to_main_wallet(
1030
- self.usdc_token_info.get("token_id"),
1031
- amount,
1032
- strategy_name=self.name,
1033
- )
1034
- if not move_status:
1035
- return (False, f"USDC return to main failed: {move_message}")
1036
-
1037
- withdrawn_breakdown.append(
1038
- (
1039
- self.usdc_token_info.get("symbol"),
1040
- self.usdc_token_info.get("chain").get("name"),
1041
- float(amount),
1014
+ usdc_amount = 0.0
1015
+ if status and raw_balance:
1016
+ usdc_amount = float(raw_balance) / 10 ** self.usdc_token_info.get(
1017
+ "decimals"
1042
1018
  )
1043
- )
1044
- withdrawn_token_ids.add(self.usdc_token_info.get("token_id"))
1045
1019
 
1046
- if self.gas_token and self.gas_token.get("token_id") not in withdrawn_token_ids:
1020
+ # Get gas balance in strategy wallet
1021
+ gas_amount = 0.0
1022
+ if self.gas_token:
1047
1023
  status, raw_gas = await self.balance_adapter.get_balance(
1048
1024
  query=self.gas_token.get("token_id"),
1049
1025
  wallet_address=self._get_strategy_wallet_address(),
1050
1026
  )
1051
1027
  if status and raw_gas:
1052
- gas_amount = (
1053
- float(raw_gas) / 10 ** self.gas_token.get("decimals")
1054
- ) * 0.9
1055
- if gas_amount > 0:
1056
- (
1057
- move_gas_status,
1058
- move_gas_message,
1059
- ) = await self.balance_adapter.move_from_strategy_wallet_to_main_wallet(
1060
- self.gas_token.get("token_id"),
1061
- gas_amount,
1062
- strategy_name=self.name,
1063
- )
1064
- if move_gas_status:
1065
- withdrawn_breakdown.append(
1066
- (
1067
- self.gas_token.get("symbol"),
1068
- self.gas_token.get("chain").get("name"),
1069
- float(gas_amount),
1070
- )
1071
- )
1072
- withdrawn_token_ids.add(self.gas_token.get("token_id"))
1028
+ gas_amount = float(raw_gas) / 10 ** self.gas_token.get("decimals")
1073
1029
 
1074
1030
  self.DEPOSIT_USDC = 0
1075
1031
  self.current_pool_balance = 0
1076
1032
 
1077
- if not withdrawn_breakdown:
1078
- return (True, f"Successfully withdrew {amount} USDC from strategy")
1079
-
1080
- breakdown_msg = ", ".join(
1081
- f"{amount:.6f} {symbol} on {chain.capitalize()}"
1082
- for symbol, chain, amount in withdrawn_breakdown
1083
- )
1084
-
1085
1033
  elapsed_time = time.time() - start_time
1086
1034
  logger.info(f"Withdrawal completed successfully in {elapsed_time:.2f} seconds")
1035
+
1036
+ strategy_address = self._get_strategy_wallet_address()
1037
+ breakdown_parts = [f"{usdc_amount:.2f} USDC"]
1038
+ if gas_amount > 0:
1039
+ breakdown_parts.append(
1040
+ f"{gas_amount:.6f} {self.gas_token.get('symbol', 'ETH')}"
1041
+ )
1042
+
1087
1043
  return (
1088
1044
  True,
1089
- f"Successfully withdrew {amount} USDC from strategy: {breakdown_msg}",
1045
+ f"Liquidated positions to strategy wallet ({strategy_address}): {', '.join(breakdown_parts)}. "
1046
+ f"Call exit() to transfer to main wallet.",
1090
1047
  )
1091
1048
 
1092
1049
  async def exit(self, **kwargs) -> StatusTuple:
@@ -118,10 +118,6 @@ def strategy():
118
118
  s.balance_adapter.move_from_strategy_wallet_to_main_wallet = AsyncMock(
119
119
  return_value=(True, "Transfer successful (simulated)")
120
120
  )
121
- if hasattr(s.balance_adapter, "wallet_provider"):
122
- s.balance_adapter.wallet_provider.broadcast_transaction = AsyncMock(
123
- return_value=(True, {"transaction_hash": "0xDEADBEEF"})
124
- )
125
121
 
126
122
  if hasattr(s, "ledger_adapter") and s.ledger_adapter:
127
123
  # NOTE: The real LedgerClient returns float, not dict!
@@ -200,10 +196,6 @@ def strategy():
200
196
  and hasattr(s.brap_adapter, "swap_from_quote")
201
197
  ):
202
198
  s.brap_adapter.swap_from_quote = AsyncMock(return_value=None)
203
- if hasattr(s, "brap_adapter") and hasattr(s.brap_adapter, "wallet_provider"):
204
- s.brap_adapter.wallet_provider.broadcast_transaction = AsyncMock(
205
- return_value=(True, {"transaction_hash": "0xBEEF"})
206
- )
207
199
 
208
200
  s.DEPOSIT_USDC = 0
209
201
  s.usdc_token_info = {
@@ -41,12 +41,10 @@ async def _status(self) -> StatusDict:
41
41
 
42
42
  Strategies typically:
43
43
 
44
- 1. Build a `DefaultWeb3Service` so every adapter shares a wallet provider.
45
44
  2. Instantiate adapters (balance, ledger, protocol specific, etc.).
46
45
  3. Register adapters via `self.register_adapters([...])` and keep references as attributes.
47
46
 
48
47
  ```python
49
- from wayfinder_paths.core.services.web3_service import DefaultWeb3Service
50
48
  from wayfinder_paths.core.strategies.Strategy import StatusDict, StatusTuple, Strategy
51
49
  from wayfinder_paths.adapters.balance_adapter.adapter import BalanceAdapter
52
50
 
@@ -57,8 +55,7 @@ class MyStrategy(Strategy):
57
55
  def __init__(self, config: dict | None = None):
58
56
  super().__init__()
59
57
  self.config = config or {}
60
- web3_service = DefaultWeb3Service(self.config)
61
- balance_adapter = BalanceAdapter(self.config, web3_service=web3_service)
58
+ balance_adapter = BalanceAdapter(self.config)
62
59
  self.register_adapters([balance_adapter])
63
60
  self.balance_adapter = balance_adapter
64
61
 
@@ -76,7 +73,6 @@ class MyStrategy(Strategy):
76
73
  if not success:
77
74
  return (False, "Unable to fetch balances")
78
75
 
79
- # Use BalanceAdapter (which leverages LocalTokenTxnService builders) for transfers.
80
76
  self.last_deposit = main_token_amount
81
77
  return (True, f"Deposited {main_token_amount} tokens")
82
78
 
@@ -1,12 +1,13 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: wayfinder-paths
3
- Version: 0.1.15
3
+ Version: 0.1.16
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
10
11
  Requires-Dist: aiohttp (>=3.13.0,<4.0.0)
11
12
  Requires-Dist: eth-account (>=0.13.7,<0.14.0)
12
13
  Requires-Dist: httpx (>=0.28.1,<0.29.0)
@@ -275,7 +276,6 @@ Strategies implement trading logic using adapters and the unified client system.
275
276
 
276
277
  ```python
277
278
  # wayfinder_paths/strategies/my_strategy/strategy.py
278
- from wayfinder_paths.core.services.web3_service import DefaultWeb3Service
279
279
  from wayfinder_paths.core.strategies.Strategy import StatusDict, StatusTuple, Strategy
280
280
  from wayfinder_paths.adapters.balance_adapter.adapter import BalanceAdapter
281
281
 
@@ -291,9 +291,8 @@ class MyStrategy(Strategy):
291
291
  ):
292
292
  super().__init__(api_key=api_key) # Pass to base class for auto-discovery
293
293
  self.config = config or {}
294
- web3_service = DefaultWeb3Service(self.config)
295
294
  # Adapters automatically discover API key from constructor or config.json
296
- balance_adapter = BalanceAdapter(self.config, web3_service=web3_service)
295
+ balance_adapter = BalanceAdapter(self.config)
297
296
  self.register_adapters([balance_adapter])
298
297
  self.balance_adapter = balance_adapter
299
298
 
@@ -311,7 +310,6 @@ class MyStrategy(Strategy):
311
310
  if not success:
312
311
  return (False, "Unable to fetch balances")
313
312
 
314
- # Use BalanceAdapter (which leverages LocalTokenTxnService builders) for transfers here.
315
313
  self.last_deposit = main_token_amount
316
314
  return (True, f"Deposited {main_token_amount} tokens")
317
315
 
@@ -344,42 +342,6 @@ The following strategies are available and can be run using the CLI:
344
342
 
345
343
  #### Running Strategies
346
344
 
347
- ```bash
348
- # Check strategy status
349
- poetry run python wayfinder_paths/scripts/run_strategy.py \
350
- --strategy moonwell_wsteth_loop_strategy \
351
- --main-wallet-label main \
352
- --strategy-wallet-label moonwell_wsteth_loop_strategy \
353
- status
354
-
355
- # Deposit funds (USDC amount, optional ETH for gas)
356
- poetry run python wayfinder_paths/scripts/run_strategy.py \
357
- --strategy moonwell_wsteth_loop_strategy \
358
- --main-wallet-label main \
359
- --strategy-wallet-label moonwell_wsteth_loop_strategy \
360
- deposit --usdc 100 --eth 0.01
361
-
362
- # Run periodic update
363
- poetry run python wayfinder_paths/scripts/run_strategy.py \
364
- --strategy moonwell_wsteth_loop_strategy \
365
- --main-wallet-label main \
366
- --strategy-wallet-label moonwell_wsteth_loop_strategy \
367
- update
368
-
369
- # Withdraw funds (omit --amount for full withdrawal)
370
- poetry run python wayfinder_paths/scripts/run_strategy.py \
371
- --strategy moonwell_wsteth_loop_strategy \
372
- --main-wallet-label main \
373
- --strategy-wallet-label moonwell_wsteth_loop_strategy \
374
- withdraw --amount 50
375
-
376
- # Run in simulation mode (no real transactions)
377
- poetry run python wayfinder_paths/scripts/run_strategy.py \
378
- --strategy moonwell_wsteth_loop_strategy \
379
- --simulation \
380
- status
381
- ```
382
-
383
345
  ### Built-in adapters
384
346
 
385
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.