wayfinder-paths 0.1.19__py3-none-any.whl → 0.1.20__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 (98) hide show
  1. wayfinder_paths/__init__.py +0 -2
  2. wayfinder_paths/adapters/balance_adapter/README.md +59 -45
  3. wayfinder_paths/adapters/balance_adapter/adapter.py +0 -21
  4. wayfinder_paths/adapters/balance_adapter/test_adapter.py +0 -14
  5. wayfinder_paths/adapters/brap_adapter/README.md +61 -184
  6. wayfinder_paths/adapters/brap_adapter/__init__.py +0 -4
  7. wayfinder_paths/adapters/brap_adapter/adapter.py +0 -147
  8. wayfinder_paths/adapters/brap_adapter/test_adapter.py +0 -15
  9. wayfinder_paths/adapters/hyperlend_adapter/__init__.py +0 -4
  10. wayfinder_paths/adapters/hyperlend_adapter/adapter.py +0 -9
  11. wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +0 -17
  12. wayfinder_paths/adapters/hyperliquid_adapter/adapter.py +3 -312
  13. wayfinder_paths/adapters/hyperliquid_adapter/executor.py +1 -71
  14. wayfinder_paths/adapters/hyperliquid_adapter/paired_filler.py +0 -57
  15. wayfinder_paths/adapters/hyperliquid_adapter/test_adapter.py +0 -17
  16. wayfinder_paths/adapters/hyperliquid_adapter/test_adapter_live.py +2 -42
  17. wayfinder_paths/adapters/hyperliquid_adapter/test_executor.py +1 -9
  18. wayfinder_paths/adapters/hyperliquid_adapter/test_utils.py +15 -47
  19. wayfinder_paths/adapters/hyperliquid_adapter/utils.py +0 -7
  20. wayfinder_paths/adapters/ledger_adapter/README.md +54 -74
  21. wayfinder_paths/adapters/ledger_adapter/__init__.py +0 -4
  22. wayfinder_paths/adapters/ledger_adapter/adapter.py +0 -106
  23. wayfinder_paths/adapters/ledger_adapter/test_adapter.py +0 -12
  24. wayfinder_paths/adapters/moonwell_adapter/README.md +67 -106
  25. wayfinder_paths/adapters/moonwell_adapter/__init__.py +0 -4
  26. wayfinder_paths/adapters/moonwell_adapter/adapter.py +9 -121
  27. wayfinder_paths/adapters/moonwell_adapter/test_adapter.py +84 -83
  28. wayfinder_paths/adapters/pool_adapter/README.md +30 -51
  29. wayfinder_paths/adapters/pool_adapter/__init__.py +0 -4
  30. wayfinder_paths/adapters/pool_adapter/adapter.py +0 -19
  31. wayfinder_paths/adapters/pool_adapter/test_adapter.py +0 -8
  32. wayfinder_paths/adapters/token_adapter/README.md +41 -49
  33. wayfinder_paths/adapters/token_adapter/adapter.py +0 -32
  34. wayfinder_paths/adapters/token_adapter/test_adapter.py +1 -12
  35. wayfinder_paths/conftest.py +0 -8
  36. wayfinder_paths/core/__init__.py +0 -2
  37. wayfinder_paths/core/adapters/BaseAdapter.py +0 -22
  38. wayfinder_paths/core/adapters/__init__.py +0 -5
  39. wayfinder_paths/core/adapters/models.py +0 -5
  40. wayfinder_paths/core/analytics/__init__.py +0 -2
  41. wayfinder_paths/core/analytics/bootstrap.py +0 -16
  42. wayfinder_paths/core/analytics/stats.py +0 -7
  43. wayfinder_paths/core/analytics/test_analytics.py +5 -34
  44. wayfinder_paths/core/clients/BRAPClient.py +0 -35
  45. wayfinder_paths/core/clients/ClientManager.py +0 -51
  46. wayfinder_paths/core/clients/HyperlendClient.py +0 -77
  47. wayfinder_paths/core/clients/LedgerClient.py +2 -122
  48. wayfinder_paths/core/clients/PoolClient.py +0 -2
  49. wayfinder_paths/core/clients/TokenClient.py +0 -39
  50. wayfinder_paths/core/clients/WalletClient.py +0 -15
  51. wayfinder_paths/core/clients/WayfinderClient.py +0 -24
  52. wayfinder_paths/core/clients/__init__.py +0 -4
  53. wayfinder_paths/core/clients/protocols.py +25 -98
  54. wayfinder_paths/core/config.py +0 -24
  55. wayfinder_paths/core/constants/__init__.py +0 -7
  56. wayfinder_paths/core/constants/base.py +2 -9
  57. wayfinder_paths/core/constants/erc20_abi.py +0 -5
  58. wayfinder_paths/core/constants/hyperlend_abi.py +0 -7
  59. wayfinder_paths/core/constants/moonwell_abi.py +0 -35
  60. wayfinder_paths/core/engine/StrategyJob.py +0 -32
  61. wayfinder_paths/core/strategies/Strategy.py +0 -99
  62. wayfinder_paths/core/strategies/__init__.py +0 -2
  63. wayfinder_paths/core/utils/__init__.py +0 -1
  64. wayfinder_paths/core/utils/erc20_service.py +0 -1
  65. wayfinder_paths/core/utils/evm_helpers.py +0 -50
  66. wayfinder_paths/core/utils/transaction.py +0 -1
  67. wayfinder_paths/run_strategy.py +0 -46
  68. wayfinder_paths/scripts/create_strategy.py +0 -17
  69. wayfinder_paths/scripts/make_wallets.py +1 -4
  70. wayfinder_paths/strategies/basis_trading_strategy/README.md +71 -163
  71. wayfinder_paths/strategies/basis_trading_strategy/snapshot_mixin.py +0 -24
  72. wayfinder_paths/strategies/basis_trading_strategy/strategy.py +36 -400
  73. wayfinder_paths/strategies/basis_trading_strategy/test_strategy.py +15 -64
  74. wayfinder_paths/strategies/basis_trading_strategy/types.py +0 -4
  75. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/README.md +65 -56
  76. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +4 -27
  77. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +0 -10
  78. wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/README.md +71 -72
  79. wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py +23 -227
  80. wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/test_strategy.py +120 -113
  81. wayfinder_paths/strategies/stablecoin_yield_strategy/README.md +64 -59
  82. wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +4 -44
  83. wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +2 -35
  84. wayfinder_paths/templates/adapter/README.md +107 -46
  85. wayfinder_paths/templates/adapter/adapter.py +0 -9
  86. wayfinder_paths/templates/adapter/test_adapter.py +0 -19
  87. wayfinder_paths/templates/strategy/README.md +113 -59
  88. wayfinder_paths/templates/strategy/strategy.py +0 -22
  89. wayfinder_paths/templates/strategy/test_strategy.py +0 -28
  90. wayfinder_paths/tests/test_test_coverage.py +2 -12
  91. wayfinder_paths/tests/test_utils.py +1 -31
  92. wayfinder_paths-0.1.20.dist-info/METADATA +355 -0
  93. wayfinder_paths-0.1.20.dist-info/RECORD +129 -0
  94. wayfinder_paths/core/adapters/base.py +0 -5
  95. wayfinder_paths-0.1.19.dist-info/METADATA +0 -592
  96. wayfinder_paths-0.1.19.dist-info/RECORD +0 -130
  97. {wayfinder_paths-0.1.19.dist-info → wayfinder_paths-0.1.20.dist-info}/LICENSE +0 -0
  98. {wayfinder_paths-0.1.19.dist-info → wayfinder_paths-0.1.20.dist-info}/WHEEL +0 -0
