wayfinder-paths 0.1.22__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.22.dist-info → wayfinder_paths-0.1.23.dist-info}/METADATA +2 -3
  49. {wayfinder_paths-0.1.22.dist-info → wayfinder_paths-0.1.23.dist-info}/RECORD +51 -60
  50. {wayfinder_paths-0.1.22.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.22.dist-info → wayfinder_paths-0.1.23.dist-info}/LICENSE +0 -0
@@ -8,49 +8,43 @@ from eth_utils import to_checksum_address
8
8
 
9
9
  from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
10
10
  from wayfinder_paths.core.clients.TokenClient import TokenClient
11
+ from wayfinder_paths.core.constants.base import MANTISSA, MAX_UINT256, SECONDS_PER_YEAR
12
+ from wayfinder_paths.core.constants.chains import CHAIN_ID_BASE
13
+ from wayfinder_paths.core.constants.contracts import (
14
+ BASE_USDC,
15
+ BASE_WETH,
16
+ BASE_WSTETH,
17
+ MOONWELL_COMPTROLLER,
18
+ MOONWELL_M_USDC,
19
+ MOONWELL_M_WETH,
20
+ MOONWELL_M_WSTETH,
21
+ MOONWELL_REWARD_DISTRIBUTOR,
22
+ MOONWELL_WELL_TOKEN,
23
+ )
11
24
  from wayfinder_paths.core.constants.moonwell_abi import (
12
25
  COMPTROLLER_ABI,
13
26
  MTOKEN_ABI,
14
27
  REWARD_DISTRIBUTOR_ABI,
15
28
  WETH_ABI,
16
29
  )
17
- from wayfinder_paths.core.utils.tokens import (
18
- build_approve_transaction,
19
- get_token_allowance,
20
- )
30
+ from wayfinder_paths.core.utils.tokens import ensure_allowance
21
31
  from wayfinder_paths.core.utils.transaction import send_transaction
22
32
  from wayfinder_paths.core.utils.web3 import web3_from_chain_id
23
33
 
24
- # Moonwell Base chain addresses
25
34
  MOONWELL_DEFAULTS = {
26
- # mToken addresses
27
- "m_usdc": "0xEdc817A28E8B93B03976FBd4a3dDBc9f7D176c22",
28
- "m_weth": "0x628ff693426583D9a7FB391E54366292F509D457",
29
- "m_wsteth": "0x627Fe393Bc6EdDA28e99AE648fD6fF362514304b",
30
- # Underlying token addresses
31
- "usdc": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
32
- "weth": "0x4200000000000000000000000000000000000006",
33
- "wsteth": "0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452",
34
- # Protocol addresses
35
- "reward_distributor": "0xe9005b078701e2a0948d2eac43010d35870ad9d2",
36
- "comptroller": "0xfbb21d0380bee3312b33c4353c8936a0f13ef26c",
37
- # WELL token address on Base
38
- "well_token": "0xA88594D404727625A9437C3f886C7643872296AE",
35
+ "m_usdc": MOONWELL_M_USDC,
36
+ "m_weth": MOONWELL_M_WETH,
37
+ "m_wsteth": MOONWELL_M_WSTETH,
38
+ "usdc": BASE_USDC,
39
+ "weth": BASE_WETH,
40
+ "wsteth": BASE_WSTETH,
41
+ "reward_distributor": MOONWELL_REWARD_DISTRIBUTOR,
42
+ "comptroller": MOONWELL_COMPTROLLER,
43
+ "well_token": MOONWELL_WELL_TOKEN,
39
44
  }
40
45
 
41
- # Base chain ID
42
- BASE_CHAIN_ID = 8453
43
-
44
- # Mantissa for collateral factor calculations (1e18)
45
- MANTISSA = 10**18
46
-
47
- # Seconds per year for APY calculations
48
- SECONDS_PER_YEAR = 365 * 24 * 60 * 60
49
-
50
- # Collateral factor cache TTL (1 hour - rarely changes, governance controlled)
46
+ BASE_CHAIN_ID = CHAIN_ID_BASE
51
47
  CF_CACHE_TTL = 3600
