wayfinder-paths 0.1.7__py3-none-any.whl → 0.1.9__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 (51) hide show
  1. wayfinder_paths/CONFIG_GUIDE.md +5 -14
  2. wayfinder_paths/adapters/brap_adapter/README.md +1 -1
  3. wayfinder_paths/adapters/brap_adapter/adapter.py +1 -53
  4. wayfinder_paths/adapters/brap_adapter/test_adapter.py +5 -7
  5. wayfinder_paths/adapters/hyperlend_adapter/adapter.py +0 -7
  6. wayfinder_paths/adapters/hyperliquid_adapter/adapter.py +0 -54
  7. wayfinder_paths/adapters/hyperliquid_adapter/test_adapter_live.py +1 -1
  8. wayfinder_paths/adapters/ledger_adapter/README.md +1 -1
  9. wayfinder_paths/adapters/ledger_adapter/test_adapter.py +3 -0
  10. wayfinder_paths/adapters/pool_adapter/README.md +3 -104
  11. wayfinder_paths/adapters/pool_adapter/adapter.py +0 -194
  12. wayfinder_paths/adapters/pool_adapter/examples.json +0 -100
  13. wayfinder_paths/adapters/pool_adapter/test_adapter.py +0 -134
  14. wayfinder_paths/adapters/token_adapter/README.md +1 -1
  15. wayfinder_paths/core/clients/AuthClient.py +0 -3
  16. wayfinder_paths/core/clients/BRAPClient.py +1 -0
  17. wayfinder_paths/core/clients/ClientManager.py +1 -22
  18. wayfinder_paths/core/clients/PoolClient.py +0 -16
  19. wayfinder_paths/core/clients/WalletClient.py +0 -8
  20. wayfinder_paths/core/clients/WayfinderClient.py +9 -14
  21. wayfinder_paths/core/clients/__init__.py +0 -8
  22. wayfinder_paths/core/clients/protocols.py +0 -64
  23. wayfinder_paths/core/config.py +5 -45
  24. wayfinder_paths/core/engine/StrategyJob.py +0 -3
  25. wayfinder_paths/core/services/base.py +0 -49
  26. wayfinder_paths/core/services/local_evm_txn.py +3 -82
  27. wayfinder_paths/core/services/local_token_txn.py +61 -70
  28. wayfinder_paths/core/services/web3_service.py +0 -2
  29. wayfinder_paths/core/settings.py +8 -8
  30. wayfinder_paths/core/strategies/Strategy.py +1 -5
  31. wayfinder_paths/core/utils/evm_helpers.py +7 -12
  32. wayfinder_paths/core/wallets/README.md +3 -6
  33. wayfinder_paths/run_strategy.py +29 -32
  34. wayfinder_paths/scripts/make_wallets.py +1 -25
  35. wayfinder_paths/scripts/run_strategy.py +0 -2
  36. wayfinder_paths/strategies/basis_trading_strategy/snapshot_mixin.py +1 -3
  37. wayfinder_paths/strategies/basis_trading_strategy/strategy.py +86 -137
  38. wayfinder_paths/strategies/basis_trading_strategy/test_strategy.py +96 -58
  39. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/README.md +2 -2
  40. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/examples.json +4 -1
  41. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +106 -28
  42. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +53 -14
  43. wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +1 -6
  44. wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +40 -17
  45. wayfinder_paths/templates/strategy/test_strategy.py +0 -4
  46. {wayfinder_paths-0.1.7.dist-info → wayfinder_paths-0.1.9.dist-info}/METADATA +33 -15
  47. {wayfinder_paths-0.1.7.dist-info → wayfinder_paths-0.1.9.dist-info}/RECORD +49 -51
  48. wayfinder_paths/core/clients/SimulationClient.py +0 -192
  49. wayfinder_paths/core/clients/TransactionClient.py +0 -63
  50. {wayfinder_paths-0.1.7.dist-info → wayfinder_paths-0.1.9.dist-info}/LICENSE +0 -0
  51. {wayfinder_paths-0.1.7.dist-info → wayfinder_paths-0.1.9.dist-info}/WHEEL +0 -0