@@ -1,10 +1,3 @@
1
- """
2
- Moonwell Adapter for lending, borrowing, and collateral management on Moonwell protocol.
3
-
4
- This adapter provides functionality for interacting with Moonwell on Base chain,
5
- including supplying/withdrawing collateral, borrowing/repaying, and claiming rewards.
6
- """
7
-
8
1
  from __future__ import annotations
9
2
 
10
3
  import asyncio
@@ -59,37 +52,31 @@ CF_CACHE_TTL = 3600
59
52
 
60
53
  # Default retry settings for rate-limited RPCs
61
54
  DEFAULT_MAX_RETRIES = 5
62
- DEFAULT_BASE_DELAY = 3.0 # seconds
55
+ DEFAULT_BASE_DELAY = 3.0
63
56
 
64
57
 
65
58
  def _is_rate_limit_error(error: Exception | str) -> bool:
66
- """Check if an error is a rate limit (429) error."""
67
59
  error_str = str(error)
68
60
  return "429" in error_str or "Too Many Requests" in error_str
69
61
 
70
62
 
71
63
  def _timestamp_rate_to_apy(rate: float) -> float:
72
- """Convert a per-second rate to APY."""
73
64
  return (1 + rate) ** SECONDS_PER_YEAR - 1
74
65
 