52
-
53
- # Default retry settings for rate-limited RPCs
54
48
  DEFAULT_MAX_RETRIES = 5
55
49
  DEFAULT_BASE_DELAY = 3.0
56
50
 
@@ -80,45 +74,49 @@ class MoonwellAdapter(BaseAdapter):
80
74
  self.token_client = token_client
81
75
  self.strategy_wallet_signing_callback = strategy_wallet_signing_callback
82
76
 
83
- self.strategy_wallet = cfg.get("strategy_wallet") or {}
77
+ strategy_wallet = cfg.get("strategy_wallet") or {}
78
+ strategy_addr = strategy_wallet.get("address")
79
+ if not strategy_addr:
80
+ raise ValueError("strategy_wallet.address is required")
81
+ self.strategy_wallet_address = to_checksum_address(strategy_addr)
84
82
  self.chain_id = adapter_cfg.get("chain_id", BASE_CHAIN_ID)
85
83
  self.chain_name = "base"
86
84
 
87
85
  # Protocol addresses (with config overrides)
88
- self.comptroller_address = self._checksum(
86
+ self.comptroller_address = to_checksum_address(
89
87
  adapter_cfg.get("comptroller") or MOONWELL_DEFAULTS["comptroller"]
90
88
  )
91
- self.reward_distributor_address = self._checksum(
89
+ self.reward_distributor_address = to_checksum_address(
92
90
  adapter_cfg.get("reward_distributor")
93
91
  or MOONWELL_DEFAULTS["reward_distributor"]
94
92
  )
95
- self.well_token = self._checksum(
93
+ self.well_token = to_checksum_address(
96
94
  adapter_cfg.get("well_token") or MOONWELL_DEFAULTS["well_token"]
97
95
  )
98
96
 
99
97
  # Token addresses
100
- self.m_usdc = self._checksum(
98
+ self.m_usdc = to_checksum_address(
101
99
  adapter_cfg.get("m_usdc") or MOONWELL_DEFAULTS["m_usdc"]
102
100
  )
103
- self.m_weth = self._checksum(
101
+ self.m_weth = to_checksum_address(
104
102
  adapter_cfg.get("m_weth") or MOONWELL_DEFAULTS["m_weth"]
105
103
  )
106
- self.m_wsteth = self._checksum(
104
+ self.m_wsteth = to_checksum_address(
107
105
  adapter_cfg.get("m_wsteth") or MOONWELL_DEFAULTS["m_wsteth"]
108
106
  )
109
- self.usdc = self._checksum(adapter_cfg.get("usdc") or MOONWELL_DEFAULTS["usdc"])
110
- self.weth = self._checksum(adapter_cfg.get("weth") or MOONWELL_DEFAULTS["weth"])
111
- self.wsteth = self._checksum(
107
+ self.usdc = to_checksum_address(
108
+ adapter_cfg.get("usdc") or MOONWELL_DEFAULTS["usdc"]
109
+ )
110
+ self.weth = to_checksum_address(
111
+ adapter_cfg.get("weth") or MOONWELL_DEFAULTS["weth"]
112
+ )
113
+ self.wsteth = to_checksum_address(
112
114
  adapter_cfg.get("wsteth") or MOONWELL_DEFAULTS["wsteth"]
113
115
  )
114
116
 
115
117
  # Collateral factor cache: mtoken -> (value, timestamp)
116
118
  self._cf_cache: dict[str, tuple[float, float]] = {}
117
119
 
118
- # ------------------------------------------------------------------ #
119
- # Public API - Lending Operations #
120
- # ------------------------------------------------------------------ #
121
-
122
120
  async def lend(
123
121
  self,
124
122
  *,
@@ -126,20 +124,23 @@ class MoonwellAdapter(BaseAdapter):
126
124
  underlying_token: str,
127
125
  amount: int,
128
126
  ) -> tuple[bool, Any]:
129
- strategy = self._strategy_address()
127
+ strategy = self.strategy_wallet_address
130
128
  amount = int(amount)
131
129
  if amount <= 0:
132
130
  return False, "amount must be positive"
133
131
 
134
- mtoken = self._checksum(mtoken)
135
- underlying_token = self._checksum(underlying_token)
132
+ mtoken = to_checksum_address(mtoken)
133
+ underlying_token = to_checksum_address(underlying_token)
136
134
 
137
135
  # Approve mToken to spend underlying tokens
138
- approved = await self._ensure_allowance(
136
+ approved = await ensure_allowance(
139
137
  token_address=underlying_token,
140
138
  owner=strategy,
141
139
  spender=mtoken,
142
140
  amount=amount,
141
+ chain_id=self.chain_id,
142
+ signing_callback=self.strategy_wallet_signing_callback,
143
+ approval_amount=MAX_UINT256,
143
144
  )
144
145
  if not approved[0]:
145
146
  return approved
@@ -152,7 +153,8 @@ class MoonwellAdapter(BaseAdapter):
152
153
  args=[amount],
153
154
  from_address=strategy,
154
155
  )
155
- return await self._send_tx(tx)
156
+ txn_hash = await send_transaction(tx, self.strategy_wallet_signing_callback)
157
+ return (True, txn_hash)
156
158
 
157
159
  async def unlend(
158
160
  self,
@@ -160,12 +162,12 @@ class MoonwellAdapter(BaseAdapter):
160
162
  mtoken: str,
161
163
  amount: int,
162
164
  ) -> tuple[bool, Any]:
163
- strategy = self._strategy_address()
165
+ strategy = self.strategy_wallet_address
164
166
  amount = int(amount)
165
167
  if amount <= 0:
166
168
  return False, "amount must be positive"
167
169
 
168
- mtoken = self._checksum(mtoken)
170
+ mtoken = to_checksum_address(mtoken)
169
171
 
170
172
  # Redeem mTokens for underlying
171
173
  tx = await self._encode_call(
@@ -175,11 +177,8 @@ class MoonwellAdapter(BaseAdapter):
175
177
  args=[amount],
176
178
  from_address=strategy,
177
179
  )
178
- return await self._send_tx(tx)
179
-
180
- # ------------------------------------------------------------------ #
181
- # Public API - Borrowing Operations #
182
- # ------------------------------------------------------------------ #
180
+ txn_hash = await send_transaction(tx, self.strategy_wallet_signing_callback)
181
+ return (True, txn_hash)
183
182
 
184
183
  async def borrow(
185
184
  self,
@@ -187,14 +186,12 @@ class MoonwellAdapter(BaseAdapter):
187
186
  mtoken: str,
188
187
  amount: int,
189
188
  ) -> tuple[bool, Any]:
190
- from loguru import logger
191
-
192
- strategy = self._strategy_address()
189
+ strategy = self.strategy_wallet_address
193
190
  amount = int(amount)
194
191
  if amount <= 0:
195
192
  return False, "amount must be positive"
196
193
 
197
- mtoken = self._checksum(mtoken)
194
+ mtoken = to_checksum_address(mtoken)
198
195
 
199
196
  borrow_before = 0
200
197
  try:
@@ -211,15 +208,15 @@ class MoonwellAdapter(BaseAdapter):
211
208
  {"from": strategy}, block_identifier="pending"
212
209
  )
213
210
  if borrow_return != 0:
214
- logger.warning(
211
+ self.logger.warning(
215
212
  f"Borrow simulation returned error code {borrow_return}. "
216
213
  "Codes: 3=COMPTROLLER_REJECTION, 9=INVALID_ACCOUNT_PAIR, "
217
214
  "14=INSUFFICIENT_LIQUIDITY"
218
215
  )
219
216
  except Exception as call_err:
220
- logger.debug(f"Borrow simulation failed: {call_err}")
217
+ self.logger.debug(f"Borrow simulation failed: {call_err}")
221
218
  except Exception as e:
222
- logger.warning(f"Failed to get pre-borrow balance: {e}")
219
+ self.logger.warning(f"Failed to get pre-borrow balance: {e}")
223
220
 
224
221
  tx = await self._encode_call(
225
222
  target=mtoken,
@@ -228,10 +225,7 @@ class MoonwellAdapter(BaseAdapter):
228
225
  args=[amount],
229
226
  from_address=strategy,
230
227
  )
231
- result = await self._send_tx(tx)
232
-
233
- if not result[0]:
234
- return result
228
+ txn_hash = await send_transaction(tx, self.strategy_wallet_signing_callback)
235
229
 
236
230
  # Verify the borrow actually succeeded by checking balance increased
237
231
  try:
@@ -247,9 +241,7 @@ class MoonwellAdapter(BaseAdapter):
247
241
  actual_increase = borrow_after - borrow_before
248
242
 
249
243
  if actual_increase < expected_increase:
250
- from loguru import logger
251
-
252
- logger.error(
244
+ self.logger.error(
253
245
  f"Borrow verification failed: balance only increased by "
254
246
  f"{actual_increase} (expected ~{amount}). "
255
247
  f"Moonwell likely returned an error code. "
@@ -261,12 +253,9 @@ class MoonwellAdapter(BaseAdapter):
261
253
  f"Before: {borrow_before}, After: {borrow_after}, Expected: +{amount}",
262
254
  )
263
255
  except Exception as e:
264
- from loguru import logger
256
+ self.logger.warning(f"Could not verify borrow balance: {e}")
265
257
 
266
- logger.warning(f"Could not verify borrow balance: {e}")
267
- # Continue with the original result if verification fails
268
-
269
- return result
258
+ return (True, txn_hash)
270
259
 
271
260
  async def repay(
272
261
  self,
@@ -276,27 +265,30 @@ class MoonwellAdapter(BaseAdapter):
276
265
  amount: int,
277
266
  repay_full: bool = False,
278
267
  ) -> tuple[bool, Any]:
279
- strategy = self._strategy_address()
268
+ strategy = self.strategy_wallet_address
280
269
  amount = int(amount)
281
270
  if amount <= 0:
282
271
  return False, "amount must be positive"
283
272
 
284
- mtoken = self._checksum(mtoken)
285
- underlying_token = self._checksum(underlying_token)
273
+ mtoken = to_checksum_address(mtoken)
274
+ underlying_token = to_checksum_address(underlying_token)
286
275
 
287
276
  # Approve mToken to spend underlying tokens for repayment
288
277
  # When repay_full=True, approve the amount we have, Moonwell will use only what's needed
289
- approved = await self._ensure_allowance(
278
+ approved = await ensure_allowance(
290
279
  token_address=underlying_token,
291
280
  owner=strategy,
292
281
  spender=mtoken,
293
282
  amount=amount,
283
+ chain_id=self.chain_id,
284
+ signing_callback=self.strategy_wallet_signing_callback,
285
+ approval_amount=MAX_UINT256,
294
286
  )
295
287
  if not approved[0]:
296
288
  return approved
297
289
 
298
290
  # Use max uint256 for full repayment to avoid balance calculation issues
299
- repay_amount = self.MAX_UINT256 if repay_full else amount
291
+ repay_amount = MAX_UINT256 if repay_full else amount
300
292
 
301
293
  tx = await self._encode_call(
302
294
  target=mtoken,
@@ -305,19 +297,16 @@ class MoonwellAdapter(BaseAdapter):
305
297
  args=[repay_amount],
306
298
  from_address=strategy,
307
299
  )
308
- return await self._send_tx(tx)
309
-
310
- # ------------------------------------------------------------------ #
311
- # Public API - Collateral Management #
312
- # ------------------------------------------------------------------ #
300
+ txn_hash = await send_transaction(tx, self.strategy_wallet_signing_callback)
301
+ return (True, txn_hash)
313
302
 
314
303
  async def set_collateral(
315
304
  self,
316
305
  *,
317
306
  mtoken: str,
318
307
  ) -> tuple[bool, Any]:
319
- strategy = self._strategy_address()
320
- mtoken = self._checksum(mtoken)
308
+ strategy = self.strategy_wallet_address
309
+ mtoken = to_checksum_address(mtoken)
321
310
 
322
311
  tx = await self._encode_call(
323
312
  target=self.comptroller_address,
@@ -326,10 +315,7 @@ class MoonwellAdapter(BaseAdapter):
326
315
  args=[[mtoken]],
327
316
  from_address=strategy,
328
317
  )
329
- result = await self._send_tx(tx)
330
-
331
- if not result[0]:
332
- return result
318
+ txn_hash = await send_transaction(tx, self.strategy_wallet_signing_callback)
333
319
 
334
320
  # Verify the market was actually entered
335
321
  try:
@@ -342,9 +328,7 @@ class MoonwellAdapter(BaseAdapter):
342
328
  ).call(block_identifier="pending")
343
329
 
344
330
  if not is_member:
345
- from loguru import logger
346
-
347
- logger.error(
331
+ self.logger.error(
348
332
  f"set_collateral verification failed: account {strategy} "
349
333
  f"is not a member of market {mtoken} after enterMarkets call"
350
334
  )
@@ -353,11 +337,9 @@ class MoonwellAdapter(BaseAdapter):
353
337
  f"enterMarkets succeeded but account is not a member of market {mtoken}",
354
338
  )
355
339
  except Exception as e:
356
- from loguru import logger
340
+ self.logger.warning(f"Could not verify market membership: {e}")
357
341
 
358
- logger.warning(f"Could not verify market membership: {e}")
359
-
360
- return result
342
+ return (True, txn_hash)
361
343
 
362
344
  async def is_market_entered(
363
345
  self,
@@ -366,8 +348,12 @@ class MoonwellAdapter(BaseAdapter):
366
348
  account: str | None = None,
367
349
  ) -> tuple[bool, bool | str]:
368
350
  try:
369
- acct = self._checksum(account) if account else self._strategy_address()
370
- mtoken = self._checksum(mtoken)
351
+ acct = (
352
+ to_checksum_address(account)
353
+ if account
354
+ else self.strategy_wallet_address
355
+ )
356
+ mtoken = to_checksum_address(mtoken)
371
357
 
372
358
  async with web3_from_chain_id(self.chain_id) as web3:
373
359
  comptroller = web3.eth.contract(
@@ -375,7 +361,7 @@ class MoonwellAdapter(BaseAdapter):
375
361
  )
376
362
  is_member = await comptroller.functions.checkMembership(
377
363
  acct, mtoken
378
- ).call()
364
+ ).call(block_identifier="pending")
379
365
  return True, bool(is_member)
380
366
  except Exception as exc:
381
367
  return False, str(exc)
@@ -385,8 +371,8 @@ class MoonwellAdapter(BaseAdapter):
385
371
  *,
386
372
  mtoken: str,
387
373
  ) -> tuple[bool, Any]:
388
- strategy = self._strategy_address()
389
- mtoken = self._checksum(mtoken)
374
+ strategy = self.strategy_wallet_address
375
+ mtoken = to_checksum_address(mtoken)
390
376
 
391
377
  tx = await self._encode_call(
392
378
  target=self.comptroller_address,
@@ -395,18 +381,15 @@ class MoonwellAdapter(BaseAdapter):
395
381
  args=[mtoken],
396
382
  from_address=strategy,
397
383
  )
398
- return await self._send_tx(tx)
399
-
400
- # ------------------------------------------------------------------ #
401
- # Public API - Rewards #
402
- # ------------------------------------------------------------------ #
384
+ txn_hash = await send_transaction(tx, self.strategy_wallet_signing_callback)
385
+ return (True, txn_hash)
403
386
 
404
387
  async def claim_rewards(
405
388
  self,
406
389
  *,
407
390
  min_rewards_usd: float = 0.0,
408
391
  ) -> tuple[bool, dict[str, int] | str]:
409
- strategy = self._strategy_address()
392
+ strategy = self.strategy_wallet_address
410
393
 
411
394
  rewards = await self._get_outstanding_rewards(strategy)
412
395
 
@@ -427,10 +410,7 @@ class MoonwellAdapter(BaseAdapter):
427
410
  args=[strategy],
428
411
  from_address=strategy,
429
412
  )
430
- result = await self._send_tx(tx)
431
- if not result[0]:
432
- return result
433
-
413
+ await send_transaction(tx, self.strategy_wallet_signing_callback)
434
414
  return True, rewards
435
415
 
436
416
  async def _get_outstanding_rewards(self, account: str) -> dict[str, int]:
@@ -476,10 +456,6 @@ class MoonwellAdapter(BaseAdapter):
476
456
  pass
477
457
  return total_usd
478
458
 
479
- # ------------------------------------------------------------------ #
480
- # Public API - Position & Market Data #
481
- # ------------------------------------------------------------------ #
482
-
483
459
  async def get_pos(
484
460
  self,
485
461
  *,
@@ -489,8 +465,10 @@ class MoonwellAdapter(BaseAdapter):
489
465
  max_retries: int = 3,
490
466
  block_identifier: int | str | None = None,
491
467
  ) -> tuple[bool, dict[str, Any] | str]:
492
- mtoken = self._checksum(mtoken)
493
- account = self._checksum(account) if account else self._strategy_address()
468
+ mtoken = to_checksum_address(mtoken)
469
+ account = (
470
+ to_checksum_address(account) if account else self.strategy_wallet_address
471
+ )
494
472
  block_id = block_identifier if block_identifier is not None else "pending"
495
473
 
496
474
  bal = exch = borrow = underlying = rewards = None
@@ -615,7 +593,7 @@ class MoonwellAdapter(BaseAdapter):
615
593
  mtoken: str,
616
594
  max_retries: int = DEFAULT_MAX_RETRIES,
617
595
  ) -> tuple[bool, float | str]:
618
- mtoken = self._checksum(mtoken)
596
+ mtoken = to_checksum_address(mtoken)
619
597
 
620
598
  now = time.time()
621
599
  if mtoken in self._cf_cache:
@@ -664,7 +642,7 @@ class MoonwellAdapter(BaseAdapter):
664
642
  include_rewards: bool = True,
665
643
  max_retries: int = DEFAULT_MAX_RETRIES,
666
644
  ) -> tuple[bool, float | str]:
667
- mtoken = self._checksum(mtoken)
645
+ mtoken = to_checksum_address(mtoken)
668
646
 
669
647
  last_error = ""
670
648
  for attempt in range(max_retries):
@@ -811,7 +789,9 @@ class MoonwellAdapter(BaseAdapter):
811
789
  account: str | None = None,
812
790
  max_retries: int = DEFAULT_MAX_RETRIES,
813
791
  ) -> tuple[bool, int | str]:
814
- account = self._checksum(account) if account else self._strategy_address()
792
+ account = (
793
+ to_checksum_address(account) if account else self.strategy_wallet_address
794
+ )
815
795
 
816
796
  last_error = ""
817
797
  for attempt in range(max_retries):
@@ -852,8 +832,10 @@ class MoonwellAdapter(BaseAdapter):
852
832
  mtoken: str,
853
833
  account: str | None = None,
854
834
  ) -> tuple[bool, dict[str, Any] | str]:
855
- mtoken = self._checksum(mtoken)
856
- account = self._checksum(account) if account else self._strategy_address()
835
+ mtoken = to_checksum_address(mtoken)
836
+ account = (
837
+ to_checksum_address(account) if account else self.strategy_wallet_address
838
+ )
857
839
 
858
840
  try:
859
841
  async with web3_from_chain_id(self.chain_id) as web3:
@@ -949,16 +931,12 @@ class MoonwellAdapter(BaseAdapter):
949
931
  except Exception as exc:
950
932
  return False, str(exc)
951
933
 
952
- # ------------------------------------------------------------------ #
953
- # Public API - ETH Wrapping #
954
- # ------------------------------------------------------------------ #
955
-
956
934
  async def wrap_eth(
957
935
  self,
958
936
  *,
959
937
  amount: int,
960
938
  ) -> tuple[bool, Any]:
961
- strategy = self._strategy_address()
939
+ strategy = self.strategy_wallet_address
962
940
  amount = int(amount)
963
941
  if amount <= 0:
964
942
  return False, "amount must be positive"
@@ -971,57 +949,8 @@ class MoonwellAdapter(BaseAdapter):
971
949
  from_address=strategy,
972
950
  value=amount,
973
951
  )