@@ -52,7 +52,6 @@ cp wayfinder_paths/config.example.json config.json
52
52
  **Option 1: Service Account (API Key) - Recommended for Production**
53
53
  - `user.api_key` - Your Wayfinder API key for service account authentication (loaded directly by clients from config.json)
54
54
  - OR `system.api_key` - System-level API key (alternative location, loaded directly by clients)
55
- - OR set `WAYFINDER_API_KEY` environment variable
56
55
  - OR pass `api_key` parameter to strategy constructor
57
56
 
58
57
  **Note:** API keys in `config.json` are loaded directly by `WayfinderClient` via `_load_config_credentials()`, not through the `UserConfig` or `SystemConfig` dataclasses. This is intentional to allow flexible credential loading.
@@ -229,7 +228,6 @@ The strategy system supports multiple wallet types through a wallet abstraction
229
228
 
230
229
  By default, adapters use `LocalWalletProvider` which resolves private keys from:
231
230
  - `wallets.json` (matched by address)
232
- - Environment variables (`PRIVATE_KEY`, `PRIVATE_KEY_STRATEGY`)
233
231
  - Wallet config in `config.json`
234
232
 
235
233
  No code changes are required - existing strategies continue to work.
@@ -270,7 +268,7 @@ Wayfinder Paths supports **dual authentication** for different use cases:
270
268
 
271
269
  **Best for:** Backend services, automated systems, and production deployments with higher rate limits.
272
270
 
273
- API keys provide service account authentication and are automatically discovered by all clients. You can provide an API key in three ways:
271
+ API keys provide service account authentication and are automatically discovered by all clients. You can provide an API key in two ways:
274
272
 
275
273
  #### Option A: Strategy Constructor (Programmatic)
276
274
  ```python
@@ -278,16 +276,11 @@ from wayfinder_paths.strategies.stablecoin_yield_strategy.strategy import Stable
278
276
 
279
277
  strategy = StablecoinYieldStrategy(
280
278
  config={...},
281
- api_key="sk_live_abc123..." # Sets WAYFINDER_API_KEY env var automatically
279
+ api_key="sk_live_abc123..." # API key is auto-discovered by all clients
282
280
  )
283
281
  ```
284
282
 
285
- #### Option B: Environment Variable
286
- ```bash
287
- export WAYFINDER_API_KEY="sk_live_abc123..."
288
- ```
289
-
290
- #### Option C: config.json
283
+ #### Option B: config.json
291
284
  ```json
292
285
  {
293
286
  "user": {
@@ -299,14 +292,12 @@ export WAYFINDER_API_KEY="sk_live_abc123..."
299
292
  }
300
293
  ```
301
294
 
302
- **Priority Order:** Constructor parameter > `config.json` (user.api_key or system.api_key) > `WAYFINDER_API_KEY` environment variable
295
+ **Priority Order:** Constructor parameter > `config.json` (user.api_key or system.api_key)
303
296
 
304
297
  **How It Works:**
305
- - When a strategy receives an `api_key`, it sets `os.environ["WAYFINDER_API_KEY"]`
306
298
  - All clients created by adapters automatically discover the API key from:
307
299
  - Constructor parameter (if passed)
308
300
  - `config.json` (via `WayfinderClient._load_config_credentials()` which reads `user.api_key` or `system.api_key`)
309
- - `WAYFINDER_API_KEY` environment variable
310
301
  - API keys are included in **all** API requests (including public endpoints) for rate limiting
311
302
  - No need to pass API keys explicitly to adapters or clients—they auto-discover it
312
303
  - **Note:** API keys in `config.json` are loaded directly by clients, not stored in the `UserConfig` or `SystemConfig` dataclasses