75
66
 
76
67
  class MoonwellAdapter(BaseAdapter):
77
- """Moonwell adapter for lending/borrowing operations on Base chain."""
78
-
79
68
  adapter_type = "MOONWELL"
80
69
 
81
70
  def __init__(
82
71
  self,
83
72
  config: dict[str, Any] | None = None,
84
73
  token_client: TokenClient | None = None,
85
- simulation: bool = False,
86
74
  strategy_wallet_signing_callback=None,
87
75
  ) -> None:
88
76
  super().__init__("moonwell_adapter", config)
89
77
  cfg = config or {}
90
78
  adapter_cfg = cfg.get("moonwell_adapter") or {}
91
79
 
92
- self.simulation = simulation
93
80
  self.token_client = token_client
94
81
  self.strategy_wallet_signing_callback = strategy_wallet_signing_callback
95
82
 
@@ -139,7 +126,6 @@ class MoonwellAdapter(BaseAdapter):
139
126
  underlying_token: str,
140
127
  amount: int,
141
128
  ) -> tuple[bool, Any]:
142
- """Supply tokens to Moonwell by minting mTokens."""
143
129
  strategy = self._strategy_address()
144
130
  amount = int(amount)
145
131
  if amount <= 0:
@@ -174,7 +160,6 @@ class MoonwellAdapter(BaseAdapter):
174
160
  mtoken: str,
175
161
  amount: int,
176
162
  ) -> tuple[bool, Any]:
177
- """Withdraw tokens from Moonwell by redeeming mTokens."""
178
163
  strategy = self._strategy_address()
179
164
  amount = int(amount)
180
165
  if amount <= 0:
@@ -202,13 +187,6 @@ class MoonwellAdapter(BaseAdapter):
202
187
  mtoken: str,
203
188
  amount: int,
204
189
  ) -> tuple[bool, Any]:
205
- """Borrow tokens from Moonwell.
206
-
207
- Note: Moonwell/Compound borrow() returns an error code, not a boolean.
208
- Even if the transaction succeeds (status=1), the borrow may have failed
209
- if the return value is non-zero. We verify success by checking that
210
- the borrow balance actually increased.
211
- """
212
190
  from loguru import logger
213
191
 
214
192
  strategy = self._strategy_address()
@@ -218,7 +196,6 @@ class MoonwellAdapter(BaseAdapter):
218
196
 
219
197
  mtoken = self._checksum(mtoken)
220
198
 
221
- # Get borrow balance before the transaction for verification
222
199
  borrow_before = 0
223
200
  try:
224
201
  async with web3_from_chain_id(self.chain_id) as web3:
@@ -266,7 +243,7 @@ class MoonwellAdapter(BaseAdapter):
266
243
 
267
244
  # Borrow balance should have increased by approximately the amount