974
- return await self._send_tx(tx)
975
-
976
- # ------------------------------------------------------------------ #
977
- # Helpers #
978
- # ------------------------------------------------------------------ #
979
-
980
- # Max uint256 for unlimited approvals
981
- MAX_UINT256 = 2**256 - 1
982
-
983
- async def _send_tx(self, tx: dict[str, Any]) -> tuple[bool, Any]:
984
952
  txn_hash = await send_transaction(tx, self.strategy_wallet_signing_callback)
985
- return True, txn_hash
986
-
987
- async def _ensure_allowance(
988
- self,
989
- *,
990
- token_address: str,
991
- owner: str,
992
- spender: str,
993
- amount: int,
994
- ) -> tuple[bool, Any]:
995
- allowance = await get_token_allowance(
996
- token_address, self.chain_id, owner, spender
997
- )
998
- if allowance >= amount:
999
- return True, {}
1000
-
1001
- # Approve for max uint256 to avoid precision/timing issues
1002
- approve_tx = await build_approve_transaction(
1003
- from_address=owner,
1004
- chain_id=self.chain_id,
1005
- token_address=token_address,
1006
- spender_address=spender,
1007
- amount=self.MAX_UINT256,
1008
- )
1009
-
1010
- result = await self._send_tx(approve_tx)
1011
-
1012
- # Small delay after approval to ensure state is propagated on providers/chains
1013
- # where we don't wait for additional confirmations by default.
1014
- if result[0]:
1015
- confirmations = 0
1016
- if isinstance(result[1], dict):
1017
- try:
1018
- confirmations = int(result[1].get("confirmations") or 0)
1019
- except (TypeError, ValueError):
1020
- confirmations = 0
1021
- if confirmations == 0:
1022
- await asyncio.sleep(1.0)
1023
-
1024
- return result
953
+ return (True, txn_hash)
1025
954
 
1026
955
  async def _encode_call(
1027
956
  self,
@@ -1052,22 +981,3 @@ class MoonwellAdapter(BaseAdapter):
1052
981
  "value": int(value),
1053
982
  }
1054
983
  return tx
1055
-
1056
- def _strategy_address(self) -> str:
1057
- addr = None
1058
- if isinstance(self.strategy_wallet, dict):
1059
- addr = self.strategy_wallet.get("address") or (
1060
- (self.strategy_wallet.get("evm") or {}).get("address")
1061
- )
1062
- elif isinstance(self.strategy_wallet, str):
1063
- addr = self.strategy_wallet
1064
- if not addr:
1065
- raise ValueError(
1066
- "strategy_wallet address is required for Moonwell operations"
1067
- )
1068
- return to_checksum_address(addr)
1069
-
1070
- def _checksum(self, address: str | None) -> str:
1071
- if not address:
1072
- raise ValueError("Missing required contract address in Moonwell config")
1073
- return to_checksum_address(address)