@@ -379,7 +370,7 @@ To use custom RPC endpoints, update the `strategy.rpc_urls` section in `config.j
379
370
  **Issue:** "Authentication failed"
380
371
  - **If using API key:**
381
372
  - Verify API key is correct and not expired
382
- - Check that API key is set in one of: constructor parameter, `config.json` (user.api_key or system.api_key), or `WAYFINDER_API_KEY` env var
373
+ - Check that API key is set in one of: constructor parameter or `config.json` (user.api_key or system.api_key)
383
374
  - Ensure API key has proper permissions for the operations you're performing
384
375
  - **If using OAuth:**
385
376
  - Check that `username` and `password` are correct in `config.json`
@@ -17,7 +17,7 @@ The adapter uses the BRAPClient which automatically handles authentication and A
17
17
 
18
18
  The BRAPClient will automatically:
19
19
  - Use the WAYFINDER_API_URL from settings
20
- - Handle authentication via environment variables or config.json
20
+ - Handle authentication via config.json
21
21
  - Manage token refresh and retry logic
22
22
 
23
23
  ## Usage
@@ -10,10 +10,6 @@ from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
10
10
  from wayfinder_paths.core.adapters.models import SWAP
11
11
  from wayfinder_paths.core.clients.BRAPClient import BRAPClient, BRAPQuote
12
12
  from wayfinder_paths.core.clients.LedgerClient import TransactionRecord
13
- from wayfinder_paths.core.clients.SimulationClient import (
14
- SimulationClient,
15
- SimulationResult,
16
- )
17
13
  from wayfinder_paths.core.clients.TokenClient import TokenClient
18
14
  from wayfinder_paths.core.constants import DEFAULT_SLIPPAGE
19
15
  from wayfinder_paths.core.constants.base import DEFAULT_TRANSACTION_TIMEOUT
@@ -45,7 +41,6 @@ class BRAPAdapter(BaseAdapter):
45
41
  config: dict[str, Any] | None = None,
46
42
  *,
47
43
  web3_service: Web3Service,
48
- simulation: bool = False,
49
44
  ):
50
45
  super().__init__("brap_adapter", config)
51
46
  self.brap_client = BRAPClient()
@@ -55,8 +50,6 @@ class BRAPAdapter(BaseAdapter):
55
50
  self.web3_service = web3_service
56
51
  self.wallet_provider = web3_service.evm_transactions
57
52
  self.token_transactions = web3_service.token_transactions
58
- self.simulation = simulation
59
- self.simulation_client = SimulationClient() if simulation else None
60
53
 
61
54
  async def get_swap_quote(
62
55
  self,
@@ -147,8 +140,7 @@ class BRAPAdapter(BaseAdapter):
147
140
  )
148
141
 
149
142
  # Extract best quote from response
150
- quotes = data.get("quotes", {})
151
- best_quote = quotes.get("best_quote")
143
+ best_quote = data["best_route"]
152
144
 
153
145
  if not best_quote:
154
146
  return (False, "No quotes available")
@@ -368,12 +360,6 @@ class BRAPAdapter(BaseAdapter):
368
360
  if not approve_success:
369
361
  return (False, approve_response)
370
362
 
371
- if self.simulation:
372
- simulation = await self._simulate_swap(
373
- from_token, to_token, from_address, chain_id, quote
374
- )
375
- return (True, {"quote": quote, "simulation": simulation})
376
-
377
363
  broadcast_success, broadcast_response = await self._broadcast_transaction(
378
364
  transaction
379
365
  )
@@ -678,44 +664,6 @@ class BRAPAdapter(BaseAdapter):
678
664
  / 10 ** int(decimals)
679
665
  )
680
666
 
681
- async def _simulate_swap(
682
- self,
683
- from_token: dict[str, Any],
684
- to_token: dict[str, Any],
685
- from_address: str,
686
- chain_id: int,
687
- quote: dict[str, Any],
688
- ) -> SimulationResult:
689
- client = await self._get_simulation_client()
690
- initial_balances = {"native": "5000000000000000000"}
691
- if from_token.get("address"):
692
- initial_balances[from_token.get("address")] = "1000000000000000000000000"
693
-
694
- slippage = quote.get("slippage") or quote.get("slippage_percent")
695
- if isinstance(slippage, str):
696
- try:
697
- slippage = float(slippage)
698
- except ValueError:
699
- slippage = DEFAULT_SLIPPAGE
700
- slippage = slippage or DEFAULT_SLIPPAGE
701
-
702
- amount = quote.get("input_amount") or quote.get("inputAmount") or "0"
703
- return await client.simulate_swap(
704
- from_token_address=from_token.get("address"),
705
- to_token_address=to_token.get("address"),
706
- from_chain_id=chain_id,
707
- to_chain_id=chain_id,
708
- amount=str(amount),
709
- from_address=from_address,
710
- slippage=float(slippage),
711
- initial_balances=initial_balances,
712
- )
713
-
714
- async def _get_simulation_client(self) -> SimulationClient:
715
- if not self.simulation_client:
716
- self.simulation_client = SimulationClient()
717
- return self.simulation_client
718
-
719
667
  def _chain_id(self, chain: Any) -> int:
720
668
  if isinstance(chain, dict):
721
669
  chain_id = chain.get("id") or chain.get("chain_id")
@@ -81,12 +81,10 @@ class TestBRAPAdapter:
81
81
  async def test_get_best_quote_success(self, adapter, mock_brap_client):
82
82
  """Test successful best quote retrieval"""
83
83
  mock_response = {
84
- "quotes": {
85
- "best_quote": {
86
- "input_amount": "1000000000000000000",
87
- "output_amount": "995000000000000000",
88
- "total_fee": "8000000000000000",
89
- }
84
+ "best_route": {
85
+ "input_amount": "1000000000000000000",
86
+ "output_amount": "995000000000000000",
87
+ "total_fee": "8000000000000000",
90
88
  }
91
89
  }
92
90
  mock_brap_client.get_quote = AsyncMock(return_value=mock_response)
@@ -108,7 +106,7 @@ class TestBRAPAdapter:
108
106
  @pytest.mark.asyncio
109
107
  async def test_get_best_quote_no_quotes(self, adapter, mock_brap_client):
110
108
  """Test best quote retrieval when no quotes available"""
111
- mock_response = {"quotes": {}}
109
+ mock_response = {"best_route": None}
112
110
  mock_brap_client.get_quote = AsyncMock(return_value=mock_response)
113
111
 
114
112
  success, data = await adapter.get_best_quote(
@@ -12,7 +12,6 @@ from wayfinder_paths.core.clients.HyperlendClient import (
12
12
  MarketEntry,
13
13
  StableMarket,
14
14
  )
15
- from wayfinder_paths.core.clients.SimulationClient import SimulationClient
16
15
  from wayfinder_paths.core.constants.base import DEFAULT_TRANSACTION_TIMEOUT
17
16
  from wayfinder_paths.core.constants.hyperlend_abi import (
18
17
  POOL_ABI,
@@ -37,16 +36,12 @@ class HyperlendAdapter(BaseAdapter):
37
36
  self,
38
37
  config: dict[str, Any],
39
38
  web3_service: Web3Service,
40
- simulation: bool = False,
41
39
  ) -> None:
42
40
  super().__init__("hyperlend_adapter", config)
43
41
  cfg = config or {}
44
42
  adapter_cfg = cfg.get("hyperlend_adapter") or {}
45
43
 
46
44
  self.hyperlend_client = HyperlendClient()
47
- self.simulation = simulation
48
- self.simulation_client = SimulationClient() if simulation else None
49
-
50
45
  self.web3 = web3_service
51
46
  self.token_txn_service = web3_service.token_transactions
52
47
 
@@ -237,8 +232,6 @@ class HyperlendAdapter(BaseAdapter):
237
232
  return await self._broadcast_transaction(approve_tx)
238
233
 
239
234
  async def _execute(self, tx: dict[str, Any]) -> tuple[bool, Any]:
240
- if self.simulation:
241
- return True, {"simulation": tx}
242
235
  return await self.web3.broadcast_transaction(
243
236
  tx, wait_for_receipt=True, timeout=DEFAULT_TRANSACTION_TIMEOUT
244
237
  )
@@ -74,7 +74,6 @@ class HyperliquidAdapter(BaseAdapter):
74
74
  self,
75
75
  config: dict[str, Any] | None = None,
76
76
  *,
77
- simulation: bool = False,
78
77
  executor: HyperliquidExecutor | None = None,
79
78
  ) -> None:
80
79
  super().__init__("hyperliquid_adapter", config)
@@ -85,7 +84,6 @@ class HyperliquidAdapter(BaseAdapter):
85
84
  "Install with: poetry add hyperliquid"
86
85
  )
87
86
 
88
- self.simulation = simulation
89
87
  self._cache = SimpleCache()
90
88
  self._executor = executor
91
89
 
@@ -481,13 +479,6 @@ class HyperliquidAdapter(BaseAdapter):
481
479
  Returns:
482
480
  (success, response_data or error_message)
483
481
  """
484
- if self.simulation:
485
- self.logger.info(
486
- f"[SIMULATION] place_market_order: asset={asset_id}, "
487
- f"is_buy={is_buy}, size={size}, address={address}"
488
- )
489
- return True, {"simulation": True, "status": "ok"}
490
-
491
482
  if not self._executor:
492
483
  raise NotImplementedError(
493
484
  "No Hyperliquid executor configured. "
@@ -525,12 +516,6 @@ class HyperliquidAdapter(BaseAdapter):
525
516
  Returns:
526
517
  (success, response_data or error_message)
527
518
  """
528
- if self.simulation:
529
- self.logger.info(
530
- f"[SIMULATION] cancel_order: asset={asset_id}, oid={order_id}"
531
- )
532
- return True, {"simulation": True, "status": "ok"}
533
-
534
519
  if not self._executor:
535
520
  raise NotImplementedError(
536
521
  "No Hyperliquid executor configured. "
@@ -565,12 +550,6 @@ class HyperliquidAdapter(BaseAdapter):
565
550
  Returns:
566
551
  (success, response_data or error_message)
567
552
  """
568
- if self.simulation:
569
- self.logger.info(
570
- f"[SIMULATION] update_leverage: asset={asset_id}, leverage={leverage}"
571
- )
572
- return True, {"simulation": True, "status": "ok"}
573
-
574
553
  if not self._executor:
575
554
  raise NotImplementedError("No Hyperliquid executor configured.")
576
555
 
@@ -590,10 +569,6 @@ class HyperliquidAdapter(BaseAdapter):
590
569
  address: str,
591
570
  ) -> tuple[bool, dict[str, Any]]:
592
571
  """Transfer USDC from spot to perp balance."""
593
- if self.simulation:
594
- self.logger.info(f"[SIMULATION] transfer_spot_to_perp: {amount} USDC")
595
- return True, {"simulation": True, "status": "ok"}
596
-
597
572
  if not self._executor:
598
573
  raise NotImplementedError("No Hyperliquid executor configured.")
599
574
 
@@ -611,10 +586,6 @@ class HyperliquidAdapter(BaseAdapter):
611
586
  address: str,
612
587
  ) -> tuple[bool, dict[str, Any]]:
613
588
  """Transfer USDC from perp to spot balance."""
614
- if self.simulation:
615
- self.logger.info(f"[SIMULATION] transfer_perp_to_spot: {amount} USDC")
616
- return True, {"simulation": True, "status": "ok"}
617
-
618
589
  if not self._executor:
619
590
  raise NotImplementedError("No Hyperliquid executor configured.")
620
591
 
@@ -647,13 +618,6 @@ class HyperliquidAdapter(BaseAdapter):
647
618
  Returns:
648
619
  (success, response_data or error_message)
649
620
  """
650
- if self.simulation:
651
- self.logger.info(
652
- f"[SIMULATION] place_stop_loss: asset={asset_id}, "
653
- f"trigger={trigger_price}, size={size}"
654
- )
655
- return True, {"simulation": True, "status": "ok"}
656
-
657
621
  if not self._executor:
658
622
  raise NotImplementedError("No Hyperliquid executor configured.")
659
623
 
@@ -758,10 +722,6 @@ class HyperliquidAdapter(BaseAdapter):
758
722
 
759
723
  Note: This is an L1 withdrawal handled by the Hyperliquid executor (signing required).
760
724
  """
761
- if self.simulation:
762
- self.logger.info(f"[SIMULATION] withdraw: {amount} USDC")
763
- return True, {"simulation": True, "status": "ok"}
764
-
765
725
  if not self._executor:
766
726
  raise NotImplementedError("No Hyperliquid executor configured.")
767
727
 
@@ -856,13 +816,6 @@ class HyperliquidAdapter(BaseAdapter):
856
816
  Returns:
857
817
  (success, response_data or error_message)
858
818
  """
859
- if self.simulation:
860
- self.logger.info(
861
- f"[SIMULATION] approve_builder_fee: builder={builder}, "
862
- f"rate={max_fee_rate}, address={address}"
863
- )
864
- return True, {"simulation": True, "status": "ok"}
865
-
866
819
  if not self._executor:
867
820
  raise NotImplementedError("No Hyperliquid executor configured.")
868
821
 
@@ -903,13 +856,6 @@ class HyperliquidAdapter(BaseAdapter):
903
856
  Returns:
904
857
  (success, response_data or error_message)
905
858
  """
906
- if self.simulation:
907
- self.logger.info(
908
- f"[SIMULATION] place_limit_order: asset={asset_id}, "
909
- f"is_buy={is_buy}, price={price}, size={size}"
910
- )
911
- return True, {"simulation": True, "status": "ok"}
912
-
913
859
  if not self._executor:
914
860
  raise NotImplementedError("No Hyperliquid executor configured.")
915
861
 
@@ -17,7 +17,7 @@ from wayfinder_paths.adapters.hyperliquid_adapter.adapter import HyperliquidAdap
17
17
  @pytest.fixture
18
18
  def live_adapter():
19
19
  """Create adapter connected to real Hyperliquid API."""
20
- return HyperliquidAdapter(config={}, simulation=True)
20
+ return HyperliquidAdapter(config={})
21
21
 
22
22
 
23
23
  class TestSpotAssetIDs:
@@ -17,7 +17,7 @@ The adapter uses the LedgerClient which automatically handles authentication and
17
17
 
18
18
  The LedgerClient will automatically:
19
19
  - Use the WAYFINDER_API_URL from settings
20
- - Handle authentication via environment variables or config.json
20
+ - Handle authentication via config.json
21
21
  - Manage token refresh and retry logic
22
22
 
23
23
  ## Usage
@@ -159,12 +159,15 @@ class TestLedgerAdapter:
159
159
 
160
160
  # Test
161
161
  operation_data = SWAP(
162
+ adapter="TestAdapter",
162
163
  from_token_id="0xA0b86a33E6441c8C06DdD4D4c4c4c4c4c4c4c4c4c",
163
164
  to_token_id="0xB1c97a44F7552d9Dd5e5e5e5e5e5e5e5e5e5e5e5e5e",
164
165
  from_amount="1000000000000000000",
165
166
  to_amount="995000000000000000",
166
167
  from_amount_usd=1000.0,
167
168
  to_amount_usd=995.0,
169
+ transaction_hash="0x123abc",
170
+ transaction_chain_id=8453,
168
171
  )
169
172
 
170
173
  success, data = await adapter.record_operation(
@@ -15,8 +15,9 @@ A Wayfinder adapter that provides high-level operations for DeFi pool data and a
15
15
  The adapter uses the PoolClient which automatically handles authentication and API configuration through the Wayfinder settings. No additional configuration is required.
16
16
 
17
17
  The PoolClient will automatically:
18
+
18
19
  - Use the WAYFINDER_API_URL from settings
19
- - Handle authentication via environment variables or config.json
20
+ - Handle authentication via config.json
20
21
  - Manage token refresh and retry logic
21
22
 
22
23
  ## Usage
@@ -44,68 +45,6 @@ else:
44
45
  print(f"Error: {data}")
45
46
  ```