268
245
  # Allow for some interest accrual
269
- expected_increase = amount * 0.99 # Allow 1% tolerance for interest
246
+ expected_increase = amount * 0.99
270
247
  actual_increase = borrow_after - borrow_before
271
248
 
272
249
  if actual_increase < expected_increase:
@@ -299,14 +276,6 @@ class MoonwellAdapter(BaseAdapter):
299
276
  amount: int,
300
277
  repay_full: bool = False,
301
278
  ) -> tuple[bool, Any]:
302
- """Repay borrowed tokens to Moonwell.
303
-
304
- Args:
305
- mtoken: The mToken address
306
- underlying_token: The underlying token address (e.g., WETH)
307
- amount: Amount to repay (used for approval if repay_full=True)
308
- repay_full: If True, uses type(uint256).max to repay exact debt
309
- """
310
279
  strategy = self._strategy_address()
311
280
  amount = int(amount)
312
281
  if amount <= 0:
@@ -347,11 +316,6 @@ class MoonwellAdapter(BaseAdapter):
347
316
  *,
348
317
  mtoken: str,
349
318
  ) -> tuple[bool, Any]:
350
- """Enable a market as collateral (enter market).
351
-
352
- Note: enterMarkets returns an array of error codes. We verify success
353
- by checking if the account has actually entered the market.
354
- """
355
319
  strategy = self._strategy_address()
356
320
  mtoken = self._checksum(mtoken)
357
321
 
@@ -401,10 +365,6 @@ class MoonwellAdapter(BaseAdapter):
401
365
  mtoken: str,
402
366
  account: str | None = None,
403
367
  ) -> tuple[bool, bool | str]:
404
- """Check whether an account has entered a given market (as collateral / borrowing market)."""
405
- if self.simulation:
406
- return True, True
407
-
408
368
  try:
409
369
  acct = self._checksum(account) if account else self._strategy_address()
410
370
  mtoken = self._checksum(mtoken)
@@ -425,7 +385,6 @@ class MoonwellAdapter(BaseAdapter):
425
385
  *,
426
386
  mtoken: str,
427
387
  ) -> tuple[bool, Any]:
428
- """Disable a market as collateral (exit market)."""
429
388
  strategy = self._strategy_address()
430
389
  mtoken = self._checksum(mtoken)
431
390
 
@@ -447,21 +406,18 @@ class MoonwellAdapter(BaseAdapter):
447
406
  *,
448
407
  min_rewards_usd: float = 0.0,
449
408
  ) -> tuple[bool, dict[str, int] | str]:
450
- """Claim WELL rewards from Moonwell. Skips if below min_rewards_usd threshold."""
451
409
  strategy = self._strategy_address()
452
410
 
453
- # Get outstanding rewards first
454
411
  rewards = await self._get_outstanding_rewards(strategy)
455
412
 
456
413
  # Skip if no rewards to claim
457
414
  if not rewards:
458
415
  return True, {}
459
416
 
460
- # Check minimum threshold if token_client available
461
417
  if min_rewards_usd > 0 and self.token_client:
462
418
  total_usd = await self._calculate_rewards_usd(rewards)
463
419
  if total_usd < min_rewards_usd:
464
- return True, {} # Skip claiming, below threshold
420
+ return True, {}
465
421
 
466
422
  # Claim via comptroller (like reference implementation)