46
47
 
47
- ### Get All Pools
48
-
49
- ```python
50
- success, data = await adapter.get_all_pools(merge_external=False)
51
- if success:
52
- pools = data.get("pools", [])
53
- print(f"Total pools available: {len(pools)}")
54
- else:
55
- print(f"Error: {data}")
56
- ```
57
-
58
- ### Find High Yield Pools
59
-
60
- ```python
61
- success, data = await adapter.find_high_yield_pools(
62
- min_apy=0.03, # 3% minimum APY
63
- min_tvl=500000, # $500k minimum TVL
64
- stablecoin_only=True,
65
- network_codes=["base", "ethereum"]
66
- )
67
- if success:
68
- pools = data.get("pools", [])
69
- print(f"Found {len(pools)} high-yield pools")
70
- for pool in pools:
71
- print(f"Pool: {pool.get('id')} - APY: {pool.get('llama_apy_pct')}%")
72
- else:
73
- print(f"Error: {data}")
74
- ```
75
-
76
- ### Get Pool Analytics
77
-
78
- ```python
79
- success, data = await adapter.get_pool_analytics(
80
- pool_ids=["pool-123", "pool-456"]
81
- )
82
- if success:
83
- analytics = data.get("analytics", [])
84
- for pool_analytics in analytics:
85
- pool = pool_analytics.get("pool", {})
86
- combined_apy = pool_analytics.get("combined_apy", 0)
87
- tvl_usd = pool_analytics.get("tvl_usd", 0)
88
- print(f"Pool: {pool.get('name')} - APY: {combined_apy:.2%} - TVL: ${tvl_usd:,.0f}")
89
- else:
90
- print(f"Error: {data}")
91
- ```
92
-
93
- ### Search Pools
94
-
95
- ```python
96
- success, data = await adapter.search_pools(
97
- query="USDC",
98
- limit=10
99
- )
100
- if success:
101
- pools = data.get("pools", [])
102
- print(f"Found {len(pools)} pools matching 'USDC'")
103
- for pool in pools:
104
- print(f"Pool: {pool.get('name')} - {pool.get('symbol')}")
105
- else:
106
- print(f"Error: {data}")
107
- ```
108
-
109
48
  ### Get Llama Matches
110
49
 
111
50
  ```python
@@ -136,47 +75,6 @@ else:
136
75
 
137
76
  ## Advanced Usage
138
77
 
139
- ### Filtering High Yield Pools
140
-
141
- The `find_high_yield_pools` method provides powerful filtering capabilities:
142
-
143
- ```python
144
- # Find stablecoin pools with high yield on specific networks
145
- success, data = await adapter.find_high_yield_pools(
146
- min_apy=0.05, # 5% minimum APY
147
- min_tvl=1000000, # $1M minimum TVL
148
- stablecoin_only=True, # Only stablecoin pools
149
- network_codes=["base", "arbitrum"] # Specific networks
150
- )
151
-
152
- if success:
153
- pools = data.get("pools", [])
154
- # Pools are automatically sorted by APY (highest first)
155
- best_pool = pools[0] if pools else None
156
- if best_pool:
157
- print(f"Best pool: {best_pool.get('id')} - APY: {best_pool.get('llama_apy_pct')}%")
158
- ```
159
-
160
- ### Comprehensive Pool Analysis
161
-
162
- ```python
163
- # Get detailed analytics for specific pools
164
- success, data = await adapter.get_pool_analytics(["pool-123"])
165
-
166
- if success:
167
- analytics = data.get("analytics", [])
168
- for pool_analytics in analytics:
169
- pool = pool_analytics.get("pool", {})
170
- llama_data = pool_analytics.get("llama_data", {})
171
-
172
- print(f"Pool: {pool.get('name')}")
173
- print(f" Combined APY: {pool_analytics.get('combined_apy', 0):.2%}")
174
- print(f" TVL: ${pool_analytics.get('tvl_usd', 0):,.0f}")
175
- print(f" Llama APY: {llama_data.get('llama_apy_pct', 0)}%")
176
- print(f" Stablecoin: {llama_data.get('llama_stablecoin', False)}")
177
- print(f" IL Risk: {llama_data.get('llama_il_risk', 'unknown')}")
178
- ```
179
-
180
78
  ## API Endpoints
181
79
 
182
80
  The adapter uses the following Wayfinder API endpoints:
@@ -189,6 +87,7 @@ The adapter uses the following Wayfinder API endpoints:
189
87
  ## Error Handling
190
88
 
191
89
  All methods return a tuple of `(success: bool, data: Any)` where:
90
+
192
91
  - `success` is `True` if the operation succeeded
193
92
  - `data` contains the response data on success or error message on failure
194
93