467
423
  tx = await self._encode_call(
@@ -478,14 +434,12 @@ class MoonwellAdapter(BaseAdapter):
478
434
  return True, rewards
479
435
 
480
436
  async def _get_outstanding_rewards(self, account: str) -> dict[str, int]:
481
- """Get outstanding rewards for an account across all markets."""
482
437
  try:
483
438
  async with web3_from_chain_id(self.chain_id) as web3:
484
439
  contract = web3.eth.contract(
485
440
  address=self.reward_distributor_address, abi=REWARD_DISTRIBUTOR_ABI
486
441
  )
487
442
 
488
- # Call getOutstandingRewardsForUser(user)
489
443
  all_rewards = await contract.functions.getOutstandingRewardsForUser(
490
444
  account
491
445
  ).call(block_identifier="pending")
@@ -507,7 +461,6 @@ class MoonwellAdapter(BaseAdapter):
507
461
  return {}
508
462
 
509
463
  async def _calculate_rewards_usd(self, rewards: dict[str, int]) -> float:
510
- """Calculate total USD value of rewards."""
511
464
  if not self.token_client:
512
465
  return 0.0
513
466
 
@@ -536,20 +489,6 @@ class MoonwellAdapter(BaseAdapter):
536
489
  max_retries: int = 3,
537
490
  block_identifier: int | str | None = None,
538
491
  ) -> tuple[bool, dict[str, Any] | str]:
539
- """Get position data (balances, rewards) for an account in a market.
540
-
541
- Args:
542
- mtoken: The mToken address
543
- account: Account to query (defaults to strategy wallet)
544
- include_usd: Whether to include USD values
545
- max_retries: Number of retry attempts
546
- block_identifier: Block to query at. Can be:
547
- - int: specific block number (for pinning to tx block)
548
- - "safe": OP Stack safe block (data posted to L1)
549
- - None/"pending": current head (default)
550
-
551
- Includes retry logic with exponential backoff for rate-limited RPCs.
552
- """
553
492
  mtoken = self._checksum(mtoken)
554
493
  account = self._checksum(account) if account else self._strategy_address()
555
494
  block_id = block_identifier if block_identifier is not None else "pending"
@@ -566,7 +505,6 @@ class MoonwellAdapter(BaseAdapter):
566
505
  abi=REWARD_DISTRIBUTOR_ABI,
567
506
  )
568
507
 
569
- # Fetch data sequentially to avoid overwhelming rate-limited public RPCs
570
508
  # (parallel fetch would make 5 simultaneous calls per position)
571
509
  bal = await mtoken_contract.functions.balanceOf(account).call(
572
510
  block_identifier=block_id
@@ -585,12 +523,12 @@ class MoonwellAdapter(BaseAdapter):
585
523
  mtoken, account
586
524
  ).call(block_identifier=block_id)
587
525
  )
588
- break # Success, exit retry loop
526
+ break
589
527
  except Exception as exc:
590
528
  last_error = str(exc)
591
529
  if "429" in last_error or "Too Many Requests" in last_error:
592
530
  if attempt < max_retries - 1:
593
- wait_time = 2 ** (attempt + 1) # 2, 4, 8 seconds
531
+ wait_time = 2 ** (attempt + 1)
594
532
  await asyncio.sleep(wait_time)
595
533
  continue
596
534
  return False, last_error
@@ -599,10 +537,8 @@ class MoonwellAdapter(BaseAdapter):
599
537
  return False, last_error
600
538
 
601
539
  try:
602
- # Process rewards
603
540
  reward_balances = self._process_rewards(rewards)
604
541
 
605
- # Build balances dict
606
542
  mtoken_key = f"{self.chain_name}_{mtoken}"
607
543
  underlying_key = f"{self.chain_name}_{underlying}"
608
544
 
@@ -621,7 +557,6 @@ class MoonwellAdapter(BaseAdapter):
621
557
  "underlying_token": underlying,
622
558
  }
623
559
 
624
- # Calculate USD values if requested and token_client available
625
560
  if include_usd and self.token_client:
626
561
  usd_balances = await self._calculate_usd_balances(
627
562
  balances, underlying_key, exch
@@ -633,7 +568,6 @@ class MoonwellAdapter(BaseAdapter):
633
568
  return False, str(exc)
634
569
 
635
570
  def _process_rewards(self, rewards: list) -> dict[str, int]:
636
- """Process rewards tuple into dict mapping token keys to amounts."""
637
571
  result: dict[str, int] = {}
638
572
  for reward_info in rewards:
639
573
  if len(reward_info) >= 2:
@@ -647,11 +581,9 @@ class MoonwellAdapter(BaseAdapter):
647
581
  async def _calculate_usd_balances(
648
582
  self, balances: dict[str, int], underlying_key: str, _exchange_rate: int
649
583
  ) -> dict[str, float | None]:
650
- """Calculate USD values for balances."""
651
584
  if not self.token_client:
652
585
  return {}
653
586
 
654
- # Fetch token data for all tokens
655
587
  tokens = set(balances.keys()) | {underlying_key}
656
588
  token_data: dict[str, dict | None] = {}
657
589
  for token_key in tokens:
@@ -662,7 +594,6 @@ class MoonwellAdapter(BaseAdapter):
662
594
  except Exception:
663
595
  token_data[token_key] = None
664
596
 
665
- # Calculate USD values
666
597
  usd_balances: dict[str, float | None] = {}
667
598
  for token_key, bal in balances.items():
668
599
  data = token_data.get(token_key)
@@ -684,14 +615,8 @@ class MoonwellAdapter(BaseAdapter):
684
615
  mtoken: str,
685
616
  max_retries: int = DEFAULT_MAX_RETRIES,
686
617
  ) -> tuple[bool, float | str]:
687
- """Get the collateral factor for a market as decimal (e.g., 0.75 for 75%).
688
-
689
- Uses a 1-hour cache since collateral factors rarely change (governance controlled).
690
- Includes retry logic with exponential backoff for rate-limited RPCs.
691
- """
692
618
  mtoken = self._checksum(mtoken)
693
619
 
694
- # Check cache first
695
620
  now = time.time()
696
621
  if mtoken in self._cf_cache:
697
622
  cached_value, cached_time = self._cf_cache[mtoken]
@@ -715,7 +640,6 @@ class MoonwellAdapter(BaseAdapter):
715
640
  if not is_listed:
716
641
  return False, f"Market {mtoken} is not listed"
717
642
 
718
- # Convert from mantissa to decimal
719
643
  collateral_factor = collateral_factor_mantissa / MANTISSA
720
644
 
721
645
  # Cache the result
@@ -740,10 +664,6 @@ class MoonwellAdapter(BaseAdapter):
740
664
  include_rewards: bool = True,
741
665
  max_retries: int = DEFAULT_MAX_RETRIES,
742
666
  ) -> tuple[bool, float | str]:
743
- """Get supply or borrow APY for a market, optionally including WELL rewards.
744
-
745
- Includes retry logic with exponential backoff for rate-limited RPCs.
746
- """
747
667
  mtoken = self._checksum(mtoken)
748
668
 
749
669
  last_error = ""
@@ -756,7 +676,6 @@ class MoonwellAdapter(BaseAdapter):
756
676
  abi=REWARD_DISTRIBUTOR_ABI,
757
677
  )
758
678
 
759
- # Get base rate (sequential to avoid rate limits)
760
679
  if apy_type == "supply":
761
680
  rate_per_timestamp = await mtoken_contract.functions.supplyRatePerTimestamp().call(
762
681
  block_identifier="pending"
@@ -786,11 +705,9 @@ class MoonwellAdapter(BaseAdapter):
786
705
  )
787
706
  )
788
707
 
789
- # Convert rate per second to APY
790
708
  rate = rate_per_timestamp / MANTISSA
791
709
  apy = _timestamp_rate_to_apy(rate)
792
710
 
793
- # Add WELL rewards APY if requested and token_client available
794
711
  if include_rewards and self.token_client and total_value > 0:
795
712
  rewards_apr = await self._calculate_rewards_apr(
796
713
  mtoken, mkt_config, total_value, apy_type
@@ -815,7 +732,6 @@ class MoonwellAdapter(BaseAdapter):
815
732
  total_value: int,
816
733
  apy_type: str,
817
734
  ) -> float:
818
- """Calculate WELL rewards APR for a market."""
819
735
  if not self.token_client:
820
736
  return 0.0
821
737
 
@@ -830,12 +746,11 @@ class MoonwellAdapter(BaseAdapter):
830
746
  if not well_config:
831
747
  return 0.0
832
748
 
833
- # Get emission rate (supply or borrow)
834
749
  # Config format: (mToken, rewardToken, owner, emissionCap, supplyEmissionsPerSec, borrowEmissionsPerSec, ...)
835
750
  if apy_type == "supply":
836
- well_rate = well_config[4] # supplyEmissionsPerSec
751
+ well_rate = well_config[4]
837
752
  else:
838
- well_rate = well_config[5] # borrowEmissionsPerSec
753
+ well_rate = well_config[5]
839
754
  # Borrow rewards are shown as negative in some implementations
840
755
  if well_rate < 0:
841
756
  well_rate = -well_rate
@@ -843,14 +758,12 @@ class MoonwellAdapter(BaseAdapter):
843
758
  if well_rate == 0:
844
759
  return 0.0
845
760
 
846
- # Get underlying token for decimals
847
761
  async with web3_from_chain_id(self.chain_id) as web3:
848
762
  mtoken_contract = web3.eth.contract(address=mtoken, abi=MTOKEN_ABI)
849
763
  underlying_addr = await mtoken_contract.functions.underlying().call(
850
764
  block_identifier="pending"
851
765
  )
852
766
 
853
- # Get prices
854
767
  well_key = f"{self.chain_name}_{self.well_token}"
855
768
  underlying_key = f"{self.chain_name}_{underlying_addr}"
856
769
 
@@ -876,7 +789,6 @@ class MoonwellAdapter(BaseAdapter):
876
789
  if not well_price or not underlying_price:
877
790
  return 0.0
878
791
 
879
- # Calculate total value in USD
880
792
  total_value_usd = (
881
793
  total_value / (10**underlying_decimals)
882
794
  ) * underlying_price
@@ -884,7 +796,6 @@ class MoonwellAdapter(BaseAdapter):
884
796
  if total_value_usd == 0:
885
797
  return 0.0
886
798
 
887
- # Calculate rewards APR
888
799
  # rewards_apr = well_price * emissions_per_second * seconds_per_year / total_value_usd
889
800
  rewards_apr = (
890
801
  well_price * (well_rate / MANTISSA) * SECONDS_PER_YEAR / total_value_usd
@@ -900,10 +811,6 @@ class MoonwellAdapter(BaseAdapter):
900
811
  account: str | None = None,
901
812
  max_retries: int = DEFAULT_MAX_RETRIES,
902
813
  ) -> tuple[bool, int | str]:
903
- """Get the maximum borrowable amount for an account (USD with 18 decimals).
904
-
905
- Includes retry logic with exponential backoff for rate-limited RPCs.
906
- """
907
814
  account = self._checksum(account) if account else self._strategy_address()
908
815
 
909
816
  last_error = ""
@@ -914,7 +821,6 @@ class MoonwellAdapter(BaseAdapter):
914
821
  address=self.comptroller_address, abi=COMPTROLLER_ABI
915
822
  )
916
823
 
917
- # getAccountLiquidity returns (error, liquidity, shortfall)
918
824
  (
919
825
  error,
920
826
  liquidity,
@@ -946,7 +852,6 @@ class MoonwellAdapter(BaseAdapter):
946
852
  mtoken: str,
947
853
  account: str | None = None,
948
854
  ) -> tuple[bool, dict[str, Any] | str]:
949
- """Calculate max mTokens withdrawable without liquidation using binary search."""
950
855
  mtoken = self._checksum(mtoken)
951
856
  account = self._checksum(account) if account else self._strategy_address()
952
857
 
@@ -957,7 +862,6 @@ class MoonwellAdapter(BaseAdapter):
957
862
  )
958
863
  mtoken_contract = web3.eth.contract(address=mtoken, abi=MTOKEN_ABI)
959
864
 
960
- # Get all needed data in parallel
961
865
  bal_raw, exch_raw, cash_raw, m_dec, u_addr = await asyncio.gather(
962
866
  mtoken_contract.functions.balanceOf(account).call(
963
867
  block_identifier="pending"
@@ -988,8 +892,7 @@ class MoonwellAdapter(BaseAdapter):
988
892
  "underlying_decimals": None,
989
893
  }
990
894
 
991
- # Get underlying decimals
992
- u_dec = 18 # Default
895
+ u_dec = 18
993
896
  if self.token_client:
994
897
  try:
995
898
  u_key = f"{self.chain_name}_{u_addr}"
@@ -1013,7 +916,7 @@ class MoonwellAdapter(BaseAdapter):
1013
916
  if err != 0:
1014
917
  return False, f"Comptroller error {err}"
1015
918
  if short == 0:
1016
- lo = mid # Safe, try more
919
+ lo = mid
1017
920
  else:
1018
921
  hi = mid - 1
1019
922
 
@@ -1055,7 +958,6 @@ class MoonwellAdapter(BaseAdapter):
1055
958
  *,
1056
959
  amount: int,
1057
960
  ) -> tuple[bool, Any]:
1058
- """Wrap ETH to WETH."""
1059
961
  strategy = self._strategy_address()
1060
962
  amount = int(amount)
1061
963
  if amount <= 0:
@@ -1079,9 +981,6 @@ class MoonwellAdapter(BaseAdapter):
1079
981
  MAX_UINT256 = 2**256 - 1
1080
982
 
1081
983
  async def _send_tx(self, tx: dict[str, Any]) -> tuple[bool, Any]:
1082
- """Send transaction with simulation check."""
1083
- if self.simulation:
1084
- return True, {"simulation": tx}
1085
984
  txn_hash = await send_transaction(tx, self.strategy_wallet_signing_callback)
1086
985
  return True, txn_hash
1087
986
 
@@ -1093,14 +992,6 @@ class MoonwellAdapter(BaseAdapter):
1093
992
  spender: str,
1094
993
  amount: int,
1095
994
  ) -> tuple[bool, Any]:
1096
- """Ensure token allowance is sufficient, approving if needed.
1097
-
1098
- Approves for max uint256 to avoid precision issues with exact amounts.
1099
- In simulation mode, skips the allowance check and assumes approval needed.
1100
- """
1101
- if self.simulation:
1102
- return True, {} # Skip allowance check in simulation
1103
-
1104
995
  allowance = await get_token_allowance(
1105
996
  token_address, self.chain_id, owner, spender
1106
997
  )
@@ -1142,7 +1033,6 @@ class MoonwellAdapter(BaseAdapter):
1142
1033
  from_address: str,
1143
1034
  value: int = 0,
1144
1035
  ) -> dict[str, Any]:
1145
- """Encode a contract call without touching the network."""
1146
1036
  async with web3_from_chain_id(self.chain_id) as web3:
1147
1037
  contract = web3.eth.contract(address=target, abi=abi)
1148
1038
 
@@ -1164,7 +1054,6 @@ class MoonwellAdapter(BaseAdapter):
1164
1054
  return tx
1165
1055
 
1166
1056
  def _strategy_address(self) -> str:
1167
- """Get the strategy wallet address."""
1168
1057
  addr = None
1169
1058
  if isinstance(self.strategy_wallet, dict):
1170
1059
  addr = self.strategy_wallet.get("address") or (
@@ -1179,7 +1068,6 @@ class MoonwellAdapter(BaseAdapter):
1179
1068
  return to_checksum_address(addr)
1180
1069
 
1181
1070
  def _checksum(self, address: str | None) -> str:
1182
- """Convert address to checksum format."""
1183
1071
  if not address:
1184
1072
  raise ValueError("Missing required contract address in Moonwell config")
1185
1073
  return to_checksum_address(address)